From 7efdf30e6a2112e6f2ba5faecda8aa1fe0f9b28a Mon Sep 17 00:00:00 2001 From: Sabari Jaganathan <93724860+sajagana@users.noreply.github.com> Date: Thu, 5 Mar 2026 18:35:55 +0530 Subject: [PATCH 1/5] [minor_change] Add fabric_resource_policies_physical_interface resource and datasource --- .../main.tf | 64 +++ ...ic_resource_policies_physical_interface.go | 98 ++++ ...source_policies_physical_interface_test.go | 97 ++++ mso/provider.go | 2 + ...ic_resource_policies_physical_interface.go | 447 ++++++++++++++++++ ...source_policies_physical_interface_test.go | 322 +++++++++++++ ...o_tenant_policies_ipsla_track_list_test.go | 1 - mso/test_constants.go | 22 + ..._policies_physical_interface.html.markdown | 43 ++ ..._policies_physical_interface.html.markdown | 87 ++++ 10 files changed, 1182 insertions(+), 1 deletion(-) create mode 100644 examples/fabric_resource_policies_physical_interface/main.tf create mode 100644 mso/datasource_mso_fabric_resource_policies_physical_interface.go create mode 100644 mso/datasource_mso_fabric_resource_policies_physical_interface_test.go create mode 100644 mso/resource_mso_fabric_resource_policies_physical_interface.go create mode 100644 mso/resource_mso_fabric_resource_policies_physical_interface_test.go create mode 100644 website/docs/d/fabric_resource_policies_physical_interface.html.markdown create mode 100644 website/docs/r/fabric_resource_policies_physical_interface.html.markdown diff --git a/examples/fabric_resource_policies_physical_interface/main.tf b/examples/fabric_resource_policies_physical_interface/main.tf new file mode 100644 index 00000000..27a97a28 --- /dev/null +++ b/examples/fabric_resource_policies_physical_interface/main.tf @@ -0,0 +1,64 @@ +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" "physical_interface" { + template_id = mso_template.fabric_policy_template.id + type = "physical" + name = "physical_interface" +} + +resource "mso_template" "fabric_resource_template" { + template_name = "fabric_resource_template" + template_type = "fabric_resource" +} + +resource "mso_fabric_resource_policies_physical_interface" "physical" { + template_id = mso_template.fabric_resource_template.id + name = "physical_interface" + description = "Terraform test Physical Interface" + nodes = ["101", "102"] + interfaces = ["1/1", "1/2"] + interface_policy_uuid = mso_fabric_policies_interface_setting.physical_interface.id + interface_descriptions { + interface = "1/1" + description = "Interface Description 1/1" + } + interface_descriptions { + interface = "1/2" + description = "Interface Description 1/2" + } +} + +resource "mso_fabric_resource_policies_physical_interface" "breakout" { + template_id = mso_template.fabric_resource_template.id + name = "breakout_mode_physical_interface" + description = "Terraform test Physical Interface with breakout mode" + nodes = ["101", "102"] + interfaces = ["1/1", "1/2"] + breakout_mode = "4x100G" + interface_descriptions { + interface = "1/1" + description = "Interface Description 1/1" + } + interface_descriptions { + interface = "1/2" + description = "Interface Description 1/2" + } +} \ No newline at end of file diff --git a/mso/datasource_mso_fabric_resource_policies_physical_interface.go b/mso/datasource_mso_fabric_resource_policies_physical_interface.go new file mode 100644 index 00000000..43486300 --- /dev/null +++ b/mso/datasource_mso_fabric_resource_policies_physical_interface.go @@ -0,0 +1,98 @@ +package mso + +import ( + "fmt" + "log" + + "github.com/ciscoecosystem/mso-go-client/client" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" +) + +func datasourceMSOPhysicalInterface() *schema.Resource { + return &schema.Resource{ + Read: dataSourceMSOPhysicalInterfaceRead, + + Schema: map[string]*schema.Schema{ + "template_id": { + Type: schema.TypeString, + Required: true, + }, + "name": { + Type: schema.TypeString, + Required: true, + }, + "description": { + Type: schema.TypeString, + Computed: true, + }, + "nodes": { + Type: schema.TypeList, + Elem: &schema.Schema{ + 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, + }, + "breakout_mode": { + 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, + }, + "policy_group_type": { + Type: schema.TypeString, + Computed: true, + }, + }, + } +} + +func dataSourceMSOPhysicalInterfaceRead(d *schema.ResourceData, m interface{}) error { + log.Printf("[DEBUG] MSO Physical 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", "interfaceProfiles") + if err != nil { + return err + } + + setPhysicalInterfaceData(d, policy, templateId) + log.Printf("[DEBUG] MSO Physical Interface Data Source - Read Complete: %v", d.Id()) + return nil +} diff --git a/mso/datasource_mso_fabric_resource_policies_physical_interface_test.go b/mso/datasource_mso_fabric_resource_policies_physical_interface_test.go new file mode 100644 index 00000000..6c481bdd --- /dev/null +++ b/mso/datasource_mso_fabric_resource_policies_physical_interface_test.go @@ -0,0 +1,97 @@ +package mso + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" +) + +func TestAccMSOFabricResourcePhysicalInterfaceDataSource(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + PreConfig: func() { fmt.Println("Test: Physical Interface Data Source - With Interface type physical") }, + Config: testAccMSOFabricResourcePhysicalInterfaceTypePhysicalDataSource(), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("data.mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName, "name", msoFabricResourcePhysicalInterfaceName), + resource.TestCheckResourceAttr("data.mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName, "policy_group_type", "physical"), + resource.TestCheckResourceAttr("data.mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName, "description", "Terraform test Physical Interface updated"), + resource.TestCheckResourceAttr("data.mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName, "nodes.#", "2"), + resource.TestCheckResourceAttr("data.mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName, "interfaces.#", "2"), + resource.TestCheckResourceAttrSet("data.mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName, "uuid"), + resource.TestCheckResourceAttrSet("data.mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName, "template_id"), + resource.TestCheckResourceAttrSet("data.mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName, "interface_policy_uuid"), + resource.TestCheckResourceAttr("data.mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName, "interface_descriptions.#", "2"), + CustomTestCheckTypeSetElemAttrs("data.mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName, "interface_descriptions", + map[string]string{ + "interface": "1/1", + "description": "Interface Description 1/1", + }, + ), + CustomTestCheckTypeSetElemAttrs("data.mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName, "interface_descriptions", + map[string]string{ + "interface": "1/2", + "description": "Interface Description 1/2", + }, + ), + ), + }, + { + PreConfig: func() { fmt.Println("Test: Physical Interface Data Source - Breakout Mode setup") }, + Config: testAccMSOFabricResourcePhysicalInterfaceBreakoutModeConfigUpdateRemovingExtraInterfaceDescription(), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName+"_breakout", "name", msoFabricResourcePhysicalInterfaceName+"_breakout_updated"), + resource.TestCheckResourceAttr("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName+"_breakout", "policy_group_type", "breakout"), + ), + }, + { + PreConfig: func() { fmt.Println("Test: Physical Interface Data Source - Breakout Mode") }, + Config: testAccMSOFabricResourcePhysicalInterfaceTypeBreakoutDataSource(), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("data.mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName+"_breakout", "name", msoFabricResourcePhysicalInterfaceName+"_breakout_updated"), + resource.TestCheckResourceAttr("data.mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName+"_breakout", "policy_group_type", "breakout"), + resource.TestCheckResourceAttrSet("data.mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName+"_breakout", "uuid"), + resource.TestCheckResourceAttrSet("data.mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName+"_breakout", "template_id"), + resource.TestCheckResourceAttr("data.mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName+"_breakout", "breakout_mode", "4x100G"), + resource.TestCheckResourceAttr("data.mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName+"_breakout", "description", "Terraform test Physical Interface updated"), + resource.TestCheckResourceAttr("data.mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName+"_breakout", "nodes.#", "1"), + resource.TestCheckResourceAttr("data.mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName+"_breakout", "interfaces.#", "2"), + resource.TestCheckResourceAttr("data.mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName+"_breakout", "interface_descriptions.#", "1"), + CustomTestCheckTypeSetElemAttrs("data.mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName+"_breakout", "interface_descriptions", + map[string]string{ + "interface": "1/2", + "description": "Interface Description 1/2", + }, + ), + ), + }, + }, + }) +} + +func testAccMSOFabricResourcePhysicalInterfaceTypePhysicalDataSource() string { + return fmt.Sprintf(`%[1]s + data "mso_fabric_resource_policies_physical_interface" "%[2]s" { + template_id = mso_template.%[3]s.id + name = mso_fabric_resource_policies_physical_interface.%[2]s.name + }`, + testAccMSOFabricResourcePhysicalInterfaceConfigUpdateAddingExtraInterfaceDescription(), + msoFabricResourcePhysicalInterfaceName, + msoFabricResourceTemplateName, + ) +} + +func testAccMSOFabricResourcePhysicalInterfaceTypeBreakoutDataSource() string { + return fmt.Sprintf(`%[1]s + data "mso_fabric_resource_policies_physical_interface" "%[2]s" { + template_id = mso_template.%[3]s.id + name = mso_fabric_resource_policies_physical_interface.%[2]s.name + }`, + testAccMSOFabricResourcePhysicalInterfaceBreakoutModeConfigUpdateRemovingExtraInterfaceDescription(), + msoFabricResourcePhysicalInterfaceName+"_breakout", + msoFabricResourceTemplateName, + ) +} diff --git a/mso/provider.go b/mso/provider.go index 18d1c7ab..cb527948 100644 --- a/mso/provider.go +++ b/mso/provider.go @@ -142,6 +142,7 @@ func Provider() terraform.ResourceProvider { "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_physical_interface": resourceMSOPhysicalInterface(), }, DataSourcesMap: map[string]*schema.Resource{ @@ -217,6 +218,7 @@ func Provider() terraform.ResourceProvider { "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_physical_interface": datasourceMSOPhysicalInterface(), }, ConfigureFunc: configureClient, diff --git a/mso/resource_mso_fabric_resource_policies_physical_interface.go b/mso/resource_mso_fabric_resource_policies_physical_interface.go new file mode 100644 index 00000000..1ed55b56 --- /dev/null +++ b/mso/resource_mso_fabric_resource_policies_physical_interface.go @@ -0,0 +1,447 @@ +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 resourceMSOPhysicalInterface() *schema.Resource { + return &schema.Resource{ + Create: resourceMSOPhysicalInterfaceCreate, + Read: resourceMSOPhysicalInterfaceRead, + Update: resourceMSOPhysicalInterfaceUpdate, + Delete: resourceMSOPhysicalInterfaceDelete, + Importer: &schema.ResourceImporter{ + State: resourceMSOPhysicalInterfaceImport, + }, + + CustomizeDiff: customizeDiffPhysicalInterface, + + SchemaVersion: 1, + Schema: map[string]*schema.Schema{ + "template_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "name": { + Type: schema.TypeString, + Required: true, + }, + "description": { + Type: schema.TypeString, + Optional: true, + Computed: true, + }, + "nodes": { + Type: schema.TypeSet, + Required: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "interfaces": { + Type: schema.TypeSet, + Required: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "interface_policy_uuid": { + Type: schema.TypeString, + Optional: true, + ConflictsWith: []string{"breakout_mode"}, + }, + "breakout_mode": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringInSlice([]string{ + "4x100G", + "4x25G", + "4x10G", + }, false), + ConflictsWith: []string{"interface_policy_uuid"}, + }, + "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, + }, + "policy_group_type": { + Type: schema.TypeString, + Computed: true, + }, + }, + } +} + +func customizeDiffPhysicalInterface(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 getInterfaceDescriptionsPayloadPhysical(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{}{ + "interfaceID": interfaceDescriptionMap["interface"].(string), + "description": interfaceDescriptionMap["description"].(string), + }) + } + return payload +} + +func nodeSetToStringList(nodeSet *schema.Set) []interface{} { + nodeList := make([]interface{}, 0) + if nodeSet != nil && nodeSet.Len() > 0 { + nodeList = make([]interface{}, 0, nodeSet.Len()) + for _, node := range nodeSet.List() { + nodeList = append(nodeList, node.(string)) + } + } + return nodeList +} + +func physicalInterfaceSetToString(interfaceSet *schema.Set) string { + interfaceList := make([]string, 0) + if interfaceSet != nil && interfaceSet.Len() > 0 { + interfaceList = make([]string, 0, interfaceSet.Len()) + for _, memberInterface := range interfaceSet.List() { + interfaceList = append(interfaceList, memberInterface.(string)) + } + } + return strings.Join(interfaceList, ",") +} + +func physicalInterfaceStringToSet(interfaceString string) []interface{} { + interfaceSet := make([]interface{}, 0) + if interfaceString != "" { + 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 setPhysicalInterfaceData(d *schema.ResourceData, response *container.Container, templateId string) error { + d.SetId(fmt.Sprintf("templateId/%s/PhysicalInterface/%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("interfaces", physicalInterfaceStringToSet(models.StripQuotes(response.S("interfaces").String()))) + d.Set("policy_group_type", models.StripQuotes(response.S("policyGroupType").String())) + + if response.Exists("nodes") { + nodeCount, err := response.ArrayCount("nodes") + if err == nil { + nodeList := make([]interface{}, 0, nodeCount) + for i := 0; i < nodeCount; i++ { + nodeElement, err := response.ArrayElement(i, "nodes") + if err == nil { + nodeList = append(nodeList, models.StripQuotes(nodeElement.String())) + } + } + d.Set("nodes", nodeList) + } + } + + if response.Exists("policy") { + d.Set("interface_policy_uuid", models.StripQuotes(response.S("policy").String())) + } + + if response.Exists("breakoutMode") { + d.Set("breakout_mode", models.StripQuotes(response.S("breakoutMode").String())) + } + + interfaceDescriptionsList := make([]map[string]interface{}, 0) + count, err := response.ArrayCount("interfaceDescriptions") + if err == nil { + for i := 0; i < count; i++ { + 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 resourceMSOPhysicalInterfaceImport(d *schema.ResourceData, m interface{}) ([]*schema.ResourceData, error) { + log.Printf("[DEBUG] MSO Physical Interface Resource - Beginning Import: %v", d.Id()) + resourceMSOPhysicalInterfaceRead(d, m) + log.Printf("[DEBUG] MSO Physical Interface Resource - Import Complete: %v", d.Id()) + return []*schema.ResourceData{d}, nil +} + +func resourceMSOPhysicalInterfaceCreate(d *schema.ResourceData, m interface{}) error { + log.Printf("[DEBUG] MSO Physical 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) + } + + if nodes, ok := d.GetOk("nodes"); ok { + payload["nodes"] = nodeSetToStringList(nodes.(*schema.Set)) + } + + if memberInterfaces, ok := d.GetOk("interfaces"); ok { + payload["interfaces"] = physicalInterfaceSetToString(memberInterfaces.(*schema.Set)) + } + + interfacePolicyUUID := d.Get("interface_policy_uuid").(string) + breakoutMode := d.Get("breakout_mode").(string) + + if interfacePolicyUUID == "" && breakoutMode == "" { + return fmt.Errorf("Either 'interface_policy_uuid' or 'breakout_mode' must be specified for creating a Physical Interface") + } + + if interfacePolicyUUID != "" { + payload["policy"] = interfacePolicyUUID + payload["policyGroupType"] = "physical" + } else { + payload["breakoutMode"] = breakoutMode + payload["policyGroupType"] = "breakout" + } + + if interfaceDescriptions, ok := d.GetOk("interface_descriptions"); ok { + payload["interfaceDescriptions"] = getInterfaceDescriptionsPayloadPhysical(interfaceDescriptions.(*schema.Set)) + } + + payloadModel := models.GetPatchPayload("add", "/fabricResourceTemplate/template/interfaceProfiles/-", payload) + + _, err := msoClient.PatchbyID(fmt.Sprintf("api/v1/templates/%s", templateId), payloadModel) + if err != nil { + return err + } + + d.SetId(fmt.Sprintf("templateId/%s/PhysicalInterface/%s", templateId, d.Get("name").(string))) + log.Printf("[DEBUG] MSO Physical Interface Resource - Create Complete: %v", d.Id()) + return resourceMSOPhysicalInterfaceRead(d, m) +} + +func resourceMSOPhysicalInterfaceRead(d *schema.ResourceData, m interface{}) error { + log.Printf("[DEBUG] MSO Physical 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(), "PhysicalInterface") + if err != nil { + return err + } + + policy, err := GetPolicyByName(response, policyName, "fabricResourceTemplate", "template", "interfaceProfiles") + if err != nil { + return err + } + + err = setPhysicalInterfaceData(d, policy, templateId) + if err != nil { + return err + } + + log.Printf("[DEBUG] MSO Physical Interface Resource - Read Complete: %v", d.Id()) + return nil +} + +func resourceMSOPhysicalInterfaceUpdate(d *schema.ResourceData, m interface{}) error { + log.Printf("[DEBUG] MSO Physical Interface Resource - Beginning Update: %v", d.Id()) + msoClient := m.(*client.Client) + templateId := d.Get("template_id").(string) + + if d.Get("interface_policy_uuid").(string) == "" && d.Get("breakout_mode").(string) == "" { + return fmt.Errorf("Either 'interface_policy_uuid' or 'breakout_mode' must be specified for creating a Physical Interface") + } + + 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", "interfaceProfiles") + if err != nil { + return err + } + + updatePath := fmt.Sprintf("/fabricResourceTemplate/template/interfaceProfiles/%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("nodes") { + err := addPatchPayloadToContainer(payloadCont, "replace", fmt.Sprintf("%s/nodes", updatePath), nodeSetToStringList(d.Get("nodes").(*schema.Set))) + if err != nil { + return err + } + } + + if d.HasChange("interfaces") { + err := addPatchPayloadToContainer(payloadCont, "replace", fmt.Sprintf("%s/interfaces", updatePath), physicalInterfaceSetToString(d.Get("interfaces").(*schema.Set))) + if err != nil { + return err + } + } + + if d.HasChange("interface_policy_uuid") { + interfacePolicyUUID := d.Get("interface_policy_uuid").(string) + err := addPatchPayloadToContainer(payloadCont, "replace", fmt.Sprintf("%s/policy", updatePath), interfacePolicyUUID) + if err != nil { + return err + } + } + + if d.HasChange("breakout_mode") { + breakoutMode := d.Get("breakout_mode").(string) + err := addPatchPayloadToContainer(payloadCont, "replace", fmt.Sprintf("%s/breakoutMode", updatePath), breakoutMode) + if err != nil { + return err + } + } + + if d.HasChange("interface_descriptions") { + err := addPatchPayloadToContainer(payloadCont, "replace", fmt.Sprintf("%s/interfaceDescriptions", updatePath), getInterfaceDescriptionsPayloadPhysical(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/PhysicalInterface/%s", templateId, d.Get("name").(string))) + log.Printf("[DEBUG] MSO Physical Interface Resource - Update Complete: %v", d.Id()) + return resourceMSOPhysicalInterfaceRead(d, m) +} + +func resourceMSOPhysicalInterfaceDelete(d *schema.ResourceData, m interface{}) error { + log.Printf("[DEBUG] MSO Physical 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", "interfaceProfiles") + if err != nil { + return err + } + + payloadModel := models.GetRemovePatchPayload(fmt.Sprintf("/fabricResourceTemplate/template/interfaceProfiles/%d", policyIndex)) + + _, err = msoClient.PatchbyID(fmt.Sprintf("api/v1/templates/%s", templateId), payloadModel) + if err != nil { + return err + } + + d.SetId("") + log.Printf("[DEBUG] MSO Physical Interface Resource - Delete Complete: %v", d.Id()) + return nil +} diff --git a/mso/resource_mso_fabric_resource_policies_physical_interface_test.go b/mso/resource_mso_fabric_resource_policies_physical_interface_test.go new file mode 100644 index 00000000..ef6bac91 --- /dev/null +++ b/mso/resource_mso_fabric_resource_policies_physical_interface_test.go @@ -0,0 +1,322 @@ +package mso + +import ( + "fmt" + "regexp" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" +) + +func TestAccMSOFabricResourcePhysicalInterfaceResource(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + PreConfig: func() { fmt.Println("Test: Missing interface_policy_uuid and breakout_mode (error)") }, + Config: testAccMSOFabricResourcePhysicalInterfaceConfigErrorMissingInterfacePolicyAndBreakoutMode(), + ExpectError: regexp.MustCompile(`Either 'interface_policy_uuid' or 'breakout_mode' must be specified for creating a Physical Interface`), + }, + { + PreConfig: func() { fmt.Println("Test: Create Physical Interface") }, + Config: testAccMSOFabricResourcePhysicalInterfaceConfigCreate(), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName, "name", msoFabricResourcePhysicalInterfaceName), + resource.TestCheckResourceAttr("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName, "policy_group_type", "physical"), + resource.TestCheckResourceAttr("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName, "description", "Terraform test Physical Interface"), + resource.TestCheckResourceAttr("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName, "nodes.#", "1"), + resource.TestCheckResourceAttr("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName, "interfaces.#", "2"), + resource.TestCheckResourceAttrSet("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName, "uuid"), + resource.TestCheckResourceAttrSet("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName, "template_id"), + resource.TestCheckResourceAttrSet("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName, "interface_policy_uuid"), + ), + }, + { + PreConfig: func() { fmt.Println("Test: Update Physical Interface adding interface descriptions") }, + Config: testAccMSOFabricResourcePhysicalInterfaceConfigUpdateAddingInterfaceDescriptions(), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName, "name", msoFabricResourcePhysicalInterfaceName), + resource.TestCheckResourceAttr("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName, "description", "Terraform test Physical Interface updated"), + resource.TestCheckResourceAttr("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName, "nodes.#", "2"), + resource.TestCheckResourceAttr("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName, "interfaces.#", "2"), + resource.TestCheckResourceAttr("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName, "interface_descriptions.#", "1"), + CustomTestCheckTypeSetElemAttrs("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName, "interface_descriptions", + map[string]string{ + "interface": "1/1", + "description": "Interface Description 1/1", + }, + ), + ), + }, + { + PreConfig: func() { fmt.Println("Test: Update Physical Interface adding extra interface description") }, + Config: testAccMSOFabricResourcePhysicalInterfaceConfigUpdateAddingExtraInterfaceDescription(), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName, "name", msoFabricResourcePhysicalInterfaceName), + resource.TestCheckResourceAttr("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName, "description", "Terraform test Physical Interface updated"), + resource.TestCheckResourceAttr("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName, "nodes.#", "2"), + resource.TestCheckResourceAttr("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName, "interfaces.#", "2"), + resource.TestCheckResourceAttr("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName, "interface_descriptions.#", "2"), + CustomTestCheckTypeSetElemAttrs("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName, "interface_descriptions", + map[string]string{ + "interface": "1/1", + "description": "Interface Description 1/1", + }, + ), + CustomTestCheckTypeSetElemAttrs("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName, "interface_descriptions", + map[string]string{ + "interface": "1/2", + "description": "Interface Description 1/2", + }, + ), + ), + }, + { + PreConfig: func() { fmt.Println("Test: Update Physical Interface removing extra interface description") }, + Config: testAccMSOFabricResourcePhysicalInterfaceConfigUpdateRemovingExtraInterfaceDescription(), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName, "name", msoFabricResourcePhysicalInterfaceName+"_updated"), + resource.TestCheckResourceAttr("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName, "description", "Terraform test Physical Interface updated"), + resource.TestCheckResourceAttr("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName, "nodes.#", "1"), + resource.TestCheckResourceAttr("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName, "interfaces.#", "2"), + resource.TestCheckResourceAttr("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName, "interface_descriptions.#", "1"), + CustomTestCheckTypeSetElemAttrs("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName, "interface_descriptions", + map[string]string{ + "interface": "1/2", + "description": "Interface Description 1/2", + }, + ), + ), + }, + { + PreConfig: func() { fmt.Println("Test: Import Physical Interface") }, + ResourceName: "mso_fabric_resource_policies_physical_interface." + msoFabricResourcePhysicalInterfaceName, + ImportState: true, + ImportStateVerify: true, + }, + { + PreConfig: func() { fmt.Println("Test: Create Physical Interface with Breakout Mode") }, + Config: testAccMSOFabricResourcePhysicalInterfaceBreakoutModeConfigCreate(), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName+"_breakout", "name", msoFabricResourcePhysicalInterfaceName+"_breakout"), + resource.TestCheckResourceAttr("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName+"_breakout", "policy_group_type", "breakout"), + resource.TestCheckResourceAttr("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName+"_breakout", "description", "Terraform test Physical Interface"), + resource.TestCheckResourceAttr("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName+"_breakout", "nodes.#", "1"), + resource.TestCheckResourceAttr("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName+"_breakout", "interfaces.#", "2"), + resource.TestCheckResourceAttr("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName+"_breakout", "breakout_mode", "4x10G"), + resource.TestCheckResourceAttrSet("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName+"_breakout", "uuid"), + resource.TestCheckResourceAttrSet("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName+"_breakout", "template_id"), + ), + }, + { + PreConfig: func() { fmt.Println("Test: Update Breakout Mode and add interface descriptions") }, + Config: testAccMSOFabricResourcePhysicalInterfaceBreakoutModeConfigUpdateAddingInterfaceDescriptions(), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName+"_breakout", "name", msoFabricResourcePhysicalInterfaceName+"_breakout"), + resource.TestCheckResourceAttr("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName+"_breakout", "description", "Terraform test Physical Interface updated"), + resource.TestCheckResourceAttr("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName+"_breakout", "nodes.#", "2"), + resource.TestCheckResourceAttr("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName+"_breakout", "interfaces.#", "2"), + resource.TestCheckResourceAttr("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName+"_breakout", "breakout_mode", "4x25G"), + resource.TestCheckResourceAttr("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName+"_breakout", "interface_descriptions.#", "1"), + CustomTestCheckTypeSetElemAttrs("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName+"_breakout", "interface_descriptions", + map[string]string{ + "interface": "1/1", + "description": "Interface Description 1/1", + }, + ), + ), + }, + { + PreConfig: func() { fmt.Println("Test: Update Breakout Mode and add extra interface description") }, + Config: testAccMSOFabricResourcePhysicalInterfaceBreakoutModeConfigUpdateAddingExtraInterfaceDescription(), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName+"_breakout", "name", msoFabricResourcePhysicalInterfaceName+"_breakout"), + resource.TestCheckResourceAttr("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName+"_breakout", "description", "Terraform test Physical Interface updated"), + resource.TestCheckResourceAttr("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName+"_breakout", "nodes.#", "2"), + resource.TestCheckResourceAttr("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName+"_breakout", "interfaces.#", "2"), + resource.TestCheckResourceAttr("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName+"_breakout", "breakout_mode", "4x100G"), + resource.TestCheckResourceAttr("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName+"_breakout", "interface_descriptions.#", "2"), + CustomTestCheckTypeSetElemAttrs("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName+"_breakout", "interface_descriptions", + map[string]string{ + "interface": "1/1", + "description": "Interface Description 1/1", + }, + ), + CustomTestCheckTypeSetElemAttrs("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName+"_breakout", "interface_descriptions", + map[string]string{ + "interface": "1/2", + "description": "Interface Description 1/2", + }, + ), + ), + }, + { + PreConfig: func() { fmt.Println("Test: Update Breakout Mode and remove extra interface description") }, + Config: testAccMSOFabricResourcePhysicalInterfaceBreakoutModeConfigUpdateRemovingExtraInterfaceDescription(), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName+"_breakout", "name", msoFabricResourcePhysicalInterfaceName+"_breakout_updated"), + resource.TestCheckResourceAttr("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName+"_breakout", "description", "Terraform test Physical Interface updated"), + resource.TestCheckResourceAttr("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName+"_breakout", "nodes.#", "1"), + resource.TestCheckResourceAttr("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName+"_breakout", "interfaces.#", "2"), + resource.TestCheckResourceAttr("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName+"_breakout", "breakout_mode", "4x100G"), + resource.TestCheckResourceAttr("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName+"_breakout", "interface_descriptions.#", "1"), + CustomTestCheckTypeSetElemAttrs("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName+"_breakout", "interface_descriptions", + map[string]string{ + "interface": "1/2", + "description": "Interface Description 1/2", + }, + ), + ), + }, + { + PreConfig: func() { fmt.Println("Test: Import Physical Interface with Breakout Mode") }, + ResourceName: "mso_fabric_resource_policies_physical_interface." + msoFabricResourcePhysicalInterfaceName + "_breakout", + ImportState: true, + ImportStateVerify: true, + }, + }, + CheckDestroy: testCheckResourceDestroyPolicyWithPathAttributesAndArguments("mso_fabric_resource_policies_physical_interface", "fabricResourceTemplate", "template", "physicalInterfaces"), + }) +} + +var fabricResourcePhysicalInterfacePreConfig = testFabricResourceTemplateConfig() + testFabricPolicyTemplateConfig() + testFabricPoliciesInterfaceSettingPhysicalConfig() + +func testAccMSOFabricResourcePhysicalInterfaceConfigErrorMissingInterfacePolicyAndBreakoutMode() string { + return fmt.Sprintf(`%[1]s + resource "mso_fabric_resource_policies_physical_interface" "%[2]s" { + template_id = mso_template.%[3]s.id + name = "%[2]s" + description = "Terraform test Physical Interface" + nodes = ["101"] + interfaces = ["1/1","1/2"] + }`, fabricResourcePhysicalInterfacePreConfig, msoFabricResourcePhysicalInterfaceName, msoFabricResourceTemplateName) +} + +func testAccMSOFabricResourcePhysicalInterfaceConfigCreate() string { + return fmt.Sprintf(`%[1]s + resource "mso_fabric_resource_policies_physical_interface" "%[2]s" { + template_id = mso_template.%[4]s.id + name = "%[2]s" + description = "Terraform test Physical Interface" + nodes = ["101"] + interfaces = ["1/1","1/2"] + interface_policy_uuid = mso_fabric_policies_interface_setting.%[3]s_physical.uuid + }`, fabricResourcePhysicalInterfacePreConfig, msoFabricResourcePhysicalInterfaceName, msoFabricPolicyTemplateInterfaceSettingName, msoFabricResourceTemplateName) +} + +func testAccMSOFabricResourcePhysicalInterfaceConfigUpdateAddingInterfaceDescriptions() string { + return fmt.Sprintf(`%[1]s + resource "mso_fabric_resource_policies_physical_interface" "%[2]s" { + template_id = mso_template.%[4]s.id + name = "%[2]s" + description = "Terraform test Physical Interface updated" + nodes = ["101", "102"] + interfaces = ["1/1","1/2"] + interface_policy_uuid = mso_fabric_policies_interface_setting.%[3]s_physical.uuid + interface_descriptions { + interface = "1/1" + description = "Interface Description 1/1" + } + }`, fabricResourcePhysicalInterfacePreConfig, msoFabricResourcePhysicalInterfaceName, msoFabricPolicyTemplateInterfaceSettingName, msoFabricResourceTemplateName) +} + +func testAccMSOFabricResourcePhysicalInterfaceConfigUpdateAddingExtraInterfaceDescription() string { + return fmt.Sprintf(`%[1]s + resource "mso_fabric_resource_policies_physical_interface" "%[2]s" { + template_id = mso_template.%[4]s.id + name = "%[2]s" + description = "Terraform test Physical Interface updated" + nodes = ["101", "102"] + interfaces = ["1/1","1/2"] + interface_policy_uuid = mso_fabric_policies_interface_setting.%[3]s_physical.uuid + interface_descriptions { + interface = "1/1" + description = "Interface Description 1/1" + } + interface_descriptions { + interface = "1/2" + description = "Interface Description 1/2" + } + }`, fabricResourcePhysicalInterfacePreConfig, msoFabricResourcePhysicalInterfaceName, msoFabricPolicyTemplateInterfaceSettingName, msoFabricResourceTemplateName) +} + +func testAccMSOFabricResourcePhysicalInterfaceConfigUpdateRemovingExtraInterfaceDescription() string { + return fmt.Sprintf(`%[1]s + resource "mso_fabric_resource_policies_physical_interface" "%[2]s" { + template_id = mso_template.%[4]s.id + name = "%[2]s_updated" + description = "Terraform test Physical Interface updated" + nodes = ["101"] + interfaces = ["1/1","1/2"] + interface_policy_uuid = mso_fabric_policies_interface_setting.%[3]s_physical.uuid + interface_descriptions { + interface = "1/2" + description = "Interface Description 1/2" + } + }`, fabricResourcePhysicalInterfacePreConfig, msoFabricResourcePhysicalInterfaceName, msoFabricPolicyTemplateInterfaceSettingName, msoFabricResourceTemplateName) +} + +func testAccMSOFabricResourcePhysicalInterfaceBreakoutModeConfigCreate() string { + return fmt.Sprintf(`%[1]s + resource "mso_fabric_resource_policies_physical_interface" "%[2]s_breakout" { + template_id = mso_template.%[3]s.id + name = "%[2]s_breakout" + description = "Terraform test Physical Interface" + nodes = ["101"] + interfaces = ["1/1","1/2"] + breakout_mode = "4x10G" + }`, fabricResourcePhysicalInterfacePreConfig, msoFabricResourcePhysicalInterfaceName, msoFabricResourceTemplateName) +} + +func testAccMSOFabricResourcePhysicalInterfaceBreakoutModeConfigUpdateAddingInterfaceDescriptions() string { + return fmt.Sprintf(`%[1]s + resource "mso_fabric_resource_policies_physical_interface" "%[2]s_breakout" { + template_id = mso_template.%[3]s.id + name = "%[2]s_breakout" + description = "Terraform test Physical Interface updated" + nodes = ["101", "102"] + interfaces = ["1/1","1/2"] + breakout_mode = "4x25G" + interface_descriptions { + interface = "1/1" + description = "Interface Description 1/1" + } + }`, fabricResourcePhysicalInterfacePreConfig, msoFabricResourcePhysicalInterfaceName, msoFabricResourceTemplateName) +} + +func testAccMSOFabricResourcePhysicalInterfaceBreakoutModeConfigUpdateAddingExtraInterfaceDescription() string { + return fmt.Sprintf(`%[1]s + resource "mso_fabric_resource_policies_physical_interface" "%[2]s_breakout" { + template_id = mso_template.%[3]s.id + name = "%[2]s_breakout" + description = "Terraform test Physical Interface updated" + nodes = ["101", "102"] + interfaces = ["1/1","1/2"] + breakout_mode = "4x100G" + interface_descriptions { + interface = "1/1" + description = "Interface Description 1/1" + } + interface_descriptions { + interface = "1/2" + description = "Interface Description 1/2" + } + }`, fabricResourcePhysicalInterfacePreConfig, msoFabricResourcePhysicalInterfaceName, msoFabricResourceTemplateName) +} + +func testAccMSOFabricResourcePhysicalInterfaceBreakoutModeConfigUpdateRemovingExtraInterfaceDescription() string { + return fmt.Sprintf(`%[1]s + resource "mso_fabric_resource_policies_physical_interface" "%[2]s_breakout" { + template_id = mso_template.%[3]s.id + name = "%[2]s_breakout_updated" + description = "Terraform test Physical Interface updated" + nodes = ["101"] + interfaces = ["1/1","1/2"] + breakout_mode = "4x100G" + interface_descriptions { + interface = "1/2" + description = "Interface Description 1/2" + } + }`, fabricResourcePhysicalInterfacePreConfig, msoFabricResourcePhysicalInterfaceName, msoFabricResourceTemplateName) +} diff --git a/mso/resource_mso_tenant_policies_ipsla_track_list_test.go b/mso/resource_mso_tenant_policies_ipsla_track_list_test.go index 5fb85d70..b19c1466 100644 --- a/mso/resource_mso_tenant_policies_ipsla_track_list_test.go +++ b/mso/resource_mso_tenant_policies_ipsla_track_list_test.go @@ -8,7 +8,6 @@ import ( ) func TestAccMSOTenantPoliciesIPSLATrackListResource(t *testing.T) { - print(testAccMSOTenantPoliciesIPSLATrackListConfigCreate()) resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, diff --git a/mso/test_constants.go b/mso/test_constants.go index d6ac91e7..1b842f7d 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 msoFabricResourcePhysicalInterfaceName = acctest.RandStringFromCharSet(10, acctest.CharSetAlpha) + func testSiteConfigAnsibleTest() string { return fmt.Sprintf(` data "mso_site" "%[1]s" { @@ -292,3 +295,22 @@ 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) +} + +func testFabricPoliciesInterfaceSettingPhysicalConfig() string { + return fmt.Sprintf(` +resource "mso_fabric_policies_interface_setting" "%[1]s_physical" { + template_id = mso_template.%[2]s.id + type = "physical" + name = "%[1]s_physical" +} +`, msoFabricPolicyTemplateInterfaceSettingName, msoFabricPolicyTemplateName) +} diff --git a/website/docs/d/fabric_resource_policies_physical_interface.html.markdown b/website/docs/d/fabric_resource_policies_physical_interface.html.markdown new file mode 100644 index 00000000..3fe61970 --- /dev/null +++ b/website/docs/d/fabric_resource_policies_physical_interface.html.markdown @@ -0,0 +1,43 @@ +--- +layout: "mso" +page_title: "MSO: mso_fabric_resource_policies_physical_interface" +sidebar_current: "docs-mso-data-source-fabric_resource_policies_physical_interface" +description: |- + Data source for Fabric Resource Policies Physical Interface on Cisco Nexus Dashboard Orchestrator (NDO) +--- + +# mso_fabric_resource_policies_physical_interface # + +Data source for Fabric Resource Policies Physical 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 -> Physical Interfaces + +## Example Usage ## + +```hcl +data "mso_fabric_resource_policies_physical_interface" "example" { + template_id = mso_template.fabric_resource_template.id + name = "physical_interface" +} +``` + +## Argument Reference ## + +* `template_id` - (Required) The ID of the Fabric Resource template. +* `name` - (Required) The name of the Physical Interface. + +## Attribute Reference ## + +* `id` - (Read-Only) The unique Terraform identifier of the Physical Interface. +* `uuid` - (Read-Only) The NDO UUID of the Physical Interface. +* `description` - (Read-Only) The description of the Physical Interface. +* `nodes` - (Read-Only) A list of node IDs of the Physical Interface. +* `interfaces` - (Read-Only) A list of interfaces of the Physical Interface. +* `interface_policy_uuid` - (Read-Only) The UUID of the Physical Interface Policy associated with the Physical Interface. +* `breakout_mode` - (Read-Only) The breakout mode of the Physical Interface. +* `interface_descriptions` - (Read-Only) A list of interface descriptions of the Physical Interface member interfaces. + * `interface` - (Read-Only) The interface ID of the member interface. + * `description` - (Read-Only) The description of the member interface. +* `policy_group_type` - (Read-Only) The policy group type of the Physical Interface. \ No newline at end of file diff --git a/website/docs/r/fabric_resource_policies_physical_interface.html.markdown b/website/docs/r/fabric_resource_policies_physical_interface.html.markdown new file mode 100644 index 00000000..797f3075 --- /dev/null +++ b/website/docs/r/fabric_resource_policies_physical_interface.html.markdown @@ -0,0 +1,87 @@ +--- +layout: "mso" +page_title: "MSO: mso_fabric_resource_policies_physical_interface" +sidebar_current: "docs-mso-resource-fabric_resource_policies_physical_interface" +description: |- + Manages Fabric Resource Policies Physical Interface on Cisco Nexus Dashboard Orchestrator (NDO) +--- + +# mso_fabric_resource_policies_physical_interface # + +Manages Fabric Resource Policies Physical 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 -> Physical Interfaces + +## Example Usage ## + +### Physical Interface with Interface Policy + +```hcl +resource "mso_fabric_resource_policies_physical_interface" "physical" { + template_id = mso_template.fabric_resource_template.id + name = "physical_interface" + description = "Terraform test Physical Interface" + nodes = ["101", "102"] + interfaces = ["1/1", "1/2"] + interface_policy_uuid = mso_fabric_policies_interface_setting.physical_interface.id + interface_descriptions { + interface = "1/1" + description = "Interface Description 1/1" + } + interface_descriptions { + interface = "1/2" + description = "Interface Description 1/2" + } +} +``` + +### Physical Interface with Breakout Mode + +```hcl +resource "mso_fabric_resource_policies_physical_interface" "breakout" { + template_id = mso_template.fabric_resource_template.id + name = "breakout_mode_physical_interface" + description = "Terraform test Physical Interface with breakout mode" + nodes = ["101", "102"] + interfaces = ["1/1", "1/2"] + breakout_mode = "4x100G" + interface_descriptions { + interface = "1/1" + description = "Interface Description 1/1" + } + interface_descriptions { + interface = "1/2" + description = "Interface Description 1/2" + } +} +``` + +## Argument Reference ## + +* `template_id` - (Required) The ID of the Fabric Resource template. +* `name` - (Required) The name of the Physical Interface. +* `description` - (Optional) The description of the Physical Interface. +* `nodes` - (Required) A list of node IDs of the Physical Interface. This is required when creating or updating a Physical Interface. +* `interfaces` - (Required) A list of interfaces of the Physical Interface. This is required when creating or updating a Physical Interface. +* `interface_policy_uuid` - (Optional) The UUID of the Physical Interface Policy to associate with the Physical Interface. Either `interface_policy_uuid` or `breakout_mode` must be specified when creating or updating a Physical Interface. +* `breakout_mode` - (Optional) The breakout mode of the Physical Interface. Valid values are `4x100G`, `4x25G`, and `4x10G`. Either `interface_policy_uuid` or `breakout_mode` must be specified when creating or updating a Physical Interface. +* `interface_descriptions` - (Optional) A list of interface descriptions of the Physical Interface 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 Physical Interface. +* `uuid` - (Read-Only) The NDO UUID of the Physical Interface. +* `policy_group_type` - (Read-Only) The policy group type of the Physical Interface. + +## Importing ## + +An existing MSO Fabric Resource Policies Physical 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_physical_interface.example templateId/{template_id}/PhysicalInterface/{name} +``` \ No newline at end of file From 020ff8b60489a47ed2296283995e27d93464aa59 Mon Sep 17 00:00:00 2001 From: Sabari Jaganathan <93724860+sajagana@users.noreply.github.com> Date: Tue, 24 Mar 2026 14:58:53 +0530 Subject: [PATCH 2/5] [ignore] Fix the fabric_resource_policies_physical_interface resource and documentation --- ...ic_resource_policies_physical_interface.go | 65 +++---------------- ...source_policies_physical_interface_test.go | 9 +-- mso/utils.go | 23 +++++++ mso/utils_test.go | 33 ++++++++++ ..._policies_physical_interface.html.markdown | 20 +++--- ..._policies_physical_interface.html.markdown | 22 +++---- 6 files changed, 89 insertions(+), 83 deletions(-) create mode 100644 mso/utils_test.go diff --git a/mso/resource_mso_fabric_resource_policies_physical_interface.go b/mso/resource_mso_fabric_resource_policies_physical_interface.go index 1ed55b56..115c3898 100644 --- a/mso/resource_mso_fabric_resource_policies_physical_interface.go +++ b/mso/resource_mso_fabric_resource_policies_physical_interface.go @@ -38,7 +38,6 @@ func resourceMSOPhysicalInterface() *schema.Resource { "description": { Type: schema.TypeString, Optional: true, - Computed: true, }, "nodes": { Type: schema.TypeSet, @@ -81,7 +80,6 @@ func resourceMSOPhysicalInterface() *schema.Resource { "description": { Type: schema.TypeString, Optional: true, - Computed: true, }, }, }, @@ -140,7 +138,7 @@ func customizeDiffPhysicalInterface(d *schema.ResourceDiff, m interface{}) error func getInterfaceDescriptionsPayloadPhysical(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{}{ @@ -151,56 +149,19 @@ func getInterfaceDescriptionsPayloadPhysical(interfaceDescriptions *schema.Set) return payload } -func nodeSetToStringList(nodeSet *schema.Set) []interface{} { - nodeList := make([]interface{}, 0) - if nodeSet != nil && nodeSet.Len() > 0 { - nodeList = make([]interface{}, 0, nodeSet.Len()) - for _, node := range nodeSet.List() { - nodeList = append(nodeList, node.(string)) - } - } - return nodeList -} - -func physicalInterfaceSetToString(interfaceSet *schema.Set) string { - interfaceList := make([]string, 0) - if interfaceSet != nil && interfaceSet.Len() > 0 { - interfaceList = make([]string, 0, interfaceSet.Len()) - for _, memberInterface := range interfaceSet.List() { - interfaceList = append(interfaceList, memberInterface.(string)) - } - } - return strings.Join(interfaceList, ",") -} - -func physicalInterfaceStringToSet(interfaceString string) []interface{} { - interfaceSet := make([]interface{}, 0) - if interfaceString != "" { - 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 setPhysicalInterfaceData(d *schema.ResourceData, response *container.Container, templateId string) error { d.SetId(fmt.Sprintf("templateId/%s/PhysicalInterface/%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("interfaces", physicalInterfaceStringToSet(models.StripQuotes(response.S("interfaces").String()))) + d.Set("interfaces", splitCommaString(models.StripQuotes(response.S("interfaces").String()))) d.Set("policy_group_type", models.StripQuotes(response.S("policyGroupType").String())) if response.Exists("nodes") { nodeCount, err := response.ArrayCount("nodes") if err == nil { - nodeList := make([]interface{}, 0, nodeCount) + nodeList := make([]interface{}, 0) for i := 0; i < nodeCount; i++ { nodeElement, err := response.ArrayElement(i, "nodes") if err == nil { @@ -261,14 +222,8 @@ func resourceMSOPhysicalInterfaceCreate(d *schema.ResourceData, m interface{}) e payload["description"] = description.(string) } - if nodes, ok := d.GetOk("nodes"); ok { - payload["nodes"] = nodeSetToStringList(nodes.(*schema.Set)) - } - - if memberInterfaces, ok := d.GetOk("interfaces"); ok { - payload["interfaces"] = physicalInterfaceSetToString(memberInterfaces.(*schema.Set)) - } - + payload["nodes"] = getListOfStringsFromSchemaSet(d, "nodes") + payload["interfaces"] = strings.Join(getListOfStringsFromSchemaSet(d, "interfaces"), ",") interfacePolicyUUID := d.Get("interface_policy_uuid").(string) breakoutMode := d.Get("breakout_mode").(string) @@ -372,30 +327,28 @@ func resourceMSOPhysicalInterfaceUpdate(d *schema.ResourceData, m interface{}) e } if d.HasChange("nodes") { - err := addPatchPayloadToContainer(payloadCont, "replace", fmt.Sprintf("%s/nodes", updatePath), nodeSetToStringList(d.Get("nodes").(*schema.Set))) + err := addPatchPayloadToContainer(payloadCont, "replace", fmt.Sprintf("%s/nodes", updatePath), getListOfStringsFromSchemaSet(d, "nodes")) if err != nil { return err } } if d.HasChange("interfaces") { - err := addPatchPayloadToContainer(payloadCont, "replace", fmt.Sprintf("%s/interfaces", updatePath), physicalInterfaceSetToString(d.Get("interfaces").(*schema.Set))) + err := addPatchPayloadToContainer(payloadCont, "replace", fmt.Sprintf("%s/interfaces", updatePath), strings.Join(getListOfStringsFromSchemaSet(d, "interfaces"), ",")) if err != nil { return err } } if d.HasChange("interface_policy_uuid") { - interfacePolicyUUID := d.Get("interface_policy_uuid").(string) - err := addPatchPayloadToContainer(payloadCont, "replace", fmt.Sprintf("%s/policy", updatePath), interfacePolicyUUID) + err := addPatchPayloadToContainer(payloadCont, "replace", fmt.Sprintf("%s/policy", updatePath), d.Get("interface_policy_uuid").(string)) if err != nil { return err } } if d.HasChange("breakout_mode") { - breakoutMode := d.Get("breakout_mode").(string) - err := addPatchPayloadToContainer(payloadCont, "replace", fmt.Sprintf("%s/breakoutMode", updatePath), breakoutMode) + err := addPatchPayloadToContainer(payloadCont, "replace", fmt.Sprintf("%s/breakoutMode", updatePath), d.Get("breakout_mode").(string)) if err != nil { return err } diff --git a/mso/resource_mso_fabric_resource_policies_physical_interface_test.go b/mso/resource_mso_fabric_resource_policies_physical_interface_test.go index ef6bac91..49706546 100644 --- a/mso/resource_mso_fabric_resource_policies_physical_interface_test.go +++ b/mso/resource_mso_fabric_resource_policies_physical_interface_test.go @@ -24,7 +24,7 @@ func TestAccMSOFabricResourcePhysicalInterfaceResource(t *testing.T) { Check: resource.ComposeAggregateTestCheckFunc( resource.TestCheckResourceAttr("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName, "name", msoFabricResourcePhysicalInterfaceName), resource.TestCheckResourceAttr("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName, "policy_group_type", "physical"), - resource.TestCheckResourceAttr("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName, "description", "Terraform test Physical Interface"), + resource.TestCheckResourceAttr("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName, "description", ""), resource.TestCheckResourceAttr("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName, "nodes.#", "1"), resource.TestCheckResourceAttr("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName, "interfaces.#", "2"), resource.TestCheckResourceAttrSet("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName, "uuid"), @@ -77,14 +77,14 @@ func TestAccMSOFabricResourcePhysicalInterfaceResource(t *testing.T) { Config: testAccMSOFabricResourcePhysicalInterfaceConfigUpdateRemovingExtraInterfaceDescription(), Check: resource.ComposeAggregateTestCheckFunc( resource.TestCheckResourceAttr("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName, "name", msoFabricResourcePhysicalInterfaceName+"_updated"), - resource.TestCheckResourceAttr("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName, "description", "Terraform test Physical Interface updated"), + resource.TestCheckResourceAttr("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName, "description", ""), resource.TestCheckResourceAttr("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName, "nodes.#", "1"), resource.TestCheckResourceAttr("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName, "interfaces.#", "2"), resource.TestCheckResourceAttr("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName, "interface_descriptions.#", "1"), CustomTestCheckTypeSetElemAttrs("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName, "interface_descriptions", map[string]string{ "interface": "1/2", - "description": "Interface Description 1/2", + "description": "", }, ), ), @@ -198,7 +198,6 @@ func testAccMSOFabricResourcePhysicalInterfaceConfigCreate() string { resource "mso_fabric_resource_policies_physical_interface" "%[2]s" { template_id = mso_template.%[4]s.id name = "%[2]s" - description = "Terraform test Physical Interface" nodes = ["101"] interfaces = ["1/1","1/2"] interface_policy_uuid = mso_fabric_policies_interface_setting.%[3]s_physical.uuid @@ -246,13 +245,11 @@ func testAccMSOFabricResourcePhysicalInterfaceConfigUpdateRemovingExtraInterface resource "mso_fabric_resource_policies_physical_interface" "%[2]s" { template_id = mso_template.%[4]s.id name = "%[2]s_updated" - description = "Terraform test Physical Interface updated" nodes = ["101"] interfaces = ["1/1","1/2"] interface_policy_uuid = mso_fabric_policies_interface_setting.%[3]s_physical.uuid interface_descriptions { interface = "1/2" - description = "Interface Description 1/2" } }`, fabricResourcePhysicalInterfacePreConfig, msoFabricResourcePhysicalInterfaceName, msoFabricPolicyTemplateInterfaceSettingName, msoFabricResourceTemplateName) } 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_physical_interface.html.markdown b/website/docs/d/fabric_resource_policies_physical_interface.html.markdown index 3fe61970..64f7c8f9 100644 --- a/website/docs/d/fabric_resource_policies_physical_interface.html.markdown +++ b/website/docs/d/fabric_resource_policies_physical_interface.html.markdown @@ -26,18 +26,18 @@ data "mso_fabric_resource_policies_physical_interface" "example" { ## Argument Reference ## * `template_id` - (Required) The ID of the Fabric Resource template. -* `name` - (Required) The name of the Physical Interface. +* `name` - (Required) The name of the Physical Interface Policy. ## Attribute Reference ## -* `id` - (Read-Only) The unique Terraform identifier of the Physical Interface. -* `uuid` - (Read-Only) The NDO UUID of the Physical Interface. -* `description` - (Read-Only) The description of the Physical Interface. -* `nodes` - (Read-Only) A list of node IDs of the Physical Interface. -* `interfaces` - (Read-Only) A list of interfaces of the Physical Interface. -* `interface_policy_uuid` - (Read-Only) The UUID of the Physical Interface Policy associated with the Physical Interface. -* `breakout_mode` - (Read-Only) The breakout mode of the Physical Interface. -* `interface_descriptions` - (Read-Only) A list of interface descriptions of the Physical Interface member interfaces. +* `id` - (Read-Only) The unique Terraform identifier of the Physical Interface Policy. +* `uuid` - (Read-Only) The NDO UUID of the Physical Interface Policy. +* `description` - (Read-Only) The description of the Physical Interface Policy. +* `nodes` - (Read-Only) A list of node IDs where this Physical Interface Policy will be applied. +* `interfaces` - (Read-Only) A list of interfaces where this Physical Interface Policy will be applied. +* `interface_policy_uuid` - (Read-Only) The UUID of the (physical) interface settings policy to associate with the Physical Interface Policy. This policy will be applied to every interface listed in the `interfaces` attribute. +* `breakout_mode` - (Read-Only) The breakout mode of the Physical Interface Policy. +* `interface_descriptions` - (Read-Only) A list of interface descriptions of the Physical Interface Policy. * `interface` - (Read-Only) The interface ID of the member interface. * `description` - (Read-Only) The description of the member interface. -* `policy_group_type` - (Read-Only) The policy group type of the Physical Interface. \ No newline at end of file +* `policy_group_type` - (Read-Only) The policy group type of the Physical Interface. diff --git a/website/docs/r/fabric_resource_policies_physical_interface.html.markdown b/website/docs/r/fabric_resource_policies_physical_interface.html.markdown index 797f3075..9e5cd6ac 100644 --- a/website/docs/r/fabric_resource_policies_physical_interface.html.markdown +++ b/website/docs/r/fabric_resource_policies_physical_interface.html.markdown @@ -61,25 +61,25 @@ resource "mso_fabric_resource_policies_physical_interface" "breakout" { ## Argument Reference ## * `template_id` - (Required) The ID of the Fabric Resource template. -* `name` - (Required) The name of the Physical Interface. -* `description` - (Optional) The description of the Physical Interface. -* `nodes` - (Required) A list of node IDs of the Physical Interface. This is required when creating or updating a Physical Interface. -* `interfaces` - (Required) A list of interfaces of the Physical Interface. This is required when creating or updating a Physical Interface. -* `interface_policy_uuid` - (Optional) The UUID of the Physical Interface Policy to associate with the Physical Interface. Either `interface_policy_uuid` or `breakout_mode` must be specified when creating or updating a Physical Interface. -* `breakout_mode` - (Optional) The breakout mode of the Physical Interface. Valid values are `4x100G`, `4x25G`, and `4x10G`. Either `interface_policy_uuid` or `breakout_mode` must be specified when creating or updating a Physical Interface. -* `interface_descriptions` - (Optional) A list of interface descriptions of the Physical Interface member interfaces. +* `name` - (Required) The name of the Physical Interface Policy. +* `description` - (Optional) The description of the Physical Interface Policy. +* `nodes` - (Required) A list of node IDs where this Physical Interface Policy will be applied. This is required when creating or updating a Physical Interface Policy. +* `interfaces` - (Required) A list of interfaces where this Physical Interface Policy will be applied. This is required when creating or updating a Physical Interface Policy. +* `interface_policy_uuid` - (Optional) The UUID of the (physical) interface settings policy to associate with the Physical Interface Policy. This policy will be applied to every interface listed in the `interfaces` attribute. Either `interface_policy_uuid` or `breakout_mode` must be specified when creating or updating a Physical Interface Policy. +* `breakout_mode` - (Optional) The breakout mode of the Physical Interface Policy. Valid values are `4x100G`, `4x25G`, and `4x10G`. Either `interface_policy_uuid` or `breakout_mode` must be specified when creating or updating a Physical Interface Policy. +* `interface_descriptions` - (Optional) A list of interface descriptions of the Physical 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 Physical Interface. -* `uuid` - (Read-Only) The NDO UUID of the Physical Interface. -* `policy_group_type` - (Read-Only) The policy group type of the Physical Interface. +* `id` - (Read-Only) The unique Terraform identifier of the Physical Interface Policy. +* `uuid` - (Read-Only) The NDO UUID of the Physical Interface Policy. +* `policy_group_type` - (Read-Only) The policy group type of the Physical Interface Policy. ## Importing ## -An existing MSO Fabric Resource Policies Physical Interface can be [imported][docs-import] into this resource via its ID, using the following command: +An existing MSO Fabric Resource Policies Physical 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 755c27437c5bfd0645145c9732c6e0dd7eded7bf Mon Sep 17 00:00:00 2001 From: Sabari Jaganathan <93724860+sajagana@users.noreply.github.com> Date: Fri, 27 Mar 2026 12:20:38 +0530 Subject: [PATCH 3/5] [ignore] Remove resource level unnecessary custom validations and add test for the API config issues --- ...ic_resource_policies_physical_interface.go | 42 --------------- ...source_policies_physical_interface_test.go | 52 ++++++++++++++++++- 2 files changed, 51 insertions(+), 43 deletions(-) diff --git a/mso/resource_mso_fabric_resource_policies_physical_interface.go b/mso/resource_mso_fabric_resource_policies_physical_interface.go index 115c3898..94a03c99 100644 --- a/mso/resource_mso_fabric_resource_policies_physical_interface.go +++ b/mso/resource_mso_fabric_resource_policies_physical_interface.go @@ -22,8 +22,6 @@ func resourceMSOPhysicalInterface() *schema.Resource { State: resourceMSOPhysicalInterfaceImport, }, - CustomizeDiff: customizeDiffPhysicalInterface, - SchemaVersion: 1, Schema: map[string]*schema.Schema{ "template_id": { @@ -96,46 +94,6 @@ func resourceMSOPhysicalInterface() *schema.Resource { } } -func customizeDiffPhysicalInterface(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 getInterfaceDescriptionsPayloadPhysical(interfaceDescriptions *schema.Set) []map[string]interface{} { interfaceDescriptionsList := interfaceDescriptions.List() payload := make([]map[string]interface{}, 0) diff --git a/mso/resource_mso_fabric_resource_policies_physical_interface_test.go b/mso/resource_mso_fabric_resource_policies_physical_interface_test.go index 49706546..fd6268e7 100644 --- a/mso/resource_mso_fabric_resource_policies_physical_interface_test.go +++ b/mso/resource_mso_fabric_resource_policies_physical_interface_test.go @@ -14,7 +14,7 @@ func TestAccMSOFabricResourcePhysicalInterfaceResource(t *testing.T) { Providers: testAccProviders, Steps: []resource.TestStep{ { - PreConfig: func() { fmt.Println("Test: Missing interface_policy_uuid and breakout_mode (error)") }, + PreConfig: func() { fmt.Println("Test: Create Without interface_policy_uuid and breakout_mode (error)") }, Config: testAccMSOFabricResourcePhysicalInterfaceConfigErrorMissingInterfacePolicyAndBreakoutMode(), ExpectError: regexp.MustCompile(`Either 'interface_policy_uuid' or 'breakout_mode' must be specified for creating a Physical Interface`), }, @@ -175,6 +175,16 @@ func TestAccMSOFabricResourcePhysicalInterfaceResource(t *testing.T) { ImportState: true, ImportStateVerify: true, }, + { + PreConfig: func() { fmt.Println("Test: Duplicate interface descriptions (error)") }, + Config: testAccMSOFabricResourcePhysicalInterfaceBreakoutModeConfigUpdateRemovingDuplicateInterfaceDescription(), + ExpectError: regexp.MustCompile(regexp.QuoteMeta(fmt.Sprintf("interface profile %s_breakout_updated have more than one description for interface 1/2", msoFabricResourcePhysicalInterfaceName))), + }, + { + PreConfig: func() { fmt.Println("Test: Invalid interface in interface descriptions (error)") }, + Config: testAccMSOFabricResourcePhysicalInterfaceBreakoutModeConfigUpdateRemovingInvalidInterfaceDescription(), + ExpectError: regexp.MustCompile(regexp.QuoteMeta(fmt.Sprintf("interface profile %s_breakout_updated doesn't have interface 1/3 which is used in description", msoFabricResourcePhysicalInterfaceName))), + }, }, CheckDestroy: testCheckResourceDestroyPolicyWithPathAttributesAndArguments("mso_fabric_resource_policies_physical_interface", "fabricResourceTemplate", "template", "physicalInterfaces"), }) @@ -317,3 +327,43 @@ func testAccMSOFabricResourcePhysicalInterfaceBreakoutModeConfigUpdateRemovingEx } }`, fabricResourcePhysicalInterfacePreConfig, msoFabricResourcePhysicalInterfaceName, msoFabricResourceTemplateName) } + +func testAccMSOFabricResourcePhysicalInterfaceBreakoutModeConfigUpdateRemovingDuplicateInterfaceDescription() string { + return fmt.Sprintf(`%[1]s + resource "mso_fabric_resource_policies_physical_interface" "%[2]s_breakout" { + template_id = mso_template.%[3]s.id + name = "%[2]s_breakout_updated" + description = "Terraform test Physical Interface updated" + nodes = ["101"] + interfaces = ["1/1","1/2"] + breakout_mode = "4x100G" + interface_descriptions { + interface = "1/2" + description = "Interface Description 1/2" + } + interface_descriptions { + interface = "1/2" + description = "Interface Description 1/2 duplicate" + } + }`, fabricResourcePhysicalInterfacePreConfig, msoFabricResourcePhysicalInterfaceName, msoFabricResourceTemplateName) +} + +func testAccMSOFabricResourcePhysicalInterfaceBreakoutModeConfigUpdateRemovingInvalidInterfaceDescription() string { + return fmt.Sprintf(`%[1]s + resource "mso_fabric_resource_policies_physical_interface" "%[2]s_breakout" { + template_id = mso_template.%[3]s.id + name = "%[2]s_breakout_updated" + description = "Terraform test Physical Interface updated" + nodes = ["101"] + interfaces = ["1/1","1/2"] + breakout_mode = "4x100G" + interface_descriptions { + interface = "1/2" + description = "Interface Description 1/2" + } + interface_descriptions { + interface = "1/3" + description = "Interface Description 1/2 duplicate" + } + }`, fabricResourcePhysicalInterfacePreConfig, msoFabricResourcePhysicalInterfaceName, msoFabricResourceTemplateName) +} From e7631a38c336badc07d1ecb5dad447f9813a2d26 Mon Sep 17 00:00:00 2001 From: Sabari Jaganathan <93724860+sajagana@users.noreply.github.com> Date: Tue, 7 Apr 2026 09:26:44 +0530 Subject: [PATCH 4/5] [ignore] Rename interface_policy_uuid attribute to interface_policy_group_uuid in the mso_fabric_resource_policies_physical_interface resource --- .../main.tf | 12 ++--- ...ic_resource_policies_physical_interface.go | 8 ++- ...source_policies_physical_interface_test.go | 2 +- ...ic_resource_policies_physical_interface.go | 26 ++++++---- ...source_policies_physical_interface_test.go | 50 +++++++++---------- ..._policies_physical_interface.html.markdown | 2 +- ..._policies_physical_interface.html.markdown | 16 +++--- 7 files changed, 62 insertions(+), 54 deletions(-) diff --git a/examples/fabric_resource_policies_physical_interface/main.tf b/examples/fabric_resource_policies_physical_interface/main.tf index 27a97a28..2f779734 100644 --- a/examples/fabric_resource_policies_physical_interface/main.tf +++ b/examples/fabric_resource_policies_physical_interface/main.tf @@ -30,12 +30,12 @@ resource "mso_template" "fabric_resource_template" { } resource "mso_fabric_resource_policies_physical_interface" "physical" { - template_id = mso_template.fabric_resource_template.id - name = "physical_interface" - description = "Terraform test Physical Interface" - nodes = ["101", "102"] - interfaces = ["1/1", "1/2"] - interface_policy_uuid = mso_fabric_policies_interface_setting.physical_interface.id + template_id = mso_template.fabric_resource_template.id + name = "physical_interface" + description = "Terraform test Physical Interface" + nodes = ["101", "102"] + interfaces = ["1/1", "1/2"] + interface_policy_group_uuid = mso_fabric_policies_interface_setting.physical_interface.id interface_descriptions { interface = "1/1" description = "Interface Description 1/1" diff --git a/mso/datasource_mso_fabric_resource_policies_physical_interface.go b/mso/datasource_mso_fabric_resource_policies_physical_interface.go index 43486300..7b8bf648 100644 --- a/mso/datasource_mso_fabric_resource_policies_physical_interface.go +++ b/mso/datasource_mso_fabric_resource_policies_physical_interface.go @@ -39,7 +39,7 @@ func datasourceMSOPhysicalInterface() *schema.Resource { }, Computed: true, }, - "interface_policy_uuid": { + "interface_policy_group_uuid": { Type: schema.TypeString, Computed: true, }, @@ -92,7 +92,11 @@ func dataSourceMSOPhysicalInterfaceRead(d *schema.ResourceData, m interface{}) e return err } - setPhysicalInterfaceData(d, policy, templateId) + err = setPhysicalInterfaceData(d, policy, templateId) + if err != nil { + return err + } + log.Printf("[DEBUG] MSO Physical Interface Data Source - Read Complete: %v", d.Id()) return nil } diff --git a/mso/datasource_mso_fabric_resource_policies_physical_interface_test.go b/mso/datasource_mso_fabric_resource_policies_physical_interface_test.go index 6c481bdd..e81b5e0f 100644 --- a/mso/datasource_mso_fabric_resource_policies_physical_interface_test.go +++ b/mso/datasource_mso_fabric_resource_policies_physical_interface_test.go @@ -23,7 +23,7 @@ func TestAccMSOFabricResourcePhysicalInterfaceDataSource(t *testing.T) { resource.TestCheckResourceAttr("data.mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName, "interfaces.#", "2"), resource.TestCheckResourceAttrSet("data.mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName, "uuid"), resource.TestCheckResourceAttrSet("data.mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName, "template_id"), - resource.TestCheckResourceAttrSet("data.mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName, "interface_policy_uuid"), + resource.TestCheckResourceAttrSet("data.mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName, "interface_policy_group_uuid"), resource.TestCheckResourceAttr("data.mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName, "interface_descriptions.#", "2"), CustomTestCheckTypeSetElemAttrs("data.mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName, "interface_descriptions", map[string]string{ diff --git a/mso/resource_mso_fabric_resource_policies_physical_interface.go b/mso/resource_mso_fabric_resource_policies_physical_interface.go index 94a03c99..05600dbd 100644 --- a/mso/resource_mso_fabric_resource_policies_physical_interface.go +++ b/mso/resource_mso_fabric_resource_policies_physical_interface.go @@ -51,7 +51,7 @@ func resourceMSOPhysicalInterface() *schema.Resource { Type: schema.TypeString, }, }, - "interface_policy_uuid": { + "interface_policy_group_uuid": { Type: schema.TypeString, Optional: true, ConflictsWith: []string{"breakout_mode"}, @@ -64,7 +64,7 @@ func resourceMSOPhysicalInterface() *schema.Resource { "4x25G", "4x10G", }, false), - ConflictsWith: []string{"interface_policy_uuid"}, + ConflictsWith: []string{"interface_policy_group_uuid"}, }, "interface_descriptions": { Type: schema.TypeSet, @@ -131,7 +131,7 @@ func setPhysicalInterfaceData(d *schema.ResourceData, response *container.Contai } 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())) } if response.Exists("breakoutMode") { @@ -160,7 +160,10 @@ func setPhysicalInterfaceData(d *schema.ResourceData, response *container.Contai func resourceMSOPhysicalInterfaceImport(d *schema.ResourceData, m interface{}) ([]*schema.ResourceData, error) { log.Printf("[DEBUG] MSO Physical Interface Resource - Beginning Import: %v", d.Id()) - resourceMSOPhysicalInterfaceRead(d, m) + err := resourceMSOPhysicalInterfaceRead(d, m) + if err != nil { + return nil, err + } log.Printf("[DEBUG] MSO Physical Interface Resource - Import Complete: %v", d.Id()) return []*schema.ResourceData{d}, nil } @@ -182,16 +185,16 @@ func resourceMSOPhysicalInterfaceCreate(d *schema.ResourceData, m interface{}) e payload["nodes"] = getListOfStringsFromSchemaSet(d, "nodes") payload["interfaces"] = strings.Join(getListOfStringsFromSchemaSet(d, "interfaces"), ",") - interfacePolicyUUID := d.Get("interface_policy_uuid").(string) + interfacePolicyUUID := d.Get("interface_policy_group_uuid").(string) breakoutMode := d.Get("breakout_mode").(string) + // API error message is not clear when both fields are empty, so adding an explicit check here to return a clearer error message if interfacePolicyUUID == "" && breakoutMode == "" { - return fmt.Errorf("Either 'interface_policy_uuid' or 'breakout_mode' must be specified for creating a Physical Interface") + return fmt.Errorf("Either 'interface_policy_group_uuid' or 'breakout_mode' must be specified for creating a Physical Interface") } if interfacePolicyUUID != "" { payload["policy"] = interfacePolicyUUID - payload["policyGroupType"] = "physical" } else { payload["breakoutMode"] = breakoutMode payload["policyGroupType"] = "breakout" @@ -251,8 +254,9 @@ func resourceMSOPhysicalInterfaceUpdate(d *schema.ResourceData, m interface{}) e msoClient := m.(*client.Client) templateId := d.Get("template_id").(string) - if d.Get("interface_policy_uuid").(string) == "" && d.Get("breakout_mode").(string) == "" { - return fmt.Errorf("Either 'interface_policy_uuid' or 'breakout_mode' must be specified for creating a Physical Interface") + // API error message is not clear when both fields are empty, so adding an explicit check here to return a clearer error message + if d.Get("interface_policy_group_uuid").(string) == "" && d.Get("breakout_mode").(string) == "" { + return fmt.Errorf("Either 'interface_policy_group_uuid' or 'breakout_mode' must be specified for creating a Physical Interface") } templateContainer, err := msoClient.GetViaURL(fmt.Sprintf("api/v1/templates/%s", templateId)) @@ -298,8 +302,8 @@ func resourceMSOPhysicalInterfaceUpdate(d *schema.ResourceData, m interface{}) e } } - if d.HasChange("interface_policy_uuid") { - err := addPatchPayloadToContainer(payloadCont, "replace", fmt.Sprintf("%s/policy", updatePath), d.Get("interface_policy_uuid").(string)) + if d.HasChange("interface_policy_group_uuid") { + err := addPatchPayloadToContainer(payloadCont, "replace", fmt.Sprintf("%s/policy", updatePath), d.Get("interface_policy_group_uuid").(string)) if err != nil { return err } diff --git a/mso/resource_mso_fabric_resource_policies_physical_interface_test.go b/mso/resource_mso_fabric_resource_policies_physical_interface_test.go index fd6268e7..bcf7c064 100644 --- a/mso/resource_mso_fabric_resource_policies_physical_interface_test.go +++ b/mso/resource_mso_fabric_resource_policies_physical_interface_test.go @@ -14,9 +14,9 @@ func TestAccMSOFabricResourcePhysicalInterfaceResource(t *testing.T) { Providers: testAccProviders, Steps: []resource.TestStep{ { - PreConfig: func() { fmt.Println("Test: Create Without interface_policy_uuid and breakout_mode (error)") }, + PreConfig: func() { fmt.Println("Test: Create Without interface_policy_group_uuid and breakout_mode (error)") }, Config: testAccMSOFabricResourcePhysicalInterfaceConfigErrorMissingInterfacePolicyAndBreakoutMode(), - ExpectError: regexp.MustCompile(`Either 'interface_policy_uuid' or 'breakout_mode' must be specified for creating a Physical Interface`), + ExpectError: regexp.MustCompile(`Either 'interface_policy_group_uuid' or 'breakout_mode' must be specified for creating a Physical Interface`), }, { PreConfig: func() { fmt.Println("Test: Create Physical Interface") }, @@ -29,7 +29,7 @@ func TestAccMSOFabricResourcePhysicalInterfaceResource(t *testing.T) { resource.TestCheckResourceAttr("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName, "interfaces.#", "2"), resource.TestCheckResourceAttrSet("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName, "uuid"), resource.TestCheckResourceAttrSet("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName, "template_id"), - resource.TestCheckResourceAttrSet("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName, "interface_policy_uuid"), + resource.TestCheckResourceAttrSet("mso_fabric_resource_policies_physical_interface."+msoFabricResourcePhysicalInterfaceName, "interface_policy_group_uuid"), ), }, { @@ -206,23 +206,23 @@ func testAccMSOFabricResourcePhysicalInterfaceConfigErrorMissingInterfacePolicyA func testAccMSOFabricResourcePhysicalInterfaceConfigCreate() string { return fmt.Sprintf(`%[1]s resource "mso_fabric_resource_policies_physical_interface" "%[2]s" { - template_id = mso_template.%[4]s.id - name = "%[2]s" - nodes = ["101"] - interfaces = ["1/1","1/2"] - interface_policy_uuid = mso_fabric_policies_interface_setting.%[3]s_physical.uuid + template_id = mso_template.%[4]s.id + name = "%[2]s" + nodes = ["101"] + interfaces = ["1/1","1/2"] + interface_policy_group_uuid = mso_fabric_policies_interface_setting.%[3]s_physical.uuid }`, fabricResourcePhysicalInterfacePreConfig, msoFabricResourcePhysicalInterfaceName, msoFabricPolicyTemplateInterfaceSettingName, msoFabricResourceTemplateName) } func testAccMSOFabricResourcePhysicalInterfaceConfigUpdateAddingInterfaceDescriptions() string { return fmt.Sprintf(`%[1]s resource "mso_fabric_resource_policies_physical_interface" "%[2]s" { - template_id = mso_template.%[4]s.id - name = "%[2]s" - description = "Terraform test Physical Interface updated" - nodes = ["101", "102"] - interfaces = ["1/1","1/2"] - interface_policy_uuid = mso_fabric_policies_interface_setting.%[3]s_physical.uuid + template_id = mso_template.%[4]s.id + name = "%[2]s" + description = "Terraform test Physical Interface updated" + nodes = ["101", "102"] + interfaces = ["1/1","1/2"] + interface_policy_group_uuid = mso_fabric_policies_interface_setting.%[3]s_physical.uuid interface_descriptions { interface = "1/1" description = "Interface Description 1/1" @@ -233,12 +233,12 @@ func testAccMSOFabricResourcePhysicalInterfaceConfigUpdateAddingInterfaceDescrip func testAccMSOFabricResourcePhysicalInterfaceConfigUpdateAddingExtraInterfaceDescription() string { return fmt.Sprintf(`%[1]s resource "mso_fabric_resource_policies_physical_interface" "%[2]s" { - template_id = mso_template.%[4]s.id - name = "%[2]s" - description = "Terraform test Physical Interface updated" - nodes = ["101", "102"] - interfaces = ["1/1","1/2"] - interface_policy_uuid = mso_fabric_policies_interface_setting.%[3]s_physical.uuid + template_id = mso_template.%[4]s.id + name = "%[2]s" + description = "Terraform test Physical Interface updated" + nodes = ["101", "102"] + interfaces = ["1/1","1/2"] + interface_policy_group_uuid = mso_fabric_policies_interface_setting.%[3]s_physical.uuid interface_descriptions { interface = "1/1" description = "Interface Description 1/1" @@ -253,11 +253,11 @@ func testAccMSOFabricResourcePhysicalInterfaceConfigUpdateAddingExtraInterfaceDe func testAccMSOFabricResourcePhysicalInterfaceConfigUpdateRemovingExtraInterfaceDescription() string { return fmt.Sprintf(`%[1]s resource "mso_fabric_resource_policies_physical_interface" "%[2]s" { - template_id = mso_template.%[4]s.id - name = "%[2]s_updated" - nodes = ["101"] - interfaces = ["1/1","1/2"] - interface_policy_uuid = mso_fabric_policies_interface_setting.%[3]s_physical.uuid + template_id = mso_template.%[4]s.id + name = "%[2]s_updated" + nodes = ["101"] + interfaces = ["1/1","1/2"] + interface_policy_group_uuid = mso_fabric_policies_interface_setting.%[3]s_physical.uuid interface_descriptions { interface = "1/2" } diff --git a/website/docs/d/fabric_resource_policies_physical_interface.html.markdown b/website/docs/d/fabric_resource_policies_physical_interface.html.markdown index 64f7c8f9..f874fae8 100644 --- a/website/docs/d/fabric_resource_policies_physical_interface.html.markdown +++ b/website/docs/d/fabric_resource_policies_physical_interface.html.markdown @@ -35,7 +35,7 @@ data "mso_fabric_resource_policies_physical_interface" "example" { * `description` - (Read-Only) The description of the Physical Interface Policy. * `nodes` - (Read-Only) A list of node IDs where this Physical Interface Policy will be applied. * `interfaces` - (Read-Only) A list of interfaces where this Physical Interface Policy will be applied. -* `interface_policy_uuid` - (Read-Only) The UUID of the (physical) interface settings policy to associate with the Physical Interface Policy. This policy will be applied to every interface listed in the `interfaces` attribute. +* `interface_policy_group_uuid` - (Read-Only) The UUID of the (physical) interface settings policy to associate with the Physical Interface Policy. This policy will be applied to every interface listed in the `interfaces` attribute. * `breakout_mode` - (Read-Only) The breakout mode of the Physical Interface Policy. * `interface_descriptions` - (Read-Only) A list of interface descriptions of the Physical Interface Policy. * `interface` - (Read-Only) The interface ID of the member interface. diff --git a/website/docs/r/fabric_resource_policies_physical_interface.html.markdown b/website/docs/r/fabric_resource_policies_physical_interface.html.markdown index 9e5cd6ac..95cd9e3a 100644 --- a/website/docs/r/fabric_resource_policies_physical_interface.html.markdown +++ b/website/docs/r/fabric_resource_policies_physical_interface.html.markdown @@ -20,12 +20,12 @@ Manages Fabric Resource Policies Physical Interface on Cisco Nexus Dashboard Orc ```hcl resource "mso_fabric_resource_policies_physical_interface" "physical" { - template_id = mso_template.fabric_resource_template.id - name = "physical_interface" - description = "Terraform test Physical Interface" - nodes = ["101", "102"] - interfaces = ["1/1", "1/2"] - interface_policy_uuid = mso_fabric_policies_interface_setting.physical_interface.id + template_id = mso_template.fabric_resource_template.id + name = "physical_interface" + description = "Terraform test Physical Interface" + nodes = ["101", "102"] + interfaces = ["1/1", "1/2"] + interface_policy_group_uuid = mso_fabric_policies_interface_setting.physical_interface.id interface_descriptions { interface = "1/1" description = "Interface Description 1/1" @@ -65,8 +65,8 @@ resource "mso_fabric_resource_policies_physical_interface" "breakout" { * `description` - (Optional) The description of the Physical Interface Policy. * `nodes` - (Required) A list of node IDs where this Physical Interface Policy will be applied. This is required when creating or updating a Physical Interface Policy. * `interfaces` - (Required) A list of interfaces where this Physical Interface Policy will be applied. This is required when creating or updating a Physical Interface Policy. -* `interface_policy_uuid` - (Optional) The UUID of the (physical) interface settings policy to associate with the Physical Interface Policy. This policy will be applied to every interface listed in the `interfaces` attribute. Either `interface_policy_uuid` or `breakout_mode` must be specified when creating or updating a Physical Interface Policy. -* `breakout_mode` - (Optional) The breakout mode of the Physical Interface Policy. Valid values are `4x100G`, `4x25G`, and `4x10G`. Either `interface_policy_uuid` or `breakout_mode` must be specified when creating or updating a Physical Interface Policy. +* `interface_policy_group_uuid` - (Optional) The UUID of the (physical) interface settings policy to associate with the Physical Interface Policy. This policy will be applied to every interface listed in the `interfaces` attribute. Either `interface_policy_group_uuid` or `breakout_mode` must be specified when creating or updating a Physical Interface Policy. +* `breakout_mode` - (Optional) The breakout mode of the Physical Interface Policy. Valid values are `4x100G`, `4x25G`, and `4x10G`. Either `interface_policy_group_uuid` or `breakout_mode` must be specified when creating or updating a Physical Interface Policy. * `interface_descriptions` - (Optional) A list of interface descriptions of the Physical 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. From 097d5f49299ea4b49547a405d3f95fb49a5924fb Mon Sep 17 00:00:00 2001 From: Sabari Jaganathan <93724860+sajagana@users.noreply.github.com> Date: Wed, 8 Apr 2026 20:41:40 +0530 Subject: [PATCH 5/5] [ignore] Remove UUID check from the mso_tenant_policies_ipsla_track_list resource test file --- ...o_tenant_policies_ipsla_track_list_test.go | 32 +++++++------------ 1 file changed, 12 insertions(+), 20 deletions(-) diff --git a/mso/resource_mso_tenant_policies_ipsla_track_list_test.go b/mso/resource_mso_tenant_policies_ipsla_track_list_test.go index b19c1466..608c6e82 100644 --- a/mso/resource_mso_tenant_policies_ipsla_track_list_test.go +++ b/mso/resource_mso_tenant_policies_ipsla_track_list_test.go @@ -24,11 +24,9 @@ func TestAccMSOTenantPoliciesIPSLATrackListResource(t *testing.T) { resource.TestCheckResourceAttr("mso_tenant_policies_ipsla_track_list."+msoTenantPolicyTemplateIPSLATrackListName, "members.#", "1"), CustomTestCheckTypeSetElemAttrs("mso_tenant_policies_ipsla_track_list."+msoTenantPolicyTemplateIPSLATrackListName, "members", map[string]string{ - "destination_ip": "1.1.1.1", - "ipsla_monitoring_policy_uuid": fmt.Sprintf("mso_tenant_policies_ipsla_monitoring_policy.%s.uuid", msoTenantPolicyTemplateIPSLAMonitoringPolicyName), - "scope_type": "bd", - "scope_uuid": fmt.Sprintf("mso_schema_template_bd.%s.uuid", msoSchemaTemplateBdName), - "weight": "10", + "destination_ip": "1.1.1.1", + "scope_type": "bd", + "weight": "10", }, ), ), @@ -45,20 +43,16 @@ func TestAccMSOTenantPoliciesIPSLATrackListResource(t *testing.T) { resource.TestCheckResourceAttr("mso_tenant_policies_ipsla_track_list."+msoTenantPolicyTemplateIPSLATrackListName, "members.#", "2"), CustomTestCheckTypeSetElemAttrs("mso_tenant_policies_ipsla_track_list."+msoTenantPolicyTemplateIPSLATrackListName, "members", map[string]string{ - "destination_ip": "1.1.1.3", - "ipsla_monitoring_policy_uuid": fmt.Sprintf("mso_tenant_policies_ipsla_monitoring_policy.%s.uuid", msoTenantPolicyTemplateIPSLAMonitoringPolicyName), - "scope_type": "bd", - "scope_uuid": fmt.Sprintf("mso_schema_template_bd.%s.uuid", msoSchemaTemplateBdName), - "weight": "10", + "destination_ip": "1.1.1.3", + "scope_type": "bd", + "weight": "10", }, ), CustomTestCheckTypeSetElemAttrs("mso_tenant_policies_ipsla_track_list."+msoTenantPolicyTemplateIPSLATrackListName, "members", map[string]string{ - "destination_ip": "1.1.1.2", - "ipsla_monitoring_policy_uuid": fmt.Sprintf("mso_tenant_policies_ipsla_monitoring_policy.%s.uuid", msoTenantPolicyTemplateIPSLAMonitoringPolicyName), - "scope_type": "bd", - "scope_uuid": fmt.Sprintf("mso_schema_template_bd.%s.uuid", msoSchemaTemplateBdName), - "weight": "10", + "destination_ip": "1.1.1.2", + "scope_type": "bd", + "weight": "10", }, ), ), @@ -75,11 +69,9 @@ func TestAccMSOTenantPoliciesIPSLATrackListResource(t *testing.T) { resource.TestCheckResourceAttr("mso_tenant_policies_ipsla_track_list."+msoTenantPolicyTemplateIPSLATrackListName, "members.#", "1"), CustomTestCheckTypeSetElemAttrs("mso_tenant_policies_ipsla_track_list."+msoTenantPolicyTemplateIPSLATrackListName, "members", map[string]string{ - "destination_ip": "1.1.1.2", - "ipsla_monitoring_policy_uuid": fmt.Sprintf("mso_tenant_policies_ipsla_monitoring_policy.%s.uuid", msoTenantPolicyTemplateIPSLAMonitoringPolicyName), - "scope_type": "bd", - "scope_uuid": fmt.Sprintf("mso_schema_template_bd.%s.uuid", msoSchemaTemplateBdName), - "weight": "10", + "destination_ip": "1.1.1.2", + "scope_type": "bd", + "weight": "10", }, ), ),