From e1a956bc6c66dbf304a825dd3ad377dddf03989b Mon Sep 17 00:00:00 2001 From: Alex Pilon Date: Wed, 23 Feb 2022 19:15:38 -0500 Subject: [PATCH] Move to runtime validation --- vsphere/resource_vsphere_tag_category.go | 47 ++++++++++--------- vsphere/resource_vsphere_tag_category_test.go | 29 ++++++++++++ vsphere/tags_helper.go | 20 ++++++++ 3 files changed, 74 insertions(+), 22 deletions(-) diff --git a/vsphere/resource_vsphere_tag_category.go b/vsphere/resource_vsphere_tag_category.go index 9c99e3952..c90c09eca 100644 --- a/vsphere/resource_vsphere_tag_category.go +++ b/vsphere/resource_vsphere_tag_category.go @@ -63,28 +63,6 @@ func resourceVSphereTagCategory() *schema.Resource { Description: "Object types to which this category's tags can be attached. Valid types include: Folder, ClusterComputeResource, Datacenter, Datastore, StoragePod, DistributedVirtualPortgroup, DistributedVirtualSwitch, VmwareDistributedVirtualSwitch, HostSystem, com.vmware.content.Library, com.vmware.content.library.Item, HostNetwork, Network, OpaqueNetwork, ResourcePool, VirtualApp, VirtualMachine.", Elem: &schema.Schema{Type: schema.TypeString}, Required: true, - ValidateFunc: validation.StringInSlice( - []string{ - "Folder", - "ClusterComputeResource", - "Datacenter", - "Datastore", - "StoragePod", - "DistributedVirtualPortgroup", - "DistributedVirtualSwitch", - "VmwareDistributedVirtualSwitch", - "HostSystem", - "com.vmware.content.Library", - "com.vmware.content.library.Item", - "HostNetwork", - "Network", - "OpaqueNetwork", - "ResourcePool", - "VirtualApp", - "VirtualMachine", - }, - false, - ), }, }, } @@ -96,6 +74,9 @@ func resourceVSphereTagCategoryCreate(d *schema.ResourceData, meta interface{}) return err } associableTypesRaw := structure.SliceInterfacesToStrings(d.Get("associable_types").(*schema.Set).List()) + if err := validateAssociableTypes(associableTypesRaw); err != nil { + return err + } associableTypes := appendPrefix(associableTypesRaw) spec := &tags.Category{ @@ -169,6 +150,9 @@ func resourceVSphereTagCategoryUpdate(d *schema.ResourceData, meta interface{}) id := d.Id() associableTypesRaw := structure.SliceInterfacesToStrings(d.Get("associable_types").(*schema.Set).List()) + if err := validateAssociableTypes(associableTypesRaw); err != nil { + return err + } associableTypes := appendPrefix(associableTypesRaw) spec := &tags.Category{ @@ -228,3 +212,22 @@ func appendPrefix(associableTypes []string) []string { } return appendedTypes } + +func validateAssociableTypes(types []string) error { + + mapOf := func(s []string) map[string]struct{} { + m := make(map[string]struct{}, len(s)) + for _, k := range s { + m[k] = struct{}{} + } + return m + } + + validTypesMap := mapOf(vSphereTagTypes) + for _, t := range types { + if _, exists := validTypesMap[t]; !exists { + return fmt.Errorf("%s is not a valid associable_type, valid types include: %v", t, vSphereTagTypes) + } + } + return nil +} diff --git a/vsphere/resource_vsphere_tag_category_test.go b/vsphere/resource_vsphere_tag_category_test.go index 1b0205d86..31317d569 100644 --- a/vsphere/resource_vsphere_tag_category_test.go +++ b/vsphere/resource_vsphere_tag_category_test.go @@ -108,6 +108,23 @@ func TestAccResourceVSphereTagCategory_removeTypeShouldError(t *testing.T) { }) } +func TestAccResourceVSphereTagCategory_invalidTypeShouldError(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { + RunSweepers() + testAccPreCheck(t) + }, + Providers: testAccProviders, + CheckDestroy: testAccResourceVSphereTagCategoryExists(false), + Steps: []resource.TestStep{ + { + Config: testAccResourceVSphereTagCategoryConfigInvalid, + ExpectError: regexp.MustCompile("is not a valid associable_type"), + }, + }, + }) +} + func TestAccResourceVSphereTagCategory_rename(t *testing.T) { resource.Test(t, resource.TestCase{ PreCheck: func() { @@ -262,6 +279,18 @@ resource "vsphere_tag_category" "testacc-category" { } ` +const testAccResourceVSphereTagCategoryConfigInvalid = ` +resource "vsphere_tag_category" "testacc-category" { + name = "testacc-category" + description = "Managed by Terraform" + cardinality = "SINGLE" + + associable_types = [ + "invalid", + ] +} +` + const testAccResourceVSphereTagCategoryConfigMultiCardinality = ` resource "vsphere_tag_category" "testacc-category" { name = "testacc-category" diff --git a/vsphere/tags_helper.go b/vsphere/tags_helper.go index 7f0040875..f00b91187 100644 --- a/vsphere/tags_helper.go +++ b/vsphere/tags_helper.go @@ -21,6 +21,26 @@ const ( vSphereTagTypeVirtualMachine = "VirtualMachine" ) +var vSphereTagTypes = []string{ + "Folder", + "ClusterComputeResource", + "Datacenter", + vSphereTagTypeDatastore, + "StoragePod", + "DistributedVirtualPortgroup", + "DistributedVirtualSwitch", + "VmwareDistributedVirtualSwitch", + "HostSystem", + "com.vmware.content.Library", + "com.vmware.content.library.Item", + "HostNetwork", + "Network", + "OpaqueNetwork", + "ResourcePool", + "VirtualApp", + vSphereTagTypeVirtualMachine, +} + // vSphereTagCategorySearchErrMultiple is an error message format for a tag // category search that returned multiple results. This is a bug and needs to // be reported so we can adjust the API.