Manage a Cisco ACI VRF's Any contract-scope object and its consumer/provider/contract-interface relations (class
vzAny, DNuni/tn-{tenant}/ctx-{vrf}/any) as one typed, secure-by-default building block targetingCiscoDevNet/aci ~> 2.20.
This module manages a VRF's "Any" contract-scope object and the relation objects that bind it to contracts, as one coherent, secure-by-default unit:
- π The Any object (
aci_any.this) βvzAnyrepresents every EPG in the VRF for contract-matching purposes; it is a VRF singleton addressed by the Distinguished Nameuni/tn-{tenant}/ctx-{vrf}/any. - π€ Consumer-contract relations β
aci_relation_from_any_to_consumer_contract.this,for_eachover a typedconsumed_contractsmap, makes every EPG in the VRF a consumer of the named contract. - π€ Provider-contract relations β
aci_relation_from_any_to_provider_contract.this,for_eachover a typedprovided_contractsmap, makes every EPG in the VRF a provider of the named contract. - π Contract-interface relations β
aci_relation_from_any_to_contract_interface.this,for_eachover a typedcontract_interfacesmap, consumes a contract imported from another tenant. - π Secure posture by default β
match_criteriadefaults toAtleastOneandpreferred_group_memberdefaults todisabled, so EPGs are not silently admitted into the VRF's unenforced preferred group.
π‘ Why it matters: relations bound at the VRF's Any object apply fabric-wide across every EPG in the VRF, not to a single EPG β a materially larger blast radius than an EPG-scoped contract relation. Managing this scope as its own typed, reviewable unit keeps VRF-wide contract exposure deliberate and auditable rather than an incidental side effect of an EPG change.
If these Terraform modules have been helpful to you or your organization, I'd appreciate your support in any of the following ways:
- β Star this repository to help others discover this Terraform module.
- π€ Connect with me on LinkedIn: linkedin.com/in/microsoftexpert
- β Buy me a coffee: buymeacoffee.com/microsoftexpert
Whether it's a star, a professional connection, or a coffee, every gesture helps keep these modules actively maintained and continually improving. Thank you for being part of the community!
graph LR
apic["Cisco APIC fabric (provider auth, out of band)"]:::ext
tenant["terraform-aci-tenant"]:::sib
vrf["terraform-aci-vrf"]:::sib
anymod["terraform-aci-any-vrf-contract (this module)"]:::this
vzany["aci_any - class vzAny - DN uni/tn-{tenant}/ctx-{vrf}/any"]:::keystone
contract["terraform-aci-contract"]:::sib
epg["terraform-aci-application-epg"]:::sib
apic -->|"provider configured by caller"| anymod
tenant -->|"tenant_dn"| vrf
vrf -->|"vrf_dn"| anymod
anymod -->|"manages"| vzany
contract -->|"contract name (consumed_contracts / provided_contracts)"| anymod
epg -.->|"EPG-scoped contracts (separate binding, out of scope here)"| contract
classDef this fill:#00BCEB,color:#fff,stroke:#00BCEB;
classDef keystone fill:#0D274D,color:#fff,stroke:#0D274D;
classDef sib fill:#f5f5f5,color:#333,stroke:#cccccc;
classDef ext fill:#eeeeff,color:#333,stroke:#9999ff;
The Any object nests directly under a VRF and takes the VRF's DN as its only parent input. It consumes contracts (and imported contract interfaces) by name β those objects are owned and versioned by their own modules. EPG-scoped contract relations are a separate, EPG-owned binding and are intentionally out of scope here.
graph TD
vrfdn["vrf_dn (parent VRF DN)"]:::in
anycfg["any: match_criteria / preferred_group_member / metadata"]:::in
cc["consumed_contracts (map)"]:::in
pc["provided_contracts (map)"]:::in
ci["contract_interfaces (map)"]:::in
this["aci_any.this (keystone, vzAny)"]:::this
ccr["aci_relation_from_any_to_consumer_contract.this (for_each)"]:::this
pcr["aci_relation_from_any_to_provider_contract.this (for_each)"]:::this
cir["aci_relation_from_any_to_contract_interface.this (for_each)"]:::this
oid["output: id"]:::out
omc["output: match_criteria"]:::out
occ["output: consumer_contract_dns"]:::out
opc["output: provider_contract_dns"]:::out
oci["output: contract_interface_dns"]:::out
vrfdn --> this
anycfg --> this
this --> ccr
cc --> ccr
this --> pcr
pc --> pcr
this --> cir
ci --> cir
this --> oid
this --> omc
ccr --> occ
pcr --> opc
cir --> oci
classDef this fill:#00BCEB,color:#fff,stroke:#00BCEB;
classDef in fill:#f5f5f5,color:#333,stroke:#cccccc;
classDef out fill:#eeeeff,color:#333,stroke:#9999ff;
Resource inventory
| Resource | Name | Cardinality | Role |
|---|---|---|---|
aci_any |
this |
1 (keystone) | The VRF's Any contract-scope object (vzAny). |
aci_relation_from_any_to_consumer_contract |
this |
0..N (for_each) |
Consumer-contract relation (vzRsAnyToCons), keyed by contract name. |
aci_relation_from_any_to_provider_contract |
this |
0..N (for_each) |
Provider-contract relation (vzRsAnyToProv), keyed by contract name. |
aci_relation_from_any_to_contract_interface |
this |
0..N (for_each) |
Contract-interface relation (vzRsAnyToConsIf), keyed by imported contract name. |
| Requirement | Value |
|---|---|
| Terraform | >= 1.3.0 (uses optional() object defaults) |
| Provider | CiscoDevNet/aci ~> 2.20 |
| Provider block | None in this module β the caller configures and authenticates the provider (username/password, X.509 signature, or login domain) out of band. |
| Scope | Parent VRF DN (vrf_dn) β required; the Any object is a VRF singleton. |
Schema notes that bite (verified against the live provider schema):
- π
aci_anyis a VRF singleton. Its DN's trailing path segment is the literalany, independent of anynamevalue β the live schema exposesnameas optional/computed, but this module does not surface it because it has no bearing on identity or placement. β οΈ match_criteriaandmatch_tare mutually exclusive. Setting both onaci_anyfails at plan/apply withAttribute "match_criteria" cannot be specified when "match_t" is specified. This module manages only the currentmatch_criteriaattribute;match_tis the deprecated alias and is not used.β οΈ preferred_group_memberandpref_gr_membare mutually exclusive, for the same reason. This module manages onlypreferred_group_member, surfaced as abooland rendered to the provider's"enabled"/"disabled"string.- π
vrf_dn(the resource attribute) is deprecated. The live schema emits anAttribute Deprecatedwarning directing callers toparent_dn; this module wires the parent exclusively throughparent_dn. - βΉοΈ All four resources are migrated (plugin-framework).
annotations/tagsare typed{key, value}lists, assigned with=, not HCL blocks. The provider also retains classic flatrelation_vz_rs_any_to_cons/relation_vz_rs_any_to_cons_if/relation_vz_rs_any_to_provset-of-string attributes; this module uses the dedicated, richer relation resources instead and leaves the classic flat attributes to the provider. - βΉοΈ
priorityaccepts two representations: a named QoS class (level1-level6,unspecified) or a single-digit numeric string (0-9), confirmed by the live validator's error text. β οΈ validate_relation_dn(provider defaulttrue) fails apply if a contract named inconsumed_contracts/provided_contracts, or the imported contract behindcontract_interfaces, does not exist.
Scope the caller's APIC login to the least privilege this module needs:
- Create / modify the Any object and its contract relations: the
tenant-adminrole (or a custom role with tenant-security write privilege) scoped to the tenant's security domain. - Referenced contracts / contract interface: read on every contract named in
consumed_contracts/provided_contracts, and on the exporting tenant's contract interface referenced bycontract_interfaces.
The module never sees a credential β authentication is a provider/caller concern supplied out of band (e.g. ACI_USERNAME / ACI_PASSWORD, or ACI_PRIVATE_KEY / ACI_CERT_NAME for signature-based auth).
- A reachable Cisco APIC (
ACI_URL) whose version is compatible with the~> 2.20provider, with the provider configured and authenticated by the caller. - In production, the provider should be configured with
insecure = falseand proper CA trust β the provider's own default (insecure = true) is not a safe steady state. - The parent VRF (
vrf_dn) exists. - Every contract named in
consumed_contracts/provided_contractsexists (or is created in the same apply); the imported contract behind anycontract_interfacesentry exists in its exporting tenant. - The APIC version supports the chosen
match_criteriavalue (vzAnymatching has been available since ACI 1.0(1e)).
terraform-aci-any-vrf-contract/
βββ providers.tf # terraform{} + required_providers (aci ~> 2.20); no provider block
βββ variables.tf # vrf_dn, any, consumed_contracts, provided_contracts, contract_interfaces
βββ main.tf # aci_any.this (keystone) + the three for_each relation children
βββ outputs.tf # id (the DN) first, then match/posture and child relation DN maps
βββ README.md # this document
βββ SCOPE.md # cross-module contract (scope, consumes/emits, roles, prerequisites)
βββ LICENSE # MIT
βββ .gitignore # canonical library ignore set
# The caller configures the provider (authentication is out of band).
provider "aci" {
# username / password, or private_key + cert_name for signature auth;
# url = "https://apic.example.com"; set insecure = false in production.
}
module "any" {
source = "git::https://github.com/microsoftexpert/terraform-aci-any-vrf-contract.git?ref=v1.0.0"
vrf_dn = "uni/tn-core-prod/ctx-core-vrf" # e.g. module.vrf.id
consumed_contracts = {
"shared-dns" = {}
}
}
output "any_dn" {
value = module.any.id
}Consumes
| Input | Type | Typical source |
|---|---|---|
vrf_dn |
string (DN) | terraform-aci-vrf |
any |
object({...}) |
caller (match criteria + preferred-group posture + metadata) |
consumed_contracts |
map(object({...})) |
caller (contract names from terraform-aci-contract) |
provided_contracts |
map(object({...})) |
caller (contract names from terraform-aci-contract) |
contract_interfaces |
map(object({...})) |
caller (imported contract names from an exporting tenant) |
Emits
| Output | Description | Consumed by |
|---|---|---|
id |
Any object DN (uni/tn-{tenant}/ctx-{vrf}/any) |
audits / downstream reference |
match_criteria |
Configured provider-label match criteria | audit |
preferred_group_member |
Configured preferred-group posture (enabled/disabled) |
audit |
consumer_contract_dns |
Map of contract name β consumer-contract relation DN | audits / policy review |
provider_contract_dns |
Map of contract name β provider-contract relation DN | audits / policy review |
contract_interface_dns |
Map of imported contract name β contract-interface relation DN | audits / policy review |
1 Β· Minimal β the Any object with secure defaults
module "any" {
source = "git::https://github.com/microsoftexpert/terraform-aci-any-vrf-contract.git?ref=v1.0.0"
vrf_dn = "uni/tn-core-prod/ctx-core-vrf"
}π‘ The minimal call creates only
aci_any.thiswithmatch_criteria = "AtleastOne"andpreferred_group_member = "disabled"β no contract relations, no permissive posture.
2 Β· Widening the match criteria
module "any" {
source = "git::https://github.com/microsoftexpert/terraform-aci-any-vrf-contract.git?ref=v1.0.0"
vrf_dn = "uni/tn-core-prod/ctx-core-vrf"
any = {
match_criteria = "All"
}
}βΉοΈ
match_criteriacontrols how provider labels are matched against consumer labels:Allrequires every label to match,AtleastOne(the default) requires one,AtmostOneallows at most one, andNonerequires no match.
3 Β· Enabling the VRF preferred group (documented risk)
module "any" {
source = "git::https://github.com/microsoftexpert/terraform-aci-any-vrf-contract.git?ref=v1.0.0"
vrf_dn = "uni/tn-core-prod/ctx-core-vrf"
any = {
preferred_group_member = true
}
}
β οΈ Enablingpreferred_group_memberallows EPGs placed in the VRF's preferred group to communicate without any contract β a materially more permissive posture. This suite defaults it tofalse; opt in deliberately and document the change.
4 Β· Metadata tail β GUI alias and description
module "any" {
source = "git::https://github.com/microsoftexpert/terraform-aci-any-vrf-contract.git?ref=v1.0.0"
vrf_dn = "uni/tn-core-prod/ctx-core-vrf"
any = {
name_alias = "Core VRF Any"
description = "VRF-wide contract scope for core-prod's core-vrf"
}
}βΉοΈ
name_aliasis a display alias shown in the APIC GUI; it has no bearing on the object's DN.
5 Β· User metadata via annotations and tags
module "any" {
source = "git::https://github.com/microsoftexpert/terraform-aci-any-vrf-contract.git?ref=v1.0.0"
vrf_dn = "uni/tn-core-prod/ctx-core-vrf"
any = {
annotations = { "cost-center" = "CC-4021", "environment" = "production" }
tags = { "tier" = "gold" }
}
}βΉοΈ
annotations/tagsare given as ergonomic{ key = value }maps and rendered to the provider's[{key, value}]list shape.
6 Β· A custom annotation marker
module "any" {
source = "git::https://github.com/microsoftexpert/terraform-aci-any-vrf-contract.git?ref=v1.0.0"
vrf_dn = "uni/tn-core-prod/ctx-core-vrf"
any = {
annotation = "orchestrator:terraform:platform-team"
}
}π Keep the
orchestrator:terraformprefix so Terraform-managed objects stay identifiable in APIC. This suite defaultsannotationtoorchestrator:terraform; override it only to extend, not to erase, that marker.
7 Β· A single consumer-contract relation
module "any" {
source = "git::https://github.com/microsoftexpert/terraform-aci-any-vrf-contract.git?ref=v1.0.0"
vrf_dn = "uni/tn-core-prod/ctx-core-vrf"
consumed_contracts = {
"shared-dns" = {}
}
}
β οΈ Every EPG in this VRF becomes a consumer ofshared-dnsβ a VRF-wide effect, not an EPG-scoped one.
8 Β· A consumer-contract relation with an explicit QoS priority
module "any" {
source = "git::https://github.com/microsoftexpert/terraform-aci-any-vrf-contract.git?ref=v1.0.0"
vrf_dn = "uni/tn-core-prod/ctx-core-vrf"
consumed_contracts = {
"shared-dns" = {
priority = "level3"
}
}
}βΉοΈ
priorityaccepts a named QoS class (level1-level6,unspecified) or a single-digit numeric string (0-9), per the live provider schema.
9 Β· A provider-contract relation with a narrower match criteria
module "any" {
source = "git::https://github.com/microsoftexpert/terraform-aci-any-vrf-contract.git?ref=v1.0.0"
vrf_dn = "uni/tn-core-prod/ctx-core-vrf"
provided_contracts = {
"shared-ntp" = {
match_criteria = "AtmostOne"
}
}
}βΉοΈ
provided_contracts[*].match_criteriaoverrides the provider-label match algorithm for that specific relation, independent ofany.match_criteria.
10 Β· A contract-interface relation (importing another tenant's contract)
module "any" {
source = "git::https://github.com/microsoftexpert/terraform-aci-any-vrf-contract.git?ref=v1.0.0"
vrf_dn = "uni/tn-core-prod/ctx-core-vrf"
contract_interfaces = {
"shared-svcs-egress" = {}
}
}
β οΈ The imported contract must exist in its exporting tenant so the provider'svalidate_relation_dncheck passes at apply.
11 Β· Multiple consumed and provided contracts together
module "any" {
source = "git::https://github.com/microsoftexpert/terraform-aci-any-vrf-contract.git?ref=v1.0.0"
vrf_dn = "uni/tn-core-prod/ctx-core-vrf"
consumed_contracts = {
"shared-dns" = {}
"shared-ntp" = {}
}
provided_contracts = {
"core-vrf-health-check" = { priority = "level6" }
}
}π‘ Every entry is a
for_eachmap keyed by contract name β adding or removing one contract never churns the others.
12 Β· Least-privilege operating model (documentation variant)
# Configure the provider with a login scoped to tenant-security management only β
# not a fabric-wide admin β for day-2 contract-scope changes.
provider "aci" {
# username = "svc-tenant-security" # a tenant-admin role, write-scoped to
# # this tenant's security domain
# private_key = var.apic_private_key # signature auth avoids login-rate limits
# cert_name = "terraform-cert"
# url = "https://apic.example.com"
# insecure = false
}
module "any" {
source = "git::https://github.com/microsoftexpert/terraform-aci-any-vrf-contract.git?ref=v1.0.0"
vrf_dn = "uni/tn-core-prod/ctx-core-vrf"
}π Prefer signature-based (X.509) auth for automation to avoid APIC login-rate thresholds.
13 Β· Wiring the VRF DN from terraform-aci-vrf
module "vrf" {
source = "git::https://github.com/microsoftexpert/terraform-aci-vrf.git?ref=v1.0.0"
tenant_dn = "uni/tn-core-prod"
vrf = { name = "core-vrf" }
}
module "any" {
source = "git::https://github.com/microsoftexpert/terraform-aci-any-vrf-contract.git?ref=v1.0.0"
vrf_dn = module.vrf.id # <-- the VRF's DN becomes this module's parent
consumed_contracts = {
"shared-dns" = {}
}
}14 Β· Reading outputs for downstream audit
module "any" {
source = "git::https://github.com/microsoftexpert/terraform-aci-any-vrf-contract.git?ref=v1.0.0"
vrf_dn = "uni/tn-core-prod/ctx-core-vrf"
consumed_contracts = { "shared-dns" = {} }
provided_contracts = { "shared-ntp" = {} }
}
output "any_dn" { value = module.any.id }
output "consumer_contract_dns" { value = module.any.consumer_contract_dns }
output "provider_contract_dns" { value = module.any.provider_contract_dns }15 Β· ποΈ End-to-end composition β tenant β VRF β Any (VRF-wide contract scope) β contract
provider "aci" {
# configured + authenticated by the caller; insecure = false in production
}
# 1) The keystone tenant.
module "tenant" {
source = "git::https://github.com/microsoftexpert/terraform-aci-tenant.git?ref=v1.0.0"
tenant = { name = "core-prod", description = "Core production tenant" }
}
# 2) A VRF in the tenant.
module "vrf" {
source = "git::https://github.com/microsoftexpert/terraform-aci-vrf.git?ref=v1.0.0"
tenant_dn = module.tenant.id
vrf = { name = "core-vrf" }
}
# 3) A contract to expose fabric-wide within the VRF.
module "contract" {
source = "git::https://github.com/microsoftexpert/terraform-aci-contract.git?ref=v1.0.0"
tenant_dn = module.tenant.id
contract = { name = "shared-dns" }
}
# 4) This module β bind the contract at the VRF's Any object.
module "any" {
source = "git::https://github.com/microsoftexpert/terraform-aci-any-vrf-contract.git?ref=v1.0.0"
vrf_dn = module.vrf.id
provided_contracts = {
(module.contract.name) = { priority = "unspecified" }
}
}
output "any_dn" { value = module.any.id }ποΈ One tenant, one VRF, and one contract in; a fabric-wide, VRF-scoped contract binding out. Every EPG in
core-vrfbecomes a provider ofshared-dnswithout any EPG-level configuration β review this relation with the same rigor as a fabric-wide security change.
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
vrf_dn |
string |
β | β | Parent VRF DN (uni/tn-{tenant}/ctx-{vrf}). |
any |
object({...}) |
β | {} |
Match criteria, preferred-group posture, and metadata tail. |
consumed_contracts |
map(object({...})) |
β | {} |
Consumer-contract relations, keyed by contract name. |
provided_contracts |
map(object({...})) |
β | {} |
Provider-contract relations, keyed by contract name. |
contract_interfaces |
map(object({...})) |
β | {} |
Contract-interface relations, keyed by imported contract name. |
Full input schema (from variables.tf)
variable "vrf_dn" {
type = string
# validation: matches ^uni/tn-[^/]+/ctx-[^/]+$
}
variable "any" {
type = object({
match_criteria = optional(string, "AtleastOne") # All | AtleastOne | AtmostOne | None
preferred_group_member = optional(bool, false) # renders enabled/disabled
annotation = optional(string, "orchestrator:terraform")
name_alias = optional(string, null)
description = optional(string, null)
annotations = optional(map(string), {})
tags = optional(map(string), {})
})
default = {}
}
variable "consumed_contracts" {
type = map(object({
priority = optional(string, "unspecified") # level1-level6 | unspecified | 0-9
annotation = optional(string, "orchestrator:terraform")
annotations = optional(map(string), {})
tags = optional(map(string), {})
}))
default = {}
}
variable "provided_contracts" {
type = map(object({
priority = optional(string, "unspecified")
match_criteria = optional(string, "AtleastOne")
annotation = optional(string, "orchestrator:terraform")
annotations = optional(map(string), {})
tags = optional(map(string), {})
}))
default = {}
}
variable "contract_interfaces" {
type = map(object({
priority = optional(string, "unspecified")
annotation = optional(string, "orchestrator:terraform")
annotations = optional(map(string), {})
tags = optional(map(string), {})
}))
default = {}
}| Output | Description | Notes |
|---|---|---|
id |
Any object DN (uni/tn-{tenant}/ctx-{vrf}/any) |
Primary reference; usually for audit rather than as a downstream parent_dn. |
match_criteria |
Configured provider-label match criteria | β |
preferred_group_member |
Configured preferred-group posture (enabled/disabled) |
β |
consumer_contract_dns |
Map of contract name β consumer-contract relation DN | Empty map if consumed_contracts is empty. |
provider_contract_dns |
Map of contract name β provider-contract relation DN | Empty map if provided_contracts is empty. |
contract_interface_dns |
Map of imported contract name β contract-interface relation DN | Empty map if contract_interfaces is empty. |
- One keystone, three relation families.
aci_any.thisis the singleton keystone; each of the three relation types is its ownfor_eachmap keyed by a stable natural key (contract name, or imported contract name for interfaces) β nevercountβ so adding one relation never churns the others. - Deprecated-attribute avoidance. The parent is wired through
parent_dn, not the deprecatedvrf_dnresource attribute;match_criteria/preferred_group_memberare used instead of their deprecatedmatch_t/pref_gr_membaliases, which the live schema rejects if set alongside the current attribute. - No
namesurfaced.aci_anyis a VRF singleton whose DN never varies withname; the module omits it rather than exposing a field with no effect. - Dedicated relation resources over inline nesting. The live schema also exposes
relation_to_consumer_contracts/relation_to_provider_contracts/relation_to_contract_interfacesas inline nested attributes directly onaci_any. This module instead uses the dedicated standalone relation resources assigned to it, keeping each relation independently addressable and matching this suite'sfor_each-child convention. - Unmanaged when empty.
annotations/tagspassnullrather than an empty list when empty, on both the keystone and every child, so the module never fights provider-computed state. - Blast radius. Every relation created here applies VRF-wide, across every EPG in the VRF β treat changes to
consumed_contracts/provided_contracts/contract_interfacesas VRF-scoped security changes, not EPG-scoped ones.
| Concern | Secure default | How to opt out (deliberately) |
|---|---|---|
any.match_criteria |
AtleastOne β require at least one matching provider label |
Set to All, AtmostOne, or None per the desired matching semantics. |
any.preferred_group_member |
false (disabled) β EPGs do not bypass contract enforcement via the preferred group |
Set to true (enabled) deliberately, and document the widened blast radius. |
consumed_contracts / provided_contracts / contract_interfaces |
{} β no relations managed, no VRF-wide exposure by default |
Populate the maps explicitly, one entry per contract. |
any.annotation |
orchestrator:terraform β Terraform-managed objects stay identifiable in APIC |
Extend the marker; do not blank it. |
| Transport (provider) | This suite instructs callers to set insecure = false with CA trust |
The provider default is insecure = true; do not keep it as a steady state. |
| Secrets | None accepted or emitted | n/a β this module carries no secret material; credentials are provider config. |
# From the module directory (offline, no credentials, no backend):
terraform init -backend=false
terraform validate
terraform fmt -check- Pin the module by immutable tag:
?ref=v1.0.0β never a branch. - This module is plan-only from the library's perspective. A human runs
terraform plan/applyagainst a sub-production APIC from their own pipeline, with a login scoped to the permissions above. No cloud apply happens here.
The offline proof gate for this module:
- β
terraform validateβ parses the module, resolves theany/consumed_contracts/provided_contracts/contract_interfacesobject types, runs every enum and DN-format validation, and confirms every argument exists in the provider schema. - β
terraform fmt -checkβ canonical formatting. - β Not exercised offline (only a real
plan/applyagainst an APIC covers these): DN validation of the parent VRF and every referenced contract (server-sidevalidate_relation_dn), APIC-side name-collision checks, and the computed DNs returned as outputs.
$ terraform output
id = "uni/tn-core-prod/ctx-core-vrf/any"
match_criteria = "AtleastOne"
preferred_group_member = "disabled"
consumer_contract_dns = {}
provider_contract_dns = {
"shared-dns" = "uni/tn-core-prod/ctx-core-vrf/any/rsanyToProv-shared-dns"
}
contract_interface_dns = {}
| Symptom | Cause | Fix |
|---|---|---|
vrf_dn must be a VRF DN of the form uni/tn-{tenant}/ctx-{vrf} |
vrf_dn is missing the tenant/VRF path segments |
Pass the VRF's actual DN (e.g. module.vrf.id), not a tenant DN or a free-form string. |
any.match_criteria must be one of: All, AtleastOne, AtmostOne, None |
Unsupported value passed for any.match_criteria |
Use one of the four documented values. |
Every consumed_contracts[*].priority must be one of level1-level6, unspecified, or a single digit 0-9 |
Unsupported priority value |
Use a named QoS class or a single digit 0-9. |
Attribute "match_criteria" cannot be specified when "match_t" is specified |
Both a current and deprecated attribute set on the same resource | This module manages only match_criteria; do not add match_t alongside it. |
| Apply fails validating a contract or contract-interface relation | Referenced contract (or the imported contract behind contract_interfaces) does not exist |
Create the contract first (or in the same apply); do not disable validate_relation_dn. |
| Every EPG in the VRF unexpectedly gained contract exposure | A relation was added at the Any (VRF-wide) scope instead of at the EPG | Confirm whether the intended scope is VRF-wide (this module) or EPG-scoped (the application-EPG module) before adding an entry. |
Post ... 401 / authentication error |
Provider not configured or wrong credentials | Configure the aci provider with valid credentials and url; prefer signature auth for automation. |
- Cisco ACI provider β
aci_any - Cisco ACI provider β
aci_relation_from_any_to_consumer_contract - Cisco ACI provider β
aci_relation_from_any_to_provider_contract - Cisco ACI provider β
aci_relation_from_any_to_contract_interface - Cisco APIC object model β class
vzAny(the VRF's contract-scope "any EPG"). - Sibling modules:
terraform-aci-vrf,terraform-aci-contract,terraform-aci-application-epg. - This module's
SCOPE.mdβ the cross-module contract.
π "Infrastructure as Code should be standardized, consistent, and secure."