diff --git a/examples/template/main.tf b/examples/template/main.tf index 8d8f1397..18737ed5 100644 --- a/examples/template/main.tf +++ b/examples/template/main.tf @@ -30,7 +30,7 @@ data "mso_tenant" "example_tenant" { resource "mso_template" "tenant_template" { template_name = "tenant_template" template_type = "tenant" - tenant_name = data.mso_tenant.example_tenant.display_name + tenant_id = data.mso_tenant.example_tenant.id sites = [data.mso_site.site_1.id, data.mso_site.site_2.id] } @@ -39,7 +39,7 @@ resource "mso_template" "tenant_template" { resource "mso_template" "l3out_template" { template_name = "l3out_template" template_type = "l3out" - tenant_name = data.mso_tenant.example_tenant.display_name + tenant_id = data.mso_tenant.example_tenant.id sites = [data.mso_site.site_1.id] } @@ -64,7 +64,7 @@ resource "mso_template" "fabric_resource_template" { resource "mso_template" "monitoring_tenant_template" { template_name = "monitoring_tenant_template" template_type = "monitoring_tenant" - tenant_name = data.mso_tenant.example_tenant.display_name + tenant_id = data.mso_tenant.example_tenant.id sites = [data.mso_site.site_1.id] } @@ -81,6 +81,6 @@ resource "mso_template" "monitoring_access_template" { resource "mso_template" "service_device_template" { template_name = "service_device_template" template_type = "service_device" - tenant_name = data.mso_tenant.example_tenant.display_name + tenant_id = data.mso_tenant.example_tenant.id sites = [data.mso_site.site_1.id, data.mso_site.site_2.id] } diff --git a/mso/datasource_mso_template.go b/mso/datasource_mso_template.go index 1a2fe309..310b2b83 100644 --- a/mso/datasource_mso_template.go +++ b/mso/datasource_mso_template.go @@ -20,19 +20,16 @@ func datasourceMSOTemplate() *schema.Resource { "template_id": &schema.Schema{ Type: schema.TypeString, Optional: true, - Computed: true, ValidateFunc: validation.StringLenBetween(1, 1000), }, "template_name": &schema.Schema{ Type: schema.TypeString, Optional: true, - Computed: true, ValidateFunc: validation.StringLenBetween(1, 1000), }, "template_type": &schema.Schema{ Type: schema.TypeString, Optional: true, - Computed: true, ValidateFunc: validation.StringInSlice([]string{ "tenant", "l3out", @@ -43,7 +40,7 @@ func datasourceMSOTemplate() *schema.Resource { "service_device", }, false), }, - "tenant_name": &schema.Schema{ + "tenant_id": &schema.Schema{ Type: schema.TypeString, Computed: true, }, diff --git a/mso/datasource_mso_template_test.go b/mso/datasource_mso_template_test.go new file mode 100644 index 00000000..9cda222c --- /dev/null +++ b/mso/datasource_mso_template_test.go @@ -0,0 +1,143 @@ +package mso + +import ( + "fmt" + "regexp" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" +) + +func TestAccMSOTemplateDatasourceTenantErrors(t *testing.T) { + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + PreConfig: func() { fmt.Println("Test: No template_id or template_name provided in Template configuration") }, + Config: testAccMSOTemplateDatasourceErrorNoIdOrNameConfig(), + ExpectError: regexp.MustCompile("either `template_id` or `template_name` must be provided"), + }, + { + PreConfig: func() { fmt.Println("Test: No template_type with name provided in Template configuration") }, + Config: testAccMSOTemplateDatasourceErrorNoTypeConfig(), + ExpectError: regexp.MustCompile("`template_type` must be provided when `template_name` is provided"), + }, + { + PreConfig: func() { fmt.Println("Test: Both template_id and template_name provided in Template configuration") }, + Config: testAccMSOTemplateDatasourceErrorIdAndNameConfig(), + ExpectError: regexp.MustCompile("only one of `template_id` or `template_name` must be provided"), + }, + { + PreConfig: func() { fmt.Println("Test: Non existing template name provided in Template configuration") }, + Config: testAccMSOTemplateDatasourceErrorNonExistingConfig(), + ExpectError: regexp.MustCompile("Template with name 'non_existing_template_name' not found."), + }, + }, + }) +} + +func TestAccMSOTemplateDatasourceTenantName(t *testing.T) { + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + PreConfig: func() { fmt.Println("Test: Tenant template with name and type provided in Template configuration") }, + Config: testAccMSOTemplateDatasourceNameAndTypeConfig(), + Check: resource.ComposeTestCheckFunc( + testAccMSOTemplateState( + "data.mso_template.template_tenant", + &TemplateTest{ + TemplateName: "test_template_tenant", + TemplateType: "tenant", + Tenant: msoTemplateTenantName, + Sites: []string{msoTemplateSiteName1, msoTemplateSiteName2}, + }, + false, + ), + ), + }, + }, + }) +} + +func TestAccMSOTemplateDatasourceTenantId(t *testing.T) { + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + PreConfig: func() { fmt.Println("Test: Tenant template with id provided in Template configuration") }, + Config: testAccMSOTemplateDatasourceIdConfig(), + Check: resource.ComposeTestCheckFunc( + testAccMSOTemplateState( + "data.mso_template.template_tenant", + &TemplateTest{ + TemplateName: "test_template_tenant", + TemplateType: "tenant", + Tenant: msoTemplateTenantName, + Sites: []string{msoTemplateSiteName1, msoTemplateSiteName2}, + }, + false, + ), + ), + }, + }, + }) +} + +func testAccMSOTemplateDatasourceNameAndTypeConfig() string { + return fmt.Sprintf(`%s + data "mso_template" "template_tenant" { + template_name = mso_template.template_tenant.template_name + template_type = "tenant" + } + `, testAccMSOTemplateResourceTenanTwoSitesConfig()) +} + +func testAccMSOTemplateDatasourceIdConfig() string { + return fmt.Sprintf(`%s + data "mso_template" "template_tenant" { + template_id = mso_template.template_tenant.id + } + `, testAccMSOTemplateResourceTenanTwoSitesConfig()) +} + +func testAccMSOTemplateDatasourceErrorNoIdOrNameConfig() string { + return fmt.Sprintf(` + data "mso_template" "template_tenant" { + template_type = "tenant" + } + `) +} + +func testAccMSOTemplateDatasourceErrorNoTypeConfig() string { + return fmt.Sprintf(` + data "mso_template" "template_tenant" { + template_name = "non_existing_template_name" + } + `) +} + +func testAccMSOTemplateDatasourceErrorIdAndNameConfig() string { + return fmt.Sprintf(` + data "mso_template" "template_tenant" { + template_id = "non_existing_template_id" + template_name = "non_existing_template_name" + template_type = "tenant" + } + `) +} + +func testAccMSOTemplateDatasourceErrorNonExistingConfig() string { + return fmt.Sprintf(` + data "mso_template" "template_tenant" { + template_name = "non_existing_template_name" + template_type = "tenant" + } + `) +} diff --git a/mso/resource_mso_template.go b/mso/resource_mso_template.go index 3e4c379e..30ab91c0 100644 --- a/mso/resource_mso_template.go +++ b/mso/resource_mso_template.go @@ -43,7 +43,7 @@ func resourceMSOTemplate() *schema.Resource { "service_device", }, false), }, - "tenant_name": { + "tenant_id": { Type: schema.TypeString, Optional: true, Computed: true, @@ -150,28 +150,26 @@ type ndoTemplate struct { id string templateName string templateType string - tenantName string + tenantId string sites []string msoClient *client.Client - ndoTenants map[string]string - ndoSites map[string]string } func (ndoTemplate *ndoTemplate) SetToSchema(d *schema.ResourceData) { d.SetId(ndoTemplate.id) d.Set("template_name", ndoTemplate.templateName) d.Set("template_type", ndoTemplate.templateType) - d.Set("tenant_name", ndoTemplate.tenantName) + d.Set("tenant_id", ndoTemplate.tenantId) d.Set("sites", ndoTemplate.sites) } func (ndoTemplate *ndoTemplate) validateConfig() []error { errors := []error{} - if ndoTemplate.tenantName != "" && !ndoTemplateTypes[ndoTemplate.templateType].tenant { + if ndoTemplate.tenantId != "" && !ndoTemplateTypes[ndoTemplate.templateType].tenant { errors = append(errors, fmt.Errorf(fmt.Sprintf("Tenant cannot be attached to template of type %s.", ndoTemplate.templateType))) } - if ndoTemplate.tenantName == "" && ndoTemplateTypes[ndoTemplate.templateType].tenant { + if ndoTemplate.tenantId == "" && ndoTemplateTypes[ndoTemplate.templateType].tenant { errors = append(errors, fmt.Errorf(fmt.Sprintf("Tenant is required for template of type %s.", ndoTemplate.templateType))) } if len(ndoTemplate.sites) == 0 && ndoTemplateTypes[ndoTemplate.templateType].siteAmount == 1 { @@ -182,7 +180,7 @@ func (ndoTemplate *ndoTemplate) validateConfig() []error { } duplicates := duplicatesInList(ndoTemplate.sites) if len(duplicates) > 0 { - duplicatesErrors := []error{fmt.Errorf("duplication found in the sites list")} + duplicatesErrors := []error{fmt.Errorf("Duplication found in the sites list")} for _, site := range duplicates { duplicatesErrors = append(duplicatesErrors, fmt.Errorf(fmt.Sprintf("Site %s is duplicated", site))) } @@ -202,71 +200,33 @@ func (ndoTemplate *ndoTemplate) ToMap() (map[string]interface{}, error) { func (ndoTemplate *ndoTemplate) createTypeSpecificPayload() map[string]interface{} { if ndoTemplate.templateType == "tenant" { - return map[string]interface{}{"template": map[string]interface{}{"tenantId": ndoTemplate.ndoTenants[ndoTemplate.tenantName]}, "sites": ndoTemplate.createSitesPayload()} + return map[string]interface{}{"template": map[string]interface{}{"tenantId": ndoTemplate.tenantId}, "sites": ndoTemplate.createSitesPayload()} } else if ndoTemplate.templateType == "l3out" { - return map[string]interface{}{"tenantId": ndoTemplate.ndoTenants[ndoTemplate.tenantName], "siteId": ndoTemplate.createSitesPayload()[0]["siteId"]} + return map[string]interface{}{"tenantId": ndoTemplate.tenantId, "siteId": ndoTemplate.createSitesPayload()[0]["siteId"]} } else if ndoTemplate.templateType == "fabric_policy" { return map[string]interface{}{"sites": ndoTemplate.createSitesPayload()} } else if ndoTemplate.templateType == "fabric_resource" { return map[string]interface{}{"sites": ndoTemplate.createSitesPayload()} } else if ndoTemplate.templateType == "monitoring_tenant" { - return map[string]interface{}{"template": map[string]interface{}{"mtType": "tenant", "tenant": ndoTemplate.ndoTenants[ndoTemplate.tenantName]}, "sites": ndoTemplate.createSitesPayload()} + return map[string]interface{}{"template": map[string]interface{}{"mtType": "tenant", "tenant": ndoTemplate.tenantId}, "sites": ndoTemplate.createSitesPayload()} } else if ndoTemplate.templateType == "monitoring_access" { return map[string]interface{}{"template": map[string]interface{}{"mtType": "access"}, "sites": ndoTemplate.createSitesPayload()} } else if ndoTemplate.templateType == "service_device" { - return map[string]interface{}{"template": map[string]interface{}{"tenantId": ndoTemplate.ndoTenants[ndoTemplate.tenantName]}, "sites": ndoTemplate.createSitesPayload()} + return map[string]interface{}{"template": map[string]interface{}{"tenantId": ndoTemplate.tenantId}, "sites": ndoTemplate.createSitesPayload()} } return nil } func (ndoTemplate *ndoTemplate) createSitesPayload() []map[string]interface{} { siteIds := []map[string]interface{}{} - for _, site := range ndoTemplate.sites { - siteIds = append(siteIds, ndoTemplate.createSitePayload(site)) + for _, siteId := range ndoTemplate.sites { + siteIds = append(siteIds, ndoTemplate.createSitePayload(siteId)) } return siteIds } -func (ndoTemplate *ndoTemplate) createSitePayload(site string) map[string]interface{} { - return map[string]interface{}{"siteId": ndoTemplate.ndoSites[site]} -} - -func (ndoTemplate *ndoTemplate) setNdoSites() error { - cont, err := ndoTemplate.msoClient.GetViaURL(fmt.Sprintf("api/v1/sites")) - if err != nil { - return err - } - if cont.Exists("sites") { - ndoTemplate.ndoSites = map[string]string{} - for siteIndex, _ := range cont.S("sites").Data().([]interface{}) { - siteCont, err := cont.ArrayElement(siteIndex, "sites") - if err != nil { - return err - } - ndoTemplate.ndoSites[models.StripQuotes(siteCont.S("id").String())] = models.StripQuotes(siteCont.S("name").String()) - ndoTemplate.ndoSites[models.StripQuotes(siteCont.S("name").String())] = models.StripQuotes(siteCont.S("id").String()) - } - } - return nil -} - -func (ndoTemplate *ndoTemplate) setNdoTenants() error { - cont, err := ndoTemplate.msoClient.GetViaURL(fmt.Sprintf("api/v1/tenants")) - if err != nil { - return err - } - if cont.Exists("tenants") { - ndoTemplate.ndoTenants = map[string]string{} - for tenantIndex, _ := range cont.S("tenants").Data().([]interface{}) { - tenantCont, err := cont.ArrayElement(tenantIndex, "tenants") - if err != nil { - return err - } - ndoTemplate.ndoTenants[models.StripQuotes(tenantCont.S("id").String())] = models.StripQuotes(tenantCont.S("displayName").String()) - ndoTemplate.ndoTenants[models.StripQuotes(tenantCont.S("displayName").String())] = models.StripQuotes(tenantCont.S("id").String()) - } - } - return nil +func (ndoTemplate *ndoTemplate) createSitePayload(siteId string) map[string]interface{} { + return map[string]interface{}{"siteId": siteId} } func (ndoTemplate *ndoTemplate) getTemplate(errorNotFound bool) error { @@ -290,27 +250,17 @@ func (ndoTemplate *ndoTemplate) getTemplate(errorNotFound bool) error { ndoTemplate.sites = []string{} - err = ndoTemplate.setNdoTenants() - if err != nil { - return err - } - - err = ndoTemplate.setNdoSites() - if err != nil { - return err - } - ndoTemplate.templateName = models.StripQuotes(cont.S("displayName").String()) templateType := models.StripQuotes(cont.S("templateType").String()) if templateType == "tenantPolicy" { ndoTemplate.templateType = "tenant" - ndoTemplate.tenantName = ndoTemplate.ndoTenants[models.StripQuotes(cont.S(ndoTemplateTypes[ndoTemplate.templateType].templateTypeContainer).S("template").S("tenantId").String())] + ndoTemplate.tenantId = models.StripQuotes(cont.S(ndoTemplateTypes[ndoTemplate.templateType].templateTypeContainer).S("template").S("tenantId").String()) } else if templateType == "l3out" { ndoTemplate.templateType = "l3out" - ndoTemplate.tenantName = ndoTemplate.ndoTenants[models.StripQuotes(cont.S(ndoTemplateTypes[ndoTemplate.templateType].templateTypeContainer).S("tenantId").String())] - ndoTemplate.sites = append(ndoTemplate.sites, ndoTemplate.ndoSites[models.StripQuotes(cont.S(ndoTemplateTypes[ndoTemplate.templateType].templateTypeContainer).S("siteId").String())]) + ndoTemplate.tenantId = models.StripQuotes(cont.S(ndoTemplateTypes[ndoTemplate.templateType].templateTypeContainer).S("tenantId").String()) + ndoTemplate.sites = append(ndoTemplate.sites, models.StripQuotes(cont.S(ndoTemplateTypes[ndoTemplate.templateType].templateTypeContainer).S("siteId").String())) } else if templateType == "fabricPolicy" { ndoTemplate.templateType = "fabric_policy" @@ -322,19 +272,19 @@ func (ndoTemplate *ndoTemplate) getTemplate(errorNotFound bool) error { ndoTemplate.templateType = "monitoring_access" if models.StripQuotes(cont.S(ndoTemplateTypes[ndoTemplate.templateType].templateTypeContainer).S("template").S("mtType").String()) == "tenant" { ndoTemplate.templateType = "monitoring_tenant" - ndoTemplate.tenantName = ndoTemplate.ndoTenants[models.StripQuotes(cont.S(ndoTemplateTypes[ndoTemplate.templateType].templateTypeContainer).S("template").S("tenant").String())] + ndoTemplate.tenantId = models.StripQuotes(cont.S(ndoTemplateTypes[ndoTemplate.templateType].templateTypeContainer).S("template").S("tenant").String()) } } else if templateType == "serviceDevice" { ndoTemplate.templateType = "service_device" - ndoTemplate.tenantName = ndoTemplate.ndoTenants[models.StripQuotes(cont.S(ndoTemplateTypes[ndoTemplate.templateType].templateTypeContainer).S("template").S("tenantId").String())] + ndoTemplate.tenantId = models.StripQuotes(cont.S(ndoTemplateTypes[ndoTemplate.templateType].templateTypeContainer).S("template").S("tenantId").String()) } if ndoTemplate.templateType != "l3out" { if cont.S(ndoTemplateTypes[ndoTemplate.templateType].templateTypeContainer).Exists("sites") { for _, site := range cont.S(ndoTemplateTypes[ndoTemplate.templateType].templateTypeContainer).S("sites").Data().([]interface{}) { siteId := models.StripQuotes(site.(map[string]interface{})["siteId"].(string)) - ndoTemplate.sites = append(ndoTemplate.sites, ndoTemplate.ndoSites[siteId]) + ndoTemplate.sites = append(ndoTemplate.sites, siteId) } } } @@ -361,40 +311,25 @@ func (ndoTemplate *ndoTemplate) setTemplateId() error { } } - return fmt.Errorf("Template with name %s not found.", ndoTemplate.templateName) + return fmt.Errorf("Template with name '%s' not found.", ndoTemplate.templateName) } func resourceMSOTemplateCreate(d *schema.ResourceData, m interface{}) error { log.Println("[DEBUG] MSO Template Resource: Beginning Create", d.Id()) msoClient := m.(*client.Client) - sites := getListOfStringsFromSchemaList(d, "sites") - tenant := d.Get("tenant_name").(string) - ndoTemplate := ndoTemplate{ msoClient: msoClient, templateName: d.Get("template_name").(string), templateType: d.Get("template_type").(string), - tenantName: tenant, - sites: sites, + sites: getListOfStringsFromSchemaList(d, "sites"), } - validationErrors := ndoTemplate.validateConfig() - - if len(sites) > 0 { - err := ndoTemplate.setNdoSites() - if err != nil { - return err - } - } - - if tenant != "" { - err := ndoTemplate.setNdoTenants() - if err != nil { - return err - } + if tenantId, ok := d.GetOk("tenant_id"); ok { + ndoTemplate.tenantId = tenantId.(string) } + validationErrors := ndoTemplate.validateConfig() if len(validationErrors) > 0 { d.SetId("") return errors.Join(validationErrors...) @@ -429,30 +364,24 @@ func resourceMSOTemplateUpdate(d *schema.ResourceData, m interface{}) error { templateType := d.Get("template_type").(string) templateName := d.Get("template_name").(string) + sites := getListOfStringsFromSchemaList(d, "sites") if ndoTemplateTypes[templateType].siteAmount == 1 && d.HasChange("sites") { return fmt.Errorf("Cannot change site for template of type %s.", templateType) } - sites := getListOfStringsFromSchemaList(d, "sites") - ndoTemplate := ndoTemplate{ msoClient: msoClient, templateName: templateName, templateType: templateType, - tenantName: d.Get("tenant_name").(string), sites: sites, } - if len(sites) > 0 { - err := ndoTemplate.setNdoSites() - if err != nil { - return err - } + if tenantId, ok := d.GetOk("tenant_id"); ok { + ndoTemplate.tenantId = tenantId.(string) } validationErrors := ndoTemplate.validateConfig() - if len(validationErrors) > 0 { return errors.Join(validationErrors...) } diff --git a/mso/resource_mso_template_test.go b/mso/resource_mso_template_test.go new file mode 100644 index 00000000..006d4d9f --- /dev/null +++ b/mso/resource_mso_template_test.go @@ -0,0 +1,819 @@ +package mso + +import ( + "fmt" + "regexp" + "strconv" + "testing" + + "github.com/ciscoecosystem/mso-go-client/client" + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/terraform" +) + +const msoTemplateTenantName = "tf_test_mso_template_tenant" +const msoTemplateSiteName1 = "ansible_test" +const msoTemplateSiteName2 = "ansible_test_2" + +var msoTemplateId string + +func TestAccMSOTemplateResourceTenant(t *testing.T) { + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + PreConfig: func() { fmt.Println("Test: Duplicate sites provided in Tenant Template configuration (error)") }, + Config: testAccMSOTemplateResourceTenantErrorDuplicateSitesConfig(), + ExpectError: regexp.MustCompile(`Duplication found in the sites list`), + }, + { + PreConfig: func() { fmt.Println("Test: No tenant provided in Tenant Template configuration (error)") }, + Config: testAccMSOTemplateResourceTenanErrorNoTenantConfig(), + ExpectError: regexp.MustCompile(`Tenant is required for template of type tenant.`), + }, + { + PreConfig: func() { fmt.Println("Test: Create Tenant Template without sites") }, + Config: testAccMSOTemplateResourceTenantConfig(), + Check: resource.ComposeTestCheckFunc( + testAccMSOTemplateState( + "mso_template.template_tenant", + &TemplateTest{ + TemplateName: "test_template_tenant", + TemplateType: "tenant", + Tenant: msoTemplateTenantName, + Sites: []string{}, + }, + true, + ), + ), + }, + { + PreConfig: func() { fmt.Println("Test: Import the Tenant Template with no sites configuration") }, + ResourceName: "mso_template.template_tenant", + ImportState: true, + ImportStateId: msoTemplateId, + ImportStateVerify: true, + }, + { + PreConfig: func() { + fmt.Println("Test: Import the Tenant Template with no sites configuration with wrong ID (error)") + }, + ResourceName: "mso_template.template_tenant", + ImportState: true, + ImportStateId: "non_existing_template_id", + ImportStateVerify: true, + ExpectError: regexp.MustCompile("invalid character 'p' after top-level value"), + }, + { + PreConfig: func() { fmt.Println("Test: Update the Tenant Template with 1 site") }, + Config: testAccMSOTemplateResourceTenanSiteAnsibleTestConfig(), + Check: resource.ComposeTestCheckFunc( + testAccMSOTemplateState( + "mso_template.template_tenant", + &TemplateTest{ + TemplateName: "test_template_tenant", + TemplateType: "tenant", + Tenant: msoTemplateTenantName, + Sites: []string{msoTemplateSiteName1}, + }, + false, + ), + ), + }, + { + PreConfig: func() { fmt.Println("Test: Update the Tenant Template with 2 sites") }, + Config: testAccMSOTemplateResourceTenanTwoSitesConfig(), + Check: resource.ComposeTestCheckFunc( + testAccMSOTemplateState( + "mso_template.template_tenant", + &TemplateTest{ + TemplateName: "test_template_tenant", + TemplateType: "tenant", + Tenant: msoTemplateTenantName, + Sites: []string{msoTemplateSiteName1, msoTemplateSiteName2}, + }, + false, + ), + ), + }, + { + PreConfig: func() { fmt.Println("Test: Update the Tenant Template with reverse order of sites") }, + Config: testAccMSOTemplateResourceTenanTwoSitesReversedConfig(), + Check: resource.ComposeTestCheckFunc( + testAccMSOTemplateState( + "mso_template.template_tenant", + &TemplateTest{ + TemplateName: "test_template_tenant", + TemplateType: "tenant", + Tenant: msoTemplateTenantName, + Sites: []string{msoTemplateSiteName1, msoTemplateSiteName2}, + }, + false, + ), + ), + }, + { + PreConfig: func() { fmt.Println("Test: Update the Tenant Template with removal of site 2") }, + Config: testAccMSOTemplateResourceTenanSiteAnsibleTest2Config(), + Check: resource.ComposeTestCheckFunc( + testAccMSOTemplateState( + "mso_template.template_tenant", + &TemplateTest{ + TemplateName: "test_template_tenant", + TemplateType: "tenant", + Tenant: msoTemplateTenantName, + Sites: []string{msoTemplateSiteName2}, + }, + false, + ), + ), + }, + { + PreConfig: func() { fmt.Println("Test: Update the Tenant Template with change of site 2 to site 1") }, + Config: testAccMSOTemplateResourceTenanSiteAnsibleTestConfig(), + Check: resource.ComposeTestCheckFunc( + testAccMSOTemplateState( + "mso_template.template_tenant", + &TemplateTest{ + TemplateName: "test_template_tenant", + TemplateType: "tenant", + Tenant: msoTemplateTenantName, + Sites: []string{msoTemplateSiteName1}, + }, + false, + ), + ), + }, + { + PreConfig: func() { fmt.Println("Test: Update the Tenant Template with removal of sites configuration") }, + Config: testAccMSOTemplateResourceTenantNoSitesConfig(), + Check: resource.ComposeTestCheckFunc( + testAccMSOTemplateState( + "mso_template.template_tenant", + &TemplateTest{ + TemplateName: "test_template_tenant", + TemplateType: "tenant", + Tenant: msoTemplateTenantName, + Sites: []string{}, + }, + false, + ), + ), + }, + { + PreConfig: func() { fmt.Println("Test: Update the Tenant Template name") }, + Config: testAccMSOTemplateResourceTenantNameChangeConfig(), + Check: resource.ComposeTestCheckFunc( + testAccMSOTemplateState( + "mso_template.template_tenant", + &TemplateTest{ + TemplateName: "test_template_tenant_changed", + TemplateType: "tenant", + Tenant: msoTemplateTenantName, + Sites: []string{}, + }, + false, + ), + ), + }, + { + PreConfig: func() { fmt.Println("Test: Update the Tenant Template with duplicate sites (error)") }, + Config: testAccMSOTemplateResourceTenantErrorDuplicateSitesConfig(), + ExpectError: regexp.MustCompile(`Duplication found in the sites list`), + }, + { + PreConfig: func() { + fmt.Println("Test: Update the Tenant Template after manual removal from MSO") + msoClient := testAccProvider.Meta().(*client.Client) + err := msoClient.DeletebyId(fmt.Sprintf("api/v1/templates/%s", msoTemplateId)) + if err != nil { + t.Fatalf("Failed to manually delete template '%s': %v", msoTemplateId, err) + } + }, + Config: testAccMSOTemplateResourceTenantNameChangeConfig(), + Check: resource.ComposeTestCheckFunc( + testAccMSOTemplateState( + "mso_template.template_tenant", + &TemplateTest{ + TemplateName: "test_template_tenant_changed", + TemplateType: "tenant", + Tenant: msoTemplateTenantName, + Sites: []string{}, + }, + false, + ), + ), + }, + }, + }) +} + +type TemplateTest struct { + TemplateName string `json:",omitempty"` + TemplateType string `json:",omitempty"` + Tenant string `json:",omitempty"` + Sites []string `json:",omitempty"` +} + +func testAccMSOTemplateState(resourceName string, stateTemplate *TemplateTest, setmsoTemplateId bool) resource.TestCheckFunc { + return func(s *terraform.State) error { + + rootModule, err := s.RootModule().Resources[resourceName] + if !err { + return fmt.Errorf("%v", err) + } + + if rootModule.Primary.ID == "" { + return fmt.Errorf("No ID is set for the template") + } + + // Set the ID for the template to global variable only when called from specific resource test + // This is to avoid setting the ID issues when data source test is called first + if setmsoTemplateId { + msoTemplateId = rootModule.Primary.ID + } + + if rootModule.Primary.Attributes["tenant_id"] == "" && stateTemplate.Tenant != "" { + return fmt.Errorf("No tenant ID is set for the template") + } else if stateTemplate.Tenant != "" { + tenantState, err := s.RootModule().Resources[fmt.Sprintf("mso_tenant.%s", stateTemplate.Tenant)] + if !err { + return fmt.Errorf("Tenant %s not found in state", stateTemplate.Tenant) + } + if tenantState.Primary.Attributes["display_name"] != stateTemplate.Tenant { + return fmt.Errorf("Tenant display name does not match, expected: %s, got: %s", stateTemplate.Tenant, tenantState.Primary.Attributes["display_name"]) + } + } + + if rootModule.Primary.Attributes["template_name"] != stateTemplate.TemplateName { + return fmt.Errorf("Template name does not match, expected: %s, got: %s", stateTemplate.TemplateName, rootModule.Primary.Attributes["template_name"]) + } + + if rootModule.Primary.Attributes["template_type"] != stateTemplate.TemplateType { + return fmt.Errorf("Template type does not match, expected: %s, got: %s", stateTemplate.TemplateType, rootModule.Primary.Attributes["template_type"]) + } + + if sites, ok := rootModule.Primary.Attributes["sites.#"]; ok { + if siteAmount, e := strconv.Atoi(sites); e != nil { + return fmt.Errorf("Could not convert sites amount to integer") + } else if siteAmount != len(stateTemplate.Sites) { + return fmt.Errorf("Amount of sites do not match, expected: %d, got: %d", len(stateTemplate.Sites), len(rootModule.Primary.Attributes["sites.#"])) + } + + for _, site := range stateTemplate.Sites { + siteState, err := s.RootModule().Resources[fmt.Sprintf("data.mso_site.%s", site)] + if !err { + return fmt.Errorf("Site %s not found in state", site) + } + if siteState.Primary.Attributes["name"] != site { + return fmt.Errorf("Site display name does not match, expected: %s, got: %s", site, siteState.Primary.Attributes["display_name"]) + } + } + } else { + if len(stateTemplate.Sites) != 0 { + return fmt.Errorf("Amount of sites do not match, expected: %d, got: 0", len(stateTemplate.Sites)) + } + } + + return nil + } +} + +func testSiteConfigAnsibleTest() string { + return fmt.Sprintf(` + data "mso_site" "%s" { + name = "%s" + } + `, msoTemplateSiteName1, msoTemplateSiteName1) +} + +func testSiteConfigAnsibleTest2() string { + return fmt.Sprintf(` + data "mso_site" "%s" { + name = "%s" + } + `, msoTemplateSiteName2, msoTemplateSiteName2) +} + +func testTenantConfig() string { + return fmt.Sprintf(` + %s%s + resource "mso_tenant" "%s" { + name = "%s" + display_name = "%s" + site_associations { + site_id = data.mso_site.%s.id + } + site_associations { + site_id = data.mso_site.%s.id + } + } + `, testSiteConfigAnsibleTest(), testSiteConfigAnsibleTest2(), msoTemplateTenantName, msoTemplateTenantName, msoTemplateTenantName, msoTemplateSiteName1, msoTemplateSiteName2) +} + +func testAccMSOTemplateResourceTenantConfig() string { + return fmt.Sprintf(`%s + resource "mso_template" "template_tenant" { + template_name = "test_template_tenant" + template_type = "tenant" + tenant_id = mso_tenant.%s.id + } + `, testTenantConfig(), msoTemplateTenantName) +} + +func testAccMSOTemplateResourceTenantNameChangeConfig() string { + return fmt.Sprintf(`%s + resource "mso_template" "template_tenant" { + template_name = "test_template_tenant_changed" + template_type = "tenant" + tenant_id = mso_tenant.%s.id + } + `, testTenantConfig(), msoTemplateTenantName) +} + +func testAccMSOTemplateResourceTenantNoSitesConfig() string { + return fmt.Sprintf(`%s + resource "mso_template" "template_tenant" { + template_name = "test_template_tenant" + template_type = "tenant" + tenant_id = mso_tenant.%s.id + sites = [] + } + `, testTenantConfig(), msoTemplateTenantName) +} + +func testAccMSOTemplateResourceTenanSiteAnsibleTestConfig() string { + return fmt.Sprintf(`%s + resource "mso_template" "template_tenant" { + template_name = "test_template_tenant" + template_type = "tenant" + tenant_id = mso_tenant.%s.id + sites = [data.mso_site.%s.id] + } + `, testTenantConfig(), msoTemplateTenantName, msoTemplateSiteName1) +} + +func testAccMSOTemplateResourceTenanSiteAnsibleTest2Config() string { + return fmt.Sprintf(`%s + resource "mso_template" "template_tenant" { + template_name = "test_template_tenant" + template_type = "tenant" + tenant_id = mso_tenant.%s.id + sites = [data.mso_site.%s.id] + } + `, testTenantConfig(), msoTemplateTenantName, msoTemplateSiteName2) +} + +func testAccMSOTemplateResourceTenanTwoSitesConfig() string { + return fmt.Sprintf(`%s + resource "mso_template" "template_tenant" { + template_name = "test_template_tenant" + template_type = "tenant" + tenant_id = mso_tenant.%s.id + sites = [data.mso_site.%s.id, data.mso_site.%s.id] + } + `, testTenantConfig(), msoTemplateTenantName, msoTemplateSiteName1, msoTemplateSiteName2) +} + +func testAccMSOTemplateResourceTenanTwoSitesReversedConfig() string { + return fmt.Sprintf(`%s + resource "mso_template" "template_tenant" { + template_name = "test_template_tenant" + template_type = "tenant" + tenant_id = mso_tenant.%s.id + sites = [data.mso_site.%s.id, data.mso_site.%s.id] + } + `, testTenantConfig(), msoTemplateTenantName, msoTemplateSiteName2, msoTemplateSiteName1) +} + +func testAccMSOTemplateResourceTenantErrorDuplicateSitesConfig() string { + return fmt.Sprintf(`%s + resource "mso_template" "template_tenant" { + template_name = "test_template_tenant" + template_type = "tenant" + tenant_id = mso_tenant.%s.id + sites = [data.mso_site.%s.id, data.mso_site.%s.id] + } + `, testTenantConfig(), msoTemplateTenantName, msoTemplateSiteName1, msoTemplateSiteName1) +} + +func testAccMSOTemplateResourceTenanErrorNoTenantConfig() string { + return fmt.Sprintf(`%s%s + resource "mso_template" "template_tenant" { + template_name = "test_template_tenant" + template_type = "tenant" + sites = [data.mso_site.%s.id, data.mso_site.%s.id] + } + `, testSiteConfigAnsibleTest(), testSiteConfigAnsibleTest2(), msoTemplateSiteName1, msoTemplateSiteName2) +} + +func TestAccMSOTemplateResourceL3out(t *testing.T) { + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + PreConfig: func() { fmt.Println("Test: No tenant provided in L3out Template configuration (error)") }, + Config: testAccMSOTemplateResourceL3outErrorNoTenantConfig(), + ExpectError: regexp.MustCompile(`Tenant is required for template of type l3out.`), + }, + { + PreConfig: func() { fmt.Println("Test: No sites provided in L3out Template configuration (error)") }, + Config: testAccMSOTemplateResourceL3outErrorNoSitesConfig(), + ExpectError: regexp.MustCompile(`Site is required for template of type l3out.`), + }, + { + PreConfig: func() { fmt.Println("Test: Two sites provided in L3out Template configuration (error)") }, + Config: testAccMSOTemplateResourceL3outErrorTwositesConfig(), + ExpectError: regexp.MustCompile(`Only one site is allowed for template of type l3out.`), + }, + { + PreConfig: func() { fmt.Println("Test: Create L3out Template with 1 site") }, + Config: testAccMSOTemplateResourceL3outConfig(), + Check: resource.ComposeTestCheckFunc( + testAccMSOTemplateState( + "mso_template.template_l3out", + &TemplateTest{ + TemplateName: "test_template_l3out", + TemplateType: "l3out", + Tenant: msoTemplateTenantName, + Sites: []string{msoTemplateSiteName1}, + }, + false, + ), + ), + }, + { + PreConfig: func() { fmt.Println("Test: Update the L3out Template with change of site 1 to site 2 (error)") }, + Config: testAccMSOTemplateResourceL3outErrorChangeSiteConfig(), + ExpectError: regexp.MustCompile(`Cannot change site for template of type l3out.`), + }, + }, + }) +} + +func testAccMSOTemplateResourceL3outConfig() string { + return fmt.Sprintf(`%s + resource "mso_template" "template_l3out" { + template_name = "test_template_l3out" + template_type = "l3out" + tenant_id = mso_tenant.%s.id + sites = [data.mso_site.%s.id] + } + `, testTenantConfig(), msoTemplateTenantName, msoTemplateSiteName1) +} + +func testAccMSOTemplateResourceL3outErrorNoTenantConfig() string { + return fmt.Sprintf(`%s + resource "mso_template" "template_l3out" { + template_name = "test_template_l3out" + template_type = "l3out" + sites = [data.mso_site.%s.id] + } + `, testSiteConfigAnsibleTest(), msoTemplateSiteName1) +} + +func testAccMSOTemplateResourceL3outErrorNoSitesConfig() string { + return fmt.Sprintf(`%s + resource "mso_template" "template_l3out" { + template_name = "test_template_l3out" + template_type = "l3out" + tenant_id = mso_tenant.%s.id + } + `, testTenantConfig(), msoTemplateTenantName) +} + +func testAccMSOTemplateResourceL3outErrorTwositesConfig() string { + return fmt.Sprintf(`%s + resource "mso_template" "template_l3out" { + template_name = "test_template_l3out" + template_type = "l3out" + tenant_id = mso_tenant.%s.id + sites = [data.mso_site.%s.id, data.mso_site.%s.id] + } + `, testTenantConfig(), msoTemplateTenantName, msoTemplateSiteName1, msoTemplateSiteName2) +} + +func testAccMSOTemplateResourceL3outErrorChangeSiteConfig() string { + return fmt.Sprintf(`%s + resource "mso_template" "template_l3out" { + template_name = "test_template_l3out" + template_type = "l3out" + tenant_id = mso_tenant.%s.id + sites = [data.mso_site.%s.id] + } + `, testTenantConfig(), msoTemplateTenantName, msoTemplateSiteName2) +} + +func TestAccMSOTemplateResourceFabricPolicy(t *testing.T) { + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + PreConfig: func() { fmt.Println("Test: No tenant provided in Fabric Policy Template configuration (error)") }, + Config: testAccMSOTemplateResourceFabricPolicyErrorTenantConfig(), + ExpectError: regexp.MustCompile(`Tenant cannot be attached to template of type fabric_policy.`), + }, + { + PreConfig: func() { fmt.Println("Test: Create Fabric Policy Template without sites") }, + Config: testAccMSOTemplateResourceFabricPolicyConfig(), + Check: resource.ComposeTestCheckFunc( + testAccMSOTemplateState( + "mso_template.template_fabric_policy", + &TemplateTest{ + TemplateName: "test_template_fabric_policy", + TemplateType: "fabric_policy", + Sites: []string{}, + }, + false, + ), + ), + }, + }, + }) +} + +func testAccMSOTemplateResourceFabricPolicyConfig() string { + return fmt.Sprintf(` + resource "mso_template" "template_fabric_policy" { + template_name = "test_template_fabric_policy" + template_type = "fabric_policy" + } + `) +} + +func testAccMSOTemplateResourceFabricPolicyErrorTenantConfig() string { + return fmt.Sprintf(`%s + resource "mso_template" "template_fabric_policy" { + template_name = "test_template_fabric_policy" + template_type = "fabric_policy" + tenant_id = mso_tenant.%s.id + } + `, testTenantConfig(), msoTemplateTenantName) +} + +func TestAccMSOTemplateResourceFabricResource(t *testing.T) { + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + PreConfig: func() { fmt.Println("Test: Tenant provided in Fabric Resource Template configuration (error)") }, + Config: testAccMSOTemplateResourceFabricResourceErrorTenantConfig(), + ExpectError: regexp.MustCompile(`Tenant cannot be attached to template of type fabric_resource.`), + }, + { + PreConfig: func() { fmt.Println("Test: Create Fabric Resource Template without sites") }, + Config: testAccMSOTemplateResourceFabricResourceConfig(), + Check: resource.ComposeTestCheckFunc( + testAccMSOTemplateState( + "mso_template.template_fabric_resource", + &TemplateTest{ + TemplateName: "test_template_fabric_resource", + TemplateType: "fabric_resource", + Sites: []string{}, + }, + false, + ), + ), + }, + }, + }) +} + +func testAccMSOTemplateResourceFabricResourceConfig() string { + return fmt.Sprintf(` + resource "mso_template" "template_fabric_resource" { + template_name = "test_template_fabric_resource" + template_type = "fabric_resource" + } + `) +} + +func testAccMSOTemplateResourceFabricResourceErrorTenantConfig() string { + return fmt.Sprintf(`%s + resource "mso_template" "template_fabric_resource" { + template_name = "test_template_fabric_resource" + template_type = "fabric_resource" + tenant_id = mso_tenant.%s.id + } + `, testTenantConfig(), msoTemplateTenantName) +} + +func TestAccMSOTemplateResourceMonitoringTenant(t *testing.T) { + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + PreConfig: func() { fmt.Println("Test: No tenant provided in Monitoring Tenant Template configuration (error)") }, + Config: testAccMSOTemplateResourceMonitoringTenantErrorNoTenantConfig(), + ExpectError: regexp.MustCompile(`Tenant is required for template of type monitoring_tenant.`), + }, + { + PreConfig: func() { fmt.Println("Test: No site provided in Monitoring Tenant Template configuration (error)") }, + Config: testAccMSOTemplateResourceMonitoringTenantErrorNoSiteConfig(), + ExpectError: regexp.MustCompile(`Site is required for template of type monitoring_tenant.`), + }, + { + PreConfig: func() { fmt.Println("Test: Two sites provided in Monitoring Tenant Template configuration (error)") }, + Config: testAccMSOTemplateResourceMonitoringTenantErrorTwoSitesConfig(), + ExpectError: regexp.MustCompile(`Only one site is allowed for template of type monitoring_tenant.`), + }, + { + PreConfig: func() { fmt.Println("Test: Create Monitoring Tenant Template with 1 site") }, + Config: testAccMSOTemplateResourceMonitoringTenantConfig(), + Check: resource.ComposeTestCheckFunc( + testAccMSOTemplateState( + "mso_template.template_monitoring_tenant", + &TemplateTest{ + TemplateName: "test_template_monitoring_tenant", + TemplateType: "monitoring_tenant", + Sites: []string{msoTemplateSiteName1}, + }, + false, + ), + ), + }, + }, + }) +} + +func testAccMSOTemplateResourceMonitoringTenantErrorNoTenantConfig() string { + return fmt.Sprintf(`%s + resource "mso_template" "template_monitoring_tenant" { + template_name = "test_template_monitoring_tenant" + template_type = "monitoring_tenant" + sites = [data.mso_site.%s.id] + } + `, testTenantConfig(), msoTemplateSiteName1) +} + +func testAccMSOTemplateResourceMonitoringTenantErrorNoSiteConfig() string { + return fmt.Sprintf(`%s + resource "mso_template" "template_monitoring_tenant" { + template_name = "test_template_monitoring_tenant" + template_type = "monitoring_tenant" + tenant_id = mso_tenant.%s.id + } + `, testTenantConfig(), msoTemplateTenantName) +} + +func testAccMSOTemplateResourceMonitoringTenantErrorTwoSitesConfig() string { + return fmt.Sprintf(`%s + resource "mso_template" "template_monitoring_tenant" { + template_name = "test_template_monitoring_tenant" + template_type = "monitoring_tenant" + tenant_id = mso_tenant.%s.id + sites = [data.mso_site.%s.id, data.mso_site.%s.id] + } + `, testTenantConfig(), msoTemplateTenantName, msoTemplateSiteName1, msoTemplateSiteName2) +} + +func testAccMSOTemplateResourceMonitoringTenantConfig() string { + return fmt.Sprintf(`%s + resource "mso_template" "template_monitoring_tenant" { + template_name = "test_template_monitoring_tenant" + template_type = "monitoring_tenant" + tenant_id = mso_tenant.%s.id + sites = [data.mso_site.%s.id] + } + `, testTenantConfig(), msoTemplateTenantName, msoTemplateSiteName1) +} + +func TestAccMSOTemplateResourceMonitoringAccess(t *testing.T) { + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + PreConfig: func() { fmt.Println("Test: Tenant provided in Monitoring Access Template configuration (error)") }, + Config: testAccMSOTemplateResourceMonitoringAccessErrorTenantConfig(), + ExpectError: regexp.MustCompile(`Tenant cannot be attached to template of type monitoring_access.`), + }, + { + PreConfig: func() { fmt.Println("Test: No site provided in Monitoring Access Template configuration (error)") }, + Config: testAccMSOTemplateResourceMonitoringAccessErrorNoSiteConfig(), + ExpectError: regexp.MustCompile(`Site is required for template of type monitoring_access.`), + }, + { + PreConfig: func() { fmt.Println("Test: Two sites provided in Monitoring Access Template configuration (error)") }, + Config: testAccMSOTemplateResourceMonitoringAccessErrorTwoSitesConfig(), + ExpectError: regexp.MustCompile(`Only one site is allowed for template of type monitoring_access.`), + }, + { + PreConfig: func() { fmt.Println("Test: Create Monitoring Access Template with 1 site") }, + Config: testAccMSOTemplateResourceMonitoringAccessConfig(), + Check: resource.ComposeTestCheckFunc( + testAccMSOTemplateState( + "mso_template.template_monitoring_access", + &TemplateTest{ + TemplateName: "test_template_monitoring_access", + TemplateType: "monitoring_access", + Sites: []string{msoTemplateSiteName1}, + }, + false, + ), + ), + }, + }, + }) +} + +func testAccMSOTemplateResourceMonitoringAccessErrorTenantConfig() string { + return fmt.Sprintf(`%s + resource "mso_template" "template_monitoring_access" { + template_name = "test_template_monitoring_access" + template_type = "monitoring_access" + tenant_id = mso_tenant.%s.id + sites = [data.mso_site.%s.id] + } + `, testTenantConfig(), msoTemplateTenantName, msoTemplateSiteName1) +} + +func testAccMSOTemplateResourceMonitoringAccessErrorNoSiteConfig() string { + return fmt.Sprintf(`%s + resource "mso_template" "template_monitoring_access" { + template_name = "test_template_monitoring_access" + template_type = "monitoring_access" + } + `, testTenantConfig()) +} + +func testAccMSOTemplateResourceMonitoringAccessErrorTwoSitesConfig() string { + return fmt.Sprintf(`%s + resource "mso_template" "template_monitoring_access" { + template_name = "test_template_monitoring_access" + template_type = "monitoring_access" + sites = [data.mso_site.%s.id, data.mso_site.%s.id] + } + `, testTenantConfig(), msoTemplateSiteName1, msoTemplateSiteName2) +} + +func testAccMSOTemplateResourceMonitoringAccessConfig() string { + return fmt.Sprintf(`%s + resource "mso_template" "template_monitoring_access" { + template_name = "test_template_monitoring_access" + template_type = "monitoring_access" + sites = [data.mso_site.%s.id] + } + `, testTenantConfig(), msoTemplateSiteName1) +} + +func TestAccMSOTemplateResourceServiceDevice(t *testing.T) { + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + PreConfig: func() { fmt.Println("Test: No tenant provided in Service Device Template configuration (error)") }, + Config: testAccMSOTemplateResourceServiceDeviceErrorNoTenantConfig(), + ExpectError: regexp.MustCompile(`Tenant is required for template of type service_device.`), + }, + { + PreConfig: func() { fmt.Println("Test: Create Service Device Template with 2 sites") }, + Config: testAccMSOTemplateResourceServiceDeviceConfig(), + Check: resource.ComposeTestCheckFunc( + testAccMSOTemplateState( + "mso_template.template_service_device", + &TemplateTest{ + TemplateName: "test_template_service_device", + TemplateType: "service_device", + Sites: []string{msoTemplateSiteName1, msoTemplateSiteName2}, + }, + false, + ), + ), + }, + }, + }) +} + +func testAccMSOTemplateResourceServiceDeviceErrorNoTenantConfig() string { + return fmt.Sprintf(`%s + resource "mso_template" "template_service_device" { + template_name = "test_template_service_device" + template_type = "service_device" + } + `, testTenantConfig()) +} + +func testAccMSOTemplateResourceServiceDeviceConfig() string { + return fmt.Sprintf(`%s + resource "mso_template" "template_service_device" { + template_name = "test_template_service_device" + template_type = "service_device" + tenant_id = mso_tenant.%s.id + sites = [data.mso_site.%s.id, data.mso_site.%s.id] + } + `, testTenantConfig(), msoTemplateTenantName, msoTemplateSiteName1, msoTemplateSiteName2) +} diff --git a/website/docs/d/template.html.markdown b/website/docs/d/template.html.markdown index b746b54c..43d603b0 100644 --- a/website/docs/d/template.html.markdown +++ b/website/docs/d/template.html.markdown @@ -33,5 +33,5 @@ data "mso_template" "example_with_id" { ## Attribute Reference ## -* `tenant_name` - (Read-Only) The name of the tenant to associate with the template. -* `sites` - (Read-Only) A list of site names to associate with the template. +* `tenant_id` - (Read-Only) The ID of the tenant associated with the template. +* `sites` - (Read-Only) A list of site names associated with the template. diff --git a/website/docs/r/template.html.markdown b/website/docs/r/template.html.markdown index d44b5880..7ae6879c 100644 --- a/website/docs/r/template.html.markdown +++ b/website/docs/r/template.html.markdown @@ -17,7 +17,7 @@ Manages MSO Template resource "mso_template" "tenant_template" { template_name = "tenant_template" template_type = "tenant" - tenant_name = data.mso_tenant.example_tenant.display_name + tenant_id = data.mso_tenant.example_tenant.id sites = [data.mso_site.site_1.id, data.mso_site.site_2.id] } @@ -27,8 +27,8 @@ resource "mso_template" "tenant_template" { * `template_name` - (Required) The name of the template. * `template_type` - (Required) The type of the template. Allowed values are `tenant`, `l3out`, `fabric_policy`, `fabric_resource`, `monitoring_tenant`, `monitoring_access`, or `service_device`. -* `tenant_name` - (Optional) The name of the tenant to associate with the template. -* `sites` - (Optional) A list of site names to associate with the template. +* `tenant_id` - (Optional) The ID of the tenant to associate with the template. +* `sites` - (Optional) A list of site IDs to associate with the template. ## Attribute Reference ##