Setup GitLab CI/CD
NaC Introduction
  • Introduction
  • NaC Introduction
  • Manual Validation
  • CXTM Introduction
  • CXTM Projects
  • CXTM Test Cases
  • CXTM Test Automation
  • CXTM Git Integration
  • CXTM Batches
  • CXTM Notifications
  • Final Deployment
  • CXTM Reporting
  • CXTM References
  • Bonus Content

Setup GitLab CI/CD

In this section, you will create the .gitlab-ci.yml file that defines the CI/CD pipeline to deploy the Nexus fabric configurations.

Understanding the CI/CD Pipeline Stages

The GitLab CI/CD pipeline consists of three sequential stages that automate the deployment workflow:

  • Validate - Checks YAML file syntax and verifies Terraform configuration formatting to ensure all configuration files are properly structured before proceeding to deployment.
  • Plan - Runs Terraform plan to preview infrastructure changes and generates a detailed execution plan showing what will be created, updated, or deleted without applying any changes.
  • Deploy - Applies the Terraform configuration to the Nexus fabric devices, executing the planned changes and pushing configurations to the switches in the network.

As you create and review the pipeline below, make note of the only and except keys. These dictate which stages are run against which branch or not run against a branch. As done in this lab, typically it is the main branch that is used with these keys. For example, when you want the pipeline to run against your staging setup, then you will notice that except is used so that a particular step is not run on main.

The last two pieces to this pipeline is the usage of the only key to also control when the pipeline is run. For example, you could have the pipeline run against staging every single time a commit is pushed to the repo. Depending on your DevOps process, that may be required, but for this lab, only will be used to control the pipeline running when a merge request is created. A merge request will be expanded on in the next section, but in short, this is the process of merging your code from another branch, such as your staging branch in this case, into main. The other piece is the script key that defines a list of the commands to execute to run your automation. Additionally, the artifacts key is used to save job output files (like validation results, terraform plans, and logs) so they can be passed between pipeline stages or downloaded for review.

The variables section defines environment variables used throughout the pipeline, including credentials for NX-OS devices (NXOS_USERNAME, NXOS_PASSWORD), Webex notifications (WEBEX_ROOM_ID, WEBEX_TOKEN), and Terraform state management configurations. These variable values are already pre-populated in the CI/CD Variables section of your GitLab project settings, so the pipeline can securely access them during execution without exposing sensitive credentials in the YAML file.

Understanding Pipeline Variables

Pipeline variables allow you to securely store sensitive information like credentials, API tokens, and configuration parameters outside of your code. GitLab stores these variables encrypted in the project settings, and they are injected into the pipeline environment during execution. This approach follows security best practices by separating secrets from your source code while making them accessible to your CI/CD automation.

Step 1 - Navigate to CI/CD Settings in Your GitLab Project

For this lab, the initially required pipeline variables have already been created and populated in your GitLab project's CI/CD settings. Let's navigate to view these pre-configured variables by returning to your GitLab browser window and accessing the CI/CD settings.

  1. Click Settings
  2. Click CI/CD


Step 2 - Navigate to CI/CD Variables

On your GitLab repo's CI/CD Settings page:

  1. Locate Variables
  2. Click Expand



  3. View Variables



Step 3 - Create .gitlab-ci.yml File

You will create the .gitlab-ci.yml file in the LTROPS-2711 repository root. This file defines the complete CI/CD pipeline configuration including all stages, variables, and job definitions.

  1. Return to your VS Code Server tab and copy and paste the below command in the VS Code Server terminal window to create the .gitlab-ci.yml file.

  2. 
    code-server -r .gitlab-ci.yml
    
            

  3. There are three stages defined for pipeline execution by the .gitlab-ci.yml file. Lets review the pipeline stages, before creating the file.

    1. validate: The validation stage is executed to perform a syntactic and semantic validation of YAML files containing the configurations for the Nexus fabric. The nac-validate command validates all YAML configuration files in the data directory against the NaC schema, ensuring proper syntax and structure. The output is captured using validate_output.txt for later review and stored as an artifact.

    2. 
      validate:
        stage: validate
        script:
          - set -o pipefail && tofu 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: []
        only:
          - merge_requests
      
                  
    3. plan: The plan stage executes Terraform planning to preview infrastructure changes before applying them to the Nexus fabric. The tofu init command initializes the Terraform backend and downloads required provider plugins. The tofu plan command generates an execution plan showing what resources will be created, modified, or deleted. The plan output is saved for review and as GitLab artifacts for tracking changes.

      
      plan:
        stage: plan
        resource_group: nxos
        script:
          - tofu init -input=false
          - tofu plan -out=plan.tfplan -input=false
          - tofu show -no-color plan.tfplan > plan.txt
          - tofu show -json plan.tfplan | jq > plan.json
          - tofu 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
        artifacts:
          paths:
            - plan.json
            - plan.txt
            - plan.tfplan
            - plan_gitlab.json
          reports:
            terraform: plan_gitlab.json
        dependencies: []
        needs:
          - validate
        only:
          - merge_requests
      
                  
    4. deploy: The deploy stage applies the Terraform execution plan to the Nexus fabric switches, pushing the validated configurations to the network devices. The tofu apply command applies the plan generated in the previous stage without manual intervention, automating the configuration deployment. The stage depends on the plan stage and only runs after successful validation and planning.

      
      deploy:
        stage: deploy
        resource_group: nxos
        script:
          - tofu init -input=false
          - tofu apply -input=false -auto-approve plan.tfplan
        dependencies:
          - plan
        needs:
          - plan
        only:
          - merge_requests
      
                  
  4. Now that you have reviewed each stage of the pipeline, you can create the complete .gitlab-ci.yml file. This file combines all three stages along with variable definitions, caching configuration, and job dependencies to orchestrate the automated deployment workflow. Copy the following code into your newly created .gitlab-ci.yml file.

  5. 
    ---
    image: cait:26.2
    stages:
      - validate
      - plan
      - deploy
    
    variables:
      GIT_SSL_NO_VERIFY: "true"
      NXOS_USERNAME:
        description: "Cisco NX-OS Username"
      NXOS_PASSWORD:
        description: "Cisco NX-OS Password"
      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
      TF_HTTP_SKIP_CERT_VERIFICATION:
        description: "Skip SSL certificate verification"
        value: "true"
      SSL_CERT_DIR: /etc/gitlab-runner/ssl
    
    cache:
      key: terraform_modules_and_lock
      paths:
        - .terraform
        - .terraform.lock.hcl
    
    validate:
      stage: validate
      script:
        - set -o pipefail && tofu 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: []
      only:
        - merge_requests
    
    plan:
      stage: plan
      resource_group: nxos
      script:
        - tofu init -input=false
        - tofu plan -out=plan.tfplan -input=false
        - tofu show -no-color plan.tfplan > plan.txt
        - tofu show -json plan.tfplan | jq > plan.json
        - tofu 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
      artifacts:
        paths:
          - plan.json
          - plan.txt
          - plan.tfplan
          - plan_gitlab.json
        reports:
          terraform: plan_gitlab.json
      dependencies: []
      needs:
        - validate
      only:
        - merge_requests
    
    deploy:
      stage: deploy
      resource_group: nxos
      script:
        - tofu init -input=false
        - tofu apply -input=false -auto-approve plan.tfplan
      dependencies:
        - plan
      needs:
        - plan
      only:
        - merge_requests
    
    
            

  6. Press Ctrl + s to save the .gitlab-ci.yml file.
    If the keyboard shortcut does not work, please open the VS Code Server hamburger menu and click File > Save.

Warning

Be sure to save your file! Not saving will result in your code not executing.


Step 4 - Apply the fabric configuration

It is time to add these files with Git in preparation for committing them to the repo. You perform the action of adding files with git add. You will add your .gitlab-ci.yml file and add your data directory.

  1. Perform a git add of the files created. Copy and paste the below command in the VS Code Server terminal window to add the files.

  2. 
    git add .gitlab-ci.yml
    git add data/
    
            

  3. Next, you will perform a git commit and push the configuration files from local to the remote repository in GitLab. This will trigger the pipeline to apply the fabric configuration changes.

  4. 
    git commit -m "Initial Fabric Deployment"
    
            

  5. Finally, perform a git push of the files to the remote repository. This will automatically trigger the pipeline to apply the configuration changes to the nexus fabric. Copy and paste the below command in the VS Code Server terminal window to push the files.

  6. 
    git push -u origin fabric-deployment
    
            

Continue to the next section to review the pipeline details, trigger the pipeline, and review the execution results.