Create
Pipeline

Step 1 - Review GitLab CI Variables and Define Variable

In Gitlab, you need to review and define the variables that will be used in the CI/CD pipeline as environment variables. These variables are used to store sensitive information such as usernames and passwords, which should not be hardcoded in the pipeline file and are similar in usage to the secrets.sh file you created in the previous part of the lab but did not store in git.

As there is a finite amount of time for this lab, several variables have been pre-defined. Your task is to add the remaining variable needed that will be used in the pipeline.

  1. Hover over the Settings tab, then click on CI/CD in the left navigation pane.




  2. Click the arrow next to Variables to expand the section.
  3. Click on Add variable on the right side of the CI/CD Variables table header. It's located directly above the "Actions" column.




  4. A new "Add variable" form will appear. Fill in the following details:
    • Type: Variable (default)
    • Environment: All (default)
    • Visibility: Masked
    • Protect variable: *Unchecked*
    • Expand variable reference: Checked
    • Key: ND_PASSWORD
    • Value: cisco.123

  5. Click on the Add variable button at the bottom of the form to save the variable.





  6. Verify your ND_PASSWORD variable was saved and your variables match the screenshot below.




Step 2 - Create The GitLab CI/CD Pipeline Job Control File

The pipeline defines the stages of the CI/CD workflow. Some stages should be triggered when a PR is created, and some should be triggered when the code is merged. Different VCSs have different methods to define the pipeline. Since we are using Gitlab, the pipeline stages are defined in file .gitlab-ci.yml in the project root folder.


touch ~/workspace/ndlab/nac/.gitlab-ci.yml
code-server -r ~/workspace/ndlab/nac/.gitlab-ci.yml


Step 3 - Copy and Paste The Following Into the GitLab Job Control File


---
image:
  name: mtarking/nac-vxlan:0.6.0

variables:
  FF_SCRIPT_SECTIONS: true
  ANSIBLE_FORCE_COLOR: true
  ANSIBLE_PERSISTENT_COMMAND_TIMEOUT: 1000
  ANSIBLE_PERSISTENT_CONNECT_TIMEOUT: 1000
  ND_USERNAME:
    description: "Cisco ND Username"
  ND_PASSWORD:
    description: "Cisco ND Password"
  NDFC_SW_USERNAME:
    description: "Cisco NDFC Switch Username"
  NDFC_SW_PASSWORD:
    description: "Cisco NDFC Switch Password"

stages:
  - lint
  - stage
  - deploy
  - test


yamllint:
  stage: lint
  rules:
    - if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS
      when: never
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
    - if: $CI_COMMIT_BRANCH
  script:
    - echo "Checking YAML files..."
    - set -o pipefail && yamllint -d relaxed ./host_vars/msd-fabric-group |& tee yamllint_msd.txt
    - set -o pipefail && yamllint -d relaxed ./vxlan.yml |& tee yamllint_vxlan.txt
  artifacts:
    when: on_failure
    paths:
      - ./yamllint_*.txt

ansible_lint:
  stage: lint
  rules:
    - if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS
      when: never
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
    - if: $CI_COMMIT_BRANCH
  script:
    - set -o pipefail && ansible-lint -p vxlan.yml |& tee ansible_lint_vxlan.txt
  artifacts:
    when: always
    paths:
      - ./ansible_lint_*.txt

nac_validate:
  stage: lint
  rules:
    - if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS
      when: never
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
    - if: $CI_COMMIT_BRANCH
  script:
    - set -o pipefail && ansible-playbook -i hosts.msd.yml validate.yml |& tee nac_validate.txt
  artifacts:
    when: always
    paths:
      - ./nac_validate_*.txt


stage:
  stage: stage
  needs:
    - yamllint
    - ansible_lint
    - nac_validate
  rules:
    - if: $CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "main"
  script:
    - set -o pipefail && ansible-playbook -i hosts.msd.yml vxlan.yml -t role_create |& tee stage_msd.txt
  artifacts:
    when: always
    paths:
      - ./stage_*.txt

deploy:
  stage: deploy
  needs:
    - yamllint
    - ansible_lint
    - nac_validate
  rules:
    - if: $CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "main"
  script:
    - set -o pipefail && ansible-playbook -i hosts.msd.yml vxlan.yml -t role_deploy,role_remove |& tee deploy_msd.txt
  artifacts:
    when: always
    paths:
      - ./deploy_*.txt


test:
  stage: test
  needs:
    - stage
    - deploy
  rules:
    - if: $CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "main"
  script:
    - set -o pipefail && pyats run job ${PWD}/tests/pyats_easypy.py --testbed-file ${PWD}/tests/testbed.yml --data_model_dir ${PWD}/host_vars/msd-fabric-group/ --archive-dir=${PWD}/tests/results --xunit=${PWD}/tests/results --no-archive-subdir --no-mail |& tee test_msd.txt
  artifacts:
    when: always
    paths:
      - tests/results/*.zip
      - tests/results/report.html
    reports:
      junit: tests/results/xunit.xml


The pipeline file above defines four stages.
  • lint stage
  • stage stage
  • deploy stage
  • test stage

Lint Stage

The lint stage above will run when you commit a branch, when a merge request is open, and when merging to your main branch. The ansible-lint tool runs against the vxlan.yml playbook file in your repository. Ansible Lint is a command-line tool for linting playbooks, roles and collections aimed towards any Ansible users. Its main goal is to promote proven practices, patterns and behaviors while avoiding common pitfalls that can easily lead to bugs or make code harder to maintain. This CI stage can be extended to lint any additional files as required.

Stage Stage

The stage stage above will only run when you commit or push code to the stage branch. The ansible-lint tool runs against the vxlan.yml playbook file in your repository. Ansible Lint is a command-line tool for linting playbooks, roles and collections aimed towards any Ansible users. Its main goal is to promote proven practices, patterns and behaviors while avoiding common pitfalls that can easily lead to bugs or make code harder to maintain. This CI stage can be extended to lint any additional files as required.

Deploy Stage

The deploy stage above will only run when a pull request or merge request is opened against the main branch or when code is committed or pushed to the main branch.
  • When a merge request is opened from the stage branch against the main branch, the vxlan.yml playbook will run against the staging environment.
  • When the code from the merge request is pushed from the stage branch into the main branch, the vxlan.yml playbook will run against the production environment.

Test Stage

The test stage above will only run when a pull request or merge request is opened against the main branch or when code is committed or pushed to the main branch.
  • When a merge request is opened from the stage branch against the main branch, the test.yml playbook will run against the staging environment.
  • When the code from the merge request is pushed from the stage branch into the main branch, the test.yml playbook will run against the production environment.

All of these stages run in a Docker container that is built with the ansible-lint, ansible-playbook and ansible-galaxy binaries.


Step 4 - Create Validate Playbook Used in the Lint Stage (Pre-Validation)


touch ~/workspace/ndlab/nac/validate.yml
cat << EOF > ~/workspace/ndlab/nac/validate.yml
---

- name: Validate Playbook
  hosts: nd
  any_errors_fatal: true
  gather_facts: false

  roles:
    - role: cisco.nac_dc_vxlan.validate
EOF


Step 5 - Add the .gitlab-ci file to GitLab Repo

Add your current files to your staging area for committing to your GitLab repo.


git add .


Step 6 - Double Check Files Staged For Commit

Check your git status of your working directory and staging area.


git status .


The following files are staged for commit. Make sure your list matches the output below!

    On branch main
    Your branch is up to date with 'origin/main'.

    Changes to be committed:
      (use "git restore --staged <file>..." to unstage)
            new file:   .gitlab-ci.yml
            new file:   validate.yml

Step 7 - Commit Files to the GitLab Repo

Issue a git commit which is like a save point of your current local repo.


git commit -m "Add .gitlab-ci pipeline file"


  [main 80d530b] Add .gitlab-ci pipeline file
  2 files changed, 120 insertions(+)
  create mode 100644 .gitlab-ci.yml
  create mode 100644 validate.yml

Step 8 - Push Files to the GitLab Repo

With your local repo added and committed to staging, push your content to your remote GitLab repo.


git push -u origin main


    Enumerating objects: 5, done.
    Counting objects: 100% (5/5), done.
    Delta compression using up to 8 threads
    Compressing objects: 100% (4/4), done.
    Writing objects: 100% (4/4), 1.19 KiB | 1.19 MiB/s, done.
    Total 4 (delta 1), reused 0 (delta 0), pack-reused 0
    To 10.15.0.159:Pod01_2025_01/LTRDCN-3439.git
      1e88683..80d530b  main -> main
    Branch 'main' set up to track remote branch 'main' from 'origin'.

Step 9 - Close All Open Tabs

In your VSCode application.

  1. Right-Click on any open tab
  2. Select "Close All" from the drop-down menu


Step 10 - Review Main Branch Pipeline in GitLab

Return to GitLab and navigate to your pipelines page for your project. You should see a pipeline running for the main branch.

  1. Hover over the Build tab, then click on Pipelines in the left navigation pane.
  2. Review your one pipeline that is running for the main branch.
  3. Click on the pipeline to review the details of the pipeline run.




  4. Review the pipeline graph to see the stages and jobs that are running in the pipeline.




  5. Review the job dependencies in the pipeline graph.




  6. Once the stage stage starts running, click on stage to review the job running within that stage.
  7. Return to the pipeline view by clicking the pipeline number.





  8. Wait until the deploy and test stage completes.




  9. Review the tests that ran and registered with GitLab. You may need to refresh your browser to see the test results show up in GitLab after the test stage completes.
  10. Click Tests located above the Job dependencies button.
  11. Click test under the Jobs table to view all the tests executed.




  12. Review that all tests passed successfully.





Continue to the next section to onboard a new overlay as a day 2 operation using NaC and NetDevOps.