| #!/usr/bin/env bash |
| # Licensed to the Apache Software Foundation (ASF) under one |
| # or more contributor license agreements. See the NOTICE file |
| # distributed with this work for additional information |
| # regarding copyright ownership. The ASF licenses this file |
| # to you under the Apache License, Version 2.0 (the |
| # "License"); you may not use this file except in compliance |
| # with the License. You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, |
| # software distributed under the License is distributed on an |
| # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| # KIND, either express or implied. See the License for the |
| # specific language governing permissions and limitations |
| # under the License. |
| |
| set -euo pipefail |
| |
| usage() { |
| cat <<'EOF' |
| Usage: scripts/ci/test-helm.sh <validate|smoke|cleanup-smoke|collect-smoke-diagnostics> [--cleanup] |
| |
| Commands: |
| validate Run Helm lint and render validation scenarios. |
| smoke Run the Helm runtime smoke scenario against the current Kubernetes context. |
| cleanup-smoke Remove the Helm smoke release namespace and any failed-install leftovers. |
| collect-smoke-diagnostics Collect diagnostics for the Helm smoke namespace. |
| |
| Notes: |
| - validate requires helm. |
| - smoke requires helm, kubectl, and curl, plus an existing cluster with Gateway API CRDs and Envoy Gateway installed. |
| - pass --cleanup with smoke to remove the Helm smoke namespace after a successful run. |
| - cleanup-smoke requires kubectl and optionally helm. |
| - collect-smoke-diagnostics is best-effort and does not fail on missing resources. |
| EOF |
| } |
| |
| REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" |
| cd "$REPO_ROOT" |
| |
| CHART_DIR="${CHART_DIR:-helm/charts/iggy}" |
| HELM_RENDER_DIR="${HELM_RENDER_DIR:-/tmp/helm-render}" |
| HELM_SMOKE_NAMESPACE="${HELM_SMOKE_NAMESPACE:-iggy-smoke}" |
| HELM_SMOKE_RELEASE="${HELM_SMOKE_RELEASE:-iggy-smoke}" |
| HELM_SMOKE_REPORT_DIR="${HELM_SMOKE_REPORT_DIR:-reports/helm-smoke}" |
| HELM_SMOKE_SERVER_HOST="${HELM_SMOKE_SERVER_HOST:-server.iggy.local}" |
| HELM_SMOKE_UI_HOST="${HELM_SMOKE_UI_HOST:-ui.iggy.local}" |
| HELM_SMOKE_TIMEOUT="${HELM_SMOKE_TIMEOUT:-5m}" |
| HELM_SMOKE_GATEWAY_NAMESPACE="${HELM_SMOKE_GATEWAY_NAMESPACE:-envoy-gateway-system}" |
| HELM_SMOKE_GATEWAY_NAME="${HELM_SMOKE_GATEWAY_NAME:-iggy-smoke-gateway}" |
| HELM_SMOKE_GATEWAY_PF_PORT="${HELM_SMOKE_GATEWAY_PF_PORT:-8080}" |
| HELM_SMOKE_KIND_NAME="${HELM_SMOKE_KIND_NAME:-iggy-helm-smoke}" |
| HELM_SMOKE_SERVER_CPU_ALLOCATION="${HELM_SMOKE_SERVER_CPU_ALLOCATION:-1}" |
| |
| # HELM_SMOKE_GATEWAY_NAMESPACE and HELM_SMOKE_GATEWAY_NAME must match the |
| # defaults in scripts/ci/setup-helm-smoke-cluster.sh - the HTTPRoute |
| # parentRef below targets the Gateway by ns + name and overriding one |
| # without the other silently breaks route attach. |
| |
| require_command() { |
| if ! command -v "$1" >/dev/null 2>&1; then |
| echo "Error: required command '$1' not found" >&2 |
| exit 1 |
| fi |
| } |
| |
| extract_chart_field() { |
| local field="$1" |
| local value |
| |
| value="$( |
| awk -v field="$field" ' |
| $1 == field ":" { |
| gsub(/"/, "", $2) |
| print $2 |
| exit |
| } |
| ' "$CHART_DIR/Chart.yaml" |
| )" |
| |
| if [ -z "$value" ]; then |
| echo "Error: could not extract '$field' from $CHART_DIR/Chart.yaml" >&2 |
| exit 1 |
| fi |
| |
| printf '%s\n' "$value" |
| } |
| |
| extract_values_tag() { |
| local section="$1" |
| local value |
| |
| value="$( |
| awk -v section="$section" ' |
| $1 == section ":" { |
| in_section = 1 |
| next |
| } |
| in_section && /^[^[:space:]]/ { |
| in_section = 0 |
| } |
| in_section && $1 == "tag:" { |
| gsub(/"/, "", $2) |
| print $2 |
| exit |
| } |
| ' "$CHART_DIR/values.yaml" |
| )" |
| |
| if [ -z "$value" ]; then |
| echo "Error: could not extract '$section.image.tag' from $CHART_DIR/values.yaml" >&2 |
| exit 1 |
| fi |
| |
| printf '%s\n' "$value" |
| } |
| |
| prepare_render_dir() { |
| if [ -z "$HELM_RENDER_DIR" ] || [ "$HELM_RENDER_DIR" = "/" ]; then |
| echo "Error: HELM_RENDER_DIR must not be empty or /" >&2 |
| exit 1 |
| fi |
| |
| rm -rf "$HELM_RENDER_DIR" |
| mkdir -p "$HELM_RENDER_DIR" |
| } |
| |
| extract_kind_names() { |
| local file="$1" |
| local kind="$2" |
| |
| awk -v kind="$kind" ' |
| /^kind: / { |
| current_kind = $2 |
| in_metadata = 0 |
| next |
| } |
| /^metadata:$/ { |
| in_metadata = 1 |
| next |
| } |
| in_metadata && /^ name: / { |
| if (current_kind == kind) { |
| print $2 |
| } |
| in_metadata = 0 |
| } |
| ' "$file" |
| } |
| |
| validate_yamllint() { |
| if ! command -v yamllint >/dev/null 2>&1; then |
| echo "Warning: yamllint not found, skipping YAML lint check" >&2 |
| return 0 |
| fi |
| |
| echo "Running yamllint on Helm chart..." |
| yamllint -c "$CHART_DIR/.yamllint.yml" "$CHART_DIR" |
| } |
| |
| validate_helmfmt() { |
| if ! command -v helmfmt >/dev/null 2>&1; then |
| echo "Warning: helmfmt not found, skipping Helm template format check" >&2 |
| return 0 |
| fi |
| |
| echo "Checking Helm template formatting..." |
| if ! helmfmt --check "$CHART_DIR"; then |
| echo "Error: Helm templates are not formatted. Run 'helmfmt $CHART_DIR' locally and commit the changes." >&2 |
| exit 1 |
| fi |
| } |
| |
| validate_helm_docs() { |
| if ! command -v helm-docs >/dev/null 2>&1; then |
| echo "Warning: helm-docs not found, skipping README drift check" >&2 |
| return 0 |
| fi |
| |
| local readme_before |
| local readme_after |
| |
| readme_before="$(cat "$CHART_DIR/README.md")" |
| helm-docs --chart-search-root "$CHART_DIR" --template-files README.md.gotmpl |
| readme_after="$(cat "$CHART_DIR/README.md")" |
| |
| if [ "$readme_before" != "$readme_after" ]; then |
| echo "Error: README.md is out of sync with values.yaml. Run 'helm-docs' locally and commit the updated README." >&2 |
| exit 1 |
| fi |
| } |
| |
| validate() { |
| require_command helm |
| |
| local chart_version |
| local chart_app_version |
| local server_image_tag |
| local ui_image_tag |
| |
| chart_version="$(extract_chart_field version)" |
| chart_app_version="$(extract_chart_field appVersion)" |
| server_image_tag="$(extract_values_tag server)" |
| ui_image_tag="$(extract_values_tag ui)" |
| |
| prepare_render_dir |
| |
| helm lint --strict "$CHART_DIR" |
| |
| helm template iggy "$CHART_DIR" > "$HELM_RENDER_DIR/default.yaml" |
| test "$(grep -c '^kind: Deployment$' "$HELM_RENDER_DIR/default.yaml")" -eq 2 |
| test "$(grep -c '^kind: Service$' "$HELM_RENDER_DIR/default.yaml")" -eq 2 |
| test "$(grep -c '^kind: ServiceAccount$' "$HELM_RENDER_DIR/default.yaml")" -eq 1 |
| test "$(grep -c '^kind: Secret$' "$HELM_RENDER_DIR/default.yaml")" -eq 1 |
| grep -q "helm.sh/chart: iggy-${chart_version}" "$HELM_RENDER_DIR/default.yaml" |
| grep -q "helm.sh/chart: iggy-ui-${chart_version}" "$HELM_RENDER_DIR/default.yaml" |
| grep -q "app.kubernetes.io/version: \"${chart_app_version}\"" "$HELM_RENDER_DIR/default.yaml" |
| grep -q "image: \"apache/iggy:${server_image_tag}\"" "$HELM_RENDER_DIR/default.yaml" |
| grep -q "image: \"apache/iggy-web-ui:${ui_image_tag}\"" "$HELM_RENDER_DIR/default.yaml" |
| |
| helm template iggy "$CHART_DIR" \ |
| --set server.persistence.enabled=true \ |
| --set autoscaling.enabled=true \ |
| --set autoscaling.targetCPUUtilizationPercentage=80 \ |
| --set server.ingress.enabled=true \ |
| --set ui.ingress.enabled=true \ |
| --set server.serviceMonitor.enabled=true \ |
| > "$HELM_RENDER_DIR/all-features.yaml" |
| grep -q '^kind: PersistentVolumeClaim$' "$HELM_RENDER_DIR/all-features.yaml" |
| grep -q '^kind: HorizontalPodAutoscaler$' "$HELM_RENDER_DIR/all-features.yaml" |
| test "$(grep -c '^kind: Ingress$' "$HELM_RENDER_DIR/all-features.yaml")" -eq 2 |
| test "$(extract_kind_names "$HELM_RENDER_DIR/all-features.yaml" Ingress | sort -u | wc -l | tr -d ' ')" -eq 2 |
| extract_kind_names "$HELM_RENDER_DIR/all-features.yaml" Ingress | grep -qx 'iggy' |
| extract_kind_names "$HELM_RENDER_DIR/all-features.yaml" Ingress | grep -qx 'iggy-ui' |
| grep -q '^kind: ServiceMonitor$' "$HELM_RENDER_DIR/all-features.yaml" |
| |
| helm template iggy "$CHART_DIR" \ |
| --kube-version 1.18.0 \ |
| --api-versions networking.k8s.io/v1beta1 \ |
| --api-versions autoscaling/v2beta2 \ |
| --set autoscaling.enabled=true \ |
| --set autoscaling.targetCPUUtilizationPercentage=80 \ |
| --set server.ingress.enabled=true \ |
| --set ui.ingress.enabled=true \ |
| > "$HELM_RENDER_DIR/legacy-k8s-1.18.yaml" |
| test "$(grep -c '^apiVersion: networking.k8s.io/v1beta1$' "$HELM_RENDER_DIR/legacy-k8s-1.18.yaml")" -eq 2 |
| grep -q '^apiVersion: autoscaling/v2beta2$' "$HELM_RENDER_DIR/legacy-k8s-1.18.yaml" |
| |
| helm template iggy "$CHART_DIR" --set ui.enabled=false > "$HELM_RENDER_DIR/server-only.yaml" |
| test "$(grep -c '^kind: Deployment$' "$HELM_RENDER_DIR/server-only.yaml")" -eq 1 |
| test "$(grep -c '^kind: Service$' "$HELM_RENDER_DIR/server-only.yaml")" -eq 1 |
| |
| helm template iggy "$CHART_DIR" --set server.enabled=false > "$HELM_RENDER_DIR/ui-only.yaml" |
| test "$(grep -c '^kind: Deployment$' "$HELM_RENDER_DIR/ui-only.yaml")" -eq 1 |
| test "$(grep -c '^kind: Service$' "$HELM_RENDER_DIR/ui-only.yaml")" -eq 1 |
| |
| helm template iggy "$CHART_DIR" \ |
| --set server.users.root.createSecret=false \ |
| --set server.users.root.existingSecret.name=supersecret \ |
| > "$HELM_RENDER_DIR/existing-secret.yaml" |
| if grep -q 'root-credentials' "$HELM_RENDER_DIR/existing-secret.yaml"; then |
| echo "Error: existing-secret render should not include generated root credentials" >&2 |
| exit 1 |
| fi |
| grep -q 'name: supersecret' "$HELM_RENDER_DIR/existing-secret.yaml" |
| |
| validate_yamllint |
| validate_helmfmt |
| validate_helm_docs |
| } |
| |
| # PID of the kubectl port-forward process started by smoke(). |
| # Stored at script scope so the EXIT trap can kill it on any code path. |
| HELM_SMOKE_GW_PF_PID="" |
| # Temp values file that may need cleanup if smoke() aborts mid-flight. |
| HELM_SMOKE_VALUES_FILE="" |
| |
| cleanup_smoke_state() { |
| if [ -n "${HELM_SMOKE_GW_PF_PID:-}" ]; then |
| kill "$HELM_SMOKE_GW_PF_PID" 2>/dev/null || true |
| HELM_SMOKE_GW_PF_PID="" |
| fi |
| if [ -n "${HELM_SMOKE_VALUES_FILE:-}" ]; then |
| rm -f "$HELM_SMOKE_VALUES_FILE" |
| HELM_SMOKE_VALUES_FILE="" |
| fi |
| } |
| |
| # Look up the Service that fronts the Envoy Gateway. Retries briefly to |
| # tolerate the gap between Gateway "Programmed" and the owning Service |
| # appearing - kubectl jsonpath on an empty `items` array exits non-zero, |
| # so we also swallow stderr to avoid leaking "array index out of bounds". |
| find_gateway_service() { |
| local svc_selector |
| local svc_name |
| local _ |
| |
| svc_selector="gateway.envoyproxy.io/owning-gateway-name=${HELM_SMOKE_GATEWAY_NAME},gateway.envoyproxy.io/owning-gateway-namespace=${HELM_SMOKE_GATEWAY_NAMESPACE}" |
| |
| for _ in $(seq 1 15); do |
| svc_name="$(kubectl get svc \ |
| --namespace "$HELM_SMOKE_GATEWAY_NAMESPACE" \ |
| --selector "$svc_selector" \ |
| -o jsonpath='{.items[0].metadata.name}' 2>/dev/null || true)" |
| if [ -n "$svc_name" ]; then |
| printf '%s\n' "$svc_name" |
| return 0 |
| fi |
| sleep 1 |
| done |
| |
| echo "Error: could not find Envoy Gateway proxy service after 15 attempts" >&2 |
| return 1 |
| } |
| |
| # Start kubectl port-forward in the caller's shell (not a subshell) so the |
| # PID is visible to the EXIT trap. Waits up to ~45 s for the tunnel to |
| # accept connections (15 iterations * (curl --max-time 2 + sleep 1)). |
| # curl returns 0 on any HTTP response (even 4xx/5xx); non-zero means |
| # the tunnel isn't ready yet. |
| start_gateway_port_forward() { |
| local svc_name="$1" |
| local ready=false |
| local _ |
| |
| kubectl port-forward "svc/${svc_name}" "${HELM_SMOKE_GATEWAY_PF_PORT}:80" \ |
| --namespace "$HELM_SMOKE_GATEWAY_NAMESPACE" \ |
| >/dev/null 2>&1 & |
| HELM_SMOKE_GW_PF_PID=$! |
| |
| for _ in $(seq 1 15); do |
| if curl -s --connect-timeout 1 --max-time 2 \ |
| -o /dev/null "http://127.0.0.1:${HELM_SMOKE_GATEWAY_PF_PORT}" 2>/dev/null; then |
| ready=true |
| break |
| fi |
| if ! kill -0 "$HELM_SMOKE_GW_PF_PID" 2>/dev/null; then |
| echo "Error: gateway port-forward process exited unexpectedly" >&2 |
| HELM_SMOKE_GW_PF_PID="" |
| return 1 |
| fi |
| sleep 1 |
| done |
| |
| if [ "$ready" = false ]; then |
| echo "Error: gateway port-forward did not become ready within 45 s" >&2 |
| return 1 |
| fi |
| } |
| |
| smoke() { |
| local cleanup_after_success="$1" |
| require_command helm |
| require_command kubectl |
| require_command curl |
| |
| local ui_image_tag |
| local server_ping_status |
| local ui_healthz_status |
| local leftover_resources |
| local helm_status |
| local gateway_svc |
| local gateway_url |
| |
| trap cleanup_smoke_state EXIT |
| |
| mkdir -p "$HELM_SMOKE_REPORT_DIR" |
| |
| if ! helm status "$HELM_SMOKE_RELEASE" -n "$HELM_SMOKE_NAMESPACE" >/dev/null 2>&1; then |
| leftover_resources="$( |
| kubectl -n "$HELM_SMOKE_NAMESPACE" get deployment,service,secret,serviceaccount \ |
| -l "app.kubernetes.io/instance=${HELM_SMOKE_RELEASE}" \ |
| -o name 2>/dev/null || true |
| )" |
| if [ -n "$leftover_resources" ]; then |
| cat >&2 <<EOF |
| Found leftover resources for a failed Helm smoke install in namespace '${HELM_SMOKE_NAMESPACE}'. |
| Run 'scripts/ci/test-helm.sh cleanup-smoke' once, then rerun the smoke test. |
| EOF |
| printf '%s\n' "$leftover_resources" >&2 |
| exit 1 |
| fi |
| fi |
| |
| ui_image_tag="$(extract_values_tag ui)" |
| |
| echo "$ui_image_tag" > "$HELM_SMOKE_REPORT_DIR/ui-image-tag.txt" |
| |
| HELM_SMOKE_VALUES_FILE="$(mktemp "${TMPDIR:-/tmp}/iggy-helm-smoke-values.XXXXXX.yaml")" |
| |
| cat > "$HELM_SMOKE_VALUES_FILE" <<EOF |
| server: |
| env: |
| - name: RUST_LOG |
| value: info |
| - name: IGGY_HTTP_ADDRESS |
| value: "0.0.0.0:3000" |
| - name: IGGY_TCP_ADDRESS |
| value: "0.0.0.0:8090" |
| - name: IGGY_QUIC_ADDRESS |
| value: "0.0.0.0:8080" |
| - name: IGGY_WEBSOCKET_ADDRESS |
| value: "0.0.0.0:8092" |
| - name: IGGY_SYSTEM_SHARDING_CPU_ALLOCATION |
| value: "${HELM_SMOKE_SERVER_CPU_ALLOCATION}" |
| ui: |
| image: |
| tag: "${ui_image_tag}" |
| EOF |
| |
| helm_status=0 |
| if helm upgrade --install "$HELM_SMOKE_RELEASE" "$CHART_DIR" \ |
| --atomic \ |
| --namespace "$HELM_SMOKE_NAMESPACE" \ |
| --create-namespace \ |
| --wait \ |
| --timeout "$HELM_SMOKE_TIMEOUT" \ |
| -f "$HELM_SMOKE_VALUES_FILE"; then |
| helm_status=0 |
| else |
| helm_status=$? |
| fi |
| |
| rm -f "$HELM_SMOKE_VALUES_FILE" |
| HELM_SMOKE_VALUES_FILE="" |
| |
| if [ "$helm_status" -ne 0 ]; then |
| return "$helm_status" |
| fi |
| |
| kubectl apply -f - <<EOF |
| apiVersion: gateway.networking.k8s.io/v1 |
| kind: HTTPRoute |
| metadata: |
| name: iggy-server |
| namespace: ${HELM_SMOKE_NAMESPACE} |
| spec: |
| parentRefs: |
| - name: ${HELM_SMOKE_GATEWAY_NAME} |
| namespace: ${HELM_SMOKE_GATEWAY_NAMESPACE} |
| hostnames: |
| - "${HELM_SMOKE_SERVER_HOST}" |
| rules: |
| - matches: |
| - path: |
| type: PathPrefix |
| value: / |
| backendRefs: |
| - name: ${HELM_SMOKE_RELEASE} |
| port: 3000 |
| --- |
| apiVersion: gateway.networking.k8s.io/v1 |
| kind: HTTPRoute |
| metadata: |
| name: iggy-ui |
| namespace: ${HELM_SMOKE_NAMESPACE} |
| spec: |
| parentRefs: |
| - name: ${HELM_SMOKE_GATEWAY_NAME} |
| namespace: ${HELM_SMOKE_GATEWAY_NAMESPACE} |
| hostnames: |
| - "${HELM_SMOKE_UI_HOST}" |
| rules: |
| - matches: |
| - path: |
| type: PathPrefix |
| value: / |
| backendRefs: |
| - name: ${HELM_SMOKE_RELEASE}-ui |
| port: 3050 |
| EOF |
| |
| gateway_svc="$(find_gateway_service)" |
| start_gateway_port_forward "$gateway_svc" |
| gateway_url="http://127.0.0.1:${HELM_SMOKE_GATEWAY_PF_PORT}" |
| |
| kubectl version --client=true > "$HELM_SMOKE_REPORT_DIR/kubectl-version.txt" |
| kubectl -n "$HELM_SMOKE_NAMESPACE" get pods,svc,httproutes > "$HELM_SMOKE_REPORT_DIR/resources.txt" |
| |
| for _ in $(seq 1 30); do |
| server_ping_status="$( |
| curl -sS -o "$HELM_SMOKE_REPORT_DIR/ping.txt" -w '%{http_code}' \ |
| -H "Host: ${HELM_SMOKE_SERVER_HOST}" \ |
| "${gateway_url}/ping" || true |
| )" |
| if [ "$server_ping_status" = "200" ] && grep -qx 'pong' "$HELM_SMOKE_REPORT_DIR/ping.txt"; then |
| break |
| fi |
| sleep 2 |
| done |
| |
| test "$server_ping_status" = "200" |
| grep -qx 'pong' "$HELM_SMOKE_REPORT_DIR/ping.txt" |
| |
| for _ in $(seq 1 30); do |
| ui_healthz_status="$( |
| curl -sS -o "$HELM_SMOKE_REPORT_DIR/ui-healthz.txt" -w '%{http_code}' \ |
| -H "Host: ${HELM_SMOKE_UI_HOST}" \ |
| "${gateway_url}/healthz" || true |
| )" |
| if [ "$ui_healthz_status" = "200" ]; then |
| break |
| fi |
| sleep 2 |
| done |
| |
| test "$ui_healthz_status" = "200" |
| |
| if [ "$cleanup_after_success" = true ]; then |
| cleanup_smoke |
| fi |
| } |
| |
| cleanup_smoke() { |
| require_command kubectl |
| |
| if command -v helm >/dev/null 2>&1; then |
| helm uninstall "$HELM_SMOKE_RELEASE" -n "$HELM_SMOKE_NAMESPACE" >/dev/null 2>&1 || true |
| fi |
| |
| kubectl delete namespace "$HELM_SMOKE_NAMESPACE" --ignore-not-found=true --wait=true >/dev/null 2>&1 || true |
| } |
| |
| collect_smoke_diagnostics() { |
| set +e |
| |
| mkdir -p "$HELM_SMOKE_REPORT_DIR" |
| |
| helm list -A > "$HELM_SMOKE_REPORT_DIR/helm-list.txt" 2>&1 || true |
| kubectl get namespaces > "$HELM_SMOKE_REPORT_DIR/namespaces.txt" 2>&1 || true |
| kubectl -n "$HELM_SMOKE_GATEWAY_NAMESPACE" get all > "$HELM_SMOKE_REPORT_DIR/envoy-gateway.txt" 2>&1 || true |
| kubectl -n "$HELM_SMOKE_NAMESPACE" get all > "$HELM_SMOKE_REPORT_DIR/get-all.txt" 2>&1 || true |
| kubectl -n "$HELM_SMOKE_NAMESPACE" get httproutes > "$HELM_SMOKE_REPORT_DIR/httproutes.txt" 2>&1 || true |
| kubectl -n "$HELM_SMOKE_NAMESPACE" describe "deployment/$HELM_SMOKE_RELEASE" > "$HELM_SMOKE_REPORT_DIR/describe-deployment.txt" 2>&1 || true |
| kubectl -n "$HELM_SMOKE_NAMESPACE" describe "deployment/${HELM_SMOKE_RELEASE}-ui" > "$HELM_SMOKE_REPORT_DIR/describe-ui-deployment.txt" 2>&1 || true |
| kubectl -n "$HELM_SMOKE_NAMESPACE" describe pods > "$HELM_SMOKE_REPORT_DIR/describe-pods.txt" 2>&1 || true |
| kubectl -n "$HELM_SMOKE_NAMESPACE" logs "deployment/$HELM_SMOKE_RELEASE" --all-containers=true > "$HELM_SMOKE_REPORT_DIR/server.log" 2>&1 || true |
| kubectl -n "$HELM_SMOKE_NAMESPACE" logs "deployment/${HELM_SMOKE_RELEASE}-ui" --all-containers=true > "$HELM_SMOKE_REPORT_DIR/ui.log" 2>&1 || true |
| kubectl -n "$HELM_SMOKE_GATEWAY_NAMESPACE" logs deployment/envoy-gateway --all-containers=true > "$HELM_SMOKE_REPORT_DIR/envoy-gateway.log" 2>&1 || true |
| |
| if command -v kind >/dev/null 2>&1; then |
| kind export logs "$HELM_SMOKE_REPORT_DIR/kind-logs" --name "$HELM_SMOKE_KIND_NAME" >/dev/null 2>&1 || true |
| fi |
| } |
| |
| main() { |
| local command |
| local smoke_cleanup=false |
| |
| if [ $# -lt 1 ]; then |
| usage |
| exit 1 |
| fi |
| |
| command="$1" |
| shift |
| |
| while [ $# -gt 0 ]; do |
| case "$1" in |
| --cleanup) |
| smoke_cleanup=true |
| ;; |
| --help|-h|help) |
| usage |
| exit 0 |
| ;; |
| *) |
| echo "Error: unknown option '$1'" >&2 |
| usage |
| exit 1 |
| ;; |
| esac |
| shift |
| done |
| |
| case "$command" in |
| validate) |
| if [ "$smoke_cleanup" = true ]; then |
| echo "Error: --cleanup is only supported with the smoke command" >&2 |
| exit 1 |
| fi |
| validate |
| ;; |
| smoke) |
| smoke "$smoke_cleanup" |
| ;; |
| cleanup-smoke) |
| if [ "$smoke_cleanup" = true ]; then |
| echo "Error: --cleanup is only supported with the smoke command" >&2 |
| exit 1 |
| fi |
| cleanup_smoke |
| ;; |
| collect-smoke-diagnostics) |
| if [ "$smoke_cleanup" = true ]; then |
| echo "Error: --cleanup is only supported with the smoke command" >&2 |
| exit 1 |
| fi |
| collect_smoke_diagnostics |
| ;; |
| --help|-h|help) |
| usage |
| ;; |
| *) |
| echo "Error: unknown command '$command'" >&2 |
| usage |
| exit 1 |
| ;; |
| esac |
| } |
| |
| main "$@" |