From 8b44c1b66cab62ee2a18d220016d1df39771e99c Mon Sep 17 00:00:00 2001 From: Anna Khmelnitsky Date: Wed, 24 Jul 2024 20:08:41 +0000 Subject: [PATCH] VPC 2.0 Service Profile support Extended tests will be added as follow up Signed-off-by: Anna Khmelnitsky --- nsxt/provider.go | 1 + nsxt/resource_nsxt_vpc_service_profile.go | 450 ++++++++++++++++++ .../resource_nsxt_vpc_service_profile_test.go | 226 +++++++++ nsxt/utils_test.go | 7 + .../docs/r/vpc_service_profile.html.markdown | 91 ++++ 5 files changed, 775 insertions(+) create mode 100644 nsxt/resource_nsxt_vpc_service_profile.go create mode 100644 nsxt/resource_nsxt_vpc_service_profile_test.go create mode 100644 website/docs/r/vpc_service_profile.html.markdown diff --git a/nsxt/provider.go b/nsxt/provider.go index 66e28d00d..047dc7328 100644 --- a/nsxt/provider.go +++ b/nsxt/provider.go @@ -499,6 +499,7 @@ func Provider() *schema.Provider { "nsxt_vpc_security_policy": resourceNsxtVPCSecurityPolicy(), "nsxt_vpc_group": resourceNsxtVPCGroup(), "nsxt_vpc_gateway_policy": resourceNsxtVPCGatewayPolicy(), + "nsxt_vpc_service_profile": resourceNsxtVpcServiceProfile(), "nsxt_policy_share": resourceNsxtPolicyShare(), "nsxt_policy_shared_resource": resourceNsxtPolicySharedResource(), }, diff --git a/nsxt/resource_nsxt_vpc_service_profile.go b/nsxt/resource_nsxt_vpc_service_profile.go new file mode 100644 index 000000000..40686c470 --- /dev/null +++ b/nsxt/resource_nsxt_vpc_service_profile.go @@ -0,0 +1,450 @@ +/* Copyright © 2024 Broadcom, Inc. All Rights Reserved. + SPDX-License-Identifier: MPL-2.0 */ + +package nsxt + +import ( + "fmt" + "log" + "reflect" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" + "github.com/vmware/vsphere-automation-sdk-go/runtime/protocol/client" + "github.com/vmware/vsphere-automation-sdk-go/services/nsxt/model" + clientLayer "github.com/vmware/vsphere-automation-sdk-go/services/nsxt/orgs/projects" + + utl "github.com/vmware/terraform-provider-nsxt/api/utl" + "github.com/vmware/terraform-provider-nsxt/nsxt/metadata" +) + +var vpcServiceProfileModeValues = []string{ + model.VpcProfileDhcpConfig_MODE_IP_ALLOCATION_BY_PORT, + model.VpcProfileDhcpConfig_MODE_IP_ALLOCATION_BY_MAC, + model.VpcProfileDhcpConfig_MODE_RELAY, + model.VpcProfileDhcpConfig_MODE_DEACTIVATED, +} + +var vpcServiceProfileLogLevelValues = []string{ + model.PolicyVpcDnsForwarder_LOG_LEVEL_DEBUG, + model.PolicyVpcDnsForwarder_LOG_LEVEL_INFO, + model.PolicyVpcDnsForwarder_LOG_LEVEL_ERROR, + model.PolicyVpcDnsForwarder_LOG_LEVEL_WARNING, + model.PolicyVpcDnsForwarder_LOG_LEVEL_FATAL, +} + +var vpcServiceProfileSchema = map[string]*metadata.ExtendedSchema{ + "nsx_id": metadata.GetExtendedSchema(getNsxIDSchema()), + "path": metadata.GetExtendedSchema(getPathSchema()), + "display_name": metadata.GetExtendedSchema(getDisplayNameSchema()), + "description": metadata.GetExtendedSchema(getDescriptionSchema()), + "revision": metadata.GetExtendedSchema(getRevisionSchema()), + "tag": metadata.GetExtendedSchema(getTagsSchema()), + "context": metadata.GetExtendedSchema(getContextSchema(true, false, false)), + "is_default": { + Schema: schema.Schema{ + Type: schema.TypeBool, + Optional: true, + }, + Metadata: metadata.Metadata{ + SchemaType: "bool", + SdkFieldName: "IsDefault", + }, + }, + "mac_discovery_profile": { + Schema: schema.Schema{ + Type: schema.TypeString, + Optional: true, + ValidateFunc: validatePolicyPath(), + }, + Metadata: metadata.Metadata{ + SchemaType: "string", + SdkFieldName: "MacDiscoveryProfile", + }, + }, + "spoof_guard_profile": { + Schema: schema.Schema{ + Type: schema.TypeString, + Optional: true, + ValidateFunc: validatePolicyPath(), + }, + Metadata: metadata.Metadata{ + SchemaType: "string", + SdkFieldName: "SpoofGuardProfile", + }, + }, + "dhcp_config": { + Schema: schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Required: true, + Elem: &metadata.ExtendedResource{ + Schema: map[string]*metadata.ExtendedSchema{ + "ntp_servers": { + Schema: schema.Schema{ + Type: schema.TypeList, + Elem: &metadata.ExtendedSchema{ + Schema: schema.Schema{ + Type: schema.TypeString, + }, + Metadata: metadata.Metadata{ + SchemaType: "string", + }, + }, + Optional: true, + }, + Metadata: metadata.Metadata{ + SchemaType: "list", + SdkFieldName: "NtpServers", + }, + }, + "dns_client_config": { + Schema: schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Elem: &metadata.ExtendedResource{ + Schema: map[string]*metadata.ExtendedSchema{ + "dns_server_ips": { + Schema: schema.Schema{ + Type: schema.TypeList, + Elem: &metadata.ExtendedSchema{ + Schema: schema.Schema{ + Type: schema.TypeString, + }, + Metadata: metadata.Metadata{ + SchemaType: "string", + }, + }, + Optional: true, + }, + Metadata: metadata.Metadata{ + SchemaType: "list", + SdkFieldName: "DnsServerIps", + }, + }, + }, + }, + Optional: true, + }, + Metadata: metadata.Metadata{ + SchemaType: "struct", + SdkFieldName: "DnsClientConfig", + ReflectType: reflect.TypeOf(model.DnsClientConfig{}), + }, + }, + "lease_time": { + Schema: schema.Schema{ + Type: schema.TypeInt, + Optional: true, + Default: 86400, + }, + Metadata: metadata.Metadata{ + SchemaType: "int", + SdkFieldName: "LeaseTime", + }, + }, + "mode": { + Schema: schema.Schema{ + Type: schema.TypeString, + ValidateFunc: validation.StringInSlice(vpcServiceProfileModeValues, false), + Optional: true, + Default: model.VpcProfileDhcpConfig_MODE_IP_ALLOCATION_BY_PORT, + }, + Metadata: metadata.Metadata{ + SchemaType: "string", + SdkFieldName: "Mode", + }, + }, + "dhcp_relay_config": { + Schema: schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Elem: &metadata.ExtendedResource{ + Schema: map[string]*metadata.ExtendedSchema{ + "server_addresses": { + Schema: schema.Schema{ + Type: schema.TypeList, + Elem: &metadata.ExtendedSchema{ + Schema: schema.Schema{ + Type: schema.TypeString, + }, + Metadata: metadata.Metadata{ + SchemaType: "string", + }, + }, + Optional: true, + }, + Metadata: metadata.Metadata{ + SchemaType: "list", + SdkFieldName: "ServerAddresses", + }, + }, + }, + }, + Optional: true, + }, + Metadata: metadata.Metadata{ + SchemaType: "struct", + SdkFieldName: "DhcpRelayConfig", + ReflectType: reflect.TypeOf(model.VpcDhcpRelayConfig{}), + }, + }, + }, + }, + }, + Metadata: metadata.Metadata{ + SchemaType: "struct", + SdkFieldName: "DhcpConfig", + ReflectType: reflect.TypeOf(model.VpcProfileDhcpConfig{}), + }, + }, + "ip_discovery_profile": { + Schema: schema.Schema{ + Type: schema.TypeString, + Optional: true, + ValidateFunc: validatePolicyPath(), + }, + Metadata: metadata.Metadata{ + SchemaType: "string", + SdkFieldName: "IpDiscoveryProfile", + }, + }, + "security_profile": { + Schema: schema.Schema{ + Type: schema.TypeString, + Optional: true, + ValidateFunc: validatePolicyPath(), + }, + Metadata: metadata.Metadata{ + SchemaType: "string", + SdkFieldName: "SecurityProfile", + }, + }, + "qos_profile": { + Schema: schema.Schema{ + Type: schema.TypeString, + Optional: true, + ValidateFunc: validatePolicyPath(), + }, + Metadata: metadata.Metadata{ + SchemaType: "string", + SdkFieldName: "QosProfile", + }, + }, + "dns_forwarder_config": { + Schema: schema.Schema{ + Type: schema.TypeList, + MaxItems: 1, + Elem: &metadata.ExtendedResource{ + Schema: map[string]*metadata.ExtendedSchema{ + "cache_size": { + Schema: schema.Schema{ + Type: schema.TypeInt, + Optional: true, + Default: 1024, + }, + Metadata: metadata.Metadata{ + SchemaType: "int", + SdkFieldName: "CacheSize", + }, + }, + "log_level": { + Schema: schema.Schema{ + Type: schema.TypeString, + ValidateFunc: validation.StringInSlice(vpcServiceProfileLogLevelValues, false), + Optional: true, + Default: model.PolicyVpcDnsForwarder_LOG_LEVEL_INFO, + }, + Metadata: metadata.Metadata{ + SchemaType: "string", + SdkFieldName: "LogLevel", + }, + }, + "conditional_forwarder_zone_paths": { + Schema: schema.Schema{ + Type: schema.TypeList, + Elem: &metadata.ExtendedSchema{ + Schema: schema.Schema{ + Type: schema.TypeString, + ValidateFunc: validatePolicyPath(), + }, + Metadata: metadata.Metadata{ + SchemaType: "string", + }, + }, + Optional: true, + }, + Metadata: metadata.Metadata{ + SchemaType: "list", + SdkFieldName: "ConditionalForwarderZonePaths", + }, + }, + "default_forwarder_zone_path": { + Schema: schema.Schema{ + Type: schema.TypeString, + ValidateFunc: validatePolicyPath(), + Optional: true, + }, + Metadata: metadata.Metadata{ + SchemaType: "string", + SdkFieldName: "DefaultForwarderZonePath", + }, + }, + }, + }, + Optional: true, + }, + Metadata: metadata.Metadata{ + SchemaType: "struct", + SdkFieldName: "DnsForwarderConfig", + ReflectType: reflect.TypeOf(model.PolicyVpcDnsForwarder{}), + }, + }, +} + +func resourceNsxtVpcServiceProfile() *schema.Resource { + return &schema.Resource{ + Create: resourceNsxtVpcServiceProfileCreate, + Read: resourceNsxtVpcServiceProfileRead, + Update: resourceNsxtVpcServiceProfileUpdate, + Delete: resourceNsxtVpcServiceProfileDelete, + Importer: &schema.ResourceImporter{ + State: nsxtPolicyPathResourceImporter, + }, + Schema: metadata.GetSchemaFromExtendedSchema(vpcServiceProfileSchema), + } +} + +func resourceNsxtVpcServiceProfileExists(sessionContext utl.SessionContext, id string, connector client.Connector) (bool, error) { + var err error + parents := getVpcParentsFromContext(sessionContext) + client := clientLayer.NewVpcServiceProfilesClient(connector) + _, err = client.Get(parents[0], parents[1], id) + if err == nil { + return true, nil + } + + if isNotFoundError(err) { + return false, nil + } + + return false, logAPIError("Error retrieving resource", err) +} + +func resourceNsxtVpcServiceProfileCreate(d *schema.ResourceData, m interface{}) error { + connector := getPolicyConnector(m) + + id, err := getOrGenerateID2(d, m, resourceNsxtVpcServiceProfileExists) + if err != nil { + return err + } + + parents := getVpcParentsFromContext(getSessionContext(d, m)) + displayName := d.Get("display_name").(string) + description := d.Get("description").(string) + tags := getPolicyTagsFromSchema(d) + + obj := model.VpcServiceProfile{ + DisplayName: &displayName, + Description: &description, + Tags: tags, + } + + elem := reflect.ValueOf(&obj).Elem() + if err := metadata.SchemaToStruct(elem, d, vpcServiceProfileSchema, "", nil); err != nil { + return err + } + + log.Printf("[INFO] Creating VpcServiceProfile with ID %s", id) + + client := clientLayer.NewVpcServiceProfilesClient(connector) + err = client.Patch(parents[0], parents[1], id, obj) + if err != nil { + return handleCreateError("VpcServiceProfile", id, err) + } + d.SetId(id) + d.Set("nsx_id", id) + + return resourceNsxtVpcServiceProfileRead(d, m) +} + +func resourceNsxtVpcServiceProfileRead(d *schema.ResourceData, m interface{}) error { + connector := getPolicyConnector(m) + + id := d.Id() + if id == "" { + return fmt.Errorf("Error obtaining VpcServiceProfile ID") + } + + client := clientLayer.NewVpcServiceProfilesClient(connector) + parents := getVpcParentsFromContext(getSessionContext(d, m)) + obj, err := client.Get(parents[0], parents[1], id) + if err != nil { + return handleReadError(d, "VpcServiceProfile", id, err) + } + + setPolicyTagsInSchema(d, obj.Tags) + d.Set("nsx_id", id) + d.Set("display_name", obj.DisplayName) + d.Set("description", obj.Description) + d.Set("revision", obj.Revision) + d.Set("path", obj.Path) + + elem := reflect.ValueOf(&obj).Elem() + return metadata.StructToSchema(elem, d, vpcServiceProfileSchema, "", nil) +} + +func resourceNsxtVpcServiceProfileUpdate(d *schema.ResourceData, m interface{}) error { + + connector := getPolicyConnector(m) + + id := d.Id() + if id == "" { + return fmt.Errorf("Error obtaining VpcServiceProfile ID") + } + + parents := getVpcParentsFromContext(getSessionContext(d, m)) + description := d.Get("description").(string) + displayName := d.Get("display_name").(string) + tags := getPolicyTagsFromSchema(d) + + revision := int64(d.Get("revision").(int)) + + obj := model.VpcServiceProfile{ + DisplayName: &displayName, + Description: &description, + Tags: tags, + Revision: &revision, + } + + elem := reflect.ValueOf(&obj).Elem() + if err := metadata.SchemaToStruct(elem, d, vpcServiceProfileSchema, "", nil); err != nil { + return err + } + client := clientLayer.NewVpcServiceProfilesClient(connector) + _, err := client.Update(parents[0], parents[1], id, obj) + if err != nil { + return handleUpdateError("VpcServiceProfile", id, err) + } + + return resourceNsxtVpcServiceProfileRead(d, m) +} + +func resourceNsxtVpcServiceProfileDelete(d *schema.ResourceData, m interface{}) error { + id := d.Id() + if id == "" { + return fmt.Errorf("Error obtaining VpcServiceProfile ID") + } + + connector := getPolicyConnector(m) + parents := getVpcParentsFromContext(getSessionContext(d, m)) + + client := clientLayer.NewVpcServiceProfilesClient(connector) + err := client.Delete(parents[0], parents[1], id) + + if err != nil { + return handleDeleteError("VpcServiceProfile", id, err) + } + + return nil +} diff --git a/nsxt/resource_nsxt_vpc_service_profile_test.go b/nsxt/resource_nsxt_vpc_service_profile_test.go new file mode 100644 index 000000000..7adaf46f3 --- /dev/null +++ b/nsxt/resource_nsxt_vpc_service_profile_test.go @@ -0,0 +1,226 @@ +/* Copyright © 2024 Broadcom, Inc. All Rights Reserved. + SPDX-License-Identifier: MPL-2.0 */ + +package nsxt + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" +) + +var accTestPolicyVpcServiceProfileCreateAttributes = map[string]string{ + "display_name": getAccTestResourceName(), + "description": "terraform created", + "ntp_servers": "5.5.5.5", + "lease_time": "50840", + "mode": "DHCP_IP_ALLOCATION_BY_PORT", + "dns_server_ips": "7.7.7.7", + "server_addresses": "11.11.11.11", + "cache_size": "2048", + "log_level": "DEBUG", +} + +var accTestPolicyVpcServiceProfileUpdateAttributes = map[string]string{ + "display_name": getAccTestResourceName(), + "description": "terraform updated", + "ntp_servers": "5.5.5.7", + "lease_time": "148000", + "mode": "DHCP_IP_ALLOCATION_BY_MAC", + "dns_server_ips": "7.7.7.2", + "server_addresses": "11.11.11.111", + "cache_size": "1024", + "log_level": "INFO", +} + +func TestAccResourceNsxtVpcServiceProfile_basic(t *testing.T) { + testResourceName := "nsxt_vpc_service_profile.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t); testAccOnlyVPC(t) }, + Providers: testAccProviders, + CheckDestroy: func(state *terraform.State) error { + return testAccNsxtVpcServiceProfileCheckDestroy(state, accTestPolicyVpcServiceProfileUpdateAttributes["display_name"]) + }, + Steps: []resource.TestStep{ + { + Config: testAccNsxtVpcServiceProfileTemplate(true), + Check: resource.ComposeTestCheckFunc( + testAccNsxtVpcServiceProfileExists(accTestPolicyVpcServiceProfileCreateAttributes["display_name"], testResourceName), + resource.TestCheckResourceAttr(testResourceName, "display_name", accTestPolicyVpcServiceProfileCreateAttributes["display_name"]), + resource.TestCheckResourceAttr(testResourceName, "description", accTestPolicyVpcServiceProfileCreateAttributes["description"]), + resource.TestCheckResourceAttr(testResourceName, "dns_forwarder_config.#", "1"), + resource.TestCheckResourceAttr(testResourceName, "dhcp_config.0.ntp_servers.0", accTestPolicyVpcServiceProfileCreateAttributes["ntp_servers"]), + resource.TestCheckResourceAttr(testResourceName, "dhcp_config.0.dns_client_config.#", "1"), + resource.TestCheckResourceAttr(testResourceName, "dhcp_config.0.lease_time", accTestPolicyVpcServiceProfileCreateAttributes["lease_time"]), + resource.TestCheckResourceAttr(testResourceName, "dhcp_config.0.mode", accTestPolicyVpcServiceProfileCreateAttributes["mode"]), + resource.TestCheckResourceAttr(testResourceName, "dhcp_config.0.dhcp_relay_config.#", "0"), + resource.TestCheckResourceAttr(testResourceName, "dhcp_config.0.dns_client_config.0.dns_server_ips.0", accTestPolicyVpcServiceProfileCreateAttributes["dns_server_ips"]), + resource.TestCheckResourceAttr(testResourceName, "dns_forwarder_config.0.cache_size", accTestPolicyVpcServiceProfileCreateAttributes["cache_size"]), + resource.TestCheckResourceAttr(testResourceName, "dns_forwarder_config.0.log_level", accTestPolicyVpcServiceProfileCreateAttributes["log_level"]), + + resource.TestCheckResourceAttrSet(testResourceName, "nsx_id"), + resource.TestCheckResourceAttrSet(testResourceName, "path"), + resource.TestCheckResourceAttrSet(testResourceName, "revision"), + resource.TestCheckResourceAttr(testResourceName, "tag.#", "1"), + ), + }, + { + Config: testAccNsxtVpcServiceProfileTemplate(false), + Check: resource.ComposeTestCheckFunc( + testAccNsxtVpcServiceProfileExists(accTestPolicyVpcServiceProfileUpdateAttributes["display_name"], testResourceName), + resource.TestCheckResourceAttr(testResourceName, "display_name", accTestPolicyVpcServiceProfileUpdateAttributes["display_name"]), + resource.TestCheckResourceAttr(testResourceName, "description", accTestPolicyVpcServiceProfileUpdateAttributes["description"]), + resource.TestCheckResourceAttr(testResourceName, "dhcp_config.#", "1"), + resource.TestCheckResourceAttr(testResourceName, "dns_forwarder_config.#", "1"), + resource.TestCheckResourceAttr(testResourceName, "dhcp_config.0.ntp_servers.0", accTestPolicyVpcServiceProfileUpdateAttributes["ntp_servers"]), + resource.TestCheckResourceAttr(testResourceName, "dhcp_config.0.dns_client_config.#", "1"), + resource.TestCheckResourceAttr(testResourceName, "dhcp_config.0.lease_time", accTestPolicyVpcServiceProfileUpdateAttributes["lease_time"]), + resource.TestCheckResourceAttr(testResourceName, "dhcp_config.0.mode", accTestPolicyVpcServiceProfileUpdateAttributes["mode"]), + resource.TestCheckResourceAttr(testResourceName, "dhcp_config.0.dhcp_relay_config.#", "0"), + resource.TestCheckResourceAttr(testResourceName, "dhcp_config.0.dns_client_config.0.dns_server_ips.0", accTestPolicyVpcServiceProfileUpdateAttributes["dns_server_ips"]), + resource.TestCheckResourceAttr(testResourceName, "dns_forwarder_config.0.cache_size", accTestPolicyVpcServiceProfileUpdateAttributes["cache_size"]), + resource.TestCheckResourceAttr(testResourceName, "dns_forwarder_config.0.log_level", accTestPolicyVpcServiceProfileUpdateAttributes["log_level"]), + + resource.TestCheckResourceAttrSet(testResourceName, "nsx_id"), + resource.TestCheckResourceAttrSet(testResourceName, "path"), + resource.TestCheckResourceAttrSet(testResourceName, "revision"), + resource.TestCheckResourceAttr(testResourceName, "tag.#", "1"), + ), + }, + { + Config: testAccNsxtVpcServiceProfileMinimalistic(), + Check: resource.ComposeTestCheckFunc( + testAccNsxtVpcServiceProfileExists(accTestPolicyVpcServiceProfileCreateAttributes["display_name"], testResourceName), + resource.TestCheckResourceAttr(testResourceName, "description", ""), + resource.TestCheckResourceAttrSet(testResourceName, "nsx_id"), + resource.TestCheckResourceAttrSet(testResourceName, "path"), + resource.TestCheckResourceAttrSet(testResourceName, "revision"), + resource.TestCheckResourceAttr(testResourceName, "tag.#", "0"), + ), + }, + }, + }) +} + +func TestAccResourceNsxtVpcServiceProfile_importBasic(t *testing.T) { + name := getAccTestResourceName() + testResourceName := "nsxt_vpc_service_profile.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t); testAccOnlyVPC(t) }, + Providers: testAccProviders, + CheckDestroy: func(state *terraform.State) error { + return testAccNsxtVpcServiceProfileCheckDestroy(state, name) + }, + Steps: []resource.TestStep{ + { + Config: testAccNsxtVpcServiceProfileMinimalistic(), + }, + { + ResourceName: testResourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateIdFunc: testAccResourceNsxtPolicyImportIDRetriever(testResourceName), + }, + }, + }) +} + +func testAccNsxtVpcServiceProfileExists(displayName string, resourceName string) resource.TestCheckFunc { + return func(state *terraform.State) error { + + connector := getPolicyConnector(testAccProvider.Meta().(nsxtClients)) + + rs, ok := state.RootModule().Resources[resourceName] + if !ok { + return fmt.Errorf("Policy VpcServiceProfile resource %s not found in resources", resourceName) + } + + resourceID := rs.Primary.ID + if resourceID == "" { + return fmt.Errorf("Policy VpcServiceProfile resource ID not set in resources") + } + + exists, err := resourceNsxtVpcServiceProfileExists(testAccGetSessionProjectContext(), resourceID, connector) + if err != nil { + return err + } + if !exists { + return fmt.Errorf("Policy VpcServiceProfile %s does not exist", resourceID) + } + + return nil + } +} + +func testAccNsxtVpcServiceProfileCheckDestroy(state *terraform.State, displayName string) error { + connector := getPolicyConnector(testAccProvider.Meta().(nsxtClients)) + for _, rs := range state.RootModule().Resources { + + if rs.Type != "nsxt_vpc_service_profile" { + continue + } + + resourceID := rs.Primary.Attributes["id"] + exists, err := resourceNsxtVpcServiceProfileExists(testAccGetSessionProjectContext(), resourceID, connector) + if err == nil { + return err + } + + if exists { + return fmt.Errorf("Policy VpcServiceProfile %s still exists", displayName) + } + } + return nil +} + +func testAccNsxtVpcServiceProfileTemplate(createFlow bool) string { + var attrMap map[string]string + if createFlow { + attrMap = accTestPolicyVpcServiceProfileCreateAttributes + } else { + attrMap = accTestPolicyVpcServiceProfileUpdateAttributes + } + return fmt.Sprintf(` +resource "nsxt_vpc_service_profile" "test" { + %s + display_name = "%s" + description = "%s" + + dhcp_config { + ntp_servers = ["%s"] + + lease_time = %s + mode = "%s" + + dns_client_config { + dns_server_ips = ["%s"] + } + } + + dns_forwarder_config { + cache_size = %s + log_level = "%s" + } + + tag { + scope = "scope1" + tag = "tag1" + } +}`, testAccNsxtProjectContext(), attrMap["display_name"], attrMap["description"], attrMap["ntp_servers"], attrMap["lease_time"], attrMap["mode"], attrMap["dns_server_ips"], attrMap["cache_size"], attrMap["log_level"]) +} + +func testAccNsxtVpcServiceProfileMinimalistic() string { + return fmt.Sprintf(` +resource "nsxt_vpc_service_profile" "test" { + %s + display_name = "%s" + + dhcp_config { + mode = "%s" + } +}`, testAccNsxtProjectContext(), accTestPolicyVpcServiceProfileUpdateAttributes["display_name"], accTestPolicyVpcServiceProfileUpdateAttributes["mode"]) +} diff --git a/nsxt/utils_test.go b/nsxt/utils_test.go index 5683c43b9..1614cc8b0 100644 --- a/nsxt/utils_test.go +++ b/nsxt/utils_test.go @@ -262,6 +262,13 @@ func testAccGetSessionContext() tf_api.SessionContext { return tf_api.SessionContext{ProjectID: projectID, ClientType: clientType, VPCID: vpcID} } +func testAccGetSessionProjectContext() tf_api.SessionContext { + clientType := testAccIsGlobalManager2() + projectID := os.Getenv("NSXT_PROJECT_ID") + vpcID := "" + return tf_api.SessionContext{ProjectID: projectID, ClientType: clientType, VPCID: vpcID} +} + func testAccGetProjectContext() tf_api.SessionContext { projectID := os.Getenv("NSXT_PROJECT_ID") return tf_api.SessionContext{ProjectID: projectID, ClientType: tf_api.Multitenancy} diff --git a/website/docs/r/vpc_service_profile.html.markdown b/website/docs/r/vpc_service_profile.html.markdown new file mode 100644 index 000000000..06b326126 --- /dev/null +++ b/website/docs/r/vpc_service_profile.html.markdown @@ -0,0 +1,91 @@ +--- +subcategory: "VPC" +layout: "nsxt" +page_title: "NSXT: nsxt_policy_service_profile" +description: A resource to configure a VPC Service Profile. +--- + +# nsxt_policy_service_profile + +This resource provides a method for the management of a VPC Service Profile. + +This resource is applicable to NSX Policy Manager. + +## Example Usage + +```hcl +resource "nsxt_policy_service_profile" "vpc1_service_profile" { + display_name = "vpc1" + description = "Terraform provisioned Vpc Service Profile" + + mac_discovery_profile = nsxt_policy_mac_discovery_profile.for_vpc1.path + spoof_guard_profile = nsxt_policy_spoof_guard_profile.for_vpc1.path + ip_discovery_profile = nsxt_policy_ip_discovery_profile.for_vpc1.path + qos_profile = nsxt_policy_qos_profile.for_vpc1.path + + dhcp_config { + ntp_servers = ["20.2.60.5"] + + lease_time = 50840 + mode = "DHCP_IP_ALLOCATION_BY_PORT" + + dns_client_config { + dns_server_ips = ["10.204.2.20"] + } + } + + dns_forwarder_config { + cache_size = 1024 + log_level = "WARNING" + } +} +``` + +## Argument Reference + +The following arguments are supported: + +* `display_name` - (Required) Display name of the resource. +* `description` - (Optional) Description of the resource. +* `tag` - (Optional) A list of scope + tag pairs to associate with this resource. +* `nsx_id` - (Optional) The NSX ID of this resource. If set, this ID will be used to create the resource. +* `mac_discovery_profile` - (Optional) Policy path for Mac Discovery Profile +* `spoof_guard_profile` - (Optional) Policy path for Spoof Guard Profile +* `ip_discovery_profile` - (Optional) Policy path for IP Discovery Profile +* `security_profile` - (Optional) Policy path for Security Profile +* `qos_profile` - (Optional) Policy path for QoS profile +* `dhcp_config` - (Required) DHCP configuration for this profile + * `ntp_servers` - (Optional) List of NTP servers + * `dns_client_config` - (Optional) DNS Client configuration + * `dns_server_ips` - (Optional) List of IP addresses of the DNS servers which need to be configured on the workload VMs + * `lease_time` - (Optional) DHCP lease time in seconds. + + * `mode` - (Optional) DHCP mode of the VPC Profile DHCP Config. Possible values are `DHCP_IP_ALLOCATION_BY_PORT`, `DHCP_IP_ALLOCATION_BY_MAC`, `DHCP_RELAY`, `DHCP_DEACTIVATED`. Default is `DHCP_IP_ALLOCATION_BY_PORT`. + * `dhcp_relay_config` - (Optional) DHCP Relay configuration + * `server_addresses` - (Optional) List of DHCP server IP addresses for DHCP relay configuration. Both IPv4 and IPv6 addresses are supported. +* `dns_forwarder_config` - (Optional) DNS Forwarder configuration + * `cache_size` - (Optional) Cache size in KB + * `log_level` - (Optional) Log level of the DNS forwarder. Possible values: `DEBUG`, `INFO`, `WARNING`, `ERROR`, `FATAL` + * `conditional_forwarder_zone_paths` - (Optional) Path of conditional DNS zones + * `default_forwarder_zone_path` - (Optional) Path of the default DNS zone + + +## Attributes Reference + +In addition to arguments listed above, the following attributes are exported: + +* `id` - ID of the resource. +* `revision` - Indicates current revision number of the object as seen by NSX-T API server. This attribute can be useful for debugging. +* `path` - The NSX path of the policy resource. + +## Importing + +An existing object can be [imported][docs-import] into this resource, via the following command: + +[docs-import]: https://www.terraform.io/cli/import + +``` +terraform import nsxt_policy_service_profile.test UUID +``` + +The above command imports VpcServiceProfile named `test` with the NSX ID `UUID`.