sassoftware / viya4-monitoring-kubernetes

Provides simple scripts and customization options to deploy monitoring, alerts, and log aggregation for Viya 4 running on Kubernetes
Apache License 2.0
54 stars 32 forks source link

Example gh action #593

Closed ceelias closed 9 months ago

ceelias commented 9 months ago

Just made a random change to show what the github actions looks like when it runs into issues. it creates a commnent that shows what the issues are and also how they can be fixed. This doesn't block the merge and can ultimately be ignored

github-actions[bot] commented 9 months ago

sh-checker report

To get the full details, please check in the job output.

shellcheck errors ``` 'shellcheck -e SC1004' returned error 1 finding the following syntactical issues: ---------- In bin/common.sh line 1: # Copyright © 2021, SAS Institute Inc., Cary, NC, USA. All Rights Reserved. ^-- SC2148 (error): Tips depend on target shell and yours is unknown. Add a shebang or a 'shell' directive. In bin/common.sh line 20: extract_trap_cmd() { printf '%s\n' "$3"; } ^----------------^ SC2317 (info): Command appears to be unreachable. Check usage (or ignore if invoked indirectly). In bin/common.sh line 29: log_error "Exiting script [`basename $0`] due to an error executing the command [$BASH_COMMAND]." ^-----------^ SC2006 (style): Use $(...) notation instead of legacy backticks `...`. ^-- SC2086 (info): Double quote to prevent globbing and word splitting. Did you mean: log_error "Exiting script [$(basename "$0")] due to an error executing the command [$BASH_COMMAND]." In bin/common.sh line 31: log_debug "Trap [ERR] triggered in [`basename $0`] while executing the command [$BASH_COMMAND]." ^-----------^ SC2006 (style): Use $(...) notation instead of legacy backticks `...`. ^-- SC2086 (info): Double quote to prevent globbing and word splitting. Did you mean: log_debug "Trap [ERR] triggered in [$(basename "$0")] while executing the command [$BASH_COMMAND]." In bin/common.sh line 40: source bin/colors-include.sh ^-------------------^ SC1091 (info): Not following: bin/colors-include.sh was not specified as input (see shellcheck -x). In bin/common.sh line 41: source bin/log-include.sh ^----------------^ SC1091 (info): Not following: bin/log-include.sh was not specified as input (see shellcheck -x). In bin/common.sh line 42: source bin/openshift-include.sh ^----------------------^ SC1091 (info): Not following: bin/openshift-include.sh was not specified as input (see shellcheck -x). In bin/common.sh line 44: if [ ! $(which sha256sum) ]; then ^----------------^ SC2046 (warning): Quote this to prevent word splitting. In bin/common.sh line 57: export $userEnv ^------^ SC2163 (warning): This does not export 'userEnv'. Remove $/${} for that, or use ${var?} to quiet. ^------^ SC2086 (info): Double quote to prevent globbing and word splitting. Did you mean: export "$userEnv" In bin/common.sh line 69: export USER_DIR=$(cd "$(dirname "$USER_DIR")"; pwd)/$(basename "$USER_DIR") ^------^ SC2155 (warning): Declare and assign separately to avoid masking return values. ^-------------------------^ SC2164 (warning): Use 'cd ... || exit' or 'cd ... || return' in case cd fails. Did you mean: export USER_DIR=$(cd "$(dirname "$USER_DIR")" || exit; pwd)/$(basename "$USER_DIR") In bin/common.sh line 72: userEnv=$(grep -v '^[[:blank:]]*$' $USER_DIR/user.env | grep -v '^#' | xargs) ^-------^ SC2086 (info): Double quote to prevent globbing and word splitting. Did you mean: userEnv=$(grep -v '^[[:blank:]]*$' "$USER_DIR"/user.env | grep -v '^#' | xargs) In bin/common.sh line 76: export $userEnv ^------^ SC2163 (warning): This does not export 'userEnv'. Remove $/${} for that, or use ${var?} to quiet. ^------^ SC2086 (info): Double quote to prevent globbing and word splitting. Did you mean: export "$userEnv" In bin/common.sh line 88: source bin/helm-include.sh ^-----------------^ SC1091 (info): Not following: bin/helm-include.sh was not specified as input (see shellcheck -x). In bin/common.sh line 94: source bin/kube-include.sh ^-----------------^ SC1091 (info): Not following: bin/kube-include.sh was not specified as input (see shellcheck -x). In bin/common.sh line 121: export TMP_DIR=$(mktemp -d -t sas.mon.XXXXXXXX) ^-----^ SC2155 (warning): Declare and assign separately to avoid masking return values. In bin/common.sh line 127: echo "# This file intentionally empty" > $TMP_DIR/empty.yaml ^------^ SC2086 (info): Double quote to prevent globbing and word splitting. Did you mean: echo "# This file intentionally empty" > "$TMP_DIR"/empty.yaml In bin/common.sh line 177: for n in ${reservedNames[@]}; do ^-----------------^ SC2068 (error): Double quote array expansions to avoid re-splitting elements. In bin/common.sh line 218: kubectl -n $ns patch serviceAccount $sa_name -p '{"automountServiceAccountToken":false}' ^-^ SC2086 (info): Double quote to prevent globbing and word splitting. ^------^ SC2086 (info): Double quote to prevent globbing and word splitting. Did you mean: kubectl -n "$ns" patch serviceAccount "$sa_name" -p '{"automountServiceAccountToken":false}' In bin/common.sh line 239: kubectl -n $ns patch $resource_type $resource_name -p '{"spec": {"template": {"spec": {"automountServiceAccountToken":true}}}}' ^-^ SC2086 (info): Double quote to prevent globbing and word splitting. ^------------^ SC2086 (info): Double quote to prevent globbing and word splitting. ^------------^ SC2086 (info): Double quote to prevent globbing and word splitting. Did you mean: kubectl -n "$ns" patch "$resource_type" "$resource_name" -p '{"spec": {"template": {"spec": {"automountServiceAccountToken":true}}}}' For more information: https://www.shellcheck.net/wiki/SC2068 -- Double quote array expansions to ... https://www.shellcheck.net/wiki/SC2148 -- Tips depend on target shell and y... https://www.shellcheck.net/wiki/SC2046 -- Quote this to prevent word splitt... ---------- You can address the above issues in one of three ways: 1. Manually correct the issue in the offending shell script; 2. Disable specific issues by adding the comment: # shellcheck disable=NNNN above the line that contains the issue, where NNNN is the error code; 3. Add '-e NNNN' to the SHELLCHECK_OPTS setting in your .yml action file. ```
shfmt errors ``` 'shfmt -s' returned error 1 finding the following formatting issues: ---------- --- bin/common.sh.orig +++ bin/common.sh @@ -5,245 +5,244 @@ # Current directory must be the root directory of the repo function trap_add() { - # based on https://stackoverflow.com/questions/3338030/multiple-bash-traps-for-the-same-signal - # but: prepends new cmd rather than append it, changed var names and eliminated messages + # based on https://stackoverflow.com/questions/3338030/multiple-bash-traps-for-the-same-signal + # but: prepends new cmd rather than append it, changed var names and eliminated messages - local cmd_to_add signal + local cmd_to_add signal - cmd_to_add=$1; shift - for signal in "$@"; do - trap -- "$( - # print the new trap command - printf '%s\n' "${cmd_to_add}" - # helper fn to get existing trap command from output - # of trap -p - extract_trap_cmd() { printf '%s\n' "$3"; } - # print existing trap command with newline - eval "extract_trap_cmd $(trap -p "${signal}")" - )" "${signal}" - done + cmd_to_add=$1 + shift + for signal in "$@"; do + trap -- "$( + # print the new trap command + printf '%s\n' "${cmd_to_add}" + # helper fn to get existing trap command from output + # of trap -p + extract_trap_cmd() { printf '%s\n' "$3"; } + # print existing trap command with newline + eval "extract_trap_cmd $(trap -p "${signal}")" + )" "${signal}" + done } function errexit_msg { - if [ -o errexit ]; then - log_error "Exiting script [`basename $0`] due to an error executing the command [$BASH_COMMAND]." - else - log_debug "Trap [ERR] triggered in [`basename $0`] while executing the command [$BASH_COMMAND]." - fi + if [ -o errexit ]; then + log_error "Exiting script [$(basename $0)] due to an error executing the command [$BASH_COMMAND]." + else + log_debug "Trap [ERR] triggered in [$(basename $0)] while executing the command [$BASH_COMMAND]." + fi } if [ "$SAS_COMMON_SOURCED" = "" ]; then - # Save standard out to a new descriptor - exec 3>&1 + # Save standard out to a new descriptor + exec 3>&1 - # Includes - source bin/colors-include.sh - source bin/log-include.sh - source bin/openshift-include.sh + # Includes + source bin/colors-include.sh + source bin/log-include.sh + source bin/openshift-include.sh - if [ ! $(which sha256sum) ]; then - log_error "Missing required utility: sha256sum" - exit 1 - fi + if [ ! $(which sha256sum) ]; then + log_error "Missing required utility: sha256sum" + exit 1 + fi - # Load component Helm chart version infomation - # NOTE: This is loaded prior to the USER_DIR to allow - # overriding these defaults via USER_DIR user.env files - if [ -f "component_versions.env" ]; then - userEnv=$(grep -v '^[[:blank:]]*$' component_versions.env | grep -v '^#' | xargs) - if [ "$userEnv" != "" ]; then - log_debug "Loading global user environment file: component_versions.env" - if [ "$userEnv" != "" ]; then - export $userEnv - fi - fi - else - log_debug "No component_versions.env file found" - fi + # Load component Helm chart version infomation + # NOTE: This is loaded prior to the USER_DIR to allow + # overriding these defaults via USER_DIR user.env files + if [ -f "component_versions.env" ]; then + userEnv=$(grep -v '^[[:blank:]]*$' component_versions.env | grep -v '^#' | xargs) + if [ "$userEnv" != "" ]; then + log_debug "Loading global user environment file: component_versions.env" + if [ "$userEnv" != "" ]; then + export $userEnv + fi + fi + else + log_debug "No component_versions.env file found" + fi + export USER_DIR=${USER_DIR:-$(pwd)} + if [ -d "$USER_DIR" ]; then + # Resolve full path + export USER_DIR=$( + cd "$(dirname "$USER_DIR")" + pwd + )/$(basename "$USER_DIR") + fi + if [ -f "$USER_DIR/user.env" ]; then + userEnv=$(grep -v '^[[:blank:]]*$' $USER_DIR/user.env | grep -v '^#' | xargs) + if [ "$userEnv" != "" ]; then + log_debug "Loading global user environment file: $USER_DIR/user.env" + if [ "$userEnv" != "" ]; then + export $userEnv + fi + fi + fi + log_debug "Working directory: $(pwd)" + log_info "User directory: $USER_DIR" - export USER_DIR=${USER_DIR:-$(pwd)} - if [ -d "$USER_DIR" ]; then - # Resolve full path - export USER_DIR=$(cd "$(dirname "$USER_DIR")"; pwd)/$(basename "$USER_DIR") - fi - if [ -f "$USER_DIR/user.env" ]; then - userEnv=$(grep -v '^[[:blank:]]*$' $USER_DIR/user.env | grep -v '^#' | xargs) - if [ "$userEnv" != "" ]; then - log_debug "Loading global user environment file: $USER_DIR/user.env" - if [ "$userEnv" != "" ]; then - export $userEnv - fi - fi - fi + export AIRGAP_DEPLOYMENT=${AIRGAP_DEPLOYMENT:-false} - log_debug "Working directory: $(pwd)" - log_info "User directory: $USER_DIR" + CHECK_HELM=${CHECK_HELM:-true} + if [ "$CHECK_HELM" == "true" ]; then + source bin/helm-include.sh + log_verbose "Helm client version: $HELM_VER_FULL" + fi - export AIRGAP_DEPLOYMENT=${AIRGAP_DEPLOYMENT:-false} - - CHECK_HELM=${CHECK_HELM:-true} - if [ "$CHECK_HELM" == "true" ]; then - source bin/helm-include.sh - log_verbose "Helm client version: $HELM_VER_FULL" - fi + CHECK_KUBERNETES=${CHECK_KUBERNETES:-true} + if [ "$CHECK_KUBERNETES" == "true" ]; then + source bin/kube-include.sh - CHECK_KUBERNETES=${CHECK_KUBERNETES:-true} - if [ "$CHECK_KUBERNETES" == "true" ]; then - source bin/kube-include.sh + log_verbose Kubernetes client version: "$KUBE_CLIENT_VER" + log_verbose Kubernetes server version: "$KUBE_SERVER_VER" - log_verbose Kubernetes client version: "$KUBE_CLIENT_VER" - log_verbose Kubernetes server version: "$KUBE_SERVER_VER" + # Check that the current KUBECONFIG has admin access + CHECK_ADMIN=${CHECK_ADMIN:-true} + if [ "$CHECK_ADMIN" == "true" ]; then + if [ "$(kubectl auth can-i create namespace --all-namespaces)" == "no" ]; then + ctx=$(kubectl config current-context) + log_error "The current kubectl context [$ctx] does not have cluster admin access" + exit 1 + else + log_debug "Cluster admin check OK" + fi + else + log_debug "Cluster admin check disabled" + fi + fi - # Check that the current KUBECONFIG has admin access - CHECK_ADMIN=${CHECK_ADMIN:-true} - if [ "$CHECK_ADMIN" == "true" ]; then - if [ "$(kubectl auth can-i create namespace --all-namespaces)" == "no" ]; then - ctx=$(kubectl config current-context) - log_error "The current kubectl context [$ctx] does not have cluster admin access" - exit 1 - else - log_debug "Cluster admin check OK" - fi - else - log_debug "Cluster admin check disabled" - fi - fi + # set TLS Cert Generator (cert-manager|openssl) + export CERT_GENERATOR="${CERT_GENERATOR:-openssl}" - # set TLS Cert Generator (cert-manager|openssl) - export CERT_GENERATOR="${CERT_GENERATOR:-openssl}" + # Set default timeout for kubectl namespace delete command + export KUBE_NAMESPACE_DELETE_TIMEOUT=${KUBE_NAMESPACE_DELETE_TIMEOUT:-5m} + export TMP_DIR=$(mktemp -d -t sas.mon.XXXXXXXX) + if [ ! -d "$TMP_DIR" ]; then + log_error "Could not create temporary directory [$TMP_DIR]" + exit 1 + fi + log_debug "Temporary directory: [$TMP_DIR]" + echo "# This file intentionally empty" >$TMP_DIR/empty.yaml - # Set default timeout for kubectl namespace delete command - export KUBE_NAMESPACE_DELETE_TIMEOUT=${KUBE_NAMESPACE_DELETE_TIMEOUT:-5m} + # Delete the temp directory on exit + function cleanup { + KEEP_TMP_DIR=${KEEP_TMP_DIR:-false} + if [ "$KEEP_TMP_DIR" != "true" ]; then + rm -rf "$TMP_DIR" + log_debug "Deleted temporary directory: [$TMP_DIR]" + else + log_info "TMP_DIR [$TMP_DIR] was not removed" + fi + } + trap_add cleanup EXIT - export TMP_DIR=$(mktemp -d -t sas.mon.XXXXXXXX) - if [ ! -d "$TMP_DIR" ]; then - log_error "Could not create temporary directory [$TMP_DIR]" - exit 1 - fi - log_debug "Temporary directory: [$TMP_DIR]" - echo "# This file intentionally empty" > $TMP_DIR/empty.yaml + trap_add errexit_msg ERR - # Delete the temp directory on exit - function cleanup { - KEEP_TMP_DIR=${KEEP_TMP_DIR:-false} - if [ "$KEEP_TMP_DIR" != "true" ]; then - rm -rf "$TMP_DIR" - log_debug "Deleted temporary directory: [$TMP_DIR]" - else - log_info "TMP_DIR [$TMP_DIR] was not removed" - fi - } - trap_add cleanup EXIT - - trap_add errexit_msg ERR - - export SAS_COMMON_SOURCED=true + export SAS_COMMON_SOURCED=true fi function checkDefaultStorageClass { - if [ -z "$defaultStorageClass" ]; then - # Check for kubernetes environment conflicts/requirements - defaultStorageClass=$(kubectl get storageclass -o jsonpath="{range .items[*]}{.metadata.name}{'\t'}{.metadata.annotations..storageclass\.kubernetes\.io/is-default-class}{'\n'}{end}" | grep true | awk '{print $1}') - if [ "$defaultStorageClass" ]; then - log_debug "Found default storageClass: [$defaultStorageClass]" - else - # Try again with beta storageclass annotation key - defaultStorageClass=$(kubectl get storageclass -o jsonpath="{range .items[*]}{.metadata.name}{'\t'}{.metadata.annotations..storageclass\.beta\.kubernetes\.io/is-default-class}{'\n'}{end}" | grep true | awk '{print $1}') - if [ "$defaultStorageClass" ]; then - log_debug "Found default storageClass: [$defaultStorageClass]" - else - log_warn "This cluster does not have a default storageclass defined" - log_warn "This may cause errors unless storageclass values are explicitly defined" - defaultStorageClass=_NONE_ - fi - fi - fi + if [ -z "$defaultStorageClass" ]; then + # Check for kubernetes environment conflicts/requirements + defaultStorageClass=$(kubectl get storageclass -o jsonpath="{range .items[*]}{.metadata.name}{'\t'}{.metadata.annotations..storageclass\.kubernetes\.io/is-default-class}{'\n'}{end}" | grep true | awk '{print $1}') + if [ "$defaultStorageClass" ]; then + log_debug "Found default storageClass: [$defaultStorageClass]" + else + # Try again with beta storageclass annotation key + defaultStorageClass=$(kubectl get storageclass -o jsonpath="{range .items[*]}{.metadata.name}{'\t'}{.metadata.annotations..storageclass\.beta\.kubernetes\.io/is-default-class}{'\n'}{end}" | grep true | awk '{print $1}') + if [ "$defaultStorageClass" ]; then + log_debug "Found default storageClass: [$defaultStorageClass]" + else + log_warn "This cluster does not have a default storageclass defined" + log_warn "This may cause errors unless storageclass values are explicitly defined" + defaultStorageClass=_NONE_ + fi + fi + fi } function validateTenantID { - tenantID=$1 - reservedNames=(default provider shared sharedservices spre uaa viya) + tenantID=$1 + reservedNames=(default provider shared sharedservices spre uaa viya) - CHECK_TENANT_NAME=${CHECK_TENANT_NAME:-true} - if [ "$CHECK_TENANT_NAME" == "true" ]; then - if [[ $tenantID =~ ^[a-z]([a-z0-9]){0,15}$ ]]; then - if [[ $tenantID =~ ^sas ]]; then - log_error "Tenant names cannot start with 'sas'" - exit 1 - fi - for n in ${reservedNames[@]}; do - if [ "$tenantID" == "$n" ]; then - log_error "The tenant name [$tenantID] is a reserved name" - exit 1 - fi - done - else - log_error "[$tenantID] is not a valid tenant name" - exit 1 - fi - else - log_debug "Tenant name validation is disabled" - fi + CHECK_TENANT_NAME=${CHECK_TENANT_NAME:-true} + if [ "$CHECK_TENANT_NAME" == "true" ]; then + if [[ $tenantID =~ ^[a-z]([a-z0-9]){0,15}$ ]]; then + if [[ $tenantID =~ ^sas ]]; then + log_error "Tenant names cannot start with 'sas'" + exit 1 + fi + for n in ${reservedNames[@]}; do + if [ "$tenantID" == "$n" ]; then + log_error "The tenant name [$tenantID] is a reserved name" + exit 1 + fi + done + else + log_error "[$tenantID] is not a valid tenant name" + exit 1 + fi + else + log_debug "Tenant name validation is disabled" + fi } - function validateNamespace { - local namespace - namespace="$1" - if [[ "$namespace" =~ ^[a-z0-9]([\-a-z0-9]*[a-z0-9])?$ ]]; then - log_debug "Namespace [$namespace] passes validation" - else - log_error "[$namespace] is not a valid namespace name" - exit 1 - fi + local namespace + namespace="$1" + if [[ $namespace =~ ^[a-z0-9]([\-a-z0-9]*[a-z0-9])?$ ]]; then + log_debug "Namespace [$namespace] passes validation" + else + log_error "[$namespace] is not a valid namespace name" + exit 1 + fi } - function randomPassword { - date +%s | sha256sum | base64 | head -c 32 ; echo + date +%s | sha256sum | base64 | head -c 32 + echo } function disable_sa_token_automount { - local ns sa_name should_disable - ns=$1 - sa_name=$2 - should_disable=${SEC_DISABLE_SA_TOKEN_AUTOMOUNT:-true} - - if [ "$should_disable" == "true" ]; then - if [ -n "$(kubectl -n "$ns" get serviceAccount "$sa_name" -o name 2>/dev/null)" ]; then - log_debug "Disabling automount of API tokens for serviceAccount [$ns/$sa_name]" - kubectl -n $ns patch serviceAccount $sa_name -p '{"automountServiceAccountToken":false}' - else - log_debug "ServiceAccount [$ns/$sa_name] not found. Skipping patch" - fi - else - log_debug "NOT disabling token automount serviceAccount [$ns/$sa_name]; SEC_DISABLE_SA_TOKEN_AUTOMOUNT set to [$SEC_DISABLE_SA_TOKEN_AUTOMOUNT]" - fi + local ns sa_name should_disable + ns=$1 + sa_name=$2 + should_disable=${SEC_DISABLE_SA_TOKEN_AUTOMOUNT:-true} + + if [ "$should_disable" == "true" ]; then + if [ -n "$(kubectl -n "$ns" get serviceAccount "$sa_name" -o name 2>/dev/null)" ]; then + log_debug "Disabling automount of API tokens for serviceAccount [$ns/$sa_name]" + kubectl -n $ns patch serviceAccount $sa_name -p '{"automountServiceAccountToken":false}' + else + log_debug "ServiceAccount [$ns/$sa_name] not found. Skipping patch" + fi + else + log_debug "NOT disabling token automount serviceAccount [$ns/$sa_name]; SEC_DISABLE_SA_TOKEN_AUTOMOUNT set to [$SEC_DISABLE_SA_TOKEN_AUTOMOUNT]" + fi } function enable_pod_token_automount { - local ns resource_type resource_name should_disable - ns=$1 - resource_type=$2 - resource_name=$3 - should_disable=${SEC_DISABLE_SA_TOKEN_AUTOMOUNT:-true} + local ns resource_type resource_name should_disable + ns=$1 + resource_type=$2 + resource_name=$3 + should_disable=${SEC_DISABLE_SA_TOKEN_AUTOMOUNT:-true} + if [ "$should_disable" == "true" ]; then + log_debug "Enabling automount of API tokens for pods deployed via [$resource_type/$resource_name]" - if [ "$should_disable" == "true" ]; then - log_debug "Enabling automount of API tokens for pods deployed via [$resource_type/$resource_name]" - - if [ "$resource_type" == "daemonset" ] || [ "$resource_type" == "deployment" ]; then - kubectl -n $ns patch $resource_type $resource_name -p '{"spec": {"template": {"spec": {"automountServiceAccountToken":true}}}}' - else - log_error "Invalid request to function [${FUNCNAME[0]}]; unsupported resource_type [$resource_type]" - return 1 - fi - else - log_debug "NOT enabling token automount on pods for [$ns/$resource_type/$resource_name]; SEC_DISABLE_SA_TOKEN_AUTOMOUNT set to [$SEC_DISABLE_SA_TOKEN_AUTOMOUNT]" - fi + if [ "$resource_type" == "daemonset" ] || [ "$resource_type" == "deployment" ]; then + kubectl -n $ns patch $resource_type $resource_name -p '{"spec": {"template": {"spec": {"automountServiceAccountToken":true}}}}' + else + log_error "Invalid request to function [${FUNCNAME[0]}]; unsupported resource_type [$resource_type]" + return 1 + fi + else + log_debug "NOT enabling token automount on pods for [$ns/$resource_type/$resource_name]; SEC_DISABLE_SA_TOKEN_AUTOMOUNT set to [$SEC_DISABLE_SA_TOKEN_AUTOMOUNT]" + fi } export -f checkDefaultStorageClass ---------- You can reformat the above files to meet shfmt's requirements by typing: shfmt -s -w filename ```