Skip to content

Commit

Permalink
fix: missing vds info with r/cluster import
Browse files Browse the repository at this point in the history
Updating Cluster import to solve issues where vds is blank on data source.

Signed-off-by: Jared Burns <jared.burns@broadcom.com>
  • Loading branch information
burnsjared0415 authored and tenthirtyam committed Dec 5, 2024
1 parent facc44a commit 2963fc2
Show file tree
Hide file tree
Showing 6 changed files with 133 additions and 52 deletions.
100 changes: 70 additions & 30 deletions internal/cluster/cluster_operations.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ import (

"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/vmware/terraform-provider-vcf/internal/api_client"
"github.com/vmware/vcf-sdk-go/vcf"

"github.com/vmware/terraform-provider-vcf/internal/api_client"
"github.com/vmware/terraform-provider-vcf/internal/datastores"
"github.com/vmware/terraform-provider-vcf/internal/network"
"github.com/vmware/terraform-provider-vcf/internal/resource_utils"
Expand Down Expand Up @@ -370,19 +370,19 @@ func FlattenCluster(ctx context.Context, clusterObj *vcf.Cluster, apiClient *vcf
result["is_default"] = clusterObj.IsDefault
result["is_stretched"] = clusterObj.IsStretched

if clusterObj.VdsSpecs != nil {
flattenedVdsSpecs := getFlattenedVdsSpecsForRefs(*clusterObj.VdsSpecs)
result["vds"] = flattenedVdsSpecs
flattenedVdsSpecs, err := getFlattenedVdsSpecsForRefs(ctx, *clusterObj.Id, apiClient)
if err != nil {
return nil, fmt.Errorf("failed to get flattened VDS specs: %w", err)
}
result["vds"] = flattenedVdsSpecs

if clusterObj.Hosts != nil {
flattenedHostSpecs, err := getFlattenedHostSpecsForRefs(ctx, *clusterObj.Hosts, apiClient)
if err != nil {
return nil, err
}
result["host"] = flattenedHostSpecs
flattenedHostSpecs, err := getFlattenedHostSpecsForRefs(ctx, *clusterObj.Hosts, apiClient)
if err != nil {
return nil, err
}

result["host"] = flattenedHostSpecs

return &result, nil
}

Expand All @@ -404,18 +404,17 @@ func ImportCluster(ctx context.Context, data *schema.ResourceData, apiClient *vc
_ = data.Set("primary_datastore_type", clusterObj.PrimaryDatastoreType)
_ = data.Set("is_default", clusterObj.IsDefault)
_ = data.Set("is_stretched", clusterObj.IsStretched)
if clusterObj.VdsSpecs != nil {
flattenedVdsSpecs := getFlattenedVdsSpecsForRefs(*clusterObj.VdsSpecs)
_ = data.Set("vds", flattenedVdsSpecs)
flattenedVdsSpecs, err := getFlattenedVdsSpecsForRefs(ctx, *clusterObj.Id, apiClient)
if err != nil {
return nil, err
}
_ = data.Set("vds", flattenedVdsSpecs)

if clusterObj.Hosts != nil {
flattenedHostSpecs, err := getFlattenedHostSpecsForRefs(ctx, *clusterObj.Hosts, apiClient)
if err != nil {
return nil, err
}
_ = data.Set("host", flattenedHostSpecs)
flattenedHostSpecs, err := getFlattenedHostSpecsForRefs(ctx, *clusterObj.Hosts, apiClient)
if err != nil {
return nil, err
}
_ = data.Set("host", flattenedHostSpecs)

// get all domains and find our cluster to set the "domain_id" attribute, because
// cluster API doesn't provide parent domain ID.
Expand Down Expand Up @@ -462,20 +461,61 @@ func getFlattenedHostSpecsForRefs(ctx context.Context, hostRefs []vcf.HostRefere
api_client.LogError(vcfErr)
return nil, errors.New(*vcfErr.Message)
}
flattenedHostSpecs = append(flattenedHostSpecs, *FlattenHost(*hostObj))
flattenedHostSpecs = append(flattenedHostSpecs, FlattenHost(*hostObj))
}
return flattenedHostSpecs, nil
}

func getFlattenedVdsSpecsForRefs(vdsSpecs []vcf.VdsSpec) []map[string]interface{} {
flattenedVdsSpecs := *new([]map[string]interface{})
// Since backend API returns objects in random order sort VDSSpec list to ensure
// import is reproducible
sort.SliceStable(vdsSpecs, func(i, j int) bool {
return vdsSpecs[i].Name < vdsSpecs[j].Name
})
for _, vdsSpec := range vdsSpecs {
flattenedVdsSpecs = append(flattenedVdsSpecs, network.FlattenVdsSpec(vdsSpec))
func getFlattenedVdsSpecsForRefs(ctx context.Context, clusterId string, apiClient *vcf.ClientWithResponses) ([]map[string]interface{}, error) {
vdsResponse, err := apiClient.GetVdsesWithResponse(ctx, clusterId)
if err != nil {
return nil, err
}
return flattenedVdsSpecs

if vdsResponse.JSON200 == nil {
return nil, fmt.Errorf("vdsResponse.JSON200 is nil")
}

flattenedVdsSpecs := make([]map[string]interface{}, len(*vdsResponse.JSON200))
for i, vds := range *vdsResponse.JSON200 {
portGroups := vds.PortGroups
portGroupSpecs := make([]vcf.PortgroupSpec, len(*portGroups))
for j, pg := range *portGroups {
portGroupSpecs[j] = vcf.PortgroupSpec{
Name: pg.Name,
TransportType: pg.TransportType,
ActiveUplinks: pg.ActiveUplinks,
}
}

niocBandwidthAllocations := vds.NiocBandwidthAllocations
niocSpecs := make([]vcf.NiocBandwidthAllocationSpec, len(*niocBandwidthAllocations))
for k, nioc := range *niocBandwidthAllocations {
niocType := ""
if nioc.Type != nil {
niocType = *nioc.Type
}

niocSpecs[k] = vcf.NiocBandwidthAllocationSpec{
Type: niocType,
NiocTrafficResourceAllocation: vcf.NiocTrafficResourceAllocation{
SharesInfo: &vcf.SharesInfo{
Shares: nioc.NiocTrafficResourceAllocation.SharesInfo.Shares,
Level: nioc.NiocTrafficResourceAllocation.SharesInfo.Level,
},
},
}
}

vdsSpec := vcf.VdsSpec{
Name: vds.Name,
IsUsedByNsxt: vds.IsUsedByNsxt,
PortGroupSpecs: &portGroupSpecs,
NiocBandwidthAllocationSpecs: &niocSpecs,
}

flattenedVdsSpecs[i] = network.FlattenVdsSpec(&vdsSpec)
}

return flattenedVdsSpecs, nil
}
39 changes: 33 additions & 6 deletions internal/cluster/host_spec_subresource.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,22 +82,49 @@ func HostSpecSchema() *schema.Resource {
Type: schema.TypeList,
Optional: true,
Description: "vmnic configuration for the ESXi host",
Elem: network.VMNicSchema(),
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
Description: "Name of the physical NIC",
},
"mac_address": {
Type: schema.TypeString,
Required: true,
Description: "MAC address of the physical NIC",
},
},
},
},
},
}
}

func FlattenHost(host vcf.Host) *map[string]interface{} {
func FlattenHost(host vcf.Host) map[string]interface{} {
result := make(map[string]interface{})
result["id"] = host.Id
result["host_name"] = host.Fqdn
ipAddresses := *host.IpAddresses
if len(ipAddresses) > 0 {
result["ip_address"] = ipAddresses[0].IpAddress

if host.IpAddresses != nil {
ipAddresses := *host.IpAddresses
if len(ipAddresses) > 0 {
result["ip_address"] = ipAddresses[0].IpAddress
}
}

if host.PhysicalNics != nil {
var physicalNics []map[string]interface{}
for _, nic := range *host.PhysicalNics {
nicMap := make(map[string]interface{})
nicMap["name"] = nic.DeviceName
nicMap["mac_address"] = nic.MacAddress
physicalNics = append(physicalNics, nicMap)
}
result["vmnic"] = physicalNics
}

return &result
return result
}

func TryConvertToHostSpec(object map[string]interface{}) (*vcf.HostSpec, error) {
Expand Down
10 changes: 6 additions & 4 deletions internal/network/nioc_bandwidth_allocation_subresource.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,11 +109,13 @@ func tryConvertToNiocBandwidthAllocationSpec(object map[string]interface{}) (*vc

func flattenNiocBandwidthAllocationSpec(spec vcf.NiocBandwidthAllocationSpec) map[string]interface{} {
result := make(map[string]interface{})

result["type"] = spec.Type
result["limit"] = *spec.NiocTrafficResourceAllocation.Limit
result["reservation"] = *spec.NiocTrafficResourceAllocation.Reservation
result["shares"] = spec.NiocTrafficResourceAllocation.SharesInfo.Shares
result["shares_level"] = spec.NiocTrafficResourceAllocation.SharesInfo.Level

if spec.NiocTrafficResourceAllocation.SharesInfo != nil {
result["shares"] = spec.NiocTrafficResourceAllocation.SharesInfo.Shares
result["shares_level"] = spec.NiocTrafficResourceAllocation.SharesInfo.Level
}

return result
}
31 changes: 19 additions & 12 deletions internal/network/vds_subresource.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import (

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
utils "github.com/vmware/terraform-provider-vcf/internal/resource_utils"
"github.com/vmware/vcf-sdk-go/vcf"

utils "github.com/vmware/terraform-provider-vcf/internal/resource_utils"
validationutils "github.com/vmware/terraform-provider-vcf/internal/validation"
)

Expand Down Expand Up @@ -98,23 +98,30 @@ func TryConvertToVdsSpec(object map[string]interface{}) (*vcf.VdsSpec, error) {
return result, nil
}

func FlattenVdsSpec(vdsSpec vcf.VdsSpec) map[string]interface{} {
func FlattenVdsSpec(vdsSpec *vcf.VdsSpec) map[string]interface{} {
result := make(map[string]interface{})
if vdsSpec == nil {
return result
}
result["name"] = vdsSpec.Name
result["is_used_by_nsx"] = vdsSpec.IsUsedByNsxt
flattenedNiocBandwidthAllocationSpecs := *new([]map[string]interface{})
for _, niocBandwidthAllocationSpec := range *vdsSpec.NiocBandwidthAllocationSpecs {
flattenedNiocBandwidthAllocationSpecs = append(flattenedNiocBandwidthAllocationSpecs,
flattenNiocBandwidthAllocationSpec(niocBandwidthAllocationSpec))

if vdsSpec.NiocBandwidthAllocationSpecs != nil {
flattenedNiocBandwidthAllocationSpecs := make([]map[string]interface{}, 0, len(*vdsSpec.NiocBandwidthAllocationSpecs))
for _, niocBandwidthAllocationSpec := range *vdsSpec.NiocBandwidthAllocationSpecs {
flattenedSpec := flattenNiocBandwidthAllocationSpec(niocBandwidthAllocationSpec)
flattenedNiocBandwidthAllocationSpecs = append(flattenedNiocBandwidthAllocationSpecs, flattenedSpec)
}
result["nioc_bandwidth_allocations"] = flattenedNiocBandwidthAllocationSpecs
}
result["nioc_bandwidth_allocations"] = flattenedNiocBandwidthAllocationSpecs

flattenedPortgroupSpecs := *new([]map[string]interface{})
for _, portgroupSpec := range *vdsSpec.PortGroupSpecs {
flattenedPortgroupSpecs = append(flattenedPortgroupSpecs,
flattenPortgroupSpec(portgroupSpec))
if vdsSpec.PortGroupSpecs != nil {
flattenedPortgroupSpecs := make([]map[string]interface{}, 0, len(*vdsSpec.PortGroupSpecs))
for _, portgroupSpec := range *vdsSpec.PortGroupSpecs {
flattenedPortgroupSpecs = append(flattenedPortgroupSpecs, flattenPortgroupSpec(portgroupSpec))
}
result["portgroup"] = flattenedPortgroupSpecs
}
result["portgroup"] = flattenedPortgroupSpecs

return result
}
1 change: 1 addition & 0 deletions internal/provider/data_source_cluster_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ func TestAccDataSourceVcfCluster(t *testing.T) {
resource.TestCheckResourceAttrSet("data.vcf_cluster.cluster1", "primary_datastore_type"),
resource.TestCheckResourceAttrSet("data.vcf_cluster.cluster1", "is_default"),
resource.TestCheckResourceAttrSet("data.vcf_cluster.cluster1", "is_stretched"),
resource.TestCheckResourceAttrSet("data.vcf_cluster.cluster1", "vds"),
resource.TestCheckResourceAttrSet("data.vcf_cluster.cluster1", "host.0.id"),
resource.TestCheckResourceAttrSet("data.vcf_cluster.cluster1", "host.0.host_name"),
resource.TestCheckResourceAttrSet("data.vcf_cluster.cluster1", "host.0.ip_address"),
Expand Down
4 changes: 4 additions & 0 deletions internal/provider/resource_cluster_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ func TestAccResourceVcfClusterCreate(t *testing.T) {
resource.TestCheckResourceAttrSet("vcf_cluster.cluster1", "primary_datastore_type"),
resource.TestCheckResourceAttrSet("vcf_cluster.cluster1", "is_default"),
resource.TestCheckResourceAttrSet("vcf_cluster.cluster1", "is_stretched"),
resource.TestCheckResourceAttrSet("vcf_cluster.cluster1", "vds"),
resource.TestCheckResourceAttrSet("vcf_cluster.cluster1", "host.0.id"),
resource.TestCheckResourceAttrSet("vcf_cluster.cluster1", "host.1.id"),
resource.TestCheckResourceAttrSet("vcf_cluster.cluster1", "host.2.id"),
Expand Down Expand Up @@ -116,6 +117,7 @@ func TestAccResourceVcfClusterFull(t *testing.T) {
resource.TestCheckResourceAttrSet("vcf_cluster.cluster1", "primary_datastore_type"),
resource.TestCheckResourceAttrSet("vcf_cluster.cluster1", "is_default"),
resource.TestCheckResourceAttrSet("vcf_cluster.cluster1", "is_stretched"),
resource.TestCheckResourceAttrSet("vcf_cluster.cluster1", "vds"),
resource.TestCheckResourceAttrSet("vcf_cluster.cluster1", "host.0.id"),
resource.TestCheckResourceAttrSet("vcf_cluster.cluster1", "host.1.id"),
resource.TestCheckResourceAttrSet("vcf_cluster.cluster1", "host.2.id"),
Expand Down Expand Up @@ -151,6 +153,7 @@ func TestAccResourceVcfClusterFull(t *testing.T) {
resource.TestCheckResourceAttrSet("vcf_cluster.cluster1", "primary_datastore_type"),
resource.TestCheckResourceAttrSet("vcf_cluster.cluster1", "is_default"),
resource.TestCheckResourceAttrSet("vcf_cluster.cluster1", "is_stretched"),
resource.TestCheckResourceAttrSet("vcf_cluster.cluster1", "vds"),
resource.TestCheckResourceAttrSet("vcf_cluster.cluster1", "host.0.id"),
resource.TestCheckResourceAttrSet("vcf_cluster.cluster1", "host.1.id"),
resource.TestCheckResourceAttrSet("vcf_cluster.cluster1", "host.2.id"),
Expand Down Expand Up @@ -180,6 +183,7 @@ func TestAccResourceVcfClusterFull(t *testing.T) {
resource.TestCheckResourceAttrSet("vcf_cluster.cluster1", "primary_datastore_type"),
resource.TestCheckResourceAttrSet("vcf_cluster.cluster1", "is_default"),
resource.TestCheckResourceAttrSet("vcf_cluster.cluster1", "is_stretched"),
resource.TestCheckResourceAttrSet("vcf_cluster.cluster1", "vds"),
resource.TestCheckResourceAttrSet("vcf_cluster.cluster1", "host.0.id"),
resource.TestCheckResourceAttrSet("vcf_cluster.cluster1", "host.1.id"),
resource.TestCheckResourceAttrSet("vcf_cluster.cluster1", "host.2.id"),
Expand Down

0 comments on commit 2963fc2

Please sign in to comment.