diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ac2f2b11..ddc816e7 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -33,6 +33,10 @@ repos: args: ["./modules/terraform-aci-access-fex-interface-selector"] - id: terraform-docs-system args: ["./modules/terraform-aci-access-fex-interface-selector/examples/complete"] + - id: terraform-docs-system + args: ["./modules/terraform-aci-access-leaf-copp-policy"] + - id: terraform-docs-system + args: ["./modules/terraform-aci-access-leaf-copp-policy/examples/complete"] - id: terraform-docs-system args: ["./modules/terraform-aci-access-leaf-interface-policy-group"] - id: terraform-docs-system @@ -65,6 +69,10 @@ repos: args: ["./modules/terraform-aci-access-span-source-group"] - id: terraform-docs-system args: ["./modules/terraform-aci-access-span-source-group/examples/complete"] + - id: terraform-docs-system + args: ["./modules/terraform-aci-access-spine-copp-policy"] + - id: terraform-docs-system + args: ["./modules/terraform-aci-access-spine-copp-policy/examples/complete"] - id: terraform-docs-system args: ["./modules/terraform-aci-access-spine-interface-policy-group"] - id: terraform-docs-system @@ -161,6 +169,11 @@ repos: args: ["./modules/terraform-aci-coop-policy"] - id: terraform-docs-system args: ["./modules/terraform-aci-coop-policy/examples/complete"] + - id: terraform-docs-system + - id: terraform-docs-system + args: ["./modules/terraform-aci-copp-interface-policy"] + - id: terraform-docs-system + args: ["./modules/terraform-aci-copp-interface-policy/examples/complete"] - id: terraform-docs-system args: ["./modules/terraform-aci-date-time-format"] - id: terraform-docs-system diff --git a/README.md b/README.md index 922f01ca..7545f3fd 100644 --- a/README.md +++ b/README.md @@ -140,6 +140,7 @@ Additional example repositories: | [aci\_access\_fex\_interface\_profile\_manual](#module\_aci\_access\_fex\_interface\_profile\_manual) | ./modules/terraform-aci-access-fex-interface-profile | n/a | | [aci\_access\_fex\_interface\_selector\_auto](#module\_aci\_access\_fex\_interface\_selector\_auto) | ./modules/terraform-aci-access-fex-interface-selector | n/a | | [aci\_access\_fex\_interface\_selector\_manual](#module\_aci\_access\_fex\_interface\_selector\_manual) | ./modules/terraform-aci-access-fex-interface-selector | n/a | +| [aci\_access\_leaf\_copp\_policy](#module\_aci\_access\_leaf\_copp\_policy) | ./modules/terraform-aci-access-leaf-copp-policy | n/a | | [aci\_access\_leaf\_interface\_policy\_group](#module\_aci\_access\_leaf\_interface\_policy\_group) | ./modules/terraform-aci-access-leaf-interface-policy-group | n/a | | [aci\_access\_leaf\_interface\_profile\_auto](#module\_aci\_access\_leaf\_interface\_profile\_auto) | ./modules/terraform-aci-access-leaf-interface-profile | n/a | | [aci\_access\_leaf\_interface\_profile\_manual](#module\_aci\_access\_leaf\_interface\_profile\_manual) | ./modules/terraform-aci-access-leaf-interface-profile | n/a | @@ -153,6 +154,7 @@ Additional example repositories: | [aci\_access\_span\_destination\_group](#module\_aci\_access\_span\_destination\_group) | ./modules/terraform-aci-access-span-destination-group | n/a | | [aci\_access\_span\_filter\_group](#module\_aci\_access\_span\_filter\_group) | ./modules/terraform-aci-access-span-filter-group | n/a | | [aci\_access\_span\_source\_group](#module\_aci\_access\_span\_source\_group) | ./modules/terraform-aci-access-span-source-group | n/a | +| [aci\_access\_spine\_copp\_policy](#module\_aci\_access\_spine\_copp\_policy) | ./modules/terraform-aci-access-spine-copp-policy | n/a | | [aci\_access\_spine\_interface\_policy\_group](#module\_aci\_access\_spine\_interface\_policy\_group) | ./modules/terraform-aci-access-spine-interface-policy-group | n/a | | [aci\_access\_spine\_interface\_profile\_auto](#module\_aci\_access\_spine\_interface\_profile\_auto) | ./modules/terraform-aci-access-spine-interface-profile | n/a | | [aci\_access\_spine\_interface\_profile\_manual](#module\_aci\_access\_spine\_interface\_profile\_manual) | ./modules/terraform-aci-access-spine-interface-profile | n/a | @@ -182,6 +184,7 @@ Additional example repositories: | [aci\_config\_passphrase](#module\_aci\_config\_passphrase) | ./modules/terraform-aci-config-passphrase | n/a | | [aci\_contract](#module\_aci\_contract) | ./modules/terraform-aci-contract | n/a | | [aci\_coop\_policy](#module\_aci\_coop\_policy) | ./modules/terraform-aci-coop-policy | n/a | +| [aci\_copp\_interface\_policy](#module\_aci\_copp\_interface\_policy) | ./modules/terraform-aci-copp-interface-policy | n/a | | [aci\_date\_time\_format](#module\_aci\_date\_time\_format) | ./modules/terraform-aci-date-time-format | n/a | | [aci\_date\_time\_policy](#module\_aci\_date\_time\_policy) | ./modules/terraform-aci-date-time-policy | n/a | | [aci\_device\_selection\_policy](#module\_aci\_device\_selection\_policy) | ./modules/terraform-aci-device-selection-policy | n/a | diff --git a/aci_access_policies.tf b/aci_access_policies.tf index 6adc0441..abce606c 100644 --- a/aci_access_policies.tf +++ b/aci_access_policies.tf @@ -133,27 +133,31 @@ module "aci_access_leaf_switch_policy_group" { forwarding_scale_policy = try("${each.value.forwarding_scale_policy}${local.defaults.apic.access_policies.switch_policies.forwarding_scale_policies.name_suffix}", "") bfd_ipv4_policy = try("${each.value.bfd_ipv4_policy}${local.defaults.apic.access_policies.switch_policies.bfd_ipv4_policies.name_suffix}", "") bfd_ipv6_policy = try("${each.value.bfd_ipv6_policy}${local.defaults.apic.access_policies.switch_policies.bfd_ipv6_policies.name_suffix}", "") + copp_leaf_policy = try("${each.value.copp_leaf_policy}${local.defaults.apic.access_policies.switch_policies.copp_leaf.name_suffix}", "") depends_on = [ module.aci_forwarding_scale_policy, module.aci_bfd_ipv4_policy, module.aci_bfd_ipv6_policy, + module.aci_access_leaf_copp_policy, ] } module "aci_access_spine_switch_policy_group" { source = "./modules/terraform-aci-access-spine-switch-policy-group" - for_each = { for pg in try(local.access_policies.spine_switch_policy_groups, []) : pg.name => pg if local.modules.aci_access_spine_switch_policy_group && var.manage_access_policies } - name = "${each.value.name}${local.defaults.apic.access_policies.spine_switch_policy_groups.name_suffix}" - lldp_policy = try("${each.value.lldp_policy}${local.defaults.apic.access_policies.interface_policies.lldp_policies.name_suffix}", "") - bfd_ipv4_policy = try("${each.value.bfd_ipv4_policy}${local.defaults.apic.access_policies.switch_policies.bfd_ipv4_policies.name_suffix}", "") - bfd_ipv6_policy = try("${each.value.bfd_ipv6_policy}${local.defaults.apic.access_policies.switch_policies.bfd_ipv6_policies.name_suffix}", "") + for_each = { for pg in try(local.access_policies.spine_switch_policy_groups, []) : pg.name => pg if local.modules.aci_access_spine_switch_policy_group && var.manage_access_policies } + name = "${each.value.name}${local.defaults.apic.access_policies.spine_switch_policy_groups.name_suffix}" + lldp_policy = try("${each.value.lldp_policy}${local.defaults.apic.access_policies.interface_policies.lldp_policies.name_suffix}", "") + bfd_ipv4_policy = try("${each.value.bfd_ipv4_policy}${local.defaults.apic.access_policies.switch_policies.bfd_ipv4_policies.name_suffix}", "") + bfd_ipv6_policy = try("${each.value.bfd_ipv6_policy}${local.defaults.apic.access_policies.switch_policies.bfd_ipv6_policies.name_suffix}", "") + copp_spine_policy = try("${each.value.copp_spine_policy}${local.defaults.apic.access_policies.switch_policies.copp_spine.name_suffix}", "") depends_on = [ module.aci_lldp_policy, module.aci_bfd_ipv4_policy, module.aci_bfd_ipv6_policy, + module.aci_access_spine_copp_policy, ] } @@ -273,6 +277,30 @@ module "aci_access_spine_switch_configuration" { ] } +locals { + copp = flatten([ + for pol in try(local.access_policies.interface_policies.copp_policies, []) : { + name = "${pol.name}${local.defaults.apic.access_policies.interface_policies.copp_policies.name_suffix}" + description = try(pol.description, "") + protocol_policies = [for pp in try(pol.protocol_policies, []) : { + name = "${pp.name}${local.defaults.apic.access_policies.interface_policies.copp_policies.name_suffix}" + rate = try(pp.rate, local.defaults.apic.access_policies.interface_policies.copp_policies.rate) + burst = try(pp.burst, local.defaults.apic.access_policies.interface_policies.copp_policies.burst) + match_protocols = try(pp.match_protocols, null) + }] + } + ]) +} + +module "aci_copp_interface_policy" { + source = "./modules/terraform-aci-copp-interface-policy" + + for_each = { for copp in try(local.copp, []) : copp.name => copp if local.modules.aci_copp_interface_policy && var.manage_access_policies } + name = each.value.name + description = each.value.description + protocol_policies = each.value.protocol_policies +} + module "aci_cdp_policy" { source = "./modules/terraform-aci-cdp-policy" @@ -390,6 +418,7 @@ module "aci_access_leaf_interface_policy_group" { map = try(each.value.map, local.defaults.apic.access_policies.leaf_interface_policy_groups.map) link_level_policy = try("${each.value.link_level_policy}${local.defaults.apic.access_policies.interface_policies.link_level_policies.name_suffix}", "") cdp_policy = try("${each.value.cdp_policy}${local.defaults.apic.access_policies.interface_policies.cdp_policies.name_suffix}", "") + copp_policy = try("${each.value.copp_policy}${local.defaults.apic.access_policies.interface_policies.copp_policies.name_suffix}", "") lldp_policy = try("${each.value.lldp_policy}${local.defaults.apic.access_policies.interface_policies.lldp_policies.name_suffix}", "") spanning_tree_policy = try("${each.value.spanning_tree_policy}${local.defaults.apic.access_policies.interface_policies.spanning_tree_policies.name_suffix}", "") mcp_policy = try("${each.value.mcp_policy}${local.defaults.apic.access_policies.interface_policies.mcp_policies.name_suffix}", "") @@ -406,6 +435,7 @@ module "aci_access_leaf_interface_policy_group" { depends_on = [ module.aci_link_level_policy, module.aci_cdp_policy, + module.aci_copp_interface_policy, module.aci_lldp_policy, module.aci_spanning_tree_policy, module.aci_mcp_policy, @@ -947,4 +977,108 @@ module "aci_netflow_record" { name = "${each.value.name}${local.defaults.apic.access_policies.interface_policies.netflow_records.name_suffix}" description = try(each.value.description, "") match_parameters = try(each.value.match_parameters, []) +} + +module "aci_access_leaf_copp_policy" { + source = "./modules/terraform-aci-access-leaf-copp-policy" + + for_each = { for pol in try(local.access_policies.leaf_copp_policies, []) : pol.name => pol if local.modules.aci_access_leaf_copp_policy && var.manage_access_policies } + name = "${each.value.name}${local.defaults.apic.access_policies.switch_policies.copp_leaf.name_suffix}" + description = try(each.value.description, "") + type = try(each.value.type, local.defaults.apic.access_policies.switch_policies.copp_leaf.type) + custom_values = { + arp_rate = try(each.value.custom_values.arp_rate, local.defaults.apic.access_policies.switch_policies.copp_leaf.custom_values.arp_rate) + arp_burst = try(each.value.custom_values.arp_burst, local.defaults.apic.access_policies.switch_policies.copp_leaf.custom_values.arp_burst) + acl_log_rate = try(each.value.custom_values.acl_log_rate, local.defaults.apic.access_policies.switch_policies.copp_leaf.custom_values.acl_log_rate) + acl_log_burst = try(each.value.custom_values.acl_log_burst, local.defaults.apic.access_policies.switch_policies.copp_leaf.custom_values.acl_log_burst) + bgp_rate = try(each.value.custom_values.bgp_rate, local.defaults.apic.access_policies.switch_policies.copp_leaf.custom_values.bgp_rate) + bgp_burst = try(each.value.custom_values.bgp_burst, local.defaults.apic.access_policies.switch_policies.copp_leaf.custom_values.bgp_burst) + cdp_rate = try(each.value.custom_values.cdp_rate, local.defaults.apic.access_policies.switch_policies.copp_leaf.custom_values.cdp_rate) + cdp_burst = try(each.value.custom_values.cdp_burst, local.defaults.apic.access_policies.switch_policies.copp_leaf.custom_values.cdp_burst) + coop_rate = try(each.value.custom_values.coop_rate, local.defaults.apic.access_policies.switch_policies.copp_leaf.custom_values.coop_rate) + coop_burst = try(each.value.custom_values.coop_burst, local.defaults.apic.access_policies.switch_policies.copp_leaf.custom_values.coop_burst) + dhcp_rate = try(each.value.custom_values.dhcp_rate, local.defaults.apic.access_policies.switch_policies.copp_leaf.custom_values.dhcp_rate) + dhcp_burst = try(each.value.custom_values.dhcp_burst, local.defaults.apic.access_policies.switch_policies.copp_leaf.custom_values.dhcp_burst) + eigrp_rate = try(each.value.custom_values.eigrp_rate, local.defaults.apic.access_policies.switch_policies.copp_leaf.custom_values.eigrp_rate) + eigrp_burst = try(each.value.custom_values.eigrp_burst, local.defaults.apic.access_policies.switch_policies.copp_leaf.custom_values.eigrp_burst) + glean_rate = try(each.value.custom_values.glean_rate, local.defaults.apic.access_policies.switch_policies.copp_leaf.custom_values.glean_rate) + glean_burst = try(each.value.custom_values.glean_burst, local.defaults.apic.access_policies.switch_policies.copp_leaf.custom_values.glean_burst) + icmp_rate = try(each.value.custom_values.icmp_rate, local.defaults.apic.access_policies.switch_policies.copp_leaf.custom_values.icmp_rate) + icmp_burst = try(each.value.custom_values.icmp_burst, local.defaults.apic.access_policies.switch_policies.copp_leaf.custom_values.icmp_burst) + ifc_rate = try(each.value.custom_values.ifc_rate, local.defaults.apic.access_policies.switch_policies.copp_leaf.custom_values.ifc_rate) + ifc_burst = try(each.value.custom_values.ifc_burst, local.defaults.apic.access_policies.switch_policies.copp_leaf.custom_values.ifc_burst) + ifc_other_rate = try(each.value.custom_values.ifc_other_rate, local.defaults.apic.access_policies.switch_policies.copp_leaf.custom_values.ifc_other_rate) + ifc_other_burst = try(each.value.custom_values.ifc_other_burst, local.defaults.apic.access_policies.switch_policies.copp_leaf.custom_values.ifc_other_burst) + ifc_span_rate = try(each.value.custom_values.ifc_span_rate, local.defaults.apic.access_policies.switch_policies.copp_leaf.custom_values.ifc_span_rate) + ifc_span_burst = try(each.value.custom_values.ifc_span_burst, local.defaults.apic.access_policies.switch_policies.copp_leaf.custom_values.ifc_span_burst) + igmp_rate = try(each.value.custom_values.igmp_rate, local.defaults.apic.access_policies.switch_policies.copp_leaf.custom_values.igmp_rate) + igmp_burst = try(each.value.custom_values.igmp_burst, local.defaults.apic.access_policies.switch_policies.copp_leaf.custom_values.igmp_burst) + infra_arp_rate = try(each.value.custom_values.infra_arp_rate, local.defaults.apic.access_policies.switch_policies.copp_leaf.custom_values.infra_arp_rate) + infra_arp_burst = try(each.value.custom_values.infra_arp_burst, local.defaults.apic.access_policies.switch_policies.copp_leaf.custom_values.infra_arp_burst) + isis_rate = try(each.value.custom_values.isis_rate, local.defaults.apic.access_policies.switch_policies.copp_leaf.custom_values.isis_rate) + isis_burst = try(each.value.custom_values.isis_burst, local.defaults.apic.access_policies.switch_policies.copp_leaf.custom_values.isis_burst) + lacp_rate = try(each.value.custom_values.lacp_rate, local.defaults.apic.access_policies.switch_policies.copp_leaf.custom_values.lacp_rate) + lacp_burst = try(each.value.custom_values.lacp_burst, local.defaults.apic.access_policies.switch_policies.copp_leaf.custom_values.lacp_burst) + lldp_rate = try(each.value.custom_values.lldp_rate, local.defaults.apic.access_policies.switch_policies.copp_leaf.custom_values.lldp_rate) + lldp_burst = try(each.value.custom_values.lldp_burst, local.defaults.apic.access_policies.switch_policies.copp_leaf.custom_values.lldp_burst) + mcp_rate = try(each.value.custom_values.mcp_rate, local.defaults.apic.access_policies.switch_policies.copp_leaf.custom_values.mcp_rate) + mcp_burst = try(each.value.custom_values.mcp_burst, local.defaults.apic.access_policies.switch_policies.copp_leaf.custom_values.mcp_burst) + nd_rate = try(each.value.custom_values.nd_rate, local.defaults.apic.access_policies.switch_policies.copp_leaf.custom_values.nd_rate) + nd_burst = try(each.value.custom_values.nd_burst, local.defaults.apic.access_policies.switch_policies.copp_leaf.custom_values.nd_burst) + ospf_rate = try(each.value.custom_values.ospf_rate, local.defaults.apic.access_policies.switch_policies.copp_leaf.custom_values.ospf_rate) + ospf_burst = try(each.value.custom_values.ospf_burst, local.defaults.apic.access_policies.switch_policies.copp_leaf.custom_values.ospf_burst) + permit_log_rate = try(each.value.custom_values.permit_log_rate, local.defaults.apic.access_policies.switch_policies.copp_leaf.custom_values.permit_log_rate) + permit_log_burst = try(each.value.custom_values.permit_log_burst, local.defaults.apic.access_policies.switch_policies.copp_leaf.custom_values.permit_log_burst) + pim_rate = try(each.value.custom_values.pim_rate, local.defaults.apic.access_policies.switch_policies.copp_leaf.custom_values.pim_rate) + pim_burst = try(each.value.custom_values.pim_burst, local.defaults.apic.access_policies.switch_policies.copp_leaf.custom_values.pim_burst) + stp_rate = try(each.value.custom_values.stp_rate, local.defaults.apic.access_policies.switch_policies.copp_leaf.custom_values.stp_rate) + stp_burst = try(each.value.custom_values.stp_burst, local.defaults.apic.access_policies.switch_policies.copp_leaf.custom_values.stp_burst) + tor_glean_rate = try(each.value.custom_values.tor_glean_rate, local.defaults.apic.access_policies.switch_policies.copp_leaf.custom_values.tor_glean_rate) + tor_glean_burst = try(each.value.custom_values.tor_glean_burst, local.defaults.apic.access_policies.switch_policies.copp_leaf.custom_values.tor_glean_burst) + traceroute_rate = try(each.value.custom_values.traceroute_rate, local.defaults.apic.access_policies.switch_policies.copp_leaf.custom_values.traceroute_rate) + traceroute_burst = try(each.value.custom_values.traceroute_burst, local.defaults.apic.access_policies.switch_policies.copp_leaf.custom_values.traceroute_burst) + } +} + +module "aci_access_spine_copp_policy" { + source = "./modules/terraform-aci-access-spine-copp-policy" + + for_each = { for pol in try(local.access_policies.spine_copp_policies, []) : pol.name => pol if local.modules.aci_access_spine_copp_policy && var.manage_access_policies } + name = "${each.value.name}${local.defaults.apic.access_policies.switch_policies.copp_spine.name_suffix}" + description = try(each.value.description, "") + type = try(each.value.type, local.defaults.apic.access_policies.switch_policies.copp_spine.type) + custom_values = { + arp_rate = try(each.value.custom_values.arp_rate, local.defaults.apic.access_policies.switch_policies.copp_spine.custom_values.arp_rate) + arp_burst = try(each.value.custom_values.arp_burst, local.defaults.apic.access_policies.switch_policies.copp_spine.custom_values.arp_burst) + bgp_rate = try(each.value.custom_values.bgp_rate, local.defaults.apic.access_policies.switch_policies.copp_spine.custom_values.bgp_rate) + bgp_burst = try(each.value.custom_values.bgp_burst, local.defaults.apic.access_policies.switch_policies.copp_spine.custom_values.bgp_burst) + cdp_rate = try(each.value.custom_values.cdp_rate, local.defaults.apic.access_policies.switch_policies.copp_spine.custom_values.cdp_rate) + cdp_burst = try(each.value.custom_values.cdp_burst, local.defaults.apic.access_policies.switch_policies.copp_spine.custom_values.cdp_burst) + coop_rate = try(each.value.custom_values.coop_rate, local.defaults.apic.access_policies.switch_policies.copp_spine.custom_values.coop_rate) + coop_burst = try(each.value.custom_values.coop_burst, local.defaults.apic.access_policies.switch_policies.copp_spine.custom_values.coop_burst) + dhcp_rate = try(each.value.custom_values.dhcp_rate, local.defaults.apic.access_policies.switch_policies.copp_spine.custom_values.dhcp_rate) + dhcp_burst = try(each.value.custom_values.dhcp_burst, local.defaults.apic.access_policies.switch_policies.copp_spine.custom_values.dhcp_burst) + glean_rate = try(each.value.custom_values.glean_rate, local.defaults.apic.access_policies.switch_policies.copp_spine.custom_values.glean_rate) + glean_burst = try(each.value.custom_values.glean_burst, local.defaults.apic.access_policies.switch_policies.copp_spine.custom_values.glean_burst) + ifc_rate = try(each.value.custom_values.ifc_rate, local.defaults.apic.access_policies.switch_policies.copp_spine.custom_values.ifc_rate) + ifc_burst = try(each.value.custom_values.ifc_burst, local.defaults.apic.access_policies.switch_policies.copp_spine.custom_values.ifc_burst) + ifc_other_rate = try(each.value.custom_values.ifc_other_rate, local.defaults.apic.access_policies.switch_policies.copp_spine.custom_values.ifc_other_rate) + ifc_other_burst = try(each.value.custom_values.ifc_other_burst, local.defaults.apic.access_policies.switch_policies.copp_spine.custom_values.ifc_other_burst) + ifc_span_rate = try(each.value.custom_values.ifc_span_rate, local.defaults.apic.access_policies.switch_policies.copp_spine.custom_values.ifc_span_rate) + ifc_span_burst = try(each.value.custom_values.ifc_span_burst, local.defaults.apic.access_policies.switch_policies.copp_spine.custom_values.ifc_span_burst) + igmp_rate = try(each.value.custom_values.igmp_rate, local.defaults.apic.access_policies.switch_policies.copp_spine.custom_values.igmp_rate) + igmp_burst = try(each.value.custom_values.igmp_burst, local.defaults.apic.access_policies.switch_policies.copp_spine.custom_values.igmp_burst) + infra_arp_rate = try(each.value.custom_values.infra_arp_rate, local.defaults.apic.access_policies.switch_policies.copp_spine.custom_values.infra_arp_rate) + infra_arp_burst = try(each.value.custom_values.infra_arp_burst, local.defaults.apic.access_policies.switch_policies.copp_spine.custom_values.infra_arp_burst) + isis_rate = try(each.value.custom_values.isis_rate, local.defaults.apic.access_policies.switch_policies.copp_spine.custom_values.isis_rate) + isis_burst = try(each.value.custom_values.isis_burst, local.defaults.apic.access_policies.switch_policies.copp_spine.custom_values.isis_burst) + lldp_rate = try(each.value.custom_values.lldp_rate, local.defaults.apic.access_policies.switch_policies.copp_spine.custom_values.lldp_rate) + lldp_burst = try(each.value.custom_values.lldp_burst, local.defaults.apic.access_policies.switch_policies.copp_spine.custom_values.lldp_burst) + ospf_rate = try(each.value.custom_values.ospf_rate, local.defaults.apic.access_policies.switch_policies.copp_spine.custom_values.ospf_rate) + ospf_burst = try(each.value.custom_values.ospf_burst, local.defaults.apic.access_policies.switch_policies.copp_spine.custom_values.ospf_burst) + tor_glean_rate = try(each.value.custom_values.tor_glean_rate, local.defaults.apic.access_policies.switch_policies.copp_spine.custom_values.tor_glean_rate) + tor_glean_burst = try(each.value.custom_values.tor_glean_burst, local.defaults.apic.access_policies.switch_policies.copp_spine.custom_values.tor_glean_burst) + traceroute_rate = try(each.value.custom_values.traceroute_rate, local.defaults.apic.access_policies.switch_policies.copp_spine.custom_values.traceroute_rate) + traceroute_burst = try(each.value.custom_values.traceroute_burst, local.defaults.apic.access_policies.switch_policies.copp_spine.custom_values.traceroute_burst) + } } \ No newline at end of file diff --git a/defaults/defaults.yaml b/defaults/defaults.yaml index 541a7a6c..9f1be0e1 100644 --- a/defaults/defaults.yaml +++ b/defaults/defaults.yaml @@ -441,6 +441,96 @@ defaults: dhcp_relay_policies: name_suffix: "" switch_policies: + copp_leaf: + name_suffix: "" + type: default + custom_values: + acl_log_rate: default + acl_log_burst: default + arp_rate: default + arp_burst: default + bgp_rate: default + bgp_burst: default + cdp_rate: default + cdp_burst: default + coop_rate: default + coop_burst: default + dhcp_rate: default + dhcp_burst: default + eigrp_rate: default + eigrp_burst: default + glean_rate: default + glean_burst: default + icmp_rate: default + icmp_burst: default + ifc_rate: default + ifc_burst: default + ifc_other_rate: default + ifc_other_burst: default + ifc_span_rate: default + ifc_span_burst: default + igmp_rate: default + igmp_burst: default + infra_arp_rate: default + infra_arp_burst: default + isis_rate: default + isis_burst: default + lacp_rate: default + lacp_burst: default + lldp_rate: default + lldp_burst: default + mcp_rate: default + mcp_burst: default + nd_rate: default + nd_burst: default + ospf_rate: default + ospf_burst: default + permit_log_rate: default + permit_log_burst: default + pim_rate: default + pim_burst: default + stp_rate: default + stp_burst: default + tor_glean_rate: default + tor_glean_burst: default + traceroute_rate: default + traceroute_burst: default + copp_spine: + name_suffix: "" + type: default + custom_values: + arp_rate: default + arp_burst: default + bgp_rate: default + bgp_burst: default + cdp_rate: default + cdp_burst: default + coop_rate: default + coop_burst: default + dhcp_rate: default + dhcp_burst: default + glean_rate: default + glean_burst: default + ifc_rate: default + ifc_burst: default + ifc_other_rate: default + ifc_other_burst: default + ifc_span_rate: default + ifc_span_burst: default + igmp_rate: default + igmp_burst: default + infra_arp_rate: default + infra_arp_burst: default + isis_rate: default + isis_burst: default + lldp_rate: default + lldp_burst: default + ospf_rate: default + ospf_burst: default + tor_glean_rate: default + tor_glean_burst: default + traceroute_rate: default + traceroute_burst: default vpc_policies: name_suffix: "" peer_dead_interval: 200 @@ -482,6 +572,11 @@ defaults: node_blocks: name_suffix: "" interface_policies: + copp_policies: + name_suffix: "" + rate: 10 + burst: 10 + match_protocols: "" cdp_policies: name_suffix: "" lldp_policies: diff --git a/defaults/modules.yaml b/defaults/modules.yaml index 47a1d357..fe5a83e6 100644 --- a/defaults/modules.yaml +++ b/defaults/modules.yaml @@ -4,6 +4,7 @@ modules: aci_aaep: true aci_access_fex_interface_profile: true aci_access_fex_interface_selector: true + aci_access_leaf_copp_policy: true aci_access_leaf_interface_policy_group: true aci_access_leaf_interface_profile: true aci_access_leaf_interface_selector: true @@ -12,6 +13,7 @@ modules: aci_access_span_destination_group: true aci_access_span_filter_group: true aci_access_span_source_group: true + aci_access_spine_copp_policy: true aci_access_spine_interface_policy_group: true aci_access_spine_interface_profile: true aci_access_spine_interface_selector: true @@ -36,6 +38,7 @@ modules: aci_config_passphrase: true aci_contract: true aci_coop_policy: true + aci_copp_interface_policy: true aci_date_time_format: true aci_date_time_policy: true aci_device_selection_policy: true diff --git a/modules/terraform-aci-access-leaf-copp-policy/.terraform-docs.yml b/modules/terraform-aci-access-leaf-copp-policy/.terraform-docs.yml new file mode 100644 index 00000000..33061f71 --- /dev/null +++ b/modules/terraform-aci-access-leaf-copp-policy/.terraform-docs.yml @@ -0,0 +1,34 @@ +version: '>= 0.14.0' + +formatter: markdown table + +content: |- + # Terraform ACI Access Leaf CoPP Policy Module + + Manages ACI Access Leaf CoPP Policy + + Location in GUI: + `Fabric` » `Access Policies` » `Policies` » `Switch` » `CoPP Leaf` + + ## Examples + + ```hcl + {{ include "./examples/complete/main.tf" }} + ``` + + {{ .Requirements }} + + {{ .Providers }} + + {{ .Inputs }} + + {{ .Outputs }} + + {{ .Resources }} + +output: + file: README.md + mode: replace + +sort: + enabled: false diff --git a/modules/terraform-aci-access-leaf-copp-policy/README.md b/modules/terraform-aci-access-leaf-copp-policy/README.md new file mode 100644 index 00000000..5a677fc5 --- /dev/null +++ b/modules/terraform-aci-access-leaf-copp-policy/README.md @@ -0,0 +1,61 @@ + +# Terraform ACI Access Leaf CoPP Policy Module + +Manages ACI Access Leaf CoPP Policy + +Location in GUI: +`Fabric` » `Access Policies` » `Policies` » `Switch` » `CoPP Leaf` + +## Examples + +```hcl +module "aci_access_leaf_copp_policy" { + source = "netascode/nac-aci/aci//modules/terraform-aci-access-leaf-copp-policy" + version = ">= 0.8.0" + + name = "POL1" + description = "POL1" + type = "custom" + custom_values = { + arp_rate = 1234 + arp_burst = 300 + acl_log_rate = 150 + acl_log_burst = 300 + } +} +``` + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.0.0 | +| [aci](#requirement\_aci) | >= 2.0.0 | + +## Providers + +| Name | Version | +|------|---------| +| [aci](#provider\_aci) | >= 2.0.0 | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [name](#input\_name) | Attachable access entity profile name. | `string` | n/a | yes | +| [description](#input\_description) | Attachable access entity profile description | `string` | `""` | no | +| [type](#input\_type) | Profile type. Allowed values: `default`, `custom`, `strict`, `moderate`, `lenient`. | `string` | `"default"` | no | +| [custom\_values](#input\_custom\_values) | Custom CoPP values | `any` | n/a | yes | + +## Outputs + +| Name | Description | +|------|-------------| +| [dn](#output\_dn) | Distinguished name of `coppLeafProfile` object. | + +## Resources + +| Name | Type | +|------|------| +| [aci_rest_managed.coppLeafProfile](https://registry.terraform.io/providers/CiscoDevNet/aci/latest/docs/resources/rest_managed) | resource | + \ No newline at end of file diff --git a/modules/terraform-aci-access-leaf-copp-policy/examples/complete/.terraform-docs.yml b/modules/terraform-aci-access-leaf-copp-policy/examples/complete/.terraform-docs.yml new file mode 100644 index 00000000..7570b1f6 --- /dev/null +++ b/modules/terraform-aci-access-leaf-copp-policy/examples/complete/.terraform-docs.yml @@ -0,0 +1,24 @@ +version: '>= 0.14.0' + +formatter: markdown table + +content: |- + # Access Leaf CoPP Policy Example + + To run this example you need to execute: + + ```bash + $ terraform init + $ terraform plan + $ terraform apply + ``` + + Note that this example will create resources. Resources can be destroyed with `terraform destroy`. + + ```hcl + {{ include "./main.tf" }} + ``` + +output: + file: README.md + mode: replace diff --git a/modules/terraform-aci-access-leaf-copp-policy/examples/complete/README.md b/modules/terraform-aci-access-leaf-copp-policy/examples/complete/README.md new file mode 100644 index 00000000..0787cb60 --- /dev/null +++ b/modules/terraform-aci-access-leaf-copp-policy/examples/complete/README.md @@ -0,0 +1,30 @@ + +# Access Leaf CoPP Policy Example + +To run this example you need to execute: + +```bash +$ terraform init +$ terraform plan +$ terraform apply +``` + +Note that this example will create resources. Resources can be destroyed with `terraform destroy`. + +```hcl +module "aci_access_leaf_copp_policy" { + source = "netascode/nac-aci/aci//modules/terraform-aci-access-leaf-copp-policy" + version = ">= 0.8.0" + + name = "POL1" + description = "POL1" + type = "custom" + custom_values = { + arp_rate = 1234 + arp_burst = 300 + acl_log_rate = 150 + acl_log_burst = 300 + } +} +``` + \ No newline at end of file diff --git a/modules/terraform-aci-access-leaf-copp-policy/examples/complete/main.tf b/modules/terraform-aci-access-leaf-copp-policy/examples/complete/main.tf new file mode 100644 index 00000000..68058aa0 --- /dev/null +++ b/modules/terraform-aci-access-leaf-copp-policy/examples/complete/main.tf @@ -0,0 +1,14 @@ +module "aci_access_leaf_copp_policy" { + source = "netascode/nac-aci/aci//modules/terraform-aci-access-leaf-copp-policy" + version = ">= 0.8.0" + + name = "POL1" + description = "POL1" + type = "custom" + custom_values = { + arp_rate = 1234 + arp_burst = 300 + acl_log_rate = 150 + acl_log_burst = 300 + } +} \ No newline at end of file diff --git a/modules/terraform-aci-access-leaf-copp-policy/examples/complete/versions.tf b/modules/terraform-aci-access-leaf-copp-policy/examples/complete/versions.tf new file mode 100644 index 00000000..e8b775ae --- /dev/null +++ b/modules/terraform-aci-access-leaf-copp-policy/examples/complete/versions.tf @@ -0,0 +1,11 @@ + +terraform { + required_version = ">= 1.0.0" + + required_providers { + aci = { + source = "CiscoDevNet/aci" + version = ">= 2.0.0" + } + } +} diff --git a/modules/terraform-aci-access-leaf-copp-policy/main.tf b/modules/terraform-aci-access-leaf-copp-policy/main.tf new file mode 100644 index 00000000..044ccf5e --- /dev/null +++ b/modules/terraform-aci-access-leaf-copp-policy/main.tf @@ -0,0 +1,72 @@ + +resource "aci_rest_managed" "coppLeafProfile" { + dn = "uni/infra/coppleafp-${var.name}" + class_name = "coppLeafProfile" + + content = { + name = var.name + descr = var.description + type = var.type + } + + dynamic "child" { + for_each = var.type == "custom" ? [0] : [] + content { + class_name = "coppLeafGen1CustomValues" + rn = "leafgen1customvalues" + content = { + dn = "uni/infra/coppleafp-${var.name}/leafgen1customvalues" + acllogRate = var.custom_values.acl_log_rate == "default" ? 500 : var.custom_values.acl_log_rate + acllogBurst = var.custom_values.acl_log_burst == "default" ? 500 : var.custom_values.acl_log_burst + arpRate = var.custom_values.arp_rate == "default" ? 1360 : var.custom_values.arp_rate + arpBurst = var.custom_values.arp_burst == "default" ? 340 : var.custom_values.arp_burst + bgpRate = var.custom_values.bgp_rate == "default" ? 5000 : var.custom_values.bgp_rate + bgpBurst = var.custom_values.bgp_burst == "default" ? 5000 : var.custom_values.bgp_burst + cdpRate = var.custom_values.cdp_rate == "default" ? 1000 : var.custom_values.cdp_rate + cdpBurst = var.custom_values.cdp_burst == "default" ? 1000 : var.custom_values.cdp_burst + coopRate = var.custom_values.coop_rate == "default" ? 5000 : var.custom_values.coop_rate + coopBurst = var.custom_values.coop_burst == "default" ? 5000 : var.custom_values.coop_burst + dhcpRate = var.custom_values.dhcp_rate == "default" ? 1360 : var.custom_values.dhcp_rate + dhcpBurst = var.custom_values.dhcp_burst == "default" ? 340 : var.custom_values.dhcp_burst + eigrpRate = var.custom_values.eigrp_rate == "default" ? 2000 : var.custom_values.eigrp_rate + eigrpBurst = var.custom_values.eigrp_burst == "default" ? 2000 : var.custom_values.eigrp_burst + gleanRate = var.custom_values.glean_rate == "default" ? 100 : var.custom_values.glean_rate + gleanBurst = var.custom_values.glean_burst == "default" ? 100 : var.custom_values.glean_burst + icmpRate = var.custom_values.icmp_rate == "default" ? 500 : var.custom_values.icmp_rate + icmpBurst = var.custom_values.icmp_burst == "default" ? 500 : var.custom_values.icmp_burst + ifcRate = var.custom_values.ifc_rate == "default" ? 10000 : var.custom_values.ifc_rate + ifcBurst = var.custom_values.ifc_burst == "default" ? 10000 : var.custom_values.ifc_burst + ifcOtherRate = var.custom_values.ifc_other_rate == "default" ? 332800 : var.custom_values.ifc_other_rate + ifcOtherBurst = var.custom_values.ifc_other_burst == "default" ? 5000 : var.custom_values.ifc_other_burst + ifcSpanRate = var.custom_values.ifc_span_rate == "default" ? 2000 : var.custom_values.ifc_span_rate + ifcSpanBurst = var.custom_values.ifc_span_burst == "default" ? 2000 : var.custom_values.ifc_span_burst + igmpRate = var.custom_values.igmp_rate == "default" ? 1500 : var.custom_values.igmp_rate + igmpBurst = var.custom_values.igmp_burst == "default" ? 1500 : var.custom_values.igmp_burst + infraArpRate = var.custom_values.infra_arp_rate == "default" ? 300 : var.custom_values.infra_arp_rate + infraArpBurst = var.custom_values.infra_arp_burst == "default" ? 300 : var.custom_values.infra_arp_burst + isisRate = var.custom_values.isis_rate == "default" ? 1500 : var.custom_values.isis_rate + isisBurst = var.custom_values.isis_burst == "default" ? 5000 : var.custom_values.isis_burst + lacpRate = var.custom_values.lacp_rate == "default" ? 1000 : var.custom_values.lacp_rate + lacpBurst = var.custom_values.lacp_burst == "default" ? 1000 : var.custom_values.lacp_burst + lldpRate = var.custom_values.lldp_rate == "default" ? 1000 : var.custom_values.lldp_rate + lldpBurst = var.custom_values.lldp_burst == "default" ? 1000 : var.custom_values.lldp_burst + mcpRate = var.custom_values.mcp_rate == "default" ? 1500 : var.custom_values.mcp_rate + mcpBurst = var.custom_values.mcp_burst == "default" ? 1500 : var.custom_values.mcp_burst + ndRate = var.custom_values.nd_rate == "default" ? 1000 : var.custom_values.nd_rate + ndBurst = var.custom_values.nd_burst == "default" ? 1000 : var.custom_values.nd_burst + ospfRate = var.custom_values.ospf_rate == "default" ? 2000 : var.custom_values.ospf_rate + ospfBurst = var.custom_values.ospf_burst == "default" ? 2000 : var.custom_values.ospf_burst + permitlogRate = var.custom_values.permit_log_rate == "default" ? 300 : var.custom_values.permit_log_rate + permitlogBurst = var.custom_values.permit_log_burst == "default" ? 300 : var.custom_values.permit_log_burst + pimRate = var.custom_values.pim_rate == "default" ? 500 : var.custom_values.pim_rate + pimBurst = var.custom_values.pim_burst == "default" ? 500 : var.custom_values.pim_burst + stpRate = var.custom_values.stp_rate == "default" ? 1000 : var.custom_values.stp_rate + stpBurst = var.custom_values.stp_burst == "default" ? 1000 : var.custom_values.stp_burst + torGleanRate = var.custom_values.tor_glean_rate == "default" ? 100 : var.custom_values.tor_glean_rate + torGleanBurst = var.custom_values.tor_glean_burst == "default" ? 100 : var.custom_values.tor_glean_burst + tracerouteRate = var.custom_values.traceroute_rate == "default" ? 500 : var.custom_values.traceroute_rate + tracerouteBurst = var.custom_values.traceroute_burst == "default" ? 500 : var.custom_values.traceroute_burst + } + } + } +} diff --git a/modules/terraform-aci-access-leaf-copp-policy/outputs.tf b/modules/terraform-aci-access-leaf-copp-policy/outputs.tf new file mode 100644 index 00000000..22a70b1b --- /dev/null +++ b/modules/terraform-aci-access-leaf-copp-policy/outputs.tf @@ -0,0 +1,4 @@ +output "dn" { + value = aci_rest_managed.coppLeafProfile.id + description = "Distinguished name of `coppLeafProfile` object." +} \ No newline at end of file diff --git a/modules/terraform-aci-access-leaf-copp-policy/variables.tf b/modules/terraform-aci-access-leaf-copp-policy/variables.tf new file mode 100644 index 00000000..b5277ae6 --- /dev/null +++ b/modules/terraform-aci-access-leaf-copp-policy/variables.tf @@ -0,0 +1,287 @@ +variable "name" { + description = "Attachable access entity profile name." + type = string + + validation { + condition = can(regex("^[a-zA-Z0-9_.:-]{0,64}$", var.name)) + error_message = "Allowed characters: `a`-`z`, `A`-`Z`, `0`-`9`, `_`, `.`, `:`, `-`. Maximum characters: 64." + } +} + +variable "description" { + description = "Attachable access entity profile description" + type = string + default = "" + + validation { + condition = can(regex("^[a-zA-Z0-9\\!#$%()*,-./:;@ _{|}~?&+]{0,128}$", var.description)) + error_message = "Allowed characters: `a`-`z`, `A`-`Z`, `0`-`9`, `\\`, `!`, `#`, `$`, `%`, `(`, `)`, `*`, `,`, `-`, `.`, `/`, `:`, `;`, `@`, ` `, `_`, `{`, `|`, }`, `~`, `?`, `&`, `+`. Maximum characters: 128." + } +} + +variable "type" { + description = "Profile type. Allowed values: `default`, `custom`, `strict`, `moderate`, `lenient`." + type = string + default = "default" + + validation { + condition = contains(["default", "custom", "strict", "moderate", "lenient"], var.type) + error_message = "Allowed values: `default`, `custom`, `strict`, `moderate`, `lenient`." + } +} + +variable "custom_values" { + description = "Custom CoPP values" + type = any + + validation { + condition = try(var.custom_values.acl_log_rate == "default" || try(tonumber(var.custom_values.acl_log_rate) >= 10 && tonumber(var.custom_values.acl_log_rate) <= 500, false), var.custom_values.acl_log_rate) + error_message = "Allowed Values: `default` or a number between 10 and 500." + } + + validation { + condition = try(var.custom_values.acl_log_burst == "default" || try(tonumber(var.custom_values.acl_log_burst) >= 10 && tonumber(var.custom_values.acl_log_burst) <= 500, false), var.custom_values.acl_log_burst) + error_message = "Allowed Values: `default` or a number between 10 and 500." + } + + validation { + condition = try(var.custom_values.arp_rate == "default" || try(tonumber(var.custom_values.arp_rate) >= 10 && tonumber(var.custom_values.arp_rate) <= 1360, false), var.custom_values.arp_rate) + error_message = "Allowed Values: `default` or a number between 10 and 1360." + } + + validation { + condition = try(var.custom_values.arp_burst == "default" || try(tonumber(var.custom_values.arp_burst) >= 10 && tonumber(var.custom_values.arp_burst) <= 340, false), var.custom_values.arp_burst) + error_message = "Allowed Values: `default` or a number between 10 and 340." + } + + validation { + condition = try(var.custom_values.bgp_rate == "default" || try(tonumber(var.custom_values.bgp_rate) >= 10 && tonumber(var.custom_values.bgp_rate) <= 5000, false), var.custom_values.bgp_rate) + error_message = "Allowed Values: `default` or a number between 10 and 5000." + } + + validation { + condition = try(var.custom_values.bgp_burst == "default" || try(tonumber(var.custom_values.bgp_burst) >= 10 && tonumber(var.custom_values.bgp_burst) <= 5000, false), var.custom_values.bgp_burst) + error_message = "Allowed Values: `default` or a number between 10 and 5000." + } + + validation { + condition = try(var.custom_values.cdp_rate == "default" || try(tonumber(var.custom_values.cdp_rate) >= 10 && tonumber(var.custom_values.cdp_rate) <= 1000, false), var.custom_values.cdp_rate) + error_message = "Allowed Values: `default` or a number between 10 and 1000." + } + + validation { + condition = try(var.custom_values.cdp_burst == "default" || try(tonumber(var.custom_values.cdp_burst) >= 10 && tonumber(var.custom_values.cdp_burst) <= 1000, false), var.custom_values.cdp_burst) + error_message = "Allowed Values: `default` or a number between 10 and 1000." + } + + validation { + condition = try(var.custom_values.coop_rate == "default" || try(tonumber(var.custom_values.coop_rate) >= 1000 && tonumber(var.custom_values.coop_rate) <= 5000, false), var.custom_values.coop_rate) + error_message = "Allowed Values: `default` or a number between 1000 and 5000." + } + + validation { + condition = try(var.custom_values.coop_burst == "default" || try(tonumber(var.custom_values.coop_burst) >= 1000 && tonumber(var.custom_values.coop_burst) <= 5000, false), var.custom_values.coop_burst) + error_message = "Allowed Values: `default` or a number between 1000 and 5000." + } + + validation { + condition = try(var.custom_values.dhcp_rate == "default" || try(tonumber(var.custom_values.dhcp_rate) >= 100 && tonumber(var.custom_values.dhcp_rate) <= 1360, false), var.custom_values.dhcp_rate) + error_message = "Allowed Values: `default` or a number between 100 and 1360." + } + + validation { + condition = try(var.custom_values.dhcp_burst == "default" || try(tonumber(var.custom_values.dhcp_burst) >= 100 && tonumber(var.custom_values.dhcp_burst) <= 340, false), var.custom_values.dhcp_burst) + error_message = "Allowed Values: `default` or a number between 100 and 340." + } + + validation { + condition = try(var.custom_values.eigrp_rate == "default" || try(tonumber(var.custom_values.eigrp_rate) >= 10 && tonumber(var.custom_values.eigrp_rate) <= 2000, false), var.custom_values.eigrp_rate) + error_message = "Allowed Values: `default` or a number between 10 and 2000." + } + + validation { + condition = try(var.custom_values.eigrp_burst == "default" || try(tonumber(var.custom_values.eigrp_burst) >= 10 && tonumber(var.custom_values.eigrp_burst) <= 2000, false), var.custom_values.eigrp_burst) + error_message = "Allowed Values: `default` or a number between 10 and 2000." + } + + validation { + condition = try(var.custom_values.glean_rate == "default" || try(tonumber(var.custom_values.glean_rate) >= 10 && tonumber(var.custom_values.glean_rate) <= 500, false), var.custom_values.glean_rate) + error_message = "Allowed Values: `default` or a number between 10 and 500." + } + + validation { + condition = try(var.custom_values.glean_burst == "default" || try(tonumber(var.custom_values.glean_burst) >= 10 && tonumber(var.custom_values.glean_burst) <= 500, false), var.custom_values.glean_burst) + error_message = "Allowed Values: `default` or a number between 10 and 500." + } + + validation { + condition = try(var.custom_values.icmp_rate == "default" || try(tonumber(var.custom_values.icmp_rate) >= 10 && tonumber(var.custom_values.icmp_rate) <= 500, false), var.custom_values.icmp_rate) + error_message = "Allowed Values: `default` or a number between 10 and 500." + } + + validation { + condition = try(var.custom_values.icmp_burst == "default" || try(tonumber(var.custom_values.icmp_burst) >= 10 && tonumber(var.custom_values.icmp_burst) <= 500, false), var.custom_values.icmp_burst) + error_message = "Allowed Values: `default` or a number between 10 and 500." + } + + validation { + condition = try(var.custom_values.ifc_rate == "default" || try(tonumber(var.custom_values.ifc_rate) == 10000, false), var.custom_values.ifc_rate) + error_message = "Allowed Values: `default` or the number 10000." + } + + validation { + condition = try(var.custom_values.ifc_burst == "default" || try(tonumber(var.custom_values.ifc_burst) == 10000, false), var.custom_values.ifc_burst) + error_message = "Allowed Values: `default` or the number 10000." + } + + validation { + condition = try(var.custom_values.ifc_other_rate == "default" || try(tonumber(var.custom_values.ifc_other_rate) >= 5000 && tonumber(var.custom_values.ifc_other_rate) <= 32800, false), var.custom_values.ifc_other_rate) + error_message = "Allowed Values: `default` or a number between 5000 and 32800." + } + + validation { + condition = try(var.custom_values.ifc_other_burst == "default" || try(tonumber(var.custom_values.ifc_other_burst) == 5000, false), var.custom_values.ifc_other_burst) + error_message = "Allowed Values: `default` or the number 5000." + } + + validation { + condition = try(var.custom_values.ifc_span_rate == "default" || try(tonumber(var.custom_values.ifc_span_rate) >= 10 && tonumber(var.custom_values.ifc_span_rate) <= 2000, false), var.custom_values.ifc_span_rate) + error_message = "Allowed Values: `default` or a number between 10 and 2000." + } + + validation { + condition = try(var.custom_values.ifc_span_burst == "default" || try(tonumber(var.custom_values.ifc_span_burst) >= 10 && tonumber(var.custom_values.ifc_span_burst) <= 2000, false), var.custom_values.ifc_span_burst) + error_message = "Allowed Values: `default` or a number between 10 and 2000." + } + + validation { + condition = try(var.custom_values.igmp_rate == "default" || try(tonumber(var.custom_values.igmp_rate) >= 10 && tonumber(var.custom_values.igmp_rate) <= 1500, false), var.custom_values.igmp_rate) + error_message = "Allowed Values: `default` or a number between 10 and 1500." + } + + validation { + condition = try(var.custom_values.igmp_burst == "default" || try(tonumber(var.custom_values.igmp_burst) >= 10 && tonumber(var.custom_values.igmp_burst) <= 1500, false), var.custom_values.igmp_burst) + error_message = "Allowed Values: `default` or a number between 10 and 1500." + } + + validation { + condition = try(var.custom_values.infra_arp_rate == "default" || try(tonumber(var.custom_values.infra_arp_rate) >= 50 && tonumber(var.custom_values.infra_arp_rate) <= 300, false), var.custom_values.infra_arp_rate) + error_message = "Allowed Values: `default` or a number between 50 and 300." + } + + validation { + condition = try(var.custom_values.infra_arp_burst == "default" || try(tonumber(var.custom_values.infra_arp_burst) >= 50 && tonumber(var.custom_values.infra_arp_burst) <= 300, false), var.custom_values.infra_arp_burst) + error_message = "Allowed Values: `default` or a number between 50 and 300." + } + + validation { + condition = try(var.custom_values.isis_rate == "default" || try(tonumber(var.custom_values.isis_rate) >= 100 && tonumber(var.custom_values.isis_rate) <= 1500, false), var.custom_values.isis_rate) + error_message = "Allowed Values: `default` or a number between 100 and 1500." + } + + validation { + condition = try(var.custom_values.isis_burst == "default" || try(tonumber(var.custom_values.isis_burst) >= 100 && tonumber(var.custom_values.isis_burst) <= 5000, false), var.custom_values.isis_burst) + error_message = "Allowed Values: `default` or a number between 100 and 5000." + } + + validation { + condition = try(var.custom_values.lacp_rate == "default" || try(tonumber(var.custom_values.lacp_rate) >= 10 && tonumber(var.custom_values.lacp_rate) <= 1000, false), var.custom_values.lacp_rate) + error_message = "Allowed Values: `default` or a number between 10 and 1000." + } + + validation { + condition = try(var.custom_values.lacp_burst == "default" || try(tonumber(var.custom_values.lacp_burst) >= 10 && tonumber(var.custom_values.lacp_burst) <= 1000, false), var.custom_values.lacp_burst) + error_message = "Allowed Values: `default` or a number between 10 and 1000." + } + + validation { + condition = try(var.custom_values.lldp_rate == "default" || try(tonumber(var.custom_values.lldp_rate) >= 10 && tonumber(var.custom_values.lldp_rate) <= 1000, false), var.custom_values.lldp_rate) + error_message = "Allowed Values: `default` or a number between 10 and 1000." + } + + validation { + condition = try(var.custom_values.lldp_burst == "default" || try(tonumber(var.custom_values.lldp_burst) >= 10 && tonumber(var.custom_values.lldp_burst) <= 1000, false), var.custom_values.lldp_burst) + error_message = "Allowed Values: `default` or a number between 10 and 1000." + } + + validation { + condition = try(var.custom_values.mcp_rate == "default" || try(tonumber(var.custom_values.mcp_rate) >= 10 && tonumber(var.custom_values.mcp_rate) <= 5000, false), var.custom_values.mcp_rate) + error_message = "Allowed Values: `default` or a number between 10 and 5000." + } + + validation { + condition = try(var.custom_values.mcp_burst == "default" || try(tonumber(var.custom_values.mcp_burst) >= 10 && tonumber(var.custom_values.mcp_burst) <= 5000, false), var.custom_values.mcp_burst) + error_message = "Allowed Values: `default` or a number between 10 and 5000." + } + + validation { + condition = try(var.custom_values.nd_rate == "default" || try(tonumber(var.custom_values.nd_rate) >= 10 && tonumber(var.custom_values.nd_rate) <= 1000, false), var.custom_values.nd_rate) + error_message = "Allowed Values: `default` or a number between 10 and 1000." + } + + validation { + condition = try(var.custom_values.nd_burst == "default" || try(tonumber(var.custom_values.nd_burst) >= 10 && tonumber(var.custom_values.nd_burst) <= 1000, false), var.custom_values.nd_burst) + error_message = "Allowed Values: `default` or a number between 10 and 1000." + } + + validation { + condition = try(var.custom_values.ospf_rate == "default" || try(tonumber(var.custom_values.ospf_rate) >= 10 && tonumber(var.custom_values.ospf_rate) <= 2000, false), var.custom_values.ospf_rate) + error_message = "Allowed Values: `default` or a number between 10 and 2000." + } + + validation { + condition = try(var.custom_values.ospf_burst == "default" || try(tonumber(var.custom_values.ospf_burst) >= 10 && tonumber(var.custom_values.ospf_burst) <= 2000, false), var.custom_values.ospf_burst) + error_message = "Allowed Values: `default` or a number between 10 and 2000." + } + + validation { + condition = try(var.custom_values.permit_log_rate == "default" || try(tonumber(var.custom_values.permit_log_rate) >= 10 && tonumber(var.custom_values.permit_log_rate) <= 300, false), var.custom_values.permit_log_rate) + error_message = "Allowed Values: `default` or a number between 10 and 300." + } + + validation { + condition = try(var.custom_values.permit_log_burst == "default" || try(tonumber(var.custom_values.permit_log_burst) >= 10 && tonumber(var.custom_values.permit_log_burst) <= 300, false), var.custom_values.permit_log_burst) + error_message = "Allowed Values: `default` or a number between 10 and 300." + } + + validation { + condition = try(var.custom_values.pim_rate == "default" || try(tonumber(var.custom_values.pim_rate) >= 10 && tonumber(var.custom_values.pim_rate) <= 500, false), var.custom_values.pim_rate) + error_message = "Allowed Values: `default` or a number between 10 and 500." + } + + validation { + condition = try(var.custom_values.pim_burst == "default" || try(tonumber(var.custom_values.pim_burst) >= 10 && tonumber(var.custom_values.pim_burst) <= 500, false), var.custom_values.pim_burst) + error_message = "Allowed Values: `default` or a number between 10 and 500." + } + + validation { + condition = try(var.custom_values.stp_rate == "default" || try(tonumber(var.custom_values.stp_rate) >= 10 && tonumber(var.custom_values.stp_rate) <= 1000, false), var.custom_values.stp_rate) + error_message = "Allowed Values: `default` or a number between 10 and 1000." + } + + validation { + condition = try(var.custom_values.stp_burst == "default" || try(tonumber(var.custom_values.stp_burst) >= 10 && tonumber(var.custom_values.stp_burst) <= 1000, false), var.custom_values.stp_burst) + error_message = "Allowed Values: `default` or a number between 10 and 1000." + } + + validation { + condition = try(var.custom_values.tor_glean_rate == "default" || try(tonumber(var.custom_values.tor_glean_rate) >= 10 && tonumber(var.custom_values.tor_glean_rate) <= 500, false), var.custom_values.tor_glean_rate) + error_message = "Allowed Values: `default` or a number between 10 and 500." + } + + validation { + condition = try(var.custom_values.tor_glean_burst == "default" || try(tonumber(var.custom_values.tor_glean_burst) >= 10 && tonumber(var.custom_values.tor_glean_burst) <= 500, false), var.custom_values.tor_glean_burst) + error_message = "Allowed Values: `default` or a number between 10 and 500." + } + + validation { + condition = try(var.custom_values.traceroute_rate == "default" || try(tonumber(var.custom_values.traceroute_rate) >= 10 && tonumber(var.custom_values.traceroute_rate) <= 500, false), var.custom_values.traceroute_rate) + error_message = "Allowed Values: `default` or a number between 10 and 500." + } + + validation { + condition = try(var.custom_values.traceroute_burst == "default" || try(tonumber(var.custom_values.traceroute_burst) >= 10 && tonumber(var.custom_values.traceroute_burst) <= 500, false), var.custom_values.traceroute_burst) + error_message = "Allowed Values: `default` or a number between 10 and 500." + } + +} diff --git a/modules/terraform-aci-access-leaf-copp-policy/versions.tf b/modules/terraform-aci-access-leaf-copp-policy/versions.tf new file mode 100644 index 00000000..e8b775ae --- /dev/null +++ b/modules/terraform-aci-access-leaf-copp-policy/versions.tf @@ -0,0 +1,11 @@ + +terraform { + required_version = ">= 1.0.0" + + required_providers { + aci = { + source = "CiscoDevNet/aci" + version = ">= 2.0.0" + } + } +} diff --git a/modules/terraform-aci-access-leaf-interface-policy-group/README.md b/modules/terraform-aci-access-leaf-interface-policy-group/README.md index 9518c40c..4038baa0 100644 --- a/modules/terraform-aci-access-leaf-interface-policy-group/README.md +++ b/modules/terraform-aci-access-leaf-interface-policy-group/README.md @@ -18,6 +18,7 @@ module "aci_access_leaf_interface_policy_group" { type = "vpc" link_level_policy = "10G" cdp_policy = "CDP-ON" + copp_policy = "COPP-POLICY" lldp_policy = "LLDP-OFF" spanning_tree_policy = "BPDU-GUARD" mcp_policy = "MCP-ON" @@ -52,6 +53,7 @@ module "aci_access_leaf_interface_policy_group" { | [map](#input\_map) | Breakout map. Only relevant if `type` is `breakout`. Choices: `none`, `10g-4x`, `25g-4x`, `100g-2x`, `50g-8x`, `100g-4x`. | `string` | `"none"` | no | | [link\_level\_policy](#input\_link\_level\_policy) | Link level policy name. | `string` | `""` | no | | [cdp\_policy](#input\_cdp\_policy) | CDP policy name. | `string` | `""` | no | +| [copp\_policy](#input\_copp\_policy) | CoPP policy name. | `string` | `""` | no | | [lldp\_policy](#input\_lldp\_policy) | LLDP policy name. | `string` | `""` | no | | [spanning\_tree\_policy](#input\_spanning\_tree\_policy) | Spanning tree policy name. | `string` | `""` | no | | [mcp\_policy](#input\_mcp\_policy) | MCP policy name. | `string` | `""` | no | @@ -77,6 +79,7 @@ module "aci_access_leaf_interface_policy_group" { | [aci_rest_managed.infraAccGrp](https://registry.terraform.io/providers/CiscoDevNet/aci/latest/docs/resources/rest_managed) | resource | | [aci_rest_managed.infraRsAttEntP](https://registry.terraform.io/providers/CiscoDevNet/aci/latest/docs/resources/rest_managed) | resource | | [aci_rest_managed.infraRsCdpIfPol](https://registry.terraform.io/providers/CiscoDevNet/aci/latest/docs/resources/rest_managed) | resource | +| [aci_rest_managed.infraRsCoppIfPol](https://registry.terraform.io/providers/CiscoDevNet/aci/latest/docs/resources/rest_managed) | resource | | [aci_rest_managed.infraRsHIfPol](https://registry.terraform.io/providers/CiscoDevNet/aci/latest/docs/resources/rest_managed) | resource | | [aci_rest_managed.infraRsL2IfPol](https://registry.terraform.io/providers/CiscoDevNet/aci/latest/docs/resources/rest_managed) | resource | | [aci_rest_managed.infraRsLacpInterfacePol](https://registry.terraform.io/providers/CiscoDevNet/aci/latest/docs/resources/rest_managed) | resource | diff --git a/modules/terraform-aci-access-leaf-interface-policy-group/examples/complete/README.md b/modules/terraform-aci-access-leaf-interface-policy-group/examples/complete/README.md index c1ccff1a..3fbcf775 100644 --- a/modules/terraform-aci-access-leaf-interface-policy-group/examples/complete/README.md +++ b/modules/terraform-aci-access-leaf-interface-policy-group/examples/complete/README.md @@ -21,6 +21,7 @@ module "aci_access_leaf_interface_policy_group" { type = "vpc" link_level_policy = "10G" cdp_policy = "CDP-ON" + copp_policy = "COPP-POLICY" lldp_policy = "LLDP-OFF" spanning_tree_policy = "BPDU-GUARD" mcp_policy = "MCP-ON" diff --git a/modules/terraform-aci-access-leaf-interface-policy-group/examples/complete/main.tf b/modules/terraform-aci-access-leaf-interface-policy-group/examples/complete/main.tf index 7703b81f..07c27ffb 100644 --- a/modules/terraform-aci-access-leaf-interface-policy-group/examples/complete/main.tf +++ b/modules/terraform-aci-access-leaf-interface-policy-group/examples/complete/main.tf @@ -7,6 +7,7 @@ module "aci_access_leaf_interface_policy_group" { type = "vpc" link_level_policy = "10G" cdp_policy = "CDP-ON" + copp_policy = "COPP-POLICY" lldp_policy = "LLDP-OFF" spanning_tree_policy = "BPDU-GUARD" mcp_policy = "MCP-ON" diff --git a/modules/terraform-aci-access-leaf-interface-policy-group/main.tf b/modules/terraform-aci-access-leaf-interface-policy-group/main.tf index 8e72488e..888c0482 100644 --- a/modules/terraform-aci-access-leaf-interface-policy-group/main.tf +++ b/modules/terraform-aci-access-leaf-interface-policy-group/main.tf @@ -27,6 +27,15 @@ resource "aci_rest_managed" "infraRsCdpIfPol" { } } +resource "aci_rest_managed" "infraRsCoppIfPol" { + count = var.type != "breakout" ? 1 : 0 + dn = "${aci_rest_managed.infraAccGrp.dn}/rscoppIfPol" + class_name = "infraRsCoppIfPol" + content = { + tnCoppIfPolName = var.copp_policy + } +} + resource "aci_rest_managed" "infraRsLldpIfPol" { count = var.type != "breakout" ? 1 : 0 dn = "${aci_rest_managed.infraAccGrp.dn}/rslldpIfPol" diff --git a/modules/terraform-aci-access-leaf-interface-policy-group/variables.tf b/modules/terraform-aci-access-leaf-interface-policy-group/variables.tf index 2cce957c..c39f7ebd 100644 --- a/modules/terraform-aci-access-leaf-interface-policy-group/variables.tf +++ b/modules/terraform-aci-access-leaf-interface-policy-group/variables.tf @@ -63,6 +63,17 @@ variable "cdp_policy" { } } +variable "copp_policy" { + description = "CoPP policy name." + type = string + default = "" + + validation { + condition = can(regex("^[a-zA-Z0-9_.:-]{0,64}$", var.copp_policy)) + error_message = "Allowed characters: `a`-`z`, `A`-`Z`, `0`-`9`, `_`, `.`, `:`, `-`. Maximum characters: 64." + } +} + variable "lldp_policy" { description = "LLDP policy name." type = string diff --git a/modules/terraform-aci-access-leaf-switch-policy-group/README.md b/modules/terraform-aci-access-leaf-switch-policy-group/README.md index 69a208e8..fc650c49 100644 --- a/modules/terraform-aci-access-leaf-switch-policy-group/README.md +++ b/modules/terraform-aci-access-leaf-switch-policy-group/README.md @@ -17,6 +17,7 @@ module "aci_access_leaf_switch_policy_group" { forwarding_scale_policy = "HIGH-DUAL-STACK" bfd_ipv4_policy = "BFD-IPV4-POLICY" bfd_ipv6_policy = "BFD-IPV6-POLICY" + copp_leaf_policy = "COPP-LEAF-POLICY" } ``` @@ -41,6 +42,7 @@ module "aci_access_leaf_switch_policy_group" { | [forwarding\_scale\_policy](#input\_forwarding\_scale\_policy) | Forwarding scale policy name. | `string` | `""` | no | | [bfd\_ipv4\_policy](#input\_bfd\_ipv4\_policy) | BFD IPv4 policy name. | `string` | `""` | no | | [bfd\_ipv6\_policy](#input\_bfd\_ipv6\_policy) | BFD IPv6 policy name. | `string` | `""` | no | +| [copp\_leaf\_policy](#input\_copp\_leaf\_policy) | CoPP Leaf policy name. | `string` | `""` | no | ## Outputs @@ -56,5 +58,6 @@ module "aci_access_leaf_switch_policy_group" { | [aci_rest_managed.infraAccNodePGrp](https://registry.terraform.io/providers/CiscoDevNet/aci/latest/docs/resources/rest_managed) | resource | | [aci_rest_managed.infraRsBfdIpv4InstPol](https://registry.terraform.io/providers/CiscoDevNet/aci/latest/docs/resources/rest_managed) | resource | | [aci_rest_managed.infraRsBfdIpv6InstPol](https://registry.terraform.io/providers/CiscoDevNet/aci/latest/docs/resources/rest_managed) | resource | +| [aci_rest_managed.infraRsLeafCoppProfile](https://registry.terraform.io/providers/CiscoDevNet/aci/latest/docs/resources/rest_managed) | resource | | [aci_rest_managed.infraRsTopoctrlFwdScaleProfPol](https://registry.terraform.io/providers/CiscoDevNet/aci/latest/docs/resources/rest_managed) | resource | \ No newline at end of file diff --git a/modules/terraform-aci-access-leaf-switch-policy-group/examples/complete/README.md b/modules/terraform-aci-access-leaf-switch-policy-group/examples/complete/README.md index 3dc158d5..51b90268 100644 --- a/modules/terraform-aci-access-leaf-switch-policy-group/examples/complete/README.md +++ b/modules/terraform-aci-access-leaf-switch-policy-group/examples/complete/README.md @@ -20,6 +20,7 @@ module "aci_access_leaf_switch_policy_group" { forwarding_scale_policy = "HIGH-DUAL-STACK" bfd_ipv4_policy = "BFD-IPV4-POLICY" bfd_ipv6_policy = "BFD-IPV6-POLICY" + copp_leaf_policy = "COPP-LEAF-POLICY" } ``` \ No newline at end of file diff --git a/modules/terraform-aci-access-leaf-switch-policy-group/examples/complete/main.tf b/modules/terraform-aci-access-leaf-switch-policy-group/examples/complete/main.tf index 253d30b0..a0f2735a 100644 --- a/modules/terraform-aci-access-leaf-switch-policy-group/examples/complete/main.tf +++ b/modules/terraform-aci-access-leaf-switch-policy-group/examples/complete/main.tf @@ -6,4 +6,5 @@ module "aci_access_leaf_switch_policy_group" { forwarding_scale_policy = "HIGH-DUAL-STACK" bfd_ipv4_policy = "BFD-IPV4-POLICY" bfd_ipv6_policy = "BFD-IPV6-POLICY" + copp_leaf_policy = "COPP-LEAF-POLICY" } diff --git a/modules/terraform-aci-access-leaf-switch-policy-group/main.tf b/modules/terraform-aci-access-leaf-switch-policy-group/main.tf index 24b40c2f..5c77ca04 100644 --- a/modules/terraform-aci-access-leaf-switch-policy-group/main.tf +++ b/modules/terraform-aci-access-leaf-switch-policy-group/main.tf @@ -29,3 +29,11 @@ resource "aci_rest_managed" "infraRsBfdIpv6InstPol" { tnBfdIpv6InstPolName = var.bfd_ipv6_policy } } + +resource "aci_rest_managed" "infraRsLeafCoppProfile" { + dn = "${aci_rest_managed.infraAccNodePGrp.dn}/rsleafCoppProfile" + class_name = "infraRsLeafCoppProfile" + content = { + tnCoppLeafProfileName = var.copp_leaf_policy + } +} diff --git a/modules/terraform-aci-access-leaf-switch-policy-group/variables.tf b/modules/terraform-aci-access-leaf-switch-policy-group/variables.tf index 0cc40784..ea340f0d 100644 --- a/modules/terraform-aci-access-leaf-switch-policy-group/variables.tf +++ b/modules/terraform-aci-access-leaf-switch-policy-group/variables.tf @@ -40,3 +40,14 @@ variable "bfd_ipv6_policy" { error_message = "Allowed characters: `a`-`z`, `A`-`Z`, `0`-`9`, `_`, `.`, `:`, `-`. Maximum characters: 64." } } + +variable "copp_leaf_policy" { + description = "CoPP Leaf policy name." + type = string + default = "" + + validation { + condition = can(regex("^[a-zA-Z0-9_.:-]{0,64}$", var.copp_leaf_policy)) + error_message = "Allowed characters: `a`-`z`, `A`-`Z`, `0`-`9`, `_`, `.`, `:`, `-`. Maximum characters: 64." + } +} diff --git a/modules/terraform-aci-access-spine-copp-policy/.terraform-docs.yml b/modules/terraform-aci-access-spine-copp-policy/.terraform-docs.yml new file mode 100644 index 00000000..350c6837 --- /dev/null +++ b/modules/terraform-aci-access-spine-copp-policy/.terraform-docs.yml @@ -0,0 +1,34 @@ +version: '>= 0.14.0' + +formatter: markdown table + +content: |- + # Terraform ACI Access Spine CoPP Policy Module + + Manages ACI Access Spine CoPP Policy + + Location in GUI: + `Fabric` » `Access Policies` » `Policies` » `Switch` » `CoPP Spine` + + ## Examples + + ```hcl + {{ include "./examples/complete/main.tf" }} + ``` + + {{ .Requirements }} + + {{ .Providers }} + + {{ .Inputs }} + + {{ .Outputs }} + + {{ .Resources }} + +output: + file: README.md + mode: replace + +sort: + enabled: false diff --git a/modules/terraform-aci-access-spine-copp-policy/README.md b/modules/terraform-aci-access-spine-copp-policy/README.md new file mode 100644 index 00000000..4a115bd2 --- /dev/null +++ b/modules/terraform-aci-access-spine-copp-policy/README.md @@ -0,0 +1,61 @@ + +# Terraform ACI Access Spine CoPP Policy Module + +Manages ACI Access Spine CoPP Policy + +Location in GUI: +`Fabric` » `Access Policies` » `Policies` » `Switch` » `CoPP Spine` + +## Examples + +```hcl +module "aci_access_spine_copp_policy" { + source = "netascode/nac-aci/aci//modules/terraform-aci-access-spine-copp-policy" + version = ">= 0.8.0" + + name = "POL1" + description = "POL1" + type = "custom" + custom_values = { + arp_rate = 1234 + arp_burst = 300 + acl_log_rate = 150 + acl_log_burst = 300 + } +} +``` + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.0.0 | +| [aci](#requirement\_aci) | >= 2.0.0 | + +## Providers + +| Name | Version | +|------|---------| +| [aci](#provider\_aci) | >= 2.0.0 | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [name](#input\_name) | Attachable access entity profile name. | `string` | n/a | yes | +| [description](#input\_description) | Attachable access entity profile description | `string` | `""` | no | +| [type](#input\_type) | Profile type. Allowed values: `default`, `custom`, `strict`, `moderate`, `lenient`. | `string` | `"default"` | no | +| [custom\_values](#input\_custom\_values) | Custom CoPP values | `any` | n/a | yes | + +## Outputs + +| Name | Description | +|------|-------------| +| [dn](#output\_dn) | Distinguished name of `coppSpineProfile` object. | + +## Resources + +| Name | Type | +|------|------| +| [aci_rest_managed.coppSpineProfile](https://registry.terraform.io/providers/CiscoDevNet/aci/latest/docs/resources/rest_managed) | resource | + \ No newline at end of file diff --git a/modules/terraform-aci-access-spine-copp-policy/examples/complete/.terraform-docs.yml b/modules/terraform-aci-access-spine-copp-policy/examples/complete/.terraform-docs.yml new file mode 100644 index 00000000..3c15ffc6 --- /dev/null +++ b/modules/terraform-aci-access-spine-copp-policy/examples/complete/.terraform-docs.yml @@ -0,0 +1,24 @@ +version: '>= 0.14.0' + +formatter: markdown table + +content: |- + # Access Spine CoPP Policy Example + + To run this example you need to execute: + + ```bash + $ terraform init + $ terraform plan + $ terraform apply + ``` + + Note that this example will create resources. Resources can be destroyed with `terraform destroy`. + + ```hcl + {{ include "./main.tf" }} + ``` + +output: + file: README.md + mode: replace diff --git a/modules/terraform-aci-access-spine-copp-policy/examples/complete/README.md b/modules/terraform-aci-access-spine-copp-policy/examples/complete/README.md new file mode 100644 index 00000000..8d4a287c --- /dev/null +++ b/modules/terraform-aci-access-spine-copp-policy/examples/complete/README.md @@ -0,0 +1,30 @@ + +# Access Spine CoPP Policy Example + +To run this example you need to execute: + +```bash +$ terraform init +$ terraform plan +$ terraform apply +``` + +Note that this example will create resources. Resources can be destroyed with `terraform destroy`. + +```hcl +module "aci_access_spine_copp_policy" { + source = "netascode/nac-aci/aci//modules/terraform-aci-access-spine-copp-policy" + version = ">= 0.8.0" + + name = "POL1" + description = "POL1" + type = "custom" + custom_values = { + arp_rate = 1234 + arp_burst = 300 + acl_log_rate = 150 + acl_log_burst = 300 + } +} +``` + \ No newline at end of file diff --git a/modules/terraform-aci-access-spine-copp-policy/examples/complete/main.tf b/modules/terraform-aci-access-spine-copp-policy/examples/complete/main.tf new file mode 100644 index 00000000..14540797 --- /dev/null +++ b/modules/terraform-aci-access-spine-copp-policy/examples/complete/main.tf @@ -0,0 +1,14 @@ +module "aci_access_spine_copp_policy" { + source = "netascode/nac-aci/aci//modules/terraform-aci-access-spine-copp-policy" + version = ">= 0.8.0" + + name = "POL1" + description = "POL1" + type = "custom" + custom_values = { + arp_rate = 1234 + arp_burst = 300 + acl_log_rate = 150 + acl_log_burst = 300 + } +} \ No newline at end of file diff --git a/modules/terraform-aci-access-spine-copp-policy/examples/complete/versions.tf b/modules/terraform-aci-access-spine-copp-policy/examples/complete/versions.tf new file mode 100644 index 00000000..e8b775ae --- /dev/null +++ b/modules/terraform-aci-access-spine-copp-policy/examples/complete/versions.tf @@ -0,0 +1,11 @@ + +terraform { + required_version = ">= 1.0.0" + + required_providers { + aci = { + source = "CiscoDevNet/aci" + version = ">= 2.0.0" + } + } +} diff --git a/modules/terraform-aci-access-spine-copp-policy/main.tf b/modules/terraform-aci-access-spine-copp-policy/main.tf new file mode 100644 index 00000000..8752ae32 --- /dev/null +++ b/modules/terraform-aci-access-spine-copp-policy/main.tf @@ -0,0 +1,53 @@ +resource "aci_rest_managed" "coppSpineProfile" { + dn = "uni/infra/coppspinep-${var.name}" + class_name = "coppSpineProfile" + + content = { + name = var.name + descr = var.description + type = var.type + } + + dynamic "child" { + for_each = var.type == "custom" ? [0] : [] + content { + class_name = "coppSpineGen1CustomValues" + rn = "spinegen1customvalues" + content = { + dn = "uni/infra/coppspinep-${var.name}/spinegen1customvalues" + arpRate = var.custom_values.arp_rate == "default" ? 1360 : var.custom_values.arp_rate + arpBurst = var.custom_values.arp_burst == "default" ? 340 : var.custom_values.arp_burst + bgpRate = var.custom_values.bgp_rate == "default" ? 5000 : var.custom_values.bgp_rate + bgpBurst = var.custom_values.bgp_burst == "default" ? 5000 : var.custom_values.bgp_burst + cdpRate = var.custom_values.cdp_rate == "default" ? 1000 : var.custom_values.cdp_rate + cdpBurst = var.custom_values.cdp_burst == "default" ? 1000 : var.custom_values.cdp_burst + coopRate = var.custom_values.coop_rate == "default" ? 5000 : var.custom_values.coop_rate + coopBurst = var.custom_values.coop_burst == "default" ? 5000 : var.custom_values.coop_burst + dhcpRate = var.custom_values.dhcp_rate == "default" ? 1360 : var.custom_values.dhcp_rate + dhcpBurst = var.custom_values.dhcp_burst == "default" ? 340 : var.custom_values.dhcp_burst + gleanRate = var.custom_values.glean_rate == "default" ? 100 : var.custom_values.glean_rate + gleanBurst = var.custom_values.glean_burst == "default" ? 100 : var.custom_values.glean_burst + ifcRate = var.custom_values.ifc_rate == "default" ? 10000 : var.custom_values.ifc_rate + ifcBurst = var.custom_values.ifc_burst == "default" ? 10000 : var.custom_values.ifc_burst + ifcOtherRate = var.custom_values.ifc_other_rate == "default" ? 332800 : var.custom_values.ifc_other_rate + ifcOtherBurst = var.custom_values.ifc_other_burst == "default" ? 5000 : var.custom_values.ifc_other_burst + ifcSpanRate = var.custom_values.ifc_span_rate == "default" ? 2000 : var.custom_values.ifc_span_rate + ifcSpanBurst = var.custom_values.ifc_span_burst == "default" ? 2000 : var.custom_values.ifc_span_burst + igmpRate = var.custom_values.igmp_rate == "default" ? 1500 : var.custom_values.igmp_rate + igmpBurst = var.custom_values.igmp_burst == "default" ? 1500 : var.custom_values.igmp_burst + infraArpRate = var.custom_values.infra_arp_rate == "default" ? 300 : var.custom_values.infra_arp_rate + infraArpBurst = var.custom_values.infra_arp_burst == "default" ? 300 : var.custom_values.infra_arp_burst + isisRate = var.custom_values.isis_rate == "default" ? 1500 : var.custom_values.isis_rate + isisBurst = var.custom_values.isis_burst == "default" ? 5000 : var.custom_values.isis_burst + lldpRate = var.custom_values.lldp_rate == "default" ? 1000 : var.custom_values.lldp_rate + lldpBurst = var.custom_values.lldp_burst == "default" ? 1000 : var.custom_values.lldp_burst + ospfRate = var.custom_values.ospf_rate == "default" ? 2000 : var.custom_values.ospf_rate + ospfBurst = var.custom_values.ospf_burst == "default" ? 2000 : var.custom_values.ospf_burst + torGleanRate = var.custom_values.tor_glean_rate == "default" ? 100 : var.custom_values.tor_glean_rate + torGleanBurst = var.custom_values.tor_glean_burst == "default" ? 100 : var.custom_values.tor_glean_burst + tracerouteRate = var.custom_values.traceroute_rate == "default" ? 500 : var.custom_values.traceroute_rate + tracerouteBurst = var.custom_values.traceroute_burst == "default" ? 500 : var.custom_values.traceroute_burst + } + } + } +} diff --git a/modules/terraform-aci-access-spine-copp-policy/outputs.tf b/modules/terraform-aci-access-spine-copp-policy/outputs.tf new file mode 100644 index 00000000..b1906a75 --- /dev/null +++ b/modules/terraform-aci-access-spine-copp-policy/outputs.tf @@ -0,0 +1,4 @@ +output "dn" { + value = aci_rest_managed.coppSpineProfile.id + description = "Distinguished name of `coppSpineProfile` object." +} \ No newline at end of file diff --git a/modules/terraform-aci-access-spine-copp-policy/variables.tf b/modules/terraform-aci-access-spine-copp-policy/variables.tf new file mode 100644 index 00000000..2b2b8aaf --- /dev/null +++ b/modules/terraform-aci-access-spine-copp-policy/variables.tf @@ -0,0 +1,198 @@ +variable "name" { + description = "Attachable access entity profile name." + type = string + + validation { + condition = can(regex("^[a-zA-Z0-9_.:-]{0,64}$", var.name)) + error_message = "Allowed characters: `a`-`z`, `A`-`Z`, `0`-`9`, `_`, `.`, `:`, `-`. Maximum characters: 64." + } +} + +variable "description" { + description = "Attachable access entity profile description" + type = string + default = "" + + validation { + condition = can(regex("^[a-zA-Z0-9\\!#$%()*,-./:;@ _{|}~?&+]{0,128}$", var.description)) + error_message = "Allowed characters: `a`-`z`, `A`-`Z`, `0`-`9`, `\\`, `!`, `#`, `$`, `%`, `(`, `)`, `*`, `,`, `-`, `.`, `/`, `:`, `;`, `@`, ` `, `_`, `{`, `|`, }`, `~`, `?`, `&`, `+`. Maximum characters: 128." + } +} + +variable "type" { + description = "Profile type. Allowed values: `default`, `custom`, `strict`, `moderate`, `lenient`." + type = string + default = "default" + + validation { + condition = contains(["default", "custom", "strict", "moderate", "lenient"], var.type) + error_message = "Allowed values: `default`, `custom`, `strict`, `moderate`, `lenient`." + } +} + +variable "custom_values" { + description = "Custom CoPP values" + type = any + # default = null + + validation { + condition = try(var.custom_values.arp_rate == "default" || try(tonumber(var.custom_values.arp_rate) >= 10 && tonumber(var.custom_values.arp_rate) <= 1360, false), var.custom_values.arp_rate) + error_message = "Allowed Values: `default` or a number between 10 and 1360." + } + + validation { + condition = try(var.custom_values.arp_burst == "default" || try(tonumber(var.custom_values.arp_burst) >= 10 && tonumber(var.custom_values.arp_burst) <= 340, false), var.custom_values.arp_burst) + error_message = "Allowed Values: `default` or a number between 10 and 340." + } + + validation { + condition = try(var.custom_values.bgp_rate == "default" || try(tonumber(var.custom_values.bgp_rate) >= 10 && tonumber(var.custom_values.bgp_rate) <= 5000, false), var.custom_values.bgp_rate) + error_message = "Allowed Values: `default` or a number between 10 and 5000." + } + + validation { + condition = try(var.custom_values.bgp_burst == "default" || try(tonumber(var.custom_values.bgp_burst) >= 10 && tonumber(var.custom_values.bgp_burst) <= 5000, false), var.custom_values.bgp_burst) + error_message = "Allowed Values: `default` or a number between 10 and 5000." + } + + validation { + condition = try(var.custom_values.cdp_rate == "default" || try(tonumber(var.custom_values.cdp_rate) >= 10 && tonumber(var.custom_values.cdp_rate) <= 1000, false), var.custom_values.cdp_rate) + error_message = "Allowed Values: `default` or a number between 10 and 1000." + } + + validation { + condition = try(var.custom_values.cdp_burst == "default" || try(tonumber(var.custom_values.cdp_burst) >= 10 && tonumber(var.custom_values.cdp_burst) <= 1000, false), var.custom_values.cdp_burst) + error_message = "Allowed Values: `default` or a number between 10 and 1000." + } + + validation { + condition = try(var.custom_values.coop_rate == "default" || try(tonumber(var.custom_values.coop_rate) >= 1000 && tonumber(var.custom_values.coop_rate) <= 5000, false), var.custom_values.coop_rate) + error_message = "Allowed Values: `default` or a number between 1000 and 5000." + } + + validation { + condition = try(var.custom_values.coop_burst == "default" || try(tonumber(var.custom_values.coop_burst) >= 1000 && tonumber(var.custom_values.coop_burst) <= 5000, false), var.custom_values.coop_burst) + error_message = "Allowed Values: `default` or a number between 1000 and 5000." + } + + validation { + condition = try(var.custom_values.dhcp_rate == "default" || try(tonumber(var.custom_values.dhcp_rate) >= 100 && tonumber(var.custom_values.dhcp_rate) <= 1360, false), var.custom_values.dhcp_rate) + error_message = "Allowed Values: `default` or a number between 100 and 1360." + } + + validation { + condition = try(var.custom_values.dhcp_burst == "default" || try(tonumber(var.custom_values.dhcp_burst) >= 100 && tonumber(var.custom_values.dhcp_burst) <= 340, false), var.custom_values.dhcp_burst) + error_message = "Allowed Values: `default` or a number between 100 and 340." + } + + validation { + condition = try(var.custom_values.glean_rate == "default" || try(tonumber(var.custom_values.glean_rate) >= 10 && tonumber(var.custom_values.glean_rate) <= 500, false), var.custom_values.glean_rate) + error_message = "Allowed Values: `default` or a number between 10 and 500." + } + + validation { + condition = try(var.custom_values.glean_burst == "default" || try(tonumber(var.custom_values.glean_burst) >= 10 && tonumber(var.custom_values.glean_burst) <= 500, false), var.custom_values.glean_burst) + error_message = "Allowed Values: `default` or a number between 10 and 500." + } + + validation { + condition = try(var.custom_values.ifc_rate == "default" || try(tonumber(var.custom_values.ifc_rate) <= 5000 && tonumber(var.custom_values.ifc_rate) <= 10000, false), var.custom_values.ifc_rate) + error_message = "Allowed Values: `default` or a number between 5000 and 10000." + } + + validation { + condition = try(var.custom_values.ifc_burst == "default" || try(tonumber(var.custom_values.ifc_burst) <= 5000 && tonumber(var.custom_values.ifc_burst) <= 10000, false), var.custom_values.ifc_burst) + error_message = "Allowed Values: `default` or a number between 5000 and 10000." + } + + validation { + condition = try(var.custom_values.ifc_other_rate == "default" || try(tonumber(var.custom_values.ifc_other_rate) >= 5000 && tonumber(var.custom_values.ifc_other_rate) <= 32800, false), var.custom_values.ifc_other_rate) + error_message = "Allowed Values: `default` or a number between 5000 and 32800." + } + + validation { + condition = try(var.custom_values.ifc_other_burst == "default" || try(tonumber(var.custom_values.ifc_other_burst) == 5000, false), var.custom_values.ifc_other_burst) + error_message = "Allowed Values: `default` or the number 5000." + } + + validation { + condition = try(var.custom_values.ifc_span_rate == "default" || try(tonumber(var.custom_values.ifc_span_rate) >= 10 && tonumber(var.custom_values.ifc_span_rate) <= 2000, false), var.custom_values.ifc_span_rate) + error_message = "Allowed Values: `default` or a number between 10 and 2000." + } + + validation { + condition = try(var.custom_values.ifc_span_burst == "default" || try(tonumber(var.custom_values.ifc_span_burst) >= 10 && tonumber(var.custom_values.ifc_span_burst) <= 2000, false), var.custom_values.ifc_span_burst) + error_message = "Allowed Values: `default` or a number between 10 and 2000." + } + + validation { + condition = try(var.custom_values.igmp_rate == "default" || try(tonumber(var.custom_values.igmp_rate) >= 10 && tonumber(var.custom_values.igmp_rate) <= 1500, false), var.custom_values.igmp_rate) + error_message = "Allowed Values: `default` or a number between 10 and 1500." + } + + validation { + condition = try(var.custom_values.igmp_burst == "default" || try(tonumber(var.custom_values.igmp_burst) >= 10 && tonumber(var.custom_values.igmp_burst) <= 1500, false), var.custom_values.igmp_burst) + error_message = "Allowed Values: `default` or a number between 10 and 1500." + } + + validation { + condition = try(var.custom_values.infra_arp_rate == "default" || try(tonumber(var.custom_values.infra_arp_rate) >= 50 && tonumber(var.custom_values.infra_arp_rate) <= 300, false), var.custom_values.infra_arp_rate) + error_message = "Allowed Values: `default` or a number between 50 and 300." + } + + validation { + condition = try(var.custom_values.infra_arp_burst == "default" || try(tonumber(var.custom_values.infra_arp_burst) >= 50 && tonumber(var.custom_values.infra_arp_burst) <= 300, false), var.custom_values.infra_arp_burst) + error_message = "Allowed Values: `default` or a number between 50 and 300." + } + + validation { + condition = try(var.custom_values.isis_rate == "default" || try(tonumber(var.custom_values.isis_rate) >= 100 && tonumber(var.custom_values.isis_rate) <= 1500, false), var.custom_values.isis_rate) + error_message = "Allowed Values: `default` or a number between 100 and 1500." + } + + validation { + condition = try(var.custom_values.isis_burst == "default" || try(tonumber(var.custom_values.isis_burst) >= 100 && tonumber(var.custom_values.isis_burst) <= 5000, false), var.custom_values.isis_burst) + error_message = "Allowed Values: `default` or a number between 100 and 5000." + } + + validation { + condition = try(var.custom_values.lldp_rate == "default" || try(tonumber(var.custom_values.lldp_rate) >= 10 && tonumber(var.custom_values.lldp_rate) <= 1000, false), var.custom_values.lldp_rate) + error_message = "Allowed Values: `default` or a number between 10 and 1000." + } + + validation { + condition = try(var.custom_values.lldp_burst == "default" || try(tonumber(var.custom_values.lldp_burst) >= 10 && tonumber(var.custom_values.lldp_burst) <= 1000, false), var.custom_values.lldp_burst) + error_message = "Allowed Values: `default` or a number between 10 and 1000." + } + + validation { + condition = try(var.custom_values.ospf_rate == "default" || try(tonumber(var.custom_values.ospf_rate) >= 10 && tonumber(var.custom_values.ospf_rate) <= 2000, false), var.custom_values.ospf_rate) + error_message = "Allowed Values: `default` or a number between 10 and 2000." + } + + validation { + condition = try(var.custom_values.ospf_burst == "default" || try(tonumber(var.custom_values.ospf_burst) >= 10 && tonumber(var.custom_values.ospf_burst) <= 2000, false), var.custom_values.ospf_burst) + error_message = "Allowed Values: `default` or a number between 10 and 2000." + } + + validation { + condition = try(var.custom_values.tor_glean_rate == "default" || try(tonumber(var.custom_values.tor_glean_rate) >= 10 && tonumber(var.custom_values.tor_glean_rate) <= 500, false), var.custom_values.tor_glean_rate) + error_message = "Allowed Values: `default` or a number between 10 and 500." + } + + validation { + condition = try(var.custom_values.tor_glean_burst == "default" || try(tonumber(var.custom_values.tor_glean_burst) >= 10 && tonumber(var.custom_values.tor_glean_burst) <= 500, false), var.custom_values.tor_glean_burst) + error_message = "Allowed Values: `default` or a number between 10 and 500." + } + + validation { + condition = try(var.custom_values.traceroute_rate == "default" || try(tonumber(var.custom_values.traceroute_rate) >= 10 && tonumber(var.custom_values.traceroute_rate) <= 500, false), var.custom_values.traceroute_rate) + error_message = "Allowed Values: `default` or a number between 10 and 500." + } + + validation { + condition = try(var.custom_values.traceroute_burst == "default" || try(tonumber(var.custom_values.traceroute_burst) >= 10 && tonumber(var.custom_values.traceroute_burst) <= 500, false), var.custom_values.traceroute_burst) + error_message = "Allowed Values: `default` or a number between 10 and 500." + } + +} diff --git a/modules/terraform-aci-access-spine-copp-policy/versions.tf b/modules/terraform-aci-access-spine-copp-policy/versions.tf new file mode 100644 index 00000000..e8b775ae --- /dev/null +++ b/modules/terraform-aci-access-spine-copp-policy/versions.tf @@ -0,0 +1,11 @@ + +terraform { + required_version = ">= 1.0.0" + + required_providers { + aci = { + source = "CiscoDevNet/aci" + version = ">= 2.0.0" + } + } +} diff --git a/modules/terraform-aci-access-spine-switch-policy-group/README.md b/modules/terraform-aci-access-spine-switch-policy-group/README.md index a884c2a0..8519bb43 100644 --- a/modules/terraform-aci-access-spine-switch-policy-group/README.md +++ b/modules/terraform-aci-access-spine-switch-policy-group/README.md @@ -13,10 +13,11 @@ module "aci_access_spine_switch_policy_group" { source = "netascode/nac-aci/aci//modules/terraform-aci-access-spine-switch-policy-group" version = ">= 0.8.0" - name = "SW-PG1" - lldp_policy = "LLDP-ON" - bfd_ipv4_policy = "BFD-IPV4-POLICY" - bfd_ipv6_policy = "BFD-IPV6-POLICY" + name = "SW-PG1" + lldp_policy = "LLDP-ON" + bfd_ipv4_policy = "BFD-IPV4-POLICY" + bfd_ipv6_policy = "BFD-IPV6-POLICY" + copp_spine_policy = "COPP-SPINE-POLICY" } ``` @@ -41,6 +42,7 @@ module "aci_access_spine_switch_policy_group" { | [lldp\_policy](#input\_lldp\_policy) | LLDP policy name. | `string` | `""` | no | | [bfd\_ipv4\_policy](#input\_bfd\_ipv4\_policy) | BFD IPv4 policy name. | `string` | `""` | no | | [bfd\_ipv6\_policy](#input\_bfd\_ipv6\_policy) | BFD IPv6 policy name. | `string` | `""` | no | +| [copp\_spine\_policy](#input\_copp\_spine\_policy) | CoPP Spine policy name. | `string` | `""` | no | ## Outputs @@ -55,6 +57,7 @@ module "aci_access_spine_switch_policy_group" { |------|------| | [aci_rest_managed.infraRsBfdIpv4InstPol](https://registry.terraform.io/providers/CiscoDevNet/aci/latest/docs/resources/rest_managed) | resource | | [aci_rest_managed.infraRsBfdIpv6InstPol](https://registry.terraform.io/providers/CiscoDevNet/aci/latest/docs/resources/rest_managed) | resource | +| [aci_rest_managed.infraRsSpineCoppProfile](https://registry.terraform.io/providers/CiscoDevNet/aci/latest/docs/resources/rest_managed) | resource | | [aci_rest_managed.infraRsSpinePGrpToLldpIfPol](https://registry.terraform.io/providers/CiscoDevNet/aci/latest/docs/resources/rest_managed) | resource | | [aci_rest_managed.infraSpineAccNodePGrp](https://registry.terraform.io/providers/CiscoDevNet/aci/latest/docs/resources/rest_managed) | resource | \ No newline at end of file diff --git a/modules/terraform-aci-access-spine-switch-policy-group/examples/complete/README.md b/modules/terraform-aci-access-spine-switch-policy-group/examples/complete/README.md index 7edbab64..4af01299 100644 --- a/modules/terraform-aci-access-spine-switch-policy-group/examples/complete/README.md +++ b/modules/terraform-aci-access-spine-switch-policy-group/examples/complete/README.md @@ -16,10 +16,11 @@ module "aci_access_spine_switch_policy_group" { source = "netascode/nac-aci/aci//modules/terraform-aci-access-spine-switch-policy-group" version = ">= 0.8.0" - name = "SW-PG1" - lldp_policy = "LLDP-ON" - bfd_ipv4_policy = "BFD-IPV4-POLICY" - bfd_ipv6_policy = "BFD-IPV6-POLICY" + name = "SW-PG1" + lldp_policy = "LLDP-ON" + bfd_ipv4_policy = "BFD-IPV4-POLICY" + bfd_ipv6_policy = "BFD-IPV6-POLICY" + copp_spine_policy = "COPP-SPINE-POLICY" } ``` \ No newline at end of file diff --git a/modules/terraform-aci-access-spine-switch-policy-group/examples/complete/main.tf b/modules/terraform-aci-access-spine-switch-policy-group/examples/complete/main.tf index ab3e626d..7fd2fc54 100644 --- a/modules/terraform-aci-access-spine-switch-policy-group/examples/complete/main.tf +++ b/modules/terraform-aci-access-spine-switch-policy-group/examples/complete/main.tf @@ -2,8 +2,9 @@ module "aci_access_spine_switch_policy_group" { source = "netascode/nac-aci/aci//modules/terraform-aci-access-spine-switch-policy-group" version = ">= 0.8.0" - name = "SW-PG1" - lldp_policy = "LLDP-ON" - bfd_ipv4_policy = "BFD-IPV4-POLICY" - bfd_ipv6_policy = "BFD-IPV6-POLICY" + name = "SW-PG1" + lldp_policy = "LLDP-ON" + bfd_ipv4_policy = "BFD-IPV4-POLICY" + bfd_ipv6_policy = "BFD-IPV6-POLICY" + copp_spine_policy = "COPP-SPINE-POLICY" } diff --git a/modules/terraform-aci-access-spine-switch-policy-group/main.tf b/modules/terraform-aci-access-spine-switch-policy-group/main.tf index 207bb48e..c1ac3aff 100644 --- a/modules/terraform-aci-access-spine-switch-policy-group/main.tf +++ b/modules/terraform-aci-access-spine-switch-policy-group/main.tf @@ -29,3 +29,11 @@ resource "aci_rest_managed" "infraRsBfdIpv6InstPol" { tnBfdIpv6InstPolName = var.bfd_ipv6_policy } } + +resource "aci_rest_managed" "infraRsSpineCoppProfile" { + dn = "${aci_rest_managed.infraSpineAccNodePGrp.dn}/rsspineCoppProfile" + class_name = "infraRsSpineCoppProfile" + content = { + tnCoppSpineProfileName = var.copp_spine_policy + } +} \ No newline at end of file diff --git a/modules/terraform-aci-access-spine-switch-policy-group/variables.tf b/modules/terraform-aci-access-spine-switch-policy-group/variables.tf index bcd9b9e8..7eb8724d 100644 --- a/modules/terraform-aci-access-spine-switch-policy-group/variables.tf +++ b/modules/terraform-aci-access-spine-switch-policy-group/variables.tf @@ -40,3 +40,16 @@ variable "bfd_ipv6_policy" { error_message = "Allowed characters: `a`-`z`, `A`-`Z`, `0`-`9`, `_`, `.`, `:`, `-`. Maximum characters: 64." } } + + +variable "copp_spine_policy" { + description = "CoPP Spine policy name." + type = string + default = "" + + validation { + condition = can(regex("^[a-zA-Z0-9_.:-]{0,64}$", var.copp_spine_policy)) + error_message = "Allowed characters: `a`-`z`, `A`-`Z`, `0`-`9`, `_`, `.`, `:`, `-`. Maximum characters: 64." + } +} + diff --git a/modules/terraform-aci-copp-interface-policy/.terraform-docs.yml b/modules/terraform-aci-copp-interface-policy/.terraform-docs.yml new file mode 100644 index 00000000..693c38ac --- /dev/null +++ b/modules/terraform-aci-copp-interface-policy/.terraform-docs.yml @@ -0,0 +1,34 @@ +version: '>= 0.14.0' + +formatter: markdown table + +content: |- + # Terraform CoPP Interface Policy Module + + Manages CoPP Interface Policy + + Location in GUI: + `Fabric` » `Access Policies` » `Policies` » `Interface` » `CoPP Interface` + + ## Examples + + ```hcl + {{ include "./examples/complete/main.tf" }} + ``` + + {{ .Requirements }} + + {{ .Providers }} + + {{ .Inputs }} + + {{ .Outputs }} + + {{ .Resources }} + +output: + file: README.md + mode: replace + +sort: + enabled: false diff --git a/modules/terraform-aci-copp-interface-policy/README.md b/modules/terraform-aci-copp-interface-policy/README.md new file mode 100644 index 00000000..40044071 --- /dev/null +++ b/modules/terraform-aci-copp-interface-policy/README.md @@ -0,0 +1,60 @@ + +# Terraform CoPP Interface Policy Module + +Manages CoPP Interface Policy + +Location in GUI: +`Fabric` » `Access Policies` » `Policies` » `Interface` » `CoPP Interface` + +## Examples + +```hcl +module "aci_copp_interface_policy" { + source = "netascode/nac-aci/aci//modules/terraform-aci-copp-interface-policy" + version = ">= 0.8.0" + + name = "COPP1" + description = "COPP1 Description" + protocol_policies = [{ + name = "COPP-PROTO1" + rate = "123" + burst = "1234" + match_protocols = ["bgp", "ospf"] + }] +} +``` + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.0.0 | +| [aci](#requirement\_aci) | >= 2.0.0 | + +## Providers + +| Name | Version | +|------|---------| +| [aci](#provider\_aci) | >= 2.0.0 | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [name](#input\_name) | CoPP Interface policy name. | `string` | n/a | yes | +| [description](#input\_description) | CoPP Interface policy description. | `string` | `""` | no | +| [protocol\_policies](#input\_protocol\_policies) | CoPP protocol policies. |
list(object({
name = string
rate = optional(string, 10)
burst = optional(string, 10)
match_protocols = optional(list(string), null)
}))
| `[]` | no | + +## Outputs + +| Name | Description | +|------|-------------| +| [dn](#output\_dn) | Distinguished name of `coppIfPol` object. | + +## Resources + +| Name | Type | +|------|------| +| [aci_rest_managed.coppIfPol](https://registry.terraform.io/providers/CiscoDevNet/aci/latest/docs/resources/rest_managed) | resource | +| [aci_rest_managed.coppProtoClassP](https://registry.terraform.io/providers/CiscoDevNet/aci/latest/docs/resources/rest_managed) | resource | + \ No newline at end of file diff --git a/modules/terraform-aci-copp-interface-policy/examples/complete/.terraform-docs.yml b/modules/terraform-aci-copp-interface-policy/examples/complete/.terraform-docs.yml new file mode 100644 index 00000000..b7db1ab3 --- /dev/null +++ b/modules/terraform-aci-copp-interface-policy/examples/complete/.terraform-docs.yml @@ -0,0 +1,24 @@ +version: '>= 0.14.0' + +formatter: markdown table + +content: |- + # CoPP Interface Policy Example + + To run this example you need to execute: + + ```bash + $ terraform init + $ terraform plan + $ terraform apply + ``` + + Note that this example will create resources. Resources can be destroyed with `terraform destroy`. + + ```hcl + {{ include "./main.tf" }} + ``` + +output: + file: README.md + mode: replace diff --git a/modules/terraform-aci-copp-interface-policy/examples/complete/README.md b/modules/terraform-aci-copp-interface-policy/examples/complete/README.md new file mode 100644 index 00000000..9161a33d --- /dev/null +++ b/modules/terraform-aci-copp-interface-policy/examples/complete/README.md @@ -0,0 +1,29 @@ + +# CoPP Interface Policy Example + +To run this example you need to execute: + +```bash +$ terraform init +$ terraform plan +$ terraform apply +``` + +Note that this example will create resources. Resources can be destroyed with `terraform destroy`. + +```hcl +module "aci_copp_interface_policy" { + source = "netascode/nac-aci/aci//modules/terraform-aci-copp-interface-policy" + version = ">= 0.8.0" + + name = "COPP1" + description = "COPP1 Description" + protocol_policies = [{ + name = "COPP-PROTO1" + rate = "123" + burst = "1234" + match_protocols = ["bgp", "ospf"] + }] +} +``` + \ No newline at end of file diff --git a/modules/terraform-aci-copp-interface-policy/examples/complete/main.tf b/modules/terraform-aci-copp-interface-policy/examples/complete/main.tf new file mode 100644 index 00000000..1fae90e6 --- /dev/null +++ b/modules/terraform-aci-copp-interface-policy/examples/complete/main.tf @@ -0,0 +1,13 @@ +module "aci_copp_interface_policy" { + source = "netascode/nac-aci/aci//modules/terraform-aci-copp-interface-policy" + version = ">= 0.8.0" + + name = "COPP1" + description = "COPP1 Description" + protocol_policies = [{ + name = "COPP-PROTO1" + rate = "123" + burst = "1234" + match_protocols = ["bgp", "ospf"] + }] +} diff --git a/modules/terraform-aci-copp-interface-policy/examples/complete/versions.tf b/modules/terraform-aci-copp-interface-policy/examples/complete/versions.tf new file mode 100644 index 00000000..e8b775ae --- /dev/null +++ b/modules/terraform-aci-copp-interface-policy/examples/complete/versions.tf @@ -0,0 +1,11 @@ + +terraform { + required_version = ">= 1.0.0" + + required_providers { + aci = { + source = "CiscoDevNet/aci" + version = ">= 2.0.0" + } + } +} diff --git a/modules/terraform-aci-copp-interface-policy/main.tf b/modules/terraform-aci-copp-interface-policy/main.tf new file mode 100644 index 00000000..114d0fe9 --- /dev/null +++ b/modules/terraform-aci-copp-interface-policy/main.tf @@ -0,0 +1,22 @@ +resource "aci_rest_managed" "coppIfPol" { + dn = "uni/infra/coppifpol-${var.name}" + class_name = "coppIfPol" + + content = { + name = var.name + descr = var.description + } +} + +resource "aci_rest_managed" "coppProtoClassP" { + for_each = { for pcp in var.protocol_policies : pcp.name => pcp } + dn = "${aci_rest_managed.coppIfPol.dn}/protoclassp-${each.value.name}" + class_name = "coppProtoClassP" + + content = { + name = each.value.name + rate = each.value.rate + burst = each.value.burst + matchProto = try(join(",", sort(each.value.match_protocols)), null) + } +} \ No newline at end of file diff --git a/modules/terraform-aci-copp-interface-policy/outputs.tf b/modules/terraform-aci-copp-interface-policy/outputs.tf new file mode 100644 index 00000000..10a7fdf2 --- /dev/null +++ b/modules/terraform-aci-copp-interface-policy/outputs.tf @@ -0,0 +1,4 @@ +output "dn" { + value = aci_rest_managed.coppIfPol.id + description = "Distinguished name of `coppIfPol` object." +} \ No newline at end of file diff --git a/modules/terraform-aci-copp-interface-policy/variables.tf b/modules/terraform-aci-copp-interface-policy/variables.tf new file mode 100644 index 00000000..73ef20a2 --- /dev/null +++ b/modules/terraform-aci-copp-interface-policy/variables.tf @@ -0,0 +1,59 @@ +variable "name" { + description = "CoPP Interface policy name." + type = string + + validation { + condition = can(regex("^[a-zA-Z0-9_.:-]{0,64}$", var.name)) + error_message = "Allowed characters: `a`-`z`, `A`-`Z`, `0`-`9`, `_`, `.`, `:`, `-`. Maximum characters: 64." + } +} + +variable "description" { + description = "CoPP Interface policy description." + type = string + default = "" + + validation { + condition = can(regex("^[a-zA-Z0-9\\!#$%()*,-./:;@ _{|}~?&+]{0,128}$", var.description)) + error_message = "Allowed characters: `a`-`z`, `A`-`Z`, `0`-`9`, `\\`, `!`, `#`, `$`, `%`, `(`, `)`, `*`, `,`, `-`, `.`, `/`, `:`, `;`, `@`, ` `, `_`, `{`, `|`, }`, `~`, `?`, `&`, `+`. Maximum characters: 128." + } +} + +variable "protocol_policies" { + description = "CoPP protocol policies." + type = list(object({ + name = string + rate = optional(string, 10) + burst = optional(string, 10) + match_protocols = optional(list(string), null) + })) + default = [] + + validation { + condition = alltrue([ + for pp in var.protocol_policies : can(regex("^[a-zA-Z0-9_.:-]{0,64}$", pp.name)) + ]) + error_message = "Allowed characters: `a`-`z`, `A`-`Z`, `0`-`9`, `_`, `.`, `:`, `-`. Maximum characters: 64." + } + + validation { + condition = alltrue([ + for pp in var.protocol_policies : try(tonumber(pp.burst) >= 10, false) && try(tonumber(pp.burst) <= 549755813760, false) + ]) + error_message = "Allowed Values: A number between 10 and 549,755,813,760." + } + + validation { + condition = alltrue([ + for pp in var.protocol_policies : try(tonumber(pp.rate) >= 10, false) && try(tonumber(pp.rate) <= 4398046510080, false) + ]) + error_message = "Allowed Values: A number between 10 and 4,398,046,510,080." + } + + validation { + condition = alltrue(flatten([ + for pp in coalesce(var.protocol_policies, []) : [for mp in coalesce(pp.match_protocols, []) : contains(["icmp", "arp", "stp", "lldp", "bgp", "ospf", "bfd", "lacp", "cdp"], mp)] + ])) + error_message = "`match_protocol`: Allowed Values: `icmp`, `arp`, `stp`, `lldp`, `bgp`, `ospf`, `bfd`, `lacp`, `cdp`." + } +} \ No newline at end of file diff --git a/modules/terraform-aci-copp-interface-policy/versions.tf b/modules/terraform-aci-copp-interface-policy/versions.tf new file mode 100644 index 00000000..e8b775ae --- /dev/null +++ b/modules/terraform-aci-copp-interface-policy/versions.tf @@ -0,0 +1,11 @@ + +terraform { + required_version = ">= 1.0.0" + + required_providers { + aci = { + source = "CiscoDevNet/aci" + version = ">= 2.0.0" + } + } +}