diff --git a/docs/resources/cluster_aws.md b/docs/resources/cluster_aws.md index 40731de3..e310f16f 100644 --- a/docs/resources/cluster_aws.md +++ b/docs/resources/cluster_aws.md @@ -166,6 +166,7 @@ Required: Optional: +- `control_plane_lb` (String) Control plane load balancer type. Valid values are `Internet-facing` and `internal`. Defaults to `` (empty string). - `vpc_id` (String) diff --git a/docs/resources/virtual_cluster.md b/docs/resources/virtual_cluster.md index 7ec4bbb0..eca48d19 100644 --- a/docs/resources/virtual_cluster.md +++ b/docs/resources/virtual_cluster.md @@ -62,6 +62,7 @@ resource "spectrocloud_virtual_cluster" "cluster" { - `cluster_group_uid` (String) - `cluster_profile` (Block List) (see [below for nested schema](#nestedblock--cluster_profile)) - `cluster_rbac_binding` (Block List) (see [below for nested schema](#nestedblock--cluster_rbac_binding)) +- `context` (String) - `force_delete` (Boolean) If set to `true`, the cluster will be force deleted and user has to manually clean up the provisioned cloud resources. - `force_delete_delay` (Number) Delay duration in minutes to before invoking cluster force delete. Default and minimum is 20. - `host_cluster_uid` (String) diff --git a/spectrocloud/cluster_common_profiles.go b/spectrocloud/cluster_common_profiles.go index a087c76f..7689f54b 100644 --- a/spectrocloud/cluster_common_profiles.go +++ b/spectrocloud/cluster_common_profiles.go @@ -13,14 +13,28 @@ import ( "github.com/spectrocloud/terraform-provider-spectrocloud/types" ) -func toProfiles(c *client.V1Client, d *schema.ResourceData) ([]*models.V1SpectroClusterProfileEntity, error) { - clusterContext := d.Get("context").(string) +func toProfiles(c *client.V1Client, d *schema.ResourceData, clusterContext string) ([]*models.V1SpectroClusterProfileEntity, error) { return toProfilesCommon(c, d, d.Id(), clusterContext) } func toAddonDeplProfiles(c *client.V1Client, d *schema.ResourceData) ([]*models.V1SpectroClusterProfileEntity, error) { - clusterUid := d.Get("cluster_uid").(string) - clusterContext := d.Get("cluster_context").(string) + clusterUid := "" + clusterContext := "" + // handling cluster attachment flow for cluster created outside terraform and attaching addon profile to it + if uid, ok := d.GetOk("cluster_uid"); ok && uid != nil { + clusterUid = uid.(string) //d.Get("cluster_uid").(string) + } + if ct, ok := d.GetOk("cluster_context"); ok && c != nil { + clusterContext = ct.(string) //d.Get("cluster_context").(string) + } + // handling cluster day 2 addon profile operation flow + if clusterUid == "" { + clusterUid = d.Id() + } + if clusterContext == "" { + clusterContext = d.Get("context").(string) + } + return toProfilesCommon(c, d, clusterUid, clusterContext) } diff --git a/spectrocloud/cluster_node_common.go b/spectrocloud/cluster_node_common.go index e0ce2a3b..68fad29f 100644 --- a/spectrocloud/cluster_node_common.go +++ b/spectrocloud/cluster_node_common.go @@ -2,12 +2,14 @@ package spectrocloud import ( "context" + "fmt" + "log" + "time" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/spectrocloud/hapi/models" "github.com/spectrocloud/palette-sdk-go/client" - "log" - "time" ) var NodeMaintenanceLifecycleStates = []string{ @@ -84,7 +86,12 @@ func resourceNodeAction(c *client.V1Client, ctx context.Context, newMachinePool func flattenNodeMaintenanceStatus(c *client.V1Client, d *schema.ResourceData, fn GetNodeStatusMap, mPools []interface{}, cloudConfigId string, ClusterContext string) ([]interface{}, error) { _, n := d.GetChange("machine_pool") nsMap := make(map[string]interface{}) - for _, mp := range n.(*schema.Set).List() { + machinePoolsList, i, err := getMachinePoolList(n) + if err != nil { + return i, err + } + + for _, mp := range machinePoolsList { machinePool := mp.(map[string]interface{}) nsMap[machinePool["name"].(string)] = machinePool } @@ -117,3 +124,19 @@ func flattenNodeMaintenanceStatus(c *client.V1Client, d *schema.ResourceData, fn } return mPools, nil } + +func getMachinePoolList(n interface{}) ([]interface{}, []interface{}, error) { + var machinePoolsList []interface{} + + // Check if n is of type *schema.Set + if set, ok := n.(*schema.Set); ok { + machinePoolsList = set.List() + } else if list, ok := n.([]interface{}); ok { + // If n is already a slice of interfaces + machinePoolsList = list + } else { + // Handle error: n is neither *schema.Set nor []interface{} + return nil, nil, fmt.Errorf("unexpected type for n: %T", n) + } + return machinePoolsList, nil, nil +} diff --git a/spectrocloud/cluster_node_common_test.go b/spectrocloud/cluster_node_common_test.go new file mode 100644 index 00000000..a99597ec --- /dev/null +++ b/spectrocloud/cluster_node_common_test.go @@ -0,0 +1,47 @@ +package spectrocloud + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/stretchr/testify/assert" +) + +func TestGetMachinePoolList(t *testing.T) { + tests := []struct { + name string + input interface{} + want []interface{} + wantErr bool + }{ + { + name: "Handle *schema.Set", + input: schema.NewSet(schema.HashString, []interface{}{"a", "b"}), + want: []interface{}{"a", "b"}, + wantErr: false, + }, + { + name: "Handle []interface{}", + input: []interface{}{"a", "b"}, + want: []interface{}{"a", "b"}, + wantErr: false, + }, + { + name: "Handle unexpected type", + input: "unexpected", + want: nil, + wantErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, _, err := getMachinePoolList(tt.input) + if (err != nil) != tt.wantErr { + t.Errorf("getMachinePoolList() error = %v, wantErr %v", err, tt.wantErr) + return + } + assert.ElementsMatch(t, tt.want, got) + }) + } +} diff --git a/spectrocloud/data_source_registry_pack.go b/spectrocloud/data_source_registry_pack.go index 0fe46c83..bae9deb7 100644 --- a/spectrocloud/data_source_registry_pack.go +++ b/spectrocloud/data_source_registry_pack.go @@ -32,12 +32,12 @@ func dataSourceRegistryPackRead(_ context.Context, d *schema.ResourceData, m int c := m.(*client.V1Client) var diags diag.Diagnostics if v, ok := d.GetOk("name"); ok { - registry, err := c.GetPackRegistryByName(v.(string)) + registry, err := c.GetPackRegistryCommonByName(v.(string)) if err != nil { return diag.FromErr(err) } - d.SetId(registry.Metadata.UID) - if err := d.Set("name", registry.Metadata.Name); err != nil { + d.SetId(registry.UID) + if err := d.Set("name", registry.Name); err != nil { return diag.FromErr(err) } } diff --git a/spectrocloud/resource_cluster_aks.go b/spectrocloud/resource_cluster_aks.go index b7e16de8..ccc63575 100644 --- a/spectrocloud/resource_cluster_aks.go +++ b/spectrocloud/resource_cluster_aks.go @@ -454,7 +454,8 @@ func toAksCluster(c *client.V1Client, d *schema.ResourceData) (*models.V1Spectro } } - profiles, err := toProfiles(c, d) + clusterContext := d.Get("context").(string) + profiles, err := toProfiles(c, d, clusterContext) if err != nil { return nil, err } diff --git a/spectrocloud/resource_cluster_aws.go b/spectrocloud/resource_cluster_aws.go index 1536c861..bc1a02b4 100644 --- a/spectrocloud/resource_cluster_aws.go +++ b/spectrocloud/resource_cluster_aws.go @@ -125,6 +125,14 @@ func resourceClusterAws() *schema.Resource { ForceNew: true, Optional: true, }, + "control_plane_lb": { + Type: schema.TypeString, + ForceNew: true, + Default: "", + Optional: true, + ValidateFunc: validation.StringInSlice([]string{"", "Internet-facing", "internal"}, false), + Description: "Control plane load balancer type. Valid values are `Internet-facing` and `internal`. Defaults to `` (empty string).", + }, }, }, }, @@ -501,7 +509,8 @@ func toAwsCluster(c *client.V1Client, d *schema.ResourceData) (*models.V1Spectro // gnarly, I know! =/ cloudConfig := d.Get("cloud_config").([]interface{})[0].(map[string]interface{}) - profiles, err := toProfiles(c, d) + clusterContext := d.Get("context").(string) + profiles, err := toProfiles(c, d, clusterContext) if err != nil { return nil, err } @@ -516,9 +525,10 @@ func toAwsCluster(c *client.V1Client, d *schema.ResourceData) (*models.V1Spectro Profiles: profiles, Policies: toPolicies(d), CloudConfig: &models.V1AwsClusterConfig{ - SSHKeyName: cloudConfig["ssh_key_name"].(string), - Region: types.Ptr(cloudConfig["region"].(string)), - VpcID: cloudConfig["vpc_id"].(string), + SSHKeyName: cloudConfig["ssh_key_name"].(string), + Region: types.Ptr(cloudConfig["region"].(string)), + VpcID: cloudConfig["vpc_id"].(string), + ControlPlaneLoadBalancer: cloudConfig["control_plane_lb"].(string), }, }, } diff --git a/spectrocloud/resource_cluster_azure.go b/spectrocloud/resource_cluster_azure.go index 3f16e47a..c1beb411 100644 --- a/spectrocloud/resource_cluster_azure.go +++ b/spectrocloud/resource_cluster_azure.go @@ -489,7 +489,8 @@ func toAzureCluster(c *client.V1Client, d *schema.ResourceData) (*models.V1Spect cloudConfig := d.Get("cloud_config").([]interface{})[0].(map[string]interface{}) //clientSecret := strfmt.Password(d.Get("azure_client_secret").(string)) - profiles, err := toProfiles(c, d) + clusterContext := d.Get("context").(string) + profiles, err := toProfiles(c, d, clusterContext) if err != nil { return nil, err } diff --git a/spectrocloud/resource_cluster_coxedge.go b/spectrocloud/resource_cluster_coxedge.go index 65ced376..3221a27c 100644 --- a/spectrocloud/resource_cluster_coxedge.go +++ b/spectrocloud/resource_cluster_coxedge.go @@ -674,7 +674,8 @@ func toCoxEdgeCluster(c *client.V1Client, d *schema.ResourceData) (*models.V1Spe } } - profiles, err := toProfiles(c, d) + clusterContext := d.Get("context").(string) + profiles, err := toProfiles(c, d, clusterContext) if err != nil { return nil, err } diff --git a/spectrocloud/resource_cluster_edge_native.go b/spectrocloud/resource_cluster_edge_native.go index 8c0950cd..2165e804 100644 --- a/spectrocloud/resource_cluster_edge_native.go +++ b/spectrocloud/resource_cluster_edge_native.go @@ -439,7 +439,8 @@ func toEdgeNativeCluster(c *client.V1Client, d *schema.ResourceData) (*models.V1 } } - profiles, err := toProfiles(c, d) + clusterContext := d.Get("context").(string) + profiles, err := toProfiles(c, d, clusterContext) if err != nil { return nil, err } diff --git a/spectrocloud/resource_cluster_edge_vsphere.go b/spectrocloud/resource_cluster_edge_vsphere.go index a60f7ba0..77b640de 100644 --- a/spectrocloud/resource_cluster_edge_vsphere.go +++ b/spectrocloud/resource_cluster_edge_vsphere.go @@ -494,7 +494,8 @@ func toEdgeVsphereCluster(c *client.V1Client, d *schema.ResourceData) (*models.V vip := cloudConfig["vip"].(string) - profiles, err := toProfiles(c, d) + clusterContext := d.Get("context").(string) + profiles, err := toProfiles(c, d, clusterContext) if err != nil { return nil, err } diff --git a/spectrocloud/resource_cluster_eks.go b/spectrocloud/resource_cluster_eks.go index 1b32f4d5..56539037 100644 --- a/spectrocloud/resource_cluster_eks.go +++ b/spectrocloud/resource_cluster_eks.go @@ -666,7 +666,8 @@ func toEksCluster(c *client.V1Client, d *schema.ResourceData) (*models.V1Spectro } } - profiles, err := toProfiles(c, d) + clusterContext := d.Get("context").(string) + profiles, err := toProfiles(c, d, clusterContext) if err != nil { return nil, err } diff --git a/spectrocloud/resource_cluster_gcp.go b/spectrocloud/resource_cluster_gcp.go index 8b5c32c9..59cc725f 100644 --- a/spectrocloud/resource_cluster_gcp.go +++ b/spectrocloud/resource_cluster_gcp.go @@ -413,7 +413,8 @@ func toGcpCluster(c *client.V1Client, d *schema.ResourceData) (*models.V1Spectro cloudConfig := d.Get("cloud_config").([]interface{})[0].(map[string]interface{}) //clientSecret := strfmt.Password(d.Get("gcp_client_secret").(string)) - profiles, err := toProfiles(c, d) + clusterContext := d.Get("context").(string) + profiles, err := toProfiles(c, d, clusterContext) if err != nil { return nil, err } diff --git a/spectrocloud/resource_cluster_import.go b/spectrocloud/resource_cluster_import.go index ae5ebce0..4cea3983 100644 --- a/spectrocloud/resource_cluster_import.go +++ b/spectrocloud/resource_cluster_import.go @@ -207,7 +207,8 @@ func resourceCloudClusterUpdate(_ context.Context, d *schema.ResourceData, m int func toCloudClusterProfiles(c *client.V1Client, d *schema.ResourceData) (*models.V1SpectroClusterProfiles, error) { if profiles := d.Get("cluster_profile").([]interface{}); len(profiles) > 0 { - profiles, err := toProfiles(c, d) + clusterContext := d.Get("context").(string) + profiles, err := toProfiles(c, d, clusterContext) if err != nil { return nil, err } diff --git a/spectrocloud/resource_cluster_libvirt.go b/spectrocloud/resource_cluster_libvirt.go index ac6f9d8e..4eb71496 100644 --- a/spectrocloud/resource_cluster_libvirt.go +++ b/spectrocloud/resource_cluster_libvirt.go @@ -607,7 +607,8 @@ func toLibvirtCluster(c *client.V1Client, d *schema.ResourceData) (*models.V1Spe return nil, err } - profiles, err := toProfiles(c, d) + clusterContext := d.Get("context").(string) + profiles, err := toProfiles(c, d, clusterContext) if err != nil { return nil, err } diff --git a/spectrocloud/resource_cluster_maas.go b/spectrocloud/resource_cluster_maas.go index 59e41d80..87aa0db5 100644 --- a/spectrocloud/resource_cluster_maas.go +++ b/spectrocloud/resource_cluster_maas.go @@ -453,7 +453,8 @@ func toMaasCluster(c *client.V1Client, d *schema.ResourceData) (*models.V1Spectr cloudConfig := d.Get("cloud_config").([]interface{})[0].(map[string]interface{}) DomainVal := cloudConfig["domain"].(string) - profiles, err := toProfiles(c, d) + clusterContext := d.Get("context").(string) + profiles, err := toProfiles(c, d, clusterContext) if err != nil { return nil, err } diff --git a/spectrocloud/resource_cluster_openstack.go b/spectrocloud/resource_cluster_openstack.go index 32899335..0786fd6b 100644 --- a/spectrocloud/resource_cluster_openstack.go +++ b/spectrocloud/resource_cluster_openstack.go @@ -271,7 +271,8 @@ func toOpenStackCluster(c *client.V1Client, d *schema.ResourceData) (*models.V1S cloudConfig := d.Get("cloud_config").([]interface{})[0].(map[string]interface{}) - profiles, err := toProfiles(c, d) + clusterContext := d.Get("context").(string) + profiles, err := toProfiles(c, d, clusterContext) if err != nil { return nil, err } diff --git a/spectrocloud/resource_cluster_tke.go b/spectrocloud/resource_cluster_tke.go index bd0257bc..e4293c77 100644 --- a/spectrocloud/resource_cluster_tke.go +++ b/spectrocloud/resource_cluster_tke.go @@ -426,7 +426,8 @@ func toTkeCluster(c *client.V1Client, d *schema.ResourceData) (*models.V1Spectro sshKeyIds = append(sshKeyIds, cloudConfig["ssh_key_name"].(string)) } - profiles, err := toProfiles(c, d) + clusterContext := d.Get("context").(string) + profiles, err := toProfiles(c, d, clusterContext) if err != nil { return nil, err } diff --git a/spectrocloud/resource_cluster_virtual.go b/spectrocloud/resource_cluster_virtual.go index 41ca8127..19474b26 100644 --- a/spectrocloud/resource_cluster_virtual.go +++ b/spectrocloud/resource_cluster_virtual.go @@ -36,6 +36,12 @@ func resourceClusterVirtual() *schema.Resource { Required: true, ForceNew: true, }, + "context": { + Type: schema.TypeString, + Optional: true, + Default: "project", + ValidateFunc: validation.StringInSlice([]string{"project", "cluster"}, false), + }, "tags": { Type: schema.TypeSet, Optional: true, @@ -368,7 +374,8 @@ func toVirtualCluster(c *client.V1Client, d *schema.ResourceData) (*models.V1Spe kubernetesVersion = cloudConfig["k8s_version"].(string) } - profiles, err := toProfiles(c, d) + clusterContext := d.Get("context").(string) + profiles, err := toProfiles(c, d, clusterContext) if err != nil { return nil, err } diff --git a/spectrocloud/resource_cluster_virtual_test.go b/spectrocloud/resource_cluster_virtual_test.go new file mode 100644 index 00000000..7c65cd3e --- /dev/null +++ b/spectrocloud/resource_cluster_virtual_test.go @@ -0,0 +1,70 @@ +package spectrocloud + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/spectrocloud/palette-sdk-go/client" + "github.com/stretchr/testify/assert" +) + +func prepareVirtualClusterTestData() *schema.ResourceData { + d := resourceClusterVirtual().TestResourceData() + + d.SetId("") + d.Set("name", "virtual-picard-2") + + // Cluster Profile for Virtual Cluster + cProfile := make([]map[string]interface{}, 0) + cProfile = append(cProfile, map[string]interface{}{ + "id": "virtual-basic-infra-profile-id", + }) + d.Set("cluster_profile", cProfile) + d.Set("host_cluster_uid", "host-cluster-id") + d.Set("cluster_group_uid", "group-cluster-id") + + // Cloud Config for Virtual Cluster + cloudConfig := make([]map[string]interface{}, 0) + vCloud := map[string]interface{}{ + "chart_name": "virtual-chart-name", + "chart_repo": "virtual-chart-repo", + "chart_version": "v1.0.0", + "chart_values": "default-values", + "k8s_version": "v1.20.0", + } + cloudConfig = append(cloudConfig, vCloud) + d.Set("cloud_config", cloudConfig) + + return d +} + +func TestToVirtualCluster(t *testing.T) { + assert := assert.New(t) + // Create a mock ResourceData object + d := prepareVirtualClusterTestData() + + // Mock the client + mockClient := &client.V1Client{} + + // Create a mock ResourceData for testing + vCluster, err := toVirtualCluster(mockClient, d) + assert.Nil(err) + + // Check the output against the expected values + + // Verifying cluster name attribute + assert.Equal(d.Get("name").(string), vCluster.Metadata.Name) + + // Verifying host cluster uid and cluster group uid attributes + assert.Equal(d.Get("host_cluster_uid").(string), vCluster.Spec.ClusterConfig.HostClusterConfig.HostCluster.UID) + assert.Equal(d.Get("cluster_group_uid").(string), vCluster.Spec.ClusterConfig.HostClusterConfig.ClusterGroup.UID) + + // Verifying cloud config attributes + val, _ := d.GetOk("cloud_config") + cloudConfig := val.([]interface{})[0].(map[string]interface{}) + assert.Equal(cloudConfig["chart_name"].(string), vCluster.Spec.CloudConfig.HelmRelease.Chart.Name) + assert.Equal(cloudConfig["chart_repo"].(string), vCluster.Spec.CloudConfig.HelmRelease.Chart.Repo) + assert.Equal(cloudConfig["chart_version"].(string), vCluster.Spec.CloudConfig.HelmRelease.Chart.Version) + assert.Equal(cloudConfig["chart_values"].(string), vCluster.Spec.CloudConfig.HelmRelease.Values) + assert.Equal(cloudConfig["k8s_version"].(string), vCluster.Spec.CloudConfig.KubernetesVersion) +} diff --git a/spectrocloud/resource_cluster_vsphere.go b/spectrocloud/resource_cluster_vsphere.go index 64e9a3b5..432398ab 100644 --- a/spectrocloud/resource_cluster_vsphere.go +++ b/spectrocloud/resource_cluster_vsphere.go @@ -678,7 +678,8 @@ func toVsphereCluster(c *client.V1Client, d *schema.ResourceData) (*models.V1Spe cloudConfig := d.Get("cloud_config").([]interface{})[0].(map[string]interface{}) //clientSecret := strfmt.Password(d.Get("azure_client_secret").(string)) - profiles, err := toProfiles(c, d) + clusterContext := d.Get("context").(string) + profiles, err := toProfiles(c, d, clusterContext) if err != nil { return nil, err }