From dbdf29013b4aef7deac6a430718570f24645877f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A9sz=C3=A1ros=20Gergely?= Date: Fri, 1 Dec 2023 16:56:01 +0100 Subject: [PATCH] CDPCP-10967 - GCP environment creation Terraform Resource fails due to incorrect value returned for storage location base --- resources/environments/converter_gcp.go | 30 +++- resources/environments/converter_gcp_test.go | 170 +++++++++++++++++++ 2 files changed, 193 insertions(+), 7 deletions(-) diff --git a/resources/environments/converter_gcp.go b/resources/environments/converter_gcp.go index cf8f1d2d..1a606716 100644 --- a/resources/environments/converter_gcp.go +++ b/resources/environments/converter_gcp.go @@ -80,19 +80,35 @@ func toGcpEnvironmentResource(ctx context.Context, env *environmentsmodels.Envir tflog.Info(ctx, "about to convert log storage.") if env.LogStorage != nil { if env.LogStorage.GcpDetails != nil { + backupStorageLocationBase := "" + if model.LogStorage != nil && !model.LogStorage.BackupStorageLocationBase.IsNull() && + !model.LogStorage.BackupStorageLocationBase.IsUnknown() { + backupStorageLocationBase = model.LogStorage.BackupStorageLocationBase.ValueString() + } model.LogStorage = &GcpLogStorage{ - StorageLocationBase: types.StringValue(env.LogStorage.GcpDetails.StorageLocationBase), - BackupStorageLocationBase: types.StringValue(env.LogStorage.GcpDetails.ServiceAccountEmail), + StorageLocationBase: types.StringValue(env.LogStorage.GcpDetails.StorageLocationBase), + BackupStorageLocationBase: func(base string) types.String { + if len(base) > 0 { + return types.StringValue(base) + } + return types.StringNull() + }(backupStorageLocationBase), } } } tflog.Info(ctx, "about to convert network.") if env.Network != nil { - subnets := model.ExistingNetworkParams.SubnetNames - model.ExistingNetworkParams = &ExistingNetworkParams{ - NetworkName: types.StringValue(*env.Network.Gcp.NetworkName), - SharedProjectId: types.StringValue(env.Network.Gcp.SharedProjectID), - SubnetNames: subnets, + if model.ExistingNetworkParams != nil { + model.ExistingNetworkParams = &ExistingNetworkParams{ + NetworkName: types.StringValue(*env.Network.Gcp.NetworkName), + SharedProjectId: types.StringValue(env.Network.Gcp.SharedProjectID), + SubnetNames: model.ExistingNetworkParams.SubnetNames, + } + } else { + model.ExistingNetworkParams = &ExistingNetworkParams{ + NetworkName: types.StringValue(*env.Network.Gcp.NetworkName), + SharedProjectId: types.StringValue(env.Network.Gcp.SharedProjectID), + } } } tflog.Info(ctx, "about to convert proxy config.") diff --git a/resources/environments/converter_gcp_test.go b/resources/environments/converter_gcp_test.go index 93ce2f81..30d077ee 100644 --- a/resources/environments/converter_gcp_test.go +++ b/resources/environments/converter_gcp_test.go @@ -12,14 +12,21 @@ package environments import ( "context" + "github.com/go-openapi/strfmt" "github.com/hashicorp/terraform-plugin-framework/attr" "github.com/hashicorp/terraform-plugin-framework/types" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" "testing" + environmentsmodels "github.com/cloudera/terraform-provider-cdp/cdp-sdk-go/gen/environments/models" "github.com/cloudera/terraform-provider-cdp/utils" ) +type GcpEnvironmentResourceModelMock struct { + mock.Mock +} + func TestToGcpEnvironmentRequestRootFields(t *testing.T) { testObject := createFilledGcpEnvironmentResourceModel() @@ -79,6 +86,27 @@ func TestToGcpEnvironmentRequestFreeIpa(t *testing.T) { assert.Equal(t, testObject.FreeIpa.InstanceType.ValueString(), result.FreeIpa.InstanceType) } +func TestToGcpEnvironmentResourceRootFields(t *testing.T) { + testModel := &gcpEnvironmentResourceModel{} + testEnv := createFilledEnvironment() + + toGcpEnvironmentResource(context.TODO(), testEnv, testModel, getTestPollingOption(), nil) + + stringExists(t, *testEnv.Crn, testModel.Crn) + stringExists(t, *testEnv.Region, testModel.Region) + stringExists(t, *testEnv.Status, testModel.Status) + stringExists(t, testEnv.Description, testModel.Description) + stringExists(t, testEnv.StatusReason, testModel.StatusReason) + stringExists(t, *testEnv.CredentialName, testModel.CredentialName) + stringExists(t, *testEnv.EnvironmentName, testModel.EnvironmentName) +} + +func stringExists(t *testing.T, expected string, underTest types.String) { + assert.True(t, !underTest.IsNull()) + assert.True(t, !underTest.IsUnknown()) + assert.Equal(t, expected, underTest.ValueString()) +} + func createFilledGcpEnvironmentResourceModel() *gcpEnvironmentResourceModel { return &gcpEnvironmentResourceModel{ EnvironmentName: types.StringValue("someEnvironmentName"), @@ -122,6 +150,148 @@ func createFilledGcpEnvironmentResourceModel() *gcpEnvironmentResourceModel { } } +func createFilledEnvironment() *environmentsmodels.Environment { + return &environmentsmodels.Environment{ + Authentication: &environmentsmodels.Authentication{ + LoginUserName: "someLoginUserName", + PublicKey: "somePublicKey", + PublicKeyID: "somePublicKeyID", + }, + AwsDetails: &environmentsmodels.EnvironmentAwsDetails{}, + BackupStorage: &environmentsmodels.BackupStorage{ + AwsDetails: &environmentsmodels.BackupStorageAwsDetails{ + InstanceProfile: "someInstanceProfile", + StorageLocationBase: "someStorageLocationBase", + }, + AzureDetails: &environmentsmodels.BackupStorageAzureDetails{ + ManagedIdentity: "someManagedIdentity", + StorageLocationBase: "someStorageLocationBase", + }, + Enabled: true, + GcpDetails: &environmentsmodels.BackupStorageGcpDetails{ + ServiceAccountEmail: "someServiceAccountEmail", + StorageLocationBase: "someStorageLocationBase", + }, + }, + CloudPlatform: func(s string) *string { return &s }("someCloudPlatform"), + Created: strfmt.NewDateTime(), + Creator: "someone", + CredentialName: func(s string) *string { return &s }("someCredential"), + Crn: func(s string) *string { return &s }("someCrn"), + Description: "someDescription", + EnvironmentName: func(s string) *string { return &s }("someEnvironmentName"), + Freeipa: &environmentsmodels.FreeipaDetails{ + Crn: "someFreeIpaCrn", + Domain: "someDomain", + Hostname: "someHostname", + Instances: []*environmentsmodels.FreeIpaInstance{{ + AttachedVolumes: []*environmentsmodels.AttachedVolumeDetail{ + { + Count: 1, + Size: 1, + VolumeType: "someVolumeType", + }, + }, + AvailabilityZone: "someAvailabilityZone", + DiscoveryFQDN: "someDiscoveryFQDN", + InstanceGroup: "someInstanceGroup", + InstanceID: "someInstanceID", + InstanceStatus: "someInstanceStatus", + InstanceStatusReason: "someInstanceStatusReason", + InstanceType: "someInstanceType", + InstanceVMType: "someInstanceVMType", + LifeCycle: "someLifeCycle", + PrivateIP: "somePrivateIP", + PublicIP: "somePublicIP", + SSHPort: 1, + SubnetID: "someSubnetID", + }}, + Recipes: []string{"someFreeIpaRecipe"}, + ServerIP: []string{"someServerIp"}, + }, + GcpDetails: &environmentsmodels.EnvironmentGcpDetails{}, + LogStorage: &environmentsmodels.LogStorage{ + AwsDetails: &environmentsmodels.LogStorageAwsDetails{ + InstanceProfile: "someInstanceProfile", + StorageLocationBase: "someStorageLocationBase", + }, + AzureDetails: &environmentsmodels.LogStorageAzureDetails{ + ManagedIdentity: "someManagedIdentity", + StorageLocationBase: "someStorageLocationBase", + }, + Enabled: func(b bool) *bool { return &b }(true), + GcpDetails: &environmentsmodels.LogStorageGcpDetails{ + ServiceAccountEmail: "someServiceAccountEmail", + StorageLocationBase: "someStorageLocationBase", + }, + }, + Network: &environmentsmodels.Network{ + Aws: &environmentsmodels.NetworkAwsParams{}, + Azure: &environmentsmodels.NetworkAzureParams{ + AksPrivateDNSZoneID: "someAksPrivateDNSZoneID", + DatabasePrivateDNSZoneID: "someDatabasePrivateDNSZoneID", + EnableOutboundLoadBalancer: true, + NetworkID: func(s string) *string { return &s }("someNetworkID"), + ResourceGroupName: func(s string) *string { return &s }("someResourceGroupName"), + UsePublicIP: func(b bool) *bool { return &b }(true), + }, + EndpointAccessGatewayScheme: "someEndpointAccessGatewayScheme", + EndpointAccessGatewaySubnetIds: []string{"someEndpointAccessGatewaySubnetId"}, + Gcp: &environmentsmodels.NetworkGcpParams{ + NetworkName: func(s string) *string { return &s }("someNetworkName"), + SharedProjectID: "someSharedProjectID", + UsePublicIP: func(b bool) *bool { return &b }(true), + }, + NetworkCidr: "someNetworkCidr", + NetworkName: func(s string) *string { return &s }("someNetworkName"), + SubnetIds: []string{"someSubnetId"}, + SubnetMetadata: map[string]environmentsmodels.CloudSubnet{ + "someSubnetMetadata": { + AvailabilityZone: "someAvailabilityZone", + Cidr: "someCidr", + SubnetID: "someSubnetID", + SubnetName: "someSubnetName", + }, + }, + }, + ProxyConfig: &environmentsmodels.ProxyConfig{ + Crn: func(s string) *string { return &s }("someProxyCrn"), + Description: "someDescription", + Host: func(s string) *string { return &s }("someHost"), + NoProxyHosts: "someNoProxyHosts", + Password: "somePassword", + Port: func(i int32) *int32 { return &i }(int32(1)), + Protocol: func(s string) *string { return &s }("someProtocol"), + ProxyConfigName: func(s string) *string { return &s }("someProxyConfigName"), + User: "someUser", + }, + Region: func(s string) *string { return &s }("someRegion"), + ReportDeploymentLogs: true, + SecurityAccess: &environmentsmodels.SecurityAccess{ + Cidr: "someCidr", + DefaultSecurityGroupID: "someDefaultSecurityGroupID", + SecurityGroupIDForKnox: "someSecurityGroupIDForKnox", + }, + Status: func(s string) *string { return &s }("someStatus"), + StatusReason: "someStatusReason", + Tags: &environmentsmodels.EnvironmentTags{ + Defaults: map[string]string{ + "someDefaultKey": "someDefaultValue", + }, + UserDefined: map[string]string{ + "someUserDefinedKey": "someUserDefinedValue", + }, + }, + TunnelEnabled: true, + TunnelType: environmentsmodels.TunnelTypeCCMV2, + WorkloadAnalytics: true, + } +} + +func getTestPollingOption() *utils.PollingOptions { + return &utils.PollingOptions{PollingTimeout: types.Int64Value(1234)} +} + func createListOfStrings() types.List { var elems []attr.Value elems = make([]attr.Value, 0)