#bash (2024-05)

A channel for bash scripting

2024-05-31

Jason avatar

I need some people that know #bash please

Jason avatar

Hi guys, I need help with this bash script please. For some reason, my flags are not being passed through. I’m using getopts,

Could someone take a look and let me know where I am going wrong?

#!/bin/bash
### Pass Flags
#Define the help function
function help(){
    echo "Options:";
    echo "-rg    Resource Group Name"
    echo "-loc    Location of Resource Group"
    echo "-clus    Cluster Name"
    echo "-e    Email for LetsEncrypt"
    echo "-hos    Hostname for Nginx"
    exit 1;
}


#Initialize the default values for the variables.
rg="rg";
loc="location";
clus="cluster";
e="email";
hos="hostname";

#Define the getopts variables
options="rg:loc:clus:e:hos:h";

#Start the getopts code
while getopts $options opt; do
    case $opt in
            rg) #Get the username
                    rg=$OPTARG
            ;;
            loc) #Get the password
                    location=$OPTARG
            ;;
            clus) #Get the repository name
                    cluster=$OPTARG
            ;;
            e) #Get the service name
                    email=$OPTARG
            ;;
            hos) #Get the branch name
                    hostname=$OPTARG
            ;;
            h) #Execute the help function
        "echo here"
                    help;
            ;;
            \?) #unrecognized option - show help
                    echo "Invalid option."
                    help;
            ;;
    esac
done

#This tells getopts to move on to the next argument.
shift $((OPTIND-1))
#End getopts code


#rg="jc-test29-aks-rg"
#location="francecentral"
#cluster="jc-aks-test29-cluster"

## Create RG
echo "Creating Resource Group $rg"
az group create --name $rg --location $location

## Create AKS Cluster
echo "Creating AKS Cluster $cluster"

az aks create -g $rg -n $cluster --enable-managed-identity --node-vm-size Standard_B2s --node-count 3 --load-balancer-sku Standard

## Conect to Cluster
echo "Connecting to AKS Cluster"
az aks get-credentials --resource-group $rg --name $cluster --overwrite-existing

## Wait for the Cluster to Come online.
sleep 5m

## Add the Repos
helm repo add ingress-nginx <https://kubernetes.github.io/ingress-nginx>
helm repo add cert-manager <https://charts.jetstack.io>
helm repo add argo <https://argoproj.github.io/argo-helm>

## Install nginx-ingress
helm install nginx-ingress ingress-nginx/ingress-nginx \
--namespace ingress-nginx --create-namespace \
--set controller.replicaCount=2 \
--set controller.admissionWebhooks.patch.nodeSelector."kubernetes\.io/os"=linux \
--set controller.service.annotations."service\.beta\.kubernetes\.io/azure-load-balancer-health-probe-request-path"=/healthz \
--set controller.service.externalTrafficPolicy=Local \
--set controller.nodeSelector."kubernetes\.io/os"=linux \
--set defaultBackend.nodeSelector."kubernetes\.io/os"=linux

## Install Cert Manager
helm install cert-manager cert-manager/cert-manager \
--namespace cert-manager --create-namespace \
--version v1.14.5 \
--set nodeSelector."kubernetes\.io/os"=linux \
--set installCRDs=true \
--set 'extraArgs={--dns01-recursive-nameservers=1.1.1.1:53}'

## Install ArgoCD 
helm install argocd argo/argo-cd \
--namespace argocd --create-namespace \
--version "6.9.2" \
--set installCRDs=true \
-f argocd-values.yaml \
-f deployenvcongifmap.yaml

cat << EOF | kubectl - 
port-forward svc/argocd-server 8080:443 
EOF

<strong><a href='/git'>#git</a></strong> clone <https://github.com/cloudflare/origin-ca-issuer.git>

cd origin-ca-issuer

kubectl apply -f deploy/crds

kubectl apply -f deploy/rbac

kubectl apply -f deploy/manifests


kubectl create secret generic jasons-api-key \
    -n cert-manager\
    --from-literal api-token='VALUE'

sleep 60

cat  << EOF | kubectl apply -f -
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: lets-encrypt-jasons-cert
  namespace: cert-manager
spec:
  acme:
    email: $email
    server: <https://acme-v02.api.letsencrypt.org/directory>
    privateKeySecretRef:
      # Secret resource that will be used to store the account's private key.
      name: lets-encrypt-jasons-cert
    solvers:
    - dns01:
        cloudflare:
          email: $email
          apiTokenSecretRef:
            name: jasons-api-key
            key: api-token
      selector:
        dnsZones:
        - 'companydomain.com'
EOF

cat << EOF | kubectl apply -f -
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: letsencrypt-jasons-cert
spec:
  secretName: letsencrypt-jasons-cert
  issuerRef:
    name: lets-encrypt-jasons-cert
    kind: ClusterIssuer
  commonName: 'testing-jc2.companydomain.com'
  dnsNames:
  - 'testing-jc2.companydoamin.com'
EOF


cat << EOF | kubectl replace -f -
apiVersion: v1
kind: Service
metadata:
  labels:
    app.kubernetes.io/component: server
    app.kubernetes.io/name: argocd-server
    app.kubernetes.io/part-of: argocd
  name: argocd-server
  namespace: argocd
spec:
  ports:
    - name: http
      port: 80
      protocol: TCP
      targetPort: 8080
    - name: https
      port: 443
      protocol: TCP
      targetPort: 8080
  selector:
    app.kubernetes.io/name: argocd-server
EOF

cat << EOF | kubectl apply -f - 
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: argocd-server-ingress
  namespace: argocd
  annotations:
    cert-manager.io/cluster-issuer: lets-encrypt-jasons-cert
    kubernetes.io/ingress.class: nginx
    kubernetes.io/tls-acme: 'true'
    nginx.ingress.kubernetes.io/ssl-passthrough: 'true'
    nginx.ingress.kubernetes.io/backend-protocol: 'HTTPS'
spec:
  rules:
    - host: $hostname
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: argocd-server
                port:
                  name: https
  tls:
    - hosts:
        - $hostname
      secretName: argocdingress-cert
EOF

echo "Deployment Complete"
Erik Osterman (Cloud Posse) avatar
Erik Osterman (Cloud Posse)
What is a reason for using shift $((OPTIND-1)) after getopts?

I realise that shift moves the array of cli args n space to the left, and the default of n is 1. This means I can assign the values the array to existing varibles using $1 shift inside a whil…

Jason avatar

thanks I solved it now

Erik Osterman (Cloud Posse) avatar
Erik Osterman (Cloud Posse)

What was the problem?

Jason avatar
Bash Flags are not passing through

I need help with this bash script please. For some reason, my flags are not being passed through. I’m using the unix getopts function, Could someone take a look and let me know where I am going wro…

Erik Osterman (Cloud Posse) avatar
Erik Osterman (Cloud Posse)

ah yes…. easily mistaken.

Erik Osterman (Cloud Posse) avatar
Erik Osterman (Cloud Posse)

Glad you figured it out.

Jason avatar

Well it was with the help of someone on the Mac Admins slack As that was the first time I had worked with CLI parameters in Bash

1
Jason avatar

Now I cant get Terraform to run the stupid script!!

Jason avatar

Script works fine outside of terraform but it refuses to run it.

Jason avatar

When it did run once it gave me a silly error about the script does not come back.

Hao Wang avatar
Hao Wang

can TF_LOG flag work?

Hao Wang avatar
Hao Wang

yeah getopts is not easy to work with

Erik Osterman (Cloud Posse) avatar
Erik Osterman (Cloud Posse)


When it did run once it gave me a silly error about the script does not come back.
What’s the silly error?

GFox)(AWSDevSecOps avatar
GFox)(AWSDevSecOps

Curious is my wash :soap: thru ChatGPT turned out the fix; I have worked in Azure in about 2-3 years so not sure :thinking_face:

Issues with the Script

Here are some of the issues with your script and how to fix them:

  1. getopts Syntax: ◦ The getopts options string should include colons after options that expect arguments. For example, rg:loc:clus:e:hos:h should be r:l:c:e:h:o:.
  2. Variable Assignment in getopts: ◦ The variable names used in the case statements should match the initialized variable names. For example, loc should match location.
  3. Missing Double Quotes: ◦ Always use double quotes around variable expansions to prevent word splitting and globbing issues.
  4. Help Function Call: ◦ Remove the "echo here" line and ensure proper indentation. Here’s a corrected version of your script:
bash
#!/bin/bash

# Define the help function
function help(){
    echo "Options:"
    echo "-r    Resource Group Name"
    echo "-l    Location of Resource Group"
    echo "-c    Cluster Name"
    echo "-e    Email for LetsEncrypt"
    echo "-o    Hostname for Nginx"
    exit 1
}

# Initialize the default values for the variables
rg="rg"
loc="location"
clus="cluster"
e="email"
hos="hostname"

# Define the getopts variables
options="r:l:c:e:o:h"

# Start the getopts code
while getopts $options opt; do
    case $opt in
        r) # Get the resource group name
            rg="$OPTARG"
        ;;
        l) # Get the location
            loc="$OPTARG"
        ;;
        c) # Get the cluster name
            clus="$OPTARG"
        ;;
        e) # Get the email
            e="$OPTARG"
        ;;
        o) # Get the hostname
            hos="$OPTARG"
        ;;
        h) # Execute the help function
            help
        ;;
        \?) # Unrecognized option - show help
            echo "Invalid option."
            help
        ;;
    esac
done

# This tells getopts to move on to the next argument.
shift $((OPTIND-1))

# Create Resource Group
echo "Creating Resource Group $rg"
az group create --name "$rg" --location "$loc"

# Create AKS Cluster
echo "Creating AKS Cluster $clus"
az aks create -g "$rg" -n "$clus" --enable-managed-identity --node-vm-size Standard_B2s --node-count 3 --load-balancer-sku Standard

# Connect to Cluster
echo "Connecting to AKS Cluster"
az aks get-credentials --resource-group "$rg" --name "$clus" --overwrite-existing

# Wait for the Cluster to Come online
sleep 5m

# Add the Repos
helm repo add ingress-nginx <https://kube><https://kubernetes.github.io/ingress-nginx|rnetes.github.io/ingress-nginx
helm repo a>dd cert-manager <https://char><https://charts.jetstack.io|ts.jetstack.io
helm repo a>dd argo <https://argo><https://argoproj.github.io/argo-helm|proj.github.io/argo-helm

# Install >nginx-ingress
helm install nginx-ingress ingress-nginx/ingress-nginx \
--namespace ingress-nginx --create-namespace \
--set controller.replicaCount=2 \
--set controller.admissionWebhooks.patch.nodeSelector."kubernetes\.io/os"=linux \
--set controller.service.annotations."service\.beta\.kubernetes\.io/azure-load-balancer-health-probe-request-path"=/healthz \
--set controller.service.externalTrafficPolicy=Local \
--set controller.nodeSelector."kubernetes\.io/os"=linux \
--set defaultBackend.nodeSelector."kubernetes\.io/os"=linux

# Install Cert Manager
helm install cert-manager cert-manager/cert-manager \
--namespace cert-manager --create-namespace \
--version v1.14.5 \
--set nodeSelector."kubernetes\.io/os"=linux \
--set installCRDs=true \
--set 'extraArgs={--dns01-recursive-nameservers=1.1.1.1:53}'

# Install ArgoCD
helm install argocd argo/argo-cd \
--namespace argocd --create-namespace \
--version "6.9.2" \
--set installCRDs=true \
-f argocd-values.yaml \
-f deployenvcongifmap.yaml

kubectl port-forward svc/argocd-server 8080:443 &

# Assuming you have the repository cloned in the current directory
cd origin-ca-issuer

kubectl apply -f deploy/crds
kubectl apply -f deploy/rbac
kubectl apply -f deploy/manifests

kubectl create secret generic jasons-api-key \
    -n cert-manager \
    --from-literal api-token='VALUE'

sleep 60

cat << EOF | kubectl apply -f -
apiVersion: cert-manager<http://cert-manager.io/v1|.io/v1
kind: Clust>erIssuer
metadata:
  name: lets-encrypt-jasons-cert
  namespace: cert-manager
spec:
  acme:
    email: $e
    server: <https://acme><https://acme-v02.api.letsencrypt.org/directory|-v02.api.letsencrypt.org/directory
    private>KeySecretRef:
      name: lets-encrypt-jasons-cert
    solvers:
    ◦ dns01:
        cloudflare:
          email: $e
          apiTokenSecretRef:
            name: jasons-api-key
            key: api-token
      selector:
        dnsZones:
        ▪︎ 'companydomain.com'
EOF

cat << EOF | kubectl apply -f -
apiVersion: cert-manager.io/v1
kind:<http://cert-manager.io/v1| Certificate
metad>ata:
  name: letsencrypt-jasons-cert
spec:
  secretName: letsencrypt-jasons-cert
  issuerRef:
    name: lets-encrypt-jasons-cert
    kind: ClusterIssuer
  commonName: 'testing-jc2.companydomai<http://testing-jc2.companydomain.com|n.com'
  dnsNames:
>
• 'testing-jc2.companydoamin.com'
<<http://testing-jc2.companydoamin.com>|EOF

cat << EOF | kubect>l replace -f -
apiVersion: v1
kind: Service
metadata:
  labels:
    app.kubernetes.io/componen<http://app.kubernetes.io/component:|t: server
    app.kubernetes>.io/name: ar<http://app.kubernetes.io/name:|gocd-server
    app.kub>ernetes.io/part-of:<http://app.kubernetes.io/part-of:| argocd
  name: argocd-ser>ver
  namespace: argocd
spec:
  ports:
    ◦ name: http
      port: 80
      protocol: TCP
      targetPort: 8080
    ◦ name: https
      port: 443
      protocol: TCP
      targetPort: 8080
  selector:
    app.kubernetes.io/name: argocd-ser<<http://app.kubernetes.io/name:%7Cver>
EOF

cat << EOF | k>ubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: Ingress<http://networking.k8s.io/v1|
metadata:
  name: a>rgocd-server-ingress
  namespace: argocd
  annotations:
    cert-manager.io/cluster-issuer: le<http://cert-manager.io/cluster-issuer:|ts-encrypt-jasons-cert
    kube>rnetes.io/ingress.class: nginx<http://kubernetes.io/ingress.class:|
    kubernetes.io/tls-acme:> 'true'
    nginx.ingress.kubernetes.io/ssl-pa<http://nginx.ingress.kubernetes.io/ssl-passthrough:|ssthrough: 'true'
    nginx.ingress.kubernet>es.io/backen<http://nginx.ingress.kubernetes.io/backend-protocol:|d-protocol: 'HTTPS'
spec:
  rules:
>
    ◦ host: $hos
      http:
        paths:
            • path: /
            pathType: Prefix
            backend:
              service:
                name: argocd-server
                port:
                  name: https
  tls:
    ◦ hosts:
        ▪︎ $hos
      secretName: argocdingress-cert
EOF

echo "Deployment Complete"

Changes Made:

  1. Corrected the getopts options string to include colons for arguments.
  2. Matched variable names in case statements to initialized variables.
  3. Added double quotes around variable expansions.
  4. Removed unnecessary echo statement and ensured proper indentation and spacing. By correcting these issues, the script should now properly handle the flags and pass them through as intended.
    keyboard_arrow_up