Skip to content

Phase 4 — Teardown

Phase 4 removes all objects created during the exercise in reverse dependency order. This phase requires explicit human confirmation before any destructive operations.

Remove objects in reverse creation order — delete objects that depend on other objects first:

  1. Mitigated Domains — delete all CSD mitigated domains created in Phase 3
  2. HTTPS Load Balancer (${F5XC_LB_NAME}-https) — strip to skeleton (preserve Let’s Encrypt certificate); full DELETE if NAMESPACE_CREATED=true or on explicit request
  3. HTTP Load Balancer (${F5XC_LB_NAME}-http) — depends on Origin Pool
  4. Origin Pool — depends on Healthcheck (if created)
  5. DNS zone cleanup — the HTTPS LB skeleton retains its managed A and ACME records (this is desired — it keeps the certificate valid). The HTTP LB’s managed records auto-clean on deletion. Manual records in default_rr_set_group need manual cleanup via PUT
  6. Healthcheck — only if created in Phase 1 Step 1
  7. Protected Domain — delete the CSD protected domain registration
  8. Namespace — only if created during Phase 1 Step 0 (NAMESPACE_CREATED=true)

If Phase 3 was executed, delete all mitigated domains before removing infrastructure objects. The standard simulation creates 6 mitigated domains:

Terminal window
for domain in cdn.jsdelivr.net esm.sh unpkg.com ga.jspm.io httpbin.org jsonplaceholder.typicode.com; do
curl -s -X DELETE \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/shape/csd/namespaces/xF5XC_NAMESPACEx/mitigated_domains/$domain"
done

Verify: List mitigated domains to confirm the count is 0 (or 1 — see note below):

Terminal window
curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/shape/csd/namespaces/xF5XC_NAMESPACEx/mitigated_domains" \
| jq '{count: (.items | length)}'

The HTTPS LB teardown behavior depends on whether the namespace was created during this demo session (NAMESPACE_CREATED variable from Phase 1 Step 0):

  • NAMESPACE_CREATED=false (pre-existing namespace) — strip to skeleton state, preserving the Let’s Encrypt certificate for reuse
  • NAMESPACE_CREATED=true (namespace created during demo) — full DELETE, since the namespace itself will be deleted and the certificate cannot be preserved

Path A: Strip to Skeleton (Pre-existing Namespace)

Section titled “Path A: Strip to Skeleton (Pre-existing Namespace)”

When the namespace is pre-existing, strip the HTTPS LB to a skeleton state — remove the origin pool reference and CSD configuration while preserving the domain binding, https_auto_cert settings, and the Let’s Encrypt certificate. This avoids triggering a new certificate request on the next demo run (Let’s Encrypt enforces a limit of 5 duplicate certificates per exact identifier set per 7 days).

Step 1 — GET the current HTTPS LB config:

Terminal window
HTTPS_LB_JSON=$(curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/config/namespaces/xF5XC_NAMESPACEx/http_loadbalancers/xF5XC_LB_NAMEx-https")

Step 2 — Strip to skeleton via jq and PUT back:

Terminal window
echo "$HTTPS_LB_JSON" | jq '{
metadata: .metadata,
spec: (.spec | del(.client_side_defense) | .disable_client_side_defense = {} | .default_route_pools = [])
}' | curl -s -X PUT \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
-H "Content-Type: application/json" \
-d @- \
"xF5XC_API_URLx/api/config/namespaces/xF5XC_NAMESPACEx/http_loadbalancers/xF5XC_LB_NAMEx-https" \
| jq .

The jq filter preserves the entire spec (domains, https_auto_cert, advertise_on_public_default_vip, and all disabled feature flags) while removing client_side_defense (replaced with disable_client_side_defense: {}) and clearing default_route_pools to an empty array. The certificate and DNS bindings remain intact.

Verify the HTTPS LB is now a skeleton:

Terminal window
curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/config/namespaces/xF5XC_NAMESPACEx/http_loadbalancers/xF5XC_LB_NAMEx-https" \
| jq '{
name: .metadata.name,
domains: .spec.domains,
has_origin_pools: ((.spec.default_route_pools // []) | length > 0),
has_csd: (.spec.client_side_defense != null),
cert_state: .spec.cert_state
}'

Expected: has_origin_pools: false, has_csd: false, domains still populated, cert_state unchanged (e.g., CertificateValid).

Path B: Full Delete (Namespace Created During Demo)

Section titled “Path B: Full Delete (Namespace Created During Demo)”

When the namespace was created during this demo session, the HTTPS LB must be fully deleted — skeleton preservation is unnecessary because the namespace itself will be removed at the end of teardown.

Terminal window
curl -s -X DELETE \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/config/namespaces/xF5XC_NAMESPACEx/http_loadbalancers/xF5XC_LB_NAMEx-https"

Verify: GET /api/config/namespaces/\{namespace\}/http_loadbalancers should not contain ${F5XC_LB_NAME}-https.

Delete the primary HTTP LB:

Terminal window
curl -s -X DELETE \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/config/namespaces/xF5XC_NAMESPACEx/http_loadbalancers/xF5XC_LB_NAMEx-http"

Verify: GET /api/config/namespaces/\{namespace\}/http_loadbalancers should not contain ${F5XC_LB_NAME}-http. If the object still appears in the list after DELETE returned 200, wait 30 seconds and re-check once. If still present after the second check, report to operator — do not proceed.

Terminal window
curl -s -X DELETE \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/config/namespaces/xF5XC_NAMESPACEx/origin_pools/xF5XC_ORIGIN_POOLx"

Verify: GET /api/config/namespaces/\{namespace\}/origin_pools should not contain the pool name. If the object still appears in the list after DELETE returned 200, wait 30 seconds and re-check once. If still present after the second check, report to operator.

Terminal window
curl -s -X DELETE \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/config/namespaces/xF5XC_NAMESPACEx/healthchecks/xF5XC_HC_NAMEx"

Verify: GET /api/config/namespaces/\{namespace\}/healthchecks should not contain the healthcheck name. If the object still appears in the list after DELETE returned 200, wait 30 seconds and re-check once. If still present after the second check, report to operator.

Delete the CSD protected domain registration. The protected domain is tenant-scoped (not namespace-scoped), but it is a CSD configuration object tied to this deployment — not shared infrastructure like the DNS zone.

Terminal window
curl -s -X DELETE \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/shape/csd/namespaces/xF5XC_NAMESPACEx/protected_domains/xF5XC_ROOT_DOMAINx"

Verify: List protected domains to confirm the domain is no longer registered:

Terminal window
curl -s -X GET \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/shape/csd/namespaces/xF5XC_NAMESPACEx/protected_domains" \
| jq '.items // [] | map(.metadata.name)'

This step runs only if the namespace was created during Phase 1 Step 0 (NAMESPACE_CREATED=true). If the namespace was pre-existing (NAMESPACE_CREATED=false), skip this step entirely — the namespace is shared infrastructure that must not be deleted.

Terminal window
if [ "$NAMESPACE_CREATED" = "true" ]; then
curl -s -X POST \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
-H "Content-Type: application/json" \
-d '{"name": "xF5XC_NAMESPACEx"}' \
"xF5XC_API_URLx/api/web/namespaces/xF5XC_NAMESPACEx/cascade_delete" | jq .
fi

Verify: Confirm the namespace no longer exists:

Terminal window
curl -s -o /dev/null -w '%\{http_code\}' \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/web/namespaces/xF5XC_NAMESPACEx"

Expected: 404 if NAMESPACE_CREATED=true, 200 if NAMESPACE_CREATED=false.

ObjectDelete StatusVerify Status
Mitigated Domains (6)All 200 (empty \{\}) or skipped if Phase 3 not runCount 0 (or 1 phantom) — PASS
HTTPS Load Balancer (-https)200 (skeleton PUT) or 200 (full DELETE if NAMESPACE_CREATED=true)Skeleton verified or not in list — PASS
HTTP Load Balancer (-http)200 (empty \{\})Not in list — PASS
Origin Pool200 (empty \{\})Not in list — PASS
Healthcheck200 (empty \{\}) or skippedNot in list — PASS
Protected Domain200 (empty \{\})Not in list — PASS
DNS zoneNOT deleted (shared infra)Zone still exists — PASS
Namespace200 (cascade delete) if NAMESPACE_CREATED=true, skipped otherwise404 if deleted, 200 if preserved — PASS

Teardown complete. When the namespace was pre-existing (NAMESPACE_CREATED=false), all deployment objects have been removed except the HTTPS LB skeleton, which preserves the Let’s Encrypt certificate and domain binding for the next demo run. When the namespace was created during the demo (NAMESPACE_CREATED=true), all objects including the HTTPS LB and namespace have been fully deleted. The DNS zone and its non-managed records remain intact in both cases.