|
| 1 | +#!/bin/bash |
| 2 | +# Force-tears-down a bosh-lite environment directly via the GCP CPI and |
| 3 | +# gcloud, bypassing bbl/bosh's graceful deployment-deletion path entirely. |
| 4 | +# |
| 5 | +# Use this when `bbl down` hangs or fails - e.g. warden bind-mount |
| 6 | +# "target is busy" errors during deployment deletion, or SSH-tunnel |
| 7 | +# connectivity issues to an unhealthy director/jumpbox. `bosh delete-env` |
| 8 | +# only needs the local state file + the CPI (GCP API) to destroy a VM, so it |
| 9 | +# works even when the director/jumpbox is unresponsive or already gone. |
| 10 | +# |
| 11 | +# Usage: force-delete-env.sh <env-name> |
| 12 | +# Required env vars: BBL_GCP_SERVICE_ACCOUNT_KEY_PATH, GOOGLE_CLOUD_PROJECT, |
| 13 | +# BBL_GCP_REGION |
| 14 | +# Expects <env-name>/bbl-state to already be downloaded in the cwd. |
| 15 | + |
| 16 | +set -uo pipefail |
| 17 | + |
| 18 | +env_name="$1" |
| 19 | +state_dir="${env_name}/bbl-state" |
| 20 | +zone="$(jq -r '.gcp.zone' "${state_dir}/bbl-state.json")" |
| 21 | + |
| 22 | +echo "Force-deleting director VM for ${env_name}" |
| 23 | +bosh delete-env \ |
| 24 | + "${state_dir}/bosh-deployment/bosh.yml" \ |
| 25 | + --state "${state_dir}/vars/bosh-state.json" \ |
| 26 | + --vars-store "${state_dir}/vars/director-vars-store.yml" \ |
| 27 | + --vars-file "${state_dir}/vars/director-vars-file.yml" \ |
| 28 | + -o "${state_dir}/bosh-deployment/gcp/cpi.yml" \ |
| 29 | + -o "${state_dir}/bosh-deployment/jumpbox-user.yml" \ |
| 30 | + -o "${state_dir}/bosh-deployment/uaa.yml" \ |
| 31 | + -o "${state_dir}/bosh-deployment/credhub.yml" \ |
| 32 | + -o "${state_dir}/bbl-ops-files/gcp/bosh-director-ephemeral-ip-ops.yml" \ |
| 33 | + --var-file gcp_credentials_json="${BBL_GCP_SERVICE_ACCOUNT_KEY_PATH}" \ |
| 34 | + -v project_id="${GOOGLE_CLOUD_PROJECT}" \ |
| 35 | + -v zone="${zone}" \ |
| 36 | + --non-interactive || true |
| 37 | + |
| 38 | +echo "Force-deleting jumpbox VM for ${env_name}" |
| 39 | +bosh delete-env \ |
| 40 | + "${state_dir}/jumpbox-deployment/jumpbox.yml" \ |
| 41 | + --state "${state_dir}/vars/jumpbox-state.json" \ |
| 42 | + --vars-store "${state_dir}/vars/jumpbox-vars-store.yml" \ |
| 43 | + --vars-file "${state_dir}/vars/jumpbox-vars-file.yml" \ |
| 44 | + -o "${state_dir}/jumpbox-deployment/gcp/cpi.yml" \ |
| 45 | + --var-file gcp_credentials_json="${BBL_GCP_SERVICE_ACCOUNT_KEY_PATH}" \ |
| 46 | + -v project_id="${GOOGLE_CLOUD_PROJECT}" \ |
| 47 | + -v zone="${zone}" \ |
| 48 | + --non-interactive || true |
| 49 | + |
| 50 | +tfstate="${state_dir}/vars/terraform.tfstate" |
| 51 | +if [ -f "$tfstate" ]; then |
| 52 | + echo "Deleting remaining terraform-managed network resources for ${env_name}" |
| 53 | + |
| 54 | + jq -r '.resources[] | select(.type=="google_compute_firewall") | .instances[0].attributes.name' "$tfstate" | \ |
| 55 | + while read -r name; do gcloud compute firewall-rules delete "$name" --quiet || true; done |
| 56 | + |
| 57 | + jq -r '.resources[] | select(.type=="google_dns_record_set") | "\(.instances[0].attributes.name)\t\(.instances[0].attributes.managed_zone)\t\(.instances[0].attributes.type)"' "$tfstate" | \ |
| 58 | + while IFS=$'\t' read -r name dns_zone rtype; do gcloud dns record-sets delete "$name" --zone "$dns_zone" --type "$rtype" --quiet || true; done |
| 59 | + |
| 60 | + jq -r '.resources[] | select(.type=="google_compute_route") | .instances[0].attributes.name' "$tfstate" | \ |
| 61 | + while read -r name; do gcloud compute routes delete "$name" --quiet || true; done |
| 62 | + |
| 63 | + jq -r '.resources[] | select(.type=="google_compute_router") | .instances[0].attributes.name' "$tfstate" | \ |
| 64 | + while read -r name; do gcloud compute routers delete "$name" --region "${BBL_GCP_REGION}" --quiet || true; done |
| 65 | + |
| 66 | + jq -r '.resources[] | select(.type=="google_compute_address") | .instances[0].attributes.name' "$tfstate" | \ |
| 67 | + while read -r name; do gcloud compute addresses delete "$name" --region "${BBL_GCP_REGION}" --quiet || true; done |
| 68 | + |
| 69 | + jq -r '.resources[] | select(.type=="google_compute_subnetwork") | .instances[0].attributes.name' "$tfstate" | \ |
| 70 | + while read -r name; do gcloud compute networks subnets delete "$name" --region "${BBL_GCP_REGION}" --quiet || true; done |
| 71 | + |
| 72 | + jq -r '.resources[] | select(.type=="google_compute_network") | .instances[0].attributes.name' "$tfstate" | \ |
| 73 | + while read -r name; do gcloud compute networks delete "$name" --quiet || true; done |
| 74 | +fi |
| 75 | + |
| 76 | +echo "Force-delete complete for ${env_name}" |
0 commit comments