diff --git a/spectrocloud/cluster_common.go b/spectrocloud/cluster_common.go index b223cc82..d976ff30 100644 --- a/spectrocloud/cluster_common.go +++ b/spectrocloud/cluster_common.go @@ -137,3 +137,41 @@ func updateAgentUpgradeSetting(c *client.V1Client, d *schema.ResourceData) error } return nil } + +// This function is called during import cluster from palette to set default terraform value +func flattenCommonAttributeForClusterImport(c *client.V1Client, d *schema.ResourceData) error { + clusterProfiles, err := flattenClusterProfileForImport(c, d) + if err != nil { + return err + } + err = d.Set("cluster_profile", clusterProfiles) + if err != nil { + return err + } + + err = d.Set("apply_setting", "DownloadAndInstall") + if err != nil { + return err + } + err = d.Set("force_delete", false) + if err != nil { + return err + } + err = d.Set("force_delete_delay", 20) + if err != nil { + return err + } + err = d.Set("os_patch_on_boot", false) + if err != nil { + return err + } + err = d.Set("pause_agent_upgrades", "unlock") + if err != nil { + return err + } + err = d.Set("skip_completion", false) + if err != nil { + return err + } + return nil +} diff --git a/spectrocloud/resource_cluster_aks_import.go b/spectrocloud/resource_cluster_aks_import.go index 79d5a0d6..f9b31de7 100644 --- a/spectrocloud/resource_cluster_aks_import.go +++ b/spectrocloud/resource_cluster_aks_import.go @@ -22,6 +22,12 @@ func resourceClusterAksImport(ctx context.Context, d *schema.ResourceData, m int return nil, fmt.Errorf("could not read cluster for import: %v", diags) } + // cluster profile and common default cluster attribute is get set here + err = flattenCommonAttributeForClusterImport(c, d) + if err != nil { + return nil, err + } + // Return the resource data. In most cases, this method is only used to // import one resource at a time, so you should return the resource data // in a slice with a single element. diff --git a/spectrocloud/resource_cluster_aws_import.go b/spectrocloud/resource_cluster_aws_import.go index 49994fd4..74064cfe 100644 --- a/spectrocloud/resource_cluster_aws_import.go +++ b/spectrocloud/resource_cluster_aws_import.go @@ -21,6 +21,12 @@ func resourceClusterAwsImport(ctx context.Context, d *schema.ResourceData, m int return nil, fmt.Errorf("could not read cluster for import: %v", diags) } + // cluster profile and common default cluster attribute is get set here + err = flattenCommonAttributeForClusterImport(c, d) + if err != nil { + return nil, err + } + // Return the resource data. In most cases, this method is only used to // import one resource at a time, so you should return the resource data // in a slice with a single element. diff --git a/spectrocloud/resource_cluster_azure.go b/spectrocloud/resource_cluster_azure.go index 94eeff5e..5e7dd4cf 100644 --- a/spectrocloud/resource_cluster_azure.go +++ b/spectrocloud/resource_cluster_azure.go @@ -23,7 +23,10 @@ func resourceClusterAzure() *schema.Resource { ReadContext: resourceClusterAzureRead, UpdateContext: resourceClusterAzureUpdate, DeleteContext: resourceClusterDelete, - Description: "Resource for managing Azure clusters in Spectro Cloud through Palette.", + Importer: &schema.ResourceImporter{ + StateContext: resourceClusterAzureImport, + }, + Description: "Resource for managing Azure clusters in Spectro Cloud through Palette.", Timeouts: &schema.ResourceTimeout{ Create: schema.DefaultTimeout(60 * time.Minute), @@ -386,7 +389,11 @@ func resourceClusterAzureRead(_ context.Context, d *schema.ResourceData, m inter d.SetId("") return diags } - + // verify cluster type + err = ValidateCloudType("spectrocloud_cluster_azure", cluster) + if err != nil { + return diag.FromErr(err) + } diagnostics, done := readCommonFields(c, d, cluster) if done { return diagnostics @@ -394,7 +401,59 @@ func resourceClusterAzureRead(_ context.Context, d *schema.ResourceData, m inter return flattenCloudConfigAzure(cluster.Spec.CloudConfigRef.UID, d, c) } +func flattenClusterConfigsAzure(config *models.V1AzureCloudConfig) []interface{} { + if config == nil || config.Spec == nil || config.Spec.ClusterConfig == nil { + return make([]interface{}, 0) + } + m := make(map[string]interface{}) + if config.Spec.ClusterConfig.SubscriptionID != nil { + m["subscription_id"] = config.Spec.ClusterConfig.SubscriptionID + } + if config.Spec.ClusterConfig.ResourceGroup != "" { + m["resource_group"] = config.Spec.ClusterConfig.ResourceGroup + } + if config.Spec.ClusterConfig.Location != nil { + m["region"] = config.Spec.ClusterConfig.Location + } + if config.Spec.ClusterConfig.SSHKey != nil { + m["ssh_key"] = config.Spec.ClusterConfig.SSHKey + } + if config.Spec.ClusterConfig.StorageAccountName != "" { + m["storage_account_name"] = config.Spec.ClusterConfig.StorageAccountName + } + if config.Spec.ClusterConfig.ContainerName != "" { + m["container_name"] = config.Spec.ClusterConfig.ContainerName + } + if config.Spec.ClusterConfig.VnetResourceGroup != "" { + m["network_resource_group"] = config.Spec.ClusterConfig.VnetResourceGroup + } + if config.Spec.ClusterConfig.VnetName != "" { + m["virtual_network_name"] = config.Spec.ClusterConfig.VnetName + } + if config.Spec.ClusterConfig.VnetCidrBlock != "" { + m["virtual_network_cidr_block"] = config.Spec.ClusterConfig.VnetCidrBlock + } + if config.Spec.ClusterConfig.VnetResourceGroup != "" && config.Spec.ClusterConfig.VnetName != "" && config.Spec.ClusterConfig.VnetCidrBlock != "" { + if config.Spec.ClusterConfig.ControlPlaneSubnet != nil { + cpSubnet := map[string]interface{}{ + "name": config.Spec.ClusterConfig.ControlPlaneSubnet.Name, + "cidr_block": config.Spec.ClusterConfig.ControlPlaneSubnet.CidrBlock, + "security_group_name": config.Spec.ClusterConfig.ControlPlaneSubnet.SecurityGroupName, + } + m["control_plane_subnet"] = []interface{}{cpSubnet} + } + if config.Spec.ClusterConfig.WorkerSubnet != nil { + workerSubnet := map[string]interface{}{ + "name": config.Spec.ClusterConfig.WorkerSubnet.Name, + "cidr_block": config.Spec.ClusterConfig.WorkerSubnet.CidrBlock, + "security_group_name": config.Spec.ClusterConfig.WorkerSubnet.SecurityGroupName, + } + m["worker_node_subnet"] = []interface{}{workerSubnet} + } + } + return []interface{}{m} +} func flattenCloudConfigAzure(configUID string, d *schema.ResourceData, c *client.V1Client) diag.Diagnostics { ClusterContext := d.Get("context").(string) if err := d.Set("cloud_config_id", configUID); err != nil { @@ -403,6 +462,12 @@ func flattenCloudConfigAzure(configUID string, d *schema.ResourceData, c *client if config, err := c.GetCloudConfigAzure(configUID, ClusterContext); err != nil { return diag.FromErr(err) } else { + if err := d.Set("cloud_account_id", config.Spec.CloudAccountRef.UID); err != nil { + return diag.FromErr(err) + } + if err := d.Set("cloud_config", flattenClusterConfigsAzure(config)); err != nil { + return diag.FromErr(err) + } mp := flattenMachinePoolConfigsAzure(config.Spec.MachinePoolConfig) mp, err := flattenNodeMaintenanceStatus(c, d, c.GetNodeStatusMapAzure, mp, configUID, ClusterContext) if err != nil { diff --git a/spectrocloud/resource_cluster_azure_import.go b/spectrocloud/resource_cluster_azure_import.go new file mode 100644 index 00000000..1726687f --- /dev/null +++ b/spectrocloud/resource_cluster_azure_import.go @@ -0,0 +1,29 @@ +package spectrocloud + +import ( + "context" + "fmt" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/spectrocloud/palette-sdk-go/client" +) + +func resourceClusterAzureImport(ctx context.Context, d *schema.ResourceData, m interface{}) ([]*schema.ResourceData, error) { + c := m.(*client.V1Client) + err := GetCommonCluster(d, c) + if err != nil { + return nil, err + } + + diags := resourceClusterAzureRead(ctx, d, m) + if diags.HasError() { + return nil, fmt.Errorf("could not read cluster for import: %v", diags) + } + + // cluster profile and common default cluster attribute is get set here + err = flattenCommonAttributeForClusterImport(c, d) + if err != nil { + return nil, err + } + + return []*schema.ResourceData{d}, nil +} diff --git a/spectrocloud/resource_cluster_azure_test.go b/spectrocloud/resource_cluster_azure_test.go index 63c6db08..336b0035 100644 --- a/spectrocloud/resource_cluster_azure_test.go +++ b/spectrocloud/resource_cluster_azure_test.go @@ -1,6 +1,8 @@ package spectrocloud import ( + "github.com/spectrocloud/gomi/pkg/ptr" + "sort" "testing" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" @@ -274,3 +276,98 @@ func TestFlattenMachinePoolConfigsAzure(t *testing.T) { assert.Equal(t, machinePools[0].NodeRepaveInterval, actual["node_repave_interval"]) assert.Equal(t, machinePools[0].Size, actual["count"]) } + +func TestFlattenClusterConfigsAzure(t *testing.T) { + t.Run("NilConfig", func(t *testing.T) { + result := flattenClusterConfigsAzure(nil) + assert.Equal(t, []interface{}{}, result) + }) + + t.Run("EmptyConfig", func(t *testing.T) { + config := &models.V1AzureCloudConfig{} + result := flattenClusterConfigsAzure(config) + assert.Equal(t, []interface{}{}, result) + }) + + t.Run("PartialConfig", func(t *testing.T) { + config := &models.V1AzureCloudConfig{ + Spec: &models.V1AzureCloudConfigSpec{ + ClusterConfig: &models.V1AzureClusterConfig{ + SubscriptionID: types.Ptr("test-subscription-id"), + ResourceGroup: "test-resource-group", + Location: types.Ptr("test-location"), + SSHKey: types.Ptr("test-ssh-key"), + StorageAccountName: "test-storage-account", + ContainerName: "test-container", + VnetResourceGroup: "test-network-resource-group", + VnetName: "test-vnet", + VnetCidrBlock: "10.0.0.0/16", + ControlPlaneSubnet: &models.V1Subnet{Name: "cp-subnet", CidrBlock: "10.0.1.0/24", SecurityGroupName: "cp-sg"}, + WorkerSubnet: &models.V1Subnet{Name: "worker-subnet", CidrBlock: "10.0.2.0/24", SecurityGroupName: "worker-sg"}, + }, + }, + } + + expected := []interface{}{ + map[string]interface{}{ + "subscription_id": ptr.StringPtr("test-subscription-id"), + "resource_group": "test-resource-group", + "region": ptr.StringPtr("test-location"), + "ssh_key": ptr.StringPtr("test-ssh-key"), + "storage_account_name": "test-storage-account", + "container_name": "test-container", + "network_resource_group": "test-network-resource-group", + "virtual_network_name": "test-vnet", + "virtual_network_cidr_block": "10.0.0.0/16", + "control_plane_subnet": []interface{}{ + map[string]interface{}{ + "name": "cp-subnet", + "cidr_block": "10.0.1.0/24", + "security_group_name": "cp-sg", + }, + }, + "worker_node_subnet": []interface{}{ + map[string]interface{}{ + "name": "worker-subnet", + "cidr_block": "10.0.2.0/24", + "security_group_name": "worker-sg", + }, + }, + }, + } + + result := flattenClusterConfigsAzure(config) + sortSliceOfMaps(expected) + sortSliceOfMaps(result) + assert.Equal(t, expected, result) + }) + + t.Run("MissingFields", func(t *testing.T) { + config := &models.V1AzureCloudConfig{ + Spec: &models.V1AzureCloudConfigSpec{ + ClusterConfig: &models.V1AzureClusterConfig{ + ResourceGroup: "test-resource-group", + Location: types.Ptr("test-location"), + }, + }, + } + + expected := []interface{}{ + map[string]interface{}{ + "resource_group": "test-resource-group", + "region": ptr.StringPtr("test-location"), + }, + } + + result := flattenClusterConfigsAzure(config) + assert.Equal(t, expected, result) + }) +} + +func sortSliceOfMaps(slice []interface{}) { + sort.SliceStable(slice, func(i, j int) bool { + mapI := slice[i].(map[string]interface{}) + mapJ := slice[j].(map[string]interface{}) + return mapI["name"].(string) < mapJ["name"].(string) + }) +} diff --git a/spectrocloud/resource_cluster_edge_native_import.go b/spectrocloud/resource_cluster_edge_native_import.go index f441ebfc..49d070ea 100644 --- a/spectrocloud/resource_cluster_edge_native_import.go +++ b/spectrocloud/resource_cluster_edge_native_import.go @@ -22,6 +22,12 @@ func resourceClusterEdgeNativeImport(ctx context.Context, d *schema.ResourceData return nil, fmt.Errorf("could not read cluster for import: %v", diags) } + // cluster profile and common default cluster attribute is get set here + err = flattenCommonAttributeForClusterImport(c, d) + if err != nil { + return nil, err + } + // Return the resource data. In most cases, this method is only used to // import one resource at a time, so you should return the resource data // in a slice with a single element. diff --git a/spectrocloud/resource_cluster_eks.go b/spectrocloud/resource_cluster_eks.go index 6440be85..0f9a6890 100644 --- a/spectrocloud/resource_cluster_eks.go +++ b/spectrocloud/resource_cluster_eks.go @@ -22,7 +22,10 @@ func resourceClusterEks() *schema.Resource { ReadContext: resourceClusterEksRead, UpdateContext: resourceClusterEksUpdate, DeleteContext: resourceClusterDelete, - Description: "Resource for managing EKS clusters in Spectro Cloud through Palette.", + Importer: &schema.ResourceImporter{ + StateContext: resourceClusterEksImport, + }, + Description: "Resource for managing EKS clusters in Spectro Cloud through Palette.", Timeouts: &schema.ResourceTimeout{ Create: schema.DefaultTimeout(60 * time.Minute), @@ -417,7 +420,9 @@ func resourceClusterEksRead(_ context.Context, d *schema.ResourceData, m interfa if config, err = c.GetCloudConfigEks(configUID, ClusterContext); err != nil { return diag.FromErr(err) } - + if err := d.Set("cloud_account_id", config.Spec.CloudAccountRef.UID); err != nil { + return diag.FromErr(err) + } cloudConfigFlatten := flattenClusterConfigsEKS(config) if err := d.Set("cloud_config", cloudConfigFlatten); err != nil { return diag.FromErr(err) @@ -438,6 +443,12 @@ func resourceClusterEksRead(_ context.Context, d *schema.ResourceData, m interfa return diag.FromErr(err) } + // verify cluster type + err = ValidateCloudType("spectrocloud_cluster_eks", cluster) + if err != nil { + return diag.FromErr(err) + } + diagnostics, done := readCommonFields(c, d, cluster) if done { return diagnostics diff --git a/spectrocloud/resource_cluster_eks_import.go b/spectrocloud/resource_cluster_eks_import.go new file mode 100644 index 00000000..0ce06064 --- /dev/null +++ b/spectrocloud/resource_cluster_eks_import.go @@ -0,0 +1,32 @@ +package spectrocloud + +import ( + "context" + "fmt" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/spectrocloud/palette-sdk-go/client" +) + +func resourceClusterEksImport(ctx context.Context, d *schema.ResourceData, m interface{}) ([]*schema.ResourceData, error) { + c := m.(*client.V1Client) + err := GetCommonCluster(d, c) + if err != nil { + return nil, err + } + + diags := resourceClusterEksRead(ctx, d, m) + if diags.HasError() { + return nil, fmt.Errorf("could not read cluster for import: %v", diags) + } + + // cluster profile and common default cluster attribute is get set here + err = flattenCommonAttributeForClusterImport(c, d) + if err != nil { + return nil, err + } + + // Return the resource data. In most cases, this method is only used to + // import one resource at a time, so you should return the resource data + // in a slice with a single element. + return []*schema.ResourceData{d}, nil +} diff --git a/spectrocloud/resource_cluster_gcp_import.go b/spectrocloud/resource_cluster_gcp_import.go index 826527c7..2edc6b60 100644 --- a/spectrocloud/resource_cluster_gcp_import.go +++ b/spectrocloud/resource_cluster_gcp_import.go @@ -19,13 +19,11 @@ func resourceClusterGcpImport(ctx context.Context, d *schema.ResourceData, m int return nil, fmt.Errorf("could not read cluster for import: %v", diags) } - clusterProfiles, err := flattenClusterProfileForImport(c, d) + // cluster profile and common default cluster attribute is get set here + err = flattenCommonAttributeForClusterImport(c, d) if err != nil { return nil, err } - if err := d.Set("cluster_profile", clusterProfiles); err != nil { - return nil, fmt.Errorf("could not read cluster for import: %v", diags) - } // Return the resource data. In most cases, this method is only used to // import one resource at a time, so you should return the resource data diff --git a/spectrocloud/resource_cluster_gke_import.go b/spectrocloud/resource_cluster_gke_import.go index 7c0cd8dd..55387383 100644 --- a/spectrocloud/resource_cluster_gke_import.go +++ b/spectrocloud/resource_cluster_gke_import.go @@ -21,13 +21,11 @@ func resourceClusterGkeImport(ctx context.Context, d *schema.ResourceData, m int return nil, fmt.Errorf("could not read cluster for import: %v", diags) } - clusterProfiles, err := flattenClusterProfileForImport(c, d) + // cluster profile and common default cluster attribute is get set here + err = flattenCommonAttributeForClusterImport(c, d) if err != nil { return nil, err } - if err := d.Set("cluster_profile", clusterProfiles); err != nil { - return nil, fmt.Errorf("could not read cluster for import: %v", diags) - } // Return the resource data. In most cases, this method is only used to // import one resource at a time, so you should return the resource data diff --git a/spectrocloud/resource_cluster_maas_import.go b/spectrocloud/resource_cluster_maas_import.go index 67fd5212..f23d5490 100644 --- a/spectrocloud/resource_cluster_maas_import.go +++ b/spectrocloud/resource_cluster_maas_import.go @@ -22,6 +22,12 @@ func resourceClusterMaasImport(ctx context.Context, d *schema.ResourceData, m in return nil, fmt.Errorf("could not read cluster for import: %v", diags) } + // cluster profile and common default cluster attribute is get set here + err = flattenCommonAttributeForClusterImport(c, d) + if err != nil { + return nil, err + } + // Return the resource data. In most cases, this method is only used to // import one resource at a time, so you should return the resource data // in a slice with a single element. diff --git a/spectrocloud/resource_cluster_openstack.go b/spectrocloud/resource_cluster_openstack.go index 1e12dedb..f55e1bcc 100644 --- a/spectrocloud/resource_cluster_openstack.go +++ b/spectrocloud/resource_cluster_openstack.go @@ -23,7 +23,10 @@ func resourceClusterOpenStack() *schema.Resource { ReadContext: resourceClusterOpenStackRead, UpdateContext: resourceClusterOpenStackUpdate, DeleteContext: resourceClusterDelete, - Description: "Resource for managing Openstack clusters in Spectro Cloud through Palette.", + Importer: &schema.ResourceImporter{ + StateContext: resourceClusterOpenstackImport, + }, + Description: "Resource for managing Openstack clusters in Spectro Cloud through Palette.", Timeouts: &schema.ResourceTimeout{ Create: schema.DefaultTimeout(180 * time.Minute), @@ -380,6 +383,11 @@ func resourceClusterOpenStackRead(_ context.Context, d *schema.ResourceData, m i return diags } + err = ValidateCloudType("spectrocloud_cluster_openstack", cluster) + if err != nil { + return diag.FromErr(err) + } + configUID := cluster.Spec.CloudConfigRef.UID if err := d.Set("cloud_config_id", configUID); err != nil { return diag.FromErr(err) @@ -388,6 +396,16 @@ func resourceClusterOpenStackRead(_ context.Context, d *schema.ResourceData, m i if config, err := c.GetCloudConfigOpenStack(configUID, ClusterContext); err != nil { return diag.FromErr(err) } else { + + if config.Spec != nil && config.Spec.CloudAccountRef != nil { + if err := d.Set("cloud_account_id", config.Spec.CloudAccountRef.UID); err != nil { + return diag.FromErr(err) + } + } + if err := d.Set("cloud_config", flattenClusterConfigsOpenstack(config)); err != nil { + return diag.FromErr(err) + } + mp := flattenMachinePoolConfigsOpenStack(config.Spec.MachinePoolConfig) mp, err := flattenNodeMaintenanceStatus(c, d, c.GetNodeStatusMapOpenStack, mp, configUID, ClusterContext) if err != nil { @@ -406,6 +424,41 @@ func resourceClusterOpenStackRead(_ context.Context, d *schema.ResourceData, m i return diags } +func flattenClusterConfigsOpenstack(config *models.V1OpenStackCloudConfig) []interface{} { + if config == nil || config.Spec == nil || config.Spec.ClusterConfig == nil { + return make([]interface{}, 0) + } + + m := make(map[string]interface{}) + + if config.Spec.ClusterConfig.Domain != nil { + m["domain"] = *config.Spec.ClusterConfig.Domain + } + if config.Spec.ClusterConfig.Region != "" { + m["region"] = config.Spec.ClusterConfig.Region + } + if config.Spec.ClusterConfig.Project != nil { + m["project"] = config.Spec.ClusterConfig.Project + } + if config.Spec.ClusterConfig.SSHKeyName != "" { + m["ssh_key"] = config.Spec.ClusterConfig.SSHKeyName + } + if config.Spec.ClusterConfig.Network != nil { + m["network_id"] = config.Spec.ClusterConfig.Network.ID + } + if config.Spec.ClusterConfig.Subnet != nil { + m["subnet_id"] = config.Spec.ClusterConfig.Subnet.ID + } + if config.Spec.ClusterConfig.DNSNameservers != nil { + m["dns_servers"] = config.Spec.ClusterConfig.DNSNameservers + } + if config.Spec.ClusterConfig.NodeCidr != "" { + m["subnet_cidr"] = config.Spec.ClusterConfig.NodeCidr + } + + return []interface{}{m} +} + func flattenMachinePoolConfigsOpenStack(machinePools []*models.V1OpenStackMachinePoolConfig) []interface{} { if machinePools == nil { diff --git a/spectrocloud/resource_cluster_openstack_import.go b/spectrocloud/resource_cluster_openstack_import.go new file mode 100644 index 00000000..bba53e0b --- /dev/null +++ b/spectrocloud/resource_cluster_openstack_import.go @@ -0,0 +1,34 @@ +package spectrocloud + +import ( + "context" + "fmt" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/spectrocloud/palette-sdk-go/client" +) + +func resourceClusterOpenstackImport(ctx context.Context, d *schema.ResourceData, m interface{}) ([]*schema.ResourceData, error) { + // m is the client, which can be used to make API requests to the infrastructure + c := m.(*client.V1Client) + + err := GetCommonCluster(d, c) + if err != nil { + return nil, err + } + + diags := resourceClusterOpenStackRead(ctx, d, m) + if diags.HasError() { + return nil, fmt.Errorf("could not read cluster for import: %v", diags) + } + + // cluster profile and common default cluster attribute is get set here + err = flattenCommonAttributeForClusterImport(c, d) + if err != nil { + return nil, err + } + + // Return the resource data. In most cases, this method is only used to + // import one resource at a time, so you should return the resource data + // in a slice with a single element. + return []*schema.ResourceData{d}, nil +} diff --git a/spectrocloud/resource_cluster_tke.go b/spectrocloud/resource_cluster_tke.go index df761d2f..444b7589 100644 --- a/spectrocloud/resource_cluster_tke.go +++ b/spectrocloud/resource_cluster_tke.go @@ -21,7 +21,10 @@ func resourceClusterTke() *schema.Resource { ReadContext: resourceClusterTkeRead, UpdateContext: resourceClusterTkeUpdate, DeleteContext: resourceClusterDelete, - Description: "Resource for managing TKE clusters in Spectro Cloud through Palette.", + Importer: &schema.ResourceImporter{ + StateContext: resourceClusterTkeImport, + }, + Description: "Resource for managing TKE clusters in Spectro Cloud through Palette.", Timeouts: &schema.ResourceTimeout{ Create: schema.DefaultTimeout(60 * time.Minute), @@ -310,6 +313,11 @@ func resourceClusterTkeRead(_ context.Context, d *schema.ResourceData, m interfa return diags } + err = ValidateCloudType("spectrocloud_cluster_tke", cluster) + if err != nil { + return diag.FromErr(err) + } + configUID := cluster.Spec.CloudConfigRef.UID if err := d.Set("cloud_config_id", configUID); err != nil { return diag.FromErr(err) @@ -318,6 +326,15 @@ func resourceClusterTkeRead(_ context.Context, d *schema.ResourceData, m interfa if config, err := c.GetCloudConfigTke(configUID, ClusterContext); err != nil { return diag.FromErr(err) } else { + if config.Spec != nil && config.Spec.CloudAccountRef != nil { + if err := d.Set("cloud_account_id", config.Spec.CloudAccountRef.UID); err != nil { + return diag.FromErr(err) + } + } + if err := d.Set("cloud_config", flattenClusterConfigsTke(config)); err != nil { + return diag.FromErr(err) + } + mp := flattenMachinePoolConfigsTke(config.Spec.MachinePoolConfig) mp, err := flattenNodeMaintenanceStatus(c, d, c.GetNodeStatusMapTke, mp, configUID, ClusterContext) if err != nil { @@ -336,6 +353,40 @@ func resourceClusterTkeRead(_ context.Context, d *schema.ResourceData, m interfa return diags } +func flattenClusterConfigsTke(config *models.V1TencentCloudConfig) []interface{} { + if config == nil || config.Spec == nil || config.Spec.ClusterConfig == nil { + return make([]interface{}, 0) + } + + m := make(map[string]interface{}) + + if config.Spec.ClusterConfig.Region != nil { + m["region"] = *config.Spec.ClusterConfig.Region + } + if config.Spec.ClusterConfig.SSHKeyIDs != nil { + m["ssh_key_name"] = config.Spec.ClusterConfig.SSHKeyIDs + } + if config.Spec.ClusterConfig.VpcID != "" { + m["vpc_id"] = config.Spec.ClusterConfig.VpcID + } + if config.Spec.ClusterConfig.EndpointAccess != nil { + if config.Spec.ClusterConfig.EndpointAccess.Private { + m["endpoint_access"] = "private" + } + if config.Spec.ClusterConfig.EndpointAccess.Public { + m["endpoint_access"] = "public" + } + if config.Spec.ClusterConfig.EndpointAccess.Private && config.Spec.ClusterConfig.EndpointAccess.Public { + m["endpoint_access"] = "private_and_public" + } + if config.Spec.ClusterConfig.EndpointAccess.PublicCIDRs != nil { + m["public_access_cidrs"] = config.Spec.ClusterConfig.EndpointAccess.PublicCIDRs + } + } + + return []interface{}{m} +} + func flattenMachinePoolConfigsTke(machinePools []*models.V1TencentMachinePoolConfig) []interface{} { if machinePools == nil { diff --git a/spectrocloud/resource_cluster_tke_import.go b/spectrocloud/resource_cluster_tke_import.go new file mode 100644 index 00000000..8c6fcd3d --- /dev/null +++ b/spectrocloud/resource_cluster_tke_import.go @@ -0,0 +1,31 @@ +package spectrocloud + +import ( + "context" + "fmt" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/spectrocloud/palette-sdk-go/client" +) + +func resourceClusterTkeImport(ctx context.Context, d *schema.ResourceData, m interface{}) ([]*schema.ResourceData, error) { + // m is the client, which can be used to make API requests to the infrastructure + c := m.(*client.V1Client) + + err := GetCommonCluster(d, c) + if err != nil { + return nil, err + } + + diags := resourceClusterTkeRead(ctx, d, m) + if diags.HasError() { + return nil, fmt.Errorf("could not read cluster for import: %v", diags) + } + + // cluster profile and common default cluster attribute is get set here + err = flattenCommonAttributeForClusterImport(c, d) + if err != nil { + return nil, err + } + + return []*schema.ResourceData{d}, nil +} diff --git a/spectrocloud/resource_cluster_vsphere.go b/spectrocloud/resource_cluster_vsphere.go index ca92fe6f..a6d36496 100644 --- a/spectrocloud/resource_cluster_vsphere.go +++ b/spectrocloud/resource_cluster_vsphere.go @@ -25,7 +25,10 @@ func resourceClusterVsphere() *schema.Resource { ReadContext: resourceClusterVsphereRead, UpdateContext: resourceClusterVsphereUpdate, DeleteContext: resourceClusterDelete, - Description: "A resource to manage a vSphere cluster in Palette.", + Importer: &schema.ResourceImporter{ + StateContext: resourceClusterVsphereImport, + }, + Description: "A resource to manage a vSphere cluster in Palette.", Timeouts: &schema.ResourceTimeout{ Create: schema.DefaultTimeout(180 * time.Minute), @@ -414,6 +417,13 @@ func resourceClusterVsphereRead(_ context.Context, d *schema.ResourceData, m int if config, err := c.GetCloudConfigVsphere(configUID, ClusterContext); err != nil { return diag.FromErr(err) } else { + if err := d.Set("cloud_account_id", config.Spec.CloudAccountRef.UID); err != nil { + return diag.FromErr(err) + } + cloudConfigFlatten := flattenClusterConfigsVsphere(d, config) + if err := d.Set("cloud_config", cloudConfigFlatten); err != nil { + return diag.FromErr(err) + } mp := flattenMachinePoolConfigsVsphere(config.Spec.MachinePoolConfig) mp, err := flattenNodeMaintenanceStatus(c, d, c.GetNodeStatusMapVsphere, mp, configUID, ClusterContext) if err != nil { @@ -465,26 +475,41 @@ func flattenClusterConfigsVsphere(d *schema.ResourceData, cloudConfig *models.V1 } ret := make(map[string]interface{}) + if cloudConfig.Spec.ClusterConfig == nil { + return cloudConfigFlatten + } + + if cloudConfig.Spec.ClusterConfig.ControlPlaneEndpoint != nil { + cpEndpoint := cloudConfig.Spec.ClusterConfig.ControlPlaneEndpoint + if cpEndpoint.Type != "" { + ret["network_type"] = cpEndpoint.Type + } - cpEndpoint := cloudConfig.Spec.ClusterConfig.ControlPlaneEndpoint - placement := cloudConfig.Spec.ClusterConfig.Placement - ret["datacenter"] = placement.Datacenter - ret["folder"] = placement.Folder + if cpEndpoint.DdnsSearchDomain != "" { + ret["network_search_domain"] = cpEndpoint.DdnsSearchDomain + } + } + //Setting up placement attributes if its defined + if cloudConfig.Spec.ClusterConfig.Placement != nil { + placement := cloudConfig.Spec.ClusterConfig.Placement + ret["datacenter"] = placement.Datacenter + ret["folder"] = placement.Folder + } + //Currently we do support ssh_key and ssh_keys in vsphere cluster. + //Handling flatten for if ssh_key is set if _, ok := d.GetOk("cloud_config.0.ssh_key"); ok { ret["ssh_key"] = strings.TrimSpace(cloudConfig.Spec.ClusterConfig.SSHKeys[0]) } + //Handling flatten for if ssh_keys is set if _, ok := d.GetOk("cloud_config.0.ssh_keys"); ok { ret["ssh_keys"] = cloudConfig.Spec.ClusterConfig.SSHKeys } - ret["static_ip"] = cloudConfig.Spec.ClusterConfig.StaticIP - - if cpEndpoint.Type != "" { - ret["network_type"] = cpEndpoint.Type + //During cluster import by default we are setting up ssh_keys, above 2 conditions will not be true for import case. + if len(cloudConfig.Spec.ClusterConfig.SSHKeys) != 0 { + ret["ssh_keys"] = cloudConfig.Spec.ClusterConfig.SSHKeys } - if cpEndpoint.DdnsSearchDomain != "" { - ret["network_search_domain"] = cpEndpoint.DdnsSearchDomain - } + ret["static_ip"] = cloudConfig.Spec.ClusterConfig.StaticIP if cloudConfig.Spec.ClusterConfig.NtpServers != nil { ret["ntp_servers"] = cloudConfig.Spec.ClusterConfig.NtpServers diff --git a/spectrocloud/resource_cluster_vsphere_import.go b/spectrocloud/resource_cluster_vsphere_import.go new file mode 100644 index 00000000..03345189 --- /dev/null +++ b/spectrocloud/resource_cluster_vsphere_import.go @@ -0,0 +1,29 @@ +package spectrocloud + +import ( + "context" + "fmt" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/spectrocloud/palette-sdk-go/client" +) + +func resourceClusterVsphereImport(ctx context.Context, d *schema.ResourceData, m interface{}) ([]*schema.ResourceData, error) { + c := m.(*client.V1Client) + err := GetCommonCluster(d, c) + if err != nil { + return nil, err + } + + diags := resourceClusterVsphereRead(ctx, d, m) + if diags.HasError() { + return nil, fmt.Errorf("could not read cluster for import: %v", diags) + } + + // cluster profile and common default cluster attribute is get set here + err = flattenCommonAttributeForClusterImport(c, d) + if err != nil { + return nil, err + } + + return []*schema.ResourceData{d}, nil +} diff --git a/spectrocloud/resource_cluster_vsphere_test.go b/spectrocloud/resource_cluster_vsphere_test.go index 18dec64a..e54b489c 100644 --- a/spectrocloud/resource_cluster_vsphere_test.go +++ b/spectrocloud/resource_cluster_vsphere_test.go @@ -659,7 +659,15 @@ func getCloudConfig() *models.V1VsphereCloudConfig { Kind: "", Metadata: nil, Spec: &models.V1VsphereCloudConfigSpec{ - CloudAccountRef: nil, + CloudAccountRef: &models.V1ObjectReference{ + APIVersion: "", + FieldPath: "", + Kind: "", + Name: "", + Namespace: "", + ResourceVersion: "", + UID: "vmware-basic-account-id", + }, ClusterConfig: nil, EdgeHostRef: nil, MachinePoolConfig: getMPools(),