From 3581133eb51ba887f23cbbd9ef8f6250c37b7568 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A9sz=C3=A1ros=20Gergely?= Date: Thu, 7 Nov 2024 17:47:31 +0100 Subject: [PATCH] PoC for env edit in case of AWS --- .../environments/model_aws_environment.go | 2 + .../environments/resource_aws_environment.go | 70 +++++++++++- .../environments/schema_aws_environment.go | 4 + .../update_aws_environment_service.go | 100 ++++++++++++++++++ 4 files changed, 171 insertions(+), 5 deletions(-) create mode 100644 resources/environments/update_aws_environment_service.go diff --git a/resources/environments/model_aws_environment.go b/resources/environments/model_aws_environment.go index 0f856c7f..4c60c9bd 100644 --- a/resources/environments/model_aws_environment.go +++ b/resources/environments/model_aws_environment.go @@ -100,4 +100,6 @@ type SecurityAccess struct { SecurityGroupIDForKnox types.String `tfsdk:"security_group_id_for_knox"` SecurityGroupIDsForKnox types.Set `tfsdk:"security_group_ids_for_knox"` + + GatewayNodeSecurityGroupID types.String `tfsdk:"gateway_node_security_group_id"` } diff --git a/resources/environments/resource_aws_environment.go b/resources/environments/resource_aws_environment.go index c2ef1775..c13ab678 100644 --- a/resources/environments/resource_aws_environment.go +++ b/resources/environments/resource_aws_environment.go @@ -12,6 +12,7 @@ package environments import ( "context" + "reflect" "github.com/hashicorp/terraform-plugin-framework/diag" "github.com/hashicorp/terraform-plugin-framework/resource" @@ -123,7 +124,65 @@ func (r *awsEnvironmentResource) Read(ctx context.Context, req resource.ReadRequ } func (r *awsEnvironmentResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { + var plan awsEnvironmentResourceModel + planDiags := req.Plan.Get(ctx, &plan) + resp.Diagnostics.Append(planDiags...) + if resp.Diagnostics.HasError() { + return + } + var state awsEnvironmentResourceModel + stateDiags := req.State.Get(ctx, &state) + resp.Diagnostics.Append(stateDiags...) + if resp.Diagnostics.HasError() { + return + } + + if state.EncryptionKeyArn != plan.EncryptionKeyArn { + if err := updateAwsDiskEncryptionParameters(ctx, r.client.Environments, plan); err != nil { + utils.AddEnvironmentDiagnosticsError(err, &resp.Diagnostics, "update disk encryption parameters") + return + } + state.EncryptionKeyArn = plan.EncryptionKeyArn + } + if plan.Authentication != nil && (plan.Authentication != state.Authentication) { + if err := updateSshKey(ctx, r.client.Environments, plan.Authentication, plan.EnvironmentName.ValueStringPointer()); err != nil { + utils.AddEnvironmentDiagnosticsError(err, &resp.Diagnostics, "update SSH key") + return + } + state.Authentication = plan.Authentication + } + if !reflect.DeepEqual(utils.FromSetValueToStringList(plan.SubnetIds), utils.FromSetValueToStringList(state.SubnetIds)) || + !reflect.DeepEqual(plan.EndpointAccessGatewaySubnetIds, state.EndpointAccessGatewaySubnetIds) { + if err := updateSubnet(ctx, r.client.Environments, plan); err != nil { + utils.AddEnvironmentDiagnosticsError(err, &resp.Diagnostics, "update subnet") + return + } + state.SubnetIds = plan.SubnetIds + state.EndpointAccessGatewaySubnetIds = plan.EndpointAccessGatewaySubnetIds + } + if plan.SecurityAccess != nil && (plan.SecurityAccess != state.SecurityAccess) { + if err := updateSecurityAccess(ctx, r.client.Environments, plan); err != nil { + utils.AddEnvironmentDiagnosticsError(err, &resp.Diagnostics, "update security access") + return + } + state.SecurityAccess = plan.SecurityAccess + } + if !plan.Tags.IsNull() && !reflect.DeepEqual(plan.Tags, state.Tags) { + if err := updateTags(ctx, r.client.Environments, plan); err != nil { + utils.AddEnvironmentDiagnosticsError(err, &resp.Diagnostics, "update tags") + return + } + state.Tags = plan.Tags + } + if plan.ProxyConfigName != state.ProxyConfigName { + if err := updateProxyConfig(ctx, r.client.Environments, plan); err != nil { + utils.AddEnvironmentDiagnosticsError(err, &resp.Diagnostics, "update proxy config") + return + } + state.ProxyConfigName = plan.ProxyConfigName + } + resp.State.Set(ctx, state) } func (r *awsEnvironmentResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { @@ -211,11 +270,12 @@ func toAwsEnvironmentResource(ctx context.Context, env *environmentsmodels.Envir sgIDsknox = model.SecurityAccess.SecurityGroupIDsForKnox } model.SecurityAccess = &SecurityAccess{ - Cidr: types.StringValue(env.SecurityAccess.Cidr), - DefaultSecurityGroupID: types.StringValue(env.SecurityAccess.DefaultSecurityGroupID), - DefaultSecurityGroupIDs: dsgIDs, - SecurityGroupIDForKnox: types.StringValue(env.SecurityAccess.SecurityGroupIDForKnox), - SecurityGroupIDsForKnox: sgIDsknox, + Cidr: types.StringValue(env.SecurityAccess.Cidr), + DefaultSecurityGroupID: types.StringValue(env.SecurityAccess.DefaultSecurityGroupID), + DefaultSecurityGroupIDs: dsgIDs, + SecurityGroupIDForKnox: types.StringValue(env.SecurityAccess.SecurityGroupIDForKnox), + SecurityGroupIDsForKnox: sgIDsknox, + GatewayNodeSecurityGroupID: model.SecurityAccess.GatewayNodeSecurityGroupID, } } model.Status = types.StringPointerValue(env.Status) diff --git a/resources/environments/schema_aws_environment.go b/resources/environments/schema_aws_environment.go index b01bcf49..276bb050 100644 --- a/resources/environments/schema_aws_environment.go +++ b/resources/environments/schema_aws_environment.go @@ -224,6 +224,10 @@ var AwsEnvironmentSchema = schema.Schema{ Optional: true, ElementType: types.StringType, }, + "gateway_node_security_group_id": schema.StringAttribute{ + Optional: true, + Computed: true, + }, }, }, "status": schema.StringAttribute{ diff --git a/resources/environments/update_aws_environment_service.go b/resources/environments/update_aws_environment_service.go new file mode 100644 index 00000000..fcb2a4bf --- /dev/null +++ b/resources/environments/update_aws_environment_service.go @@ -0,0 +1,100 @@ +// 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 environments + +import ( + "context" + "github.com/hashicorp/terraform-plugin-log/tflog" + + environmentsclient "github.com/cloudera/terraform-provider-cdp/cdp-sdk-go/gen/environments/client" + "github.com/cloudera/terraform-provider-cdp/cdp-sdk-go/gen/environments/client/operations" + environmentsmodels "github.com/cloudera/terraform-provider-cdp/cdp-sdk-go/gen/environments/models" + "github.com/cloudera/terraform-provider-cdp/utils" +) + +func updateAwsDiskEncryptionParameters(ctx context.Context, client *environmentsclient.Environments, plan awsEnvironmentResourceModel) error { + params := operations.NewUpdateAwsDiskEncryptionParametersParamsWithContext(ctx) + params.WithInput(&environmentsmodels.UpdateAwsDiskEncryptionParametersRequest{ + EncryptionKeyArn: plan.EncryptionKeyArn.ValueStringPointer(), + Environment: plan.EnvironmentName.ValueStringPointer(), + }) + tflog.Info(ctx, "Updating disk encryption parameters in the environment") + _, err := client.Operations.UpdateAwsDiskEncryptionParameters(params) + return err +} + +func updateSshKey(ctx context.Context, client *environmentsclient.Environments, authPlan *Authentication, env *string) error { + params := operations.NewUpdateSSHKeyParamsWithContext(ctx) + if !authPlan.PublicKey.IsNull() && authPlan.PublicKey.ValueString() != "" { + params.WithInput(&environmentsmodels.UpdateSSHKeyRequest{ + Environment: env, + NewPublicKey: authPlan.PublicKey.ValueString(), + ExistingPublicKeyID: "", + }) + } else { + params.WithInput(&environmentsmodels.UpdateSSHKeyRequest{ + Environment: env, + ExistingPublicKeyID: authPlan.PublicKeyID.ValueString(), + NewPublicKey: "", + }) + } + tflog.Info(ctx, "Updating SSH key in the environment") + _, err := client.Operations.UpdateSSHKey(params) + return err +} + +func updateSubnet(ctx context.Context, client *environmentsclient.Environments, plan awsEnvironmentResourceModel) error { + params := operations.NewUpdateSubnetParamsWithContext(ctx) + params.WithInput(&environmentsmodels.UpdateSubnetRequest{ + Environment: plan.EnvironmentName.ValueStringPointer(), + SubnetIds: utils.FromSetValueToStringList(plan.SubnetIds), + EndpointAccessGatewaySubnetIds: utils.FromSetValueToStringList(plan.EndpointAccessGatewaySubnetIds), + }) + tflog.Info(ctx, "Updating subnet(s) in the environment") + _, err := client.Operations.UpdateSubnet(params) + return err +} + +func updateSecurityAccess(ctx context.Context, client *environmentsclient.Environments, plan awsEnvironmentResourceModel) error { + params := operations.NewUpdateSecurityAccessParamsWithContext(ctx) + params.WithInput(&environmentsmodels.UpdateSecurityAccessRequest{ + DefaultSecurityGroupID: plan.SecurityAccess.DefaultSecurityGroupID.ValueStringPointer(), + Environment: plan.EnvironmentName.ValueStringPointer(), + GatewayNodeSecurityGroupID: plan.SecurityAccess.GatewayNodeSecurityGroupID.ValueStringPointer(), + }) + tflog.Info(ctx, "Updating security access in the environment") + _, err := client.Operations.UpdateSecurityAccess(params) + return err +} + +func updateTags(ctx context.Context, _ *environmentsclient.Environments, _ awsEnvironmentResourceModel) error { + tflog.Error(ctx, "UpdateTags is not implemented yet, it has to be present in BETA SDK beforehand") + return nil +} + +func updateProxyConfig(ctx context.Context, client *environmentsclient.Environments, plan awsEnvironmentResourceModel) error { + params := operations.NewUpdateProxyConfigParamsWithContext(ctx) + if plan.ProxyConfigName.IsNull() || plan.ProxyConfigName.ValueString() == "" { + params.WithInput(&environmentsmodels.UpdateProxyConfigRequest{ + Environment: plan.EnvironmentName.ValueStringPointer(), + RemoveProxy: true, + }) + tflog.Info(ctx, "Removing proxy configuration from the environment") + } else { + params.WithInput(&environmentsmodels.UpdateProxyConfigRequest{ + Environment: plan.EnvironmentName.ValueStringPointer(), + ProxyConfigName: plan.ProxyConfigName.ValueString(), + }) + tflog.Info(ctx, "Updating proxy configuration in the environment") + } + _, err := client.Operations.UpdateProxyConfig(params) + return err +}