From 05bd00557cd504c37dfb3b45867c3804e3cc1d53 Mon Sep 17 00:00:00 2001 From: mohitrajain Date: Sun, 28 Dec 2025 18:55:16 +0100 Subject: [PATCH 1/9] build: wpb-21356 add cd_staging script --- offline/cd_staging.sh | 141 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 141 insertions(+) create mode 100755 offline/cd_staging.sh diff --git a/offline/cd_staging.sh b/offline/cd_staging.sh new file mode 100755 index 000000000..73743cae8 --- /dev/null +++ b/offline/cd_staging.sh @@ -0,0 +1,141 @@ +#!/usr/bin/env bash + +set -euo pipefail + +CD_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +TF_DIR="${CD_DIR}/../terraform/examples/wiab-staging-hetzner" +ARTIFACTS_DIR="${CD_DIR}/default-build/output" +VALUES_DIR="${CD_DIR}/../values" +COMMIT_HASH="${GITHUB_SHA}" +ARTIFACT="wire-server-deploy-static-${COMMIT_HASH}" + +# Retry configuration +MAX_RETRIES=3 +RETRY_DELAY=30 + +echo "Wire Offline Deployment with Retry Logic" +echo "========================================" + +function cleanup { + (cd "$TF_DIR" && terraform destroy -auto-approve) + echo "Cleanup completed" +} +trap cleanup EXIT + +cd "$TF_DIR" +terraform init + +# Retry loop for terraform apply +echo "Starting deployment with automatic retry on resource unavailability..." +for attempt in $(seq 1 $MAX_RETRIES); do + echo "" + echo "Deployment attempt $attempt of $MAX_RETRIES" + date + + if terraform apply -auto-approve; then + echo "Infrastructure deployment successful on attempt $attempt!" + break + else + echo "Infrastructure deployment failed on attempt $attempt" + + if [[ $attempt -lt $MAX_RETRIES ]]; then + echo "Will retry with different configuration..." + + # Clean up partial deployment + echo "Cleaning up partial deployment..." + terraform destroy -auto-approve || true + + # Wait for resources to potentially become available + echo "Waiting ${RETRY_DELAY}s for resources to become available..." + sleep $RETRY_DELAY + + } + + # Modify configuration for better availability + echo "Adjusting server type preferences for attempt $((attempt + 1))..." + case $attempt in + 1) + # Attempt 2: Prioritize cpx22 and cx53 + sed -i.bak 's/"cx33", "cpx22", "cx43"/"cpx22", "cx43", "cx33"/' main.tf + sed -i.bak 's/"cx43", "cx53", "cpx42"/"cx53", "cpx42", "cx43"/' main.tf + echo " -> Prioritizing cpx22 and cx53 server types" + ;; + 2) + # Attempt 3: Use biggest available types + sed -i.bak 's/"cpx22", "cx43", "cx33"/"cx43", "cx33", "cpx22"/' main.tf + sed -i.bak 's/"cx53", "cpx42", "cx43"/"cpx42", "cx43", "cx53"/' main.tf + echo " -> Using Biggest available server types" + ;; + esac + + terraform init -reconfigure + else + echo "All deployment attempts failed after $MAX_RETRIES tries" + echo "" + echo "This usually means:" + echo " 1. High demand for Hetzner Cloud resources in EU regions" + echo " 2. Your account may have resource limits" + echo " 3. Try again later when resources become available" + echo "" + echo "Manual solutions:" + echo " 1. Check Hetzner Console for resource limits" + echo " 2. Try different server types manually" + echo " 3. Contact Hetzner support for resource availability" + + # Restore original config + if [[ -f main.tf.bak ]]; then + mv main.tf.bak main.tf + terraform init -reconfigure + fi + + exit 1 + fi + fi +done + +# Restore original config after successful deployment +if [[ -f main.tf.bak ]]; then + mv main.tf.bak main.tf + terraform init -reconfigure +fi + +echo "" +echo "Infrastructure ready! Proceeding with application deployment..." + +# Continue with the rest of the original cd.sh logic +adminhost=$(terraform output -raw adminhost) +ssh_private_key=$(terraform output ssh_private_key) + +eval "$(ssh-agent)" +ssh-add - <<< "$ssh_private_key" +rm -f ssh_private_key || true +echo "$ssh_private_key" > ssh_private_key +chmod 400 ssh_private_key + +# TO-DO: make changes to test the deployment with demo user in +terraform output -json static-inventory > inventory.json +yq eval -o=yaml '.' inventory.json > inventory.yml + +echo "Running ansible playbook setup_nodes.yml via adminhost ($adminhost)..." +ansible-playbook -i inventory.yml setup_nodes.yml --private-key "ssh_private_key" + +# user demo needs to exist +ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ConnectionAttempts=10 \ + "demo@$adminhost" wget -q "https://s3-eu-west-1.amazonaws.com/public.wire.com/artifacts/${ARTIFACT}.tgz" + +ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ConnectionAttempts=10 \ + "demo@$adminhost" tar xzf "$ARTIFACT.tgz" + +# override for ingress-nginx-controller values for hetzner environment $TF_DIR/setup_nodes.yml +scp -A "$VALUES_DIR/ingress-nginx-controller/hetzner-ci.example.yaml" "demo@$adminhost:./values/ingress-nginx-controller/prod-values.example.yaml" + +scp inventory.yml "demo@$adminhost":./ansible/inventory/offline/inventory.yml + +ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ConnectionAttempts=10 "demo@$adminhost" cat ./ansible/inventory/offline/inventory.yml || true + +# NOTE: Agent is forwarded; so that the adminhost can provision the other boxes +ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ConnectionAttempts=10 -A "demo@$adminhost" ./bin/offline-deploy.sh + +echo "" +echo "Wire offline deployment completed successfully!" +cleanup From d8c293993911ea648058baef746ef797f28d1e30 Mon Sep 17 00:00:00 2001 From: mohitrajain Date: Sun, 28 Dec 2025 19:06:13 +0100 Subject: [PATCH 2/9] build: wpb-21356 add changelog for cd_staging script --- changelog.d/3-deploy-builds/wiab-staging | 1 + 1 file changed, 1 insertion(+) diff --git a/changelog.d/3-deploy-builds/wiab-staging b/changelog.d/3-deploy-builds/wiab-staging index 634572285..b428dbc9f 100644 --- a/changelog.d/3-deploy-builds/wiab-staging +++ b/changelog.d/3-deploy-builds/wiab-staging @@ -3,3 +3,4 @@ Added: now offline-vm-setup.sh waits on VMs to be alive, and health checks them. Changed: Add ansible playbook for wiab-staging VM provisioning Fixed: offline-deploy.sh for SSH_AUTH_SOCK handling and remove defunct passwords for postgresql Added: terraform resources for wiab-staging +Added: cd_staging script to verify the default build bundle From ce275489906816037220457ec3edf8413267b014 Mon Sep 17 00:00:00 2001 From: mohitrajain Date: Sun, 28 Dec 2025 22:40:41 +0100 Subject: [PATCH 3/9] build: wpb-21356 enable creating secondary inventory for the VMs --- offline/cd_staging.sh | 71 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 67 insertions(+), 4 deletions(-) diff --git a/offline/cd_staging.sh b/offline/cd_staging.sh index 73743cae8..680393f43 100755 --- a/offline/cd_staging.sh +++ b/offline/cd_staging.sh @@ -49,8 +49,6 @@ for attempt in $(seq 1 $MAX_RETRIES); do echo "Waiting ${RETRY_DELAY}s for resources to become available..." sleep $RETRY_DELAY - } - # Modify configuration for better availability echo "Adjusting server type preferences for attempt $((attempt + 1))..." case $attempt in @@ -112,7 +110,6 @@ rm -f ssh_private_key || true echo "$ssh_private_key" > ssh_private_key chmod 400 ssh_private_key -# TO-DO: make changes to test the deployment with demo user in terraform output -json static-inventory > inventory.json yq eval -o=yaml '.' inventory.json > inventory.yml @@ -129,7 +126,73 @@ ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ConnectionAt # override for ingress-nginx-controller values for hetzner environment $TF_DIR/setup_nodes.yml scp -A "$VALUES_DIR/ingress-nginx-controller/hetzner-ci.example.yaml" "demo@$adminhost:./values/ingress-nginx-controller/prod-values.example.yaml" -scp inventory.yml "demo@$adminhost":./ansible/inventory/offline/inventory.yml +# Source and target files +SOURCE="inventory.yml" +cp "${CD_DIR}/../ansible/inventory/offline/staging.yml" "inventory-secondary.yml" +TARGET="inventory-secondary.yml" + +# Read assethost IP +ASSETHOST_IP=$(yq eval '.assethost.hosts.assethost.ansible_host' "$SOURCE") +yq eval -i ".assethost.hosts.assethost.ansible_host = \"$ASSETHOST_IP\"" "$TARGET" + +# Read kube-node IPs using to_entries +KUBENODE1_IP=$(yq eval '.["kube-node"].hosts | to_entries | .[0].value.ansible_host' "$SOURCE") +KUBENODE2_IP=$(yq eval '.["kube-node"].hosts | to_entries | .[1].value.ansible_host' "$SOURCE") +KUBENODE3_IP=$(yq eval '.["kube-node"].hosts | to_entries | .[2].value.ansible_host' "$SOURCE") + +yq eval -i ".kube-node.hosts.kubenode1.ansible_host = \"$KUBENODE1_IP\"" "$TARGET" +yq eval -i ".kube-node.hosts.kubenode2.ansible_host = \"$KUBENODE2_IP\"" "$TARGET" +yq eval -i ".kube-node.hosts.kubenode3.ansible_host = \"$KUBENODE3_IP\"" "$TARGET" + +# Read datanode IPs using to_entries +DATANODE1_IP=$(yq eval '.datanode.hosts | to_entries | .[0].value.ansible_host' "$SOURCE") +DATANODE2_IP=$(yq eval '.datanode.hosts | to_entries | .[1].value.ansible_host' "$SOURCE") +DATANODE3_IP=$(yq eval '.datanode.hosts | to_entries | .[2].value.ansible_host' "$SOURCE") + +# Set cassandra IPs +yq eval -i ".cassandra.hosts.cassandra1.ansible_host = \"$DATANODE1_IP\"" "$TARGET" +yq eval -i ".cassandra.hosts.cassandra2.ansible_host = \"$DATANODE2_IP\"" "$TARGET" +yq eval -i ".cassandra.hosts.cassandra3.ansible_host = \"$DATANODE3_IP\"" "$TARGET" + +# Set elasticsearch IPs +yq eval -i ".elasticsearch.hosts.elasticsearch1.ansible_host = \"$DATANODE1_IP\"" "$TARGET" +yq eval -i ".elasticsearch.hosts.elasticsearch2.ansible_host = \"$DATANODE2_IP\"" "$TARGET" +yq eval -i ".elasticsearch.hosts.elasticsearch3.ansible_host = \"$DATANODE3_IP\"" "$TARGET" + +# Set minio IPs +yq eval -i ".minio.hosts.minio1.ansible_host = \"$DATANODE1_IP\"" "$TARGET" +yq eval -i ".minio.hosts.minio2.ansible_host = \"$DATANODE2_IP\"" "$TARGET" +yq eval -i ".minio.hosts.minio3.ansible_host = \"$DATANODE3_IP\"" "$TARGET" + +# Set rabbitmq IPs +yq eval -i ".rabbitmq.hosts.rabbitmq1.ansible_host = \"$DATANODE1_IP\"" "$TARGET" +yq eval -i ".rabbitmq.hosts.rabbitmq2.ansible_host = \"$DATANODE2_IP\"" "$TARGET" +yq eval -i ".rabbitmq.hosts.rabbitmq3.ansible_host = \"$DATANODE3_IP\"" "$TARGET" + +# Set postgresql IPs +yq eval -i ".postgresql.hosts.postgresql1.ansible_host = \"$DATANODE1_IP\"" "$TARGET" +yq eval -i ".postgresql.hosts.postgresql2.ansible_host = \"$DATANODE2_IP\"" "$TARGET" +yq eval -i ".postgresql.hosts.postgresql3.ansible_host = \"$DATANODE3_IP\"" "$TARGET" + +# Override network_interface from SOURCE to TARGET for all service groups +NETWORK_INTERFACE=$(yq eval '.datanode.vars.datanode_network_interface' "$SOURCE") +yq eval -i ".cassandra.vars.cassandra_network_interface = \"$NETWORK_INTERFACE\"" "$TARGET" +yq eval -i ".elasticsearch.vars.elasticsearch_network_interface = \"$NETWORK_INTERFACE\"" "$TARGET" +yq eval -i ".minio.vars.minio_network_interface = \"$NETWORK_INTERFACE\"" "$TARGET" +yq eval -i ".rabbitmq.vars.rabbitmq_network_interface = \"$NETWORK_INTERFACE\"" "$TARGET" +yq eval -i ".postgresql.vars.postgresql_network_interface = \"$NETWORK_INTERFACE\"" "$TARGET" + +# Extract all kube-node vars from SOURCE and merge into TARGET +KUBE_NODE_VARS_FILE=$(mktemp) +yq eval '.["kube-node"].vars' "$SOURCE" > "$KUBE_NODE_VARS_FILE" +yq eval -i '.kube-node.vars |= load("'"$KUBE_NODE_VARS_FILE"'")' "$TARGET" +rm -f "$KUBE_NODE_VARS_FILE" + +yq eval -i ".all.vars.ansible_ssh_private_key_file = \"ssh/ssh_private_key\"" "$TARGET" + +echo "created secondary inventory file $TARGET successfully" + +scp "$TARGET" "demo@$adminhost":./ansible/inventory/offline/inventory.yml ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ConnectionAttempts=10 "demo@$adminhost" cat ./ansible/inventory/offline/inventory.yml || true From 875d9d5584428e891a85467baa115b4c34465892 Mon Sep 17 00:00:00 2001 From: mohitrajain Date: Fri, 9 Jan 2026 11:30:45 +0100 Subject: [PATCH 4/9] fix: wpb-22439 cd_staging script as per wiab-staging inventory --- offline/cd_staging.sh | 28 ++++------------------------ 1 file changed, 4 insertions(+), 24 deletions(-) diff --git a/offline/cd_staging.sh b/offline/cd_staging.sh index 680393f43..348661588 100755 --- a/offline/cd_staging.sh +++ b/offline/cd_staging.sh @@ -149,30 +149,10 @@ DATANODE1_IP=$(yq eval '.datanode.hosts | to_entries | .[0].value.ansible_host' DATANODE2_IP=$(yq eval '.datanode.hosts | to_entries | .[1].value.ansible_host' "$SOURCE") DATANODE3_IP=$(yq eval '.datanode.hosts | to_entries | .[2].value.ansible_host' "$SOURCE") -# Set cassandra IPs -yq eval -i ".cassandra.hosts.cassandra1.ansible_host = \"$DATANODE1_IP\"" "$TARGET" -yq eval -i ".cassandra.hosts.cassandra2.ansible_host = \"$DATANODE2_IP\"" "$TARGET" -yq eval -i ".cassandra.hosts.cassandra3.ansible_host = \"$DATANODE3_IP\"" "$TARGET" - -# Set elasticsearch IPs -yq eval -i ".elasticsearch.hosts.elasticsearch1.ansible_host = \"$DATANODE1_IP\"" "$TARGET" -yq eval -i ".elasticsearch.hosts.elasticsearch2.ansible_host = \"$DATANODE2_IP\"" "$TARGET" -yq eval -i ".elasticsearch.hosts.elasticsearch3.ansible_host = \"$DATANODE3_IP\"" "$TARGET" - -# Set minio IPs -yq eval -i ".minio.hosts.minio1.ansible_host = \"$DATANODE1_IP\"" "$TARGET" -yq eval -i ".minio.hosts.minio2.ansible_host = \"$DATANODE2_IP\"" "$TARGET" -yq eval -i ".minio.hosts.minio3.ansible_host = \"$DATANODE3_IP\"" "$TARGET" - -# Set rabbitmq IPs -yq eval -i ".rabbitmq.hosts.rabbitmq1.ansible_host = \"$DATANODE1_IP\"" "$TARGET" -yq eval -i ".rabbitmq.hosts.rabbitmq2.ansible_host = \"$DATANODE2_IP\"" "$TARGET" -yq eval -i ".rabbitmq.hosts.rabbitmq3.ansible_host = \"$DATANODE3_IP\"" "$TARGET" - -# Set postgresql IPs -yq eval -i ".postgresql.hosts.postgresql1.ansible_host = \"$DATANODE1_IP\"" "$TARGET" -yq eval -i ".postgresql.hosts.postgresql2.ansible_host = \"$DATANODE2_IP\"" "$TARGET" -yq eval -i ".postgresql.hosts.postgresql3.ansible_host = \"$DATANODE3_IP\"" "$TARGET" +# Set datanodes IPs +yq eval -i ".datanodes.hosts.datanode1.ansible_host = \"$DATANODE1_IP\"" "$TARGET" +yq eval -i ".datanodes.hosts.datanode2.ansible_host = \"$DATANODE2_IP\"" "$TARGET" +yq eval -i ".datanodes.hosts.datanode3.ansible_host = \"$DATANODE3_IP\"" "$TARGET" # Override network_interface from SOURCE to TARGET for all service groups NETWORK_INTERFACE=$(yq eval '.datanode.vars.datanode_network_interface' "$SOURCE") From bc301d85c198a34d89c971e8a451f07893989bdb Mon Sep 17 00:00:00 2001 From: mohitrajain Date: Thu, 29 Jan 2026 18:22:22 +0100 Subject: [PATCH 5/9] fix: wpb-22439 fix secondary-inventory geenration logic to keep the original hostnames and bring SSH_OPTS --- offline/cd_staging.sh | 39 ++++++++++++++++++--------------------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/offline/cd_staging.sh b/offline/cd_staging.sh index 348661588..e9d2febdc 100755 --- a/offline/cd_staging.sh +++ b/offline/cd_staging.sh @@ -100,6 +100,9 @@ fi echo "" echo "Infrastructure ready! Proceeding with application deployment..." +# Common SSH options for all ssh and scp commands +SSH_OPTS="-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ConnectionAttempts=10 -o ConnectTimeout=15 -o ServerAliveInterval=15 -o ServerAliveCountMax=4 -o TCPKeepAlive=yes" + # Continue with the rest of the original cd.sh logic adminhost=$(terraform output -raw adminhost) ssh_private_key=$(terraform output ssh_private_key) @@ -117,14 +120,12 @@ echo "Running ansible playbook setup_nodes.yml via adminhost ($adminhost)..." ansible-playbook -i inventory.yml setup_nodes.yml --private-key "ssh_private_key" # user demo needs to exist -ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ConnectionAttempts=10 \ - "demo@$adminhost" wget -q "https://s3-eu-west-1.amazonaws.com/public.wire.com/artifacts/${ARTIFACT}.tgz" +ssh $SSH_OPTS "demo@$adminhost" wget -q "https://s3-eu-west-1.amazonaws.com/public.wire.com/artifacts/${ARTIFACT}.tgz" -ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ConnectionAttempts=10 \ - "demo@$adminhost" tar xzf "$ARTIFACT.tgz" +ssh $SSH_OPTS "demo@$adminhost" tar xzf "$ARTIFACT.tgz" # override for ingress-nginx-controller values for hetzner environment $TF_DIR/setup_nodes.yml -scp -A "$VALUES_DIR/ingress-nginx-controller/hetzner-ci.example.yaml" "demo@$adminhost:./values/ingress-nginx-controller/prod-values.example.yaml" +scp $SSH_OPTS "$VALUES_DIR/ingress-nginx-controller/hetzner-ci.example.yaml" "demo@$adminhost:./values/ingress-nginx-controller/prod-values.example.yaml" # Source and target files SOURCE="inventory.yml" @@ -144,23 +145,21 @@ yq eval -i ".kube-node.hosts.kubenode1.ansible_host = \"$KUBENODE1_IP\"" "$TARGE yq eval -i ".kube-node.hosts.kubenode2.ansible_host = \"$KUBENODE2_IP\"" "$TARGET" yq eval -i ".kube-node.hosts.kubenode3.ansible_host = \"$KUBENODE3_IP\"" "$TARGET" -# Read datanode IPs using to_entries -DATANODE1_IP=$(yq eval '.datanode.hosts | to_entries | .[0].value.ansible_host' "$SOURCE") -DATANODE2_IP=$(yq eval '.datanode.hosts | to_entries | .[1].value.ansible_host' "$SOURCE") -DATANODE3_IP=$(yq eval '.datanode.hosts | to_entries | .[2].value.ansible_host' "$SOURCE") - -# Set datanodes IPs -yq eval -i ".datanodes.hosts.datanode1.ansible_host = \"$DATANODE1_IP\"" "$TARGET" -yq eval -i ".datanodes.hosts.datanode2.ansible_host = \"$DATANODE2_IP\"" "$TARGET" -yq eval -i ".datanodes.hosts.datanode3.ansible_host = \"$DATANODE3_IP\"" "$TARGET" +# Reset datanodes hosts and repopulate with actual names from SOURCE +yq eval -i '.datanodes.hosts = {}' "$TARGET" +while IFS= read -r DATANODE_NAME; do + DATANODE_IP=$(yq eval ".datanode.hosts[\"${DATANODE_NAME}\"].ansible_host" "$SOURCE") + yq eval -i ".datanodes.hosts[\"${DATANODE_NAME}\"].ansible_host = \"${DATANODE_IP}\"" "$TARGET" +done < <(yq eval '.datanode.hosts | keys | .[]' "$SOURCE") # Override network_interface from SOURCE to TARGET for all service groups NETWORK_INTERFACE=$(yq eval '.datanode.vars.datanode_network_interface' "$SOURCE") yq eval -i ".cassandra.vars.cassandra_network_interface = \"$NETWORK_INTERFACE\"" "$TARGET" yq eval -i ".elasticsearch.vars.elasticsearch_network_interface = \"$NETWORK_INTERFACE\"" "$TARGET" yq eval -i ".minio.vars.minio_network_interface = \"$NETWORK_INTERFACE\"" "$TARGET" -yq eval -i ".rabbitmq.vars.rabbitmq_network_interface = \"$NETWORK_INTERFACE\"" "$TARGET" -yq eval -i ".postgresql.vars.postgresql_network_interface = \"$NETWORK_INTERFACE\"" "$TARGET" +yq eval -i ".rmq-cluster.vars.rabbitmq_network_interface = \"$NETWORK_INTERFACE\"" "$TARGET" +RABBITMQ_MASTER=$(yq eval '.datanode.hosts | keys | .[0]' "$SOURCE") +yq eval -i ".rmq-cluster.vars.rabbitmq_cluster_master = \"${RABBITMQ_MASTER}\"" "$TARGET" # Extract all kube-node vars from SOURCE and merge into TARGET KUBE_NODE_VARS_FILE=$(mktemp) @@ -168,16 +167,14 @@ yq eval '.["kube-node"].vars' "$SOURCE" > "$KUBE_NODE_VARS_FILE" yq eval -i '.kube-node.vars |= load("'"$KUBE_NODE_VARS_FILE"'")' "$TARGET" rm -f "$KUBE_NODE_VARS_FILE" -yq eval -i ".all.vars.ansible_ssh_private_key_file = \"ssh/ssh_private_key\"" "$TARGET" - echo "created secondary inventory file $TARGET successfully" -scp "$TARGET" "demo@$adminhost":./ansible/inventory/offline/inventory.yml +scp $SSH_OPTS "$TARGET" "demo@$adminhost":./ansible/inventory/offline/inventory.yml -ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ConnectionAttempts=10 "demo@$adminhost" cat ./ansible/inventory/offline/inventory.yml || true +ssh $SSH_OPTS "demo@$adminhost" cat ./ansible/inventory/offline/inventory.yml || true # NOTE: Agent is forwarded; so that the adminhost can provision the other boxes -ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ConnectionAttempts=10 -A "demo@$adminhost" ./bin/offline-deploy.sh +ssh $SSH_OPTS -A "demo@$adminhost" ./bin/offline-deploy.sh echo "" echo "Wire offline deployment completed successfully!" From e5745b4a4e11bb00f0590a98be6cc33d316c3cc5 Mon Sep 17 00:00:00 2001 From: mohitrajain Date: Thu, 29 Jan 2026 20:15:55 +0100 Subject: [PATCH 6/9] fix: wpb-22439 create a separate group for rabbitmq-hosts and keep other groups same --- offline/cd_staging.sh | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/offline/cd_staging.sh b/offline/cd_staging.sh index e9d2febdc..3cbb9765c 100755 --- a/offline/cd_staging.sh +++ b/offline/cd_staging.sh @@ -145,12 +145,15 @@ yq eval -i ".kube-node.hosts.kubenode1.ansible_host = \"$KUBENODE1_IP\"" "$TARGE yq eval -i ".kube-node.hosts.kubenode2.ansible_host = \"$KUBENODE2_IP\"" "$TARGET" yq eval -i ".kube-node.hosts.kubenode3.ansible_host = \"$KUBENODE3_IP\"" "$TARGET" -# Reset datanodes hosts and repopulate with actual names from SOURCE -yq eval -i '.datanodes.hosts = {}' "$TARGET" -while IFS= read -r DATANODE_NAME; do - DATANODE_IP=$(yq eval ".datanode.hosts[\"${DATANODE_NAME}\"].ansible_host" "$SOURCE") - yq eval -i ".datanodes.hosts[\"${DATANODE_NAME}\"].ansible_host = \"${DATANODE_IP}\"" "$TARGET" -done < <(yq eval '.datanode.hosts | keys | .[]' "$SOURCE") +# Read datanode IPs using to_entries +DATANODE1_IP=$(yq eval '.datanode.hosts | to_entries | .[0].value.ansible_host' "$SOURCE") +DATANODE2_IP=$(yq eval '.datanode.hosts | to_entries | .[1].value.ansible_host' "$SOURCE") +DATANODE3_IP=$(yq eval '.datanode.hosts | to_entries | .[2].value.ansible_host' "$SOURCE") + +# Set datanodes IPs +yq eval -i ".datanodes.hosts.datanode1.ansible_host = \"$DATANODE1_IP\"" "$TARGET" +yq eval -i ".datanodes.hosts.datanode2.ansible_host = \"$DATANODE2_IP\"" "$TARGET" +yq eval -i ".datanodes.hosts.datanode3.ansible_host = \"$DATANODE3_IP\"" "$TARGET" # Override network_interface from SOURCE to TARGET for all service groups NETWORK_INTERFACE=$(yq eval '.datanode.vars.datanode_network_interface' "$SOURCE") @@ -158,8 +161,18 @@ yq eval -i ".cassandra.vars.cassandra_network_interface = \"$NETWORK_INTERFACE\" yq eval -i ".elasticsearch.vars.elasticsearch_network_interface = \"$NETWORK_INTERFACE\"" "$TARGET" yq eval -i ".minio.vars.minio_network_interface = \"$NETWORK_INTERFACE\"" "$TARGET" yq eval -i ".rmq-cluster.vars.rabbitmq_network_interface = \"$NETWORK_INTERFACE\"" "$TARGET" -RABBITMQ_MASTER=$(yq eval '.datanode.hosts | keys | .[0]' "$SOURCE") -yq eval -i ".rmq-cluster.vars.rabbitmq_cluster_master = \"${RABBITMQ_MASTER}\"" "$TARGET" + +# create a new group rabbitmq-nodes with actual names from SOURCE +while IFS= read -r DATANODE_NAME; do + DATANODE_IP=$(yq eval ".datanode.hosts[\"${DATANODE_NAME}\"].ansible_host" "$SOURCE") + yq eval -i ".rabbitmq-nodes.hosts[\"${DATANODE_NAME}\"].ansible_host = \"${DATANODE_IP}\"" "$TARGET" +done < <(yq eval '.datanode.hosts | keys | .[]' "$SOURCE") + +# point rmq-cluster to use rabbitmq-nodes +yq eval -i '.rmq-cluster.children.rabbitmq-nodes = {}' "$TARGET" + +DATANODE1=$(yq eval '.datanode.hosts | keys | .[0]' "$SOURCE") +yq eval -i ".rmq-cluster.vars.rabbitmq_cluster_master = \"${DATANODE1}\"" "$TARGET" # Extract all kube-node vars from SOURCE and merge into TARGET KUBE_NODE_VARS_FILE=$(mktemp) From cbaec2cd26acc0d5d769ac095ec9c32736e9210c Mon Sep 17 00:00:00 2001 From: mohitrajain Date: Fri, 30 Jan 2026 09:46:24 +0100 Subject: [PATCH 7/9] fix: wpb-22439 remove old children group for rmq-cluster before adding new one --- offline/cd_staging.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/offline/cd_staging.sh b/offline/cd_staging.sh index 3cbb9765c..7ea36989d 100755 --- a/offline/cd_staging.sh +++ b/offline/cd_staging.sh @@ -168,6 +168,8 @@ while IFS= read -r DATANODE_NAME; do yq eval -i ".rabbitmq-nodes.hosts[\"${DATANODE_NAME}\"].ansible_host = \"${DATANODE_IP}\"" "$TARGET" done < <(yq eval '.datanode.hosts | keys | .[]' "$SOURCE") +# clean old children nodes for rmq-cluster +yq eval -i '.rmq-cluster.children = {}' "$TARGET" # point rmq-cluster to use rabbitmq-nodes yq eval -i '.rmq-cluster.children.rabbitmq-nodes = {}' "$TARGET" From a63123a65da041798579afb351adb071269c3f1c Mon Sep 17 00:00:00 2001 From: mohitrajain Date: Fri, 30 Jan 2026 11:06:19 +0100 Subject: [PATCH 8/9] fix: wpb-22439 fix postgresql_network_interface variable for postgresql --- offline/cd_staging.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/offline/cd_staging.sh b/offline/cd_staging.sh index 7ea36989d..9f3dd9e32 100755 --- a/offline/cd_staging.sh +++ b/offline/cd_staging.sh @@ -160,6 +160,7 @@ NETWORK_INTERFACE=$(yq eval '.datanode.vars.datanode_network_interface' "$SOURCE yq eval -i ".cassandra.vars.cassandra_network_interface = \"$NETWORK_INTERFACE\"" "$TARGET" yq eval -i ".elasticsearch.vars.elasticsearch_network_interface = \"$NETWORK_INTERFACE\"" "$TARGET" yq eval -i ".minio.vars.minio_network_interface = \"$NETWORK_INTERFACE\"" "$TARGET" +yq eval -i ".postgresql.vars.postgresql_network_interface = \"$NETWORK_INTERFACE\"" "$TARGET" yq eval -i ".rmq-cluster.vars.rabbitmq_network_interface = \"$NETWORK_INTERFACE\"" "$TARGET" # create a new group rabbitmq-nodes with actual names from SOURCE From 087061d81aec6f9ebc262e4425d536473fab3413 Mon Sep 17 00:00:00 2001 From: mohitrajain Date: Tue, 17 Feb 2026 17:15:52 +0100 Subject: [PATCH 9/9] fix: wpb-22439 cd_staging.sh script to handle terrafrom nodenames for all the iventory groups --- offline/cd_staging.sh | 54 ++++++++++++++++++++++++++++--------------- 1 file changed, 36 insertions(+), 18 deletions(-) diff --git a/offline/cd_staging.sh b/offline/cd_staging.sh index 9f3dd9e32..d70028468 100755 --- a/offline/cd_staging.sh +++ b/offline/cd_staging.sh @@ -145,15 +145,23 @@ yq eval -i ".kube-node.hosts.kubenode1.ansible_host = \"$KUBENODE1_IP\"" "$TARGE yq eval -i ".kube-node.hosts.kubenode2.ansible_host = \"$KUBENODE2_IP\"" "$TARGET" yq eval -i ".kube-node.hosts.kubenode3.ansible_host = \"$KUBENODE3_IP\"" "$TARGET" -# Read datanode IPs using to_entries +# Read datanodes IPs using to_entries DATANODE1_IP=$(yq eval '.datanode.hosts | to_entries | .[0].value.ansible_host' "$SOURCE") DATANODE2_IP=$(yq eval '.datanode.hosts | to_entries | .[1].value.ansible_host' "$SOURCE") DATANODE3_IP=$(yq eval '.datanode.hosts | to_entries | .[2].value.ansible_host' "$SOURCE") -# Set datanodes IPs -yq eval -i ".datanodes.hosts.datanode1.ansible_host = \"$DATANODE1_IP\"" "$TARGET" -yq eval -i ".datanodes.hosts.datanode2.ansible_host = \"$DATANODE2_IP\"" "$TARGET" -yq eval -i ".datanodes.hosts.datanode3.ansible_host = \"$DATANODE3_IP\"" "$TARGET" +# Read datanodes names using to_entries +DATANODE1_NAME=$(yq eval '.datanode.hosts | keys | .[0]' "$SOURCE") +DATANODE2_NAME=$(yq eval '.datanode.hosts | keys | .[1]' "$SOURCE") +DATANODE3_NAME=$(yq eval '.datanode.hosts | keys | .[2]' "$SOURCE") + +# clean old hosts for datanodes +yq eval -i '.datanodes.hosts = {}' "$TARGET" + +# re-create the datanodes group with actual names from SOURCE +yq eval -i ".datanodes.hosts[\"${DATANODE1_NAME}\"].ansible_host = \"${DATANODE1_IP}\"" "$TARGET" +yq eval -i ".datanodes.hosts[\"${DATANODE2_NAME}\"].ansible_host = \"${DATANODE2_IP}\"" "$TARGET" +yq eval -i ".datanodes.hosts[\"${DATANODE3_NAME}\"].ansible_host = \"${DATANODE3_IP}\"" "$TARGET" # Override network_interface from SOURCE to TARGET for all service groups NETWORK_INTERFACE=$(yq eval '.datanode.vars.datanode_network_interface' "$SOURCE") @@ -163,24 +171,34 @@ yq eval -i ".minio.vars.minio_network_interface = \"$NETWORK_INTERFACE\"" "$TARG yq eval -i ".postgresql.vars.postgresql_network_interface = \"$NETWORK_INTERFACE\"" "$TARGET" yq eval -i ".rmq-cluster.vars.rabbitmq_network_interface = \"$NETWORK_INTERFACE\"" "$TARGET" -# create a new group rabbitmq-nodes with actual names from SOURCE -while IFS= read -r DATANODE_NAME; do - DATANODE_IP=$(yq eval ".datanode.hosts[\"${DATANODE_NAME}\"].ansible_host" "$SOURCE") - yq eval -i ".rabbitmq-nodes.hosts[\"${DATANODE_NAME}\"].ansible_host = \"${DATANODE_IP}\"" "$TARGET" -done < <(yq eval '.datanode.hosts | keys | .[]' "$SOURCE") - -# clean old children nodes for rmq-cluster -yq eval -i '.rmq-cluster.children = {}' "$TARGET" -# point rmq-cluster to use rabbitmq-nodes -yq eval -i '.rmq-cluster.children.rabbitmq-nodes = {}' "$TARGET" - -DATANODE1=$(yq eval '.datanode.hosts | keys | .[0]' "$SOURCE") -yq eval -i ".rmq-cluster.vars.rabbitmq_cluster_master = \"${DATANODE1}\"" "$TARGET" +# re-writing sub-groups for rabbitmq_cluster_master, cassandra_seed, postgresql_rw and postgresql_ro +yq eval -i ".rmq-cluster.vars.rabbitmq_cluster_master = \"${DATANODE1_NAME}\"" "$TARGET" + +yq eval -i '.cassandra_seed.hosts = {}' "$TARGET" +yq eval -i ".cassandra_seed.hosts.[\"${DATANODE1_NAME}\"] = \"\"" "$TARGET" + +yq eval -i '.postgresql_rw.hosts = {}' "$TARGET" +yq eval -i '.postgresql_ro.hosts = {}' "$TARGET" +yq eval -i ".postgresql_rw.hosts.[\"${DATANODE1_NAME}\"] = \"\"" "$TARGET" +yq eval -i ".postgresql_ro.hosts.[\"${DATANODE2_NAME}\"] = \"\"" "$TARGET" +yq eval -i ".postgresql_ro.hosts.[\"${DATANODE3_NAME}\"] = \"\"" "$TARGET" + +# re-populate the postgresql.vars.repmgr_node_config group with actual names from SOURCE +i=1 +while IFS= read -r actual_name; do + yq eval -i " + .postgresql.vars.repmgr_node_config[\"${actual_name}\"] = + .postgresql.vars.repmgr_node_config.datanode${i} + | del(.postgresql.vars.repmgr_node_config.datanode${i}) + " "$TARGET" + i=$((i+1)) +done < <(yq eval -r '.datanode.hosts | keys | .[]' "$SOURCE") # Extract all kube-node vars from SOURCE and merge into TARGET KUBE_NODE_VARS_FILE=$(mktemp) yq eval '.["kube-node"].vars' "$SOURCE" > "$KUBE_NODE_VARS_FILE" yq eval -i '.kube-node.vars |= load("'"$KUBE_NODE_VARS_FILE"'")' "$TARGET" + rm -f "$KUBE_NODE_VARS_FILE" echo "created secondary inventory file $TARGET successfully"