From 2fb82f67662c4af397631b3e1d83c4cf16b3d358 Mon Sep 17 00:00:00 2001 From: Sabari Jaganathan <93724860+sajagana@users.noreply.github.com> Date: Fri, 27 Feb 2026 20:22:04 +0530 Subject: [PATCH 1/3] [minor_change] Add mso_fabric_resource_policies_port_channel_interface resource and datasource --- .../main.tf | 47 +++ ...esource_policies_port_channel_interface.go | 87 ++++ ...ce_policies_port_channel_interface_test.go | 55 +++ mso/provider.go | 294 +++++++------- ...esource_policies_port_channel_interface.go | 381 ++++++++++++++++++ ...ce_policies_port_channel_interface_test.go | 162 ++++++++ mso/test_constants.go | 12 + ...icies_port_channel_interface.html.markdown | 43 ++ ...icies_port_channel_interface.html.markdown | 62 +++ 9 files changed, 997 insertions(+), 146 deletions(-) create mode 100644 examples/fabric_resource_policies_port_channel_interface/main.tf create mode 100644 mso/datasource_mso_fabric_resource_policies_port_channel_interface.go create mode 100644 mso/datasource_mso_fabric_resource_policies_port_channel_interface_test.go create mode 100644 mso/resource_mso_fabric_resource_policies_port_channel_interface.go create mode 100644 mso/resource_mso_fabric_resource_policies_port_channel_interface_test.go create mode 100644 website/docs/d/fabric_resource_policies_port_channel_interface.html.markdown create mode 100644 website/docs/r/fabric_resource_policies_port_channel_interface.html.markdown diff --git a/examples/fabric_resource_policies_port_channel_interface/main.tf b/examples/fabric_resource_policies_port_channel_interface/main.tf new file mode 100644 index 00000000..7c0ba7ac --- /dev/null +++ b/examples/fabric_resource_policies_port_channel_interface/main.tf @@ -0,0 +1,47 @@ +terraform { + required_providers { + mso = { + source = "CiscoDevNet/mso" + } + } +} + +provider "mso" { + username = "" # + password = "" # + url = "" # + insecure = true +} + +resource "mso_template" "fabric_policy_template" { + template_name = "fabric_policy_template" + template_type = "fabric_policy" +} + +resource "mso_fabric_policies_interface_setting" "port_channel_interface" { + template_id = mso_template.fabric_policy_template.id + type = "portchannel" + name = "port_channel_interface" +} + +resource "mso_template" "fabric_resource_template" { + template_name = "fabric_resource_template" + template_type = "fabric_resource" +} + +resource "mso_fabric_resource_policies_port_channel_interface" "example" { + template_id = mso_template.fabric_resource_template.id + name = "example" + description = "example description" + node = "101" + interfaces = ["1/1", "1/2"] + interface_policy_uuid = mso_fabric_policies_interface_setting.port_channel_interface.id + interface_descriptions { + interface = "1/1" + description = "1/1 description" + } + interface_descriptions { + interface = "1/2" + description = "1/2 description" + } +} \ No newline at end of file diff --git a/mso/datasource_mso_fabric_resource_policies_port_channel_interface.go b/mso/datasource_mso_fabric_resource_policies_port_channel_interface.go new file mode 100644 index 00000000..26d80fe5 --- /dev/null +++ b/mso/datasource_mso_fabric_resource_policies_port_channel_interface.go @@ -0,0 +1,87 @@ +package mso + +import ( + "fmt" + "log" + + "github.com/ciscoecosystem/mso-go-client/client" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" +) + +func datasourceMSOPortChannelInterface() *schema.Resource { + return &schema.Resource{ + Read: dataSourceMSOPortChannelInterfaceRead, + + Schema: map[string]*schema.Schema{ + "template_id": { + Type: schema.TypeString, + Required: true, + }, + "name": { + Type: schema.TypeString, + Required: true, + }, + "description": { + Type: schema.TypeString, + Computed: true, + }, + "node": { + Type: schema.TypeString, + Computed: true, + }, + "interfaces": { + Type: schema.TypeList, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + Computed: true, + }, + "interface_policy_uuid": { + Type: schema.TypeString, + Computed: true, + }, + "interface_descriptions": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "interface": { + Type: schema.TypeString, + Computed: true, + }, + "description": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + "uuid": { + Type: schema.TypeString, + Computed: true, + }, + }, + } +} + +func dataSourceMSOPortChannelInterfaceRead(d *schema.ResourceData, m interface{}) error { + log.Printf("[DEBUG] MSO Port Channel Interface Data Source - Beginning Read") + msoClient := m.(*client.Client) + + templateId := d.Get("template_id").(string) + policyName := d.Get("name").(string) + + response, err := msoClient.GetViaURL(fmt.Sprintf("api/v1/templates/%s", templateId)) + if err != nil { + return err + } + + policy, err := GetPolicyByName(response, policyName, "fabricResourceTemplate", "template", "portChannels") + if err != nil { + return err + } + + setPortChannelInterfaceData(d, policy, templateId) + log.Printf("[DEBUG] MSO Port Channel Interface Data Source - Read Complete: %v", d.Id()) + return nil +} diff --git a/mso/datasource_mso_fabric_resource_policies_port_channel_interface_test.go b/mso/datasource_mso_fabric_resource_policies_port_channel_interface_test.go new file mode 100644 index 00000000..33135499 --- /dev/null +++ b/mso/datasource_mso_fabric_resource_policies_port_channel_interface_test.go @@ -0,0 +1,55 @@ +package mso + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" +) + +func TestAccMSOFabricResourcePortChannelInterfaceDataSource(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + PreConfig: func() { fmt.Println("Test: Port Channel Interface Data Source - With Interface Descriptions") }, + Config: testAccMSOFabricResourcePortChannelInterfaceDataSourceWithInterfaceDescriptions(), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("data.mso_fabric_resource_policies_port_channel_interface."+msoFabricResourcePortChannelInterfaceName, "name", msoFabricResourcePortChannelInterfaceName), + resource.TestCheckResourceAttr("data.mso_fabric_resource_policies_port_channel_interface."+msoFabricResourcePortChannelInterfaceName, "description", "Terraform test Port Channel Interface updated"), + resource.TestCheckResourceAttr("data.mso_fabric_resource_policies_port_channel_interface."+msoFabricResourcePortChannelInterfaceName, "node", "101"), + resource.TestCheckResourceAttr("data.mso_fabric_resource_policies_port_channel_interface."+msoFabricResourcePortChannelInterfaceName, "interfaces.#", "2"), + resource.TestCheckResourceAttrSet("data.mso_fabric_resource_policies_port_channel_interface."+msoFabricResourcePortChannelInterfaceName, "uuid"), + resource.TestCheckResourceAttrSet("data.mso_fabric_resource_policies_port_channel_interface."+msoFabricResourcePortChannelInterfaceName, "template_id"), + resource.TestCheckResourceAttrSet("data.mso_fabric_resource_policies_port_channel_interface."+msoFabricResourcePortChannelInterfaceName, "interface_policy_uuid"), + resource.TestCheckResourceAttr("data.mso_fabric_resource_policies_port_channel_interface."+msoFabricResourcePortChannelInterfaceName, "interface_descriptions.#", "2"), + CustomTestCheckTypeSetElemAttrs("data.mso_fabric_resource_policies_port_channel_interface."+msoFabricResourcePortChannelInterfaceName, "interface_descriptions", + map[string]string{ + "interface": "1/1", + "description": "Interface Description 1/1", + }, + ), + CustomTestCheckTypeSetElemAttrs("data.mso_fabric_resource_policies_port_channel_interface."+msoFabricResourcePortChannelInterfaceName, "interface_descriptions", + map[string]string{ + "interface": "1/2", + "description": "Interface Description 1/2", + }, + ), + ), + }, + }, + }) +} + +func testAccMSOFabricResourcePortChannelInterfaceDataSourceWithInterfaceDescriptions() string { + return fmt.Sprintf(`%[1]s + data "mso_fabric_resource_policies_port_channel_interface" "%[2]s" { + template_id = mso_template.%[3]s.id + name = mso_fabric_resource_policies_port_channel_interface.%[2]s.name + }`, + testAccMSOFabricResourcePortChannelInterfaceConfigUpdateAddingExtraInterfaceDescription(), + msoFabricResourcePortChannelInterfaceName, + msoFabricResourceTemplateName, + ) +} diff --git a/mso/provider.go b/mso/provider.go index 18d1c7ab..ab309c67 100644 --- a/mso/provider.go +++ b/mso/provider.go @@ -68,155 +68,157 @@ func Provider() terraform.ResourceProvider { }, ResourcesMap: map[string]*schema.Resource{ - "mso_schema": resourceMSOSchema(), - "mso_schema_site": resourceMSOSchemaSite(), - "mso_site": resourceMSOSite(), - "mso_remote_location": resourceMSORemoteLocation(), - "mso_user": resourceMSOUser(), - "mso_label": resourceMSOLabel(), - "mso_schema_template": resourceMSOSchemaTemplate(), - "mso_tenant": resourceMSOTenant(), - "mso_schema_template_bd": resourceMSOTemplateBD(), - "mso_schema_template_vrf": resourceMSOSchemaTemplateVrf(), - "mso_schema_template_bd_subnet": resourceMSOTemplateBDSubnet(), - "mso_schema_template_anp": resourceMSOSchemaTemplateAnp(), - "mso_schema_template_anp_epg": resourceMSOSchemaTemplateAnpEpg(), - "mso_schema_template_anp_epg_contract": resourceMSOTemplateAnpEpgContract(), - "mso_schema_template_contract": resourceMSOTemplateContract(), - "mso_schema_template_anp_epg_subnet": resourceMSOSchemaTemplateAnpEpgSubnet(), - "mso_schema_template_l3out": resourceMSOTemplateL3out(), - "mso_schema_template_external_epg": resourceMSOTemplateExtenalepg(), - "mso_schema_template_contract_filter": resourceMSOTemplateContractFilter(), - "mso_schema_template_external_epg_contract": resourceMSOTemplateExternalEpgContract(), - "mso_schema_template_filter_entry": resourceMSOSchemaTemplateFilterEntry(), - "mso_schema_template_external_epg_subnet": resourceMSOTemplateExtenalepgSubnet(), - "mso_schema_site_anp_epg_static_leaf": resourceMSOSchemaSiteAnpEpgStaticleaf(), - "mso_schema_site_anp_epg_static_port": resourceMSOSchemaSiteAnpEpgStaticPort(), - "mso_schema_site_anp_epg_bulk_staticport": resourceMSOSchemaSiteAnpEpgBulkStaticPort(), - "mso_schema_site_bd": resourceMSOSchemaSiteBd(), - "mso_schema_site_anp_epg_subnet": resourceMSOSchemaSiteAnpEpgSubnet(), - "mso_schema_site_anp_epg_domain": resourceMSOSchemaSiteAnpEpgDomain(), - "mso_schema_site_bd_l3out": resourceMSOSchemaSiteBdL3out(), - "mso_schema_site_vrf": resourceMSOSchemaSiteVrf(), - "mso_schema_site_vrf_route_leak": resourceMSOSchemaSiteVrfRouteLeak(), - "mso_schema_site_vrf_region": resourceMSOSchemaSiteVrfRegion(), - "mso_schema_site_bd_subnet": resourceMSOSchemaSiteBdSubnet(), - "mso_rest": resourceMSORest(), - "mso_schema_template_deploy": resourceMSOSchemaTemplateDeploy(), - "mso_schema_template_deploy_ndo": resourceNDOSchemaTemplateDeploy(), - "mso_schema_site_vrf_region_cidr_subnet": resourceMSOSchemaSiteVrfRegionCidrSubnet(), - "mso_schema_site_vrf_region_cidr": resourceMSOSchemaSiteVrfRegionCidr(), - "mso_schema_site_anp": resourceMSOSchemaSiteAnp(), - "mso_schema_site_anp_epg": resourceMSOSchemaSiteAnpEpg(), - "mso_schema_template_anp_epg_selector": resourceMSOSchemaTemplateAnpEpgSelector(), - "mso_schema_site_external_epg": resourceMSOSchemaSiteExternalEpg(), - "mso_schema_template_external_epg_selector": resourceSchemaTemplateExternalEPGSelector(), - "mso_schema_template_anp_epg_useg_attr": resourceMSOSchemaTemplateAnpEpgUsegAttr(), - "mso_schema_site_anp_epg_selector": resourceMSOSchemaSiteAnpEpgSelector(), - "mso_schema_template_vrf_contract": resourceMSOTemplateVRFContract(), - "mso_schema_site_external_epg_selector": resourceMSOSchemaSiteExternalEpgSelector(), - "mso_schema_template_service_graph": resourceMSOSchemaTemplateServiceGraphs(), - "mso_schema_site_service_graph_node": resourceMSOSchemaSiteServiceGraphNode(), - "mso_schema_site_service_graph": resourceMSOSchemaSiteServiceGraph(), - "mso_service_node_type": resourceMSOServiceNodeType(), - "mso_schema_template_contract_service_graph": resourceMSOSchemaTemplateContractServiceGraph(), - "mso_system_config": resourceMSOSystemConfig(), - "mso_schema_site_contract_service_graph": resourceMSOSchemaSiteContractServiceGraph(), - "mso_schema_site_contract_service_graph_listener": resourceMSOSchemaSiteContractServiceGraphListener(), - "mso_template": resourceMSOTemplate(), - "mso_tenant_policies_ipsla_monitoring_policy": resourceMSOIPSLAMonitoringPolicy(), - "mso_tenant_policies_route_map_policy_multicast": resourceMSOMcastRouteMapPolicy(), - "mso_tenant_policies_dhcp_relay_policy": resourceMSOTenantPoliciesDHCPRelayPolicy(), - "mso_fabric_policies_vlan_pool": resourceMSOVlanPool(), - "mso_fabric_policies_physical_domain": resourceMSOPhysicalDomain(), - "mso_service_device_cluster": resourceMSOServiceDeviceCluster(), - "mso_fabric_policies_synce_interface_policy": resourceMSOSyncEInterfacePolicy(), - "mso_fabric_policies_macsec_policy": resourceMSOMacsecPolicy(), - "mso_schema_template_contract_service_chaining": resourceMSOSchemaTemplateContractServiceChaining(), - "mso_tenant_policies_bgp_peer_prefix_policy": resourceMSOBGPPeerPrefixPolicy(), - "mso_fabric_policies_l3_domain": resourceMSOL3Domain(), - "mso_tenant_policies_custom_qos_policy": resourceMSOCustomQoSPolicy(), - "mso_tenant_policies_dhcp_option_policy": resourceMSODHCPOptionPolicy(), - "mso_tenant_policies_mld_snooping_policy": resourceMSOMLDSnoopingPolicy(), - "mso_fabric_policies_mcp_global_policy": resourceMSOMCPGlobalPolicy(), - "mso_tenant_policies_ipsla_track_list": resourceMSOIPSLATrackList(), - "mso_tenant_policies_l3out_interface_routing_policy": resourceMSOL3OutInterfaceRoutingPolicy(), - "mso_fabric_policies_interface_setting": resourceMSOInterfaceSetting(), + "mso_schema": resourceMSOSchema(), + "mso_schema_site": resourceMSOSchemaSite(), + "mso_site": resourceMSOSite(), + "mso_remote_location": resourceMSORemoteLocation(), + "mso_user": resourceMSOUser(), + "mso_label": resourceMSOLabel(), + "mso_schema_template": resourceMSOSchemaTemplate(), + "mso_tenant": resourceMSOTenant(), + "mso_schema_template_bd": resourceMSOTemplateBD(), + "mso_schema_template_vrf": resourceMSOSchemaTemplateVrf(), + "mso_schema_template_bd_subnet": resourceMSOTemplateBDSubnet(), + "mso_schema_template_anp": resourceMSOSchemaTemplateAnp(), + "mso_schema_template_anp_epg": resourceMSOSchemaTemplateAnpEpg(), + "mso_schema_template_anp_epg_contract": resourceMSOTemplateAnpEpgContract(), + "mso_schema_template_contract": resourceMSOTemplateContract(), + "mso_schema_template_anp_epg_subnet": resourceMSOSchemaTemplateAnpEpgSubnet(), + "mso_schema_template_l3out": resourceMSOTemplateL3out(), + "mso_schema_template_external_epg": resourceMSOTemplateExtenalepg(), + "mso_schema_template_contract_filter": resourceMSOTemplateContractFilter(), + "mso_schema_template_external_epg_contract": resourceMSOTemplateExternalEpgContract(), + "mso_schema_template_filter_entry": resourceMSOSchemaTemplateFilterEntry(), + "mso_schema_template_external_epg_subnet": resourceMSOTemplateExtenalepgSubnet(), + "mso_schema_site_anp_epg_static_leaf": resourceMSOSchemaSiteAnpEpgStaticleaf(), + "mso_schema_site_anp_epg_static_port": resourceMSOSchemaSiteAnpEpgStaticPort(), + "mso_schema_site_anp_epg_bulk_staticport": resourceMSOSchemaSiteAnpEpgBulkStaticPort(), + "mso_schema_site_bd": resourceMSOSchemaSiteBd(), + "mso_schema_site_anp_epg_subnet": resourceMSOSchemaSiteAnpEpgSubnet(), + "mso_schema_site_anp_epg_domain": resourceMSOSchemaSiteAnpEpgDomain(), + "mso_schema_site_bd_l3out": resourceMSOSchemaSiteBdL3out(), + "mso_schema_site_vrf": resourceMSOSchemaSiteVrf(), + "mso_schema_site_vrf_route_leak": resourceMSOSchemaSiteVrfRouteLeak(), + "mso_schema_site_vrf_region": resourceMSOSchemaSiteVrfRegion(), + "mso_schema_site_bd_subnet": resourceMSOSchemaSiteBdSubnet(), + "mso_rest": resourceMSORest(), + "mso_schema_template_deploy": resourceMSOSchemaTemplateDeploy(), + "mso_schema_template_deploy_ndo": resourceNDOSchemaTemplateDeploy(), + "mso_schema_site_vrf_region_cidr_subnet": resourceMSOSchemaSiteVrfRegionCidrSubnet(), + "mso_schema_site_vrf_region_cidr": resourceMSOSchemaSiteVrfRegionCidr(), + "mso_schema_site_anp": resourceMSOSchemaSiteAnp(), + "mso_schema_site_anp_epg": resourceMSOSchemaSiteAnpEpg(), + "mso_schema_template_anp_epg_selector": resourceMSOSchemaTemplateAnpEpgSelector(), + "mso_schema_site_external_epg": resourceMSOSchemaSiteExternalEpg(), + "mso_schema_template_external_epg_selector": resourceSchemaTemplateExternalEPGSelector(), + "mso_schema_template_anp_epg_useg_attr": resourceMSOSchemaTemplateAnpEpgUsegAttr(), + "mso_schema_site_anp_epg_selector": resourceMSOSchemaSiteAnpEpgSelector(), + "mso_schema_template_vrf_contract": resourceMSOTemplateVRFContract(), + "mso_schema_site_external_epg_selector": resourceMSOSchemaSiteExternalEpgSelector(), + "mso_schema_template_service_graph": resourceMSOSchemaTemplateServiceGraphs(), + "mso_schema_site_service_graph_node": resourceMSOSchemaSiteServiceGraphNode(), + "mso_schema_site_service_graph": resourceMSOSchemaSiteServiceGraph(), + "mso_service_node_type": resourceMSOServiceNodeType(), + "mso_schema_template_contract_service_graph": resourceMSOSchemaTemplateContractServiceGraph(), + "mso_system_config": resourceMSOSystemConfig(), + "mso_schema_site_contract_service_graph": resourceMSOSchemaSiteContractServiceGraph(), + "mso_schema_site_contract_service_graph_listener": resourceMSOSchemaSiteContractServiceGraphListener(), + "mso_template": resourceMSOTemplate(), + "mso_tenant_policies_ipsla_monitoring_policy": resourceMSOIPSLAMonitoringPolicy(), + "mso_tenant_policies_route_map_policy_multicast": resourceMSOMcastRouteMapPolicy(), + "mso_tenant_policies_dhcp_relay_policy": resourceMSOTenantPoliciesDHCPRelayPolicy(), + "mso_fabric_policies_vlan_pool": resourceMSOVlanPool(), + "mso_fabric_policies_physical_domain": resourceMSOPhysicalDomain(), + "mso_service_device_cluster": resourceMSOServiceDeviceCluster(), + "mso_fabric_policies_synce_interface_policy": resourceMSOSyncEInterfacePolicy(), + "mso_fabric_policies_macsec_policy": resourceMSOMacsecPolicy(), + "mso_schema_template_contract_service_chaining": resourceMSOSchemaTemplateContractServiceChaining(), + "mso_tenant_policies_bgp_peer_prefix_policy": resourceMSOBGPPeerPrefixPolicy(), + "mso_fabric_policies_l3_domain": resourceMSOL3Domain(), + "mso_tenant_policies_custom_qos_policy": resourceMSOCustomQoSPolicy(), + "mso_tenant_policies_dhcp_option_policy": resourceMSODHCPOptionPolicy(), + "mso_tenant_policies_mld_snooping_policy": resourceMSOMLDSnoopingPolicy(), + "mso_fabric_policies_mcp_global_policy": resourceMSOMCPGlobalPolicy(), + "mso_tenant_policies_ipsla_track_list": resourceMSOIPSLATrackList(), + "mso_tenant_policies_l3out_interface_routing_policy": resourceMSOL3OutInterfaceRoutingPolicy(), + "mso_fabric_policies_interface_setting": resourceMSOInterfaceSetting(), + "mso_fabric_resource_policies_port_channel_interface": resourceMSOPortChannelInterface(), }, DataSourcesMap: map[string]*schema.Resource{ - "mso_schema": datasourceMSOSchema(), - "mso_schema_site": datasourceMSOSchemaSite(), - "mso_site": datasourceMSOSite(), - "mso_remote_location": datasourceMSORemoteLocation(), - "mso_role": datasourceMSORole(), - "mso_user": datasourceMSOUser(), - "mso_label": datasourceMSOLabel(), - "mso_schema_template": datasourceMSOSchemaTemplate(), - "mso_tenant": datasourceMSOTenant(), - "mso_schema_template_bd": dataSourceMSOTemplateBD(), - "mso_schema_template_vrf": datasourceMSOSchemaTemplateVrf(), - "mso_schema_template_bd_subnet": dataSourceMSOTemplateSubnetBD(), - "mso_schema_template_anp": datasourceMSOSchemaTemplateAnp(), - "mso_schema_template_anp_epg": datasourceMSOSchemaTemplateAnpEpg(), - "mso_schema_template_anp_epg_contract": dataSourceMSOTemplateAnpEpgContract(), - "mso_schema_template_contract": dataSourceMSOTemplateContract(), - "mso_schema_template_anp_epg_subnet": dataSourceMSOSchemaTemplateAnpEpgSubnet(), - "mso_schema_template_l3out": dataSourceMSOTemplateL3out(), - "mso_schema_template_external_epg": dataSourceMSOTemplateExternalepg(), - "mso_schema_template_contract_filter": dataSourceMSOTemplateContractFilter(), - "mso_schema_template_external_epg_contract": dataSourceMSOTemplateExternalEpgContract(), - "mso_schema_template_filter_entry": dataSourceMSOSchemaTemplateFilterEntry(), - "mso_schema_template_external_epg_subnet": dataSourceMSOTemplateExternalEpgSubnet(), - "mso_schema_site_anp": dataSourceMSOSchemaSiteAnp(), - "mso_schema_site_anp_epg": dataSourceMSOSchemaSiteAnpEpg(), - "mso_schema_site_anp_epg_static_leaf": dataSourceMSOSchemaSiteAnpEpgStaticleaf(), - "mso_schema_site_anp_epg_static_port": datasourceMSOSchemaSiteAnpEpgStaticPort(), - "mso_schema_site_anp_epg_bulk_staticport": datasourceMSOSchemaSiteAnpEpgBulkStaticPort(), - "mso_schema_site_bd": dataSourceMSOSchemaSiteBd(), - "mso_schema_site_anp_epg_subnet": datasourceMSOSchemaSiteAnpEpgSubnet(), - "mso_schema_site_anp_epg_domain": dataSourceMSOSchemaSiteAnpEpgDomain(), - "mso_schema_site_bd_l3out": dataSourceMSOSchemaSiteBdL3out(), - "mso_schema_site_vrf": dataSourceMSOSchemaSiteVrf(), - "mso_schema_site_vrf_region": dataSourceMSOSchemaSiteVrfRegion(), - "mso_schema_site_vrf_route_leak": dataSourceMSOSchemaSiteVrfRouteLeak(), - "mso_schema_site_bd_subnet": dataSourceMSOSchemaSiteBdSubnet(), - "mso_schema_site_vrf_region_cidr_subnet": dataSourceMSOSchemaSiteVrfRegionCidrSubnet(), - "mso_schema_site_vrf_region_cidr": dataSourceMSOSchemaSiteVrfRegionCidr(), - "mso_schema_template_anp_epg_selector": datasourceMSOSchemaTemplateAnpEpgSelector(), - "mso_schema_site_external_epg": dataSourceMSOSchemaSiteExternalEpg(), - "mso_schema_template_external_epg_selector": datasourceSchemaTemplateExternalEPGSelector(), - "mso_schema_template_anp_epg_useg_attr": dataSourceMSOSchemaTemplateAnpEpgUsegAttr(), - "mso_schema_site_anp_epg_selector": datasourceMSOSchemaSiteAnpEpgSelector(), - "mso_schema_template_vrf_contract": dataSourceMSOTemplateVRFContract(), - "mso_schema_site_external_epg_selector": datasourceMSOSchemaSiteExternalEpgSelector(), - "mso_schema_template_service_graph": dataSourceMSOSchemaTemplateServiceGraph(), - "mso_service_node_type": dataSourceMSOServiceNodeType(), - "mso_schema_site_service_graph": datasourceMSOSchemaSiteServiceGraph(), - "mso_schema_template_contract_service_graph": dataSourceMSOSchemaTemplateContractServiceGraph(), - "mso_system_config": dataSourceMSOSystemConfig(), - "mso_rest": datasourceMSORest(), - "mso_schema_site_contract_service_graph": dataSourceMSOSchemaSiteContractServiceGraph(), - "mso_schema_site_contract_service_graph_listener": dataSourceMSOSchemaSiteContractServiceGraphListener(), - "mso_template": datasourceMSOTemplate(), - "mso_tenant_policies_ipsla_monitoring_policy": datasourceMSOIPSLAMonitoringPolicy(), - "mso_tenant_policies_route_map_policy_multicast": datasourceMSOMcastRouteMapPolicy(), - "mso_tenant_policies_dhcp_relay_policy": datasourceMSOTenantPoliciesDHCPRelayPolicy(), - "mso_fabric_policies_vlan_pool": datasourceMSOVlanPool(), - "mso_fabric_policies_physical_domain": datasourceMSOPhysicalDomain(), - "mso_service_device_cluster": datasourceMSOServiceDeviceCluster(), - "mso_fabric_policies_synce_interface_policy": datasourceMSOSyncEInterfacePolicy(), - "mso_fabric_policies_macsec_policy": datasourceMacsecPolicy(), - "mso_schema_template_contract_service_chaining": datasourceMSOSchemaTemplateContractServiceChaining(), - "mso_tenant_policies_bgp_peer_prefix_policy": datasourceMSOBGPPeerPrefixPolicy(), - "mso_fabric_policies_l3_domain": datasourceMSOL3Domain(), - "mso_tenant_policies_custom_qos_policy": datasourceMSOCustomQoSPolicy(), - "mso_tenant_policies_dhcp_option_policy": datasourceMSODHCPOptionPolicy(), - "mso_tenant_policies_mld_snooping_policy": datasourceMSOMLDSnoopingPolicy(), - "mso_fabric_policies_mcp_global_policy": datasourceMSOMCPGlobalPolicy(), - "mso_tenant_policies_ipsla_track_list": datasourceMSOIPSLATrackList(), - "mso_tenant_policies_l3out_interface_routing_policy": datasourceMSOL3OutInterfaceRoutingPolicy(), - "mso_fabric_policies_interface_setting": datasourceMSOInterfaceSetting(), + "mso_schema": datasourceMSOSchema(), + "mso_schema_site": datasourceMSOSchemaSite(), + "mso_site": datasourceMSOSite(), + "mso_remote_location": datasourceMSORemoteLocation(), + "mso_role": datasourceMSORole(), + "mso_user": datasourceMSOUser(), + "mso_label": datasourceMSOLabel(), + "mso_schema_template": datasourceMSOSchemaTemplate(), + "mso_tenant": datasourceMSOTenant(), + "mso_schema_template_bd": dataSourceMSOTemplateBD(), + "mso_schema_template_vrf": datasourceMSOSchemaTemplateVrf(), + "mso_schema_template_bd_subnet": dataSourceMSOTemplateSubnetBD(), + "mso_schema_template_anp": datasourceMSOSchemaTemplateAnp(), + "mso_schema_template_anp_epg": datasourceMSOSchemaTemplateAnpEpg(), + "mso_schema_template_anp_epg_contract": dataSourceMSOTemplateAnpEpgContract(), + "mso_schema_template_contract": dataSourceMSOTemplateContract(), + "mso_schema_template_anp_epg_subnet": dataSourceMSOSchemaTemplateAnpEpgSubnet(), + "mso_schema_template_l3out": dataSourceMSOTemplateL3out(), + "mso_schema_template_external_epg": dataSourceMSOTemplateExternalepg(), + "mso_schema_template_contract_filter": dataSourceMSOTemplateContractFilter(), + "mso_schema_template_external_epg_contract": dataSourceMSOTemplateExternalEpgContract(), + "mso_schema_template_filter_entry": dataSourceMSOSchemaTemplateFilterEntry(), + "mso_schema_template_external_epg_subnet": dataSourceMSOTemplateExternalEpgSubnet(), + "mso_schema_site_anp": dataSourceMSOSchemaSiteAnp(), + "mso_schema_site_anp_epg": dataSourceMSOSchemaSiteAnpEpg(), + "mso_schema_site_anp_epg_static_leaf": dataSourceMSOSchemaSiteAnpEpgStaticleaf(), + "mso_schema_site_anp_epg_static_port": datasourceMSOSchemaSiteAnpEpgStaticPort(), + "mso_schema_site_anp_epg_bulk_staticport": datasourceMSOSchemaSiteAnpEpgBulkStaticPort(), + "mso_schema_site_bd": dataSourceMSOSchemaSiteBd(), + "mso_schema_site_anp_epg_subnet": datasourceMSOSchemaSiteAnpEpgSubnet(), + "mso_schema_site_anp_epg_domain": dataSourceMSOSchemaSiteAnpEpgDomain(), + "mso_schema_site_bd_l3out": dataSourceMSOSchemaSiteBdL3out(), + "mso_schema_site_vrf": dataSourceMSOSchemaSiteVrf(), + "mso_schema_site_vrf_region": dataSourceMSOSchemaSiteVrfRegion(), + "mso_schema_site_vrf_route_leak": dataSourceMSOSchemaSiteVrfRouteLeak(), + "mso_schema_site_bd_subnet": dataSourceMSOSchemaSiteBdSubnet(), + "mso_schema_site_vrf_region_cidr_subnet": dataSourceMSOSchemaSiteVrfRegionCidrSubnet(), + "mso_schema_site_vrf_region_cidr": dataSourceMSOSchemaSiteVrfRegionCidr(), + "mso_schema_template_anp_epg_selector": datasourceMSOSchemaTemplateAnpEpgSelector(), + "mso_schema_site_external_epg": dataSourceMSOSchemaSiteExternalEpg(), + "mso_schema_template_external_epg_selector": datasourceSchemaTemplateExternalEPGSelector(), + "mso_schema_template_anp_epg_useg_attr": dataSourceMSOSchemaTemplateAnpEpgUsegAttr(), + "mso_schema_site_anp_epg_selector": datasourceMSOSchemaSiteAnpEpgSelector(), + "mso_schema_template_vrf_contract": dataSourceMSOTemplateVRFContract(), + "mso_schema_site_external_epg_selector": datasourceMSOSchemaSiteExternalEpgSelector(), + "mso_schema_template_service_graph": dataSourceMSOSchemaTemplateServiceGraph(), + "mso_service_node_type": dataSourceMSOServiceNodeType(), + "mso_schema_site_service_graph": datasourceMSOSchemaSiteServiceGraph(), + "mso_schema_template_contract_service_graph": dataSourceMSOSchemaTemplateContractServiceGraph(), + "mso_system_config": dataSourceMSOSystemConfig(), + "mso_rest": datasourceMSORest(), + "mso_schema_site_contract_service_graph": dataSourceMSOSchemaSiteContractServiceGraph(), + "mso_schema_site_contract_service_graph_listener": dataSourceMSOSchemaSiteContractServiceGraphListener(), + "mso_template": datasourceMSOTemplate(), + "mso_tenant_policies_ipsla_monitoring_policy": datasourceMSOIPSLAMonitoringPolicy(), + "mso_tenant_policies_route_map_policy_multicast": datasourceMSOMcastRouteMapPolicy(), + "mso_tenant_policies_dhcp_relay_policy": datasourceMSOTenantPoliciesDHCPRelayPolicy(), + "mso_fabric_policies_vlan_pool": datasourceMSOVlanPool(), + "mso_fabric_policies_physical_domain": datasourceMSOPhysicalDomain(), + "mso_service_device_cluster": datasourceMSOServiceDeviceCluster(), + "mso_fabric_policies_synce_interface_policy": datasourceMSOSyncEInterfacePolicy(), + "mso_fabric_policies_macsec_policy": datasourceMacsecPolicy(), + "mso_schema_template_contract_service_chaining": datasourceMSOSchemaTemplateContractServiceChaining(), + "mso_tenant_policies_bgp_peer_prefix_policy": datasourceMSOBGPPeerPrefixPolicy(), + "mso_fabric_policies_l3_domain": datasourceMSOL3Domain(), + "mso_tenant_policies_custom_qos_policy": datasourceMSOCustomQoSPolicy(), + "mso_tenant_policies_dhcp_option_policy": datasourceMSODHCPOptionPolicy(), + "mso_tenant_policies_mld_snooping_policy": datasourceMSOMLDSnoopingPolicy(), + "mso_fabric_policies_mcp_global_policy": datasourceMSOMCPGlobalPolicy(), + "mso_tenant_policies_ipsla_track_list": datasourceMSOIPSLATrackList(), + "mso_tenant_policies_l3out_interface_routing_policy": datasourceMSOL3OutInterfaceRoutingPolicy(), + "mso_fabric_policies_interface_setting": datasourceMSOInterfaceSetting(), + "mso_fabric_resource_policies_port_channel_interface": datasourceMSOPortChannelInterface(), }, ConfigureFunc: configureClient, diff --git a/mso/resource_mso_fabric_resource_policies_port_channel_interface.go b/mso/resource_mso_fabric_resource_policies_port_channel_interface.go new file mode 100644 index 00000000..b5275259 --- /dev/null +++ b/mso/resource_mso_fabric_resource_policies_port_channel_interface.go @@ -0,0 +1,381 @@ +package mso + +import ( + "fmt" + "log" + "strings" + + "github.com/ciscoecosystem/mso-go-client/client" + "github.com/ciscoecosystem/mso-go-client/container" + "github.com/ciscoecosystem/mso-go-client/models" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/helper/validation" +) + +func resourceMSOPortChannelInterface() *schema.Resource { + return &schema.Resource{ + Create: resourceMSOPortChannelInterfaceCreate, + Read: resourceMSOPortChannelInterfaceRead, + Update: resourceMSOPortChannelInterfaceUpdate, + Delete: resourceMSOPortChannelInterfaceDelete, + Importer: &schema.ResourceImporter{ + State: resourceMSOPortChannelInterfaceImport, + }, + + CustomizeDiff: customizeDiffPortChannelInterface, + + SchemaVersion: 1, + Schema: map[string]*schema.Schema{ + "template_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "name": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringLenBetween(1, 64), + }, + "description": { + Type: schema.TypeString, + Optional: true, + Computed: true, + }, + "node": { + Type: schema.TypeString, + Required: true, + }, + "interfaces": { + Type: schema.TypeSet, + Required: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "interface_policy_uuid": { + Type: schema.TypeString, + Required: true, + }, + "interface_descriptions": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "interface": { + Type: schema.TypeString, + Required: true, + }, + "description": { + Type: schema.TypeString, + Optional: true, + Computed: true, + }, + }, + }, + }, + "uuid": { + Type: schema.TypeString, + Computed: true, + }, + }, + } +} + +func customizeDiffPortChannelInterface(d *schema.ResourceDiff, m interface{}) error { + interfacesRaw := d.Get("interfaces") + if interfacesRaw == nil { + return nil + } + interfaces := interfacesRaw.(*schema.Set) + if interfaces.Len() == 0 { + return nil + } + + // Create a map for quick lookup + interfaceMap := make(map[string]bool) + for _, memberInterface := range interfaces.List() { + interfaceMap[memberInterface.(string)] = true + } + + interfaceDescriptionsRaw := d.Get("interface_descriptions") + if interfaceDescriptionsRaw == nil { + return nil + } + interfaceDescriptions := interfaceDescriptionsRaw.(*schema.Set) + if interfaceDescriptions.Len() == 0 { + return nil + } + + // Validate each interface_description + for _, interfaceDescriptionRaw := range interfaceDescriptions.List() { + interfaceDescription := interfaceDescriptionRaw.(map[string]interface{}) + interfaceID := interfaceDescription["interface"].(string) + + if !interfaceMap[interfaceID] { + return fmt.Errorf("Interface '%s' specified in 'interface_descriptions' must be defined in the 'interfaces' list", interfaceID) + } + } + + return nil +} + +func getInterfaceDescriptionsPayload(node string, interfaceDescriptions *schema.Set) []map[string]interface{} { + interfaceDescriptionsList := interfaceDescriptions.List() + payload := make([]map[string]interface{}, 0, len(interfaceDescriptionsList)) + for _, interfaceDescription := range interfaceDescriptionsList { + interfaceDescriptionMap := interfaceDescription.(map[string]interface{}) + payload = append(payload, map[string]interface{}{ + "nodeID": node, + "interfaceID": interfaceDescriptionMap["interface"].(string), + "description": interfaceDescriptionMap["description"].(string), + }) + } + return payload +} + +func interfaceSetToString(interfaceSet *schema.Set) string { + if interfaceSet == nil || interfaceSet.Len() == 0 { + return "" + } + interfaceList := make([]string, 0, interfaceSet.Len()) + for _, memberInterface := range interfaceSet.List() { + interfaceList = append(interfaceList, memberInterface.(string)) + } + return strings.Join(interfaceList, ",") +} + +func interfaceStringToSet(interfaceString string) []interface{} { + if interfaceString == "" { + return []interface{}{} + } + interfaceList := strings.Split(interfaceString, ",") + interfaceSet := make([]interface{}, 0, len(interfaceList)) + for _, interfaceID := range interfaceList { + cleanedInterfaceID := strings.TrimSpace(interfaceID) + if cleanedInterfaceID != "" { + interfaceSet = append(interfaceSet, cleanedInterfaceID) + } + } + return interfaceSet +} + +func setPortChannelInterfaceData(d *schema.ResourceData, response *container.Container, templateId string) error { + d.SetId(fmt.Sprintf("templateId/%s/PortChannelInterface/%s", templateId, models.StripQuotes(response.S("name").String()))) + d.Set("template_id", templateId) + d.Set("name", models.StripQuotes(response.S("name").String())) + d.Set("description", models.StripQuotes(response.S("description").String())) + d.Set("uuid", models.StripQuotes(response.S("uuid").String())) + d.Set("node", models.StripQuotes(response.S("node").String())) + d.Set("interfaces", interfaceStringToSet(models.StripQuotes(response.S("memberInterfaces").String()))) + + if response.Exists("policy") { + d.Set("interface_policy_uuid", models.StripQuotes(response.S("policy").String())) + } + + interfaceDescriptionsList := make([]map[string]interface{}, 0) + count, err := response.ArrayCount("interfaceDescriptions") + if err == nil { + for i := range count { + descriptionContainer, err := response.ArrayElement(i, "interfaceDescriptions") + if err != nil { + return err + } + interfaceDescriptionsList = append(interfaceDescriptionsList, map[string]interface{}{ + "interface": models.StripQuotes(descriptionContainer.S("interfaceID").String()), + "description": models.StripQuotes(descriptionContainer.S("description").String()), + }) + } + } + + d.Set("interface_descriptions", interfaceDescriptionsList) + + return nil +} + +func resourceMSOPortChannelInterfaceImport(d *schema.ResourceData, m interface{}) ([]*schema.ResourceData, error) { + log.Printf("[DEBUG] MSO Port Channel Interface Resource - Beginning Import: %v", d.Id()) + resourceMSOPortChannelInterfaceRead(d, m) + log.Printf("[DEBUG] MSO Port Channel Interface Resource - Import Complete: %v", d.Id()) + return []*schema.ResourceData{d}, nil +} + +func resourceMSOPortChannelInterfaceCreate(d *schema.ResourceData, m interface{}) error { + log.Printf("[DEBUG] MSO Port Channel Interface Resource - Beginning Create: %v", d.Id()) + msoClient := m.(*client.Client) + + templateId := d.Get("template_id").(string) + + payload := map[string]interface{}{ + "name": d.Get("name").(string), + "templateId": templateId, + } + + if description, ok := d.GetOk("description"); ok { + payload["description"] = description.(string) + } + + node := d.Get("node").(string) + if node != "" { + payload["node"] = node + } + + if memberInterfaces, ok := d.GetOk("interfaces"); ok { + payload["memberInterfaces"] = interfaceSetToString(memberInterfaces.(*schema.Set)) + } + + if interfacePolicyUUID, ok := d.GetOk("interface_policy_uuid"); ok { + payload["policy"] = interfacePolicyUUID.(string) + } + + if interfaceDescriptions, ok := d.GetOk("interface_descriptions"); ok { + payload["interfaceDescriptions"] = getInterfaceDescriptionsPayload(node, interfaceDescriptions.(*schema.Set)) + } + + payloadModel := models.GetPatchPayload("add", "/fabricResourceTemplate/template/portChannels/-", payload) + + _, err := msoClient.PatchbyID(fmt.Sprintf("api/v1/templates/%s", templateId), payloadModel) + if err != nil { + return err + } + + d.SetId(fmt.Sprintf("templateId/%s/PortChannelInterface/%s", templateId, d.Get("name").(string))) + log.Printf("[DEBUG] MSO Port Channel Interface Resource - Create Complete: %v", d.Id()) + return resourceMSOPortChannelInterfaceRead(d, m) +} + +func resourceMSOPortChannelInterfaceRead(d *schema.ResourceData, m interface{}) error { + log.Printf("[DEBUG] MSO Port Channel Interface Resource - Beginning Read: %v", d.Id()) + msoClient := m.(*client.Client) + + templateId, err := GetTemplateIdFromResourceId(d.Id()) + if err != nil { + return err + } + + response, err := msoClient.GetViaURL(fmt.Sprintf("api/v1/templates/%s", templateId)) + if err != nil { + return err + } + + policyName, err := GetPolicyNameFromResourceId(d.Id(), "PortChannelInterface") + if err != nil { + return err + } + + policy, err := GetPolicyByName(response, policyName, "fabricResourceTemplate", "template", "portChannels") + if err != nil { + return err + } + + err = setPortChannelInterfaceData(d, policy, templateId) + if err != nil { + return err + } + + log.Printf("[DEBUG] MSO Port Channel Interface Resource - Read Complete: %v", d.Id()) + return nil +} + +func resourceMSOPortChannelInterfaceUpdate(d *schema.ResourceData, m interface{}) error { + log.Printf("[DEBUG] MSO Port Channel Interface Resource - Beginning Update: %v", d.Id()) + msoClient := m.(*client.Client) + templateId := d.Get("template_id").(string) + node := d.Get("node").(string) + + templateContainer, err := msoClient.GetViaURL(fmt.Sprintf("api/v1/templates/%s", templateId)) + if err != nil { + return err + } + + policyIndex, err := GetPolicyIndexByKeyAndValue(templateContainer, "uuid", d.Get("uuid").(string), "fabricResourceTemplate", "template", "portChannels") + if err != nil { + return err + } + + updatePath := fmt.Sprintf("/fabricResourceTemplate/template/portChannels/%d", policyIndex) + + payloadCont := container.New() + payloadCont.Array() + + if d.HasChange("name") { + err := addPatchPayloadToContainer(payloadCont, "replace", fmt.Sprintf("%s/name", updatePath), d.Get("name").(string)) + if err != nil { + return err + } + } + + if d.HasChange("description") { + err := addPatchPayloadToContainer(payloadCont, "replace", fmt.Sprintf("%s/description", updatePath), d.Get("description").(string)) + if err != nil { + return err + } + } + + if d.HasChange("node") { + err := addPatchPayloadToContainer(payloadCont, "replace", fmt.Sprintf("%s/node", updatePath), d.Get("node").(string)) + if err != nil { + return err + } + } + + if d.HasChange("interfaces") { + err := addPatchPayloadToContainer(payloadCont, "replace", fmt.Sprintf("%s/memberInterfaces", updatePath), interfaceSetToString(d.Get("interfaces").(*schema.Set))) + if err != nil { + return err + } + } + + if d.HasChange("interface_policy_uuid") { + interfacePolicyUUID := d.Get("interface_policy_uuid").(string) + if interfacePolicyUUID != "" { + err := addPatchPayloadToContainer(payloadCont, "replace", fmt.Sprintf("%s/policy", updatePath), interfacePolicyUUID) + if err != nil { + return err + } + } + } + + if d.HasChange("interface_descriptions") { + err := addPatchPayloadToContainer(payloadCont, "replace", fmt.Sprintf("%s/interfaceDescriptions", updatePath), getInterfaceDescriptionsPayload(node, d.Get("interface_descriptions").(*schema.Set))) + if err != nil { + return err + } + } + + err = doPatchRequest(msoClient, fmt.Sprintf("api/v1/templates/%s", templateId), payloadCont) + if err != nil { + return err + } + + d.SetId(fmt.Sprintf("templateId/%s/PortChannelInterface/%s", templateId, d.Get("name").(string))) + log.Printf("[DEBUG] MSO Port Channel Interface Resource - Update Complete: %v", d.Id()) + return resourceMSOPortChannelInterfaceRead(d, m) +} + +func resourceMSOPortChannelInterfaceDelete(d *schema.ResourceData, m interface{}) error { + log.Printf("[DEBUG] MSO Port Channel Interface Resource - Beginning Delete: %v", d.Id()) + msoClient := m.(*client.Client) + + templateId := d.Get("template_id").(string) + + templateContainer, err := msoClient.GetViaURL(fmt.Sprintf("api/v1/templates/%s", templateId)) + if err != nil { + return err + } + + policyIndex, err := GetPolicyIndexByKeyAndValue(templateContainer, "uuid", d.Get("uuid").(string), "fabricResourceTemplate", "template", "portChannels") + if err != nil { + return err + } + + payloadModel := models.GetRemovePatchPayload(fmt.Sprintf("/fabricResourceTemplate/template/portChannels/%d", policyIndex)) + + _, err = msoClient.PatchbyID(fmt.Sprintf("api/v1/templates/%s", templateId), payloadModel) + if err != nil { + return err + } + + d.SetId("") + log.Printf("[DEBUG] MSO Port Channel Interface Resource - Delete Complete: %v", d.Id()) + return nil +} diff --git a/mso/resource_mso_fabric_resource_policies_port_channel_interface_test.go b/mso/resource_mso_fabric_resource_policies_port_channel_interface_test.go new file mode 100644 index 00000000..713849cb --- /dev/null +++ b/mso/resource_mso_fabric_resource_policies_port_channel_interface_test.go @@ -0,0 +1,162 @@ +package mso + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" +) + +var msoFabricResourcePortChannelInterfacePolicyUUID = "97c9e606-cfd6-4bb9-bcf9-10efae49dcfb" + +func TestAccMSOFabricResourcePortChannelInterfaceResource(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + PreConfig: func() { fmt.Println("Test: Create Port Channel Interface") }, + Config: testAccMSOFabricResourcePortChannelInterfaceConfigCreate(), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("mso_fabric_resource_policies_port_channel_interface."+msoFabricResourcePortChannelInterfaceName, "name", msoFabricResourcePortChannelInterfaceName), + resource.TestCheckResourceAttr("mso_fabric_resource_policies_port_channel_interface."+msoFabricResourcePortChannelInterfaceName, "description", "Terraform test Port Channel Interface"), + resource.TestCheckResourceAttr("mso_fabric_resource_policies_port_channel_interface."+msoFabricResourcePortChannelInterfaceName, "node", "101"), + resource.TestCheckResourceAttr("mso_fabric_resource_policies_port_channel_interface."+msoFabricResourcePortChannelInterfaceName, "interfaces.#", "2"), + resource.TestCheckResourceAttrSet("mso_fabric_resource_policies_port_channel_interface."+msoFabricResourcePortChannelInterfaceName, "uuid"), + resource.TestCheckResourceAttrSet("mso_fabric_resource_policies_port_channel_interface."+msoFabricResourcePortChannelInterfaceName, "template_id"), + resource.TestCheckResourceAttrSet("mso_fabric_resource_policies_port_channel_interface."+msoFabricResourcePortChannelInterfaceName, "interface_policy_uuid"), + ), + }, + { + PreConfig: func() { fmt.Println("Test: Update Port Channel Interface adding interface descriptions") }, + Config: testAccMSOFabricResourcePortChannelInterfaceConfigUpdateAddingInterfaceDescriptions(), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("mso_fabric_resource_policies_port_channel_interface."+msoFabricResourcePortChannelInterfaceName, "name", msoFabricResourcePortChannelInterfaceName), + resource.TestCheckResourceAttr("mso_fabric_resource_policies_port_channel_interface."+msoFabricResourcePortChannelInterfaceName, "description", "Terraform test Port Channel Interface updated"), + resource.TestCheckResourceAttr("mso_fabric_resource_policies_port_channel_interface."+msoFabricResourcePortChannelInterfaceName, "node", "101"), + resource.TestCheckResourceAttr("mso_fabric_resource_policies_port_channel_interface."+msoFabricResourcePortChannelInterfaceName, "interfaces.#", "2"), + resource.TestCheckResourceAttr("mso_fabric_resource_policies_port_channel_interface."+msoFabricResourcePortChannelInterfaceName, "interface_descriptions.#", "1"), + CustomTestCheckTypeSetElemAttrs("mso_fabric_resource_policies_port_channel_interface."+msoFabricResourcePortChannelInterfaceName, "interface_descriptions", + map[string]string{ + "interface": "1/1", + "description": "Interface Description 1/1", + }, + ), + ), + }, + { + PreConfig: func() { fmt.Println("Test: Update Port Channel Interface adding extra interface description") }, + Config: testAccMSOFabricResourcePortChannelInterfaceConfigUpdateAddingExtraInterfaceDescription(), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("mso_fabric_resource_policies_port_channel_interface."+msoFabricResourcePortChannelInterfaceName, "name", msoFabricResourcePortChannelInterfaceName), + resource.TestCheckResourceAttr("mso_fabric_resource_policies_port_channel_interface."+msoFabricResourcePortChannelInterfaceName, "description", "Terraform test Port Channel Interface updated"), + resource.TestCheckResourceAttr("mso_fabric_resource_policies_port_channel_interface."+msoFabricResourcePortChannelInterfaceName, "node", "101"), + resource.TestCheckResourceAttr("mso_fabric_resource_policies_port_channel_interface."+msoFabricResourcePortChannelInterfaceName, "interfaces.#", "2"), + resource.TestCheckResourceAttr("mso_fabric_resource_policies_port_channel_interface."+msoFabricResourcePortChannelInterfaceName, "interface_descriptions.#", "2"), + CustomTestCheckTypeSetElemAttrs("mso_fabric_resource_policies_port_channel_interface."+msoFabricResourcePortChannelInterfaceName, "interface_descriptions", + map[string]string{ + "interface": "1/1", + "description": "Interface Description 1/1", + }, + ), + CustomTestCheckTypeSetElemAttrs("mso_fabric_resource_policies_port_channel_interface."+msoFabricResourcePortChannelInterfaceName, "interface_descriptions", + map[string]string{ + "interface": "1/2", + "description": "Interface Description 1/2", + }, + ), + ), + }, + { + PreConfig: func() { fmt.Println("Test: Update Port Channel Interface removing extra interface description") }, + Config: testAccMSOFabricResourcePortChannelInterfaceConfigUpdateRemovingExtraInterfaceDescription(), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("mso_fabric_resource_policies_port_channel_interface."+msoFabricResourcePortChannelInterfaceName, "name", msoFabricResourcePortChannelInterfaceName), + resource.TestCheckResourceAttr("mso_fabric_resource_policies_port_channel_interface."+msoFabricResourcePortChannelInterfaceName, "description", "Terraform test Port Channel Interface updated"), + resource.TestCheckResourceAttr("mso_fabric_resource_policies_port_channel_interface."+msoFabricResourcePortChannelInterfaceName, "node", "101"), + resource.TestCheckResourceAttr("mso_fabric_resource_policies_port_channel_interface."+msoFabricResourcePortChannelInterfaceName, "interfaces.#", "2"), + resource.TestCheckResourceAttr("mso_fabric_resource_policies_port_channel_interface."+msoFabricResourcePortChannelInterfaceName, "interface_descriptions.#", "1"), + CustomTestCheckTypeSetElemAttrs("mso_fabric_resource_policies_port_channel_interface."+msoFabricResourcePortChannelInterfaceName, "interface_descriptions", + map[string]string{ + "interface": "1/2", + "description": "Interface Description 1/2", + }, + ), + ), + }, + { + PreConfig: func() { fmt.Println("Test: Import Port Channel Interface") }, + ResourceName: "mso_fabric_resource_policies_port_channel_interface." + msoFabricResourcePortChannelInterfaceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + CheckDestroy: testCheckResourceDestroyPolicyWithPathAttributesAndArguments("mso_fabric_resource_policies_port_channel_interface", "fabricResourceTemplate", "template", "portChannels"), + }) +} + +var fabricResourcePortChannelInterfacePreConfig = testFabricResourceTemplateConfig() + +func testAccMSOFabricResourcePortChannelInterfaceConfigCreate() string { + return fmt.Sprintf(`%[1]s + resource "mso_fabric_resource_policies_port_channel_interface" "%[2]s" { + template_id = mso_template.%[4]s.id + name = "%[2]s" + description = "Terraform test Port Channel Interface" + node = "101" + interfaces = ["1/1","1/2"] + interface_policy_uuid = "%[3]s" + }`, fabricResourcePortChannelInterfacePreConfig, msoFabricResourcePortChannelInterfaceName, msoFabricResourcePortChannelInterfacePolicyUUID, msoFabricResourceTemplateName) +} + +func testAccMSOFabricResourcePortChannelInterfaceConfigUpdateAddingInterfaceDescriptions() string { + return fmt.Sprintf(`%[1]s + resource "mso_fabric_resource_policies_port_channel_interface" "%[2]s" { + template_id = mso_template.%[4]s.id + name = "%[2]s" + description = "Terraform test Port Channel Interface updated" + node = "101" + interfaces = ["1/1","1/2"] + interface_policy_uuid = "%[3]s" + interface_descriptions { + interface = "1/1" + description = "Interface Description 1/1" + } + }`, fabricResourcePortChannelInterfacePreConfig, msoFabricResourcePortChannelInterfaceName, msoFabricResourcePortChannelInterfacePolicyUUID, msoFabricResourceTemplateName) +} + +func testAccMSOFabricResourcePortChannelInterfaceConfigUpdateAddingExtraInterfaceDescription() string { + return fmt.Sprintf(`%[1]s + resource "mso_fabric_resource_policies_port_channel_interface" "%[2]s" { + template_id = mso_template.%[4]s.id + name = "%[2]s" + description = "Terraform test Port Channel Interface updated" + node = "101" + interfaces = ["1/1","1/2"] + interface_policy_uuid = "%[3]s" + interface_descriptions { + interface = "1/1" + description = "Interface Description 1/1" + } + interface_descriptions { + interface = "1/2" + description = "Interface Description 1/2" + } + }`, fabricResourcePortChannelInterfacePreConfig, msoFabricResourcePortChannelInterfaceName, msoFabricResourcePortChannelInterfacePolicyUUID, msoFabricResourceTemplateName) +} + +func testAccMSOFabricResourcePortChannelInterfaceConfigUpdateRemovingExtraInterfaceDescription() string { + return fmt.Sprintf(`%[1]s + resource "mso_fabric_resource_policies_port_channel_interface" "%[2]s" { + template_id = mso_template.%[4]s.id + name = "%[2]s" + description = "Terraform test Port Channel Interface updated" + node = "101" + interfaces = ["1/1","1/2"] + interface_policy_uuid = "%[3]s" + interface_descriptions { + interface = "1/2" + description = "Interface Description 1/2" + } + }`, fabricResourcePortChannelInterfacePreConfig, msoFabricResourcePortChannelInterfaceName, msoFabricResourcePortChannelInterfacePolicyUUID, msoFabricResourceTemplateName) +} diff --git a/mso/test_constants.go b/mso/test_constants.go index d6ac91e7..16c768a8 100644 --- a/mso/test_constants.go +++ b/mso/test_constants.go @@ -34,6 +34,9 @@ var msoSchemaTemplateVrfL3MulticastName = acctest.RandStringFromCharSet(10, acct const msoSchemaTemplateAnpEpgSubnetIp = "10.0.0.1/24" +var msoFabricResourceTemplateName = acctest.RandStringFromCharSet(10, acctest.CharSetAlpha) +var msoFabricResourcePortChannelInterfaceName = acctest.RandStringFromCharSet(10, acctest.CharSetAlpha) + func testSiteConfigAnsibleTest() string { return fmt.Sprintf(` data "mso_site" "%[1]s" { @@ -292,3 +295,12 @@ resource "mso_schema_template_anp_epg_subnet" "%[1]s_subnet" { } `, msoSchemaTemplateAnpEpgName, msoSchemaName, msoSchemaTemplateName, msoSchemaTemplateAnpName, msoSchemaTemplateAnpEpgName, msoSchemaTemplateAnpEpgSubnetIp) } + +func testFabricResourceTemplateConfig() string { + return fmt.Sprintf(` + resource "mso_template" "%[1]s" { + template_name = "%[1]s" + template_type = "fabric_resource" + } + `, msoFabricResourceTemplateName) +} diff --git a/website/docs/d/fabric_resource_policies_port_channel_interface.html.markdown b/website/docs/d/fabric_resource_policies_port_channel_interface.html.markdown new file mode 100644 index 00000000..faadb4c1 --- /dev/null +++ b/website/docs/d/fabric_resource_policies_port_channel_interface.html.markdown @@ -0,0 +1,43 @@ +--- +layout: "mso" +page_title: "MSO: mso_fabric_resource_policies_port_channel_interface" +sidebar_current: "docs-mso-data-source-fabric_resource_policies_port_channel_interface" +description: |- + Data source for Fabric Resource Policies Port Channel Interface on Cisco Nexus Dashboard Orchestrator (NDO) +--- + + + +# mso_fabric_resource_policies_port_channel_interface # + +Data source for Fabric Resource Policies Port Channel Interface on Cisco Nexus Dashboard Orchestrator (NDO). This data source is supported in NDO v4.1 or higher. + +## GUI Information ## + +* `Location` - Manage -> Fabric Resource Template -> Fabric Resource Policies -> Port Channel Interfaces + +## Example Usage ## + +```hcl +data "mso_fabric_resource_policies_port_channel_interface" "example" { + template_id = mso_template.fabric_resource_template.id + name = "port_channel_interface_example" +} +``` + +## Argument Reference ## + +* `template_id` - (Required) The unique ID of the Fabric Resource template. +* `name` - (Required) The name of the Port Channel Interface. + +## Attribute Reference ## + +* `id` - (Read-Only) The unique Terraform identifier of the Port Channel Interface. +* `uuid` - (Read-Only) The NDO UUID of the Port Channel Interface. +* `description` - (Read-Only) The description of the Port Channel Interface. +* `node` - (Read-Only) The node ID of the Port Channel Interface. +* `interfaces` - (Read-Only) The member interfaces of the Port Channel. +* `interface_policy_uuid` - (Read-Only) The UUID of the Port Channel/Virtual Port Channel Interface Policy associated with the Port Channel Interface. +* `interface_descriptions` - (Read-Only) A list of interface descriptions for the Port Channel member interfaces. + * `interface` - (Read-Only) The interface ID of the member interface. + * `description` - (Read-Only) The description of the member interface. diff --git a/website/docs/r/fabric_resource_policies_port_channel_interface.html.markdown b/website/docs/r/fabric_resource_policies_port_channel_interface.html.markdown new file mode 100644 index 00000000..fb63ab18 --- /dev/null +++ b/website/docs/r/fabric_resource_policies_port_channel_interface.html.markdown @@ -0,0 +1,62 @@ +--- +layout: "mso" +page_title: "MSO: mso_fabric_resource_policies_port_channel_interface" +sidebar_current: "docs-mso-resource-fabric_resource_policies_port_channel_interface" +description: |- + Manages Fabric Resource Policies Port Channel Interface on Cisco Nexus Dashboard Orchestrator (NDO) +--- + +# mso_fabric_resource_policies_port_channel_interface # + +Manages Fabric Resource Policies Port Channel Interface on Cisco Nexus Dashboard Orchestrator (NDO). This resource is supported in NDO v4.1 or higher. + +## GUI Information ## + +* `Location`: Manage -> Fabric Resource Template -> Fabric Resource Policies -> Port Channel Interfaces + +## Example Usage ## + +```hcl +resource "mso_fabric_resource_policies_port_channel_interface" "example" { + template_id = mso_template.fabric_resource_template.id + name = "example" + description = "example description" + node = "101" + interfaces = ["1/1", "1/2"] + interface_policy_uuid = mso_fabric_policies_interface_setting.port_channel_interface.id + interface_descriptions { + interface = "1/1" + description = "1/1 description" + } + interface_descriptions { + interface = "1/2" + description = "1/2 description" + } +} +``` + +## Argument Reference ## + +* `template_id` - (Required) The unique ID of the Fabric Resource template. +* `name` - (Required) The name of the Port Channel Interface. +* `description` - (Optional) The description of the Port Channel Interface. +* `node` - (Required) The node ID of the Port Channel Interface. This is required when creating or updating a Port Channel Interface. +* `interfaces` - (Required) The member interfaces of the Port Channel. This is required when creating or updating a Port Channel Interface. +* `interface_policy_uuid` - (Required) The UUID of the Port Channel/Virtual Port Channel Interface Policy to associate with the Port Channel Interface. This is required when creating a Port Channel Interface. +* `interface_descriptions` - (Optional) A list of interface descriptions for the Port Channel member interfaces. + * `interface` - (Required) The interface ID of the member interface. Must match an interface defined in the `interfaces` attribute. + * `description` - (Optional) The description of the member interface. + +## Attribute Reference ## + +* `id` - (Read-Only) The unique Terraform identifier of the Port Channel Interface. +* `uuid` - (Read-Only) The NDO UUID of the Port Channel Interface. + +## Importing ## + +An existing MSO Fabric Resource Policies Port Channel Interface can be [imported][docs-import] into this resource via its ID, using the following command: +[docs-import]: https://www.terraform.io/docs/import/index.html + +```bash +terraform import mso_fabric_resource_policies_port_channel_interface.example templateId/{template_id}/PortChannelInterface/{name} +``` From f4f78a1d7ffd00e95273944b76fcdee52ee0ba55 Mon Sep 17 00:00:00 2001 From: Sabari Jaganathan <93724860+sajagana@users.noreply.github.com> Date: Tue, 24 Mar 2026 16:27:56 +0530 Subject: [PATCH 2/3] [ignore] Fix the mso_fabric_resource_policies_port_channel_interface resource and documentation --- ...esource_policies_port_channel_interface.go | 51 +++---------------- ...ce_policies_port_channel_interface_test.go | 29 +++++------ mso/test_constants.go | 18 +++++-- mso/utils.go | 23 +++++++++ mso/utils_test.go | 33 ++++++++++++ ...icies_port_channel_interface.html.markdown | 16 +++--- ...icies_port_channel_interface.html.markdown | 18 +++---- 7 files changed, 106 insertions(+), 82 deletions(-) create mode 100644 mso/utils_test.go diff --git a/mso/resource_mso_fabric_resource_policies_port_channel_interface.go b/mso/resource_mso_fabric_resource_policies_port_channel_interface.go index b5275259..c2ed922a 100644 --- a/mso/resource_mso_fabric_resource_policies_port_channel_interface.go +++ b/mso/resource_mso_fabric_resource_policies_port_channel_interface.go @@ -39,7 +39,6 @@ func resourceMSOPortChannelInterface() *schema.Resource { "description": { Type: schema.TypeString, Optional: true, - Computed: true, }, "node": { Type: schema.TypeString, @@ -68,7 +67,6 @@ func resourceMSOPortChannelInterface() *schema.Resource { "description": { Type: schema.TypeString, Optional: true, - Computed: true, }, }, }, @@ -121,7 +119,7 @@ func customizeDiffPortChannelInterface(d *schema.ResourceDiff, m interface{}) er func getInterfaceDescriptionsPayload(node string, interfaceDescriptions *schema.Set) []map[string]interface{} { interfaceDescriptionsList := interfaceDescriptions.List() - payload := make([]map[string]interface{}, 0, len(interfaceDescriptionsList)) + payload := make([]map[string]interface{}, 0) for _, interfaceDescription := range interfaceDescriptionsList { interfaceDescriptionMap := interfaceDescription.(map[string]interface{}) payload = append(payload, map[string]interface{}{ @@ -133,32 +131,6 @@ func getInterfaceDescriptionsPayload(node string, interfaceDescriptions *schema. return payload } -func interfaceSetToString(interfaceSet *schema.Set) string { - if interfaceSet == nil || interfaceSet.Len() == 0 { - return "" - } - interfaceList := make([]string, 0, interfaceSet.Len()) - for _, memberInterface := range interfaceSet.List() { - interfaceList = append(interfaceList, memberInterface.(string)) - } - return strings.Join(interfaceList, ",") -} - -func interfaceStringToSet(interfaceString string) []interface{} { - if interfaceString == "" { - return []interface{}{} - } - interfaceList := strings.Split(interfaceString, ",") - interfaceSet := make([]interface{}, 0, len(interfaceList)) - for _, interfaceID := range interfaceList { - cleanedInterfaceID := strings.TrimSpace(interfaceID) - if cleanedInterfaceID != "" { - interfaceSet = append(interfaceSet, cleanedInterfaceID) - } - } - return interfaceSet -} - func setPortChannelInterfaceData(d *schema.ResourceData, response *container.Container, templateId string) error { d.SetId(fmt.Sprintf("templateId/%s/PortChannelInterface/%s", templateId, models.StripQuotes(response.S("name").String()))) d.Set("template_id", templateId) @@ -166,7 +138,7 @@ func setPortChannelInterfaceData(d *schema.ResourceData, response *container.Con d.Set("description", models.StripQuotes(response.S("description").String())) d.Set("uuid", models.StripQuotes(response.S("uuid").String())) d.Set("node", models.StripQuotes(response.S("node").String())) - d.Set("interfaces", interfaceStringToSet(models.StripQuotes(response.S("memberInterfaces").String()))) + d.Set("interfaces", splitCommaString(models.StripQuotes(response.S("memberInterfaces").String()))) if response.Exists("policy") { d.Set("interface_policy_uuid", models.StripQuotes(response.S("policy").String())) @@ -214,21 +186,12 @@ func resourceMSOPortChannelInterfaceCreate(d *schema.ResourceData, m interface{} payload["description"] = description.(string) } - node := d.Get("node").(string) - if node != "" { - payload["node"] = node - } - - if memberInterfaces, ok := d.GetOk("interfaces"); ok { - payload["memberInterfaces"] = interfaceSetToString(memberInterfaces.(*schema.Set)) - } - - if interfacePolicyUUID, ok := d.GetOk("interface_policy_uuid"); ok { - payload["policy"] = interfacePolicyUUID.(string) - } + payload["node"] = d.Get("node").(string) + payload["memberInterfaces"] = strings.Join(getListOfStringsFromSchemaSet(d, "interfaces"), ",") + payload["policy"] = d.Get("interface_policy_uuid").(string) if interfaceDescriptions, ok := d.GetOk("interface_descriptions"); ok { - payload["interfaceDescriptions"] = getInterfaceDescriptionsPayload(node, interfaceDescriptions.(*schema.Set)) + payload["interfaceDescriptions"] = getInterfaceDescriptionsPayload(payload["node"].(string), interfaceDescriptions.(*schema.Set)) } payloadModel := models.GetPatchPayload("add", "/fabricResourceTemplate/template/portChannels/-", payload) @@ -319,7 +282,7 @@ func resourceMSOPortChannelInterfaceUpdate(d *schema.ResourceData, m interface{} } if d.HasChange("interfaces") { - err := addPatchPayloadToContainer(payloadCont, "replace", fmt.Sprintf("%s/memberInterfaces", updatePath), interfaceSetToString(d.Get("interfaces").(*schema.Set))) + err := addPatchPayloadToContainer(payloadCont, "replace", fmt.Sprintf("%s/memberInterfaces", updatePath), strings.Join(getListOfStringsFromSchemaSet(d, "interfaces"), ",")) if err != nil { return err } diff --git a/mso/resource_mso_fabric_resource_policies_port_channel_interface_test.go b/mso/resource_mso_fabric_resource_policies_port_channel_interface_test.go index 713849cb..fdaae2aa 100644 --- a/mso/resource_mso_fabric_resource_policies_port_channel_interface_test.go +++ b/mso/resource_mso_fabric_resource_policies_port_channel_interface_test.go @@ -7,8 +7,6 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/helper/resource" ) -var msoFabricResourcePortChannelInterfacePolicyUUID = "97c9e606-cfd6-4bb9-bcf9-10efae49dcfb" - func TestAccMSOFabricResourcePortChannelInterfaceResource(t *testing.T) { resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -19,7 +17,7 @@ func TestAccMSOFabricResourcePortChannelInterfaceResource(t *testing.T) { Config: testAccMSOFabricResourcePortChannelInterfaceConfigCreate(), Check: resource.ComposeAggregateTestCheckFunc( resource.TestCheckResourceAttr("mso_fabric_resource_policies_port_channel_interface."+msoFabricResourcePortChannelInterfaceName, "name", msoFabricResourcePortChannelInterfaceName), - resource.TestCheckResourceAttr("mso_fabric_resource_policies_port_channel_interface."+msoFabricResourcePortChannelInterfaceName, "description", "Terraform test Port Channel Interface"), + resource.TestCheckResourceAttr("mso_fabric_resource_policies_port_channel_interface."+msoFabricResourcePortChannelInterfaceName, "description", ""), resource.TestCheckResourceAttr("mso_fabric_resource_policies_port_channel_interface."+msoFabricResourcePortChannelInterfaceName, "node", "101"), resource.TestCheckResourceAttr("mso_fabric_resource_policies_port_channel_interface."+msoFabricResourcePortChannelInterfaceName, "interfaces.#", "2"), resource.TestCheckResourceAttrSet("mso_fabric_resource_policies_port_channel_interface."+msoFabricResourcePortChannelInterfaceName, "uuid"), @@ -72,14 +70,14 @@ func TestAccMSOFabricResourcePortChannelInterfaceResource(t *testing.T) { Config: testAccMSOFabricResourcePortChannelInterfaceConfigUpdateRemovingExtraInterfaceDescription(), Check: resource.ComposeAggregateTestCheckFunc( resource.TestCheckResourceAttr("mso_fabric_resource_policies_port_channel_interface."+msoFabricResourcePortChannelInterfaceName, "name", msoFabricResourcePortChannelInterfaceName), - resource.TestCheckResourceAttr("mso_fabric_resource_policies_port_channel_interface."+msoFabricResourcePortChannelInterfaceName, "description", "Terraform test Port Channel Interface updated"), + resource.TestCheckResourceAttr("mso_fabric_resource_policies_port_channel_interface."+msoFabricResourcePortChannelInterfaceName, "description", ""), resource.TestCheckResourceAttr("mso_fabric_resource_policies_port_channel_interface."+msoFabricResourcePortChannelInterfaceName, "node", "101"), resource.TestCheckResourceAttr("mso_fabric_resource_policies_port_channel_interface."+msoFabricResourcePortChannelInterfaceName, "interfaces.#", "2"), resource.TestCheckResourceAttr("mso_fabric_resource_policies_port_channel_interface."+msoFabricResourcePortChannelInterfaceName, "interface_descriptions.#", "1"), CustomTestCheckTypeSetElemAttrs("mso_fabric_resource_policies_port_channel_interface."+msoFabricResourcePortChannelInterfaceName, "interface_descriptions", map[string]string{ "interface": "1/2", - "description": "Interface Description 1/2", + "description": "", }, ), ), @@ -95,18 +93,17 @@ func TestAccMSOFabricResourcePortChannelInterfaceResource(t *testing.T) { }) } -var fabricResourcePortChannelInterfacePreConfig = testFabricResourceTemplateConfig() +var fabricResourcePortChannelInterfacePreConfig = testFabricResourceTemplateConfig() + testFabricPolicyTemplateConfig() + testFabricPoliciesInterfaceSettingPortChannelConfig() func testAccMSOFabricResourcePortChannelInterfaceConfigCreate() string { return fmt.Sprintf(`%[1]s resource "mso_fabric_resource_policies_port_channel_interface" "%[2]s" { template_id = mso_template.%[4]s.id name = "%[2]s" - description = "Terraform test Port Channel Interface" node = "101" interfaces = ["1/1","1/2"] - interface_policy_uuid = "%[3]s" - }`, fabricResourcePortChannelInterfacePreConfig, msoFabricResourcePortChannelInterfaceName, msoFabricResourcePortChannelInterfacePolicyUUID, msoFabricResourceTemplateName) + interface_policy_uuid = mso_fabric_policies_interface_setting.%[3]s_portchannel.uuid + }`, fabricResourcePortChannelInterfacePreConfig, msoFabricResourcePortChannelInterfaceName, msoFabricPolicyTemplateInterfaceSettingName, msoFabricResourceTemplateName) } func testAccMSOFabricResourcePortChannelInterfaceConfigUpdateAddingInterfaceDescriptions() string { @@ -117,12 +114,12 @@ func testAccMSOFabricResourcePortChannelInterfaceConfigUpdateAddingInterfaceDesc description = "Terraform test Port Channel Interface updated" node = "101" interfaces = ["1/1","1/2"] - interface_policy_uuid = "%[3]s" + interface_policy_uuid = mso_fabric_policies_interface_setting.%[3]s_portchannel.uuid interface_descriptions { interface = "1/1" description = "Interface Description 1/1" } - }`, fabricResourcePortChannelInterfacePreConfig, msoFabricResourcePortChannelInterfaceName, msoFabricResourcePortChannelInterfacePolicyUUID, msoFabricResourceTemplateName) + }`, fabricResourcePortChannelInterfacePreConfig, msoFabricResourcePortChannelInterfaceName, msoFabricPolicyTemplateInterfaceSettingName, msoFabricResourceTemplateName) } func testAccMSOFabricResourcePortChannelInterfaceConfigUpdateAddingExtraInterfaceDescription() string { @@ -133,7 +130,7 @@ func testAccMSOFabricResourcePortChannelInterfaceConfigUpdateAddingExtraInterfac description = "Terraform test Port Channel Interface updated" node = "101" interfaces = ["1/1","1/2"] - interface_policy_uuid = "%[3]s" + interface_policy_uuid = mso_fabric_policies_interface_setting.%[3]s_portchannel.uuid interface_descriptions { interface = "1/1" description = "Interface Description 1/1" @@ -142,7 +139,7 @@ func testAccMSOFabricResourcePortChannelInterfaceConfigUpdateAddingExtraInterfac interface = "1/2" description = "Interface Description 1/2" } - }`, fabricResourcePortChannelInterfacePreConfig, msoFabricResourcePortChannelInterfaceName, msoFabricResourcePortChannelInterfacePolicyUUID, msoFabricResourceTemplateName) + }`, fabricResourcePortChannelInterfacePreConfig, msoFabricResourcePortChannelInterfaceName, msoFabricPolicyTemplateInterfaceSettingName, msoFabricResourceTemplateName) } func testAccMSOFabricResourcePortChannelInterfaceConfigUpdateRemovingExtraInterfaceDescription() string { @@ -150,13 +147,11 @@ func testAccMSOFabricResourcePortChannelInterfaceConfigUpdateRemovingExtraInterf resource "mso_fabric_resource_policies_port_channel_interface" "%[2]s" { template_id = mso_template.%[4]s.id name = "%[2]s" - description = "Terraform test Port Channel Interface updated" node = "101" interfaces = ["1/1","1/2"] - interface_policy_uuid = "%[3]s" + interface_policy_uuid = mso_fabric_policies_interface_setting.%[3]s_portchannel.uuid interface_descriptions { interface = "1/2" - description = "Interface Description 1/2" } - }`, fabricResourcePortChannelInterfacePreConfig, msoFabricResourcePortChannelInterfaceName, msoFabricResourcePortChannelInterfacePolicyUUID, msoFabricResourceTemplateName) + }`, fabricResourcePortChannelInterfacePreConfig, msoFabricResourcePortChannelInterfaceName, msoFabricPolicyTemplateInterfaceSettingName, msoFabricResourceTemplateName) } diff --git a/mso/test_constants.go b/mso/test_constants.go index 16c768a8..d74f09cb 100644 --- a/mso/test_constants.go +++ b/mso/test_constants.go @@ -298,9 +298,19 @@ resource "mso_schema_template_anp_epg_subnet" "%[1]s_subnet" { func testFabricResourceTemplateConfig() string { return fmt.Sprintf(` - resource "mso_template" "%[1]s" { - template_name = "%[1]s" - template_type = "fabric_resource" - } +resource "mso_template" "%[1]s" { + template_name = "%[1]s" + template_type = "fabric_resource" +} `, msoFabricResourceTemplateName) } + +func testFabricPoliciesInterfaceSettingPortChannelConfig() string { + return fmt.Sprintf(` +resource "mso_fabric_policies_interface_setting" "%[1]s_portchannel" { + template_id = mso_template.%[2]s.id + type = "portchannel" + name = "%[1]s_portchannel" +} +`, msoFabricPolicyTemplateInterfaceSettingName, msoFabricPolicyTemplateName) +} diff --git a/mso/utils.go b/mso/utils.go index 7fc0678c..9d1204c3 100644 --- a/mso/utils.go +++ b/mso/utils.go @@ -301,6 +301,13 @@ func getListOfStringsFromSchemaList(d *schema.ResourceData, key string) []string return nil } +func getListOfStringsFromSchemaSet(d *schema.ResourceData, key string) []string { + if values, ok := d.GetOk(key); ok { + return convertToListOfStrings(values.(*schema.Set).List()) + } + return nil +} + func convertToListOfStrings(values []interface{}) []string { result := []string{} for _, item := range values { @@ -540,3 +547,19 @@ func GetDeployedSiteIdsForApplicationTemplate(msoClient *client.Client, schemaId } return siteIds, nil } + +func splitCommaString(s string) []string { + s = strings.TrimSpace(s) + if s == "" { + return []string{} + } + parts := strings.Split(s, ",") + out := make([]string, 0, len(parts)) + for _, part := range parts { + part = strings.TrimSpace(part) + if part != "" { + out = append(out, part) + } + } + return out +} diff --git a/mso/utils_test.go b/mso/utils_test.go new file mode 100644 index 00000000..a480f896 --- /dev/null +++ b/mso/utils_test.go @@ -0,0 +1,33 @@ +package mso + +import ( + "reflect" + "testing" +) + +func TestSplitCommaString(t *testing.T) { + cases := []struct { + name string + input string + expected []string + }{ + {"empty", "", []string{}}, + {"whitespace_only", " \t ", []string{}}, + {"single_token", "1/1", []string{"1/1"}}, + {"single_token_with_spaces", " 1/1 ", []string{"1/1"}}, + {"multiple_tokens", "1/1,1/2", []string{"1/1", "1/2"}}, + {"multiple_tokens_with_spaces", " 1/1 , 1/2 ", []string{"1/1", "1/2"}}, + {"drops_empty_tokens_leading_trailing_commas", ",1/1,1/2,", []string{"1/1", "1/2"}}, + {"drops_empty_tokens_repeated_commas", "1/1,,1/2", []string{"1/1", "1/2"}}, + {"all_empty_tokens", ",,,", []string{}}, + } + + for _, testCase := range cases { + t.Run(testCase.name, func(t *testing.T) { + got := splitCommaString(testCase.input) + if !reflect.DeepEqual(got, testCase.expected) { + t.Fatalf("splitCommaString(%q) = %#v, expected %#v", testCase.input, got, testCase.expected) + } + }) + } +} diff --git a/website/docs/d/fabric_resource_policies_port_channel_interface.html.markdown b/website/docs/d/fabric_resource_policies_port_channel_interface.html.markdown index faadb4c1..01b8aec2 100644 --- a/website/docs/d/fabric_resource_policies_port_channel_interface.html.markdown +++ b/website/docs/d/fabric_resource_policies_port_channel_interface.html.markdown @@ -28,16 +28,16 @@ data "mso_fabric_resource_policies_port_channel_interface" "example" { ## Argument Reference ## * `template_id` - (Required) The unique ID of the Fabric Resource template. -* `name` - (Required) The name of the Port Channel Interface. +* `name` - (Required) The name of the Port Channel Interface Policy. ## Attribute Reference ## -* `id` - (Read-Only) The unique Terraform identifier of the Port Channel Interface. -* `uuid` - (Read-Only) The NDO UUID of the Port Channel Interface. -* `description` - (Read-Only) The description of the Port Channel Interface. -* `node` - (Read-Only) The node ID of the Port Channel Interface. -* `interfaces` - (Read-Only) The member interfaces of the Port Channel. -* `interface_policy_uuid` - (Read-Only) The UUID of the Port Channel/Virtual Port Channel Interface Policy associated with the Port Channel Interface. -* `interface_descriptions` - (Read-Only) A list of interface descriptions for the Port Channel member interfaces. +* `id` - (Read-Only) The unique Terraform identifier of the Port Channel Interface Policy. +* `uuid` - (Read-Only) The NDO UUID of the Port Channel Interface Policy. +* `description` - (Read-Only) The description of the Port Channel Interface Policy. +* `node` - (Read-Only) The node ID of the Port Channel Interface Policy. +* `interfaces` - (Read-Only) A list of interfaces where this Port Channel Interface Policy will be applied. +* `interface_policy_uuid` - (Read-Only) The UUID of the (Port Channel/Virtual Port Channel) interface settings policy to associate with the Port Channel Interface Policy. +* `interface_descriptions` - (Read-Only) A list of interface descriptions of the Port Channel Interface Policy. * `interface` - (Read-Only) The interface ID of the member interface. * `description` - (Read-Only) The description of the member interface. diff --git a/website/docs/r/fabric_resource_policies_port_channel_interface.html.markdown b/website/docs/r/fabric_resource_policies_port_channel_interface.html.markdown index fb63ab18..477d83f6 100644 --- a/website/docs/r/fabric_resource_policies_port_channel_interface.html.markdown +++ b/website/docs/r/fabric_resource_policies_port_channel_interface.html.markdown @@ -38,23 +38,23 @@ resource "mso_fabric_resource_policies_port_channel_interface" "example" { ## Argument Reference ## * `template_id` - (Required) The unique ID of the Fabric Resource template. -* `name` - (Required) The name of the Port Channel Interface. -* `description` - (Optional) The description of the Port Channel Interface. -* `node` - (Required) The node ID of the Port Channel Interface. This is required when creating or updating a Port Channel Interface. -* `interfaces` - (Required) The member interfaces of the Port Channel. This is required when creating or updating a Port Channel Interface. -* `interface_policy_uuid` - (Required) The UUID of the Port Channel/Virtual Port Channel Interface Policy to associate with the Port Channel Interface. This is required when creating a Port Channel Interface. -* `interface_descriptions` - (Optional) A list of interface descriptions for the Port Channel member interfaces. +* `name` - (Required) The name of the Port Channel Interface Policy. +* `description` - (Optional) The description of the Port Channel Interface Policy. +* `node` - (Required) The node ID of the Port Channel Interface Policy. This is required when creating or updating a Port Channel Interface Policy. +* `interfaces` - (Required) A list of interfaces where this Port Channel Interface Policy will be applied. This is required when creating or updating a Port Channel Interface Policy. +* `interface_policy_uuid` - (Required) The UUID of the (Port Channel/Virtual Port Channel) interface settings policy to associate with the Port Channel Interface Policy. This is required when creating a Port Channel Interface Policy. +* `interface_descriptions` - (Optional) A list of interface descriptions of the Port Channel Interface Policy. * `interface` - (Required) The interface ID of the member interface. Must match an interface defined in the `interfaces` attribute. * `description` - (Optional) The description of the member interface. ## Attribute Reference ## -* `id` - (Read-Only) The unique Terraform identifier of the Port Channel Interface. -* `uuid` - (Read-Only) The NDO UUID of the Port Channel Interface. +* `id` - (Read-Only) The unique Terraform identifier of the Port Channel Interface Policy. +* `uuid` - (Read-Only) The NDO UUID of the Port Channel Interface Policy. ## Importing ## -An existing MSO Fabric Resource Policies Port Channel Interface can be [imported][docs-import] into this resource via its ID, using the following command: +An existing MSO Fabric Resource Policies Port Channel Interface Policy can be [imported][docs-import] into this resource via its ID, using the following command: [docs-import]: https://www.terraform.io/docs/import/index.html ```bash From d372b4f4f04b15f9542efee94c7c64b9e89a33f1 Mon Sep 17 00:00:00 2001 From: Sabari Jaganathan <93724860+sajagana@users.noreply.github.com> Date: Mon, 6 Apr 2026 18:47:07 +0530 Subject: [PATCH 3/3] [ignore] Rename the interface_policy_uuid attribute to interface_policy_group_uuid in mso_fabric_resource_policies_port_channel_interface --- .../main.tf | 12 ++--- ...esource_policies_port_channel_interface.go | 8 +++- ...ce_policies_port_channel_interface_test.go | 2 +- ...esource_policies_port_channel_interface.go | 19 ++++---- ...ce_policies_port_channel_interface_test.go | 46 +++++++++---------- ...icies_port_channel_interface.html.markdown | 2 +- ...icies_port_channel_interface.html.markdown | 14 +++--- 7 files changed, 54 insertions(+), 49 deletions(-) diff --git a/examples/fabric_resource_policies_port_channel_interface/main.tf b/examples/fabric_resource_policies_port_channel_interface/main.tf index 7c0ba7ac..299a92bd 100644 --- a/examples/fabric_resource_policies_port_channel_interface/main.tf +++ b/examples/fabric_resource_policies_port_channel_interface/main.tf @@ -30,12 +30,12 @@ resource "mso_template" "fabric_resource_template" { } resource "mso_fabric_resource_policies_port_channel_interface" "example" { - template_id = mso_template.fabric_resource_template.id - name = "example" - description = "example description" - node = "101" - interfaces = ["1/1", "1/2"] - interface_policy_uuid = mso_fabric_policies_interface_setting.port_channel_interface.id + template_id = mso_template.fabric_resource_template.id + name = "example" + description = "example description" + node = "101" + interfaces = ["1/1", "1/2"] + interface_policy_group_uuid = mso_fabric_policies_interface_setting.port_channel_interface.id interface_descriptions { interface = "1/1" description = "1/1 description" diff --git a/mso/datasource_mso_fabric_resource_policies_port_channel_interface.go b/mso/datasource_mso_fabric_resource_policies_port_channel_interface.go index 26d80fe5..0dcc468b 100644 --- a/mso/datasource_mso_fabric_resource_policies_port_channel_interface.go +++ b/mso/datasource_mso_fabric_resource_policies_port_channel_interface.go @@ -36,7 +36,7 @@ func datasourceMSOPortChannelInterface() *schema.Resource { }, Computed: true, }, - "interface_policy_uuid": { + "interface_policy_group_uuid": { Type: schema.TypeString, Computed: true, }, @@ -81,7 +81,11 @@ func dataSourceMSOPortChannelInterfaceRead(d *schema.ResourceData, m interface{} return err } - setPortChannelInterfaceData(d, policy, templateId) + err = setPortChannelInterfaceData(d, policy, templateId) + if err != nil { + return err + } + log.Printf("[DEBUG] MSO Port Channel Interface Data Source - Read Complete: %v", d.Id()) return nil } diff --git a/mso/datasource_mso_fabric_resource_policies_port_channel_interface_test.go b/mso/datasource_mso_fabric_resource_policies_port_channel_interface_test.go index 33135499..9d4f2115 100644 --- a/mso/datasource_mso_fabric_resource_policies_port_channel_interface_test.go +++ b/mso/datasource_mso_fabric_resource_policies_port_channel_interface_test.go @@ -22,7 +22,7 @@ func TestAccMSOFabricResourcePortChannelInterfaceDataSource(t *testing.T) { resource.TestCheckResourceAttr("data.mso_fabric_resource_policies_port_channel_interface."+msoFabricResourcePortChannelInterfaceName, "interfaces.#", "2"), resource.TestCheckResourceAttrSet("data.mso_fabric_resource_policies_port_channel_interface."+msoFabricResourcePortChannelInterfaceName, "uuid"), resource.TestCheckResourceAttrSet("data.mso_fabric_resource_policies_port_channel_interface."+msoFabricResourcePortChannelInterfaceName, "template_id"), - resource.TestCheckResourceAttrSet("data.mso_fabric_resource_policies_port_channel_interface."+msoFabricResourcePortChannelInterfaceName, "interface_policy_uuid"), + resource.TestCheckResourceAttrSet("data.mso_fabric_resource_policies_port_channel_interface."+msoFabricResourcePortChannelInterfaceName, "interface_policy_group_uuid"), resource.TestCheckResourceAttr("data.mso_fabric_resource_policies_port_channel_interface."+msoFabricResourcePortChannelInterfaceName, "interface_descriptions.#", "2"), CustomTestCheckTypeSetElemAttrs("data.mso_fabric_resource_policies_port_channel_interface."+msoFabricResourcePortChannelInterfaceName, "interface_descriptions", map[string]string{ diff --git a/mso/resource_mso_fabric_resource_policies_port_channel_interface.go b/mso/resource_mso_fabric_resource_policies_port_channel_interface.go index c2ed922a..e2c31560 100644 --- a/mso/resource_mso_fabric_resource_policies_port_channel_interface.go +++ b/mso/resource_mso_fabric_resource_policies_port_channel_interface.go @@ -51,7 +51,7 @@ func resourceMSOPortChannelInterface() *schema.Resource { Type: schema.TypeString, }, }, - "interface_policy_uuid": { + "interface_policy_group_uuid": { Type: schema.TypeString, Required: true, }, @@ -141,7 +141,7 @@ func setPortChannelInterfaceData(d *schema.ResourceData, response *container.Con d.Set("interfaces", splitCommaString(models.StripQuotes(response.S("memberInterfaces").String()))) if response.Exists("policy") { - d.Set("interface_policy_uuid", models.StripQuotes(response.S("policy").String())) + d.Set("interface_policy_group_uuid", models.StripQuotes(response.S("policy").String())) } interfaceDescriptionsList := make([]map[string]interface{}, 0) @@ -166,7 +166,10 @@ func setPortChannelInterfaceData(d *schema.ResourceData, response *container.Con func resourceMSOPortChannelInterfaceImport(d *schema.ResourceData, m interface{}) ([]*schema.ResourceData, error) { log.Printf("[DEBUG] MSO Port Channel Interface Resource - Beginning Import: %v", d.Id()) - resourceMSOPortChannelInterfaceRead(d, m) + err := resourceMSOPortChannelInterfaceRead(d, m) + if err != nil { + return nil, err + } log.Printf("[DEBUG] MSO Port Channel Interface Resource - Import Complete: %v", d.Id()) return []*schema.ResourceData{d}, nil } @@ -182,13 +185,11 @@ func resourceMSOPortChannelInterfaceCreate(d *schema.ResourceData, m interface{} "templateId": templateId, } - if description, ok := d.GetOk("description"); ok { - payload["description"] = description.(string) - } + payload["description"] = d.Get("description").(string) payload["node"] = d.Get("node").(string) payload["memberInterfaces"] = strings.Join(getListOfStringsFromSchemaSet(d, "interfaces"), ",") - payload["policy"] = d.Get("interface_policy_uuid").(string) + payload["policy"] = d.Get("interface_policy_group_uuid").(string) if interfaceDescriptions, ok := d.GetOk("interface_descriptions"); ok { payload["interfaceDescriptions"] = getInterfaceDescriptionsPayload(payload["node"].(string), interfaceDescriptions.(*schema.Set)) @@ -288,8 +289,8 @@ func resourceMSOPortChannelInterfaceUpdate(d *schema.ResourceData, m interface{} } } - if d.HasChange("interface_policy_uuid") { - interfacePolicyUUID := d.Get("interface_policy_uuid").(string) + if d.HasChange("interface_policy_group_uuid") { + interfacePolicyUUID := d.Get("interface_policy_group_uuid").(string) if interfacePolicyUUID != "" { err := addPatchPayloadToContainer(payloadCont, "replace", fmt.Sprintf("%s/policy", updatePath), interfacePolicyUUID) if err != nil { diff --git a/mso/resource_mso_fabric_resource_policies_port_channel_interface_test.go b/mso/resource_mso_fabric_resource_policies_port_channel_interface_test.go index fdaae2aa..9b826b66 100644 --- a/mso/resource_mso_fabric_resource_policies_port_channel_interface_test.go +++ b/mso/resource_mso_fabric_resource_policies_port_channel_interface_test.go @@ -22,7 +22,7 @@ func TestAccMSOFabricResourcePortChannelInterfaceResource(t *testing.T) { resource.TestCheckResourceAttr("mso_fabric_resource_policies_port_channel_interface."+msoFabricResourcePortChannelInterfaceName, "interfaces.#", "2"), resource.TestCheckResourceAttrSet("mso_fabric_resource_policies_port_channel_interface."+msoFabricResourcePortChannelInterfaceName, "uuid"), resource.TestCheckResourceAttrSet("mso_fabric_resource_policies_port_channel_interface."+msoFabricResourcePortChannelInterfaceName, "template_id"), - resource.TestCheckResourceAttrSet("mso_fabric_resource_policies_port_channel_interface."+msoFabricResourcePortChannelInterfaceName, "interface_policy_uuid"), + resource.TestCheckResourceAttrSet("mso_fabric_resource_policies_port_channel_interface."+msoFabricResourcePortChannelInterfaceName, "interface_policy_group_uuid"), ), }, { @@ -98,23 +98,23 @@ var fabricResourcePortChannelInterfacePreConfig = testFabricResourceTemplateConf func testAccMSOFabricResourcePortChannelInterfaceConfigCreate() string { return fmt.Sprintf(`%[1]s resource "mso_fabric_resource_policies_port_channel_interface" "%[2]s" { - template_id = mso_template.%[4]s.id - name = "%[2]s" - node = "101" - interfaces = ["1/1","1/2"] - interface_policy_uuid = mso_fabric_policies_interface_setting.%[3]s_portchannel.uuid + template_id = mso_template.%[4]s.id + name = "%[2]s" + node = "101" + interfaces = ["1/1","1/2"] + interface_policy_group_uuid = mso_fabric_policies_interface_setting.%[3]s_portchannel.uuid }`, fabricResourcePortChannelInterfacePreConfig, msoFabricResourcePortChannelInterfaceName, msoFabricPolicyTemplateInterfaceSettingName, msoFabricResourceTemplateName) } func testAccMSOFabricResourcePortChannelInterfaceConfigUpdateAddingInterfaceDescriptions() string { return fmt.Sprintf(`%[1]s resource "mso_fabric_resource_policies_port_channel_interface" "%[2]s" { - template_id = mso_template.%[4]s.id - name = "%[2]s" - description = "Terraform test Port Channel Interface updated" - node = "101" - interfaces = ["1/1","1/2"] - interface_policy_uuid = mso_fabric_policies_interface_setting.%[3]s_portchannel.uuid + template_id = mso_template.%[4]s.id + name = "%[2]s" + description = "Terraform test Port Channel Interface updated" + node = "101" + interfaces = ["1/1","1/2"] + interface_policy_group_uuid = mso_fabric_policies_interface_setting.%[3]s_portchannel.uuid interface_descriptions { interface = "1/1" description = "Interface Description 1/1" @@ -125,12 +125,12 @@ func testAccMSOFabricResourcePortChannelInterfaceConfigUpdateAddingInterfaceDesc func testAccMSOFabricResourcePortChannelInterfaceConfigUpdateAddingExtraInterfaceDescription() string { return fmt.Sprintf(`%[1]s resource "mso_fabric_resource_policies_port_channel_interface" "%[2]s" { - template_id = mso_template.%[4]s.id - name = "%[2]s" - description = "Terraform test Port Channel Interface updated" - node = "101" - interfaces = ["1/1","1/2"] - interface_policy_uuid = mso_fabric_policies_interface_setting.%[3]s_portchannel.uuid + template_id = mso_template.%[4]s.id + name = "%[2]s" + description = "Terraform test Port Channel Interface updated" + node = "101" + interfaces = ["1/1","1/2"] + interface_policy_group_uuid = mso_fabric_policies_interface_setting.%[3]s_portchannel.uuid interface_descriptions { interface = "1/1" description = "Interface Description 1/1" @@ -145,11 +145,11 @@ func testAccMSOFabricResourcePortChannelInterfaceConfigUpdateAddingExtraInterfac func testAccMSOFabricResourcePortChannelInterfaceConfigUpdateRemovingExtraInterfaceDescription() string { return fmt.Sprintf(`%[1]s resource "mso_fabric_resource_policies_port_channel_interface" "%[2]s" { - template_id = mso_template.%[4]s.id - name = "%[2]s" - node = "101" - interfaces = ["1/1","1/2"] - interface_policy_uuid = mso_fabric_policies_interface_setting.%[3]s_portchannel.uuid + template_id = mso_template.%[4]s.id + name = "%[2]s" + node = "101" + interfaces = ["1/1","1/2"] + interface_policy_group_uuid = mso_fabric_policies_interface_setting.%[3]s_portchannel.uuid interface_descriptions { interface = "1/2" } diff --git a/website/docs/d/fabric_resource_policies_port_channel_interface.html.markdown b/website/docs/d/fabric_resource_policies_port_channel_interface.html.markdown index 01b8aec2..f4617718 100644 --- a/website/docs/d/fabric_resource_policies_port_channel_interface.html.markdown +++ b/website/docs/d/fabric_resource_policies_port_channel_interface.html.markdown @@ -37,7 +37,7 @@ data "mso_fabric_resource_policies_port_channel_interface" "example" { * `description` - (Read-Only) The description of the Port Channel Interface Policy. * `node` - (Read-Only) The node ID of the Port Channel Interface Policy. * `interfaces` - (Read-Only) A list of interfaces where this Port Channel Interface Policy will be applied. -* `interface_policy_uuid` - (Read-Only) The UUID of the (Port Channel/Virtual Port Channel) interface settings policy to associate with the Port Channel Interface Policy. +* `interface_policy_group_uuid` - (Read-Only) The UUID of the (Port Channel/Virtual Port Channel) interface settings policy to associate with the Port Channel Interface Policy. * `interface_descriptions` - (Read-Only) A list of interface descriptions of the Port Channel Interface Policy. * `interface` - (Read-Only) The interface ID of the member interface. * `description` - (Read-Only) The description of the member interface. diff --git a/website/docs/r/fabric_resource_policies_port_channel_interface.html.markdown b/website/docs/r/fabric_resource_policies_port_channel_interface.html.markdown index 477d83f6..b928a363 100644 --- a/website/docs/r/fabric_resource_policies_port_channel_interface.html.markdown +++ b/website/docs/r/fabric_resource_policies_port_channel_interface.html.markdown @@ -18,12 +18,12 @@ Manages Fabric Resource Policies Port Channel Interface on Cisco Nexus Dashboard ```hcl resource "mso_fabric_resource_policies_port_channel_interface" "example" { - template_id = mso_template.fabric_resource_template.id - name = "example" - description = "example description" - node = "101" - interfaces = ["1/1", "1/2"] - interface_policy_uuid = mso_fabric_policies_interface_setting.port_channel_interface.id + template_id = mso_template.fabric_resource_template.id + name = "example" + description = "example description" + node = "101" + interfaces = ["1/1", "1/2"] + interface_policy_group_uuid = mso_fabric_policies_interface_setting.port_channel_interface.id interface_descriptions { interface = "1/1" description = "1/1 description" @@ -42,7 +42,7 @@ resource "mso_fabric_resource_policies_port_channel_interface" "example" { * `description` - (Optional) The description of the Port Channel Interface Policy. * `node` - (Required) The node ID of the Port Channel Interface Policy. This is required when creating or updating a Port Channel Interface Policy. * `interfaces` - (Required) A list of interfaces where this Port Channel Interface Policy will be applied. This is required when creating or updating a Port Channel Interface Policy. -* `interface_policy_uuid` - (Required) The UUID of the (Port Channel/Virtual Port Channel) interface settings policy to associate with the Port Channel Interface Policy. This is required when creating a Port Channel Interface Policy. +* `interface_policy_group_uuid` - (Required) The UUID of the (Port Channel/Virtual Port Channel) interface settings policy to associate with the Port Channel Interface Policy. This is required when creating a Port Channel Interface Policy. * `interface_descriptions` - (Optional) A list of interface descriptions of the Port Channel Interface Policy. * `interface` - (Required) The interface ID of the member interface. Must match an interface defined in the `interfaces` attribute. * `description` - (Optional) The description of the member interface.