Infrastructure as Code (IAC) with Cisco DNA Center and Terraform
Let’s talk about how to configure your Network Infrastructure in Campus, with Terraform using Cisco DNA Center.
Cisco DNA Center has APIs that can be used for several different use cases.
(Cisco DNA Center Platform API overview article)
Some of these use cases could be configuring intent based networks, on several different Campus Networks.
In January 2021 a new Terraform provider was published, called dnacenter.
(Based on the Cisco DNA Center Golang SDK)
Terraform
If you aren’t familiar with Terraform, then I recommend that to take a look at their website, that includes use cases and samples (AWS, Azure, GCP, Cisco ACI, Cisco InterSight).
One simple way of describing Terraform, is that you put your code as resources in Terraform HCL (Hashicorp Configuration Language) files.
Together with a Terraform provider for Cisco DNA Center, you can then create and maintain the state of these resources.
These certain resources can consist of several Cisco DNA Center API calls to collect data that is needed for Terraform to maintain a proper state.
But don’t worry, it’s up to the Terraform provider to handle this and it is documented for each provider (link).
First of all, let’s get terraform cli installed in your development setup.
Follow these instructions and once you're ready, you should be able to use this command in your terminal.
$ terraform -version
Terraform v0.14.9
dnacenter provider
Essentially a Terraform provider will define how we can create resources towards a system, in this case Cisco DNA Center.
We need to define this provider in our module (.tf filename extension).
For simplicity of getting started, we’ll use main.tf as our module.
$ touch main.tf
Inside of main.tf we add the follow configuration towards the preferred Terraform provider.
terraform {
required_providers {
dnacenter = {
source = "cisco-en-programmability/dnacenter"
version = "0.0.3"
}
}
}
Next, we need to define the credentials for our Cisco DNA Center.
(You can reserve a free Cisco DNA Center here or here)
variable "username" {
type = string
}variable "password" {
type = string
}provider "dnacenter" {
username = var.username
password = var.password
base_url = "https://your.cisco.dna.center.tld"
ssl_verify = "false" # if cert can't be trusted
}
As you can see, we are passing the var.username and var.password as variables in Terraform HCL. Instead of hard coding the username and password.
Set the variables as environment variables.
(If you don’t want to manually enter the variables everytime you interact with the terraform command)
# Set secrets via environment variables
export TF_VAR_username=(the username)
export TF_VAR_password=(the password)
Finally it’s time to add our first resource that we want Terraform to maintain.
This resource will use the Cisco DNA Center APIs to create a site area under Global, called Terraform.
resource "dna_site" "area" {
provider = dnacenter
item {
type = "area"
name = "Terraform"
parent_name = "Global"
}
}
Init
Before you can get Terraform working with your provider, you need to download it to your working directory.
Use terraform init to initialize Terraform inside that folder, where main.tf is located.
$ terraform init
This will result in a download of dnacenter provider from registry.terraform.io, which is a repository for Terraform providers.
Plan
Before we are ready to push this configuration (Infrastructure as Code) towards Cisco DNA Center, we can see what kind of changes there are going to happen, when this module is applied.
$ terraform plan
The results from terraform plan show that it will create a resource from dna_site and we are calling it “area” within Terraform configuration.
Before we deploy this, we are going to add a building and a floor.
But these are dependent of each other, because we can’t have a floor before the building and we want this building to be create in this area which Terraform previously created.
Terraform offers a possibility of using “depends_on” in the module.
This makes it possible to create the resources in the correct order.
resource "dna_site" "building_10" {
provider = dnacenter
depends_on = [ dna_site.area ]
item {
type = "building"
name = "Building_10"
parent_name = dna_site.area.id
address = "Cisco - Building 10, 300 E Tasman Dr, San Jose, California 95134, United States"
}
}resource "dna_site" "building_10_floor1" {
provider = dnacenter
depends_on = [ dna_site.building_10 ]
item {
type = "floor"
name = "Floor 1"
parent_name = dna_site.building_10.id
rf_model = "Cubes And Walled Offices"
height = 100
length = 100
width = 100
}
}
Running terraform plan will now display these resources that we have defined and we are ready to take the next step, applying this.
Errors
If there would be any configuration issues, based on how the dnacenter provider is handling these resources, then those issues would have been displayed during terraform plan or terraform apply command.
$ terraform planError: Unsupported argumenton main.tf line 30, in resource "dna_site" "area":
30: site_name = "fake error"An argument named "site_name" is not expected here.$ terraform applyError: Unsupported argumenton main.tf line 30, in resource "dna_site" "area":
30: site_name = "fake error"An argument named "site_name" is not expected here.
We can see in the documentation what is expected for dna_site resource, by using dnacenter provider. The same applies for other providers on registry.terraform.io.
Apply
Now it’s time to push the configuration to Cisco DNA Center.
Using the terraform apply will display what is going to happen, but it will also ask you if you want to approve these changes.
This is a good habit in the beginning, to verify the configuration changes (added, changed or deleted resources) before approving it.
In this case, it looks correct as we are supposed to create these 3 items (area, building, floor). Type yes in the prompt and continue.
(-auto-approve
Skips interactive approval of plan before applying)
State
If you’d be runnig your own API requests towards Cisco DNA Center, you’d have to keep track of the id (uuid) of each element that you created. In case you want to modify or delete these.
Looking at the terraform.tfstate file, you’ll see how Terraform manages the state of these resources, when using terraform apply. This includes the id for each resource and dependency.
Destroy
If we want to revert or remove the resources that we have created with Terraform, then we can use the terraform destroy command.
This will display the resources (id’s) which Terraform maintains a state for and what is supposed to be deleted as well.
We need to approve this change, before Terraform will make this change.
(Same as for terraform apply, when we create resources)
That’s it. We removed the same resources that we created before.
Conclusion
By using Terraform with dnacenter provider, we are able to define our resources in Cisco DNA Center using HCL (Hashicorp Configuration Language) configuration with Terraform.
If you want to learn more about Terraform and Cisco DevNet.
- Get started with Infrastructure as Code at Cisco DevNet
- Cisco DevNet Learning Labs with Terraform
- Cisco DNA Center Platform API
- Terraform Tutorials at HashiCorp Learn
- Cisco DevNet Helps You Architect for Agility with IaC and SASE
Hope you enjoyed this article! Thanks!
Disclaimer: I work for Cisco as a Technical Solutions Architect
These articles are my own and not Cisco’s