Sunday, May 7, 2023

k3d walkthrough - does it replace minikube?

What is k3d?

k3d is a lightweight Kubernetes, which can be installed on your notebook, or low-power devices to test Kubernetes nodes and clusters. 

Problems with minikube

Previously I was happily using Minikube, an alternative single-node cluster for development. But I found some issues like port-forwarding, and not restarting after the host system restarts. I did a lot of research, and I found some solutions for that like these (to access Minikube from any host in the home network.)

kubectl port-forward 

minikube tunnel 

These solutions worked to some extent, but I have noticed they created a lot of unnecessary processes when I checked with "htop" command. 

I tried installing Nginx and did reverse-proxy to forward the traffic into the ingress load balancer. I was somehow happy with this. Also, I could even directly provide minikube ip address as the local service in cloudflare tunnel configuration. So, everything was working like a charm. However when I restarted my host system where minikube was running, I saw Minikube was stopped, and when I tried to start again, I got errors. For that, I had to stop and delete Minikube and redeploy all manifests which is tedious. 


Why k3d

I compared Minikube with Kind and k3d, I have chosen k3d because it is lightweight and very easy to install. 


Installation

Installation of k3d is very simple. Just run the following command:

curl -s https://raw.githubusercontent.com/k3d-io/k3d/main/install.sh | bash 

(Pre-requisite: docker should be installed, can be checked with docker --version)

Now k3d can be directly tested.

Create clusters and nodes

k3d cluster create tkb --servers 1 --agents 3 --image rancher/k3s:latest

kubectl cluster-info

k3d cluster list

k3d cluster delete tkb

Install ingress 

kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/provider/cloud/deploy.yaml

Now the cool thing is, we can forward traffic from the host system into the ingress load balancer

k3d cluster create tkb -p "80:80@loadbalancer" --servers 1 --agents 3

Here, calling port 80 in the host will directly access the load balancer. To access hostnames, we need to write the hostnames information in "/etc/hosts" file in Linux. Or you can simply use central pi-hole dns configuration). We can simply call the services using hostnames

http://tomcat.kpaudel.lab

If the record of tomcat.kpaudel.lab exists in "/etc/hosts" file with the IP of the host system running k3d, we can get the tomcat service.  We dont need any reverse proxy. This actually worked in Cloudflare tunnel configuration too, I just need to provide the host IP address (192.168.1.XXX), not the cluster IP address. 


Friday, May 5, 2023

Make k8s services available globally

 Solution from cloudflare

Create account 

https://www.cloudflare.com/ 

Create a web application and set up your domain. 

Update the nameservers by logging domain registration page. (register.com.np) 

It will take about 24 hours to update your nameserver records until you can start further testing. 


Create tunnel

Zero Trust => Access=> Tunnel and click create tunnel. Provide the tunnel name. 

Then select docker and copy the docker command to run on your server.  The recommended way is to create compose file and set the token as an environmental variable because the token should be very secure.  (.bashrc is one of the places where environmental variables are stored)

docker-compose.yaml

ersion: '3.0'

networks:
minikube:
external: true

services:
cloudflaretunnel:
container_name: cloudflaretunnel-demo-1
image: cloudflare/cloudflared:latest
restart: unless-stopped
environment:
- TUNNEL_TOKEN=$CLOUDFLARE_TUNNEL_TOKEN
command: tunnel --no-autoupdate run
networks:
- minikube

Run this with "docker compose up", and that's it, tunnel creation is done. Now, Cloudflare can forward the traffic from this container to the services running on the server. 

Now, check the created tunnel, if it is shown as "Healthy", we are sure that everything is working so far. 

Now we configure the tunnel. We define the public hostnames and map the services in the local server. 

We provide the ingress ip address in Service URL, with type HTTP. 


In ingress ruleset, this hostname should be configured. And clicking "save hostname", we see the magic, the public hostname "subdomain.domain" will access the service running in your local network. 


So, you don't need to configure anything, no port forwarding, no router settings, no static ip adress. This solution I was looking for 7 years, now I have got it. 

Credit goes to this guy
https://www.youtube.com/watch?v=yMmxw-DZ5Ec 


Accessing k8s services in home network

Challenge: to access Kubernetes services from a remote computer in LAN.

>> Ingress configure

>> Forward traffic from the host system to ingress (using Nginx)

>> We need to use subdomains to avoid Link problems in the app.  For example: 

    kpaudel.com/tomcat will successfully open tomcat, but the button link in the tomcat itself does not point to the correct URL. 

So, instead, we define subdomains(for example tomcat.kpaudel.com). So, we could have many subdomains to point to the same address. Some mechanisms to implement wildcard DNS. 

>> Wildcard dns (multiple domains pointing to the same IP address)

WildCart DNS in Pi-hole

https://hetzbiz.cloud/2022/03/04/wildcard-dns-in-pihole/ 

(Alternative: create your own bind9+docker)

Sunday, March 19, 2023

Minikube - Persistence Volume

One of the important concepts in Kubernetes is to define persistence volumes to retain the data when nodes get deleted or restarted. I have not studied the methods for persistent volume in detail, but to fulfill my requirements, I found choosing persistent volume with NFS(network file system) to be very useful, so that I can assign an external volume mounted as NFS as a persistent volume in Kubernetes' pods. 

Some of the mechanisms of the persistent volume are 

1) Hostpath => Volume in the host system of the node. It is destroyed when a node is restarted or removed. 

2) Local => accessible to pods in  a node (any mounted partition can be assigned)

3) NFS => This one is the best for me. I can use any system in the network and mount the network file system (NFS) to use as a persistent volume. 

NFS Persistent Volume 

 https://kubernetes.io/docs/concepts/storage/volumes/#local 

In summary, we need to install nfs-kernel-server on the host system.

sudo apt update

sudo apt install nsf-kernel-server

Then we create a shared directory

sudo mkdir /Backup/k8s-volume

cd /Backup/k8s-volume

NFS will translate any root operations on the client to the nobody:nogroup credentials as a security measure. Therefore, you need to change the directory ownership to match those credentials.

sudo chown nobody:nogroup /Backup/k8s-volume

sudo service nfs-kernel-server restart


We now want to config NFS exports on the host

The following line in /etc/exports will suffice 

/Backup/k8s_volume *(rw,sync,no_subtree_check,no_root_squash,no_all_squash,insecure)

The exported volume can be mounted anywhere from the network. So even if the nodes got destroyed or restarted, we have persistent data safe in the network system. 

sudo exportfs -rav  (exports all filesystem paths)

sudo exportfs -v  (verify)

Finally, restart the server:

sudo systemctl restart nfs-kernel-server

Now the server is running. If the server is using some firewall techniques, we have to allow the NFS port 2049. 

Command to verify (from client)

sudo mount -t nfs <server(ip/hostname)>:/Backup/k8s_volume /mnt

The files will be mounted into /mnt folder 

To unmount

sudo umount /mnt


Note: There is much other information in the link given above. For Kubernetes, this will be enough.

Now let's create pv.yaml file with NFS persistent volume:

apiVersion: v1
kind: PersistentVolume
metadata:
name: persistent-volume
labels:
type: nfs
app: k8s_volume
spec:
capacity:
storage: 10Gi
volumeMode: Filesystem
accessModes:
- ReadWriteMany
storageClassName: manual
#hostPath:
# path: /Backup/temp/volumes
nfs:
path: /Backup/k8s_volume
server: 192.168.x.xxx
readOnly: false

kubectl apply -f pv.yaml

kubectl get pv 

The result shows the create persistent volume. We can then allocate the volume needed for pods, which is called "persistent volume claim" or pvc. For example: pvc.yaml

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: postgres-volume-claim
labels:
app: k8s_volume
spec:
storageClassName: manual
accessModes:
- ReadWriteMany
resources:
requests:
storage: 1Gi  

Note the app name in pv.yaml and pvc.yaml is the same so that PVC knows from where the volume to claim is. 


Sunday, March 12, 2023

Preparing Mini-Server - Part 2 (Minikube)

Minikube

While docker and docker-compose are simple and fulfill the basic requirement, I prefer Kubernetes' way of managing containers also can be scaled. So, if there is some problem in one pod, Kubernetes automatically fixes the pod, recovering the downtime. 

Kubernetes can be best managed by creating multiple nodes, but setting Kubernetes cluster at home seems advanced. So, we need to find out a way to set up a Kubernetes cluster in one machine in a single node, and Minikube is developed for that. There are some alternatives to Minikube like Kind and k3s, but I am going to install Minikube and learn Kubernetes concepts. My final goal will be to fully deploy my services into Kubernetes, the services are currently running on Docker. 

So, here I describe all the processes to make Minikube's single node up and running. 

1) Installation of docker (in Ubuntu, tested in 22.04)

sudo apt-get remove docker docker-engine docker.io containerd runc

sudo mkdir -m 0755 -p /etc/apt/keyrings

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg

echo   "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \

 $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

Test the installation

sudo docker run hello-world

Check if everything is fine

sudo service docker status

sudo systemctl status docker.service  

sudo systemctl is-enabled docker.service 

sudo systemctl is-active docker.service 

sudo docker compose version


Add user to docker group (so that you do not need to provide sudo with docker) 

Check if the docker group exists in /etc/group file. If no, add a docker group. 

sudo groupadd docker

Add the user to the docker group.

sudo usermod -aG docker $USER

Restart the system, test 

docker run hello-world

Refefence: https://docs.docker.com/engine/install/ubuntu/ 

2) Installation of Minikube

wget https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64

chmod +x minikube-linux-amd64 

sudo install minikube-linux-amd64 /usr/local/bin/minikube

Verify

minikube version

Start

minikube start

Ref: https://r2schools.com/how-to-install-minikube-on-ubuntu-22-04-lts/

3) Installation of kubectl

curl -LO https://storage.googleapis.com/kubernetes-release/release/`curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt`/bin/linux/amd64/kubectl

chmod +x kubectl 


sudo install kubectl /usr/local/bin/kubectl

Verify

kubectl version -o json --client 

Ref: https://r2schools.com/how-to-install-minikube-on-ubuntu-22-04-lts/

4) Enable autocomplete for kubectl

  • Check if bash-completion is already installed. 
    type _init_completion
          
        If already installed, you will see some messages. If not installed, install it.
       apt-get install bash-completion 

  • Enable kubectl autocompletion and reload bash
        kubectl completion bash | sudo tee /etc/bash_completion.d/kubectl > /dev/null

  • Setup alias for kubectl
    echo 'alias k=kubectl' >>~/.bashrc

  • Enable the alias for auto-completion and reload bash. (source ~/.bashrc)
    echo 'complete -o default -F __start_kubectl k' >>~/.bashrc

  Now, autocomplete will work for the alias too :)

Reference: https://spacelift.io/blog/kubectl-auto-completion 


Preparing Mini-Server - Part 1 (System)

BACKGROUND

In this article, I am going to share my experience with mini-server preparation. Actually, this whole job I have carried out as my hobby project and a kind of research & development. In my free time, I develop interesting projects and want to run them somewhere with 100% availability.

I got one free web space from somewhere (don't remember now) and I could run my small PHP project to save my personal passwords. Actually, I did not have much interest and wanted to switch to java which I am comfortable with. I then started looking for some java (free) servers where I can host my applications, unfortunately, I did not find any such provider. I had one notebook which I made run for 24 hours as a server and deployed my java applications. One big problem with this is it used to consume lots of power (almost 28W) and to run for 24 hours is, I think, not a good idea. Also, the noise produced by the notebook was also noticeable(when it runs for 24 hours).

Then I decided to purchase a virtual private server from Amazon. I was very excited to have almost 30 GB of space and 1 GB of RAM. I could run simple programs without any problem. More interesting is that I have full access to the system, and is very secure to save my private data there, than some random webspace provider. I had to pay ca. 5 EURO per month for this amazing service provided by amazon (EC2). And as compared to the electricity cost of running a full system, it was economical too. Later I found an economical option called Vultr(https://vultr.com), which I used for a couple of months, and later unsubscribed because of inactivity. IAAS provided by Amazon and Vultr was amazing, the only problem is resources that 1GB of RAM and 30 GB of SSD were not enough to run many applications parallel. You have to upgrade the resources costing more money. There were options too, to only run specific time intervals which sacrificed the availability of the service.

MINI-PC

The idea of MINI-PC came when I realize that instead of letting your data online in the cloud (which in my opinion has some sort of security and availability risks), you can have your data on your server and make it available on the internet through your router. So, you have full access to your system and can manage it in your own way. Another plus point you can get high SSD volume and more RAM. Your data will be stored locally, it does not go external world, by some security mechanism, you can fully secure your sensitive data. 

Factors to consider for a mini-server

We have to consider some points before you purchase a PC for a server to let it run for 24 hours. There are many min-pc available in the market. There are powerful mini-pc that consume more power and run warmer. The cooling system should run to make the system cool. Although they can do complex tasks faster, for a server that runs 24 hours a day, we want it to be as quiet as possible. Mini servers normally run without any graphical display, and they are not meant for gaming. So, a normal graphics card that comes with a processor should be enough. CPUs should consume as low power as possible (preferably 10W-15W - Celeron) and with this power bound as many cores as possible.  

Regarding fans, some mini-pcs have louder fans installed which can be heard in the room. For a server running 24 hours, PCs with louder fans are NOT recommended. There are BIOS settings that can set the fan speed based on temperature, to make the fan run quieter. For example, when I turned on the new mini-PC from NUC, the fan was always running, because the default setting was to run cooler with the fan always running. After changes in BIOS, the fan stopped running, and it was fully quiet. The minimum temperature to run the fan was made increased, so that fan starts running when the CPU temperature reaches that minimum temperature. 

I have done tons of research, and even though the price is higher compared to others, I could not compromise the build quality of Intel NUC PCs. My expectation was fulfilled by Intel NUC BOXNUC6CAYH (4 core intel Celeron & 8 GB memory), which is running since 2019 (almost 4 years now!) without any issues. The good part is that it has a passive fan and runs very cool 24 hours a day. I reboot the system very when there are kernel updates, that's it!

OPERATING SYSTEM

I have NOT done any research regarding the best operating system for the mini-pc. I needed lightweight, without any bloatware, and ubuntu-server met the requirements.


 The installation of the minimal server is very light and you can install the required packages/services later. After installation, I installed open-ssh to access the system remotely. Surprisingly, in contrast to windows, the memory usage was just 400 megabytes and CPU usage was almost zero. 



Enable Remote Login

To enable remote login, we have to install the open-ssh service. To allow remote login with password, you have to uncomment the following line in /etc/ssh/sshd_config file.

# PasswordAuthentication yes

Configure Network
One of the challenging tasks after installation of the ubuntu-server is to configure the network and assign an IP address to the system. 

>> Command to check all the interfaces and IP address
     ip a 
    We can see the network information including the IP addresses of all the interfaces.


Here, the first one is the lookback interface. The second one is ethernet and the third one is a wireless interface. The default network configuration is DHCP, so the IP address is assigned by a DHCP server in the network. If we want to assign static IP address, then we have to assign IP address statically. For that, we need to edit the file in the /etc/netplan folder. There are yaml files and we change dhcp to static and provided our information manually.

Wifi:
A typical wifi configuration looks something like this: 


Ethernet:
A typical ethernet configuration looks something like this:

Here I have disabled DHCP, so I have provided the Ip address, nameservers, and gateway myself. 

Note: to avoid the network verification time (ca. 2 minutes) while booting, we have made optional true, which skips the network checking.

After you have changes in one of those files, you run the following command to verify:
sudo netplan generate 
sudo netplan apply 

If you see no error messages there, you are good to go, otherwise, you have to fix the configuration problems. 

Notes:

1) Please don't enable disk encryption, which needs human intervention to provide the passphrase when the system is rebooted(which is infeasible to do remotely)
2) Use this command if "lsblk" or "df -h" not showing full disk size

sudo lvextend -l +100%FREE /dev/mapper/ubuntu--vg-ubuntu--lv


Sunday, October 9, 2022

Auto-Reload Spring MVC Project

This is a much-required process while we develop spring boot applications. We do changes continuously and want to see the result at the same time without manually rebuilding the application. 

For the changes in Java files, we need to include a dependency 

developmentOnly 'org.springframework.boot:spring-boot-devtools'


In Eclipse, this should be enough, I have not tested it though.

If you are using IntelliJ, we need to do one extra step to enable hot-reload.





You need to go to settings (CTRL+ALT+S) and click "Build, Execution, Deployment" select "Compiler", and then on the right side, select the select "Build project automatically".


So far, we have implemented the hot reload of Java files. 

This does not take care of the changes in other files, for example, changes in template files, or other resources files. There are many alternatives to implement this, I prefer using gulp which watches the changes in the resource files and transfers the changes files into the build directory.  

(Reference:https: //attacomsian.com/blog/spring-boot-auto-reload-thymeleaf-templates )

1) Your system should have the latest npm and node. 
2) Instal gulp-client 
npm install gulp-cli -g
Installing globally makes it available to all other applications too.
3) Create a file package.json in the root folder with the following content

{
"name": "Corona Tracker",
"scripts": {
"gulp-watch": "gulp-watch"
},
"dependencies": {
"gulp": "^4.0.2",
"gulp-watch": "^5.0.1"
}
}


4) Run the command npm install (which installs these packages) 
5) Now, we have to define the actual task of watching and taking action. For that, create a file called "gulpfile.js" with the following text:

var gulp =require('gulp'),
watch=require('gulp-watch');

gulp.task('watch',function(){
return watch('src/main/resources/templates/**/*.*',()=>{
gulp.src('src/main/resources/templates/**')
.pipe(gulp.dest('build/resources/main/templates/'));
});
});

The task defined here is "watch"

6) Run "gulp watch" which watches directory templates, and if any changes are there, it copies the changes into the build directory. 


I preferred this method of loading static file changes because it is fast and fully customizable. The method in IntelliJ did not work in my case. (Changing IntelliJ registry did not sound good to me) 

Monday, September 19, 2022

Access Systems in a LAN in Windows 10

Accessing a remote system with a hostname is a bit tricky in windows 10. I went on forgetting after it is done, so writing it as a reference.

It is very easy to map remote ip with a hostname. 

The file is located under

C:\Windows\System32\drivers\etc\hosts

You need to be an administrator or open notepad to change the file. 

In this file, you just need to type ip address of the remote system and the hostname to access it. 

Thats it !

Sunday, February 27, 2022

Scala 3 Introduction

Scala3 is trending and it's a significant upgrade from scala2. In this article, I am going to write a short introduction to what actually does Scala do and how can we start programming with it. I have done some research on the recently released version (called Scala3) and how can we get started with it. 

Preparing Environment

To prepare the development environment for scala, we have to install java, scala, and configure the JAVA_HOME path so that scala knows where the java is installed. The use of sdkman makes the task of managing the SDKs easier, I prefer to install it. 

1) Install SDKMan

The installation of sdkman is simple. Go to this URL and follow the instructions


Commands:
Installation
$ curl -s "https://get.sdkman.io" | bash
Load Environment
source "$HOME/.sdkman/bin/sdkman-init.sh"
Test it 
$ sdk version

2) Install JDK
$ sdk install java

3) Install Scala

$ sdk install scala

4) Install SBT

$ sdk install sbt

You can verify the installation from the command line. 


Create a sample Scala3 project:
sbt new scala/scala3.g8
This will create a sample Scala3 project. We can take this to start a project. 

Saturday, October 17, 2020

Design Pattern Walkthrough

The term Design Pattern is a buzzword in the software development world. Actually, we can develop software even without a design pattern, but software development is a continuous process, changes come and the software should adapt to the changes. So, if the software is developed without any consideration of the design pattern, then it is difficult to scale and maintain. Also, if design patterns are properly used, it's very easy to understand your code to other developers. A design pattern is nothing, but the adapted practices by experienced software developers, so it is a good idea to consider design patterns while we develop software.

Basically, we can divide the design pattern into the following categories:

A. Creational Design Pattern
B. Structural Design Pattern
C. Behavioural Design Pattern
D. J2EE Design Pattern (Only for Java)


A. Creational Design Pattern
1) Singleton
2) Factory
3) Abstract Factory 
4) Builder
5) Prototype 

B. Structural Design Pattern
1) Adapter 
2) Decorator
3) Bridge
4) Composite
5) Facade 
6) Flyweight 
7) Proxy

C. Behavioural Design Pattern
1) Command
2) Observer
3) Iterator
4) Memento
5) Template
6) State
7) Strategy
8) Visitor
9) Mediator 
10) Chain of Responsibility

D. J2EE Design Pattern



Thursday, October 15, 2020

Create USB Windows 10 Installer in Ubuntu System

 As the title clearly says, creating bootable USB in the Ubuntu system is a bit challenging as compared to the Windows system. Windows system provided their own tool and we can seamlessly create a bootable thumb drive. After the less availability of CD ROMs, it is very important to know how to create bootable USB disks. 

Yes, I also tried to use some of the tools I was familiar with, such as UnetBootIn, copying with dd tool, etc, but unfortunately, I was unsuccessful. It creates a bootable USB, but the problem, the installation of windows crashes, with some file related error. 

Because I did not have any windows system in my machines, and I have to install windows in my newly bought notebook, I have to create anyhow a bootable Windows 10 installer using my Linux machine. I carried out some research on this, got a working tool to create a bootable Windows installer on USB.

1) Installation of WOEUSB command

What I did is, I have first of all run a couple of Linux commands to add the repository, then install the tool.

sudo add-apt-repository ppa:nilarimogard/webupd8

sudo apt udpate

sudo apt intall woeusb

Now installation completes. 

2) Get USB Info

We have to find out the usb device id (for example: /dev/sdb or /dev/sdc). Using one of the following commands, we can find out that information:

sudo fdisk -l

lsblk 

3) Unmount the USB Disk

This is important, we have to unmount the USB before carrying out the problem. There is a simple command to carry out this task:

sudo umount /dev/sdb1

3) Create the installer 

The final step is to run a command to create the actual installer. 

sudo woeusb --target-filesystem NTFS --device Win10_2004_English_x64.iso /dev/sdb

Here, Win10_2004_English_x64.iso is the iso file downloaded from the Microsoft site. Which can be freely downloaded. 

/dev/sdb is the path of the USB disk.

It can take up to 5-6 minutes depending upon how fast your system is.

After the process finishes, we are ready to use it as a windows 10 installer. 



Friday, April 10, 2020

Creating multipurpose executable Jar file

As the title says, this recipe is focused on creating a multipurpose jar file, where a single jar file can be used for multiple requirements. I am going to cover the whole process by diving into the following steps:
1) Create a Java application
2) Bundling into an executable Jar file
3) Running a Jar file

I take a problem scenario to explain the above steps and how they are carried out.

Problem:
We want to have a java application, which should have addition, subtraction, multiplication and division functionalities,  that we can call those functionalities providing the command line parameters. For example

add 2 4 4 (result=2+4+4)
subtract 54 12  (result=54+12)
multiply 12 54 55 (result=12*54*55)
divide 34 17 (result=34/17)


So, let's start:
1) Create a Java application
I am creating a Java application with Gradle as a build tool because it is easy to use. I am creating 4 classes with the main method which is responsible for corresponding operation and parameters. One option could be to create a single method and get an operation as a parameter, which makes it really complex to handle parameters. If we create a main method for each operation, it makes our tasks of handling parameters easy.

So, I begin with creating four java classes with main method, which manipulates the arguments to get the corresponding result. Because the example task is very simple, our actual task could be way bigger with many dependent libraries. So, we define a bunch of libraries in "build.gradle" file and we create a "fatJar" with all dependencies included in the jar file. An alternative will be we copy dependent libraries in the classpath.

I begin with the fatJar method, which create a jar file with all dependent libraries automatically from gradle. For this, we have to write a method to create fatJar. Have a look at the sample build.gradle file.

File: build.gradle



settings.gradle



The method jar create the jar file without dependencies. But the fatJar create a jar file with all dependencies, and we can use out of the box.

So, after definition of Gradle build information.

Now, we create class files with specific operation in main methods. The class files look something like this:

Add.java



Subtract.java



Multiply.java



Division.java



The application structure looks like this:



So far, we have created a java application with the required operations.


2) Bundling into an executable Jar file

Bundling into an executable Jar file is quite easy because we have already written a method in build.gradle file above. So, we just call

gradle clean && gradle fatJar

The created Jar file will be in folder build/libs as shown above(Operations.jar)

Note: If we simply run "gradle build", then it will create a thin jar file(i.e. without dependencies)


3) Running a Jar file

The Last Step is to execute the Jar file Operations.jar. The bundled jar file includes all the classes, and we can run all operations providing corresponding arguments.
For example:
java -cp Operations.jar com.kpaudel.operations.Add 12 34.33 45.3

Result=91.63

Similarly, we can check all other operations providing the parameters. 

java -cp Operations.jar com.kpaudel.operations.Subtract 123.56 23
Result=100.56

java -cp Operations.jar com.kpaudel.operations.Multiply 12.2 34.5
Result=420.9

java -cp Operations.jar com.kpaudel.operations.Division 12 2 2
Result=3.0


So, we can independently manage each operation with their own arguments, which makes very easy to handle input arguments. Apart from this advantage, bundling into a single jar file makes it easy to deploy, which means only a single jar file with many operations can be called separately.

I am using this method to create download and upload operations for my cloud storage, getting advantage of using the same jar file for different purposes of download and upload operations(with independent input parameters.) 


I hope you have enjoyed this recipe.  Thanks for reading :)

Wednesday, October 30, 2019

LED Strips Programming (Arduino)

Today, I am going to share my experience on the LED Strips programming using Arduino. It will be fantastic to decorate on Christmas nights, which you can program each LEDs as required like we could create a cool animation.

This article does not go into detail. This will just give you the idea on how we can program LED strips and you can program the lights according to your need.

Let's begin, we need the following items before we begin the programming.

1) Arduino
2) Power Source (10 V)
3) Wires
4) LED Strip

We connect the power source to one end of the led strip. Normally positive wire of the strip is red, and the negative is white. The white is grounded with the ground of the strip. Strip has also cables to be connected to the Arduino. GND should be connected to the negative power supply. Note that the green color cable is used for the color signal which we normally connect to PIN 7 of Arduino.

If you are using an external 10V power supply, we connect the positive to the red and negative to the white one. NEVER connect the red one into the 5V pin of the Arduino which burns it. I have burnt 3 Arduino by mistakenly connecting this 10V in 5V pin in Arduino.

So, the connection will be like this:

1) Without external power
If we DON'T want to use external power, then we need to use an Arduino +5V pin as a power supply to the LED strip. Please note that, because Arduino can't deliver enough power, we have to compromise the brightness of the LED Strips.

The connection diagram will be as follows:


2) With external power supply
If the Arduino power is not enough for the LED strips, we need external power supply. I have used 15V 5A power supply.  Please be very careful while connecting external power supply. Note that if you mistakenly connect your +15 V in the +5V pin, then you will burn your Arduio which I did 4 times!
So, if you using an external power supply, never connect the red (positive) +15V to the Arduino. But the negative of the power supply (normally white line) should be connected to the GND of the Arduino. The PIN 7 should be connected to the green line DIN of the strip. 
Please look into the connection diagram

Please note that the +15V red line is not connected to the Arduino.

Now we come to our actual task: programming. Before we start we have to install the needed libraries.

We need Adafruit_Neopixel and optional Tinkerkit libraries. Adafruit library is used to actual programming while Tinkerkit libraries make it easy to read sensor values because we are using sensors to control the led lights.

The code is made downloadable from git repository:


This example code is just a kind of animation I have created. But we can use the power of
Arduino to define cool animations in your own way.
Just try yourself :)

Monday, April 22, 2019

Arduino Basics

Arduino is a simple, programmable micro-controller.  In this article, I am gonna write some tips which make programming with Arduino more simple.

1) Installation 

The first step will be the installation of Arduino from here:

https://www.arduino.cc/en/Main/Software

You, normally select the latest version for download, not nightly build versions.

I downloaded 1.8.9 version.

Extract the downloaded compressed file into /opt/arduino (for example). Just run the install.sh file inside the extracted Arduino folder.


2) Settings for Visual Studio Code

After installation is complete, we have to carry out some settings in visual studio code. First, install the Arduino extension and after installation is complete, restart IDE. Then we create a workspace folder.

~/workspace/arduino /src/Project1

Now, we open the arduino folder from VSCode IDE. Now, using

CTRL+SHIFT+P

A: Arduino:BoardConfig
B: Arduino:Initialize
C: Arduino:Select Serial Port

The final step is to define the build folder in arduino.json created in the root directory.

 "output": "build",

This is, I guess, automatically created. But to be safe, add this line.

3) Create a Program

The most interesting part is here.

Create a new program example.ino  with the following contents

void setup() {
// initialize digital pin LED_BUILTIN as an output.
pinMode(LED_BUILTIN, OUTPUT);
}

// the loop function runs over and over again forever
void loop() {
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1000); // wait for a second
digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW
delay(1000); // wait for a second
}


Then we first verify the correctness of the program. And then upload the program.

Verification:  CTRL+SHIFT+P => Arduino:Verify  (Shortcut: CTRL+ALT+R)
Upload: CTRL+SHIFT+P => Arduino:Upload (Shortcut: CTRL+ALT+U)


Problems faced

While uploading I faced the following problem

An error occurred while uploading the sketch
avrdude: ser_open(): can't open device "/dev/ttyACM0": Permission denied

I did not know how secure is this, but I made the terminal readable and writable for all. And restarted IDE, then it worked! I ran the following command from the terminal.

sudo chmod a+rw /dev/ttyACM0 

Now, we can use the power of visual studio code to develop Arduino programs. 

Note: Because we can not place multiple files and run. To achieve this we create a folder structuer inside src folder of root.  For example:

ArduinoRoot
.....src
----------Project1
----------Project2
-------------------SubProject1










Monday, March 11, 2019

Simple Windows Installer

For windows system, is there any possibilities of creating a packaged installer like DEB in Ubuntu system? I have carried out some research and studies to find out the solution for this. Although there are possibilities to create a packages exetutable installers using different tools. After thorough comparison and reviews I got to conclusion that NSIS (Nullsoft Scriptable Install System) provides the best solution for that. It is really simple, everything is scripts, also very scalabale and powerful.


So, lets get started!

I create a basic installer using some files and scripts as resources. Please note that there are many possibilities we could add more functionalities. This article describes a very basic example on how we can create a simple installable packaged executable which can be deployed for installation.

We just write scripts into a file with extension *.nsi and installer is created from the scripts defined in the file. There are possibilities to create shortcuts, copy resources, define UI and many more. 

The first step to begin with is to install NSIS software which can be found at

https://sourceforge.net/projects/nsis/

After installation, we have to install NSIS plugin for visual studio code. Then, we have advantage of autocompletion and easy compilation. 

Writing a NSI file is divied into different blocks with their specific tasks and all blocks are run sequentially(there are some exceptions like Uninstall block runs at the time of uninstalling the application.) 

1) Definition Block

This block defines different variables which we wanted to define here. We can define a variable using

!define MUI_PRODUCT "Frietec Google Service"
!define AUTHOR "paudekri@frietec.com"

2) Basic Block

The basic block is very important because we define the Name, output file and install directory where the application is supposed to be installed. For example

Name "${MUI_PRODUCT}"
OutFile "FE-Google.exe"
InstallDir "C:\Frietec\${MUI_PRODUCT}"

3) Macro Block

We can create installed without macro block, but using macro block makes further improvements such as greater looking GUI and so on. A sample macro block is 

!include MUI2.nsh
!define MUI_ICON "Resources\installer.ico"
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_PAGE_FINISH
!insertmacro MUI_LANGUAGE "German"

4) Section Block

The section block backbone where we define the processese of installation in different sections. We define scripts to copy resources or create uninstaller and define scripts and so on. 

For example:

Section "install" Installation
  # Copy scripts 
  SetOutPath $INSTDIR
  #File Scripts\Calendar.bat
  #File Scripts\Drive.bat
  #File Scripts\Email.bat
  File /r Scripts scripts
  SetOutPath $INSTDIR\resources
  File Resources\email.ico
  File Resources\drive.ico
  File Resources\calendar.ico
  File Resources\installer.ico  
  WriteUninstaller $INSTDIR\uninstall.exe
SectionEnd

Section "Shortcuts"
  CreateDirectory "$Desktop\${MUI_PRODUCT}"
  CreateShortCut "$Desktop\${MUI_PRODUCT}\Uninstall.lnk" "$INSTDIR\Uninstall.exe"
  CreateShortCut "$Desktop\${MUI_PRODUCT}\Shortcut to Email.lnk" $INSTDIR\scripts\"Email.bat" Icon $INSTDIR\resources\"email.ico"
  CreateShortCut "$Desktop\${MUI_PRODUCT}\Shortcut to Drive.lnk" $INSTDIR\scripts\"Drive.bat" Icon $INSTDIR\resources\"drive.ico"
  CreateShortCut "$Desktop\${MUI_PRODUCT}\Shortcut to Kalendar.lnk" $INSTDIR\scripts\"Calendar.bat" Icon $INSTDIR\resources\"calendar.ico"  

  CreateDirectory "$SMPROGRAMS\${MUI_PRODUCT}"
  CreateShortCut "$SMPROGRAMS\${MUI_PRODUCT}\Uninstall.lnk" "$INSTDIR\Uninstall.exe"
  CreateShortCut "$SMPROGRAMS\${MUI_PRODUCT}\Email.lnk" "$INSTDIR\scripts\Email.bat" Icon $INSTDIR\resources\"email.ico"
  CreateShortCut "$SMPROGRAMS\${MUI_PRODUCT}\Drive.lnk" "$INSTDIR\scripts\Drive.bat" Icon $INSTDIR\resources\"drive.ico"
  CreateShortCut "$SMPROGRAMS\${MUI_PRODUCT}\Kalendar.lnk" "$INSTDIR\scripts\Calendar.bat" Icon $INSTDIR\resources\"calendar.ico"
SectionEnd

Section "Uninstall"
  Delete $INSTDIR\uninstall.exe
  RMDir /r "$INSTDIR\*.*"
  #Delete $INSTDIR\*.*
  RMDir $INSTDIR
  
  Delete "$Desktop\${MUI_PRODUCT}\*.*"
  RMDir "$Desktop\${MUI_PRODUCT}"
  Delete "$SMPROGRAMS\${MUI_PRODUCT}\*.*"
  RMDir "$SMPROGRAMS\${MUI_PRODUCT}"
  #Delete "$Desktop\FE-Google\Shortcut to Kalendar.lnk"
SectionEnd


5) Function Block

The block block is where we define functions. A typical usage is to display messagebox when installation success or uninstallation is done.

For example:

#Function that calls a messagebox when installation finished correctly
Function .onInstSuccess
  MessageBox MB_OK "You have successfully installed ${MUI_PRODUCT}. Use the desktop icon to start the program."
FunctionEnd
  
Function un.onUninstSuccess 
  MessageBox MB_OK "Sie haben erfolgereich deinstalliert=> ${MUI_PRODUCT}."
FunctionEnd


The compilation creates an executable installer file in the same directory. We can execute this file to get installed. Similarly we can install it by clicking the unistall link in the installation directory or can be defined as a short for simplicity.

The full project is available at the following github location:

https://github.com/krishna444/MyWindowsInstallaer.git




Friday, February 22, 2019

Spring Boot with GWT using gradle build

Today I am going to write an interesting concept, which will be quite useful to quickly start and deploy a  big project without worrying about any javascript complexities.

It is well accepted that Spring Boot is very popular backend framework and I have to say, it is not quite supportive for front-end development. For that we have to use frontend development system using Javascript, because Javascript is the only option. And the communication to the server using Javascript makes less maintainable code. Also, using GWT, we write both server and client side program using a single programming language Java, which makes it a very scalabale and maintaible project. That's my experience because I use a framework called echo(echo.nextapp.com) which is quite stable and very very maintainable.

Lets begin implementing Spring boot with GWT. It seems a bit complicated, have a patience because end result is very interesting.

I am using eclipse IDE for development. So, I assume you have already installed it including JDK(1.8 is preferrable). Please be sure the installed gradle version is greater or equal to 4.0 for SpringBoot to work.

Step 1: Project Creation

Now create a new gradle project from eclipse IDE or using gradle command.

gradle init --type java-library


and just import created project into eclipse. This is the basic project project. We have modify this project.


Step 2: Configuration

We carry out build configuration in build.gradle file. It is recommended to remove all the contents and use the following content:
//build.gradle
buildscript{
repositories{
mavenCentral()
}
dependencies{
classpath 'org.wisepersist:gwt-gradle-plugin:1.0.6'
}
}

plugins{
//Required for springboot
id 'java'
id 'org.springframework.boot' version '2.1.3.RELEASE'
}
apply plugin: 'gwt'
apply plugin: 'io.spring.dependency-management'

sourceCompatibility =1.8
targetCompatibility=1.8
def GWT_VERSION='2.8.2' //latest version

repositories{
  jcenter()
}

//not needed (if you use default values). The following values
// are default values, so not necessary.
sourceSets{
main.java.srcDir "src/main/java"
main.resources.srcDir "src/main/resources"
test.java.srcDir "src/test/java"
test.resources.srcDir "src/test/resources"
}

dependencies{
//Just add this 4 libraries for gwt
compileOnly("com.google.gwt:gwt-user:${GWT_VERSION}")
    compileOnly("com.google.gwt:gwt-dev:${GWT_VERSION}")
    compileOnly('org.fusesource.restygwt:restygwt:2.2.3')
    compile('javax.ws.rs:javax.ws.rs-api:2.1.1')
    
    //Spring libraries
    compile('org.springframework.boot:spring-boot-starter-data-jpa')
    compile('org.springframework.boot:spring-boot-starter-jetty')
    testCompile('org.springframework.boot:spring-boot-starter-test')
    compile('org.springframework.boot:spring-boot-starter-web'){
      exclude module: 'spring-boot-starter-tomcat'    
    }      
}
 //gwt configuration
 gwt{
     gwtVersion=GWT_VERSION
     modules 'com.kpaudel.frontend.SpringBootGwt'
     maxHeapSize="1024M"
 }


//package
task copyGWTCode(type:Copy){
  //from compileGwt.outputs
  from file("${buildDir}/gwt/out")
  into file("${buildDir}/resources/main/static")
 }

 copyGWTCode.dependsOn compileGwt

 bootJar{
  dependsOn copyGWTCode
  doLast{
  mkdir "${buildDir}/target"
  setDestinationDir(file("${buildDir}/target"))
  copy()
  }

 } 

Step 3: Create a GWT module

It is important step. Here we provide the path of the module definition file. This file defines all GWT related information.  There can be multiple modules,  which should be first define in build.gradle file(in gwt block) above. In packaging system, suppose we create a package called

com.kpaudel.com.frontend

Then module information file is located in the package(the file extension of module file name is always *.gwt.xml). We create a module definition file name with the following contents:

   

So, we create two packages, one for client and one for shared.

com.kpaudel.frontend.client This package for client only files
com.kpaudel.frontend.shared This package for shared files(both client and server)

Like we defined entry point class in module definition file above, we create a Java File as entry point:
Here is a very simple example:

//SpringBootGwt.java
package com.kpaudel.frontend.client;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootPanel;

public class SpringBootGwt implements EntryPoint {

@Override
public void onModuleLoad() {
RootPanel.get().add(new Label("Hello World"));
}
}

Step 4: Compilation

What we did so far can convert our java files into javascript file using the following gradle script in the project root path.

./gradlew compileGwt

The compiled javascript files are located in build/gwt/out/frontend folder. The folder name frontend comes from the module name defined in the module definition file.

Step 5: Server Stuffs

Now, we can do server stuffs now. Because we are backed up by very powerful spring framework, so we can do whatever we want using this technology.

Step 6: Packaging

Packing stuffs into a bundle jar is a bit complicated in the sense that we have to include some scripts in build.gradle file. Please have a look at the last lines of build.gradle file.

Sunday, February 10, 2019

Thursday, January 17, 2019

Windows10 Licencing

Licencing is a headache, if you don't do it, even if you paid for licence, you can not use a product. This short article touches the surface of licencing in Windows 10.

View Installed Licence

Yes, to use Windows 10, we need a valid licence. Windows stores this licence somewhere in your system, so that, it normally automatically activates your system and you do not need licence again. Sometimes, this is not enough because we need to manually activate the system and in this situation, we need the actual licence.

Windows hides the licence from viewing(only last 5 letters are shown), that means we need to get the script which shows the installed licence in the system.

I got a working Visual Basic Script which shows the installed licence in the system.

File: GetProductKey.vbs
(script source: https://www.winhelponline.com/blog/view-your-product-key-windows-10-8-7-script/)
Option Explicit  
 
Dim objshell,path,DigitalID, Result  
Set objshell = CreateObject("WScript.Shell") 
'Set registry key path 
Path = "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\" 
'Registry key value 
DigitalID = objshell.RegRead(Path & "DigitalProductId") 
Dim ProductName,ProductID,ProductKey,ProductData 
'Get ProductName, ProductID, ProductKey 
ProductName = "Product Name: " & objshell.RegRead(Path & "ProductName") 
ProductID = "Product ID: " & objshell.RegRead(Path & "ProductID") 
ProductKey = "Installed Key: " & ConvertToKey(DigitalID)  
ProductData = ProductName  & vbNewLine & ProductID  & vbNewLine & ProductKey 
'Show messbox if save to a file  
If vbYes = MsgBox(ProductData  & vblf & vblf & "Save to a file?", vbYesNo + vbQuestion, "BackUp Windows Key Information") then 
   Save ProductData  
End If 
 
 
 
'Convert binary to chars 
Function ConvertToKey(Key) 
    Const KeyOffset = 52 
    Dim isWin8, Maps, i, j, Current, KeyOutput, Last, keypart1, insert 
    'Check if OS is Windows 8 
    isWin8 = (Key(66) \ 6) And 1 
    Key(66) = (Key(66) And &HF7) Or ((isWin8 And 2) * 4) 
    i = 24 
    Maps = "BCDFGHJKMPQRTVWXY2346789" 
    Do 
           Current= 0 
        j = 14 
        Do 
           Current = Current* 256 
           Current = Key(j + KeyOffset) + Current 
           Key(j + KeyOffset) = (Current \ 24) 
           Current=Current Mod 24 
            j = j -1 
        Loop While j >= 0 
        i = i -1 
        KeyOutput = Mid(Maps,Current+ 1, 1) & KeyOutput 
        Last = Current 
    Loop While i >= 0  
     
    If (isWin8 = 1) Then 
        keypart1 = Mid(KeyOutput, 2, Last) 
        insert = "N" 
        KeyOutput = Replace(KeyOutput, keypart1, keypart1 & insert, 2, 1, 0) 
        If Last = 0 Then KeyOutput = insert & KeyOutput 
    End If     
     
 
    ConvertToKey = Mid(KeyOutput, 1, 5) & "-" & Mid(KeyOutput, 6, 5) & "-" & Mid(KeyOutput, 11, 5) & "-" & Mid(KeyOutput, 16, 5) & "-" & Mid(KeyOutput, 21, 5) 
    
     
End Function 
'Save data to a file 
Function Save(Data) 
    Dim fso, fName, txt,objshell,UserName 
    Set objshell = CreateObject("wscript.shell") 
    'Get current user name  
    UserName = objshell.ExpandEnvironmentStrings("%UserName%")  
    'Create a text file on desktop  
    fName = "C:\Users\" & UserName & "\Desktop\WindowsKeyInfo.txt" 
    Set fso = CreateObject("Scripting.FileSystemObject") 
    Set txt = fso.CreateTextFile(fName) 
    txt.Writeline Data 
    txt.Close 
End Function

After saving this content into the file, we can execute the file which shows the installed licence.

 How to Activate Licence (slmgr)

Windows has given us a very useful tool called slmgr.vbs which is used to view licence information and many other licence related operations.

Please have a look at this article for detailed information regarding slmgr tool:

https://www.howtogeek.com/245445/how-to-use-slmgr-to-change-remove-or-extend-your-windows-license/

I have listed some useful commands using slmgr.vbs tool.

a) slmgr.vbs /dli (Display licence information)
b) slmgr.vbs /dlv (Detail licence view)
c) slmgr.vbs /xpr (Expiration date)
d) slmgr.vbs /upk (Uninstall product key) => Restart required.
e) slmgr.vbs /cpky (Clear product key from registry only)
f) slmgr.vbs /ipk ####-####-####-####-#### (Install product key)
g) slmgr.vbs /ato (Activate online)
h) slmgr.vbs /dti (Displays confirmation Id) => this id should be given to support for offline activation, then support gives your activation_id.
g) slmgr.vbs /atp activation_id (Activate with id)