{"id":20324553,"url":"https://github.com/netascode/ansible-dc-vxlan-example","last_synced_at":"2025-03-04T10:21:52.167Z","repository":{"id":243260703,"uuid":"773964001","full_name":"netascode/ansible-dc-vxlan-example","owner":"netascode","description":null,"archived":false,"fork":false,"pushed_at":"2025-01-27T03:51:53.000Z","size":84,"stargazers_count":4,"open_issues_count":1,"forks_count":2,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-02-26T17:36:40.794Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/netascode.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-03-18T17:49:40.000Z","updated_at":"2025-01-27T03:51:55.000Z","dependencies_parsed_at":"2024-08-06T15:49:51.715Z","dependency_job_id":"2b41b381-1684-422a-bfdf-05617b7a6b70","html_url":"https://github.com/netascode/ansible-dc-vxlan-example","commit_stats":null,"previous_names":["netascode/ansible-dc-vxlan-example"],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/netascode%2Fansible-dc-vxlan-example","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/netascode%2Fansible-dc-vxlan-example/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/netascode%2Fansible-dc-vxlan-example/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/netascode%2Fansible-dc-vxlan-example/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/netascode","download_url":"https://codeload.github.com/netascode/ansible-dc-vxlan-example/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241827465,"owners_count":20026693,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-14T19:34:27.942Z","updated_at":"2025-03-04T10:21:52.156Z","avatar_url":"https://github.com/netascode.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# Ansible NDFC VXLAN Example Repository\n\nThis repository is designed to build the skeleton for the [Network as Code DC VXLAN Ansible Galaxy Collection](https://galaxy.ansible.com/ui/repo/published/cisco/nac_dc_vxlan/). Cloning this repository will create a working structure that can be extended to automate your Cisco Nexus Data Center network using Nexus Dashboard Fabric Controller (NDFC).\n\n## Setting up environment for the collection\n\nInstallation of a Python virtual environment is needed in order to install the collection and it's requirements. We recommend [pyenv](https://github.com/pyenv/pyenv) which provides a robust Python virtual environment capability that also allows for management of different Python versions. The following instructions are detailed around using pyenv. For pipeline execution please refer to the *pipeline section* which is documented at container level.\n\n### Step 1 - Installing the example repository\n\nTo simplify getting started with this collection we are providing you with an [example repository](https://github.com/netascode/ansible-dc-vxlan-example) that you can clone from GitHub.  This repository creates the required skeleton structure including examples for pipelines. Cloaning this repository requires the installation of [git client](https://git-scm.com/downloads) which is available for all platforms.\n\nRun the following command in the location of interest.\n\n```bash\ngit clone https://github.com/netascode/ansible-dc-vxlan-example.git nac-vxlan\n```\n\nThis will clone the repository into the directory nac-vxlan.\n\n### Step 2 - Create the virtual environment with pyenv\n\nIn this directory create a new virtual environment and install a Python version of your choice. At the _time of writting_, a commonly used version is Python version 3.10.13.  Command `pyenv install 3.10.13` will install this version. For detailed instructions please visit the [pyenv](https://github.com/pyenv/pyenv) site.\n\n```bash\ncd nac-vxlan\npyenv virtualenv \u003cPython_version\u003e nac-ndfc\npyenv local nac-ndfc\n```\n\nExecuting command `pyenv local \u003cenv_name\u003e` sets the environment so that whenever the directory is entered it will change into the right virtual environment.\n\n### Step 3 - Install Ansible and additional required tools\n\nIncluded in the example repository is the requirements file to install Ansible. First upgrade PIP to latest version.\n\n```bash\npip install --upgrade pip\npip install -r requirements.txt\n```\n\n### Step 4 - Install Ansible Galaxy Collection (default placement)\n\nThe default placement for Ansible Galaxy Collections is in your home directory under `.ansible/collections/ansible_collections/`. To install the collection in the default location run the following command:\n\n```bash\nansible-galaxy collection install -r requirements.yaml\n```\n\n### Step 5 - Install Ansible Galaxy Collection (non-default placement)\n\nIf you wish to install the Galaxy Collection inside the repository you are creating with this example repository, you can run the following command:\n\n```bash\nansible-galaxy collection install -p collections/ansible_collections/ -r requirements.yaml\n```\n\nYou will need to then configure your ansible.cfg file to point to the correct collection location. \n\nThis sets the correct path for all the Python modules and libraries in the virtual environment that was created. If you look in that directory you will find the collections package locations. Below is the base `ansible.cfg` file. You will need to adjust the `collections_path` to your environment paths:\n\n```bash\n[defaults]\ncollections_path = ./collections/ansible_collections/\n\n```\n\n### Step 6 - Change Ansible callbacks\n\nIf you wish to add any ansible callbacks ( the listed below expand on displaying time execution ) you can add the following to the `ansible.cfg` file:\n\n```ini\ncallback_whitelist=ansible.posix.timer,ansible.posix.profile_tasks,ansible.posix.profile_roles\ncallbacks_enabled=ansible.posix.timer,ansible.posix.profile_tasks,ansible.posix.profile_roles\nbin_ansible_callbacks = True\n```\n\n### Step 7 - Verify the installation\n\nVerify that the ansible configuration file is being read and all the paths are correct inside of this virtual environment. \n\n```bash\nansible --version\n```\n\nYour output should be similar to the output below\n\n```bash\nansible [core 2.16.3]\n  config file = /Users/username/tmp/nac-vxlan/ansible.cfg\n  configured module search path = ['/Users/username/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']\n  ansible python module location = /Users/username/.pyenv/versions/3.10.13/envs/nac-ndfc/lib/python3.10/site-packages/ansible\n  ansible collection location = /Users/username/path/to/collections/ansible_collections\n  executable location = /Users/username/.pyenv/versions/nac-ndfc/bin/ansible\n  python version = 3.10.13 (main, Oct 29 2023, 00:04:17) [Clang 15.0.0 (clang-1500.0.40.1)] (/Users/username/.pyenv/versions/3.10.13/envs/nac-ndfc/bin/python3.10)\n  jinja version = 3.1.4\n  libyaml = True\n```\n\n## Inventory host files\n\nAs is standard with Ansible best practices, inventory files provide the destination targets for the automation. For this collection, the inventory file is a YAML file that contains the information about the devices that are going to be configured. The inventory files is called `inventory.yaml` and is located in the root of the repository.\n\nThe inventory file is going to contain a structure similar to this:\n\n```yaml\n---\nall:\n  children:\n    ndfc:\n      hosts:\n        nac-ndfc1:\n          ansible_host: 10.X.X.X\n        nac-ndfc1-ipv6:\n          ansible_host: \"[2001:XXX:XXXX:XXXX::XX]\"\n```\n\n\u003e [!NOTE]\n\u003e For IPv6 the ansible_host must be formated like the example above\n\u003e \"[ipv6 address]\"\n\nThis structure creates two things in Ansible:\n  * A group called `ndfc`\n  * A host called `nac-ndfc1`\n\nThese are tied back to the directory structure of the repository that contains two folders in the top directory:\n\n```mermaid\ngraph\n  root--\u003egroup_vars\n  root--\u003ehost_vars\n  group_vars--\u003endfc\n  ndfc--\u003econnection.yaml\n  host_vars--\u003enac-ndfc1\n  nac-ndfc1--\u003edata_model_files\n```\n\nThe data model **must** exist under the `host_vars` directory structure. The inventory file organizes how the variables are read using both `group_vars` and `host_vars` directories. Under `group_vars` is where you populate the `connection.yaml` file which stores the credential information for the NDFC controller.\n\nThe collection is **pre-built** to make use of the `group_vars` and `host_vars` data and matches what is already constructed in the repository. There is a 1:1 relationship between the code in the repository and the NDFC fabric. For more complex environments, the inventory file can be expanded to include multiple groups and hosts including managment of multi-site fabrics which is explained in a separate document.\n\n### Step 1 - Update the inventory file\n\nIn the provided `inventory.yaml` file in the root directory, update the `ansible_host` variable to point to your NDFC controller by replacing `10.X.X.X` with the IP address of the NDFC controller.\n\n### Step 2 - Configure ansible connection file\n\nIn the directory `group_vars/ndfc` is a file called `connection.yaml` that contains example data:\n\n```yaml\n---\n# Connection Parameters for 'ndfc' inventory group\n#\n# Controller Credentials\nansible_connection: ansible.netcommon.httpapi\nansible_httpapi_port: 443\nansible_httpapi_use_ssl: true\nansible_httpapi_validate_certs: false\nansible_network_os: cisco.dcnm.dcnm\n# NDFC API Credentials\nansible_user: \"{{ lookup('env', 'ND_USERNAME') }}\"\nansible_password: \"{{ lookup('env', 'ND_PASSWORD') }}\"\n# Credentials for switches in inventory\nndfc_switch_username: \"{{ lookup('env', 'NDFC_SW_USERNAME') }}\"\nndfc_switch_password: \"{{ lookup('env', 'NDFC_SW_PASSWORD') }}\"\n\n```\n\nThis file contains the connection parameters required for reachability to the NDFC controller. The `ansible_user`, and `ansible_password` credentials must be set to establish a connection to the NDFC controller. For the devices, you will set the `ndfc_switch_username` and `ndfc_switch_username` variables which can also be configured as environment variables. Environment variables provide extra security so that the credentials are not stored in plain text inside the repository. Accidentaly including your credentials in a repository is a very difficult to remove. Hence, the usage of environment variables is recommended as a starting point.\n\nAdditionally, if a pipeline is required, the environment variables can be stored in the pipeline configuration using secure methods and prevents them from being exposed in the repository.\n\n[Ansible vault](https://docs.ansible.com/ansible/latest/vault_guide/index.html) can also be used to encrypt the contents of the connection file or simply encrypt the variables.\n\n### Step 3 - Set environment variables\n\nThe environment variables should be set in the shell where the playbook is executed. They are configured via the `export` command in the shell (bash). Using this template set the environment variables to the correct credentials for the NDFC controller and the fabric devices that will be managed by NDFC.\n\n```bash\n# These are the credentials for ND\nexport ND_USERNAME=admin\nexport ND_PASSWORD=Admin_123\n# These are the credentials for the devices in the inventory\nexport NDFC_SW_USERNAME=admin\nexport NDFC_SW_PASSWORD=Admin_123\n```\n\n## Understanding our Ansible roles\n\n### Validate role\n\nRole: [cisco.nac_dc_vxlan.validate](https://github.com/netascode/ansible-dc-vxlan/blob/develop/roles/validate/README.md)\n\nThe `validate` role ensures that the data model is correct and that the data model can be processed by the subsequent roles. The validate role reads all the files in the `host_vars` directory and create a single data model in memory for execution.\n\nAs part of the VXLAN as Code service from Cisco, you will also be able to utilize the semantic validation feature to make sure that the data model matches the intended expected values. This is a powerful feature that allows you to ensure that the data model is correct before it is deployed to the network. Additonally the validate role allows creation of rules that can be used to prevent operators from making specific configurations that are not allowed in the network. These can be as simple as enforcing proper naming conventions to more complex rules for interconnectivity issues that should be avoided. These rules are coded in Python and can be constructed as part of the Services as Code offer. \n\n### Create role\n\nRole: [cisco.nac_dc_vxlan.dtc.create](https://github.com/netascode/ansible-dc-vxlan/blob/develop/roles/dtc/create/README.md)\n\nThe `create` role builds all of the templates and variable parameters required to deploy the VXLAN fabric and creates fabric state in NDFC. The data model is converted into the proper templates required by the Ansible modules used to communicate with the NDFC controller and manage the fabric state.\n\n### Deploy role\n\nRole: [cisco.nac_dc_vxlan.dtc.deploy](https://github.com/netascode/ansible-dc-vxlan/blob/develop/roles/dtc/deploy/README.md)\n\nThe `deploy` role deploys the fabric state created using the Create role to the NDFC managed devices.\n\n### Remove role\n\nRole: [cisco.nac_dc_vxlan.dtc.remove](https://github.com/netascode/ansible-dc-vxlan/blob/develop/roles/dtc/remove/README.md)\n\nThe `remove` role removes state from the NDFC controller and the devices managed by the NDFC controller. When the collection discoveres managed state in NDFC that is not defined the the data model it gets removed by this role.  For this reason this role requires the following variables to be set to `true` under the `group_vars` directory. This avoids accidental removal of configuration from NDFC that might impact the network.\n\nInside the example repository under `group_vars/ndfc` is a file called `ndfc.yaml` that contains the variables:\n\n```yaml\n# Control Parameters for 'Remove' role tasks\ninterface_delete_mode: false\ninventory_delete_mode: false\nlink_fabric_delete_mode: false\nlink_vpc_delete_mode: false\nnetwork_delete_mode: false\npolicy_delete_mode: false\nvpc_delete_mode: false\nvrf_delete_mode: false\n```\n\n**Note:** These variables are set to `false` by default to avoid accidental removal of configuration from NDFC that might impact the network. \n\n### Advantages of the roles in the workflow\n\nThese roles when run in sequence (validate, create, deploy, remove) are designed to build out the entire fabric and can be executed by a pipeline.  The roles can also be run in isolation by simply commenting out the roles that are not required during testing and fabric buildout to validate incremental changes.\n\n## Building the primary playbook\n\nThe following playbook for the NDFC as Code collection is the central execution point for this collection. Compared to automation in other collections, this playbook is designed to be mostly static and typically will not change. What gets executed during automation is based entirely on changes in the data model. When changes are made in the data model, the playbook will call the various roles and underlying modules to process the changes and update the NDFC managed fabric.\n\nThe playbook is located in the root of the repository and is called `vxlan.yaml`. It contains the following:\n\n```yaml\n---\n# This is the main entry point playbook for calling the various\n# roles in this collection.\n- hosts: nac-ndfc1\n  any_errors_fatal: true\n  gather_facts: no\n\n  roles:\n    # Prepare service model for all subsequent roles\n    #\n    - role: cisco.nac_dc_vxlan.validate\n\n    # -----------------------\n    # DataCenter Roles\n    #   Role: cisco.netascode_dc_vxlan.dtc manages direct to controller NDFC workflows\n    #\n    - role: cisco.nac_dc_vxlan.dtc.create\n      tags: 'role_create'\n\n    - role: cisco.nac_dc_vxlan.dtc.deploy\n      tags: 'role_deploy'\n\n    - role: cisco.nac_dc_vxlan.dtc.remove\n      tags: 'role_remove'\n```\n\nThe `host` is defined as nac-ndfc1 which references back to the `inventory.yaml` file. The `roles` section is where the various collection roles are called.\n\nThe first role is `cisco.nac_dc_vxlan.validate` which is going to validate the data model. This is a required step to ensure that the data model is correct and that the data model is going to be able to be processed by the subsequent roles.\n\nThe subsequent roles are the `cisco.nac_dc_vxlan.dtc.create`, `cisco.nac_dc_vxlan.dtc.deploy`, and `cisco.nac_dc_vxlan.dtc.remove` roles. These roles are the primary roles that will invoke changes in NDFC as described earlier.\n\n\n\u003e **Note**: For your safety as indicated ealier, the `remove` role also requires setting some variables to `true` under the `group_vars` directory. This is to avoid accidental removal of configuration from NDFC that might impact the network. This will be covered in more detail below.\n\nThe playbook can be configured to execute only the roles that are required. For example, as you are building your data model and familiarizing yourself with the collection, you may comment out the `deploy` and `remove` roles and only execute the `validate` and `create` roles. This provides a quick way to make sure that the data model is structured correctly.\n\n------\n**Role Level Tags:**\n\nTo speed up execution when only certain roles need to be run the following role level tags are provided:\n\n * role_validate - Select and run `cisco.nac_dc_vxlan.validate` role\n * role_create - Select and run `cisco.nac_dc_vxlan.create` role\n * role_deploy  - Select and run `cisco.nac_dc_vxlan.deploy` role\n * role_remove  - Select and run `cisco.nac_dc_vxlan.remove` role\n\nThe validate role will automatically run if tags `role_create, role_deploy, role_remove` are specified.\n\nExample: Selectively Run `cisco.nac_dc_vxlan.create` role alone\n\n```bash\nansible-playbook -i inventory.yml vxlan.yml --tags role_create\n```\n\n## Service Model Data\n\nThe following sample data is available under the `host_vars/nac-ndfc1` directory in this repository.  This data can be used to build out your first fabric using this collection.\n\n### Global configuration\n\nThis data is defined in `host_vars/nac-ndfc1/global.nac.yaml` and contains the global parameters for the VXLAN fabric.\n\n```yaml\n---\nvxlan:\n  fabric:\n    name: nac-ndfc1\n    type: VXLAN_EVPN\n  global:\n    bgp_asn: 65001\n    route_reflectors: 2\n    anycast_gateway_mac: 12:34:56:78:90:00\n    dns_servers:\n      - ip_address: 10.0.0.2\n        vrf: management\n    ntp_servers:\n      - ip_address: 10.55.0.2\n        vrf: management\n```\n\n### Topology inventory configuration\n\nThis data is defined in `host_vars/nac-ndfc1/topology_switches.nac.yaml` and contains the base topology inventory for switches in the fabric.\n\n```yaml\n---\nvxlan:\n  topology:\n    switches:\n      - name: netascode-spine1\n        serial_number: 99H2TUPCVFK\n        role: spine\n        management:\n          default_gateway_v4: 10.1.1.1\n          management_ipv4_address: 10.1.1.21\n        routing_loopback_id: 0\n        vtep_loopback_id: 1\n      - name: netascode-spine2\n        serial_number: 941L30Q8ZYI\n        role: spine\n        management:\n          default_gateway_v4: 10.1.1.1\n          management_ipv4_address: 10.1.1.22\n        routing_loopback_id: 0\n        vtep_loopback_id: 1\n      - name: netascode-leaf1\n        serial_number: 9LWGEUPJOCM\n        role: leaf\n        management:\n          default_gateway_v4: 10.1.1.1\n          management_ipv4_address: 10.1.1.11\n        routing_loopback_id: 0\n        vtep_loopback_id: 1\n      - name: netascode-leaf2\n        serial_number: 9YEXD0OHA7Z\n        role: leaf\n        management:\n          default_gateway_v4: 10.1.1.1\n          management_ipv4_address: 10.1.1.12\n        routing_loopback_id: 0\n        vtep_loopback_id: 1\n      - name: netascode-leaf3\n        serial_number: 9M2TXMZ7D3N\n        role: leaf\n        management:\n          default_gateway_v4: 10.1.1.1\n          management_ipv4_address: 10.1.1.13\n        routing_loopback_id: 0\n        vtep_loopback_id: 1\n      - name: netascode-leaf4\n        serial_number: 982YGMKUY2B\n        role: leaf\n        management:\n          default_gateway_v4: 10.1.1.1\n          management_ipv4_address: 10.1.1.14\n        routing_loopback_id: 0\n        vtep_loopback_id: 1\n```\n\n### Underlay configuration\n\nThis data is defined in `host_vars/nac-ndfc1/underlay.nac.yaml` and contains the underlay settings for the fabric.\n\n```yaml\n---\nvxlan:\n  underlay:\n    general:\n      routing_protocol: ospf\n      enable_ipv6_underlay: false\n      replication_mode: multicast\n      fabric_interface_numbering: p2p\n      subnet_mask: 31\n      underlay_routing_loopback_id: 0\n      underlay_vtep_loopback_id: 1\n      underlay_routing_protocol_tag: UNDERLAY\n      underlay_rp_loopback_id: 250\n      intra_fabric_interface_mtu: 9216\n      layer2_host_interfacde_mtu: 9216\n      unshut_host_interfaces: true\n    ipv4:\n      underlay_routing_loopback_ip_range: 10.0.0.0/22\n      underlay_vtep_loopback_ip_range: 10.100.100.0/22\n      underlay_rp_loopback_ip_range: 10.250.250.0/24\n      underlay_subnet_ip_range: 10.1.0.0/16\n    ipv6:\n      enable_ipv6_link_local_address: false\n      underlay_subnet_mask: 64\n    ospf:\n      area_id: 0.0.0.0\n      authentication_enable: false\n      authentication_key_id: 0\n      authentication_key: \"\"\n    multicast:\n      underlay_rp_loopback_id: 250\n      underlay_primary_rp_loopback_id: 0\n```\n\n### VRF configuration\n\nThis data is defined in `host_vars/nac-ndfc1/vrfs.nac.yaml` and contains the overlay VRF data.\n\n```yaml\n---\nvxlan:\n  overlay:\n    vrfs:\n      - name: NaC-VRF01\n        vrf_id: 150001\n        vlan_id: 2001\n        attach_group: all\n      - name: NaC-VRF02\n        vrf_id: 150002\n        vlan_id: 2002\n        attach_group: leaf1\n      - name: NaC-VRF03\n        vrf_id: 150003\n        vlan_id: 2003\n        attach_group: leaf2\n    vrf_attach_groups:\n      - name: all\n        switches:\n          - { hostname: netascode-leaf1 }\n          - { hostname: netascode-leaf2 }\n          - { hostname: netascode-leaf3 }\n          - { hostname: netascode-leaf4 }\n      - name: leaf1\n        switches:\n          - { hostname: netascode-leaf1 }\n      - name: leaf2\n        switches:\n          - { hostname: netascode-leaf2 }\n      - name: leaf3\n        switches:\n          - { hostname: netascode-leaf3 }\n      - name: leaf4\n        switches:\n          - { hostname: netascode-leaf4 }\n```\n\n\n### Network configuration\n\nThis data is defined in `host_vars/nac-ndfc1/networks.nac.yaml` and contains the overlay Network data.\n\n```yaml\n---\nvxlan:\n  overlay:\n    networks:\n      - name: NaC-Net01\n        vrf_name: NaC-VRF01\n        net_id: 130001\n        vlan_id: 2301\n        vlan_name: NaC-Net01_vlan2301\n        gw_ip_address: \"192.168.12.1/24\"\n        attach_group: all\n      - name: NaC-Net02\n        vrf_name: NaC-VRF02\n        net_id: 130002\n        vlan_id: 2302\n        vlan_name: NaC-Net02_vlan2302\n        gw_ip_address: \"192.168.12.2/24\"\n        attach_group: leaf1\n      - name: NaC-Net03\n        vrf_name: NaC-VRF03\n        net_id: 130003\n        vlan_id: 2303\n        vlan_name: NaC-Net03_vlan2303\n        gw_ip_address: \"192.168.12.3/24\"\n        gw_ipv6_address: \"2001::1/64\"\n        route_target_both: True\n        l3gw_on_border: True\n        mtu_l3intf: 7600\n        int_desc: \"Configured by NetAsCode\"\n        attach_group: leaf2\n    network_attach_groups:\n      - name: all\n        switches:\n          - { hostname: netascode-leaf1, ports: [Ethernet1/13, Ethernet1/14] }\n          - { hostname: netascode-leaf2, ports: [Ethernet1/13, Ethernet1/14] }\n      - name: leaf1\n        switches:\n          - { hostname: netascode-leaf1, ports: [] }\n      - name: leaf2\n        switches:\n          - { hostname: netascode-leaf2, ports: [] }\n```\n\n## Running the Playbook\n\nRun the playbook using the following command:\n\n```bash\nansible-playbook -i inventory.yaml vxlan.yaml\n```\n\nThe data in `host_vars/nac-ndfc1` will be processed by the main `vxlan.yaml` playbook and do the following:\n\n* Create a fabric called `nac-ndfc1` using the data from `global.nac.yaml` and `underlay.nac.yaml` files.\n* Add 2 Spine and 4 Leaf devices using the data defined in the `topology_switches.nac.yaml` file.\n* Add 3 VRFs and 3 Networks using the data defined in `vrfs.nac.yaml` and `networks.nac.yaml` files.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnetascode%2Fansible-dc-vxlan-example","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnetascode%2Fansible-dc-vxlan-example","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnetascode%2Fansible-dc-vxlan-example/lists"}