Lesson 6 of 6

CI/CD for Network Infrastructure

Objective

In this lesson you will apply CI/CD principles to network infrastructure for an SD‑Access deployment. You will build a Git-driven workflow that stores Terraform HCL describing Catalyst Center resources, run local validation, and deploy the desired state to Catalyst Center using Terraform. This matters in production because it converts manual, error‑prone device changes into auditable, repeatable, and testable pipeline steps — reducing outages and enabling faster, safer change. Real-world scenario: an NOC team manages SDA fabrics for multiple sites and must push consistent virtual network and anycast gateway objects to Catalyst Center via automated pipelines triggered by Git merges.

Quick Recap

This lesson builds on the lab topology introduced earlier. We will not add new IPs or devices; we reference the Catalyst Center instance and a managed switch from the earlier lab.

ASCII topology (minimal, showing exact IPs available in the reference):

Operator Workstation --- HTTPS ---> Catalyst Center
                               (API) 10.1.1.1

Catalyst Center (10.1.1.1)
       |
       | managed device provisioning / telemetry
       |
 Switch P3-BN1 ---------- mgmt IP ---------- 192.168.30.64
       name: P3-BN1.lab.nhprep.com

Tip: The topology emphasizes the Catalyst Center API endpoint (10.1.1.1) and the managed device (192.168.30.64). All pipeline actions act against the Catalyst Center API; Catalyst Center then configures devices like P3-BN1.lab.nhprep.com.

Key Concepts

  • Declarative desired state (Terraform HCL): Instead of issuing imperative CLI commands to devices, you declare the objects you want (for example, a fabric virtual network or anycast gateway). Terraform computes the diff and applies only the changes. In production, this reduces configuration drift and makes rollbacks possible.

  • Providers and resources: Terraform uses a provider (here: catalystcenter) to translate HCL into API calls. A resource block like catalystcenter_fabric_virtual_network represents a platform object that will be created via Catalyst Center APIs.

  • Plan, Review, Apply: terraform plan queries the provider for current runtime state, then shows a delta (add/modify/delete). terraform apply sends the changes. In CI/CD pipelines, plan runs on merge requests to allow human review before apply runs in a controlled environment.

  • Git-based change control: Store HCL in Git. Developers create feature branches, push changes, and open merge requests. Automation (GitLab/GitHub actions) runs validation + terraform plan. Only merged changes trigger terraform apply in the production pipeline.

  • Idempotence and state: Terraform maintains state so subsequent applies are incremental. In production, store state remotely (e.g., remote backend) and protect it; here we demonstrate local state for learning.

Step-by-step configuration

Step 1: Create a Git feature branch and add Terraform files

What we are doing: Initialize a Git repository, create a feature branch, and add the Terraform configuration that describes Catalyst Center provider and two resources: a fabric virtual network (VN1) and an anycast gateway (CORP). This matters because Git is the source of truth; changes to HCL are what CI will validate and apply.

# Initialize repository and create feature branch
git init
git checkout -b feature/sda-vn-declare

# Create main.tf with provider and resources
cat > main.tf <<'EOF'
provider "catalystcenter" {
  username = "admin"
  password = "Lab@123"
  url      = "https://10.1.1.1"
}

resource "catalystcenter_fabric_virtual_network" "VN1" {
  name = "VN1"
}

resource "catalystcenter_anycast_gateway" "CORP" {
  vlan_name         = "VLAN_CORP"
  vlan_id           = 201
  traffic_type      = "DATA"
  l3_virtual_network = catalystcenter_fabric_virtual_network.VN1.name
}
EOF

# Add and commit
git add main.tf
git commit -m "Declare VN1 and CORP anycast gateway"

What just happened: git init created a local Git repository. The main.tf file defines the Catalyst Center provider configured to the API at https://10.1.1.1 with credentials admin/Lab@123. Two resources are declared: a fabric virtual network ("VN1") and an anycast gateway ("CORP") bound to VLAN 201, referencing the VN1 resource. Committing saves these changes in the feature branch, which is the unit of change reviewed by CI.

Real-world note: In production avoid committing plaintext credentials. Instead, use pipeline secrets or remote state backends. This lab uses local creds for clarity.

Verify:

git status --porcelain
# Expected output:
# (no untracked files, only committed main.tf)
# (empty output means clean working directory)

git log --oneline -n 1
# Expected output:
# <hash> Declare VN1 and CORP anycast gateway

Step 2: Initialize Terraform in the working directory

What we are doing: Run terraform init to prepare the working directory. It installs the catalystcenter provider plugin so Terraform can talk to the Catalyst Center API. This step matters because providers are required to translate HCL into API calls.

terraform init

What just happened: Terraform downloaded and installed the provider plugin for Catalyst Center (if available), created a .terraform directory, and prepared the directory for planning and applying. Without init, Terraform cannot query or change the remote system.

Real-world note: In CI pipelines, terraform init runs inside a workspace/container so plugins are always restored and cached in the pipeline runner.

Verify:

terraform init
# Expected output (trimmed to show the important lines; not abbreviated in the lesson)
# Initializing the backend...
#
# Initializing provider plugins...
# - Finding latest version of hashicorp/catalystcenter...
# - Installing hashicorp/catalystcenter vX.Y.Z...
# - Installed hashicorp/catalystcenter vX.Y.Z (signed by HashiCorp)
#
# Terraform has been successfully initialized!
#
# You may now begin working with Terraform. Try running "terraform plan" to see
# any changes that are required for your infrastructure. All Terraform commands
# should now work.

Step 3: Run terraform plan to inspect changes

What we are doing: Run terraform plan which queries Catalyst Center (via provider) to compute a change set between the desired HCL state and the current runtime state. This matters because plan is a safety gate: CI can surface the exact additions or deletions for review before applying.

terraform plan -out=plan.out

What just happened: Terraform contacted the Catalyst Center API at https://10.1.1.1, read current resources, and compared against the HCL. It produced a plan file plan.out that contains the actions to be taken. The plan shows + for resources to be created, - for deletions, and ~ for modifications.

Real-world note: In a merge request pipeline, terraform plan output is posted to the MR so stakeholders can review proposed changes.

Verify:

terraform plan -out=plan.out
# Expected output (complete plan summary)
# Refreshing Terraform state in-memory prior to plan...
#
# An execution plan has been generated and is shown below.
# Resource actions are indicated with the following symbols:
#   + create
#
# Terraform will perform the following actions:
#
#   # catalystcenter_fabric_virtual_network.VN1 will be created
#   + resource "catalystcenter_fabric_virtual_network" "VN1" {
#       + id   = (known after apply)
#       + name = "VN1"
#     }
#
#   # catalystcenter_anycast_gateway.CORP will be created
#   + resource "catalystcenter_anycast_gateway" "CORP" {
#       + id                 = (known after apply)
#       + l3_virtual_network = "VN1"
#       + traffic_type       = "DATA"
#       + vlan_id            = 201
#       + vlan_name          = "VLAN_CORP"
#     }
#
# Plan: 2 to add, 0 to change, 0 to destroy.
#
# Saved the plan to: plan.out

Step 4: Apply the plan to Catalyst Center

What we are doing: Execute terraform apply using the previously generated plan to create the resources on Catalyst Center. This matters because it performs the exact, reviewed changes and records state so future plans are incremental.

terraform apply "plan.out"

What just happened: Terraform executed the API calls to Catalyst Center at https://10.1.1.1, creating the fabric virtual network named VN1 and the anycast gateway CORP with VLAN 201. The provider returned resource identifiers and Terraform recorded the state locally in terraform.tfstate.

Real-world note: In production pipelines, apply should run in a controlled runner with proper credentials and audit logging; humans typically do not run apply directly on the clipboard branch but via a merge pipeline.

Verify:

terraform apply "plan.out"
# Expected output (showing create operations and summary)
# catalystcenter_fabric_virtual_network.VN1: Creating...
# catalystcenter_fabric_virtual_network.VN1: Creation complete after 2s [id=vn-12345]
# catalystcenter_anycast_gateway.CORP: Creating...
# catalystcenter_anycast_gateway.CORP: Creation complete after 1s [id=agw-67890]
#
# Apply complete! Resources: 2 added, 0 changed, 0 destroyed.

To inspect state and resource attributes:

terraform state list
# Expected output:
# catalystcenter_fabric_virtual_network.VN1
# catalystcenter_anycast_gateway.CORP

terraform state show catalystcenter_fabric_virtual_network.VN1
# Expected output:
# id = "vn-12345"
# name = "VN1"

terraform state show catalystcenter_anycast_gateway.CORP
# Expected output:
# id = "agw-67890"
# vlan_name = "VLAN_CORP"
# vlan_id = 201
# traffic_type = "DATA"
# l3_virtual_network = "VN1"

Step 5: Merge workflow and automated plan in CI

What we are doing: Describe the Git merge process that triggers CI validation. In practice you push the feature branch to a remote, open a merge request (MR), and a CI pipeline runs terraform init and terraform plan to validate. Only after approval does the pipeline run terraform apply (usually on master/production branch). This matters because it enforces peer review and automated checks before changing production Catalyst Center objects.

# Push branch to remote (example)
git remote add origin https://git.example.com/NHPREP/sda-config.git
git push -u origin feature/sda-vn-declare

# On merge to master, CI job would run:
terraform init
terraform plan -out=plan.out
# (human review the plan)
# then pipeline run (in protected environment)
terraform apply "plan.out"

What just happened: Pushing the branch stores your change in the Git server and enables pipeline execution. The CI pipeline performs the same init/plan steps we ran locally; by automating these steps you get consistent validation and an auditable trail of changes.

Real-world note: Replace https://git.example.com with your organization’s Git server and secure credentials in pipeline secrets. Protect the production apply stage behind approvals.

Verify:

# Verification is CI-focused: ensure the plan job returns exit code 0 and posts the plan.
# Example verification commands that CI would run and expect success
terraform init
terraform plan -out=plan.out
# Expected exit status: 0
# Expected output: "Plan: 2 to add, 0 to change, 0 to destroy."

Verification Checklist

  • Check 1: Terraform initializes successfully — run terraform init and expect "Terraform has been successfully initialized!"
  • Check 2: terraform plan shows two resources to add — expect "Plan: 2 to add, 0 to change, 0 to destroy."
  • Check 3: After terraform apply, terraform state list contains catalystcenter_fabric_virtual_network.VN1 and catalystcenter_anycast_gateway.CORP

Common Mistakes

SymptomCauseFix
terraform init fails with provider not foundProvider plugin not available or network blocked to download providersEnsure internet access from runner OR use a provider mirror / pre-cached plugin in CI; re-run terraform init
terraform plan shows no changes when you expect addsYou ran apply previously or state is out of syncRun terraform state list to inspect state; use terraform refresh to reconcile; verify HCL resource names and attributes
Apply fails with authentication errorIncorrect username/password or API unreachable at https://10.1.1.1Verify credentials (admin/Lab@123 in lab) and network connectivity to Catalyst Center API; fix secrets in CI
Merge request pipeline shows plan but apply not executedProtection/approval policy in CI or missing pipeline permissionEnsure apply stage runs in a protected runner with required approvals or service account permissions

Key Takeaways

  • CI/CD for network infrastructure replaces ad‑hoc CLI changes with versioned, reviewable, and repeatable pipeline actions that call Catalyst Center APIs via Terraform.
  • Always run terraform plan for human review before apply; plan is the safety gate that shows exact deltas.
  • Keep secrets and state secure: in production use pipeline secrets and remote backends rather than committing credentials or local state.
  • This approach scales: by storing HCL in Git and automating plan/apply, multiple sites and fabrics can be managed consistently and audited — critical for enterprise SDA deployments.

Final note: In production, adapt this lab workflow to use remote state, credential vaulting, and protected pipeline stages. The patterns you practiced here — declare, plan, review, and apply — form the foundation of safe, auditable network CI/CD.