From 9cebca353569f2c77ec39b8a0304256a265e8f9b Mon Sep 17 00:00:00 2001 From: cloudneutral Date: Tue, 9 Dec 2025 17:25:55 +0800 Subject: [PATCH] Refine Vultr Terraform pipelines for bootstrap and landing --- ...d-iac-pipeline-vultr-global-bootstrap.yaml | 115 ++---------------- ...ine-vultr-global-landingzone-baseline.yaml | 45 ++++--- ...ipeline-vultr-global-resources-matrix.yaml | 74 +++++++++++ 3 files changed, 107 insertions(+), 127 deletions(-) create mode 100644 .github/workflows/terraform-standard-iac-pipeline-vultr-global-resources-matrix.yaml diff --git a/.github/workflows/terraform-standard-iac-pipeline-vultr-global-bootstrap.yaml b/.github/workflows/terraform-standard-iac-pipeline-vultr-global-bootstrap.yaml index 21d5bd89..dea82ee0 100644 --- a/.github/workflows/terraform-standard-iac-pipeline-vultr-global-bootstrap.yaml +++ b/.github/workflows/terraform-standard-iac-pipeline-vultr-global-bootstrap.yaml @@ -1,4 +1,4 @@ -name: Terraform Standard - Vultr Account Bootstrap +name: Terraform Standard - Vultr Global Bootstrap concurrency: group: terraform-vultr-bootstrap-${{ github.ref }} @@ -9,6 +9,7 @@ on: paths: - 'iac-template/terraform-hcl-standard/vultr-vps/bootstrap-object-storage/**' - 'iac-template/terraform-hcl-standard/vultr-vps/bootstrap-iam/**' + - 'iac-template/terraform-hcl-standard/vultr-vps/config/**' - '.github/workflows/terraform-standard-iac-pipeline-vultr-global-bootstrap.yaml' workflow_dispatch: inputs: @@ -18,12 +19,12 @@ on: default: plan env: - TF_WORKDIR: iac-template/terraform-hcl-standard/vultr-vps + TF_ROOT: iac-template/terraform-hcl-standard/vultr-vps DEPLOY_ACTION: ${{ github.event.inputs.deploy_action || 'plan' }} jobs: bootstrap: - name: "Bootstrap Vultr state backends & identity" + name: "Bootstrap Vultr backend & provider" runs-on: ubuntu-latest strategy: @@ -33,112 +34,18 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Document Bootstrap Scope - run: | - cat <<'SUMMARY' >> "$GITHUB_STEP_SUMMARY" - ## Vultr bootstrap scope - - Object Storage: create S3-compatible bucket + API keys for Terraform state - - IAM: create limited-access user and upload SSH public key - - Variables such as bucket name, region and API keys are sourced from GitHub secrets. - SUMMARY - - uses: hashicorp/setup-terraform@v3 with: terraform_version: 1.9.5 - - name: Export shared credentials + - name: Export Vultr API key run: echo "TF_VAR_vultr_api_key=${{ secrets.VULTR_API_KEY }}" >> "$GITHUB_ENV" - - name: Init - working-directory: ${{ env.TF_WORKDIR }}/${{ matrix.target }} - env: - TF_VAR_region: ${{ secrets.VULTR_REGION }} - TF_VAR_cluster_id: ${{ secrets.VULTR_OBJECT_STORAGE_CLUSTER_ID }} - TF_VAR_bucket: ${{ secrets.VULTR_STATE_BUCKET }} - TF_VAR_seed_secret: ${{ secrets.VULTR_STATE_SEED_SECRET }} - TF_VAR_user_email: ${{ secrets.VULTR_BOOTSTRAP_USER_EMAIL }} - TF_VAR_user_password: ${{ secrets.VULTR_BOOTSTRAP_USER_PASSWORD }} - TF_VAR_public_key: ${{ secrets.VULTR_BOOTSTRAP_PUBLIC_KEY }} - run: terraform init -upgrade + - name: Select Terraform workdir + run: echo "TF_WORKDIR=${TF_ROOT}/${{ matrix.target }}" >> "$GITHUB_ENV" - - name: Plan - if: env.DEPLOY_ACTION == 'plan' - working-directory: ${{ env.TF_WORKDIR }}/${{ matrix.target }} - env: - TF_VAR_region: ${{ secrets.VULTR_REGION }} - TF_VAR_cluster_id: ${{ secrets.VULTR_OBJECT_STORAGE_CLUSTER_ID }} - TF_VAR_bucket: ${{ secrets.VULTR_STATE_BUCKET }} - TF_VAR_seed_secret: ${{ secrets.VULTR_STATE_SEED_SECRET }} - TF_VAR_user_email: ${{ secrets.VULTR_BOOTSTRAP_USER_EMAIL }} - TF_VAR_user_password: ${{ secrets.VULTR_BOOTSTRAP_USER_PASSWORD }} - TF_VAR_public_key: ${{ secrets.VULTR_BOOTSTRAP_PUBLIC_KEY }} - run: terraform plan + - name: Terraform Init + run: terraform -chdir=$TF_WORKDIR init - - name: Apply - if: env.DEPLOY_ACTION == 'apply' - working-directory: ${{ env.TF_WORKDIR }}/${{ matrix.target }} - env: - TF_VAR_region: ${{ secrets.VULTR_REGION }} - TF_VAR_cluster_id: ${{ secrets.VULTR_OBJECT_STORAGE_CLUSTER_ID }} - TF_VAR_bucket: ${{ secrets.VULTR_STATE_BUCKET }} - TF_VAR_seed_secret: ${{ secrets.VULTR_STATE_SEED_SECRET }} - TF_VAR_user_email: ${{ secrets.VULTR_BOOTSTRAP_USER_EMAIL }} - TF_VAR_user_password: ${{ secrets.VULTR_BOOTSTRAP_USER_PASSWORD }} - TF_VAR_public_key: ${{ secrets.VULTR_BOOTSTRAP_PUBLIC_KEY }} - run: terraform apply -auto-approve - - - name: Destroy - if: env.DEPLOY_ACTION == 'destroy' - working-directory: ${{ env.TF_WORKDIR }}/${{ matrix.target }} - env: - TF_VAR_region: ${{ secrets.VULTR_REGION }} - TF_VAR_cluster_id: ${{ secrets.VULTR_OBJECT_STORAGE_CLUSTER_ID }} - TF_VAR_bucket: ${{ secrets.VULTR_STATE_BUCKET }} - TF_VAR_seed_secret: ${{ secrets.VULTR_STATE_SEED_SECRET }} - TF_VAR_user_email: ${{ secrets.VULTR_BOOTSTRAP_USER_EMAIL }} - TF_VAR_user_password: ${{ secrets.VULTR_BOOTSTRAP_USER_PASSWORD }} - TF_VAR_public_key: ${{ secrets.VULTR_BOOTSTRAP_PUBLIC_KEY }} - run: terraform destroy -auto-approve - - - name: Save Outputs - if: env.DEPLOY_ACTION == 'apply' - working-directory: ${{ env.TF_WORKDIR }}/${{ matrix.target }} - run: terraform output -json > ../outputs_${{ matrix.target }}.json - - - uses: actions/upload-artifact@v4 - if: env.DEPLOY_ACTION == 'apply' - with: - name: vultr-${{ matrix.target }}-outputs - path: iac-template/terraform-hcl-standard/vultr-vps/outputs_${{ matrix.target }}.json - retention-days: 30 - - aggregate: - name: "Aggregate Vultr Bootstrap Outputs" - runs-on: ubuntu-latest - needs: bootstrap - - if: ${{ github.event.inputs.deploy_action == 'apply' }} - - steps: - - uses: actions/download-artifact@v4 - with: - path: ./outputs - - - name: Merge Outputs - run: | - echo "{" > vultr_bootstrap_outputs.json - first=true - for x in outputs/**/outputs_*.json; do - key=$(basename "$x" .json | sed 's/outputs_//') - [ "$first" = true ] && first=false || echo "," >> vultr_bootstrap_outputs.json - echo "\"$key\": $(cat "$x")" >> vultr_bootstrap_outputs.json - done - echo "}" >> vultr_bootstrap_outputs.json - - - run: cat vultr_bootstrap_outputs.json - - - uses: actions/upload-artifact@v4 - with: - name: vultr-bootstrap-final-output - path: vultr_bootstrap_outputs.json + - name: Terraform ${{ env.DEPLOY_ACTION }} + run: terraform -chdir=$TF_WORKDIR $DEPLOY_ACTION -input=false diff --git a/.github/workflows/terraform-standard-iac-pipeline-vultr-global-landingzone-baseline.yaml b/.github/workflows/terraform-standard-iac-pipeline-vultr-global-landingzone-baseline.yaml index 5689b12e..7732bdfe 100644 --- a/.github/workflows/terraform-standard-iac-pipeline-vultr-global-landingzone-baseline.yaml +++ b/.github/workflows/terraform-standard-iac-pipeline-vultr-global-landingzone-baseline.yaml @@ -1,12 +1,15 @@ name: Terraform Standard - Vultr Global LandingZone Baseline +concurrency: + group: terraform-vultr-landingzone-${{ github.ref }} + cancel-in-progress: false + on: push: paths: - - 'iac-template/terraform-hcl-standard/vultr-vps/**' + - 'iac-template/terraform-hcl-standard/vultr-vps/modules/vpc/**' + - 'iac-template/terraform-hcl-standard/vultr-vps/config/**' - '.github/workflows/terraform-standard-iac-pipeline-vultr-global-landingzone-baseline.yaml' - pull_request: - branches: [main] workflow_dispatch: inputs: deploy_action: @@ -16,12 +19,12 @@ on: default: plan env: - TF_WORKDIR: iac-template/terraform-hcl-standard/vultr-vps + TF_ROOT: iac-template/terraform-hcl-standard/vultr-vps/modules/vpc DEPLOY_ACTION: ${{ github.event.inputs.deploy_action || 'plan' }} jobs: landingzone: - name: "Deploy Vultr LandingZone Baseline" + name: "Baseline VPC + Firewall + SSH keys" runs-on: ubuntu-latest steps: @@ -31,27 +34,23 @@ jobs: with: terraform_version: 1.9.5 - - name: Export Vultr credentials + - name: Export Vultr API key run: echo "TF_VAR_vultr_api_key=${{ secrets.VULTR_API_KEY }}" >> "$GITHUB_ENV" - - name: Terraform Init (LandingZone) - run: terraform -chdir=${{ env.TF_WORKDIR }}/envs/dev init -upgrade + - name: Terraform Init + run: terraform -chdir=$TF_ROOT init - - name: Terraform Plan (LandingZone) - if: env.DEPLOY_ACTION == 'plan' - run: terraform -chdir=${{ env.TF_WORKDIR }}/envs/dev plan -no-color > plan_output.txt + - name: Terraform ${{ env.DEPLOY_ACTION }} + run: terraform -chdir=$TF_ROOT $DEPLOY_ACTION -input=false - - name: Upload LandingZone Plan Artifact - if: env.DEPLOY_ACTION == 'plan' + - name: Capture LandingZone outputs + if: env.DEPLOY_ACTION == 'apply' + run: terraform -chdir=$TF_ROOT output -json > landingzone-baseline-outputs.json + + - name: Upload LandingZone outputs + if: env.DEPLOY_ACTION == 'apply' uses: actions/upload-artifact@v4 with: - name: vultr-landingzone-plan - path: ${{ env.TF_WORKDIR }}/envs/dev/plan_output.txt - - - name: Terraform Apply (LandingZone) - if: env.DEPLOY_ACTION == 'apply' - run: terraform -chdir=${{ env.TF_WORKDIR }}/envs/dev apply -auto-approve - - - name: Terraform Destroy (LandingZone) - if: env.DEPLOY_ACTION == 'destroy' - run: terraform -chdir=${{ env.TF_WORKDIR }}/envs/dev destroy -auto-approve + name: vultr-landingzone-baseline-outputs + path: landingzone-baseline-outputs.json + retention-days: 7 diff --git a/.github/workflows/terraform-standard-iac-pipeline-vultr-global-resources-matrix.yaml b/.github/workflows/terraform-standard-iac-pipeline-vultr-global-resources-matrix.yaml new file mode 100644 index 00000000..5cdceb91 --- /dev/null +++ b/.github/workflows/terraform-standard-iac-pipeline-vultr-global-resources-matrix.yaml @@ -0,0 +1,74 @@ +name: Terraform Standard - Vultr Global Resources Matrix + +concurrency: + group: terraform-vultr-resources-${{ github.ref }} + cancel-in-progress: false + +on: + push: + paths: + - 'iac-template/terraform-hcl-standard/vultr-vps/envs/dev/**' + - 'iac-template/terraform-hcl-standard/vultr-vps/modules/compute/**' + - 'iac-template/terraform-hcl-standard/vultr-vps/modules/storage/**' + - 'iac-template/terraform-hcl-standard/vultr-vps/modules/data_store/**' + - 'iac-template/terraform-hcl-standard/vultr-vps/config/**' + - '.github/workflows/terraform-standard-iac-pipeline-vultr-global-resources-matrix.yaml' + workflow_dispatch: + inputs: + deploy_action: + type: choice + options: [plan, apply, destroy] + default: plan + +env: + TF_ROOT: iac-template/terraform-hcl-standard/vultr-vps/envs + DEPLOY_ACTION: ${{ github.event.inputs.deploy_action || 'plan' }} + +jobs: + resources: + name: "${{ matrix.environment }} :: ${{ matrix.region }} :: ${{ matrix.instance_type }}" + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + environment: [dev] + region: [ewr, lax, sin] + instance_type: [cpu, gpu] + + steps: + - uses: actions/checkout@v4 + + - uses: hashicorp/setup-terraform@v3 + with: + terraform_version: 1.9.5 + + - name: Export Vultr API key + run: echo "TF_VAR_vultr_api_key=${{ secrets.VULTR_API_KEY }}" >> "$GITHUB_ENV" + + - name: Select Terraform workdir + run: echo "TF_WORKDIR=${TF_ROOT}/${{ matrix.environment }}" >> "$GITHUB_ENV" + + - name: Terraform Init + env: + TF_VAR_region: ${{ matrix.region }} + TF_VAR_instance_type: ${{ matrix.instance_type }} + run: terraform -chdir=$TF_WORKDIR init + + - name: Terraform ${{ env.DEPLOY_ACTION }} + env: + TF_VAR_region: ${{ matrix.region }} + TF_VAR_instance_type: ${{ matrix.instance_type }} + run: terraform -chdir=$TF_WORKDIR $DEPLOY_ACTION -input=false + + - name: Capture resource outputs + if: env.DEPLOY_ACTION == 'apply' + run: terraform -chdir=$TF_WORKDIR output -json > vultr-resources-${{ matrix.environment }}-${{ matrix.region }}-${{ matrix.instance_type }}.json + + - name: Upload resource outputs + if: env.DEPLOY_ACTION == 'apply' + uses: actions/upload-artifact@v4 + with: + name: vultr-resources-${{ matrix.environment }}-${{ matrix.region }}-${{ matrix.instance_type }} + path: vultr-resources-${{ matrix.environment }}-${{ matrix.region }}-${{ matrix.instance_type }}.json + retention-days: 7