-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
DWX-18732 Create and delete CDW AWS cluster object
This commit adds the basic creation and deletion capabilities - The model and schema for a data warehouse kubernetes cluster creation. - The creation call - The deletion call - Some very basic unit tests
- Loading branch information
Showing
7 changed files
with
907 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
## Copyright 2024 Cloudera. All Rights Reserved. | ||
# | ||
# This file is licensed under the Apache License Version 2.0 (the "License"). | ||
# You may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. | ||
# | ||
# This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS | ||
# OF ANY KIND, either express or implied. Refer to the License for the specific | ||
# permissions and limitations governing your use of the file. | ||
|
||
resource "cdp_dw_aws_cluster" "example" { | ||
crn = cdp_datalake_aws_datalake.example.crn | ||
name = "<value>" | ||
cluster_id = "<value>" | ||
node_role_cdw_managed_policy_arn = "<value>" | ||
database_backup_retention_days = 7 | ||
custom_registry_options = var.custom_registry_options | ||
custom_subdomain = "" | ||
network_settings = { | ||
worker_subnet_ids = ["<value>", "<value>", "<value>"] | ||
load_balancer_subnet_ids = ["<value>", "<value>", "<value>"] | ||
use_overlay_network = false | ||
whitelist_k8s_cluster_access_ip_cidrs = ["0.0.0.0/0"] | ||
whitelist_workload_access_ip_cidrs = ["0.0.0.0/0"] | ||
use_private_load_balancer = true | ||
use_public_worker_node = false | ||
} | ||
instance_settings = { | ||
custom_ami_id = "" | ||
enable_spot_instances = false | ||
compute_instance_types = ["<value>"] | ||
additional_instance_types = ["<value>"] | ||
} | ||
} | ||
|
||
output "crn" { | ||
value = cdp_dw_aws_cluster.example.crn | ||
} | ||
|
||
output "cluster_id" { | ||
value = cdp_dw_aws_cluster.example.cluster_id | ||
} | ||
|
||
output "name" { | ||
value = cdp_dw_aws_cluster.example.name | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
// Copyright 2024 Cloudera. All Rights Reserved. | ||
// | ||
// This file is licensed under the Apache License Version 2.0 (the "License"). | ||
// You may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. | ||
// | ||
// This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS | ||
// OF ANY KIND, either express or implied. Refer to the License for the specific | ||
// permissions and limitations governing your use of the file. | ||
|
||
package aws | ||
|
||
import ( | ||
"github.com/hashicorp/terraform-plugin-framework/types" | ||
|
||
"github.com/cloudera/terraform-provider-cdp/cdp-sdk-go/gen/dw/models" | ||
"github.com/cloudera/terraform-provider-cdp/utils" | ||
) | ||
|
||
type networkResourceModel struct { | ||
WorkerSubnetIDs types.List `tfsdk:"worker_subnet_ids"` | ||
LoadBalancerSubnetIDs types.List `tfsdk:"load_balancer_subnet_ids"` | ||
UseOverlayNetwork types.Bool `tfsdk:"use_overlay_network"` | ||
WhitelistK8sClusterAccessIPCIDRs types.List `tfsdk:"whitelist_k8s_cluster_access_ip_cidrs"` | ||
WhitelistWorkloadAccessIPCIDRs types.List `tfsdk:"whitelist_workload_access_ip_cidrs"` | ||
UsePrivateLoadBalancer types.Bool `tfsdk:"use_private_load_balancer"` | ||
UsePublicWorkerNode types.Bool `tfsdk:"use_public_worker_node"` | ||
} | ||
|
||
type customRegistryOptions struct { | ||
RegistryType types.String `tfsdk:"registry_type"` | ||
RepositoryURL types.String `tfsdk:"repository_url"` | ||
} | ||
|
||
type instanceResourceModel struct { | ||
CustomAmiID types.String `tfsdk:"custom_ami_id"` | ||
EnableSpotInstances types.Bool `tfsdk:"enable_spot_instances"` | ||
ComputeInstanceTypes types.List `tfsdk:"compute_instance_types"` | ||
AdditionalInstanceTypes types.List `tfsdk:"additional_instance_types"` | ||
} | ||
|
||
type resourceModel struct { | ||
ID types.String `tfsdk:"id"` | ||
Crn types.String `tfsdk:"crn"` | ||
Name types.String `tfsdk:"name"` | ||
ClusterID types.String `tfsdk:"cluster_id"` | ||
LastUpdated types.String `tfsdk:"last_updated"` | ||
NodeRoleCDWManagedPolicyArn types.String `tfsdk:"node_role_cdw_managed_policy_arn"` | ||
DatabaseBackupRetentionDays types.Int64 `tfsdk:"database_backup_retention_days"` | ||
CustomRegistryOptions *customRegistryOptions `tfsdk:"custom_registry_options"` | ||
CustomSubdomain types.String `tfsdk:"custom_subdomain"` | ||
NetworkSettings *networkResourceModel `tfsdk:"network_settings"` | ||
InstanceSettings *instanceResourceModel `tfsdk:"instance_settings"` | ||
} | ||
|
||
func (p *resourceModel) convertToCreateAwsClusterRequest() *models.CreateAwsClusterRequest { | ||
return &models.CreateAwsClusterRequest{ | ||
EnvironmentCrn: p.Crn.ValueStringPointer(), | ||
UseOverlayNetwork: p.NetworkSettings.UseOverlayNetwork.ValueBool(), | ||
WhitelistK8sClusterAccessIPCIDRs: utils.FromListValueToStringList(p.NetworkSettings.WhitelistK8sClusterAccessIPCIDRs), | ||
WhitelistWorkloadAccessIPCIDRs: utils.FromListValueToStringList(p.NetworkSettings.WhitelistWorkloadAccessIPCIDRs), | ||
UsePrivateLoadBalancer: p.NetworkSettings.UsePrivateLoadBalancer.ValueBool(), | ||
UsePublicWorkerNode: p.NetworkSettings.UsePublicWorkerNode.ValueBool(), | ||
WorkerSubnetIds: utils.FromListValueToStringList(p.NetworkSettings.WorkerSubnetIDs), | ||
LbSubnetIds: utils.FromListValueToStringList(p.NetworkSettings.LoadBalancerSubnetIDs), | ||
NodeRoleCDWManagedPolicyArn: p.NodeRoleCDWManagedPolicyArn.ValueString(), | ||
DatabaseBackupRetentionPeriod: utils.Int64To32Pointer(p.DatabaseBackupRetentionDays), | ||
CustomSubdomain: p.CustomSubdomain.ValueString(), | ||
CustomRegistryOptions: p.getCustomRegistryOptions(), | ||
EnableSpotInstances: p.getEnableSpotInstances(), | ||
CustomAmiID: p.getCustomAmiID(), | ||
ComputeInstanceTypes: p.getComputeInstanceTypes(), | ||
AdditionalInstanceTypes: p.getAdditionalInstanceTypes(), | ||
} | ||
} | ||
|
||
func (p *resourceModel) getEnableSpotInstances() *bool { | ||
if i := p.InstanceSettings; i != nil { | ||
return i.EnableSpotInstances.ValueBoolPointer() | ||
} | ||
return nil | ||
} | ||
|
||
func (p *resourceModel) getCustomAmiID() string { | ||
if i := p.InstanceSettings; i != nil { | ||
return p.InstanceSettings.CustomAmiID.ValueString() | ||
} | ||
return "" | ||
} | ||
|
||
func (p *resourceModel) getComputeInstanceTypes() []string { | ||
if i := p.InstanceSettings; i != nil { | ||
return utils.FromListValueToStringList(p.InstanceSettings.ComputeInstanceTypes) | ||
} | ||
return nil | ||
} | ||
|
||
func (p *resourceModel) getAdditionalInstanceTypes() []string { | ||
if i := p.InstanceSettings; i != nil { | ||
return utils.FromListValueToStringList(p.InstanceSettings.AdditionalInstanceTypes) | ||
} | ||
return nil | ||
} | ||
|
||
func (p *resourceModel) getCustomRegistryOptions() *models.CustomRegistryOptions { | ||
if cro := p.CustomRegistryOptions; cro != nil { | ||
return &models.CustomRegistryOptions{ | ||
DisableImageVerification: true, // option will be deprecated, we should disallow image verification | ||
RegistryType: p.CustomRegistryOptions.RegistryType.ValueString(), | ||
RepositoryURL: p.CustomRegistryOptions.RepositoryURL.ValueString(), | ||
} | ||
} | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
// Copyright 2024 Cloudera. All Rights Reserved. | ||
// | ||
// This file is licensed under the Apache License Version 2.0 (the "License"). | ||
// You may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. | ||
// | ||
// This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS | ||
// OF ANY KIND, either express or implied. Refer to the License for the specific | ||
// permissions and limitations governing your use of the file. | ||
|
||
package aws | ||
|
||
import ( | ||
"context" | ||
"time" | ||
|
||
"github.com/hashicorp/terraform-plugin-framework/resource" | ||
"github.com/hashicorp/terraform-plugin-framework/types" | ||
"github.com/hashicorp/terraform-plugin-log/tflog" | ||
|
||
"github.com/cloudera/terraform-provider-cdp/cdp-sdk-go/cdp" | ||
"github.com/cloudera/terraform-provider-cdp/cdp-sdk-go/gen/dw/client/operations" | ||
"github.com/cloudera/terraform-provider-cdp/cdp-sdk-go/gen/dw/models" | ||
"github.com/cloudera/terraform-provider-cdp/utils" | ||
) | ||
|
||
type dwClusterResource struct { | ||
client *cdp.Client | ||
} | ||
|
||
var ( | ||
_ resource.Resource = (*dwClusterResource)(nil) | ||
_ resource.ResourceWithConfigure = (*dwClusterResource)(nil) | ||
) | ||
|
||
func NewDwClusterResource() resource.Resource { | ||
return &dwClusterResource{} | ||
} | ||
|
||
func (r *dwClusterResource) Configure(_ context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) { | ||
r.client = utils.GetCdpClientForResource(req, resp) | ||
} | ||
|
||
func (r *dwClusterResource) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { | ||
resp.TypeName = req.ProviderTypeName + "_dw_aws_cluster" | ||
} | ||
|
||
func (r *dwClusterResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) { | ||
resp.Schema = dwClusterSchema | ||
} | ||
|
||
func (r *dwClusterResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { | ||
// Retrieve values from plan | ||
var plan resourceModel | ||
diags := req.Plan.Get(ctx, &plan) | ||
resp.Diagnostics.Append(diags...) | ||
if resp.Diagnostics.HasError() { | ||
return | ||
} | ||
|
||
// Generate API request body from plan | ||
clusterParams := operations.NewCreateAwsClusterParamsWithContext(ctx). | ||
WithInput(plan.convertToCreateAwsClusterRequest()) | ||
|
||
// Create new aws cluster | ||
response, err := r.client.Dw.Operations.CreateAwsCluster(clusterParams) | ||
if err != nil { | ||
resp.Diagnostics.AddError( | ||
"Error creating data warehouse aws cluster", | ||
"Could not create cluster, unexpected error: "+err.Error(), | ||
) | ||
return | ||
} | ||
|
||
payload := response.GetPayload() | ||
desc := operations.NewDescribeClusterParamsWithContext(ctx). | ||
WithInput(&models.DescribeClusterRequest{ClusterID: &payload.ClusterID}) | ||
describe, err := r.client.Dw.Operations.DescribeCluster(desc) | ||
if err != nil { | ||
resp.Diagnostics.AddError( | ||
"Error creating data warehouse aws cluster", | ||
"Could not describe cluster, unexpected error: "+err.Error(), | ||
) | ||
return | ||
} | ||
|
||
cluster := describe.GetPayload() | ||
|
||
// Map response body to schema and populate Computed attribute values | ||
plan.ID = types.StringValue(cluster.Cluster.EnvironmentCrn) | ||
plan.Crn = types.StringValue(cluster.Cluster.EnvironmentCrn) | ||
plan.Name = types.StringValue(cluster.Cluster.Name) | ||
plan.ClusterID = types.StringValue(cluster.Cluster.ID) | ||
plan.LastUpdated = types.StringValue(time.Now().Format(time.RFC850)) | ||
|
||
// Set state to fully populated data | ||
diags = resp.State.Set(ctx, plan) | ||
resp.Diagnostics.Append(diags...) | ||
if resp.Diagnostics.HasError() { | ||
return | ||
} | ||
|
||
} | ||
|
||
func (r *dwClusterResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { | ||
tflog.Warn(ctx, "Read operation is not implemented yet.") | ||
} | ||
|
||
func (r *dwClusterResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { | ||
tflog.Warn(ctx, "Update operation is not implemented yet.") | ||
} | ||
|
||
func (r *dwClusterResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { | ||
var state resourceModel | ||
|
||
// Read Terraform prior state into the model | ||
resp.Diagnostics.Append(req.State.Get(ctx, &state)...) | ||
|
||
if resp.Diagnostics.HasError() { | ||
return | ||
} | ||
|
||
op := operations.NewDeleteClusterParamsWithContext(ctx). | ||
WithInput(&models.DeleteClusterRequest{ | ||
ClusterID: state.ClusterID.ValueStringPointer(), | ||
// Force: true, | ||
}) | ||
|
||
if _, err := r.client.Dw.Operations.DeleteCluster(op); err != nil { | ||
resp.Diagnostics.AddError( | ||
"Error deleting data warehouse aws cluster", | ||
"Could not delete cluster, unexpected error: "+err.Error(), | ||
) | ||
return | ||
} | ||
} |
Oops, something went wrong.