Skip to content

APPENDIX I

GitLab CI/CD pipeline definition file

Here is the final .gitlab-ci.yml file including the test stage from Task 14 - Edit CI/CD:

.gitlab-ci.yml
---
image: danischm/nac:0.1.6
stages:
  - validate
  - plan
  - deploy
  - test
  - notify

variables:
  # Disable SSL verification for git operations
  GIT_SSL_NO_VERIFY: "true"

  IOSXE_USERNAME:
    description: "Cisco IOS XE Username"
  IOSXE_PASSWORD:
    description: "Cisco IOS XE Password"
  IOSXE_PROTOCOL:
    description: "Cisco IOS XE connection protocol"
    value: "netconf"
  GITLAB_TOKEN:
    description: "User Access Token. Used to create comments on Merge Requests"
  TF_HTTP_USERNAME:
    description: "GitLab Username"
    value: "gitlab-ci-token"
  TF_HTTP_PASSWORD:
    description: "GitLab Access Token"
    value: "${CI_JOB_TOKEN}"
  WEBEX_ROOM_ID:
    description: "Cisco Webex Room ID"
  WEBEX_TOKEN:
    description: "Cisco Webex Bot Token"
  GITLAB_API_URL:
    description: "GitLab API v4 root URL"
    value: "${CI_API_V4_URL}"
  TF_HTTP_ADDRESS:
    description: "GitLab HTTP Address to store the TF state file"
    value: "${GITLAB_API_URL}/projects/${CI_PROJECT_ID}/terraform/state/tfstate"
  TF_HTTP_LOCK_ADDRESS:
    description: "GitLab HTTP Address to lock the TF state file"
    value: ${TF_HTTP_ADDRESS}/lock
  TF_HTTP_LOCK_METHOD:
    description: "Method to lock TF state file"
    value: POST
  TF_HTTP_UNLOCK_ADDRESS:
    description: "GitLab HTTP Address to unlock the TF state file"
    value: ${TF_HTTP_ADDRESS}/lock
  TF_HTTP_UNLOCK_METHOD:
    description: "Method to unlock TF state file"
    value: DELETE

cache:
  key: terraform_modules_and_lock
  paths:
    - .terraform
    - .terraform.lock.hcl
    - defaults.yaml
    - model.yaml

validate:
  stage: validate
  script:
    - set -o pipefail && terraform fmt -check |& tee fmt_output.txt
    - set -o pipefail && nac-validate ./data/ |& tee validate_output.txt
  artifacts:
    paths:
      - fmt_output.txt
      - validate_output.txt
  cache: []
  rules:
    - if: $CI_COMMIT_TAG == null

plan:
  stage: plan
  resource_group: iosxe
  script:
    - terraform init -upgrade -input=false
    - terraform plan -out=plan.tfplan -input=false
    - terraform show -no-color plan.tfplan > plan.txt
    - terraform show -json plan.tfplan | jq > plan.json
    - terraform show -json plan.tfplan | jq '([.resource_changes[]?.change.actions?]|flatten)|{"create":(map(select(.=="create"))|length),"update":(map(select(.=="update"))|length),"delete":(map(select(.=="delete"))|length)}' > plan_gitlab.json
    - python3 .ci/gitlab-comment.py
  artifacts:
    paths:
      - plan.json
      - plan.txt
      - plan.tfplan
      - plan_gitlab.json
    reports:
      terraform: plan_gitlab.json
  dependencies: []
  needs:
    - validate
  only:
    - merge_requests
    - main

deploy:
  stage: deploy
  resource_group: iosxe
  script:
    - terraform init -input=false
    - terraform apply -input=false -auto-approve plan.tfplan
  artifacts:
    paths:
      - defaults.yaml
  dependencies:
    - plan
  needs:
    - plan
  only:
    - main

test-integration:
  stage: test
  script:
    - echo "=== PWD and tree ==="; pwd; ls -la
    - echo "=== Inputs nac-test needs ==="; ls -la model.yaml defaults.yaml || true
    - echo "=== tests/ scaffolding ==="; ls -la tests/ tests/templates tests/filters || true
    - echo "=== nac-test version ==="; nac-test --version || true
    - mkdir -p tests/results
    - set -o pipefail && nac-test --data ./model.yaml --data ./defaults.yaml --templates ./tests/templates --filters ./tests/filters --output ./tests/results |& tee test_output.txt
  after_script:
    - echo "=== tests/results contents (post-run) ==="; ls -la tests/results || true
    - echo "=== last 50 lines of test_output.txt ==="; tail -n 50 test_output.txt || true
  artifacts:
    when: always
    paths:
      - tests/results/
      - test_output.txt
    reports:
      junit: tests/results/xunit.xml
  dependencies:
    - deploy
  needs:
    - deploy
  only:
    - main

test-idempotency:
  stage: test
  resource_group: iosxe
  script:
    - terraform init -input=false
    - terraform plan -input=false -detailed-exitcode
  dependencies:
    - deploy
  needs:
    - deploy
  only:
    - main

failure:
  stage: notify
  script:
    - python3 .ci/webex-notification-gitlab.py -f
  when: on_failure
  artifacts:
    when: always
    paths:
      - tests/results/*.html
      - tests/results/xunit.xml
      - plan.txt
      - fmt_output.txt
      - validate_output.txt
      - test_output.txt
  cache: []

success:
  stage: notify
  script:
    - python3 .ci/webex-notification-gitlab.py -s
  when: on_success
  artifacts:
    when: always
    paths:
      - tests/results/*.html
      - tests/results/xunit.xml
      - plan.txt
      - fmt_output.txt
      - validate_output.txt
      - test_output.txt
  cache: []

← Previous: Conclusion · Next: Appendix II - Schema reference