This is an automated email from the ASF dual-hosted git repository.

lhotari pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/pulsar-helm-chart.git


The following commit(s) were added to refs/heads/master by this push:
     new 800e18b  Apply ShellCheck suggested fixes to pulsar Bash scripts (#663)
800e18b is described below

commit 800e18b420a3b3bf5ca6cd2f853f32ac34b9aa9f
Author: frankgrimes97 <[email protected]>
AuthorDate: Wed Mar 18 18:09:24 2026 +0000

    Apply ShellCheck suggested fixes to pulsar Bash scripts (#663)
    
    ShellCheck: https://github.com/koalaman/shellcheck
    
    Also suppressed a few ShellCheck warnings where deemed necessary.
---
 .ci/chart_test.sh                                  |  15 +-
 .ci/configure_ci_runner_for_debugging.sh           |   6 +-
 .ci/helm.sh                                        | 256 +++++++++++----------
 hack/common.sh                                     |  40 ++--
 hack/kind-cluster-build.sh                         |  43 ++--
 scripts/cert-manager/install-cert-manager.sh       |   3 +-
 scripts/pulsar/cleanup_helm_release.sh             |   8 +-
 scripts/pulsar/common.sh                           |   4 +-
 scripts/pulsar/common_auth.sh                      |   3 +-
 scripts/pulsar/generate_token.sh                   |  41 ++--
 scripts/pulsar/generate_token_secret_key.sh        |  32 +--
 scripts/pulsar/get_token.sh                        |  12 +-
 scripts/pulsar/prepare_helm_release.sh             |  19 +-
 scripts/set-pulsar-version.sh                      |   2 +-
 .../resolve_vm_operator_version.sh                 |   4 +-
 15 files changed, 255 insertions(+), 233 deletions(-)

diff --git a/.ci/chart_test.sh b/.ci/chart_test.sh
index c61da42..3cef385 100755
--- a/.ci/chart_test.sh
+++ b/.ci/chart_test.sh
@@ -30,7 +30,8 @@ FUNCTION=${FUNCTION:-"false"}
 MANAGER=${MANAGER:-"false"}
 ALLOW_LOADBALANCERS=${ALLOW_LOADBALANCERS:-"false"}
 
-source ${PULSAR_HOME}/.ci/helm.sh
+# shellcheck source=.ci/helm.sh
+source "${PULSAR_HOME}"/.ci/helm.sh
 
 # create cluster
 ci::create_cluster
@@ -46,11 +47,11 @@ while [[ $# -gt 0 ]]; do
     shift
 done
 
-if [[ "x${SYMMETRIC}" == "xtrue" ]]; then
+if [[ "${SYMMETRIC}" == "true" ]]; then
     extra_opts+=("-s")
 fi
 
-if [[ "x${EXTRA_SUPERUSERS}" != "x" ]]; then
+if [[ "${EXTRA_SUPERUSERS}" != "" ]]; then
     extra_opts+=("--pulsar-superusers" 
"proxy-admin,broker-admin,admin,${EXTRA_SUPERUSERS}")
 fi
 
@@ -62,9 +63,9 @@ if [[ "$UPGRADE_FROM_VERSION" != "" ]]; then
     PULSAR_CHART_VERSION="$UPGRADE_FROM_VERSION"
 
     # Install Prometheus Operator CRDs using the upgrade script since 
kube-prometheus-stack is now disabled before the upgrade
-    
${PULSAR_HOME}/scripts/kube-prometheus-stack/upgrade_prometheus_operator_crds.sh
+    
"${PULSAR_HOME}"/scripts/kube-prometheus-stack/upgrade_prometheus_operator_crds.sh
 
-    ci::install_pulsar_chart install ${PULSAR_HOME}/.ci/values-common.yaml 
${PULSAR_HOME}/${VALUES_FILE} --set kube-prometheus-stack.enabled=false 
"${extra_opts[@]}"
+    ci::install_pulsar_chart install "${PULSAR_HOME}"/.ci/values-common.yaml 
"${PULSAR_HOME}"/"${VALUES_FILE}" --set kube-prometheus-stack.enabled=false 
"${extra_opts[@]}"
     install_type="upgrade"
     echo "Wait 10 seconds"
     sleep 10
@@ -78,13 +79,13 @@ if [[ "$UPGRADE_FROM_VERSION" != "" ]]; then
 
     if [[ "$(ci::helm_values_for_deployment | yq 
.victoria-metrics-k8s-stack.enabled)" == "true" ]]; then
         echo "Upgrade Victoria Metrics Operator CRDs before upgrading the 
deployment"
-        
${PULSAR_HOME}/scripts/victoria-metrics-k8s-stack/upgrade_vm_operator_crds.sh
+        
"${PULSAR_HOME}"/scripts/victoria-metrics-k8s-stack/upgrade_vm_operator_crds.sh
     fi
 fi
 
 PULSAR_CHART_VERSION="local"
 # install (or upgrade) pulsar chart
-ci::install_pulsar_chart ${install_type} ${PULSAR_HOME}/.ci/values-common.yaml 
${PULSAR_HOME}/${VALUES_FILE} "${extra_opts[@]}"
+ci::install_pulsar_chart "${install_type}" 
"${PULSAR_HOME}"/.ci/values-common.yaml "${PULSAR_HOME}"/"${VALUES_FILE}" 
"${extra_opts[@]}"
 
 echo "Wait 10 seconds"
 sleep 10
diff --git a/.ci/configure_ci_runner_for_debugging.sh 
b/.ci/configure_ci_runner_for_debugging.sh
index 9c61bca..cca9b32 100755
--- a/.ci/configure_ci_runner_for_debugging.sh
+++ b/.ci/configure_ci_runner_for_debugging.sh
@@ -6,7 +6,7 @@ if [[ -z "${GITHUB_ACTIONS}" ]]; then
     exit 1
 fi
 
-cat >> $HOME/.bashrc <<'EOF'
+cat >> "$HOME"/.bashrc <<'EOF'
 function use_kind_kubeconfig() {
     export KUBECONFIG=$(ls $HOME/kind/pulsar-ci-*/kubeconfig.yaml)
 }
@@ -34,8 +34,8 @@ function k9s() {
 
 alias k=kubectl
 EOF
-cat >> $HOME/.bash_profile <<'EOF'
+cat >> "$HOME"/.bash_profile <<'EOF'
 if [ -f ~/.bashrc ]; then
     source ~/.bashrc
 fi
-EOF
\ No newline at end of file
+EOF
diff --git a/.ci/helm.sh b/.ci/helm.sh
index 833d823..8e5be40 100755
--- a/.ci/helm.sh
+++ b/.ci/helm.sh
@@ -23,12 +23,13 @@ CHARTS_HOME=${PULSAR_HOME}
 PULSAR_CHART_LOCAL=${CHARTS_HOME}/charts/pulsar
 PULSAR_CHART_VERSION=${PULSAR_CHART_VERSION:-"local"}
 OUTPUT_BIN=${CHARTS_HOME}/output/bin
+# shellcheck disable=SC2034
 KIND_BIN=$OUTPUT_BIN/kind
 HELM=${OUTPUT_BIN}/helm
-: ${KUBECTL:=$OUTPUT_BIN/kubectl}
-: ${NAMESPACE:=pulsar}
+: "${KUBECTL:=$OUTPUT_BIN/kubectl}"
+: "${NAMESPACE:=pulsar}"
 CLUSTER=pulsar-ci
-: ${CLUSTER_ID:=$(uuidgen)}
+: "${CLUSTER_ID:=$(uuidgen)}"
 K8S_LOGS_DIR="${K8S_LOGS_DIR:-/tmp/k8s-logs}"
 export PATH="$OUTPUT_BIN:$PATH"
 
@@ -56,23 +57,23 @@ fi
 
 function ci::create_cluster() {
     echo "Creating a kind cluster ..."
-    ${CHARTS_HOME}/hack/kind-cluster-build.sh --name pulsar-ci-${CLUSTER_ID} 
-c 1 -v 10
+    "${CHARTS_HOME}"/hack/kind-cluster-build.sh --name 
pulsar-ci-"${CLUSTER_ID}" -c 1 -v 10
     echo "Successfully created a kind cluster."
 }
 
 function ci::delete_cluster() {
     echo "Deleting a kind cluster ..."
-    kind delete cluster --name=pulsar-ci-${CLUSTER_ID}
+    kind delete cluster --name=pulsar-ci-"${CLUSTER_ID}"
     echo "Successfully delete a kind cluster."
 }
 
 function ci::install_cert_manager() {
     echo "Installing the cert-manager ..."
     ${KUBECTL} create namespace cert-manager
-    ${CHARTS_HOME}/scripts/cert-manager/install-cert-manager.sh
+    "${CHARTS_HOME}"/scripts/cert-manager/install-cert-manager.sh
     WC=$(${KUBECTL} get pods -n cert-manager 
--field-selector=status.phase=Running | wc -l)
     while [[ ${WC} -lt 3 ]]; do
-      echo ${WC};
+      echo "${WC}";
       sleep 15
       ${KUBECTL} get pods -n cert-manager
       ${KUBECTL} get events --sort-by=.lastTimestamp -A | tail -n 30 || true
@@ -92,22 +93,22 @@ function ci::helm_repo_add() {
 
 function ci::print_pod_logs() {
     echo "Logs for all containers:"
-    for k8sobject in $(${KUBECTL} get pods,jobs -n ${NAMESPACE} -o=name); do
-      ${KUBECTL} logs -n ${NAMESPACE} "$k8sobject" --all-containers=true 
--ignore-errors=true --prefix=true --tail=100 || true
+    for k8sobject in $(${KUBECTL} get pods,jobs -n "${NAMESPACE}" -o=name); do
+      ${KUBECTL} logs -n "${NAMESPACE}" "$k8sobject" --all-containers=true 
--ignore-errors=true --prefix=true --tail=100 || true
     done;
 }
 
 function ci::collect_k8s_logs() {
-    mkdir -p "${K8S_LOGS_DIR}" && cd "${K8S_LOGS_DIR}"
+    mkdir -p "${K8S_LOGS_DIR}" && cd "${K8S_LOGS_DIR}" || exit
     echo "Collecting k8s logs to ${K8S_LOGS_DIR}"
-    for k8sobject in $(${KUBECTL} get pods,jobs -n ${NAMESPACE} -o=name); do
+    for k8sobject in $(${KUBECTL} get pods,jobs -n "${NAMESPACE}" -o=name); do
       filebase="${k8sobject//\//_}"
-      ${KUBECTL} logs -n ${NAMESPACE} "$k8sobject" --all-containers=true 
--ignore-errors=true --prefix=true > "${filebase}.$$.log.txt" || true
-      ${KUBECTL} logs -n ${NAMESPACE} "$k8sobject" --all-containers=true 
--ignore-errors=true --prefix=true --previous=true > 
"${filebase}.previous.$$.log.txt" || true
+      ${KUBECTL} logs -n "${NAMESPACE}" "$k8sobject" --all-containers=true 
--ignore-errors=true --prefix=true > "${filebase}.$$.log.txt" || true
+      ${KUBECTL} logs -n "${NAMESPACE}" "$k8sobject" --all-containers=true 
--ignore-errors=true --prefix=true --previous=true > 
"${filebase}.previous.$$.log.txt" || true
     done;
     ${KUBECTL} get events --sort-by=.lastTimestamp -A > events.$$.log.txt || 
true
     ${KUBECTL} get events --sort-by=.lastTimestamp -A -o yaml > 
events.$$.log.yaml || true
-    ${KUBECTL} get -n ${NAMESPACE} all -o yaml > k8s_resources.$$.yaml || true
+    ${KUBECTL} get -n "${NAMESPACE}" all -o yaml > k8s_resources.$$.yaml || 
true
 }
 
 function ci::install_pulsar_chart() {
@@ -129,14 +130,14 @@ function ci::install_pulsar_chart() {
             extra_opts+=("$arg")
         fi
     done
-    local install_args
+    local -a install_args
 
     if [[ "${install_type}" == "install" ]]; then
       echo "Installing the pulsar chart"
-      ${KUBECTL} create namespace ${NAMESPACE}
+      ${KUBECTL} create namespace "${NAMESPACE}"
       ci::install_cert_manager
-      echo ${CHARTS_HOME}/scripts/pulsar/prepare_helm_release.sh -k ${CLUSTER} 
-n ${NAMESPACE} "${extra_opts[@]}"
-      ${CHARTS_HOME}/scripts/pulsar/prepare_helm_release.sh -k ${CLUSTER} -n 
${NAMESPACE} "${extra_opts[@]}"
+      echo "${CHARTS_HOME}"/scripts/pulsar/prepare_helm_release.sh -k 
"${CLUSTER}" -n "${NAMESPACE}" "${extra_opts[@]}"
+      "${CHARTS_HOME}"/scripts/pulsar/prepare_helm_release.sh -k "${CLUSTER}" 
-n "${NAMESPACE}" "${extra_opts[@]}"
       sleep 10
 
       # install metallb for loadbalancer support
@@ -148,46 +149,46 @@ function ci::install_pulsar_chart() {
                 --selector=app=metallb \
                 --timeout=120s
       # configure metallb
-      ${KUBECTL} apply -f ${BINDIR}/metallb/metallb-config.yaml
-      install_args=""
+      ${KUBECTL} apply -f "${BINDIR}"/metallb/metallb-config.yaml
 
       # create auth resources
-      if [[ "x${AUTHENTICATION_PROVIDER}" == "xopenid" ]]; then
+      if [[ "${AUTHENTICATION_PROVIDER}" == "openid" ]]; then
           ci::create_openid_resources
       fi
     else
-      install_args="--wait --wait-for-jobs --timeout 360s --debug"
+      install_args+=("--wait" "--wait-for-jobs" "--timeout=360s" "--debug")
     fi
 
-    CHART_ARGS=""
+    declare -a CHART_ARGS
     if [[ "${PULSAR_CHART_VERSION}" == "local" ]]; then
       set -x
-      ${HELM} dependency update ${PULSAR_CHART_LOCAL}
+      ${HELM} dependency update "${PULSAR_CHART_LOCAL}"
       set +x
-      CHART_ARGS="${PULSAR_CHART_LOCAL}"
+      CHART_ARGS+=("${PULSAR_CHART_LOCAL}")
     else
       set -x
       ${HELM} repo add apache https://pulsar.apache.org/charts
       set +x
-      CHART_ARGS="apache/pulsar --dependency-update"
+      CHART_ARGS+=("apache/pulsar" "--dependency-update")
       if [[ "${PULSAR_CHART_VERSION}" != "latest" ]]; then
-        CHART_ARGS="${CHART_ARGS} --version ${PULSAR_CHART_VERSION}"
+        CHART_ARGS+=("--version=${PULSAR_CHART_VERSION}")
       fi
     fi
     set -x
-    ${HELM} template --values ${common_value_file} --values ${value_file} 
"${extra_values[@]}" ${CLUSTER} ${CHART_ARGS}
-    ${HELM} ${install_type} --values ${common_value_file} --values 
${value_file} "${extra_values[@]}" --namespace=${NAMESPACE} ${CLUSTER} 
${CHART_ARGS} ${install_args}
+    ${HELM} template --values "${common_value_file}" --values "${value_file}" 
"${extra_values[@]}" "${CLUSTER}" "${CHART_ARGS[@]}"
+    ${HELM} "${install_type}" --values "${common_value_file}" --values 
"${value_file}" "${extra_values[@]}" --namespace="${NAMESPACE}" "${CLUSTER}" 
"${CHART_ARGS[@]}" "${install_args[@]}"
     set +x
 
     if [[ "${install_type}" == "install" ]]; then
       echo "wait until broker is alive"
-      WC=$(${KUBECTL} get pods -n ${NAMESPACE} 
--field-selector=status.phase=Running | grep ${CLUSTER}-broker | wc -l)
+      # shellcheck disable=SC2126
+      WC=$(${KUBECTL} get pods -n "${NAMESPACE}" 
--field-selector=status.phase=Running | grep "${CLUSTER}"-broker | wc -l)
       counter=1
       while [[ ${WC} -lt 1 ]]; do
         ((counter++))
-        echo ${WC};
+        echo "${WC}";
         sleep 15
-        ${KUBECTL} get pods,jobs -n ${NAMESPACE}
+        ${KUBECTL} get pods,jobs -n "${NAMESPACE}"
         ${KUBECTL} get events --sort-by=.lastTimestamp -A | tail -n 30 || true
         if [[ $((counter % 20)) -eq 0 ]]; then
           ci::print_pod_logs
@@ -196,23 +197,27 @@ function ci::install_pulsar_chart() {
             exit 1
           fi
         fi
-        WC=$(${KUBECTL} get pods -n ${NAMESPACE} | grep ${CLUSTER}-broker | wc 
-l)
+        # shellcheck disable=SC2126
+        WC=$(${KUBECTL} get pods -n "${NAMESPACE}" | grep "${CLUSTER}"-broker 
| wc -l)
         if [[ ${WC} -gt 1 ]]; then
-          ${KUBECTL} describe pod -n ${NAMESPACE} pulsar-ci-broker-0
-          ${KUBECTL} logs -n ${NAMESPACE} pulsar-ci-broker-0
+          ${KUBECTL} describe pod -n "${NAMESPACE}" pulsar-ci-broker-0
+          ${KUBECTL} logs -n "${NAMESPACE}" pulsar-ci-broker-0
         fi
-        WC=$(${KUBECTL} get pods -n ${NAMESPACE} 
--field-selector=status.phase=Running | grep ${CLUSTER}-broker | wc -l)
+        # shellcheck disable=SC2126
+        WC=$(${KUBECTL} get pods -n "${NAMESPACE}" 
--field-selector=status.phase=Running | grep "${CLUSTER}"-broker | wc -l)
       done
-      timeout 300s ${KUBECTL} exec -n ${NAMESPACE} ${CLUSTER}-toolset-0 -- 
bash -c 'until nslookup pulsar-ci-broker; do sleep 3; done' || { echo >&2 
"Timeout waiting..."; ci::print_pod_logs; exit 1; }
-      timeout 120s ${KUBECTL} exec -n ${NAMESPACE} ${CLUSTER}-toolset-0 -- 
bash -c 'until [ "$(curl -s -L http://pulsar-ci-broker:8080/status.html)" == 
"OK" ]; do sleep 3; done' || { echo >&2 "Timeout waiting..."; 
ci::print_pod_logs; exit 1; }
+      timeout 300s "${KUBECTL}" exec -n "${NAMESPACE}" "${CLUSTER}"-toolset-0 
-- bash -c 'until nslookup pulsar-ci-broker; do sleep 3; done' || { echo >&2 
"Timeout waiting..."; ci::print_pod_logs; exit 1; }
+      # shellcheck disable=SC2016
+      timeout 120s "${KUBECTL}" exec -n "${NAMESPACE}" "${CLUSTER}"-toolset-0 
-- bash -c 'until [ "$(curl -s -L http://pulsar-ci-broker:8080/status.html)" == 
"OK" ]; do sleep 3; done' || { echo >&2 "Timeout waiting..."; 
ci::print_pod_logs; exit 1; }
 
-      WC=$(${KUBECTL} get pods -n ${NAMESPACE} 
--field-selector=status.phase=Running | grep ${CLUSTER}-proxy | wc -l)
+      # shellcheck disable=SC2126
+      WC=$(${KUBECTL} get pods -n "${NAMESPACE}" 
--field-selector=status.phase=Running | grep "${CLUSTER}"-proxy | wc -l)
       counter=1
       while [[ ${WC} -lt 1 ]]; do
         ((counter++))
-        echo ${WC};
+        echo "${WC}";
         sleep 15
-        ${KUBECTL} get pods,jobs -n ${NAMESPACE}
+        ${KUBECTL} get pods,jobs -n "${NAMESPACE}"
         ${KUBECTL} get events --sort-by=.lastTimestamp -A | tail -n 30 || true
         if [[ $((counter % 8)) -eq 0 ]]; then
           ci::print_pod_logs
@@ -221,16 +226,18 @@ function ci::install_pulsar_chart() {
             exit 1
           fi
         fi
-        WC=$(${KUBECTL} get pods -n ${NAMESPACE} 
--field-selector=status.phase=Running | grep ${CLUSTER}-proxy | wc -l)
+        # shellcheck disable=SC2126
+        WC=$(${KUBECTL} get pods -n "${NAMESPACE}" 
--field-selector=status.phase=Running | grep ${CLUSTER}-proxy | wc -l)
       done
-      timeout 300s ${KUBECTL} exec -n ${NAMESPACE} ${CLUSTER}-toolset-0 -- 
bash -c 'until nslookup pulsar-ci-proxy; do sleep 3; done' || { echo >&2 
"Timeout waiting..."; ci::print_pod_logs; exit 1; }
+      timeout 300s "${KUBECTL}" exec -n "${NAMESPACE}" "${CLUSTER}"-toolset-0 
-- bash -c 'until nslookup pulsar-ci-proxy; do sleep 3; done' || { echo >&2 
"Timeout waiting..."; ci::print_pod_logs; exit 1; }
       echo "Install complete"
     else
       echo "wait until broker is alive"
-      timeout 300s ${KUBECTL} exec -n ${NAMESPACE} ${CLUSTER}-toolset-0 -- 
bash -c 'until nslookup pulsar-ci-broker; do sleep 3; done' || { echo >&2 
"Timeout waiting..."; ci::print_pod_logs; exit 1; }
-      timeout 120s ${KUBECTL} exec -n ${NAMESPACE} ${CLUSTER}-toolset-0 -- 
bash -c 'until [ "$(curl -s -L http://pulsar-ci-broker:8080/status.html)" == 
"OK" ]; do sleep 3; done' || { echo >&2 "Timeout waiting..."; 
ci::print_pod_logs; exit 1; }
+      timeout 300s "${KUBECTL}" exec -n "${NAMESPACE}" "${CLUSTER}"-toolset-0 
-- bash -c 'until nslookup pulsar-ci-broker; do sleep 3; done' || { echo >&2 
"Timeout waiting..."; ci::print_pod_logs; exit 1; }
+      # shellcheck disable=SC2016
+      timeout 120s "${KUBECTL}" exec -n "${NAMESPACE}" "${CLUSTER}"-toolset-0 
-- bash -c 'until [ "$(curl -s -L http://pulsar-ci-broker:8080/status.html)" == 
"OK" ]; do sleep 3; done' || { echo >&2 "Timeout waiting..."; 
ci::print_pod_logs; exit 1; }
       echo "wait until proxy is alive"
-      timeout 300s ${KUBECTL} exec -n ${NAMESPACE} ${CLUSTER}-toolset-0 -- 
bash -c 'until nslookup pulsar-ci-proxy; do sleep 3; done' || { echo >&2 
"Timeout waiting..."; ci::print_pod_logs; exit 1; }
+      timeout 300s "${KUBECTL}" exec -n "${NAMESPACE}" "${CLUSTER}"-toolset-0 
-- bash -c 'until nslookup pulsar-ci-proxy; do sleep 3; done' || { echo >&2 
"Timeout waiting..."; ci::print_pod_logs; exit 1; }
       echo "Upgrade complete"
     fi
 }
@@ -239,27 +246,28 @@ helm_values_cached=""
 
 function ci::helm_values_for_deployment() {
     if [[ -z "${helm_values_cached}" ]]; then
-        helm_values_cached=$(helm get values -n ${NAMESPACE} ${CLUSTER} -a -o 
yaml)
+        helm_values_cached=$(helm get values -n "${NAMESPACE}" "${CLUSTER}" -a 
-o yaml)
     fi
     printf "%s" "${helm_values_cached}"
 }
 
 function ci::check_pulsar_environment() {
     echo "Wait until pulsar-ci-broker is ready"
-    ${KUBECTL} exec -n ${NAMESPACE} ${CLUSTER}-toolset-0 -- bash -c 'until 
nslookup pulsar-ci-broker; do sleep 3; done'
+    ${KUBECTL} exec -n "${NAMESPACE}" "${CLUSTER}"-toolset-0 -- bash -c 'until 
nslookup pulsar-ci-broker; do sleep 3; done'
     echo "Wait until pulsar-ci-proxy is ready"
-    ${KUBECTL} exec -n ${NAMESPACE} ${CLUSTER}-toolset-0 -- bash -c 'until 
nslookup pulsar-ci-proxy; do sleep 3; done'
+    ${KUBECTL} exec -n "${NAMESPACE}" "${CLUSTER}"-toolset-0 -- bash -c 'until 
nslookup pulsar-ci-proxy; do sleep 3; done'
     echo "bookie-0 disk usage"
-    ${KUBECTL} exec -n ${NAMESPACE} ${CLUSTER}-bookie-0 -- df -h
+    ${KUBECTL} exec -n "${NAMESPACE}" "${CLUSTER}"-bookie-0 -- df -h
     echo "bookie-0 bookkeeper.conf"
-    ${KUBECTL} exec -n ${NAMESPACE} ${CLUSTER}-bookie-0 -- cat 
conf/bookkeeper.conf
+    ${KUBECTL} exec -n "${NAMESPACE}" "${CLUSTER}"-bookie-0 -- cat 
conf/bookkeeper.conf
     echo "bookie-0 bookies list (rw)"
-    ${KUBECTL} exec -n ${NAMESPACE} ${CLUSTER}-toolset-0 -- bin/bookkeeper 
shell listbookies -rw | grep ListBookiesCommand
+    ${KUBECTL} exec -n "${NAMESPACE}" "${CLUSTER}"-toolset-0 -- bin/bookkeeper 
shell listbookies -rw | grep ListBookiesCommand
     echo "bookie-0 bookies list (ro)"
-    ${KUBECTL} exec -n ${NAMESPACE} ${CLUSTER}-toolset-0 -- bin/bookkeeper 
shell listbookies -ro | grep ListBookiesCommand
+    ${KUBECTL} exec -n "${NAMESPACE}" "${CLUSTER}"-toolset-0 -- bin/bookkeeper 
shell listbookies -ro | grep ListBookiesCommand
 }
 
 # function to retry a given commend 3 times with a backoff of 10 seconds in 
between
+# shellcheck disable=SC2015
 function ci::retry() {
   local n=1
   local max=3
@@ -279,12 +287,12 @@ function ci::retry() {
 
 function ci::test_pulsar_admin_api_access() {
   echo "Test pulsar admin api access"
-  ci::retry ${KUBECTL} exec -n ${NAMESPACE} ${CLUSTER}-toolset-0 -- 
bin/pulsar-admin tenants list
+  ci::retry "${KUBECTL}" exec -n "${NAMESPACE}" "${CLUSTER}"-toolset-0 -- 
bin/pulsar-admin tenants list
 }
 
 function ci::test_create_test_namespace() {
-    ${KUBECTL} exec -n ${NAMESPACE} ${CLUSTER}-toolset-0 -- bin/pulsar-admin 
tenants create pulsar-ci
-    ${KUBECTL} exec -n ${NAMESPACE} ${CLUSTER}-toolset-0 -- bin/pulsar-admin 
namespaces create pulsar-ci/test
+    "${KUBECTL}" exec -n "${NAMESPACE}" "${CLUSTER}"-toolset-0 -- 
bin/pulsar-admin tenants create pulsar-ci
+    "${KUBECTL}" exec -n "${NAMESPACE}" "${CLUSTER}"-toolset-0 -- 
bin/pulsar-admin namespaces create pulsar-ci/test
 }
 
 function ci::test_pulsar_producer_consumer() {
@@ -298,23 +306,24 @@ function ci::test_pulsar_producer_consumer() {
     set -x
     if [[ "${action}" == "produce" || "${action}" == "produce-consume" ]]; then
       ci::test_create_test_namespace
-      ${KUBECTL} exec -n ${NAMESPACE} ${CLUSTER}-toolset-0 -- bin/pulsar-admin 
topics create pulsar-ci/test/test-topic
-      ${KUBECTL} exec -n ${NAMESPACE} ${CLUSTER}-toolset-0 -- bin/pulsar-admin 
topics create-subscription -s test pulsar-ci/test/test-topic
-      ${KUBECTL} exec -n ${NAMESPACE} ${CLUSTER}-toolset-0 -- 
bin/pulsar-client produce -m "test-message" pulsar-ci/test/test-topic
-      ${KUBECTL} exec -n ${NAMESPACE} ${CLUSTER}-toolset-0 -- bin/pulsar-admin 
topics create-subscription -s test2 pulsar-ci/test/test-topic
-      ${KUBECTL} exec -n ${NAMESPACE} ${CLUSTER}-toolset-0 -- 
bin/pulsar-client --url "${PROXY_URL}" produce -m "test-message2" 
pulsar-ci/test/test-topic
+      "${KUBECTL}" exec -n "${NAMESPACE}" "${CLUSTER}"-toolset-0 -- 
bin/pulsar-admin topics create pulsar-ci/test/test-topic
+      "${KUBECTL}" exec -n "${NAMESPACE}" "${CLUSTER}"-toolset-0 -- 
bin/pulsar-admin topics create-subscription -s test pulsar-ci/test/test-topic
+      "${KUBECTL}" exec -n "${NAMESPACE}" "${CLUSTER}"-toolset-0 -- 
bin/pulsar-client produce -m "test-message" pulsar-ci/test/test-topic
+      "${KUBECTL}" exec -n "${NAMESPACE}" "${CLUSTER}"-toolset-0 -- 
bin/pulsar-admin topics create-subscription -s test2 pulsar-ci/test/test-topic
+      "${KUBECTL}" exec -n "${NAMESPACE}" "${CLUSTER}"-toolset-0 -- 
bin/pulsar-client --url "${PROXY_URL}" produce -m "test-message2" 
pulsar-ci/test/test-topic
     fi
     if [[ "${action}" == "consume" || "${action}" == "produce-consume" ]]; then
-      ${KUBECTL} exec -n ${NAMESPACE} ${CLUSTER}-toolset-0 -- 
bin/pulsar-client consume -s test pulsar-ci/test/test-topic
-      ${KUBECTL} exec -n ${NAMESPACE} ${CLUSTER}-toolset-0 -- 
bin/pulsar-client --url "${PROXY_URL}" consume -s test2 
pulsar-ci/test/test-topic
+      "${KUBECTL}" exec -n "${NAMESPACE}" "${CLUSTER}"-toolset-0 -- 
bin/pulsar-client consume -s test pulsar-ci/test/test-topic
+      "${KUBECTL}" exec -n "${NAMESPACE}" "${CLUSTER}"-toolset-0 -- 
bin/pulsar-client --url "${PROXY_URL}" consume -s test2 
pulsar-ci/test/test-topic
     fi
     set +x
 }
 
 function ci::wait_function_running() {
-    local function_status=$(${KUBECTL} exec -n ${NAMESPACE} 
${CLUSTER}-toolset-0 -- bash -c 'bin/pulsar-admin functions status --tenant 
pulsar-ci --namespace test --name test-function | grep -v INFO')
+    local function_status
+    function_status=$(${KUBECTL} exec -n "${NAMESPACE}" "${CLUSTER}"-toolset-0 
-- bash -c 'bin/pulsar-admin functions status --tenant pulsar-ci --namespace 
test --name test-function | grep -v INFO')
     echo "Function status: $function_status"
-    num_running=$(echo $function_status | jq .numRunning || echo 0)
+    num_running=$(echo "$function_status" | jq .numRunning || echo 0)
     counter=1
     while [[ ${num_running} -lt 1 ]]; do
       ((counter++))
@@ -324,24 +333,24 @@ function ci::wait_function_running() {
       fi
       echo "Waiting 15 seconds for function to be running"
       sleep 15
-      ${KUBECTL} get pods -n ${NAMESPACE} -l component=function || true
+      ${KUBECTL} get pods -n "${NAMESPACE}" -l component=function || true
       ${KUBECTL} get events --sort-by=.lastTimestamp -A | tail -n 30 || true
-      podname=$(${KUBECTL} get pods -l component=function -n ${NAMESPACE} 
--no-headers -o custom-columns=":metadata.name") || true
+      podname=$(${KUBECTL} get pods -l component=function -n "${NAMESPACE}" 
--no-headers -o custom-columns=":metadata.name") || true
       if [[ -n "$podname" ]]; then
         echo "Function pod is $podname"
-        ${KUBECTL} describe pod -n ${NAMESPACE} $podname
+        ${KUBECTL} describe pod -n "${NAMESPACE}" "$podname"
         echo "Function pod logs"
-        ${KUBECTL} logs -n ${NAMESPACE} $podname
+        ${KUBECTL} logs -n "${NAMESPACE}" "$podname"
       fi
-      function_status=$(${KUBECTL} exec -n ${NAMESPACE} ${CLUSTER}-toolset-0 
-- bash -c 'bin/pulsar-admin functions status --tenant pulsar-ci --namespace 
test --name test-function | grep -v INFO')
+      function_status=$(${KUBECTL} exec -n "${NAMESPACE}" 
"${CLUSTER}"-toolset-0 -- bash -c 'bin/pulsar-admin functions status --tenant 
pulsar-ci --namespace test --name test-function | grep -v INFO')
       echo "Function status: $function_status"
-      num_running=$(echo $function_status | jq .numRunning || echo 0)
+      num_running=$(echo "$function_status" | jq .numRunning || echo 0)
     done
 }
 
 function ci::wait_message_processed() {
-    num_processed=$(${KUBECTL} exec -n ${NAMESPACE} ${CLUSTER}-toolset-0 -- 
bash -c 'bin/pulsar-admin functions stats --tenant pulsar-ci --namespace test 
--name test-function | grep -v INFO' | jq .processedSuccessfullyTotal)
-    podname=$(${KUBECTL} get pods -l component=function -n ${NAMESPACE} 
--no-headers -o custom-columns=":metadata.name")
+    num_processed=$(${KUBECTL} exec -n "${NAMESPACE}" "${CLUSTER}"-toolset-0 
-- bash -c 'bin/pulsar-admin functions stats --tenant pulsar-ci --namespace 
test --name test-function | grep -v INFO' | jq .processedSuccessfullyTotal)
+    podname=$(${KUBECTL} get pods -l component=function -n "${NAMESPACE}" 
--no-headers -o custom-columns=":metadata.name")
     counter=1
     while [[ ${num_processed} -lt 1 ]]; do
       ((counter++))
@@ -352,66 +361,66 @@ function ci::wait_message_processed() {
       echo "Waiting 15 seconds for message to be processed"
       sleep 15
       echo "Function pod is $podname"
-      ${KUBECTL} describe pod -n ${NAMESPACE} $podname
+      ${KUBECTL} describe pod -n "${NAMESPACE}" "$podname"
       echo "Function pod logs"
-      ${KUBECTL} logs -n ${NAMESPACE} $podname
-      ${KUBECTL} exec -n ${NAMESPACE} ${CLUSTER}-toolset-0 -- bin/pulsar-admin 
functions stats --tenant pulsar-ci --namespace test --name test-function | grep 
-v INFO
-      num_processed=$(${KUBECTL} exec -n ${NAMESPACE} ${CLUSTER}-toolset-0 -- 
bash -c 'bin/pulsar-admin functions stats --tenant pulsar-ci --namespace test 
--name test-function | grep -v INFO' | jq .processedSuccessfullyTotal)
+      ${KUBECTL} logs -n "${NAMESPACE}" "$podname"
+      ${KUBECTL} exec -n "${NAMESPACE}" "${CLUSTER}"-toolset-0 -- 
bin/pulsar-admin functions stats --tenant pulsar-ci --namespace test --name 
test-function | grep -v INFO
+      num_processed=$(${KUBECTL} exec -n "${NAMESPACE}" "${CLUSTER}"-toolset-0 
-- bash -c 'bin/pulsar-admin functions stats --tenant pulsar-ci --namespace 
test --name test-function | grep -v INFO' | jq .processedSuccessfullyTotal)
     done
 }
 
 function ci::test_pulsar_function() {
     echo "Testing functions"
     echo "Creating function"
-    ${KUBECTL} exec -n ${NAMESPACE} ${CLUSTER}-toolset-0 -- bin/pulsar-admin 
functions create --tenant pulsar-ci --namespace test --name test-function 
--inputs "pulsar-ci/test/test_input" --output "pulsar-ci/test/test_output" 
--parallelism 1 --classname 
org.apache.pulsar.functions.api.examples.ExclamationFunction --jar 
/pulsar/examples/api-examples.jar
+    ${KUBECTL} exec -n "${NAMESPACE}" "${CLUSTER}"-toolset-0 -- 
bin/pulsar-admin functions create --tenant pulsar-ci --namespace test --name 
test-function --inputs "pulsar-ci/test/test_input" --output 
"pulsar-ci/test/test_output" --parallelism 1 --classname 
org.apache.pulsar.functions.api.examples.ExclamationFunction --jar 
/pulsar/examples/api-examples.jar
     echo "Creating subscription for output topic"
-    ${KUBECTL} exec -n ${NAMESPACE} ${CLUSTER}-toolset-0 -- bin/pulsar-admin 
topics create-subscription -s test pulsar-ci/test/test_output
+    ${KUBECTL} exec -n "${NAMESPACE}" "${CLUSTER}"-toolset-0 -- 
bin/pulsar-admin topics create-subscription -s test pulsar-ci/test/test_output
     echo "Waiting for function to be ready"
     # wait until the function is running
     ci::wait_function_running
     echo "Sending input message"
-    ${KUBECTL} exec -n ${NAMESPACE} ${CLUSTER}-toolset-0 -- bin/pulsar-client 
produce -m 'hello pulsar function!' pulsar-ci/test/test_input
+    ${KUBECTL} exec -n "${NAMESPACE}" "${CLUSTER}"-toolset-0 -- 
bin/pulsar-client produce -m 'hello pulsar function!' pulsar-ci/test/test_input
     echo "Waiting for message to be processed"
     ci::wait_message_processed
     echo "Consuming output message"
-    ${KUBECTL} exec -n ${NAMESPACE} ${CLUSTER}-toolset-0 -- bin/pulsar-client 
consume -s test pulsar-ci/test/test_output
+    ${KUBECTL} exec -n "${NAMESPACE}" "${CLUSTER}"-toolset-0 -- 
bin/pulsar-client consume -s test pulsar-ci/test/test_output
 }
 
 function ci::test_pulsar_manager() {
   echo "Testing pulsar manager"
 
-  until ${KUBECTL} get jobs -n ${NAMESPACE} ${CLUSTER}-pulsar-manager-init -o 
json | jq -r '.status.conditions[] | select (.type | test("Complete")).status' 
| grep True; do sleep 3; done
-  ${KUBECTL} describe job -n ${NAMESPACE} ${CLUSTER}-pulsar-manager-init
-  ${KUBECTL} logs -n ${NAMESPACE} job.batch/${CLUSTER}-pulsar-manager-init
-  ${KUBECTL} exec -n ${NAMESPACE} ${CLUSTER}-pulsar-manager-0 -- cat 
/pulsar-manager/pulsar-manager.log
+  until ${KUBECTL} get jobs -n "${NAMESPACE}" "${CLUSTER}"-pulsar-manager-init 
-o json | jq -r '.status.conditions[] | select (.type | 
test("Complete")).status' | grep True; do sleep 3; done
+  ${KUBECTL} describe job -n "${NAMESPACE}" "${CLUSTER}"-pulsar-manager-init
+  ${KUBECTL} logs -n "${NAMESPACE}" job.batch/"${CLUSTER}"-pulsar-manager-init
+  ${KUBECTL} exec -n "${NAMESPACE}" "${CLUSTER}"-pulsar-manager-0 -- cat 
/pulsar-manager/pulsar-manager.log
   echo "Checking Podname"
-  podname=$(${KUBECTL} get pods -n ${NAMESPACE} -l component=pulsar-manager 
--no-headers -o custom-columns=":metadata.name")
+  podname=$(${KUBECTL} get pods -n "${NAMESPACE}" -l component=pulsar-manager 
--no-headers -o custom-columns=":metadata.name")
   echo "Getting pulsar manager UI password"
-  PASSWORD=$(${KUBECTL} get secret -n ${NAMESPACE} -l component=pulsar-manager 
-o=jsonpath="{.items[0].data.UI_PASSWORD}" | base64 --decode)
+  PASSWORD=$(${KUBECTL} get secret -n "${NAMESPACE}" -l 
component=pulsar-manager -o=jsonpath="{.items[0].data.UI_PASSWORD}" | base64 
--decode)
 
   echo "Getting CSRF_TOKEN"
-  CSRF_TOKEN=$(${KUBECTL} exec -n ${NAMESPACE} ${podname} -- curl 
http://127.0.0.1:7750/pulsar-manager/csrf-token)
+  CSRF_TOKEN=$(${KUBECTL} exec -n "${NAMESPACE}" "${podname}" -- curl 
http://127.0.0.1:7750/pulsar-manager/csrf-token)
 
   echo "Performing login"
-  ${KUBECTL} exec -n ${NAMESPACE} ${podname} -- curl -X POST 
http://127.0.0.1:9527/pulsar-manager/login \
+  ${KUBECTL} exec -n "${NAMESPACE}" "${podname}" -- curl -X POST 
http://127.0.0.1:9527/pulsar-manager/login \
                                                  -H 'Accept: application/json, 
text/plain, */*' \
                                                  -H 'Content-Type: 
application/json' \
                                                  -H "X-XSRF-TOKEN: 
$CSRF_TOKEN" \
                                                  -H "Cookie: 
XSRF-TOKEN=$CSRF_TOKEN" \
                                                  -sS -D headers.txt \
-                                                 -d '{"username": "pulsar", 
"password": "'${PASSWORD}'"}'
-  LOGIN_TOKEN=$(${KUBECTL} exec -n ${NAMESPACE} ${podname} -- grep "token:" 
headers.txt | sed 's/^.*: //')
-  LOGIN_JSESSIONID=$(${KUBECTL} exec -n ${NAMESPACE} ${podname} -- grep -o 
"JSESSIONID=[a-zA-Z0-9_]*" headers.txt | sed 's/^.*=//')
+                                                 -d '{"username": "pulsar", 
"password": "'"${PASSWORD}"'"}'
+  LOGIN_TOKEN=$(${KUBECTL} exec -n "${NAMESPACE}" "${podname}" -- grep 
"token:" headers.txt | sed 's/^.*: //')
+  LOGIN_JSESSIONID=$(${KUBECTL} exec -n "${NAMESPACE}" "${podname}" -- grep -o 
"JSESSIONID=[a-zA-Z0-9_]*" headers.txt | sed 's/^.*=//')
 
   echo "Checking environment"
-  envs=$(${KUBECTL} exec -n ${NAMESPACE} ${podname} -- curl -X GET 
http://127.0.0.1:9527/pulsar-manager/environments \
+  envs=$(${KUBECTL} exec -n "${NAMESPACE}" "${podname}" -- curl -X GET 
http://127.0.0.1:9527/pulsar-manager/environments \
                   -H 'Content-Type: application/json' \
                   -H "token: $LOGIN_TOKEN" \
                   -H "X-XSRF-TOKEN: $CSRF_TOKEN" \
                   -H "username: pulsar" \
                   -H "Cookie: XSRF-TOKEN=$CSRF_TOKEN; 
JSESSIONID=$LOGIN_JSESSIONID;")
   echo "$envs"
-  number_of_envs=$(echo $envs | jq '.total')
+  number_of_envs=$(echo "$envs" | jq '.total')
   if [ "$number_of_envs" -ne 1 ]; then
     echo "Error: Did not find expected environment"
     exit 1
@@ -419,8 +428,8 @@ function ci::test_pulsar_manager() {
 
   # Force manager to query broker for tenant info. This will require use of 
the manager's JWT, if JWT authentication is enabled.
   echo "Checking tenants"
-  pulsar_env=$(echo $envs | jq -r '.data[0].name')
-  tenants=$(${KUBECTL} exec -n ${NAMESPACE} ${podname} -- curl -X GET 
http://127.0.0.1:9527/pulsar-manager/admin/v2/tenants \
+  pulsar_env=$(echo "$envs" | jq -r '.data[0].name')
+  tenants=$(${KUBECTL} exec -n "${NAMESPACE}" "${podname}" -- curl -X GET 
http://127.0.0.1:9527/pulsar-manager/admin/v2/tenants \
                   -H 'Content-Type: application/json' \
                   -H "token: $LOGIN_TOKEN" \
                   -H "X-XSRF-TOKEN: $CSRF_TOKEN" \
@@ -429,7 +438,7 @@ function ci::test_pulsar_manager() {
                   -H "environment: ${pulsar_env}" \
                   -H "Cookie: XSRF-TOKEN=$CSRF_TOKEN; 
JSESSIONID=$LOGIN_JSESSIONID;")
   echo "$tenants"
-  number_of_tenants=$(echo $tenants | jq '.total')
+  number_of_tenants=$(echo "$tenants" | jq '.total')
   if [ "$number_of_tenants" -lt 1 ]; then
     echo "Error: Found no tenants!"
     exit 1
@@ -439,8 +448,7 @@ function ci::test_pulsar_manager() {
 function ci::check_loadbalancers() {
   (
   set +e
-  ${KUBECTL} get services -n ${NAMESPACE} | grep LoadBalancer
-  if [ $? -eq 0 ]; then
+  if ${KUBECTL} get services -n "${NAMESPACE}" | grep -q LoadBalancer; then
     echo "Error: Found service with type LoadBalancer. This is not allowed 
because of security reasons."
     exit 1
   fi
@@ -454,21 +462,22 @@ function ci::validate_kustomize_yaml() {
     KUSTOMIZE_VERSION=5.6.0
     KUSTOMIZE_DIR=$(mktemp -d)
     echo "Installing kustomize ${KUSTOMIZE_VERSION} to ${KUSTOMIZE_DIR}"
-    curl -s 
"https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh";
 | bash -s ${KUSTOMIZE_VERSION} ${KUSTOMIZE_DIR}
+    curl -s 
"https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh";
 | bash -s "${KUSTOMIZE_VERSION}" "${KUSTOMIZE_DIR}"
     export PATH=${KUSTOMIZE_DIR}:$PATH
   fi
   # prevent regression of 
https://github.com/apache/pulsar-helm-chart/issues/569
-  local kustomize_yaml_dir=$(mktemp -d)
-  cp ${PULSAR_HOME}/.ci/kustomization.yaml ${kustomize_yaml_dir}
-  PULSAR_HOME=${PULSAR_HOME} yq -i '.helmGlobals.chartHome = env(PULSAR_HOME) 
+ "/charts"' ${kustomize_yaml_dir}/kustomization.yaml
+  local kustomize_yaml_dir
+  kustomize_yaml_dir=$(mktemp -d)
+  cp "${PULSAR_HOME}"/.ci/kustomization.yaml "${kustomize_yaml_dir}"
+  PULSAR_HOME="${PULSAR_HOME}" yq -i '.helmGlobals.chartHome = 
env(PULSAR_HOME) + "/charts"' "${kustomize_yaml_dir}"/kustomization.yaml
   failures=0
   # validate zookeeper init
   echo "Validating kustomize yaml output with zookeeper init"
-  _ci::validate_kustomize_yaml ${kustomize_yaml_dir} || ((failures++))
+  _ci::validate_kustomize_yaml "${kustomize_yaml_dir}" || ((failures++))
   # validate oxia init
-  yq -i '.helmCharts[0].valuesInline.components += {"zookeeper": false, 
"oxia": true}' ${kustomize_yaml_dir}/kustomization.yaml
+  yq -i '.helmCharts[0].valuesInline.components += {"zookeeper": false, 
"oxia": true}' "${kustomize_yaml_dir}"/kustomization.yaml
   echo "Validating kustomize yaml output with oxia init"
-  _ci::validate_kustomize_yaml ${kustomize_yaml_dir} || ((failures++)) 
+  _ci::validate_kustomize_yaml "${kustomize_yaml_dir}" || ((failures++)) 
   if [ $failures -gt 0 ]; then
     exit 1
   fi
@@ -476,7 +485,7 @@ function ci::validate_kustomize_yaml() {
 
 function _ci::validate_kustomize_yaml() {
   local kustomize_yaml_dir=$1
-  kustomize build --enable-helm --helm-kube-version 1.23.0 
--load-restrictor=LoadRestrictionsNone ${kustomize_yaml_dir} | yq 
'select(.spec.template.spec.containers[0].args != null) | 
.spec.template.spec.containers[0].args' | \
+  kustomize build --enable-helm --helm-kube-version 1.23.0 
--load-restrictor=LoadRestrictionsNone "${kustomize_yaml_dir}" | yq 
'select(.spec.template.spec.containers[0].args != null) | 
.spec.template.spec.containers[0].args' | \
   awk '{
     if (prev_line ~ /\\$/ && $0 ~ /^$/) {
       print "Found issue: backslash at end of line followed by empty line. 
Must use pipe character for multiline strings to support kustomize due to 
kubernetes-sigs/kustomize#4201.";
@@ -499,16 +508,17 @@ function ci::create_openid_resources() {
 
   echo "Creating openid resources"
 
-  cp ${PULSAR_HOME}/.ci/auth/keycloak/0-realm-pulsar-partial-export.json 
/tmp/realm-pulsar.json
+  cp "${PULSAR_HOME}"/.ci/auth/keycloak/0-realm-pulsar-partial-export.json 
/tmp/realm-pulsar.json
 
   for component in broker proxy admin manager; do
 
     echo "Creating openid resources for ${component}"
 
-    local client_id=pulsar-${component}
+    local client_id=pulsar-"${component}"
 
     # Github action hang up when read string from /dev/urandom, so use python 
to generate a random string
-    local client_secret=$(python -c "import secrets; import string; length = 
32; random_string = ''.join(secrets.choice(string.ascii_letters + 
string.digits) for _ in range(length)); print(random_string);")
+    local client_secret
+    client_secret=$(python -c "import secrets; import string; length = 32; 
random_string = ''.join(secrets.choice(string.ascii_letters + string.digits) 
for _ in range(length)); print(random_string);")
 
     if [[ "${component}" == "admin" ]]; then
       local sub_claim_value="admin"
@@ -517,14 +527,14 @@ function ci::create_openid_resources() {
     fi
 
     # Create the client credentials file
-    jq -n --arg CLIENT_ID $client_id --arg CLIENT_SECRET "$client_secret" -f 
${PULSAR_HOME}/.ci/auth/oauth2/credentials_file.json > 
/tmp/${component}-credentials_file.json
+    jq -n --arg CLIENT_ID "$client_id" --arg CLIENT_SECRET "$client_secret" -f 
"${PULSAR_HOME}"/.ci/auth/oauth2/credentials_file.json > 
/tmp/"${component}"-credentials_file.json
 
     # Create the secret for the client credentials
     local secret_name="pulsar-${component}-credentials"
-    ${KUBECTL} create secret generic ${secret_name} 
--from-file=credentials_file.json=/tmp/${component}-credentials_file.json -n 
${NAMESPACE}
+    ${KUBECTL} create secret generic "${secret_name}" 
--from-file=credentials_file.json=/tmp/"${component}"-credentials_file.json -n 
"${NAMESPACE}"
 
     # Create the keycloak client file
-    jq -n --arg CLIENT_ID $client_id --arg CLIENT_SECRET "$client_secret" 
--arg SUB_CLAIM_VALUE "$sub_claim_value" -f 
${PULSAR_HOME}/.ci/auth/keycloak/1-client-template.json > 
/tmp/${component}-keycloak-client.json
+    jq -n --arg CLIENT_ID "$client_id" --arg CLIENT_SECRET "$client_secret" 
--arg SUB_CLAIM_VALUE "$sub_claim_value" -f 
"${PULSAR_HOME}"/.ci/auth/keycloak/1-client-template.json > 
/tmp/"${component}"-keycloak-client.json
 
     # Merge the keycloak client file with the realm
     jq '.clients += [input]' /tmp/realm-pulsar.json 
/tmp/${component}-keycloak-client.json > /tmp/realm-pulsar.json.tmp
@@ -533,19 +543,20 @@ function ci::create_openid_resources() {
   done
 
   echo "Create keycloak realm configuration"
-  ${KUBECTL} create secret generic keycloak-ci-realm-config 
--from-file=realm-pulsar.json=/tmp/realm-pulsar.json -n ${NAMESPACE}
+  ${KUBECTL} create secret generic keycloak-ci-realm-config 
--from-file=realm-pulsar.json=/tmp/realm-pulsar.json -n "${NAMESPACE}"
 
   echo "Installing keycloak helm chart"
-  ${HELM} install keycloak-ci codecentric/keycloakx --version 7.1.8 --values 
${PULSAR_HOME}/.ci/auth/keycloak/values.yaml -n ${NAMESPACE}
+  ${HELM} install keycloak-ci codecentric/keycloakx --version 7.1.8 --values 
"${PULSAR_HOME}"/.ci/auth/keycloak/values.yaml -n "${NAMESPACE}"
 
   echo "Wait until keycloak is running"
-  WC=$(${KUBECTL} get pods -n ${NAMESPACE} 
--field-selector=status.phase=Running | grep keycloak-ci-keycloakx-0 | wc -l)
+  # shellcheck disable=SC2126
+  WC=$(${KUBECTL} get pods -n "${NAMESPACE}" 
--field-selector=status.phase=Running | grep keycloak-ci-keycloakx-0 | wc -l)
   counter=1
   while [[ ${WC} -lt 1 ]]; do
     ((counter++))
-    echo ${WC};
+    echo "${WC}";
     sleep 15
-    ${KUBECTL} get pods,jobs -n ${NAMESPACE}
+    ${KUBECTL} get pods,jobs -n "${NAMESPACE}"
     ${KUBECTL} get events --sort-by=.lastTimestamp -A | tail -n 30 || true
     if [[ $((counter % 20)) -eq 0 ]]; then
       ci::print_pod_logs
@@ -554,11 +565,12 @@ function ci::create_openid_resources() {
         exit 1
       fi
     fi
-    WC=$(${KUBECTL} get pods -n ${NAMESPACE} 
--field-selector=status.phase=Running | grep keycloak-ci-keycloakx-0 | wc -l)
+    # shellcheck disable=SC2126
+    WC=$(${KUBECTL} get pods -n "${NAMESPACE}" 
--field-selector=status.phase=Running | grep keycloak-ci-keycloakx-0 | wc -l)
   done
 
   echo "Wait until keycloak is ready"
-  ${KUBECTL} wait --for=condition=Ready pod/keycloak-ci-keycloakx-0 -n 
${NAMESPACE} --timeout 180s
+  ${KUBECTL} wait --for=condition=Ready pod/keycloak-ci-keycloakx-0 -n 
"${NAMESPACE}" --timeout 180s
 }
 
 # lists all available functions in this tool
@@ -577,7 +589,7 @@ if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
   ci_function_name="ci::$1"
   shift
   if [[ "$(LC_ALL=C type -t "${ci_function_name}")" == "function" ]]; then
-    eval "$ci_function_name" "$@"
+    "$ci_function_name" "$@"
     exit $?
   else
     echo "Invalid ci function"
@@ -585,4 +597,4 @@ if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
     ci::list_functions
     exit 1
   fi
-fi
\ No newline at end of file
+fi
diff --git a/hack/common.sh b/hack/common.sh
index d6c0f11..5f4f4ff 100755
--- a/hack/common.sh
+++ b/hack/common.sh
@@ -69,15 +69,16 @@ function hack::ensure_kubectl() {
     fi
     echo "Installing kubectl v$KUBECTL_VERSION..."
     tmpfile=$(mktemp)
-    trap "test -f $tmpfile && rm $tmpfile" RETURN
-    curl --retry 10 -L -o $tmpfile 
https://dl.k8s.io/release/v${KUBECTL_VERSION}/bin/${OS}/${ARCH}/kubectl
-    mv $tmpfile $KUBECTL_BIN
-    chmod +x $KUBECTL_BIN
+    trap 'test -f "$tmpfile" && rm "$tmpfile"' RETURN
+    curl --retry 10 -L -o "$tmpfile" 
https://dl.k8s.io/release/v"${KUBECTL_VERSION}"/bin/"${OS}"/"${ARCH}"/kubectl
+    mv "$tmpfile" "$KUBECTL_BIN"
+    chmod +x "$KUBECTL_BIN"
 }
 
 function hack::verify_helm() {
     if test -x "$HELM_BIN"; then
-        local v=$($HELM_BIN version --short --client | grep -o -E 
'[0-9]+\.[0-9]+\.[0-9]+')
+        local v
+        v=$($HELM_BIN version --short --client | grep -o -E 
'[0-9]+\.[0-9]+\.[0-9]+')
         [[ "$v" == "$HELM_VERSION" ]]
         return
     fi
@@ -88,8 +89,9 @@ function hack::ensure_helm() {
     if hack::verify_helm; then
         return 0
     fi
-    local 
HELM_URL=https://get.helm.sh/helm-v${HELM_VERSION}-${OS}-${ARCH}.tar.gz
-    curl --retry 10 -L -s "$HELM_URL" | tar --strip-components 1 -C 
$OUTPUT_BIN -zxf - ${OS}-${ARCH}/helm
+    local HELM_URL
+    HELM_URL=https://get.helm.sh/helm-v${HELM_VERSION}-${OS}-${ARCH}.tar.gz
+    curl --retry 10 -L -s "$HELM_URL" | tar --strip-components 1 -C 
"$OUTPUT_BIN" -zxf - "${OS}"-"${ARCH}"/helm
 }
 
 function hack::verify_kind() {
@@ -106,10 +108,10 @@ function hack::ensure_kind() {
     fi
     echo "Installing kind v$KIND_VERSION..."
     tmpfile=$(mktemp)
-    trap "test -f $tmpfile && rm $tmpfile" RETURN
-    curl --retry 10 -L -o $tmpfile 
https://github.com/kubernetes-sigs/kind/releases/download/v${KIND_VERSION}/kind-${OS}-${ARCH}
-    mv $tmpfile $KIND_BIN
-    chmod +x $KIND_BIN
+    trap 'test -f "$tmpfile" && rm "$tmpfile"' RETURN
+    curl --retry 10 -L -o "$tmpfile" 
https://github.com/kubernetes-sigs/kind/releases/download/v"${KIND_VERSION}"/kind-"${OS}"-"${ARCH}";
+    mv "$tmpfile" "$KIND_BIN"
+    chmod +x "$KIND_BIN"
 }
 
 # hack::version_ge "$v1" "$v2" checks whether "v1" is greater or equal to "v2"
@@ -131,16 +133,16 @@ function hack::ensure_cr() {
     fi
     echo "Installing chart-releaser ${CR_VERSION} ..."
     tmpfile=$(mktemp)
-    trap "test -f $tmpfile && rm $tmpfile" RETURN
-    echo curl --retry 10 -L -o $tmpfile 
https://github.com/helm/chart-releaser/releases/download/v${CR_VERSION}/chart-releaser_${CR_VERSION}_${OS}_${ARCH}.tar.gz
-    curl --retry 10 -L -o $tmpfile 
https://github.com/helm/chart-releaser/releases/download/v${CR_VERSION}/chart-releaser_${CR_VERSION}_${OS}_${ARCH}.tar.gz
-    mv $tmpfile $CR_BIN
-    chmod +x $CR_BIN
+    trap 'test -f "$tmpfile" && rm "$tmpfile"' RETURN
+    echo curl --retry 10 -L -o "$tmpfile" 
https://github.com/helm/chart-releaser/releases/download/v"${CR_VERSION}"/chart-releaser_"${CR_VERSION}"_"${OS}"_"${ARCH}".tar.gz
+    curl --retry 10 -L -o "$tmpfile" 
https://github.com/helm/chart-releaser/releases/download/v"${CR_VERSION}"/chart-releaser_"${CR_VERSION}"_"${OS}"_"${ARCH}".tar.gz
+    mv "$tmpfile" "$CR_BIN"
+    chmod +x "$CR_BIN"
     $CR_BIN version
 }
 
 function hack::ensure_kubeconform() {
     echo "Installing kubeconform v$KUBECONFORM_VERSION..."
-    curl -s --retry 10 -L 
https://github.com/yannh/kubeconform/releases/download/v${KUBECONFORM_VERSION}/kubeconform-${OS}-${ARCH}.tar.gz
 | tar -xzO kubeconform > $KUBECONFORM_BIN
-    chmod +x $KUBECONFORM_BIN
-}
\ No newline at end of file
+    curl -s --retry 10 -L 
https://github.com/yannh/kubeconform/releases/download/v"${KUBECONFORM_VERSION}"/kubeconform-"${OS}"-"${ARCH}".tar.gz
 | tar -xzO kubeconform > "$KUBECONFORM_BIN"
+    chmod +x "$KUBECONFORM_BIN"
+}
diff --git a/hack/kind-cluster-build.sh b/hack/kind-cluster-build.sh
index e7915e0..5dc8648 100755
--- a/hack/kind-cluster-build.sh
+++ b/hack/kind-cluster-build.sh
@@ -18,10 +18,11 @@
 # under the License.
 #
 
-PULSAR_CHART_HOME=$(unset CDPATH && cd $(dirname "${BASH_SOURCE[0]}")/.. && 
pwd)
-cd ${PULSAR_CHART_HOME}
+PULSAR_CHART_HOME=$(unset CDPATH && cd "$(dirname "${BASH_SOURCE[0]}")/.." && 
pwd)
+cd "${PULSAR_CHART_HOME}" || exit
 
-source ${PULSAR_CHART_HOME}/hack/common.sh
+# shellcheck source=hack/common.sh
+source "${PULSAR_CHART_HOME}/hack/common.sh"
 
 hack::ensure_kubectl
 hack::ensure_helm
@@ -107,18 +108,18 @@ done
 
 echo "############# start create cluster:[${clusterName}] #############"
 workDir=${HOME}/kind/${clusterName}
-mkdir -p ${workDir}
+mkdir -p "${workDir}"
 
 data_dir=${workDir}/data
 
 echo "clean data dir: ${data_dir}"
-if [ -d ${data_dir} ]; then
-    rm -rf ${data_dir}
+if [ -d "${data_dir}" ]; then
+    rm -rf "${data_dir}"
 fi
 
 configFile=${workDir}/kind-config.yaml
 
-cat <<EOF > ${configFile}
+cat <<EOF > "${configFile}"
 kind: Cluster
 apiVersion: kind.x-k8s.io/v1alpha4
 networking:
@@ -132,39 +133,39 @@ nodes:
     protocol: TCP
 EOF
 
-for ((i=0;i<${nodeNum};i++))
+for ((i=0;i<nodeNum;i++))
 do
-    mkdir -p ${data_dir}/worker${i}
-    cat <<EOF >>  ${configFile}
+    mkdir -p "${data_dir}"/worker${i}
+    cat <<EOF >> "${configFile}"
 - role: worker
   extraMounts:
 EOF
-    for ((k=1;k<=${volumeNum};k++))
+    for ((k=1;k<=volumeNum;k++))
     do
-        mkdir -p ${data_dir}/worker${i}/vol${k}
-        cat <<EOF >> ${configFile}
+        mkdir -p "${data_dir}"/worker${i}/vol${k}
+        cat <<EOF >> "${configFile}"
   - containerPath: /mnt/disks/vol${k}
     hostPath: ${data_dir}/worker${i}/vol${k}
 EOF
     done
 done
 
-matchedCluster=$(kind get clusters | grep ${clusterName})
+matchedCluster=$(kind get clusters | grep "${clusterName}")
 if [[ "${matchedCluster}" == "${clusterName}" ]]; then
     echo "Kind cluster ${clusterName} already exists"
-    kind delete cluster --name=${clusterName}
+    kind delete cluster --name="${clusterName}"
 fi
 echo "start to create k8s cluster"
-kind create cluster --config ${configFile} --image kindest/node:${k8sVersion} 
--name=${clusterName} --verbosity 3
+kind create cluster --config "${configFile}" --image 
kindest/node:"${k8sVersion}" --name="${clusterName}" --verbosity 3
 export KUBECONFIG=${workDir}/kubeconfig.yaml
-kind get kubeconfig --name=${clusterName} > ${KUBECONFIG}
+kind get kubeconfig --name="${clusterName}" > "${KUBECONFIG}"
 
 echo "deploy docker registry in kind"
 registryNode=${clusterName}-control-plane
-registryNodeIP=$($KUBECTL_BIN get nodes ${registryNode} -o template 
--template='{{range.status.addresses}}{{if eq .type 
"InternalIP"}}{{.address}}{{end}}{{end}}')
+registryNodeIP=$($KUBECTL_BIN get nodes "${registryNode}" -o template 
--template='{{range.status.addresses}}{{if eq .type 
"InternalIP"}}{{.address}}{{end}}{{end}}')
 registryFile=${workDir}/registry.yaml
 
-cat <<EOF >${registryFile}
+cat <<EOF > "${registryFile}"
 apiVersion: apps/v1
 kind: DaemonSet
 metadata:
@@ -232,14 +233,14 @@ spec:
           - tcp-listen:5000,fork,reuseaddr
           - tcp-connect:${registryNodeIP}:5000
 EOF
-$KUBECTL_BIN apply -f ${registryFile}
+$KUBECTL_BIN apply -f "${registryFile}"
 
 echo "############# success create cluster:[${clusterName}] #############"
 
 echo "To start using your cluster, run:"
 echo "    export KUBECONFIG=${KUBECONFIG}"
 echo ""
-echo <<EOF
+cat <<EOF
 NOTE: In kind, nodes run docker network and cannot access host network.
 If you configured local HTTP proxy in your docker, images may cannot be pulled
 because http proxy is inaccessible.
diff --git a/scripts/cert-manager/install-cert-manager.sh 
b/scripts/cert-manager/install-cert-manager.sh
index b35a334..d92c6b7 100755
--- a/scripts/cert-manager/install-cert-manager.sh
+++ b/scripts/cert-manager/install-cert-manager.sh
@@ -1,3 +1,4 @@
+#!/usr/bin/env bash
 #
 # Licensed to the Apache Software Foundation (ASF) under one
 # or more contributor license agreements.  See the NOTICE file
@@ -17,8 +18,6 @@
 # under the License.
 #
 
-#!/usr/bin/env bash
-
 # If installation fails, the build should fail
 set -e
 
diff --git a/scripts/pulsar/cleanup_helm_release.sh 
b/scripts/pulsar/cleanup_helm_release.sh
index 98da7bd..aa781c8 100755
--- a/scripts/pulsar/cleanup_helm_release.sh
+++ b/scripts/pulsar/cleanup_helm_release.sh
@@ -18,8 +18,8 @@
 # under the License.
 #
 
-CHART_HOME=$(unset CDPATH && cd $(dirname "${BASH_SOURCE[0]}")/../.. && pwd)
-cd ${CHART_HOME}
+CHART_HOME=$(unset CDPATH && cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)
+cd "${CHART_HOME}" || exit
 
 usage() {
     cat <<EOF
@@ -73,12 +73,12 @@ release=${release:-pulsar-dev}
 
 function delete_namespace() {
     if [[ "${delete_namespace}" == "true" ]]; then
-        kubectl delete namespace ${namespace}
+        kubectl delete namespace "${namespace}"
     fi
 }
 
 # delete tokens
-kubectl get secrets -n ${namespace} | grep ${release}-token- | awk '{print 
$1}' | xargs kubectl delete secrets -n ${namespace}
+kubectl get secrets -n "${namespace}" | grep "${release}-token-" | awk '{print 
$1}' | xargs kubectl delete secrets -n "${namespace}"
 
 # delete namespace
 delete_namespace
diff --git a/scripts/pulsar/common.sh b/scripts/pulsar/common.sh
index 099ec28..5754311 100755
--- a/scripts/pulsar/common.sh
+++ b/scripts/pulsar/common.sh
@@ -57,12 +57,12 @@ function validate_gke_required_tools(){
     command  -v "${comm}" > /dev/null 2>&1 || "need_${comm}"
   done
 
-  gcloud container clusters list --project $PROJECT >/dev/null 2>&1 || { echo 
>&2 "Gcloud seems to be configured incorrectly or authentication is 
unsuccessfull"; exit 1; }
+  gcloud container clusters list --project "$PROJECT" >/dev/null 2>&1 || { 
echo >&2 "Gcloud seems to be configured incorrectly or authentication is 
unsuccessfull"; exit 1; }
 
 }
 
 function cluster_admin_password_gke(){
-  gcloud container clusters describe $CLUSTER_NAME --zone $ZONE --project 
$PROJECT --format='value(masterAuth.password)';
+  gcloud container clusters describe "$CLUSTER_NAME" --zone "$ZONE" --project 
"$PROJECT" --format='value(masterAuth.password)';
 }
 
 function validate_eks_required_tools(){
diff --git a/scripts/pulsar/common_auth.sh b/scripts/pulsar/common_auth.sh
index fdc7eaf..3b6ef31 100755
--- a/scripts/pulsar/common_auth.sh
+++ b/scripts/pulsar/common_auth.sh
@@ -27,4 +27,5 @@ if [ -z "$PULSAR_VERSION" ]; then
         PULSAR_VERSION="4.0.3"
     fi
 fi
-PULSAR_TOKENS_CONTAINER_IMAGE="apachepulsar/pulsar:${PULSAR_VERSION}"
\ No newline at end of file
+# shellcheck disable=SC2034
+PULSAR_TOKENS_CONTAINER_IMAGE="apachepulsar/pulsar:${PULSAR_VERSION}"
diff --git a/scripts/pulsar/generate_token.sh b/scripts/pulsar/generate_token.sh
index 45a5543..70e8306 100755
--- a/scripts/pulsar/generate_token.sh
+++ b/scripts/pulsar/generate_token.sh
@@ -22,8 +22,9 @@ set -e
 
 SCRIPT_DIR="$(unset CDPATH && cd "$(dirname "${BASH_SOURCE[0]}")" &>/dev/null 
&& pwd)"
 CHART_HOME=$(unset CDPATH && cd "$SCRIPT_DIR/../.." && pwd)
-cd ${CHART_HOME}
+cd "${CHART_HOME}"
 
+# shellcheck source=scripts/pulsar/common_auth.sh
 source "${SCRIPT_DIR}/common_auth.sh"
 
 usage() {
@@ -83,7 +84,7 @@ case $key in
 esac
 done
 
-if [[ "x${role}" == "x" ]]; then
+if [[ "${role}" == "" ]]; then
     echo "No pulsar role is provided!"
     usage
     exit 1
@@ -96,11 +97,11 @@ function pulsar::jwt::get_secret() {
     local type=$1
     local tmpfile=$2
     local secret_name=$3
-    echo ${secret_name}
+    echo "${secret_name}"
     if [[ "${local}" == "true" ]]; then
-        cp ${type} ${tmpfile}
+        cp "${type}" "${tmpfile}"
     else
-        kubectl get -n ${namespace} secrets ${secret_name} -o 
jsonpath="{.data['${type}']}" | base64 --decode > ${tmpfile}
+        kubectl get -n "${namespace}" secrets "${secret_name}" -o 
jsonpath="{.data['${type}']}" | base64 --decode > "${tmpfile}"
     fi
 }
 
@@ -109,40 +110,42 @@ function pulsar::jwt::generate_symmetric_token() {
     local secret_name="${release}-token-symmetric-key"
 
 
-    local tmpdir=$(mktemp -d)
-    trap "test -d $tmpdir && rm -rf $tmpdir" RETURN
+    local tmpdir
+    tmpdir=$(mktemp -d)
+    trap 'test -d "$tmpdir" && rm -rf "$tmpdir"' RETURN
     secretkeytmpfile=${tmpdir}/secret.key
     tokentmpfile=${tmpdir}/token.jwt
 
-    pulsar::jwt::get_secret SECRETKEY ${secretkeytmpfile} ${secret_name}
+    pulsar::jwt::get_secret SECRETKEY "${secretkeytmpfile}" "${secret_name}"
 
-    docker run --user 0 --rm -v ${tmpdir}:/keydir 
${PULSAR_TOKENS_CONTAINER_IMAGE} bin/pulsar tokens create -a HS256 --subject 
"${role}" --secret-key=file:/keydir/secret.key > ${tokentmpfile}
+    docker run --user 0 --rm -v "${tmpdir}":/keydir 
"${PULSAR_TOKENS_CONTAINER_IMAGE}" bin/pulsar tokens create -a HS256 --subject 
"${role}" --secret-key=file:/keydir/secret.key > "${tokentmpfile}"
     
     newtokentmpfile=${tmpdir}/token.jwt.new
-    tr -d '\n' < ${tokentmpfile} > ${newtokentmpfile}
-    kubectl create secret generic ${token_name} -n ${namespace} 
--from-file="TOKEN=${newtokentmpfile}" --from-literal="TYPE=symmetric" 
${local:+ -o yaml --dry-run=client}
-    rm -rf $tmpdir
+    tr -d '\n' < "${tokentmpfile}" > "${newtokentmpfile}"
+    kubectl create secret generic "${token_name}" -n "${namespace}" 
--from-file="TOKEN=${newtokentmpfile}" --from-literal="TYPE=symmetric" 
${local:+ -o yaml --dry-run=client}
+    rm -rf "$tmpdir"
 }
 
 function pulsar::jwt::generate_asymmetric_token() {
     local token_name="${release}-token-${role}"
     local secret_name="${release}-token-asymmetric-key"
 
-    local tmpdir=$(mktemp -d)
-    trap "test -d $tmpdir && rm -rf $tmpdir" RETURN
+    local tmpdir
+    tmpdir=$(mktemp -d)
+    trap 'test -d "$tmpdir" && rm -rf "$tmpdir"' RETURN
 
     privatekeytmpfile=${tmpdir}/privatekey.der
     tokentmpfile=${tmpdir}/token.jwt
 
-    pulsar::jwt::get_secret PRIVATEKEY ${privatekeytmpfile} ${secret_name}
+    pulsar::jwt::get_secret PRIVATEKEY "${privatekeytmpfile}" "${secret_name}"
 
     # Generate token
-    docker run --user 0 --rm -v ${tmpdir}:/keydir 
${PULSAR_TOKENS_CONTAINER_IMAGE} bin/pulsar tokens create -a RS256 --subject 
"${role}" --private-key=file:/keydir/privatekey.der > ${tokentmpfile}
+    docker run --user 0 --rm -v "${tmpdir}":/keydir 
"${PULSAR_TOKENS_CONTAINER_IMAGE}" bin/pulsar tokens create -a RS256 --subject 
"${role}" --private-key=file:/keydir/privatekey.der > "${tokentmpfile}"
 
     newtokentmpfile=${tmpdir}/token.jwt.new
-    tr -d '\n' < ${tokentmpfile} > ${newtokentmpfile}
-    kubectl create secret generic ${token_name} -n ${namespace} 
--from-file="TOKEN=${newtokentmpfile}" --from-literal="TYPE=asymmetric" 
${local:+ -o yaml --dry-run=client}
-    rm -rf $tmpdir
+    tr -d '\n' < "${tokentmpfile}" > "${newtokentmpfile}"
+    kubectl create secret generic "${token_name}" -n "${namespace}" 
--from-file="TOKEN=${newtokentmpfile}" --from-literal="TYPE=asymmetric" 
${local:+ -o yaml --dry-run=client}
+    rm -rf "$tmpdir"
 }
 
 if [[ "${symmetric}" == "true" ]]; then
diff --git a/scripts/pulsar/generate_token_secret_key.sh 
b/scripts/pulsar/generate_token_secret_key.sh
index f61322a..e084f90 100755
--- a/scripts/pulsar/generate_token_secret_key.sh
+++ b/scripts/pulsar/generate_token_secret_key.sh
@@ -22,8 +22,9 @@ set -e
 
 SCRIPT_DIR="$(unset CDPATH && cd "$(dirname "${BASH_SOURCE[0]}")" &>/dev/null 
&& pwd)"
 CHART_HOME=$(unset CDPATH && cd "$SCRIPT_DIR/../.." && pwd)
-cd ${CHART_HOME}
+cd "${CHART_HOME}"
 
+# shellcheck source=scripts/pulsar/common_auth.sh
 source "${SCRIPT_DIR}/common_auth.sh"
 
 usage() {
@@ -79,43 +80,44 @@ done
 
 namespace=${namespace:-pulsar}
 release=${release:-pulsar-dev}
-local_cmd=${file:+-o yaml --dry-run=client >secret.yaml}
 
 function pulsar::jwt::generate_symmetric_key() {
     local secret_name="${release}-token-symmetric-key"
 
-    local tmpdir=$(mktemp -d)
-    trap "test -d $tmpdir && rm -rf $tmpdir" RETURN
+    local tmpdir
+    tmpdir=$(mktemp -d)
+    trap 'test -d "$tmpdir" && rm -rf "$tmpdir"' RETURN
     local tmpfile=${tmpdir}/SECRETKEY
-    docker run --rm -t ${PULSAR_TOKENS_CONTAINER_IMAGE} bin/pulsar tokens 
create-secret-key > "${tmpfile}"
-    kubectl create secret generic ${secret_name} -n ${namespace} 
--from-file=$tmpfile ${local:+ -o yaml --dry-run=client}
+    docker run --rm -t "${PULSAR_TOKENS_CONTAINER_IMAGE}" bin/pulsar tokens 
create-secret-key > "${tmpfile}"
+    kubectl create secret generic "${secret_name}" -n "${namespace}" 
--from-file="$tmpfile" ${local:+ -o yaml --dry-run=client}
     # if local is true, keep the file available for debugging purposes
     if [[ "${local}" == "true" ]]; then
-        mv $tmpfile SECRETKEY
+        mv "$tmpfile" SECRETKEY
     fi
-    rm -rf $tmpdir
+    rm -rf "$tmpdir"
 }
 
 function pulsar::jwt::generate_asymmetric_key() {
     local secret_name="${release}-token-asymmetric-key"
 
-    local tmpdir=$(mktemp -d)
-    trap "test -d $tmpdir && rm -rf $tmpdir" RETURN
+    local tmpdir
+    tmpdir=$(mktemp -d)
+    trap 'test -d "$tmpdir" && rm -rf "$tmpdir"' RETURN
 
     privatekeytmpfile=${tmpdir}/PRIVATEKEY
     publickeytmpfile=${tmpdir}/PUBLICKEY
 
     # Generate key pair
-    docker run --user 0 --rm -t -v ${tmpdir}:/keydir 
${PULSAR_TOKENS_CONTAINER_IMAGE} bin/pulsar tokens create-key-pair 
--output-private-key=/keydir/PRIVATEKEY --output-public-key=/keydir/PUBLICKEY
+    docker run --user 0 --rm -t -v "${tmpdir}":/keydir 
"${PULSAR_TOKENS_CONTAINER_IMAGE}" bin/pulsar tokens create-key-pair 
--output-private-key=/keydir/PRIVATEKEY --output-public-key=/keydir/PUBLICKEY
 
-    kubectl create secret generic ${secret_name} -n ${namespace} 
--from-file=$privatekeytmpfile --from-file=$publickeytmpfile ${local:+ -o yaml 
--dry-run=client}
+    kubectl create secret generic "${secret_name}" -n "${namespace}" 
--from-file="$privatekeytmpfile" --from-file="$publickeytmpfile" ${local:+ -o 
yaml --dry-run=client}
 
     # if local is true, keep the files available for debugging purposes
     if [[ "${local}" == "true" ]]; then
-        mv $privatekeytmpfile PRIVATEKEY
-        mv $publickeytmpfile PUBLICKEY
+        mv "$privatekeytmpfile" PRIVATEKEY
+        mv "$publickeytmpfile" PUBLICKEY
     fi
-    rm -rf $tmpdir
+    rm -rf "$tmpdir"
 }
 
 if [[ "${symmetric}" == "true" ]]; then
diff --git a/scripts/pulsar/get_token.sh b/scripts/pulsar/get_token.sh
index 31003ad..b6e9bed 100755
--- a/scripts/pulsar/get_token.sh
+++ b/scripts/pulsar/get_token.sh
@@ -20,8 +20,8 @@
 
 set -e
 
-CHART_HOME=$(unset CDPATH && cd $(dirname "${BASH_SOURCE[0]}")/../.. && pwd)
-cd ${CHART_HOME}
+CHART_HOME=$(unset CDPATH && cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)
+cd "${CHART_HOME}"
 
 usage() {
     cat <<EOF
@@ -68,7 +68,7 @@ case $key in
 esac
 done
 
-if [[ "x${role}" == "x" ]]; then
+if [[ "${role}" == "" ]]; then
     echo "No pulsar role is provided!"
     usage
     exit 1
@@ -80,8 +80,10 @@ release=${release:-pulsar-dev}
 function pulsar::jwt::get_token() {
     local token_name="${release}-token-${role}"
 
-    local token=$(kubectl get -n ${namespace} secrets ${token_name} -o 
jsonpath="{.data['TOKEN']}" | base64 --decode)
-    local token_type=$(kubectl get -n ${namespace} secrets ${token_name} -o 
jsonpath="{.data['TYPE']}" | base64 --decode)
+    local token
+    token=$(kubectl get -n "${namespace}" secrets "${token_name}" -o 
jsonpath="{.data['TOKEN']}" | base64 --decode)
+    local token_type
+    token_type=$(kubectl get -n "${namespace}" secrets "${token_name}" -o 
jsonpath="{.data['TYPE']}" | base64 --decode)
 
     echo "token type: ${token_type}"
     echo "-------------------------"
diff --git a/scripts/pulsar/prepare_helm_release.sh 
b/scripts/pulsar/prepare_helm_release.sh
index 647b7c9..384815b 100755
--- a/scripts/pulsar/prepare_helm_release.sh
+++ b/scripts/pulsar/prepare_helm_release.sh
@@ -18,8 +18,8 @@
 # under the License.
 #
 
-CHART_HOME=$(unset CDPATH && cd $(dirname "${BASH_SOURCE[0]}")/../.. && pwd)
-cd ${CHART_HOME}
+CHART_HOME=$(unset CDPATH && cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)
+cd "${CHART_HOME}" || exit
 
 usage() {
     cat <<EOF
@@ -97,31 +97,30 @@ function new_k8s_object() {
 function do_create_namespace() {
     if [[ "${create_namespace}" == "true" ]]; then
         new_k8s_object
-        kubectl create namespace ${namespace} ${local:+ -o yaml 
--dry-run=client}
+        kubectl create namespace "${namespace}" ${local:+ -o yaml 
--dry-run=client}
     fi
 }
 
 do_create_namespace
 
-kubectl get namespace "${namespace}" > /dev/null 2>&1
-if [ $? -ne 0 ]; then
+if ! kubectl get namespace "${namespace}" > /dev/null 2>&1; then
   echo "error: failed to get namespace '${namespace}'"
   echo "please check that this namespace exists, or use the '-c' option to 
create it"
   exit 1
 fi
 
-extra_opts=""
+declare -a extra_opts
 if [[ "${symmetric}" == "true" ]]; then
-  extra_opts="${extra_opts} -s"
+  extra_opts+=("-s")
 fi
 
 if [[ "${local}" == "true" ]]; then
-  extra_opts="${extra_opts} -l"
+  extra_opts+=("-l")
 fi
 
 echo "generate the token keys for the pulsar cluster" >&2
 new_k8s_object
-${CHART_HOME}/scripts/pulsar/generate_token_secret_key.sh -n ${namespace} -k 
${release} ${extra_opts}
+"${CHART_HOME}"/scripts/pulsar/generate_token_secret_key.sh -n "${namespace}" 
-k "${release}" "${extra_opts[@]}"
 
 echo "generate the tokens for the super-users: ${pulsar_superusers}" >&2
 
@@ -130,7 +129,7 @@ for user in "${superusers[@]}"
 do
     echo "generate the token for $user" >&2
     new_k8s_object
-    ${CHART_HOME}/scripts/pulsar/generate_token.sh -n ${namespace} -k 
${release} -r ${user} ${extra_opts} 
+    "${CHART_HOME}"/scripts/pulsar/generate_token.sh -n "${namespace}" -k 
"${release}" -r "${user}" "${extra_opts[@]}"
 done
 
 echo "-------------------------------------" >&2
diff --git a/scripts/set-pulsar-version.sh b/scripts/set-pulsar-version.sh
index 2c9b147..5478011 100755
--- a/scripts/set-pulsar-version.sh
+++ b/scripts/set-pulsar-version.sh
@@ -29,7 +29,7 @@ set -e
 OLD_VERSION=${1}
 NEW_VERSION=${2}
 
-if [[ "" == ${OLD_VERSION} || "" == ${NEW_VERSION} ]]; then
+if [[ "" == "${OLD_VERSION}" || "" == "${NEW_VERSION}" ]]; then
   echo "You need to provide the old_version and new_version"
   exit 1
 fi
diff --git a/scripts/victoria-metrics-k8s-stack/resolve_vm_operator_version.sh 
b/scripts/victoria-metrics-k8s-stack/resolve_vm_operator_version.sh
index ac31680..a9031be 100755
--- a/scripts/victoria-metrics-k8s-stack/resolve_vm_operator_version.sh
+++ b/scripts/victoria-metrics-k8s-stack/resolve_vm_operator_version.sh
@@ -27,7 +27,7 @@ fi
 
 SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" &>/dev/null && pwd)"
 # Run "helm dependency update" in charts/pulsar
-cd "$SCRIPT_DIR/../../charts/pulsar"
+cd "$SCRIPT_DIR/../../charts/pulsar" || exit
 helm dependency update 2>/dev/null 1>&2
 tar -zxf charts/victoria-metrics-k8s-stack-*.tgz \
-  --to-stdout 
victoria-metrics-k8s-stack/charts/victoria-metrics-operator/Chart.yaml | yq 
.appVersion
\ No newline at end of file
+  --to-stdout 
victoria-metrics-k8s-stack/charts/victoria-metrics-operator/Chart.yaml | yq 
.appVersion

Reply via email to