stages: [validate, security, image, plan, apply, drift] default: image: $CI_REGISTRY_IMAGE/iac-runner:latest variables: ARM_USE_OIDC: "true" TF_IN_AUTOMATION: "true" TF_INPUT: "false" TF_VAR_ssh_public_key_path: $SSH_PUBLIC_KEY # Datei-Variable -> Pfad # Pipelines nur für Merge Requests, Pushes auf main und Zeitpläne workflow: rules: - if: $CI_PIPELINE_SOURCE == "merge_request_event" - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH - if: $CI_PIPELINE_SOURCE == "schedule" # ---------------------------------------------------------------- Vorlagen .rules_mr_and_main: rules: - if: $CI_PIPELINE_SOURCE == "merge_request_event" - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $CI_PIPELINE_SOURCE == "push" .id_plan: id_tokens: AZURE_ID_TOKEN: aud: api://AzureADTokenExchange variables: ARM_CLIENT_ID: $AZURE_CLIENT_ID_PLAN before_script: - export ARM_OIDC_TOKEN="$AZURE_ID_TOKEN" .id_apply: id_tokens: AZURE_ID_TOKEN: aud: api://AzureADTokenExchange variables: ARM_CLIENT_ID: $AZURE_CLIENT_ID_APPLY before_script: - export ARM_OIDC_TOKEN="$AZURE_ID_TOKEN" .tf_init: &tf_init - cd "$STACK" - terraform init -backend-config=../backend.hcl -backend-config="key=lab/${STACK}.tfstate" # ---------------------------------------------------------------- validate fmt: stage: validate extends: .rules_mr_and_main script: - terraform fmt -check -recursive -diff validate: stage: validate extends: .rules_mr_and_main parallel: matrix: - STACK: [base, workload] script: - cd "$STACK" - terraform init -backend=false - terraform validate - tflint --init --config=../.tflint.hcl - tflint --config=../.tflint.hcl packer:validate: stage: validate extends: .rules_mr_and_main script: - cd packer - packer init . - packer validate -var image_version=0.0.0 . # ---------------------------------------------------------------- security checkov: stage: security extends: .rules_mr_and_main script: - checkov -d . # ---------------------------------------------------------------- image image:build: stage: image extends: .id_apply script: - az login --service-principal -u "$ARM_CLIENT_ID" -t "$ARM_TENANT_ID" --federated-token "$AZURE_ID_TOKEN" -o none - az account set -s "$ARM_SUBSCRIPTION_ID" - cd packer - packer init . - packer build -color=false -var image_version="$(cat VERSION)" . rules: - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $CI_PIPELINE_SOURCE == "push" changes: [packer/**/*, ansible/**/*] # ---------------------------------------------------------------- plan .plan: stage: plan extends: [.id_plan, .rules_mr_and_main] script: - *tf_init - terraform plan -lock=false -out=tfplan - terraform show -no-color tfplan > plan.txt - | terraform show -json tfplan | jq -r '([.resource_changes[]?.change.actions?]|flatten)|{"create":(map(select(.=="create"))|length),"update":(map(select(.=="update"))|length),"delete":(map(select(.=="delete"))|length)}' > plan.json artifacts: paths: ["$STACK/tfplan", "$STACK/plan.txt"] reports: terraform: "$STACK/plan.json" expire_in: 1 week plan:base: extends: .plan variables: STACK: base plan:workload: extends: .plan variables: STACK: workload # ---------------------------------------------------------------- apply .apply: stage: apply extends: .id_apply environment: name: lab script: - *tf_init - terraform apply tfplan rules: - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $CI_PIPELINE_SOURCE == "push" when: manual apply:base: extends: .apply resource_group: tf-base variables: STACK: base needs: ["plan:base"] apply:workload: extends: .apply resource_group: tf-workload variables: STACK: workload needs: ["plan:workload", "apply:base"] # ---------------------------------------------------------------- drift drift: stage: drift extends: .id_plan parallel: matrix: - STACK: [base, workload] script: - *tf_init - rc=0; terraform plan -lock=false -detailed-exitcode || rc=$? - | if [ "$rc" -eq 2 ]; then echo "DRIFT in Schicht $STACK: Azure weicht vom Code ab." exit 1 fi exit "$rc" rules: - if: $CI_PIPELINE_SOURCE == "schedule"