Sunday, July 23, 2023

Restoring Images Exif Data after upload to Google Photos

 Recently my Google free storage of 15GB is getting full so wished to get the photos back to my local system. Yes we can quickly download it but found that Google has wiped off of the Exif data, specially the dates.


So to restore it, luckily it still retained the file names like : IMG_20230508_110348.jpg

So quickly created the below script and it worked :)


SETLOCAL ENABLEDELAYEDEXPANSION

for %%c in (*.jpg) do ( 

set a=%%~nc

set x=!a:~4,15!

set y=!x:~0,4!:!x:~4,2!:!x:~6,2! !x:~9,2!:!x:~11,2!:!x:~13,2!

echo !y!

"<exiv2_location>\exiv2" -k -M"set Exif.Image.DateTime Ascii !y!" %%c

)


Also it need a PowerShell script to update the created Date and Modified date:


$modifyfiles = Get-ChildItem -force *.jpg| Where-Object {! $_.PSIsContainer}

foreach($object in $modifyfiles)

{

$object.CreationTime=[datetime]::ParseExact($object.BaseName.Substring(4),"yyyyMMdd_HHmmss",$null)

$object.LastWritetime=[datetime]::ParseExact($object.BaseName.Substring(4),"yyyyMMdd_HHmmss",$null)

}

Thursday, July 8, 2021

AWS : NodeJS : Hello World on EC2

 Although I have an account in AWS for over a decade, I really did not do much with it other than launching a EC2 instance and then say print Hello World.

A decade has passed and now AWS has caught up with me professionally so need to build come competencies around it.

First is to get the the Hello world back again using Node on a Web Page.

Assumptions:

  1. You have a AWS account. I am using the free tier one.
  2. Have basic understanding of Node
  3. Have basic understanding of AWS specially EC2, VPC and ACLs.

Steps:
  1. Go to EC2. Select "Amazon Linux 2 AMI (HVM), SSD Volume Type" of type "t2.micro" and launch it. 

  2. You will get a public key .pem file. Keep it safely.

  3. On Windows, you will need to set the permissions of the file correctly to mimic chmod 400 of linux:
    1. icacls.exe key.pem /reset
    2. icacls.exe key.pem /grant:r "$($env:username):(r)"
    3. icacls.exe key.pem /inheritance:r

  4. Go to Security Group and Edit Inbound rule to allow:
    1. SSH (port 22) from anywhere
    2. HTTP (port 3000) from anywhere

      This will allow you to connect to the EC2 instance from your local laptop as well as browse the Hello World node site in there.

  5. Coming back to EC2 dashboard, you should see 1 Instance running

  6. You should be able to connect to it using SSH client and see the welcome logo:
           __|  __|_  )
           __|  __|_  )
           _|  (     /   Amazon Linux 2 AMI
          ___|\___|___|
    https://aws.amazon.com/amazon-linux-2/

  7. Now that you have a shell access to your EC2 instance, lets install Node JS.

  8. We will use nvm for it.

  9. curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.38.0/install.sh | bash

  10. Activate nvm using simply bash or . ~/.nvm/nvm.sh

  11. nvm install node

  12. check node installed:
    node -v
    v16.4.2

  13. Now let just start a simple Express web app
    mkdir myapp
    cd myapp
    npm init (and just enter till the end)
    npm install express --save
    vi app.js
    const express = require('express')
    const app = express()
    const port = 3000

    app.get('/', (req, res) => {
      res.send('Hello World!')
    })

    app.listen(port, () => {
      console.log(`Example app listening at http://localhost:${port}`)
     
    })
  14. node app.js
    Example app listening at http://localhost:3000
  15. So our web app is up are running on 3000 but its still within the EC2 instance. To be able to access it from the internet, we need to modify the security group of the EC2 instance to allow the port 3000 be exposed. This has been done in Step 2.

  16. So access the web app using the public IP or hostname of the EC2 instance. Note to use http:// and not https:// and append the port 3000 at the end. It should show up as :

    Hello World!
Thats all for today. Next we will connect the mighty Database :)

Wednesday, April 14, 2021

Kubernetes : Getting started on Windows

I had setup Kubernetes on local laptop and had tried a few things 2-3 years back. In the meantime the laptop got replaced and recently got some work around it. So it was time to set it up again.

I found that Docker Desktop does now support Kubernetes so thought it will be pretty easy to get up back again. So went to Docker Desktop -> Settings -> Kubernetes and selected Enable Kubernetes. In a few minutes it got enabled and on the command prompt I got kubectl. Wow, its all done.

Now the problems started.

First, when I executed kubectl version, I did get the client version but for the server version I got:

kubectl unable to connect to server: x509: certificate signed by unknown authority

So spent quite a few hours trying to work this out. There is enough documentation on the web but nothing specific to docker desktop. So despite the trials and errors, it did not work so abandoned it and went back to my earlier trusty minikube.

First had to remove Kubernetes from Docker Desktop but it was not allowing me to do it !!. So had to uninstall the whole of Docker Desktop.

Then installed the following using Chocolatey:

  1. Install kubectl : choco install kubernetes-cli
  2. Install Minikube : choco install minikube
Then installed Docker Desktop as well as had uninstalled it earlier.

All done, lets check all things are fine:

  1. Start the cluster : minikube start
  2. Check kubectl : kubectl version

    Client Version: version.Info{Major:"1", Minor:"21", GitVersion:"v1.21.0", GitCommit:"cb303e613a121a29364f75cc67d3d580833a7479", GitTreeState:"clean", BuildDate:"2021-04-08T16:31:21Z", GoVersion:"go1.16.1", Compiler:"gc", Platform:"windows/amd64"}
    Server Version: version.Info{Major:"1", Minor:"20", GitVersion:"v1.20.2", GitCommit:"faecb196815e248d3ecfb03c680a4507229c2a56", GitTreeState:"clean", BuildDate:"2021-01-13T13:20:00Z", GoVersion:"go1.15.5", Compiler:"gc", Platform:"linux/amd64"}

  3. Check cluster : kubectl cluster-info

    Kubernetes control plane is running at https://127.0.0.1:61152
    KubeDNS is running at https://127.0.0.1:61152/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

  4. All good, lets start the dashboard : minikube dashboard

    * Enabling dashboard ...
      - Using image kubernetesui/dashboard:v2.1.0
      - Using image kubernetesui/metrics-scraper:v1.0.4
    * Verifying dashboard health ...
    * Launching proxy ...
    * Verifying proxy health ...
    * Opening http://127.0.0.1:60036/api/v1/namespaces/kubernetes-dashboard/services/http:kubernetes-dashboard:/proxy/ in your default browser...

    Open the browser and view the brand new Kubernetes cluster in all its glory :)

So we have our K8 cluster setup. Lets start some sample applications just to test it out and revise some of the old stuff. So I tried to setup nginx as will be working on application which will have a HTTP interface.

So first create the nginx.yml file for the deployment:

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: nginx
  name: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx:latest
        name: nginx

and apply it on the K8 cluster : 

> kubectl apply -f nginx.yml
deployment.apps/nginx created

Go to the MiniKube dashboard and under deployments, you will find:


 Under Pods, you will find:


The equivalent command line will be 
  • kubectl get deployments
  • kubectl get pods

So all good, we have deployed nginx which is running in a container within pod. Still we need to expose nginx on a port in the container so that it is accessible. Update the yaml file to:

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: nginx
  name: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx:latest
        name: nginx
        ports:
        - containerPort: 80
          name: nginx

and apply it : kubectl apply -f nginx.yml

So now we have set port 80 where it will receive the request and forward it to nginx. Still this port is exposed within the K8 cluster and not to outer world. To expose it to outer world or host, we need to create a service which will do so. 

So create the nginx_service.yml as:

apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  selector:
    app: nginx
  ports:
    - protocol: TCP
      targetPort: 80
      port: 8082

and apply it :
>kubectl apply -f nginx_service.yml
service/nginx created

In the minikube dashboard, you will find:

As you can well see that it was exposed the port 8082 for the app: nginx

Now you can check it on your local browser : http://localhost:8082 or http://127.0.0.1:8082/

All good. Now get will app development and deployment on K8 cluster :)

Saturday, June 6, 2020

How to Set Up a WRT54G as a Repeater

I have been using Linksys WRT54G for over 15 years now and it has been an excellent router.

Over time the broadband speeds have increased and my current broadband plan supports 200 Mbps. My router has an official peak speed of 54 Mbps but practically even if I sit next to it, I get around 20 Mbps which falls to less than 10Mbps in the next room and by the time I reach my 3rd bedroom, the signal is almost gone. So I felt, I am losing out on the speed I am paying for.

Another issue was the increase of device counts connecting to the router. Earlier it used to be just my laptop. Now we have 3 laptops, 2 smart phones, 1 Smart TV and the count will simply increase in future. In here my router was unable to cope up with. So if my child is watching YouTube on TV in FullHD , (in lock down due to Corona), my Skype and Team calls get impacted although I have enough bandwidth to support all in parallel.

So it was time for an upgrade. Did my research and finally concluded on TP-Link Archer C60 AC1350 primarily due to:

  1. Wanted a dual band router as it can support up to 867 Mbps @ 5 GHz. I don't think I will cross that speed in next 3-4 years
  2. It support MU-MIMO which will help support multiple devices in parallel
  3. Has 5 Antennas
  4. Cost was Rs 2200 on Amazon which was like 300 more than next model but had more features.
With the new router coming in, I did not want to throw my old router as the new one still did not reach my 3rd bedroom well. So started looking up on Google to convert my Linksys WRT54G in to a repeated. And yes it was possible.

The 2 reference links are :
Although the links are pretty accurate, there are some misses in there which I believe is more like article was written in the past and things have changed.

To flash the router and install DD-WRT on it

  1. DO the hard reset exactly as its said i.e. 30-30-30. Actually I did like 60-60-60 to be safe and all went fine.
  2. The GV5Flash.zip download is missing vximgtoolgui executable although the folder name is the same. The executable inside the folder is wrt_vx_imgtool which is like command line version of the tool . To get the GUI, use this url : http://web.archive.org/web/20060708130642/http://www.bitsum.com/files/vximgtoolgui.zip
Configure the  repeater

  1. In here skip the 'Reset Router' and 'Update Firmware' sections
  2. Start from 'Set Static IP Address'
  3. if you favour command line, you can use
    netsh interface ip set address name="Ethernet" static 192.168.1.9 255.255.255.0 192.168.1.1
    netsh interface ip set address name="Ethernet" dhcp
  4. Change Router Settings : Step 7 - You can put a better SSID than 'bridge' like _rpt or _ext
  5. An important step missed in here is to secure the repeater itself. To do so, go to Wireless :: Wireless Security Tab :: Virtual Interfaces section. In there you can set security mode for the repeater like WPA2 Personal and the key.

Now a bigger issue is once you have setup the repeater, there is no way you can access it over WiFi as its a plain proxy. If you try http://192.168.0.1/ , you will end up with the primary router. and there is no http://192.168.1.1/. So to access it back again, 
  1. you will need to setup you local laptop with static IP :
    netsh interface ip set address name="Ethernet" 
  2. Connect your laptop to the repeater using the Ethernet cable
  3. Now try http://192.168.1.2/ as the repeaters own address is 1.2 with 1.1. being the gateway (as configured in Step 3 of 'Change Router Settings'

So all good, I ended up with 3 SSIDs:
  1. Primary 2.4 GHz
  2. Primary 5 GHz
  3. Repeater 2.4 GHz
and yes my whole house is now covered :)

Monday, September 23, 2019

GIT Commit Stats using Command Line to analyse in Excel

git log --all --no-merges  --pretty=format:"%aE - %aI : %s" --after="2019-04-01 00:00"  > git.log

Sunday, September 22, 2019

Static code analysis and source code complexity tool - Plato for Typescript

I was looking for a tool which can report code complexity for an Angular application. The application is written in Typescript and there are hardly any tools for it.

The first place to look was Wikipedia : https://en.wikipedia.org/wiki/List_of_tools_for_static_code_analysis#JavaScript which has some tools for Javascript but none for Typescript.

Looking across the web : https://www.npmjs.com/search?q=keywords:complexity , I came across tools like Plato and Complexity Report based on EsComplex. I was quickly drawn to Plato for it nice graphical reports.

npm install -g plato

Still the problem was how to make Plato run on TypeScript. Yes there were people asking for it on the web but no answers.

Now I knew all the TS code of my angular application is compiled and put into main.js. So I applied Plato on the file directly. First thing I hit was a memory constraint put by node that it can use a maximum memory of around 1.5GB. So had to increase it using:

node --max_old_space_size=4096 ./node_modules/es6-plato/bin/plato -r -d report -e .eslintrc.json -t "MyApp" -x .json dist\MyApp\main.js.

It worked but resultant report was so big that beyond the basic summary, navigating it was causing browser to error out. Looking into it in notepad++, I found that it a lot of Angular internal code around Webpack and then a small amount of the application code.

So had to work out a better solution. Need to compile the individual TS files in to JS file and run plato only on them.

Luckily we have a tsc compiler for TS which will output the JS and then can run plato on it.
So first install:

npm install -g typescript

Now we can run the build task from VS Code directly using CTRL+SHIFT+B i.e. Run Build Task and select tsc:build

This will execute the command:

node_modules\.bin\tsc.cmd -p tsconfig.json

Depending on your tsconfig.json, your output will normally be at :

"outDir": "./dist/out-tsc",

Now when I look at ./dist/out-tsc/src/app, I see all by TS files compiled and resulting in to JS and JS.MAP files.

Now I can run plato and it does not even hit the 1.5 GB memory as it has smaller files to look into :

plato -r -d report -e .eslintrc.json -t "MyApp" -x .json dist/out-tsc/src

and see some wonderful results:



TSLint to ESLint

As a active Angular developer, maintaining a good based is pretty important. All along, the standard was TSLint which has now been deprecated in favour of ESLint.

Luckily tools are available to do the migration at : https://github.com/typescript-eslint/typescript-eslint

Unfortunately the documentation is not elaborate and did not work for me. So wanted to note down what worked for me.

First install / update your ESLint as it already has configured to support TypeScript:

npm install eslint --save-dev

Create the configuration file

node_modules\.bin\eslint --init

You can choose your options. I chose:

? How would you like to use ESLint? To check syntax and find problems
? What type of modules does your project use? JavaScript modules (import/export)
? Which framework does your project use? None of these
? Does your project use TypeScript? Yes
? Where does your code run? Browser, Node
? What format do you want your config file to be in? JSON
The config that you've selected requires the following dependencies:

@typescript-eslint/eslint-plugin@latest @typescript-eslint/parser@latest
? Would you like to install them now with npm? Yes

Installing @typescript-eslint/eslint-plugin@latest, @typescript-eslint/parser@latest

It will create a .eslintrc.json file which will look like:

{
    "env": {
        "browser": true,
        "es6": true,
        "node": true
    },
    "extends": [
        "eslint:recommended",
        "plugin:@typescript-eslint/eslint-recommended"
    ],
    "globals": {
        "Atomics": "readonly",
        "SharedArrayBuffer": "readonly"
    },
    "parser": "@typescript-eslint/parser",
    "parserOptions": {
        "ecmaVersion": 2018,
        "sourceType": "module"
    },
    "plugins": [
        "@typescript-eslint"
    ],
    "rules": {
    }
}

Now you check your file or folder :

node_modules\.bin\eslint src\app\app.component.ts

node_modules\.bin\eslint --ext .ts,.js src/

That's all good from command line. Lets not integrate it with VS Code : 

Open File -> Preferences-> Settings -> Open Settings (JSON) (on top right corner)

Append:

"eslint.validate": [
  "javascript",
  "javascriptreact",
  { "language": "typescript", "autoFix": true },
  { "language": "typescriptreact", "autoFix": true }

]