From 6aa30673afbde5ec692f6eb20097b0a92f51d922 Mon Sep 17 00:00:00 2001 From: Jared Burns Date: Thu, 22 Aug 2024 09:52:51 -0400 Subject: [PATCH] feat: add name option to `d/domain` (#228) Updated `d/vcf_domain` to support `name` alongside the existing `domain_id`. Signed-off-by: Jared Burns Co-authored-by: Ryan Johnson --- docs/data-sources/domain.md | 57 ++++++------ examples/data-sources/domain/variables.tf | 25 +++--- examples/data-sources/domain/vcf_domain.tf | 8 +- internal/constants/constants.go | 4 + internal/provider/data_source_domain.go | 68 +++++++++++--- internal/provider/data_source_domain_test.go | 94 ++++++++++++-------- 6 files changed, 166 insertions(+), 90 deletions(-) diff --git a/docs/data-sources/domain.md b/docs/data-sources/domain.md index 1aabfe9..51459ae 100644 --- a/docs/data-sources/domain.md +++ b/docs/data-sources/domain.md @@ -3,47 +3,45 @@ page_title: "vcf_domain Data Source - terraform-provider-vcf" subcategory: "" description: |- - + --- # vcf_domain (Data Source) -A workload domain is a policy based resource container with specific availability and performance attributes that combines compute (vSphere), -storage (vSAN/NFS/VMFS on FC/VVOL) and networking (NSX) into a single consumable entity. +A workload domain is a policy based resource container with specific availability and performance +attributes that combines compute (vSphere), storage (vSAN/NFS/VMFS on FC/VVOL) and networking (NSX) +into a single consumable entity. ## Schema -### Required - -- `domain_id` (String) The ID of the Domain to be used as data source - -### Optional +- `domain_id` (String) The ID of the workload domain. +- `name` (String) The name of the workload domain. - `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts)) ### Read-Only -- `cluster` (List of Object) Specification representing the clusters in the workload domain (see [below for nested schema](#nestedatt--cluster)) +- `cluster` (List of Object) The cluster references associated with the workload domain (see [below for nested schema](#nestedatt--cluster)) - `id` (String) The ID of this resource. -- `is_management_sso_domain` (Boolean) Shows whether the domain is joined to the management domain SSO -- `name` (String) Name of the domain -- `nsx_configuration` (List of Object) Represents NSX Manager cluster references associated with the domain (see [below for nested schema](#nestedatt--nsx_configuration)) -- `sso_id` (String) ID of the SSO domain associated with the workload domain -- `sso_name` (String) Name of the SSO domain associated with the workload domain -- `status` (String) Status of the workload domain -- `type` (String) Type of the workload domain -- `vcenter_configuration` (List of Object) Specification describing vCenter Server instance settings (see [below for nested schema](#nestedatt--vcenter_configuration)) +- `is_management_sso_domain` (Boolean) Indicates if the workload domain is joined to the management domain's SSO domain. +- `nsx_configuration` (List of Object) The NSX Manager cluster references associated with the workload domain. (see [below for nested schema](#nestedatt--nsx_configuration)) +- `sso_id` (String) The ID of the SSO domain associated with the workload domain. +- `sso_name` (String) The name of the SSO domain associated with the workload domain. +- `status` (String) The status of the workload domain. +- `type` (String) The type of workload domain. +- `vcenter_configuration` (List of Object) The vCenter Server instance references associated with the workload domain. (see [below for nested schema](#nestedatt--vcenter_configuration)) + ### Nested Schema for `timeouts` Optional: - `read` (String) - + ### Nested Schema for `cluster` Read-Only: @@ -67,6 +65,7 @@ Read-Only: - `vvol_datastores` (List of Object) Cluster storage configuration for VVOL (see [below for nested schema](#nestedobjatt--cluster--vvol_datastores)) + ### Nested Schema for `cluster.host` Read-Only: @@ -83,6 +82,7 @@ Read-Only: - `vmnic` (List of Object) vmnic configuration for the ESXi host (see [below for nested schema](#nestedobjatt--cluster--host--vmnic)) + ### Nested Schema for `cluster.host.vmnic` Read-Only: @@ -91,9 +91,8 @@ Read-Only: - `uplink` (String) Uplink associated with vmnic - `vds_name` (String) Name of the VDS associated with the ESXi host - - + ### Nested Schema for `cluster.nfs_datastores` Read-Only: @@ -104,8 +103,8 @@ Read-Only: - `server_name` (String) Fully qualified domain name or IP address of the NFS endpoint - `user_tag` (String) User tag used to annotate NFS share - + ### Nested Schema for `cluster.vds` Read-Only: @@ -116,6 +115,7 @@ Read-Only: - `portgroup` (List of Object) List of portgroups associated with the vSphere Distributed Switch (see [below for nested schema](#nestedobjatt--cluster--vds--portgroup)) + ### Nested Schema for `cluster.vds.nioc_bandwidth_allocations` Read-Only: @@ -126,8 +126,8 @@ Read-Only: - `shares_level` (String) The allocation level. The level is a simplified view of shares. Levels map to a pre-determined set of numeric values for shares. - `type` (String) Host infrastructure traffic type. - + ### Nested Schema for `cluster.vds.portgroup` Read-Only: @@ -136,17 +136,16 @@ Read-Only: - `active_uplinks` (List of String) List of active uplinks associated with portgroup. - `transport_type` (String) Port group transport type - - + ### Nested Schema for `cluster.vmfs_datastore` Read-Only: - `datastore_names` (List of String) VMFS datastore names used for VMFS on FC for cluster creation - + ### Nested Schema for `cluster.vsan_datastore` Read-Only: @@ -156,16 +155,16 @@ Read-Only: - `failures_to_tolerate` (Number) Number of ESXi host failures to tolerate in the vSAN cluster - `license_key` (String) vSAN license key used - + ### Nested Schema for `cluster.vsan_remote_datastore_cluster` Read-Only: - `datastore_uuids` (List of String) vSAN HCI Mesh remote datastore UUIDs - + ### Nested Schema for `cluster.vvol_datastores` Read-Only: @@ -184,6 +183,7 @@ Read-Only: - `vip_fqdn` (String) Fully qualified domain name of the NSX Manager cluster VIP + ### Nested Schema for `nsx_configuration.nsx_manager_node` Read-Only: @@ -192,9 +192,8 @@ Read-Only: - `ip_address` (String) IPv4 address of the NSX Manager appliance - `name` (String) Name of the NSX Manager appliance, e.g., sfo-w01-nsx01 - - + ### Nested Schema for `vcenter_configuration` Read-Only: diff --git a/examples/data-sources/domain/variables.tf b/examples/data-sources/domain/variables.tf index b2a8c03..83b64ca 100644 --- a/examples/data-sources/domain/variables.tf +++ b/examples/data-sources/domain/variables.tf @@ -1,19 +1,22 @@ +variable "sddc_manager_host" { + description = "The fully qualified domain name of the SDDC Manager instance." +} + variable "sddc_manager_username" { - description = "Username used to authenticate against an SDDC Manager instance" - default = "" + description = "The username to authenticate to the SDDC Manager instance." + sensitive = true } variable "sddc_manager_password" { - description = "Password used to authenticate against an SDDC Manager instance" - default = "" + description = "The password to authenticate to the SDDC Manager instance." + sensitive = true } -variable "sddc_manager_host" { - description = "Fully qualified domain name of an SDDC Manager instance" - default = "" +variable "domain_id" { + description = "The ID of the workload domain." } -variable "vcf_domain_id" { - description = "Id of the domain that is to be used as a data source. Note: management domain ID can be used to refer to some of it's attributes" - default = "" -} \ No newline at end of file +variable "domain_name" { + description = "The name of the workload domain." + name = "sfo-w01" +} diff --git a/examples/data-sources/domain/vcf_domain.tf b/examples/data-sources/domain/vcf_domain.tf index dce1620..6fe69da 100644 --- a/examples/data-sources/domain/vcf_domain.tf +++ b/examples/data-sources/domain/vcf_domain.tf @@ -12,6 +12,10 @@ provider "vcf" { sddc_manager_host = var.sddc_manager_host } -data "vcf_domain" "domain1" { - domain_id = var.vcf_domain_id +data "vcf_domain" "sfo-m01" { + domain_id = var.domain_id +} + +data "vcf_domain" "sfo-w01" { + name = var.domain_name } \ No newline at end of file diff --git a/internal/constants/constants.go b/internal/constants/constants.go index 45c7a2b..1d83268 100644 --- a/internal/constants/constants.go +++ b/internal/constants/constants.go @@ -119,6 +119,10 @@ const ( // Typically, the id of management domain is used as it is already created during bringup. VcfTestDomainDataSourceId = "VCF_DOMAIN_DATA_SOURCE_ID" + // VcfTestDomainDataSourceName name of a workload domain used in workload domain data source acceptance test. + // Typically, the name of management domain is used as it is already created during bringup. + VcfTestDomainDataSourceName = "VCF_DOMAIN_DATA_SOURCE_NAME" + // VcfTestClusterDataSourceId id of cluster used in cluster data source acceptance test. // Typically, the id of the default cluster in the management domain is used as it is // already created during bringup. diff --git a/internal/provider/data_source_domain.go b/internal/provider/data_source_domain.go index 4063725..0595c98 100644 --- a/internal/provider/data_source_domain.go +++ b/internal/provider/data_source_domain.go @@ -6,13 +6,19 @@ package provider import ( "context" + "errors" + "fmt" "time" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" + "github.com/vmware/vcf-sdk-go/client" + "github.com/vmware/vcf-sdk-go/client/domains" + "github.com/vmware/vcf-sdk-go/models" "github.com/vmware/terraform-provider-vcf/internal/api_client" + "github.com/vmware/terraform-provider-vcf/internal/constants" "github.com/vmware/terraform-provider-vcf/internal/domain" "github.com/vmware/terraform-provider-vcf/internal/network" "github.com/vmware/terraform-provider-vcf/internal/vcenter" @@ -27,57 +33,57 @@ func DataSourceDomain() *schema.Resource { Schema: map[string]*schema.Schema{ "domain_id": { Type: schema.TypeString, - Required: true, ValidateFunc: validation.NoZeroValues, - Description: "The ID of the Domain to be used as data source", + Optional: true, + Description: "The ID of the workload domain.", }, "name": { Type: schema.TypeString, - Computed: true, - Description: "Name of the domain", + Optional: true, + Description: "The name of the workload domain.", }, "cluster": { Type: schema.TypeList, Computed: true, - Description: "Specification representing the clusters in the workload domain", + Description: "The cluster references associated with the workload domain", Elem: clusterSubresourceSchema(), }, "nsx_configuration": { Type: schema.TypeList, Computed: true, - Description: "Represents NSX Manager cluster references associated with the domain", + Description: "The NSX Manager cluster references associated with the workload domain.", Elem: network.NsxSchema(), }, "vcenter_configuration": { Type: schema.TypeList, Computed: true, - Description: "Specification describing vCenter Server instance settings", + Description: "The vCenter Server instance references associated with the workload domain.", Elem: vcenter.VCSubresourceSchema(), }, "status": { Type: schema.TypeString, Computed: true, - Description: "Status of the workload domain", + Description: "The status of the workload domain.", }, "type": { Type: schema.TypeString, Computed: true, - Description: "Type of the workload domain", + Description: "The type of workload domain.", }, "sso_id": { Type: schema.TypeString, Computed: true, - Description: "ID of the SSO domain associated with the workload domain", + Description: "The ID of the SSO domain associated with the workload domain.", }, "sso_name": { Type: schema.TypeString, Computed: true, - Description: "Name of the SSO domain associated with the workload domain", + Description: "The name of the SSO domain associated with the workload domain.", }, "is_management_sso_domain": { Type: schema.TypeBool, Computed: true, - Description: "Shows whether the domain is joined to the management domain SSO", + Description: "Indicates if the workload domain is joined to the management domain's SSO domain.", }, }, } @@ -85,11 +91,49 @@ func DataSourceDomain() *schema.Resource { func dataSourceDomainRead(ctx context.Context, data *schema.ResourceData, meta interface{}) diag.Diagnostics { apiClient := meta.(*api_client.SddcManagerClient).ApiClient + domainId := data.Get("domain_id").(string) + domainName := data.Get("name").(string) + + if domainId == "" { + if domainName == "" { + return diag.Errorf("either 'domain_id' or 'name' must be provided") + } + + domainInfo, err := getDomainByName(ctx, apiClient, domainName) + if err != nil { + return diag.FromErr(err) + } + domainId = domainInfo.ID + } _, err := domain.ImportDomain(ctx, data, apiClient, domainId, true) if err != nil { return diag.FromErr(err) } + return nil } + +func getDomainByName(ctx context.Context, apiClient *client.VcfClient, name string) (*models.Domain, error) { + params := domains.NewGetDomainsParamsWithContext(ctx). + WithTimeout(constants.DefaultVcfApiCallTimeout) + + domainsResponse, err := apiClient.Domains.GetDomains(params) + if err != nil { + return nil, err + } + + if domainsResponse.Payload == nil { + return nil, errors.New("no domains found") + } + + for _, domainElement := range domainsResponse.Payload.Elements { + domain := *domainElement + if domain.Name == name { + return &domain, nil + } + } + + return nil, fmt.Errorf("domain name '%s' not found", name) +} diff --git a/internal/provider/data_source_domain_test.go b/internal/provider/data_source_domain_test.go index 629fc4f..324dad9 100644 --- a/internal/provider/data_source_domain_test.go +++ b/internal/provider/data_source_domain_test.go @@ -14,46 +14,68 @@ import ( "github.com/vmware/terraform-provider-vcf/internal/constants" ) -func TestAccDataSourceVcfDomain(t *testing.T) { +func testAccVcfDomainDataSourceSteps(config string) []resource.TestStep { + return []resource.TestStep{ + { + Config: config, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("data.vcf_domain.domain1", "vcenter_configuration.0.id"), + resource.TestCheckResourceAttrSet("data.vcf_domain.domain1", "vcenter_configuration.0.fqdn"), + resource.TestCheckResourceAttrSet("data.vcf_domain.domain1", "status"), + resource.TestCheckResourceAttrSet("data.vcf_domain.domain1", "type"), + resource.TestCheckResourceAttrSet("data.vcf_domain.domain1", "sso_id"), + resource.TestCheckResourceAttrSet("data.vcf_domain.domain1", "sso_name"), + resource.TestCheckResourceAttrSet("data.vcf_domain.domain1", "cluster.0.id"), + resource.TestCheckResourceAttrSet("data.vcf_domain.domain1", "cluster.0.name"), + resource.TestCheckResourceAttrSet("data.vcf_domain.domain1", "cluster.0.primary_datastore_name"), + resource.TestCheckResourceAttrSet("data.vcf_domain.domain1", "cluster.0.primary_datastore_type"), + resource.TestCheckResourceAttrSet("data.vcf_domain.domain1", "cluster.0.is_default"), + resource.TestCheckResourceAttrSet("data.vcf_domain.domain1", "cluster.0.is_stretched"), + resource.TestCheckResourceAttrSet("data.vcf_domain.domain1", "cluster.0.host.0.id"), + resource.TestCheckResourceAttrSet("data.vcf_domain.domain1", "cluster.0.host.1.id"), + resource.TestCheckResourceAttrSet("data.vcf_domain.domain1", "cluster.0.host.2.id"), + resource.TestCheckResourceAttrSet("data.vcf_domain.domain1", "cluster.0.host.3.id"), + resource.TestCheckResourceAttrSet("data.vcf_domain.domain1", "nsx_configuration.0.id"), + resource.TestCheckResourceAttrSet("data.vcf_domain.domain1", "nsx_configuration.0.vip"), + resource.TestCheckResourceAttrSet("data.vcf_domain.domain1", "nsx_configuration.0.vip_fqdn"), + resource.TestCheckResourceAttrSet("data.vcf_domain.domain1", "nsx_configuration.0.nsx_manager_node.0.name"), + resource.TestCheckResourceAttrSet("data.vcf_domain.domain1", "nsx_configuration.0.nsx_manager_node.0.ip_address"), + resource.TestCheckResourceAttrSet("data.vcf_domain.domain1", "nsx_configuration.0.nsx_manager_node.0.fqdn"), + ), + }, + } +} + +func testAccVcfDomainDataSourceConfigById(domainId string) string { + return fmt.Sprintf(` + data "vcf_domain" "domain1" { + domain_id = %q + }`, domainId) +} + +func testAccVcfDomainDataSourceConfigByName(name string) string { + return fmt.Sprintf(` + data "vcf_domain" "domain1" { + name = %q + }`, name) +} + +func TestAccDataSourceVcfDomainById(t *testing.T) { + config := testAccVcfDomainDataSourceConfigById(os.Getenv(constants.VcfTestDomainDataSourceId)) + resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, ProviderFactories: providerFactories, - Steps: []resource.TestStep{ - { - Config: testAccVcfDomainDataSourceConfig( - os.Getenv(constants.VcfTestDomainDataSourceId)), - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttrSet("data.vcf_domain.domain1", "vcenter_configuration.0.id"), - resource.TestCheckResourceAttrSet("data.vcf_domain.domain1", "vcenter_configuration.0.fqdn"), - resource.TestCheckResourceAttrSet("data.vcf_domain.domain1", "status"), - resource.TestCheckResourceAttrSet("data.vcf_domain.domain1", "type"), - resource.TestCheckResourceAttrSet("data.vcf_domain.domain1", "sso_id"), - resource.TestCheckResourceAttrSet("data.vcf_domain.domain1", "sso_name"), - resource.TestCheckResourceAttrSet("data.vcf_domain.domain1", "cluster.0.id"), - resource.TestCheckResourceAttrSet("data.vcf_domain.domain1", "cluster.0.name"), - resource.TestCheckResourceAttrSet("data.vcf_domain.domain1", "cluster.0.primary_datastore_name"), - resource.TestCheckResourceAttrSet("data.vcf_domain.domain1", "cluster.0.primary_datastore_type"), - resource.TestCheckResourceAttrSet("data.vcf_domain.domain1", "cluster.0.is_default"), - resource.TestCheckResourceAttrSet("data.vcf_domain.domain1", "cluster.0.is_stretched"), - resource.TestCheckResourceAttrSet("data.vcf_domain.domain1", "cluster.0.host.0.id"), - resource.TestCheckResourceAttrSet("data.vcf_domain.domain1", "cluster.0.host.1.id"), - resource.TestCheckResourceAttrSet("data.vcf_domain.domain1", "cluster.0.host.2.id"), - resource.TestCheckResourceAttrSet("data.vcf_domain.domain1", "cluster.0.host.3.id"), - resource.TestCheckResourceAttrSet("data.vcf_domain.domain1", "nsx_configuration.0.id"), - resource.TestCheckResourceAttrSet("data.vcf_domain.domain1", "nsx_configuration.0.vip"), - resource.TestCheckResourceAttrSet("data.vcf_domain.domain1", "nsx_configuration.0.vip_fqdn"), - resource.TestCheckResourceAttrSet("data.vcf_domain.domain1", "nsx_configuration.0.nsx_manager_node.0.name"), - resource.TestCheckResourceAttrSet("data.vcf_domain.domain1", "nsx_configuration.0.nsx_manager_node.0.ip_address"), - resource.TestCheckResourceAttrSet("data.vcf_domain.domain1", "nsx_configuration.0.nsx_manager_node.0.fqdn"), - ), - }, - }, + Steps: testAccVcfDomainDataSourceSteps(config), }) } -func testAccVcfDomainDataSourceConfig(domainId string) string { - return fmt.Sprintf(` - data "vcf_domain" "domain1" { - domain_id = %q - }`, domainId) +func TestAccDataSourceVcfDomainByName(t *testing.T) { + config := testAccVcfDomainDataSourceConfigByName(os.Getenv(constants.VcfTestDomainDataSourceName)) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProviderFactories: providerFactories, + Steps: testAccVcfDomainDataSourceSteps(config), + }) }