One of the core prerequisites of adopting DevOps practices is to establish a Single Source of Truth. This is typically a software version control repository of some kind - most often either GitHub or GitLab - and Infrastructure as Code (IaC) definitions are stored in it. Finally, some form of a Continuous Integration/Continuous Deployment (CI/CD) pipeline is created in order to:
As you can imagine, these three simple steps obscure the great deal of work required to achieve this outcome. However, by leveraging product APIs and simple scripting capabilities we can take the first steps toward building a DevOps practice within your organization.
This project contains a Python script which can connect to a Cisco Catalyst Center (formerly DNA Center) appliance AND a GitHub repository, download all templates from the Catalyst Center, and compare them (line-by-line) with matching files stored in the GitHub repository. If there are any updates to existing templates, or if new templates are added, the script will copy those templates into the repository and push them up to the GitHub server.
Additionally, the project contains a Dockerfile definition for creating a Docker image, and a simple Jenkinsfile for building and running the Docker container, which is where the Python script will be executed. The files in this project provide you with the first step in building a DevOps workflow for maintaining Configuration Templates within your Catalyst Center appliance. (This is a one-way sync - effectively a system for backup and versioning of templates from Catalyst Center to GitHub)
The Python script relies on four external packages, which must be downloaded and installed from PyPi.org:
dnacentersdk
: Cisco's Python SDK package for simplifying interactions with Catalyst Center's API interface.deepdiff
: A Python package for performing deep comparison analysis of JSON datasets. This is necessary because the order of array elements in the JSON data returned by Catalyst Center's "Export Templates" API (such as the templateParams
array) is random. In order to be certain that two copies of a template's JSON structure contain identical data, we must compare them element-by-element.GitPython
: A Python package that simplifies working with git repositories and communicating with GitHub's APIs.tabulate
: A Python package that prints data to STDOUT as nicely formatted tables.
To run the script as a standalone task, you can simply install the required Python packages using the Pip module in Python:
Mac or Linux:
pip3 install -r requirements.txt
Windows:
py.exe -m pip install requirements.txt
Next, take the following steps in GitHub:
GITHUB_DNAC_TEMPLATE_REPO
Environment Variable below).projects
at the root level of this repository.GITHUB_APP_CREDS
Environment Variable below), which has permission to Read
and Write
to the GitHub repository.Finally, you will need to create Environment Variables that define your Catalyst Center appliance, username and password, GitHub username and Personal Access Token, and the GitHub repository URL. The process for creating Environment Variables varies between Windows and Mac/Linux, but you can use the included default.env
file as a template for creating these variables. Here is an example for Linux:
export DNAC_SERVER=192.168.1.1 export DNAC_CREDS_USR=dnacuser export DNAC_CREDS_PSW=dnacpassword export GITHUB_APP_CREDS=githubuser:ghp_abcd1234 export GITHUB_DNAC_TEMPLATE_REPO=https://github.com/githubuser/my_repo.git
Alternatively, you can install the dotenv
package from PyPi.org (pip3 install dotenv
), rename the default.env
file to .env
, and edit the file accordingly. If the Python script finds a file named .env
adjacent to itself, it will attempt to import the dotenv
package and load the .env
file values into Environment Variables.
To run the Python script, simply execute it without any command line arguments:
Mac or Linux:
python3 dnac_template_export.py
Windows:
py.exe dnac_template_export.py
The Python script accepts two optional command line arguments:
--verbose
, -v
: Print out full details of API responses, and other troubleshooting data.--compare_only
, -c
: Perform only a comparison of templates between GitHub and Catalyst Center - NO updates or write operations will be performed against the GitHub repository.For similar help information, you can run the Python script with the --help
command line argument.
The included Dockerfile
can be used to build a Docker Image, using python:alpine3.18
as the base image. Alpine Linux is an extremely small and fast OS that can run in a Docker container, using as little as 7MB of space! (or about 52MB when Python3 is installed) The full image for this project takes up approximately 200MB of space, once all dependencies are installed.
NOTE: Docker requires a Linux operating system to function. If you are using a Windows or Mac operating system, you will need to install Docker Desktop.
To build a Docker image for this project, run the following command (or similar - you can adjust CLI options as necessary):
docker build -t dnac_templates .
The
-t
option applies a "tag", or friendly name, to the resulting image. The.
tells Docker to search for a file namedDockerfile
in the current directory.
Next, you need to ensure the .env
file has been created and updated with your Environment Variable data, as detailed in the previous section.
NOTE: The
Dockerfile
contains a hard-codedTZ
Environment Variable, for setting the timezone inside the image. You can update this variable value to change the local timezone inside the image. This will ensure that log timestamps are adjusted to your desired timezone.
Finally, you can build and run a container based on the new Docker image you just created, and execute the Python script inside it:
docker run --rm --name dnac_templates --env-file .env dnac_templates python dnac_template_export.py
Let's break down this command and explain each component:
docker run
: Creates a new container (if the named container doesn't already exist), and runs it.--rm
: Delete the container once it finishes and exits. If you want to keep the container, you can omit this option.--name dnac_templates
: Assign the friendly name dnac_templates
to this container. Yes, it can have the same name as the image used to create it.--env-file .env
: Look for a file named .env
and use it to generate Environment Variables inside the container.dnac_templates
: The name of the Docker Image to use when creating this container. We built this image in the first step.python dnac_template_export.py
: The Shell command(s) to pass into the container upon startup. This will cause the Python script to run inside the container, and upon completion the container will exit and stop.Jenkins is an popular open-source automation server, commonly used by software developers to create CI/CD pipelines, which can build, test and deploy software code. Jenkins is just one of many tools that can be used to create CI/CD pipelines - I am using it for this project because it is readily available to me. If you have experience with GitHub Actions, GitLab CI, Circle CI, Travis CI, or many other platforms, you could easily adapt this project to run on them.
This project contains a file named Jenkinsfile
, which can be used by Jenkins to automatically build and execute a pipeline. There are many ways to build and execute Jenkins pipelines however, in this example we will leverage GitHub (again) to host a repository containing all of the code in this project. The resulting setup works like this:
Pipeline script from SCM
, and point it at the GitHub repository.Jenkinsfile
and begin executing it.Dockerfile
and use it to build a Docker image.There is a lot going on "behind the scenes" here, which Jenkins makes simple for us. To set up your Jenkins Pipeline, you can follow these steps:
.env
file to the Credentials Store in Jenkins:
DNAC_Jenkins_User_Account
Username with password
_USR
at the end. The password credential will append _PSW
at the end. Example: DNAC_CREDS_USR
and DNAC_CREDS_PSW
. You can find more information here.GitHub_Personal_Access_Token
Username with password
https://username:password@github_url.com/repository_path.git
.DNAC_Github_Template_Repo
Secret text
https://github_url.com/repository_path.git
Pipeline script from SCM
from the "Definition" dropdown menu.Git
.master
.Jenkinsfile
document (if you've renamed or moved it, you will need to specify those changes here).Owner
Contributors
Categories
Products
Catalyst CenterProgramming Languages
PythonLicense
Code Exchange Community
Get help, share code, and collaborate with other developers in the Code Exchange community.View Community