Overview
VXLAN as Code
  • Introduction
  • Dev Setup
  • NDFC
  • REST API
  • Python
  • Ansible
  • VXLAN as Code
  • NetDevOps
  • Bonus: Terraform
  • Bonus: Postman
  • Reference: More Ansible

VXLAN as Code aims to reduce time to value by lowering the barrier of entry to network orchestration through simplification, abstraction, and curated examples.

It allows users to instantiate network fabrics in minutes using an easy to use, opinionated data model and takes away the complexity of having to deal with references, dependencies or loops. Users can focus on describing the intended configuration while using a set of maintained and tested Ansible Modules without the need to understand the low-level network device configuration.

The data model is built by network engineers for each Cisco feature that is implemented and incorporates best practices. The data model allows the representation of network complexity in a simple structure where validation and testing can be incorporated.

Setup


Step 1 - Setup Ansible Directory Structure Required for VXLAN as Code

Return to your Visual Studio Code Terminal window.

Create a directory called nac under the /home/cisco/Documents/ndfclab project directory.


mkdir -p ~/workspace/ndfclab/nac
cd ~/workspace/ndfclab/nac

Within the ~/workspace/ndfclab/nac directory create additional directories;

  • group_vars
  • host_vars
  • for staging and production fabric data under host_vars; stage and prod respectively
  • collections

This directory structure will keep things organized for clarity and demonstrate some other ways to work with file structures in Ansible.

Reminder

Remember that you can click the copy button in the upper right hand corner of each Visual Sudio Code Termnial section in this lab guide and then paste it into the actual VSCode terminal instead of typing everything out!

Simply hover your mouse pointer above the upper right hand corner of the window below to make the copy button appear.


mkdir group_vars
mkdir -p group_vars/ndfc
mkdir host_vars
mkdir -p host_vars/fabric-stage
mkdir -p host_vars/fabric-prod
mkdir collections


Step 2 - Verify Ansible Version

Since you're operating in the same virtualenv, Ansible is already installed and you can confirm by checking the version. Again, you're be working with Ansible Core release 2.17.10.


ansible --version

Upon a successful installation and verification of the Ansible version, your output should look as follows:

    ansible [core 2.17.10]
      config file = None
      configured module search path = ['/home/pod06/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
      ansible python module location = /home/pod06/.pyenv/versions/3.11.9/envs/ndfclab/lib/python3.11/site-packages/ansible
      ansible collection location = /home/pod06/.ansible/collections:/usr/share/ansible/collections
      executable location = /home/pod06/.pyenv/versions/ndfclab/bin/ansible
      python version = 3.11.9 (main, Apr 25 2025, 11:33:57) [GCC 11.4.0] (/home/pod06/.pyenv/versions/3.11.9/envs/ndfclab/bin/python)
      jinja version = 3.1.6
      libyaml = True

Step 3 - Install VXLAN as Code Python Dependencies

First, create a requirements.txt file in the ~/workspace/ndfclab/nac directory.


touch ~/workspace/ndfclab/nac/requirements.txt
cat << EOF > ~/workspace/ndfclab/nac/requirements.txt

ansible-core==2.17.10
ansible-lint==24.10.0
iac-validate==0.2.6
macaddress==2.0.2
netaddr==1.3.0
packaging==25.0
requests==2.32.2
jmespath==1.0.1
EOF

Install the Python dependencies required for the VXLAN as Code solution.


pip install -r requirements.txt


Step 4 - Create Ansible Config File

Create an ansible.cfg file to disable hostkey checking and set your python interpreter for the purposes of this lab. Additionally, NDFC Ansible modules require the Ansible persistent_connection to have some values modified. The command_timeout and connect_timeout are required to be set to a 1000 seconds or greater. If this is something you forget to do in your environment outside of this lab, not to worry, the modules will notify you upon execution time.


touch ~/workspace/ndfclab/nac/ansible.cfg
cat << EOF > ~/workspace/ndfclab/nac/ansible.cfg

[defaults]
interpreter_python = "$PYENV_VIRTUAL_ENV/bin/python"
host_key_checking = False
collections_path = ./collections/
callback_whitelist=ansible.posix.timer,ansible.posix.profile_tasks,ansible.posix.profile_roles
callbacks_enabled=ansible.posix.timer,ansible.posix.profile_tasks,ansible.posix.profile_roles
bin_ansible_callbacks = True

[persistent_connection]
command_timeout=7200
connect_timeout=7200
EOF


Step 5 - Install VXLAN as Code Collection Dependencies

First, create a requirements.yml file in the ~/workspace/ndfclab/nac directory.


touch ~/workspace/ndfclab/nac/requirements.yml
cat << EOF > ~/workspace/ndfclab/nac/requirements.yml

collections:
  - name: community.general
    version: 10.6.0 
  - name: ansible.posix
    version: 2.0.0
  - name: ansible.utils
    version: 6.0.0
  - name: ansible.netcommon
    version: 8.0.0
  - name: cisco.dcnm
    version: 3.8.0
EOF

Install the Ansible Collection dependencies required for the VXLAN as Code solution.


ansible-galaxy collection install  -r requirements.yml -p ./collections


Step 6 - Install VXLAN as Code Ansible Collection


ansible-galaxy collection install cisco.nac_dc_vxlan==0.4.2 -p ./collections

Use the following ansible-galaxy command to verify the collection was installed properly and make note of the dependent collections installed; one of them should look familiar.


ansible-galaxy collection list

You should see the following output:

    # /home/pod06/workspace/ndfclab/ansible/collections/ansible_collections
    Collection         Version
    -----------------  -------
    ansible.netcommon  8.0.0
    ansible.posix      2.0.0
    ansible.utils      6.0.0
    cisco.dcnm         3.8.0
    cisco.nac_dc_vxlan 0.4.2
    community.general  10.6.0 


Ansible Documentation


    All documentation for the VXLAN as Code, nac_dc_vxlan, Ansible collection can be found on Ansible Galaxy. Navigate to Ansible Galaxy to see the list of modules and review the documentation.





Step 7 - Create Ansible Inventory File for NDFC Staging Fabric

The Ansible inventory file defines how Ansible will connect and authenticate with NDFC.


touch ~/workspace/ndfclab/nac/hosts.stage.yml
cat << EOF > ~/workspace/ndfclab/nac/hosts.stage.yml
---
# Inventory Information For Staging Fabric
ndfc:
  hosts:
    fabric-stage:
      ansible_host: 10.15.0.26
EOF


Step 8 - Create Ansible Group Vars Files for NDFC VXLAN as Code

The following file should look familiar as it is similar to the one you created in the previous Ansible section. In this section you will use the lookup plugin and use environment variables to pass sensitive information such as usernames and passwords to Ansible.

The lookup plugin allows you to access data from outside of Ansible, such as environment variables, or files, and use that data in your playbooks. In this case, you will be using the lookup plugin to access environment variables that you will set in a shell script. This allows you to keep sensitive information, such as passwords, out of your playbooks and inventory files, while still being able to use them in your Ansible tasks.


touch ~/workspace/ndfclab/nac/group_vars/ndfc/connection.yml
cat << EOF > ~/workspace/ndfclab/nac/group_vars/ndfc/connection.yml
---
# Connection Parameters for 'ndfc' inventory group
#
# Controller Credentials
ansible_connection: ansible.netcommon.httpapi
ansible_network_os: cisco.dcnm.dcnm
ansible_httpapi_port: 443
ansible_httpapi_use_ssl: true
ansible_httpapi_validate_certs: false
# ansible_httpapi_login_domain: local
# NDFC API Credentials
ansible_user: "{{ lookup('ansible.builtin.env', 'ND_USERNAME') }}"
ansible_password: "{{ lookup('ansible.builtin.env', 'ND_PASSWORD') }}"
# Credentials for devices in Inventory
ndfc_switch_username: "{{ lookup('ansible.builtin.env', 'NDFC_SW_USERNAME') }}"
ndfc_switch_password: "{{ lookup('ansible.builtin.env', 'NDFC_SW_PASSWORD') }}"
EOF

Next, you will create a file named ndfc.yml that will contain the parameters to control what elements are allowed to be removed using Remove role. This will be used as a safety net to ensure that you do not accidentally remove any elements that you do not intend to remove. If you do wish to remove any of the elements, you can set the corresponding parameter to true in the ndfc.yml file.


touch ~/workspace/ndfclab/nac/group_vars/ndfc/ndfc.yml
cat << EOF > ~/workspace/ndfclab/nac/group_vars/ndfc/ndfc.yml
---
# Parameter to ignore diff-run
force_run_all: true

# Parameters for the tasks in the 'Remove' role
interface_delete_mode: false
inventory_delete_mode: false
link_vpc_delete_mode: false
network_delete_mode: false
policy_delete_mode: false
vpc_delete_mode: false
vrf_delete_mode: false
EOF


Step 9 - Create Shell Script to Set ND Password as Env Var

First, let's create a quick shell script to set an environment variable for your ND user's password. Again, your command line program will first try to leverage an environment variable named ND_PASSWORD for authentication purposes with your ndfc ndclient object.



touch ~/workspace/ndfclab/nac/secrets.sh
cat <<EOF >> ~/workspace/ndfclab/nac/secrets.sh
export ND_USERNAME="admin"
export ND_PASSWORD="cisco.123"
export NDFC_SW_USERNAME="admin"
export NDFC_SW_PASSWORD="cisco.123"
EOF


Step 10 - Source the Shell Script to Set Env Var

Source the simple shell script to set the secret env variables.


source secrets.sh

You can check if your env variable is set by issuing the below command in your VSCode terminal window:


env | grep -E "^ND"


$ env | grep -E "^ND"
ND_PASSWORD=cisco.123
NDFC_SW_USERNAME=admin
ND_USERNAME=admin
NDFC_SW_PASSWORD=cisco.123

Navigate to the next section to begin working with VXLAN as Code.