Skip to content

Commit

Permalink
updating freeipa as well v1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
gregito committed Nov 26, 2024
1 parent 41f82db commit ebd8204
Show file tree
Hide file tree
Showing 4 changed files with 306 additions and 92 deletions.
29 changes: 29 additions & 0 deletions resources/environments/environment_action_util.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"github.com/hashicorp/terraform-plugin-log/tflog"

"github.com/cloudera/terraform-provider-cdp/cdp-sdk-go/cdp"
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"
Expand Down Expand Up @@ -106,3 +107,31 @@ func waitForCreateEnvironmentWithDiagnosticHandle(ctx context.Context, client *c
}
return descEnvResp.GetPayload().Environment, nil
}

func waitForStartEnvironmentWithDiagnosticHandle(ctx context.Context, client *environmentsclient.Environments, id string, envName string, resp *resource.UpdateResponse, options *utils.PollingOptions,
stateSaverCb func(*environmentsmodels.Environment)) (*environmentsmodels.Environment, error) {
if err := waitForEnvironmentToBeAvailable(id, timeoutOneHour, callFailureThreshold, client, ctx, options, stateSaverCb); err != nil {
utils.AddEnvironmentDiagnosticsError(err, &resp.Diagnostics, "starting Environment failed")
return nil, err
}

environmentName := envName
descParams := operations.NewDescribeEnvironmentParamsWithContext(ctx)
descParams.WithInput(&environmentsmodels.DescribeEnvironmentRequest{
EnvironmentName: &environmentName,
})
descEnvResp, err := client.Operations.DescribeEnvironment(descParams)
if err != nil {
if isEnvNotFoundError(err) {
resp.Diagnostics.AddWarning("Resource not found on provider", "Environment not found, removing from state.")
tflog.Warn(ctx, "Environment not found, removing from state", map[string]interface{}{
"id": id,
})
resp.State.RemoveResource(ctx)
return nil, err
}
utils.AddEnvironmentDiagnosticsError(err, &resp.Diagnostics, "starting Environment failed")
return nil, err
}
return descEnvResp.GetPayload().Environment, nil
}
57 changes: 56 additions & 1 deletion resources/environments/polling.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,12 @@ func waitForEnvironmentToBeAvailable(environmentName string, fallbackTimeout tim
"ENVIRONMENT_RESOURCE_ENCRYPTION_INITIALIZATION_IN_PROGRESS",
"ENVIRONMENT_VALIDATION_IN_PROGRESS",
"ENVIRONMENT_INITIALIZATION_IN_PROGRESS",
"FREEIPA_CREATION_IN_PROGRESS"},
"FREEIPA_CREATION_IN_PROGRESS",
"START_DATALAKE_STARTED",
"START_DATAHUB_STARTED",
"START_SYNCHRONIZE_USERS_STARTED",
"START_FREEIPA_STARTED",
"ENV_STOPPED"},
Target: []string{"AVAILABLE"},
Delay: 5 * time.Second,
Timeout: *timeout,
Expand Down Expand Up @@ -151,6 +156,56 @@ func waitForEnvironmentToBeAvailable(environmentName string, fallbackTimeout tim
return err
}

func waitForEnvironmentToBeStopped(environmentName string, fallbackTimeout time.Duration, callFailureThresholdDefault int, client *client.Environments, ctx context.Context, pollingOptions *utils.PollingOptions) error {
timeout, err := utils.CalculateTimeoutOrDefault(ctx, pollingOptions, fallbackTimeout)
if err != nil {
return err
}
callFailureThreshold, failureThresholdError := utils.CalculateCallFailureThresholdOrDefault(ctx, pollingOptions, callFailureThresholdDefault)
if failureThresholdError != nil {
return failureThresholdError
}
callFailedCount := 0
stateConf := &retry.StateChangeConf{
Pending: []string{
"STOP_DATAHUB_STARTED",
"STOP_DATALAKE_STARTED",
"STOP_FREEIPA_STARTED",
"VERTICAL_SCALE_ON_FREEIPA_IN_PROGRESS",
},
Target: []string{"ENV_STOPPED"},
Delay: 5 * time.Second,
Timeout: *timeout,
PollInterval: 10 * time.Second,
Refresh: func() (interface{}, string, error) {
tflog.Debug(ctx, fmt.Sprintf("About to describe environment %s", environmentName))
params := operations.NewDescribeEnvironmentParamsWithContext(ctx)
params.WithInput(&environmentsmodels.DescribeEnvironmentRequest{EnvironmentName: &environmentName})
resp, err := client.Operations.DescribeEnvironment(params)
if err != nil {
if isEnvNotFoundError(err) {
tflog.Debug(ctx, fmt.Sprintf("Recoverable error describing environment: %s", err))
callFailedCount = 0
return nil, "", nil
}
callFailedCount++
if callFailedCount <= callFailureThreshold {
tflog.Warn(ctx, fmt.Sprintf("Error describing environment with call failure due to [%s] but threshold limit is not reached yet (%d out of %d).", err.Error(), callFailedCount, callFailureThreshold))
return nil, "", nil
}
tflog.Error(ctx, fmt.Sprintf("Error describing environment (due to: %s) and call failure threshold limit exceeded.", err))
return nil, "", err
}
callFailedCount = 0
tflog.Info(ctx, fmt.Sprintf("Described environment's status: %s", *resp.GetPayload().Environment.Status))
return checkResponseStatusForError(resp)
},
}
_, err = stateConf.WaitForStateContext(ctx)

return err
}

func checkResponseStatusForError(resp *operations.DescribeEnvironmentOK) (interface{}, string, error) {
if utils.ContainsAsSubstring([]string{"FAILED", "ERROR"}, *resp.GetPayload().Environment.Status) {
return nil, "", fmt.Errorf("unexpected Enviornment status: %s. Reason: %s", *resp.GetPayload().Environment.Status, resp.GetPayload().Environment.StatusReason)
Expand Down
194 changes: 103 additions & 91 deletions resources/environments/resource_aws_environment.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"github.com/hashicorp/terraform-plugin-log/tflog"

"github.com/cloudera/terraform-provider-cdp/cdp-sdk-go/cdp"
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"
Expand Down Expand Up @@ -127,105 +128,20 @@ func (r *awsEnvironmentResource) Update(ctx context.Context, req resource.Update
var plan awsEnvironmentResourceModel
var state awsEnvironmentResourceModel
planDiags := req.Plan.Get(ctx, &plan)
stateDiags := req.State.Get(ctx, &state)
var stateDiags = req.State.Get(ctx, &state)
resp.Diagnostics.Append(planDiags...)
resp.Diagnostics.Append(stateDiags...)
if resp.Diagnostics.HasError() {
tflog.Error(ctx, "Got Error while trying to set plan")
return
}

if plan.CredentialName.ValueString() != state.CredentialName.ValueString() {
params := operations.NewChangeEnvironmentCredentialParamsWithContext(ctx)
params.WithInput(&environmentsmodels.ChangeEnvironmentCredentialRequest{
CredentialName: plan.CredentialName.ValueStringPointer(),
EnvironmentName: state.EnvironmentName.ValueStringPointer(),
})
_, err := r.client.Environments.Operations.ChangeEnvironmentCredential(params)
if err != nil {
utils.AddEnvironmentDiagnosticsError(err, &resp.Diagnostics, "change AWS Environment credential")
return
}
stateDiags = resp.State.Set(ctx, state)
resp.Diagnostics.Append(stateDiags...)
if resp.Diagnostics.HasError() {
return
}
}
updateEnvironment(ctx, &plan, &state, r.client.Environments, resp)
updateFreeIpa(ctx, &plan, &state, r.client.Environments, resp)

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
stateDiags = resp.State.Set(ctx, state)
resp.Diagnostics.Append(stateDiags...)
if resp.Diagnostics.HasError() {
return
}
}
if plan.Authentication != nil && !reflect.DeepEqual(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
stateDiags = resp.State.Set(ctx, state)
resp.Diagnostics.Append(stateDiags...)
if resp.Diagnostics.HasError() {
return
}
}
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
stateDiags = resp.State.Set(ctx, state)
resp.Diagnostics.Append(stateDiags...)
if resp.Diagnostics.HasError() {
return
}
}
if plan.SecurityAccess != nil && !reflect.DeepEqual(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
stateDiags = resp.State.Set(ctx, state)
resp.Diagnostics.Append(stateDiags...)
if resp.Diagnostics.HasError() {
return
}
}
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
stateDiags = resp.State.Set(ctx, state)
resp.Diagnostics.Append(stateDiags...)
if resp.Diagnostics.HasError() {
return
}
}
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
stateDiags = resp.State.Set(ctx, state)
resp.Diagnostics.Append(stateDiags...)
if resp.Diagnostics.HasError() {
return
}
stateDiags = resp.State.Set(ctx, state)
if resp.Diagnostics.HasError() {
return
}
resp.State.Set(ctx, state)
}
Expand Down Expand Up @@ -335,3 +251,99 @@ func toAwsEnvironmentResource(ctx context.Context, env *environmentsmodels.Envir
model.TunnelType = types.StringValue(string(env.TunnelType))
model.WorkloadAnalytics = types.BoolValue(env.WorkloadAnalytics)
}

func updateEnvironment(ctx context.Context, plan *awsEnvironmentResourceModel, state *awsEnvironmentResourceModel, client *environmentsclient.Environments, resp *resource.UpdateResponse) *resource.UpdateResponse {
if plan.CredentialName.ValueString() != state.CredentialName.ValueString() {
params := operations.NewChangeEnvironmentCredentialParamsWithContext(ctx)
params.WithInput(&environmentsmodels.ChangeEnvironmentCredentialRequest{
CredentialName: plan.CredentialName.ValueStringPointer(),
EnvironmentName: state.EnvironmentName.ValueStringPointer(),
})
_, err := client.Operations.ChangeEnvironmentCredential(params)
if err != nil {
utils.AddEnvironmentDiagnosticsError(err, &resp.Diagnostics, "change AWS Environment credential")
return resp
}
}

if state.EncryptionKeyArn != plan.EncryptionKeyArn {
if err := updateAwsDiskEncryptionParameters(ctx, client, *plan); err != nil {
utils.AddEnvironmentDiagnosticsError(err, &resp.Diagnostics, "update disk encryption parameters")
return resp
}
state.EncryptionKeyArn = plan.EncryptionKeyArn
}

if plan.Authentication != nil && !reflect.DeepEqual(plan.Authentication, state.Authentication) {
if err := updateSshKey(ctx, client, plan.Authentication, plan.EnvironmentName.ValueStringPointer()); err != nil {
utils.AddEnvironmentDiagnosticsError(err, &resp.Diagnostics, "update SSH key")
return resp
}
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, client, *plan); err != nil {
utils.AddEnvironmentDiagnosticsError(err, &resp.Diagnostics, "update subnet")
return resp
}
state.SubnetIds = plan.SubnetIds
state.EndpointAccessGatewaySubnetIds = plan.EndpointAccessGatewaySubnetIds
}

if plan.SecurityAccess != nil && !reflect.DeepEqual(plan.SecurityAccess, state.SecurityAccess) {
if err := updateSecurityAccess(ctx, client, *plan); err != nil {
utils.AddEnvironmentDiagnosticsError(err, &resp.Diagnostics, "update security access")
return resp
}
state.SecurityAccess = plan.SecurityAccess
}

if !plan.Tags.IsNull() && !reflect.DeepEqual(plan.Tags, state.Tags) {
if err := updateTags(ctx, client, *plan); err != nil {
utils.AddEnvironmentDiagnosticsError(err, &resp.Diagnostics, "update tags")
return resp
}
state.Tags = plan.Tags
}

if plan.ProxyConfigName != state.ProxyConfigName {
if err := updateProxyConfig(ctx, client, *plan); err != nil {
utils.AddEnvironmentDiagnosticsError(err, &resp.Diagnostics, "update proxy config")
return resp
}
state.ProxyConfigName = plan.ProxyConfigName
}
return resp
}

func startEnvironment(ctx context.Context, state *awsEnvironmentResourceModel, resp *resource.UpdateResponse, client *environmentsclient.Environments) error {
if !(state.PollingOptions != nil && state.PollingOptions.Async.ValueBool()) {
stateSaver := func(env *environmentsmodels.Environment) {
toAwsEnvironmentResource(ctx, utils.LogEnvironmentSilently(ctx, env, describeLogPrefix), state, state.PollingOptions, &resp.Diagnostics)
}
_, err := waitForStartEnvironmentWithDiagnosticHandle(ctx, client, state.ID.ValueString(), state.EnvironmentName.ValueString(), resp, state.PollingOptions, stateSaver)
if err != nil {
return err
}
}
return nil
}

func stopAndWaitForEnvironment(ctx context.Context, environment string, pollingOptions *utils.PollingOptions, resp *resource.UpdateResponse, client *environmentsclient.Environments) error {
params := operations.NewStopEnvironmentParamsWithContext(ctx)
params.WithInput(&environmentsmodels.StopEnvironmentRequest{
EnvironmentName: &environment,
})
_, err := client.Operations.StopEnvironment(params)
if err != nil {
utils.AddEnvironmentDiagnosticsError(err, &resp.Diagnostics, "stop Environment")
return err
}
if err := waitForEnvironmentToBeStopped(environment, timeoutOneHour, callFailureThreshold, client, ctx, pollingOptions); err != nil {
utils.AddEnvironmentDiagnosticsError(err, &resp.Diagnostics, "create Environment failed")
return err
}
return nil
}
Loading

0 comments on commit ebd8204

Please sign in to comment.