From bda35541bb87a8dcc40054b642e783f731bb21e6 Mon Sep 17 00:00:00 2001 From: Javi Date: Fri, 19 Dec 2025 16:09:10 -0300 Subject: [PATCH 01/20] feat: endpoint exposer feat: implement external dns and httproute feat: change logic to get specification id feat: add switch for different dns types feat: add switch for different dns types feat: add endpoint exposer service specs feat: add domain editable feat: add domain editable feat: implement new route schema feat: implement new route schema feat: implement new route schema feat: implement new route schema feat: implement new route schema feat: implement new route schema fix: get scope fix: get scope fix: path fix: get httproute if exists fix: get httproute if exists fix: get httproute rules feat: implement echo for link and unlink feat: implement echo for link and unlink feat: implement echo for link and unlink feat: implement echo for link and unlink feat: implement echo for link and unlink chore: change service slug feat: update flow feat: update flow feat: update flow feat: update flow feat: update flow feat: update flow feat: update flow feat: update flow feat: update flow feat: accept prefix and reg ex --- .gitignore | 3 + endpoint-exposer/configure | 162 ++++++++ .../deployment/sync_exposer | 134 +++++++ .../deployment/workflows/blue_green.yaml | 5 + .../deployment/workflows/delete.yaml | 5 + .../deployment/workflows/finalize.yaml | 5 + .../deployment/workflows/initial.yaml | 5 + .../deployment/workflows/rollback.yaml | 5 + .../deployment/workflows/switch_traffic.yaml | 5 + .../container-scope-override/values.yaml | 3 + endpoint-exposer/entrypoint/entrypoint | 57 +++ endpoint-exposer/entrypoint/link | 34 ++ endpoint-exposer/entrypoint/service | 28 ++ endpoint-exposer/examples/create-link.json | 65 ++++ endpoint-exposer/examples/create.json | 64 ++++ endpoint-exposer/examples/delete-link.json | 71 ++++ endpoint-exposer/examples/delete.json | 50 +++ endpoint-exposer/examples/read.json | 50 +++ endpoint-exposer/examples/refresh.json | 61 +++ endpoint-exposer/scripts/alb/apply | 25 ++ endpoint-exposer/scripts/alb/build_context | 36 ++ endpoint-exposer/scripts/alb/build_ingress | 22 ++ .../scripts/alb/build_ingress_with_rule | 199 ++++++++++ .../scripts/alb/build_ingress_without_rule | 47 +++ endpoint-exposer/scripts/alb/build_rule | 22 ++ .../scripts/alb/fetch_provider_data | 22 ++ endpoint-exposer/scripts/alb/read_ingress | 5 + endpoint-exposer/scripts/alb/update_service | 21 + .../scripts/alb/validate_unique_rule | 12 + endpoint-exposer/scripts/common/echo | 3 + endpoint-exposer/scripts/dns/build_dns | 15 + .../scripts/dns/build_dns_endpoint | 42 ++ endpoint-exposer/scripts/istio/apply | 25 ++ endpoint-exposer/scripts/istio/build_context | 45 +++ endpoint-exposer/scripts/istio/build_ingress | 22 ++ .../scripts/istio/build_ingress_with_rule | 361 ++++++++++++++++++ ...ld_ingress_with_rule_virtualservice_backup | 278 ++++++++++++++ .../scripts/istio/build_ingress_without_rule | 62 +++ endpoint-exposer/scripts/istio/build_rule | 179 +++++++++ .../scripts/istio/clean_httproute_rules | 30 ++ .../scripts/istio/fetch_httproute | 45 +++ .../scripts/istio/fetch_provider_data | 22 ++ endpoint-exposer/scripts/istio/process_routes | 118 ++++++ endpoint-exposer/scripts/istio/read_ingress | 5 + .../scripts/istio/update_httproute_hostname | 29 ++ endpoint-exposer/scripts/istio/update_service | 21 + .../scripts/istio/validate_unique_rule | 12 + endpoint-exposer/specs/actions/read.json.tpl | 25 ++ endpoint-exposer/specs/link-spec.json.tpl | 28 ++ endpoint-exposer/specs/links/refresh.json.tpl | 25 ++ endpoint-exposer/specs/service-spec.json.tpl | 138 +++++++ endpoint-exposer/templates/alb/empty.yaml.tpl | 32 ++ .../templates/istio/dns-endpoint.yaml.tpl | 16 + .../templates/istio/empty.yaml.tpl | 24 ++ endpoint-exposer/values.yaml | 2 + endpoint-exposer/workflows/alb/create.yaml | 44 +++ endpoint-exposer/workflows/alb/delete.yaml | 6 + endpoint-exposer/workflows/alb/link.yaml | 56 +++ endpoint-exposer/workflows/alb/read.yaml | 32 ++ endpoint-exposer/workflows/alb/refresh.yaml | 7 + endpoint-exposer/workflows/alb/unlink.yaml | 47 +++ endpoint-exposer/workflows/istio/create.yaml | 56 +++ endpoint-exposer/workflows/istio/delete.yaml | 6 + endpoint-exposer/workflows/istio/link.yaml | 6 + endpoint-exposer/workflows/istio/read.yaml | 32 ++ endpoint-exposer/workflows/istio/refresh.yaml | 7 + endpoint-exposer/workflows/istio/unlink.yaml | 6 + endpoint-exposer/workflows/istio/update.yaml | 60 +++ 68 files changed, 3192 insertions(+) create mode 100755 endpoint-exposer/configure create mode 100755 endpoint-exposer/container-scope-override/deployment/sync_exposer create mode 100644 endpoint-exposer/container-scope-override/deployment/workflows/blue_green.yaml create mode 100644 endpoint-exposer/container-scope-override/deployment/workflows/delete.yaml create mode 100644 endpoint-exposer/container-scope-override/deployment/workflows/finalize.yaml create mode 100644 endpoint-exposer/container-scope-override/deployment/workflows/initial.yaml create mode 100644 endpoint-exposer/container-scope-override/deployment/workflows/rollback.yaml create mode 100644 endpoint-exposer/container-scope-override/deployment/workflows/switch_traffic.yaml create mode 100644 endpoint-exposer/container-scope-override/values.yaml create mode 100755 endpoint-exposer/entrypoint/entrypoint create mode 100755 endpoint-exposer/entrypoint/link create mode 100755 endpoint-exposer/entrypoint/service create mode 100644 endpoint-exposer/examples/create-link.json create mode 100644 endpoint-exposer/examples/create.json create mode 100644 endpoint-exposer/examples/delete-link.json create mode 100644 endpoint-exposer/examples/delete.json create mode 100644 endpoint-exposer/examples/read.json create mode 100644 endpoint-exposer/examples/refresh.json create mode 100644 endpoint-exposer/scripts/alb/apply create mode 100644 endpoint-exposer/scripts/alb/build_context create mode 100644 endpoint-exposer/scripts/alb/build_ingress create mode 100644 endpoint-exposer/scripts/alb/build_ingress_with_rule create mode 100644 endpoint-exposer/scripts/alb/build_ingress_without_rule create mode 100644 endpoint-exposer/scripts/alb/build_rule create mode 100755 endpoint-exposer/scripts/alb/fetch_provider_data create mode 100644 endpoint-exposer/scripts/alb/read_ingress create mode 100644 endpoint-exposer/scripts/alb/update_service create mode 100644 endpoint-exposer/scripts/alb/validate_unique_rule create mode 100755 endpoint-exposer/scripts/common/echo create mode 100755 endpoint-exposer/scripts/dns/build_dns create mode 100755 endpoint-exposer/scripts/dns/build_dns_endpoint create mode 100644 endpoint-exposer/scripts/istio/apply create mode 100644 endpoint-exposer/scripts/istio/build_context create mode 100644 endpoint-exposer/scripts/istio/build_ingress create mode 100755 endpoint-exposer/scripts/istio/build_ingress_with_rule create mode 100644 endpoint-exposer/scripts/istio/build_ingress_with_rule_virtualservice_backup create mode 100644 endpoint-exposer/scripts/istio/build_ingress_without_rule create mode 100644 endpoint-exposer/scripts/istio/build_rule create mode 100755 endpoint-exposer/scripts/istio/clean_httproute_rules create mode 100755 endpoint-exposer/scripts/istio/fetch_httproute create mode 100755 endpoint-exposer/scripts/istio/fetch_provider_data create mode 100755 endpoint-exposer/scripts/istio/process_routes create mode 100644 endpoint-exposer/scripts/istio/read_ingress create mode 100755 endpoint-exposer/scripts/istio/update_httproute_hostname create mode 100644 endpoint-exposer/scripts/istio/update_service create mode 100644 endpoint-exposer/scripts/istio/validate_unique_rule create mode 100644 endpoint-exposer/specs/actions/read.json.tpl create mode 100644 endpoint-exposer/specs/link-spec.json.tpl create mode 100644 endpoint-exposer/specs/links/refresh.json.tpl create mode 100644 endpoint-exposer/specs/service-spec.json.tpl create mode 100644 endpoint-exposer/templates/alb/empty.yaml.tpl create mode 100644 endpoint-exposer/templates/istio/dns-endpoint.yaml.tpl create mode 100644 endpoint-exposer/templates/istio/empty.yaml.tpl create mode 100644 endpoint-exposer/values.yaml create mode 100644 endpoint-exposer/workflows/alb/create.yaml create mode 100644 endpoint-exposer/workflows/alb/delete.yaml create mode 100644 endpoint-exposer/workflows/alb/link.yaml create mode 100644 endpoint-exposer/workflows/alb/read.yaml create mode 100644 endpoint-exposer/workflows/alb/refresh.yaml create mode 100644 endpoint-exposer/workflows/alb/unlink.yaml create mode 100644 endpoint-exposer/workflows/istio/create.yaml create mode 100644 endpoint-exposer/workflows/istio/delete.yaml create mode 100644 endpoint-exposer/workflows/istio/link.yaml create mode 100644 endpoint-exposer/workflows/istio/read.yaml create mode 100644 endpoint-exposer/workflows/istio/refresh.yaml create mode 100644 endpoint-exposer/workflows/istio/unlink.yaml create mode 100644 endpoint-exposer/workflows/istio/update.yaml diff --git a/.gitignore b/.gitignore index 4f27a85..4c3570f 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,6 @@ *.iml out gen + +# VSCode project files +.vscode/ \ No newline at end of file diff --git a/endpoint-exposer/configure b/endpoint-exposer/configure new file mode 100755 index 0000000..380957d --- /dev/null +++ b/endpoint-exposer/configure @@ -0,0 +1,162 @@ +#!/bin/bash + +set -euo pipefail + +# Colors +GREEN="\033[0;32m" +BLUE="\033[0;34m" +YELLOW="\033[1;33m" +RED="\033[0;31m" +NC="\033[0m" + +# Spinner state +SPINNER_PID="" +SPINNER_MSG="" + +start_spinner() { + SPINNER_MSG="$1" + echo -ne "${BLUE}==>${NC} $SPINNER_MSG..." + ( + while true; do + for c in / - \\ \|; do + echo -ne "\r${BLUE}==>${NC} $SPINNER_MSG... $c" + sleep 0.1 + done + done + ) & + SPINNER_PID=$! + disown +} + +stop_spinner_success() { + kill "$SPINNER_PID" >/dev/null 2>&1 || true + wait "$SPINNER_PID" 2>/dev/null || true + echo -ne "\r\033[K" + echo -e "${GREEN}✔${NC} $SPINNER_MSG" +} + +stop_spinner_error() { + kill "$SPINNER_PID" >/dev/null 2>&1 || true + wait "$SPINNER_PID" 2>/dev/null || true + echo -ne "\r\033[K" + echo -e "${RED}✖${NC} $SPINNER_MSG" + exit 1 +} + +# --- Step 1: Environment Validation --- + +start_spinner "Validating that the NRN has been loaded into the environment." +if [ -z "${NRN:-}" ]; then + stop_spinner_error "NRN is not set. Please export the NRN environment variable before running this script." +fi +stop_spinner_success "NRN found and loaded successfully." + +start_spinner "Validating that the ENVIRONMENT has been loaded into the environment." +if [ -z "${ENVIRONMENT:-}" ]; then + stop_spinner_error "ENVIRONMENT is not set. Please export the ENVIRONMENT environment variable before running this script." +fi +stop_spinner_success "ENVIRONMENT found and loaded successfully." + +start_spinner "Validating that the REPO_PATH has been loaded into the environment." +if [ -z "${REPO_PATH:-}" ]; then + stop_spinner_error "REPO_PATH is not set. Please export the REPO_PATH environment variable before running this script." +fi +stop_spinner_success "REPO_PATH found and loaded successfully." + +# --- Step 2: Generate and Create Service Specification --- + +SERVICE_SPEC_PATH="specs/service-spec.json" +LINK_SPEC_PATH="specs/link-spec.json" +LINK_ACTION_DIR="specs/link-actions" +SERVICE_ACTION_DIR="specs/service-actions" + +gomplate --file "$SERVICE_SPEC_PATH.tpl" --out "$SERVICE_SPEC_PATH" + +start_spinner "Creating the service specification in the platform." +{ + SERVICE_SPEC_BODY=$(cat "$SERVICE_SPEC_PATH") + SERVICE_SPEC=$(np service specification create --body "$SERVICE_SPEC_BODY" --format json) + SERVICE_SPECIFICATION_ID=$(echo "$SERVICE_SPEC" | jq -r .id) + SERVICE_SLUG=$(echo "$SERVICE_SPEC" | jq -r .slug) +} || stop_spinner_error "Failed to create or parse the service specification." +stop_spinner_success "Service specification created successfully (id=$SERVICE_SPECIFICATION_ID, slug=$SERVICE_SLUG)." + +rm "$SERVICE_SPEC_PATH" +export SERVICE_SPECIFICATION_ID +export SERVICE_SLUG + +# --- Step 3: Generate and Create Link Specification --- +gomplate --file "$LINK_SPEC_PATH.tpl" --out "$LINK_SPEC_PATH" + +start_spinner "Creating the link specification in the platform." +{ + LINK_SPEC_BODY=$(cat "$LINK_SPEC_PATH") + LINK_SPEC=$(np link specification create --body "$LINK_SPEC_BODY" --format json) + LINK_SPECIFICATION_ID=$(echo "$LINK_SPEC" | jq -r .id) + LINK_SLUG=$(echo "$LINK_SPEC" | jq -r .slug) +} || stop_spinner_error "Failed to create or parse the service specification." +stop_spinner_success "Link specification created successfully (id=$LINK_SPECIFICATION_ID, slug=$LINK_SLUG)." + +rm "$LINK_SPEC_PATH" +export LINK_SPECIFICATION_ID +export LINK_SLUG + +# --- Step 4: Create Action Specifications --- + +find "$LINK_ACTION_DIR" -type f -name "*.tpl" | while read -r TEMPLATE_FILE; do + REL_PATH="${TEMPLATE_FILE#$LINK_ACTION_DIR/}" + OUTPUT_PATH="$LINK_ACTION_DIR/${REL_PATH%.tpl}" + + gomplate --file "$TEMPLATE_FILE" --out "$OUTPUT_PATH" + + ACTION_SPEC_BODY=$(cat "$OUTPUT_PATH") + + start_spinner "Registering action specification: ${REL_PATH%.json.tpl}." + { + ACTION_SPEC=$(np link specification action specification create \ + --linkSpecificationId "$LINK_SPECIFICATION_ID" \ + --body "$ACTION_SPEC_BODY" \ + --format json) + ACTION_SPEC_ID=$(echo "$ACTION_SPEC" | jq -r .id) + } || stop_spinner_error "Failed to create action specification: $REL_PATH." + + rm "$OUTPUT_PATH" + stop_spinner_success "Action specification created successfully (id=$ACTION_SPEC_ID)." +done + +find "$SERVICE_ACTION_DIR" -type f -name "*.tpl" | while read -r TEMPLATE_FILE; do + REL_PATH="${TEMPLATE_FILE#$SERVICE_ACTION_DIR/}" + OUTPUT_PATH="$SERVICE_ACTION_DIR/${REL_PATH%.tpl}" + + gomplate --file "$TEMPLATE_FILE" --out "$OUTPUT_PATH" + + ACTION_SPEC_BODY=$(cat "$OUTPUT_PATH") + + start_spinner "Registering action specification: ${REL_PATH%.json.tpl}." + { + ACTION_SPEC=$(np service specification action specification create \ + --serviceSpecificationId "$SERVICE_SPECIFICATION_ID" \ + --body "$ACTION_SPEC_BODY" \ + --format json) + ACTION_SPEC_ID=$(echo "$ACTION_SPEC" | jq -r .id) + } || stop_spinner_error "Failed to create action specification: $REL_PATH." + + rm "$OUTPUT_PATH" + stop_spinner_success "Action specification created successfully (id=$ACTION_SPEC_ID)." +done + +# --- Step 5: Create Notification Channel --- + +NOTIFICATION_CHANNEL_PATH="specs/notification-channel.json" + +gomplate --file "$NOTIFICATION_CHANNEL_PATH.tpl" --out "$NOTIFICATION_CHANNEL_PATH" + +start_spinner "Creating the notification channel." +{ +NOTIFICATION_CHANNEL_BODY=$(cat "$NOTIFICATION_CHANNEL_PATH") +NOTIFICATION_CHANNEL=$(np notification channel create --format json --body "$NOTIFICATION_CHANNEL_BODY") +NOTIFICATION_CHANNEL_ID=$(echo "$NOTIFICATION_CHANNEL" | jq -r .id) +} || stop_spinner_error "Failed to create the notification channel." + +rm "$NOTIFICATION_CHANNEL_PATH" +stop_spinner_success "Notification channel created successfully (id=$NOTIFICATION_CHANNEL_ID)." diff --git a/endpoint-exposer/container-scope-override/deployment/sync_exposer b/endpoint-exposer/container-scope-override/deployment/sync_exposer new file mode 100755 index 0000000..570373c --- /dev/null +++ b/endpoint-exposer/container-scope-override/deployment/sync_exposer @@ -0,0 +1,134 @@ +#!/bin/bash + +echo "=== DEBUG: Starting sync_exposer script ===" +echo "DEBUG: CONTEXT=$CONTEXT" +echo "DEBUG: SERVICE_SPECIFICATION_SLUG=$SERVICE_SPECIFICATION_SLUG" + +SCOPE_NRN=$(echo "$CONTEXT" | jq -r .scope.nrn) + +echo "SERVICE SPECIFICATION SLUG: $SERVICE_SPECIFICATION_SLUG, SCOPE_NRN: $SCOPE_NRN" + +# Step 1: Get service specification by slug +echo "DEBUG: Fetching service specifications..." +SERVICE_SPECS=$(np service specification list --nrn "$SCOPE_NRN" --type dependency --format json) +echo "DEBUG: Service specifications fetched: $SERVICE_SPECS" + +SERVICE_SPEC=$(echo "$SERVICE_SPECS" | jq -c --arg slug "$SERVICE_SPECIFICATION_SLUG" ' + .results + | map(select(.slug == $slug)) + | .[0] +') +echo "DEBUG: Filtered service spec: $SERVICE_SPEC" + +SERVICE_SPEC_ID=$(echo "$SERVICE_SPEC" | jq -r .id) + +if [[ -z "$SERVICE_SPEC_ID" || "$SERVICE_SPEC_ID" == "null" ]]; then + echo "Error: Could not find service specification with slug '$SERVICE_SPECIFICATION_SLUG'" + exit 1 +fi + +echo "DEBUG: SERVICE_SPEC_ID=$SERVICE_SPEC_ID" + +# Step 2: Get link specification with slug "publish" +echo "DEBUG: Fetching link specifications for service spec..." +LINK_SPECS=$(np service specification link specification list --id "$SERVICE_SPEC_ID" --format json) +echo "DEBUG: Link specifications fetched: $LINK_SPECS" + +PUBLISH_LINK_SPEC=$(echo "$LINK_SPECS" | jq -c ' + .results + | map(select(.slug == "publish")) + | .[0] +') +echo "DEBUG: Filtered publish link spec: $PUBLISH_LINK_SPEC" + +LINK_SPECIFICATION_ID=$(echo "$PUBLISH_LINK_SPEC" | jq -r .id) + +if [[ -z "$LINK_SPECIFICATION_ID" || "$LINK_SPECIFICATION_ID" == "null" ]]; then + echo "Error: Could not find link specification with slug 'publish' for service specification '$SERVICE_SPEC_ID'" + exit 1 +fi + +echo "DEBUG: LINK_SPECIFICATION_ID=$LINK_SPECIFICATION_ID" + +echo "DEBUG: Fetching links for scope..." +LINKS=$(np link list --nrn "$SCOPE_NRN" --format json --status active) +echo "DEBUG: Links fetched. Response: $LINKS" + +EXPOSER_LINKS=$(echo "$LINKS" | jq -c --arg spec "$LINK_SPECIFICATION_ID" ' + .results + | map(select(.specification_id == $spec)) +') +echo "DEBUG: EXPOSER_LINKS filtered: $EXPOSER_LINKS" + +COUNT=$(echo "$EXPOSER_LINKS" | jq 'length') +echo "DEBUG: COUNT=$COUNT" + +if [[ "$COUNT" -eq 0 ]]; then + echo "This scope is not public, skipping public ingress synchronization" + return +fi + +echo "This is a public scope, starting public ingress synchronization" + +ACTIONS=$(np link specification action specification list --linkSpecificationId "$LINK_SPECIFICATION_ID" --format json) + +REFRESH_ACTION=$(echo "$ACTIONS" | jq -c ' + .results + | map(select(.slug == "refresh")) + | .[0] +') + +REFRESH_ACTION_ID=$(echo "$REFRESH_ACTION" | jq -r .id) +echo "DEBUG: REFRESH_ACTION_ID=$REFRESH_ACTION_ID" + +# Iterate over matches +echo "DEBUG: Starting iteration over exposer links..." +echo "$EXPOSER_LINKS" | jq -c '.[]' | while read -r link; do + echo "DEBUG: Processing link: $link" + + # Extract useful values + LINK_ID=$(echo "$link" | jq -r '.id') + echo "DEBUG: LINK_ID=$LINK_ID" + + echo "DEBUG: Creating link action..." + ACTION=$(np link action create --linkId "$LINK_ID" --body "{\"name\": \"refresh\", \"parameters\":{}, \"specification_id\": \"$REFRESH_ACTION_ID\"}" --format json) + echo "DEBUG: Action created: $ACTION" + + ACTION_ID=$(echo "$ACTION" | jq -r .id) + echo "DEBUG: ACTION_ID=$ACTION_ID" + + echo "Created public ingress synchronization action[id=$ACTION_ID], waiting for its completion" + + MAX_ITERATIONS=20 + iteration=0 + + echo "DEBUG: Starting polling loop for action status..." + while true; do + ((iteration++)) + echo "DEBUG: Iteration $iteration/$MAX_ITERATIONS" + + if [ "$iteration" -gt $MAX_ITERATIONS ]; then + echo "Error: Maximum number of iterations (${MAX_ITERATIONS}) reached. Could not refresh the exposer." + exit 1 + fi + + echo "DEBUG: Reading action status..." + ACTION_STATUS=$(np link action read --linkId "$LINK_ID" --id "$ACTION_ID" --format json | jq -r .status) + + echo "Checking public ingress synchronization action[id=$ACTION_ID, status=$ACTION_STATUS]" + + if [[ "$ACTION_STATUS" == "success" ]]; then + echo "✅ Public ingress successfully synchronized" + break + elif [[ "$ACTION_STATUS" == "failed" ]]; then + echo "❌ Could not synchronize public ingress, deployment will be rollbacked" + exit 1 + fi + + echo "DEBUG: Sleeping for 5 seconds..." + sleep 5 + done + echo "DEBUG: Finished processing link $LINK_ID" +done + +echo "=== DEBUG: sync_exposer script completed successfully ===" diff --git a/endpoint-exposer/container-scope-override/deployment/workflows/blue_green.yaml b/endpoint-exposer/container-scope-override/deployment/workflows/blue_green.yaml new file mode 100644 index 0000000..6d43a5e --- /dev/null +++ b/endpoint-exposer/container-scope-override/deployment/workflows/blue_green.yaml @@ -0,0 +1,5 @@ +steps: + - name: sync_exposer + type: script + file: "$OVERRIDES_PATH/deployment/sync_exposer" + after: apply diff --git a/endpoint-exposer/container-scope-override/deployment/workflows/delete.yaml b/endpoint-exposer/container-scope-override/deployment/workflows/delete.yaml new file mode 100644 index 0000000..6d74ddd --- /dev/null +++ b/endpoint-exposer/container-scope-override/deployment/workflows/delete.yaml @@ -0,0 +1,5 @@ +steps: + - name: sync_exposer + type: script + file: "$OVERRIDES_PATH/deployment/sync_exposer" + after: apply traffic \ No newline at end of file diff --git a/endpoint-exposer/container-scope-override/deployment/workflows/finalize.yaml b/endpoint-exposer/container-scope-override/deployment/workflows/finalize.yaml new file mode 100644 index 0000000..6d43a5e --- /dev/null +++ b/endpoint-exposer/container-scope-override/deployment/workflows/finalize.yaml @@ -0,0 +1,5 @@ +steps: + - name: sync_exposer + type: script + file: "$OVERRIDES_PATH/deployment/sync_exposer" + after: apply diff --git a/endpoint-exposer/container-scope-override/deployment/workflows/initial.yaml b/endpoint-exposer/container-scope-override/deployment/workflows/initial.yaml new file mode 100644 index 0000000..6d43a5e --- /dev/null +++ b/endpoint-exposer/container-scope-override/deployment/workflows/initial.yaml @@ -0,0 +1,5 @@ +steps: + - name: sync_exposer + type: script + file: "$OVERRIDES_PATH/deployment/sync_exposer" + after: apply diff --git a/endpoint-exposer/container-scope-override/deployment/workflows/rollback.yaml b/endpoint-exposer/container-scope-override/deployment/workflows/rollback.yaml new file mode 100644 index 0000000..6d43a5e --- /dev/null +++ b/endpoint-exposer/container-scope-override/deployment/workflows/rollback.yaml @@ -0,0 +1,5 @@ +steps: + - name: sync_exposer + type: script + file: "$OVERRIDES_PATH/deployment/sync_exposer" + after: apply diff --git a/endpoint-exposer/container-scope-override/deployment/workflows/switch_traffic.yaml b/endpoint-exposer/container-scope-override/deployment/workflows/switch_traffic.yaml new file mode 100644 index 0000000..6d43a5e --- /dev/null +++ b/endpoint-exposer/container-scope-override/deployment/workflows/switch_traffic.yaml @@ -0,0 +1,5 @@ +steps: + - name: sync_exposer + type: script + file: "$OVERRIDES_PATH/deployment/sync_exposer" + after: apply diff --git a/endpoint-exposer/container-scope-override/values.yaml b/endpoint-exposer/container-scope-override/values.yaml new file mode 100644 index 0000000..784fe86 --- /dev/null +++ b/endpoint-exposer/container-scope-override/values.yaml @@ -0,0 +1,3 @@ +configuration: + SERVICE_SPECIFICATION_SLUG: service-exposer-v2 + \ No newline at end of file diff --git a/endpoint-exposer/entrypoint/entrypoint b/endpoint-exposer/entrypoint/entrypoint new file mode 100755 index 0000000..81c3f2b --- /dev/null +++ b/endpoint-exposer/entrypoint/entrypoint @@ -0,0 +1,57 @@ +#!/bin/bash + +# Check if NP_ACTION_CONTEXT is set +if [ -z "$NP_ACTION_CONTEXT" ]; then + echo "NP_ACTION_CONTEXT is not set. Exiting." + exit 1 +fi + +CLEAN_CONTEXT=$(echo "$NP_ACTION_CONTEXT" | sed "s/^'//;s/'$//") + +export NP_ACTION_CONTEXT="$CLEAN_CONTEXT" + +# Parse the JSON properly - remove the extra quotes +export CONTEXT=$(echo "$CLEAN_CONTEXT" | jq '.notification') +export SERVICE_ACTION=$(echo "$CONTEXT" | jq -r '.slug') +export SERVICE_ACTION_TYPE=$(echo "$CONTEXT" | jq -r '.type') +export NOTIFICATION_ACTION=$(echo "$CONTEXT" | jq -r '.action') + +export LINK=$(echo "$CONTEXT" | jq '.link') + +ACTION_SOURCE=service + +IS_LINK_ACTION=$(echo "$CONTEXT" | jq '.link != null') + +if [ "$IS_LINK_ACTION" = "true" ]; then + ACTION_SOURCE=link +fi + +export WORKING_DIRECTORY="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +SERVICE_PATH="" +OVERRIDES_PATH="" + +for arg in "$@"; do + case $arg in + --service-path=*) + SERVICE_PATH="${arg#*=}" + ;; + --overrides-path=*) + OVERRIDES_PATH="${arg#*=}" + ;; + *) + echo "Unknown argument: $arg" + exit 1 + ;; + esac +done + +OVERRIDES_PATH="${OVERRIDES_PATH:-$SERVICE_PATH/overrides}" + +export SERVICE_PATH +export OVERRIDES_PATH + +# export util functions +#eval "$WORKING_DIRECTORY"/$ACTION_SOURCE + +np service-action exec --live-output --live-report --script="$WORKING_DIRECTORY/$ACTION_SOURCE" diff --git a/endpoint-exposer/entrypoint/link b/endpoint-exposer/entrypoint/link new file mode 100755 index 0000000..253ef01 --- /dev/null +++ b/endpoint-exposer/entrypoint/link @@ -0,0 +1,34 @@ +#!/bin/bash + +echo "Executing link action=$SERVICE_ACTION type=$SERVICE_ACTION_TYPE" + +ACTION_TO_EXECUTE="$SERVICE_ACTION_TYPE" + +case "$SERVICE_ACTION_TYPE" in + "custom") + ACTION_TO_EXECUTE="$SERVICE_ACTION" + ;; + "create") + ACTION_TO_EXECUTE="link" + ;; + "delete") + ACTION_TO_EXECUTE="unlink" + ;; +esac + +INGRESS_TYPE="${INGRESS_TYPE:-alb}" + +echo "INGRESS_TYPE is set to '$INGRESS_TYPE'" + +WORKFLOW_PATH="$SERVICE_PATH/workflows/$INGRESS_TYPE/$ACTION_TO_EXECUTE.yaml" +OVERRIDES_WORKFLOW_PATH="$OVERRIDES_PATH/workflows/$INGRESS_TYPE/$ACTION_TO_EXECUTE.yaml" +VALUES_PATH="$SERVICE_PATH/values.yaml" + +CMD="np service workflow exec --workflow $WORKFLOW_PATH --values $VALUES_PATH" + +if [[ -f "$OVERRIDES_WORKFLOW_PATH" ]]; then + CMD="$CMD --overrides $OVERRIDES_WORKFLOW_PATH" +fi + +echo "Executing command: $CMD" +eval "$CMD" diff --git a/endpoint-exposer/entrypoint/service b/endpoint-exposer/entrypoint/service new file mode 100755 index 0000000..ad77e32 --- /dev/null +++ b/endpoint-exposer/entrypoint/service @@ -0,0 +1,28 @@ +#!/bin/bash + +echo "Executing service action=$SERVICE_ACTION type=$SERVICE_ACTION_TYPE" + +ACTION_TO_EXECUTE="$SERVICE_ACTION_TYPE" + +case "$SERVICE_ACTION_TYPE" in + "custom") + ACTION_TO_EXECUTE="$SERVICE_ACTION" + ;; +esac + +INGRESS_TYPE="${INGRESS_TYPE:-alb}" + +echo "INGRESS_TYPE is set to '$INGRESS_TYPE'" + +WORKFLOW_PATH="$SERVICE_PATH/workflows/$INGRESS_TYPE/$ACTION_TO_EXECUTE.yaml" +OVERRIDES_WORKFLOW_PATH="$OVERRIDES_PATH/workflows/$INGRESS_TYPE/$ACTION_TO_EXECUTE.yaml" +VALUES_PATH="$SERVICE_PATH/values.yaml" + +CMD="np service workflow exec --workflow $WORKFLOW_PATH --values $VALUES_PATH" + +if [[ -f "$OVERRIDES_WORKFLOW_PATH" ]]; then + CMD="$CMD --overrides $OVERRIDES_WORKFLOW_PATH" +fi + +echo "Executing command: $CMD" +eval "$CMD" diff --git a/endpoint-exposer/examples/create-link.json b/endpoint-exposer/examples/create-link.json new file mode 100644 index 0000000..2f86a2e --- /dev/null +++ b/endpoint-exposer/examples/create-link.json @@ -0,0 +1,65 @@ +{ + "id": "ba21e8e6-dcc1-4b9f-87a4-3610c61dfda4", + "source": "service", + "event": "service:action:create", + "created_at": "2025-06-18T13:01:20.204Z", + "notification": { + "action": "service:action:create", + "id": "5b426145-cc25-429e-88d2-83407a6f08b3", + "name": "create-the-link-name-from-the-user", + "slug": "create-the-link-name-from-the-user", + "status": "pending", + "created_at": "2025-06-18T13:01:20.207Z", + "updated_at": "2025-06-18T13:01:20.207Z", + "parameters": { + "path": "/users" + }, + "results": {}, + "type": "create", + "specification": { + "id": "0dc917a7-180c-4155-ad84-767dc5be61a4", + "slug": "create-publish" + }, + "service": { + "id": "4f3fc1da-10bf-47e7-8dd8-b9febc3ddea1", + "slug": "the-service-name-from-the-user", + "attributes": { + "domain": "some-domain.com" + }, + "specification": { + "id": "e820250b-62e3-4e20-8647-dd41b20d1bb9", + "slug": "publish" + }, + "dimensions": { + "environment": "development", + "country": "argentina" + } + }, + "link": { + "id": "64cc013c-9545-495e-a2ac-40df06af84d6", + "slug": "the-link-name-from-the-user", + "attributes": { + "path": "/users", + "scope": "dev-us" + }, + "specification": { + "id": "39d2d131-50b5-41b9-a739-1c3edde913ec", + "slug": "publish" + }, + "dimensions": {} + }, + "tags": { + "organization_id": "1255165411", + "organization": "kwik-e-mart", + "account_id": "95118862", + "account": "kwik-e-mart-main", + "namespace_id": "1068437903", + "namespace": "fede-m", + "application_id": "857154851", + "application": "scope-exposer", + "scope_id": "704207903", + "scope": "public-argentina" + }, + "entity_nrn": "organization=1255165411:account=95118862:namespace=1249051863:application=454567105:scope=704207903" + } +} \ No newline at end of file diff --git a/endpoint-exposer/examples/create.json b/endpoint-exposer/examples/create.json new file mode 100644 index 0000000..f6912ce --- /dev/null +++ b/endpoint-exposer/examples/create.json @@ -0,0 +1,64 @@ +{ + "action": "service:action:create", + "id": "d7f7698d-ce17-4dd5-9cb6-02dc39e7a726", + "name": "create-test-javi", + "slug": "create-test-javi", + "status": "pending", + "created_by": "1621446846", + "created_at": "2025-12-30T16:34:40.773Z", + "updated_at": "2025-12-30T16:34:40.773Z", + "parameters": { + "routes": [ + { + "method": "GET", + "path": "/health", + "scope": "DevelopmentScope", + "visibility": "public" + } + ], + "public_domain": "javi.edenred.nullimplementation.com", + "private_domain": "javi.edenred.nullimplementation.com" + }, + "results": { + "routes": [ + { + "method": "GET", + "path": "/health", + "scope": "DevelopmentScope", + "visibility": "public" + } + ], + "public_domain": "javi.edenred.nullimplementation.com", + "private_domain": "javi.edenred.nullimplementation.com" + }, + "type": "create", + "specification": { + "id": "b9c6e9b5-c292-4ad1-9af8-650cac4ea587", + "slug": "create-service-exposer-v2" + }, + "service": { + "id": "babaa91d-89fb-4ee3-ba23-529620d1834f", + "slug": "test-javi", + "attributes": {}, + "type": "dependency", + "specification": { + "id": "70d51cc6-591d-4282-927c-4757b092604b", + "slug": "service-exposer-v2" + }, + "dimensions": { + "environment": "development" + } + }, + "link": null, + "tags": { + "namespace_id": "1340017944", + "namespace": "playground", + "organization_id": "1858797910", + "organization": "edenred", + "account_id": "758973013", + "account": "playground", + "application_id": "179976948", + "application": "floppy-bird-api" + }, + "entity_nrn": "organization=1858797910:account=758973013:namespace=1340017944:application=179976948" +} \ No newline at end of file diff --git a/endpoint-exposer/examples/delete-link.json b/endpoint-exposer/examples/delete-link.json new file mode 100644 index 0000000..b17be37 --- /dev/null +++ b/endpoint-exposer/examples/delete-link.json @@ -0,0 +1,71 @@ +{ + "id": "ba21e8e6-dcc1-4b9f-87a4-3610c61dfda4", + "source": "service", + "event": "service:action:delete", + "created_at": "2025-06-18T13:01:20.204Z", + "notification": { + "action": "service:action:delete", + "id": "5b426145-cc25-429e-88d2-83407a6f08b3", + "name": "delete-the-link-name-from-the-user", + "slug": "delete-the-link-name-from-the-user", + "status": "pending", + "created_at": "2025-06-18T13:01:20.207Z", + "updated_at": "2025-06-18T13:01:20.207Z", + "parameters": { + "path": "/users" + }, + "results": {}, + "type": "delete", + "specification": { + "id": "0dc917a7-180c-4155-ad84-767dc5be61a4", + "slug": "delete-publish" + }, + "service": { + "id": "4f3fc1da-10bf-47e7-8dd8-b9febc3ddea1", + "slug": "the-service-name-from-the-user", + "attributes": { + "domain": "some-domain.com", + "rules": [ + { + "path": "/users", + "scope": "public-argentina" + } + ] + }, + "specification": { + "id": "e820250b-62e3-4e20-8647-dd41b20d1bb9", + "slug": "publish" + }, + "dimensions": { + "environment": "development", + "country": "argentina" + } + }, + "link": { + "id": "64cc013c-9545-495e-a2ac-40df06af84d6", + "slug": "the-link-name-from-the-user", + "attributes": { + "path": "/users", + "scope": "dev-us" + }, + "specification": { + "id": "39d2d131-50b5-41b9-a739-1c3edde913ec", + "slug": "publish" + }, + "dimensions": {} + }, + "tags": { + "organization_id": "1255165411", + "organization": "kwik-e-mart", + "account_id": "95118862", + "account": "kwik-e-mart-main", + "namespace_id": "1068437903", + "namespace": "fede-m", + "application_id": "857154851", + "application": "scope-exposer", + "scope_id": "704207903", + "scope": "public-argentina" + }, + "entity_nrn": "organization=1255165411:account=95118862:namespace=1249051863:application=454567105:scope=704207903" + } +} \ No newline at end of file diff --git a/endpoint-exposer/examples/delete.json b/endpoint-exposer/examples/delete.json new file mode 100644 index 0000000..ac6a64d --- /dev/null +++ b/endpoint-exposer/examples/delete.json @@ -0,0 +1,50 @@ +{ + "id": "c266d1aa-23d7-4a23-8954-346824186c9a", + "source": "service", + "event": "service:action:delete", + "created_at": "2025-06-17T15:24:05.861Z", + "notification": { + "action": "service:action:delete", + "id": "b9a9971b-acce-421b-b7b7-4e940e73fac8", + "name": "create-the-service-name-from-the-user", + "slug": "create-the-service-name-from-the-user", + "status": "pending", + "created_at": "2025-06-17T15:24:05.861Z", + "updated_at": "2025-06-17T15:24:05.861Z", + "parameters": { + }, + "results": {}, + "type": "delete", + "specification": { + "id": "03bcdc47-212c-4b64-a2cc-ed0365e4228c", + "slug": "create-service-exposer" + }, + "service": { + "id": "4f3fc1da-10bf-47e7-8dd8-b9febc3ddea1", + "slug": "the-service-name-from-the-user", + "attributes": { + "rules": [], + "domain": "domain.com" + }, + "specification": { + "id": "f66f5e37-0303-48aa-bc9d-aeda1f909a10", + "slug": "service-exposer" + }, + "dimensions": { + "environment": "development" + } + }, + "link": null, + "tags": { + "organization_id": "1255165411", + "organization": "kwik-e-mart", + "account_id": "95118862", + "account": "kwik-e-mart-main", + "namespace_id": "1068437903", + "namespace": "fede-m", + "application_id": "857154851", + "application": "scope-exposer" + }, + "entity_nrn": "organization=1255165411:account=95118862:namespace=1068437903:application=857154851" + } +} \ No newline at end of file diff --git a/endpoint-exposer/examples/read.json b/endpoint-exposer/examples/read.json new file mode 100644 index 0000000..f165523 --- /dev/null +++ b/endpoint-exposer/examples/read.json @@ -0,0 +1,50 @@ +{ + "id": "c266d1aa-23d7-4a23-8954-346824186c9a", + "source": "service", + "event": "service:action:write", + "created_at": "2025-06-17T15:24:05.861Z", + "notification": { + "action": "service:action:write", + "id": "b9a9971b-acce-421b-b7b7-4e940e73fac8", + "name": "Read", + "slug": "read", + "status": "pending", + "created_at": "2025-06-17T15:24:05.861Z", + "updated_at": "2025-06-17T15:24:05.861Z", + "parameters": { + }, + "results": {}, + "type": "custom", + "specification": { + "id": "03bcdc47-212c-4b64-a2cc-ed0365e4228c", + "slug": "read" + }, + "service": { + "id": "4f3fc1da-10bf-47e7-8dd8-b9febc3ddea1", + "slug": "the-service-name-from-the-user", + "attributes": { + "rules": [], + "domain": "domain.com" + }, + "specification": { + "id": "f66f5e37-0303-48aa-bc9d-aeda1f909a10", + "slug": "service-exposer" + }, + "dimensions": { + "environment": "development" + } + }, + "link": null, + "tags": { + "organization_id": "1255165411", + "organization": "kwik-e-mart", + "account_id": "95118862", + "account": "kwik-e-mart-main", + "namespace_id": "1068437903", + "namespace": "fede-m", + "application_id": "857154851", + "application": "scope-exposer" + }, + "entity_nrn": "organization=1255165411:account=95118862:namespace=1068437903:application=857154851" + } +} \ No newline at end of file diff --git a/endpoint-exposer/examples/refresh.json b/endpoint-exposer/examples/refresh.json new file mode 100644 index 0000000..ae32f56 --- /dev/null +++ b/endpoint-exposer/examples/refresh.json @@ -0,0 +1,61 @@ +{ + "id": "ba21e8e6-dcc1-4b9f-87a4-3610c61dfda4", + "source": "service", + "event": "service:action:update", + "created_at": "2025-06-18T13:01:20.204Z", + "notification": { + "action": "service:action:update", + "id": "5b426145-cc25-429e-88d2-83407a6f08b3", + "name": "Refresh", + "slug": "refresh", + "status": "pending", + "created_at": "2025-06-18T13:01:20.207Z", + "updated_at": "2025-06-18T13:01:20.207Z", + "parameters": {}, + "results": {}, + "type": "custom", + "specification": { + "id": "0dc917a7-180c-4155-ad84-767dc5be61a4", + "slug": "delete-publish" + }, + "service": { + "id": "4f3fc1da-10bf-47e7-8dd8-b9febc3ddea1", + "slug": "the-service-name-from-the-user", + "attributes": {}, + "specification": { + "id": "e820250b-62e3-4e20-8647-dd41b20d1bb9", + "slug": "publish" + }, + "dimensions": { + "environment": "development", + "country": "argentina" + } + }, + "link": { + "id": "64cc013c-9545-495e-a2ac-40df06af84d6", + "slug": "the-link-name-from-the-user", + "attributes": { + "path": "/users", + "scope": "dev-us" + }, + "specification": { + "id": "39d2d131-50b5-41b9-a739-1c3edde913ec", + "slug": "publish" + }, + "dimensions": {} + }, + "tags": { + "organization_id": "1255165411", + "organization": "kwik-e-mart", + "account_id": "95118862", + "account": "kwik-e-mart-main", + "namespace_id": "1068437903", + "namespace": "fede-m", + "application_id": "857154851", + "application": "scope-exposer", + "scope_id": "704207903", + "scope": "public-argentina" + }, + "entity_nrn": "organization=1255165411:account=95118862:namespace=1249051863:application=454567105:scope=704207903" + } +} \ No newline at end of file diff --git a/endpoint-exposer/scripts/alb/apply b/endpoint-exposer/scripts/alb/apply new file mode 100644 index 0000000..2692c3c --- /dev/null +++ b/endpoint-exposer/scripts/alb/apply @@ -0,0 +1,25 @@ +#!/bin/bash + +set -euo pipefail + +echo "TEMPLATE DIR: $OUTPUT_DIR, ACTION: $ACTION, DRY_RUN: $DRY_RUN" + +# Find all .yaml files that were not yet applied / deleted +find "$OUTPUT_DIR" \( -path "*/apply" -o -path "*/delete" \) -prune -o -type f -name "*.yaml" -print | while read -r TEMPLATE_FILE; do + echo "kubectl $ACTION $TEMPLATE_FILE" + + if [[ "$DRY_RUN" == "false" ]]; then + kubectl "$ACTION" -f "$TEMPLATE_FILE" + fi + + BASE_DIR="$(dirname "$TEMPLATE_FILE")" + FILENAME="$(basename "$TEMPLATE_FILE")" + DEST_DIR="${BASE_DIR}/$ACTION" + + mkdir -p "$DEST_DIR" + mv "$TEMPLATE_FILE" "$DEST_DIR/$FILENAME" +done + +if [[ "$DRY_RUN" == "true" ]]; then + exit 1 +fi \ No newline at end of file diff --git a/endpoint-exposer/scripts/alb/build_context b/endpoint-exposer/scripts/alb/build_context new file mode 100644 index 0000000..761fed4 --- /dev/null +++ b/endpoint-exposer/scripts/alb/build_context @@ -0,0 +1,36 @@ +#!/bin/bash + +set -euo pipefail + +SERVICE_ID=$(echo "$CONTEXT" | jq -r .service.id) +SERVICE_NAME=$(echo "$CONTEXT" | jq -r .service.slug) + +ACTION_ID=$(echo "$CONTEXT" | jq -r .id) +ACTION_NAME=$(echo "$CONTEXT" | jq -r .slug) + +LINK_ID=$(echo "$CONTEXT" | jq -r .link.id) +LINK_NAME=$(echo "$CONTEXT" | jq -r .link.slug) + +CONTEXT=$(echo "$CONTEXT" | jq \ + --arg k8s_namespace "$K8S_NAMESPACE" \ + --arg alb_name "$ALB_NAME" \ + '. + {k8s_namespace: $k8s_namespace, alb_name: $alb_name}') + +SCOPE_ID=$(echo "$CONTEXT" | jq -r .tags.scope_id) +SCOPE_SLUG=$(echo "$CONTEXT" | jq -r .tags.scope) + +RULE_PATH=$(echo "$CONTEXT" | jq -r '.link.attributes.path // .parameters.path') + +export OUTPUT_DIR="$SERVICE_PATH/output/$SERVICE_NAME-$SERVICE_ID/$ACTION_NAME-$ACTION_ID" + +mkdir -p "$OUTPUT_DIR" + +export SERVICE_ID +export SERVICE_NAME +export ACTION_ID +export ACTION_NAME +export LINK_ID +export LINK_NAME +export SCOPE_ID +export SCOPE_SLUG +export RULE_PATH \ No newline at end of file diff --git a/endpoint-exposer/scripts/alb/build_ingress b/endpoint-exposer/scripts/alb/build_ingress new file mode 100644 index 0000000..610c439 --- /dev/null +++ b/endpoint-exposer/scripts/alb/build_ingress @@ -0,0 +1,22 @@ +#!/bin/bash + +set -euo pipefail + +SERVICE_DOMAIN=$(echo "$CONTEXT" | jq -r .parameters.domain) + +echo "Creating ingress for service $SERVICE_NAME with domain $SERVICE_DOMAIN" + +echo "Creating public ingress..." + +INGRESS_FILE="$OUTPUT_DIR/ingress-$SERVICE_ID-public.yaml" +CONTEXT_PATH="$OUTPUT_DIR/context-$SERVICE_ID.json" + +echo "$CONTEXT" > "$CONTEXT_PATH" + +echo "Building Template: $TEMPLATE to $INGRESS_FILE" + +gomplate -c .="$CONTEXT_PATH" \ + --file "$TEMPLATE" \ + --out "$INGRESS_FILE" + +rm "$CONTEXT_PATH" \ No newline at end of file diff --git a/endpoint-exposer/scripts/alb/build_ingress_with_rule b/endpoint-exposer/scripts/alb/build_ingress_with_rule new file mode 100644 index 0000000..f3f4e5f --- /dev/null +++ b/endpoint-exposer/scripts/alb/build_ingress_with_rule @@ -0,0 +1,199 @@ +#!/bin/bash + +set -euo pipefail + +is_ingress_empty() { + local yaml_content="$1" + + local num_rules + local num_paths + local path + local service_name + local service_port + + num_rules=$(yq '.spec.rules | length' <<< "$yaml_content") + num_paths=$(yq '.spec.rules[0].http.paths | length' <<< "$yaml_content") + path=$(yq '.spec.rules[0].http.paths[0].path' <<< "$yaml_content") + service_name=$(yq '.spec.rules[0].http.paths[0].backend.service.name' <<< "$yaml_content") + service_port=$(yq '.spec.rules[0].http.paths[0].backend.service.port.name' <<< "$yaml_content") + + if [[ "$num_rules" -eq 1 && \ + "$num_paths" -eq 1 && \ + "$path" == "/" && \ + "$service_name" == "response-404" && \ + "$service_port" == "use-annotation" ]]; then + echo "true" + else + echo "false" + fi +} + +create_path_rule() { + local rule_path="$1" + local service_json="$2" + + jq -n \ + --arg path "$rule_path" \ + --argjson service "$service_json" \ + '{ + path: $path, + pathType: "Prefix", + backend: { + service: $service + } + }' +} + +add_annotation_if_needed() { + local ingress_yaml="$1" + local annotation="$2" + local scope_id="$3" + + if [[ "$annotation" != "null" && -n "$annotation" ]]; then + local annotation_key="alb.ingress.kubernetes.io/actions.bg-deployment-$scope_id" + + # Escape the value so it’s properly quoted in YAML + local escaped_annotation + escaped_annotation=$(printf '%s\n' "$annotation" | jq -Rs .) # wrap & escape as JSON string + + echo "$ingress_yaml" | yq eval ".metadata.annotations.\"$annotation_key\" = $escaped_annotation" + else + echo "$ingress_yaml" + fi +} + +update_ingress_rule() { + local ingress_yaml="$1" + local rule_path="$2" + local service_json="$3" + local annotation="$4" + local scope_id="$5" + + local updated_ingress + + # Replace the current rule with the new rule data + updated_ingress=$(echo "$ingress_yaml" | yq eval '.spec.rules[0].http.paths[0].path = "'$rule_path'"') + updated_ingress=$(echo "$updated_ingress" | yq eval '.spec.rules[0].http.paths[0].pathType = "Prefix"') + updated_ingress=$(echo "$updated_ingress" | yq eval '.spec.rules[0].http.paths[0].backend.service = '"$service_json") + + # Add annotation if needed + updated_ingress=$(add_annotation_if_needed "$updated_ingress" "$annotation" "$scope_id") + + echo "$updated_ingress" +} + +find_path_index() { + local ingress_yaml="$1" + local target_path="$2" + + local num_paths + local i + local current_path + + num_paths=$(yq '.spec.rules[0].http.paths | length' <<< "$ingress_yaml") + + for ((i=0; i "$INGRESS_FILE" +else + PATH_INDEX=$(find_path_index "$INGRESS" "$RULE_PATH") + + # if there is a rule for the path we replace it + if [[ "$PATH_INDEX" != "-1" ]]; then + UPDATED_INGRESS=$(replace_existing_rule "$INGRESS" "$RULE_PATH" "$SERVICE" "$ANNOTATION" "$SCOPE_ID" "$PATH_INDEX") + echo "$UPDATED_INGRESS" | yq "." > "$INGRESS_FILE" + else + # if there is no rule for the path we add a new one + UPDATED_INGRESS=$(add_new_rule "$INGRESS" "$RULE_PATH" "$SERVICE" "$ANNOTATION" "$SCOPE_ID") + echo "$UPDATED_INGRESS" | yq "." > "$INGRESS_FILE" + fi +fi + +echo "Ingress configuration saved to: $INGRESS_FILE" \ No newline at end of file diff --git a/endpoint-exposer/scripts/alb/build_ingress_without_rule b/endpoint-exposer/scripts/alb/build_ingress_without_rule new file mode 100644 index 0000000..282fff7 --- /dev/null +++ b/endpoint-exposer/scripts/alb/build_ingress_without_rule @@ -0,0 +1,47 @@ +#!/bin/bash + +set -euo pipefail + +find_path_index() { + local ingress_yaml="$1" + local target_path="$2" + + local num_paths + local i + local current_path + + num_paths=$(yq '.spec.rules[0].http.paths | length' <<< "$ingress_yaml") + + for ((i=0; i "$INGRESS_FILE" + + diff --git a/endpoint-exposer/scripts/alb/build_rule b/endpoint-exposer/scripts/alb/build_rule new file mode 100644 index 0000000..1de728a --- /dev/null +++ b/endpoint-exposer/scripts/alb/build_rule @@ -0,0 +1,22 @@ +#!/bin/bash + +set -euo pipefail + +INGRESS_NAME=$(kubectl get ingress -n "$K8S_NAMESPACE" -l "scope_id=$SCOPE_ID" -o jsonpath="{.items[0].metadata.name}" 2>/dev/null || echo "") + +# Check if ingress exists +if [ -z "$INGRESS_NAME" ]; then + echo "There is no ingress for scope $SCOPE_ID. Publishing the rule with an empty backend" + + SCOPE_RULE='{"blue_green_annotation": null, "service": {"name": "response-404", "port": { "name": "use-annotation"} }}' +else + echo "Found ingress for scope $SCOPE_ID. Publishing the backend service configuration" + INGRESS=$(kubectl get ingress -n "$K8S_NAMESPACE" "$INGRESS_NAME" -o json) + + SCOPE_RULE=$(echo "$INGRESS" | jq '{ + blue_green_annotation: .metadata.annotations["alb.ingress.kubernetes.io/actions.bg-deployment"], + service: .spec.rules[0].http.paths[0].backend.service + }') +fi + +export SCOPE_RULE \ No newline at end of file diff --git a/endpoint-exposer/scripts/alb/fetch_provider_data b/endpoint-exposer/scripts/alb/fetch_provider_data new file mode 100755 index 0000000..51603cf --- /dev/null +++ b/endpoint-exposer/scripts/alb/fetch_provider_data @@ -0,0 +1,22 @@ +#!/bin/bash + +NRN=$(echo "$CONTEXT" | jq -r .entity_nrn) + +DIMENSIONS=$(echo "$CONTEXT" | jq .service.dimensions) + +DIMENSION_FILTER=$(echo "$DIMENSIONS" | jq -r 'to_entries | map("\(.key):\(.value)") | join(",")') + +if [ -z "$DIMENSION_FILTER" ] || [ "$DIMENSION_FILTER" = "" ]; then + PROVIDER_DATA=$(np provider list --categories container-orchestration --nrn "$NRN" --format json | jq -r ".results[0]") +else + PROVIDER_DATA=$(np provider list --categories container-orchestration --nrn "$NRN" --dimensions "$DIMENSION_FILTER" --format json | jq -r ".results[0]") +fi + +K8S_NAMESPACE=$(echo "$PROVIDER_DATA" | jq -r .attributes.cluster.namespace) + +ALB_NAME=$(echo "$PROVIDER_DATA" | jq -r --arg default "k8s-nullplatform-internet-facing" ' + .attributes.balancer.public_name // $default +') + +export K8S_NAMESPACE +export ALB_NAME \ No newline at end of file diff --git a/endpoint-exposer/scripts/alb/read_ingress b/endpoint-exposer/scripts/alb/read_ingress new file mode 100644 index 0000000..bde7c9f --- /dev/null +++ b/endpoint-exposer/scripts/alb/read_ingress @@ -0,0 +1,5 @@ +#!/bin/bash + +INGRESS_NAME=$(kubectl get ingress -n "$K8S_NAMESPACE" -l "service_id=$SERVICE_ID" -o jsonpath="{.items[0].metadata.name}") + +kubectl get ingress -n "$K8S_NAMESPACE" "$INGRESS_NAME" -o yaml diff --git a/endpoint-exposer/scripts/alb/update_service b/endpoint-exposer/scripts/alb/update_service new file mode 100644 index 0000000..5f743d3 --- /dev/null +++ b/endpoint-exposer/scripts/alb/update_service @@ -0,0 +1,21 @@ +#!/bin/bash + +if [[ $ACTION == "add" ]]; then + UPDATED_ATTRIBUTES=$(echo "$CONTEXT" | jq --arg path "$RULE_PATH" --arg scope "$SCOPE_SLUG" ' + .service.attributes |= (.rules //= [] | .rules += [{path: $path, scope: $scope}]) | + { + attributes: .service.attributes, + entity_nrn: (.entity_nrn | sub(":scope=[^:]+$"; "")) + } + ') +elif [[ $ACTION == "remove" ]]; then + UPDATED_ATTRIBUTES=$(echo "$CONTEXT" | jq --arg path "$RULE_PATH" ' + .service.attributes |= (.rules //= [] | .rules |= map(select(.path != $path))) | + { + attributes: .service.attributes, + entity_nrn: (.entity_nrn | sub(":scope=[^:]+$"; "")) + } + ') +fi + +np service patch --id "$SERVICE_ID" --body "$UPDATED_ATTRIBUTES" diff --git a/endpoint-exposer/scripts/alb/validate_unique_rule b/endpoint-exposer/scripts/alb/validate_unique_rule new file mode 100644 index 0000000..49a56b1 --- /dev/null +++ b/endpoint-exposer/scripts/alb/validate_unique_rule @@ -0,0 +1,12 @@ +#!/bin/bash + +EXISTS=$(echo "$CONTEXT" | jq --arg path "$RULE_PATH" ' + (.service.attributes.rules // []) + | map(select(.path == $path)) + | length +') + +if [[ "$EXISTS" -gt 0 ]]; then + echo "Error: A rule with path '$RULE_PATH' already exists." + exit 1 +fi \ No newline at end of file diff --git a/endpoint-exposer/scripts/common/echo b/endpoint-exposer/scripts/common/echo new file mode 100755 index 0000000..ace31ee --- /dev/null +++ b/endpoint-exposer/scripts/common/echo @@ -0,0 +1,3 @@ +#!/bin/bash + +echo "$MESSAGE" \ No newline at end of file diff --git a/endpoint-exposer/scripts/dns/build_dns b/endpoint-exposer/scripts/dns/build_dns new file mode 100755 index 0000000..6a6641b --- /dev/null +++ b/endpoint-exposer/scripts/dns/build_dns @@ -0,0 +1,15 @@ +#!/bin/bash + +# Build DNS context based on DNS_TYPE +echo "=== DEBUG: Starting build_dns ===" +echo "DNS_TYPE=$DNS_TYPE" + +case "$DNS_TYPE" in + external_dns) + "$SERVICE_PATH/scripts/dns/build_dns_endpoint" + ;; + *) + echo "Error: Unsupported DNS type '$DNS_TYPE'" + exit 1 + ;; +esac \ No newline at end of file diff --git a/endpoint-exposer/scripts/dns/build_dns_endpoint b/endpoint-exposer/scripts/dns/build_dns_endpoint new file mode 100755 index 0000000..c43327f --- /dev/null +++ b/endpoint-exposer/scripts/dns/build_dns_endpoint @@ -0,0 +1,42 @@ +#!/bin/bash + +set -euo pipefail + +echo "=== DEBUG: Starting build_dns_endpoint ===" + +SERVICE_DOMAIN=$(echo "$CONTEXT" | jq -r '.parameters.public_domain') +echo "DEBUG: SERVICE_DOMAIN=$SERVICE_DOMAIN" + + +PUBLIC_GATEWAY_NAME=${PUBLIC_GATEWAY_NAME:-"gateway-public"} +GATEWAY_NAMESPACE=${GATEWAY_NAMESPACE:-"gateways"} + +echo "DEBUG: Fetching gateway IP from $PUBLIC_GATEWAY_NAME..." +GATEWAY_IP=$(kubectl get gateway -n "$GATEWAY_NAMESPACE" "$PUBLIC_GATEWAY_NAME" -o jsonpath='{.status.addresses[0].value}') +echo "DEBUG: GATEWAY_IP=$GATEWAY_IP" + +if [[ -z "$GATEWAY_IP" || "$GATEWAY_IP" == "null" ]]; then + echo "ERROR: Could not retrieve gateway IP from $PUBLIC_GATEWAY_NAME" + exit 1 +fi + +echo "Creating DNSEndpoint for service $SERVICE_NAME with domain $SERVICE_DOMAIN" + +DNS_FILE="$OUTPUT_DIR/dnsendpoint-$SERVICE_ID-public.yaml" +CONTEXT_PATH="$OUTPUT_DIR/context-dns-$SERVICE_ID.json" + +# Add gateway_ip to context +CONTEXT_WITH_IP=$(echo "$CONTEXT" | jq --arg gateway_ip "$GATEWAY_IP" '. + {gateway_ip: $gateway_ip}') + +echo "$CONTEXT_WITH_IP" > "$CONTEXT_PATH" + +echo "Building DNSEndpoint Template to $DNS_FILE" + +gomplate -c .="$CONTEXT_PATH" \ + --file "$SERVICE_PATH/templates/istio/dns-endpoint.yaml.tpl" \ + --out "$DNS_FILE" + +rm "$CONTEXT_PATH" + +echo "DEBUG: DNSEndpoint created at $DNS_FILE" +echo "=== DEBUG: build_dns_endpoint completed ===" diff --git a/endpoint-exposer/scripts/istio/apply b/endpoint-exposer/scripts/istio/apply new file mode 100644 index 0000000..2692c3c --- /dev/null +++ b/endpoint-exposer/scripts/istio/apply @@ -0,0 +1,25 @@ +#!/bin/bash + +set -euo pipefail + +echo "TEMPLATE DIR: $OUTPUT_DIR, ACTION: $ACTION, DRY_RUN: $DRY_RUN" + +# Find all .yaml files that were not yet applied / deleted +find "$OUTPUT_DIR" \( -path "*/apply" -o -path "*/delete" \) -prune -o -type f -name "*.yaml" -print | while read -r TEMPLATE_FILE; do + echo "kubectl $ACTION $TEMPLATE_FILE" + + if [[ "$DRY_RUN" == "false" ]]; then + kubectl "$ACTION" -f "$TEMPLATE_FILE" + fi + + BASE_DIR="$(dirname "$TEMPLATE_FILE")" + FILENAME="$(basename "$TEMPLATE_FILE")" + DEST_DIR="${BASE_DIR}/$ACTION" + + mkdir -p "$DEST_DIR" + mv "$TEMPLATE_FILE" "$DEST_DIR/$FILENAME" +done + +if [[ "$DRY_RUN" == "true" ]]; then + exit 1 +fi \ No newline at end of file diff --git a/endpoint-exposer/scripts/istio/build_context b/endpoint-exposer/scripts/istio/build_context new file mode 100644 index 0000000..5303734 --- /dev/null +++ b/endpoint-exposer/scripts/istio/build_context @@ -0,0 +1,45 @@ +#!/bin/bash + +set -euo pipefail + +SERVICE_ID=$(echo "$CONTEXT" | jq -r .service.id) +SERVICE_NAME=$(echo "$CONTEXT" | jq -r .service.slug) + +ACTION_ID=$(echo "$CONTEXT" | jq -r .id) +ACTION_NAME=$(echo "$CONTEXT" | jq -r .slug) + +# Extract domains from parameters +PUBLIC_DOMAIN=$(echo "$CONTEXT" | jq -r '.parameters.public_domain // ""') +PRIVATE_DOMAIN=$(echo "$CONTEXT" | jq -r '.parameters.private_domain // ""') + +# Extract routes array from parameters +ROUTES_JSON=$(echo "$CONTEXT" | jq -c '.parameters.routes // []') + +# For backward compatibility with link-based workflow +LINK_ID=$(echo "$CONTEXT" | jq -r '.link.id // ""') +LINK_NAME=$(echo "$CONTEXT" | jq -r '.link.slug // ""') +SCOPE_ID=$(echo "$CONTEXT" | jq -r '.tags.scope_id // ""') +SCOPE_SLUG=$(echo "$CONTEXT" | jq -r '.tags.scope // ""') +RULE_PATH=$(echo "$CONTEXT" | jq -r '.link.attributes.path // .parameters.path // ""') + +CONTEXT=$(echo "$CONTEXT" | jq \ + --arg k8s_namespace "$K8S_NAMESPACE" \ + --arg alb_name "$ALB_NAME" \ + '. + {k8s_namespace: $k8s_namespace, alb_name: $alb_name}') + +export OUTPUT_DIR="$SERVICE_PATH/output/$SERVICE_NAME-$SERVICE_ID/$ACTION_NAME-$ACTION_ID" + +mkdir -p "$OUTPUT_DIR" + +export SERVICE_ID +export SERVICE_NAME +export ACTION_ID +export ACTION_NAME +export PUBLIC_DOMAIN +export PRIVATE_DOMAIN +export ROUTES_JSON +export LINK_ID +export LINK_NAME +export SCOPE_ID +export SCOPE_SLUG +export RULE_PATH \ No newline at end of file diff --git a/endpoint-exposer/scripts/istio/build_ingress b/endpoint-exposer/scripts/istio/build_ingress new file mode 100644 index 0000000..bbea5c3 --- /dev/null +++ b/endpoint-exposer/scripts/istio/build_ingress @@ -0,0 +1,22 @@ +#!/bin/bash + +set -euo pipefail + +SERVICE_DOMAIN=$(echo "$CONTEXT" | jq -r '.parameters.public_domain // .service.attributes.domain') + +echo "Creating HTTPRoute for service $SERVICE_NAME with domain $SERVICE_DOMAIN" + +echo "Creating public HTTPRoute..." + +HTTPROUTE_FILE="$OUTPUT_DIR/httproute-$SERVICE_ID-public.yaml" +CONTEXT_PATH="$OUTPUT_DIR/context-$SERVICE_ID.json" + +echo "$CONTEXT" > "$CONTEXT_PATH" + +echo "Building Template: $TEMPLATE to $HTTPROUTE_FILE" + +gomplate -c .="$CONTEXT_PATH" \ + --file "$TEMPLATE" \ + --out "$HTTPROUTE_FILE" + +rm "$CONTEXT_PATH" \ No newline at end of file diff --git a/endpoint-exposer/scripts/istio/build_ingress_with_rule b/endpoint-exposer/scripts/istio/build_ingress_with_rule new file mode 100755 index 0000000..eb5bae1 --- /dev/null +++ b/endpoint-exposer/scripts/istio/build_ingress_with_rule @@ -0,0 +1,361 @@ +#!/bin/bash + +set -euo pipefail + +# Detect path type and convert path value accordingly +# Returns: "type:value" format +detect_path_type() { + local path="$1" + + # Check for wildcard (*) - use PathPrefix + if [[ "$path" == *"*"* ]]; then + # Remove trailing /* or * + local prefix_path="${path%/*}" + if [[ -z "$prefix_path" ]]; then + prefix_path="/" + fi + echo "PathPrefix:$prefix_path" + return + fi + + # Check for path parameters (:param) - use RegularExpression + if [[ "$path" == *:* ]]; then + # Replace :param with [^/]+ + local regex_path="${path//:+([^\/])/[^/]+}" + # For bash pattern replacement, we need to handle it differently + regex_path=$(echo "$path" | sed 's/:[^/]*/[^\/]+/g') + echo "RegularExpression:$regex_path" + return + fi + + # Default: Exact match + echo "Exact:$path" +} + +# Get priority for path type (lower number = higher priority) +get_path_priority() { + local path="$1" + + if [[ "$path" != *":"* && "$path" != *"*"* ]]; then + echo "1" # Exact - highest priority + elif [[ "$path" == *":"* ]]; then + echo "2" # RegularExpression - medium priority + else + echo "3" # PathPrefix - lowest priority + fi +} + +is_httproute_empty() { + local yaml_content="$1" + + local num_rules + local backend_name + local backend_weight + + num_rules=$(yq '.spec.rules | length' <<< "$yaml_content") + backend_name=$(yq '.spec.rules[0].backendRefs[0].name' <<< "$yaml_content") + backend_weight=$(yq '.spec.rules[0].backendRefs[0].weight' <<< "$yaml_content") + + # An HTTPRoute is "empty" if it only has one rule with response-404 backend and weight 0 + if [[ "$num_rules" -eq 1 && \ + "$backend_name" == "response-404" && \ + "$backend_weight" == "0" ]]; then + echo "true" + else + echo "false" + fi +} + +create_http_rule() { + local rule_path="$1" + local service_json="$2" + local blue_green_config="$3" + local method="${4:-}" + local visibility="${5:-public}" + + local service_name + local service_port + + service_name=$(echo "$service_json" | jq -r '.name') + service_port=$(echo "$service_json" | jq -r '.port.number // .port.name // 80') + + # Detect path type and get the converted path value + local path_type_value + path_type_value=$(detect_path_type "$rule_path") + local path_type="${path_type_value%%:*}" + local path_value="${path_type_value#*:}" + + echo "DEBUG: Original path='$rule_path', Detected type='$path_type', Converted value='$path_value'" >&2 + + # Build matches array with path and optional method + local matches_json + + # Add method if specified + if [[ -n "$method" && "$method" != "null" ]]; then + matches_json=$(jq -n \ + --arg path "$path_value" \ + --arg path_type "$path_type" \ + --arg method "$method" \ + '[{ + path: { + type: $path_type, + value: $path + }, + method: $method + }]') + else + matches_json=$(jq -n \ + --arg path "$path_value" \ + --arg path_type "$path_type" \ + '[{ + path: { + type: $path_type, + value: $path + } + }]') + fi + + # Check if there's blue/green configuration + if [[ "$blue_green_config" != "null" && -n "$blue_green_config" ]]; then + # Parse blue/green destinations and weights from the annotation + local blue_weight green_weight blue_service green_service + + blue_weight=$(echo "$blue_green_config" | jq -r '.forward.targetGroups[0].weight // 100') + green_weight=$(echo "$blue_green_config" | jq -r '.forward.targetGroups[1].weight // 0') + blue_service=$(echo "$blue_green_config" | jq -r '.forward.targetGroups[0].serviceName') + green_service=$(echo "$blue_green_config" | jq -r '.forward.targetGroups[1].serviceName') + + # Create rule with weighted backends (no URL rewrite) + jq -n \ + --argjson matches "$matches_json" \ + --arg blue_service "$blue_service" \ + --arg green_service "$green_service" \ + --arg service_port "$service_port" \ + --argjson blue_weight "$blue_weight" \ + --argjson green_weight "$green_weight" \ + '{ + matches: $matches, + backendRefs: [ + { + name: $blue_service, + port: ($service_port | tonumber), + weight: $blue_weight + }, + { + name: $green_service, + port: ($service_port | tonumber), + weight: $green_weight + } + ] + }' + else + # Single destination without blue/green (no URL rewrite) + jq -n \ + --argjson matches "$matches_json" \ + --arg service_name "$service_name" \ + --arg service_port "$service_port" \ + '{ + matches: $matches, + backendRefs: [ + { + name: $service_name, + port: ($service_port | tonumber) + } + ] + }' + fi +} + +update_httproute_rule() { + local hr_yaml="$1" + local rule_path="$2" + local service_json="$3" + local blue_green_config="$4" + + local service_name + local service_port + local updated_hr + + service_name=$(echo "$service_json" | jq -r '.name') + service_port=$(echo "$service_json" | jq -r '.port.number // .port.name // 80') + + # Update the first rule's path with Exact type (no URL rewrite) + updated_hr=$(echo "$hr_yaml" | yq eval ".spec.rules[0].matches[0].path.type = \"Exact\"") + updated_hr=$(echo "$updated_hr" | yq eval ".spec.rules[0].matches[0].path.value = \"$rule_path\"") + + # Remove filters (no URL rewrite needed) + updated_hr=$(echo "$updated_hr" | yq eval "del(.spec.rules[0].filters)") + + # Check if there's blue/green configuration + if [[ "$blue_green_config" != "null" && -n "$blue_green_config" ]]; then + # Parse blue/green destinations and weights + local blue_weight green_weight blue_service green_service + + blue_weight=$(echo "$blue_green_config" | jq -r '.forward.targetGroups[0].weight // 100') + green_weight=$(echo "$blue_green_config" | jq -r '.forward.targetGroups[1].weight // 0') + blue_service=$(echo "$blue_green_config" | jq -r '.forward.targetGroups[0].serviceName') + green_service=$(echo "$blue_green_config" | jq -r '.forward.targetGroups[1].serviceName') + + # Set blue backend + updated_hr=$(echo "$updated_hr" | yq eval ".spec.rules[0].backendRefs[0].name = \"${blue_service}\"") + updated_hr=$(echo "$updated_hr" | yq eval ".spec.rules[0].backendRefs[0].port = $service_port") + updated_hr=$(echo "$updated_hr" | yq eval ".spec.rules[0].backendRefs[0].weight = $blue_weight") + + # Add green backend + updated_hr=$(echo "$updated_hr" | yq eval ".spec.rules[0].backendRefs += [{\"name\": \"${green_service}\", \"port\": $service_port, \"weight\": $green_weight}]") + else + # Single destination + updated_hr=$(echo "$updated_hr" | yq eval ".spec.rules[0].backendRefs[0].name = \"${service_name}\"") + updated_hr=$(echo "$updated_hr" | yq eval ".spec.rules[0].backendRefs[0].port = $service_port") + updated_hr=$(echo "$updated_hr" | yq eval "del(.spec.rules[0].backendRefs[0].weight)") + fi + + echo "$updated_hr" +} + +find_rule_index() { + local hr_yaml="$1" + local target_path="$2" + + local num_rules + local i + local current_path + + num_rules=$(yq '.spec.rules | length' <<< "$hr_yaml") + + for ((i=0; i "$HTTPROUTE_FILE" +else + RULE_INDEX=$(find_rule_index "$HTTPROUTE" "$RULE_PATH") + echo "Found rule index for path '$RULE_PATH': $RULE_INDEX" + + # if there is a rule for the path we replace it + if [[ "$RULE_INDEX" != "-1" ]]; then + echo "Case 2: Replacing existing rule at index $RULE_INDEX" + UPDATED_HR=$(replace_existing_rule "$HTTPROUTE" "$RULE_PATH" "$SERVICE" "$BLUE_GREEN_CONFIG" "$RULE_INDEX" "${METHOD:-}" "${VISIBILITY:-public}") + echo "$UPDATED_HR" | yq "." > "$HTTPROUTE_FILE" + else + # if there is no rule for the path we add a new one + echo "Case 3: Adding new rule" + UPDATED_HR=$(add_new_rule "$HTTPROUTE" "$RULE_PATH" "$SERVICE" "$BLUE_GREEN_CONFIG" "${METHOD:-}" "${VISIBILITY:-public}") + + # Debug: Check if hostnames and parentRefs are present before saving + echo "DEBUG: Checking HTTPRoute before saving..." + HOSTNAMES=$(echo "$UPDATED_HR" | yq eval '.spec.hostnames | length' -) + PARENTREFS=$(echo "$UPDATED_HR" | yq eval '.spec.parentRefs | length' -) + echo "DEBUG: Number of hostnames: $HOSTNAMES" + echo "DEBUG: Number of parentRefs: $PARENTREFS" + + echo "$UPDATED_HR" | yq "." > "$HTTPROUTE_FILE" + fi +fi + +echo "" +echo "=== HTTPRoute configuration saved to: $HTTPROUTE_FILE ===" diff --git a/endpoint-exposer/scripts/istio/build_ingress_with_rule_virtualservice_backup b/endpoint-exposer/scripts/istio/build_ingress_with_rule_virtualservice_backup new file mode 100644 index 0000000..3367222 --- /dev/null +++ b/endpoint-exposer/scripts/istio/build_ingress_with_rule_virtualservice_backup @@ -0,0 +1,278 @@ +#!/bin/bash + +set -euo pipefail + +is_virtualservice_empty() { + local yaml_content="$1" + + local num_http_routes + local has_fault + local service_host + + num_http_routes=$(yq '.spec.http | length' <<< "$yaml_content") + has_fault=$(yq '.spec.http[0].fault.abort' <<< "$yaml_content") + service_host=$(yq '.spec.http[0].route[0].destination.host' <<< "$yaml_content") + + # A VirtualService is "empty" if it only has one route with a 404 fault injection to response-404 + if [[ "$num_http_routes" -eq 1 && \ + "$has_fault" != "null" && \ + "$service_host" =~ response-404 ]]; then + echo "true" + else + echo "false" + fi +} + +create_http_route() { + local rule_path="$1" + local service_json="$2" + local blue_green_config="$3" + + local service_name + local service_port + + service_name=$(echo "$service_json" | jq -r '.name') + service_port=$(echo "$service_json" | jq -r '.port.number // .port.name // 80') + + # Check if there's blue/green configuration + if [[ "$blue_green_config" != "null" && -n "$blue_green_config" ]]; then + # Parse blue/green destinations and weights from the annotation + local blue_weight green_weight blue_service green_service + + blue_weight=$(echo "$blue_green_config" | jq -r '.forward.targetGroups[0].weight // 100') + green_weight=$(echo "$blue_green_config" | jq -r '.forward.targetGroups[1].weight // 0') + blue_service=$(echo "$blue_green_config" | jq -r '.forward.targetGroups[0].serviceName') + green_service=$(echo "$blue_green_config" | jq -r '.forward.targetGroups[1].serviceName') + + # Create route with weighted destinations + jq -n \ + --arg path "$rule_path" \ + --arg blue_service "$blue_service" \ + --arg green_service "$green_service" \ + --arg service_port "$service_port" \ + --arg namespace "$K8S_NAMESPACE" \ + --argjson blue_weight "$blue_weight" \ + --argjson green_weight "$green_weight" \ + '{ + match: [ + { + uri: { + prefix: $path + } + } + ], + route: [ + { + destination: { + host: ($blue_service + "." + $namespace + ".svc.cluster.local"), + port: { + number: ($service_port | tonumber) + } + }, + weight: $blue_weight + }, + { + destination: { + host: ($green_service + "." + $namespace + ".svc.cluster.local"), + port: { + number: ($service_port | tonumber) + } + }, + weight: $green_weight + } + ] + }' + else + # Single destination without blue/green + jq -n \ + --arg path "$rule_path" \ + --arg service_name "$service_name" \ + --arg service_port "$service_port" \ + --arg namespace "$K8S_NAMESPACE" \ + '{ + match: [ + { + uri: { + prefix: $path + } + } + ], + route: [ + { + destination: { + host: ($service_name + "." + $namespace + ".svc.cluster.local"), + port: { + number: ($service_port | tonumber) + } + } + } + ] + }' + fi +} + +update_virtualservice_route() { + local vs_yaml="$1" + local rule_path="$2" + local service_json="$3" + local blue_green_config="$4" + + local service_name + local service_port + local updated_vs + + service_name=$(echo "$service_json" | jq -r '.name') + service_port=$(echo "$service_json" | jq -r '.port.number // .port.name // 80') + + # Remove fault injection + updated_vs=$(echo "$vs_yaml" | yq eval 'del(.spec.http[0].fault)') + updated_vs=$(echo "$updated_vs" | yq eval ".spec.http[0].match[0].uri.prefix = \"$rule_path\"") + + # Check if there's blue/green configuration + if [[ "$blue_green_config" != "null" && -n "$blue_green_config" ]]; then + # Parse blue/green destinations and weights + local blue_weight green_weight blue_service green_service + + blue_weight=$(echo "$blue_green_config" | jq -r '.forward.targetGroups[0].weight // 100') + green_weight=$(echo "$blue_green_config" | jq -r '.forward.targetGroups[1].weight // 0') + blue_service=$(echo "$blue_green_config" | jq -r '.forward.targetGroups[0].serviceName') + green_service=$(echo "$blue_green_config" | jq -r '.forward.targetGroups[1].serviceName') + + # Set blue destination + updated_vs=$(echo "$updated_vs" | yq eval ".spec.http[0].route[0].destination.host = \"${blue_service}.${K8S_NAMESPACE}.svc.cluster.local\"") + updated_vs=$(echo "$updated_vs" | yq eval ".spec.http[0].route[0].destination.port.number = $service_port") + updated_vs=$(echo "$updated_vs" | yq eval ".spec.http[0].route[0].weight = $blue_weight") + + # Add green destination + updated_vs=$(echo "$updated_vs" | yq eval ".spec.http[0].route += [{\"destination\": {\"host\": \"${green_service}.${K8S_NAMESPACE}.svc.cluster.local\", \"port\": {\"number\": $service_port}}, \"weight\": $green_weight}]") + else + # Single destination + updated_vs=$(echo "$updated_vs" | yq eval ".spec.http[0].route[0].destination.host = \"${service_name}.${K8S_NAMESPACE}.svc.cluster.local\"") + updated_vs=$(echo "$updated_vs" | yq eval ".spec.http[0].route[0].destination.port.number = $service_port") + fi + + echo "$updated_vs" +} + +find_route_index() { + local vs_yaml="$1" + local target_path="$2" + + local num_routes + local i + local current_path + + num_routes=$(yq '.spec.http | length' <<< "$vs_yaml") + + for ((i=0; i "$VS_FILE" +else + ROUTE_INDEX=$(find_route_index "$VIRTUALSERVICE" "$RULE_PATH") + echo "Found route index for path '$RULE_PATH': $ROUTE_INDEX" + + # if there is a route for the path we replace it + if [[ "$ROUTE_INDEX" != "-1" ]]; then + echo "Case 2: Replacing existing route at index $ROUTE_INDEX" + UPDATED_VS=$(replace_existing_route "$VIRTUALSERVICE" "$RULE_PATH" "$SERVICE" "$BLUE_GREEN_CONFIG" "$ROUTE_INDEX") + echo "$UPDATED_VS" | yq "." > "$VS_FILE" + else + # if there is no route for the path we add a new one + echo "Case 3: Adding new route" + UPDATED_VS=$(add_new_route "$VIRTUALSERVICE" "$RULE_PATH" "$SERVICE" "$BLUE_GREEN_CONFIG") + echo "$UPDATED_VS" | yq "." > "$VS_FILE" + fi +fi + +echo "" +echo "=== VirtualService configuration saved to: $VS_FILE ===" \ No newline at end of file diff --git a/endpoint-exposer/scripts/istio/build_ingress_without_rule b/endpoint-exposer/scripts/istio/build_ingress_without_rule new file mode 100644 index 0000000..2fef8a3 --- /dev/null +++ b/endpoint-exposer/scripts/istio/build_ingress_without_rule @@ -0,0 +1,62 @@ +#!/bin/bash + +set -euo pipefail + +find_rule_index() { + local hr_yaml="$1" + local target_path="$2" + + local num_rules + local i + local current_path + + num_rules=$(yq '.spec.rules | length' <<< "$hr_yaml") + + for ((i=0; i "$HTTPROUTE_FILE" + +echo "=== HTTPRoute configuration saved to: $HTTPROUTE_FILE ===" diff --git a/endpoint-exposer/scripts/istio/build_rule b/endpoint-exposer/scripts/istio/build_rule new file mode 100644 index 0000000..ef5675a --- /dev/null +++ b/endpoint-exposer/scripts/istio/build_rule @@ -0,0 +1,179 @@ +#!/bin/bash + +set -euo pipefail + +echo "=== DEBUG: Starting build_rule script ===" +echo "DEBUG: K8S_NAMESPACE=$K8S_NAMESPACE" +echo "DEBUG: SCOPE_ID=$SCOPE_ID" + +# Check for in-progress deployment +echo "DEBUG: Checking for in-progress deployment..." +SCOPE_JSON=$(np scope read --id "$SCOPE_ID" --format json) +echo "DEBUG: Scope JSON retrieved" + +IN_PROGRESS_DEPLOYMENT=$(echo "$SCOPE_JSON" | jq -r '.in_progress_deployment // "null"') +echo "DEBUG: IN_PROGRESS_DEPLOYMENT=$IN_PROGRESS_DEPLOYMENT" + +DEPLOYMENT_STATUS="" +SWITCHED_TRAFFIC=0 + +if [[ "$IN_PROGRESS_DEPLOYMENT" != "null" ]]; then + echo "DEBUG: Found in-progress deployment, fetching details..." + DEPLOYMENT_JSON=$(np deployment read --id "$IN_PROGRESS_DEPLOYMENT" --format json) + DEPLOYMENT_STATUS=$(echo "$DEPLOYMENT_JSON" | jq -r '.status') + SWITCHED_TRAFFIC=$(echo "$DEPLOYMENT_JSON" | jq -r '.strategy_data.desired_switched_traffic // 0') + echo "DEBUG: DEPLOYMENT_STATUS=$DEPLOYMENT_STATUS" + echo "DEBUG: SWITCHED_TRAFFIC=$SWITCHED_TRAFFIC" +fi + +# Get all services and filter by scope_id in selector +# Note: kubectl -l only filters by labels, not by selectors. scope_id is in the selector field. +echo "DEBUG: Fetching all services from namespace..." +ALL_SERVICES=$(kubectl get services -n "$K8S_NAMESPACE" -o json 2>&1) + +# Try to sanitize the JSON by removing any control characters or ANSI escape codes +echo "DEBUG: Sanitizing JSON output..." +ALL_SERVICES_CLEAN=$(echo "$ALL_SERVICES" | sed $'s/\x1b\\[[0-9;]*m//g' | tr -d '\000-\011\013-\037') +echo "DEBUG: Cleaned JSON length: ${#ALL_SERVICES_CLEAN} characters" + +# Check if we have valid JSON +if echo "$ALL_SERVICES_CLEAN" | jq empty 2>/dev/null; then + echo "DEBUG: JSON is valid after cleaning" + ALL_SERVICES="$ALL_SERVICES_CLEAN" +else + echo "DEBUG: WARNING - JSON may still have issues, attempting to parse anyway" + ALL_SERVICES="$ALL_SERVICES_CLEAN" +fi + +# Filter services by scope_id in selector (not label) +echo "DEBUG: Filtering services with scope_id=$SCOPE_ID in selector..." +SERVICES_JSON=$(echo "$ALL_SERVICES" | jq --arg scope_id "$SCOPE_ID" '{ + apiVersion: .apiVersion, + kind: .kind, + metadata: .metadata, + items: [.items[] | select(.spec.selector.scope_id == $scope_id)] +}') +echo "DEBUG: Filtered services JSON" + +NUM_SERVICES=$(echo "$SERVICES_JSON" | jq '.items | length') +echo "DEBUG: NUM_SERVICES=$NUM_SERVICES" + +if [[ "$NUM_SERVICES" -eq 0 ]]; then + echo "There is no service for scope_id=$SCOPE_ID. Publishing the rule with an empty backend" + + SCOPE_RULE='{"service": {"name": "response-404", "port": { "number": 80} }}' + echo "DEBUG: SCOPE_RULE (no services)=$SCOPE_RULE" +elif [[ "$NUM_SERVICES" -eq 1 ]]; then + echo "Found single service for scope_id=$SCOPE_ID" + + echo "DEBUG: Extracting service name and port..." + SERVICE_NAME=$(echo "$SERVICES_JSON" | jq -r '.items[0].metadata.name') + SERVICE_PORT=$(echo "$SERVICES_JSON" | jq -r '.items[0].spec.ports[0].port') + + echo "Service: $SERVICE_NAME, Port: $SERVICE_PORT" + echo "DEBUG: SERVICE_NAME=$SERVICE_NAME, SERVICE_PORT=$SERVICE_PORT" + + echo "DEBUG: Building SCOPE_RULE for single service..." + SCOPE_RULE=$(jq -n \ + --arg name "$SERVICE_NAME" \ + --argjson port "$SERVICE_PORT" \ + '{ + service: { + name: $name, + port: { + number: $port + } + } + }') + echo "DEBUG: SCOPE_RULE (single service)=$SCOPE_RULE" +else + echo "Detected blue/green deployment with $NUM_SERVICES services for scope_id=$SCOPE_ID" + + # Check if deployment is finalized - if so, only use the latest service + if [[ "$DEPLOYMENT_STATUS" == "finalized" ]]; then + echo "DEBUG: Deployment is finalized, using only the latest service" + + # Use only the first service (latest deployment) + BLUE_SERVICE=$(echo "$SERVICES_JSON" | jq -r '.items[0].metadata.name') + BLUE_PORT=$(echo "$SERVICES_JSON" | jq -r '.items[0].spec.ports[0].port') + + echo "Deployment finalized. Using service: $BLUE_SERVICE" + echo "DEBUG: SERVICE_NAME=$BLUE_SERVICE, SERVICE_PORT=$BLUE_PORT" + + SCOPE_RULE=$(jq -n \ + --arg name "$BLUE_SERVICE" \ + --argjson port "$BLUE_PORT" \ + '{ + service: { + name: $name, + port: { + number: $port + } + } + }') + echo "DEBUG: SCOPE_RULE (finalized deployment)=$SCOPE_RULE" + else + # Extract blue and green services + echo "DEBUG: Extracting blue service details..." + BLUE_SERVICE=$(echo "$SERVICES_JSON" | jq -r '.items[0].metadata.name') + BLUE_PORT=$(echo "$SERVICES_JSON" | jq -r '.items[0].spec.ports[0].port') + echo "DEBUG: BLUE_SERVICE=$BLUE_SERVICE, BLUE_PORT=$BLUE_PORT" + + echo "DEBUG: Extracting green service details..." + GREEN_SERVICE=$(echo "$SERVICES_JSON" | jq -r '.items[1].metadata.name') + GREEN_PORT=$(echo "$SERVICES_JSON" | jq -r '.items[1].spec.ports[0].port') + echo "DEBUG: GREEN_SERVICE=$GREEN_SERVICE, GREEN_PORT=$GREEN_PORT" + + # Determine weights based on deployment status + if [[ "$DEPLOYMENT_STATUS" == "running" ]]; then + echo "DEBUG: Deployment is running, using switched_traffic for weights" + # New service (green) gets the switched traffic percentage + GREEN_WEIGHT=$SWITCHED_TRAFFIC + # Old service (blue) gets the remaining traffic + BLUE_WEIGHT=$((100 - SWITCHED_TRAFFIC)) + echo "DEBUG: Using deployment weights - BLUE_WEIGHT=$BLUE_WEIGHT, GREEN_WEIGHT=$GREEN_WEIGHT" + else + # Fallback to annotation-based weights + echo "DEBUG: No running deployment, using annotation-based weights" + BLUE_WEIGHT=$(echo "$SERVICES_JSON" | jq -r '.items[0].metadata.annotations["weight"] // "100"' | sed 's/"//g') + GREEN_WEIGHT=$(echo "$SERVICES_JSON" | jq -r '.items[1].metadata.annotations["weight"] // "0"' | sed 's/"//g') + echo "DEBUG: BLUE_WEIGHT=$BLUE_WEIGHT (from annotation), GREEN_WEIGHT=$GREEN_WEIGHT (from annotation)" + fi + + echo "Blue: $BLUE_SERVICE (weight: $BLUE_WEIGHT), Green: $GREEN_SERVICE (weight: $GREEN_WEIGHT)" + + # Build blue/green annotation similar to ALB format + echo "DEBUG: Building SCOPE_RULE for blue/green deployment..." + SCOPE_RULE=$(jq -n \ + --arg blue_service "$BLUE_SERVICE" \ + --argjson blue_weight "$BLUE_WEIGHT" \ + --arg green_service "$GREEN_SERVICE" \ + --argjson green_weight "$GREEN_WEIGHT" \ + --argjson port "$BLUE_PORT" \ + '{ + blue_green_annotation: { + forward: { + targetGroups: [ + { + serviceName: $blue_service, + weight: $blue_weight + }, + { + serviceName: $green_service, + weight: $green_weight + } + ] + } + }, + service: { + name: $blue_service, + port: { + number: $port + } + } + }') + echo "DEBUG: SCOPE_RULE (blue/green)=$SCOPE_RULE" + fi +fi + +export SCOPE_RULE \ No newline at end of file diff --git a/endpoint-exposer/scripts/istio/clean_httproute_rules b/endpoint-exposer/scripts/istio/clean_httproute_rules new file mode 100755 index 0000000..85179f6 --- /dev/null +++ b/endpoint-exposer/scripts/istio/clean_httproute_rules @@ -0,0 +1,30 @@ +#!/bin/bash + +set -euo pipefail + +echo "=== Cleaning HTTPRoute rules ===" +echo "HTTPROUTE_FILE: $HTTPROUTE_FILE" + +# Read the HTTPRoute +HTTPROUTE=$(cat "$HTTPROUTE_FILE") +echo "$HTTPROUTE" > "$HTTPROUTE_FILE.before" + +# Keep only the first rule (the fallback rule with response-404) +# Reset to empty state with just the fallback rule +CLEANED_HR=$(echo "$HTTPROUTE" | yq eval 'del(.spec.rules[1:])' -) + +# Ensure the first rule is the fallback rule +FIRST_RULE_BACKEND=$(echo "$CLEANED_HR" | yq eval '.spec.rules[0].backendRefs[0].name' -) + +if [[ "$FIRST_RULE_BACKEND" != "response-404" ]]; then + echo "WARNING: First rule is not the fallback rule. Resetting to fallback rule..." + + # Create a clean HTTPRoute with only the fallback rule + CLEANED_HR=$(echo "$CLEANED_HR" | yq eval '.spec.rules = [{"matches": [{"path": {"type": "PathPrefix", "value": "/"}}], "backendRefs": [{"name": "response-404", "port": 80, "weight": 0}]}]' -) +fi + +# Save the cleaned HTTPRoute +echo "$CLEANED_HR" > "$HTTPROUTE_FILE" +echo "$CLEANED_HR" > "$HTTPROUTE_FILE.cleaned" + +echo "HTTPRoute rules cleaned. Only fallback rule remains." diff --git a/endpoint-exposer/scripts/istio/fetch_httproute b/endpoint-exposer/scripts/istio/fetch_httproute new file mode 100755 index 0000000..080f4d3 --- /dev/null +++ b/endpoint-exposer/scripts/istio/fetch_httproute @@ -0,0 +1,45 @@ +#!/bin/bash + +set -euo pipefail + +echo "=== Fetching existing HTTPRoute from Kubernetes ===" +echo "SERVICE_ID: $SERVICE_ID" +echo "SERVICE_NAME: $SERVICE_NAME" +echo "K8S_NAMESPACE: $K8S_NAMESPACE" + +# Build the HTTPRoute name using the same pattern as the template +HTTPROUTE_NAME="${SERVICE_NAME}-${SERVICE_ID}-route" +echo "HTTPRoute name: $HTTPROUTE_NAME" + +# Define output file +HTTPROUTE_FILE="$OUTPUT_DIR/httproute-$SERVICE_ID-public.yaml" + +# Create output directory if it doesn't exist +mkdir -p "$OUTPUT_DIR" + +# Fetch the existing HTTPRoute from Kubernetes +echo "Fetching HTTPRoute '$HTTPROUTE_NAME' from namespace '$K8S_NAMESPACE'..." +if kubectl get httproute "$HTTPROUTE_NAME" -n "$K8S_NAMESPACE" -o yaml > "$HTTPROUTE_FILE" 2>/dev/null; then + echo "HTTPRoute fetched successfully" + + # Remove only managed fields and status, but keep important metadata + yq eval 'del(.metadata.managedFields, .status)' -i "$HTTPROUTE_FILE" + + echo "HTTPRoute cleaned and saved to: $HTTPROUTE_FILE" +else + echo "ERROR: HTTPRoute '$HTTPROUTE_NAME' not found in namespace '$K8S_NAMESPACE'" + echo "Creating new HTTPRoute from template instead..." + + # If HTTPRoute doesn't exist, create from template as fallback + CONTEXT_PATH="$OUTPUT_DIR/context-$SERVICE_ID.json" + echo "$CONTEXT" > "$CONTEXT_PATH" + + gomplate -c .="$CONTEXT_PATH" \ + --file "$SERVICE_PATH/templates/istio/empty.yaml.tpl" \ + --out "$HTTPROUTE_FILE" + + rm "$CONTEXT_PATH" + echo "New HTTPRoute created from template" +fi + +echo "HTTPRoute file ready at: $HTTPROUTE_FILE" diff --git a/endpoint-exposer/scripts/istio/fetch_provider_data b/endpoint-exposer/scripts/istio/fetch_provider_data new file mode 100755 index 0000000..282c9a1 --- /dev/null +++ b/endpoint-exposer/scripts/istio/fetch_provider_data @@ -0,0 +1,22 @@ +#!/bin/bash + +NRN=$(echo "$CONTEXT" | jq -r .entity_nrn) + +DIMENSIONS=$(echo "$CONTEXT" | jq .service.dimensions) + +DIMENSION_FILTER=$(echo "$DIMENSIONS" | jq -r 'to_entries | map("\(.key):\(.value)") | join(",")') + +if [ -z "$DIMENSION_FILTER" ] || [ "$DIMENSION_FILTER" = "" ]; then + PROVIDER_DATA=$(np provider list --categories container-orchestration --nrn "$NRN" --format json | jq -r ".results[0]") +else + PROVIDER_DATA=$(np provider list --categories container-orchestration --nrn "$NRN" --dimensions "$DIMENSION_FILTER" --format json | jq -r ".results[0]") +fi + +# K8S_NAMESPACE=$(echo "$PROVIDER_DATA" | jq -r .attributes.cluster.namespace) + +ALB_NAME=$(echo "$PROVIDER_DATA" | jq -r --arg default "k8s-nullplatform-internet-facing" ' + .attributes.balancer.public_name // $default +') + +export K8S_NAMESPACE +export ALB_NAME \ No newline at end of file diff --git a/endpoint-exposer/scripts/istio/process_routes b/endpoint-exposer/scripts/istio/process_routes new file mode 100755 index 0000000..383330b --- /dev/null +++ b/endpoint-exposer/scripts/istio/process_routes @@ -0,0 +1,118 @@ +#!/bin/bash + +set -euo pipefail + +echo "=== Starting process_routes script ===" +echo "SERVICE_ID: $SERVICE_ID" +echo "SERVICE_NAME: $SERVICE_NAME" +echo "K8S_NAMESPACE: $K8S_NAMESPACE" +echo "ROUTES_JSON: $ROUTES_JSON" + +# Check if we have any routes to process +NUM_ROUTES=$(echo "$ROUTES_JSON" | jq 'length') +echo "Number of routes to process: $NUM_ROUTES" + +if [[ "$NUM_ROUTES" -eq 0 ]]; then + echo "No routes to process" + exit 0 +fi + +# Build the HTTPRoute name using the same pattern as the template +HTTPROUTE_NAME="${SERVICE_NAME}-${SERVICE_ID}-route" +echo "HTTPRoute name: $HTTPROUTE_NAME" + +# Define output file +HTTPROUTE_FILE="$OUTPUT_DIR/httproute-$SERVICE_ID-public.yaml" +export HTTPROUTE_FILE + +# Read the HTTPRoute from the file created in the previous step +if [[ ! -f "$HTTPROUTE_FILE" ]]; then + echo "ERROR: HTTPRoute file not found at $HTTPROUTE_FILE" + exit 1 +fi + +HTTPROUTE=$(cat "$HTTPROUTE_FILE") + +# Save initial HTTPRoute to file +echo "$HTTPROUTE" > "$HTTPROUTE_FILE" + +# Get application ID once +APPLICATION_ID=$(echo "$CONTEXT" | jq -r '.tags.application_id // empty') +if [[ -n "$APPLICATION_ID" ]]; then + echo "Application ID: $APPLICATION_ID" +else + echo "No Application ID found in context" + exit 1 +fi + +# Fetch all scopes once +echo "Fetching scopes for application $APPLICATION_ID..." +SCOPES_JSON=$(np scope list --application_id "$APPLICATION_ID" --format json | jq -rs ".[].results") +echo "Scopes fetched successfully" + +# Sort routes by path specificity (Exact > RegularExpression > PathPrefix) +# Priority: 1=Exact, 2=RegularExpression, 3=PathPrefix +echo "" +echo "=== Sorting routes by specificity ===" +SORTED_ROUTES=$(echo "$ROUTES_JSON" | jq 'sort_by( + if (.path | contains("*")) then 3 + elif (.path | contains(":")) then 2 + else 1 + end +)') +ROUTES_JSON="$SORTED_ROUTES" +echo "Routes sorted by specificity (Exact > RegularExpression > PathPrefix)" + +# Process each route +for ((i=0; i "$HTTPROUTE_FILE" + +echo "HTTPRoute hostname updated to: $PUBLIC_DOMAIN" +echo "HTTPRoute parentRefs set to gateway-public" + +# Debug: Verify the file was saved correctly +echo "DEBUG: Verifying saved file..." +SAVED_HOSTNAMES=$(cat "$HTTPROUTE_FILE" | yq eval '.spec.hostnames | length' -) +SAVED_PARENTREFS=$(cat "$HTTPROUTE_FILE" | yq eval '.spec.parentRefs | length' -) +echo "DEBUG: Saved file has $SAVED_HOSTNAMES hostnames" +echo "DEBUG: Saved file has $SAVED_PARENTREFS parentRefs" diff --git a/endpoint-exposer/scripts/istio/update_service b/endpoint-exposer/scripts/istio/update_service new file mode 100644 index 0000000..5f743d3 --- /dev/null +++ b/endpoint-exposer/scripts/istio/update_service @@ -0,0 +1,21 @@ +#!/bin/bash + +if [[ $ACTION == "add" ]]; then + UPDATED_ATTRIBUTES=$(echo "$CONTEXT" | jq --arg path "$RULE_PATH" --arg scope "$SCOPE_SLUG" ' + .service.attributes |= (.rules //= [] | .rules += [{path: $path, scope: $scope}]) | + { + attributes: .service.attributes, + entity_nrn: (.entity_nrn | sub(":scope=[^:]+$"; "")) + } + ') +elif [[ $ACTION == "remove" ]]; then + UPDATED_ATTRIBUTES=$(echo "$CONTEXT" | jq --arg path "$RULE_PATH" ' + .service.attributes |= (.rules //= [] | .rules |= map(select(.path != $path))) | + { + attributes: .service.attributes, + entity_nrn: (.entity_nrn | sub(":scope=[^:]+$"; "")) + } + ') +fi + +np service patch --id "$SERVICE_ID" --body "$UPDATED_ATTRIBUTES" diff --git a/endpoint-exposer/scripts/istio/validate_unique_rule b/endpoint-exposer/scripts/istio/validate_unique_rule new file mode 100644 index 0000000..49a56b1 --- /dev/null +++ b/endpoint-exposer/scripts/istio/validate_unique_rule @@ -0,0 +1,12 @@ +#!/bin/bash + +EXISTS=$(echo "$CONTEXT" | jq --arg path "$RULE_PATH" ' + (.service.attributes.rules // []) + | map(select(.path == $path)) + | length +') + +if [[ "$EXISTS" -gt 0 ]]; then + echo "Error: A rule with path '$RULE_PATH' already exists." + exit 1 +fi \ No newline at end of file diff --git a/endpoint-exposer/specs/actions/read.json.tpl b/endpoint-exposer/specs/actions/read.json.tpl new file mode 100644 index 0000000..f6a4c52 --- /dev/null +++ b/endpoint-exposer/specs/actions/read.json.tpl @@ -0,0 +1,25 @@ +{ + "name": "Read", + "slug": "read", + "type": "custom", + "annotations": {}, + "enabled_when": "", + "retryable": false, + "service_specification_id": "{{ env.Getenv "SERVICE_SPECIFICATION_ID" }}", + "parameters": { + "schema": { + "type": "object", + "required": [], + "properties": {} + }, + "values": {} + }, + "results": { + "schema": { + "type": "object", + "required": [], + "properties": {} + }, + "values": {} + } +} \ No newline at end of file diff --git a/endpoint-exposer/specs/link-spec.json.tpl b/endpoint-exposer/specs/link-spec.json.tpl new file mode 100644 index 0000000..3f45d10 --- /dev/null +++ b/endpoint-exposer/specs/link-spec.json.tpl @@ -0,0 +1,28 @@ +{ + "assignable_to": "scope", + "attributes": { + "schema": { + "properties": { + }, + "required": [ + ], + "type": "object" + }, + "values": {} + }, + "dimensions": {}, + "name": "Publish", + "selectors": { + "category": "any", + "imported": false, + "provider": "any", + "sub_category": "any" + }, + "slug": "publish", + "specification_id": "{{ env.Getenv "SERVICE_SPECIFICATION_ID" }}", + "unique": false, + "use_default_actions": true, + "visible_to": [ + "{{ env.Getenv "NRN" }}" + ] +} diff --git a/endpoint-exposer/specs/links/refresh.json.tpl b/endpoint-exposer/specs/links/refresh.json.tpl new file mode 100644 index 0000000..bd56670 --- /dev/null +++ b/endpoint-exposer/specs/links/refresh.json.tpl @@ -0,0 +1,25 @@ +{ + "name": "Refresh", + "slug": "refresh", + "type": "custom", + "annotations": {}, + "enabled_when": "", + "retryable": false, + "link_specification_id": "{{ env.Getenv "LINK_SPECIFICATION_ID" }}", + "parameters": { + "schema": { + "type": "object", + "required": [], + "properties": {} + }, + "values": {} + }, + "results": { + "schema": { + "type": "object", + "required": [], + "properties": {} + }, + "values": {} + } +} \ No newline at end of file diff --git a/endpoint-exposer/specs/service-spec.json.tpl b/endpoint-exposer/specs/service-spec.json.tpl new file mode 100644 index 0000000..741adad --- /dev/null +++ b/endpoint-exposer/specs/service-spec.json.tpl @@ -0,0 +1,138 @@ +{ + "assignable_to": "dimension", + "attributes": { + "schema": { + "type": "object", + "$schema": "http://json-schema.org/draft-07/schema#", + "uiSchema": { + "type": "VerticalLayout", + "elements": [ + { + "type": "Group", + "label": "Domains", + "elements": [ + { + "type": "Control", + "scope": "#/properties/publicDomain" + }, + { + "type": "Control", + "scope": "#/properties/privateDomain" + } + ] + }, + { + "type": "Group", + "label": "Routes", + "elements": [ + { + "type": "Control", + "scope": "#/properties/routes", + "options": { + "detail": { + "type": "GridLayout", + "columns": 4, + "elements": [ + { + "type": "Control", + "label": "Verb", + "scope": "#/items/properties/method" + }, + { + "type": "Control", + "label": "Path", + "scope": "#/items/properties/path" + }, + { + "type": "Control", + "label": "Visibility", + "scope": "#/items/properties/visibility" + }, + { + "type": "Control", + "label": "Scope", + "scope": "#/items/properties/scope" + } + ] + }, + "showSortButtons": true + } + } + ] + } + ] + }, + "properties": { + "publicDomain": { + "type": "string", + "editableOn": ["create", "update"] + }, + "privateDomain": { + "type": "string", + "editableOn": ["create", "update"] + }, + "routes": { + "items": { + "properties": { + "method": { + "type": "string", + "title": "Verb", + "enum": ["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"] + }, + "path": { + "type": "string", + "title": "Path" + }, + "visibility": { + "type": "string", + "title": "Visibility", + "enum": ["internal", "public"] + }, + "scope": { + "type": "string", + "title": "Scope", + "description": "The scope slug", + "additionalKeywords": { + "enum": "[.scopes[]?.slug]" + } + } + }, + "required": [ + "method", + "path", + "visibility", + "scope" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "publicDomain", + "privateDomain" + ], + "type": "object" + }, + "values": {} + }, + "dimensions": {}, + "name": "Service exposer V2", + "selectors": { + "category": "any", + "imported": false, + "provider": "any", + "sub_category": "any" + }, + "slug": "service-exposer", + "type": "dependency", + "use_default_actions": true, + "available_actions": [ + "read" + ], + "available_links": [ + ], + "visible_to": [ + "{{ env.Getenv "NRN" }}" + ] +} diff --git a/endpoint-exposer/templates/alb/empty.yaml.tpl b/endpoint-exposer/templates/alb/empty.yaml.tpl new file mode 100644 index 0000000..35ef800 --- /dev/null +++ b/endpoint-exposer/templates/alb/empty.yaml.tpl @@ -0,0 +1,32 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: k-8-s-{{ .service.slug }}-{{ .service.id }}-public + namespace: {{ .k8s_namespace }} + labels: + nullplatform: "true" + service: {{ .service.slug }} + service_id: {{ .service.id }} + annotations: + kubernetes.io/ingress.class: alb + alb.ingress.kubernetes.io/group.name: {{ .alb_name }} + alb.ingress.kubernetes.io/load-balancer-name: {{ .alb_name }} + alb.ingress.kubernetes.io/scheme: internet-facing + alb.ingress.kubernetes.io/target-type: ip + alb.ingress.kubernetes.io/listen-ports: '[{"HTTP":80},{"HTTPS":443}]' + alb.ingress.kubernetes.io/ssl-redirect: "443" + alb.ingress.kubernetes.io/actions.response-404: >- + {"type":"fixed-response","fixedResponseConfig":{"contentType":"text/plain","statusCode":"404","messageBody":"no scopes exposed through this service."}} +spec: + ingressClassName: alb + rules: + - host: {{ .parameters.domain }} + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: response-404 + port: + name: use-annotation \ No newline at end of file diff --git a/endpoint-exposer/templates/istio/dns-endpoint.yaml.tpl b/endpoint-exposer/templates/istio/dns-endpoint.yaml.tpl new file mode 100644 index 0000000..e8983cf --- /dev/null +++ b/endpoint-exposer/templates/istio/dns-endpoint.yaml.tpl @@ -0,0 +1,16 @@ +apiVersion: externaldns.k8s.io/v1alpha1 +kind: DNSEndpoint +metadata: + name: {{ .service.slug }}-{{ .service.id }}-dns + namespace: {{ .k8s_namespace }} + labels: + nullplatform: "true" + service: {{ .service.slug }} + service_id: {{ .service.id }} +spec: + endpoints: + - dnsName: {{ if has . "parameters" }}{{ if has .parameters "public_domain" }}{{ .parameters.public_domain }}{{ else if has .parameters "domain" }}{{ .parameters.domain }}{{ else }}{{ .service.attributes.domain }}{{ end }}{{ else }}{{ .service.attributes.domain }}{{ end }} + recordTTL: 60 + recordType: A + targets: + - "{{ .gateway_ip }}" diff --git a/endpoint-exposer/templates/istio/empty.yaml.tpl b/endpoint-exposer/templates/istio/empty.yaml.tpl new file mode 100644 index 0000000..d0dd6de --- /dev/null +++ b/endpoint-exposer/templates/istio/empty.yaml.tpl @@ -0,0 +1,24 @@ +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: {{ .service.slug }}-{{ .service.id }}-route + namespace: {{ .k8s_namespace }} + labels: + nullplatform: "true" + service: {{ .service.slug }} + service_id: {{ .service.id }} +spec: + parentRefs: + - name: gateway-public + namespace: gateways + hostnames: + - {{ if has . "parameters" }}{{ if has .parameters "public_domain" }}{{ .parameters.public_domain }}{{ else if has .parameters "domain" }}{{ .parameters.domain }}{{ else }}{{ .service.attributes.domain }}{{ end }}{{ else }}{{ .service.attributes.domain }}{{ end }} + rules: + - matches: + - path: + type: PathPrefix + value: / + backendRefs: + - name: response-404 + port: 80 + weight: 0 \ No newline at end of file diff --git a/endpoint-exposer/values.yaml b/endpoint-exposer/values.yaml new file mode 100644 index 0000000..6831afc --- /dev/null +++ b/endpoint-exposer/values.yaml @@ -0,0 +1,2 @@ +configuration: + K8S_NAMESPACE: nullplatform \ No newline at end of file diff --git a/endpoint-exposer/workflows/alb/create.yaml b/endpoint-exposer/workflows/alb/create.yaml new file mode 100644 index 0000000..7c8c3a2 --- /dev/null +++ b/endpoint-exposer/workflows/alb/create.yaml @@ -0,0 +1,44 @@ +steps: + - name: "find k8s namespace" + type: script + file: "$SERVICE_PATH/scripts/alb/fetch_provider_data" + output: + - name: K8S_NAMESPACE + type: environment + - name: ALB_NAME + type: environment + - name: "build context" + type: script + file: "$SERVICE_PATH/scripts/alb/build_context" + output: + - name: SERVICE_ID + type: environment + - name: SERVICE_NAME + type: environment + - name: ACTION_ID + type: environment + - name: ACTION_NAME + type: environment + - name: LINK_ID + type: environment + - name: LINK_NAME + type: environment + - name: SCOPE_ID + type: environment + - name: RULE_PATH + type: environment + - name: "build template" + type: script + file: "$SERVICE_PATH/scripts/alb/build_ingress" + configuration: + TEMPLATE: "$SERVICE_PATH/templates/alb/empty.yaml.tpl" + output: + - name: INGRESS_FILE + type: file + file: "$OUTPUT_DIR/ingress-$SERVICE_ID-$SCOPE_ID-public.yaml" + - name: apply + type: script + file: "$SERVICE_PATH/scripts/alb/apply" + configuration: + ACTION: apply + DRY_RUN: false \ No newline at end of file diff --git a/endpoint-exposer/workflows/alb/delete.yaml b/endpoint-exposer/workflows/alb/delete.yaml new file mode 100644 index 0000000..3c7309e --- /dev/null +++ b/endpoint-exposer/workflows/alb/delete.yaml @@ -0,0 +1,6 @@ +include: + - "$SERVICE_PATH/workflows/alb/create.yaml" +steps: + - name: apply + configuration: + ACTION: delete \ No newline at end of file diff --git a/endpoint-exposer/workflows/alb/link.yaml b/endpoint-exposer/workflows/alb/link.yaml new file mode 100644 index 0000000..0145798 --- /dev/null +++ b/endpoint-exposer/workflows/alb/link.yaml @@ -0,0 +1,56 @@ +steps: + - name: "find k8s namespace" + type: script + file: "$SERVICE_PATH/scripts/alb/fetch_provider_data" + output: + - name: K8S_NAMESPACE + type: environment + - name: ALB_NAME + type: environment + - name: "build context" + type: script + file: "$SERVICE_PATH/scripts/alb/build_context" + output: + - name: SERVICE_ID + type: environment + - name: SERVICE_NAME + type: environment + - name: ACTION_ID + type: environment + - name: ACTION_NAME + type: environment + - name: LINK_ID + type: environment + - name: LINK_NAME + type: environment + - name: SCOPE_ID + type: environment + - name: RULE_PATH + type: environment + - name: "validate_unique_rule" + type: script + file: "$SERVICE_PATH/scripts/alb/validate_unique_rule" + - name: "build_rule" + type: script + file : "$SERVICE_PATH/scripts/alb/build_rule" + output: + - name: SCOPE_RULE + type: environment + - name: "build_ingress" + type: script + file: "$SERVICE_PATH/scripts/alb/build_ingress_with_rule" + output: + - name: INGRESS_FILE + type: file + file: "$OUTPUT_DIR/ingress-$SERVICE_ID-$SCOPE_ID-public.yaml" + - name: apply + type: script + file: "$SERVICE_PATH/scripts/alb/apply" + configuration: + ACTION: apply + DRY_RUN: false + - name: "add_rule_to_service" + type: script + file: "$SERVICE_PATH/scripts/alb/update_service" + configuration: + ACTION: add \ No newline at end of file diff --git a/endpoint-exposer/workflows/alb/read.yaml b/endpoint-exposer/workflows/alb/read.yaml new file mode 100644 index 0000000..8dea452 --- /dev/null +++ b/endpoint-exposer/workflows/alb/read.yaml @@ -0,0 +1,32 @@ +steps: + - name: "find k8s namespace" + type: script + file: "$SERVICE_PATH/scripts/alb/fetch_provider_data" + output: + - name: K8S_NAMESPACE + type: environment + - name: ALB_NAME + type: environment + - name: "build context" + type: script + file: "$SERVICE_PATH/scripts/alb/build_context" + output: + - name: SERVICE_ID + type: environment + - name: SERVICE_NAME + type: environment + - name: ACTION_ID + type: environment + - name: ACTION_NAME + type: environment + - name: LINK_ID + type: environment + - name: LINK_NAME + type: environment + - name: SCOPE_ID + type: environment + - name: RULE_PATH + type: environment + - name: read + type: script + file: "$SERVICE_PATH/scripts/alb/read_ingress" \ No newline at end of file diff --git a/endpoint-exposer/workflows/alb/refresh.yaml b/endpoint-exposer/workflows/alb/refresh.yaml new file mode 100644 index 0000000..6edef06 --- /dev/null +++ b/endpoint-exposer/workflows/alb/refresh.yaml @@ -0,0 +1,7 @@ +include: + - "$SERVICE_PATH/workflows/alb/link.yaml" +steps: + - name: "validate_unique_rule" + action: skip + - name: "add_rule_to_service" + action: skip \ No newline at end of file diff --git a/endpoint-exposer/workflows/alb/unlink.yaml b/endpoint-exposer/workflows/alb/unlink.yaml new file mode 100644 index 0000000..690374a --- /dev/null +++ b/endpoint-exposer/workflows/alb/unlink.yaml @@ -0,0 +1,47 @@ +steps: + - name: "find k8s namespace" + type: script + file: "$SERVICE_PATH/scripts/alb/fetch_provider_data" + output: + - name: K8S_NAMESPACE + type: environment + - name: ALB_NAME + type: environment + - name: "build context" + type: script + file: "$SERVICE_PATH/scripts/alb/build_context" + output: + - name: SERVICE_ID + type: environment + - name: SERVICE_NAME + type: environment + - name: ACTION_ID + type: environment + - name: ACTION_NAME + type: environment + - name: LINK_ID + type: environment + - name: LINK_NAME + type: environment + - name: SCOPE_ID + type: environment + - name: RULE_PATH + type: environment + - name: "build_template" + type: script + file: "$SERVICE_PATH/scripts/alb/build_ingress_without_rule" + output: + - name: INGRESS_FILE + type: file + file: "$OUTPUT_DIR/ingress-$SERVICE_ID-$SCOPE_ID-public.yaml" + - name: apply + type: script + file: "$SERVICE_PATH/scripts/alb/apply" + configuration: + ACTION: apply + DRY_RUN: false + - name: "add_rule_to_service" + type: script + file: "$SERVICE_PATH/scripts/alb/update_service" + configuration: + ACTION: remove \ No newline at end of file diff --git a/endpoint-exposer/workflows/istio/create.yaml b/endpoint-exposer/workflows/istio/create.yaml new file mode 100644 index 0000000..2d28e27 --- /dev/null +++ b/endpoint-exposer/workflows/istio/create.yaml @@ -0,0 +1,56 @@ +steps: + - name: "find k8s namespace" + type: script + file: "$SERVICE_PATH/scripts/istio/fetch_provider_data" + output: + - name: K8S_NAMESPACE + type: environment + - name: ALB_NAME + type: environment + - name: "build context" + type: script + file: "$SERVICE_PATH/scripts/istio/build_context" + output: + - name: SERVICE_ID + type: environment + - name: SERVICE_NAME + type: environment + - name: ACTION_ID + type: environment + - name: ACTION_NAME + type: environment + - name: PUBLIC_DOMAIN + type: environment + - name: PRIVATE_DOMAIN + type: environment + - name: ROUTES_JSON + type: environment + - name: "build httproute" + type: script + file: "$SERVICE_PATH/scripts/istio/build_ingress" + configuration: + TEMPLATE: "$SERVICE_PATH/templates/istio/empty.yaml.tpl" + output: + - name: HTTPROUTE_FILE + type: file + file: "$OUTPUT_DIR/httproute-$SERVICE_ID-public.yaml" + - name: "process routes" + type: script + file: "$SERVICE_PATH/scripts/istio/process_routes" + output: + - name: HTTPROUTE_FILE + type: file + file: "$OUTPUT_DIR/httproute-$SERVICE_ID-public.yaml" + - name: "build dns endpoint" + type: script + file: "$SERVICE_PATH/scripts/dns/build_dns" + output: + - name: DNS_FILE + type: file + file: "$OUTPUT_DIR/dnsendpoint-$SERVICE_ID-public.yaml" + - name: apply + type: script + file: "$SERVICE_PATH/scripts/istio/apply" + configuration: + ACTION: apply + DRY_RUN: false \ No newline at end of file diff --git a/endpoint-exposer/workflows/istio/delete.yaml b/endpoint-exposer/workflows/istio/delete.yaml new file mode 100644 index 0000000..1f4d320 --- /dev/null +++ b/endpoint-exposer/workflows/istio/delete.yaml @@ -0,0 +1,6 @@ +include: + - "$SERVICE_PATH/workflows/istio/create.yaml" +steps: + - name: apply + configuration: + ACTION: delete \ No newline at end of file diff --git a/endpoint-exposer/workflows/istio/link.yaml b/endpoint-exposer/workflows/istio/link.yaml new file mode 100644 index 0000000..8c757ea --- /dev/null +++ b/endpoint-exposer/workflows/istio/link.yaml @@ -0,0 +1,6 @@ +steps: + - name: "link created" + type: script + file: "$SERVICE_PATH/scripts/common/echo" + configuration: + MESSAGE: "link-created" diff --git a/endpoint-exposer/workflows/istio/read.yaml b/endpoint-exposer/workflows/istio/read.yaml new file mode 100644 index 0000000..5251e42 --- /dev/null +++ b/endpoint-exposer/workflows/istio/read.yaml @@ -0,0 +1,32 @@ +steps: + - name: "find k8s namespace" + type: script + file: "$SERVICE_PATH/scripts/istio/fetch_provider_data" + output: + - name: K8S_NAMESPACE + type: environment + - name: ALB_NAME + type: environment + - name: "build context" + type: script + file: "$SERVICE_PATH/scripts/istio/build_context" + output: + - name: SERVICE_ID + type: environment + - name: SERVICE_NAME + type: environment + - name: ACTION_ID + type: environment + - name: ACTION_NAME + type: environment + - name: LINK_ID + type: environment + - name: LINK_NAME + type: environment + - name: SCOPE_ID + type: environment + - name: RULE_PATH + type: environment + - name: read + type: script + file: "$SERVICE_PATH/scripts/istio/read_ingress" \ No newline at end of file diff --git a/endpoint-exposer/workflows/istio/refresh.yaml b/endpoint-exposer/workflows/istio/refresh.yaml new file mode 100644 index 0000000..a920564 --- /dev/null +++ b/endpoint-exposer/workflows/istio/refresh.yaml @@ -0,0 +1,7 @@ +include: + - "$SERVICE_PATH/workflows/istio/link.yaml" +steps: + - name: "validate_unique_rule" + action: skip + - name: "add_rule_to_service" + action: skip \ No newline at end of file diff --git a/endpoint-exposer/workflows/istio/unlink.yaml b/endpoint-exposer/workflows/istio/unlink.yaml new file mode 100644 index 0000000..5ac94f9 --- /dev/null +++ b/endpoint-exposer/workflows/istio/unlink.yaml @@ -0,0 +1,6 @@ +steps: + - name: "link removed" + type: script + file: "$SERVICE_PATH/scripts/common/echo" + configuration: + MESSAGE: "link-removed" diff --git a/endpoint-exposer/workflows/istio/update.yaml b/endpoint-exposer/workflows/istio/update.yaml new file mode 100644 index 0000000..e1e66a6 --- /dev/null +++ b/endpoint-exposer/workflows/istio/update.yaml @@ -0,0 +1,60 @@ +steps: + - name: "find k8s namespace" + type: script + file: "$SERVICE_PATH/scripts/istio/fetch_provider_data" + output: + - name: K8S_NAMESPACE + type: environment + - name: ALB_NAME + type: environment + - name: "build context" + type: script + file: "$SERVICE_PATH/scripts/istio/build_context" + output: + - name: SERVICE_ID + type: environment + - name: SERVICE_NAME + type: environment + - name: ACTION_ID + type: environment + - name: ACTION_NAME + type: environment + - name: PUBLIC_DOMAIN + type: environment + - name: PRIVATE_DOMAIN + type: environment + - name: ROUTES_JSON + type: environment + - name: "fetch existing httproute" + type: script + file: "$SERVICE_PATH/scripts/istio/fetch_httproute" + output: + - name: HTTPROUTE_FILE + type: file + file: "$OUTPUT_DIR/httproute-$SERVICE_ID-public.yaml" + - name: "update httproute hostname" + type: script + file: "$SERVICE_PATH/scripts/istio/update_httproute_hostname" + - name: "clean httproute rules" + type: script + file: "$SERVICE_PATH/scripts/istio/clean_httproute_rules" + - name: "process routes" + type: script + file: "$SERVICE_PATH/scripts/istio/process_routes" + output: + - name: HTTPROUTE_FILE + type: file + file: "$OUTPUT_DIR/httproute-$SERVICE_ID-public.yaml" + - name: "update dns endpoint" + type: script + file: "$SERVICE_PATH/scripts/dns/build_dns" + output: + - name: DNS_FILE + type: file + file: "$OUTPUT_DIR/dnsendpoint-$SERVICE_ID-public.yaml" + - name: apply + type: script + file: "$SERVICE_PATH/scripts/istio/apply" + configuration: + ACTION: apply + DRY_RUN: false From 303f6ce169b4c46ab269a1c1fd55f77dde09fd2c Mon Sep 17 00:00:00 2001 From: Javi Date: Mon, 5 Jan 2026 15:36:15 -0300 Subject: [PATCH 02/20] feat: http routes to handle private and public traffic --- endpoint-exposer/scripts/istio/build_ingress | 23 ++- .../scripts/istio/fetch_httproute | 20 ++- endpoint-exposer/scripts/istio/process_routes | 151 +++++++++++------- .../scripts/istio/update_httproute_hostname | 19 ++- .../templates/istio/empty-private.yaml.tpl | 25 +++ endpoint-exposer/workflows/istio/create.yaml | 19 ++- endpoint-exposer/workflows/istio/update.yaml | 43 ++++- 7 files changed, 218 insertions(+), 82 deletions(-) create mode 100644 endpoint-exposer/templates/istio/empty-private.yaml.tpl diff --git a/endpoint-exposer/scripts/istio/build_ingress b/endpoint-exposer/scripts/istio/build_ingress index bbea5c3..72f849a 100644 --- a/endpoint-exposer/scripts/istio/build_ingress +++ b/endpoint-exposer/scripts/istio/build_ingress @@ -2,13 +2,24 @@ set -euo pipefail -SERVICE_DOMAIN=$(echo "$CONTEXT" | jq -r '.parameters.public_domain // .service.attributes.domain') +# Determine output file - use OUTPUT_FILE if set, otherwise default to public +if [[ -n "${OUTPUT_FILE:-}" ]]; then + HTTPROUTE_FILE="$OUTPUT_FILE" + echo "Using specified output file: $HTTPROUTE_FILE" +else + HTTPROUTE_FILE="$OUTPUT_DIR/httproute-$SERVICE_ID-public.yaml" + echo "Using default output file: $HTTPROUTE_FILE" +fi + +# Determine which domain to use based on template +if [[ "$TEMPLATE" == *"private"* ]]; then + SERVICE_DOMAIN=$(echo "$CONTEXT" | jq -r '.parameters.private_domain // .service.attributes.private_domain') + echo "Creating private HTTPRoute for service $SERVICE_NAME with domain $SERVICE_DOMAIN" +else + SERVICE_DOMAIN=$(echo "$CONTEXT" | jq -r '.parameters.public_domain // .service.attributes.domain') + echo "Creating public HTTPRoute for service $SERVICE_NAME with domain $SERVICE_DOMAIN" +fi -echo "Creating HTTPRoute for service $SERVICE_NAME with domain $SERVICE_DOMAIN" - -echo "Creating public HTTPRoute..." - -HTTPROUTE_FILE="$OUTPUT_DIR/httproute-$SERVICE_ID-public.yaml" CONTEXT_PATH="$OUTPUT_DIR/context-$SERVICE_ID.json" echo "$CONTEXT" > "$CONTEXT_PATH" diff --git a/endpoint-exposer/scripts/istio/fetch_httproute b/endpoint-exposer/scripts/istio/fetch_httproute index 080f4d3..a5ce47a 100755 --- a/endpoint-exposer/scripts/istio/fetch_httproute +++ b/endpoint-exposer/scripts/istio/fetch_httproute @@ -7,12 +7,26 @@ echo "SERVICE_ID: $SERVICE_ID" echo "SERVICE_NAME: $SERVICE_NAME" echo "K8S_NAMESPACE: $K8S_NAMESPACE" +# Determine visibility (default to public if not set) +VISIBILITY="${VISIBILITY:-public}" +echo "Visibility: $VISIBILITY" + # Build the HTTPRoute name using the same pattern as the template -HTTPROUTE_NAME="${SERVICE_NAME}-${SERVICE_ID}-route" +if [[ "$VISIBILITY" == "private" ]]; then + HTTPROUTE_NAME="${SERVICE_NAME}-${SERVICE_ID}-route-private" + TEMPLATE="$SERVICE_PATH/templates/istio/empty-private.yaml.tpl" +else + HTTPROUTE_NAME="${SERVICE_NAME}-${SERVICE_ID}-route" + TEMPLATE="$SERVICE_PATH/templates/istio/empty.yaml.tpl" +fi echo "HTTPRoute name: $HTTPROUTE_NAME" -# Define output file -HTTPROUTE_FILE="$OUTPUT_DIR/httproute-$SERVICE_ID-public.yaml" +# Define output file - use OUTPUT_FILE if set, otherwise default based on visibility +if [[ -n "${OUTPUT_FILE:-}" ]]; then + HTTPROUTE_FILE="$OUTPUT_FILE" +else + HTTPROUTE_FILE="$OUTPUT_DIR/httproute-$SERVICE_ID-$VISIBILITY.yaml" +fi # Create output directory if it doesn't exist mkdir -p "$OUTPUT_DIR" diff --git a/endpoint-exposer/scripts/istio/process_routes b/endpoint-exposer/scripts/istio/process_routes index 383330b..a1e60f5 100755 --- a/endpoint-exposer/scripts/istio/process_routes +++ b/endpoint-exposer/scripts/istio/process_routes @@ -17,25 +17,6 @@ if [[ "$NUM_ROUTES" -eq 0 ]]; then exit 0 fi -# Build the HTTPRoute name using the same pattern as the template -HTTPROUTE_NAME="${SERVICE_NAME}-${SERVICE_ID}-route" -echo "HTTPRoute name: $HTTPROUTE_NAME" - -# Define output file -HTTPROUTE_FILE="$OUTPUT_DIR/httproute-$SERVICE_ID-public.yaml" -export HTTPROUTE_FILE - -# Read the HTTPRoute from the file created in the previous step -if [[ ! -f "$HTTPROUTE_FILE" ]]; then - echo "ERROR: HTTPRoute file not found at $HTTPROUTE_FILE" - exit 1 -fi - -HTTPROUTE=$(cat "$HTTPROUTE_FILE") - -# Save initial HTTPRoute to file -echo "$HTTPROUTE" > "$HTTPROUTE_FILE" - # Get application ID once APPLICATION_ID=$(echo "$CONTEXT" | jq -r '.tags.application_id // empty') if [[ -n "$APPLICATION_ID" ]]; then @@ -63,56 +44,110 @@ SORTED_ROUTES=$(echo "$ROUTES_JSON" | jq 'sort_by( ROUTES_JSON="$SORTED_ROUTES" echo "Routes sorted by specificity (Exact > RegularExpression > PathPrefix)" -# Process each route -for ((i=0; i "$HTTPROUTE_FILE" -echo "HTTPRoute hostname updated to: $PUBLIC_DOMAIN" -echo "HTTPRoute parentRefs set to gateway-public" +echo "HTTPRoute hostname updated to: $DOMAIN" +echo "HTTPRoute parentRefs set to: $GATEWAY" # Debug: Verify the file was saved correctly echo "DEBUG: Verifying saved file..." diff --git a/endpoint-exposer/templates/istio/empty-private.yaml.tpl b/endpoint-exposer/templates/istio/empty-private.yaml.tpl new file mode 100644 index 0000000..ae74cf3 --- /dev/null +++ b/endpoint-exposer/templates/istio/empty-private.yaml.tpl @@ -0,0 +1,25 @@ +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: {{ .service.slug }}-{{ .service.id }}-route-private + namespace: {{ .k8s_namespace }} + labels: + nullplatform: "true" + service: {{ .service.slug }} + service_id: {{ .service.id }} + visibility: private +spec: + parentRefs: + - name: gateway-public + namespace: gateways + hostnames: + - {{ if has . "parameters" }}{{ if has .parameters "private_domain" }}{{ .parameters.private_domain }}{{ else }}{{ .service.attributes.private_domain }}{{ end }}{{ else }}{{ .service.attributes.private_domain }}{{ end }} + rules: + - matches: + - path: + type: PathPrefix + value: / + backendRefs: + - name: response-404 + port: 80 + weight: 0 diff --git a/endpoint-exposer/workflows/istio/create.yaml b/endpoint-exposer/workflows/istio/create.yaml index 2d28e27..ae9efb2 100644 --- a/endpoint-exposer/workflows/istio/create.yaml +++ b/endpoint-exposer/workflows/istio/create.yaml @@ -25,22 +25,35 @@ steps: type: environment - name: ROUTES_JSON type: environment - - name: "build httproute" + - name: "build public httproute" type: script file: "$SERVICE_PATH/scripts/istio/build_ingress" configuration: TEMPLATE: "$SERVICE_PATH/templates/istio/empty.yaml.tpl" output: - - name: HTTPROUTE_FILE + - name: HTTPROUTE_FILE_PUBLIC type: file file: "$OUTPUT_DIR/httproute-$SERVICE_ID-public.yaml" + - name: "build private httproute" + type: script + file: "$SERVICE_PATH/scripts/istio/build_ingress" + configuration: + TEMPLATE: "$SERVICE_PATH/templates/istio/empty-private.yaml.tpl" + OUTPUT_FILE: "$OUTPUT_DIR/httproute-$SERVICE_ID-private.yaml" + output: + - name: HTTPROUTE_FILE_PRIVATE + type: file + file: "$OUTPUT_DIR/httproute-$SERVICE_ID-private.yaml" - name: "process routes" type: script file: "$SERVICE_PATH/scripts/istio/process_routes" output: - - name: HTTPROUTE_FILE + - name: HTTPROUTE_FILE_PUBLIC type: file file: "$OUTPUT_DIR/httproute-$SERVICE_ID-public.yaml" + - name: HTTPROUTE_FILE_PRIVATE + type: file + file: "$OUTPUT_DIR/httproute-$SERVICE_ID-private.yaml" - name: "build dns endpoint" type: script file: "$SERVICE_PATH/scripts/dns/build_dns" diff --git a/endpoint-exposer/workflows/istio/update.yaml b/endpoint-exposer/workflows/istio/update.yaml index e1e66a6..c6e5b6e 100644 --- a/endpoint-exposer/workflows/istio/update.yaml +++ b/endpoint-exposer/workflows/istio/update.yaml @@ -25,26 +25,59 @@ steps: type: environment - name: ROUTES_JSON type: environment - - name: "fetch existing httproute" + - name: "fetch existing public httproute" type: script file: "$SERVICE_PATH/scripts/istio/fetch_httproute" + configuration: + VISIBILITY: "public" output: - - name: HTTPROUTE_FILE + - name: HTTPROUTE_FILE_PUBLIC type: file file: "$OUTPUT_DIR/httproute-$SERVICE_ID-public.yaml" - - name: "update httproute hostname" + - name: "fetch existing private httproute" + type: script + file: "$SERVICE_PATH/scripts/istio/fetch_httproute" + configuration: + VISIBILITY: "private" + OUTPUT_FILE: "$OUTPUT_DIR/httproute-$SERVICE_ID-private.yaml" + output: + - name: HTTPROUTE_FILE_PRIVATE + type: file + file: "$OUTPUT_DIR/httproute-$SERVICE_ID-private.yaml" + - name: "update public httproute hostname" type: script file: "$SERVICE_PATH/scripts/istio/update_httproute_hostname" - - name: "clean httproute rules" + configuration: + HTTPROUTE_FILE: "$OUTPUT_DIR/httproute-$SERVICE_ID-public.yaml" + DOMAIN: "$PUBLIC_DOMAIN" + GATEWAY: "gateway-public" + - name: "update private httproute hostname" + type: script + file: "$SERVICE_PATH/scripts/istio/update_httproute_hostname" + configuration: + HTTPROUTE_FILE: "$OUTPUT_DIR/httproute-$SERVICE_ID-private.yaml" + DOMAIN: "$PRIVATE_DOMAIN" + GATEWAY: "gateway-private" + - name: "clean public httproute rules" type: script file: "$SERVICE_PATH/scripts/istio/clean_httproute_rules" + configuration: + HTTPROUTE_FILE: "$OUTPUT_DIR/httproute-$SERVICE_ID-public.yaml" + - name: "clean private httproute rules" + type: script + file: "$SERVICE_PATH/scripts/istio/clean_httproute_rules" + configuration: + HTTPROUTE_FILE: "$OUTPUT_DIR/httproute-$SERVICE_ID-private.yaml" - name: "process routes" type: script file: "$SERVICE_PATH/scripts/istio/process_routes" output: - - name: HTTPROUTE_FILE + - name: HTTPROUTE_FILE_PUBLIC type: file file: "$OUTPUT_DIR/httproute-$SERVICE_ID-public.yaml" + - name: HTTPROUTE_FILE_PRIVATE + type: file + file: "$OUTPUT_DIR/httproute-$SERVICE_ID-private.yaml" - name: "update dns endpoint" type: script file: "$SERVICE_PATH/scripts/dns/build_dns" From c95b552ea74876bece0af2dda40fb35bf02a9879 Mon Sep 17 00:00:00 2001 From: Javi Date: Mon, 5 Jan 2026 15:47:44 -0300 Subject: [PATCH 03/20] feat: http routes to handle private and public traffic --- .../scripts/dns/build_dns_endpoint | 34 ++++++++++++++----- .../istio/dns-endpoint-private.yaml.tpl | 17 ++++++++++ .../templates/istio/empty-private.yaml.tpl | 2 +- endpoint-exposer/workflows/istio/create.yaml | 15 ++++++-- endpoint-exposer/workflows/istio/update.yaml | 15 ++++++-- 5 files changed, 69 insertions(+), 14 deletions(-) create mode 100644 endpoint-exposer/templates/istio/dns-endpoint-private.yaml.tpl diff --git a/endpoint-exposer/scripts/dns/build_dns_endpoint b/endpoint-exposer/scripts/dns/build_dns_endpoint index c43327f..1340a11 100755 --- a/endpoint-exposer/scripts/dns/build_dns_endpoint +++ b/endpoint-exposer/scripts/dns/build_dns_endpoint @@ -4,26 +4,42 @@ set -euo pipefail echo "=== DEBUG: Starting build_dns_endpoint ===" -SERVICE_DOMAIN=$(echo "$CONTEXT" | jq -r '.parameters.public_domain') -echo "DEBUG: SERVICE_DOMAIN=$SERVICE_DOMAIN" +# Determine visibility (default to public if not set) +VISIBILITY="${VISIBILITY:-public}" +echo "DEBUG: VISIBILITY=$VISIBILITY" + +# Select domain and gateway based on visibility +if [[ "$VISIBILITY" == "private" ]]; then + SERVICE_DOMAIN=$(echo "$CONTEXT" | jq -r '.parameters.private_domain') + GATEWAY_NAME=${PRIVATE_GATEWAY_NAME:-"gateway-private"} + DNS_TEMPLATE="$SERVICE_PATH/templates/istio/dns-endpoint-private.yaml.tpl" + DNS_FILE="$OUTPUT_DIR/dnsendpoint-$SERVICE_ID-private.yaml" + echo "DEBUG: Building PRIVATE DNS endpoint" +else + SERVICE_DOMAIN=$(echo "$CONTEXT" | jq -r '.parameters.public_domain') + GATEWAY_NAME=${PUBLIC_GATEWAY_NAME:-"gateway-public"} + DNS_TEMPLATE="$SERVICE_PATH/templates/istio/dns-endpoint.yaml.tpl" + DNS_FILE="$OUTPUT_DIR/dnsendpoint-$SERVICE_ID-public.yaml" + echo "DEBUG: Building PUBLIC DNS endpoint" +fi +echo "DEBUG: SERVICE_DOMAIN=$SERVICE_DOMAIN" +echo "DEBUG: GATEWAY_NAME=$GATEWAY_NAME" -PUBLIC_GATEWAY_NAME=${PUBLIC_GATEWAY_NAME:-"gateway-public"} GATEWAY_NAMESPACE=${GATEWAY_NAMESPACE:-"gateways"} -echo "DEBUG: Fetching gateway IP from $PUBLIC_GATEWAY_NAME..." -GATEWAY_IP=$(kubectl get gateway -n "$GATEWAY_NAMESPACE" "$PUBLIC_GATEWAY_NAME" -o jsonpath='{.status.addresses[0].value}') +echo "DEBUG: Fetching gateway IP from $GATEWAY_NAME..." +GATEWAY_IP=$(kubectl get gateway -n "$GATEWAY_NAMESPACE" "$GATEWAY_NAME" -o jsonpath='{.status.addresses[0].value}') echo "DEBUG: GATEWAY_IP=$GATEWAY_IP" if [[ -z "$GATEWAY_IP" || "$GATEWAY_IP" == "null" ]]; then - echo "ERROR: Could not retrieve gateway IP from $PUBLIC_GATEWAY_NAME" + echo "ERROR: Could not retrieve gateway IP from $GATEWAY_NAME" exit 1 fi echo "Creating DNSEndpoint for service $SERVICE_NAME with domain $SERVICE_DOMAIN" -DNS_FILE="$OUTPUT_DIR/dnsendpoint-$SERVICE_ID-public.yaml" -CONTEXT_PATH="$OUTPUT_DIR/context-dns-$SERVICE_ID.json" +CONTEXT_PATH="$OUTPUT_DIR/context-dns-$SERVICE_ID-$VISIBILITY.json" # Add gateway_ip to context CONTEXT_WITH_IP=$(echo "$CONTEXT" | jq --arg gateway_ip "$GATEWAY_IP" '. + {gateway_ip: $gateway_ip}') @@ -33,7 +49,7 @@ echo "$CONTEXT_WITH_IP" > "$CONTEXT_PATH" echo "Building DNSEndpoint Template to $DNS_FILE" gomplate -c .="$CONTEXT_PATH" \ - --file "$SERVICE_PATH/templates/istio/dns-endpoint.yaml.tpl" \ + --file "$DNS_TEMPLATE" \ --out "$DNS_FILE" rm "$CONTEXT_PATH" diff --git a/endpoint-exposer/templates/istio/dns-endpoint-private.yaml.tpl b/endpoint-exposer/templates/istio/dns-endpoint-private.yaml.tpl new file mode 100644 index 0000000..5bcdc5c --- /dev/null +++ b/endpoint-exposer/templates/istio/dns-endpoint-private.yaml.tpl @@ -0,0 +1,17 @@ +apiVersion: externaldns.k8s.io/v1alpha1 +kind: DNSEndpoint +metadata: + name: {{ .service.slug }}-{{ .service.id }}-dns-private + namespace: {{ .k8s_namespace }} + labels: + nullplatform: "true" + service: {{ .service.slug }} + service_id: {{ .service.id }} + visibility: private +spec: + endpoints: + - dnsName: {{ if has . "parameters" }}{{ if has .parameters "private_domain" }}{{ .parameters.private_domain }}{{ else }}{{ .service.attributes.private_domain }}{{ end }}{{ else }}{{ .service.attributes.private_domain }}{{ end }} + recordTTL: 60 + recordType: A + targets: + - "{{ .gateway_ip }}" diff --git a/endpoint-exposer/templates/istio/empty-private.yaml.tpl b/endpoint-exposer/templates/istio/empty-private.yaml.tpl index ae74cf3..65698f2 100644 --- a/endpoint-exposer/templates/istio/empty-private.yaml.tpl +++ b/endpoint-exposer/templates/istio/empty-private.yaml.tpl @@ -10,7 +10,7 @@ metadata: visibility: private spec: parentRefs: - - name: gateway-public + - name: gateway-private namespace: gateways hostnames: - {{ if has . "parameters" }}{{ if has .parameters "private_domain" }}{{ .parameters.private_domain }}{{ else }}{{ .service.attributes.private_domain }}{{ end }}{{ else }}{{ .service.attributes.private_domain }}{{ end }} diff --git a/endpoint-exposer/workflows/istio/create.yaml b/endpoint-exposer/workflows/istio/create.yaml index ae9efb2..538d8f7 100644 --- a/endpoint-exposer/workflows/istio/create.yaml +++ b/endpoint-exposer/workflows/istio/create.yaml @@ -54,13 +54,24 @@ steps: - name: HTTPROUTE_FILE_PRIVATE type: file file: "$OUTPUT_DIR/httproute-$SERVICE_ID-private.yaml" - - name: "build dns endpoint" + - name: "build public dns endpoint" type: script file: "$SERVICE_PATH/scripts/dns/build_dns" + configuration: + VISIBILITY: "public" output: - - name: DNS_FILE + - name: DNS_FILE_PUBLIC type: file file: "$OUTPUT_DIR/dnsendpoint-$SERVICE_ID-public.yaml" + - name: "build private dns endpoint" + type: script + file: "$SERVICE_PATH/scripts/dns/build_dns" + configuration: + VISIBILITY: "private" + output: + - name: DNS_FILE_PRIVATE + type: file + file: "$OUTPUT_DIR/dnsendpoint-$SERVICE_ID-private.yaml" - name: apply type: script file: "$SERVICE_PATH/scripts/istio/apply" diff --git a/endpoint-exposer/workflows/istio/update.yaml b/endpoint-exposer/workflows/istio/update.yaml index c6e5b6e..41cbd4b 100644 --- a/endpoint-exposer/workflows/istio/update.yaml +++ b/endpoint-exposer/workflows/istio/update.yaml @@ -78,13 +78,24 @@ steps: - name: HTTPROUTE_FILE_PRIVATE type: file file: "$OUTPUT_DIR/httproute-$SERVICE_ID-private.yaml" - - name: "update dns endpoint" + - name: "update public dns endpoint" type: script file: "$SERVICE_PATH/scripts/dns/build_dns" + configuration: + VISIBILITY: "public" output: - - name: DNS_FILE + - name: DNS_FILE_PUBLIC type: file file: "$OUTPUT_DIR/dnsendpoint-$SERVICE_ID-public.yaml" + - name: "update private dns endpoint" + type: script + file: "$SERVICE_PATH/scripts/dns/build_dns" + configuration: + VISIBILITY: "private" + output: + - name: DNS_FILE_PRIVATE + type: file + file: "$OUTPUT_DIR/dnsendpoint-$SERVICE_ID-private.yaml" - name: apply type: script file: "$SERVICE_PATH/scripts/istio/apply" From d63abe289ed3ea5415a7221f68ccb21e3f15cbca Mon Sep 17 00:00:00 2001 From: Javi Date: Mon, 5 Jan 2026 16:08:47 -0300 Subject: [PATCH 04/20] feat: http routes to handle private and public traffic --- .../scripts/dns/build_dns_endpoint | 10 +++--- endpoint-exposer/scripts/istio/build_ingress | 4 +-- .../scripts/istio/fetch_httproute | 6 ++-- endpoint-exposer/scripts/istio/process_routes | 14 ++++---- ...aml.tpl => dns-endpoint-internal.yaml.tpl} | 4 +-- ...ivate.yaml.tpl => empty-internal.yaml.tpl} | 6 ++-- endpoint-exposer/workflows/istio/create.yaml | 24 +++++++------- endpoint-exposer/workflows/istio/update.yaml | 32 +++++++++---------- 8 files changed, 50 insertions(+), 50 deletions(-) rename endpoint-exposer/templates/istio/{dns-endpoint-private.yaml.tpl => dns-endpoint-internal.yaml.tpl} (86%) rename endpoint-exposer/templates/istio/{empty-private.yaml.tpl => empty-internal.yaml.tpl} (85%) diff --git a/endpoint-exposer/scripts/dns/build_dns_endpoint b/endpoint-exposer/scripts/dns/build_dns_endpoint index 1340a11..a5bc6ef 100755 --- a/endpoint-exposer/scripts/dns/build_dns_endpoint +++ b/endpoint-exposer/scripts/dns/build_dns_endpoint @@ -9,12 +9,12 @@ VISIBILITY="${VISIBILITY:-public}" echo "DEBUG: VISIBILITY=$VISIBILITY" # Select domain and gateway based on visibility -if [[ "$VISIBILITY" == "private" ]]; then +if [[ "$VISIBILITY" == "internal" ]]; then SERVICE_DOMAIN=$(echo "$CONTEXT" | jq -r '.parameters.private_domain') - GATEWAY_NAME=${PRIVATE_GATEWAY_NAME:-"gateway-private"} - DNS_TEMPLATE="$SERVICE_PATH/templates/istio/dns-endpoint-private.yaml.tpl" - DNS_FILE="$OUTPUT_DIR/dnsendpoint-$SERVICE_ID-private.yaml" - echo "DEBUG: Building PRIVATE DNS endpoint" + GATEWAY_NAME=${INTERNAL_GATEWAY_NAME:-"gateway-internal"} + DNS_TEMPLATE="$SERVICE_PATH/templates/istio/dns-endpoint-internal.yaml.tpl" + DNS_FILE="$OUTPUT_DIR/dnsendpoint-$SERVICE_ID-internal.yaml" + echo "DEBUG: Building INTERNAL DNS endpoint" else SERVICE_DOMAIN=$(echo "$CONTEXT" | jq -r '.parameters.public_domain') GATEWAY_NAME=${PUBLIC_GATEWAY_NAME:-"gateway-public"} diff --git a/endpoint-exposer/scripts/istio/build_ingress b/endpoint-exposer/scripts/istio/build_ingress index 72f849a..34fff61 100644 --- a/endpoint-exposer/scripts/istio/build_ingress +++ b/endpoint-exposer/scripts/istio/build_ingress @@ -12,9 +12,9 @@ else fi # Determine which domain to use based on template -if [[ "$TEMPLATE" == *"private"* ]]; then +if [[ "$TEMPLATE" == *"internal"* ]]; then SERVICE_DOMAIN=$(echo "$CONTEXT" | jq -r '.parameters.private_domain // .service.attributes.private_domain') - echo "Creating private HTTPRoute for service $SERVICE_NAME with domain $SERVICE_DOMAIN" + echo "Creating internal HTTPRoute for service $SERVICE_NAME with domain $SERVICE_DOMAIN" else SERVICE_DOMAIN=$(echo "$CONTEXT" | jq -r '.parameters.public_domain // .service.attributes.domain') echo "Creating public HTTPRoute for service $SERVICE_NAME with domain $SERVICE_DOMAIN" diff --git a/endpoint-exposer/scripts/istio/fetch_httproute b/endpoint-exposer/scripts/istio/fetch_httproute index a5ce47a..a9835b4 100755 --- a/endpoint-exposer/scripts/istio/fetch_httproute +++ b/endpoint-exposer/scripts/istio/fetch_httproute @@ -12,9 +12,9 @@ VISIBILITY="${VISIBILITY:-public}" echo "Visibility: $VISIBILITY" # Build the HTTPRoute name using the same pattern as the template -if [[ "$VISIBILITY" == "private" ]]; then - HTTPROUTE_NAME="${SERVICE_NAME}-${SERVICE_ID}-route-private" - TEMPLATE="$SERVICE_PATH/templates/istio/empty-private.yaml.tpl" +if [[ "$VISIBILITY" == "internal" ]]; then + HTTPROUTE_NAME="${SERVICE_NAME}-${SERVICE_ID}-route-internal" + TEMPLATE="$SERVICE_PATH/templates/istio/empty-internal.yaml.tpl" else HTTPROUTE_NAME="${SERVICE_NAME}-${SERVICE_ID}-route" TEMPLATE="$SERVICE_PATH/templates/istio/empty.yaml.tpl" diff --git a/endpoint-exposer/scripts/istio/process_routes b/endpoint-exposer/scripts/istio/process_routes index a1e60f5..44bb233 100755 --- a/endpoint-exposer/scripts/istio/process_routes +++ b/endpoint-exposer/scripts/istio/process_routes @@ -48,13 +48,13 @@ echo "Routes sorted by specificity (Exact > RegularExpression > PathPrefix)" echo "" echo "=== Separating routes by visibility ===" PUBLIC_ROUTES=$(echo "$ROUTES_JSON" | jq '[.[] | select(.visibility == "public")]') -PRIVATE_ROUTES=$(echo "$ROUTES_JSON" | jq '[.[] | select(.visibility == "private")]') +INTERNAL_ROUTES=$(echo "$ROUTES_JSON" | jq '[.[] | select(.visibility == "internal")]') NUM_PUBLIC=$(echo "$PUBLIC_ROUTES" | jq 'length') -NUM_PRIVATE=$(echo "$PRIVATE_ROUTES" | jq 'length') +NUM_INTERNAL=$(echo "$INTERNAL_ROUTES" | jq 'length') echo "Public routes: $NUM_PUBLIC" -echo "Private routes: $NUM_PRIVATE" +echo "Internal routes: $NUM_INTERNAL" # Function to process routes for a specific visibility process_routes_for_visibility() { @@ -75,8 +75,8 @@ process_routes_for_visibility() { HTTPROUTE_FILE="$OUTPUT_DIR/httproute-$SERVICE_ID-public.yaml" HTTPROUTE_NAME="${SERVICE_NAME}-${SERVICE_ID}-route" else - HTTPROUTE_FILE="$OUTPUT_DIR/httproute-$SERVICE_ID-private.yaml" - HTTPROUTE_NAME="${SERVICE_NAME}-${SERVICE_ID}-route-private" + HTTPROUTE_FILE="$OUTPUT_DIR/httproute-$SERVICE_ID-internal.yaml" + HTTPROUTE_NAME="${SERVICE_NAME}-${SERVICE_ID}-route-internal" fi export HTTPROUTE_FILE @@ -146,8 +146,8 @@ process_routes_for_visibility() { # Process public routes process_routes_for_visibility "public" "$PUBLIC_ROUTES" "$NUM_PUBLIC" -# Process private routes -process_routes_for_visibility "private" "$PRIVATE_ROUTES" "$NUM_PRIVATE" +# Process internal routes +process_routes_for_visibility "internal" "$INTERNAL_ROUTES" "$NUM_INTERNAL" echo "" echo "=== All routes processed successfully ===" diff --git a/endpoint-exposer/templates/istio/dns-endpoint-private.yaml.tpl b/endpoint-exposer/templates/istio/dns-endpoint-internal.yaml.tpl similarity index 86% rename from endpoint-exposer/templates/istio/dns-endpoint-private.yaml.tpl rename to endpoint-exposer/templates/istio/dns-endpoint-internal.yaml.tpl index 5bcdc5c..8cb3198 100644 --- a/endpoint-exposer/templates/istio/dns-endpoint-private.yaml.tpl +++ b/endpoint-exposer/templates/istio/dns-endpoint-internal.yaml.tpl @@ -1,13 +1,13 @@ apiVersion: externaldns.k8s.io/v1alpha1 kind: DNSEndpoint metadata: - name: {{ .service.slug }}-{{ .service.id }}-dns-private + name: {{ .service.slug }}-{{ .service.id }}-dns-internal namespace: {{ .k8s_namespace }} labels: nullplatform: "true" service: {{ .service.slug }} service_id: {{ .service.id }} - visibility: private + visibility: internal spec: endpoints: - dnsName: {{ if has . "parameters" }}{{ if has .parameters "private_domain" }}{{ .parameters.private_domain }}{{ else }}{{ .service.attributes.private_domain }}{{ end }}{{ else }}{{ .service.attributes.private_domain }}{{ end }} diff --git a/endpoint-exposer/templates/istio/empty-private.yaml.tpl b/endpoint-exposer/templates/istio/empty-internal.yaml.tpl similarity index 85% rename from endpoint-exposer/templates/istio/empty-private.yaml.tpl rename to endpoint-exposer/templates/istio/empty-internal.yaml.tpl index 65698f2..58df21c 100644 --- a/endpoint-exposer/templates/istio/empty-private.yaml.tpl +++ b/endpoint-exposer/templates/istio/empty-internal.yaml.tpl @@ -1,16 +1,16 @@ apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: - name: {{ .service.slug }}-{{ .service.id }}-route-private + name: {{ .service.slug }}-{{ .service.id }}-route-internal namespace: {{ .k8s_namespace }} labels: nullplatform: "true" service: {{ .service.slug }} service_id: {{ .service.id }} - visibility: private + visibility: internal spec: parentRefs: - - name: gateway-private + - name: gateway-internal namespace: gateways hostnames: - {{ if has . "parameters" }}{{ if has .parameters "private_domain" }}{{ .parameters.private_domain }}{{ else }}{{ .service.attributes.private_domain }}{{ end }}{{ else }}{{ .service.attributes.private_domain }}{{ end }} diff --git a/endpoint-exposer/workflows/istio/create.yaml b/endpoint-exposer/workflows/istio/create.yaml index 538d8f7..9247872 100644 --- a/endpoint-exposer/workflows/istio/create.yaml +++ b/endpoint-exposer/workflows/istio/create.yaml @@ -21,7 +21,7 @@ steps: type: environment - name: PUBLIC_DOMAIN type: environment - - name: PRIVATE_DOMAIN + - name: INTERNAL_DOMAIN type: environment - name: ROUTES_JSON type: environment @@ -34,16 +34,16 @@ steps: - name: HTTPROUTE_FILE_PUBLIC type: file file: "$OUTPUT_DIR/httproute-$SERVICE_ID-public.yaml" - - name: "build private httproute" + - name: "build internal httproute" type: script file: "$SERVICE_PATH/scripts/istio/build_ingress" configuration: - TEMPLATE: "$SERVICE_PATH/templates/istio/empty-private.yaml.tpl" - OUTPUT_FILE: "$OUTPUT_DIR/httproute-$SERVICE_ID-private.yaml" + TEMPLATE: "$SERVICE_PATH/templates/istio/empty-internal.yaml.tpl" + OUTPUT_FILE: "$OUTPUT_DIR/httproute-$SERVICE_ID-internal.yaml" output: - - name: HTTPROUTE_FILE_PRIVATE + - name: HTTPROUTE_FILE_INTERNAL type: file - file: "$OUTPUT_DIR/httproute-$SERVICE_ID-private.yaml" + file: "$OUTPUT_DIR/httproute-$SERVICE_ID-internal.yaml" - name: "process routes" type: script file: "$SERVICE_PATH/scripts/istio/process_routes" @@ -51,9 +51,9 @@ steps: - name: HTTPROUTE_FILE_PUBLIC type: file file: "$OUTPUT_DIR/httproute-$SERVICE_ID-public.yaml" - - name: HTTPROUTE_FILE_PRIVATE + - name: HTTPROUTE_FILE_INTERNAL type: file - file: "$OUTPUT_DIR/httproute-$SERVICE_ID-private.yaml" + file: "$OUTPUT_DIR/httproute-$SERVICE_ID-internal.yaml" - name: "build public dns endpoint" type: script file: "$SERVICE_PATH/scripts/dns/build_dns" @@ -63,15 +63,15 @@ steps: - name: DNS_FILE_PUBLIC type: file file: "$OUTPUT_DIR/dnsendpoint-$SERVICE_ID-public.yaml" - - name: "build private dns endpoint" + - name: "build internal dns endpoint" type: script file: "$SERVICE_PATH/scripts/dns/build_dns" configuration: - VISIBILITY: "private" + VISIBILITY: "internal" output: - - name: DNS_FILE_PRIVATE + - name: DNS_FILE_INTERNAL type: file - file: "$OUTPUT_DIR/dnsendpoint-$SERVICE_ID-private.yaml" + file: "$OUTPUT_DIR/dnsendpoint-$SERVICE_ID-internal.yaml" - name: apply type: script file: "$SERVICE_PATH/scripts/istio/apply" diff --git a/endpoint-exposer/workflows/istio/update.yaml b/endpoint-exposer/workflows/istio/update.yaml index 41cbd4b..f5c0819 100644 --- a/endpoint-exposer/workflows/istio/update.yaml +++ b/endpoint-exposer/workflows/istio/update.yaml @@ -34,16 +34,16 @@ steps: - name: HTTPROUTE_FILE_PUBLIC type: file file: "$OUTPUT_DIR/httproute-$SERVICE_ID-public.yaml" - - name: "fetch existing private httproute" + - name: "fetch existing internal httproute" type: script file: "$SERVICE_PATH/scripts/istio/fetch_httproute" configuration: - VISIBILITY: "private" - OUTPUT_FILE: "$OUTPUT_DIR/httproute-$SERVICE_ID-private.yaml" + VISIBILITY: "internal" + OUTPUT_FILE: "$OUTPUT_DIR/httproute-$SERVICE_ID-internal.yaml" output: - - name: HTTPROUTE_FILE_PRIVATE + - name: HTTPROUTE_FILE_INTERNAL type: file - file: "$OUTPUT_DIR/httproute-$SERVICE_ID-private.yaml" + file: "$OUTPUT_DIR/httproute-$SERVICE_ID-internal.yaml" - name: "update public httproute hostname" type: script file: "$SERVICE_PATH/scripts/istio/update_httproute_hostname" @@ -51,23 +51,23 @@ steps: HTTPROUTE_FILE: "$OUTPUT_DIR/httproute-$SERVICE_ID-public.yaml" DOMAIN: "$PUBLIC_DOMAIN" GATEWAY: "gateway-public" - - name: "update private httproute hostname" + - name: "update internal httproute hostname" type: script file: "$SERVICE_PATH/scripts/istio/update_httproute_hostname" configuration: - HTTPROUTE_FILE: "$OUTPUT_DIR/httproute-$SERVICE_ID-private.yaml" + HTTPROUTE_FILE: "$OUTPUT_DIR/httproute-$SERVICE_ID-internal.yaml" DOMAIN: "$PRIVATE_DOMAIN" - GATEWAY: "gateway-private" + GATEWAY: "gateway-internal" - name: "clean public httproute rules" type: script file: "$SERVICE_PATH/scripts/istio/clean_httproute_rules" configuration: HTTPROUTE_FILE: "$OUTPUT_DIR/httproute-$SERVICE_ID-public.yaml" - - name: "clean private httproute rules" + - name: "clean internal httproute rules" type: script file: "$SERVICE_PATH/scripts/istio/clean_httproute_rules" configuration: - HTTPROUTE_FILE: "$OUTPUT_DIR/httproute-$SERVICE_ID-private.yaml" + HTTPROUTE_FILE: "$OUTPUT_DIR/httproute-$SERVICE_ID-internal.yaml" - name: "process routes" type: script file: "$SERVICE_PATH/scripts/istio/process_routes" @@ -75,9 +75,9 @@ steps: - name: HTTPROUTE_FILE_PUBLIC type: file file: "$OUTPUT_DIR/httproute-$SERVICE_ID-public.yaml" - - name: HTTPROUTE_FILE_PRIVATE + - name: HTTPROUTE_FILE_INTERNAL type: file - file: "$OUTPUT_DIR/httproute-$SERVICE_ID-private.yaml" + file: "$OUTPUT_DIR/httproute-$SERVICE_ID-internal.yaml" - name: "update public dns endpoint" type: script file: "$SERVICE_PATH/scripts/dns/build_dns" @@ -87,15 +87,15 @@ steps: - name: DNS_FILE_PUBLIC type: file file: "$OUTPUT_DIR/dnsendpoint-$SERVICE_ID-public.yaml" - - name: "update private dns endpoint" + - name: "update internal dns endpoint" type: script file: "$SERVICE_PATH/scripts/dns/build_dns" configuration: - VISIBILITY: "private" + VISIBILITY: "internal" output: - - name: DNS_FILE_PRIVATE + - name: DNS_FILE_INTERNAL type: file - file: "$OUTPUT_DIR/dnsendpoint-$SERVICE_ID-private.yaml" + file: "$OUTPUT_DIR/dnsendpoint-$SERVICE_ID-internal.yaml" - name: apply type: script file: "$SERVICE_PATH/scripts/istio/apply" From 470b16d045a65de109c4f230852f6d4dd91a9558 Mon Sep 17 00:00:00 2001 From: Javi Date: Mon, 5 Jan 2026 16:28:02 -0300 Subject: [PATCH 05/20] feat: http routes to handle private and public traffic --- endpoint-exposer/scripts/istio/build_ingress | 23 ++++++++++--------- .../scripts/istio/clean_httproute_rules | 5 ++++ .../scripts/istio/fetch_httproute | 2 ++ .../scripts/istio/update_httproute_hostname | 5 ++++ endpoint-exposer/workflows/istio/create.yaml | 4 +--- endpoint-exposer/workflows/istio/update.yaml | 12 ++++------ 6 files changed, 30 insertions(+), 21 deletions(-) diff --git a/endpoint-exposer/scripts/istio/build_ingress b/endpoint-exposer/scripts/istio/build_ingress index 34fff61..ad54d62 100644 --- a/endpoint-exposer/scripts/istio/build_ingress +++ b/endpoint-exposer/scripts/istio/build_ingress @@ -2,22 +2,19 @@ set -euo pipefail -# Determine output file - use OUTPUT_FILE if set, otherwise default to public -if [[ -n "${OUTPUT_FILE:-}" ]]; then - HTTPROUTE_FILE="$OUTPUT_FILE" - echo "Using specified output file: $HTTPROUTE_FILE" -else - HTTPROUTE_FILE="$OUTPUT_DIR/httproute-$SERVICE_ID-public.yaml" - echo "Using default output file: $HTTPROUTE_FILE" -fi - -# Determine which domain to use based on template +# Determine which domain to use and output file based on template if [[ "$TEMPLATE" == *"internal"* ]]; then + # Internal HTTPRoute SERVICE_DOMAIN=$(echo "$CONTEXT" | jq -r '.parameters.private_domain // .service.attributes.private_domain') + HTTPROUTE_FILE="${OUTPUT_FILE:-$OUTPUT_DIR/httproute-$SERVICE_ID-internal.yaml}" echo "Creating internal HTTPRoute for service $SERVICE_NAME with domain $SERVICE_DOMAIN" + echo "Output file: $HTTPROUTE_FILE" else + # Public HTTPRoute SERVICE_DOMAIN=$(echo "$CONTEXT" | jq -r '.parameters.public_domain // .service.attributes.domain') + HTTPROUTE_FILE="${OUTPUT_FILE:-$OUTPUT_DIR/httproute-$SERVICE_ID-public.yaml}" echo "Creating public HTTPRoute for service $SERVICE_NAME with domain $SERVICE_DOMAIN" + echo "Output file: $HTTPROUTE_FILE" fi CONTEXT_PATH="$OUTPUT_DIR/context-$SERVICE_ID.json" @@ -30,4 +27,8 @@ gomplate -c .="$CONTEXT_PATH" \ --file "$TEMPLATE" \ --out "$HTTPROUTE_FILE" -rm "$CONTEXT_PATH" \ No newline at end of file +rm "$CONTEXT_PATH" + +# Export the file path for the workflow +export HTTPROUTE_FILE +echo "HTTPRoute created at: $HTTPROUTE_FILE" \ No newline at end of file diff --git a/endpoint-exposer/scripts/istio/clean_httproute_rules b/endpoint-exposer/scripts/istio/clean_httproute_rules index 85179f6..55c7dda 100755 --- a/endpoint-exposer/scripts/istio/clean_httproute_rules +++ b/endpoint-exposer/scripts/istio/clean_httproute_rules @@ -2,6 +2,11 @@ set -euo pipefail +# If HTTPROUTE_FILE_VAR is provided, use it to get the file path from that variable +if [[ -n "${HTTPROUTE_FILE_VAR:-}" ]]; then + HTTPROUTE_FILE="${!HTTPROUTE_FILE_VAR}" +fi + echo "=== Cleaning HTTPRoute rules ===" echo "HTTPROUTE_FILE: $HTTPROUTE_FILE" diff --git a/endpoint-exposer/scripts/istio/fetch_httproute b/endpoint-exposer/scripts/istio/fetch_httproute index a9835b4..a30d3c7 100755 --- a/endpoint-exposer/scripts/istio/fetch_httproute +++ b/endpoint-exposer/scripts/istio/fetch_httproute @@ -56,4 +56,6 @@ else echo "New HTTPRoute created from template" fi +# Export the file path for the workflow +export HTTPROUTE_FILE echo "HTTPRoute file ready at: $HTTPROUTE_FILE" diff --git a/endpoint-exposer/scripts/istio/update_httproute_hostname b/endpoint-exposer/scripts/istio/update_httproute_hostname index 7b22353..7f7b044 100755 --- a/endpoint-exposer/scripts/istio/update_httproute_hostname +++ b/endpoint-exposer/scripts/istio/update_httproute_hostname @@ -2,6 +2,11 @@ set -euo pipefail +# If HTTPROUTE_FILE_VAR is provided, use it to get the file path from that variable +if [[ -n "${HTTPROUTE_FILE_VAR:-}" ]]; then + HTTPROUTE_FILE="${!HTTPROUTE_FILE_VAR}" +fi + # Use DOMAIN and GATEWAY if provided via configuration, otherwise use PUBLIC_DOMAIN and gateway-public DOMAIN="${DOMAIN:-${PUBLIC_DOMAIN}}" GATEWAY="${GATEWAY:-gateway-public}" diff --git a/endpoint-exposer/workflows/istio/create.yaml b/endpoint-exposer/workflows/istio/create.yaml index 9247872..3290a23 100644 --- a/endpoint-exposer/workflows/istio/create.yaml +++ b/endpoint-exposer/workflows/istio/create.yaml @@ -39,11 +39,9 @@ steps: file: "$SERVICE_PATH/scripts/istio/build_ingress" configuration: TEMPLATE: "$SERVICE_PATH/templates/istio/empty-internal.yaml.tpl" - OUTPUT_FILE: "$OUTPUT_DIR/httproute-$SERVICE_ID-internal.yaml" output: - name: HTTPROUTE_FILE_INTERNAL - type: file - file: "$OUTPUT_DIR/httproute-$SERVICE_ID-internal.yaml" + type: environment - name: "process routes" type: script file: "$SERVICE_PATH/scripts/istio/process_routes" diff --git a/endpoint-exposer/workflows/istio/update.yaml b/endpoint-exposer/workflows/istio/update.yaml index f5c0819..6bbd32d 100644 --- a/endpoint-exposer/workflows/istio/update.yaml +++ b/endpoint-exposer/workflows/istio/update.yaml @@ -39,35 +39,33 @@ steps: file: "$SERVICE_PATH/scripts/istio/fetch_httproute" configuration: VISIBILITY: "internal" - OUTPUT_FILE: "$OUTPUT_DIR/httproute-$SERVICE_ID-internal.yaml" output: - name: HTTPROUTE_FILE_INTERNAL - type: file - file: "$OUTPUT_DIR/httproute-$SERVICE_ID-internal.yaml" + type: environment - name: "update public httproute hostname" type: script file: "$SERVICE_PATH/scripts/istio/update_httproute_hostname" configuration: - HTTPROUTE_FILE: "$OUTPUT_DIR/httproute-$SERVICE_ID-public.yaml" + HTTPROUTE_FILE_VAR: "HTTPROUTE_FILE_PUBLIC" DOMAIN: "$PUBLIC_DOMAIN" GATEWAY: "gateway-public" - name: "update internal httproute hostname" type: script file: "$SERVICE_PATH/scripts/istio/update_httproute_hostname" configuration: - HTTPROUTE_FILE: "$OUTPUT_DIR/httproute-$SERVICE_ID-internal.yaml" + HTTPROUTE_FILE_VAR: "HTTPROUTE_FILE_INTERNAL" DOMAIN: "$PRIVATE_DOMAIN" GATEWAY: "gateway-internal" - name: "clean public httproute rules" type: script file: "$SERVICE_PATH/scripts/istio/clean_httproute_rules" configuration: - HTTPROUTE_FILE: "$OUTPUT_DIR/httproute-$SERVICE_ID-public.yaml" + HTTPROUTE_FILE_VAR: "HTTPROUTE_FILE_PUBLIC" - name: "clean internal httproute rules" type: script file: "$SERVICE_PATH/scripts/istio/clean_httproute_rules" configuration: - HTTPROUTE_FILE: "$OUTPUT_DIR/httproute-$SERVICE_ID-internal.yaml" + HTTPROUTE_FILE_VAR: "HTTPROUTE_FILE_INTERNAL" - name: "process routes" type: script file: "$SERVICE_PATH/scripts/istio/process_routes" From 9518ebd9b280299a1263c972d1f603a51d095f74 Mon Sep 17 00:00:00 2001 From: Javi Date: Mon, 5 Jan 2026 16:40:22 -0300 Subject: [PATCH 06/20] chore: link to public gateway --- endpoint-exposer/templates/istio/empty-internal.yaml.tpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/endpoint-exposer/templates/istio/empty-internal.yaml.tpl b/endpoint-exposer/templates/istio/empty-internal.yaml.tpl index 58df21c..4878ed3 100644 --- a/endpoint-exposer/templates/istio/empty-internal.yaml.tpl +++ b/endpoint-exposer/templates/istio/empty-internal.yaml.tpl @@ -10,7 +10,7 @@ metadata: visibility: internal spec: parentRefs: - - name: gateway-internal + - name: gateway-public namespace: gateways hostnames: - {{ if has . "parameters" }}{{ if has .parameters "private_domain" }}{{ .parameters.private_domain }}{{ else }}{{ .service.attributes.private_domain }}{{ end }}{{ else }}{{ .service.attributes.private_domain }}{{ end }} From 467abb806b45ab99a17b01635db3895ff0892861 Mon Sep 17 00:00:00 2001 From: Javi Date: Mon, 5 Jan 2026 16:48:24 -0300 Subject: [PATCH 07/20] chore: replace gateway --- endpoint-exposer/examples/create-link.json | 65 ----------------- endpoint-exposer/examples/create.json | 64 ----------------- endpoint-exposer/examples/delete-link.json | 71 ------------------- endpoint-exposer/examples/delete.json | 50 ------------- endpoint-exposer/examples/read.json | 50 ------------- endpoint-exposer/examples/refresh.json | 61 ---------------- .../scripts/dns/build_dns_endpoint | 2 +- .../templates/istio/empty-internal.yaml.tpl | 2 +- endpoint-exposer/workflows/istio/update.yaml | 2 +- 9 files changed, 3 insertions(+), 364 deletions(-) delete mode 100644 endpoint-exposer/examples/create-link.json delete mode 100644 endpoint-exposer/examples/create.json delete mode 100644 endpoint-exposer/examples/delete-link.json delete mode 100644 endpoint-exposer/examples/delete.json delete mode 100644 endpoint-exposer/examples/read.json delete mode 100644 endpoint-exposer/examples/refresh.json diff --git a/endpoint-exposer/examples/create-link.json b/endpoint-exposer/examples/create-link.json deleted file mode 100644 index 2f86a2e..0000000 --- a/endpoint-exposer/examples/create-link.json +++ /dev/null @@ -1,65 +0,0 @@ -{ - "id": "ba21e8e6-dcc1-4b9f-87a4-3610c61dfda4", - "source": "service", - "event": "service:action:create", - "created_at": "2025-06-18T13:01:20.204Z", - "notification": { - "action": "service:action:create", - "id": "5b426145-cc25-429e-88d2-83407a6f08b3", - "name": "create-the-link-name-from-the-user", - "slug": "create-the-link-name-from-the-user", - "status": "pending", - "created_at": "2025-06-18T13:01:20.207Z", - "updated_at": "2025-06-18T13:01:20.207Z", - "parameters": { - "path": "/users" - }, - "results": {}, - "type": "create", - "specification": { - "id": "0dc917a7-180c-4155-ad84-767dc5be61a4", - "slug": "create-publish" - }, - "service": { - "id": "4f3fc1da-10bf-47e7-8dd8-b9febc3ddea1", - "slug": "the-service-name-from-the-user", - "attributes": { - "domain": "some-domain.com" - }, - "specification": { - "id": "e820250b-62e3-4e20-8647-dd41b20d1bb9", - "slug": "publish" - }, - "dimensions": { - "environment": "development", - "country": "argentina" - } - }, - "link": { - "id": "64cc013c-9545-495e-a2ac-40df06af84d6", - "slug": "the-link-name-from-the-user", - "attributes": { - "path": "/users", - "scope": "dev-us" - }, - "specification": { - "id": "39d2d131-50b5-41b9-a739-1c3edde913ec", - "slug": "publish" - }, - "dimensions": {} - }, - "tags": { - "organization_id": "1255165411", - "organization": "kwik-e-mart", - "account_id": "95118862", - "account": "kwik-e-mart-main", - "namespace_id": "1068437903", - "namespace": "fede-m", - "application_id": "857154851", - "application": "scope-exposer", - "scope_id": "704207903", - "scope": "public-argentina" - }, - "entity_nrn": "organization=1255165411:account=95118862:namespace=1249051863:application=454567105:scope=704207903" - } -} \ No newline at end of file diff --git a/endpoint-exposer/examples/create.json b/endpoint-exposer/examples/create.json deleted file mode 100644 index f6912ce..0000000 --- a/endpoint-exposer/examples/create.json +++ /dev/null @@ -1,64 +0,0 @@ -{ - "action": "service:action:create", - "id": "d7f7698d-ce17-4dd5-9cb6-02dc39e7a726", - "name": "create-test-javi", - "slug": "create-test-javi", - "status": "pending", - "created_by": "1621446846", - "created_at": "2025-12-30T16:34:40.773Z", - "updated_at": "2025-12-30T16:34:40.773Z", - "parameters": { - "routes": [ - { - "method": "GET", - "path": "/health", - "scope": "DevelopmentScope", - "visibility": "public" - } - ], - "public_domain": "javi.edenred.nullimplementation.com", - "private_domain": "javi.edenred.nullimplementation.com" - }, - "results": { - "routes": [ - { - "method": "GET", - "path": "/health", - "scope": "DevelopmentScope", - "visibility": "public" - } - ], - "public_domain": "javi.edenred.nullimplementation.com", - "private_domain": "javi.edenred.nullimplementation.com" - }, - "type": "create", - "specification": { - "id": "b9c6e9b5-c292-4ad1-9af8-650cac4ea587", - "slug": "create-service-exposer-v2" - }, - "service": { - "id": "babaa91d-89fb-4ee3-ba23-529620d1834f", - "slug": "test-javi", - "attributes": {}, - "type": "dependency", - "specification": { - "id": "70d51cc6-591d-4282-927c-4757b092604b", - "slug": "service-exposer-v2" - }, - "dimensions": { - "environment": "development" - } - }, - "link": null, - "tags": { - "namespace_id": "1340017944", - "namespace": "playground", - "organization_id": "1858797910", - "organization": "edenred", - "account_id": "758973013", - "account": "playground", - "application_id": "179976948", - "application": "floppy-bird-api" - }, - "entity_nrn": "organization=1858797910:account=758973013:namespace=1340017944:application=179976948" -} \ No newline at end of file diff --git a/endpoint-exposer/examples/delete-link.json b/endpoint-exposer/examples/delete-link.json deleted file mode 100644 index b17be37..0000000 --- a/endpoint-exposer/examples/delete-link.json +++ /dev/null @@ -1,71 +0,0 @@ -{ - "id": "ba21e8e6-dcc1-4b9f-87a4-3610c61dfda4", - "source": "service", - "event": "service:action:delete", - "created_at": "2025-06-18T13:01:20.204Z", - "notification": { - "action": "service:action:delete", - "id": "5b426145-cc25-429e-88d2-83407a6f08b3", - "name": "delete-the-link-name-from-the-user", - "slug": "delete-the-link-name-from-the-user", - "status": "pending", - "created_at": "2025-06-18T13:01:20.207Z", - "updated_at": "2025-06-18T13:01:20.207Z", - "parameters": { - "path": "/users" - }, - "results": {}, - "type": "delete", - "specification": { - "id": "0dc917a7-180c-4155-ad84-767dc5be61a4", - "slug": "delete-publish" - }, - "service": { - "id": "4f3fc1da-10bf-47e7-8dd8-b9febc3ddea1", - "slug": "the-service-name-from-the-user", - "attributes": { - "domain": "some-domain.com", - "rules": [ - { - "path": "/users", - "scope": "public-argentina" - } - ] - }, - "specification": { - "id": "e820250b-62e3-4e20-8647-dd41b20d1bb9", - "slug": "publish" - }, - "dimensions": { - "environment": "development", - "country": "argentina" - } - }, - "link": { - "id": "64cc013c-9545-495e-a2ac-40df06af84d6", - "slug": "the-link-name-from-the-user", - "attributes": { - "path": "/users", - "scope": "dev-us" - }, - "specification": { - "id": "39d2d131-50b5-41b9-a739-1c3edde913ec", - "slug": "publish" - }, - "dimensions": {} - }, - "tags": { - "organization_id": "1255165411", - "organization": "kwik-e-mart", - "account_id": "95118862", - "account": "kwik-e-mart-main", - "namespace_id": "1068437903", - "namespace": "fede-m", - "application_id": "857154851", - "application": "scope-exposer", - "scope_id": "704207903", - "scope": "public-argentina" - }, - "entity_nrn": "organization=1255165411:account=95118862:namespace=1249051863:application=454567105:scope=704207903" - } -} \ No newline at end of file diff --git a/endpoint-exposer/examples/delete.json b/endpoint-exposer/examples/delete.json deleted file mode 100644 index ac6a64d..0000000 --- a/endpoint-exposer/examples/delete.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "id": "c266d1aa-23d7-4a23-8954-346824186c9a", - "source": "service", - "event": "service:action:delete", - "created_at": "2025-06-17T15:24:05.861Z", - "notification": { - "action": "service:action:delete", - "id": "b9a9971b-acce-421b-b7b7-4e940e73fac8", - "name": "create-the-service-name-from-the-user", - "slug": "create-the-service-name-from-the-user", - "status": "pending", - "created_at": "2025-06-17T15:24:05.861Z", - "updated_at": "2025-06-17T15:24:05.861Z", - "parameters": { - }, - "results": {}, - "type": "delete", - "specification": { - "id": "03bcdc47-212c-4b64-a2cc-ed0365e4228c", - "slug": "create-service-exposer" - }, - "service": { - "id": "4f3fc1da-10bf-47e7-8dd8-b9febc3ddea1", - "slug": "the-service-name-from-the-user", - "attributes": { - "rules": [], - "domain": "domain.com" - }, - "specification": { - "id": "f66f5e37-0303-48aa-bc9d-aeda1f909a10", - "slug": "service-exposer" - }, - "dimensions": { - "environment": "development" - } - }, - "link": null, - "tags": { - "organization_id": "1255165411", - "organization": "kwik-e-mart", - "account_id": "95118862", - "account": "kwik-e-mart-main", - "namespace_id": "1068437903", - "namespace": "fede-m", - "application_id": "857154851", - "application": "scope-exposer" - }, - "entity_nrn": "organization=1255165411:account=95118862:namespace=1068437903:application=857154851" - } -} \ No newline at end of file diff --git a/endpoint-exposer/examples/read.json b/endpoint-exposer/examples/read.json deleted file mode 100644 index f165523..0000000 --- a/endpoint-exposer/examples/read.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "id": "c266d1aa-23d7-4a23-8954-346824186c9a", - "source": "service", - "event": "service:action:write", - "created_at": "2025-06-17T15:24:05.861Z", - "notification": { - "action": "service:action:write", - "id": "b9a9971b-acce-421b-b7b7-4e940e73fac8", - "name": "Read", - "slug": "read", - "status": "pending", - "created_at": "2025-06-17T15:24:05.861Z", - "updated_at": "2025-06-17T15:24:05.861Z", - "parameters": { - }, - "results": {}, - "type": "custom", - "specification": { - "id": "03bcdc47-212c-4b64-a2cc-ed0365e4228c", - "slug": "read" - }, - "service": { - "id": "4f3fc1da-10bf-47e7-8dd8-b9febc3ddea1", - "slug": "the-service-name-from-the-user", - "attributes": { - "rules": [], - "domain": "domain.com" - }, - "specification": { - "id": "f66f5e37-0303-48aa-bc9d-aeda1f909a10", - "slug": "service-exposer" - }, - "dimensions": { - "environment": "development" - } - }, - "link": null, - "tags": { - "organization_id": "1255165411", - "organization": "kwik-e-mart", - "account_id": "95118862", - "account": "kwik-e-mart-main", - "namespace_id": "1068437903", - "namespace": "fede-m", - "application_id": "857154851", - "application": "scope-exposer" - }, - "entity_nrn": "organization=1255165411:account=95118862:namespace=1068437903:application=857154851" - } -} \ No newline at end of file diff --git a/endpoint-exposer/examples/refresh.json b/endpoint-exposer/examples/refresh.json deleted file mode 100644 index ae32f56..0000000 --- a/endpoint-exposer/examples/refresh.json +++ /dev/null @@ -1,61 +0,0 @@ -{ - "id": "ba21e8e6-dcc1-4b9f-87a4-3610c61dfda4", - "source": "service", - "event": "service:action:update", - "created_at": "2025-06-18T13:01:20.204Z", - "notification": { - "action": "service:action:update", - "id": "5b426145-cc25-429e-88d2-83407a6f08b3", - "name": "Refresh", - "slug": "refresh", - "status": "pending", - "created_at": "2025-06-18T13:01:20.207Z", - "updated_at": "2025-06-18T13:01:20.207Z", - "parameters": {}, - "results": {}, - "type": "custom", - "specification": { - "id": "0dc917a7-180c-4155-ad84-767dc5be61a4", - "slug": "delete-publish" - }, - "service": { - "id": "4f3fc1da-10bf-47e7-8dd8-b9febc3ddea1", - "slug": "the-service-name-from-the-user", - "attributes": {}, - "specification": { - "id": "e820250b-62e3-4e20-8647-dd41b20d1bb9", - "slug": "publish" - }, - "dimensions": { - "environment": "development", - "country": "argentina" - } - }, - "link": { - "id": "64cc013c-9545-495e-a2ac-40df06af84d6", - "slug": "the-link-name-from-the-user", - "attributes": { - "path": "/users", - "scope": "dev-us" - }, - "specification": { - "id": "39d2d131-50b5-41b9-a739-1c3edde913ec", - "slug": "publish" - }, - "dimensions": {} - }, - "tags": { - "organization_id": "1255165411", - "organization": "kwik-e-mart", - "account_id": "95118862", - "account": "kwik-e-mart-main", - "namespace_id": "1068437903", - "namespace": "fede-m", - "application_id": "857154851", - "application": "scope-exposer", - "scope_id": "704207903", - "scope": "public-argentina" - }, - "entity_nrn": "organization=1255165411:account=95118862:namespace=1249051863:application=454567105:scope=704207903" - } -} \ No newline at end of file diff --git a/endpoint-exposer/scripts/dns/build_dns_endpoint b/endpoint-exposer/scripts/dns/build_dns_endpoint index a5bc6ef..7ec49a9 100755 --- a/endpoint-exposer/scripts/dns/build_dns_endpoint +++ b/endpoint-exposer/scripts/dns/build_dns_endpoint @@ -11,7 +11,7 @@ echo "DEBUG: VISIBILITY=$VISIBILITY" # Select domain and gateway based on visibility if [[ "$VISIBILITY" == "internal" ]]; then SERVICE_DOMAIN=$(echo "$CONTEXT" | jq -r '.parameters.private_domain') - GATEWAY_NAME=${INTERNAL_GATEWAY_NAME:-"gateway-internal"} + GATEWAY_NAME=${INTERNAL_GATEWAY_NAME:-"gateway-public"} DNS_TEMPLATE="$SERVICE_PATH/templates/istio/dns-endpoint-internal.yaml.tpl" DNS_FILE="$OUTPUT_DIR/dnsendpoint-$SERVICE_ID-internal.yaml" echo "DEBUG: Building INTERNAL DNS endpoint" diff --git a/endpoint-exposer/templates/istio/empty-internal.yaml.tpl b/endpoint-exposer/templates/istio/empty-internal.yaml.tpl index 4878ed3..a03c394 100644 --- a/endpoint-exposer/templates/istio/empty-internal.yaml.tpl +++ b/endpoint-exposer/templates/istio/empty-internal.yaml.tpl @@ -20,6 +20,6 @@ spec: type: PathPrefix value: / backendRefs: - - name: response-404 + - name: response-404F port: 80 weight: 0 diff --git a/endpoint-exposer/workflows/istio/update.yaml b/endpoint-exposer/workflows/istio/update.yaml index 6bbd32d..cd7bc77 100644 --- a/endpoint-exposer/workflows/istio/update.yaml +++ b/endpoint-exposer/workflows/istio/update.yaml @@ -55,7 +55,7 @@ steps: configuration: HTTPROUTE_FILE_VAR: "HTTPROUTE_FILE_INTERNAL" DOMAIN: "$PRIVATE_DOMAIN" - GATEWAY: "gateway-internal" + GATEWAY: "gateway-public" - name: "clean public httproute rules" type: script file: "$SERVICE_PATH/scripts/istio/clean_httproute_rules" From 3dfdf917ae3149fa57da9f8aab4464aa9aa9fd4a Mon Sep 17 00:00:00 2001 From: Javi Date: Mon, 5 Jan 2026 18:50:49 -0300 Subject: [PATCH 08/20] chore: link to private gateway --- endpoint-exposer/scripts/dns/build_dns_endpoint | 2 +- endpoint-exposer/templates/istio/empty-internal.yaml.tpl | 4 ++-- endpoint-exposer/workflows/istio/update.yaml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/endpoint-exposer/scripts/dns/build_dns_endpoint b/endpoint-exposer/scripts/dns/build_dns_endpoint index 7ec49a9..e55e181 100755 --- a/endpoint-exposer/scripts/dns/build_dns_endpoint +++ b/endpoint-exposer/scripts/dns/build_dns_endpoint @@ -11,7 +11,7 @@ echo "DEBUG: VISIBILITY=$VISIBILITY" # Select domain and gateway based on visibility if [[ "$VISIBILITY" == "internal" ]]; then SERVICE_DOMAIN=$(echo "$CONTEXT" | jq -r '.parameters.private_domain') - GATEWAY_NAME=${INTERNAL_GATEWAY_NAME:-"gateway-public"} + GATEWAY_NAME=${INTERNAL_GATEWAY_NAME:-"gateway-private"} DNS_TEMPLATE="$SERVICE_PATH/templates/istio/dns-endpoint-internal.yaml.tpl" DNS_FILE="$OUTPUT_DIR/dnsendpoint-$SERVICE_ID-internal.yaml" echo "DEBUG: Building INTERNAL DNS endpoint" diff --git a/endpoint-exposer/templates/istio/empty-internal.yaml.tpl b/endpoint-exposer/templates/istio/empty-internal.yaml.tpl index a03c394..8beaccd 100644 --- a/endpoint-exposer/templates/istio/empty-internal.yaml.tpl +++ b/endpoint-exposer/templates/istio/empty-internal.yaml.tpl @@ -10,7 +10,7 @@ metadata: visibility: internal spec: parentRefs: - - name: gateway-public + - name: gateway-private namespace: gateways hostnames: - {{ if has . "parameters" }}{{ if has .parameters "private_domain" }}{{ .parameters.private_domain }}{{ else }}{{ .service.attributes.private_domain }}{{ end }}{{ else }}{{ .service.attributes.private_domain }}{{ end }} @@ -20,6 +20,6 @@ spec: type: PathPrefix value: / backendRefs: - - name: response-404F + - name: response-404 port: 80 weight: 0 diff --git a/endpoint-exposer/workflows/istio/update.yaml b/endpoint-exposer/workflows/istio/update.yaml index cd7bc77..d8b3d04 100644 --- a/endpoint-exposer/workflows/istio/update.yaml +++ b/endpoint-exposer/workflows/istio/update.yaml @@ -55,7 +55,7 @@ steps: configuration: HTTPROUTE_FILE_VAR: "HTTPROUTE_FILE_INTERNAL" DOMAIN: "$PRIVATE_DOMAIN" - GATEWAY: "gateway-public" + GATEWAY: "gateway-private" - name: "clean public httproute rules" type: script file: "$SERVICE_PATH/scripts/istio/clean_httproute_rules" From 9cc69db558932f3bc6c6ab3572f3d96c399f2a60 Mon Sep 17 00:00:00 2001 From: Javi Date: Mon, 5 Jan 2026 18:51:59 -0300 Subject: [PATCH 09/20] chore: remove alb scripts --- endpoint-exposer/scripts/alb/apply | 25 -- endpoint-exposer/scripts/alb/build_context | 36 --- endpoint-exposer/scripts/alb/build_ingress | 22 -- .../scripts/alb/build_ingress_with_rule | 199 ------------- .../scripts/alb/build_ingress_without_rule | 47 --- endpoint-exposer/scripts/alb/build_rule | 22 -- .../scripts/alb/fetch_provider_data | 22 -- endpoint-exposer/scripts/alb/read_ingress | 5 - endpoint-exposer/scripts/alb/update_service | 21 -- .../scripts/alb/validate_unique_rule | 12 - ...ld_ingress_with_rule_virtualservice_backup | 278 ------------------ 11 files changed, 689 deletions(-) delete mode 100644 endpoint-exposer/scripts/alb/apply delete mode 100644 endpoint-exposer/scripts/alb/build_context delete mode 100644 endpoint-exposer/scripts/alb/build_ingress delete mode 100644 endpoint-exposer/scripts/alb/build_ingress_with_rule delete mode 100644 endpoint-exposer/scripts/alb/build_ingress_without_rule delete mode 100644 endpoint-exposer/scripts/alb/build_rule delete mode 100755 endpoint-exposer/scripts/alb/fetch_provider_data delete mode 100644 endpoint-exposer/scripts/alb/read_ingress delete mode 100644 endpoint-exposer/scripts/alb/update_service delete mode 100644 endpoint-exposer/scripts/alb/validate_unique_rule delete mode 100644 endpoint-exposer/scripts/istio/build_ingress_with_rule_virtualservice_backup diff --git a/endpoint-exposer/scripts/alb/apply b/endpoint-exposer/scripts/alb/apply deleted file mode 100644 index 2692c3c..0000000 --- a/endpoint-exposer/scripts/alb/apply +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/bash - -set -euo pipefail - -echo "TEMPLATE DIR: $OUTPUT_DIR, ACTION: $ACTION, DRY_RUN: $DRY_RUN" - -# Find all .yaml files that were not yet applied / deleted -find "$OUTPUT_DIR" \( -path "*/apply" -o -path "*/delete" \) -prune -o -type f -name "*.yaml" -print | while read -r TEMPLATE_FILE; do - echo "kubectl $ACTION $TEMPLATE_FILE" - - if [[ "$DRY_RUN" == "false" ]]; then - kubectl "$ACTION" -f "$TEMPLATE_FILE" - fi - - BASE_DIR="$(dirname "$TEMPLATE_FILE")" - FILENAME="$(basename "$TEMPLATE_FILE")" - DEST_DIR="${BASE_DIR}/$ACTION" - - mkdir -p "$DEST_DIR" - mv "$TEMPLATE_FILE" "$DEST_DIR/$FILENAME" -done - -if [[ "$DRY_RUN" == "true" ]]; then - exit 1 -fi \ No newline at end of file diff --git a/endpoint-exposer/scripts/alb/build_context b/endpoint-exposer/scripts/alb/build_context deleted file mode 100644 index 761fed4..0000000 --- a/endpoint-exposer/scripts/alb/build_context +++ /dev/null @@ -1,36 +0,0 @@ -#!/bin/bash - -set -euo pipefail - -SERVICE_ID=$(echo "$CONTEXT" | jq -r .service.id) -SERVICE_NAME=$(echo "$CONTEXT" | jq -r .service.slug) - -ACTION_ID=$(echo "$CONTEXT" | jq -r .id) -ACTION_NAME=$(echo "$CONTEXT" | jq -r .slug) - -LINK_ID=$(echo "$CONTEXT" | jq -r .link.id) -LINK_NAME=$(echo "$CONTEXT" | jq -r .link.slug) - -CONTEXT=$(echo "$CONTEXT" | jq \ - --arg k8s_namespace "$K8S_NAMESPACE" \ - --arg alb_name "$ALB_NAME" \ - '. + {k8s_namespace: $k8s_namespace, alb_name: $alb_name}') - -SCOPE_ID=$(echo "$CONTEXT" | jq -r .tags.scope_id) -SCOPE_SLUG=$(echo "$CONTEXT" | jq -r .tags.scope) - -RULE_PATH=$(echo "$CONTEXT" | jq -r '.link.attributes.path // .parameters.path') - -export OUTPUT_DIR="$SERVICE_PATH/output/$SERVICE_NAME-$SERVICE_ID/$ACTION_NAME-$ACTION_ID" - -mkdir -p "$OUTPUT_DIR" - -export SERVICE_ID -export SERVICE_NAME -export ACTION_ID -export ACTION_NAME -export LINK_ID -export LINK_NAME -export SCOPE_ID -export SCOPE_SLUG -export RULE_PATH \ No newline at end of file diff --git a/endpoint-exposer/scripts/alb/build_ingress b/endpoint-exposer/scripts/alb/build_ingress deleted file mode 100644 index 610c439..0000000 --- a/endpoint-exposer/scripts/alb/build_ingress +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/bash - -set -euo pipefail - -SERVICE_DOMAIN=$(echo "$CONTEXT" | jq -r .parameters.domain) - -echo "Creating ingress for service $SERVICE_NAME with domain $SERVICE_DOMAIN" - -echo "Creating public ingress..." - -INGRESS_FILE="$OUTPUT_DIR/ingress-$SERVICE_ID-public.yaml" -CONTEXT_PATH="$OUTPUT_DIR/context-$SERVICE_ID.json" - -echo "$CONTEXT" > "$CONTEXT_PATH" - -echo "Building Template: $TEMPLATE to $INGRESS_FILE" - -gomplate -c .="$CONTEXT_PATH" \ - --file "$TEMPLATE" \ - --out "$INGRESS_FILE" - -rm "$CONTEXT_PATH" \ No newline at end of file diff --git a/endpoint-exposer/scripts/alb/build_ingress_with_rule b/endpoint-exposer/scripts/alb/build_ingress_with_rule deleted file mode 100644 index f3f4e5f..0000000 --- a/endpoint-exposer/scripts/alb/build_ingress_with_rule +++ /dev/null @@ -1,199 +0,0 @@ -#!/bin/bash - -set -euo pipefail - -is_ingress_empty() { - local yaml_content="$1" - - local num_rules - local num_paths - local path - local service_name - local service_port - - num_rules=$(yq '.spec.rules | length' <<< "$yaml_content") - num_paths=$(yq '.spec.rules[0].http.paths | length' <<< "$yaml_content") - path=$(yq '.spec.rules[0].http.paths[0].path' <<< "$yaml_content") - service_name=$(yq '.spec.rules[0].http.paths[0].backend.service.name' <<< "$yaml_content") - service_port=$(yq '.spec.rules[0].http.paths[0].backend.service.port.name' <<< "$yaml_content") - - if [[ "$num_rules" -eq 1 && \ - "$num_paths" -eq 1 && \ - "$path" == "/" && \ - "$service_name" == "response-404" && \ - "$service_port" == "use-annotation" ]]; then - echo "true" - else - echo "false" - fi -} - -create_path_rule() { - local rule_path="$1" - local service_json="$2" - - jq -n \ - --arg path "$rule_path" \ - --argjson service "$service_json" \ - '{ - path: $path, - pathType: "Prefix", - backend: { - service: $service - } - }' -} - -add_annotation_if_needed() { - local ingress_yaml="$1" - local annotation="$2" - local scope_id="$3" - - if [[ "$annotation" != "null" && -n "$annotation" ]]; then - local annotation_key="alb.ingress.kubernetes.io/actions.bg-deployment-$scope_id" - - # Escape the value so it’s properly quoted in YAML - local escaped_annotation - escaped_annotation=$(printf '%s\n' "$annotation" | jq -Rs .) # wrap & escape as JSON string - - echo "$ingress_yaml" | yq eval ".metadata.annotations.\"$annotation_key\" = $escaped_annotation" - else - echo "$ingress_yaml" - fi -} - -update_ingress_rule() { - local ingress_yaml="$1" - local rule_path="$2" - local service_json="$3" - local annotation="$4" - local scope_id="$5" - - local updated_ingress - - # Replace the current rule with the new rule data - updated_ingress=$(echo "$ingress_yaml" | yq eval '.spec.rules[0].http.paths[0].path = "'$rule_path'"') - updated_ingress=$(echo "$updated_ingress" | yq eval '.spec.rules[0].http.paths[0].pathType = "Prefix"') - updated_ingress=$(echo "$updated_ingress" | yq eval '.spec.rules[0].http.paths[0].backend.service = '"$service_json") - - # Add annotation if needed - updated_ingress=$(add_annotation_if_needed "$updated_ingress" "$annotation" "$scope_id") - - echo "$updated_ingress" -} - -find_path_index() { - local ingress_yaml="$1" - local target_path="$2" - - local num_paths - local i - local current_path - - num_paths=$(yq '.spec.rules[0].http.paths | length' <<< "$ingress_yaml") - - for ((i=0; i "$INGRESS_FILE" -else - PATH_INDEX=$(find_path_index "$INGRESS" "$RULE_PATH") - - # if there is a rule for the path we replace it - if [[ "$PATH_INDEX" != "-1" ]]; then - UPDATED_INGRESS=$(replace_existing_rule "$INGRESS" "$RULE_PATH" "$SERVICE" "$ANNOTATION" "$SCOPE_ID" "$PATH_INDEX") - echo "$UPDATED_INGRESS" | yq "." > "$INGRESS_FILE" - else - # if there is no rule for the path we add a new one - UPDATED_INGRESS=$(add_new_rule "$INGRESS" "$RULE_PATH" "$SERVICE" "$ANNOTATION" "$SCOPE_ID") - echo "$UPDATED_INGRESS" | yq "." > "$INGRESS_FILE" - fi -fi - -echo "Ingress configuration saved to: $INGRESS_FILE" \ No newline at end of file diff --git a/endpoint-exposer/scripts/alb/build_ingress_without_rule b/endpoint-exposer/scripts/alb/build_ingress_without_rule deleted file mode 100644 index 282fff7..0000000 --- a/endpoint-exposer/scripts/alb/build_ingress_without_rule +++ /dev/null @@ -1,47 +0,0 @@ -#!/bin/bash - -set -euo pipefail - -find_path_index() { - local ingress_yaml="$1" - local target_path="$2" - - local num_paths - local i - local current_path - - num_paths=$(yq '.spec.rules[0].http.paths | length' <<< "$ingress_yaml") - - for ((i=0; i "$INGRESS_FILE" - - diff --git a/endpoint-exposer/scripts/alb/build_rule b/endpoint-exposer/scripts/alb/build_rule deleted file mode 100644 index 1de728a..0000000 --- a/endpoint-exposer/scripts/alb/build_rule +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/bash - -set -euo pipefail - -INGRESS_NAME=$(kubectl get ingress -n "$K8S_NAMESPACE" -l "scope_id=$SCOPE_ID" -o jsonpath="{.items[0].metadata.name}" 2>/dev/null || echo "") - -# Check if ingress exists -if [ -z "$INGRESS_NAME" ]; then - echo "There is no ingress for scope $SCOPE_ID. Publishing the rule with an empty backend" - - SCOPE_RULE='{"blue_green_annotation": null, "service": {"name": "response-404", "port": { "name": "use-annotation"} }}' -else - echo "Found ingress for scope $SCOPE_ID. Publishing the backend service configuration" - INGRESS=$(kubectl get ingress -n "$K8S_NAMESPACE" "$INGRESS_NAME" -o json) - - SCOPE_RULE=$(echo "$INGRESS" | jq '{ - blue_green_annotation: .metadata.annotations["alb.ingress.kubernetes.io/actions.bg-deployment"], - service: .spec.rules[0].http.paths[0].backend.service - }') -fi - -export SCOPE_RULE \ No newline at end of file diff --git a/endpoint-exposer/scripts/alb/fetch_provider_data b/endpoint-exposer/scripts/alb/fetch_provider_data deleted file mode 100755 index 51603cf..0000000 --- a/endpoint-exposer/scripts/alb/fetch_provider_data +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/bash - -NRN=$(echo "$CONTEXT" | jq -r .entity_nrn) - -DIMENSIONS=$(echo "$CONTEXT" | jq .service.dimensions) - -DIMENSION_FILTER=$(echo "$DIMENSIONS" | jq -r 'to_entries | map("\(.key):\(.value)") | join(",")') - -if [ -z "$DIMENSION_FILTER" ] || [ "$DIMENSION_FILTER" = "" ]; then - PROVIDER_DATA=$(np provider list --categories container-orchestration --nrn "$NRN" --format json | jq -r ".results[0]") -else - PROVIDER_DATA=$(np provider list --categories container-orchestration --nrn "$NRN" --dimensions "$DIMENSION_FILTER" --format json | jq -r ".results[0]") -fi - -K8S_NAMESPACE=$(echo "$PROVIDER_DATA" | jq -r .attributes.cluster.namespace) - -ALB_NAME=$(echo "$PROVIDER_DATA" | jq -r --arg default "k8s-nullplatform-internet-facing" ' - .attributes.balancer.public_name // $default -') - -export K8S_NAMESPACE -export ALB_NAME \ No newline at end of file diff --git a/endpoint-exposer/scripts/alb/read_ingress b/endpoint-exposer/scripts/alb/read_ingress deleted file mode 100644 index bde7c9f..0000000 --- a/endpoint-exposer/scripts/alb/read_ingress +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash - -INGRESS_NAME=$(kubectl get ingress -n "$K8S_NAMESPACE" -l "service_id=$SERVICE_ID" -o jsonpath="{.items[0].metadata.name}") - -kubectl get ingress -n "$K8S_NAMESPACE" "$INGRESS_NAME" -o yaml diff --git a/endpoint-exposer/scripts/alb/update_service b/endpoint-exposer/scripts/alb/update_service deleted file mode 100644 index 5f743d3..0000000 --- a/endpoint-exposer/scripts/alb/update_service +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/bash - -if [[ $ACTION == "add" ]]; then - UPDATED_ATTRIBUTES=$(echo "$CONTEXT" | jq --arg path "$RULE_PATH" --arg scope "$SCOPE_SLUG" ' - .service.attributes |= (.rules //= [] | .rules += [{path: $path, scope: $scope}]) | - { - attributes: .service.attributes, - entity_nrn: (.entity_nrn | sub(":scope=[^:]+$"; "")) - } - ') -elif [[ $ACTION == "remove" ]]; then - UPDATED_ATTRIBUTES=$(echo "$CONTEXT" | jq --arg path "$RULE_PATH" ' - .service.attributes |= (.rules //= [] | .rules |= map(select(.path != $path))) | - { - attributes: .service.attributes, - entity_nrn: (.entity_nrn | sub(":scope=[^:]+$"; "")) - } - ') -fi - -np service patch --id "$SERVICE_ID" --body "$UPDATED_ATTRIBUTES" diff --git a/endpoint-exposer/scripts/alb/validate_unique_rule b/endpoint-exposer/scripts/alb/validate_unique_rule deleted file mode 100644 index 49a56b1..0000000 --- a/endpoint-exposer/scripts/alb/validate_unique_rule +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash - -EXISTS=$(echo "$CONTEXT" | jq --arg path "$RULE_PATH" ' - (.service.attributes.rules // []) - | map(select(.path == $path)) - | length -') - -if [[ "$EXISTS" -gt 0 ]]; then - echo "Error: A rule with path '$RULE_PATH' already exists." - exit 1 -fi \ No newline at end of file diff --git a/endpoint-exposer/scripts/istio/build_ingress_with_rule_virtualservice_backup b/endpoint-exposer/scripts/istio/build_ingress_with_rule_virtualservice_backup deleted file mode 100644 index 3367222..0000000 --- a/endpoint-exposer/scripts/istio/build_ingress_with_rule_virtualservice_backup +++ /dev/null @@ -1,278 +0,0 @@ -#!/bin/bash - -set -euo pipefail - -is_virtualservice_empty() { - local yaml_content="$1" - - local num_http_routes - local has_fault - local service_host - - num_http_routes=$(yq '.spec.http | length' <<< "$yaml_content") - has_fault=$(yq '.spec.http[0].fault.abort' <<< "$yaml_content") - service_host=$(yq '.spec.http[0].route[0].destination.host' <<< "$yaml_content") - - # A VirtualService is "empty" if it only has one route with a 404 fault injection to response-404 - if [[ "$num_http_routes" -eq 1 && \ - "$has_fault" != "null" && \ - "$service_host" =~ response-404 ]]; then - echo "true" - else - echo "false" - fi -} - -create_http_route() { - local rule_path="$1" - local service_json="$2" - local blue_green_config="$3" - - local service_name - local service_port - - service_name=$(echo "$service_json" | jq -r '.name') - service_port=$(echo "$service_json" | jq -r '.port.number // .port.name // 80') - - # Check if there's blue/green configuration - if [[ "$blue_green_config" != "null" && -n "$blue_green_config" ]]; then - # Parse blue/green destinations and weights from the annotation - local blue_weight green_weight blue_service green_service - - blue_weight=$(echo "$blue_green_config" | jq -r '.forward.targetGroups[0].weight // 100') - green_weight=$(echo "$blue_green_config" | jq -r '.forward.targetGroups[1].weight // 0') - blue_service=$(echo "$blue_green_config" | jq -r '.forward.targetGroups[0].serviceName') - green_service=$(echo "$blue_green_config" | jq -r '.forward.targetGroups[1].serviceName') - - # Create route with weighted destinations - jq -n \ - --arg path "$rule_path" \ - --arg blue_service "$blue_service" \ - --arg green_service "$green_service" \ - --arg service_port "$service_port" \ - --arg namespace "$K8S_NAMESPACE" \ - --argjson blue_weight "$blue_weight" \ - --argjson green_weight "$green_weight" \ - '{ - match: [ - { - uri: { - prefix: $path - } - } - ], - route: [ - { - destination: { - host: ($blue_service + "." + $namespace + ".svc.cluster.local"), - port: { - number: ($service_port | tonumber) - } - }, - weight: $blue_weight - }, - { - destination: { - host: ($green_service + "." + $namespace + ".svc.cluster.local"), - port: { - number: ($service_port | tonumber) - } - }, - weight: $green_weight - } - ] - }' - else - # Single destination without blue/green - jq -n \ - --arg path "$rule_path" \ - --arg service_name "$service_name" \ - --arg service_port "$service_port" \ - --arg namespace "$K8S_NAMESPACE" \ - '{ - match: [ - { - uri: { - prefix: $path - } - } - ], - route: [ - { - destination: { - host: ($service_name + "." + $namespace + ".svc.cluster.local"), - port: { - number: ($service_port | tonumber) - } - } - } - ] - }' - fi -} - -update_virtualservice_route() { - local vs_yaml="$1" - local rule_path="$2" - local service_json="$3" - local blue_green_config="$4" - - local service_name - local service_port - local updated_vs - - service_name=$(echo "$service_json" | jq -r '.name') - service_port=$(echo "$service_json" | jq -r '.port.number // .port.name // 80') - - # Remove fault injection - updated_vs=$(echo "$vs_yaml" | yq eval 'del(.spec.http[0].fault)') - updated_vs=$(echo "$updated_vs" | yq eval ".spec.http[0].match[0].uri.prefix = \"$rule_path\"") - - # Check if there's blue/green configuration - if [[ "$blue_green_config" != "null" && -n "$blue_green_config" ]]; then - # Parse blue/green destinations and weights - local blue_weight green_weight blue_service green_service - - blue_weight=$(echo "$blue_green_config" | jq -r '.forward.targetGroups[0].weight // 100') - green_weight=$(echo "$blue_green_config" | jq -r '.forward.targetGroups[1].weight // 0') - blue_service=$(echo "$blue_green_config" | jq -r '.forward.targetGroups[0].serviceName') - green_service=$(echo "$blue_green_config" | jq -r '.forward.targetGroups[1].serviceName') - - # Set blue destination - updated_vs=$(echo "$updated_vs" | yq eval ".spec.http[0].route[0].destination.host = \"${blue_service}.${K8S_NAMESPACE}.svc.cluster.local\"") - updated_vs=$(echo "$updated_vs" | yq eval ".spec.http[0].route[0].destination.port.number = $service_port") - updated_vs=$(echo "$updated_vs" | yq eval ".spec.http[0].route[0].weight = $blue_weight") - - # Add green destination - updated_vs=$(echo "$updated_vs" | yq eval ".spec.http[0].route += [{\"destination\": {\"host\": \"${green_service}.${K8S_NAMESPACE}.svc.cluster.local\", \"port\": {\"number\": $service_port}}, \"weight\": $green_weight}]") - else - # Single destination - updated_vs=$(echo "$updated_vs" | yq eval ".spec.http[0].route[0].destination.host = \"${service_name}.${K8S_NAMESPACE}.svc.cluster.local\"") - updated_vs=$(echo "$updated_vs" | yq eval ".spec.http[0].route[0].destination.port.number = $service_port") - fi - - echo "$updated_vs" -} - -find_route_index() { - local vs_yaml="$1" - local target_path="$2" - - local num_routes - local i - local current_path - - num_routes=$(yq '.spec.http | length' <<< "$vs_yaml") - - for ((i=0; i "$VS_FILE" -else - ROUTE_INDEX=$(find_route_index "$VIRTUALSERVICE" "$RULE_PATH") - echo "Found route index for path '$RULE_PATH': $ROUTE_INDEX" - - # if there is a route for the path we replace it - if [[ "$ROUTE_INDEX" != "-1" ]]; then - echo "Case 2: Replacing existing route at index $ROUTE_INDEX" - UPDATED_VS=$(replace_existing_route "$VIRTUALSERVICE" "$RULE_PATH" "$SERVICE" "$BLUE_GREEN_CONFIG" "$ROUTE_INDEX") - echo "$UPDATED_VS" | yq "." > "$VS_FILE" - else - # if there is no route for the path we add a new one - echo "Case 3: Adding new route" - UPDATED_VS=$(add_new_route "$VIRTUALSERVICE" "$RULE_PATH" "$SERVICE" "$BLUE_GREEN_CONFIG") - echo "$UPDATED_VS" | yq "." > "$VS_FILE" - fi -fi - -echo "" -echo "=== VirtualService configuration saved to: $VS_FILE ===" \ No newline at end of file From 82dcf6b0b28e1761400f2b7fac9c48f5d999f4dc Mon Sep 17 00:00:00 2001 From: Javi Date: Mon, 5 Jan 2026 18:52:36 -0300 Subject: [PATCH 10/20] chore: remove alb workflows --- endpoint-exposer/templates/alb/empty.yaml.tpl | 32 ----------- endpoint-exposer/workflows/alb/create.yaml | 44 --------------- endpoint-exposer/workflows/alb/delete.yaml | 6 -- endpoint-exposer/workflows/alb/link.yaml | 56 ------------------- endpoint-exposer/workflows/alb/read.yaml | 32 ----------- endpoint-exposer/workflows/alb/refresh.yaml | 7 --- endpoint-exposer/workflows/alb/unlink.yaml | 47 ---------------- 7 files changed, 224 deletions(-) delete mode 100644 endpoint-exposer/templates/alb/empty.yaml.tpl delete mode 100644 endpoint-exposer/workflows/alb/create.yaml delete mode 100644 endpoint-exposer/workflows/alb/delete.yaml delete mode 100644 endpoint-exposer/workflows/alb/link.yaml delete mode 100644 endpoint-exposer/workflows/alb/read.yaml delete mode 100644 endpoint-exposer/workflows/alb/refresh.yaml delete mode 100644 endpoint-exposer/workflows/alb/unlink.yaml diff --git a/endpoint-exposer/templates/alb/empty.yaml.tpl b/endpoint-exposer/templates/alb/empty.yaml.tpl deleted file mode 100644 index 35ef800..0000000 --- a/endpoint-exposer/templates/alb/empty.yaml.tpl +++ /dev/null @@ -1,32 +0,0 @@ -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - name: k-8-s-{{ .service.slug }}-{{ .service.id }}-public - namespace: {{ .k8s_namespace }} - labels: - nullplatform: "true" - service: {{ .service.slug }} - service_id: {{ .service.id }} - annotations: - kubernetes.io/ingress.class: alb - alb.ingress.kubernetes.io/group.name: {{ .alb_name }} - alb.ingress.kubernetes.io/load-balancer-name: {{ .alb_name }} - alb.ingress.kubernetes.io/scheme: internet-facing - alb.ingress.kubernetes.io/target-type: ip - alb.ingress.kubernetes.io/listen-ports: '[{"HTTP":80},{"HTTPS":443}]' - alb.ingress.kubernetes.io/ssl-redirect: "443" - alb.ingress.kubernetes.io/actions.response-404: >- - {"type":"fixed-response","fixedResponseConfig":{"contentType":"text/plain","statusCode":"404","messageBody":"no scopes exposed through this service."}} -spec: - ingressClassName: alb - rules: - - host: {{ .parameters.domain }} - http: - paths: - - path: / - pathType: Prefix - backend: - service: - name: response-404 - port: - name: use-annotation \ No newline at end of file diff --git a/endpoint-exposer/workflows/alb/create.yaml b/endpoint-exposer/workflows/alb/create.yaml deleted file mode 100644 index 7c8c3a2..0000000 --- a/endpoint-exposer/workflows/alb/create.yaml +++ /dev/null @@ -1,44 +0,0 @@ -steps: - - name: "find k8s namespace" - type: script - file: "$SERVICE_PATH/scripts/alb/fetch_provider_data" - output: - - name: K8S_NAMESPACE - type: environment - - name: ALB_NAME - type: environment - - name: "build context" - type: script - file: "$SERVICE_PATH/scripts/alb/build_context" - output: - - name: SERVICE_ID - type: environment - - name: SERVICE_NAME - type: environment - - name: ACTION_ID - type: environment - - name: ACTION_NAME - type: environment - - name: LINK_ID - type: environment - - name: LINK_NAME - type: environment - - name: SCOPE_ID - type: environment - - name: RULE_PATH - type: environment - - name: "build template" - type: script - file: "$SERVICE_PATH/scripts/alb/build_ingress" - configuration: - TEMPLATE: "$SERVICE_PATH/templates/alb/empty.yaml.tpl" - output: - - name: INGRESS_FILE - type: file - file: "$OUTPUT_DIR/ingress-$SERVICE_ID-$SCOPE_ID-public.yaml" - - name: apply - type: script - file: "$SERVICE_PATH/scripts/alb/apply" - configuration: - ACTION: apply - DRY_RUN: false \ No newline at end of file diff --git a/endpoint-exposer/workflows/alb/delete.yaml b/endpoint-exposer/workflows/alb/delete.yaml deleted file mode 100644 index 3c7309e..0000000 --- a/endpoint-exposer/workflows/alb/delete.yaml +++ /dev/null @@ -1,6 +0,0 @@ -include: - - "$SERVICE_PATH/workflows/alb/create.yaml" -steps: - - name: apply - configuration: - ACTION: delete \ No newline at end of file diff --git a/endpoint-exposer/workflows/alb/link.yaml b/endpoint-exposer/workflows/alb/link.yaml deleted file mode 100644 index 0145798..0000000 --- a/endpoint-exposer/workflows/alb/link.yaml +++ /dev/null @@ -1,56 +0,0 @@ -steps: - - name: "find k8s namespace" - type: script - file: "$SERVICE_PATH/scripts/alb/fetch_provider_data" - output: - - name: K8S_NAMESPACE - type: environment - - name: ALB_NAME - type: environment - - name: "build context" - type: script - file: "$SERVICE_PATH/scripts/alb/build_context" - output: - - name: SERVICE_ID - type: environment - - name: SERVICE_NAME - type: environment - - name: ACTION_ID - type: environment - - name: ACTION_NAME - type: environment - - name: LINK_ID - type: environment - - name: LINK_NAME - type: environment - - name: SCOPE_ID - type: environment - - name: RULE_PATH - type: environment - - name: "validate_unique_rule" - type: script - file: "$SERVICE_PATH/scripts/alb/validate_unique_rule" - - name: "build_rule" - type: script - file : "$SERVICE_PATH/scripts/alb/build_rule" - output: - - name: SCOPE_RULE - type: environment - - name: "build_ingress" - type: script - file: "$SERVICE_PATH/scripts/alb/build_ingress_with_rule" - output: - - name: INGRESS_FILE - type: file - file: "$OUTPUT_DIR/ingress-$SERVICE_ID-$SCOPE_ID-public.yaml" - - name: apply - type: script - file: "$SERVICE_PATH/scripts/alb/apply" - configuration: - ACTION: apply - DRY_RUN: false - - name: "add_rule_to_service" - type: script - file: "$SERVICE_PATH/scripts/alb/update_service" - configuration: - ACTION: add \ No newline at end of file diff --git a/endpoint-exposer/workflows/alb/read.yaml b/endpoint-exposer/workflows/alb/read.yaml deleted file mode 100644 index 8dea452..0000000 --- a/endpoint-exposer/workflows/alb/read.yaml +++ /dev/null @@ -1,32 +0,0 @@ -steps: - - name: "find k8s namespace" - type: script - file: "$SERVICE_PATH/scripts/alb/fetch_provider_data" - output: - - name: K8S_NAMESPACE - type: environment - - name: ALB_NAME - type: environment - - name: "build context" - type: script - file: "$SERVICE_PATH/scripts/alb/build_context" - output: - - name: SERVICE_ID - type: environment - - name: SERVICE_NAME - type: environment - - name: ACTION_ID - type: environment - - name: ACTION_NAME - type: environment - - name: LINK_ID - type: environment - - name: LINK_NAME - type: environment - - name: SCOPE_ID - type: environment - - name: RULE_PATH - type: environment - - name: read - type: script - file: "$SERVICE_PATH/scripts/alb/read_ingress" \ No newline at end of file diff --git a/endpoint-exposer/workflows/alb/refresh.yaml b/endpoint-exposer/workflows/alb/refresh.yaml deleted file mode 100644 index 6edef06..0000000 --- a/endpoint-exposer/workflows/alb/refresh.yaml +++ /dev/null @@ -1,7 +0,0 @@ -include: - - "$SERVICE_PATH/workflows/alb/link.yaml" -steps: - - name: "validate_unique_rule" - action: skip - - name: "add_rule_to_service" - action: skip \ No newline at end of file diff --git a/endpoint-exposer/workflows/alb/unlink.yaml b/endpoint-exposer/workflows/alb/unlink.yaml deleted file mode 100644 index 690374a..0000000 --- a/endpoint-exposer/workflows/alb/unlink.yaml +++ /dev/null @@ -1,47 +0,0 @@ -steps: - - name: "find k8s namespace" - type: script - file: "$SERVICE_PATH/scripts/alb/fetch_provider_data" - output: - - name: K8S_NAMESPACE - type: environment - - name: ALB_NAME - type: environment - - name: "build context" - type: script - file: "$SERVICE_PATH/scripts/alb/build_context" - output: - - name: SERVICE_ID - type: environment - - name: SERVICE_NAME - type: environment - - name: ACTION_ID - type: environment - - name: ACTION_NAME - type: environment - - name: LINK_ID - type: environment - - name: LINK_NAME - type: environment - - name: SCOPE_ID - type: environment - - name: RULE_PATH - type: environment - - name: "build_template" - type: script - file: "$SERVICE_PATH/scripts/alb/build_ingress_without_rule" - output: - - name: INGRESS_FILE - type: file - file: "$OUTPUT_DIR/ingress-$SERVICE_ID-$SCOPE_ID-public.yaml" - - name: apply - type: script - file: "$SERVICE_PATH/scripts/alb/apply" - configuration: - ACTION: apply - DRY_RUN: false - - name: "add_rule_to_service" - type: script - file: "$SERVICE_PATH/scripts/alb/update_service" - configuration: - ACTION: remove \ No newline at end of file From af379b14b61f88f3f523a2717fefe657090612c4 Mon Sep 17 00:00:00 2001 From: Javi Date: Mon, 5 Jan 2026 19:19:43 -0300 Subject: [PATCH 11/20] chore: remove unused scripts and dns endpoints --- .../scripts/{istio => common}/apply | 0 endpoint-exposer/scripts/dns/build_dns | 15 ----- .../scripts/dns/build_dns_endpoint | 58 ----------------- .../scripts/istio/build_ingress_without_rule | 62 ------------------- endpoint-exposer/scripts/istio/update_service | 21 ------- .../scripts/istio/validate_unique_rule | 12 ---- .../istio/dns-endpoint-internal.yaml.tpl | 17 ----- .../templates/istio/dns-endpoint.yaml.tpl | 16 ----- endpoint-exposer/workflows/istio/create.yaml | 20 +----- endpoint-exposer/workflows/istio/update.yaml | 20 +----- 10 files changed, 2 insertions(+), 239 deletions(-) rename endpoint-exposer/scripts/{istio => common}/apply (100%) delete mode 100755 endpoint-exposer/scripts/dns/build_dns delete mode 100755 endpoint-exposer/scripts/dns/build_dns_endpoint delete mode 100644 endpoint-exposer/scripts/istio/build_ingress_without_rule delete mode 100644 endpoint-exposer/scripts/istio/update_service delete mode 100644 endpoint-exposer/scripts/istio/validate_unique_rule delete mode 100644 endpoint-exposer/templates/istio/dns-endpoint-internal.yaml.tpl delete mode 100644 endpoint-exposer/templates/istio/dns-endpoint.yaml.tpl diff --git a/endpoint-exposer/scripts/istio/apply b/endpoint-exposer/scripts/common/apply similarity index 100% rename from endpoint-exposer/scripts/istio/apply rename to endpoint-exposer/scripts/common/apply diff --git a/endpoint-exposer/scripts/dns/build_dns b/endpoint-exposer/scripts/dns/build_dns deleted file mode 100755 index 6a6641b..0000000 --- a/endpoint-exposer/scripts/dns/build_dns +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/bash - -# Build DNS context based on DNS_TYPE -echo "=== DEBUG: Starting build_dns ===" -echo "DNS_TYPE=$DNS_TYPE" - -case "$DNS_TYPE" in - external_dns) - "$SERVICE_PATH/scripts/dns/build_dns_endpoint" - ;; - *) - echo "Error: Unsupported DNS type '$DNS_TYPE'" - exit 1 - ;; -esac \ No newline at end of file diff --git a/endpoint-exposer/scripts/dns/build_dns_endpoint b/endpoint-exposer/scripts/dns/build_dns_endpoint deleted file mode 100755 index e55e181..0000000 --- a/endpoint-exposer/scripts/dns/build_dns_endpoint +++ /dev/null @@ -1,58 +0,0 @@ -#!/bin/bash - -set -euo pipefail - -echo "=== DEBUG: Starting build_dns_endpoint ===" - -# Determine visibility (default to public if not set) -VISIBILITY="${VISIBILITY:-public}" -echo "DEBUG: VISIBILITY=$VISIBILITY" - -# Select domain and gateway based on visibility -if [[ "$VISIBILITY" == "internal" ]]; then - SERVICE_DOMAIN=$(echo "$CONTEXT" | jq -r '.parameters.private_domain') - GATEWAY_NAME=${INTERNAL_GATEWAY_NAME:-"gateway-private"} - DNS_TEMPLATE="$SERVICE_PATH/templates/istio/dns-endpoint-internal.yaml.tpl" - DNS_FILE="$OUTPUT_DIR/dnsendpoint-$SERVICE_ID-internal.yaml" - echo "DEBUG: Building INTERNAL DNS endpoint" -else - SERVICE_DOMAIN=$(echo "$CONTEXT" | jq -r '.parameters.public_domain') - GATEWAY_NAME=${PUBLIC_GATEWAY_NAME:-"gateway-public"} - DNS_TEMPLATE="$SERVICE_PATH/templates/istio/dns-endpoint.yaml.tpl" - DNS_FILE="$OUTPUT_DIR/dnsendpoint-$SERVICE_ID-public.yaml" - echo "DEBUG: Building PUBLIC DNS endpoint" -fi - -echo "DEBUG: SERVICE_DOMAIN=$SERVICE_DOMAIN" -echo "DEBUG: GATEWAY_NAME=$GATEWAY_NAME" - -GATEWAY_NAMESPACE=${GATEWAY_NAMESPACE:-"gateways"} - -echo "DEBUG: Fetching gateway IP from $GATEWAY_NAME..." -GATEWAY_IP=$(kubectl get gateway -n "$GATEWAY_NAMESPACE" "$GATEWAY_NAME" -o jsonpath='{.status.addresses[0].value}') -echo "DEBUG: GATEWAY_IP=$GATEWAY_IP" - -if [[ -z "$GATEWAY_IP" || "$GATEWAY_IP" == "null" ]]; then - echo "ERROR: Could not retrieve gateway IP from $GATEWAY_NAME" - exit 1 -fi - -echo "Creating DNSEndpoint for service $SERVICE_NAME with domain $SERVICE_DOMAIN" - -CONTEXT_PATH="$OUTPUT_DIR/context-dns-$SERVICE_ID-$VISIBILITY.json" - -# Add gateway_ip to context -CONTEXT_WITH_IP=$(echo "$CONTEXT" | jq --arg gateway_ip "$GATEWAY_IP" '. + {gateway_ip: $gateway_ip}') - -echo "$CONTEXT_WITH_IP" > "$CONTEXT_PATH" - -echo "Building DNSEndpoint Template to $DNS_FILE" - -gomplate -c .="$CONTEXT_PATH" \ - --file "$DNS_TEMPLATE" \ - --out "$DNS_FILE" - -rm "$CONTEXT_PATH" - -echo "DEBUG: DNSEndpoint created at $DNS_FILE" -echo "=== DEBUG: build_dns_endpoint completed ===" diff --git a/endpoint-exposer/scripts/istio/build_ingress_without_rule b/endpoint-exposer/scripts/istio/build_ingress_without_rule deleted file mode 100644 index 2fef8a3..0000000 --- a/endpoint-exposer/scripts/istio/build_ingress_without_rule +++ /dev/null @@ -1,62 +0,0 @@ -#!/bin/bash - -set -euo pipefail - -find_rule_index() { - local hr_yaml="$1" - local target_path="$2" - - local num_rules - local i - local current_path - - num_rules=$(yq '.spec.rules | length' <<< "$hr_yaml") - - for ((i=0; i "$HTTPROUTE_FILE" - -echo "=== HTTPRoute configuration saved to: $HTTPROUTE_FILE ===" diff --git a/endpoint-exposer/scripts/istio/update_service b/endpoint-exposer/scripts/istio/update_service deleted file mode 100644 index 5f743d3..0000000 --- a/endpoint-exposer/scripts/istio/update_service +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/bash - -if [[ $ACTION == "add" ]]; then - UPDATED_ATTRIBUTES=$(echo "$CONTEXT" | jq --arg path "$RULE_PATH" --arg scope "$SCOPE_SLUG" ' - .service.attributes |= (.rules //= [] | .rules += [{path: $path, scope: $scope}]) | - { - attributes: .service.attributes, - entity_nrn: (.entity_nrn | sub(":scope=[^:]+$"; "")) - } - ') -elif [[ $ACTION == "remove" ]]; then - UPDATED_ATTRIBUTES=$(echo "$CONTEXT" | jq --arg path "$RULE_PATH" ' - .service.attributes |= (.rules //= [] | .rules |= map(select(.path != $path))) | - { - attributes: .service.attributes, - entity_nrn: (.entity_nrn | sub(":scope=[^:]+$"; "")) - } - ') -fi - -np service patch --id "$SERVICE_ID" --body "$UPDATED_ATTRIBUTES" diff --git a/endpoint-exposer/scripts/istio/validate_unique_rule b/endpoint-exposer/scripts/istio/validate_unique_rule deleted file mode 100644 index 49a56b1..0000000 --- a/endpoint-exposer/scripts/istio/validate_unique_rule +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash - -EXISTS=$(echo "$CONTEXT" | jq --arg path "$RULE_PATH" ' - (.service.attributes.rules // []) - | map(select(.path == $path)) - | length -') - -if [[ "$EXISTS" -gt 0 ]]; then - echo "Error: A rule with path '$RULE_PATH' already exists." - exit 1 -fi \ No newline at end of file diff --git a/endpoint-exposer/templates/istio/dns-endpoint-internal.yaml.tpl b/endpoint-exposer/templates/istio/dns-endpoint-internal.yaml.tpl deleted file mode 100644 index 8cb3198..0000000 --- a/endpoint-exposer/templates/istio/dns-endpoint-internal.yaml.tpl +++ /dev/null @@ -1,17 +0,0 @@ -apiVersion: externaldns.k8s.io/v1alpha1 -kind: DNSEndpoint -metadata: - name: {{ .service.slug }}-{{ .service.id }}-dns-internal - namespace: {{ .k8s_namespace }} - labels: - nullplatform: "true" - service: {{ .service.slug }} - service_id: {{ .service.id }} - visibility: internal -spec: - endpoints: - - dnsName: {{ if has . "parameters" }}{{ if has .parameters "private_domain" }}{{ .parameters.private_domain }}{{ else }}{{ .service.attributes.private_domain }}{{ end }}{{ else }}{{ .service.attributes.private_domain }}{{ end }} - recordTTL: 60 - recordType: A - targets: - - "{{ .gateway_ip }}" diff --git a/endpoint-exposer/templates/istio/dns-endpoint.yaml.tpl b/endpoint-exposer/templates/istio/dns-endpoint.yaml.tpl deleted file mode 100644 index e8983cf..0000000 --- a/endpoint-exposer/templates/istio/dns-endpoint.yaml.tpl +++ /dev/null @@ -1,16 +0,0 @@ -apiVersion: externaldns.k8s.io/v1alpha1 -kind: DNSEndpoint -metadata: - name: {{ .service.slug }}-{{ .service.id }}-dns - namespace: {{ .k8s_namespace }} - labels: - nullplatform: "true" - service: {{ .service.slug }} - service_id: {{ .service.id }} -spec: - endpoints: - - dnsName: {{ if has . "parameters" }}{{ if has .parameters "public_domain" }}{{ .parameters.public_domain }}{{ else if has .parameters "domain" }}{{ .parameters.domain }}{{ else }}{{ .service.attributes.domain }}{{ end }}{{ else }}{{ .service.attributes.domain }}{{ end }} - recordTTL: 60 - recordType: A - targets: - - "{{ .gateway_ip }}" diff --git a/endpoint-exposer/workflows/istio/create.yaml b/endpoint-exposer/workflows/istio/create.yaml index 3290a23..90e9032 100644 --- a/endpoint-exposer/workflows/istio/create.yaml +++ b/endpoint-exposer/workflows/istio/create.yaml @@ -52,27 +52,9 @@ steps: - name: HTTPROUTE_FILE_INTERNAL type: file file: "$OUTPUT_DIR/httproute-$SERVICE_ID-internal.yaml" - - name: "build public dns endpoint" - type: script - file: "$SERVICE_PATH/scripts/dns/build_dns" - configuration: - VISIBILITY: "public" - output: - - name: DNS_FILE_PUBLIC - type: file - file: "$OUTPUT_DIR/dnsendpoint-$SERVICE_ID-public.yaml" - - name: "build internal dns endpoint" - type: script - file: "$SERVICE_PATH/scripts/dns/build_dns" - configuration: - VISIBILITY: "internal" - output: - - name: DNS_FILE_INTERNAL - type: file - file: "$OUTPUT_DIR/dnsendpoint-$SERVICE_ID-internal.yaml" - name: apply type: script - file: "$SERVICE_PATH/scripts/istio/apply" + file: "$SERVICE_PATH/scripts/common/apply" configuration: ACTION: apply DRY_RUN: false \ No newline at end of file diff --git a/endpoint-exposer/workflows/istio/update.yaml b/endpoint-exposer/workflows/istio/update.yaml index d8b3d04..29ee6aa 100644 --- a/endpoint-exposer/workflows/istio/update.yaml +++ b/endpoint-exposer/workflows/istio/update.yaml @@ -76,27 +76,9 @@ steps: - name: HTTPROUTE_FILE_INTERNAL type: file file: "$OUTPUT_DIR/httproute-$SERVICE_ID-internal.yaml" - - name: "update public dns endpoint" - type: script - file: "$SERVICE_PATH/scripts/dns/build_dns" - configuration: - VISIBILITY: "public" - output: - - name: DNS_FILE_PUBLIC - type: file - file: "$OUTPUT_DIR/dnsendpoint-$SERVICE_ID-public.yaml" - - name: "update internal dns endpoint" - type: script - file: "$SERVICE_PATH/scripts/dns/build_dns" - configuration: - VISIBILITY: "internal" - output: - - name: DNS_FILE_INTERNAL - type: file - file: "$OUTPUT_DIR/dnsendpoint-$SERVICE_ID-internal.yaml" - name: apply type: script - file: "$SERVICE_PATH/scripts/istio/apply" + file: "$SERVICE_PATH/scripts/common/apply" configuration: ACTION: apply DRY_RUN: false From 11e231578ddd5f1d37de805f6a15c222d604f52d Mon Sep 17 00:00:00 2001 From: Javi Date: Tue, 6 Jan 2026 09:32:40 -0300 Subject: [PATCH 12/20] chore: remote DEBUG logs --- .../container-scope-override/deployment/sync_exposer | 4 ---- endpoint-exposer/container-scope-override/values.yaml | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/endpoint-exposer/container-scope-override/deployment/sync_exposer b/endpoint-exposer/container-scope-override/deployment/sync_exposer index 570373c..de96760 100755 --- a/endpoint-exposer/container-scope-override/deployment/sync_exposer +++ b/endpoint-exposer/container-scope-override/deployment/sync_exposer @@ -1,8 +1,6 @@ #!/bin/bash echo "=== DEBUG: Starting sync_exposer script ===" -echo "DEBUG: CONTEXT=$CONTEXT" -echo "DEBUG: SERVICE_SPECIFICATION_SLUG=$SERVICE_SPECIFICATION_SLUG" SCOPE_NRN=$(echo "$CONTEXT" | jq -r .scope.nrn) @@ -11,14 +9,12 @@ echo "SERVICE SPECIFICATION SLUG: $SERVICE_SPECIFICATION_SLUG, SCOPE_NRN: $SCOPE # Step 1: Get service specification by slug echo "DEBUG: Fetching service specifications..." SERVICE_SPECS=$(np service specification list --nrn "$SCOPE_NRN" --type dependency --format json) -echo "DEBUG: Service specifications fetched: $SERVICE_SPECS" SERVICE_SPEC=$(echo "$SERVICE_SPECS" | jq -c --arg slug "$SERVICE_SPECIFICATION_SLUG" ' .results | map(select(.slug == $slug)) | .[0] ') -echo "DEBUG: Filtered service spec: $SERVICE_SPEC" SERVICE_SPEC_ID=$(echo "$SERVICE_SPEC" | jq -r .id) diff --git a/endpoint-exposer/container-scope-override/values.yaml b/endpoint-exposer/container-scope-override/values.yaml index 784fe86..101aee8 100644 --- a/endpoint-exposer/container-scope-override/values.yaml +++ b/endpoint-exposer/container-scope-override/values.yaml @@ -1,3 +1,3 @@ configuration: - SERVICE_SPECIFICATION_SLUG: service-exposer-v2 + SERVICE_SPECIFICATION_SLUG: endpoint-exposer \ No newline at end of file From 2b89d8a3f96c11e7332a2a04424963d128879b57 Mon Sep 17 00:00:00 2001 From: Javi Date: Tue, 6 Jan 2026 09:39:50 -0300 Subject: [PATCH 13/20] chore: remote DEBUG logs --- endpoint-exposer/scripts/istio/clean_httproute_rules | 5 ++++- endpoint-exposer/scripts/istio/update_httproute_hostname | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/endpoint-exposer/scripts/istio/clean_httproute_rules b/endpoint-exposer/scripts/istio/clean_httproute_rules index 55c7dda..ae6087c 100755 --- a/endpoint-exposer/scripts/istio/clean_httproute_rules +++ b/endpoint-exposer/scripts/istio/clean_httproute_rules @@ -4,7 +4,10 @@ set -euo pipefail # If HTTPROUTE_FILE_VAR is provided, use it to get the file path from that variable if [[ -n "${HTTPROUTE_FILE_VAR:-}" ]]; then - HTTPROUTE_FILE="${!HTTPROUTE_FILE_VAR}" + # Use indirect variable expansion safely + if [[ -n "${!HTTPROUTE_FILE_VAR:-}" ]]; then + HTTPROUTE_FILE="${!HTTPROUTE_FILE_VAR}" + fi fi echo "=== Cleaning HTTPRoute rules ===" diff --git a/endpoint-exposer/scripts/istio/update_httproute_hostname b/endpoint-exposer/scripts/istio/update_httproute_hostname index 7f7b044..df047f7 100755 --- a/endpoint-exposer/scripts/istio/update_httproute_hostname +++ b/endpoint-exposer/scripts/istio/update_httproute_hostname @@ -4,7 +4,10 @@ set -euo pipefail # If HTTPROUTE_FILE_VAR is provided, use it to get the file path from that variable if [[ -n "${HTTPROUTE_FILE_VAR:-}" ]]; then - HTTPROUTE_FILE="${!HTTPROUTE_FILE_VAR}" + # Use indirect variable expansion safely + if [[ -n "${!HTTPROUTE_FILE_VAR:-}" ]]; then + HTTPROUTE_FILE="${!HTTPROUTE_FILE_VAR}" + fi fi # Use DOMAIN and GATEWAY if provided via configuration, otherwise use PUBLIC_DOMAIN and gateway-public From d0638a0f2f12fc5bc455c248f876569795a05c16 Mon Sep 17 00:00:00 2001 From: Javi Date: Tue, 6 Jan 2026 14:35:30 -0300 Subject: [PATCH 14/20] chore: DEBUG logs --- .../container-scope-override/deployment/sync_exposer | 1 + 1 file changed, 1 insertion(+) diff --git a/endpoint-exposer/container-scope-override/deployment/sync_exposer b/endpoint-exposer/container-scope-override/deployment/sync_exposer index de96760..cd99fcc 100755 --- a/endpoint-exposer/container-scope-override/deployment/sync_exposer +++ b/endpoint-exposer/container-scope-override/deployment/sync_exposer @@ -2,6 +2,7 @@ echo "=== DEBUG: Starting sync_exposer script ===" +echo "DEBUG: $CONTEXT" SCOPE_NRN=$(echo "$CONTEXT" | jq -r .scope.nrn) echo "SERVICE SPECIFICATION SLUG: $SERVICE_SPECIFICATION_SLUG, SCOPE_NRN: $SCOPE_NRN" From 9f89c08e6dfed8c84d566f411a49915b72139596 Mon Sep 17 00:00:00 2001 From: Javi Date: Tue, 6 Jan 2026 16:08:30 -0300 Subject: [PATCH 15/20] feat: adapt endpoint exposer to work by service action --- .../deployment/sync_exposer | 144 ++++++++---------- endpoint-exposer/workflows/istio/refresh.yaml | 7 +- 2 files changed, 65 insertions(+), 86 deletions(-) diff --git a/endpoint-exposer/container-scope-override/deployment/sync_exposer b/endpoint-exposer/container-scope-override/deployment/sync_exposer index cd99fcc..08f92d6 100755 --- a/endpoint-exposer/container-scope-override/deployment/sync_exposer +++ b/endpoint-exposer/container-scope-override/deployment/sync_exposer @@ -3,21 +3,20 @@ echo "=== DEBUG: Starting sync_exposer script ===" echo "DEBUG: $CONTEXT" -SCOPE_NRN=$(echo "$CONTEXT" | jq -r .scope.nrn) +APPLICATION_NRN=$(jq -r .application.nrn <<< "$CONTEXT") -echo "SERVICE SPECIFICATION SLUG: $SERVICE_SPECIFICATION_SLUG, SCOPE_NRN: $SCOPE_NRN" +echo "SERVICE SPECIFICATION SLUG: $SERVICE_SPECIFICATION_SLUG, APPLICATION_NRN: $APPLICATION_NRN" # Step 1: Get service specification by slug echo "DEBUG: Fetching service specifications..." -SERVICE_SPECS=$(np service specification list --nrn "$SCOPE_NRN" --type dependency --format json) - -SERVICE_SPEC=$(echo "$SERVICE_SPECS" | jq -c --arg slug "$SERVICE_SPECIFICATION_SLUG" ' +SERVICE_SPECS=$(np service specification list --nrn "$APPLICATION_NRN" --type dependency --format json) +SERVICE_SPEC=$(jq -c --arg slug "$SERVICE_SPECIFICATION_SLUG" ' .results | map(select(.slug == $slug)) | .[0] -') +' <<< "$SERVICE_SPECS") -SERVICE_SPEC_ID=$(echo "$SERVICE_SPEC" | jq -r .id) +SERVICE_SPEC_ID=$(jq -r .id <<< "$SERVICE_SPEC") if [[ -z "$SERVICE_SPEC_ID" || "$SERVICE_SPEC_ID" == "null" ]]; then echo "Error: Could not find service specification with slug '$SERVICE_SPECIFICATION_SLUG'" @@ -26,106 +25,91 @@ fi echo "DEBUG: SERVICE_SPEC_ID=$SERVICE_SPEC_ID" -# Step 2: Get link specification with slug "publish" -echo "DEBUG: Fetching link specifications for service spec..." -LINK_SPECS=$(np service specification link specification list --id "$SERVICE_SPEC_ID" --format json) -echo "DEBUG: Link specifications fetched: $LINK_SPECS" +# Step 2: Get service instance that matches the SERVICE_SPEC_ID +echo "DEBUG: Fetching services for application..." +SERVICES=$(np service list --nrn "$APPLICATION_NRN" --format json) -PUBLISH_LINK_SPEC=$(echo "$LINK_SPECS" | jq -c ' +SERVICE=$(jq -c --arg spec_id "$SERVICE_SPEC_ID" ' .results - | map(select(.slug == "publish")) + | map(select(.specification_id == $spec_id)) | .[0] -') -echo "DEBUG: Filtered publish link spec: $PUBLISH_LINK_SPEC" +' <<< "$SERVICES") -LINK_SPECIFICATION_ID=$(echo "$PUBLISH_LINK_SPEC" | jq -r .id) +SERVICE_ID=$(jq -r .id <<< "$SERVICE") -if [[ -z "$LINK_SPECIFICATION_ID" || "$LINK_SPECIFICATION_ID" == "null" ]]; then - echo "Error: Could not find link specification with slug 'publish' for service specification '$SERVICE_SPEC_ID'" +if [[ -z "$SERVICE_ID" || "$SERVICE_ID" == "null" ]]; then + echo "Error: Could not find service instance for specification '$SERVICE_SPEC_ID'" exit 1 fi -echo "DEBUG: LINK_SPECIFICATION_ID=$LINK_SPECIFICATION_ID" - -echo "DEBUG: Fetching links for scope..." -LINKS=$(np link list --nrn "$SCOPE_NRN" --format json --status active) -echo "DEBUG: Links fetched. Response: $LINKS" +echo "DEBUG: SERVICE_ID=$SERVICE_ID" -EXPOSER_LINKS=$(echo "$LINKS" | jq -c --arg spec "$LINK_SPECIFICATION_ID" ' - .results - | map(select(.specification_id == $spec)) -') -echo "DEBUG: EXPOSER_LINKS filtered: $EXPOSER_LINKS" +# Step 3: Get service attributes as parameters +echo "DEBUG: Reading service attributes..." +SERVICE_DATA=$(np service read --id "$SERVICE_ID" --format json) +export PARAMETERS=$(jq -c .attributes <<< "$SERVICE_DATA") -COUNT=$(echo "$EXPOSER_LINKS" | jq 'length') -echo "DEBUG: COUNT=$COUNT" - -if [[ "$COUNT" -eq 0 ]]; then - echo "This scope is not public, skipping public ingress synchronization" - return -fi +echo "DEBUG: PARAMETERS=$PARAMETERS" -echo "This is a public scope, starting public ingress synchronization" +# Step 4: Get action specification with slug "update-" +ACTION_SLUG="update-$SERVICE_SPECIFICATION_SLUG" +echo "DEBUG: Fetching action specifications (looking for slug: $ACTION_SLUG)..." +SERVICE_ACTIONS=$(np service specification action specification list --serviceSpecificationId "$SERVICE_SPEC_ID" --format json) -ACTIONS=$(np link specification action specification list --linkSpecificationId "$LINK_SPECIFICATION_ID" --format json) - -REFRESH_ACTION=$(echo "$ACTIONS" | jq -c ' +ACTION_SPEC=$(jq -c --arg slug "$ACTION_SLUG" ' .results - | map(select(.slug == "refresh")) + | map(select(.slug == $slug)) | .[0] -') +' <<< "$SERVICE_ACTIONS") -REFRESH_ACTION_ID=$(echo "$REFRESH_ACTION" | jq -r .id) -echo "DEBUG: REFRESH_ACTION_ID=$REFRESH_ACTION_ID" +ACTION_SPEC_ID=$(jq -r .id <<< "$ACTION_SPEC") -# Iterate over matches -echo "DEBUG: Starting iteration over exposer links..." -echo "$EXPOSER_LINKS" | jq -c '.[]' | while read -r link; do - echo "DEBUG: Processing link: $link" +if [[ -z "$ACTION_SPEC_ID" || "$ACTION_SPEC_ID" == "null" ]]; then + echo "Error: Could not find action specification with slug '$ACTION_SLUG' for service specification '$SERVICE_SPEC_ID'" + exit 1 +fi - # Extract useful values - LINK_ID=$(echo "$link" | jq -r '.id') - echo "DEBUG: LINK_ID=$LINK_ID" +echo "DEBUG: ACTION_SPEC_ID=$ACTION_SPEC_ID" - echo "DEBUG: Creating link action..." - ACTION=$(np link action create --linkId "$LINK_ID" --body "{\"name\": \"refresh\", \"parameters\":{}, \"specification_id\": \"$REFRESH_ACTION_ID\"}" --format json) - echo "DEBUG: Action created: $ACTION" +# Step 5: Create service action with parameters +echo "DEBUG: Creating service action..." +ACTION=$(np service action create --serviceId "$SERVICE_ID" --body "$(jq -n --argjson params "$PARAMETERS" --arg spec_id "$ACTION_SPEC_ID" '{name: "update", parameters: $params, specification_id: $spec_id}')" --format json) - ACTION_ID=$(echo "$ACTION" | jq -r .id) - echo "DEBUG: ACTION_ID=$ACTION_ID" +ACTION_ID=$(jq -r .id <<< "$ACTION") +echo "DEBUG: ACTION_ID=$ACTION_ID" - echo "Created public ingress synchronization action[id=$ACTION_ID], waiting for its completion" +echo "Created endpoint exposer update action[id=$ACTION_ID], waiting for its completion" - MAX_ITERATIONS=20 - iteration=0 +# Step 6: Wait for action to complete +MAX_ITERATIONS=20 +iteration=0 - echo "DEBUG: Starting polling loop for action status..." - while true; do - ((iteration++)) - echo "DEBUG: Iteration $iteration/$MAX_ITERATIONS" +echo "DEBUG: Starting polling loop for action status..." +while true; do + ((iteration++)) + echo "DEBUG: Iteration $iteration/$MAX_ITERATIONS" - if [ "$iteration" -gt $MAX_ITERATIONS ]; then - echo "Error: Maximum number of iterations (${MAX_ITERATIONS}) reached. Could not refresh the exposer." - exit 1 - fi + if [ "$iteration" -gt $MAX_ITERATIONS ]; then + echo "Error: Maximum number of iterations (${MAX_ITERATIONS}) reached. Could not update the endpoint exposer." + exit 1 + fi - echo "DEBUG: Reading action status..." - ACTION_STATUS=$(np link action read --linkId "$LINK_ID" --id "$ACTION_ID" --format json | jq -r .status) + echo "DEBUG: Reading action status..." + ACTION_RESPONSE=$(np service action read --id "$ACTION_ID" --format json) + ACTION_STATUS=$(jq -r .status <<< "$ACTION_RESPONSE") - echo "Checking public ingress synchronization action[id=$ACTION_ID, status=$ACTION_STATUS]" + echo "Checking endpoint exposer update action[id=$ACTION_ID, status=$ACTION_STATUS]" - if [[ "$ACTION_STATUS" == "success" ]]; then - echo "✅ Public ingress successfully synchronized" - break - elif [[ "$ACTION_STATUS" == "failed" ]]; then - echo "❌ Could not synchronize public ingress, deployment will be rollbacked" - exit 1 - fi + if [[ "$ACTION_STATUS" == "success" ]]; then + echo "✅ Endpoint exposer successfully updated" + break + elif [[ "$ACTION_STATUS" == "failed" ]]; then + echo "❌ Could not update endpoint exposer, deployment will be rollbacked" + exit 1 + fi - echo "DEBUG: Sleeping for 5 seconds..." - sleep 5 - done - echo "DEBUG: Finished processing link $LINK_ID" + echo "DEBUG: Sleeping for 5 seconds..." + sleep 5 done echo "=== DEBUG: sync_exposer script completed successfully ===" diff --git a/endpoint-exposer/workflows/istio/refresh.yaml b/endpoint-exposer/workflows/istio/refresh.yaml index a920564..f2f102d 100644 --- a/endpoint-exposer/workflows/istio/refresh.yaml +++ b/endpoint-exposer/workflows/istio/refresh.yaml @@ -1,7 +1,2 @@ include: - - "$SERVICE_PATH/workflows/istio/link.yaml" -steps: - - name: "validate_unique_rule" - action: skip - - name: "add_rule_to_service" - action: skip \ No newline at end of file + - "$SERVICE_PATH/workflows/istio/update.yaml" \ No newline at end of file From 4f3a2ecc619f1369fa75a82212c237a72dc67a2d Mon Sep 17 00:00:00 2001 From: Javi Date: Tue, 6 Jan 2026 16:13:55 -0300 Subject: [PATCH 16/20] feat: adapt endpoint exposer to work by service action --- .../container-scope-override/deployment/sync_exposer | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/endpoint-exposer/container-scope-override/deployment/sync_exposer b/endpoint-exposer/container-scope-override/deployment/sync_exposer index 08f92d6..0999a86 100755 --- a/endpoint-exposer/container-scope-override/deployment/sync_exposer +++ b/endpoint-exposer/container-scope-override/deployment/sync_exposer @@ -95,7 +95,7 @@ while true; do fi echo "DEBUG: Reading action status..." - ACTION_RESPONSE=$(np service action read --id "$ACTION_ID" --format json) + ACTION_RESPONSE=$(np service action read --serviceId "$SERVICE_ID" --id "$ACTION_ID" --format json) ACTION_STATUS=$(jq -r .status <<< "$ACTION_RESPONSE") echo "Checking endpoint exposer update action[id=$ACTION_ID, status=$ACTION_STATUS]" From cc52ddef88027bd6566797893f08969160d24796 Mon Sep 17 00:00:00 2001 From: Javi Date: Tue, 6 Jan 2026 16:27:22 -0300 Subject: [PATCH 17/20] feat: adapt endpoint exposer to work by service action --- .../scripts/istio/build_ingress_with_rule | 37 ++++++++++++++++--- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/endpoint-exposer/scripts/istio/build_ingress_with_rule b/endpoint-exposer/scripts/istio/build_ingress_with_rule index eb5bae1..b3d5f1f 100755 --- a/endpoint-exposer/scripts/istio/build_ingress_with_rule +++ b/endpoint-exposer/scripts/istio/build_ingress_with_rule @@ -216,18 +216,41 @@ update_httproute_rule() { find_rule_index() { local hr_yaml="$1" local target_path="$2" + local target_method="${3:-}" local num_rules local i local current_path + local current_method num_rules=$(yq '.spec.rules | length' <<< "$hr_yaml") for ((i=0; i "$HTTPROUTE_FILE" else - RULE_INDEX=$(find_rule_index "$HTTPROUTE" "$RULE_PATH") - echo "Found rule index for path '$RULE_PATH': $RULE_INDEX" + # Detect the converted path value to match against existing rules + PATH_TYPE_VALUE=$(detect_path_type "$RULE_PATH") + CONVERTED_PATH="${PATH_TYPE_VALUE#*:}" + + RULE_INDEX=$(find_rule_index "$HTTPROUTE" "$CONVERTED_PATH" "${METHOD:-}") + echo "Found rule index for path '$CONVERTED_PATH' with method '${METHOD:-none}': $RULE_INDEX" # if there is a rule for the path we replace it if [[ "$RULE_INDEX" != "-1" ]]; then From 85b25e01b967d057ad287f6f6e7a1b21a68bd65b Mon Sep 17 00:00:00 2001 From: Javi Date: Tue, 6 Jan 2026 17:19:34 -0300 Subject: [PATCH 18/20] fix: retries on action creation --- .../deployment/sync_exposer | 69 +++++++++++++++++-- 1 file changed, 63 insertions(+), 6 deletions(-) diff --git a/endpoint-exposer/container-scope-override/deployment/sync_exposer b/endpoint-exposer/container-scope-override/deployment/sync_exposer index 0999a86..da6e3a4 100755 --- a/endpoint-exposer/container-scope-override/deployment/sync_exposer +++ b/endpoint-exposer/container-scope-override/deployment/sync_exposer @@ -2,7 +2,6 @@ echo "=== DEBUG: Starting sync_exposer script ===" -echo "DEBUG: $CONTEXT" APPLICATION_NRN=$(jq -r .application.nrn <<< "$CONTEXT") echo "SERVICE SPECIFICATION SLUG: $SERVICE_SPECIFICATION_SLUG, APPLICATION_NRN: $APPLICATION_NRN" @@ -71,14 +70,72 @@ fi echo "DEBUG: ACTION_SPEC_ID=$ACTION_SPEC_ID" -# Step 5: Create service action with parameters +# Step 5: Create service action with parameters (with retry for concurrency) echo "DEBUG: Creating service action..." -ACTION=$(np service action create --serviceId "$SERVICE_ID" --body "$(jq -n --argjson params "$PARAMETERS" --arg spec_id "$ACTION_SPEC_ID" '{name: "update", parameters: $params, specification_id: $spec_id}')" --format json) -ACTION_ID=$(jq -r .id <<< "$ACTION") -echo "DEBUG: ACTION_ID=$ACTION_ID" +MAX_CREATE_RETRIES=10 +RETRY_DELAY=5 +create_attempt=0 +ACTION_ID="" -echo "Created endpoint exposer update action[id=$ACTION_ID], waiting for its completion" +while [[ -z "$ACTION_ID" || "$ACTION_ID" == "null" ]]; do + ((create_attempt++)) + echo "DEBUG: Create attempt $create_attempt/$MAX_CREATE_RETRIES" + + if [ "$create_attempt" -gt $MAX_CREATE_RETRIES ]; then + echo "Error: Maximum number of create attempts (${MAX_CREATE_RETRIES}) reached. Could not create action." + exit 1 + fi + + # Add delay before retry (except on first attempt) + if [ "$create_attempt" -gt 1 ]; then + echo "DEBUG: Waiting ${RETRY_DELAY} seconds before retry..." + sleep $RETRY_DELAY + fi + + # Try to create the action + ACTION_RESPONSE=$(np service action create --serviceId "$SERVICE_ID" --body "$(jq -n --argjson params "$PARAMETERS" --arg spec_id "$ACTION_SPEC_ID" '{name: "update", parameters: $params, specification_id: $spec_id}')" --format json 2>&1 || true) + + # Check if response contains an error about action already in progress + if echo "$ACTION_RESPONSE" | grep -q "already an action with status.*in_progress"; then + echo "DEBUG: Action already in progress detected" + + # Try to find the existing in_progress action + echo "DEBUG: Attempting to find existing in_progress action..." + EXISTING_ACTIONS=$(np service action list --serviceId "$SERVICE_ID" --format json) + EXISTING_ACTION=$(echo "$EXISTING_ACTIONS" | jq -c --arg spec_id "$ACTION_SPEC_ID" ' + .results + | map(select(.specification_id == $spec_id and .status == "in_progress")) + | .[0] + ') + + EXISTING_ACTION_ID=$(echo "$EXISTING_ACTION" | jq -r '.id // empty') + + if [[ -n "$EXISTING_ACTION_ID" && "$EXISTING_ACTION_ID" != "null" ]]; then + echo "DEBUG: Found existing in_progress action with ID: $EXISTING_ACTION_ID" + ACTION_ID="$EXISTING_ACTION_ID" + echo "Using existing action instead of creating new one" + break + fi + + echo "DEBUG: No existing action found, will retry..." + elif echo "$ACTION_RESPONSE" | grep -q '"error"'; then + echo "ERROR: Failed to create action: $ACTION_RESPONSE" + echo "DEBUG: Will retry after delay..." + else + # Success - extract action ID + ACTION_ID=$(echo "$ACTION_RESPONSE" | jq -r '.id // empty') + + if [[ -n "$ACTION_ID" && "$ACTION_ID" != "null" ]]; then + echo "DEBUG: ACTION_ID=$ACTION_ID" + echo "Created endpoint exposer update action[id=$ACTION_ID], waiting for its completion" + break + else + echo "DEBUG: Could not extract ACTION_ID from response: $ACTION_RESPONSE" + echo "DEBUG: Will retry after delay..." + fi + fi +done # Step 6: Wait for action to complete MAX_ITERATIONS=20 From 3a7991eb9f0cdd9d2a2c1e2612f05b5d2e82dfd2 Mon Sep 17 00:00:00 2001 From: Javi Date: Wed, 7 Jan 2026 13:59:13 -0300 Subject: [PATCH 19/20] feat: if no service instance created allow continue without errors --- .../container-scope-override/deployment/sync_exposer | 4 ++-- endpoint-exposer/workflows/istio/refresh.yaml | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) delete mode 100644 endpoint-exposer/workflows/istio/refresh.yaml diff --git a/endpoint-exposer/container-scope-override/deployment/sync_exposer b/endpoint-exposer/container-scope-override/deployment/sync_exposer index da6e3a4..06d1058 100755 --- a/endpoint-exposer/container-scope-override/deployment/sync_exposer +++ b/endpoint-exposer/container-scope-override/deployment/sync_exposer @@ -37,8 +37,8 @@ SERVICE=$(jq -c --arg spec_id "$SERVICE_SPEC_ID" ' SERVICE_ID=$(jq -r .id <<< "$SERVICE") if [[ -z "$SERVICE_ID" || "$SERVICE_ID" == "null" ]]; then - echo "Error: Could not find service instance for specification '$SERVICE_SPEC_ID'" - exit 1 + echo "Could not find service instance for specification '$SERVICE_SPEC_ID', skipping exposer sync" + exit 0 fi echo "DEBUG: SERVICE_ID=$SERVICE_ID" diff --git a/endpoint-exposer/workflows/istio/refresh.yaml b/endpoint-exposer/workflows/istio/refresh.yaml deleted file mode 100644 index f2f102d..0000000 --- a/endpoint-exposer/workflows/istio/refresh.yaml +++ /dev/null @@ -1,2 +0,0 @@ -include: - - "$SERVICE_PATH/workflows/istio/update.yaml" \ No newline at end of file From f7b425a2e76a7ec1f092e65d234fba7b6b14736b Mon Sep 17 00:00:00 2001 From: Javi Date: Thu, 8 Jan 2026 11:44:04 -0300 Subject: [PATCH 20/20] feat: remove links --- endpoint-exposer/scripts/common/echo | 3 - endpoint-exposer/scripts/istio/build_context | 18 +-- endpoint-exposer/scripts/istio/build_ingress | 19 +-- .../scripts/istio/build_ingress_with_rule | 14 +- .../scripts/istio/clean_httproute_rules | 8 - .../scripts/istio/fetch_httproute | 17 +-- endpoint-exposer/scripts/istio/process_routes | 137 ++++++------------ .../scripts/istio/update_httproute_hostname | 10 +- endpoint-exposer/specs/link-spec.json.tpl | 28 ---- endpoint-exposer/specs/links/refresh.json.tpl | 25 ---- endpoint-exposer/specs/service-spec.json.tpl | 24 +-- .../templates/istio/empty-internal.yaml.tpl | 25 ---- endpoint-exposer/workflows/istio/create.yaml | 20 +-- endpoint-exposer/workflows/istio/link.yaml | 6 - endpoint-exposer/workflows/istio/unlink.yaml | 6 - endpoint-exposer/workflows/istio/update.yaml | 41 +----- 16 files changed, 74 insertions(+), 327 deletions(-) delete mode 100755 endpoint-exposer/scripts/common/echo delete mode 100644 endpoint-exposer/specs/link-spec.json.tpl delete mode 100644 endpoint-exposer/specs/links/refresh.json.tpl delete mode 100644 endpoint-exposer/templates/istio/empty-internal.yaml.tpl delete mode 100644 endpoint-exposer/workflows/istio/link.yaml delete mode 100644 endpoint-exposer/workflows/istio/unlink.yaml diff --git a/endpoint-exposer/scripts/common/echo b/endpoint-exposer/scripts/common/echo deleted file mode 100755 index ace31ee..0000000 --- a/endpoint-exposer/scripts/common/echo +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -echo "$MESSAGE" \ No newline at end of file diff --git a/endpoint-exposer/scripts/istio/build_context b/endpoint-exposer/scripts/istio/build_context index 5303734..9bbb3c1 100644 --- a/endpoint-exposer/scripts/istio/build_context +++ b/endpoint-exposer/scripts/istio/build_context @@ -8,20 +8,12 @@ SERVICE_NAME=$(echo "$CONTEXT" | jq -r .service.slug) ACTION_ID=$(echo "$CONTEXT" | jq -r .id) ACTION_NAME=$(echo "$CONTEXT" | jq -r .slug) -# Extract domains from parameters +# Extract domain from parameters PUBLIC_DOMAIN=$(echo "$CONTEXT" | jq -r '.parameters.public_domain // ""') -PRIVATE_DOMAIN=$(echo "$CONTEXT" | jq -r '.parameters.private_domain // ""') # Extract routes array from parameters ROUTES_JSON=$(echo "$CONTEXT" | jq -c '.parameters.routes // []') -# For backward compatibility with link-based workflow -LINK_ID=$(echo "$CONTEXT" | jq -r '.link.id // ""') -LINK_NAME=$(echo "$CONTEXT" | jq -r '.link.slug // ""') -SCOPE_ID=$(echo "$CONTEXT" | jq -r '.tags.scope_id // ""') -SCOPE_SLUG=$(echo "$CONTEXT" | jq -r '.tags.scope // ""') -RULE_PATH=$(echo "$CONTEXT" | jq -r '.link.attributes.path // .parameters.path // ""') - CONTEXT=$(echo "$CONTEXT" | jq \ --arg k8s_namespace "$K8S_NAMESPACE" \ --arg alb_name "$ALB_NAME" \ @@ -36,10 +28,4 @@ export SERVICE_NAME export ACTION_ID export ACTION_NAME export PUBLIC_DOMAIN -export PRIVATE_DOMAIN -export ROUTES_JSON -export LINK_ID -export LINK_NAME -export SCOPE_ID -export SCOPE_SLUG -export RULE_PATH \ No newline at end of file +export ROUTES_JSON \ No newline at end of file diff --git a/endpoint-exposer/scripts/istio/build_ingress b/endpoint-exposer/scripts/istio/build_ingress index ad54d62..cfa9bb8 100644 --- a/endpoint-exposer/scripts/istio/build_ingress +++ b/endpoint-exposer/scripts/istio/build_ingress @@ -2,20 +2,11 @@ set -euo pipefail -# Determine which domain to use and output file based on template -if [[ "$TEMPLATE" == *"internal"* ]]; then - # Internal HTTPRoute - SERVICE_DOMAIN=$(echo "$CONTEXT" | jq -r '.parameters.private_domain // .service.attributes.private_domain') - HTTPROUTE_FILE="${OUTPUT_FILE:-$OUTPUT_DIR/httproute-$SERVICE_ID-internal.yaml}" - echo "Creating internal HTTPRoute for service $SERVICE_NAME with domain $SERVICE_DOMAIN" - echo "Output file: $HTTPROUTE_FILE" -else - # Public HTTPRoute - SERVICE_DOMAIN=$(echo "$CONTEXT" | jq -r '.parameters.public_domain // .service.attributes.domain') - HTTPROUTE_FILE="${OUTPUT_FILE:-$OUTPUT_DIR/httproute-$SERVICE_ID-public.yaml}" - echo "Creating public HTTPRoute for service $SERVICE_NAME with domain $SERVICE_DOMAIN" - echo "Output file: $HTTPROUTE_FILE" -fi +# Determine domain and output file +SERVICE_DOMAIN=$(echo "$CONTEXT" | jq -r '.parameters.public_domain // .service.attributes.domain') +HTTPROUTE_FILE="${OUTPUT_FILE:-$OUTPUT_DIR/httproute-$SERVICE_ID-public.yaml}" +echo "Creating HTTPRoute for service $SERVICE_NAME with domain $SERVICE_DOMAIN" +echo "Output file: $HTTPROUTE_FILE" CONTEXT_PATH="$OUTPUT_DIR/context-$SERVICE_ID.json" diff --git a/endpoint-exposer/scripts/istio/build_ingress_with_rule b/endpoint-exposer/scripts/istio/build_ingress_with_rule index b3d5f1f..bfbf2ff 100755 --- a/endpoint-exposer/scripts/istio/build_ingress_with_rule +++ b/endpoint-exposer/scripts/istio/build_ingress_with_rule @@ -71,7 +71,6 @@ create_http_rule() { local service_json="$2" local blue_green_config="$3" local method="${4:-}" - local visibility="${5:-public}" local service_name local service_port @@ -264,13 +263,12 @@ replace_existing_rule() { local blue_green_config="$4" local rule_index="$5" local method="${6:-}" - local visibility="${7:-public}" local updated_hr local new_rule # Create the new rule - new_rule=$(create_http_rule "$rule_path" "$service_json" "$blue_green_config" "$method" "$visibility") + new_rule=$(create_http_rule "$rule_path" "$service_json" "$blue_green_config" "$method") # Replace the existing rule at the found index updated_hr=$(echo "$hr_yaml" | yq eval -o=json '.' | \ @@ -286,13 +284,12 @@ add_new_rule() { local service_json="$3" local blue_green_config="$4" local method="${5:-}" - local visibility="${6:-public}" local updated_hr local new_rule # Create the new http rule - new_rule=$(create_http_rule "$rule_path" "$service_json" "$blue_green_config" "$method" "$visibility") + new_rule=$(create_http_rule "$rule_path" "$service_json" "$blue_green_config" "$method") # Add the new rule to the existing rules array updated_hr=$(echo "$hr_yaml" | yq eval ".spec.rules += [$new_rule]") @@ -307,7 +304,6 @@ echo "SERVICE_ID: $SERVICE_ID" echo "SCOPE_ID: $SCOPE_ID" echo "RULE_PATH: $RULE_PATH" echo "METHOD: ${METHOD:-not specified}" -echo "VISIBILITY: ${VISIBILITY:-public}" # Check if HTTPROUTE_FILE is set (called from process_routes) if [[ -n "${HTTPROUTE_FILE:-}" && -f "$HTTPROUTE_FILE" ]]; then @@ -353,7 +349,7 @@ echo "Is HTTPRoute empty? $IS_EMPTY" if [[ "$IS_EMPTY" == "true" ]]; then echo "Case 1: Empty HTTPRoute - replacing fallback rule (index 0) with new rule" - UPDATED_HR=$(replace_existing_rule "$HTTPROUTE" "$RULE_PATH" "$SERVICE" "$BLUE_GREEN_CONFIG" "0" "${METHOD:-}" "${VISIBILITY:-public}") + UPDATED_HR=$(replace_existing_rule "$HTTPROUTE" "$RULE_PATH" "$SERVICE" "$BLUE_GREEN_CONFIG" "0" "${METHOD:-}") echo "$UPDATED_HR" | yq "." > "$HTTPROUTE_FILE" else # Detect the converted path value to match against existing rules @@ -366,12 +362,12 @@ else # if there is a rule for the path we replace it if [[ "$RULE_INDEX" != "-1" ]]; then echo "Case 2: Replacing existing rule at index $RULE_INDEX" - UPDATED_HR=$(replace_existing_rule "$HTTPROUTE" "$RULE_PATH" "$SERVICE" "$BLUE_GREEN_CONFIG" "$RULE_INDEX" "${METHOD:-}" "${VISIBILITY:-public}") + UPDATED_HR=$(replace_existing_rule "$HTTPROUTE" "$RULE_PATH" "$SERVICE" "$BLUE_GREEN_CONFIG" "$RULE_INDEX" "${METHOD:-}") echo "$UPDATED_HR" | yq "." > "$HTTPROUTE_FILE" else # if there is no rule for the path we add a new one echo "Case 3: Adding new rule" - UPDATED_HR=$(add_new_rule "$HTTPROUTE" "$RULE_PATH" "$SERVICE" "$BLUE_GREEN_CONFIG" "${METHOD:-}" "${VISIBILITY:-public}") + UPDATED_HR=$(add_new_rule "$HTTPROUTE" "$RULE_PATH" "$SERVICE" "$BLUE_GREEN_CONFIG" "${METHOD:-}") # Debug: Check if hostnames and parentRefs are present before saving echo "DEBUG: Checking HTTPRoute before saving..." diff --git a/endpoint-exposer/scripts/istio/clean_httproute_rules b/endpoint-exposer/scripts/istio/clean_httproute_rules index ae6087c..85179f6 100755 --- a/endpoint-exposer/scripts/istio/clean_httproute_rules +++ b/endpoint-exposer/scripts/istio/clean_httproute_rules @@ -2,14 +2,6 @@ set -euo pipefail -# If HTTPROUTE_FILE_VAR is provided, use it to get the file path from that variable -if [[ -n "${HTTPROUTE_FILE_VAR:-}" ]]; then - # Use indirect variable expansion safely - if [[ -n "${!HTTPROUTE_FILE_VAR:-}" ]]; then - HTTPROUTE_FILE="${!HTTPROUTE_FILE_VAR}" - fi -fi - echo "=== Cleaning HTTPRoute rules ===" echo "HTTPROUTE_FILE: $HTTPROUTE_FILE" diff --git a/endpoint-exposer/scripts/istio/fetch_httproute b/endpoint-exposer/scripts/istio/fetch_httproute index a30d3c7..1846bef 100755 --- a/endpoint-exposer/scripts/istio/fetch_httproute +++ b/endpoint-exposer/scripts/istio/fetch_httproute @@ -7,25 +7,16 @@ echo "SERVICE_ID: $SERVICE_ID" echo "SERVICE_NAME: $SERVICE_NAME" echo "K8S_NAMESPACE: $K8S_NAMESPACE" -# Determine visibility (default to public if not set) -VISIBILITY="${VISIBILITY:-public}" -echo "Visibility: $VISIBILITY" - # Build the HTTPRoute name using the same pattern as the template -if [[ "$VISIBILITY" == "internal" ]]; then - HTTPROUTE_NAME="${SERVICE_NAME}-${SERVICE_ID}-route-internal" - TEMPLATE="$SERVICE_PATH/templates/istio/empty-internal.yaml.tpl" -else - HTTPROUTE_NAME="${SERVICE_NAME}-${SERVICE_ID}-route" - TEMPLATE="$SERVICE_PATH/templates/istio/empty.yaml.tpl" -fi +HTTPROUTE_NAME="${SERVICE_NAME}-${SERVICE_ID}-route" +TEMPLATE="$SERVICE_PATH/templates/istio/empty.yaml.tpl" echo "HTTPRoute name: $HTTPROUTE_NAME" -# Define output file - use OUTPUT_FILE if set, otherwise default based on visibility +# Define output file if [[ -n "${OUTPUT_FILE:-}" ]]; then HTTPROUTE_FILE="$OUTPUT_FILE" else - HTTPROUTE_FILE="$OUTPUT_DIR/httproute-$SERVICE_ID-$VISIBILITY.yaml" + HTTPROUTE_FILE="$OUTPUT_DIR/httproute-$SERVICE_ID-public.yaml" fi # Create output directory if it doesn't exist diff --git a/endpoint-exposer/scripts/istio/process_routes b/endpoint-exposer/scripts/istio/process_routes index 44bb233..670d1a7 100755 --- a/endpoint-exposer/scripts/istio/process_routes +++ b/endpoint-exposer/scripts/istio/process_routes @@ -44,110 +44,67 @@ SORTED_ROUTES=$(echo "$ROUTES_JSON" | jq 'sort_by( ROUTES_JSON="$SORTED_ROUTES" echo "Routes sorted by specificity (Exact > RegularExpression > PathPrefix)" -# Separate routes by visibility -echo "" -echo "=== Separating routes by visibility ===" -PUBLIC_ROUTES=$(echo "$ROUTES_JSON" | jq '[.[] | select(.visibility == "public")]') -INTERNAL_ROUTES=$(echo "$ROUTES_JSON" | jq '[.[] | select(.visibility == "internal")]') - -NUM_PUBLIC=$(echo "$PUBLIC_ROUTES" | jq 'length') -NUM_INTERNAL=$(echo "$INTERNAL_ROUTES" | jq 'length') +# Define HTTPRoute file +HTTPROUTE_FILE="$OUTPUT_DIR/httproute-$SERVICE_ID-public.yaml" +HTTPROUTE_NAME="${SERVICE_NAME}-${SERVICE_ID}-route" -echo "Public routes: $NUM_PUBLIC" -echo "Internal routes: $NUM_INTERNAL" +export HTTPROUTE_FILE +echo "HTTPRoute file: $HTTPROUTE_FILE" +echo "HTTPRoute name: $HTTPROUTE_NAME" -# Function to process routes for a specific visibility -process_routes_for_visibility() { - local visibility="$1" - local routes_json="$2" - local num_routes="$3" - - if [[ "$num_routes" -eq 0 ]]; then - echo "No $visibility routes to process" - return 0 - fi +# Read the HTTPRoute from the file created in the previous step +if [[ ! -f "$HTTPROUTE_FILE" ]]; then + echo "ERROR: HTTPRoute file not found at $HTTPROUTE_FILE" + exit 1 +fi +# Process each route +for ((i=0; i