Intent-driven automation framework for deploying, validating, and verifying Cisco ACI configuration through the APIC API using Ansible and the cisco.aci collection.
This repository is designed around a simple principle:
Network changes should be validated before deployment, applied in a controlled way, and verified afterward.
The project focuses on Cisco ACI tenant networking, contracts, access policies, EPG bindings, and static-routing L3Out configuration while adding validation, change planning, verification, and operational safeguards around the automation workflow.
The repository provides a structured workflow for managing Cisco ACI configuration as code:
Intent YAML
│
▼
Schema Validation
│
▼
Dependency & Consistency Validation
│
▼
Ansible + cisco.aci
│
▼
Plan / Check Mode
│
▼
Apply
│
▼
Verify / Drift / Fault Checks
The goal is not simply to execute Ansible modules against APIC.
The goal is to build a safer automation workflow around those modules.
cisco.aci Ansible collectionCurrent release:
v0.1.x
The project is suitable for:
Before using the project in production, validate it against:
Offline validation and successful Ansible execution do not guarantee compatibility with every ACI deployment.
See:
| Area | Implemented |
|---|---|
| Tenant networking | Tenants, VRFs, Bridge Domains, IPv4 gateways |
| Application networking | Application Profiles and EPGs |
| Contracts | Filters, subjects, providers and consumers |
| Access policies | VLAN pools, domains, AEPs and interface policy objects |
| Interface configuration | Standalone leaf ports, selectors and interface profiles |
| EPG attachments | Physical domains and static path bindings |
| L3Out | Routed interfaces, node/interface profiles and static routes |
| External connectivity | External EPGs, external subnets and contract relations |
| Validation | Schema, dependency and consistency validation |
| Operations | Snapshot, plan, apply, verify and reporting |
The implementation is intentionally bounded and is not intended to expose every feature available through Cisco ACI.
These features should be designed, implemented, and tested separately before being added.
Ansible runs from the control node and communicates directly with the APIC API over HTTPS.
┌──────────────────────┐
│ Intent YAML │
│ config / examples │
└──────────┬───────────┘
│
▼
┌──────────────────────┐
│ Validation Layer │
│ JSON Schema │
│ Dependencies │
│ Consistency Checks │
└──────────┬───────────┘
│
▼
┌──────────────────────┐
│ Ansible Controller │
│ Playbooks │
│ Roles │
│ cisco.aci │
└──────────┬───────────┘
│
HTTPS
│
▼
┌──────────────────────┐
│ Cisco APIC │
└──────────┬───────────┘
│
▼
Cisco ACI Fabric
Ansible does not SSH directly to the ACI leaf switches. Configuration is performed through APIC.
Recommended control-node environment:
cisco.aci collectionCurrent tested baseline:
Python: 3.12
ansible-core: 2.20.x
cisco.aci: 2.13.x
Exact dependency constraints are maintained in:
constraints.txt
requirements.txt
requirements-dev.txt
collections/requirements.yml
Always review dependency updates before using them in production.
.
├── .github/
│ ├── ISSUE_TEMPLATE/
│ ├── workflows/
│ ├── dependabot.yml
│ └── PULL_REQUEST_TEMPLATE.md
├── collections/
│ └── requirements.yml
├── config/
│ └── README.md
├── docs/
│ ├── ACCEPTANCE.md
│ ├── MODEL.md
│ ├── MODULES.md
│ ├── RUNBOOK.md
│ ├── SOURCES.md
│ └── VALIDATION.md
├── examples/
│ ├── full-stack.yml
│ └── tenant-only.yml
├── filter_plugins/
│ └── aci_model.py
├── inventory/
│ ├── lab/
│ │ └── hosts.yml
│ └── production/
│ └── hosts.yml
├── playbooks/
│ ├── tasks/
│ ├── site.yml
│ ├── snapshot.yml
│ └── verify.yml
├── roles/
│ ├── aci_access/
│ ├── aci_bindings/
│ ├── aci_contracts/
│ ├── aci_l3out/
│ ├── aci_network/
│ └── aci_tenants/
├── schemas/
│ ├── aci.schema.json
│ └── resources.json
├── scripts/
│ ├── check_collection.py
│ ├── run.py
│ └── validate.py
├── tests/
├── .env.example
├── .gitignore
├── .python-version
├── .yamllint.yml
├── ansible.cfg
├── CHANGELOG.md
├── CONTRIBUTING.md
├── LICENSE
├── Makefile
├── NOTICE
├── README.md
├── SECURITY.md
├── constraints.txt
├── pytest.ini
├── requirements.txt
└── requirements-dev.txt
git clone https://github.com/emomeni/Cisco-ACI-Automation-with-Ansible.git cd Cisco-ACI-Automation-with-Ansible python3.12 -m venv .venv source .venv/bin/activate python -m pip install --upgrade pip python -m pip install -r requirements-dev.txt -c constraints.txt ansible-galaxy collection install \ -r collections/requirements.yml \ -p .ansible/collections make check
cp examples/full-stack.yml config/lab.yml
Then customize config/lab.yml for your environment.
Typical values to review include:
The configuration under config/ is ignored by Git by default.
Example lab inventory:
--- all: children: apic: hosts: lab_apic: aci_host: apic.lab.example.com aci_environment: lab aci_model_file: "{{ playbook_dir }}/../examples/full-stack.yml"
Replace the example hostname with your actual APIC FQDN.
Do not commit real customer or production inventory information to a public repository.
Credentials must not be stored in YAML files.
export ACI_USERNAME=automation read -rsp 'APIC password: ' ACI_PASSWORD printf '\n' export ACI_PASSWORD
Certificate authentication can also be used where appropriate.
The repository intentionally excludes:
.env
*.key
*.pem
*.p12
*.pfx
*vault*.yml
config/*
artifacts/
Never commit:
TLS certificate validation should remain enabled.
Install the APIC CA certificate into the trust store of the automation controller.
Do not disable certificate verification simply to bypass certificate errors.
Validate
↓
Plan
↓
Review
↓
Snapshot
↓
Apply
↓
Verify
↓
Operational Testing
python scripts/validate.py config/lab.yml
python scripts/run.py plan \ --inventory inventory/lab/hosts.yml \ --model config/lab.yml
python scripts/run.py apply \
--inventory inventory/lab/hosts.yml \
--model config/lab.yml \
--change-id LAB-001 \
--recovery-reference "Verified APIC backup before LAB-001"python scripts/run.py verify \ --inventory inventory/lab/hosts.yml \ --model config/lab.yml
ansible-playbook \ -i inventory/lab/hosts.yml \ playbooks/snapshot.yml
Snapshots should be stored securely and should not be committed to a public repository.
playbooks/site.ymlPrimary configuration reconciliation workflow.
playbooks/verify.ymlPost-deployment verification workflow.
playbooks/snapshot.ymlCollects relevant APIC configuration information before a change.
aci_tenantsTenant-level resources such as tenants, VRFs, Bridge Domains, application profiles, and EPGs.
aci_accessPhysical access policy configuration such as VLAN pools, domains, AEPs, interface policies, selectors, and interface profiles.
aci_networkNetwork objects and connectivity relationships.
aci_contractsCisco ACI contracts including filters, filter entries, subjects, provider relationships, and consumer relationships.
aci_l3outStatic-routing L3Out automation including node profiles, interface profiles, routed interfaces, static routes, next hops, external EPGs, and external subnets.
aci_bindingsEPG and infrastructure bindings including static path relationships.
The YAML files under examples/ demonstrate the supported intent model:
examples/tenant-only.yml
examples/full-stack.yml
The full-stack example demonstrates relationships between:
Tenant
│
├── VRF
├── Bridge Domain
├── Application Profile
│ └── EPG
├── Contracts
├── Physical Domain
├── Static Path
└── L3Out
The full-stack example is intentionally simple and should not be interpreted as a production HA architecture.
Validation includes:
YAML
↓
JSON Schema
↓
Object validation
↓
Reference validation
↓
Dependency validation
↓
Network consistency checks
↓
Ansible
Relevant files:
schemas/aci.schema.json
schemas/resources.json
filter_plugins/aci_model.py
scripts/validate.py
pytest
Or run the complete project checks:
make check
Tests do not replace validation against a real APIC environment.
GitHub Actions performs offline repository validation.
The workflow does not connect to APIC and does not require APIC credentials.
Typical CI checks include:
YAML validation
Python tests
schema validation
repository checks
collection/module compatibility checks
Public pull requests should never receive production APIC credentials.
Dependencies are managed through:
requirements.txt
requirements-dev.txt
constraints.txt
collections/requirements.yml
Dependabot monitors selected dependencies and GitHub Actions.
Dependency updates should be reviewed and tested before merging.
Before running automation against production ACI:
Automation reduces repetitive work. It does not remove the need for operational discipline.
Removing an object from the YAML model does not automatically delete that object from APIC.
The current implementation primarily uses declarative state: present behavior.
See docs/MODEL.md for detailed reconciliation semantics.
Before production adoption, complete the acceptance process described in:
At minimum, validate:
Please read:
Security recommendations include:
Contributions are welcome.
Before submitting a pull request:
make check
Please ensure that:
See CONTRIBUTING.md.
Potential future additions include:
The original code in this repository is distributed under the MIT License.
See LICENSE.
The separately installed ansible-core and Cisco cisco.aci collection retain their respective licenses.
See NOTICE.
This is an independent community project.
It is not an official Cisco or Red Hat product and is not endorsed by Cisco or Red Hat.
Always validate automation against your specific environment before production deployment.
Ehsan Momeni
Network Automation Consultant
GitHub:
https://github.com/emomeni
Repository:
https://github.com/emomeni/Cisco-ACI-Automation-with-Ansible
If you find this repository useful, consider giving it a ⭐ and sharing feedback through GitHub Issues or Pull Requests.
Owner
Contributors
Categories
Data CenterNetworkingProducts
Application Centric Infrastructure (ACI)Programming Languages
AnsibleLicense
Code Exchange Community
Get help, share code, and collaborate with other developers in the Code Exchange community.View Community