-
Notifications
You must be signed in to change notification settings - Fork 9
Aci adapter feature #100
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Aci adapter feature #100
Changes from 9 commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
ca41836
added aci adapter feature
t0m3kz f9b5bc5
Merge remote-tracking branch 'origin/main' into tz-aci-adapter-feature
e5ac3e1
Merge branch 'opsmill:main' into tz-aci-adapter-feature
t0m3kz 529c5ba
added aci adapter
08338b5
Merge branch 'opsmill:main' into tz-aci-adapter-feature
t0m3kz a864ce1
formated documentation
t0m3kz e622e7c
fixed review findings
t0m3kz 44682b6
fixed models template
t0m3kz 42a4ce5
updated config with LocationMetro
t0m3kz 3c725ee
fixed document style
t0m3kz File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,170 @@ | ||
| --- | ||
| title: Cisco ACI adapter | ||
| --- | ||
| import ReferenceLink from "../../src/components/Card"; | ||
|
|
||
| ## What is Cisco ACI? | ||
|
|
||
| The *Cisco ACI* is a software-defined networking (SDN) solution that provides a policy-based, application-centric approach to managing and orchestrating network infrastructure. It is commonly used in data centers for scalable, policy-driven networking. | ||
|
|
||
| ## Sync direction | ||
|
|
||
| Cisco ACI → Infrahub | ||
|
|
||
| :::note | ||
| Currently, the Cisco ACI adapter supports only **one-way synchronization** from ACI to Infrahub. Syncing data back into ACI is not yet supported. | ||
| ::: | ||
|
|
||
| ## Configuration | ||
|
|
||
| The adapter reads connection settings from the sync config and can be overridden by environment variables. Credentials should be provided from a secret manager or environment variables in production. | ||
|
|
||
| ### Configuration parameters | ||
|
|
||
| ```yaml | ||
| --- | ||
| name: from-cisco-aci | ||
| source: | ||
| name: aci | ||
| settings: | ||
| url: "https://<APIC_CONTROLLER>" | ||
| username: "<USER>" | ||
| password: "<PASSWORD>" | ||
| api_endpoint: "api" # optional, default: api | ||
| verify: true # boolean or string ("false","0") accepted | ||
| ``` | ||
|
|
||
| ### Environment variables | ||
|
|
||
| - CISCO_APIC_URL: overrides settings.url | ||
| - CISCO_APIC_USERNAME: overrides settings.username | ||
| - CISCO_APIC_PASSWORD: overrides settings.password | ||
| - CISCO_APIC_VERIFY: overrides settings.verify; accepts true/false/0/1 (strings are normalized) | ||
|
|
||
| Notes: | ||
|
|
||
| - Credentials must come from environment variables or a secret manager in production. Never commit secrets. | ||
| - The adapter normalizes verify to a boolean (strings like false, 0, no are treated as False). | ||
| - The adapter records login timestamps in UTC to avoid timezone related issues and ensure correct token refresh behavior. | ||
|
|
||
| ### Schema mapping examples | ||
|
|
||
| #### Basic device mapping | ||
|
|
||
| ```yaml | ||
| - name: DcimPhysicalDevice | ||
| mapping: "class/fabricNode.json" | ||
| identifiers: ["name"] | ||
| fields: | ||
| - name: name | ||
| mapping: "fabricNode.attributes.name" | ||
| - name: serial | ||
| mapping: "fabricNode.attributes.serial" | ||
| - name: role | ||
| mapping: "fabricNode.attributes.role" | ||
| filters: | ||
| - field: "fabricNode.attributes.fabricSt" | ||
| operation: "==" | ||
| value: "active" | ||
| ``` | ||
|
|
||
| #### Interface mapping with ACI Jinja filter | ||
|
|
||
| ```yaml | ||
| - name: DcimPhysicalInterface | ||
| mapping: "class/l1PhysIf.json" | ||
| identifiers: ["device", "name"] | ||
| fields: | ||
| - name: name | ||
| mapping: "l1PhysIf.attributes.id" | ||
| - name: device | ||
| mapping: "l1PhysIf.attributes.dn" | ||
| reference: DcimPhysicalDevice | ||
| - name: description | ||
| mapping: "l1PhysIf.attributes.descr" | ||
| transforms: | ||
| - field: device | ||
| expression: "{{ l1PhysIf.attributes.dn.split('/')[2].replace('node-', '') | aci_device_name }}" | ||
| - field: status | ||
| expression: "{{ 'active' if l1PhysIf.attributes.adminSt == 'up' else 'free' }}" | ||
| filters: | ||
| - field: "l1PhysIf.attributes.id" | ||
| operation: "contains" | ||
| value: "eth" | ||
| ``` | ||
|
|
||
| ## ACI-specific Jinja filters | ||
|
|
||
| The ACI adapter provides custom Jinja filters for data transformation: | ||
|
|
||
| ### `aci_device_name` filter | ||
|
|
||
| The `aci_device_name` filter resolves ACI node IDs to device names automatically. This is particularly useful when mapping physical interfaces to their parent devices. | ||
|
|
||
| **Usage:** | ||
|
|
||
| ```jinja2 | ||
| {{ node_id | aci_device_name }} | ||
| ``` | ||
|
|
||
| **Example:** | ||
|
|
||
| - Input: `"102"` (ACI node ID) | ||
| - Output: `"spine-102"` (actual device name from ACI) | ||
|
|
||
| **Common use case in transforms:** | ||
|
|
||
| ```yaml | ||
| transforms: | ||
| - field: device | ||
| expression: "{{ l1PhysIf.attributes.dn.split('/')[2].replace('node-', '') | aci_device_name }}" | ||
| ``` | ||
|
|
||
| This transform: | ||
|
|
||
| 1. Extracts the node ID from the ACI Distinguished Name (DN) | ||
| 2. Removes the `"node-"` prefix (e.g., `"node-102"` → `"102"`) | ||
| 3. Uses the `aci_device_name` filter to resolve the node ID to the actual device name | ||
|
|
||
| **How it works:** | ||
|
|
||
| - The adapter automatically queries ACI's `fabricNode` class during initialization | ||
| - Builds a mapping of node IDs to device names | ||
| - The filter performs a simple lookup with fallback to the original node ID if not found | ||
|
|
||
| ## Generating the models | ||
|
|
||
| Use the generate command to produce models from the schema mapping and examples: | ||
|
|
||
| ```bash | ||
| poetry run infrahub-sync generate --name from-cisco-aci --directory examples/ | ||
| ``` | ||
|
|
||
| ## Common issues and troubleshooting | ||
|
|
||
| ### Authentication and connectivity | ||
|
|
||
| - If you see token refresh errors, ensure the APIC response includes refreshTimeoutSeconds; the adapter forces re-login when refresh data is unavailable. | ||
| - For TLS verification problems, set CISCO_APIC_VERIFY to false in a secure environment (use with caution). | ||
|
|
||
| ### Device reference resolution | ||
|
|
||
| - **Interface-device relationship errors**: If you see "Unable to locate the node device" errors, ensure: | ||
| - The `DcimPhysicalDevice` mapping runs before `DcimPhysicalInterface` in the `order` configuration | ||
| - The device transform uses the `aci_device_name` filter correctly: `{{ node_id | aci_device_name }}` | ||
| - The ACI fabricNode query is successful (check logs for "Built ACI device mapping" messages) | ||
|
|
||
| ### Jinja filter issues | ||
|
|
||
| - **`aci_device_name` filter not found**: Ensure you're using the ACI adapter and the filter is correctly spelled | ||
| - **Filter returns node ID instead of device name**: Check that the fabricNode query was successful during adapter initialization | ||
| - **Transform expression errors**: Verify the DN parsing logic extracts the correct node ID: | ||
|
|
||
| ```yaml | ||
| expression: "{{ l1PhysIf.attributes.dn.split('/')[2].replace('node-', '') | aci_device_name }}" | ||
| ``` | ||
|
|
||
| ### General debugging | ||
|
|
||
| - Enable DEBUG logging for the adapter to see raw fetched objects and mapping decisions. Logs will not include secrets. | ||
| - Check the device mapping build process in logs: look for "Built ACI device mapping with X entries" | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| """ACI sync adapter module.""" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| from __future__ import annotations | ||
|
|
||
| from infrahub_sync.plugin_loader import PluginLoader | ||
|
|
||
| from .sync_models import ( | ||
| DcimPhysicalDevice, | ||
| DcimPhysicalInterface, | ||
| LocationBuilding, | ||
| LocationMetro, | ||
| OrganizationCustomer, | ||
| ) | ||
|
|
||
| # Load adapter class dynamically at runtime | ||
|
|
||
| _AdapterBaseClass = PluginLoader().resolve("aci") | ||
BeArchiTek marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
|
|
||
| # ------------------------------------------------------- | ||
| # AUTO-GENERATED FILE, DO NOT MODIFY | ||
| # This file has been generated with the command `infrahub-sync generate` | ||
| # All modifications will be lost the next time you reexecute this command | ||
| # ------------------------------------------------------- | ||
| class AciSync(_AdapterBaseClass): | ||
| DcimPhysicalDevice = DcimPhysicalDevice | ||
| DcimPhysicalInterface = DcimPhysicalInterface | ||
| LocationBuilding = LocationBuilding | ||
| LocationMetro = LocationMetro | ||
| OrganizationCustomer = OrganizationCustomer | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.