From d979ea7852d2b798f61303c415b197b023a846f4 Mon Sep 17 00:00:00 2001 From: samitab Date: Tue, 24 Feb 2026 16:31:02 +1000 Subject: [PATCH 1/5] [minor_change] Add mso_fabric_policies_node_settings resource and datasource. --- mso/constants.go | 9 + ...ource_mso_fabric_policies_node_settings.go | 77 +++++ ..._mso_fabric_policies_node_settings_test.go | 37 ++ mso/provider.go | 2 + ...ource_mso_fabric_policies_node_settings.go | 326 ++++++++++++++++++ ..._mso_fabric_policies_node_settings_test.go | 101 ++++++ ...abric_policies_node_settings.html.markdown | 43 +++ ...abric_policies_node_settings.html.markdown | 58 ++++ 8 files changed, 653 insertions(+) create mode 100644 mso/datasource_mso_fabric_policies_node_settings.go create mode 100644 mso/datasource_mso_fabric_policies_node_settings_test.go create mode 100644 mso/resource_mso_fabric_policies_node_settings.go create mode 100644 mso/resource_mso_fabric_policies_node_settings_test.go create mode 100644 website/docs/d/fabric_policies_node_settings.html.markdown create mode 100644 website/docs/r/fabric_policies_node_settings.html.markdown diff --git a/mso/constants.go b/mso/constants.go index a2b6eb46..bf14b4eb 100644 --- a/mso/constants.go +++ b/mso/constants.go @@ -95,3 +95,12 @@ var loadBalanceHashingMap = map[string]string{ "layer_4_source_ip": "l4-src-port", "source_ip": "src-ip", } + +var synceQualityLevelOptionsMap = map[string]string{ + "op1": "option_1", + "op2g1": "option_2_generation_1", + "op2g2": "option_2_generation_2", + "option_1": "op1", + "option_2_generation_1": "op2g1", + "option_2_generation_2": "op2g2", +} diff --git a/mso/datasource_mso_fabric_policies_node_settings.go b/mso/datasource_mso_fabric_policies_node_settings.go new file mode 100644 index 00000000..a7d7eaa0 --- /dev/null +++ b/mso/datasource_mso_fabric_policies_node_settings.go @@ -0,0 +1,77 @@ +package mso + +import ( + "log" + + "github.com/ciscoecosystem/mso-go-client/client" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" +) + +func datasourceMSONodeSettings() *schema.Resource { + return &schema.Resource{ + Read: dataSourceNodeSettingsRead, + + Schema: map[string]*schema.Schema{ + "template_id": { + Type: schema.TypeString, + Required: true, + }, + "name": { + Type: schema.TypeString, + Required: true, + }, + "description": { + Type: schema.TypeString, + Computed: true, + }, + "uuid": { + Type: schema.TypeString, + Computed: true, + }, + "synce": &schema.Schema{ + Type: schema.TypeMap, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "admin_state": { + Type: schema.TypeString, + Computed: true, + }, + "quality_level": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + "ptp": &schema.Schema{ + Type: schema.TypeMap, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "node_domain": &schema.Schema{ + Type: schema.TypeInt, + Computed: true, + }, + "priority_2": &schema.Schema{ + Type: schema.TypeInt, + Computed: true, + }, + }, + }, + }, + }, + } +} + +func dataSourceNodeSettingsRead(d *schema.ResourceData, m interface{}) error { + log.Printf("[DEBUG] MSO Node Settings Data Source - Beginning Read") + msoClient := m.(*client.Client) + + templateId := d.Get("template_id").(string) + policyName := d.Get("name").(string) + + setNodeSettingsData(d, msoClient, templateId, policyName) + log.Printf("[DEBUG] MSO Node Settings Data Source - Read Complete : %v", d.Id()) + return nil +} diff --git a/mso/datasource_mso_fabric_policies_node_settings_test.go b/mso/datasource_mso_fabric_policies_node_settings_test.go new file mode 100644 index 00000000..63517ab6 --- /dev/null +++ b/mso/datasource_mso_fabric_policies_node_settings_test.go @@ -0,0 +1,37 @@ +package mso + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" +) + +func TestAccMSONodeSettingsDataSource(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + PreConfig: func() { fmt.Println("Test: Node Settings Data Source") }, + Config: testAccMSONodeSettingsDataSource(), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("mso_fabric_policies_node_settings.node_settings", "name", "tf_test_node_settings"), + resource.TestCheckResourceAttr("mso_fabric_policies_node_settings.node_settings", "description", "Terraform test Node Settings Policy"), + resource.TestCheckResourceAttr("mso_fabric_policies_node_settings.node_settings", "synce.admin_state", "enabled"), + resource.TestCheckResourceAttr("mso_fabric_policies_node_settings.node_settings", "synce.quality_level", "option_2_generation_1"), + resource.TestCheckResourceAttr("mso_fabric_policies_node_settings.node_settings", "ptp.node_domain", "25"), + resource.TestCheckResourceAttr("mso_fabric_policies_node_settings.node_settings", "ptp.priority_2", "99"), + ), + }, + }, + }) +} + +func testAccMSONodeSettingsDataSource() string { + return fmt.Sprintf(`%s + data "mso_fabric_policies_node_settings" "node_settings" { + template_id = mso_fabric_policies_node_settings.node_settings.template_id + name = "tf_test_node_settings" + }`, testAccMSONodeSettingsConfigCreate()) +} diff --git a/mso/provider.go b/mso/provider.go index 18d1c7ab..43812ad6 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_policies_node_settings": resourceMSONodeSettings(), }, 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_policies_node_settings": datasourceMSONodeSettings(), }, ConfigureFunc: configureClient, diff --git a/mso/resource_mso_fabric_policies_node_settings.go b/mso/resource_mso_fabric_policies_node_settings.go new file mode 100644 index 00000000..bfd3212d --- /dev/null +++ b/mso/resource_mso_fabric_policies_node_settings.go @@ -0,0 +1,326 @@ +package mso + +import ( + "fmt" + "log" + "strconv" + + "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 resourceMSONodeSettings() *schema.Resource { + return &schema.Resource{ + Create: resourceMSONodeSettingsCreate, + Read: resourceMSONodeSettingsRead, + Update: resourceMSONodeSettingsUpdate, + Delete: resourceMSONodeSettingsDelete, + Importer: &schema.ResourceImporter{ + State: resourceMSONodeSettingsImport, + }, + + SchemaVersion: 1, + Schema: map[string]*schema.Schema{ + "template_id": { + Type: schema.TypeString, + ForceNew: true, + Required: true, + }, + "name": { + Type: schema.TypeString, + ForceNew: true, + Required: true, + ValidateFunc: validation.StringLenBetween(1, 64), + }, + "description": { + Type: schema.TypeString, + Optional: true, + Computed: true, + }, + "uuid": { + Type: schema.TypeString, + Computed: true, + }, + "synce": &schema.Schema{ + Type: schema.TypeMap, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "admin_state": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{ + "enabled", "disabled", + }, false), + }, + "quality_level": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{ + "option_1", "option_2_generation_1", "option_2_generation_2", + }, false), + }, + }, + }, + }, + "ptp": &schema.Schema{ + Type: schema.TypeMap, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "node_domain": &schema.Schema{ + Type: schema.TypeInt, + Required: true, + ValidateFunc: validation.IntBetween(24, 43), + }, + "priority_2": &schema.Schema{ + Type: schema.TypeInt, + Required: true, + ValidateFunc: validation.IntBetween(0, 255), + }, + }, + }, + }, + }, + } +} + +func getSyncePayload(synce any) map[string]string { + synceMap := synce.(map[string]any) + syncePayload := map[string]string{ + "adminState": synceMap["admin_state"].(string), + "qlOption": convertValueWithMap(synceMap["quality_level"].(string), synceQualityLevelOptionsMap), + } + return syncePayload +} + +func getPtpPayload(ptp any) (map[string]int, error) { + ptpMap := ptp.(map[string]any) + domain, err := strconv.Atoi(ptpMap["node_domain"].(string)) + if err != nil { + return nil, err + } + prio2, err := strconv.Atoi(ptpMap["priority_2"].(string)) + if err != nil { + return nil, err + } + ptpPayload := map[string]int{ + "domain": domain, + "prio2": prio2, + "prio1": 128, + } + return ptpPayload, nil +} + +func setNodeSettingsData(d *schema.ResourceData, msoClient *client.Client, templateId, policyName string) error { + response, err := msoClient.GetViaURL(fmt.Sprintf("api/v1/templates/%s", templateId)) + if err != nil { + return err + } + + policy, err := GetPolicyByName(response, policyName, "fabricPolicyTemplate", "template", "nodePolicyGroups") + if err != nil { + return err + } + + name := models.StripQuotes(policy.S("name").String()) + d.SetId(fmt.Sprintf("templateId/%s/nodeSettings/%s", templateId, name)) + d.Set("template_id", templateId) + d.Set("name", name) + d.Set("description", models.StripQuotes(policy.S("description").String())) + d.Set("uuid", models.StripQuotes(policy.S("uuid").String())) + + if policy.Exists("synce") { + synce := policy.S("synce") + synceMap := map[string]any{ + "admin_state": models.StripQuotes(synce.S("adminState").String()), + "quality_level": convertValueWithMap(models.StripQuotes(synce.S("qlOption").String()), synceQualityLevelOptionsMap), + } + d.Set("synce", synceMap) + } + + if policy.Exists("ptp") { + ptp := policy.S("ptp") + ptpMap := map[string]any{ + "node_domain": ptp.S("domain").Data().(float64), + "priority_2": ptp.S("prio1").Data().(float64), + } + d.Set("ptp", ptpMap) + } + + return nil +} + +func resourceMSONodeSettingsImport(d *schema.ResourceData, m any) ([]*schema.ResourceData, error) { + log.Printf("[DEBUG] MSO Node Settings Resource - Beginning Import: %v", d.Id()) + msoClient := m.(*client.Client) + + templateId, err := GetTemplateIdFromResourceId(d.Id()) + if err != nil { + return nil, err + } + + policyName, err := GetPolicyNameFromResourceId(d.Id(), "nodeSettings") + if err != nil { + return nil, err + } + + setNodeSettingsData(d, msoClient, templateId, policyName) + log.Printf("[DEBUG] MSO Node Settings Resource - Import Complete: %v", d.Id()) + return []*schema.ResourceData{d}, nil +} + +func resourceMSONodeSettingsCreate(d *schema.ResourceData, m any) error { + log.Printf("[DEBUG] MSO Node Settings Resource - Beginning Create: %v", d.Id()) + msoClient := m.(*client.Client) + + payload := map[string]any{} + + payload["name"] = d.Get("name").(string) + + if description, ok := d.GetOk("description"); ok { + payload["description"] = description.(string) + } + + if synce, ok := d.GetOk("synce"); ok { + syncePayload := getSyncePayload(synce) + payload["synce"] = syncePayload + } + + if ptp, ok := d.GetOk("ptp"); ok { + ptpPayload, err := getPtpPayload(ptp) + if err != nil { + return err + } + payload["ptp"] = ptpPayload + } + + payloadModel := models.GetPatchPayload("add", "/fabricPolicyTemplate/template/nodePolicyGroups/-", payload) + templateId := d.Get("template_id").(string) + + _, err := msoClient.PatchbyID(fmt.Sprintf("api/v1/templates/%s", templateId), payloadModel) + if err != nil { + return err + } + + d.SetId(fmt.Sprintf("templateId/%s/nodeSettings/%s", templateId, d.Get("name").(string))) + log.Printf("[DEBUG] MSO Node Settings Resource - Create Complete: %v", d.Id()) + return resourceMSONodeSettingsRead(d, m) +} + +func resourceMSONodeSettingsRead(d *schema.ResourceData, m any) error { + log.Printf("[DEBUG] MSO Node Settings Resource - Beginning Read: %v", d.Id()) + msoClient := m.(*client.Client) + + templateId := d.Get("template_id").(string) + policyName := d.Get("name").(string) + + setNodeSettingsData(d, msoClient, templateId, policyName) + log.Printf("[DEBUG] MSO Node Settings Resource - Read Complete : %v", d.Id()) + return nil +} + +func resourceMSONodeSettingsUpdate(d *schema.ResourceData, m any) error { + log.Printf("[DEBUG] MSO Node Settings Resource - Beginning Update: %v", d.Id()) + msoClient := m.(*client.Client) + templateId := d.Get("template_id").(string) + + templateCont, err := msoClient.GetViaURL(fmt.Sprintf("api/v1/templates/%s", templateId)) + if err != nil { + return err + } + + policyIndex, err := GetPolicyIndexByKeyAndValue(templateCont, "uuid", d.Get("uuid").(string), "fabricPolicyTemplate", "template", "nodePolicyGroups") + if err != nil { + return err + } + + updatePath := fmt.Sprintf("/fabricPolicyTemplate/template/nodePolicyGroups/%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("synce") { + if synce, ok := d.GetOk("synce"); ok { + syncePayload := getSyncePayload(synce) + err := addPatchPayloadToContainer(payloadCont, "replace", fmt.Sprintf("%s/synce", updatePath), syncePayload) + if err != nil { + return err + } + } else { + err := addPatchPayloadToContainer(payloadCont, "remove", fmt.Sprintf("%s/synce", updatePath), nil) + if err != nil { + return err + } + } + } + + if d.HasChange("ptp") { + if ptp, ok := d.GetOk("ptp"); ok { + ptpPayload, err := getPtpPayload(ptp) + if err != nil { + return err + } + err = addPatchPayloadToContainer(payloadCont, "replace", fmt.Sprintf("%s/ptp", updatePath), ptpPayload) + if err != nil { + return err + } + } else { + err := addPatchPayloadToContainer(payloadCont, "remove", fmt.Sprintf("%s/ptp", updatePath), nil) + 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/nodeSettings/%s", templateId, d.Get("name").(string))) + log.Printf("[DEBUG] MSO Node Settings Resource - Update Complete: %v", d.Id()) + return resourceMSONodeSettingsRead(d, m) +} + +func resourceMSONodeSettingsDelete(d *schema.ResourceData, m any) error { + log.Printf("[DEBUG] MSO Node Settings Resource - Beginning Delete: %v", d.Id()) + msoClient := m.(*client.Client) + + templateCont, err := msoClient.GetViaURL(fmt.Sprintf("api/v1/templates/%s", d.Get("template_id").(string))) + if err != nil { + return err + } + + policyIndex, err := GetPolicyIndexByKeyAndValue(templateCont, "uuid", d.Get("uuid").(string), "fabricPolicyTemplate", "template", "nodePolicyGroups") + if err != nil { + return err + } + + payloadModel := models.GetRemovePatchPayload(fmt.Sprintf("/fabricPolicyTemplate/template/nodePolicyGroups/%d", policyIndex)) + + _, err = msoClient.PatchbyID(fmt.Sprintf("api/v1/templates/%s", d.Get("template_id").(string)), payloadModel) + if err != nil { + return err + } + + d.SetId("") + log.Printf("[DEBUG] MSO Node Settings Resource - Delete Complete: %v", d.Id()) + return nil +} diff --git a/mso/resource_mso_fabric_policies_node_settings_test.go b/mso/resource_mso_fabric_policies_node_settings_test.go new file mode 100644 index 00000000..795e9f53 --- /dev/null +++ b/mso/resource_mso_fabric_policies_node_settings_test.go @@ -0,0 +1,101 @@ +package mso + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" +) + +func TestAccMSONodeSettingsResource(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + PreConfig: func() { fmt.Println("Test: Create Node Settings Policy") }, + Config: testAccMSONodeSettingsConfigCreate(), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("mso_fabric_policies_node_settings.node_settings", "name", "tf_test_node_settings"), + resource.TestCheckResourceAttr("mso_fabric_policies_node_settings.node_settings", "description", "Terraform test Node Settings Policy"), + resource.TestCheckResourceAttr("mso_fabric_policies_node_settings.node_settings", "synce.admin_state", "enabled"), + resource.TestCheckResourceAttr("mso_fabric_policies_node_settings.node_settings", "synce.quality_level", "option_2_generation_1"), + resource.TestCheckResourceAttr("mso_fabric_policies_node_settings.node_settings", "ptp.node_domain", "25"), + resource.TestCheckResourceAttr("mso_fabric_policies_node_settings.node_settings", "ptp.priority_2", "99"), + ), + }, + { + PreConfig: func() { fmt.Println("Test: Update Node Settings Policy") }, + Config: testAccMSONodeSettingsConfigUpdate(), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("mso_fabric_policies_node_settings.node_settings", "name", "tf_test_node_settings"), + resource.TestCheckResourceAttr("mso_fabric_policies_node_settings.node_settings", "description", "Terraform test Node Settings Policy updated"), + resource.TestCheckResourceAttr("mso_fabric_policies_node_settings.node_settings", "synce.admin_state", "disabled"), + resource.TestCheckResourceAttr("mso_fabric_policies_node_settings.node_settings", "synce.quality_level", "option_1"), + resource.TestCheckResourceAttr("mso_fabric_policies_node_settings.node_settings", "ptp.node_domain", "30"), + resource.TestCheckResourceAttr("mso_fabric_policies_node_settings.node_settings", "ptp.priority_2", "100"), + ), + }, + { + PreConfig: func() { fmt.Println("Test: Update Node Settings Policy Remove SyncE and PTP") }, + Config: testAccMSONodeSettingsConfigUpdateRemove(), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("mso_fabric_policies_node_settings.node_settings", "name", "tf_test_node_settings"), + resource.TestCheckResourceAttr("mso_fabric_policies_node_settings.node_settings", "description", "Terraform test Node Settings Policy removed synce and ptp"), + resource.TestCheckNoResourceAttr("mso_fabric_policies_node_settings.node_settings", "synce"), + resource.TestCheckNoResourceAttr("mso_fabric_policies_node_settings.node_settings", "ptp"), + ), + }, + { + PreConfig: func() { fmt.Println("Test: Import Node Settings Policy") }, + ResourceName: "mso_fabric_policies_node_settings.node_settings", + ImportState: true, + ImportStateVerify: true, + }, + }, + CheckDestroy: testCheckResourceDestroyPolicyWithPathAttributesAndArguments("mso_fabric_policies_node_settings", "fabricPolicyTemplate", "template", "nodePolicyGroups"), + }) +} + +func testAccMSONodeSettingsConfigCreate() string { + return fmt.Sprintf(`%s + resource "mso_fabric_policies_node_settings" "node_settings" { + template_id = mso_template.template_fabric_policy.id + name = "tf_test_node_settings" + description = "Terraform test Node Settings Policy" + synce = { + admin_state = "enabled" + quality_level = "option_2_generation_1" + } + ptp = { + node_domain = 25 + priority_2 = 99 + } + }`, testAccMSOTemplateResourceFabricPolicyConfig()) +} + +func testAccMSONodeSettingsConfigUpdate() string { + return fmt.Sprintf(`%s + resource "mso_fabric_policies_node_settings" "node_settings" { + template_id = mso_template.template_fabric_policy.id + name = "tf_test_node_settings" + description = "Terraform test Node Settings Policy updated" + synce = { + admin_state = "disabled" + quality_level = "option_1" + } + ptp = { + node_domain = 30 + priority_2 = 100 + } + }`, testAccMSOTemplateResourceFabricPolicyConfig()) +} + +func testAccMSONodeSettingsConfigUpdateRemove() string { + return fmt.Sprintf(`%s + resource "mso_fabric_policies_node_settings" "node_settings" { + template_id = mso_template.template_fabric_policy.id + name = "tf_test_node_settings" + description = "Terraform test Node Settings Policy removed synce and ptp" + }`, testAccMSOTemplateResourceFabricPolicyConfig()) +} diff --git a/website/docs/d/fabric_policies_node_settings.html.markdown b/website/docs/d/fabric_policies_node_settings.html.markdown new file mode 100644 index 00000000..26a92901 --- /dev/null +++ b/website/docs/d/fabric_policies_node_settings.html.markdown @@ -0,0 +1,43 @@ +--- +layout: "mso" +page_title: "MSO: mso_fabric_policies_node_settings" +sidebar_current: "docs-mso-data-source-fabric_policies_node_settings" +description: |- + Data source for Node Settings on Cisco Nexus Dashboard Orchestrator (NDO) +--- + + + +# mso_fabric_policies_node_settings # + +Data source for Node Settings on Cisco Nexus Dashboard Orchestrator (NDO). This data source is supported in NDO v4.3(1) or higher. + +## GUI Information ## + +* `Location` - Manage -> Fabric Template -> Fabric Policies -> Node Settings + +## Example Usage ## + +```hcl +data "mso_fabric_policies_node_settings" "node_settings" { + template_id = mso_template.fabric_policy_template.id + name = "node_settings" +} +``` + +## Argument Reference ## + +* `template_id` - (Required) The unique ID of the Fabric Policy template. +* `name` - (Required) The name of the Node Settings. + +## Attribute Reference ## + +* `uuid` - (Read-Only) The NDO UUID of the Node Settings. +* `id` - (Read-Only) The unique Terraform identifier of the Node Settings. +* `description` - (Read-Only) The description of the Node Settings. +* `synce` - (Read-Only) The SyncE configuration map of the Node Settings. + * `admin_state` - (Read-Only) The SyncE administrative state of the Node Settings. + * `quality_level` - (Read-Only) The SyncE quality level of the Node Settings. +* `ptp` - (Read-Only) The PTP configuration map of the Node Settings. + * `node_domain` - (Read-Only) The PTP domain of the Node Settings. + * `priority_2` - (Read-Only) The PTP priority 2 of the Node Settings. diff --git a/website/docs/r/fabric_policies_node_settings.html.markdown b/website/docs/r/fabric_policies_node_settings.html.markdown new file mode 100644 index 00000000..48f7cde8 --- /dev/null +++ b/website/docs/r/fabric_policies_node_settings.html.markdown @@ -0,0 +1,58 @@ +--- +layout: "mso" +page_title: "MSO: mso_fabric_policies_node_settings" +sidebar_current: "docs-mso-resource-fabric_policies_node_settings" +description: |- + Manages Node Settings on Cisco Nexus Dashboard Orchestrator (NDO) +--- + +# mso_fabric_policies_node_settings # + +Manages Node Settings on Cisco Nexus Dashboard Orchestrator (NDO). This resource is supported in NDO v4.3(1) or higher. + +## GUI Information ## + +* `Location` - Manage -> Fabric Template -> Fabric Policies -> Node Settings + +## Example Usage ## + +```hcl +resource "mso_fabric_policies_node_settings" "node_settings" { + template_id = mso_template.fabric_policy_template.id + name = "tf_node_settings" + description = "Terraform Node Settings Policy" + synce = { + admin_state = "enabled" + quality_level = "option_2_generation_1" + } + ptp = { + node_domain = 25 + priority_2 = 99 + } +} +``` + +## Argument Reference ## + +* `template_id` - (Required) The unique ID of the Fabric Policy template. +* `name` - (Required) The name of the Node Settings. +* `description` - (Optional) The description of the Node Settings. +* `synce` - (Optional) The SyncE configuration map of the Node Settings. + * `admin_state` - (Required) The SyncE administrative state of the Node Settings. Allowed values are `enabled` or `disabled`. + * `quality_level` - (Required) The SyncE quality level of the Node Settings. Allowed values are `option_1`, `option_2_generation_1` or `option_2_generation_2`. +* `ptp` - (Optional) The PTP configuration map of the Node Settings. + * `node_domain` - (Required) The PTP domain of the Node Settings. Valid range: 24-43. + * `priority_2` - (Required) The PTP priority 2 of the Node Settings. Valid range: 0-255. + +## Attribute Reference ## + +* `uuid` - (Read-Only) The NDO UUID of the Node Settings. +* `id` - (Read-Only) The unique Terraform identifier of the Node Settings. + +## Importing ## + +An existing MSO Node Settings can be [imported][docs-import] into this resource via its ID/path, via the following command: [docs-import]: + +```bash +terraform import mso_fabric_policies_node_settings.node_settings templateId/{template_id}/nodeSettings/{name} +``` From faa5322b5e8153fe89d7555e7460634152811564 Mon Sep 17 00:00:00 2001 From: samitab Date: Tue, 24 Feb 2026 16:34:30 +1000 Subject: [PATCH 2/5] [ignore] Fix go format --- .../fabric_policies_node_settings/main.tf | 37 +++++++++++++++++++ ...ource_mso_fabric_policies_node_settings.go | 8 ++-- ...ource_mso_fabric_policies_node_settings.go | 22 +++++------ 3 files changed, 52 insertions(+), 15 deletions(-) create mode 100644 examples/fabric_policies_node_settings/main.tf diff --git a/examples/fabric_policies_node_settings/main.tf b/examples/fabric_policies_node_settings/main.tf new file mode 100644 index 00000000..993afae1 --- /dev/null +++ b/examples/fabric_policies_node_settings/main.tf @@ -0,0 +1,37 @@ +terraform { + required_providers { + mso = { + source = "CiscoDevNet/mso" + } + } +} + +provider "mso" { + username = "" # + password = "" # + url = "" # + insecure = true +} + +# fabric policy template example + +resource "mso_template" "fabric_policy_template" { + template_name = "fabric_policy_template" + template_type = "fabric_policy" +} + +# fabric policies node settings example + +resource "mso_fabric_policies_node_settings" "node_settings" { + template_id = mso_template.fabric_policy_template.id + name = "tf_node_settings" + description = "Terraform Node Settings Policy" + synce = { + admin_state = "enabled" + quality_level = "option_2_generation_1" + } + ptp = { + node_domain = 25 + priority_2 = 99 + } +} diff --git a/mso/datasource_mso_fabric_policies_node_settings.go b/mso/datasource_mso_fabric_policies_node_settings.go index a7d7eaa0..b09856f4 100644 --- a/mso/datasource_mso_fabric_policies_node_settings.go +++ b/mso/datasource_mso_fabric_policies_node_settings.go @@ -17,8 +17,8 @@ func datasourceMSONodeSettings() *schema.Resource { Required: true, }, "name": { - Type: schema.TypeString, - Required: true, + Type: schema.TypeString, + Required: true, }, "description": { Type: schema.TypeString, @@ -29,7 +29,7 @@ func datasourceMSONodeSettings() *schema.Resource { Computed: true, }, "synce": &schema.Schema{ - Type: schema.TypeMap, + Type: schema.TypeMap, Computed: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ @@ -45,7 +45,7 @@ func datasourceMSONodeSettings() *schema.Resource { }, }, "ptp": &schema.Schema{ - Type: schema.TypeMap, + Type: schema.TypeMap, Computed: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ diff --git a/mso/resource_mso_fabric_policies_node_settings.go b/mso/resource_mso_fabric_policies_node_settings.go index bfd3212d..81b1a12c 100644 --- a/mso/resource_mso_fabric_policies_node_settings.go +++ b/mso/resource_mso_fabric_policies_node_settings.go @@ -45,7 +45,7 @@ func resourceMSONodeSettings() *schema.Resource { Computed: true, }, "synce": &schema.Schema{ - Type: schema.TypeMap, + Type: schema.TypeMap, Optional: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ @@ -67,18 +67,18 @@ func resourceMSONodeSettings() *schema.Resource { }, }, "ptp": &schema.Schema{ - Type: schema.TypeMap, + Type: schema.TypeMap, Optional: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "node_domain": &schema.Schema{ - Type: schema.TypeInt, - Required: true, + Type: schema.TypeInt, + Required: true, ValidateFunc: validation.IntBetween(24, 43), }, "priority_2": &schema.Schema{ - Type: schema.TypeInt, - Required: true, + Type: schema.TypeInt, + Required: true, ValidateFunc: validation.IntBetween(0, 255), }, }, @@ -132,12 +132,12 @@ func setNodeSettingsData(d *schema.ResourceData, msoClient *client.Client, templ d.Set("name", name) d.Set("description", models.StripQuotes(policy.S("description").String())) d.Set("uuid", models.StripQuotes(policy.S("uuid").String())) - + if policy.Exists("synce") { synce := policy.S("synce") synceMap := map[string]any{ - "admin_state": models.StripQuotes(synce.S("adminState").String()), - "quality_level": convertValueWithMap(models.StripQuotes(synce.S("qlOption").String()), synceQualityLevelOptionsMap), + "admin_state": models.StripQuotes(synce.S("adminState").String()), + "quality_level": convertValueWithMap(models.StripQuotes(synce.S("qlOption").String()), synceQualityLevelOptionsMap), } d.Set("synce", synceMap) } @@ -145,8 +145,8 @@ func setNodeSettingsData(d *schema.ResourceData, msoClient *client.Client, templ if policy.Exists("ptp") { ptp := policy.S("ptp") ptpMap := map[string]any{ - "node_domain": ptp.S("domain").Data().(float64), - "priority_2": ptp.S("prio1").Data().(float64), + "node_domain": ptp.S("domain").Data().(float64), + "priority_2": ptp.S("prio1").Data().(float64), } d.Set("ptp", ptpMap) } From 8ab858a5947f86c00ca2361525ac3628d43c867f Mon Sep 17 00:00:00 2001 From: samitab Date: Thu, 26 Feb 2026 07:03:07 +1000 Subject: [PATCH 3/5] [ignore] fix review comments --- mso/datasource_mso_fabric_policies_node_settings.go | 5 ++++- mso/resource_mso_fabric_policies_node_settings.go | 12 +++++++++--- .../d/fabric_policies_node_settings.html.markdown | 4 ++-- .../r/fabric_policies_node_settings.html.markdown | 4 ++-- 4 files changed, 17 insertions(+), 8 deletions(-) diff --git a/mso/datasource_mso_fabric_policies_node_settings.go b/mso/datasource_mso_fabric_policies_node_settings.go index b09856f4..bf245cb4 100644 --- a/mso/datasource_mso_fabric_policies_node_settings.go +++ b/mso/datasource_mso_fabric_policies_node_settings.go @@ -71,7 +71,10 @@ func dataSourceNodeSettingsRead(d *schema.ResourceData, m interface{}) error { templateId := d.Get("template_id").(string) policyName := d.Get("name").(string) - setNodeSettingsData(d, msoClient, templateId, policyName) + err := setNodeSettingsData(d, msoClient, templateId, policyName) + if err != nil { + return err + } log.Printf("[DEBUG] MSO Node Settings Data Source - Read Complete : %v", d.Id()) return nil } diff --git a/mso/resource_mso_fabric_policies_node_settings.go b/mso/resource_mso_fabric_policies_node_settings.go index 81b1a12c..7582a2e8 100644 --- a/mso/resource_mso_fabric_policies_node_settings.go +++ b/mso/resource_mso_fabric_policies_node_settings.go @@ -146,7 +146,7 @@ func setNodeSettingsData(d *schema.ResourceData, msoClient *client.Client, templ ptp := policy.S("ptp") ptpMap := map[string]any{ "node_domain": ptp.S("domain").Data().(float64), - "priority_2": ptp.S("prio1").Data().(float64), + "priority_2": ptp.S("prio2").Data().(float64), } d.Set("ptp", ptpMap) } @@ -168,7 +168,10 @@ func resourceMSONodeSettingsImport(d *schema.ResourceData, m any) ([]*schema.Res return nil, err } - setNodeSettingsData(d, msoClient, templateId, policyName) + err = setNodeSettingsData(d, msoClient, templateId, policyName) + if err != nil { + return nil, err + } log.Printf("[DEBUG] MSO Node Settings Resource - Import Complete: %v", d.Id()) return []*schema.ResourceData{d}, nil } @@ -218,7 +221,10 @@ func resourceMSONodeSettingsRead(d *schema.ResourceData, m any) error { templateId := d.Get("template_id").(string) policyName := d.Get("name").(string) - setNodeSettingsData(d, msoClient, templateId, policyName) + err := setNodeSettingsData(d, msoClient, templateId, policyName) + if err != nil { + return err + } log.Printf("[DEBUG] MSO Node Settings Resource - Read Complete : %v", d.Id()) return nil } diff --git a/website/docs/d/fabric_policies_node_settings.html.markdown b/website/docs/d/fabric_policies_node_settings.html.markdown index 26a92901..e5a435b8 100644 --- a/website/docs/d/fabric_policies_node_settings.html.markdown +++ b/website/docs/d/fabric_policies_node_settings.html.markdown @@ -35,9 +35,9 @@ data "mso_fabric_policies_node_settings" "node_settings" { * `uuid` - (Read-Only) The NDO UUID of the Node Settings. * `id` - (Read-Only) The unique Terraform identifier of the Node Settings. * `description` - (Read-Only) The description of the Node Settings. -* `synce` - (Read-Only) The SyncE configuration map of the Node Settings. +* `synce` - (Read-Only) The Synchronous Ethernet (SyncE) configuration map of the Node Settings. * `admin_state` - (Read-Only) The SyncE administrative state of the Node Settings. * `quality_level` - (Read-Only) The SyncE quality level of the Node Settings. -* `ptp` - (Read-Only) The PTP configuration map of the Node Settings. +* `ptp` - (Read-Only) The Precision Time Protocol (PTP) configuration map of the Node Settings. * `node_domain` - (Read-Only) The PTP domain of the Node Settings. * `priority_2` - (Read-Only) The PTP priority 2 of the Node Settings. diff --git a/website/docs/r/fabric_policies_node_settings.html.markdown b/website/docs/r/fabric_policies_node_settings.html.markdown index 48f7cde8..704b91e9 100644 --- a/website/docs/r/fabric_policies_node_settings.html.markdown +++ b/website/docs/r/fabric_policies_node_settings.html.markdown @@ -37,10 +37,10 @@ resource "mso_fabric_policies_node_settings" "node_settings" { * `template_id` - (Required) The unique ID of the Fabric Policy template. * `name` - (Required) The name of the Node Settings. * `description` - (Optional) The description of the Node Settings. -* `synce` - (Optional) The SyncE configuration map of the Node Settings. +* `synce` - (Optional) The Synchronous Ethernet (SyncE) configuration map of the Node Settings. * `admin_state` - (Required) The SyncE administrative state of the Node Settings. Allowed values are `enabled` or `disabled`. * `quality_level` - (Required) The SyncE quality level of the Node Settings. Allowed values are `option_1`, `option_2_generation_1` or `option_2_generation_2`. -* `ptp` - (Optional) The PTP configuration map of the Node Settings. +* `ptp` - (Optional) The Precision Time Protocol (PTP) configuration map of the Node Settings. * `node_domain` - (Required) The PTP domain of the Node Settings. Valid range: 24-43. * `priority_2` - (Required) The PTP priority 2 of the Node Settings. Valid range: 0-255. From fd13e950f964e2b5727341a372b6f2f01eeec1d7 Mon Sep 17 00:00:00 2001 From: samitab Date: Tue, 17 Mar 2026 12:23:39 +1000 Subject: [PATCH 4/5] [ignore] Adjust ptp and synce maps to Computed --- mso/resource_mso_fabric_policies_node_settings.go | 2 ++ mso/resource_mso_fabric_policies_node_settings_test.go | 3 +++ website/docs/r/fabric_policies_node_settings.html.markdown | 6 +++--- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/mso/resource_mso_fabric_policies_node_settings.go b/mso/resource_mso_fabric_policies_node_settings.go index 7582a2e8..32e9526a 100644 --- a/mso/resource_mso_fabric_policies_node_settings.go +++ b/mso/resource_mso_fabric_policies_node_settings.go @@ -47,6 +47,7 @@ func resourceMSONodeSettings() *schema.Resource { "synce": &schema.Schema{ Type: schema.TypeMap, Optional: true, + Computed: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "admin_state": { @@ -69,6 +70,7 @@ func resourceMSONodeSettings() *schema.Resource { "ptp": &schema.Schema{ Type: schema.TypeMap, Optional: true, + Computed: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "node_domain": &schema.Schema{ diff --git a/mso/resource_mso_fabric_policies_node_settings_test.go b/mso/resource_mso_fabric_policies_node_settings_test.go index 795e9f53..f4949ecd 100644 --- a/mso/resource_mso_fabric_policies_node_settings_test.go +++ b/mso/resource_mso_fabric_policies_node_settings_test.go @@ -97,5 +97,8 @@ func testAccMSONodeSettingsConfigUpdateRemove() string { template_id = mso_template.template_fabric_policy.id name = "tf_test_node_settings" description = "Terraform test Node Settings Policy removed synce and ptp" + + ptp = {} + synce = {} }`, testAccMSOTemplateResourceFabricPolicyConfig()) } diff --git a/website/docs/r/fabric_policies_node_settings.html.markdown b/website/docs/r/fabric_policies_node_settings.html.markdown index 704b91e9..07d4deac 100644 --- a/website/docs/r/fabric_policies_node_settings.html.markdown +++ b/website/docs/r/fabric_policies_node_settings.html.markdown @@ -37,10 +37,10 @@ resource "mso_fabric_policies_node_settings" "node_settings" { * `template_id` - (Required) The unique ID of the Fabric Policy template. * `name` - (Required) The name of the Node Settings. * `description` - (Optional) The description of the Node Settings. -* `synce` - (Optional) The Synchronous Ethernet (SyncE) configuration map of the Node Settings. +* `synce` - (Optional) The Synchronous Ethernet (SyncE) configuration map of the Node Settings. Providing an empty map `{}` will remove the SyncE configuration from the Node Settings. * `admin_state` - (Required) The SyncE administrative state of the Node Settings. Allowed values are `enabled` or `disabled`. * `quality_level` - (Required) The SyncE quality level of the Node Settings. Allowed values are `option_1`, `option_2_generation_1` or `option_2_generation_2`. -* `ptp` - (Optional) The Precision Time Protocol (PTP) configuration map of the Node Settings. +* `ptp` - (Optional) The Precision Time Protocol (PTP) configuration map of the Node Settings. Providing an empty map `{}` will remove the PTP configuration from the Node Settings. * `node_domain` - (Required) The PTP domain of the Node Settings. Valid range: 24-43. * `priority_2` - (Required) The PTP priority 2 of the Node Settings. Valid range: 0-255. @@ -51,7 +51,7 @@ resource "mso_fabric_policies_node_settings" "node_settings" { ## Importing ## -An existing MSO Node Settings can be [imported][docs-import] into this resource via its ID/path, via the following command: [docs-import]: +An existing MSO Node Setting can be [imported][docs-import] into this resource via its ID/path, via the following command: [docs-import]: ```bash terraform import mso_fabric_policies_node_settings.node_settings templateId/{template_id}/nodeSettings/{name} From 29119498d32751f2f1079200caa92166dcfe7f9b Mon Sep 17 00:00:00 2001 From: samitab Date: Fri, 27 Mar 2026 09:18:24 +1000 Subject: [PATCH 5/5] [ignore] Remove ForceNew on name and allow description to be removed. --- mso/resource_mso_fabric_policies_node_settings.go | 2 -- ...esource_mso_fabric_policies_node_settings_test.go | 12 ++++++------ .../r/fabric_policies_node_settings.html.markdown | 2 +- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/mso/resource_mso_fabric_policies_node_settings.go b/mso/resource_mso_fabric_policies_node_settings.go index 32e9526a..3aa9f215 100644 --- a/mso/resource_mso_fabric_policies_node_settings.go +++ b/mso/resource_mso_fabric_policies_node_settings.go @@ -31,14 +31,12 @@ func resourceMSONodeSettings() *schema.Resource { }, "name": { Type: schema.TypeString, - ForceNew: true, Required: true, ValidateFunc: validation.StringLenBetween(1, 64), }, "description": { Type: schema.TypeString, Optional: true, - Computed: true, }, "uuid": { Type: schema.TypeString, diff --git a/mso/resource_mso_fabric_policies_node_settings_test.go b/mso/resource_mso_fabric_policies_node_settings_test.go index f4949ecd..c0fdaa15 100644 --- a/mso/resource_mso_fabric_policies_node_settings_test.go +++ b/mso/resource_mso_fabric_policies_node_settings_test.go @@ -28,7 +28,7 @@ func TestAccMSONodeSettingsResource(t *testing.T) { PreConfig: func() { fmt.Println("Test: Update Node Settings Policy") }, Config: testAccMSONodeSettingsConfigUpdate(), Check: resource.ComposeAggregateTestCheckFunc( - resource.TestCheckResourceAttr("mso_fabric_policies_node_settings.node_settings", "name", "tf_test_node_settings"), + resource.TestCheckResourceAttr("mso_fabric_policies_node_settings.node_settings", "name", "tf_test_node_settings_new"), resource.TestCheckResourceAttr("mso_fabric_policies_node_settings.node_settings", "description", "Terraform test Node Settings Policy updated"), resource.TestCheckResourceAttr("mso_fabric_policies_node_settings.node_settings", "synce.admin_state", "disabled"), resource.TestCheckResourceAttr("mso_fabric_policies_node_settings.node_settings", "synce.quality_level", "option_1"), @@ -40,8 +40,8 @@ func TestAccMSONodeSettingsResource(t *testing.T) { PreConfig: func() { fmt.Println("Test: Update Node Settings Policy Remove SyncE and PTP") }, Config: testAccMSONodeSettingsConfigUpdateRemove(), Check: resource.ComposeAggregateTestCheckFunc( - resource.TestCheckResourceAttr("mso_fabric_policies_node_settings.node_settings", "name", "tf_test_node_settings"), - resource.TestCheckResourceAttr("mso_fabric_policies_node_settings.node_settings", "description", "Terraform test Node Settings Policy removed synce and ptp"), + resource.TestCheckResourceAttr("mso_fabric_policies_node_settings.node_settings", "name", "tf_test_node_settings_new"), + resource.TestCheckResourceAttr("mso_fabric_policies_node_settings.node_settings", "description", ""), resource.TestCheckNoResourceAttr("mso_fabric_policies_node_settings.node_settings", "synce"), resource.TestCheckNoResourceAttr("mso_fabric_policies_node_settings.node_settings", "ptp"), ), @@ -78,7 +78,7 @@ func testAccMSONodeSettingsConfigUpdate() string { return fmt.Sprintf(`%s resource "mso_fabric_policies_node_settings" "node_settings" { template_id = mso_template.template_fabric_policy.id - name = "tf_test_node_settings" + name = "tf_test_node_settings_new" description = "Terraform test Node Settings Policy updated" synce = { admin_state = "disabled" @@ -95,8 +95,8 @@ func testAccMSONodeSettingsConfigUpdateRemove() string { return fmt.Sprintf(`%s resource "mso_fabric_policies_node_settings" "node_settings" { template_id = mso_template.template_fabric_policy.id - name = "tf_test_node_settings" - description = "Terraform test Node Settings Policy removed synce and ptp" + name = "tf_test_node_settings_new" + description = "" ptp = {} synce = {} diff --git a/website/docs/r/fabric_policies_node_settings.html.markdown b/website/docs/r/fabric_policies_node_settings.html.markdown index 07d4deac..8762da64 100644 --- a/website/docs/r/fabric_policies_node_settings.html.markdown +++ b/website/docs/r/fabric_policies_node_settings.html.markdown @@ -36,7 +36,7 @@ resource "mso_fabric_policies_node_settings" "node_settings" { * `template_id` - (Required) The unique ID of the Fabric Policy template. * `name` - (Required) The name of the Node Settings. -* `description` - (Optional) The description of the Node Settings. +* `description` - (Optional) The description of the Node Settings. If this argument is omitted, the value defaults to an empty string (`""`). * `synce` - (Optional) The Synchronous Ethernet (SyncE) configuration map of the Node Settings. Providing an empty map `{}` will remove the SyncE configuration from the Node Settings. * `admin_state` - (Required) The SyncE administrative state of the Node Settings. Allowed values are `enabled` or `disabled`. * `quality_level` - (Required) The SyncE quality level of the Node Settings. Allowed values are `option_1`, `option_2_generation_1` or `option_2_generation_2`.