From 025de7eb23dea72c1fedaf3169256e116c2ac98f Mon Sep 17 00:00:00 2001 From: Federico Maleh Date: Wed, 27 May 2026 12:22:34 -0300 Subject: [PATCH 001/158] feat: opt-in ALB autocreation when pool capacity is exhausted --- CHANGELOG.md | 1 + k8s/docs/autocreate-alb.md | 76 +++++ k8s/scope/networking/autocreate_alb | 213 ++++++++++++++ k8s/scope/networking/resolve_balancer | 74 ++++- k8s/scope/templates/ingress-dummy.yaml.tpl | 28 ++ .../tests/networking/autocreate_alb.bats | 262 ++++++++++++++++++ .../tests/networking/resolve_balancer.bats | 213 +++++++++++++- k8s/values.yaml | 6 + 8 files changed, 870 insertions(+), 3 deletions(-) create mode 100644 k8s/docs/autocreate-alb.md create mode 100644 k8s/scope/networking/autocreate_alb create mode 100644 k8s/scope/templates/ingress-dummy.yaml.tpl create mode 100644 k8s/scope/tests/networking/autocreate_alb.bats diff --git a/CHANGELOG.md b/CHANGELOG.md index fb7861d6..acec6fd1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +- Add opt-in ALB autocreation for k8s scopes: when every declared ALB is at or above `ALB_MAX_CAPACITY`, the platform provisions a new ALB via a dummy Ingress, tags it for future discovery, and uses it for the scope. Disabled by default; enable with `ALB_AUTOCREATE_ENABLED=true`. Requires additional AWS permissions: `elasticloadbalancing:AddTags`, `elasticloadbalancing:DescribeTags`, `tag:GetResources` - Public and private scopes now register DNS records in their correct Route53 hosted zone when using `DNS_TYPE=external_dns`, preventing cross-zone record leakage - Add configurable main HTTP port for k8s scopes (default 8080) and HTTP support for additional ports - Improve **wait deployment active** failure logging: consolidate repeated `Unhealthy` probe events per pod into a single human-readable line, emit a progress heartbeat every 10% of timeout, and surface a targeted suggested fix based on the probe failure mode (port not open / HTTP non-2xx / probe timeout) diff --git a/k8s/docs/autocreate-alb.md b/k8s/docs/autocreate-alb.md new file mode 100644 index 00000000..bac8bb3d --- /dev/null +++ b/k8s/docs/autocreate-alb.md @@ -0,0 +1,76 @@ +# ALB Autocreation + +The k8s scope can provision new Application Load Balancers (ALBs) on demand when the declared pool of ALBs is exhausted. The behavior is opt-in and only triggers during scope creation; existing scopes are never moved to autocreated ALBs automatically. + +## When the autocreate path runs + +The flow only triggers when **all** of the following are true: + +- `ALB_AUTOCREATE_ENABLED=true` in `values.yaml` or in the `container-orchestration` provider. +- `DNS_TYPE=route53` (autocreation requires the same load-balancing path used by Route53 scopes). +- Every candidate ALB in the pool (declared base + additional balancers + previously autocreated ALBs discovered by tag) reports a rule count `>= ALB_MAX_CAPACITY`. +- The scope being created does not already have a Route53 record (a scope being recreated reuses its existing ALB and does not trigger autocreation). + +If any candidate is below the threshold, the scope creation uses that candidate and the autocreate path is not taken. + +## Configuration + +| Key | Default | Description | +|---|---|---| +| `ALB_AUTOCREATE_ENABLED` | `false` | Master switch. When `false`, behavior is identical to previous releases. | +| `ALB_AUTOCREATE_NAME_PREFIX` | `nullplatform-auto-` | Prefix for autocreated ALB names. Final name format: `-<6 hex chars>`. Total length must stay below the AWS 32-character ALB name limit. | +| `ALB_AUTOCREATE_TIMEOUT_SECONDS` | `300` | How long the script polls AWS for the new ALB to reach `state=active` before failing the scope creation. The AWS Load Balancer Controller usually takes 2–4 minutes. | + +All three keys are also readable from `providers.container-orchestration.balancer.{autocreate_enabled, autocreate_name_prefix, autocreate_timeout_seconds}`. + +## How it works + +1. `resolve_balancer` evaluates the candidate pool (declared + tag-discovered ALBs) and picks the least-loaded one as today. +2. If that candidate's rule count is at or above `ALB_MAX_CAPACITY` and `ALB_AUTOCREATE_ENABLED=true`, `resolve_balancer` sources `autocreate_alb`. +3. `autocreate_alb` generates a unique ALB name, renders `scope/templates/ingress-dummy.yaml.tpl`, and applies it. The AWS Load Balancer Controller picks up the Ingress and provisions the ALB. +4. The script polls `aws elbv2 describe-load-balancers` every 10 seconds until the ALB reports `State.Code=active` (or `failed`/timeout, in which case the scope creation fails). +5. Once active, the script tags the ALB with: + - `nullplatform:managed-by=autocreate` + - `nullplatform:visibility=internet-facing|internal` + - `nullplatform:created-by-scope-id=` +6. `resolve_balancer` substitutes the new ALB name and the rest of the scope creation proceeds. + +## Discovery of previously autocreated ALBs + +Every scope creation queries `resourcegroupstaggingapi:get-resources` for ALBs tagged `nullplatform:managed-by=autocreate` matching the scope's visibility. Discovered ALBs are merged into the candidate pool without any provider configuration change, so a single autocreated ALB serves many subsequent scopes before another autocreation is needed. + +Discovery runs regardless of `ALB_AUTOCREATE_ENABLED`: even if the flag is later turned off, previously autocreated ALBs remain usable. + +## Required AWS permissions + +In addition to the permissions already required for capacity validation, the agent role needs: + +- `elasticloadbalancing:AddTags` — to tag the new ALB so discovery can find it. +- `elasticloadbalancing:DescribeTags` — for the discovery path (covered by capacity validation in most agents, listed here for completeness). +- `tag:GetResources` — for the `resourcegroupstaggingapi` call used by discovery. + +The dummy Ingress requires no new K8s permissions beyond those the agent already has for scope resources. + +## Operational notes + +- Scope creations that trigger autocreation are slower (typically 2–4 minutes extra). This is the expected behavior, not a regression. The platform logs `🔧 All candidate ALBs are at or above capacity (...); triggering autocreate` when it happens. +- The dummy Ingress (`nullplatform-autocreate-`) is created in the scope's namespace. It exposes no traffic and exists only to keep the ALB alive. Deleting it manually will cause the AWS Load Balancer Controller to delete the ALB. +- The ALB is registered through AWS tags rather than through the nullplatform provider configuration. Two consequences: + 1. The nullplatform provider object does not need to be updated by the script; this avoids requiring API credentials inside the scope workflow. + 2. The cloud's IaC (Terraform, OpenTofu, CloudFormation) is **not** updated automatically. If your IaC is the source of truth for ALB inventory, you should reconcile autocreated ALBs into it through your own process. + +## Failure modes + +| Failure | Outcome | +|---|---| +| Dummy Ingress template render fails | Scope creation exits 1 with `Failed to render ingress-dummy template`. | +| `kubectl apply` fails | Scope creation exits 1 with `Failed to apply ingress-dummy` and prints the namespace check hint. | +| ALB never reaches `active` within `ALB_AUTOCREATE_TIMEOUT_SECONDS` | Scope creation exits 1; check controller logs and AWS quota for ALBs in the region. | +| AWS reports the ALB state as `failed` | Scope creation exits 1 immediately. | +| `AddTags` call fails (no IAM permission) | Logged as `⚠️ Could not tag ALB; subsequent discovery may not find it`. The scope creation continues; the next creation will not find this ALB by tag and may autocreate another one. | + +## What is out of scope + +- Migration of existing scopes to autocreated ALBs. Use the `Recreate scope` action if needed. +- Automatic cleanup of unused autocreated ALBs (no scopes referencing them). +- Updating the cloud IaC (Terraform / OpenTofu / CloudFormation) with the new ALB. diff --git a/k8s/scope/networking/autocreate_alb b/k8s/scope/networking/autocreate_alb new file mode 100644 index 00000000..1b6ffacb --- /dev/null +++ b/k8s/scope/networking/autocreate_alb @@ -0,0 +1,213 @@ +#!/bin/bash + +# Creates a new ALB on demand when the existing pool is exhausted. +# +# The script applies a dummy Ingress that the AWS Load Balancer Controller +# uses as the trigger to provision a new ALB. It then polls AWS until the +# ALB reaches the `active` state before returning the new ALB name to the +# caller via the AUTOCREATED_ALB_NAME output variable. +# +# Inputs (env vars): +# CONTEXT - Scope CONTEXT JSON (with .scope, .k8s_namespace, etc.) +# INGRESS_VISIBILITY - "internet-facing" or "internal" +# REGION - AWS region +# ALB_AUTOCREATE_NAME_PREFIX - Prefix for the new ALB (default: nullplatform-auto-) +# ALB_AUTOCREATE_TIMEOUT_SECONDS - Max seconds to wait for ALB active (default: 300) +# K8S_NAMESPACE - Namespace to place the dummy Ingress in +# +# Outputs (env vars): +# AUTOCREATED_ALB_NAME - Name of the ALB that was created + +_AUTOCREATE_ALB_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +if ! type -t log >/dev/null 2>&1; then + source "$_AUTOCREATE_ALB_DIR/../../logging" +fi + +if ! type -t get_config_value >/dev/null 2>&1; then + source "$_AUTOCREATE_ALB_DIR/../../utils/get_config_value" +fi + +# Generates a unique-enough ALB name for autocreation. +# Format: -<6-hex> +# Visibility short: "public" for internet-facing, "private" for internal. +# Total length kept under 32 chars (AWS ALB name limit). +generate_alb_name() { + local prefix="$1" + local visibility="$2" + + local vis_short + if [ "$visibility" = "internet-facing" ]; then + vis_short="public" + else + vis_short="private" + fi + + local suffix + suffix=$(LC_ALL=C tr -dc 'a-f0-9' < /dev/urandom 2>/dev/null | head -c 6) || { + suffix=$(printf '%06x' $((RANDOM * RANDOM % 0xFFFFFF))) + } + + echo "${prefix}${vis_short}-${suffix}" +} + +# Renders the dummy Ingress template and applies it to the cluster. +# Returns 0 on success, non-zero on failure (template render or kubectl apply). +apply_dummy_ingress() { + local alb_name="$1" + local visibility="$2" + local namespace="$3" + + local tmp_context + tmp_context=$(mktemp) || return 1 + local tmp_yaml + tmp_yaml=$(mktemp --suffix=.yaml 2>/dev/null) || tmp_yaml="$(mktemp).yaml" + + echo "$CONTEXT" | jq \ + --arg alb_name "$alb_name" \ + --arg ingress_visibility "$visibility" \ + --arg k8s_namespace "$namespace" \ + '. + {alb_name: $alb_name, ingress_visibility: $ingress_visibility, k8s_namespace: $k8s_namespace}' \ + > "$tmp_context" + + local template_path="${INGRESS_DUMMY_TEMPLATE:-$SERVICE_PATH/scope/templates/ingress-dummy.yaml.tpl}" + + if ! gomplate -c .="$tmp_context" --file "$template_path" --out "$tmp_yaml" 2>/dev/null; then + log error "❌ Failed to render ingress-dummy template" + log error "📋 Template: $template_path" + rm -f "$tmp_context" "$tmp_yaml" + return 1 + fi + + if ! kubectl apply -f "$tmp_yaml" >/dev/null 2>&1; then + log error "❌ Failed to apply ingress-dummy for ALB '$alb_name'" + log error "" + log error "💡 Possible causes:" + log error " The agent may lack permissions on Ingress resources or the namespace may not exist" + log error "" + log error "🔧 How to fix:" + log error " • kubectl apply -f $tmp_yaml" + log error " • Verify namespace '$namespace' exists" + rm -f "$tmp_context" "$tmp_yaml" + return 1 + fi + + rm -f "$tmp_context" "$tmp_yaml" + return 0 +} + +# Polls AWS until the ALB reaches the 'active' state, applying the autocreate +# tags once it is reachable. Returns 0 if active within timeout, 1 otherwise. +wait_for_alb_active() { + local alb_name="$1" + local timeout_seconds="$2" + local scope_id="$3" + local visibility="$4" + + local deadline=$(($(date +%s) + timeout_seconds)) + local poll_interval=10 + local state="" + local alb_arn="" + + log info "⏳ Waiting up to ${timeout_seconds}s for ALB '$alb_name' to become active..." + + while [ "$(date +%s)" -lt "$deadline" ]; do + alb_arn=$(aws elbv2 describe-load-balancers \ + --names "$alb_name" \ + --region "$REGION" \ + --query 'LoadBalancers[0].LoadBalancerArn' \ + --output text 2>/dev/null) || alb_arn="" + + if [ -n "$alb_arn" ] && [ "$alb_arn" != "None" ]; then + state=$(aws elbv2 describe-load-balancers \ + --names "$alb_name" \ + --region "$REGION" \ + --query 'LoadBalancers[0].State.Code' \ + --output text 2>/dev/null) || state="" + + log debug "📋 ALB '$alb_name' state: ${state:-pending}" + + if [ "$state" = "active" ]; then + log info "✅ ALB '$alb_name' is active" + tag_alb "$alb_arn" "$scope_id" "$visibility" || true + return 0 + fi + + if [ "$state" = "failed" ]; then + log error "❌ ALB '$alb_name' reached state 'failed'" + return 1 + fi + fi + + sleep "$poll_interval" + done + + log error "❌ Timed out after ${timeout_seconds}s waiting for ALB '$alb_name' to become active" + log error "" + log error "💡 Possible causes:" + log error " The AWS Load Balancer Controller may be slow, mis-configured, or the AWS account may be hitting an ALB quota" + log error "" + log error "🔧 How to fix:" + log error " • Check controller logs: kubectl -n kube-system logs deploy/aws-load-balancer-controller" + log error " • Verify ALB quota: aws service-quotas get-service-quota --service-code elasticloadbalancing --quota-code L-53DA6B97" + log error " • Inspect the dummy Ingress: kubectl get ingress -A -l alb_name=$alb_name" + return 1 +} + +# Tags the ALB so resolve_balancer can discover it in subsequent scope creations. +tag_alb() { + local alb_arn="$1" + local scope_id="$2" + local visibility="$3" + + aws elbv2 add-tags \ + --resource-arns "$alb_arn" \ + --region "$REGION" \ + --tags \ + "Key=nullplatform:managed-by,Value=autocreate" \ + "Key=nullplatform:visibility,Value=$visibility" \ + "Key=nullplatform:created-by-scope-id,Value=$scope_id" \ + >/dev/null 2>&1 || { + log warn "⚠️ Could not tag ALB; subsequent discovery may not find it" + return 1 + } + + log debug "📋 Tagged ALB with nullplatform:managed-by=autocreate" + return 0 +} + +# ============================================================================= +# Main +# ============================================================================= + +NAME_PREFIX=$(get_config_value \ + --env ALB_AUTOCREATE_NAME_PREFIX \ + --provider '.providers["container-orchestration"].balancer.autocreate_name_prefix' \ + --default "nullplatform-auto-" +) + +TIMEOUT_SECONDS=$(get_config_value \ + --env ALB_AUTOCREATE_TIMEOUT_SECONDS \ + --provider '.providers["container-orchestration"].balancer.autocreate_timeout_seconds' \ + --default "300" +) + +if ! [[ "$TIMEOUT_SECONDS" =~ ^[0-9]+$ ]]; then + log error "❌ ALB_AUTOCREATE_TIMEOUT_SECONDS must be a positive integer, got: '$TIMEOUT_SECONDS'" + return 1 +fi + +SCOPE_ID=$(echo "$CONTEXT" | jq -r '.scope.id // "unknown"') + +NEW_ALB_NAME=$(generate_alb_name "$NAME_PREFIX" "$INGRESS_VISIBILITY") +log info "🔧 Autocreating ALB '$NEW_ALB_NAME' (visibility=$INGRESS_VISIBILITY)" + +if ! apply_dummy_ingress "$NEW_ALB_NAME" "$INGRESS_VISIBILITY" "$K8S_NAMESPACE"; then + return 1 +fi + +if ! wait_for_alb_active "$NEW_ALB_NAME" "$TIMEOUT_SECONDS" "$SCOPE_ID" "$INGRESS_VISIBILITY"; then + return 1 +fi + +export AUTOCREATED_ALB_NAME="$NEW_ALB_NAME" diff --git a/k8s/scope/networking/resolve_balancer b/k8s/scope/networking/resolve_balancer index fd07a68f..57ddbac3 100755 --- a/k8s/scope/networking/resolve_balancer +++ b/k8s/scope/networking/resolve_balancer @@ -124,6 +124,32 @@ get_alb_from_route53() { echo "$alb_name" } +# Lists ALB names tagged as autocreated for the given visibility. Used to keep +# previously-autocreated ALBs in the candidate pool without requiring them to +# be declared in the provider configuration. +# Returns space-separated names on stdout (may be empty), non-zero on AWS failure. +get_autocreated_albs() { + local visibility="$1" + + local arns + arns=$(aws resourcegroupstaggingapi get-resources \ + --region "$REGION" \ + --resource-type-filters "elasticloadbalancing:loadbalancer" \ + --tag-filters \ + "Key=nullplatform:managed-by,Values=autocreate" \ + "Key=nullplatform:visibility,Values=$visibility" \ + --query 'ResourceTagMappingList[].ResourceARN' \ + --output text 2>/dev/null) || return 1 + + if [ -z "$arns" ] || [ "$arns" = "None" ]; then + return 0 + fi + + # ALB ARN format: arn:aws:elasticloadbalancing:::loadbalancer/app// + # Skip non-application LBs (would have loadbalancer/net/... or loadbalancer/gwy/...). + echo "$arns" | tr '\t' '\n' | awk -F/ '$2 == "app" { print $3 }' +} + # ============================================================================= # Main logic # ============================================================================= @@ -174,10 +200,26 @@ if [[ "$DNS_TYPE" == "route53" ]]; then ) fi + # Discovered ALBs: autocreated by previous scope creations and tagged so we + # can include them in the pool without provider config changes. + AUTOCREATED_BALANCERS=$(get_autocreated_albs "$INGRESS_VISIBILITY" 2>/dev/null) || AUTOCREATED_BALANCERS="" + + HAS_ADDITIONAL=0 if [ -n "$ADDITIONAL_BALANCERS" ] && [ "$ADDITIONAL_BALANCERS" != "null" ] && [ "$ADDITIONAL_BALANCERS" != "[]" ]; then - log debug "🔍 Additional balancers configured, resolving least-loaded ALB..." + HAS_ADDITIONAL=1 + fi + + if [ "$HAS_ADDITIONAL" -eq 1 ] || [ -n "$AUTOCREATED_BALANCERS" ]; then + log debug "🔍 Resolving least-loaded ALB across declared and autocreated candidates..." - CANDIDATES=$(echo "$ADDITIONAL_BALANCERS" | jq -r --arg base "$ALB_NAME" '[$base] + . | .[]') + if [ "$HAS_ADDITIONAL" -eq 1 ]; then + DECLARED_LIST=$(echo "$ADDITIONAL_BALANCERS" | jq -r --arg base "$ALB_NAME" '[$base] + . | .[]') + else + DECLARED_LIST="$ALB_NAME" + fi + + # Merge declared + autocreated, deduplicate, drop blanks. + CANDIDATES=$(printf '%s\n%s\n' "$DECLARED_LIST" "$AUTOCREATED_BALANCERS" | tr ' ' '\n' | awk 'NF && !seen[$0]++') log debug "📋 Candidate balancers: $(echo "$CANDIDATES" | paste -sd ',' - | sed 's/,/, /g')" @@ -203,6 +245,34 @@ if [[ "$DNS_TYPE" == "route53" ]]; then fi ALB_NAME="$BEST_ALB" + + # Autocreate fallback: every candidate is at or above the threshold and + # autocreate is enabled. Delegate to autocreate_alb to provision a new + # ALB and replace ALB_NAME with it. + AUTOCREATE_ENABLED=$(get_config_value \ + --env ALB_AUTOCREATE_ENABLED \ + --provider '.providers["container-orchestration"].balancer.autocreate_enabled' \ + --default "false" + ) + + MAX_CAPACITY=$(get_config_value \ + --env ALB_MAX_CAPACITY \ + --provider '.providers["scope-configurations"].networking.alb_max_capacity' \ + --provider '.providers["container-orchestration"].balancer.alb_capacity_threshold' \ + --default "75" + ) + + if [ "$AUTOCREATE_ENABLED" = "true" ] && [ "$MIN_RULES" -ge 0 ] && [ "$MIN_RULES" -ge "$MAX_CAPACITY" ]; then + log info "🔧 All candidate ALBs are at or above capacity ($MIN_RULES/$MAX_CAPACITY); triggering autocreate" + source "$_RESOLVE_BALANCER_DIR/autocreate_alb" || { + log error "❌ Autocreate failed; ALB '$ALB_NAME' will be used and validate_alb_capacity will reject the deployment" + return 1 + } + if [ -n "${AUTOCREATED_ALB_NAME:-}" ]; then + ALB_NAME="$AUTOCREATED_ALB_NAME" + log info "📝 Using autocreated ALB '$ALB_NAME'" + fi + fi fi fi else diff --git a/k8s/scope/templates/ingress-dummy.yaml.tpl b/k8s/scope/templates/ingress-dummy.yaml.tpl new file mode 100644 index 00000000..3d6bd3f8 --- /dev/null +++ b/k8s/scope/templates/ingress-dummy.yaml.tpl @@ -0,0 +1,28 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: nullplatform-autocreate-{{ .alb_name }} + namespace: {{ .k8s_namespace }} + labels: + nullplatform: "true" + nullplatform-autocreate: "true" + alb_name: {{ .alb_name }} + annotations: + alb.ingress.kubernetes.io/group.name: {{ .alb_name }} + alb.ingress.kubernetes.io/listen-ports: '[{"HTTP":80},{"HTTPS":443}]' + alb.ingress.kubernetes.io/load-balancer-name: {{ .alb_name }} + alb.ingress.kubernetes.io/scheme: {{ .ingress_visibility }} + alb.ingress.kubernetes.io/target-type: ip + alb.ingress.kubernetes.io/tags: nullplatform:managed-by=autocreate,nullplatform:visibility={{ .ingress_visibility }},nullplatform:created-by-scope-id={{ .scope.id }} +spec: + ingressClassName: alb + rules: + - http: + paths: + - path: /__nullplatform_autocreate_placeholder + pathType: Prefix + backend: + service: + name: nullplatform-autocreate-placeholder + port: + number: 80 diff --git a/k8s/scope/tests/networking/autocreate_alb.bats b/k8s/scope/tests/networking/autocreate_alb.bats new file mode 100644 index 00000000..03e1db17 --- /dev/null +++ b/k8s/scope/tests/networking/autocreate_alb.bats @@ -0,0 +1,262 @@ +#!/usr/bin/env bats +# ============================================================================= +# Unit tests for networking/autocreate_alb +# ============================================================================= + +setup() { + export PROJECT_ROOT="$(cd "$BATS_TEST_DIRNAME/../../../.." && pwd)" + source "$PROJECT_ROOT/testing/assertions.sh" + + log() { if [ "$1" = "error" ]; then echo "$2" >&2; else echo "$2"; fi; } + export -f log + + source "$PROJECT_ROOT/k8s/utils/get_config_value" + + export SCRIPT="$PROJECT_ROOT/k8s/scope/networking/autocreate_alb" + export REGION="us-east-1" + export INGRESS_VISIBILITY="internet-facing" + export K8S_NAMESPACE="test-ns" + export SERVICE_PATH="$PROJECT_ROOT/k8s" + export ALB_AUTOCREATE_TIMEOUT_SECONDS="2" + + export CONTEXT='{ + "scope": { "id": "scope-1", "slug": "scope-1" }, + "namespace": { "id": "ns-1", "slug": "ns-1" }, + "application": { "id": "app-1", "slug": "app-1" }, + "account": { "id": "acc-1", "slug": "acc-1" }, + "deployment": { "id": "dep-1" }, + "providers": { + "container-orchestration": {} + } + }' + + # Mocks: each test overrides as needed. + gomplate() { return 0; } + export -f gomplate + kubectl() { return 0; } + export -f kubectl + aws() { return 1; } + export -f aws + + # Tracks calls for assertions. + export CALL_LOG_FILE="$(mktemp)" +} + +teardown() { + unset -f log gomplate kubectl aws get_config_value + rm -f "$CALL_LOG_FILE" + unset AUTOCREATED_ALB_NAME +} + +# Records each invocation of a mocked binary into CALL_LOG_FILE so tests can +# assert against the sequence of calls. +record_call() { + echo "$@" >> "$CALL_LOG_FILE" +} + +# ============================================================================= +# Name generation +# ============================================================================= +@test "autocreate_alb: generates ALB name with prefix and visibility short form" { + # Mock AWS so describe-load-balancers reports active immediately. + aws() { + case "$*" in + *describe-load-balancers*--query*State.Code*) echo "active"; return 0 ;; + *describe-load-balancers*) echo "arn:aws:elasticloadbalancing:us-east-1:123:loadbalancer/app/nullplatform-auto-public-abc123/x"; return 0 ;; + *add-tags*) return 0 ;; + *) return 1 ;; + esac + } + export -f aws + + source "$SCRIPT" + + # Length and prefix + [[ "$AUTOCREATED_ALB_NAME" =~ ^nullplatform-auto-public-[a-f0-9]{6}$ ]] +} + +@test "autocreate_alb: uses private short form for internal visibility" { + export INGRESS_VISIBILITY="internal" + aws() { + case "$*" in + *describe-load-balancers*--query*State.Code*) echo "active"; return 0 ;; + *describe-load-balancers*) echo "arn:aws:elasticloadbalancing:us-east-1:123:loadbalancer/app/x/y"; return 0 ;; + *add-tags*) return 0 ;; + *) return 1 ;; + esac + } + export -f aws + + source "$SCRIPT" + + [[ "$AUTOCREATED_ALB_NAME" =~ ^nullplatform-auto-private-[a-f0-9]{6}$ ]] +} + +@test "autocreate_alb: respects custom name prefix from env" { + export ALB_AUTOCREATE_NAME_PREFIX="custom-prefix-" + aws() { + case "$*" in + *describe-load-balancers*--query*State.Code*) echo "active"; return 0 ;; + *describe-load-balancers*) echo "arn:aws:elasticloadbalancing:us-east-1:123:loadbalancer/app/x/y"; return 0 ;; + *add-tags*) return 0 ;; + *) return 1 ;; + esac + } + export -f aws + + source "$SCRIPT" + + [[ "$AUTOCREATED_ALB_NAME" =~ ^custom-prefix-public- ]] +} + +# ============================================================================= +# Ingress dummy application +# ============================================================================= +@test "autocreate_alb: renders and applies the dummy ingress before polling" { + gomplate() { record_call "gomplate $*"; return 0; } + export -f gomplate + kubectl() { record_call "kubectl $*"; return 0; } + export -f kubectl + aws() { + case "$*" in + *describe-load-balancers*--query*State.Code*) echo "active"; return 0 ;; + *describe-load-balancers*) echo "arn:aws:elasticloadbalancing:us-east-1:123:loadbalancer/app/x/y"; return 0 ;; + *add-tags*) return 0 ;; + *) return 1 ;; + esac + } + export -f aws + + source "$SCRIPT" + + # Both gomplate and kubectl must have been invoked. + grep -q "gomplate" "$CALL_LOG_FILE" + grep -q "kubectl apply" "$CALL_LOG_FILE" +} + +@test "autocreate_alb: fails if gomplate render fails" { + gomplate() { return 1; } + export -f gomplate + + run bash -c 'source "$SCRIPT"' + + [ "$status" -ne 0 ] + assert_contains "$output" "Failed to render ingress-dummy template" +} + +@test "autocreate_alb: fails if kubectl apply fails" { + kubectl() { return 1; } + export -f kubectl + + run bash -c 'source "$SCRIPT"' + + [ "$status" -ne 0 ] + assert_contains "$output" "Failed to apply ingress-dummy" +} + +# ============================================================================= +# Polling for active state +# ============================================================================= +@test "autocreate_alb: returns success when ALB becomes active within timeout" { + # First describe call returns pending arn, then state=active. + aws() { + case "$*" in + *describe-load-balancers*--query*State.Code*) echo "active"; return 0 ;; + *describe-load-balancers*) echo "arn:aws:elasticloadbalancing:us-east-1:123:loadbalancer/app/x/y"; return 0 ;; + *add-tags*) return 0 ;; + *) return 1 ;; + esac + } + export -f aws + + source "$SCRIPT" + + [ -n "$AUTOCREATED_ALB_NAME" ] +} + +@test "autocreate_alb: exits non-zero when ALB never reaches active state (timeout)" { + export ALB_AUTOCREATE_TIMEOUT_SECONDS="1" + # Always return pending state, never 'active'. + aws() { + case "$*" in + *describe-load-balancers*--query*State.Code*) echo "provisioning"; return 0 ;; + *describe-load-balancers*) echo "arn:aws:elasticloadbalancing:us-east-1:123:loadbalancer/app/x/y"; return 0 ;; + *) return 1 ;; + esac + } + export -f aws + + run bash -c 'source "$SCRIPT"' + + [ "$status" -ne 0 ] + assert_contains "$output" "Timed out" +} + +@test "autocreate_alb: exits non-zero when ALB reaches 'failed' state" { + aws() { + case "$*" in + *describe-load-balancers*--query*State.Code*) echo "failed"; return 0 ;; + *describe-load-balancers*) echo "arn:aws:elasticloadbalancing:us-east-1:123:loadbalancer/app/x/y"; return 0 ;; + *) return 1 ;; + esac + } + export -f aws + + run bash -c 'source "$SCRIPT"' + + [ "$status" -ne 0 ] + assert_contains "$output" "reached state 'failed'" +} + +# ============================================================================= +# Tagging +# ============================================================================= +@test "autocreate_alb: tags the ALB with managed-by, visibility and scope-id" { + aws() { + case "$*" in + *describe-load-balancers*--query*State.Code*) echo "active"; return 0 ;; + *describe-load-balancers*) echo "arn:aws:elasticloadbalancing:us-east-1:123:loadbalancer/app/x/y"; return 0 ;; + *add-tags*) + record_call "aws $*" + return 0 + ;; + *) return 1 ;; + esac + } + export -f aws + + source "$SCRIPT" + + grep -q "nullplatform:managed-by,Value=autocreate" "$CALL_LOG_FILE" + grep -q "nullplatform:visibility,Value=internet-facing" "$CALL_LOG_FILE" + grep -q "nullplatform:created-by-scope-id,Value=scope-1" "$CALL_LOG_FILE" +} + +@test "autocreate_alb: tagging failure does not fail the script (warn only)" { + aws() { + case "$*" in + *describe-load-balancers*--query*State.Code*) echo "active"; return 0 ;; + *describe-load-balancers*) echo "arn:aws:elasticloadbalancing:us-east-1:123:loadbalancer/app/x/y"; return 0 ;; + *add-tags*) return 1 ;; + *) return 1 ;; + esac + } + export -f aws + + source "$SCRIPT" + + # Script still exports the new ALB name even though tagging warned. + [ -n "$AUTOCREATED_ALB_NAME" ] +} + +# ============================================================================= +# Timeout validation +# ============================================================================= +@test "autocreate_alb: rejects non-numeric timeout" { + export ALB_AUTOCREATE_TIMEOUT_SECONDS="abc" + + run bash -c 'source "$SCRIPT"' + + [ "$status" -ne 0 ] + assert_contains "$output" "must be a positive integer" +} diff --git a/k8s/scope/tests/networking/resolve_balancer.bats b/k8s/scope/tests/networking/resolve_balancer.bats index 676d8c67..fa35440a 100644 --- a/k8s/scope/tests/networking/resolve_balancer.bats +++ b/k8s/scope/tests/networking/resolve_balancer.bats @@ -368,7 +368,7 @@ mock_alb_rules() { run bash -c 'export LOG_LEVEL=debug; source "$SCRIPT"' - assert_contains "$output" "🔍 Additional balancers configured, resolving least-loaded ALB..." + assert_contains "$output" "🔍 Resolving least-loaded ALB across declared and autocreated candidates..." assert_contains "$output" "📋 Candidate balancers: co-balancer-public, alb-extra-1, alb-extra-2" } @@ -497,3 +497,214 @@ mock_alb_rules() { assert_contains "$output" "DNS type is 'external_dns', skipping Route53 lookup and load balancing" } + +# ============================================================================= +# Discovery of autocreated ALBs via tags +# ============================================================================= + +# Extends mock_alb_rules behavior to also serve a resourcegroupstaggingapi +# response listing autocreated ALBs as candidates. Pass "alb_name count" pairs +# as positional args; pass the discovered ALB names via the +# DISCOVERED_AUTOCREATED env var (space-separated). +mock_alb_rules_with_discovery() { + > "$MOCK_RULES_FILE" + for pair in "$@"; do + echo "$pair" >> "$MOCK_RULES_FILE" + done + local rules_file="$MOCK_RULES_FILE" + local discovered_arns="" + for name in $DISCOVERED_AUTOCREATED; do + discovered_arns="${discovered_arns}arn:aws:elasticloadbalancing:us-east-1:123:loadbalancer/app/${name}/abc"$'\t' + done + discovered_arns="${discovered_arns%$'\t'}" + + eval "aws() { + case \"\$*\" in + *list-resource-record-sets*) echo 'None'; return 0 ;; + *resourcegroupstaggingapi*get-resources*) + echo '${discovered_arns}' + return 0 + ;; + *describe-load-balancers*--names*) + local name='' + local prev='' + for arg in \"\$@\"; do + if [ \"\$prev\" = '--names' ]; then name=\"\$arg\"; fi + prev=\"\$arg\" + done + if ! grep -q \"^\${name} \" '${rules_file}' 2>/dev/null; then + return 1 + fi + echo \"arn:aws:elasticloadbalancing:us-east-1:123:loadbalancer/app/\${name}/abc\" + return 0 + ;; + *describe-listeners*) + local lb_arn='' + local prev='' + for arg in \"\$@\"; do + if [ \"\$prev\" = '--load-balancer-arn' ]; then lb_arn=\"\$arg\"; fi + prev=\"\$arg\" + done + local alb_name=\$(echo \"\$lb_arn\" | sed 's|.*/app/||;s|/.*||') + echo \"arn:aws:elasticloadbalancing:us-east-1:123:listener/app/\${alb_name}/abc/def\" + return 0 + ;; + *describe-rules*) + local listener_arn='' + local prev='' + for arg in \"\$@\"; do + if [ \"\$prev\" = '--listener-arn' ]; then listener_arn=\"\$arg\"; fi + prev=\"\$arg\" + done + local alb_name=\$(echo \"\$listener_arn\" | sed 's|.*/app/||;s|/.*||') + local count=\$(grep \"^\${alb_name} \" '${rules_file}' | awk '{print \$2}') + if [ -z \"\$count\" ]; then + return 1 + fi + local rules='{\"Rules\": [{\"IsDefault\": true}' + local i=0 + while [ \$i -lt \$count ]; do + rules=\"\${rules}, {\\\"IsDefault\\\": false}\" + i=\$((i + 1)) + done + rules=\"\${rules}]}\" + echo \"\$rules\" + return 0 + ;; + *) return 1 ;; + esac + } + export -f aws" +} + +@test "resolve_balancer: discovers autocreated ALBs from tags and includes them as candidates" { + export INGRESS_VISIBILITY="internet-facing" + export DISCOVERED_AUTOCREATED="nullplatform-auto-public-aaaaaa" + mock_alb_rules_with_discovery "co-balancer-public 50" "nullplatform-auto-public-aaaaaa 5" + + source "$SCRIPT" + + assert_equal "$ALB_NAME" "nullplatform-auto-public-aaaaaa" +} + +@test "resolve_balancer: skips non-application LBs in discovery output" { + export INGRESS_VISIBILITY="internet-facing" + # Inject a network LB ARN that should be filtered out by the awk in get_autocreated_albs + aws() { + case "$*" in + *list-resource-record-sets*) echo "None"; return 0 ;; + *resourcegroupstaggingapi*get-resources*) + printf 'arn:aws:elasticloadbalancing:us-east-1:123:loadbalancer/net/some-nlb/abc\n' + return 0 + ;; + *) return 1 ;; + esac + } + export -f aws + + source "$SCRIPT" + + # No additional candidates → falls back to default + assert_equal "$ALB_NAME" "co-balancer-public" +} + +# ============================================================================= +# Autocreate fallback when all candidates are over capacity +# ============================================================================= +@test "resolve_balancer: triggers autocreate when all candidates over threshold and feature enabled" { + export INGRESS_VISIBILITY="internet-facing" + export ALB_AUTOCREATE_ENABLED="true" + export ALB_MAX_CAPACITY="50" + export ALB_AUTOCREATE_TIMEOUT_SECONDS="2" + export ALB_AUTOCREATE_NAME_PREFIX="auto-" + export K8S_NAMESPACE="test-ns" + export SERVICE_PATH="$PROJECT_ROOT/k8s" + export CONTEXT=$(echo "$CONTEXT" | jq ' + .providers["scope-configurations"].networking.additional_public_balancers = ["alb-extra-1"] | + .scope.slug = "s" | + .scope.id = "scope-1" | + .namespace.slug = "ns" | + .namespace.id = "ns-1" | + .application.slug = "app" | + .application.id = "app-1" | + .account.slug = "acc" | + .account.id = "acc-1" | + .deployment.id = "dep-1" + ') + + # Both declared ALBs are above threshold; aws describe for autocreate + # returns "active" immediately so the new ALB name is exported. + aws() { + case "$*" in + *list-resource-record-sets*) echo "None"; return 0 ;; + *resourcegroupstaggingapi*get-resources*) echo ""; return 0 ;; + *describe-load-balancers*--query*State.Code*) echo "active"; return 0 ;; + *describe-load-balancers*--names*) + local name='' + local prev='' + for arg in "$@"; do + if [ "$prev" = "--names" ]; then name="$arg"; fi + prev="$arg" + done + echo "arn:aws:elasticloadbalancing:us-east-1:123:loadbalancer/app/${name}/abc" + return 0 + ;; + *describe-listeners*) + local lb_arn='' + local prev='' + for arg in "$@"; do + if [ "$prev" = "--load-balancer-arn" ]; then lb_arn="$arg"; fi + prev="$arg" + done + local alb_name=$(echo "$lb_arn" | sed 's|.*/app/||;s|/.*||') + echo "arn:aws:elasticloadbalancing:us-east-1:123:listener/app/${alb_name}/abc/def" + return 0 + ;; + *describe-rules*) + # Both candidates report 60 rules (above threshold of 50) + echo '{"Rules":[{"IsDefault":true},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false}]}' + return 0 + ;; + *add-tags*) return 0 ;; + *) return 1 ;; + esac + } + export -f aws + gomplate() { return 0; } + export -f gomplate + kubectl() { return 0; } + export -f kubectl + + source "$SCRIPT" + + [[ "$ALB_NAME" =~ ^auto-public-[a-f0-9]{6}$ ]] +} + +@test "resolve_balancer: does not autocreate when feature disabled even if all candidates full" { + export INGRESS_VISIBILITY="internet-facing" + export ALB_AUTOCREATE_ENABLED="false" + export ALB_MAX_CAPACITY="50" + export CONTEXT=$(echo "$CONTEXT" | jq ' + .providers["scope-configurations"].networking.additional_public_balancers = ["alb-extra-1"] + ') + # Both above threshold but autocreate disabled → keeps least-loaded + mock_alb_rules "co-balancer-public 60" "alb-extra-1 55" + + source "$SCRIPT" + + assert_equal "$ALB_NAME" "alb-extra-1" +} + +@test "resolve_balancer: does not autocreate when at least one candidate below threshold" { + export INGRESS_VISIBILITY="internet-facing" + export ALB_AUTOCREATE_ENABLED="true" + export ALB_MAX_CAPACITY="50" + export CONTEXT=$(echo "$CONTEXT" | jq ' + .providers["scope-configurations"].networking.additional_public_balancers = ["alb-extra-1"] + ') + mock_alb_rules "co-balancer-public 60" "alb-extra-1 10" + + source "$SCRIPT" + + assert_equal "$ALB_NAME" "alb-extra-1" +} diff --git a/k8s/values.yaml b/k8s/values.yaml index d053bc0a..5700b427 100644 --- a/k8s/values.yaml +++ b/k8s/values.yaml @@ -19,6 +19,12 @@ configuration: ALB_MAX_LISTENERS: 48 ALB_METRICS_PUBLISH_ENABLED: false # ALB_METRICS_PUBLISH_TARGET: cloudwatch # Available values: cloudwatch | datadog + ALB_AUTOCREATE_ENABLED: false +# When true and every candidate ALB is at or above ALB_MAX_CAPACITY, the scope +# creation provisions a new ALB via a dummy Ingress and waits for it to become +# active. Previously-autocreated ALBs are auto-discovered by AWS tag. + ALB_AUTOCREATE_NAME_PREFIX: nullplatform-auto- + ALB_AUTOCREATE_TIMEOUT_SECONDS: 300 DEPLOYMENT_MAX_WAIT_IN_SECONDS: 600 DEPLOYMENT_TEMPLATE: "$SERVICE_PATH/deployment/templates/deployment.yaml.tpl" SECRET_TEMPLATE: "$SERVICE_PATH/deployment/templates/secret.yaml.tpl" From 59821c36acb6e47fb152211f99d765cf36b298f9 Mon Sep 17 00:00:00 2001 From: Federico Maleh Date: Wed, 27 May 2026 13:53:06 -0300 Subject: [PATCH 002/158] fix: harden autocreate input validation and merge AWS polling call --- k8s/scope/networking/autocreate_alb | 39 ++-- k8s/scope/networking/resolve_balancer | 17 +- .../tests/networking/autocreate_alb.bats | 61 +++-- .../tests/networking/resolve_balancer.bats | 210 ++++++++---------- 4 files changed, 168 insertions(+), 159 deletions(-) diff --git a/k8s/scope/networking/autocreate_alb b/k8s/scope/networking/autocreate_alb index 1b6ffacb..5c7395d0 100644 --- a/k8s/scope/networking/autocreate_alb +++ b/k8s/scope/networking/autocreate_alb @@ -45,7 +45,7 @@ generate_alb_name() { local suffix suffix=$(LC_ALL=C tr -dc 'a-f0-9' < /dev/urandom 2>/dev/null | head -c 6) || { - suffix=$(printf '%06x' $((RANDOM * RANDOM % 0xFFFFFF))) + suffix=$(printf '%06x' $((RANDOM * RANDOM % 16777215))) } echo "${prefix}${vis_short}-${suffix}" @@ -61,7 +61,8 @@ apply_dummy_ingress() { local tmp_context tmp_context=$(mktemp) || return 1 local tmp_yaml - tmp_yaml=$(mktemp --suffix=.yaml 2>/dev/null) || tmp_yaml="$(mktemp).yaml" + tmp_yaml=$(mktemp) || return 1 + trap 'rm -f "$tmp_context" "$tmp_yaml"' RETURN echo "$CONTEXT" | jq \ --arg alb_name "$alb_name" \ @@ -75,24 +76,19 @@ apply_dummy_ingress() { if ! gomplate -c .="$tmp_context" --file "$template_path" --out "$tmp_yaml" 2>/dev/null; then log error "❌ Failed to render ingress-dummy template" log error "📋 Template: $template_path" - rm -f "$tmp_context" "$tmp_yaml" return 1 fi if ! kubectl apply -f "$tmp_yaml" >/dev/null 2>&1; then log error "❌ Failed to apply ingress-dummy for ALB '$alb_name'" - log error "" log error "💡 Possible causes:" log error " The agent may lack permissions on Ingress resources or the namespace may not exist" - log error "" log error "🔧 How to fix:" log error " • kubectl apply -f $tmp_yaml" log error " • Verify namespace '$namespace' exists" - rm -f "$tmp_context" "$tmp_yaml" return 1 fi - rm -f "$tmp_context" "$tmp_yaml" return 0 } @@ -112,19 +108,16 @@ wait_for_alb_active() { log info "⏳ Waiting up to ${timeout_seconds}s for ALB '$alb_name' to become active..." while [ "$(date +%s)" -lt "$deadline" ]; do - alb_arn=$(aws elbv2 describe-load-balancers \ + local lb_json + lb_json=$(aws elbv2 describe-load-balancers \ --names "$alb_name" \ --region "$REGION" \ - --query 'LoadBalancers[0].LoadBalancerArn' \ - --output text 2>/dev/null) || alb_arn="" + --output json 2>/dev/null) || lb_json="" - if [ -n "$alb_arn" ] && [ "$alb_arn" != "None" ]; then - state=$(aws elbv2 describe-load-balancers \ - --names "$alb_name" \ - --region "$REGION" \ - --query 'LoadBalancers[0].State.Code' \ - --output text 2>/dev/null) || state="" + alb_arn=$(echo "$lb_json" | jq -r '.LoadBalancers[0].LoadBalancerArn // empty' 2>/dev/null) || alb_arn="" + state=$(echo "$lb_json" | jq -r '.LoadBalancers[0].State.Code // empty' 2>/dev/null) || state="" + if [ -n "$alb_arn" ] && [ "$alb_arn" != "None" ]; then log debug "📋 ALB '$alb_name' state: ${state:-pending}" if [ "$state" = "active" ]; then @@ -192,11 +185,23 @@ TIMEOUT_SECONDS=$(get_config_value \ --default "300" ) -if ! [[ "$TIMEOUT_SECONDS" =~ ^[0-9]+$ ]]; then +if ! [[ "$TIMEOUT_SECONDS" =~ ^[1-9][0-9]*$ ]]; then log error "❌ ALB_AUTOCREATE_TIMEOUT_SECONDS must be a positive integer, got: '$TIMEOUT_SECONDS'" return 1 fi +# Final ALB name is "-<6 hex>", which must satisfy AWS +# ALB naming rules ([a-zA-Z0-9-], ≤32 chars) and the k8s metadata.name rules +# used by the dummy Ingress. 14 = length of "private-" + 6 hex chars. +if ! [[ "$NAME_PREFIX" =~ ^[a-z0-9-]+$ ]]; then + log error "❌ ALB_AUTOCREATE_NAME_PREFIX must match ^[a-z0-9-]+$, got: '$NAME_PREFIX'" + return 1 +fi +if [ "${#NAME_PREFIX}" -gt 18 ]; then + log error "❌ ALB_AUTOCREATE_NAME_PREFIX must be ≤18 chars (AWS caps ALB names at 32, the visibility+hex suffix uses 14); got ${#NAME_PREFIX}" + return 1 +fi + SCOPE_ID=$(echo "$CONTEXT" | jq -r '.scope.id // "unknown"') NEW_ALB_NAME=$(generate_alb_name "$NAME_PREFIX" "$INGRESS_VISIBILITY") diff --git a/k8s/scope/networking/resolve_balancer b/k8s/scope/networking/resolve_balancer index 57ddbac3..2699f459 100755 --- a/k8s/scope/networking/resolve_balancer +++ b/k8s/scope/networking/resolve_balancer @@ -204,15 +204,15 @@ if [[ "$DNS_TYPE" == "route53" ]]; then # can include them in the pool without provider config changes. AUTOCREATED_BALANCERS=$(get_autocreated_albs "$INGRESS_VISIBILITY" 2>/dev/null) || AUTOCREATED_BALANCERS="" - HAS_ADDITIONAL=0 + HAS_ADDITIONAL=false if [ -n "$ADDITIONAL_BALANCERS" ] && [ "$ADDITIONAL_BALANCERS" != "null" ] && [ "$ADDITIONAL_BALANCERS" != "[]" ]; then - HAS_ADDITIONAL=1 + HAS_ADDITIONAL=true fi - if [ "$HAS_ADDITIONAL" -eq 1 ] || [ -n "$AUTOCREATED_BALANCERS" ]; then + if [ "$HAS_ADDITIONAL" = "true" ] || [ -n "$AUTOCREATED_BALANCERS" ]; then log debug "🔍 Resolving least-loaded ALB across declared and autocreated candidates..." - if [ "$HAS_ADDITIONAL" -eq 1 ]; then + if [ "$HAS_ADDITIONAL" = "true" ]; then DECLARED_LIST=$(echo "$ADDITIONAL_BALANCERS" | jq -r --arg base "$ALB_NAME" '[$base] + . | .[]') else DECLARED_LIST="$ALB_NAME" @@ -262,7 +262,14 @@ if [[ "$DNS_TYPE" == "route53" ]]; then --default "75" ) - if [ "$AUTOCREATE_ENABLED" = "true" ] && [ "$MIN_RULES" -ge 0 ] && [ "$MIN_RULES" -ge "$MAX_CAPACITY" ]; then + # Without this guard a non-numeric MAX_CAPACITY would silently disable the + # autocreate trigger (the `-ge` comparison errors out and evaluates false). + if ! [[ "$MAX_CAPACITY" =~ ^[0-9]+$ ]]; then + log warn "⚠️ ALB_MAX_CAPACITY must be numeric, got: '$MAX_CAPACITY' — skipping autocreate evaluation" + MAX_CAPACITY="" + fi + + if [ "$AUTOCREATE_ENABLED" = "true" ] && [ -n "$MAX_CAPACITY" ] && [ "$MIN_RULES" -ge 0 ] && [ "$MIN_RULES" -ge "$MAX_CAPACITY" ]; then log info "🔧 All candidate ALBs are at or above capacity ($MIN_RULES/$MAX_CAPACITY); triggering autocreate" source "$_RESOLVE_BALANCER_DIR/autocreate_alb" || { log error "❌ Autocreate failed; ALB '$ALB_NAME' will be used and validate_alb_capacity will reject the deployment" diff --git a/k8s/scope/tests/networking/autocreate_alb.bats b/k8s/scope/tests/networking/autocreate_alb.bats index 03e1db17..c5c47aa2 100644 --- a/k8s/scope/tests/networking/autocreate_alb.bats +++ b/k8s/scope/tests/networking/autocreate_alb.bats @@ -61,8 +61,7 @@ record_call() { # Mock AWS so describe-load-balancers reports active immediately. aws() { case "$*" in - *describe-load-balancers*--query*State.Code*) echo "active"; return 0 ;; - *describe-load-balancers*) echo "arn:aws:elasticloadbalancing:us-east-1:123:loadbalancer/app/nullplatform-auto-public-abc123/x"; return 0 ;; + *describe-load-balancers*) echo '{"LoadBalancers":[{"LoadBalancerArn":"arn:aws:elasticloadbalancing:us-east-1:123:loadbalancer/app/nullplatform-auto-public-abc123/x","State":{"Code":"active"}}]}'; return 0 ;; *add-tags*) return 0 ;; *) return 1 ;; esac @@ -79,8 +78,7 @@ record_call() { export INGRESS_VISIBILITY="internal" aws() { case "$*" in - *describe-load-balancers*--query*State.Code*) echo "active"; return 0 ;; - *describe-load-balancers*) echo "arn:aws:elasticloadbalancing:us-east-1:123:loadbalancer/app/x/y"; return 0 ;; + *describe-load-balancers*) echo '{"LoadBalancers":[{"LoadBalancerArn":"arn:aws:elasticloadbalancing:us-east-1:123:loadbalancer/app/x/y","State":{"Code":"active"}}]}'; return 0 ;; *add-tags*) return 0 ;; *) return 1 ;; esac @@ -96,8 +94,7 @@ record_call() { export ALB_AUTOCREATE_NAME_PREFIX="custom-prefix-" aws() { case "$*" in - *describe-load-balancers*--query*State.Code*) echo "active"; return 0 ;; - *describe-load-balancers*) echo "arn:aws:elasticloadbalancing:us-east-1:123:loadbalancer/app/x/y"; return 0 ;; + *describe-load-balancers*) echo '{"LoadBalancers":[{"LoadBalancerArn":"arn:aws:elasticloadbalancing:us-east-1:123:loadbalancer/app/x/y","State":{"Code":"active"}}]}'; return 0 ;; *add-tags*) return 0 ;; *) return 1 ;; esac @@ -119,8 +116,7 @@ record_call() { export -f kubectl aws() { case "$*" in - *describe-load-balancers*--query*State.Code*) echo "active"; return 0 ;; - *describe-load-balancers*) echo "arn:aws:elasticloadbalancing:us-east-1:123:loadbalancer/app/x/y"; return 0 ;; + *describe-load-balancers*) echo '{"LoadBalancers":[{"LoadBalancerArn":"arn:aws:elasticloadbalancing:us-east-1:123:loadbalancer/app/x/y","State":{"Code":"active"}}]}'; return 0 ;; *add-tags*) return 0 ;; *) return 1 ;; esac @@ -158,11 +154,10 @@ record_call() { # Polling for active state # ============================================================================= @test "autocreate_alb: returns success when ALB becomes active within timeout" { - # First describe call returns pending arn, then state=active. + # describe-load-balancers returns active state immediately. aws() { case "$*" in - *describe-load-balancers*--query*State.Code*) echo "active"; return 0 ;; - *describe-load-balancers*) echo "arn:aws:elasticloadbalancing:us-east-1:123:loadbalancer/app/x/y"; return 0 ;; + *describe-load-balancers*) echo '{"LoadBalancers":[{"LoadBalancerArn":"arn:aws:elasticloadbalancing:us-east-1:123:loadbalancer/app/x/y","State":{"Code":"active"}}]}'; return 0 ;; *add-tags*) return 0 ;; *) return 1 ;; esac @@ -176,11 +171,10 @@ record_call() { @test "autocreate_alb: exits non-zero when ALB never reaches active state (timeout)" { export ALB_AUTOCREATE_TIMEOUT_SECONDS="1" - # Always return pending state, never 'active'. + # Always return provisioning state, never 'active'. aws() { case "$*" in - *describe-load-balancers*--query*State.Code*) echo "provisioning"; return 0 ;; - *describe-load-balancers*) echo "arn:aws:elasticloadbalancing:us-east-1:123:loadbalancer/app/x/y"; return 0 ;; + *describe-load-balancers*) echo '{"LoadBalancers":[{"LoadBalancerArn":"arn:aws:elasticloadbalancing:us-east-1:123:loadbalancer/app/x/y","State":{"Code":"provisioning"}}]}'; return 0 ;; *) return 1 ;; esac } @@ -195,8 +189,7 @@ record_call() { @test "autocreate_alb: exits non-zero when ALB reaches 'failed' state" { aws() { case "$*" in - *describe-load-balancers*--query*State.Code*) echo "failed"; return 0 ;; - *describe-load-balancers*) echo "arn:aws:elasticloadbalancing:us-east-1:123:loadbalancer/app/x/y"; return 0 ;; + *describe-load-balancers*) echo '{"LoadBalancers":[{"LoadBalancerArn":"arn:aws:elasticloadbalancing:us-east-1:123:loadbalancer/app/x/y","State":{"Code":"failed"}}]}'; return 0 ;; *) return 1 ;; esac } @@ -214,8 +207,7 @@ record_call() { @test "autocreate_alb: tags the ALB with managed-by, visibility and scope-id" { aws() { case "$*" in - *describe-load-balancers*--query*State.Code*) echo "active"; return 0 ;; - *describe-load-balancers*) echo "arn:aws:elasticloadbalancing:us-east-1:123:loadbalancer/app/x/y"; return 0 ;; + *describe-load-balancers*) echo '{"LoadBalancers":[{"LoadBalancerArn":"arn:aws:elasticloadbalancing:us-east-1:123:loadbalancer/app/x/y","State":{"Code":"active"}}]}'; return 0 ;; *add-tags*) record_call "aws $*" return 0 @@ -235,8 +227,7 @@ record_call() { @test "autocreate_alb: tagging failure does not fail the script (warn only)" { aws() { case "$*" in - *describe-load-balancers*--query*State.Code*) echo "active"; return 0 ;; - *describe-load-balancers*) echo "arn:aws:elasticloadbalancing:us-east-1:123:loadbalancer/app/x/y"; return 0 ;; + *describe-load-balancers*) echo '{"LoadBalancers":[{"LoadBalancerArn":"arn:aws:elasticloadbalancing:us-east-1:123:loadbalancer/app/x/y","State":{"Code":"active"}}]}'; return 0 ;; *add-tags*) return 1 ;; *) return 1 ;; esac @@ -260,3 +251,33 @@ record_call() { [ "$status" -ne 0 ] assert_contains "$output" "must be a positive integer" } + +# ============================================================================= +# Name prefix validation +# ============================================================================= +@test "autocreate_alb: rejects prefix containing uppercase" { + export ALB_AUTOCREATE_NAME_PREFIX="Bad-Prefix-" + + run bash -c 'source "$SCRIPT"' + + [ "$status" -ne 0 ] + assert_contains "$output" "must match" +} + +@test "autocreate_alb: rejects prefix containing colon (YAML injection vector)" { + export ALB_AUTOCREATE_NAME_PREFIX="bad:prefix" + + run bash -c 'source "$SCRIPT"' + + [ "$status" -ne 0 ] + assert_contains "$output" "must match" +} + +@test "autocreate_alb: rejects prefix longer than 18 chars" { + export ALB_AUTOCREATE_NAME_PREFIX="this-prefix-is-way-too-long-" + + run bash -c 'source "$SCRIPT"' + + [ "$status" -ne 0 ] + assert_contains "$output" "18 chars" +} diff --git a/k8s/scope/tests/networking/resolve_balancer.bats b/k8s/scope/tests/networking/resolve_balancer.bats index fa35440a..c37888c1 100644 --- a/k8s/scope/tests/networking/resolve_balancer.bats +++ b/k8s/scope/tests/networking/resolve_balancer.bats @@ -84,75 +84,79 @@ mock_route53_alb() { export -f aws" } +# Handles the three elbv2 describe-* calls used by get_alb_rule_count. +# Reads rule counts from MOCK_RULES_FILE ("alb_name count" lines). +# Returns non-zero when an ALB name is not found in MOCK_RULES_FILE. +_mock_aws_elbv2_rule_count() { + case "$*" in + *describe-load-balancers*--names*) + local name="" prev="" + for arg in "$@"; do + if [ "$prev" = "--names" ]; then name="$arg"; fi + prev="$arg" + done + if ! grep -q "^${name} " "$MOCK_RULES_FILE" 2>/dev/null; then + return 1 + fi + echo "arn:aws:elasticloadbalancing:us-east-1:123:loadbalancer/app/${name}/abc" + ;; + *describe-listeners*) + local lb_arn="" prev="" + for arg in "$@"; do + if [ "$prev" = "--load-balancer-arn" ]; then lb_arn="$arg"; fi + prev="$arg" + done + local alb_name + alb_name=$(echo "$lb_arn" | sed 's|.*/app/||;s|/.*||') + echo "arn:aws:elasticloadbalancing:us-east-1:123:listener/app/${alb_name}/abc/def" + ;; + *describe-rules*) + local listener_arn="" prev="" + for arg in "$@"; do + if [ "$prev" = "--listener-arn" ]; then listener_arn="$arg"; fi + prev="$arg" + done + local alb_name + alb_name=$(echo "$listener_arn" | sed 's|.*/app/||;s|/.*||') + local count + count=$(grep "^${alb_name} " "$MOCK_RULES_FILE" | awk '{print $2}') + if [ -z "$count" ]; then + return 1 + fi + local rules='{"Rules": [{"IsDefault": true}' + local i=0 + while [ "$i" -lt "$count" ]; do + rules="${rules}, {\"IsDefault\": false}" + i=$((i + 1)) + done + echo "${rules}]}" + ;; + *) + return 1 + ;; + esac +} +export -f _mock_aws_elbv2_rule_count + # Sets up aws mock with no Route53 record but with rule counts for ALBs. -# Write rule counts to MOCK_RULES_FILE as "alb_name count" lines. -# The mock returns the ALB ARN with the name embedded so describe-rules -# can look up the correct rule count. +# Write rule counts to MOCK_RULES_FILE as "alb_name count" lines before calling. +# The mock returns ARNs with the name embedded so describe-rules can look up counts. mock_alb_rules() { > "$MOCK_RULES_FILE" for pair in "$@"; do echo "$pair" >> "$MOCK_RULES_FILE" done - local rules_file="$MOCK_RULES_FILE" - eval "aws() { - case \"\$*\" in - *list-resource-record-sets*) - echo 'None' - return 0 - ;; - *describe-load-balancers*--names*) - local name='' - local prev='' - for arg in \"\$@\"; do - if [ \"\$prev\" = '--names' ]; then name=\"\$arg\"; fi - prev=\"\$arg\" - done - if ! grep -q \"^\${name} \" '${rules_file}' 2>/dev/null; then - return 1 - fi - echo \"arn:aws:elasticloadbalancing:us-east-1:123:loadbalancer/app/\${name}/abc\" - return 0 - ;; - *describe-listeners*) - local lb_arn='' - local prev='' - for arg in \"\$@\"; do - if [ \"\$prev\" = '--load-balancer-arn' ]; then lb_arn=\"\$arg\"; fi - prev=\"\$arg\" - done - local alb_name=\$(echo \"\$lb_arn\" | sed 's|.*/app/||;s|/.*||') - echo \"arn:aws:elasticloadbalancing:us-east-1:123:listener/app/\${alb_name}/abc/def\" - return 0 - ;; - *describe-rules*) - local listener_arn='' - local prev='' - for arg in \"\$@\"; do - if [ \"\$prev\" = '--listener-arn' ]; then listener_arn=\"\$arg\"; fi - prev=\"\$arg\" - done - local alb_name=\$(echo \"\$listener_arn\" | sed 's|.*/app/||;s|/.*||') - local count=\$(grep \"^\${alb_name} \" '${rules_file}' | awk '{print \$2}') - if [ -z \"\$count\" ]; then - return 1 - fi - local rules='{\"Rules\": [{\"IsDefault\": true}' - local i=0 - while [ \$i -lt \$count ]; do - rules=\"\${rules}, {\\\"IsDefault\\\": false}\" - i=\$((i + 1)) - done - rules=\"\${rules}]}\" - echo \"\$rules\" - return 0 - ;; - *) - return 1 + aws() { + case "$*" in + *list-resource-record-sets*) echo "None" ;; + *describe-load-balancers*--names* | *describe-listeners* | *describe-rules*) + _mock_aws_elbv2_rule_count "$@" ;; + *) return 1 ;; esac } - export -f aws" + export -f aws } # ============================================================================= @@ -502,16 +506,13 @@ mock_alb_rules() { # Discovery of autocreated ALBs via tags # ============================================================================= -# Extends mock_alb_rules behavior to also serve a resourcegroupstaggingapi -# response listing autocreated ALBs as candidates. Pass "alb_name count" pairs -# as positional args; pass the discovered ALB names via the -# DISCOVERED_AUTOCREATED env var (space-separated). +# Extends mock_alb_rules to also serve a resourcegroupstaggingapi response +# listing autocreated ALBs as candidates. Pass "alb_name count" pairs as +# positional args; set DISCOVERED_AUTOCREATED (space-separated names) before +# calling to control which ALBs the tag-discovery API returns. mock_alb_rules_with_discovery() { - > "$MOCK_RULES_FILE" - for pair in "$@"; do - echo "$pair" >> "$MOCK_RULES_FILE" - done - local rules_file="$MOCK_RULES_FILE" + mock_alb_rules "$@" + local discovered_arns="" for name in $DISCOVERED_AUTOCREATED; do discovered_arns="${discovered_arns}arn:aws:elasticloadbalancing:us-east-1:123:loadbalancer/app/${name}/abc"$'\t' @@ -520,56 +521,13 @@ mock_alb_rules_with_discovery() { eval "aws() { case \"\$*\" in - *list-resource-record-sets*) echo 'None'; return 0 ;; *resourcegroupstaggingapi*get-resources*) echo '${discovered_arns}' return 0 ;; - *describe-load-balancers*--names*) - local name='' - local prev='' - for arg in \"\$@\"; do - if [ \"\$prev\" = '--names' ]; then name=\"\$arg\"; fi - prev=\"\$arg\" - done - if ! grep -q \"^\${name} \" '${rules_file}' 2>/dev/null; then - return 1 - fi - echo \"arn:aws:elasticloadbalancing:us-east-1:123:loadbalancer/app/\${name}/abc\" - return 0 - ;; - *describe-listeners*) - local lb_arn='' - local prev='' - for arg in \"\$@\"; do - if [ \"\$prev\" = '--load-balancer-arn' ]; then lb_arn=\"\$arg\"; fi - prev=\"\$arg\" - done - local alb_name=\$(echo \"\$lb_arn\" | sed 's|.*/app/||;s|/.*||') - echo \"arn:aws:elasticloadbalancing:us-east-1:123:listener/app/\${alb_name}/abc/def\" - return 0 - ;; - *describe-rules*) - local listener_arn='' - local prev='' - for arg in \"\$@\"; do - if [ \"\$prev\" = '--listener-arn' ]; then listener_arn=\"\$arg\"; fi - prev=\"\$arg\" - done - local alb_name=\$(echo \"\$listener_arn\" | sed 's|.*/app/||;s|/.*||') - local count=\$(grep \"^\${alb_name} \" '${rules_file}' | awk '{print \$2}') - if [ -z \"\$count\" ]; then - return 1 - fi - local rules='{\"Rules\": [{\"IsDefault\": true}' - local i=0 - while [ \$i -lt \$count ]; do - rules=\"\${rules}, {\\\"IsDefault\\\": false}\" - i=\$((i + 1)) - done - rules=\"\${rules}]}\" - echo \"\$rules\" - return 0 + *list-resource-record-sets*) echo 'None' ;; + *describe-load-balancers*--names* | *describe-listeners* | *describe-rules*) + _mock_aws_elbv2_rule_count \"\$@\" ;; *) return 1 ;; esac @@ -638,7 +596,6 @@ mock_alb_rules_with_discovery() { case "$*" in *list-resource-record-sets*) echo "None"; return 0 ;; *resourcegroupstaggingapi*get-resources*) echo ""; return 0 ;; - *describe-load-balancers*--query*State.Code*) echo "active"; return 0 ;; *describe-load-balancers*--names*) local name='' local prev='' @@ -646,8 +603,12 @@ mock_alb_rules_with_discovery() { if [ "$prev" = "--names" ]; then name="$arg"; fi prev="$arg" done - echo "arn:aws:elasticloadbalancing:us-east-1:123:loadbalancer/app/${name}/abc" - return 0 + # Return JSON when called with --output json (autocreate polling), + # or a plain ARN when called with --output text (rule count lookup). + case "$*" in + *--output*json*) echo "{\"LoadBalancers\":[{\"LoadBalancerArn\":\"arn:aws:elasticloadbalancing:us-east-1:123:loadbalancer/app/${name}/abc\",\"State\":{\"Code\":\"active\"}}]}"; return 0 ;; + *) echo "arn:aws:elasticloadbalancing:us-east-1:123:loadbalancer/app/${name}/abc"; return 0 ;; + esac ;; *describe-listeners*) local lb_arn='' @@ -708,3 +669,18 @@ mock_alb_rules_with_discovery() { assert_equal "$ALB_NAME" "alb-extra-1" } + +@test "resolve_balancer: warns and skips autocreate when ALB_MAX_CAPACITY is non-numeric" { + export INGRESS_VISIBILITY="internet-facing" + export ALB_AUTOCREATE_ENABLED="true" + export ALB_MAX_CAPACITY="not-a-number" + export CONTEXT=$(echo "$CONTEXT" | jq ' + .providers["scope-configurations"].networking.additional_public_balancers = ["alb-extra-1"] + ') + mock_alb_rules "co-balancer-public 60" "alb-extra-1 55" + + run bash -c 'source "$SCRIPT"' + + [ "$status" -eq 0 ] + assert_contains "$output" "ALB_MAX_CAPACITY must be numeric" +} From 56152e50b9162052f640fe3cddc9cb1c5b2d9ca7 Mon Sep 17 00:00:00 2001 From: Federico Maleh Date: Mon, 8 Jun 2026 14:32:04 -0300 Subject: [PATCH 003/158] refactor: address PR review feedback on autocreate flow --- k8s/scope/build_context | 15 +- k8s/scope/networking/autocreate_alb | 254 ++++++-------- k8s/scope/networking/resolve_balancer | 97 ++---- k8s/scope/networking/wait_for_alb | 86 +++++ k8s/scope/templates/ingress-dummy.yaml.tpl | 14 +- .../tests/networking/autocreate_alb.bats | 316 ++++++++---------- .../tests/networking/resolve_balancer.bats | 162 +++------ k8s/scope/tests/networking/wait_for_alb.bats | 140 ++++++++ k8s/scope/workflows/create.yaml | 14 + 9 files changed, 586 insertions(+), 512 deletions(-) create mode 100644 k8s/scope/networking/wait_for_alb create mode 100644 k8s/scope/tests/networking/wait_for_alb.bats diff --git a/k8s/scope/build_context b/k8s/scope/build_context index 8328eab6..548ca319 100755 --- a/k8s/scope/build_context +++ b/k8s/scope/build_context @@ -208,6 +208,13 @@ K8S_MODIFIERS=$(get_config_value \ ) K8S_MODIFIERS=$(echo "$K8S_MODIFIERS" | jq .) +OUTPUT_DIR="$SERVICE_PATH/output/$SCOPE_ID" +if [ -n "${NP_OUTPUT_DIR:-}" ]; then + OUTPUT_DIR="$NP_OUTPUT_DIR/output/$SCOPE_ID" +fi +mkdir -p "$OUTPUT_DIR" +export OUTPUT_DIR + source "$SCRIPT_DIR/networking/resolve_balancer" NAMESPACE_SLUG=$(echo "$CONTEXT" | jq -r .namespace.slug) @@ -227,15 +234,7 @@ CONTEXT=$(echo "$CONTEXT" | jq \ --argjson modifiers "$K8S_MODIFIERS" \ '. + {ingress_visibility: $ingress_visibility, k8s_namespace: $k8s_namespace, gateway_name: $gateway_name, region: $region, k8s_modifiers: $modifiers, alb_name: $alb_name, component: $component}') -OUTPUT_DIR="$SERVICE_PATH/output/$SCOPE_ID" -if [ -n "${NP_OUTPUT_DIR:-}" ]; then - OUTPUT_DIR="$NP_OUTPUT_DIR/output/$SCOPE_ID" -fi - -export OUTPUT_DIR export CONTEXT export REGION -mkdir -p "$OUTPUT_DIR" - log info "✅ Scope context built successfully" diff --git a/k8s/scope/networking/autocreate_alb b/k8s/scope/networking/autocreate_alb index 5c7395d0..aea35f6d 100644 --- a/k8s/scope/networking/autocreate_alb +++ b/k8s/scope/networking/autocreate_alb @@ -1,37 +1,32 @@ #!/bin/bash -# Creates a new ALB on demand when the existing pool is exhausted. +# Provisions a new ALB on demand when the existing pool is exhausted. # -# The script applies a dummy Ingress that the AWS Load Balancer Controller -# uses as the trigger to provision a new ALB. It then polls AWS until the -# ALB reaches the `active` state before returning the new ALB name to the -# caller via the AUTOCREATED_ALB_NAME output variable. +# Workflow contract: +# 1. Generates a unique ALB name. +# 2. Patches the container-orchestration provider via `np provider patch` so +# the new ALB is recorded as an additional balancer. Subsequent scope +# creations that read the provider see the new ALB and re-use it instead +# of triggering another autocreate. +# 3. Renders the dummy-ingress template to $OUTPUT_DIR. The next workflow +# step (apply_templates) applies it; that is what triggers the AWS Load +# Balancer Controller to actually provision the ALB. +# 4. Exports ALB_NAME (the new name) and ALB_AUTOCREATED=true so the wait +# step downstream knows to poll for active state and tag the ALB. # # Inputs (env vars): -# CONTEXT - Scope CONTEXT JSON (with .scope, .k8s_namespace, etc.) +# CONTEXT - Scope CONTEXT JSON # INGRESS_VISIBILITY - "internet-facing" or "internal" -# REGION - AWS region -# ALB_AUTOCREATE_NAME_PREFIX - Prefix for the new ALB (default: nullplatform-auto-) -# ALB_AUTOCREATE_TIMEOUT_SECONDS - Max seconds to wait for ALB active (default: 300) -# K8S_NAMESPACE - Namespace to place the dummy Ingress in +# K8S_NAMESPACE - Namespace for the dummy Ingress +# OUTPUT_DIR - Where the rendered YAML is written +# ALB_AUTOCREATE_NAME_PREFIX - Optional prefix for the new ALB # # Outputs (env vars): -# AUTOCREATED_ALB_NAME - Name of the ALB that was created +# ALB_NAME - Replaced with the new ALB name +# ALB_AUTOCREATED - Set to "true" _AUTOCREATE_ALB_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -if ! type -t log >/dev/null 2>&1; then - source "$_AUTOCREATE_ALB_DIR/../../logging" -fi - -if ! type -t get_config_value >/dev/null 2>&1; then - source "$_AUTOCREATE_ALB_DIR/../../utils/get_config_value" -fi - -# Generates a unique-enough ALB name for autocreation. -# Format: -<6-hex> -# Visibility short: "public" for internet-facing, "private" for internal. -# Total length kept under 32 chars (AWS ALB name limit). generate_alb_name() { local prefix="$1" local visibility="$2" @@ -51,122 +46,103 @@ generate_alb_name() { echo "${prefix}${vis_short}-${suffix}" } -# Renders the dummy Ingress template and applies it to the cluster. -# Returns 0 on success, non-zero on failure (template render or kubectl apply). -apply_dummy_ingress() { +# Reads the container-orchestration provider id and current additional balancer +# list for the requested visibility, then patches the provider to append the new +# ALB name. Surfaces the existing balancer.* attributes so the patch is a +# merge of the full balancer object, not a destructive replacement. +register_alb_in_provider() { + local new_alb_name="$1" + local visibility="$2" + local nrn + nrn=$(echo "$CONTEXT" | jq -r '.scope.nrn // empty') + if [ -z "$nrn" ]; then + log error "❌ Could not read scope NRN from CONTEXT — cannot patch provider" + exit 1 + fi + + local provider_json + provider_json=$(np provider list --categories container-orchestration --nrn "$nrn" --format json 2>/dev/null) || { + log error "❌ Failed to list container-orchestration provider for NRN '$nrn'" + exit 1 + } + + local provider_id + provider_id=$(echo "$provider_json" | jq -r '.results[0].id // empty') + if [ -z "$provider_id" ]; then + log error "❌ No container-orchestration provider found for NRN '$nrn'" + exit 1 + fi + + local field + if [ "$visibility" = "internet-facing" ]; then + field="additional_public_names" + else + field="additional_private_names" + fi + + # Merge: current balancer.* + appended ALB in the right field. + local patch_body + patch_body=$(echo "$provider_json" | jq -c \ + --arg field "$field" \ + --arg new_alb "$new_alb_name" \ + '{ + attributes: { + balancer: ( + (.results[0].attributes.balancer // {}) as $bal | + $bal + { ($field): (($bal[$field] // []) + [$new_alb] | unique) } + ) + } + }') + + log info "📝 Registering ALB '$new_alb_name' in container-orchestration provider ($field)" + if ! np provider patch --id "$provider_id" --body "$patch_body" --no-output 2>/dev/null; then + log error "❌ Failed to patch container-orchestration provider with new ALB" + log error "💡 Possible causes: agent lacks write permission on the provider, or NP_TOKEN/NULLPLATFORM_API_KEY is missing" + exit 1 + fi +} + +render_dummy_ingress() { local alb_name="$1" local visibility="$2" local namespace="$3" + if [ -z "${OUTPUT_DIR:-}" ]; then + log error "❌ OUTPUT_DIR is not set — autocreate_alb must run after OUTPUT_DIR is exported" + exit 1 + fi + mkdir -p "$OUTPUT_DIR" + local tmp_context - tmp_context=$(mktemp) || return 1 - local tmp_yaml - tmp_yaml=$(mktemp) || return 1 - trap 'rm -f "$tmp_context" "$tmp_yaml"' RETURN + tmp_context=$(mktemp) + trap 'rm -f "$tmp_context"' RETURN + + local base_domain + base_domain=$(get_config_value \ + --env DOMAIN \ + --provider '.providers["scope-configurations"].networking.base_domain' \ + --provider '.providers["container-orchestration"].networking.base_domain' \ + --default "nullapps.io" + ) echo "$CONTEXT" | jq \ --arg alb_name "$alb_name" \ --arg ingress_visibility "$visibility" \ --arg k8s_namespace "$namespace" \ - '. + {alb_name: $alb_name, ingress_visibility: $ingress_visibility, k8s_namespace: $k8s_namespace}' \ + --arg base_domain "$base_domain" \ + '. + {alb_name: $alb_name, ingress_visibility: $ingress_visibility, k8s_namespace: $k8s_namespace, base_domain: $base_domain}' \ > "$tmp_context" local template_path="${INGRESS_DUMMY_TEMPLATE:-$SERVICE_PATH/scope/templates/ingress-dummy.yaml.tpl}" + local out_path="$OUTPUT_DIR/ingress-dummy-${alb_name}.yaml" - if ! gomplate -c .="$tmp_context" --file "$template_path" --out "$tmp_yaml" 2>/dev/null; then + if ! gomplate -c .="$tmp_context" --file "$template_path" --out "$out_path"; then log error "❌ Failed to render ingress-dummy template" log error "📋 Template: $template_path" - return 1 - fi - - if ! kubectl apply -f "$tmp_yaml" >/dev/null 2>&1; then - log error "❌ Failed to apply ingress-dummy for ALB '$alb_name'" - log error "💡 Possible causes:" - log error " The agent may lack permissions on Ingress resources or the namespace may not exist" - log error "🔧 How to fix:" - log error " • kubectl apply -f $tmp_yaml" - log error " • Verify namespace '$namespace' exists" - return 1 + exit 1 fi - return 0 -} - -# Polls AWS until the ALB reaches the 'active' state, applying the autocreate -# tags once it is reachable. Returns 0 if active within timeout, 1 otherwise. -wait_for_alb_active() { - local alb_name="$1" - local timeout_seconds="$2" - local scope_id="$3" - local visibility="$4" - - local deadline=$(($(date +%s) + timeout_seconds)) - local poll_interval=10 - local state="" - local alb_arn="" - - log info "⏳ Waiting up to ${timeout_seconds}s for ALB '$alb_name' to become active..." - - while [ "$(date +%s)" -lt "$deadline" ]; do - local lb_json - lb_json=$(aws elbv2 describe-load-balancers \ - --names "$alb_name" \ - --region "$REGION" \ - --output json 2>/dev/null) || lb_json="" - - alb_arn=$(echo "$lb_json" | jq -r '.LoadBalancers[0].LoadBalancerArn // empty' 2>/dev/null) || alb_arn="" - state=$(echo "$lb_json" | jq -r '.LoadBalancers[0].State.Code // empty' 2>/dev/null) || state="" - - if [ -n "$alb_arn" ] && [ "$alb_arn" != "None" ]; then - log debug "📋 ALB '$alb_name' state: ${state:-pending}" - - if [ "$state" = "active" ]; then - log info "✅ ALB '$alb_name' is active" - tag_alb "$alb_arn" "$scope_id" "$visibility" || true - return 0 - fi - - if [ "$state" = "failed" ]; then - log error "❌ ALB '$alb_name' reached state 'failed'" - return 1 - fi - fi - - sleep "$poll_interval" - done - - log error "❌ Timed out after ${timeout_seconds}s waiting for ALB '$alb_name' to become active" - log error "" - log error "💡 Possible causes:" - log error " The AWS Load Balancer Controller may be slow, mis-configured, or the AWS account may be hitting an ALB quota" - log error "" - log error "🔧 How to fix:" - log error " • Check controller logs: kubectl -n kube-system logs deploy/aws-load-balancer-controller" - log error " • Verify ALB quota: aws service-quotas get-service-quota --service-code elasticloadbalancing --quota-code L-53DA6B97" - log error " • Inspect the dummy Ingress: kubectl get ingress -A -l alb_name=$alb_name" - return 1 -} - -# Tags the ALB so resolve_balancer can discover it in subsequent scope creations. -tag_alb() { - local alb_arn="$1" - local scope_id="$2" - local visibility="$3" - - aws elbv2 add-tags \ - --resource-arns "$alb_arn" \ - --region "$REGION" \ - --tags \ - "Key=nullplatform:managed-by,Value=autocreate" \ - "Key=nullplatform:visibility,Value=$visibility" \ - "Key=nullplatform:created-by-scope-id,Value=$scope_id" \ - >/dev/null 2>&1 || { - log warn "⚠️ Could not tag ALB; subsequent discovery may not find it" - return 1 - } - - log debug "📋 Tagged ALB with nullplatform:managed-by=autocreate" - return 0 + log debug "📝 Rendered dummy ingress to $out_path" } # ============================================================================= @@ -179,40 +155,12 @@ NAME_PREFIX=$(get_config_value \ --default "nullplatform-auto-" ) -TIMEOUT_SECONDS=$(get_config_value \ - --env ALB_AUTOCREATE_TIMEOUT_SECONDS \ - --provider '.providers["container-orchestration"].balancer.autocreate_timeout_seconds' \ - --default "300" -) - -if ! [[ "$TIMEOUT_SECONDS" =~ ^[1-9][0-9]*$ ]]; then - log error "❌ ALB_AUTOCREATE_TIMEOUT_SECONDS must be a positive integer, got: '$TIMEOUT_SECONDS'" - return 1 -fi - -# Final ALB name is "-<6 hex>", which must satisfy AWS -# ALB naming rules ([a-zA-Z0-9-], ≤32 chars) and the k8s metadata.name rules -# used by the dummy Ingress. 14 = length of "private-" + 6 hex chars. -if ! [[ "$NAME_PREFIX" =~ ^[a-z0-9-]+$ ]]; then - log error "❌ ALB_AUTOCREATE_NAME_PREFIX must match ^[a-z0-9-]+$, got: '$NAME_PREFIX'" - return 1 -fi -if [ "${#NAME_PREFIX}" -gt 18 ]; then - log error "❌ ALB_AUTOCREATE_NAME_PREFIX must be ≤18 chars (AWS caps ALB names at 32, the visibility+hex suffix uses 14); got ${#NAME_PREFIX}" - return 1 -fi - -SCOPE_ID=$(echo "$CONTEXT" | jq -r '.scope.id // "unknown"') - NEW_ALB_NAME=$(generate_alb_name "$NAME_PREFIX" "$INGRESS_VISIBILITY") log info "🔧 Autocreating ALB '$NEW_ALB_NAME' (visibility=$INGRESS_VISIBILITY)" -if ! apply_dummy_ingress "$NEW_ALB_NAME" "$INGRESS_VISIBILITY" "$K8S_NAMESPACE"; then - return 1 -fi +register_alb_in_provider "$NEW_ALB_NAME" "$INGRESS_VISIBILITY" -if ! wait_for_alb_active "$NEW_ALB_NAME" "$TIMEOUT_SECONDS" "$SCOPE_ID" "$INGRESS_VISIBILITY"; then - return 1 -fi +render_dummy_ingress "$NEW_ALB_NAME" "$INGRESS_VISIBILITY" "$K8S_NAMESPACE" -export AUTOCREATED_ALB_NAME="$NEW_ALB_NAME" +export ALB_NAME="$NEW_ALB_NAME" +export ALB_AUTOCREATED="true" diff --git a/k8s/scope/networking/resolve_balancer b/k8s/scope/networking/resolve_balancer index 2699f459..86278922 100755 --- a/k8s/scope/networking/resolve_balancer +++ b/k8s/scope/networking/resolve_balancer @@ -23,27 +23,48 @@ _RESOLVE_BALANCER_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -if ! type -t log >/dev/null 2>&1; then - source "$_RESOLVE_BALANCER_DIR/../../logging" -fi - -if ! type -t get_config_value >/dev/null 2>&1; then - source "$_RESOLVE_BALANCER_DIR/../../utils/get_config_value" -fi - # Queries AWS ELBv2 to count listener rules on an ALB's HTTPS (443) listener. # The default rule is excluded since it always exists. +# +# Special case for autocreate race: an ALB just registered in the provider by +# a concurrent scope creation may not yet be visible to AWS APIs while the +# Load Balancer Controller is still provisioning it. Treat +# LoadBalancerNotFound as "0 rules", so the in-flight ALB is selected as the +# least-loaded candidate and no second autocreate is triggered. +# # Usage: get_alb_rule_count # Returns: integer rule count on stdout, non-zero exit on failure get_alb_rule_count() { local alb_name="$1" - local alb_arn + local alb_arn aws_stderr aws_exit + aws_stderr=$(aws elbv2 describe-load-balancers \ + --names "$alb_name" \ + --region "$REGION" \ + --query 'LoadBalancers[0].LoadBalancerArn' \ + --output text 2>&1 >/dev/null) + aws_exit=$? + + if [ "$aws_exit" -ne 0 ]; then + case "$aws_stderr" in + *LoadBalancerNotFound*) + # Concurrent autocreate race: the ALB was just registered in the + # provider by another scope but is not yet visible to AWS APIs. Treat + # as 0 rules so the in-flight ALB wins selection and we don't trigger + # another autocreate. + log debug "📋 ALB '$alb_name' not yet visible in AWS (likely being provisioned); treating as 0 rules" >&2 + echo 0 + return 0 + ;; + esac + return 1 + fi + alb_arn=$(aws elbv2 describe-load-balancers \ --names "$alb_name" \ --region "$REGION" \ --query 'LoadBalancers[0].LoadBalancerArn' \ - --output text 2>/dev/null) || return 1 + --output text 2>/dev/null) if [ -z "$alb_arn" ] || [ "$alb_arn" = "None" ]; then return 1 @@ -124,32 +145,6 @@ get_alb_from_route53() { echo "$alb_name" } -# Lists ALB names tagged as autocreated for the given visibility. Used to keep -# previously-autocreated ALBs in the candidate pool without requiring them to -# be declared in the provider configuration. -# Returns space-separated names on stdout (may be empty), non-zero on AWS failure. -get_autocreated_albs() { - local visibility="$1" - - local arns - arns=$(aws resourcegroupstaggingapi get-resources \ - --region "$REGION" \ - --resource-type-filters "elasticloadbalancing:loadbalancer" \ - --tag-filters \ - "Key=nullplatform:managed-by,Values=autocreate" \ - "Key=nullplatform:visibility,Values=$visibility" \ - --query 'ResourceTagMappingList[].ResourceARN' \ - --output text 2>/dev/null) || return 1 - - if [ -z "$arns" ] || [ "$arns" = "None" ]; then - return 0 - fi - - # ALB ARN format: arn:aws:elasticloadbalancing:::loadbalancer/app// - # Skip non-application LBs (would have loadbalancer/net/... or loadbalancer/gwy/...). - echo "$arns" | tr '\t' '\n' | awk -F/ '$2 == "app" { print $3 }' -} - # ============================================================================= # Main logic # ============================================================================= @@ -200,26 +195,10 @@ if [[ "$DNS_TYPE" == "route53" ]]; then ) fi - # Discovered ALBs: autocreated by previous scope creations and tagged so we - # can include them in the pool without provider config changes. - AUTOCREATED_BALANCERS=$(get_autocreated_albs "$INGRESS_VISIBILITY" 2>/dev/null) || AUTOCREATED_BALANCERS="" - - HAS_ADDITIONAL=false if [ -n "$ADDITIONAL_BALANCERS" ] && [ "$ADDITIONAL_BALANCERS" != "null" ] && [ "$ADDITIONAL_BALANCERS" != "[]" ]; then - HAS_ADDITIONAL=true - fi + log debug "🔍 Additional balancers configured, resolving least-loaded ALB..." - if [ "$HAS_ADDITIONAL" = "true" ] || [ -n "$AUTOCREATED_BALANCERS" ]; then - log debug "🔍 Resolving least-loaded ALB across declared and autocreated candidates..." - - if [ "$HAS_ADDITIONAL" = "true" ]; then - DECLARED_LIST=$(echo "$ADDITIONAL_BALANCERS" | jq -r --arg base "$ALB_NAME" '[$base] + . | .[]') - else - DECLARED_LIST="$ALB_NAME" - fi - - # Merge declared + autocreated, deduplicate, drop blanks. - CANDIDATES=$(printf '%s\n%s\n' "$DECLARED_LIST" "$AUTOCREATED_BALANCERS" | tr ' ' '\n' | awk 'NF && !seen[$0]++') + CANDIDATES=$(echo "$ADDITIONAL_BALANCERS" | jq -r --arg base "$ALB_NAME" '[$base] + . | .[]') log debug "📋 Candidate balancers: $(echo "$CANDIDATES" | paste -sd ',' - | sed 's/,/, /g')" @@ -271,14 +250,8 @@ if [[ "$DNS_TYPE" == "route53" ]]; then if [ "$AUTOCREATE_ENABLED" = "true" ] && [ -n "$MAX_CAPACITY" ] && [ "$MIN_RULES" -ge 0 ] && [ "$MIN_RULES" -ge "$MAX_CAPACITY" ]; then log info "🔧 All candidate ALBs are at or above capacity ($MIN_RULES/$MAX_CAPACITY); triggering autocreate" - source "$_RESOLVE_BALANCER_DIR/autocreate_alb" || { - log error "❌ Autocreate failed; ALB '$ALB_NAME' will be used and validate_alb_capacity will reject the deployment" - return 1 - } - if [ -n "${AUTOCREATED_ALB_NAME:-}" ]; then - ALB_NAME="$AUTOCREATED_ALB_NAME" - log info "📝 Using autocreated ALB '$ALB_NAME'" - fi + # autocreate_alb exports ALB_NAME with the new name (or exits on failure) + source "$_RESOLVE_BALANCER_DIR/autocreate_alb" fi fi fi diff --git a/k8s/scope/networking/wait_for_alb b/k8s/scope/networking/wait_for_alb new file mode 100644 index 00000000..5af5c561 --- /dev/null +++ b/k8s/scope/networking/wait_for_alb @@ -0,0 +1,86 @@ +#!/bin/bash + +# Waits for the resolved ALB to reach `active` state in AWS. Runs as the post +# step of the apply_templates that lands the dummy Ingress (the trigger for +# the AWS Load Balancer Controller to provision the ALB). +# +# When ALB_AUTOCREATED is set, also tags the ALB so the cloud has a record of +# what is managed by the platform. The tag is documentation only — the +# authoritative registration is in the container-orchestration provider, done +# by autocreate_alb. +# +# Inputs (env vars): +# ALB_NAME - Resolved ALB name +# REGION - AWS region +# INGRESS_VISIBILITY - For the visibility tag value +# ALB_AUTOCREATED - "true" when this scope triggered autocreate +# ALB_AUTOCREATE_TIMEOUT_SECONDS - Max seconds to wait (default 300) +# CONTEXT - For scope-id in the tag value + +TIMEOUT_SECONDS=$(get_config_value \ + --env ALB_AUTOCREATE_TIMEOUT_SECONDS \ + --provider '.providers["container-orchestration"].balancer.autocreate_timeout_seconds' \ + --default "300" +) + +deadline=$(($(date +%s) + TIMEOUT_SECONDS)) +poll_interval=10 + +log info "⏳ Waiting up to ${TIMEOUT_SECONDS}s for ALB '$ALB_NAME' to become active..." + +state="" +alb_arn="" +while [ "$(date +%s)" -lt "$deadline" ]; do + lb_json=$(aws elbv2 describe-load-balancers \ + --names "$ALB_NAME" \ + --region "$REGION" \ + --output json 2>/dev/null) || lb_json="" + + alb_arn=$(echo "$lb_json" | jq -r '.LoadBalancers[0].LoadBalancerArn // empty' 2>/dev/null) || alb_arn="" + state=$(echo "$lb_json" | jq -r '.LoadBalancers[0].State.Code // empty' 2>/dev/null) || state="" + + if [ -n "$alb_arn" ]; then + log debug "📋 ALB '$ALB_NAME' state: ${state:-pending}" + + if [ "$state" = "active" ]; then + log info "✅ ALB '$ALB_NAME' is active" + break + fi + + if [ "$state" = "failed" ]; then + log error "❌ ALB '$ALB_NAME' reached state 'failed'" + exit 1 + fi + fi + + sleep "$poll_interval" +done + +if [ "$state" != "active" ]; then + log error "❌ Timed out after ${TIMEOUT_SECONDS}s waiting for ALB '$ALB_NAME' to become active" + log error "💡 Possible causes:" + log error " The AWS Load Balancer Controller may be slow, mis-configured, or the AWS account may be hitting an ALB quota" + log error "🔧 How to fix:" + log error " • Check controller logs: kubectl -n kube-system logs deploy/aws-load-balancer-controller" + log error " • Verify ALB quota: aws service-quotas get-service-quota --service-code elasticloadbalancing --quota-code L-53DA6B97" + exit 1 +fi + +# Audit tags — only on the scope that triggered the autocreate, so the cloud +# carries the lineage of which scope created which ALB. Discovery does not +# depend on these tags. +if [ "${ALB_AUTOCREATED:-false}" = "true" ]; then + scope_id=$(echo "$CONTEXT" | jq -r '.scope.id // "unknown"') + if ! aws elbv2 add-tags \ + --resource-arns "$alb_arn" \ + --region "$REGION" \ + --tags \ + "Key=nullplatform:managed-by,Value=autocreate" \ + "Key=nullplatform:visibility,Value=$INGRESS_VISIBILITY" \ + "Key=nullplatform:created-by-scope-id,Value=$scope_id" \ + >/dev/null 2>&1; then + log warn "⚠️ Could not tag ALB '$ALB_NAME' (audit only — provider registration already succeeded)" + else + log debug "📋 Tagged ALB '$ALB_NAME' with managed-by=autocreate" + fi +fi diff --git a/k8s/scope/templates/ingress-dummy.yaml.tpl b/k8s/scope/templates/ingress-dummy.yaml.tpl index 3d6bd3f8..2ded1e3c 100644 --- a/k8s/scope/templates/ingress-dummy.yaml.tpl +++ b/k8s/scope/templates/ingress-dummy.yaml.tpl @@ -8,21 +8,25 @@ metadata: nullplatform-autocreate: "true" alb_name: {{ .alb_name }} annotations: + alb.ingress.kubernetes.io/actions.response-404: >- + {"type":"fixed-response","fixedResponseConfig":{"contentType":"text/plain","statusCode":"404","messageBody":"404 + scope not found or has not been deployed yet"}} alb.ingress.kubernetes.io/group.name: {{ .alb_name }} alb.ingress.kubernetes.io/listen-ports: '[{"HTTP":80},{"HTTPS":443}]' alb.ingress.kubernetes.io/load-balancer-name: {{ .alb_name }} alb.ingress.kubernetes.io/scheme: {{ .ingress_visibility }} + alb.ingress.kubernetes.io/ssl-redirect: '443' alb.ingress.kubernetes.io/target-type: ip - alb.ingress.kubernetes.io/tags: nullplatform:managed-by=autocreate,nullplatform:visibility={{ .ingress_visibility }},nullplatform:created-by-scope-id={{ .scope.id }} spec: ingressClassName: alb rules: - - http: + - host: {{ .alb_name }}.{{ .base_domain }} + http: paths: - - path: /__nullplatform_autocreate_placeholder + - path: / pathType: Prefix backend: service: - name: nullplatform-autocreate-placeholder + name: response-404 port: - number: 80 + name: use-annotation diff --git a/k8s/scope/tests/networking/autocreate_alb.bats b/k8s/scope/tests/networking/autocreate_alb.bats index c5c47aa2..8ad6c257 100644 --- a/k8s/scope/tests/networking/autocreate_alb.bats +++ b/k8s/scope/tests/networking/autocreate_alb.bats @@ -17,10 +17,14 @@ setup() { export INGRESS_VISIBILITY="internet-facing" export K8S_NAMESPACE="test-ns" export SERVICE_PATH="$PROJECT_ROOT/k8s" - export ALB_AUTOCREATE_TIMEOUT_SECONDS="2" + export OUTPUT_DIR="$(mktemp -d)" export CONTEXT='{ - "scope": { "id": "scope-1", "slug": "scope-1" }, + "scope": { + "id": "scope-1", + "slug": "scope-1", + "nrn": "organization=1:account=2:namespace=3:application=4:scope=5" + }, "namespace": { "id": "ns-1", "slug": "ns-1" }, "application": { "id": "app-1", "slug": "app-1" }, "account": { "id": "acc-1", "slug": "acc-1" }, @@ -30,254 +34,222 @@ setup() { } }' - # Mocks: each test overrides as needed. - gomplate() { return 0; } - export -f gomplate - kubectl() { return 0; } - export -f kubectl - aws() { return 1; } - export -f aws - - # Tracks calls for assertions. export CALL_LOG_FILE="$(mktemp)" -} -teardown() { - unset -f log gomplate kubectl aws get_config_value - rm -f "$CALL_LOG_FILE" - unset AUTOCREATED_ALB_NAME + # Default mocks — each test overrides as needed. + gomplate() { + local prev="" + for arg in "$@"; do + if [ "$prev" = "--out" ]; then echo "rendered" > "$arg"; fi + prev="$arg" + done + return 0 + } + export -f gomplate + np() { + echo "np $*" >> "$CALL_LOG_FILE" + if [ "$1" = "provider" ] && [ "$2" = "list" ]; then + echo '{"results":[{"id":"prov-1","attributes":{"balancer":{}}}]}' + return 0 + fi + if [ "$1" = "provider" ] && [ "$2" = "patch" ]; then + local prev="" + for arg in "$@"; do + if [ "$prev" = "--body" ]; then echo "$arg" > "$OUTPUT_DIR/_patch_body"; fi + prev="$arg" + done + return 0 + fi + return 1 + } + export -f np } -# Records each invocation of a mocked binary into CALL_LOG_FILE so tests can -# assert against the sequence of calls. -record_call() { - echo "$@" >> "$CALL_LOG_FILE" +teardown() { + unset -f log gomplate np get_config_value + rm -rf "$OUTPUT_DIR" "$CALL_LOG_FILE" + unset ALB_NAME ALB_AUTOCREATED } # ============================================================================= # Name generation # ============================================================================= -@test "autocreate_alb: generates ALB name with prefix and visibility short form" { - # Mock AWS so describe-load-balancers reports active immediately. - aws() { - case "$*" in - *describe-load-balancers*) echo '{"LoadBalancers":[{"LoadBalancerArn":"arn:aws:elasticloadbalancing:us-east-1:123:loadbalancer/app/nullplatform-auto-public-abc123/x","State":{"Code":"active"}}]}'; return 0 ;; - *add-tags*) return 0 ;; - *) return 1 ;; - esac - } - export -f aws - +@test "autocreate_alb: generates name with default prefix and public short form" { source "$SCRIPT" - # Length and prefix - [[ "$AUTOCREATED_ALB_NAME" =~ ^nullplatform-auto-public-[a-f0-9]{6}$ ]] + [[ "$ALB_NAME" =~ ^nullplatform-auto-public-[a-f0-9]{6}$ ]] } -@test "autocreate_alb: uses private short form for internal visibility" { +@test "autocreate_alb: generates name with private short form for internal visibility" { export INGRESS_VISIBILITY="internal" - aws() { - case "$*" in - *describe-load-balancers*) echo '{"LoadBalancers":[{"LoadBalancerArn":"arn:aws:elasticloadbalancing:us-east-1:123:loadbalancer/app/x/y","State":{"Code":"active"}}]}'; return 0 ;; - *add-tags*) return 0 ;; - *) return 1 ;; - esac - } - export -f aws source "$SCRIPT" - [[ "$AUTOCREATED_ALB_NAME" =~ ^nullplatform-auto-private-[a-f0-9]{6}$ ]] + [[ "$ALB_NAME" =~ ^nullplatform-auto-private-[a-f0-9]{6}$ ]] } -@test "autocreate_alb: respects custom name prefix from env" { - export ALB_AUTOCREATE_NAME_PREFIX="custom-prefix-" - aws() { - case "$*" in - *describe-load-balancers*) echo '{"LoadBalancers":[{"LoadBalancerArn":"arn:aws:elasticloadbalancing:us-east-1:123:loadbalancer/app/x/y","State":{"Code":"active"}}]}'; return 0 ;; - *add-tags*) return 0 ;; - *) return 1 ;; - esac - } - export -f aws +@test "autocreate_alb: respects custom name prefix" { + export ALB_AUTOCREATE_NAME_PREFIX="custom-" source "$SCRIPT" - [[ "$AUTOCREATED_ALB_NAME" =~ ^custom-prefix-public- ]] + [[ "$ALB_NAME" =~ ^custom-public-[a-f0-9]{6}$ ]] } -# ============================================================================= -# Ingress dummy application -# ============================================================================= -@test "autocreate_alb: renders and applies the dummy ingress before polling" { - gomplate() { record_call "gomplate $*"; return 0; } - export -f gomplate - kubectl() { record_call "kubectl $*"; return 0; } - export -f kubectl - aws() { - case "$*" in - *describe-load-balancers*) echo '{"LoadBalancers":[{"LoadBalancerArn":"arn:aws:elasticloadbalancing:us-east-1:123:loadbalancer/app/x/y","State":{"Code":"active"}}]}'; return 0 ;; - *add-tags*) return 0 ;; - *) return 1 ;; - esac - } - export -f aws - +@test "autocreate_alb: exports ALB_AUTOCREATED=true" { source "$SCRIPT" - # Both gomplate and kubectl must have been invoked. - grep -q "gomplate" "$CALL_LOG_FILE" - grep -q "kubectl apply" "$CALL_LOG_FILE" + [ "$ALB_AUTOCREATED" = "true" ] } -@test "autocreate_alb: fails if gomplate render fails" { - gomplate() { return 1; } - export -f gomplate +# ============================================================================= +# Provider patching +# ============================================================================= +@test "autocreate_alb: calls np provider list with the scope NRN" { + source "$SCRIPT" - run bash -c 'source "$SCRIPT"' + grep -q "provider list" "$CALL_LOG_FILE" + grep -q -- "--nrn organization=1:account=2:namespace=3:application=4:scope=5" "$CALL_LOG_FILE" +} + +@test "autocreate_alb: patches additional_public_names for internet-facing visibility" { + np() { + echo "np $*" >> "$CALL_LOG_FILE" + if [ "$1" = "provider" ] && [ "$2" = "list" ]; then + echo '{"results":[{"id":"prov-1","attributes":{"balancer":{"additional_public_names":["existing-1"]}}}]}' + return 0 + fi + if [ "$1" = "provider" ] && [ "$2" = "patch" ]; then + local prev="" + for arg in "$@"; do + if [ "$prev" = "--body" ]; then echo "$arg" > "$OUTPUT_DIR/_patch_body"; fi + prev="$arg" + done + return 0 + fi + return 1 + } + export -f np - [ "$status" -ne 0 ] - assert_contains "$output" "Failed to render ingress-dummy template" -} + source "$SCRIPT" -@test "autocreate_alb: fails if kubectl apply fails" { - kubectl() { return 1; } - export -f kubectl + local body + body=$(cat "$OUTPUT_DIR/_patch_body") + echo "$body" | jq -e '.attributes.balancer.additional_public_names | length == 2' + echo "$body" | jq -e '.attributes.balancer.additional_public_names[0] == "existing-1"' + echo "$body" | jq -e ".attributes.balancer.additional_public_names[1] == \"$ALB_NAME\"" +} - run bash -c 'source "$SCRIPT"' +@test "autocreate_alb: patches additional_private_names for internal visibility" { + export INGRESS_VISIBILITY="internal" - [ "$status" -ne 0 ] - assert_contains "$output" "Failed to apply ingress-dummy" -} + source "$SCRIPT" -# ============================================================================= -# Polling for active state -# ============================================================================= -@test "autocreate_alb: returns success when ALB becomes active within timeout" { - # describe-load-balancers returns active state immediately. - aws() { - case "$*" in - *describe-load-balancers*) echo '{"LoadBalancers":[{"LoadBalancerArn":"arn:aws:elasticloadbalancing:us-east-1:123:loadbalancer/app/x/y","State":{"Code":"active"}}]}'; return 0 ;; - *add-tags*) return 0 ;; - *) return 1 ;; - esac + cat "$OUTPUT_DIR/_patch_body" | jq -e '.attributes.balancer.additional_private_names | length == 1' +} + +@test "autocreate_alb: deduplicates when name already in list (defense in depth)" { + np() { + echo "np $*" >> "$CALL_LOG_FILE" + if [ "$1" = "provider" ] && [ "$2" = "list" ]; then + # Inject a duplicate scenario: pretend existing list already contains the same name + # (impossible in practice given random suffix, but the jq pipeline must still be safe) + echo '{"results":[{"id":"prov-1","attributes":{"balancer":{"additional_public_names":["a","b"]}}}]}' + return 0 + fi + if [ "$1" = "provider" ] && [ "$2" = "patch" ]; then + local prev="" + for arg in "$@"; do + if [ "$prev" = "--body" ]; then echo "$arg" > "$OUTPUT_DIR/_patch_body"; fi + prev="$arg" + done + return 0 + fi + return 1 } - export -f aws + export -f np source "$SCRIPT" - [ -n "$AUTOCREATED_ALB_NAME" ] + cat "$OUTPUT_DIR/_patch_body" | jq -e '.attributes.balancer.additional_public_names | length == 3' } -@test "autocreate_alb: exits non-zero when ALB never reaches active state (timeout)" { - export ALB_AUTOCREATE_TIMEOUT_SECONDS="1" - # Always return provisioning state, never 'active'. - aws() { - case "$*" in - *describe-load-balancers*) echo '{"LoadBalancers":[{"LoadBalancerArn":"arn:aws:elasticloadbalancing:us-east-1:123:loadbalancer/app/x/y","State":{"Code":"provisioning"}}]}'; return 0 ;; - *) return 1 ;; - esac +@test "autocreate_alb: exits when provider list returns no results" { + np() { + if [ "$1" = "provider" ] && [ "$2" = "list" ]; then echo '{"results":[]}'; return 0; fi + return 1 } - export -f aws + export -f np run bash -c 'source "$SCRIPT"' [ "$status" -ne 0 ] - assert_contains "$output" "Timed out" + assert_contains "$output" "No container-orchestration provider found" } -@test "autocreate_alb: exits non-zero when ALB reaches 'failed' state" { - aws() { - case "$*" in - *describe-load-balancers*) echo '{"LoadBalancers":[{"LoadBalancerArn":"arn:aws:elasticloadbalancing:us-east-1:123:loadbalancer/app/x/y","State":{"Code":"failed"}}]}'; return 0 ;; - *) return 1 ;; - esac +@test "autocreate_alb: exits when np provider list fails" { + np() { + if [ "$1" = "provider" ] && [ "$2" = "list" ]; then return 2; fi + return 1 } - export -f aws + export -f np run bash -c 'source "$SCRIPT"' [ "$status" -ne 0 ] - assert_contains "$output" "reached state 'failed'" -} - -# ============================================================================= -# Tagging -# ============================================================================= -@test "autocreate_alb: tags the ALB with managed-by, visibility and scope-id" { - aws() { - case "$*" in - *describe-load-balancers*) echo '{"LoadBalancers":[{"LoadBalancerArn":"arn:aws:elasticloadbalancing:us-east-1:123:loadbalancer/app/x/y","State":{"Code":"active"}}]}'; return 0 ;; - *add-tags*) - record_call "aws $*" - return 0 - ;; - *) return 1 ;; - esac - } - export -f aws - - source "$SCRIPT" - - grep -q "nullplatform:managed-by,Value=autocreate" "$CALL_LOG_FILE" - grep -q "nullplatform:visibility,Value=internet-facing" "$CALL_LOG_FILE" - grep -q "nullplatform:created-by-scope-id,Value=scope-1" "$CALL_LOG_FILE" + assert_contains "$output" "Failed to list container-orchestration provider" } -@test "autocreate_alb: tagging failure does not fail the script (warn only)" { - aws() { - case "$*" in - *describe-load-balancers*) echo '{"LoadBalancers":[{"LoadBalancerArn":"arn:aws:elasticloadbalancing:us-east-1:123:loadbalancer/app/x/y","State":{"Code":"active"}}]}'; return 0 ;; - *add-tags*) return 1 ;; - *) return 1 ;; - esac +@test "autocreate_alb: exits when np provider patch fails" { + np() { + if [ "$1" = "provider" ] && [ "$2" = "list" ]; then + echo '{"results":[{"id":"prov-1","attributes":{"balancer":{}}}]}' + return 0 + fi + if [ "$1" = "provider" ] && [ "$2" = "patch" ]; then return 5; fi + return 1 } - export -f aws + export -f np - source "$SCRIPT" + run bash -c 'source "$SCRIPT"' - # Script still exports the new ALB name even though tagging warned. - [ -n "$AUTOCREATED_ALB_NAME" ] + [ "$status" -ne 0 ] + assert_contains "$output" "Failed to patch container-orchestration provider" } -# ============================================================================= -# Timeout validation -# ============================================================================= -@test "autocreate_alb: rejects non-numeric timeout" { - export ALB_AUTOCREATE_TIMEOUT_SECONDS="abc" +@test "autocreate_alb: exits when CONTEXT has no scope.nrn" { + export CONTEXT=$(echo "$CONTEXT" | jq 'del(.scope.nrn)') run bash -c 'source "$SCRIPT"' [ "$status" -ne 0 ] - assert_contains "$output" "must be a positive integer" + assert_contains "$output" "Could not read scope NRN" } # ============================================================================= -# Name prefix validation +# Dummy ingress rendering # ============================================================================= -@test "autocreate_alb: rejects prefix containing uppercase" { - export ALB_AUTOCREATE_NAME_PREFIX="Bad-Prefix-" - - run bash -c 'source "$SCRIPT"' +@test "autocreate_alb: renders the dummy ingress yaml to OUTPUT_DIR" { + source "$SCRIPT" - [ "$status" -ne 0 ] - assert_contains "$output" "must match" + [ -f "$OUTPUT_DIR/ingress-dummy-${ALB_NAME}.yaml" ] } -@test "autocreate_alb: rejects prefix containing colon (YAML injection vector)" { - export ALB_AUTOCREATE_NAME_PREFIX="bad:prefix" +@test "autocreate_alb: exits when gomplate fails" { + gomplate() { return 1; } + export -f gomplate run bash -c 'source "$SCRIPT"' [ "$status" -ne 0 ] - assert_contains "$output" "must match" + assert_contains "$output" "Failed to render ingress-dummy template" } -@test "autocreate_alb: rejects prefix longer than 18 chars" { - export ALB_AUTOCREATE_NAME_PREFIX="this-prefix-is-way-too-long-" +@test "autocreate_alb: exits when OUTPUT_DIR is not set" { + unset OUTPUT_DIR run bash -c 'source "$SCRIPT"' [ "$status" -ne 0 ] - assert_contains "$output" "18 chars" + assert_contains "$output" "OUTPUT_DIR is not set" } diff --git a/k8s/scope/tests/networking/resolve_balancer.bats b/k8s/scope/tests/networking/resolve_balancer.bats index c37888c1..19b29a2f 100644 --- a/k8s/scope/tests/networking/resolve_balancer.bats +++ b/k8s/scope/tests/networking/resolve_balancer.bats @@ -9,6 +9,7 @@ setup() { log() { if [ "$1" = "error" ]; then echo "$2" >&2; else echo "$2"; fi; } export -f log source "$PROJECT_ROOT/k8s/utils/get_config_value" + export -f get_config_value export SCRIPT="$PROJECT_ROOT/k8s/scope/networking/resolve_balancer" export REGION="us-east-1" @@ -372,7 +373,7 @@ mock_alb_rules() { run bash -c 'export LOG_LEVEL=debug; source "$SCRIPT"' - assert_contains "$output" "🔍 Resolving least-loaded ALB across declared and autocreated candidates..." + assert_contains "$output" "🔍 Additional balancers configured, resolving least-loaded ALB..." assert_contains "$output" "📋 Candidate balancers: co-balancer-public, alb-extra-1, alb-extra-2" } @@ -503,56 +504,38 @@ mock_alb_rules() { } # ============================================================================= -# Discovery of autocreated ALBs via tags +# LoadBalancerNotFound treated as 0 rules (concurrent autocreate race case) # ============================================================================= - -# Extends mock_alb_rules to also serve a resourcegroupstaggingapi response -# listing autocreated ALBs as candidates. Pass "alb_name count" pairs as -# positional args; set DISCOVERED_AUTOCREATED (space-separated names) before -# calling to control which ALBs the tag-discovery API returns. -mock_alb_rules_with_discovery() { - mock_alb_rules "$@" - - local discovered_arns="" - for name in $DISCOVERED_AUTOCREATED; do - discovered_arns="${discovered_arns}arn:aws:elasticloadbalancing:us-east-1:123:loadbalancer/app/${name}/abc"$'\t' - done - discovered_arns="${discovered_arns%$'\t'}" - - eval "aws() { - case \"\$*\" in - *resourcegroupstaggingapi*get-resources*) - echo '${discovered_arns}' - return 0 - ;; - *list-resource-record-sets*) echo 'None' ;; - *describe-load-balancers*--names* | *describe-listeners* | *describe-rules*) - _mock_aws_elbv2_rule_count \"\$@\" - ;; - *) return 1 ;; - esac - } - export -f aws" -} - -@test "resolve_balancer: discovers autocreated ALBs from tags and includes them as candidates" { +@test "resolve_balancer: treats LoadBalancerNotFound as 0 rules so in-flight ALB wins" { export INGRESS_VISIBILITY="internet-facing" - export DISCOVERED_AUTOCREATED="nullplatform-auto-public-aaaaaa" - mock_alb_rules_with_discovery "co-balancer-public 50" "nullplatform-auto-public-aaaaaa 5" - - source "$SCRIPT" - - assert_equal "$ALB_NAME" "nullplatform-auto-public-aaaaaa" -} + export CONTEXT=$(echo "$CONTEXT" | jq ' + .providers["scope-configurations"].networking.additional_public_balancers = ["in-flight-alb"] + ') -@test "resolve_balancer: skips non-application LBs in discovery output" { - export INGRESS_VISIBILITY="internet-facing" - # Inject a network LB ARN that should be filtered out by the awk in get_autocreated_albs aws() { case "$*" in *list-resource-record-sets*) echo "None"; return 0 ;; - *resourcegroupstaggingapi*get-resources*) - printf 'arn:aws:elasticloadbalancing:us-east-1:123:loadbalancer/net/some-nlb/abc\n' + *describe-load-balancers*--names*in-flight-alb*) + echo "An error occurred (LoadBalancerNotFound) when calling the DescribeLoadBalancers operation" >&2 + return 254 + ;; + *describe-load-balancers*--names*) + echo "arn:aws:elasticloadbalancing:us-east-1:123:loadbalancer/app/co-balancer-public/abc" + return 0 + ;; + *describe-listeners*) + echo "arn:aws:elasticloadbalancing:us-east-1:123:listener/app/co-balancer-public/abc/def" + return 0 + ;; + *describe-rules*) + local rules='{"Rules": [{"IsDefault": true}' + local i=0 + while [ $i -lt 50 ]; do + rules="${rules}, {\"IsDefault\": false}" + i=$((i + 1)) + done + rules="${rules}]}" + echo "$rules" return 0 ;; *) return 1 ;; @@ -562,83 +545,38 @@ mock_alb_rules_with_discovery() { source "$SCRIPT" - # No additional candidates → falls back to default - assert_equal "$ALB_NAME" "co-balancer-public" + assert_equal "$ALB_NAME" "in-flight-alb" } # ============================================================================= -# Autocreate fallback when all candidates are over capacity +# Autocreate trigger # ============================================================================= -@test "resolve_balancer: triggers autocreate when all candidates over threshold and feature enabled" { +@test "resolve_balancer: sources autocreate_alb when all candidates over threshold and feature enabled" { export INGRESS_VISIBILITY="internet-facing" export ALB_AUTOCREATE_ENABLED="true" export ALB_MAX_CAPACITY="50" - export ALB_AUTOCREATE_TIMEOUT_SECONDS="2" - export ALB_AUTOCREATE_NAME_PREFIX="auto-" - export K8S_NAMESPACE="test-ns" - export SERVICE_PATH="$PROJECT_ROOT/k8s" export CONTEXT=$(echo "$CONTEXT" | jq ' - .providers["scope-configurations"].networking.additional_public_balancers = ["alb-extra-1"] | - .scope.slug = "s" | - .scope.id = "scope-1" | - .namespace.slug = "ns" | - .namespace.id = "ns-1" | - .application.slug = "app" | - .application.id = "app-1" | - .account.slug = "acc" | - .account.id = "acc-1" | - .deployment.id = "dep-1" + .providers["scope-configurations"].networking.additional_public_balancers = ["alb-extra-1"] ') + mock_alb_rules "co-balancer-public 60" "alb-extra-1 55" - # Both declared ALBs are above threshold; aws describe for autocreate - # returns "active" immediately so the new ALB name is exported. - aws() { - case "$*" in - *list-resource-record-sets*) echo "None"; return 0 ;; - *resourcegroupstaggingapi*get-resources*) echo ""; return 0 ;; - *describe-load-balancers*--names*) - local name='' - local prev='' - for arg in "$@"; do - if [ "$prev" = "--names" ]; then name="$arg"; fi - prev="$arg" - done - # Return JSON when called with --output json (autocreate polling), - # or a plain ARN when called with --output text (rule count lookup). - case "$*" in - *--output*json*) echo "{\"LoadBalancers\":[{\"LoadBalancerArn\":\"arn:aws:elasticloadbalancing:us-east-1:123:loadbalancer/app/${name}/abc\",\"State\":{\"Code\":\"active\"}}]}"; return 0 ;; - *) echo "arn:aws:elasticloadbalancing:us-east-1:123:loadbalancer/app/${name}/abc"; return 0 ;; - esac - ;; - *describe-listeners*) - local lb_arn='' - local prev='' - for arg in "$@"; do - if [ "$prev" = "--load-balancer-arn" ]; then lb_arn="$arg"; fi - prev="$arg" - done - local alb_name=$(echo "$lb_arn" | sed 's|.*/app/||;s|/.*||') - echo "arn:aws:elasticloadbalancing:us-east-1:123:listener/app/${alb_name}/abc/def" - return 0 - ;; - *describe-rules*) - # Both candidates report 60 rules (above threshold of 50) - echo '{"Rules":[{"IsDefault":true},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false},{"IsDefault":false}]}' - return 0 - ;; - *add-tags*) return 0 ;; - *) return 1 ;; - esac - } - export -f aws - gomplate() { return 0; } - export -f gomplate - kubectl() { return 0; } - export -f kubectl - - source "$SCRIPT" - - [[ "$ALB_NAME" =~ ^auto-public-[a-f0-9]{6}$ ]] + # Stub autocreate_alb: simulate it exporting the new ALB name. + cat > "$BATS_TEST_TMPDIR/autocreate_alb_stub" <<'STUB' +export ALB_NAME="auto-public-stubbed" +export ALB_AUTOCREATED="true" +STUB + export INGRESS_DUMMY_TEMPLATE="$BATS_TEST_TMPDIR/ignored.tpl" + # Replace the real autocreate_alb with the stub by intercepting the source path + AUTOCREATE_STUB="$BATS_TEST_TMPDIR/autocreate_alb_stub" + # The script does: source "$_RESOLVE_BALANCER_DIR/autocreate_alb" + # Override via shadow path: copy resolve_balancer to tmp with patched source line. + PATCHED_SCRIPT="$BATS_TEST_TMPDIR/resolve_balancer_patched" + sed "s|\\\$_RESOLVE_BALANCER_DIR/autocreate_alb|$AUTOCREATE_STUB|" "$SCRIPT" > "$PATCHED_SCRIPT" + + source "$PATCHED_SCRIPT" + + assert_equal "$ALB_NAME" "auto-public-stubbed" + [ "$ALB_AUTOCREATED" = "true" ] } @test "resolve_balancer: does not autocreate when feature disabled even if all candidates full" { diff --git a/k8s/scope/tests/networking/wait_for_alb.bats b/k8s/scope/tests/networking/wait_for_alb.bats new file mode 100644 index 00000000..9b6587dc --- /dev/null +++ b/k8s/scope/tests/networking/wait_for_alb.bats @@ -0,0 +1,140 @@ +#!/usr/bin/env bats +# ============================================================================= +# Unit tests for networking/wait_for_alb +# ============================================================================= + +setup() { + export PROJECT_ROOT="$(cd "$BATS_TEST_DIRNAME/../../../.." && pwd)" + source "$PROJECT_ROOT/testing/assertions.sh" + + log() { if [ "$1" = "error" ]; then echo "$2" >&2; else echo "$2"; fi; } + export -f log + + source "$PROJECT_ROOT/k8s/utils/get_config_value" + export -f get_config_value + + export SCRIPT="$PROJECT_ROOT/k8s/scope/networking/wait_for_alb" + export REGION="us-east-1" + export ALB_NAME="test-alb" + export INGRESS_VISIBILITY="internet-facing" + export ALB_AUTOCREATE_TIMEOUT_SECONDS="2" + + export CONTEXT='{ + "scope": { "id": "scope-1" }, + "providers": { "container-orchestration": {} } + }' + + export CALL_LOG_FILE="$(mktemp)" + + aws() { return 1; } + export -f aws +} + +teardown() { + unset -f log aws get_config_value + rm -f "$CALL_LOG_FILE" + unset ALB_AUTOCREATED +} + +# Mocks describe-load-balancers + add-tags. The state arg controls what the +# describe response reports. +mock_aws_state() { + local state="$1" + local arn="arn:aws:elasticloadbalancing:us-east-1:123:loadbalancer/app/$ALB_NAME/abc" + eval "aws() { + echo \"aws \$*\" >> '$CALL_LOG_FILE' + case \"\$*\" in + *describe-load-balancers*) + echo '{\"LoadBalancers\":[{\"LoadBalancerArn\":\"${arn}\",\"State\":{\"Code\":\"${state}\"}}]}' + return 0 + ;; + *add-tags*) + return 0 + ;; + esac + return 1 + } + export -f aws" +} + +# ============================================================================= +# Active state +# ============================================================================= +@test "wait_for_alb: returns success when ALB is already active" { + mock_aws_state "active" + + run bash -c 'source "$SCRIPT"' + + [ "$status" -eq 0 ] + assert_contains "$output" "is active" +} + +# ============================================================================= +# Failed state +# ============================================================================= +@test "wait_for_alb: exits when ALB reaches state=failed" { + mock_aws_state "failed" + + run bash -c 'source "$SCRIPT"' + + [ "$status" -ne 0 ] + assert_contains "$output" "reached state 'failed'" +} + +# ============================================================================= +# Timeout +# ============================================================================= +@test "wait_for_alb: exits when ALB never reaches active within timeout" { + export ALB_AUTOCREATE_TIMEOUT_SECONDS="1" + mock_aws_state "provisioning" + + run bash -c 'source "$SCRIPT"' + + [ "$status" -ne 0 ] + assert_contains "$output" "Timed out" +} + +# ============================================================================= +# Tagging on autocreate +# ============================================================================= +@test "wait_for_alb: tags the ALB when ALB_AUTOCREATED=true" { + export ALB_AUTOCREATED="true" + mock_aws_state "active" + + source "$SCRIPT" + + grep -q "add-tags" "$CALL_LOG_FILE" + grep -q "nullplatform:managed-by,Value=autocreate" "$CALL_LOG_FILE" + grep -q "nullplatform:visibility,Value=internet-facing" "$CALL_LOG_FILE" + grep -q "nullplatform:created-by-scope-id,Value=scope-1" "$CALL_LOG_FILE" +} + +@test "wait_for_alb: does not tag when ALB_AUTOCREATED is unset" { + mock_aws_state "active" + + source "$SCRIPT" + + ! grep -q "add-tags" "$CALL_LOG_FILE" +} + +@test "wait_for_alb: tagging failure warns but does not fail the script" { + export ALB_AUTOCREATED="true" + local arn="arn:aws:elasticloadbalancing:us-east-1:123:loadbalancer/app/$ALB_NAME/abc" + eval "aws() { + echo \"aws \$*\" >> '$CALL_LOG_FILE' + case \"\$*\" in + *describe-load-balancers*) + echo '{\"LoadBalancers\":[{\"LoadBalancerArn\":\"${arn}\",\"State\":{\"Code\":\"active\"}}]}' + return 0 + ;; + *add-tags*) return 1 ;; + esac + return 1 + } + export -f aws" + + run bash -c 'source "$SCRIPT"' + + [ "$status" -eq 0 ] + assert_contains "$output" "audit only" +} diff --git a/k8s/scope/workflows/create.yaml b/k8s/scope/workflows/create.yaml index 9c0f3006..8ea24684 100644 --- a/k8s/scope/workflows/create.yaml +++ b/k8s/scope/workflows/create.yaml @@ -22,6 +22,20 @@ steps: type: environment - name: OUTPUT_DIR type: environment + - name: ALB_NAME + type: environment + - name: ALB_AUTOCREATED + type: environment + - name: apply autocreated ingress + type: script + file: "$SERVICE_PATH/apply_templates" + configuration: + ACTION: apply + DRY_RUN: false + post: + name: wait for alb + type: script + file: "$SERVICE_PATH/scope/networking/wait_for_alb" - name: validate alb capacity type: script file: "$SERVICE_PATH/scope/validate_alb_capacity" From b0b1cc1b660345de67624de10373a5f36ac49348 Mon Sep 17 00:00:00 2001 From: Federico Maleh Date: Mon, 8 Jun 2026 15:03:11 -0300 Subject: [PATCH 004/158] docs: clarify get_alb_rule_count stdout contract in race-case branch --- k8s/scope/networking/resolve_balancer | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/k8s/scope/networking/resolve_balancer b/k8s/scope/networking/resolve_balancer index 86278922..95b0cae6 100755 --- a/k8s/scope/networking/resolve_balancer +++ b/k8s/scope/networking/resolve_balancer @@ -49,9 +49,10 @@ get_alb_rule_count() { case "$aws_stderr" in *LoadBalancerNotFound*) # Concurrent autocreate race: the ALB was just registered in the - # provider by another scope but is not yet visible to AWS APIs. Treat - # as 0 rules so the in-flight ALB wins selection and we don't trigger - # another autocreate. + # provider by another scope but is not yet visible to AWS APIs. Return + # 0 rules on stdout (same contract as the success path below) so the + # in-flight ALB wins least-loaded selection and we don't trigger a + # second autocreate. log debug "📋 ALB '$alb_name' not yet visible in AWS (likely being provisioned); treating as 0 rules" >&2 echo 0 return 0 From f5026d2d1549b3614fcd3c43781e0bfd57af40b6 Mon Sep 17 00:00:00 2001 From: Federico Maleh Date: Tue, 9 Jun 2026 16:18:07 -0300 Subject: [PATCH 005/158] refactor: reuse $DOMAIN from build_context instead of recomputing --- k8s/scope/build_context | 4 +++- k8s/scope/networking/autocreate_alb | 12 +++--------- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/k8s/scope/build_context b/k8s/scope/build_context index 548ca319..0650f897 100755 --- a/k8s/scope/build_context +++ b/k8s/scope/build_context @@ -231,10 +231,12 @@ CONTEXT=$(echo "$CONTEXT" | jq \ --arg gateway_name "$GATEWAY_NAME" \ --arg alb_name "$ALB_NAME" \ --arg component "$COMPONENT" \ + --arg base_domain "$DOMAIN" \ --argjson modifiers "$K8S_MODIFIERS" \ - '. + {ingress_visibility: $ingress_visibility, k8s_namespace: $k8s_namespace, gateway_name: $gateway_name, region: $region, k8s_modifiers: $modifiers, alb_name: $alb_name, component: $component}') + '. + {ingress_visibility: $ingress_visibility, k8s_namespace: $k8s_namespace, gateway_name: $gateway_name, region: $region, k8s_modifiers: $modifiers, alb_name: $alb_name, component: $component, base_domain: $base_domain}') export CONTEXT export REGION +export DOMAIN log info "✅ Scope context built successfully" diff --git a/k8s/scope/networking/autocreate_alb b/k8s/scope/networking/autocreate_alb index aea35f6d..0a24e88d 100644 --- a/k8s/scope/networking/autocreate_alb +++ b/k8s/scope/networking/autocreate_alb @@ -117,19 +117,13 @@ render_dummy_ingress() { tmp_context=$(mktemp) trap 'rm -f "$tmp_context"' RETURN - local base_domain - base_domain=$(get_config_value \ - --env DOMAIN \ - --provider '.providers["scope-configurations"].networking.base_domain' \ - --provider '.providers["container-orchestration"].networking.base_domain' \ - --default "nullapps.io" - ) - + # build_context already exports $DOMAIN (and adds it to CONTEXT as + # `base_domain` after we return). Inject the call-specific fields here. echo "$CONTEXT" | jq \ --arg alb_name "$alb_name" \ --arg ingress_visibility "$visibility" \ --arg k8s_namespace "$namespace" \ - --arg base_domain "$base_domain" \ + --arg base_domain "$DOMAIN" \ '. + {alb_name: $alb_name, ingress_visibility: $ingress_visibility, k8s_namespace: $k8s_namespace, base_domain: $base_domain}' \ > "$tmp_context" From 940276f3e0c0dfd2bb3de87057ab68ff3d7ca556 Mon Sep 17 00:00:00 2001 From: Federico Maleh Date: Wed, 10 Jun 2026 10:13:33 -0300 Subject: [PATCH 006/158] test: assert full log messages with emojis for autocreate networking tests --- k8s/scope/networking/resolve_balancer | 5 +- .../tests/networking/autocreate_alb.bats | 140 +++++++++--------- .../tests/networking/resolve_balancer.bats | 61 +++++--- k8s/scope/tests/networking/wait_for_alb.bats | 84 +++++++---- 4 files changed, 166 insertions(+), 124 deletions(-) diff --git a/k8s/scope/networking/resolve_balancer b/k8s/scope/networking/resolve_balancer index 95b0cae6..d5214ecb 100755 --- a/k8s/scope/networking/resolve_balancer +++ b/k8s/scope/networking/resolve_balancer @@ -207,7 +207,10 @@ if [[ "$DNS_TYPE" == "route53" ]]; then BEST_ALB="$ALB_NAME" for CANDIDATE in $CANDIDATES; do - RULE_COUNT=$(get_alb_rule_count "$CANDIDATE" 2>/dev/null) || { + # No outer stderr redirect: get_alb_rule_count locally suppresses raw + # aws CLI stderr and emits only intentional `log` messages there, which + # we want visible in the operator output. + RULE_COUNT=$(get_alb_rule_count "$CANDIDATE") || { log warn "⚠️ Could not query rules for ALB '$CANDIDATE', skipping" continue } diff --git a/k8s/scope/tests/networking/autocreate_alb.bats b/k8s/scope/tests/networking/autocreate_alb.bats index 8ad6c257..f76bdd16 100644 --- a/k8s/scope/tests/networking/autocreate_alb.bats +++ b/k8s/scope/tests/networking/autocreate_alb.bats @@ -11,13 +11,16 @@ setup() { export -f log source "$PROJECT_ROOT/k8s/utils/get_config_value" + export -f get_config_value export SCRIPT="$PROJECT_ROOT/k8s/scope/networking/autocreate_alb" export REGION="us-east-1" export INGRESS_VISIBILITY="internet-facing" export K8S_NAMESPACE="test-ns" export SERVICE_PATH="$PROJECT_ROOT/k8s" + export DOMAIN="nullapps.io" export OUTPUT_DIR="$(mktemp -d)" + export PATCH_BODY_FILE="$OUTPUT_DIR/_patch_body" export CONTEXT='{ "scope": { @@ -34,8 +37,6 @@ setup() { } }' - export CALL_LOG_FILE="$(mktemp)" - # Default mocks — each test overrides as needed. gomplate() { local prev="" @@ -46,8 +47,8 @@ setup() { return 0 } export -f gomplate + np() { - echo "np $*" >> "$CALL_LOG_FILE" if [ "$1" = "provider" ] && [ "$2" = "list" ]; then echo '{"results":[{"id":"prov-1","attributes":{"balancer":{}}}]}' return 0 @@ -55,7 +56,7 @@ setup() { if [ "$1" = "provider" ] && [ "$2" = "patch" ]; then local prev="" for arg in "$@"; do - if [ "$prev" = "--body" ]; then echo "$arg" > "$OUTPUT_DIR/_patch_body"; fi + if [ "$prev" = "--body" ]; then echo "$arg" > "$PATCH_BODY_FILE"; fi prev="$arg" done return 0 @@ -63,58 +64,57 @@ setup() { return 1 } export -f np + export -f gomplate } teardown() { unset -f log gomplate np get_config_value - rm -rf "$OUTPUT_DIR" "$CALL_LOG_FILE" + rm -rf "$OUTPUT_DIR" unset ALB_NAME ALB_AUTOCREATED } # ============================================================================= -# Name generation +# Happy path — full log sequence (info logs only; debug needs LOG_LEVEL=debug) # ============================================================================= -@test "autocreate_alb: generates name with default prefix and public short form" { - source "$SCRIPT" - - [[ "$ALB_NAME" =~ ^nullplatform-auto-public-[a-f0-9]{6}$ ]] +@test "autocreate_alb: full happy-path log sequence (default prefix, public visibility)" { + run bash -c 'export LOG_LEVEL=debug; source "$SCRIPT"; echo "ALB_NAME=$ALB_NAME ALB_AUTOCREATED=$ALB_AUTOCREATED"' + + assert_equal "$status" "0" + # First log: name generated + visibility echoed + [[ "$output" =~ "🔧 Autocreating ALB 'nullplatform-auto-public-"[a-f0-9]{6}"' (visibility=internet-facing)" ]] + # Provider patch log (field name appears explicitly) + [[ "$output" =~ "📝 Registering ALB 'nullplatform-auto-public-"[a-f0-9]{6}"' in container-orchestration provider (additional_public_names)" ]] + # Render confirmation (debug) + assert_contains "$output" "📝 Rendered dummy ingress to $OUTPUT_DIR/ingress-dummy-" + # Exports + [[ "$output" =~ "ALB_NAME=nullplatform-auto-public-"[a-f0-9]{6}" ALB_AUTOCREATED=true" ]] } -@test "autocreate_alb: generates name with private short form for internal visibility" { +@test "autocreate_alb: internal visibility selects additional_private_names field in registration log" { export INGRESS_VISIBILITY="internal" - source "$SCRIPT" + run bash -c 'source "$SCRIPT"; echo "ALB_NAME=$ALB_NAME"' - [[ "$ALB_NAME" =~ ^nullplatform-auto-private-[a-f0-9]{6}$ ]] + assert_equal "$status" "0" + [[ "$output" =~ "🔧 Autocreating ALB 'nullplatform-auto-private-"[a-f0-9]{6}"' (visibility=internal)" ]] + [[ "$output" =~ "📝 Registering ALB 'nullplatform-auto-private-"[a-f0-9]{6}"' in container-orchestration provider (additional_private_names)" ]] } -@test "autocreate_alb: respects custom name prefix" { +@test "autocreate_alb: custom prefix flows into both autocreate and registration logs" { export ALB_AUTOCREATE_NAME_PREFIX="custom-" - source "$SCRIPT" - - [[ "$ALB_NAME" =~ ^custom-public-[a-f0-9]{6}$ ]] -} - -@test "autocreate_alb: exports ALB_AUTOCREATED=true" { - source "$SCRIPT" + run bash -c 'source "$SCRIPT"; echo "ALB_NAME=$ALB_NAME"' - [ "$ALB_AUTOCREATED" = "true" ] + assert_equal "$status" "0" + [[ "$output" =~ "🔧 Autocreating ALB 'custom-public-"[a-f0-9]{6}"' (visibility=internet-facing)" ]] + [[ "$output" =~ "ALB_NAME=custom-public-"[a-f0-9]{6} ]] } # ============================================================================= -# Provider patching +# Provider patch shape # ============================================================================= -@test "autocreate_alb: calls np provider list with the scope NRN" { - source "$SCRIPT" - - grep -q "provider list" "$CALL_LOG_FILE" - grep -q -- "--nrn organization=1:account=2:namespace=3:application=4:scope=5" "$CALL_LOG_FILE" -} - -@test "autocreate_alb: patches additional_public_names for internet-facing visibility" { +@test "autocreate_alb: patches additional_public_names preserving existing entries" { np() { - echo "np $*" >> "$CALL_LOG_FILE" if [ "$1" = "provider" ] && [ "$2" = "list" ]; then echo '{"results":[{"id":"prov-1","attributes":{"balancer":{"additional_public_names":["existing-1"]}}}]}' return 0 @@ -122,7 +122,7 @@ teardown() { if [ "$1" = "provider" ] && [ "$2" = "patch" ]; then local prev="" for arg in "$@"; do - if [ "$prev" = "--body" ]; then echo "$arg" > "$OUTPUT_DIR/_patch_body"; fi + if [ "$prev" = "--body" ]; then echo "$arg" > "$PATCH_BODY_FILE"; fi prev="$arg" done return 0 @@ -134,7 +134,7 @@ teardown() { source "$SCRIPT" local body - body=$(cat "$OUTPUT_DIR/_patch_body") + body=$(cat "$PATCH_BODY_FILE") echo "$body" | jq -e '.attributes.balancer.additional_public_names | length == 2' echo "$body" | jq -e '.attributes.balancer.additional_public_names[0] == "existing-1"' echo "$body" | jq -e ".attributes.balancer.additional_public_names[1] == \"$ALB_NAME\"" @@ -145,22 +145,19 @@ teardown() { source "$SCRIPT" - cat "$OUTPUT_DIR/_patch_body" | jq -e '.attributes.balancer.additional_private_names | length == 1' + cat "$PATCH_BODY_FILE" | jq -e '.attributes.balancer.additional_private_names | length == 1' } -@test "autocreate_alb: deduplicates when name already in list (defense in depth)" { +@test "autocreate_alb: deduplicates name in the patched list" { np() { - echo "np $*" >> "$CALL_LOG_FILE" if [ "$1" = "provider" ] && [ "$2" = "list" ]; then - # Inject a duplicate scenario: pretend existing list already contains the same name - # (impossible in practice given random suffix, but the jq pipeline must still be safe) echo '{"results":[{"id":"prov-1","attributes":{"balancer":{"additional_public_names":["a","b"]}}}]}' return 0 fi if [ "$1" = "provider" ] && [ "$2" = "patch" ]; then local prev="" for arg in "$@"; do - if [ "$prev" = "--body" ]; then echo "$arg" > "$OUTPUT_DIR/_patch_body"; fi + if [ "$prev" = "--body" ]; then echo "$arg" > "$PATCH_BODY_FILE"; fi prev="$arg" done return 0 @@ -171,10 +168,13 @@ teardown() { source "$SCRIPT" - cat "$OUTPUT_DIR/_patch_body" | jq -e '.attributes.balancer.additional_public_names | length == 3' + cat "$PATCH_BODY_FILE" | jq -e '.attributes.balancer.additional_public_names | length == 3' } -@test "autocreate_alb: exits when provider list returns no results" { +# ============================================================================= +# Error paths — full failure log +# ============================================================================= +@test "autocreate_alb: exits with full log when provider list returns no results" { np() { if [ "$1" = "provider" ] && [ "$2" = "list" ]; then echo '{"results":[]}'; return 0; fi return 1 @@ -183,11 +183,12 @@ teardown() { run bash -c 'source "$SCRIPT"' - [ "$status" -ne 0 ] - assert_contains "$output" "No container-orchestration provider found" + assert_equal "$status" "1" + [[ "$output" =~ "🔧 Autocreating ALB 'nullplatform-auto-public-"[a-f0-9]{6}"' (visibility=internet-facing)" ]] + assert_contains "$output" "❌ No container-orchestration provider found for NRN 'organization=1:account=2:namespace=3:application=4:scope=5'" } -@test "autocreate_alb: exits when np provider list fails" { +@test "autocreate_alb: exits with full log when np provider list fails" { np() { if [ "$1" = "provider" ] && [ "$2" = "list" ]; then return 2; fi return 1 @@ -196,11 +197,11 @@ teardown() { run bash -c 'source "$SCRIPT"' - [ "$status" -ne 0 ] - assert_contains "$output" "Failed to list container-orchestration provider" + assert_equal "$status" "1" + assert_contains "$output" "❌ Failed to list container-orchestration provider for NRN 'organization=1:account=2:namespace=3:application=4:scope=5'" } -@test "autocreate_alb: exits when np provider patch fails" { +@test "autocreate_alb: exits with full log when np provider patch fails" { np() { if [ "$1" = "provider" ] && [ "$2" = "list" ]; then echo '{"results":[{"id":"prov-1","attributes":{"balancer":{}}}]}' @@ -213,43 +214,46 @@ teardown() { run bash -c 'source "$SCRIPT"' - [ "$status" -ne 0 ] - assert_contains "$output" "Failed to patch container-orchestration provider" + assert_equal "$status" "1" + [[ "$output" =~ "📝 Registering ALB 'nullplatform-auto-public-"[a-f0-9]{6}"' in container-orchestration provider (additional_public_names)" ]] + assert_contains "$output" "❌ Failed to patch container-orchestration provider with new ALB" + assert_contains "$output" "💡 Possible causes: agent lacks write permission on the provider, or NP_TOKEN/NULLPLATFORM_API_KEY is missing" } -@test "autocreate_alb: exits when CONTEXT has no scope.nrn" { +@test "autocreate_alb: exits with full log when CONTEXT has no scope.nrn" { export CONTEXT=$(echo "$CONTEXT" | jq 'del(.scope.nrn)') run bash -c 'source "$SCRIPT"' - [ "$status" -ne 0 ] - assert_contains "$output" "Could not read scope NRN" -} - -# ============================================================================= -# Dummy ingress rendering -# ============================================================================= -@test "autocreate_alb: renders the dummy ingress yaml to OUTPUT_DIR" { - source "$SCRIPT" - - [ -f "$OUTPUT_DIR/ingress-dummy-${ALB_NAME}.yaml" ] + assert_equal "$status" "1" + assert_contains "$output" "❌ Could not read scope NRN from CONTEXT — cannot patch provider" } -@test "autocreate_alb: exits when gomplate fails" { +@test "autocreate_alb: exits with full log when gomplate fails to render" { gomplate() { return 1; } export -f gomplate run bash -c 'source "$SCRIPT"' - [ "$status" -ne 0 ] - assert_contains "$output" "Failed to render ingress-dummy template" + assert_equal "$status" "1" + assert_contains "$output" "❌ Failed to render ingress-dummy template" + assert_contains "$output" "📋 Template: $SERVICE_PATH/scope/templates/ingress-dummy.yaml.tpl" } -@test "autocreate_alb: exits when OUTPUT_DIR is not set" { +@test "autocreate_alb: exits with full log when OUTPUT_DIR is not set" { unset OUTPUT_DIR run bash -c 'source "$SCRIPT"' - [ "$status" -ne 0 ] - assert_contains "$output" "OUTPUT_DIR is not set" + assert_equal "$status" "1" + assert_contains "$output" "❌ OUTPUT_DIR is not set — autocreate_alb must run after OUTPUT_DIR is exported" +} + +# ============================================================================= +# Side effects — rendered YAML file +# ============================================================================= +@test "autocreate_alb: renders the dummy ingress yaml file inside OUTPUT_DIR" { + source "$SCRIPT" + + [ -f "$OUTPUT_DIR/ingress-dummy-${ALB_NAME}.yaml" ] } diff --git a/k8s/scope/tests/networking/resolve_balancer.bats b/k8s/scope/tests/networking/resolve_balancer.bats index 19b29a2f..9e42c15b 100644 --- a/k8s/scope/tests/networking/resolve_balancer.bats +++ b/k8s/scope/tests/networking/resolve_balancer.bats @@ -506,7 +506,7 @@ mock_alb_rules() { # ============================================================================= # LoadBalancerNotFound treated as 0 rules (concurrent autocreate race case) # ============================================================================= -@test "resolve_balancer: treats LoadBalancerNotFound as 0 rules so in-flight ALB wins" { +@test "resolve_balancer: LoadBalancerNotFound is treated as 0 rules and the in-flight ALB wins selection" { export INGRESS_VISIBILITY="internet-facing" export CONTEXT=$(echo "$CONTEXT" | jq ' .providers["scope-configurations"].networking.additional_public_balancers = ["in-flight-alb"] @@ -543,15 +543,22 @@ mock_alb_rules() { } export -f aws - source "$SCRIPT" + run bash -c 'export LOG_LEVEL=debug; source "$SCRIPT"; echo "ALB_NAME=$ALB_NAME"' - assert_equal "$ALB_NAME" "in-flight-alb" + assert_equal "$status" "0" + assert_contains "$output" "🔍 Additional balancers configured, resolving least-loaded ALB..." + assert_contains "$output" "📋 Candidate balancers: co-balancer-public, in-flight-alb" + assert_contains "$output" "📋 ALB 'co-balancer-public': 50 rules" + assert_contains "$output" "📋 ALB 'in-flight-alb' not yet visible in AWS (likely being provisioned); treating as 0 rules" + assert_contains "$output" "📋 ALB 'in-flight-alb': 0 rules" + assert_contains "$output" "📝 Selected ALB 'in-flight-alb' (0 rules) over default 'co-balancer-public'" + assert_contains "$output" "ALB_NAME=in-flight-alb" } # ============================================================================= # Autocreate trigger # ============================================================================= -@test "resolve_balancer: sources autocreate_alb when all candidates over threshold and feature enabled" { +@test "resolve_balancer: sources autocreate_alb and logs full trigger sequence when all candidates over threshold" { export INGRESS_VISIBILITY="internet-facing" export ALB_AUTOCREATE_ENABLED="true" export ALB_MAX_CAPACITY="50" @@ -560,38 +567,41 @@ mock_alb_rules() { ') mock_alb_rules "co-balancer-public 60" "alb-extra-1 55" - # Stub autocreate_alb: simulate it exporting the new ALB name. + # Stub autocreate_alb so the trigger path runs end-to-end without requiring + # gomplate / np. The stub exports the new ALB name as the real script would. cat > "$BATS_TEST_TMPDIR/autocreate_alb_stub" <<'STUB' export ALB_NAME="auto-public-stubbed" export ALB_AUTOCREATED="true" STUB - export INGRESS_DUMMY_TEMPLATE="$BATS_TEST_TMPDIR/ignored.tpl" - # Replace the real autocreate_alb with the stub by intercepting the source path - AUTOCREATE_STUB="$BATS_TEST_TMPDIR/autocreate_alb_stub" - # The script does: source "$_RESOLVE_BALANCER_DIR/autocreate_alb" - # Override via shadow path: copy resolve_balancer to tmp with patched source line. PATCHED_SCRIPT="$BATS_TEST_TMPDIR/resolve_balancer_patched" + AUTOCREATE_STUB="$BATS_TEST_TMPDIR/autocreate_alb_stub" sed "s|\\\$_RESOLVE_BALANCER_DIR/autocreate_alb|$AUTOCREATE_STUB|" "$SCRIPT" > "$PATCHED_SCRIPT" - source "$PATCHED_SCRIPT" + run bash -c "export LOG_LEVEL=debug; source '$PATCHED_SCRIPT'; echo \"ALB_NAME=\$ALB_NAME ALB_AUTOCREATED=\$ALB_AUTOCREATED\"" - assert_equal "$ALB_NAME" "auto-public-stubbed" - [ "$ALB_AUTOCREATED" = "true" ] + assert_equal "$status" "0" + assert_contains "$output" "📋 ALB 'co-balancer-public': 60 rules" + assert_contains "$output" "📋 ALB 'alb-extra-1': 55 rules" + assert_contains "$output" "🔧 All candidate ALBs are at or above capacity (55/50); triggering autocreate" + assert_contains "$output" "ALB_NAME=auto-public-stubbed ALB_AUTOCREATED=true" } -@test "resolve_balancer: does not autocreate when feature disabled even if all candidates full" { +@test "resolve_balancer: does not autocreate (no trigger log) when feature disabled even if candidates full" { export INGRESS_VISIBILITY="internet-facing" export ALB_AUTOCREATE_ENABLED="false" export ALB_MAX_CAPACITY="50" export CONTEXT=$(echo "$CONTEXT" | jq ' .providers["scope-configurations"].networking.additional_public_balancers = ["alb-extra-1"] ') - # Both above threshold but autocreate disabled → keeps least-loaded mock_alb_rules "co-balancer-public 60" "alb-extra-1 55" - source "$SCRIPT" + run bash -c 'source "$SCRIPT"; echo "ALB_NAME=$ALB_NAME"' - assert_equal "$ALB_NAME" "alb-extra-1" + assert_equal "$status" "0" + assert_contains "$output" "📝 Selected ALB 'alb-extra-1' (55 rules) over default 'co-balancer-public'" + assert_contains "$output" "ALB_NAME=alb-extra-1" + # No autocreate trigger log + [[ "$output" != *"triggering autocreate"* ]] } @test "resolve_balancer: does not autocreate when at least one candidate below threshold" { @@ -603,12 +613,15 @@ STUB ') mock_alb_rules "co-balancer-public 60" "alb-extra-1 10" - source "$SCRIPT" + run bash -c 'source "$SCRIPT"; echo "ALB_NAME=$ALB_NAME"' - assert_equal "$ALB_NAME" "alb-extra-1" + assert_equal "$status" "0" + assert_contains "$output" "📝 Selected ALB 'alb-extra-1' (10 rules) over default 'co-balancer-public'" + assert_contains "$output" "ALB_NAME=alb-extra-1" + [[ "$output" != *"triggering autocreate"* ]] } -@test "resolve_balancer: warns and skips autocreate when ALB_MAX_CAPACITY is non-numeric" { +@test "resolve_balancer: emits full warn when ALB_MAX_CAPACITY is non-numeric and skips autocreate" { export INGRESS_VISIBILITY="internet-facing" export ALB_AUTOCREATE_ENABLED="true" export ALB_MAX_CAPACITY="not-a-number" @@ -617,8 +630,10 @@ STUB ') mock_alb_rules "co-balancer-public 60" "alb-extra-1 55" - run bash -c 'source "$SCRIPT"' + run bash -c 'source "$SCRIPT"; echo "ALB_NAME=$ALB_NAME"' - [ "$status" -eq 0 ] - assert_contains "$output" "ALB_MAX_CAPACITY must be numeric" + assert_equal "$status" "0" + assert_contains "$output" "⚠️ ALB_MAX_CAPACITY must be numeric, got: 'not-a-number' — skipping autocreate evaluation" + assert_contains "$output" "ALB_NAME=alb-extra-1" + [[ "$output" != *"triggering autocreate"* ]] } diff --git a/k8s/scope/tests/networking/wait_for_alb.bats b/k8s/scope/tests/networking/wait_for_alb.bats index 9b6587dc..aa53a927 100644 --- a/k8s/scope/tests/networking/wait_for_alb.bats +++ b/k8s/scope/tests/networking/wait_for_alb.bats @@ -24,33 +24,27 @@ setup() { "providers": { "container-orchestration": {} } }' - export CALL_LOG_FILE="$(mktemp)" - aws() { return 1; } export -f aws } teardown() { unset -f log aws get_config_value - rm -f "$CALL_LOG_FILE" unset ALB_AUTOCREATED } -# Mocks describe-load-balancers + add-tags. The state arg controls what the -# describe response reports. +# Builds an aws() mock that returns the given state in a single +# describe-load-balancers --output json response. add-tags returns 0. mock_aws_state() { local state="$1" local arn="arn:aws:elasticloadbalancing:us-east-1:123:loadbalancer/app/$ALB_NAME/abc" eval "aws() { - echo \"aws \$*\" >> '$CALL_LOG_FILE' case \"\$*\" in *describe-load-balancers*) echo '{\"LoadBalancers\":[{\"LoadBalancerArn\":\"${arn}\",\"State\":{\"Code\":\"${state}\"}}]}' return 0 ;; - *add-tags*) - return 0 - ;; + *add-tags*) return 0 ;; esac return 1 } @@ -60,68 +54,93 @@ mock_aws_state() { # ============================================================================= # Active state # ============================================================================= -@test "wait_for_alb: returns success when ALB is already active" { +@test "wait_for_alb: success path logs full sequence when ALB is already active" { mock_aws_state "active" run bash -c 'source "$SCRIPT"' - [ "$status" -eq 0 ] - assert_contains "$output" "is active" + assert_equal "$status" "0" + assert_contains "$output" "⏳ Waiting up to 2s for ALB 'test-alb' to become active..." + assert_contains "$output" "📋 ALB 'test-alb' state: active" + assert_contains "$output" "✅ ALB 'test-alb' is active" +} + +@test "wait_for_alb: honors timeout value in the initial wait log" { + export ALB_AUTOCREATE_TIMEOUT_SECONDS="120" + mock_aws_state "active" + + run bash -c 'source "$SCRIPT"' + + assert_equal "$status" "0" + assert_contains "$output" "⏳ Waiting up to 120s for ALB 'test-alb' to become active..." } # ============================================================================= # Failed state # ============================================================================= -@test "wait_for_alb: exits when ALB reaches state=failed" { +@test "wait_for_alb: exits with full failure log when ALB reaches state=failed" { mock_aws_state "failed" run bash -c 'source "$SCRIPT"' - [ "$status" -ne 0 ] - assert_contains "$output" "reached state 'failed'" + assert_equal "$status" "1" + assert_contains "$output" "⏳ Waiting up to 2s for ALB 'test-alb' to become active..." + assert_contains "$output" "📋 ALB 'test-alb' state: failed" + assert_contains "$output" "❌ ALB 'test-alb' reached state 'failed'" } # ============================================================================= -# Timeout +# Timeout with full diagnostic log # ============================================================================= -@test "wait_for_alb: exits when ALB never reaches active within timeout" { +@test "wait_for_alb: timeout emits diagnostic causes and fix hints" { export ALB_AUTOCREATE_TIMEOUT_SECONDS="1" mock_aws_state "provisioning" run bash -c 'source "$SCRIPT"' - [ "$status" -ne 0 ] - assert_contains "$output" "Timed out" + assert_equal "$status" "1" + assert_contains "$output" "⏳ Waiting up to 1s for ALB 'test-alb' to become active..." + assert_contains "$output" "📋 ALB 'test-alb' state: provisioning" + assert_contains "$output" "❌ Timed out after 1s waiting for ALB 'test-alb' to become active" + assert_contains "$output" "💡 Possible causes:" + assert_contains "$output" " The AWS Load Balancer Controller may be slow, mis-configured, or the AWS account may be hitting an ALB quota" + assert_contains "$output" "🔧 How to fix:" + assert_contains "$output" " • Check controller logs: kubectl -n kube-system logs deploy/aws-load-balancer-controller" + assert_contains "$output" " • Verify ALB quota: aws service-quotas get-service-quota --service-code elasticloadbalancing --quota-code L-53DA6B97" } # ============================================================================= # Tagging on autocreate # ============================================================================= -@test "wait_for_alb: tags the ALB when ALB_AUTOCREATED=true" { +@test "wait_for_alb: tags ALB and logs full tag-success message when ALB_AUTOCREATED=true" { export ALB_AUTOCREATED="true" mock_aws_state "active" - source "$SCRIPT" + run bash -c 'source "$SCRIPT"' - grep -q "add-tags" "$CALL_LOG_FILE" - grep -q "nullplatform:managed-by,Value=autocreate" "$CALL_LOG_FILE" - grep -q "nullplatform:visibility,Value=internet-facing" "$CALL_LOG_FILE" - grep -q "nullplatform:created-by-scope-id,Value=scope-1" "$CALL_LOG_FILE" + assert_equal "$status" "0" + assert_contains "$output" "⏳ Waiting up to 2s for ALB 'test-alb' to become active..." + assert_contains "$output" "📋 ALB 'test-alb' state: active" + assert_contains "$output" "✅ ALB 'test-alb' is active" + assert_contains "$output" "📋 Tagged ALB 'test-alb' with managed-by=autocreate" } -@test "wait_for_alb: does not tag when ALB_AUTOCREATED is unset" { +@test "wait_for_alb: does not tag (no tag log) when ALB_AUTOCREATED is unset" { mock_aws_state "active" - source "$SCRIPT" + run bash -c 'source "$SCRIPT"' - ! grep -q "add-tags" "$CALL_LOG_FILE" + assert_equal "$status" "0" + assert_contains "$output" "✅ ALB 'test-alb' is active" + # No tagging log should appear + [[ "$output" != *"Tagged ALB"* ]] + [[ "$output" != *"Could not tag ALB"* ]] } -@test "wait_for_alb: tagging failure warns but does not fail the script" { +@test "wait_for_alb: tag failure logs full warn message but exits 0" { export ALB_AUTOCREATED="true" local arn="arn:aws:elasticloadbalancing:us-east-1:123:loadbalancer/app/$ALB_NAME/abc" eval "aws() { - echo \"aws \$*\" >> '$CALL_LOG_FILE' case \"\$*\" in *describe-load-balancers*) echo '{\"LoadBalancers\":[{\"LoadBalancerArn\":\"${arn}\",\"State\":{\"Code\":\"active\"}}]}' @@ -135,6 +154,7 @@ mock_aws_state() { run bash -c 'source "$SCRIPT"' - [ "$status" -eq 0 ] - assert_contains "$output" "audit only" + assert_equal "$status" "0" + assert_contains "$output" "✅ ALB 'test-alb' is active" + assert_contains "$output" "⚠️ Could not tag ALB 'test-alb' (audit only — provider registration already succeeded)" } From 33da501e28a7df1bf5b3cbee12e04ff1a98ff9c4 Mon Sep 17 00:00:00 2001 From: Federico Maleh Date: Wed, 10 Jun 2026 11:39:33 -0300 Subject: [PATCH 007/158] feat: suggest enabling ALB_AUTOCREATE_ENABLED in capacity error hints --- k8s/scope/tests/validate_alb_capacity.bats | 1 + k8s/scope/validate_alb_capacity | 1 + 2 files changed, 2 insertions(+) diff --git a/k8s/scope/tests/validate_alb_capacity.bats b/k8s/scope/tests/validate_alb_capacity.bats index af08defd..0878e4fe 100644 --- a/k8s/scope/tests/validate_alb_capacity.bats +++ b/k8s/scope/tests/validate_alb_capacity.bats @@ -127,6 +127,7 @@ teardown() { assert_contains "$output" "Increase ALB_MAX_CAPACITY in values.yaml or container-orchestration provider (AWS limit is 100 per listener)" assert_contains "$output" "Request an AWS service quota increase for rules per ALB listener" assert_contains "$output" "Consider using a separate ALB for additional scopes" + assert_contains "$output" "Enable ALB autocreation so the platform provisions a new ALB automatically when the pool is exhausted: set ALB_AUTOCREATE_ENABLED=true in values.yaml or in the container-orchestration provider" } @test "validate_alb_capacity: fails when over capacity" { diff --git a/k8s/scope/validate_alb_capacity b/k8s/scope/validate_alb_capacity index fc5eb50e..e3c81f0e 100755 --- a/k8s/scope/validate_alb_capacity +++ b/k8s/scope/validate_alb_capacity @@ -135,6 +135,7 @@ if [[ "$TOTAL_RULES" -ge "$ALB_MAX_CAPACITY" ]]; then log error " • Increase ALB_MAX_CAPACITY in values.yaml or container-orchestration provider (AWS limit is 100 per listener)" log error " • Request an AWS service quota increase for rules per ALB listener" log error " • Consider using a separate ALB for additional scopes" + log error " • Enable ALB autocreation so the platform provisions a new ALB automatically when the pool is exhausted: set ALB_AUTOCREATE_ENABLED=true in values.yaml or in the container-orchestration provider" log error "" exit 1 fi From 7f9435f09a4027707efaad7a782aa690723e00af Mon Sep 17 00:00:00 2001 From: Federico Maleh Date: Wed, 10 Jun 2026 11:53:04 -0300 Subject: [PATCH 008/158] fix(autocreate): trigger on single-ALB setups and emit step-by-step debug logs --- k8s/scope/networking/resolve_balancer | 204 ++++++++++-------- .../tests/networking/resolve_balancer.bats | 48 ++++- 2 files changed, 157 insertions(+), 95 deletions(-) diff --git a/k8s/scope/networking/resolve_balancer b/k8s/scope/networking/resolve_balancer index d5214ecb..e2ef333f 100755 --- a/k8s/scope/networking/resolve_balancer +++ b/k8s/scope/networking/resolve_balancer @@ -150,6 +150,8 @@ get_alb_from_route53() { # Main logic # ============================================================================= +log debug "🔍 Resolving ALB for visibility=$INGRESS_VISIBILITY (DNS_TYPE=$DNS_TYPE)" + # Resolve the base ALB name from configuration ALB_NAME="k8s-nullplatform-$INGRESS_VISIBILITY" @@ -167,100 +169,122 @@ else ) fi -if [[ "$DNS_TYPE" == "route53" ]]; then - # Priority 1: Check Route53 for an existing DNS record - SCOPE_DOMAIN_VAL=$(echo "$CONTEXT" | jq -r '.scope.domain // empty') - EXISTING_ALB="" +log debug "📋 Base ALB from configuration: '$ALB_NAME'" - if [ -n "$SCOPE_DOMAIN_VAL" ]; then - EXISTING_ALB=$(get_alb_from_route53 "$SCOPE_DOMAIN_VAL" "$REGION" 2>/dev/null) || true - fi +if [[ "$DNS_TYPE" != "route53" ]]; then + log debug "📋 DNS type is '$DNS_TYPE', skipping Route53 lookup and load balancing" + export ALB_NAME + return 0 2>/dev/null || true +fi + +# Priority 1: Check Route53 for an existing DNS record (DNS/ingress consistency) +SCOPE_DOMAIN_VAL=$(echo "$CONTEXT" | jq -r '.scope.domain // empty') +EXISTING_ALB="" + +if [ -n "$SCOPE_DOMAIN_VAL" ]; then + log debug "📋 Looking up Route53 alias for domain '$SCOPE_DOMAIN_VAL'..." + EXISTING_ALB=$(get_alb_from_route53 "$SCOPE_DOMAIN_VAL" "$REGION" 2>/dev/null) || true +fi + +if [ -n "$EXISTING_ALB" ]; then + log info "📝 Using ALB '$EXISTING_ALB' from Route53 record for $SCOPE_DOMAIN_VAL" + ALB_NAME="$EXISTING_ALB" + export ALB_NAME + return 0 2>/dev/null || true +fi + +log debug "📋 No Route53 record found; evaluating candidate pool" + +# Priority 2: build candidate pool (base + any additional balancers from provider) +ADDITIONAL_BALANCERS="" +if [ "$INGRESS_VISIBILITY" = "internet-facing" ]; then + ADDITIONAL_BALANCERS=$(get_config_value \ + --provider '.providers["scope-configurations"].networking.additional_public_balancers' \ + --provider '.providers["container-orchestration"].balancer.additional_public_names' \ + --default "" + ) +else + ADDITIONAL_BALANCERS=$(get_config_value \ + --provider '.providers["scope-configurations"].networking.additional_private_balancers' \ + --provider '.providers["container-orchestration"].balancer.additional_private_names' \ + --default "" + ) +fi - if [ -n "$EXISTING_ALB" ]; then - log info "📝 Using ALB '$EXISTING_ALB' from Route53 record for $SCOPE_DOMAIN_VAL" - ALB_NAME="$EXISTING_ALB" - else - # Priority 2: If additional balancers configured, pick the least-loaded one - ADDITIONAL_BALANCERS="" - if [ "$INGRESS_VISIBILITY" = "internet-facing" ]; then - ADDITIONAL_BALANCERS=$(get_config_value \ - --provider '.providers["scope-configurations"].networking.additional_public_balancers' \ - --provider '.providers["container-orchestration"].balancer.additional_public_names' \ - --default "" - ) - else - ADDITIONAL_BALANCERS=$(get_config_value \ - --provider '.providers["scope-configurations"].networking.additional_private_balancers' \ - --provider '.providers["container-orchestration"].balancer.additional_private_names' \ - --default "" - ) - fi - - if [ -n "$ADDITIONAL_BALANCERS" ] && [ "$ADDITIONAL_BALANCERS" != "null" ] && [ "$ADDITIONAL_BALANCERS" != "[]" ]; then - log debug "🔍 Additional balancers configured, resolving least-loaded ALB..." - - CANDIDATES=$(echo "$ADDITIONAL_BALANCERS" | jq -r --arg base "$ALB_NAME" '[$base] + . | .[]') - - log debug "📋 Candidate balancers: $(echo "$CANDIDATES" | paste -sd ',' - | sed 's/,/, /g')" - - MIN_RULES=-1 - BEST_ALB="$ALB_NAME" - - for CANDIDATE in $CANDIDATES; do - # No outer stderr redirect: get_alb_rule_count locally suppresses raw - # aws CLI stderr and emits only intentional `log` messages there, which - # we want visible in the operator output. - RULE_COUNT=$(get_alb_rule_count "$CANDIDATE") || { - log warn "⚠️ Could not query rules for ALB '$CANDIDATE', skipping" - continue - } - - log debug "📋 ALB '$CANDIDATE': $RULE_COUNT rules" - - if [ "$MIN_RULES" -eq -1 ] || [ "$RULE_COUNT" -lt "$MIN_RULES" ]; then - MIN_RULES=$RULE_COUNT - BEST_ALB="$CANDIDATE" - fi - done - - if [ "$BEST_ALB" != "$ALB_NAME" ]; then - log info "📝 Selected ALB '$BEST_ALB' ($MIN_RULES rules) over default '$ALB_NAME'" - fi - - ALB_NAME="$BEST_ALB" - - # Autocreate fallback: every candidate is at or above the threshold and - # autocreate is enabled. Delegate to autocreate_alb to provision a new - # ALB and replace ALB_NAME with it. - AUTOCREATE_ENABLED=$(get_config_value \ - --env ALB_AUTOCREATE_ENABLED \ - --provider '.providers["container-orchestration"].balancer.autocreate_enabled' \ - --default "false" - ) - - MAX_CAPACITY=$(get_config_value \ - --env ALB_MAX_CAPACITY \ - --provider '.providers["scope-configurations"].networking.alb_max_capacity' \ - --provider '.providers["container-orchestration"].balancer.alb_capacity_threshold' \ - --default "75" - ) - - # Without this guard a non-numeric MAX_CAPACITY would silently disable the - # autocreate trigger (the `-ge` comparison errors out and evaluates false). - if ! [[ "$MAX_CAPACITY" =~ ^[0-9]+$ ]]; then - log warn "⚠️ ALB_MAX_CAPACITY must be numeric, got: '$MAX_CAPACITY' — skipping autocreate evaluation" - MAX_CAPACITY="" - fi - - if [ "$AUTOCREATE_ENABLED" = "true" ] && [ -n "$MAX_CAPACITY" ] && [ "$MIN_RULES" -ge 0 ] && [ "$MIN_RULES" -ge "$MAX_CAPACITY" ]; then - log info "🔧 All candidate ALBs are at or above capacity ($MIN_RULES/$MAX_CAPACITY); triggering autocreate" - # autocreate_alb exports ALB_NAME with the new name (or exits on failure) - source "$_RESOLVE_BALANCER_DIR/autocreate_alb" - fi - fi +if [ -n "$ADDITIONAL_BALANCERS" ] && [ "$ADDITIONAL_BALANCERS" != "null" ] && [ "$ADDITIONAL_BALANCERS" != "[]" ]; then + CANDIDATES=$(echo "$ADDITIONAL_BALANCERS" | jq -r --arg base "$ALB_NAME" '[$base] + . | .[]') + log debug "📋 Candidate balancers (base + additional): $(echo "$CANDIDATES" | paste -sd ',' - | sed 's/,/, /g')" +else + CANDIDATES="$ALB_NAME" + log debug "📋 No additional balancers configured; candidate pool is just the base ALB '$ALB_NAME'" +fi + +# Pick least-loaded candidate. We evaluate every candidate (including the base +# alone) so capacity + autocreate decisions can fire on single-ALB setups too. +MIN_RULES=-1 +BEST_ALB="$ALB_NAME" + +for CANDIDATE in $CANDIDATES; do + # No outer stderr redirect: get_alb_rule_count locally suppresses raw aws + # CLI stderr and emits only intentional `log` messages there, which we want + # visible in the operator output. + RULE_COUNT=$(get_alb_rule_count "$CANDIDATE") || { + log warn "⚠️ Could not query rules for ALB '$CANDIDATE', skipping" + continue + } + + log debug "📋 ALB '$CANDIDATE': $RULE_COUNT rules" + + if [ "$MIN_RULES" -eq -1 ] || [ "$RULE_COUNT" -lt "$MIN_RULES" ]; then + MIN_RULES=$RULE_COUNT + BEST_ALB="$CANDIDATE" fi +done + +if [ "$BEST_ALB" != "$ALB_NAME" ]; then + log info "📝 Selected ALB '$BEST_ALB' ($MIN_RULES rules) over default '$ALB_NAME'" else - log debug "📋 DNS type is '$DNS_TYPE', skipping Route53 lookup and load balancing" + log debug "📋 Sticking with base ALB '$BEST_ALB' ($MIN_RULES rules)" +fi + +ALB_NAME="$BEST_ALB" + +# Autocreate evaluation: when the chosen ALB is at or above the capacity +# threshold and autocreate is enabled, source autocreate_alb to provision a +# new ALB and replace ALB_NAME with it. +AUTOCREATE_ENABLED=$(get_config_value \ + --env ALB_AUTOCREATE_ENABLED \ + --provider '.providers["container-orchestration"].balancer.autocreate_enabled' \ + --default "false" +) + +MAX_CAPACITY=$(get_config_value \ + --env ALB_MAX_CAPACITY \ + --provider '.providers["scope-configurations"].networking.alb_max_capacity' \ + --provider '.providers["container-orchestration"].balancer.alb_capacity_threshold' \ + --default "75" +) + +log debug "📋 Autocreate enabled: $AUTOCREATE_ENABLED | Capacity threshold: $MAX_CAPACITY" + +# Without this guard a non-numeric MAX_CAPACITY would silently disable the +# autocreate trigger (the `-ge` comparison errors out and evaluates false). +if ! [[ "$MAX_CAPACITY" =~ ^[0-9]+$ ]]; then + log warn "⚠️ ALB_MAX_CAPACITY must be numeric, got: '$MAX_CAPACITY' — skipping autocreate evaluation" + export ALB_NAME + return 0 2>/dev/null || true +fi + +if [ "$MIN_RULES" -lt 0 ]; then + log debug "📋 Could not determine rule counts for any candidate (AWS query failures); skipping autocreate evaluation" +elif [ "$MIN_RULES" -lt "$MAX_CAPACITY" ]; then + log debug "📋 Best candidate ALB '$BEST_ALB' is within capacity ($MIN_RULES/$MAX_CAPACITY); autocreate not needed" +elif [ "$AUTOCREATE_ENABLED" != "true" ]; then + log debug "📋 Best candidate ALB '$BEST_ALB' is over capacity ($MIN_RULES/$MAX_CAPACITY) but autocreate is disabled; validate_alb_capacity will reject the deployment" +else + log info "🔧 Best candidate ALB '$BEST_ALB' is at or above capacity ($MIN_RULES/$MAX_CAPACITY); triggering autocreate" + # autocreate_alb exports ALB_NAME with the new name (or exits on failure) + source "$_RESOLVE_BALANCER_DIR/autocreate_alb" fi export ALB_NAME diff --git a/k8s/scope/tests/networking/resolve_balancer.bats b/k8s/scope/tests/networking/resolve_balancer.bats index 9e42c15b..36243c4c 100644 --- a/k8s/scope/tests/networking/resolve_balancer.bats +++ b/k8s/scope/tests/networking/resolve_balancer.bats @@ -373,8 +373,8 @@ mock_alb_rules() { run bash -c 'export LOG_LEVEL=debug; source "$SCRIPT"' - assert_contains "$output" "🔍 Additional balancers configured, resolving least-loaded ALB..." - assert_contains "$output" "📋 Candidate balancers: co-balancer-public, alb-extra-1, alb-extra-2" + assert_contains "$output" "🔍 Resolving ALB for visibility=internet-facing (DNS_TYPE=route53)" + assert_contains "$output" "📋 Candidate balancers (base + additional): co-balancer-public, alb-extra-1, alb-extra-2" } # ============================================================================= @@ -546,8 +546,8 @@ mock_alb_rules() { run bash -c 'export LOG_LEVEL=debug; source "$SCRIPT"; echo "ALB_NAME=$ALB_NAME"' assert_equal "$status" "0" - assert_contains "$output" "🔍 Additional balancers configured, resolving least-loaded ALB..." - assert_contains "$output" "📋 Candidate balancers: co-balancer-public, in-flight-alb" + assert_contains "$output" "🔍 Resolving ALB for visibility=internet-facing (DNS_TYPE=route53)" + assert_contains "$output" "📋 Candidate balancers (base + additional): co-balancer-public, in-flight-alb" assert_contains "$output" "📋 ALB 'co-balancer-public': 50 rules" assert_contains "$output" "📋 ALB 'in-flight-alb' not yet visible in AWS (likely being provisioned); treating as 0 rules" assert_contains "$output" "📋 ALB 'in-flight-alb': 0 rules" @@ -582,7 +582,7 @@ STUB assert_equal "$status" "0" assert_contains "$output" "📋 ALB 'co-balancer-public': 60 rules" assert_contains "$output" "📋 ALB 'alb-extra-1': 55 rules" - assert_contains "$output" "🔧 All candidate ALBs are at or above capacity (55/50); triggering autocreate" + assert_contains "$output" "🔧 Best candidate ALB 'alb-extra-1' is at or above capacity (55/50); triggering autocreate" assert_contains "$output" "ALB_NAME=auto-public-stubbed ALB_AUTOCREATED=true" } @@ -621,6 +621,44 @@ STUB [[ "$output" != *"triggering autocreate"* ]] } +@test "resolve_balancer: triggers autocreate on single-ALB setup (no additional balancers) when over capacity" { + export INGRESS_VISIBILITY="internet-facing" + export ALB_AUTOCREATE_ENABLED="true" + export ALB_MAX_CAPACITY="10" + # No additional_public_balancers — pool is just the base ALB + mock_alb_rules "co-balancer-public 16" + + cat > "$BATS_TEST_TMPDIR/autocreate_alb_stub" <<'STUB' +export ALB_NAME="auto-public-stubbed" +export ALB_AUTOCREATED="true" +STUB + PATCHED_SCRIPT="$BATS_TEST_TMPDIR/resolve_balancer_patched" + AUTOCREATE_STUB="$BATS_TEST_TMPDIR/autocreate_alb_stub" + sed "s|\\\$_RESOLVE_BALANCER_DIR/autocreate_alb|$AUTOCREATE_STUB|" "$SCRIPT" > "$PATCHED_SCRIPT" + + run bash -c "export LOG_LEVEL=debug; source '$PATCHED_SCRIPT'; echo \"ALB_NAME=\$ALB_NAME ALB_AUTOCREATED=\$ALB_AUTOCREATED\"" + + assert_equal "$status" "0" + assert_contains "$output" "📋 No additional balancers configured; candidate pool is just the base ALB 'co-balancer-public'" + assert_contains "$output" "📋 ALB 'co-balancer-public': 16 rules" + assert_contains "$output" "🔧 Best candidate ALB 'co-balancer-public' is at or above capacity (16/10); triggering autocreate" + assert_contains "$output" "ALB_NAME=auto-public-stubbed ALB_AUTOCREATED=true" +} + +@test "resolve_balancer: single-ALB setup over capacity but autocreate disabled logs reason and lets validate reject" { + export INGRESS_VISIBILITY="internet-facing" + export ALB_AUTOCREATE_ENABLED="false" + export ALB_MAX_CAPACITY="10" + mock_alb_rules "co-balancer-public 16" + + run bash -c 'export LOG_LEVEL=debug; source "$SCRIPT"; echo "ALB_NAME=$ALB_NAME"' + + assert_equal "$status" "0" + assert_contains "$output" "📋 ALB 'co-balancer-public': 16 rules" + assert_contains "$output" "📋 Best candidate ALB 'co-balancer-public' is over capacity (16/10) but autocreate is disabled; validate_alb_capacity will reject the deployment" + assert_contains "$output" "ALB_NAME=co-balancer-public" +} + @test "resolve_balancer: emits full warn when ALB_MAX_CAPACITY is non-numeric and skips autocreate" { export INGRESS_VISIBILITY="internet-facing" export ALB_AUTOCREATE_ENABLED="true" From dff4e05c24f107c0b8e66f57354e7de724a0f38e Mon Sep 17 00:00:00 2001 From: Federico Maleh Date: Wed, 10 Jun 2026 12:04:50 -0300 Subject: [PATCH 009/158] fix: render gomplate context as .json and emit heartbeat every 30s while waiting --- k8s/scope/networking/autocreate_alb | 13 +++++++----- k8s/scope/networking/wait_for_alb | 13 +++++++++++- k8s/scope/tests/networking/wait_for_alb.bats | 21 ++++++++++++++++++++ 3 files changed, 41 insertions(+), 6 deletions(-) diff --git a/k8s/scope/networking/autocreate_alb b/k8s/scope/networking/autocreate_alb index 0a24e88d..0c2180c4 100644 --- a/k8s/scope/networking/autocreate_alb +++ b/k8s/scope/networking/autocreate_alb @@ -113,9 +113,12 @@ render_dummy_ingress() { fi mkdir -p "$OUTPUT_DIR" - local tmp_context - tmp_context=$(mktemp) - trap 'rm -f "$tmp_context"' RETURN + # The context file MUST have a .json extension. gomplate uses the extension + # to pick the parser; a plain mktemp path is treated as an opaque string + # and the template fails with "can't evaluate field X in type string". + local context_path + context_path="$OUTPUT_DIR/ingress-dummy-${alb_name}-context.json" + trap 'rm -f "$context_path"' RETURN # build_context already exports $DOMAIN (and adds it to CONTEXT as # `base_domain` after we return). Inject the call-specific fields here. @@ -125,12 +128,12 @@ render_dummy_ingress() { --arg k8s_namespace "$namespace" \ --arg base_domain "$DOMAIN" \ '. + {alb_name: $alb_name, ingress_visibility: $ingress_visibility, k8s_namespace: $k8s_namespace, base_domain: $base_domain}' \ - > "$tmp_context" + > "$context_path" local template_path="${INGRESS_DUMMY_TEMPLATE:-$SERVICE_PATH/scope/templates/ingress-dummy.yaml.tpl}" local out_path="$OUTPUT_DIR/ingress-dummy-${alb_name}.yaml" - if ! gomplate -c .="$tmp_context" --file "$template_path" --out "$out_path"; then + if ! gomplate -c .="$context_path" --file "$template_path" --out "$out_path"; then log error "❌ Failed to render ingress-dummy template" log error "📋 Template: $template_path" exit 1 diff --git a/k8s/scope/networking/wait_for_alb b/k8s/scope/networking/wait_for_alb index 5af5c561..d4aa08bc 100644 --- a/k8s/scope/networking/wait_for_alb +++ b/k8s/scope/networking/wait_for_alb @@ -23,8 +23,11 @@ TIMEOUT_SECONDS=$(get_config_value \ --default "300" ) -deadline=$(($(date +%s) + TIMEOUT_SECONDS)) +started_at=$(date +%s) +deadline=$((started_at + TIMEOUT_SECONDS)) poll_interval=10 +heartbeat_interval=30 +last_heartbeat="$started_at" log info "⏳ Waiting up to ${TIMEOUT_SECONDS}s for ALB '$ALB_NAME' to become active..." @@ -53,6 +56,14 @@ while [ "$(date +%s)" -lt "$deadline" ]; do fi fi + # Heartbeat every ~30s so the operator sees progress on long waits instead + # of staring at a frozen line for the full timeout. + now=$(date +%s) + if [ $((now - last_heartbeat)) -ge "$heartbeat_interval" ]; then + log info "⏳ Still waiting for ALB '$ALB_NAME' to become active (${state:-pending}, $((now - started_at))s elapsed)" + last_heartbeat="$now" + fi + sleep "$poll_interval" done diff --git a/k8s/scope/tests/networking/wait_for_alb.bats b/k8s/scope/tests/networking/wait_for_alb.bats index aa53a927..4545f24a 100644 --- a/k8s/scope/tests/networking/wait_for_alb.bats +++ b/k8s/scope/tests/networking/wait_for_alb.bats @@ -109,6 +109,27 @@ mock_aws_state() { assert_contains "$output" " • Verify ALB quota: aws service-quotas get-service-quota --service-code elasticloadbalancing --quota-code L-53DA6B97" } +# ============================================================================= +# Heartbeat +# ============================================================================= +@test "wait_for_alb: emits heartbeat info log when the wait crosses the threshold" { + # Shrink both the poll interval and the heartbeat threshold so the test + # exercises the heartbeat path without sitting through real 30s intervals. + PATCHED_SCRIPT="$BATS_TEST_TMPDIR/wait_for_alb_patched" + sed -e 's/^poll_interval=10$/poll_interval=1/' \ + -e 's/^heartbeat_interval=30$/heartbeat_interval=1/' \ + "$SCRIPT" > "$PATCHED_SCRIPT" + + export ALB_AUTOCREATE_TIMEOUT_SECONDS="3" + mock_aws_state "provisioning" + + run bash -c "source '$PATCHED_SCRIPT'" + + # Times out as expected, but we should see at least one heartbeat info log. + assert_equal "$status" "1" + assert_contains "$output" "⏳ Still waiting for ALB 'test-alb' to become active (provisioning," +} + # ============================================================================= # Tagging on autocreate # ============================================================================= From 8a4c12f898750e574cf7db3f3e01080c22c1ece4 Mon Sep 17 00:00:00 2001 From: Federico Maleh Date: Wed, 10 Jun 2026 13:30:45 -0300 Subject: [PATCH 010/158] fix: generate dummy ingress host via domain-generate so it matches the platform cert --- k8s/scope/networking/autocreate_alb | 42 +++++++++++++++++-- k8s/scope/templates/ingress-dummy.yaml.tpl | 6 +-- .../tests/networking/autocreate_alb.bats | 31 ++++++++++++++ 3 files changed, 71 insertions(+), 8 deletions(-) diff --git a/k8s/scope/networking/autocreate_alb b/k8s/scope/networking/autocreate_alb index 0c2180c4..517e606d 100644 --- a/k8s/scope/networking/autocreate_alb +++ b/k8s/scope/networking/autocreate_alb @@ -102,6 +102,38 @@ register_alb_in_provider() { fi } +# Builds the dummy ingress host via the same domain-generate binary the +# platform uses for scope domains. Substituting scopeSlug with the ALB name +# keeps the host inside whatever wildcard cert/DNS pattern the platform +# already maintains. +generate_dummy_host() { + local alb_name="$1" + + local account_slug namespace_slug application_slug + account_slug=$(echo "$CONTEXT" | jq -r '.account.slug') + namespace_slug=$(echo "$CONTEXT" | jq -r '.namespace.slug') + application_slug=$(echo "$CONTEXT" | jq -r '.application.slug') + + local host + host=$("$SERVICE_PATH/scope/networking/dns/domain/domain-generate" \ + --accountSlug="$account_slug" \ + --namespaceSlug="$namespace_slug" \ + --applicationSlug="$application_slug" \ + --scopeSlug="$alb_name" \ + --domain="$DOMAIN" \ + --useAccountSlug="${USE_ACCOUNT_SLUG:-false}") || { + log error "❌ Failed to generate dummy ingress host via domain-generate" + log error "💡 Possible causes:" + log error " The domain-generate binary returned an error" + log error "🔧 How to fix:" + log error " • Check the domain-generate binary exists: ls -la $SERVICE_PATH/scope/networking/dns/domain/domain-generate" + log error " • Verify the input slugs are valid" + exit 1 + } + + echo "$host" +} + render_dummy_ingress() { local alb_name="$1" local visibility="$2" @@ -113,6 +145,10 @@ render_dummy_ingress() { fi mkdir -p "$OUTPUT_DIR" + local dummy_host + dummy_host=$(generate_dummy_host "$alb_name") + log debug "📋 Dummy ingress host: $dummy_host" + # The context file MUST have a .json extension. gomplate uses the extension # to pick the parser; a plain mktemp path is treated as an opaque string # and the template fails with "can't evaluate field X in type string". @@ -120,14 +156,12 @@ render_dummy_ingress() { context_path="$OUTPUT_DIR/ingress-dummy-${alb_name}-context.json" trap 'rm -f "$context_path"' RETURN - # build_context already exports $DOMAIN (and adds it to CONTEXT as - # `base_domain` after we return). Inject the call-specific fields here. echo "$CONTEXT" | jq \ --arg alb_name "$alb_name" \ --arg ingress_visibility "$visibility" \ --arg k8s_namespace "$namespace" \ - --arg base_domain "$DOMAIN" \ - '. + {alb_name: $alb_name, ingress_visibility: $ingress_visibility, k8s_namespace: $k8s_namespace, base_domain: $base_domain}' \ + --arg dummy_host "$dummy_host" \ + '. + {alb_name: $alb_name, ingress_visibility: $ingress_visibility, k8s_namespace: $k8s_namespace, dummy_host: $dummy_host}' \ > "$context_path" local template_path="${INGRESS_DUMMY_TEMPLATE:-$SERVICE_PATH/scope/templates/ingress-dummy.yaml.tpl}" diff --git a/k8s/scope/templates/ingress-dummy.yaml.tpl b/k8s/scope/templates/ingress-dummy.yaml.tpl index 2ded1e3c..cff2e154 100644 --- a/k8s/scope/templates/ingress-dummy.yaml.tpl +++ b/k8s/scope/templates/ingress-dummy.yaml.tpl @@ -8,9 +8,7 @@ metadata: nullplatform-autocreate: "true" alb_name: {{ .alb_name }} annotations: - alb.ingress.kubernetes.io/actions.response-404: >- - {"type":"fixed-response","fixedResponseConfig":{"contentType":"text/plain","statusCode":"404","messageBody":"404 - scope not found or has not been deployed yet"}} + alb.ingress.kubernetes.io/actions.response-404: '{"type":"fixed-response","fixedResponseConfig":{"contentType":"text/plain","statusCode":"404","messageBody":"404 scope not found or has not been deployed yet"}}' alb.ingress.kubernetes.io/group.name: {{ .alb_name }} alb.ingress.kubernetes.io/listen-ports: '[{"HTTP":80},{"HTTPS":443}]' alb.ingress.kubernetes.io/load-balancer-name: {{ .alb_name }} @@ -20,7 +18,7 @@ metadata: spec: ingressClassName: alb rules: - - host: {{ .alb_name }}.{{ .base_domain }} + - host: {{ .dummy_host }} http: paths: - path: / diff --git a/k8s/scope/tests/networking/autocreate_alb.bats b/k8s/scope/tests/networking/autocreate_alb.bats index f76bdd16..a54111be 100644 --- a/k8s/scope/tests/networking/autocreate_alb.bats +++ b/k8s/scope/tests/networking/autocreate_alb.bats @@ -257,3 +257,34 @@ teardown() { [ -f "$OUTPUT_DIR/ingress-dummy-${ALB_NAME}.yaml" ] } + +# ============================================================================= +# Dummy host generation +# ============================================================================= +@test "autocreate_alb: derives dummy host via domain-generate using the ALB name as scopeSlug" { + # Run with the real domain-generate binary (no mock) — it's deterministic. + # Use a custom gomplate that writes the rendered output through so we can + # inspect the final host. + gomplate() { + local prev="" + for arg in "$@"; do + if [ "$prev" = "--out" ]; then OUT_PATH="$arg"; fi + if [ "$prev" = "-c" ]; then CTX_ARG="$arg"; fi + prev="$arg" + done + # Copy the context json next to the rendered file for assertion access + local ctx_file="${CTX_ARG#.=}" + cp "$ctx_file" "$OUTPUT_DIR/_rendered_context.json" + echo "rendered" > "$OUT_PATH" + return 0 + } + export -f gomplate + + source "$SCRIPT" + + # domain-generate produces "ns-app--.nullapps.io" with the + # slugs taken from CONTEXT.namespace / .application and scopeSlug=$ALB_NAME. + local dummy_host + dummy_host=$(jq -r '.dummy_host' "$OUTPUT_DIR/_rendered_context.json") + [[ "$dummy_host" =~ ^ns-1-app-1-${ALB_NAME}-[a-z0-9]+\.nullapps\.io$ ]] +} From a9dbc6c24675f13eb458f9ecc8f105d15f765497 Mon Sep 17 00:00:00 2001 From: Federico Maleh Date: Wed, 10 Jun 2026 13:43:37 -0300 Subject: [PATCH 011/158] fix: stable 30s heartbeat cadence and trap-safe context cleanup under set -u --- k8s/scope/networking/autocreate_alb | 6 ++++- k8s/scope/networking/wait_for_alb | 24 ++++++++++++-------- k8s/scope/tests/networking/wait_for_alb.bats | 17 ++++++++------ 3 files changed, 29 insertions(+), 18 deletions(-) diff --git a/k8s/scope/networking/autocreate_alb b/k8s/scope/networking/autocreate_alb index 517e606d..2d39adef 100644 --- a/k8s/scope/networking/autocreate_alb +++ b/k8s/scope/networking/autocreate_alb @@ -154,7 +154,11 @@ render_dummy_ingress() { # and the template fails with "can't evaluate field X in type string". local context_path context_path="$OUTPUT_DIR/ingress-dummy-${alb_name}-context.json" - trap 'rm -f "$context_path"' RETURN + # Use double quotes so $context_path is baked into the trap string now. + # Single quotes would defer expansion until the trap fires on RETURN, by + # which point the local variable is out of scope and `set -u` would trip + # with "context_path: unbound variable". + trap "rm -f '$context_path'" RETURN echo "$CONTEXT" | jq \ --arg alb_name "$alb_name" \ diff --git a/k8s/scope/networking/wait_for_alb b/k8s/scope/networking/wait_for_alb index d4aa08bc..573f1f30 100644 --- a/k8s/scope/networking/wait_for_alb +++ b/k8s/scope/networking/wait_for_alb @@ -23,11 +23,15 @@ TIMEOUT_SECONDS=$(get_config_value \ --default "300" ) -started_at=$(date +%s) -deadline=$((started_at + TIMEOUT_SECONDS)) +deadline=$(($(date +%s) + TIMEOUT_SECONDS)) poll_interval=10 -heartbeat_interval=30 -last_heartbeat="$started_at" +polls_per_heartbeat=3 +# Counter-based heartbeat: every Nth poll we emit a progress log. Using a +# counter (instead of wall-clock diff) keeps the displayed elapsed time on +# clean 30s boundaries; otherwise the latency of each AWS call drifts the +# wall-clock heartbeat to odd numbers like 33s or 63s. +polls_since_heartbeat=0 +heartbeats_emitted=0 log info "⏳ Waiting up to ${TIMEOUT_SECONDS}s for ALB '$ALB_NAME' to become active..." @@ -56,12 +60,12 @@ while [ "$(date +%s)" -lt "$deadline" ]; do fi fi - # Heartbeat every ~30s so the operator sees progress on long waits instead - # of staring at a frozen line for the full timeout. - now=$(date +%s) - if [ $((now - last_heartbeat)) -ge "$heartbeat_interval" ]; then - log info "⏳ Still waiting for ALB '$ALB_NAME' to become active (${state:-pending}, $((now - started_at))s elapsed)" - last_heartbeat="$now" + polls_since_heartbeat=$((polls_since_heartbeat + 1)) + if [ "$polls_since_heartbeat" -ge "$polls_per_heartbeat" ]; then + heartbeats_emitted=$((heartbeats_emitted + 1)) + elapsed=$((heartbeats_emitted * polls_per_heartbeat * poll_interval)) + log info "⏳ Still waiting for ALB '$ALB_NAME' to become active (${state:-pending}, ~${elapsed}s elapsed)" + polls_since_heartbeat=0 fi sleep "$poll_interval" diff --git a/k8s/scope/tests/networking/wait_for_alb.bats b/k8s/scope/tests/networking/wait_for_alb.bats index 4545f24a..6fed1b3f 100644 --- a/k8s/scope/tests/networking/wait_for_alb.bats +++ b/k8s/scope/tests/networking/wait_for_alb.bats @@ -112,22 +112,25 @@ mock_aws_state() { # ============================================================================= # Heartbeat # ============================================================================= -@test "wait_for_alb: emits heartbeat info log when the wait crosses the threshold" { - # Shrink both the poll interval and the heartbeat threshold so the test - # exercises the heartbeat path without sitting through real 30s intervals. +@test "wait_for_alb: emits heartbeat info log on clean elapsed boundaries" { + # Shrink the poll interval and the polls-per-heartbeat so the test runs + # in seconds instead of full 30s intervals. With poll_interval=1 and + # polls_per_heartbeat=2, the first heartbeat fires after 2 polls and + # the displayed elapsed is 2*1=2s. PATCHED_SCRIPT="$BATS_TEST_TMPDIR/wait_for_alb_patched" sed -e 's/^poll_interval=10$/poll_interval=1/' \ - -e 's/^heartbeat_interval=30$/heartbeat_interval=1/' \ + -e 's/^polls_per_heartbeat=3$/polls_per_heartbeat=2/' \ "$SCRIPT" > "$PATCHED_SCRIPT" - export ALB_AUTOCREATE_TIMEOUT_SECONDS="3" + export ALB_AUTOCREATE_TIMEOUT_SECONDS="5" mock_aws_state "provisioning" run bash -c "source '$PATCHED_SCRIPT'" - # Times out as expected, but we should see at least one heartbeat info log. + # Times out as expected. We should see at least one heartbeat with a clean + # elapsed multiple (2s, 4s) — never odd numbers like 3s or 5s. assert_equal "$status" "1" - assert_contains "$output" "⏳ Still waiting for ALB 'test-alb' to become active (provisioning," + assert_contains "$output" "⏳ Still waiting for ALB 'test-alb' to become active (provisioning, ~2s elapsed)" } # ============================================================================= From 257a7bcdd8c4f1106cb722fb3956be8f3373a1bb Mon Sep 17 00:00:00 2001 From: Federico Maleh Date: Wed, 10 Jun 2026 16:04:27 -0300 Subject: [PATCH 012/158] fix: gate wait_for_alb on route53, validate inputs, dedupe AWS call, reconcile docs --- CHANGELOG.md | 2 +- k8s/docs/autocreate-alb.md | 54 +++++++++---------- k8s/scope/networking/autocreate_alb | 16 ++++++ k8s/scope/networking/resolve_balancer | 18 +++---- k8s/scope/networking/wait_for_alb | 15 ++++++ .../tests/networking/autocreate_alb.bats | 18 +++++++ k8s/scope/tests/networking/wait_for_alb.bats | 34 ++++++++++++ 7 files changed, 119 insertions(+), 38 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dcfd3a75..14be5dfd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] -- Add opt-in ALB autocreation for k8s scopes: when every declared ALB is at or above `ALB_MAX_CAPACITY`, the platform provisions a new ALB via a dummy Ingress, registers it in the container-orchestration provider, and uses it for the scope. Disabled by default; enable with `ALB_AUTOCREATE_ENABLED=true`. Requires additional AWS permission: `elasticloadbalancing:AddTags` (audit tagging) +- Add opt-in ALB autocreation for k8s scopes: when every declared ALB is at or above `ALB_MAX_CAPACITY`, the platform provisions a new ALB via a dummy Ingress, registers it in the container-orchestration provider via `np provider patch`, and uses it for the scope. Disabled by default; enable with `ALB_AUTOCREATE_ENABLED=true`. Requires write access to the nullplatform API (via `NP_TOKEN` or `NULLPLATFORM_API_KEY`) and the additional AWS permission `elasticloadbalancing:AddTags` for audit tagging ## [1.12.0] - 2026-06-08 - Fix: do not inject file parameter as env vars diff --git a/k8s/docs/autocreate-alb.md b/k8s/docs/autocreate-alb.md index bac8bb3d..a800d2a0 100644 --- a/k8s/docs/autocreate-alb.md +++ b/k8s/docs/autocreate-alb.md @@ -8,7 +8,7 @@ The flow only triggers when **all** of the following are true: - `ALB_AUTOCREATE_ENABLED=true` in `values.yaml` or in the `container-orchestration` provider. - `DNS_TYPE=route53` (autocreation requires the same load-balancing path used by Route53 scopes). -- Every candidate ALB in the pool (declared base + additional balancers + previously autocreated ALBs discovered by tag) reports a rule count `>= ALB_MAX_CAPACITY`. +- Every candidate ALB in the pool (base + additional balancers declared in the provider) reports a rule count `>= ALB_MAX_CAPACITY`. - The scope being created does not already have a Route53 record (a scope being recreated reuses its existing ALB and does not trigger autocreation). If any candidate is below the threshold, the scope creation uses that candidate and the autocreate path is not taken. @@ -18,56 +18,56 @@ If any candidate is below the threshold, the scope creation uses that candidate | Key | Default | Description | |---|---|---| | `ALB_AUTOCREATE_ENABLED` | `false` | Master switch. When `false`, behavior is identical to previous releases. | -| `ALB_AUTOCREATE_NAME_PREFIX` | `nullplatform-auto-` | Prefix for autocreated ALB names. Final name format: `-<6 hex chars>`. Total length must stay below the AWS 32-character ALB name limit. | -| `ALB_AUTOCREATE_TIMEOUT_SECONDS` | `300` | How long the script polls AWS for the new ALB to reach `state=active` before failing the scope creation. The AWS Load Balancer Controller usually takes 2–4 minutes. | +| `ALB_AUTOCREATE_NAME_PREFIX` | `nullplatform-auto-` | Prefix for autocreated ALB names. Final name format: `-<6 hex chars>`. Must match `^[a-z0-9-]+$` and be ≤18 chars so the rendered name stays under the AWS 32-char ALB name limit. | +| `ALB_AUTOCREATE_TIMEOUT_SECONDS` | `300` | How long `wait_for_alb` polls AWS for the new ALB to reach `state=active` before failing the scope creation. The AWS Load Balancer Controller usually takes 2–4 minutes. Must be a positive integer. | All three keys are also readable from `providers.container-orchestration.balancer.{autocreate_enabled, autocreate_name_prefix, autocreate_timeout_seconds}`. ## How it works -1. `resolve_balancer` evaluates the candidate pool (declared + tag-discovered ALBs) and picks the least-loaded one as today. +1. `resolve_balancer` evaluates the candidate pool — the base ALB plus the `additional_public_names` / `additional_private_names` list declared in the `container-orchestration` provider — and picks the least-loaded one. 2. If that candidate's rule count is at or above `ALB_MAX_CAPACITY` and `ALB_AUTOCREATE_ENABLED=true`, `resolve_balancer` sources `autocreate_alb`. -3. `autocreate_alb` generates a unique ALB name, renders `scope/templates/ingress-dummy.yaml.tpl`, and applies it. The AWS Load Balancer Controller picks up the Ingress and provisions the ALB. -4. The script polls `aws elbv2 describe-load-balancers` every 10 seconds until the ALB reports `State.Code=active` (or `failed`/timeout, in which case the scope creation fails). -5. Once active, the script tags the ALB with: - - `nullplatform:managed-by=autocreate` - - `nullplatform:visibility=internet-facing|internal` - - `nullplatform:created-by-scope-id=` -6. `resolve_balancer` substitutes the new ALB name and the rest of the scope creation proceeds. +3. `autocreate_alb` generates a unique ALB name (`-<6 hex>`) and **patches the container-orchestration provider via `np provider patch`** to append the new name to `additional_public_names` or `additional_private_names` (visibility-dependent). The provider is the authoritative registry of ALBs the platform uses. +4. `autocreate_alb` renders `scope/templates/ingress-dummy.yaml.tpl` into `$OUTPUT_DIR/ingress-dummy-.yaml`. The dummy Ingress carries `alb.ingress.kubernetes.io/group.name=` and `alb.ingress.kubernetes.io/load-balancer-name=`, which is what makes the AWS Load Balancer Controller materialize the ALB once the file is applied. +5. The workflow step `apply autocreated ingress` (in `k8s/scope/workflows/create.yaml`) applies whatever templates are in `$OUTPUT_DIR` via the standard `apply_templates` script. Its `post: wait for alb` runs `wait_for_alb`, which polls `aws elbv2 describe-load-balancers` every 10 seconds until the ALB reports `State.Code=active` (or `failed`/timeout, in which case the scope creation fails). An info-level heartbeat is emitted every ~30s so the operator can see progress. +6. Once active, `wait_for_alb` tags the ALB with `nullplatform:managed-by=autocreate`, `nullplatform:visibility=internet-facing|internal`, and `nullplatform:created-by-scope-id=`. **These tags are audit metadata only**, surfacing the lineage of which scope provisioned which ALB. Discovery does NOT depend on these tags. +7. The rest of the scope creation proceeds with `ALB_NAME` set to the new ALB. -## Discovery of previously autocreated ALBs +## How concurrent scope creations behave -Every scope creation queries `resourcegroupstaggingapi:get-resources` for ALBs tagged `nullplatform:managed-by=autocreate` matching the scope's visibility. Discovered ALBs are merged into the candidate pool without any provider configuration change, so a single autocreated ALB serves many subsequent scopes before another autocreation is needed. +When scope A triggers autocreate, the provider is patched **before** the ALB is active. Scope B that starts during this window reads the provider list, sees the new ALB name, and treats it as a normal candidate. AWS will return `LoadBalancerNotFound` for the in-flight ALB during the few seconds before it shows up in the API; `resolve_balancer` interprets that error specifically as "0 rules" so the in-flight ALB wins least-loaded selection in scope B and no second autocreate fires. Scope B then waits on the same ALB via its own `wait_for_alb` step. -Discovery runs regardless of `ALB_AUTOCREATE_ENABLED`: even if the flag is later turned off, previously autocreated ALBs remain usable. +## Required permissions -## Required AWS permissions +In addition to the permissions already required for capacity validation, the autocreate path needs: -In addition to the permissions already required for capacity validation, the agent role needs: +**Nullplatform API credentials.** The script calls `np provider list` and `np provider patch`, so the workflow environment must provide either `NP_TOKEN` or `NULLPLATFORM_API_KEY` with write access to the container-orchestration provider for the relevant NRN. Without these, the patch step fails with `❌ Failed to patch container-orchestration provider with new ALB`. -- `elasticloadbalancing:AddTags` — to tag the new ALB so discovery can find it. -- `elasticloadbalancing:DescribeTags` — for the discovery path (covered by capacity validation in most agents, listed here for completeness). -- `tag:GetResources` — for the `resourcegroupstaggingapi` call used by discovery. +**AWS IAM (agent role).** -The dummy Ingress requires no new K8s permissions beyond those the agent already has for scope resources. +- `elasticloadbalancing:AddTags` — for the audit tags `wait_for_alb` applies once the ALB is active. Failure here is non-fatal (logged as a warning, the scope creation proceeds). + +No new Kubernetes permissions are needed beyond those the agent already has for scope resources. ## Operational notes -- Scope creations that trigger autocreation are slower (typically 2–4 minutes extra). This is the expected behavior, not a regression. The platform logs `🔧 All candidate ALBs are at or above capacity (...); triggering autocreate` when it happens. -- The dummy Ingress (`nullplatform-autocreate-`) is created in the scope's namespace. It exposes no traffic and exists only to keep the ALB alive. Deleting it manually will cause the AWS Load Balancer Controller to delete the ALB. -- The ALB is registered through AWS tags rather than through the nullplatform provider configuration. Two consequences: - 1. The nullplatform provider object does not need to be updated by the script; this avoids requiring API credentials inside the scope workflow. +- Scope creations that trigger autocreation are slower (typically 2–4 minutes extra). This is the expected behavior, not a regression. The platform logs `🔧 Best candidate ALB '...' is at or above capacity (X/Y); triggering autocreate` when it happens, followed by `⏳ Still waiting for ALB '...' to become active (provisioning, ~30s elapsed)` heartbeats while the controller provisions. +- The dummy Ingress (`nullplatform-autocreate-`) is created in the scope's namespace. It exposes no real traffic — the rule points to a fixed `404` response via the standard `alb.ingress.kubernetes.io/actions.response-404` annotation — and exists only to keep the ALB alive in the eyes of the AWS Load Balancer Controller. Deleting the dummy Ingress will cause the controller to delete the ALB. +- The ALB is registered in the nullplatform provider (not in the customer's IaC). Two consequences: + 1. The provider becomes the source of truth for the ALB pool; subsequent scope creations read it directly. 2. The cloud's IaC (Terraform, OpenTofu, CloudFormation) is **not** updated automatically. If your IaC is the source of truth for ALB inventory, you should reconcile autocreated ALBs into it through your own process. ## Failure modes | Failure | Outcome | |---|---| -| Dummy Ingress template render fails | Scope creation exits 1 with `Failed to render ingress-dummy template`. | -| `kubectl apply` fails | Scope creation exits 1 with `Failed to apply ingress-dummy` and prints the namespace check hint. | +| `ALB_AUTOCREATE_NAME_PREFIX` invalid (bad charset or >18 chars) | Scope creation exits 1 with the validation error before any AWS or provider call. | +| `np provider list` cannot find a container-orchestration provider for the NRN | Scope creation exits 1 with `❌ No container-orchestration provider found for NRN ''`. | +| `np provider patch` fails (no API token / no write access) | Scope creation exits 1 with `❌ Failed to patch container-orchestration provider with new ALB` + hint about `NP_TOKEN` / `NULLPLATFORM_API_KEY`. | +| `gomplate` render of the dummy Ingress fails | Scope creation exits 1 with `❌ Failed to render ingress-dummy template`. | | ALB never reaches `active` within `ALB_AUTOCREATE_TIMEOUT_SECONDS` | Scope creation exits 1; check controller logs and AWS quota for ALBs in the region. | | AWS reports the ALB state as `failed` | Scope creation exits 1 immediately. | -| `AddTags` call fails (no IAM permission) | Logged as `⚠️ Could not tag ALB; subsequent discovery may not find it`. The scope creation continues; the next creation will not find this ALB by tag and may autocreate another one. | +| `AddTags` call fails (no IAM permission) | Logged as `⚠️ Could not tag ALB '' (audit only — provider registration already succeeded)`. The scope creation continues; the tags are documentation only. | ## What is out of scope diff --git a/k8s/scope/networking/autocreate_alb b/k8s/scope/networking/autocreate_alb index 2d39adef..935904dc 100644 --- a/k8s/scope/networking/autocreate_alb +++ b/k8s/scope/networking/autocreate_alb @@ -190,6 +190,22 @@ NAME_PREFIX=$(get_config_value \ --default "nullplatform-auto-" ) +# Final ALB name is "-<6 hex>". AWS rejects names that +# exceed 32 chars or contain anything outside [a-zA-Z0-9-]. If an invalid name +# slips through, the AWS Load Balancer Controller silently refuses to create +# the ALB and wait_for_alb hangs to timeout with an opaque error. Catch it +# here with a clear message instead. +if ! [[ "$NAME_PREFIX" =~ ^[a-z0-9-]+$ ]]; then + log error "❌ ALB_AUTOCREATE_NAME_PREFIX must match ^[a-z0-9-]+$, got: '$NAME_PREFIX'" + exit 1 +fi + +# 14 = len("private-") + 6 hex chars; total must stay ≤32 (AWS ALB name limit) +if [ "${#NAME_PREFIX}" -gt 18 ]; then + log error "❌ ALB_AUTOCREATE_NAME_PREFIX must be ≤18 chars (AWS caps ALB names at 32, the visibility+hex suffix uses 14); got ${#NAME_PREFIX}" + exit 1 +fi + NEW_ALB_NAME=$(generate_alb_name "$NAME_PREFIX" "$INGRESS_VISIBILITY") log info "🔧 Autocreating ALB '$NEW_ALB_NAME' (visibility=$INGRESS_VISIBILITY)" diff --git a/k8s/scope/networking/resolve_balancer b/k8s/scope/networking/resolve_balancer index e2ef333f..88e46bb4 100755 --- a/k8s/scope/networking/resolve_balancer +++ b/k8s/scope/networking/resolve_balancer @@ -37,16 +37,20 @@ _RESOLVE_BALANCER_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" get_alb_rule_count() { local alb_name="$1" - local alb_arn aws_stderr aws_exit - aws_stderr=$(aws elbv2 describe-load-balancers \ + # Single AWS call: capture stdout+stderr together. On success stdout has the + # ARN; on failure stderr has the error (we case-match LoadBalancerNotFound + # for the autocreate race). Avoids two `describe-load-balancers` calls per + # candidate per scope creation. + local alb_arn aws_exit + alb_arn=$(aws elbv2 describe-load-balancers \ --names "$alb_name" \ --region "$REGION" \ --query 'LoadBalancers[0].LoadBalancerArn' \ - --output text 2>&1 >/dev/null) + --output text 2>&1) aws_exit=$? if [ "$aws_exit" -ne 0 ]; then - case "$aws_stderr" in + case "$alb_arn" in *LoadBalancerNotFound*) # Concurrent autocreate race: the ALB was just registered in the # provider by another scope but is not yet visible to AWS APIs. Return @@ -61,12 +65,6 @@ get_alb_rule_count() { return 1 fi - alb_arn=$(aws elbv2 describe-load-balancers \ - --names "$alb_name" \ - --region "$REGION" \ - --query 'LoadBalancers[0].LoadBalancerArn' \ - --output text 2>/dev/null) - if [ -z "$alb_arn" ] || [ "$alb_arn" = "None" ]; then return 1 fi diff --git a/k8s/scope/networking/wait_for_alb b/k8s/scope/networking/wait_for_alb index 573f1f30..dda06a02 100644 --- a/k8s/scope/networking/wait_for_alb +++ b/k8s/scope/networking/wait_for_alb @@ -17,12 +17,27 @@ # ALB_AUTOCREATE_TIMEOUT_SECONDS - Max seconds to wait (default 300) # CONTEXT - For scope-id in the tag value +# Step gating: only block on ALB readiness for the path that actually relies +# on it — route53 scopes that manage ALBs via the AWS Load Balancer Controller. +# Other DNS types (azure, external_dns) provision a different networking stack +# and would never see the ALB transition to `active`, so the wait would always +# time out and fail the scope creation. +if [ "${DNS_TYPE:-}" != "route53" ]; then + log debug "📋 DNS type is '${DNS_TYPE:-unset}', skipping ALB active-state wait" + return 0 2>/dev/null || exit 0 +fi + TIMEOUT_SECONDS=$(get_config_value \ --env ALB_AUTOCREATE_TIMEOUT_SECONDS \ --provider '.providers["container-orchestration"].balancer.autocreate_timeout_seconds' \ --default "300" ) +if ! [[ "$TIMEOUT_SECONDS" =~ ^[1-9][0-9]*$ ]]; then + log error "❌ ALB_AUTOCREATE_TIMEOUT_SECONDS must be a positive integer, got: '$TIMEOUT_SECONDS'" + exit 1 +fi + deadline=$(($(date +%s) + TIMEOUT_SECONDS)) poll_interval=10 polls_per_heartbeat=3 diff --git a/k8s/scope/tests/networking/autocreate_alb.bats b/k8s/scope/tests/networking/autocreate_alb.bats index a54111be..2f0f7d06 100644 --- a/k8s/scope/tests/networking/autocreate_alb.bats +++ b/k8s/scope/tests/networking/autocreate_alb.bats @@ -261,6 +261,24 @@ teardown() { # ============================================================================= # Dummy host generation # ============================================================================= +@test "autocreate_alb: rejects ALB_AUTOCREATE_NAME_PREFIX with invalid chars (uppercase)" { + export ALB_AUTOCREATE_NAME_PREFIX="Bad-Prefix-" + + run bash -c 'source "$SCRIPT"' + + assert_equal "$status" "1" + assert_contains "$output" "❌ ALB_AUTOCREATE_NAME_PREFIX must match ^[a-z0-9-]+\$, got: 'Bad-Prefix-'" +} + +@test "autocreate_alb: rejects ALB_AUTOCREATE_NAME_PREFIX longer than 18 chars" { + export ALB_AUTOCREATE_NAME_PREFIX="this-prefix-is-far-too-long-" + + run bash -c 'source "$SCRIPT"' + + assert_equal "$status" "1" + assert_contains "$output" "❌ ALB_AUTOCREATE_NAME_PREFIX must be ≤18 chars" +} + @test "autocreate_alb: derives dummy host via domain-generate using the ALB name as scopeSlug" { # Run with the real domain-generate binary (no mock) — it's deterministic. # Use a custom gomplate that writes the rendered output through so we can diff --git a/k8s/scope/tests/networking/wait_for_alb.bats b/k8s/scope/tests/networking/wait_for_alb.bats index 6fed1b3f..16118154 100644 --- a/k8s/scope/tests/networking/wait_for_alb.bats +++ b/k8s/scope/tests/networking/wait_for_alb.bats @@ -17,6 +17,7 @@ setup() { export REGION="us-east-1" export ALB_NAME="test-alb" export INGRESS_VISIBILITY="internet-facing" + export DNS_TYPE="route53" export ALB_AUTOCREATE_TIMEOUT_SECONDS="2" export CONTEXT='{ @@ -161,6 +162,39 @@ mock_aws_state() { [[ "$output" != *"Could not tag ALB"* ]] } +@test "wait_for_alb: early returns for DNS_TYPE != route53 without polling" { + export DNS_TYPE="external_dns" + # If the polling code ran, the default `aws()` returning 1 would loop until + # timeout (2s) and exit 1. The early-return must skip that entirely. + aws() { echo "AWS SHOULD NOT BE CALLED" >&2; return 1; } + export -f aws + + run bash -c 'source "$SCRIPT"' + + assert_equal "$status" "0" + assert_contains "$output" "📋 DNS type is 'external_dns', skipping ALB active-state wait" + [[ "$output" != *"AWS SHOULD NOT BE CALLED"* ]] + [[ "$output" != *"Waiting up to"* ]] +} + +@test "wait_for_alb: exits with validation error when ALB_AUTOCREATE_TIMEOUT_SECONDS is non-numeric" { + export ALB_AUTOCREATE_TIMEOUT_SECONDS="not-a-number" + + run bash -c 'source "$SCRIPT"' + + assert_equal "$status" "1" + assert_contains "$output" "❌ ALB_AUTOCREATE_TIMEOUT_SECONDS must be a positive integer, got: 'not-a-number'" +} + +@test "wait_for_alb: exits with validation error when ALB_AUTOCREATE_TIMEOUT_SECONDS is zero" { + export ALB_AUTOCREATE_TIMEOUT_SECONDS="0" + + run bash -c 'source "$SCRIPT"' + + assert_equal "$status" "1" + assert_contains "$output" "❌ ALB_AUTOCREATE_TIMEOUT_SECONDS must be a positive integer, got: '0'" +} + @test "wait_for_alb: tag failure logs full warn message but exits 0" { export ALB_AUTOCREATED="true" local arn="arn:aws:elasticloadbalancing:us-east-1:123:loadbalancer/app/$ALB_NAME/abc" From a078c5167b76c876ae7535b3d5ab93cf4b322070 Mon Sep 17 00:00:00 2001 From: Federico Maleh Date: Wed, 10 Jun 2026 17:33:27 -0300 Subject: [PATCH 013/158] docs(changelog): shorten autocreate entry to one-liner client summary --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 14be5dfd..443e82bf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] -- Add opt-in ALB autocreation for k8s scopes: when every declared ALB is at or above `ALB_MAX_CAPACITY`, the platform provisions a new ALB via a dummy Ingress, registers it in the container-orchestration provider via `np provider patch`, and uses it for the scope. Disabled by default; enable with `ALB_AUTOCREATE_ENABLED=true`. Requires write access to the nullplatform API (via `NP_TOKEN` or `NULLPLATFORM_API_KEY`) and the additional AWS permission `elasticloadbalancing:AddTags` for audit tagging +- Add support to auto-create ALBs on scope create ## [1.12.0] - 2026-06-08 - Fix: do not inject file parameter as env vars From 47c98c29c56886cedc409d9fe73970eb53769c48 Mon Sep 17 00:00:00 2001 From: Federico Maleh Date: Tue, 16 Jun 2026 12:42:44 -0300 Subject: [PATCH 014/158] feat(wait_for_alb): name the missing IAM permission in tag-failure warn --- k8s/scope/networking/wait_for_alb | 8 +++++--- k8s/scope/tests/networking/wait_for_alb.bats | 5 +++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/k8s/scope/networking/wait_for_alb b/k8s/scope/networking/wait_for_alb index dda06a02..0909f39a 100644 --- a/k8s/scope/networking/wait_for_alb +++ b/k8s/scope/networking/wait_for_alb @@ -97,8 +97,9 @@ if [ "$state" != "active" ]; then fi # Audit tags — only on the scope that triggered the autocreate, so the cloud -# carries the lineage of which scope created which ALB. Discovery does not -# depend on these tags. +# carries the lineage of which scope created which ALB. Failure is non-fatal: +# the provider registration (the authoritative source) already succeeded; the +# tags are documentation only. if [ "${ALB_AUTOCREATED:-false}" = "true" ]; then scope_id=$(echo "$CONTEXT" | jq -r '.scope.id // "unknown"') if ! aws elbv2 add-tags \ @@ -109,7 +110,8 @@ if [ "${ALB_AUTOCREATED:-false}" = "true" ]; then "Key=nullplatform:visibility,Value=$INGRESS_VISIBILITY" \ "Key=nullplatform:created-by-scope-id,Value=$scope_id" \ >/dev/null 2>&1; then - log warn "⚠️ Could not tag ALB '$ALB_NAME' (audit only — provider registration already succeeded)" + log warn "⚠️ Could not tag ALB '$ALB_NAME' (audit only — provider registration already succeeded, continuing)" + log warn "💡 The agent role needs the IAM permission 'elasticloadbalancing:AddTags' on Application Load Balancers in region '$REGION' to write the audit tags (nullplatform:managed-by, nullplatform:visibility, nullplatform:created-by-scope-id)" else log debug "📋 Tagged ALB '$ALB_NAME' with managed-by=autocreate" fi diff --git a/k8s/scope/tests/networking/wait_for_alb.bats b/k8s/scope/tests/networking/wait_for_alb.bats index 16118154..db2492c8 100644 --- a/k8s/scope/tests/networking/wait_for_alb.bats +++ b/k8s/scope/tests/networking/wait_for_alb.bats @@ -195,7 +195,7 @@ mock_aws_state() { assert_contains "$output" "❌ ALB_AUTOCREATE_TIMEOUT_SECONDS must be a positive integer, got: '0'" } -@test "wait_for_alb: tag failure logs full warn message but exits 0" { +@test "wait_for_alb: tag failure logs warn with required IAM permission but exits 0" { export ALB_AUTOCREATED="true" local arn="arn:aws:elasticloadbalancing:us-east-1:123:loadbalancer/app/$ALB_NAME/abc" eval "aws() { @@ -214,5 +214,6 @@ mock_aws_state() { assert_equal "$status" "0" assert_contains "$output" "✅ ALB 'test-alb' is active" - assert_contains "$output" "⚠️ Could not tag ALB 'test-alb' (audit only — provider registration already succeeded)" + assert_contains "$output" "⚠️ Could not tag ALB 'test-alb' (audit only — provider registration already succeeded, continuing)" + assert_contains "$output" "💡 The agent role needs the IAM permission 'elasticloadbalancing:AddTags' on Application Load Balancers in region 'us-east-1' to write the audit tags (nullplatform:managed-by, nullplatform:visibility, nullplatform:created-by-scope-id)" } From 6ab81563f7644ce611c9119a1af51e7bc17563b5 Mon Sep 17 00:00:00 2001 From: Ignacio Boudgouste Date: Fri, 13 Feb 2026 14:04:36 -0300 Subject: [PATCH 015/158] hotfix: change iteration --- CHANGELOG.md | 3 +++ k8s/deployment/wait_deployment_active | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b20b0754..081db745 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,9 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [1.10.1] - 2026-02-13 +- Hotfix on wait_deployment_iteration + ## [1.10.0] - 2026-01-14 - Add support to configure the traffic manager nginx through a configmap. - Add **k8s/diagnose** documentation && new checks diff --git a/k8s/deployment/wait_deployment_active b/k8s/deployment/wait_deployment_active index ab5186f3..2789ee3f 100755 --- a/k8s/deployment/wait_deployment_active +++ b/k8s/deployment/wait_deployment_active @@ -7,7 +7,7 @@ LATEST_TIMESTAMP="" SKIP_DEPLOYMENT_STATUS_CHECK="${SKIP_DEPLOYMENT_STATUS_CHECK:=false}" while true; do - ((iteration++)) + ((++iteration)) if [ $iteration -gt $MAX_ITERATIONS ]; then echo "ERROR: Timeout waiting for deployment. Maximum iterations (${MAX_ITERATIONS}) reached." From 2353a528fd34665ff1ed8a61f28439c04ac8cd43 Mon Sep 17 00:00:00 2001 From: David Fernandez Date: Wed, 18 Mar 2026 12:42:34 -0300 Subject: [PATCH 016/158] fix(CLIEN-688): normalize aarch64 arch name for Linux ARM64 support uname -m returns 'aarch64' on Linux ARM64 but the Go binaries are built as 'exec-arm64'. Normalize the value before building the binary path so the correct binary is selected on ARM64 nodes. Also add .worktrees/ to .gitignore. Co-Authored-By: el gallo Claudio --- .gitignore | 5 ++++- k8s/log/log | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index dc24eb3e..e285378d 100644 --- a/.gitignore +++ b/.gitignore @@ -134,4 +134,7 @@ dist .idea k8s/output np-agent-manifest.yaml -.minikube_mount_pid \ No newline at end of file +.minikube_mount_pid + +# Git worktrees +.worktrees/ \ No newline at end of file diff --git a/k8s/log/log b/k8s/log/log index 2652f0af..e4498b18 100644 --- a/k8s/log/log +++ b/k8s/log/log @@ -2,6 +2,8 @@ PLATFORM=$(uname | tr '[:upper:]' '[:lower:]') ARCH=$(uname -m) +# Normalize aarch64 (Linux ARM64) to arm64 (Go build convention) +[ "$ARCH" = "aarch64" ] && ARCH="arm64" KUBE_LOGGER_SCRIPT="$SERVICE_PATH/log/kube-logger-go/bin/$PLATFORM/exec-$ARCH" From 41ad8136c546f319076cf25753a44dd7af89d749 Mon Sep 17 00:00:00 2001 From: David Fernandez Date: Wed, 18 Mar 2026 12:49:11 -0300 Subject: [PATCH 017/158] build(CLIEN-688): add linux/arm64 binary and rebuild linux binaries Co-Authored-By: el gallo Claudio --- k8s/log/kube-logger-go/bin/linux/exec-amd64 | Bin 0 -> 25026744 bytes k8s/log/kube-logger-go/bin/linux/exec-arm64 | Bin 0 -> 23527608 bytes k8s/log/kube-logger-go/bin/linux/exec-x86_64 | Bin 25055416 -> 25026744 bytes 3 files changed, 0 insertions(+), 0 deletions(-) create mode 100755 k8s/log/kube-logger-go/bin/linux/exec-amd64 create mode 100755 k8s/log/kube-logger-go/bin/linux/exec-arm64 diff --git a/k8s/log/kube-logger-go/bin/linux/exec-amd64 b/k8s/log/kube-logger-go/bin/linux/exec-amd64 new file mode 100755 index 0000000000000000000000000000000000000000..21a4dd3ed245fa7f3813717cb7ae2c33d5d27b05 GIT binary patch literal 25026744 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 Q<+s#o7jBYQn4wsAm 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