diff --git a/helpers/helpers.sh b/helpers/helpers.sh index 05fd0a0..ec9962b 100644 --- a/helpers/helpers.sh +++ b/helpers/helpers.sh @@ -75,8 +75,12 @@ function delete_policy { # wait_policies [condition] - at least one policy must exist function wait_policies { + local resources="admissionpolicies,clusteradmissionpolicies" + # Policy groups were added in Kubewarden >= v1.17.0 + kw_version ">=1.17" && resources+=",admissionpolicygroups,clusteradmissionpolicygroups" + for chart in ${1:-PolicyActive PolicyUniquelyReachable}; do - wait_for --for=condition="$1" admissionpolicies,clusteradmissionpolicies,admissionpolicygroups,clusteradmissionpolicygroups --all -A + wait_for --for=condition="$1" "$resources" --all -A done } diff --git a/helpers/kubelib.sh b/helpers/kubelib.sh index 0257b78..5c048eb 100644 --- a/helpers/kubelib.sh +++ b/helpers/kubelib.sh @@ -20,14 +20,19 @@ jq() { command jq -e "$@"; } export -f yq jq function retry() { - local cmd=$1 - local tries=${2:-15} - local delay=${3:-20} - local i + local cmd="$1" + local tries="${2:-20}" + local delay="${3:-15}" + local i status for ((i=1; i<=tries; i++)); do - timeout 25 bash -c "$cmd" && break || echo "RETRY #$i: $cmd" - [ $i -ne $tries ] && sleep $delay || { echo "Godot: $cmd"; false; } + timeout $delay bash -c "$cmd" && break || status=$? + if [[ $i -lt $tries ]]; then + echo "RETRY #$i: $cmd" + [[ $status -ne 124 ]] && sleep $delay + else + echo "Godot ($status): $cmd"; false + fi done } @@ -35,10 +40,10 @@ function retry() { # Handles kube-api disconnects during upgrade function wait_pods() { local i output - for i in {1..20}; do + for i in {1..30}; do output=$(kubectl get pods --no-headers -o wide ${@:--n kubewarden} | grep -vw Completed || echo 'Fail') grep -vE '([0-9]+)/\1 +Running' <<< $output || break - [ $i -ne 20 ] && sleep 30 || { echo "Godot: pods not running"; false; } + [ $i -ne 30 ] && sleep 15 || { echo "Godot: pods not running"; false; } done } @@ -62,3 +67,37 @@ function wait_cluster() { wait_nodes wait_pods } + + +# ================================================================================================== +# Version helpers + +eq() { [[ "$1" == "$2"* ]]; } # Check if $1 starts with $2 +le() { printf '%s\n' "$1" "$2" | sed '/-/!{s/$/_/}' | sort -V -C; } # sed _ to sort RC < Release +ge() { printf '%s\n' "$1" "$2" | sed '/-/!{s/$/_/}' | sort -V -C -r; } +gt() { ! le "$1" "$2"; } +lt() { ! ge "$1" "$2"; } + +# Check if current version satisfies query (semver.satifies) +# $1: version query (e.g., ">=1.17", "<1.17.0", "=1.17.0-rc2") +# $2: current version (e.g., "1.17.0-rc1") +is_version() { + local qsign="${1%%[0-9]*}" # Extract sign (e.g., ">=", "=", etc.) + local qver="${1#"$qsign"}" # Remove sign from version (e.g., "1.17.0") + local current="${2/#v}" # Current version, strip the leading 'v' + + # Append ".0" to partial qver (or 1.17.0 > 1.17) + [[ "$qver" =~ ^[0-9]+\.[0-9]+$ ]] && qver="${qver}.0" + # Strip -rc from current version if not querying RC (or 1.17.0-rc2 < 1.17.0) + [[ "$qver" != *-rc* ]] && current="${current%-rc*}" + + case "$qsign" in + *">"*) gt "$current" "$qver" && return 0 ;;& + *"<"*) lt "$current" "$qver" && return 0 ;;& + *"="*) eq "$current" "$qver" && return 0 ;;& + esac + return 1 +} + +# Query against installed kubewarden app version +kw_version() { is_version "$1" "$(helm ls -n $NAMESPACE -f kubewarden-crds -o json | jq -r '.[0].app_version')"; } diff --git a/scripts/helmer.sh b/scripts/helmer.sh index d985fdd..6e6d45f 100755 --- a/scripts/helmer.sh +++ b/scripts/helmer.sh @@ -12,7 +12,12 @@ NAMESPACE=${NAMESPACE:-kubewarden} REPO_NAME=${REPO_NAME:-kubewarden} # Use charts from [./dirname|reponame] CHARTS_LOCATION=${CHARTS_LOCATION:-$REPO_NAME} -# [next|prev|v1.17.0-rc2|local] + +# [next|prev|v1.17.0-rc2|local] - defaults to local if CHARTS_LOCATION is path, otherwise next +# - next: last version from helm search kubewarden --devel +# - prev: previous stable version (older than next and not -rc) +# - v\d*: Helm app version: v1.17.0-rc2, 1.17 (autocompleted) +# - local: directory with kw charts (kubewarden-crds, kubewarden-controller, kubewarden-defaults) VERSION=${VERSION:-$( [[ "$CHARTS_LOCATION" == */* ]] && echo "local" || echo "next" )} # Extra parameters for helm install @@ -25,11 +30,13 @@ if [ -n "${LATEST:-}" ]; then CONTROLLER_ARGS="--set image.tag=latest --set auditScanner.image.tag=latest $CONTROLLER_ARGS" fi -# Add missing "v" prefix +# Prepend "v" and append .0 to partial versions [[ $VERSION =~ ^[1-9] ]] && VERSION="v$VERSION" - -# Check if local charts are available +[[ $VERSION =~ ^v[1-9]+\.[0-9]+$ ]] && VERSION="${VERSION}.0" +# Check if local charts directory exists [ "$VERSION" = local ] && test -d "$CHARTS_LOCATION/kubewarden-crds" +# Check if version is valid +[[ $VERSION =~ ^(local|next|prev|v[1-9].*)$ ]] || { echo "Bad VERSION: $VERSION"; exit 1; } # Remove kubewarden- prefix from chart name [ $# -gt 1 ] && set -- "$1" "${2/#kubewarden-}" "${@:3}" @@ -68,29 +75,25 @@ make_version_map() { # Do single helm search query to speed up the process helm repo update $REPO_NAME --fail-on-repo-update-fail >/dev/null helm search repo --fail-on-no-result $REPO_NAME/ --versions --devel -o json \ - | jq -ec --arg appv "$VERSION" ' - def remap(items): items | unique_by(.name) | map({(.name): .version}) | add; + | jq -ec --arg v "$VERSION" ' + def remap(items): items | unique_by(.name) | map({(.name): .version, app_version: .app_version}) | add; unique_by(.name) as $latest | { - appv: remap(map(select(.app_version == $appv))), + ($v): remap(map(select(.app_version == $v))), next: remap($latest), prev: remap(map(select(.app_version != $latest[0].app_version and (.app_version | contains("-rc") | not)))), }' > "$tempfile" fi - # Load $VERSION from json into vMap array + # Load app & charts from json into vMap array + vMap["app"]=$( test "$VERSION" = "local" \ + && helm show chart $CHARTS_LOCATION/kubewarden-crds | yq '.appVersion' \ + || jq -er --arg k $VERSION '.[$k]["app_version"]' "$tempfile" ) + for chart in crds controller defaults; do - case $VERSION in - # Next: last version from helm search kubewarden --devel - next) vMap["$chart"]=$(jq -er --arg c $chart '.next["kubewarden/kubewarden-" + $c]' "$tempfile") ;; - # Prev: previous stable version (older than next and not -rc) - prev) vMap["$chart"]=$(jq -er --arg c $chart '.prev["kubewarden/kubewarden-" + $c]' "$tempfile") ;; - # App: Exact helm app version: v1.17.0-rc2 - v[1-9]*) vMap["$chart"]=$(jq -er --arg c $chart '.appv["kubewarden/kubewarden-" + $c]' "$tempfile") ;; - # Local: directory with kw charts (kubewarden-crds, kubewarden-controller, kubewarden-defaults) - local) vMap["$chart"]=$(helm show chart $CHARTS_LOCATION/kubewarden-$chart | yq '.version') ;; - *) echo "Bad VERSION: ${VERSION:-}"; exit 1;; - esac + vMap["$chart"]=$( test "$VERSION" = "local" \ + && helm show chart $CHARTS_LOCATION/kubewarden-$chart | yq '.version' \ + || jq -er --arg k $VERSION --arg c $chart '.[$k]["kubewarden/kubewarden-" + $c]' "$tempfile" ) done rm "$tempfile" @@ -107,8 +110,8 @@ helm_in() { helm install --wait --wait-for-jobs --namespace $NAMESPACE "${@:2}" # Install selected $VERSION do_install() { echo "Install $VERSION: ${vMap[*]}" - # Cert-manager is required by Kubewarden <= v1.16.0 (crds < 1.9.0) - if printf '%s\n' "${vMap[crds]}" "1.8.9" | sort -V -C; then + # Cert-manager is required by Kubewarden <= v1.16.0 + if is_version "<1.17" "${vMap[app]}"; then helm repo add jetstack https://charts.jetstack.io --force-update helm upgrade -i --wait cert-manager jetstack/cert-manager -n cert-manager --create-namespace --set crds.enabled=true fi @@ -121,7 +124,7 @@ do_install() { if [ "${1:-defaults}" = 'defaults' ]; then # Initial deployment of policy-server-default is created by controller with delay - retry "kubectl get -n $NAMESPACE deployment/policy-server-default" 2 + retry "kubectl get -n $NAMESPACE deployment/policy-server-default" 5 wait_rollout -n $NAMESPACE deployment/policy-server-default fi return 0 @@ -142,9 +145,8 @@ do_upgrade() { [ "${1:-defaults}" == 'defaults' ] && wait_rollout -n $NAMESPACE deployment/policy-server-default # Cert-manager is not required by Kubewarden >= v1.17.0 (crds >= 1.9.0) - if printf '%s\n' "1.9.0" "${vMap[crds]}" | sort -V -C; then - helm uninstall --wait cert-manager -n cert-manager --ignore-not-found - fi + kw_version ">=1.17" && helm uninstall --wait cert-manager -n cert-manager --ignore-not-found + return 0 } do_uninstall() {