diff --git a/ci-operator/step-registry/gcp-hcp/e2e/gcp-hcp-e2e-workflow.yaml b/ci-operator/step-registry/gcp-hcp/e2e/gcp-hcp-e2e-workflow.yaml index 1229ffffafb8a..a18c3c14236d4 100644 --- a/ci-operator/step-registry/gcp-hcp/e2e/gcp-hcp-e2e-workflow.yaml +++ b/ci-operator/step-registry/gcp-hcp/e2e/gcp-hcp-e2e-workflow.yaml @@ -3,9 +3,17 @@ workflow: steps: pre: - ref: hypershift-gcp-wif-auth + - ref: gcp-hcp-tf-provision test: - - ref: gcp-hcp-terraform-plan - post: [] + - ref: gcp-hcp-verify-argocd-sync + post: + - ref: gcp-hcp-tf-deprovision documentation: |- - E2E workflow for gcp-hcp-infra. Authenticates to GCP via WIF - and runs terraform plan on the e2e config. + E2E workflow for gcp-hcp-infra. Provisions full platform infrastructure + (region + management cluster) using Terraform Cloud ephemeral workspaces, + runs validation tests, and cleans up resources. + + Phase breakdown: + - Pre: Authenticate via WIF, provision infrastructure with terraform apply + - Test: Validate outputs and infrastructure (placeholder for now) + - Post: Clean up resources with terraform destroy (best-effort) diff --git a/ci-operator/step-registry/gcp-hcp/tf-deprovision/OWNERS b/ci-operator/step-registry/gcp-hcp/tf-deprovision/OWNERS new file mode 100644 index 0000000000000..60325af98b50d --- /dev/null +++ b/ci-operator/step-registry/gcp-hcp/tf-deprovision/OWNERS @@ -0,0 +1,18 @@ +approvers: +- apahim +- cblecker +- ckandag +- cristianoveiga +- floresroger +- gbarabasz +- jimdaga +- patjlm +reviewers: +- apahim +- cblecker +- ckandag +- cristianoveiga +- floresroger +- gbarabasz +- jimdaga +- patjlm diff --git a/ci-operator/step-registry/gcp-hcp/tf-deprovision/gcp-hcp-tf-deprovision-commands.sh b/ci-operator/step-registry/gcp-hcp/tf-deprovision/gcp-hcp-tf-deprovision-commands.sh new file mode 100755 index 0000000000000..47f7abcc89cb7 --- /dev/null +++ b/ci-operator/step-registry/gcp-hcp/tf-deprovision/gcp-hcp-tf-deprovision-commands.sh @@ -0,0 +1,157 @@ +#!/usr/bin/env bash +set -euo pipefail + +LOG="${ARTIFACT_DIR}/deprovision.log" +log() { echo "$(date -u '+%Y-%m-%d %H:%M:%S UTC') | $*" | tee -a "${LOG}"; } + +# Try to read from SHARED_DIR, fall back to reconstructing from BUILD_ID +if [[ -f "${SHARED_DIR}/workspace-name" && -f "${SHARED_DIR}/run-id" ]]; then + WORKSPACE_NAME="$(<${SHARED_DIR}/workspace-name)" + RUN_ID="$(<${SHARED_DIR}/run-id)" + log "Using workspace info from SHARED_DIR: ${WORKSPACE_NAME}" +else + log "WARNING: Workspace info not in SHARED_DIR - reconstructing from BUILD_ID" + + # Reconstruct run-id using same hash function as provision + RUN_ID="b$(echo -n "${BUILD_ID}" | sha256sum | cut -c1-7)" + WORKSPACE_NAME="platform-e2e-${RUN_ID}" + + log "Reconstructed workspace: ${WORKSPACE_NAME}" +fi + +# Validate run-id format +if [[ ! "${RUN_ID}" =~ ^[a-z][a-z0-9]{2,15}$ ]]; then + log "ERROR: Invalid run-id '${RUN_ID}'" + exit 0 # Don't fail job +fi + +# Validate TFC token mount exists +if [[ ! -f "/etc/terraform-cloud/token" ]]; then + log "ERROR: /etc/terraform-cloud/token not found" + log "Auto-destroy will clean up resources in 24h" + exit 0 # Don't fail job +fi + +log "Deprovisioning infrastructure for workspace: ${WORKSPACE_NAME}" + +# NOTE: gcloud is NOT needed here. TFC remote execution handles GCP auth +# via the WIF variable set on the TFC workspace — no local gcloud required. + +# --- Install Terraform --- + +# The 'src' image already contains the gcp-hcp-infra repo at the working directory. +REPO_ROOT="$(pwd)" + +# Read terraform version — use awk to avoid grep pipefail on missing entry +if ! TERRAFORM_VERSION="$(awk '$1 == "terraform" { print $2; exit }' "${REPO_ROOT}/.tool-versions")" \ + || [[ -z "${TERRAFORM_VERSION}" ]]; then + log "ERROR: Failed to read terraform version from .tool-versions" + log "Auto-destroy will clean up resources in 24h" + exit 0 # Don't fail job +fi + +log "Installing Terraform ${TERRAFORM_VERSION}..." +if ! curl -fsSL --connect-timeout 15 --max-time 300 "https://releases.hashicorp.com/terraform/${TERRAFORM_VERSION}/terraform_${TERRAFORM_VERSION}_linux_amd64.zip" -o /tmp/terraform.zip; then + log "ERROR: Failed to download Terraform ${TERRAFORM_VERSION}" + log "Auto-destroy will clean up resources in 24h" + exit 0 # Don't fail job +fi +if ! python3 -c "import zipfile; zipfile.ZipFile('/tmp/terraform.zip').extractall('/tmp')"; then + log "ERROR: Failed to extract Terraform" + log "Auto-destroy will clean up resources in 24h" + exit 0 # Don't fail job +fi +if ! chmod +x /tmp/terraform; then + log "ERROR: Failed to make Terraform executable" + log "Auto-destroy will clean up resources in 24h" + exit 0 # Don't fail job +fi +export PATH="/tmp:${PATH}" + +# We need the same terraform config that was used in provision +# Re-render using the same run-id +cd "${REPO_ROOT}" # gcp-hcp-infra repo root (from: src) + +REGION="${GCP_REGION:-us-central1}" + +log "Re-rendering template for run ID: ${RUN_ID}" +RENDERED_DIR="$(./scripts/e2e-render.sh "${RUN_ID}" "${REGION}")" + +if [[ ! -d "${RENDERED_DIR}" ]]; then + log "ERROR: Render script failed - directory not created" + log "Auto-destroy will clean up resources in 24h" + exit 0 # Don't fail job +fi + +cd "${RENDERED_DIR}" + +# Configure TFC authentication via .terraformrc (avoids token in env vars) +(umask 077 && cat > "$HOME/.terraformrc" <&1 | tee -a "${LOG}"; then + log "ERROR: terraform init failed" + log "Auto-destroy will clean up resources in 24h" + exit 0 # Don't fail job +fi + +TFC_ORG="hp-platform-engineering" +log "Running terraform destroy..." +log "TFC workspace: https://app.terraform.io/app/${TFC_ORG}/workspaces/${WORKSPACE_NAME}" + +# Errors that retrying cannot fix +NON_TRANSIENT_ERRORS="quota.*exceeded|forbidden|invalid.*configuration|unauthorized" + +MAX_DESTROY_ATTEMPTS=3 +destroy_attempt=1 +destroy_wait=30 + +while (( destroy_attempt <= MAX_DESTROY_ATTEMPTS )); do + log "DESTROY ATTEMPT: ${destroy_attempt}/${MAX_DESTROY_ATTEMPTS}" + + destroy_output=$(terraform destroy -auto-approve -no-color 2>&1) + destroy_exit=$? + echo "${destroy_output}" | tee -a "${LOG}" + + if [[ ${destroy_exit} -eq 0 ]]; then + log "Terraform destroy succeeded on attempt ${destroy_attempt}" + break + fi + + # Fail fast on errors that retrying cannot fix + non_transient=$(echo "${destroy_output}" | grep -iE "${NON_TRANSIENT_ERRORS}" || true) + if [[ -n "${non_transient}" ]]; then + log "WARNING: Non-transient destroy failure, stopping retries" + log "Auto-destroy will clean up resources in 24h" + log "Check TFC workspace: https://app.terraform.io/app/${TFC_ORG}/workspaces/${WORKSPACE_NAME}" + exit 0 # Don't fail job + fi + + if (( destroy_attempt < MAX_DESTROY_ATTEMPTS )); then + log "Transient failure — waiting ${destroy_wait}s before retry..." + sleep ${destroy_wait} + destroy_wait=$((destroy_wait + 30)) + ((destroy_attempt++)) + else + log "WARNING: Terraform destroy failed after ${MAX_DESTROY_ATTEMPTS} attempts" + log "Auto-destroy will clean up resources in 24h" + log "Check TFC workspace: https://app.terraform.io/app/${TFC_ORG}/workspaces/${WORKSPACE_NAME}" + exit 0 # Don't fail job — auto-destroy is the safety net + fi +done + +log "" +log "=== Deprovision Complete ===" +log " Workspace: ${WORKSPACE_NAME}" +log " Run ID: ${RUN_ID}" +log "" +log "Infrastructure destroyed successfully" +log "TFC workspace preserved for debug history" diff --git a/ci-operator/step-registry/gcp-hcp/tf-deprovision/gcp-hcp-tf-deprovision-ref.metadata.json b/ci-operator/step-registry/gcp-hcp/tf-deprovision/gcp-hcp-tf-deprovision-ref.metadata.json new file mode 100644 index 0000000000000..860862575c07a --- /dev/null +++ b/ci-operator/step-registry/gcp-hcp/tf-deprovision/gcp-hcp-tf-deprovision-ref.metadata.json @@ -0,0 +1,25 @@ +{ + "path": "gcp-hcp/tf-deprovision/gcp-hcp-tf-deprovision-ref.yaml", + "owners": { + "approvers": [ + "apahim", + "cblecker", + "ckandag", + "cristianoveiga", + "floresroger", + "gbarabasz", + "jimdaga", + "patjlm" + ], + "reviewers": [ + "apahim", + "cblecker", + "ckandag", + "cristianoveiga", + "floresroger", + "gbarabasz", + "jimdaga", + "patjlm" + ] + } +} \ No newline at end of file diff --git a/ci-operator/step-registry/gcp-hcp/tf-deprovision/gcp-hcp-tf-deprovision-ref.yaml b/ci-operator/step-registry/gcp-hcp/tf-deprovision/gcp-hcp-tf-deprovision-ref.yaml new file mode 100644 index 0000000000000..33d20f130709a --- /dev/null +++ b/ci-operator/step-registry/gcp-hcp/tf-deprovision/gcp-hcp-tf-deprovision-ref.yaml @@ -0,0 +1,32 @@ +ref: + as: gcp-hcp-tf-deprovision + from: src + commands: gcp-hcp-tf-deprovision-commands.sh + credentials: + - mount_path: /etc/terraform-cloud + name: tfcloud-ci-secret + namespace: ci + env: + - name: GCP_REGION + default: "us-central1" + documentation: "GCP region for e2e infrastructure deployment" + resources: + requests: + cpu: 1000m + memory: 2Gi + timeout: 90m0s + grace_period: 10m0s + best_effort: true + documentation: |- + Destroys GCP HCP e2e infrastructure via terraform destroy. + + Runs in post phase to clean up resources even if tests fail. + Uses best_effort: true so job doesn't fail if cleanup has issues. + + Inputs from SHARED_DIR (written by gcp-hcp-tf-provision): + - workspace-name: TFC workspace to destroy + - run-id: run identifier for template rendering + If missing, both are reconstructed from BUILD_ID via sha256sum. + + Workspace persists in TFC for debug history. Auto-destroy (24h) + handles orphaned resources if this step fails. diff --git a/ci-operator/step-registry/gcp-hcp/tf-provision/OWNERS b/ci-operator/step-registry/gcp-hcp/tf-provision/OWNERS new file mode 100644 index 0000000000000..60325af98b50d --- /dev/null +++ b/ci-operator/step-registry/gcp-hcp/tf-provision/OWNERS @@ -0,0 +1,18 @@ +approvers: +- apahim +- cblecker +- ckandag +- cristianoveiga +- floresroger +- gbarabasz +- jimdaga +- patjlm +reviewers: +- apahim +- cblecker +- ckandag +- cristianoveiga +- floresroger +- gbarabasz +- jimdaga +- patjlm diff --git a/ci-operator/step-registry/gcp-hcp/tf-provision/gcp-hcp-tf-provision-commands.sh b/ci-operator/step-registry/gcp-hcp/tf-provision/gcp-hcp-tf-provision-commands.sh new file mode 100755 index 0000000000000..1da3e047bf4e1 --- /dev/null +++ b/ci-operator/step-registry/gcp-hcp/tf-provision/gcp-hcp-tf-provision-commands.sh @@ -0,0 +1,275 @@ +#!/usr/bin/env bash +set -euo pipefail + +LOG="${ARTIFACT_DIR}/provision.log" +log() { echo "$(date -u '+%Y-%m-%d %H:%M:%S UTC') | $*" | tee -a "${LOG}"; } + +# Validate required tools are available +# NOTE: gcloud is NOT needed here. TFC remote execution handles GCP auth +# via the WIF variable set on the TFC workspace — no local gcloud required. +for tool in jq curl sha256sum; do + if ! command -v "${tool}" >/dev/null 2>&1; then + log "ERROR: Required tool '${tool}' not found in image" + log "The gcp-hcp-infra-base image should include all required utilities" + exit 1 + fi +done + +log "All required tools available" + +# Validate TFC token mount exists +if [[ ! -f "/etc/terraform-cloud/token" ]]; then + log "ERROR: /etc/terraform-cloud/token not found" + log "The tfcloud-ci-secret vault mount must be configured" + exit 1 +fi + +# Retry wrapper for TFC API calls with exponential backoff +tfc_api_call() { + local max_retries=3 + local attempt=1 + + while (( attempt <= max_retries )); do + if output=$(curl -sf "$@" 2>&1); then + echo "${output}" + return 0 + fi + + if (( attempt < max_retries )); then + local wait_time=$((attempt * 5)) + log "API call failed (attempt ${attempt}/${max_retries}), retrying in ${wait_time}s..." >&2 + sleep ${wait_time} + fi + + ((attempt++)) + done + + log "ERROR: API call failed after ${max_retries} attempts" >&2 + return 1 +} + +# --- Install Terraform --- + +# The 'src' image already contains the gcp-hcp-infra repo at the working directory. +# Read terraform version from .tool-versions to ensure consistency with local dev. +REPO_ROOT="$(pwd)" +TERRAFORM_VERSION="$(awk '$1 == "terraform" { print $2; exit }' "${REPO_ROOT}/.tool-versions")" + +if [[ -z "${TERRAFORM_VERSION}" ]]; then + log "ERROR: Failed to read terraform version from .tool-versions" + exit 1 +fi + +if [[ ! "${TERRAFORM_VERSION}" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[a-z0-9]+)?$ ]]; then + log "ERROR: Invalid terraform version format: ${TERRAFORM_VERSION}" + exit 1 +fi + +log "Installing Terraform ${TERRAFORM_VERSION}..." +curl -fsSL --connect-timeout 15 --max-time 300 "https://releases.hashicorp.com/terraform/${TERRAFORM_VERSION}/terraform_${TERRAFORM_VERSION}_linux_amd64.zip" -o /tmp/terraform.zip +# Use python3 (available in UBI9 image) to extract zip since unzip is not installed +python3 -c "import zipfile; zipfile.ZipFile('/tmp/terraform.zip').extractall('/tmp')" +chmod +x /tmp/terraform +export PATH="/tmp:${PATH}" + +terraform version + +# --- Generate Run ID --- + +# Transform BUILD_ID (16-19 digit number) to valid run-id format +# Format: 'b' + first 7 hex chars of SHA-256(BUILD_ID) = 8 chars total +# Example: BUILD_ID=1770620651384959 → run_id=b7a3f2e1 +# Use sha256sum (universally available in UBI9 base image) +RUN_ID="b$(echo -n "${BUILD_ID}" | sha256sum | cut -c1-7)" + +log "Generated run ID: ${RUN_ID} (from BUILD_ID: ${BUILD_ID})" + +# Validate run-id format (should always pass with hash-based approach) +if [[ ! "${RUN_ID}" =~ ^[a-z][a-z0-9]{2,15}$ ]]; then + log "ERROR: Generated run-id '${RUN_ID}' is invalid" + log "This should never happen with hash-based generation" + exit 1 +fi + +WORKSPACE_NAME="platform-e2e-${RUN_ID}" +REGION="${GCP_REGION:-us-central1}" + +log "Configuration:" +log " Run ID: ${RUN_ID}" +log " Workspace: ${WORKSPACE_NAME}" +log " Region: ${REGION}" +log " BUILD_ID: ${BUILD_ID}" +log " JOB_NAME: ${JOB_NAME:-unknown}" + +# --- Render Template --- + +cd "${REPO_ROOT}" # gcp-hcp-infra repo root (from: src) + +log "Rendering e2e template..." +RENDERED_DIR="$(./scripts/e2e-render.sh "${RUN_ID}" "${REGION}")" + +if [[ ! -d "${RENDERED_DIR}" ]]; then + log "ERROR: Render script failed - directory not created" + exit 1 +fi + +log "Template rendered to: ${RENDERED_DIR}" + +# --- Configure Terraform --- + +cd "${RENDERED_DIR}" + +# Read TFC token once — used for both .terraformrc and API calls +TFC_TOKEN="$(cat /etc/terraform-cloud/token)" + +# Configure TFC authentication via .terraformrc (avoids token in env vars) +(umask 077 && cat > "$HOME/.terraformrc" <&1 | tee -a "${LOG}"; then + log "ERROR: terraform init failed" + exit 1 +fi + +log "Workspace ${WORKSPACE_NAME} created successfully" + +# --- Set Auto-Destroy --- + +log "Configuring auto-destroy (24h safety net)..." + +TFC_ORG="hp-platform-engineering" + +# Get workspace ID from TFC API (with retry) +WORKSPACE_RESPONSE=$(tfc_api_call \ + "https://app.terraform.io/api/v2/organizations/${TFC_ORG}/workspaces/${WORKSPACE_NAME}" \ + -H "Authorization: Bearer ${TFC_TOKEN}" \ + -H "Content-Type: application/vnd.api+json") + +WORKSPACE_ID=$(echo "${WORKSPACE_RESPONSE}" | jq -r '.data.id') + +if [[ -z "${WORKSPACE_ID}" || "${WORKSPACE_ID}" == "null" ]]; then + log "ERROR: Failed to retrieve workspace ID from TFC API" + log "Workspace may not have been created properly" + exit 1 +fi + +log "Workspace ID: ${WORKSPACE_ID}" + +# Set auto-destroy to 24h (with retry) +if ! tfc_api_call -X PATCH \ + "https://app.terraform.io/api/v2/workspaces/${WORKSPACE_ID}" \ + -H "Authorization: Bearer ${TFC_TOKEN}" \ + -H "Content-Type: application/vnd.api+json" \ + -d "{\"data\":{\"type\":\"workspaces\",\"attributes\":{\"auto-destroy-activity-duration\":\"24h\"}}}" \ + > /dev/null; then + log "WARNING: Failed to set auto-destroy after retries (non-fatal)" + log "Resources may need manual cleanup if pipeline crashes" +else + log "Auto-destroy configured successfully" +fi + +# --- Terraform Apply (with retry) --- + +log "Running terraform apply..." +log "TFC workspace: https://app.terraform.io/app/${TFC_ORG}/workspaces/${WORKSPACE_NAME}" + +# Errors that retrying cannot fix — fail fast instead of wasting time +NON_TRANSIENT_ERRORS="quota.*exceeded|forbidden|invalid.*configuration|unauthorized" + +MAX_APPLY_ATTEMPTS=5 +apply_attempt=1 +apply_wait=30 + +while (( apply_attempt <= MAX_APPLY_ATTEMPTS )); do + log "APPLY ATTEMPT: ${apply_attempt}/${MAX_APPLY_ATTEMPTS}" + + apply_output=$(terraform apply -auto-approve -no-color 2>&1) + apply_exit=$? + echo "${apply_output}" | tee -a "${LOG}" + + if [[ ${apply_exit} -eq 0 ]]; then + log "Terraform apply succeeded on attempt ${apply_attempt}" + break + fi + + # Fail fast on errors that retrying cannot fix + non_transient=$(echo "${apply_output}" | grep -iE "${NON_TRANSIENT_ERRORS}" || true) + if [[ -n "${non_transient}" ]]; then + log "ERROR: Non-transient failure on attempt ${apply_attempt}, aborting retries" + log "Error details:" + log "${non_transient}" + log "Check TFC workspace: https://app.terraform.io/app/${TFC_ORG}/workspaces/${WORKSPACE_NAME}" + exit 1 + fi + + if (( apply_attempt < MAX_APPLY_ATTEMPTS )); then + log "Transient failure — waiting ${apply_wait}s before retry..." + log "This is common due to GCP eventual consistency (IAM propagation, API enablement)" + sleep ${apply_wait} + apply_wait=$((apply_wait + 30)) + ((apply_attempt++)) + else + log "ERROR: Terraform apply failed after ${MAX_APPLY_ATTEMPTS} attempts" + log "Check TFC workspace: https://app.terraform.io/app/${TFC_ORG}/workspaces/${WORKSPACE_NAME}" + exit 1 + fi +done + +log "Infrastructure provisioned successfully" + +# --- Extract Outputs --- + +log "Extracting terraform outputs..." + +# Extract outputs from terraform +# NOTE: Confirmed via TFC documentation that terraform output -json works with +# CLI-driven remote execution and sensitive=true outputs are accessible via CLI. +# The output structure matches the template's output blocks. +terraform output -json > /tmp/tf-outputs.json + +# Validate output file is valid JSON +if ! jq empty /tmp/tf-outputs.json 2>/dev/null; then + log "ERROR: terraform output produced invalid JSON" + head -20 /tmp/tf-outputs.json | tee -a "${LOG}" + exit 1 +fi + +# Write individual outputs to SHARED_DIR for downstream steps +jq -r '.region.value.project_id // empty' /tmp/tf-outputs.json > "${SHARED_DIR}/region-project-id" +jq -r '.management_cluster.value.project_id // empty' /tmp/tf-outputs.json > "${SHARED_DIR}/mc-project-id" +jq -r '.management_cluster.value.cluster_name // empty' /tmp/tf-outputs.json > "${SHARED_DIR}/mc-cluster-name" +jq -r '.management_cluster.value.cluster_endpoint // empty' /tmp/tf-outputs.json > "${SHARED_DIR}/mc-cluster-endpoint" + +# Save metadata for deprovision step +echo "${WORKSPACE_NAME}" > "${SHARED_DIR}/workspace-name" +echo "${RUN_ID}" > "${SHARED_DIR}/run-id" + +# Validate critical outputs were written +for output_file in region-project-id mc-project-id mc-cluster-name mc-cluster-endpoint workspace-name run-id; do + if [[ ! -s "${SHARED_DIR}/${output_file}" ]]; then + log "ERROR: Output file ${output_file} is empty or missing" + exit 1 + fi +done + +log "" +log "=== Provision Complete ===" +log " Region Project: $(<${SHARED_DIR}/region-project-id)" +log " MC Project: $(<${SHARED_DIR}/mc-project-id)" +log " MC Cluster: $(<${SHARED_DIR}/mc-cluster-name)" +log " TFC Workspace: ${WORKSPACE_NAME}" +log " Run ID: ${RUN_ID}" +log "" +log "Outputs written to SHARED_DIR for downstream steps" +log "TFC workspace URL: https://app.terraform.io/app/${TFC_ORG}/workspaces/${WORKSPACE_NAME}" diff --git a/ci-operator/step-registry/gcp-hcp/tf-provision/gcp-hcp-tf-provision-ref.metadata.json b/ci-operator/step-registry/gcp-hcp/tf-provision/gcp-hcp-tf-provision-ref.metadata.json new file mode 100644 index 0000000000000..3ebd01fef3fa7 --- /dev/null +++ b/ci-operator/step-registry/gcp-hcp/tf-provision/gcp-hcp-tf-provision-ref.metadata.json @@ -0,0 +1,25 @@ +{ + "path": "gcp-hcp/tf-provision/gcp-hcp-tf-provision-ref.yaml", + "owners": { + "approvers": [ + "apahim", + "cblecker", + "ckandag", + "cristianoveiga", + "floresroger", + "gbarabasz", + "jimdaga", + "patjlm" + ], + "reviewers": [ + "apahim", + "cblecker", + "ckandag", + "cristianoveiga", + "floresroger", + "gbarabasz", + "jimdaga", + "patjlm" + ] + } +} \ No newline at end of file diff --git a/ci-operator/step-registry/gcp-hcp/tf-provision/gcp-hcp-tf-provision-ref.yaml b/ci-operator/step-registry/gcp-hcp/tf-provision/gcp-hcp-tf-provision-ref.yaml new file mode 100644 index 0000000000000..5742112e99dc9 --- /dev/null +++ b/ci-operator/step-registry/gcp-hcp/tf-provision/gcp-hcp-tf-provision-ref.yaml @@ -0,0 +1,32 @@ +ref: + as: gcp-hcp-tf-provision + from: src + commands: gcp-hcp-tf-provision-commands.sh + credentials: + - mount_path: /etc/terraform-cloud + name: tfcloud-ci-secret + namespace: ci + env: + - name: GCP_REGION + default: "us-central1" + documentation: "GCP region for e2e infrastructure deployment" + resources: + requests: + cpu: 1000m + memory: 2Gi + timeout: 90m0s + grace_period: 10m0s + documentation: |- + Provisions full GCP HCP e2e infrastructure (region + management cluster) + using Terraform Cloud ephemeral workspaces. + + Requires: + - TFC token mounted at /etc/terraform-cloud/token (ci-operator credential) + + Outputs to SHARED_DIR: + - region-project-id + - mc-project-id + - mc-cluster-name + - mc-cluster-endpoint + - workspace-name (for deprovision) + - run-id (for tracking) diff --git a/ci-operator/step-registry/gcp-hcp/verify-argocd-sync/OWNERS b/ci-operator/step-registry/gcp-hcp/verify-argocd-sync/OWNERS new file mode 100644 index 0000000000000..60325af98b50d --- /dev/null +++ b/ci-operator/step-registry/gcp-hcp/verify-argocd-sync/OWNERS @@ -0,0 +1,18 @@ +approvers: +- apahim +- cblecker +- ckandag +- cristianoveiga +- floresroger +- gbarabasz +- jimdaga +- patjlm +reviewers: +- apahim +- cblecker +- ckandag +- cristianoveiga +- floresroger +- gbarabasz +- jimdaga +- patjlm diff --git a/ci-operator/step-registry/gcp-hcp/verify-argocd-sync/gcp-hcp-verify-argocd-sync-commands.sh b/ci-operator/step-registry/gcp-hcp/verify-argocd-sync/gcp-hcp-verify-argocd-sync-commands.sh new file mode 100755 index 0000000000000..863e37b504240 --- /dev/null +++ b/ci-operator/step-registry/gcp-hcp/verify-argocd-sync/gcp-hcp-verify-argocd-sync-commands.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash +set -euo pipefail + +echo "=== GCP HCP E2E Test Placeholder ===" +echo "" +echo "Validating provision outputs..." + +# Check all expected outputs exist and are non-empty +REQUIRED_OUTPUTS="region-project-id mc-project-id mc-cluster-name mc-cluster-endpoint workspace-name run-id" + +for output in ${REQUIRED_OUTPUTS}; do + if [[ ! -s "${SHARED_DIR}/${output}" ]]; then + echo "ERROR: Missing or empty output: ${output}" + exit 1 + fi + echo " OK ${output}: $(<"${SHARED_DIR}/${output}")" +done + +echo "" +echo "Infrastructure Details:" +echo " Region Project: $(<"${SHARED_DIR}/region-project-id")" +echo " MC Project: $(<"${SHARED_DIR}/mc-project-id")" +echo " MC Cluster: $(<"${SHARED_DIR}/mc-cluster-name")" +echo " Workspace: $(<"${SHARED_DIR}/workspace-name")" +echo "" +echo "All provision outputs validated successfully" +echo "" +echo "NOTE: This is a placeholder. Real ArgoCD sync validation" +echo " will be implemented in a future story." diff --git a/ci-operator/step-registry/gcp-hcp/verify-argocd-sync/gcp-hcp-verify-argocd-sync-ref.metadata.json b/ci-operator/step-registry/gcp-hcp/verify-argocd-sync/gcp-hcp-verify-argocd-sync-ref.metadata.json new file mode 100644 index 0000000000000..20f79974380a9 --- /dev/null +++ b/ci-operator/step-registry/gcp-hcp/verify-argocd-sync/gcp-hcp-verify-argocd-sync-ref.metadata.json @@ -0,0 +1,25 @@ +{ + "path": "gcp-hcp/verify-argocd-sync/gcp-hcp-verify-argocd-sync-ref.yaml", + "owners": { + "approvers": [ + "apahim", + "cblecker", + "ckandag", + "cristianoveiga", + "floresroger", + "gbarabasz", + "jimdaga", + "patjlm" + ], + "reviewers": [ + "apahim", + "cblecker", + "ckandag", + "cristianoveiga", + "floresroger", + "gbarabasz", + "jimdaga", + "patjlm" + ] + } +} \ No newline at end of file diff --git a/ci-operator/step-registry/gcp-hcp/verify-argocd-sync/gcp-hcp-verify-argocd-sync-ref.yaml b/ci-operator/step-registry/gcp-hcp/verify-argocd-sync/gcp-hcp-verify-argocd-sync-ref.yaml new file mode 100644 index 0000000000000..f27861752811c --- /dev/null +++ b/ci-operator/step-registry/gcp-hcp/verify-argocd-sync/gcp-hcp-verify-argocd-sync-ref.yaml @@ -0,0 +1,15 @@ +ref: + as: gcp-hcp-verify-argocd-sync + from_image: + namespace: ocp + name: "4.22" + tag: cli + commands: gcp-hcp-verify-argocd-sync-commands.sh + resources: + requests: + cpu: 100m + memory: 256Mi + timeout: 5m0s + documentation: |- + Placeholder test step that validates provision outputs are available. + Real ArgoCD sync validation will be added in a future story.