diff --git a/go.mod b/go.mod index eafc025f3d..b6de773aef 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,7 @@ require ( github.com/hashicorp/hcl/v2 v2.24.0 github.com/hashicorp/terraform-json v0.27.2 github.com/hashicorp/terraform-plugin-sdk/v2 v2.40.1 - github.com/hashicorp/terraform-provider-google-beta v1.20.1-0.20260724005318-d2d4e6be437e + github.com/hashicorp/terraform-provider-google-beta v1.20.1-0.20260724172529-d04cccc8eafe github.com/mitchellh/go-homedir v1.1.0 github.com/pkg/errors v0.9.1 github.com/stretchr/testify v1.11.1 @@ -27,6 +27,7 @@ require ( github.com/gammazero/workerpool v1.1.3 github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 github.com/hashicorp/go-cleanhttp v0.5.2 + github.com/hashicorp/go-version v1.9.0 github.com/hashicorp/terraform-plugin-framework v1.19.0 github.com/hashicorp/terraform-plugin-framework-validators v0.19.0 github.com/sethvargo/go-retry v0.3.0 @@ -72,7 +73,6 @@ require ( github.com/googleapis/gax-go/v2 v2.22.0 // indirect github.com/hashicorp/go-hclog v1.6.3 // indirect github.com/hashicorp/go-uuid v1.0.3 // indirect - github.com/hashicorp/go-version v1.9.0 // indirect github.com/hashicorp/logutils v1.0.0 // indirect github.com/hashicorp/terraform-plugin-framework-timeouts v0.5.0 // indirect github.com/hashicorp/terraform-plugin-go v0.31.0 // indirect diff --git a/go.sum b/go.sum index 5bc4d635a7..00f7afd9d0 100644 --- a/go.sum +++ b/go.sum @@ -184,8 +184,8 @@ github.com/hashicorp/terraform-plugin-sdk/v2 v2.40.1 h1:2yPUd7esMOpuTaG3y1iEla1i github.com/hashicorp/terraform-plugin-sdk/v2 v2.40.1/go.mod h1:sq8qsxh+PwdvTQFcd17kfCoBgQo46ADNMvCpKE7t/gY= github.com/hashicorp/terraform-plugin-testing v1.15.0 h1:/fimKyl0YgD7aAtJkuuAZjwBASXhCIwWqMbDLnKLMe4= github.com/hashicorp/terraform-plugin-testing v1.15.0/go.mod h1:bGXMw7bE95EiZhSBV3rM2W8TiffaPTDuLS+HFI/lIYs= -github.com/hashicorp/terraform-provider-google-beta v1.20.1-0.20260724005318-d2d4e6be437e h1:7mt518z/EIWi3Y15HGFT4SZsC4IbSYlj/SIACIDB9tw= -github.com/hashicorp/terraform-provider-google-beta v1.20.1-0.20260724005318-d2d4e6be437e/go.mod h1:2tXyGr+pX+Tjj6rpi3JfT+mjqRWkvgsEzcvrfV1/XUk= +github.com/hashicorp/terraform-provider-google-beta v1.20.1-0.20260724172529-d04cccc8eafe h1:MDJHjlqi7x51cC7mjqUHxmjpBaUkMKvzaRd8nIhL/hQ= +github.com/hashicorp/terraform-provider-google-beta v1.20.1-0.20260724172529-d04cccc8eafe/go.mod h1:2tXyGr+pX+Tjj6rpi3JfT+mjqRWkvgsEzcvrfV1/XUk= github.com/hashicorp/terraform-registry-address v0.4.0 h1:S1yCGomj30Sao4l5BMPjTGZmCNzuv7/GDTDX99E9gTk= github.com/hashicorp/terraform-registry-address v0.4.0/go.mod h1:LRS1Ay0+mAiRkUyltGT+UHWkIqTFvigGn/LbMshfflE= github.com/hashicorp/terraform-svchost v0.1.1 h1:EZZimZ1GxdqFRinZ1tpJwVxxt49xc/S52uzrw4x0jKQ= diff --git a/pkg/services/compute/compute_backend_service.go b/pkg/services/compute/compute_backend_service.go index e825ff7d4c..723ae197af 100644 --- a/pkg/services/compute/compute_backend_service.go +++ b/pkg/services/compute/compute_backend_service.go @@ -957,6 +957,34 @@ For example: orca_load_report, tls.protocol`, Supported values: INCLUDE_ALL_OPTIONAL, EXCLUDE_ALL_OPTIONAL, CUSTOM. Possible values: ["INCLUDE_ALL_OPTIONAL", "EXCLUDE_ALL_OPTIONAL", "CUSTOM"]`, AtLeastOneOf: []string{"log_config.0.enable", "log_config.0.optional_mode", "log_config.0.sample_rate"}, }, + "request_headers": { + Type: schema.TypeList, + Optional: true, + Description: `This field can only be specified if logging is enabled for this backend service and if the BackendService protocol is one of HTTP, HTTPS, HTTP2 and GRPC. Contains a list of request headers to be logged.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "header_name": { + Type: schema.TypeString, + Required: true, + Description: `The header name to match on for logging.`, + }, + }, + }, + }, + "response_headers": { + Type: schema.TypeList, + Optional: true, + Description: `This field can only be specified if logging is enabled for this backend service and if the BackendService protocol is one of HTTP, HTTPS, HTTP2 and GRPC. Contains a list of response headers to be logged.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "header_name": { + Type: schema.TypeString, + Required: true, + Description: `The header name to match on for logging.`, + }, + }, + }, + }, "sample_rate": { Type: schema.TypeFloat, Optional: true, diff --git a/pkg/services/compute/compute_backend_service_cai2hcl.go b/pkg/services/compute/compute_backend_service_cai2hcl.go index 6e1f0ccfb2..6164e01b38 100644 --- a/pkg/services/compute/compute_backend_service_cai2hcl.go +++ b/pkg/services/compute/compute_backend_service_cai2hcl.go @@ -1704,6 +1704,10 @@ func flattenComputeBackendServiceLogConfig(v interface{}, d *schema.ResourceData flattenComputeBackendServiceLogConfigOptionalMode(original["optionalMode"], d, config) transformed["optional_fields"] = flattenComputeBackendServiceLogConfigOptionalFields(original["optionalFields"], d, config) + transformed["request_headers"] = + flattenComputeBackendServiceLogConfigRequestHeaders(original["loggingHttpRequestHeaders"], d, config) + transformed["response_headers"] = + flattenComputeBackendServiceLogConfigResponseHeaders(original["loggingHttpResponseHeaders"], d, config) if tgcresource.AllValuesAreNil(transformed) { return nil } @@ -1726,6 +1730,66 @@ func flattenComputeBackendServiceLogConfigOptionalFields(v interface{}, d *schem return v } +func flattenComputeBackendServiceLogConfigRequestHeaders(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return v + } + l := v.([]interface{}) + transformed := make([]interface{}, 0, len(l)) + for _, raw := range l { + original := raw.(map[string]interface{}) + if len(original) < 1 { + // Do not include empty json objects coming back from the api + continue + } + transformed = append(transformed, map[string]interface{}{ + "header_name": flattenComputeBackendServiceLogConfigRequestHeadersHeaderName(original["headerName"], d, config), + }) + } + return transformed +} + +func flattenComputeBackendServiceLogConfigRequestHeadersHeaderName(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return "unknown" + } + transformed := v.(string) + if transformed == "" { + return "unknown" + } + return v +} + +func flattenComputeBackendServiceLogConfigResponseHeaders(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return v + } + l := v.([]interface{}) + transformed := make([]interface{}, 0, len(l)) + for _, raw := range l { + original := raw.(map[string]interface{}) + if len(original) < 1 { + // Do not include empty json objects coming back from the api + continue + } + transformed = append(transformed, map[string]interface{}{ + "header_name": flattenComputeBackendServiceLogConfigResponseHeadersHeaderName(original["headerName"], d, config), + }) + } + return transformed +} + +func flattenComputeBackendServiceLogConfigResponseHeadersHeaderName(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return "unknown" + } + transformed := v.(string) + if transformed == "" { + return "unknown" + } + return v +} + func flattenComputeBackendServiceServiceLbPolicy(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { if v == nil { return nil diff --git a/pkg/services/compute/compute_backend_service_tfplan2cai.go b/pkg/services/compute/compute_backend_service_tfplan2cai.go index b793dfb437..b7c185e47e 100644 --- a/pkg/services/compute/compute_backend_service_tfplan2cai.go +++ b/pkg/services/compute/compute_backend_service_tfplan2cai.go @@ -1799,6 +1799,20 @@ func expandComputeBackendServiceLogConfig(v interface{}, d tpgresource.Terraform transformed["optionalFields"] = transformedOptionalFields } + transformedRequestHeaders, err := expandComputeBackendServiceLogConfigRequestHeaders(original["request_headers"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedRequestHeaders); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["loggingHttpRequestHeaders"] = transformedRequestHeaders + } + + transformedResponseHeaders, err := expandComputeBackendServiceLogConfigResponseHeaders(original["response_headers"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedResponseHeaders); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["loggingHttpResponseHeaders"] = transformedResponseHeaders + } + return transformed, nil } @@ -1818,6 +1832,64 @@ func expandComputeBackendServiceLogConfigOptionalFields(v interface{}, d tpgreso return v, nil } +func expandComputeBackendServiceLogConfigRequestHeaders(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + if v == nil { + return nil, nil + } + l := v.([]interface{}) + req := make([]interface{}, 0, len(l)) + for _, raw := range l { + if raw == nil { + continue + } + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedHeaderName, err := expandComputeBackendServiceLogConfigRequestHeadersHeaderName(original["header_name"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedHeaderName); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["headerName"] = transformedHeaderName + } + + req = append(req, transformed) + } + return req, nil +} + +func expandComputeBackendServiceLogConfigRequestHeadersHeaderName(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandComputeBackendServiceLogConfigResponseHeaders(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + if v == nil { + return nil, nil + } + l := v.([]interface{}) + req := make([]interface{}, 0, len(l)) + for _, raw := range l { + if raw == nil { + continue + } + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedHeaderName, err := expandComputeBackendServiceLogConfigResponseHeadersHeaderName(original["header_name"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedHeaderName); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["headerName"] = transformedHeaderName + } + + req = append(req, transformed) + } + return req, nil +} + +func expandComputeBackendServiceLogConfigResponseHeadersHeaderName(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + func expandComputeBackendServiceServiceLbPolicy(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { return v, nil } diff --git a/pkg/services/compute/compute_instance_helpers.go b/pkg/services/compute/compute_instance_helpers.go index 535a112279..2ec0f316f8 100644 --- a/pkg/services/compute/compute_instance_helpers.go +++ b/pkg/services/compute/compute_instance_helpers.go @@ -150,6 +150,12 @@ func expandScheduling(v interface{}) (map[string]interface{}, error) { if v, ok := original["provisioning_model"]; ok { result["provisioningModel"] = v.(string) } + + omitDurations := false + if pm, ok := result["provisioningModel"].(string); ok && pm == "RESERVATION_BOUND" { + omitDurations = true + } + if v, ok := original["instance_termination_action"]; ok { result["instanceTerminationAction"] = v.(string) } @@ -161,7 +167,9 @@ func expandScheduling(v interface{}) (map[string]interface{}, error) { if err != nil { return nil, err } - result["maxRunDuration"] = transformedMaxRunDuration + if transformedMaxRunDuration != nil || !omitDurations { + result["maxRunDuration"] = transformedMaxRunDuration + } } if v, ok := original["on_instance_stop_action"]; ok { @@ -169,14 +177,18 @@ func expandScheduling(v interface{}) (map[string]interface{}, error) { if err != nil { return nil, err } - result["onInstanceStopAction"] = transformedOnInstanceStopAction + if transformedOnInstanceStopAction != nil || !omitDurations { + result["onInstanceStopAction"] = transformedOnInstanceStopAction + } } if v, ok := original["local_ssd_recovery_timeout"]; ok { transformedLocalSsdRecoveryTimeout, err := expandComputeLocalSsdRecoveryTimeout(v) if err != nil { return nil, err } - result["localSsdRecoveryTimeout"] = transformedLocalSsdRecoveryTimeout + if transformedLocalSsdRecoveryTimeout != nil || !omitDurations { + result["localSsdRecoveryTimeout"] = transformedLocalSsdRecoveryTimeout + } } if v, ok := original["termination_time"]; ok && v.(string) != "" { result["terminationTime"] = v.(string) @@ -514,7 +526,7 @@ func flattenNetworkInterfaces(d *schema.ResourceData, config *transport_tpg.Conf "subnetwork": tpgresource.ConvertSelfLinkToV1(subnetwork), "subnetwork_project": subnet.Project, "access_config": ac, - "alias_ip_range": flattenAliasIpRange(d, aliasIpRanges, i), + "alias_ip_range": FlattenAliasIpRangeHTTP(d, aliasIpRanges, i), "nic_type": nicType, "stack_type": stackType, diff --git a/pkg/services/compute/compute_instance_http_helpers.go b/pkg/services/compute/compute_instance_http_helpers.go new file mode 100644 index 0000000000..ae898c4276 --- /dev/null +++ b/pkg/services/compute/compute_instance_http_helpers.go @@ -0,0 +1,488 @@ +package compute + +import ( + "fmt" + "reflect" + "strconv" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v7/pkg/tpgresource" +) + +var DEFAULT_SCRATCH_DISK_SIZE_GB = 375 +var VALID_SCRATCH_DISK_SIZES_GB = []int{375, 3000, 3500, 7000, 14000} + +// FlattenAliasIpRangeHTTP replaces the legacy SDK-dependent flattenAliasIpRange. +// It operates directly on API JSON response maps, allowing all direct-HTTP compute resources to share it. +func FlattenAliasIpRangeHTTP(d *schema.ResourceData, ranges []interface{}, i int) []map[string]interface{} { + prefix := fmt.Sprintf("network_interface.%d", i) + + configData := []map[string]interface{}{} + for _, item := range d.Get(prefix + ".alias_ip_range").([]interface{}) { + configData = append(configData, item.(map[string]interface{})) + } + + apiData := make([]map[string]interface{}, 0, len(ranges)) + for _, raw := range ranges { + ipRange, ok := raw.(map[string]interface{}) + if !ok || ipRange == nil { + continue + } + + ipCidrRange, _ := ipRange["ipCidrRange"].(string) + subnetworkRangeName, _ := ipRange["subnetworkRangeName"].(string) + + apiData = append(apiData, map[string]interface{}{ + "ip_cidr_range": ipCidrRange, + "subnetwork_range_name": subnetworkRangeName, + }) + } + + // Preserve config ordering to prevent permadiffs + sorted, err := tpgresource.SortMapsByConfigOrder(configData, apiData, "ip_cidr_range") + if err != nil { + return apiData + } + return sorted +} + +func FlattenDisksHTTP(disks []interface{}, d *schema.ResourceData, defaultProject string) ([]map[string]interface{}, error) { + apiDisks := make([]map[string]interface{}, len(disks)) + for i, diskRaw := range disks { + disk := diskRaw.(map[string]interface{}) + configDisk := d.Get(fmt.Sprintf("disk.%d", i)).(map[string]any) + apiDisk, err := FlattenDiskHTTP(disk, configDisk, defaultProject) + if err != nil { + return nil, err + } + apiDisks[i] = apiDisk + } + return reorderDisks(d.Get("disk").([]interface{}), apiDisks), nil +} + +func FlattenDiskHTTP(disk map[string]interface{}, configDisk map[string]any, defaultProject string) (map[string]interface{}, error) { + diskMap := make(map[string]interface{}) + diskMap["source_image_encryption_key"] = configDisk["source_image_encryption_key"] + diskMap["source_snapshot"] = configDisk["source_snapshot"] + diskMap["source_snapshot_encryption_key"] = configDisk["source_snapshot_encryption_key"] + + if initParamsRaw, ok := disk["initializeParams"]; ok && initParamsRaw != nil { + initParams := initParamsRaw.(map[string]interface{}) + if srcImg, ok := initParams["sourceImage"].(string); ok && srcImg != "" { + path, err := resolveImageRefToRelativeURI(defaultProject, srcImg) + if err != nil { + return nil, err + } + diskMap["source_image"] = path + } else { + diskMap["source_image"] = "" + } + if v, ok := initParams["diskType"]; ok { + diskMap["disk_type"] = v + } + if v, ok := initParams["provisionedIops"]; ok { + diskMap["provisioned_iops"] = ParseIntHTTP(v) + } + if v, ok := initParams["provisionedThroughput"]; ok { + diskMap["provisioned_throughput"] = ParseIntHTTP(v) + } + if v, ok := initParams["diskName"]; ok { + diskMap["disk_name"] = v + } else { + diskMap["disk_name"] = "" + } + var diskLabels map[string]string + if lRaw, ok := initParams["labels"].(map[string]interface{}); ok { + diskLabels = make(map[string]string) + for k, v := range lRaw { + if str, ok := v.(string); ok { + diskLabels[k] = str + } + } + } + diskMap["labels"] = diskLabels + + var diskSizeGb int + if v, ok := disk["diskSizeGb"]; ok { + diskSizeGb = ParseIntHTTP(v) + } + var initDiskSizeGb int + if v, ok := initParams["diskSizeGb"]; ok { + initDiskSizeGb = ParseIntHTTP(v) + } + diskTypeStr, _ := disk["type"].(string) + + if diskSizeGb == 0 && initDiskSizeGb == 0 && diskTypeStr == "SCRATCH" { + diskMap["disk_size_gb"] = DEFAULT_SCRATCH_DISK_SIZE_GB + } else if diskSizeGb != 0 { + diskMap["disk_size_gb"] = diskSizeGb + } else { + diskMap["disk_size_gb"] = initDiskSizeGb + } + + var rPolicies []string + if rpRaw, ok := initParams["resourcePolicies"].([]interface{}); ok { + for _, v := range rpRaw { + if str, ok := v.(string); ok { + rPolicies = append(rPolicies, str) + } + } + } + diskMap["resource_policies"] = rPolicies + + var rmTags map[string]string + if rmtRaw, ok := initParams["resourceManagerTags"].(map[string]interface{}); ok { + rmTags = make(map[string]string) + for k, v := range rmtRaw { + if str, ok := v.(string); ok { + rmTags[k] = str + } + } + } + diskMap["resource_manager_tags"] = rmTags + if sp, ok := initParams["storagePool"].(string); ok && sp != "" { + diskMap["storage_pool"] = tpgresource.GetResourceNameFromSelfLink(sp) + } + } + + if encKeyRaw, ok := disk["diskEncryptionKey"]; ok && encKeyRaw != nil { + encKey := encKeyRaw.(map[string]interface{}) + encryption := make([]map[string]interface{}, 1) + encryption[0] = make(map[string]interface{}) + encryption[0]["kms_key_self_link"] = encKey["kmsKeyName"] + if diskEncryptionKey, ok := configDisk["disk_encryption_key"].([]interface{}); ok && len(diskEncryptionKey) > 0 { + if encryptionKeyMap, ok := diskEncryptionKey[0].(map[string]interface{}); ok { + if kmsSa, ok := encryptionKeyMap["kms_key_service_account"].(string); ok && kmsSa != "" { + encryption[0]["kms_key_service_account"] = kmsSa + } + } + } + diskMap["disk_encryption_key"] = encryption + } + + var guestOsFeaturesSlice []interface{} + if gofRaw, ok := disk["guestOsFeatures"].([]interface{}); ok { + for _, fRaw := range gofRaw { + if f, ok := fRaw.(map[string]interface{}); ok { + if typ, ok := f["type"].(string); ok && typ != "" { + guestOsFeaturesSlice = append(guestOsFeaturesSlice, map[string]interface{}{"type": typ}) + } + } + } + } + if v, ok := disk["autoDelete"]; ok { + diskMap["auto_delete"] = v + } else { + diskMap["auto_delete"] = false + } + if v, ok := disk["boot"]; ok { + diskMap["boot"] = v + } else { + diskMap["boot"] = false + } + if v, ok := disk["deviceName"]; ok { + diskMap["device_name"] = v + } else { + diskMap["device_name"] = "" + } + if v, ok := disk["interface"]; ok { + diskMap["interface"] = v + } else { + diskMap["interface"] = "" + } + if src, ok := disk["source"].(string); ok { + diskMap["source"] = tpgresource.ConvertSelfLinkToV1(src) + } else { + diskMap["source"] = "" + } + if v, ok := disk["mode"]; ok { + diskMap["mode"] = v + } else { + diskMap["mode"] = "" + } + if v, ok := disk["type"]; ok { + diskMap["type"] = v + } else { + diskMap["type"] = "" + } + diskMap["guest_os_features"] = flattenComputeInstanceGuestOsFeatures(guestOsFeaturesSlice) + diskMap["architecture"] = configDisk["architecture"] + + return diskMap, nil +} + +func FlattenSchedulingHTTP(resp map[string]interface{}) []map[string]interface{} { + schedulingMap := map[string]interface{}{} + v_ohm, _ := resp["onHostMaintenance"].(string) + schedulingMap["on_host_maintenance"] = v_ohm + v_p, _ := resp["preemptible"].(bool) + schedulingMap["preemptible"] = v_p + schedulingMap["min_node_cpus"] = ParseIntHTTP(resp["minNodeCpus"]) + v_pm, _ := resp["provisioningModel"].(string) + schedulingMap["provisioning_model"] = v_pm + v_ita, _ := resp["instanceTerminationAction"].(string) + schedulingMap["instance_termination_action"] = v_ita + schedulingMap["availability_domain"] = ParseIntHTTP(resp["availabilityDomain"]) + v_tt, _ := resp["terminationTime"].(string) + schedulingMap["termination_time"] = v_tt + if v, ok := resp["automaticRestart"]; ok { + schedulingMap["automatic_restart"] = v + } + v_sgos, _ := resp["skipGuestOsShutdown"].(bool) + schedulingMap["skip_guest_os_shutdown"] = v_sgos + + if maxDurRaw, ok := resp["maxRunDuration"]; ok && maxDurRaw != nil { + maxDur := maxDurRaw.(map[string]interface{}) + schedulingMap["max_run_duration"] = []map[string]interface{}{ + { + "seconds": ParseIntHTTP(maxDur["seconds"]), + "nanos": ParseIntHTTP(maxDur["nanos"]), + }, + } + } + + if stopRaw, ok := resp["onInstanceStopAction"]; ok && stopRaw != nil { + stop := stopRaw.(map[string]interface{}) + schedulingMap["on_instance_stop_action"] = []map[string]interface{}{ + { + "discard_local_ssd": stop["discardLocalSsd"], + }, + } + } + + if timeoutRaw, ok := resp["localSsdRecoveryTimeout"]; ok && timeoutRaw != nil { + timeout := timeoutRaw.(map[string]interface{}) + schedulingMap["local_ssd_recovery_timeout"] = []map[string]interface{}{ + { + "seconds": ParseIntHTTP(timeout["seconds"]), + "nanos": ParseIntHTTP(timeout["nanos"]), + }, + } + } + + if pndRaw, ok := resp["preemptionNoticeDuration"]; ok && pndRaw != nil { + pnd := pndRaw.(map[string]interface{}) + schedulingMap["preemption_notice_duration"] = []map[string]interface{}{ + { + "seconds": ParseIntHTTP(pnd["seconds"]), + "nanos": ParseIntHTTP(pnd["nanos"]), + }, + } + } + + if naRaw, ok := resp["nodeAffinities"].([]interface{}); ok && naRaw != nil { + nodeAffinities := make([]map[string]interface{}, len(naRaw)) + for i, naItem := range naRaw { + na := naItem.(map[string]interface{}) + nodeAffinity := map[string]interface{}{ + "key": na["key"], + "operator": na["operator"], + } + if valsRaw, ok := na["values"].([]interface{}); ok { + nodeAffinity["values"] = valsRaw + } + nodeAffinities[i] = nodeAffinity + } + schedulingMap["node_affinities"] = nodeAffinities + } + + return []map[string]interface{}{schedulingMap} +} + +func ParseIntHTTP(v interface{}) int { + if v == nil { + return 0 + } + switch val := v.(type) { + case string: + parsed, _ := strconv.Atoi(val) + return parsed + case float64: + return int(val) + case int: + return val + case int64: + return int(val) + default: + return 0 + } +} + +func FlattenWorkloadIdentityConfigHTTP(v interface{}) []map[string]interface{} { + if v == nil { + return nil + } + config := v.(map[string]interface{}) + return []map[string]interface{}{ + { + "identity": config["identity"], + "identity_certificate_enabled": config["identityCertificateEnabled"], + }, + } +} + +type diskCharacteristics struct { + mode string + diskType string + diskSizeGb string + autoDelete bool + sourceImage string + provisionedIops string + provisionedThroughput string +} + +func diskCharacteristicsFromMap(m map[string]interface{}) diskCharacteristics { + dc := diskCharacteristics{} + if v := m["mode"]; v == nil || v.(string) == "" { + // mode has an apply-time default of READ_WRITE + dc.mode = "READ_WRITE" + } else { + dc.mode = v.(string) + } + + if v := m["disk_type"]; v != nil { + dc.diskType = v.(string) + } + + if v := m["disk_size_gb"]; v != nil { + // Terraform and GCP return ints as different types (int vs int64), so just + // use strings to compare for simplicity. + dc.diskSizeGb = fmt.Sprintf("%v", v) + } + + if v := m["auto_delete"]; v != nil { + dc.autoDelete = v.(bool) + } + + if v := m["source_image"]; v != nil { + dc.sourceImage = v.(string) + } + + if v := m["provisioned_iops"]; v != nil { + // Terraform and GCP return ints as different types (int vs int64), so just + // use strings to compare for simplicity. + dc.provisionedIops = fmt.Sprintf("%v", v) + } + + if v := m["provisioned_throughput"]; v != nil { + // Terraform and GCP return ints as different types (int vs int64), so just + // use strings to compare for simplicity. + dc.provisionedThroughput = fmt.Sprintf("%v", v) + } + + return dc +} + +func reorderDisks(configDisks []interface{}, apiDisks []map[string]interface{}) []map[string]interface{} { + if len(apiDisks) != len(configDisks) { + // There are different numbers of disks in state and returned from the API, so it's not + // worth trying to reorder them since it'll be a diff anyway. + return apiDisks + } + + result := make([]map[string]interface{}, len(apiDisks)) + + /* + Disks aren't necessarily returned from the API in the same order they were sent, so gather + information about the ones in state that we can use to map it back. We can't do this by + just looping over all of the disks, because you could end up matching things in the wrong + order. For example, if the config disks contain the following disks: + disk 1: auto delete = false, size = 10 + disk 2: auto delete = false, size = 10, device name = "disk 2" + disk 3: type = scratch + And the disks returned from the API are: + disk a: auto delete = false, size = 10, device name = "disk 2" + disk b: auto delete = false, size = 10, device name = "disk 1" + disk c: type = scratch + Then disk a will match disk 1, disk b won't match any disk, and c will match 3, making the + final order a, c, b, which is wrong. To get disk a to match disk 2, we have to go in order + of fields most specifically able to identify a disk to least. + */ + disksByDeviceName := map[string]int{} + scratchDisksByInterface := map[string][]int{} + attachedDisksBySource := map[string]int{} + attachedDisksByDiskName := map[string]int{} + attachedDisksByCharacteristics := []int{} + + for i, d := range configDisks { + if i == 0 { + // boot disk + continue + } + disk := d.(map[string]interface{}) + if v := disk["device_name"]; v.(string) != "" { + disksByDeviceName[v.(string)] = i + } else if v := disk["type"]; v.(string) == "SCRATCH" { + iface := disk["interface"].(string) + scratchDisksByInterface[iface] = append(scratchDisksByInterface[iface], i) + } else if v := disk["source"]; v.(string) != "" { + attachedDisksBySource[v.(string)] = i + } else if v := disk["disk_name"]; v.(string) != "" { + attachedDisksByDiskName[v.(string)] = i + } else { + attachedDisksByCharacteristics = append(attachedDisksByCharacteristics, i) + } + } + + // Align the disks, going from the most specific criteria to the least. + for _, apiDisk := range apiDisks { + // 1. This resource only works if the boot disk is the first one (which should be fixed + // separately), so put the boot disk first. + if apiDisk["boot"].(bool) { + result[0] = apiDisk + + // 2. All disks have a unique device name + } else if i, ok := disksByDeviceName[apiDisk["device_name"].(string)]; ok { + result[i] = apiDisk + + // 3. Scratch disks are all the same except device name and interface, so match them by + // interface. + } else if apiDisk["type"].(string) == "SCRATCH" { + iface := apiDisk["interface"].(string) + indexes := scratchDisksByInterface[iface] + if len(indexes) > 0 { + result[indexes[0]] = apiDisk + scratchDisksByInterface[iface] = indexes[1:] + } else { + result = append(result, apiDisk) + } + + // 4. Each attached disk will have a different source, so match by that. + } else if i, ok := attachedDisksBySource[apiDisk["source"].(string)]; ok { + result[i] = apiDisk + + // 5. If a disk was created for this resource via initializeParams, it will have a + // unique name. + } else if v, ok := apiDisk["disk_name"]; ok && attachedDisksByDiskName[v.(string)] != 0 { + result[attachedDisksByDiskName[v.(string)]] = apiDisk + + // 6. If no unique keys exist on this disk, then use a combination of its remaining + // characteristics to see whether it matches exactly. + } else { + found := false + for arrayIndex, i := range attachedDisksByCharacteristics { + configDisk := configDisks[i].(map[string]interface{}) + stateDc := diskCharacteristicsFromMap(configDisk) + readDc := diskCharacteristicsFromMap(apiDisk) + if reflect.DeepEqual(stateDc, readDc) { + result[i] = apiDisk + attachedDisksByCharacteristics = append(attachedDisksByCharacteristics[:arrayIndex], attachedDisksByCharacteristics[arrayIndex+1:]...) + found = true + break + } + } + if !found { + result = append(result, apiDisk) + } + } + } + + // Remove nils from map in case there were disks that could not be matched + ds := []map[string]interface{}{} + for _, d := range result { + if d != nil { + ds = append(ds, d) + } + } + return ds +} diff --git a/pkg/services/compute/compute_interconnect.go b/pkg/services/compute/compute_interconnect.go index 3a94bdf8cb..5652f12d20 100644 --- a/pkg/services/compute/compute_interconnect.go +++ b/pkg/services/compute/compute_interconnect.go @@ -106,9 +106,8 @@ bundle, not the speed of the entire bundle. Can take one of the following values "location": { Type: schema.TypeString, Required: true, - ForceNew: true, DiffSuppressFunc: tpgresource.CompareSelfLinkOrResourceName, - Description: `URL of the InterconnectLocation object that represents where this connection is to be provisioned. + Description: `URL of the InterconnectLocation object that represents where this connection is requested to be provisioned. Specifies the location inside Google's Networks.`, }, "name": { @@ -308,6 +307,12 @@ Note: 'MACSEC' is a legacy value and has the same meaning as 'IF_MACSEC'.`, Description: `All of labels (key/value pairs) present on the resource in GCP, including the labels configured through Terraform, other clients and services.`, Elem: &schema.Schema{Type: schema.TypeString}, }, + "effective_location": { + Type: schema.TypeString, + Computed: true, + Description: `URL of the InterconnectLocation object that represents where this connection is to be provisioned. +Specifies the location inside Google's Networks.`, + }, "expected_outages": { Type: schema.TypeList, Computed: true, diff --git a/pkg/services/compute/compute_interconnect_cai2hcl.go b/pkg/services/compute/compute_interconnect_cai2hcl.go index 61dde1c6a8..31988bf626 100644 --- a/pkg/services/compute/compute_interconnect_cai2hcl.go +++ b/pkg/services/compute/compute_interconnect_cai2hcl.go @@ -133,7 +133,7 @@ func (c *ComputeInterconnectCai2hclConverter) convertResourceData(asset caiasset } hclData := make(map[string]interface{}) - outputFields := map[string]struct{}{"available_features": struct{}{}, "circuit_infos": struct{}{}, "creation_timestamp": struct{}{}, "effective_labels": struct{}{}, "expected_outages": struct{}{}, "google_ip_address": struct{}{}, "google_reference_id": struct{}{}, "interconnect_attachments": struct{}{}, "interconnect_groups": struct{}{}, "label_fingerprint": struct{}{}, "operational_status": struct{}{}, "peer_ip_address": struct{}{}, "provisioned_link_count": struct{}{}, "satisfies_pzs": struct{}{}, "state": struct{}{}, "terraform_labels": struct{}{}, "wire_groups": struct{}{}} + outputFields := map[string]struct{}{"available_features": struct{}{}, "circuit_infos": struct{}{}, "creation_timestamp": struct{}{}, "effective_labels": struct{}{}, "effective_location": struct{}{}, "expected_outages": struct{}{}, "google_ip_address": struct{}{}, "google_reference_id": struct{}{}, "interconnect_attachments": struct{}{}, "interconnect_groups": struct{}{}, "label_fingerprint": struct{}{}, "operational_status": struct{}{}, "peer_ip_address": struct{}{}, "provisioned_link_count": struct{}{}, "satisfies_pzs": struct{}{}, "state": struct{}{}, "terraform_labels": struct{}{}, "wire_groups": struct{}{}} utils.ParseUrlParamValuesFromAssetName(asset.Name, "//compute.googleapis.com/projects/{{project}}/global/interconnects/{{name}}", outputFields, hclData) hclData["description"] = flattenComputeInterconnectDescription(res["description"], d, config) diff --git a/pkg/services/compute/compute_region_backend_service.go b/pkg/services/compute/compute_region_backend_service.go index f18507e461..80e7f1297b 100644 --- a/pkg/services/compute/compute_region_backend_service.go +++ b/pkg/services/compute/compute_region_backend_service.go @@ -882,6 +882,34 @@ If logging is enabled, logs will be exported to Stackdriver.`, Supported values: INCLUDE_ALL_OPTIONAL, EXCLUDE_ALL_OPTIONAL, CUSTOM. Possible values: ["INCLUDE_ALL_OPTIONAL", "EXCLUDE_ALL_OPTIONAL", "CUSTOM"]`, AtLeastOneOf: []string{"log_config.0.enable", "log_config.0.optional_mode", "log_config.0.sample_rate"}, }, + "request_headers": { + Type: schema.TypeList, + Optional: true, + Description: `This field can only be specified if logging is enabled for this backend service and if the BackendService protocol is one of HTTP, HTTPS, HTTP2 and GRPC. Contains a list of request headers to be logged.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "header_name": { + Type: schema.TypeString, + Required: true, + Description: `The header name to match on for logging.`, + }, + }, + }, + }, + "response_headers": { + Type: schema.TypeList, + Optional: true, + Description: `This field can only be specified if logging is enabled for this backend service and if the BackendService protocol is one of HTTP, HTTPS, HTTP2 and GRPC. Contains a list of response headers to be logged.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "header_name": { + Type: schema.TypeString, + Required: true, + Description: `The header name to match on for logging.`, + }, + }, + }, + }, "sample_rate": { Type: schema.TypeFloat, Optional: true, diff --git a/pkg/services/compute/compute_region_backend_service_cai2hcl.go b/pkg/services/compute/compute_region_backend_service_cai2hcl.go index 58f36c733f..ee33af6874 100644 --- a/pkg/services/compute/compute_region_backend_service_cai2hcl.go +++ b/pkg/services/compute/compute_region_backend_service_cai2hcl.go @@ -1553,6 +1553,10 @@ func flattenComputeRegionBackendServiceLogConfig(v interface{}, d *schema.Resour flattenComputeRegionBackendServiceLogConfigOptionalMode(original["optionalMode"], d, config) transformed["optional_fields"] = flattenComputeRegionBackendServiceLogConfigOptionalFields(original["optionalFields"], d, config) + transformed["request_headers"] = + flattenComputeRegionBackendServiceLogConfigRequestHeaders(original["loggingHttpRequestHeaders"], d, config) + transformed["response_headers"] = + flattenComputeRegionBackendServiceLogConfigResponseHeaders(original["loggingHttpResponseHeaders"], d, config) if tgcresource.AllValuesAreNil(transformed) { return nil } @@ -1575,6 +1579,66 @@ func flattenComputeRegionBackendServiceLogConfigOptionalFields(v interface{}, d return v } +func flattenComputeRegionBackendServiceLogConfigRequestHeaders(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return v + } + l := v.([]interface{}) + transformed := make([]interface{}, 0, len(l)) + for _, raw := range l { + original := raw.(map[string]interface{}) + if len(original) < 1 { + // Do not include empty json objects coming back from the api + continue + } + transformed = append(transformed, map[string]interface{}{ + "header_name": flattenComputeRegionBackendServiceLogConfigRequestHeadersHeaderName(original["headerName"], d, config), + }) + } + return transformed +} + +func flattenComputeRegionBackendServiceLogConfigRequestHeadersHeaderName(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return "unknown" + } + transformed := v.(string) + if transformed == "" { + return "unknown" + } + return v +} + +func flattenComputeRegionBackendServiceLogConfigResponseHeaders(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return v + } + l := v.([]interface{}) + transformed := make([]interface{}, 0, len(l)) + for _, raw := range l { + original := raw.(map[string]interface{}) + if len(original) < 1 { + // Do not include empty json objects coming back from the api + continue + } + transformed = append(transformed, map[string]interface{}{ + "header_name": flattenComputeRegionBackendServiceLogConfigResponseHeadersHeaderName(original["headerName"], d, config), + }) + } + return transformed +} + +func flattenComputeRegionBackendServiceLogConfigResponseHeadersHeaderName(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return "unknown" + } + transformed := v.(string) + if transformed == "" { + return "unknown" + } + return v +} + func flattenComputeRegionBackendServiceNetwork(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { if v == nil { return v diff --git a/pkg/services/compute/compute_region_backend_service_tfplan2cai.go b/pkg/services/compute/compute_region_backend_service_tfplan2cai.go index 61ba24e761..a000dd1142 100644 --- a/pkg/services/compute/compute_region_backend_service_tfplan2cai.go +++ b/pkg/services/compute/compute_region_backend_service_tfplan2cai.go @@ -1628,6 +1628,20 @@ func expandComputeRegionBackendServiceLogConfig(v interface{}, d tpgresource.Ter transformed["optionalFields"] = transformedOptionalFields } + transformedRequestHeaders, err := expandComputeRegionBackendServiceLogConfigRequestHeaders(original["request_headers"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedRequestHeaders); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["loggingHttpRequestHeaders"] = transformedRequestHeaders + } + + transformedResponseHeaders, err := expandComputeRegionBackendServiceLogConfigResponseHeaders(original["response_headers"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedResponseHeaders); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["loggingHttpResponseHeaders"] = transformedResponseHeaders + } + return transformed, nil } @@ -1647,6 +1661,64 @@ func expandComputeRegionBackendServiceLogConfigOptionalFields(v interface{}, d t return v, nil } +func expandComputeRegionBackendServiceLogConfigRequestHeaders(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + if v == nil { + return nil, nil + } + l := v.([]interface{}) + req := make([]interface{}, 0, len(l)) + for _, raw := range l { + if raw == nil { + continue + } + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedHeaderName, err := expandComputeRegionBackendServiceLogConfigRequestHeadersHeaderName(original["header_name"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedHeaderName); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["headerName"] = transformedHeaderName + } + + req = append(req, transformed) + } + return req, nil +} + +func expandComputeRegionBackendServiceLogConfigRequestHeadersHeaderName(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandComputeRegionBackendServiceLogConfigResponseHeaders(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + if v == nil { + return nil, nil + } + l := v.([]interface{}) + req := make([]interface{}, 0, len(l)) + for _, raw := range l { + if raw == nil { + continue + } + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedHeaderName, err := expandComputeRegionBackendServiceLogConfigResponseHeadersHeaderName(original["header_name"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedHeaderName); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["headerName"] = transformedHeaderName + } + + req = append(req, transformed) + } + return req, nil +} + +func expandComputeRegionBackendServiceLogConfigResponseHeadersHeaderName(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + func expandComputeRegionBackendServiceNetwork(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { f, err := tpgresource.ParseGlobalFieldValue("networks", v.(string), "project", d, config, true) if err != nil { diff --git a/pkg/services/container/resource_container_cluster.go b/pkg/services/container/resource_container_cluster.go index 3ebec9ec00..b9ca13dd2d 100644 --- a/pkg/services/container/resource_container_cluster.go +++ b/pkg/services/container/resource_container_cluster.go @@ -118,6 +118,7 @@ var ( "addons_config.0.slice_controller_config", "addons_config.0.pod_snapshot_config", "addons_config.0.slurm_operator_config", + "addons_config.0.node_readiness_config", } privateClusterConfigKeys = []string{ @@ -658,6 +659,22 @@ func ResourceContainerCluster() *schema.Resource { }, }, }, + "node_readiness_config": { + Type: schema.TypeList, + Optional: true, + Computed: true, + AtLeastOneOf: addonsConfigKeys, + MaxItems: 1, + Description: `The status of the Node Readiness Controller addon.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enabled": { + Type: schema.TypeBool, + Required: true, + }, + }, + }, + }, }, }, }, diff --git a/pkg/services/container/resource_container_cluster_cai2hcl.go b/pkg/services/container/resource_container_cluster_cai2hcl.go index aac0edc0ab..94e5345610 100644 --- a/pkg/services/container/resource_container_cluster_cai2hcl.go +++ b/pkg/services/container/resource_container_cluster_cai2hcl.go @@ -642,6 +642,19 @@ func flattenClusterAddonsConfig(v interface{}, enableAutopilot bool) []map[strin } } + if val, ok := c["nodeReadinessConfig"].(map[string]interface{}); ok { + enabled := false + if v, ok := val["enabled"]; ok && v != nil { + enabled = v.(bool) + } + + result["node_readiness_config"] = []map[string]interface{}{ + { + "enabled": enabled, + }, + } + } + return []map[string]interface{}{result} } diff --git a/pkg/services/container/resource_container_cluster_tfplan2cai.go b/pkg/services/container/resource_container_cluster_tfplan2cai.go index c26c956aa2..d28c4b0b30 100644 --- a/pkg/services/container/resource_container_cluster_tfplan2cai.go +++ b/pkg/services/container/resource_container_cluster_tfplan2cai.go @@ -506,6 +506,14 @@ func expandClusterAddonsConfig(configured interface{}) *container.AddonsConfig { } } + if v, ok := config["node_readiness_config"]; ok && len(v.([]interface{})) > 0 { + addon := v.([]interface{})[0].(map[string]interface{}) + ac.NodeReadinessConfig = &container.NodeReadinessConfig{ + Enabled: addon["enabled"].(bool), + ForceSendFields: []string{"Enabled"}, + } + } + return ac } diff --git a/pkg/services/secretmanager/secret_manager_secret_version.go b/pkg/services/secretmanager/secret_manager_secret_version.go index 6a8e8c9ef0..738e427ecb 100644 --- a/pkg/services/secretmanager/secret_manager_secret_version.go +++ b/pkg/services/secretmanager/secret_manager_secret_version.go @@ -85,20 +85,19 @@ func ResourceSecretManagerSecretVersion() *schema.Resource { Default: 0, }, "secret_data": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - Description: `The secret data. Must be no larger than 64KiB.`, - Sensitive: true, - ConflictsWith: []string{}, + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: `The secret data. Must be no larger than 64KiB.`, + Sensitive: true, + ExactlyOneOf: []string{"secret_data", "secret_data_wo"}, }, "secret_data_wo": { - Type: schema.TypeString, - Optional: true, - Description: `The secret data. Must be no larger than 64KiB. For more info see [updating write-only arguments](/docs/providers/google/guides/using_write_only_arguments.html#updating-write-only-arguments)`, - WriteOnly: true, - ConflictsWith: []string{"secret_data"}, - RequiredWith: []string{}, + Type: schema.TypeString, + Optional: true, + Description: `The secret data. Must be no larger than 64KiB. For more info see [updating write-only arguments](/docs/providers/google/guides/using_write_only_arguments.html#updating-write-only-arguments)`, + WriteOnly: true, + ExactlyOneOf: []string{"secret_data", "secret_data_wo"}, }, "secret": { diff --git a/test/services/compute/compute_backend_service_generated_test.go b/test/services/compute/compute_backend_service_generated_test.go index 694407ca3f..9e4a621cb2 100644 --- a/test/services/compute/compute_backend_service_generated_test.go +++ b/test/services/compute/compute_backend_service_generated_test.go @@ -136,6 +136,9 @@ func TestAccComputeBackendService(t *testing.T) { { Name: "TestAccComputeBackendService_withLogConfigMode", }, + { + Name: "TestAccComputeBackendService_withLogConfigRequestResponseHeaders", + }, { Name: "TestAccComputeBackendService_trafficDirectorUpdateBasic", }, diff --git a/test/services/compute/compute_instance_generated_test.go b/test/services/compute/compute_instance_generated_test.go index fccf8ed878..a209d5456d 100644 --- a/test/services/compute/compute_instance_generated_test.go +++ b/test/services/compute/compute_instance_generated_test.go @@ -46,6 +46,9 @@ func TestAccComputeInstance(t *testing.T) { { Name: "TestAccComputeInstance_basic5", }, + { + Name: "TestAccComputeInstance_importBlockWithResourceIdentity", + }, { Name: "TestAccComputeInstance_metadataGceContainerDeclaration", }, diff --git a/test/services/compute/compute_region_backend_service_generated_test.go b/test/services/compute/compute_region_backend_service_generated_test.go index 17d1cb7d09..1f3ee67983 100644 --- a/test/services/compute/compute_region_backend_service_generated_test.go +++ b/test/services/compute/compute_region_backend_service_generated_test.go @@ -111,6 +111,9 @@ func TestAccComputeRegionBackendService(t *testing.T) { { Name: "TestAccComputeRegionBackendService_withLogConfig", }, + { + Name: "TestAccComputeRegionBackendService_withLogConfigRequestResponseHeaders", + }, { Name: "TestAccComputeRegionBackendService_zonalILB", }, diff --git a/test/services/container/container_cluster_generated_test.go b/test/services/container/container_cluster_generated_test.go index ed652ef4fb..044dabdd74 100644 --- a/test/services/container/container_cluster_generated_test.go +++ b/test/services/container/container_cluster_generated_test.go @@ -702,6 +702,15 @@ func TestAccContainerCluster(t *testing.T) { { Name: "TestAccContainerCluster_withNodePoolTaintConfig_none", }, + { + Name: "TestAccContainerCluster_desiredEmulatedVersion", + }, + { + Name: "TestAccContainerCluster_desiredEmulatedVersionAutopilot", + }, + { + Name: "TestAccContainerCluster_withNodeReadinessConfig", + }, } for _, tt := range tests { diff --git a/test/services/secretmanager/secret_manager_secret_version_generated_test.go b/test/services/secretmanager/secret_manager_secret_version_generated_test.go index be9888d3e6..f1d15d193f 100644 --- a/test/services/secretmanager/secret_manager_secret_version_generated_test.go +++ b/test/services/secretmanager/secret_manager_secret_version_generated_test.go @@ -51,6 +51,9 @@ func TestAccSecretManagerSecretVersion(t *testing.T) { { Name: "TestAccSecretManagerSecretVersion_secretVersionWithBase64StringSecretDataWriteOnlyExample", }, + { + Name: "TestAccSecretManagerSecretVersion_neitherSecretDataSet", + }, } for _, tt := range tests { diff --git a/tfplan2cai/converters/google/resources/services/chronicle/chronicle_big_query_export.go b/tfplan2cai/converters/google/resources/services/chronicle/chronicle_big_query_export.go new file mode 100644 index 0000000000..8a247968ba --- /dev/null +++ b/tfplan2cai/converters/google/resources/services/chronicle/chronicle_big_query_export.go @@ -0,0 +1,505 @@ +// ---------------------------------------------------------------------------- +// +// *** AUTO GENERATED CODE *** Type: MMv1 *** +// +// ---------------------------------------------------------------------------- +// +// This code is generated by Magic Modules using the following: +// +// Configuration: https://github.com/GoogleCloudPlatform/magic-modules/tree/main/mmv1/products/chronicle/BigQueryExport.yaml +// Template: https://github.com/GoogleCloudPlatform/magic-modules/tree/main/mmv1/templates/tgc/resource_converter.go.tmpl +// +// DO NOT EDIT this file directly. Any changes made to this file will be +// overwritten during the next generation cycle. +// +// ---------------------------------------------------------------------------- + +package chronicle + +import ( + "bytes" + "context" + "encoding/base64" + "encoding/json" + "fmt" + "log" + "reflect" + "regexp" + "slices" + "sort" + "strconv" + "strings" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/id" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/logging" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/structure" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + + "github.com/GoogleCloudPlatform/terraform-google-conversion/v7/tfplan2cai/converters/google/resources/cai" + "github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport" + "github.com/hashicorp/terraform-provider-google-beta/google-beta/verify" + + "google.golang.org/api/googleapi" +) + +var ( + _ = bytes.Clone + _ = context.WithCancel + _ = base64.StdEncoding + _ = fmt.Sprintf + _ = json.Marshal + _ = log.Print + _ = reflect.ValueOf + _ = regexp.Match + _ = slices.Min([]int{1}) + _ = sort.IntSlice{} + _ = strconv.Atoi + _ = strings.Trim + _ = time.Now + _ = diag.Diagnostic{} + _ = customdiff.All + _ = id.UniqueId + _ = logging.LogLevel + _ = retry.Retry + _ = schema.Noop + _ = structure.ExpandJsonFromString + _ = validation.All + _ = terraform.State{} + _ = tpgresource.SetLabels + _ = transport_tpg.Config{} + _ = verify.ProjectRegex + _ = googleapi.Error{} +) + +const ChronicleBigQueryExportAssetType string = "{{location}}-chronicle.googleapis.com/BigQueryExport" + +func ResourceConverterChronicleBigQueryExport() cai.ResourceConverter { + return cai.ResourceConverter{ + AssetType: ChronicleBigQueryExportAssetType, + Convert: GetChronicleBigQueryExportCaiObject, + } +} + +func GetChronicleBigQueryExportCaiObject(d tpgresource.TerraformResourceData, config *transport_tpg.Config) ([]cai.Asset, error) { + name, err := cai.AssetName(d, config, "//chronicle.googleapis.com/projects/{{project}}/locations/{{location}}/instances/{{instance}}/bigQueryExport") + if err != nil { + return []cai.Asset{}, err + } + if obj, err := GetChronicleBigQueryExportApiObject(d, config); err == nil { + return []cai.Asset{{ + Name: name, + Type: ChronicleBigQueryExportAssetType, + Resource: &cai.AssetResource{ + Version: "v1beta", + DiscoveryDocumentURI: "https://www.googleapis.com/discovery/v1/apis/{{location}}-chronicle/v1beta/rest", + DiscoveryName: "BigQueryExport", + Data: obj, + }, + }}, nil + } else { + return []cai.Asset{}, err + } +} + +func GetChronicleBigQueryExportApiObject(d tpgresource.TerraformResourceData, config *transport_tpg.Config) (map[string]interface{}, error) { + obj := make(map[string]interface{}) + bigQueryExportPackageProp, err := expandChronicleBigQueryExportBigQueryExportPackage(d.Get("big_query_export_package"), d, config) + if err != nil { + return nil, err + } else if v, ok := d.GetOkExists("big_query_export_package"); !tpgresource.IsEmptyValue(reflect.ValueOf(bigQueryExportPackageProp)) && (ok || !reflect.DeepEqual(v, bigQueryExportPackageProp)) { + obj["bigQueryExportPackage"] = bigQueryExportPackageProp + } + entityGraphSettingsProp, err := expandChronicleBigQueryExportEntityGraphSettings(d.Get("entity_graph_settings"), d, config) + if err != nil { + return nil, err + } else if v, ok := d.GetOkExists("entity_graph_settings"); !tpgresource.IsEmptyValue(reflect.ValueOf(entityGraphSettingsProp)) && (ok || !reflect.DeepEqual(v, entityGraphSettingsProp)) { + obj["entityGraphSettings"] = entityGraphSettingsProp + } + iocMatchesSettingsProp, err := expandChronicleBigQueryExportIocMatchesSettings(d.Get("ioc_matches_settings"), d, config) + if err != nil { + return nil, err + } else if v, ok := d.GetOkExists("ioc_matches_settings"); !tpgresource.IsEmptyValue(reflect.ValueOf(iocMatchesSettingsProp)) && (ok || !reflect.DeepEqual(v, iocMatchesSettingsProp)) { + obj["iocMatchesSettings"] = iocMatchesSettingsProp + } + ruleDetectionsSettingsProp, err := expandChronicleBigQueryExportRuleDetectionsSettings(d.Get("rule_detections_settings"), d, config) + if err != nil { + return nil, err + } else if v, ok := d.GetOkExists("rule_detections_settings"); !tpgresource.IsEmptyValue(reflect.ValueOf(ruleDetectionsSettingsProp)) && (ok || !reflect.DeepEqual(v, ruleDetectionsSettingsProp)) { + obj["ruleDetectionsSettings"] = ruleDetectionsSettingsProp + } + udmEventsAggregatesSettingsProp, err := expandChronicleBigQueryExportUdmEventsAggregatesSettings(d.Get("udm_events_aggregates_settings"), d, config) + if err != nil { + return nil, err + } else if v, ok := d.GetOkExists("udm_events_aggregates_settings"); !tpgresource.IsEmptyValue(reflect.ValueOf(udmEventsAggregatesSettingsProp)) && (ok || !reflect.DeepEqual(v, udmEventsAggregatesSettingsProp)) { + obj["udmEventsAggregatesSettings"] = udmEventsAggregatesSettingsProp + } + udmEventsSettingsProp, err := expandChronicleBigQueryExportUdmEventsSettings(d.Get("udm_events_settings"), d, config) + if err != nil { + return nil, err + } else if v, ok := d.GetOkExists("udm_events_settings"); !tpgresource.IsEmptyValue(reflect.ValueOf(udmEventsSettingsProp)) && (ok || !reflect.DeepEqual(v, udmEventsSettingsProp)) { + obj["udmEventsSettings"] = udmEventsSettingsProp + } + + return obj, nil +} + +func expandChronicleBigQueryExportBigQueryExportPackage(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandChronicleBigQueryExportEntityGraphSettings(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + if v == nil { + return nil, nil + } + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedDataFreshnessTime, err := expandChronicleBigQueryExportEntityGraphSettingsDataFreshnessTime(original["data_freshness_time"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedDataFreshnessTime); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["dataFreshnessTime"] = transformedDataFreshnessTime + } + + transformedDataVolume, err := expandChronicleBigQueryExportEntityGraphSettingsDataVolume(original["data_volume"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedDataVolume); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["dataVolume"] = transformedDataVolume + } + + transformedEnabled, err := expandChronicleBigQueryExportEntityGraphSettingsEnabled(original["enabled"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedEnabled); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["enabled"] = transformedEnabled + } + + transformedLatestExportJobState, err := expandChronicleBigQueryExportEntityGraphSettingsLatestExportJobState(original["latest_export_job_state"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedLatestExportJobState); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["latestExportJobState"] = transformedLatestExportJobState + } + + transformedRetentionDays, err := expandChronicleBigQueryExportEntityGraphSettingsRetentionDays(original["retention_days"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedRetentionDays); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["retentionDays"] = transformedRetentionDays + } + + return transformed, nil +} + +func expandChronicleBigQueryExportEntityGraphSettingsDataFreshnessTime(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandChronicleBigQueryExportEntityGraphSettingsDataVolume(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandChronicleBigQueryExportEntityGraphSettingsEnabled(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandChronicleBigQueryExportEntityGraphSettingsLatestExportJobState(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandChronicleBigQueryExportEntityGraphSettingsRetentionDays(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandChronicleBigQueryExportIocMatchesSettings(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + if v == nil { + return nil, nil + } + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedDataFreshnessTime, err := expandChronicleBigQueryExportIocMatchesSettingsDataFreshnessTime(original["data_freshness_time"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedDataFreshnessTime); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["dataFreshnessTime"] = transformedDataFreshnessTime + } + + transformedDataVolume, err := expandChronicleBigQueryExportIocMatchesSettingsDataVolume(original["data_volume"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedDataVolume); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["dataVolume"] = transformedDataVolume + } + + transformedEnabled, err := expandChronicleBigQueryExportIocMatchesSettingsEnabled(original["enabled"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedEnabled); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["enabled"] = transformedEnabled + } + + transformedLatestExportJobState, err := expandChronicleBigQueryExportIocMatchesSettingsLatestExportJobState(original["latest_export_job_state"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedLatestExportJobState); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["latestExportJobState"] = transformedLatestExportJobState + } + + transformedRetentionDays, err := expandChronicleBigQueryExportIocMatchesSettingsRetentionDays(original["retention_days"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedRetentionDays); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["retentionDays"] = transformedRetentionDays + } + + return transformed, nil +} + +func expandChronicleBigQueryExportIocMatchesSettingsDataFreshnessTime(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandChronicleBigQueryExportIocMatchesSettingsDataVolume(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandChronicleBigQueryExportIocMatchesSettingsEnabled(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandChronicleBigQueryExportIocMatchesSettingsLatestExportJobState(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandChronicleBigQueryExportIocMatchesSettingsRetentionDays(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandChronicleBigQueryExportRuleDetectionsSettings(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + if v == nil { + return nil, nil + } + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedDataFreshnessTime, err := expandChronicleBigQueryExportRuleDetectionsSettingsDataFreshnessTime(original["data_freshness_time"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedDataFreshnessTime); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["dataFreshnessTime"] = transformedDataFreshnessTime + } + + transformedDataVolume, err := expandChronicleBigQueryExportRuleDetectionsSettingsDataVolume(original["data_volume"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedDataVolume); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["dataVolume"] = transformedDataVolume + } + + transformedEnabled, err := expandChronicleBigQueryExportRuleDetectionsSettingsEnabled(original["enabled"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedEnabled); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["enabled"] = transformedEnabled + } + + transformedLatestExportJobState, err := expandChronicleBigQueryExportRuleDetectionsSettingsLatestExportJobState(original["latest_export_job_state"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedLatestExportJobState); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["latestExportJobState"] = transformedLatestExportJobState + } + + transformedRetentionDays, err := expandChronicleBigQueryExportRuleDetectionsSettingsRetentionDays(original["retention_days"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedRetentionDays); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["retentionDays"] = transformedRetentionDays + } + + return transformed, nil +} + +func expandChronicleBigQueryExportRuleDetectionsSettingsDataFreshnessTime(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandChronicleBigQueryExportRuleDetectionsSettingsDataVolume(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandChronicleBigQueryExportRuleDetectionsSettingsEnabled(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandChronicleBigQueryExportRuleDetectionsSettingsLatestExportJobState(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandChronicleBigQueryExportRuleDetectionsSettingsRetentionDays(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandChronicleBigQueryExportUdmEventsAggregatesSettings(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + if v == nil { + return nil, nil + } + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedDataFreshnessTime, err := expandChronicleBigQueryExportUdmEventsAggregatesSettingsDataFreshnessTime(original["data_freshness_time"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedDataFreshnessTime); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["dataFreshnessTime"] = transformedDataFreshnessTime + } + + transformedDataVolume, err := expandChronicleBigQueryExportUdmEventsAggregatesSettingsDataVolume(original["data_volume"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedDataVolume); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["dataVolume"] = transformedDataVolume + } + + transformedEnabled, err := expandChronicleBigQueryExportUdmEventsAggregatesSettingsEnabled(original["enabled"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedEnabled); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["enabled"] = transformedEnabled + } + + transformedLatestExportJobState, err := expandChronicleBigQueryExportUdmEventsAggregatesSettingsLatestExportJobState(original["latest_export_job_state"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedLatestExportJobState); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["latestExportJobState"] = transformedLatestExportJobState + } + + transformedRetentionDays, err := expandChronicleBigQueryExportUdmEventsAggregatesSettingsRetentionDays(original["retention_days"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedRetentionDays); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["retentionDays"] = transformedRetentionDays + } + + return transformed, nil +} + +func expandChronicleBigQueryExportUdmEventsAggregatesSettingsDataFreshnessTime(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandChronicleBigQueryExportUdmEventsAggregatesSettingsDataVolume(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandChronicleBigQueryExportUdmEventsAggregatesSettingsEnabled(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandChronicleBigQueryExportUdmEventsAggregatesSettingsLatestExportJobState(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandChronicleBigQueryExportUdmEventsAggregatesSettingsRetentionDays(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandChronicleBigQueryExportUdmEventsSettings(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + if v == nil { + return nil, nil + } + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedDataFreshnessTime, err := expandChronicleBigQueryExportUdmEventsSettingsDataFreshnessTime(original["data_freshness_time"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedDataFreshnessTime); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["dataFreshnessTime"] = transformedDataFreshnessTime + } + + transformedDataVolume, err := expandChronicleBigQueryExportUdmEventsSettingsDataVolume(original["data_volume"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedDataVolume); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["dataVolume"] = transformedDataVolume + } + + transformedEnabled, err := expandChronicleBigQueryExportUdmEventsSettingsEnabled(original["enabled"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedEnabled); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["enabled"] = transformedEnabled + } + + transformedLatestExportJobState, err := expandChronicleBigQueryExportUdmEventsSettingsLatestExportJobState(original["latest_export_job_state"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedLatestExportJobState); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["latestExportJobState"] = transformedLatestExportJobState + } + + transformedRetentionDays, err := expandChronicleBigQueryExportUdmEventsSettingsRetentionDays(original["retention_days"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedRetentionDays); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["retentionDays"] = transformedRetentionDays + } + + return transformed, nil +} + +func expandChronicleBigQueryExportUdmEventsSettingsDataFreshnessTime(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandChronicleBigQueryExportUdmEventsSettingsDataVolume(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandChronicleBigQueryExportUdmEventsSettingsEnabled(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandChronicleBigQueryExportUdmEventsSettingsLatestExportJobState(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandChronicleBigQueryExportUdmEventsSettingsRetentionDays(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} diff --git a/tfplan2cai/converters/google/resources/services/colab/colab_schedule.go b/tfplan2cai/converters/google/resources/services/colab/colab_schedule.go index 45a06de0ea..e285d9b186 100644 --- a/tfplan2cai/converters/google/resources/services/colab/colab_schedule.go +++ b/tfplan2cai/converters/google/resources/services/colab/colab_schedule.go @@ -177,6 +177,18 @@ func GetColabScheduleApiObject(d tpgresource.TerraformResourceData, config *tran } else if v, ok := d.GetOkExists("create_notebook_execution_job_request"); !tpgresource.IsEmptyValue(reflect.ValueOf(createNotebookExecutionJobRequestProp)) && (ok || !reflect.DeepEqual(v, createNotebookExecutionJobRequestProp)) { obj["createNotebookExecutionJobRequest"] = createNotebookExecutionJobRequestProp } + createPipelineJobRequestProp, err := expandColabScheduleCreatePipelineJobRequest(d.Get("create_pipeline_job_request"), d, config) + if err != nil { + return nil, err + } else if v, ok := d.GetOkExists("create_pipeline_job_request"); !tpgresource.IsEmptyValue(reflect.ValueOf(createPipelineJobRequestProp)) && (ok || !reflect.DeepEqual(v, createPipelineJobRequestProp)) { + obj["createPipelineJobRequest"] = createPipelineJobRequestProp + } + maxConcurrentActiveRunCountProp, err := expandColabScheduleMaxConcurrentActiveRunCount(d.Get("max_concurrent_active_run_count"), d, config) + if err != nil { + return nil, err + } else if v, ok := d.GetOkExists("max_concurrent_active_run_count"); !tpgresource.IsEmptyValue(reflect.ValueOf(maxConcurrentActiveRunCountProp)) && (ok || !reflect.DeepEqual(v, maxConcurrentActiveRunCountProp)) { + obj["maxConcurrentActiveRunCount"] = maxConcurrentActiveRunCountProp + } return resourceColabScheduleEncoder(d, config, obj) } @@ -193,16 +205,26 @@ func resourceColabScheduleEncoder(d tpgresource.TerraformResourceData, meta inte return nil, err } - // createNotebookExecutionJobRequest does not exist in update requests - if obj["createNotebookExecutionJobRequest"] == nil { - return obj, nil + // Handle parent injection for creation requests if parent is not explicitly provided + if obj["createNotebookExecutionJobRequest"] != nil { + jobRequest, ok := obj["createNotebookExecutionJobRequest"].(map[string]interface{}) + if !ok { + return nil, fmt.Errorf("createNotebookExecutionJobRequest is not of type map[string]interface{} or is nil") + } + if jobRequest["parent"] == nil || jobRequest["parent"] == "" { + jobRequest["parent"] = fmt.Sprintf("projects/%s/locations/%s", project, location) + } } - jobRequest, ok := obj["createNotebookExecutionJobRequest"].(map[string]interface{}) - if !ok { - return nil, fmt.Errorf("createNotebookExecutionJobRequest is not of type map[string]interface{} or is nil") + if obj["createPipelineJobRequest"] != nil { + pipelineRequest, ok := obj["createPipelineJobRequest"].(map[string]interface{}) + if !ok { + return nil, fmt.Errorf("createPipelineJobRequest is not of type map[string]interface{} or is nil") + } + if pipelineRequest["parent"] == nil || pipelineRequest["parent"] == "" { + pipelineRequest["parent"] = fmt.Sprintf("projects/%s/locations/%s", project, location) + } } - jobRequest["parent"] = fmt.Sprintf("projects/%s/locations/%s", project, location) return obj, nil } @@ -254,6 +276,20 @@ func expandColabScheduleCreateNotebookExecutionJobRequest(v interface{}, d tpgre transformed["notebookExecutionJob"] = transformedNotebookExecutionJob } + transformedNotebookExecutionJobId, err := expandColabScheduleCreateNotebookExecutionJobRequestNotebookExecutionJobId(original["notebook_execution_job_id"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedNotebookExecutionJobId); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["notebookExecutionJobId"] = transformedNotebookExecutionJobId + } + + transformedParent, err := expandColabScheduleCreateNotebookExecutionJobRequestParent(original["parent"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedParent); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["parent"] = transformedParent + } + return transformed, nil } @@ -325,6 +361,76 @@ func expandColabScheduleCreateNotebookExecutionJobRequestNotebookExecutionJob(v transformed["serviceAccount"] = transformedServiceAccount } + transformedCreateTime, err := expandColabScheduleCreateNotebookExecutionJobRequestNotebookExecutionJobCreateTime(original["create_time"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedCreateTime); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["createTime"] = transformedCreateTime + } + + transformedCustomEnvironmentSpec, err := expandColabScheduleCreateNotebookExecutionJobRequestNotebookExecutionJobCustomEnvironmentSpec(original["custom_environment_spec"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedCustomEnvironmentSpec); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["customEnvironmentSpec"] = transformedCustomEnvironmentSpec + } + + transformedEncryptionSpec, err := expandColabScheduleCreateNotebookExecutionJobRequestNotebookExecutionJobEncryptionSpec(original["encryption_spec"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedEncryptionSpec); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["encryptionSpec"] = transformedEncryptionSpec + } + + transformedJobState, err := expandColabScheduleCreateNotebookExecutionJobRequestNotebookExecutionJobJobState(original["job_state"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedJobState); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["jobState"] = transformedJobState + } + + transformedKernelName, err := expandColabScheduleCreateNotebookExecutionJobRequestNotebookExecutionJobKernelName(original["kernel_name"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedKernelName); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["kernelName"] = transformedKernelName + } + + transformedLabels, err := expandColabScheduleCreateNotebookExecutionJobRequestNotebookExecutionJobLabels(original["labels"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedLabels); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["labels"] = transformedLabels + } + + transformedName, err := expandColabScheduleCreateNotebookExecutionJobRequestNotebookExecutionJobName(original["name"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedName); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["name"] = transformedName + } + + transformedScheduleResourceName, err := expandColabScheduleCreateNotebookExecutionJobRequestNotebookExecutionJobScheduleResourceName(original["schedule_resource_name"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedScheduleResourceName); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["scheduleResourceName"] = transformedScheduleResourceName + } + + transformedUpdateTime, err := expandColabScheduleCreateNotebookExecutionJobRequestNotebookExecutionJobUpdateTime(original["update_time"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedUpdateTime); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["updateTime"] = transformedUpdateTime + } + + transformedWorkbenchRuntime, err := expandColabScheduleCreateNotebookExecutionJobRequestNotebookExecutionJobWorkbenchRuntime(original["workbench_runtime"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedWorkbenchRuntime); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["workbenchRuntime"] = transformedWorkbenchRuntime + } + return transformed, nil } @@ -425,3 +531,795 @@ func expandColabScheduleCreateNotebookExecutionJobRequestNotebookExecutionJobExe func expandColabScheduleCreateNotebookExecutionJobRequestNotebookExecutionJobServiceAccount(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { return v, nil } + +func expandColabScheduleCreateNotebookExecutionJobRequestNotebookExecutionJobCreateTime(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandColabScheduleCreateNotebookExecutionJobRequestNotebookExecutionJobCustomEnvironmentSpec(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + if v == nil { + return nil, nil + } + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedMachineSpec, err := expandColabScheduleCreateNotebookExecutionJobRequestNotebookExecutionJobCustomEnvironmentSpecMachineSpec(original["machine_spec"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedMachineSpec); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["machineSpec"] = transformedMachineSpec + } + + transformedNetworkSpec, err := expandColabScheduleCreateNotebookExecutionJobRequestNotebookExecutionJobCustomEnvironmentSpecNetworkSpec(original["network_spec"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedNetworkSpec); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["networkSpec"] = transformedNetworkSpec + } + + transformedPersistentDiskSpec, err := expandColabScheduleCreateNotebookExecutionJobRequestNotebookExecutionJobCustomEnvironmentSpecPersistentDiskSpec(original["persistent_disk_spec"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedPersistentDiskSpec); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["persistentDiskSpec"] = transformedPersistentDiskSpec + } + + return transformed, nil +} + +func expandColabScheduleCreateNotebookExecutionJobRequestNotebookExecutionJobCustomEnvironmentSpecMachineSpec(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + if v == nil { + return nil, nil + } + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedAcceleratorCount, err := expandColabScheduleCreateNotebookExecutionJobRequestNotebookExecutionJobCustomEnvironmentSpecMachineSpecAcceleratorCount(original["accelerator_count"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedAcceleratorCount); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["acceleratorCount"] = transformedAcceleratorCount + } + + transformedAcceleratorType, err := expandColabScheduleCreateNotebookExecutionJobRequestNotebookExecutionJobCustomEnvironmentSpecMachineSpecAcceleratorType(original["accelerator_type"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedAcceleratorType); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["acceleratorType"] = transformedAcceleratorType + } + + transformedGpuPartitionSize, err := expandColabScheduleCreateNotebookExecutionJobRequestNotebookExecutionJobCustomEnvironmentSpecMachineSpecGpuPartitionSize(original["gpu_partition_size"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedGpuPartitionSize); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["gpuPartitionSize"] = transformedGpuPartitionSize + } + + transformedMachineType, err := expandColabScheduleCreateNotebookExecutionJobRequestNotebookExecutionJobCustomEnvironmentSpecMachineSpecMachineType(original["machine_type"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedMachineType); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["machineType"] = transformedMachineType + } + + transformedReservationAffinity, err := expandColabScheduleCreateNotebookExecutionJobRequestNotebookExecutionJobCustomEnvironmentSpecMachineSpecReservationAffinity(original["reservation_affinity"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedReservationAffinity); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["reservationAffinity"] = transformedReservationAffinity + } + + transformedTpuTopology, err := expandColabScheduleCreateNotebookExecutionJobRequestNotebookExecutionJobCustomEnvironmentSpecMachineSpecTpuTopology(original["tpu_topology"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedTpuTopology); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["tpuTopology"] = transformedTpuTopology + } + + return transformed, nil +} + +func expandColabScheduleCreateNotebookExecutionJobRequestNotebookExecutionJobCustomEnvironmentSpecMachineSpecAcceleratorCount(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandColabScheduleCreateNotebookExecutionJobRequestNotebookExecutionJobCustomEnvironmentSpecMachineSpecAcceleratorType(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandColabScheduleCreateNotebookExecutionJobRequestNotebookExecutionJobCustomEnvironmentSpecMachineSpecGpuPartitionSize(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandColabScheduleCreateNotebookExecutionJobRequestNotebookExecutionJobCustomEnvironmentSpecMachineSpecMachineType(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandColabScheduleCreateNotebookExecutionJobRequestNotebookExecutionJobCustomEnvironmentSpecMachineSpecReservationAffinity(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + if v == nil { + return nil, nil + } + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedKey, err := expandColabScheduleCreateNotebookExecutionJobRequestNotebookExecutionJobCustomEnvironmentSpecMachineSpecReservationAffinityKey(original["key"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedKey); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["key"] = transformedKey + } + + transformedReservationAffinityType, err := expandColabScheduleCreateNotebookExecutionJobRequestNotebookExecutionJobCustomEnvironmentSpecMachineSpecReservationAffinityReservationAffinityType(original["reservation_affinity_type"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedReservationAffinityType); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["reservationAffinityType"] = transformedReservationAffinityType + } + + transformedUseReservationPool, err := expandColabScheduleCreateNotebookExecutionJobRequestNotebookExecutionJobCustomEnvironmentSpecMachineSpecReservationAffinityUseReservationPool(original["use_reservation_pool"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedUseReservationPool); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["useReservationPool"] = transformedUseReservationPool + } + + transformedValues, err := expandColabScheduleCreateNotebookExecutionJobRequestNotebookExecutionJobCustomEnvironmentSpecMachineSpecReservationAffinityValues(original["values"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedValues); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["values"] = transformedValues + } + + return transformed, nil +} + +func expandColabScheduleCreateNotebookExecutionJobRequestNotebookExecutionJobCustomEnvironmentSpecMachineSpecReservationAffinityKey(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandColabScheduleCreateNotebookExecutionJobRequestNotebookExecutionJobCustomEnvironmentSpecMachineSpecReservationAffinityReservationAffinityType(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandColabScheduleCreateNotebookExecutionJobRequestNotebookExecutionJobCustomEnvironmentSpecMachineSpecReservationAffinityUseReservationPool(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandColabScheduleCreateNotebookExecutionJobRequestNotebookExecutionJobCustomEnvironmentSpecMachineSpecReservationAffinityValues(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandColabScheduleCreateNotebookExecutionJobRequestNotebookExecutionJobCustomEnvironmentSpecMachineSpecTpuTopology(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandColabScheduleCreateNotebookExecutionJobRequestNotebookExecutionJobCustomEnvironmentSpecNetworkSpec(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + if v == nil { + return nil, nil + } + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedEnableInternetAccess, err := expandColabScheduleCreateNotebookExecutionJobRequestNotebookExecutionJobCustomEnvironmentSpecNetworkSpecEnableInternetAccess(original["enable_internet_access"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedEnableInternetAccess); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["enableInternetAccess"] = transformedEnableInternetAccess + } + + transformedNetwork, err := expandColabScheduleCreateNotebookExecutionJobRequestNotebookExecutionJobCustomEnvironmentSpecNetworkSpecNetwork(original["network"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedNetwork); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["network"] = transformedNetwork + } + + transformedSubnetwork, err := expandColabScheduleCreateNotebookExecutionJobRequestNotebookExecutionJobCustomEnvironmentSpecNetworkSpecSubnetwork(original["subnetwork"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedSubnetwork); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["subnetwork"] = transformedSubnetwork + } + + return transformed, nil +} + +func expandColabScheduleCreateNotebookExecutionJobRequestNotebookExecutionJobCustomEnvironmentSpecNetworkSpecEnableInternetAccess(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandColabScheduleCreateNotebookExecutionJobRequestNotebookExecutionJobCustomEnvironmentSpecNetworkSpecNetwork(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandColabScheduleCreateNotebookExecutionJobRequestNotebookExecutionJobCustomEnvironmentSpecNetworkSpecSubnetwork(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandColabScheduleCreateNotebookExecutionJobRequestNotebookExecutionJobCustomEnvironmentSpecPersistentDiskSpec(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + if v == nil { + return nil, nil + } + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedDiskSizeGb, err := expandColabScheduleCreateNotebookExecutionJobRequestNotebookExecutionJobCustomEnvironmentSpecPersistentDiskSpecDiskSizeGb(original["disk_size_gb"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedDiskSizeGb); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["diskSizeGb"] = transformedDiskSizeGb + } + + transformedDiskType, err := expandColabScheduleCreateNotebookExecutionJobRequestNotebookExecutionJobCustomEnvironmentSpecPersistentDiskSpecDiskType(original["disk_type"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedDiskType); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["diskType"] = transformedDiskType + } + + return transformed, nil +} + +func expandColabScheduleCreateNotebookExecutionJobRequestNotebookExecutionJobCustomEnvironmentSpecPersistentDiskSpecDiskSizeGb(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandColabScheduleCreateNotebookExecutionJobRequestNotebookExecutionJobCustomEnvironmentSpecPersistentDiskSpecDiskType(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandColabScheduleCreateNotebookExecutionJobRequestNotebookExecutionJobEncryptionSpec(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + if v == nil { + return nil, nil + } + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedKmsKeyName, err := expandColabScheduleCreateNotebookExecutionJobRequestNotebookExecutionJobEncryptionSpecKmsKeyName(original["kms_key_name"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedKmsKeyName); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["kmsKeyName"] = transformedKmsKeyName + } + + return transformed, nil +} + +func expandColabScheduleCreateNotebookExecutionJobRequestNotebookExecutionJobEncryptionSpecKmsKeyName(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandColabScheduleCreateNotebookExecutionJobRequestNotebookExecutionJobJobState(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandColabScheduleCreateNotebookExecutionJobRequestNotebookExecutionJobKernelName(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandColabScheduleCreateNotebookExecutionJobRequestNotebookExecutionJobLabels(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (map[string]string, error) { + if v == nil { + return map[string]string{}, nil + } + m := make(map[string]string) + for k, val := range v.(map[string]interface{}) { + m[k] = val.(string) + } + return m, nil +} + +func expandColabScheduleCreateNotebookExecutionJobRequestNotebookExecutionJobName(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandColabScheduleCreateNotebookExecutionJobRequestNotebookExecutionJobScheduleResourceName(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandColabScheduleCreateNotebookExecutionJobRequestNotebookExecutionJobUpdateTime(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandColabScheduleCreateNotebookExecutionJobRequestNotebookExecutionJobWorkbenchRuntime(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandColabScheduleCreateNotebookExecutionJobRequestNotebookExecutionJobId(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandColabScheduleCreateNotebookExecutionJobRequestParent(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandColabScheduleCreatePipelineJobRequest(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + if v == nil { + return nil, nil + } + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedParent, err := expandColabScheduleCreatePipelineJobRequestParent(original["parent"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedParent); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["parent"] = transformedParent + } + + transformedPipelineJob, err := expandColabScheduleCreatePipelineJobRequestPipelineJob(original["pipeline_job"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedPipelineJob); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["pipelineJob"] = transformedPipelineJob + } + + transformedPipelineJobId, err := expandColabScheduleCreatePipelineJobRequestPipelineJobId(original["pipeline_job_id"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedPipelineJobId); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["pipelineJobId"] = transformedPipelineJobId + } + + return transformed, nil +} + +func expandColabScheduleCreatePipelineJobRequestParent(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandColabScheduleCreatePipelineJobRequestPipelineJob(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + if v == nil { + return nil, nil + } + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedCreateTime, err := expandColabScheduleCreatePipelineJobRequestPipelineJobCreateTime(original["create_time"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedCreateTime); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["createTime"] = transformedCreateTime + } + + transformedDisplayName, err := expandColabScheduleCreatePipelineJobRequestPipelineJobDisplayName(original["display_name"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedDisplayName); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["displayName"] = transformedDisplayName + } + + transformedEncryptionSpec, err := expandColabScheduleCreatePipelineJobRequestPipelineJobEncryptionSpec(original["encryption_spec"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedEncryptionSpec); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["encryptionSpec"] = transformedEncryptionSpec + } + + transformedEndTime, err := expandColabScheduleCreatePipelineJobRequestPipelineJobEndTime(original["end_time"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedEndTime); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["endTime"] = transformedEndTime + } + + transformedLabels, err := expandColabScheduleCreatePipelineJobRequestPipelineJobLabels(original["labels"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedLabels); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["labels"] = transformedLabels + } + + transformedName, err := expandColabScheduleCreatePipelineJobRequestPipelineJobName(original["name"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedName); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["name"] = transformedName + } + + transformedNetwork, err := expandColabScheduleCreatePipelineJobRequestPipelineJobNetwork(original["network"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedNetwork); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["network"] = transformedNetwork + } + + transformedPipelineSpec, err := expandColabScheduleCreatePipelineJobRequestPipelineJobPipelineSpec(original["pipeline_spec"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedPipelineSpec); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["pipelineSpec"] = transformedPipelineSpec + } + + transformedPreflightValidations, err := expandColabScheduleCreatePipelineJobRequestPipelineJobPreflightValidations(original["preflight_validations"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedPreflightValidations); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["preflightValidations"] = transformedPreflightValidations + } + + transformedPscInterfaceConfig, err := expandColabScheduleCreatePipelineJobRequestPipelineJobPscInterfaceConfig(original["psc_interface_config"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedPscInterfaceConfig); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["pscInterfaceConfig"] = transformedPscInterfaceConfig + } + + transformedReservedIpRanges, err := expandColabScheduleCreatePipelineJobRequestPipelineJobReservedIpRanges(original["reserved_ip_ranges"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedReservedIpRanges); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["reservedIpRanges"] = transformedReservedIpRanges + } + + transformedRuntimeConfig, err := expandColabScheduleCreatePipelineJobRequestPipelineJobRuntimeConfig(original["runtime_config"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedRuntimeConfig); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["runtimeConfig"] = transformedRuntimeConfig + } + + transformedScheduleName, err := expandColabScheduleCreatePipelineJobRequestPipelineJobScheduleName(original["schedule_name"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedScheduleName); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["scheduleName"] = transformedScheduleName + } + + transformedServiceAccount, err := expandColabScheduleCreatePipelineJobRequestPipelineJobServiceAccount(original["service_account"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedServiceAccount); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["serviceAccount"] = transformedServiceAccount + } + + transformedStartTime, err := expandColabScheduleCreatePipelineJobRequestPipelineJobStartTime(original["start_time"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedStartTime); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["startTime"] = transformedStartTime + } + + transformedState, err := expandColabScheduleCreatePipelineJobRequestPipelineJobState(original["state"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedState); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["state"] = transformedState + } + + transformedTemplateMetadata, err := expandColabScheduleCreatePipelineJobRequestPipelineJobTemplateMetadata(original["template_metadata"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedTemplateMetadata); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["templateMetadata"] = transformedTemplateMetadata + } + + transformedTemplateUri, err := expandColabScheduleCreatePipelineJobRequestPipelineJobTemplateUri(original["template_uri"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedTemplateUri); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["templateUri"] = transformedTemplateUri + } + + transformedUpdateTime, err := expandColabScheduleCreatePipelineJobRequestPipelineJobUpdateTime(original["update_time"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedUpdateTime); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["updateTime"] = transformedUpdateTime + } + + return transformed, nil +} + +func expandColabScheduleCreatePipelineJobRequestPipelineJobCreateTime(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandColabScheduleCreatePipelineJobRequestPipelineJobDisplayName(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandColabScheduleCreatePipelineJobRequestPipelineJobEncryptionSpec(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + if v == nil { + return nil, nil + } + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedKmsKeyName, err := expandColabScheduleCreatePipelineJobRequestPipelineJobEncryptionSpecKmsKeyName(original["kms_key_name"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedKmsKeyName); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["kmsKeyName"] = transformedKmsKeyName + } + + return transformed, nil +} + +func expandColabScheduleCreatePipelineJobRequestPipelineJobEncryptionSpecKmsKeyName(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandColabScheduleCreatePipelineJobRequestPipelineJobEndTime(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandColabScheduleCreatePipelineJobRequestPipelineJobLabels(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (map[string]string, error) { + if v == nil { + return map[string]string{}, nil + } + m := make(map[string]string) + for k, val := range v.(map[string]interface{}) { + m[k] = val.(string) + } + return m, nil +} + +func expandColabScheduleCreatePipelineJobRequestPipelineJobName(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandColabScheduleCreatePipelineJobRequestPipelineJobNetwork(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandColabScheduleCreatePipelineJobRequestPipelineJobPipelineSpec(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + b := []byte(v.(string)) + if len(b) == 0 { + return nil, nil + } + var j interface{} + if err := json.Unmarshal(b, &j); err != nil { + return nil, err + } + return j, nil +} + +func expandColabScheduleCreatePipelineJobRequestPipelineJobPreflightValidations(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandColabScheduleCreatePipelineJobRequestPipelineJobPscInterfaceConfig(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + if v == nil { + return nil, nil + } + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedDnsPeeringConfigs, err := expandColabScheduleCreatePipelineJobRequestPipelineJobPscInterfaceConfigDnsPeeringConfigs(original["dns_peering_configs"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedDnsPeeringConfigs); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["dnsPeeringConfigs"] = transformedDnsPeeringConfigs + } + + transformedNetworkAttachment, err := expandColabScheduleCreatePipelineJobRequestPipelineJobPscInterfaceConfigNetworkAttachment(original["network_attachment"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedNetworkAttachment); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["networkAttachment"] = transformedNetworkAttachment + } + + return transformed, nil +} + +func expandColabScheduleCreatePipelineJobRequestPipelineJobPscInterfaceConfigDnsPeeringConfigs(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + if v == nil { + return nil, nil + } + l := v.([]interface{}) + req := make([]interface{}, 0, len(l)) + for _, raw := range l { + if raw == nil { + continue + } + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedDomain, err := expandColabScheduleCreatePipelineJobRequestPipelineJobPscInterfaceConfigDnsPeeringConfigsDomain(original["domain"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedDomain); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["domain"] = transformedDomain + } + + transformedTargetNetwork, err := expandColabScheduleCreatePipelineJobRequestPipelineJobPscInterfaceConfigDnsPeeringConfigsTargetNetwork(original["target_network"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedTargetNetwork); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["targetNetwork"] = transformedTargetNetwork + } + + transformedTargetProject, err := expandColabScheduleCreatePipelineJobRequestPipelineJobPscInterfaceConfigDnsPeeringConfigsTargetProject(original["target_project"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedTargetProject); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["targetProject"] = transformedTargetProject + } + + req = append(req, transformed) + } + return req, nil +} + +func expandColabScheduleCreatePipelineJobRequestPipelineJobPscInterfaceConfigDnsPeeringConfigsDomain(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandColabScheduleCreatePipelineJobRequestPipelineJobPscInterfaceConfigDnsPeeringConfigsTargetNetwork(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandColabScheduleCreatePipelineJobRequestPipelineJobPscInterfaceConfigDnsPeeringConfigsTargetProject(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandColabScheduleCreatePipelineJobRequestPipelineJobPscInterfaceConfigNetworkAttachment(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandColabScheduleCreatePipelineJobRequestPipelineJobReservedIpRanges(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandColabScheduleCreatePipelineJobRequestPipelineJobRuntimeConfig(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + if v == nil { + return nil, nil + } + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedFailurePolicy, err := expandColabScheduleCreatePipelineJobRequestPipelineJobRuntimeConfigFailurePolicy(original["failure_policy"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedFailurePolicy); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["failurePolicy"] = transformedFailurePolicy + } + + transformedGcsOutputDirectory, err := expandColabScheduleCreatePipelineJobRequestPipelineJobRuntimeConfigGcsOutputDirectory(original["gcs_output_directory"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedGcsOutputDirectory); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["gcsOutputDirectory"] = transformedGcsOutputDirectory + } + + transformedParameterValues, err := expandColabScheduleCreatePipelineJobRequestPipelineJobRuntimeConfigParameterValues(original["parameter_values"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedParameterValues); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["parameterValues"] = transformedParameterValues + } + + return transformed, nil +} + +func expandColabScheduleCreatePipelineJobRequestPipelineJobRuntimeConfigFailurePolicy(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandColabScheduleCreatePipelineJobRequestPipelineJobRuntimeConfigGcsOutputDirectory(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandColabScheduleCreatePipelineJobRequestPipelineJobRuntimeConfigParameterValues(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (map[string]string, error) { + if v == nil { + return map[string]string{}, nil + } + m := make(map[string]string) + for k, val := range v.(map[string]interface{}) { + m[k] = val.(string) + } + return m, nil +} + +func expandColabScheduleCreatePipelineJobRequestPipelineJobScheduleName(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandColabScheduleCreatePipelineJobRequestPipelineJobServiceAccount(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandColabScheduleCreatePipelineJobRequestPipelineJobStartTime(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandColabScheduleCreatePipelineJobRequestPipelineJobState(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandColabScheduleCreatePipelineJobRequestPipelineJobTemplateMetadata(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + if v == nil { + return nil, nil + } + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedVersion, err := expandColabScheduleCreatePipelineJobRequestPipelineJobTemplateMetadataVersion(original["version"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedVersion); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["version"] = transformedVersion + } + + return transformed, nil +} + +func expandColabScheduleCreatePipelineJobRequestPipelineJobTemplateMetadataVersion(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandColabScheduleCreatePipelineJobRequestPipelineJobTemplateUri(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandColabScheduleCreatePipelineJobRequestPipelineJobUpdateTime(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandColabScheduleCreatePipelineJobRequestPipelineJobId(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandColabScheduleMaxConcurrentActiveRunCount(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} diff --git a/tfplan2cai/converters/google/resources/services/compute/compute_backend_service.go b/tfplan2cai/converters/google/resources/services/compute/compute_backend_service.go index d6fe525453..45b732c7de 100644 --- a/tfplan2cai/converters/google/resources/services/compute/compute_backend_service.go +++ b/tfplan2cai/converters/google/resources/services/compute/compute_backend_service.go @@ -2045,6 +2045,20 @@ func expandComputeBackendServiceLogConfig(v interface{}, d tpgresource.Terraform transformed["optionalFields"] = transformedOptionalFields } + transformedRequestHeaders, err := expandComputeBackendServiceLogConfigRequestHeaders(original["request_headers"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedRequestHeaders); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["loggingHttpRequestHeaders"] = transformedRequestHeaders + } + + transformedResponseHeaders, err := expandComputeBackendServiceLogConfigResponseHeaders(original["response_headers"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedResponseHeaders); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["loggingHttpResponseHeaders"] = transformedResponseHeaders + } + return transformed, nil } @@ -2064,6 +2078,64 @@ func expandComputeBackendServiceLogConfigOptionalFields(v interface{}, d tpgreso return v, nil } +func expandComputeBackendServiceLogConfigRequestHeaders(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + if v == nil { + return nil, nil + } + l := v.([]interface{}) + req := make([]interface{}, 0, len(l)) + for _, raw := range l { + if raw == nil { + continue + } + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedHeaderName, err := expandComputeBackendServiceLogConfigRequestHeadersHeaderName(original["header_name"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedHeaderName); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["headerName"] = transformedHeaderName + } + + req = append(req, transformed) + } + return req, nil +} + +func expandComputeBackendServiceLogConfigRequestHeadersHeaderName(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandComputeBackendServiceLogConfigResponseHeaders(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + if v == nil { + return nil, nil + } + l := v.([]interface{}) + req := make([]interface{}, 0, len(l)) + for _, raw := range l { + if raw == nil { + continue + } + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedHeaderName, err := expandComputeBackendServiceLogConfigResponseHeadersHeaderName(original["header_name"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedHeaderName); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["headerName"] = transformedHeaderName + } + + req = append(req, transformed) + } + return req, nil +} + +func expandComputeBackendServiceLogConfigResponseHeadersHeaderName(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + func expandComputeBackendServiceServiceLbPolicy(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { return v, nil } diff --git a/tfplan2cai/converters/google/resources/services/compute/compute_instance_helpers.go b/tfplan2cai/converters/google/resources/services/compute/compute_instance_helpers.go index af73631727..b5ca2e7741 100644 --- a/tfplan2cai/converters/google/resources/services/compute/compute_instance_helpers.go +++ b/tfplan2cai/converters/google/resources/services/compute/compute_instance_helpers.go @@ -186,6 +186,12 @@ func expandScheduling(v interface{}) (map[string]interface{}, error) { if v, ok := original["provisioning_model"]; ok { result["provisioningModel"] = v.(string) } + + omitDurations := false + if pm, ok := result["provisioningModel"].(string); ok && pm == "RESERVATION_BOUND" { + omitDurations = true + } + if v, ok := original["instance_termination_action"]; ok { result["instanceTerminationAction"] = v.(string) } @@ -197,7 +203,9 @@ func expandScheduling(v interface{}) (map[string]interface{}, error) { if err != nil { return nil, err } - result["maxRunDuration"] = transformedMaxRunDuration + if transformedMaxRunDuration != nil || !omitDurations { + result["maxRunDuration"] = transformedMaxRunDuration + } } if v, ok := original["on_instance_stop_action"]; ok { @@ -205,7 +213,9 @@ func expandScheduling(v interface{}) (map[string]interface{}, error) { if err != nil { return nil, err } - result["onInstanceStopAction"] = transformedOnInstanceStopAction + if transformedOnInstanceStopAction != nil || !omitDurations { + result["onInstanceStopAction"] = transformedOnInstanceStopAction + } } if v, ok := original["host_error_timeout_seconds"]; ok { //host_error_timeout_seconds doesn't get removed correctly due to an API bug on instances.SetScheduling. @@ -226,7 +236,9 @@ func expandScheduling(v interface{}) (map[string]interface{}, error) { if err != nil { return nil, err } - result["gracefulShutdown"] = transformedGracefulShutdown + if transformedGracefulShutdown != nil || !omitDurations { + result["gracefulShutdown"] = transformedGracefulShutdown + } } if v, ok := original["skip_guest_os_shutdown"]; ok { @@ -238,14 +250,18 @@ func expandScheduling(v interface{}) (map[string]interface{}, error) { if err != nil { return nil, err } - result["preemptionNoticeDuration"] = transformedPreemptionNoticeDuration + if transformedPreemptionNoticeDuration != nil || !omitDurations { + result["preemptionNoticeDuration"] = transformedPreemptionNoticeDuration + } } if v, ok := original["local_ssd_recovery_timeout"]; ok { transformedLocalSsdRecoveryTimeout, err := expandComputeLocalSsdRecoveryTimeout(v) if err != nil { return nil, err } - result["localSsdRecoveryTimeout"] = transformedLocalSsdRecoveryTimeout + if transformedLocalSsdRecoveryTimeout != nil || !omitDurations { + result["localSsdRecoveryTimeout"] = transformedLocalSsdRecoveryTimeout + } } if v, ok := original["termination_time"]; ok && v.(string) != "" { result["terminationTime"] = v.(string) @@ -711,7 +727,7 @@ func flattenNetworkInterfaces(d *schema.ResourceData, config *transport_tpg.Conf "subnetwork": tpgresource.ConvertSelfLinkToV1(subnetwork), "subnetwork_project": subnet.Project, "access_config": ac, - "alias_ip_range": flattenAliasIpRange(d, aliasIpRanges, i), + "alias_ip_range": FlattenAliasIpRangeHTTP(d, aliasIpRanges, i), "alias_ipv6_range": flattenIpv6AliasRange(d, getInterfaceSlice(iface["aliasIpv6Ranges"]), i), "nic_type": nicType, "stack_type": stackType, diff --git a/tfplan2cai/converters/google/resources/services/compute/compute_instance_http_helpers.go b/tfplan2cai/converters/google/resources/services/compute/compute_instance_http_helpers.go new file mode 100644 index 0000000000..dd3812c655 --- /dev/null +++ b/tfplan2cai/converters/google/resources/services/compute/compute_instance_http_helpers.go @@ -0,0 +1,510 @@ +package compute + +import ( + "fmt" + "reflect" + "strconv" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource" +) + +var DEFAULT_SCRATCH_DISK_SIZE_GB = 375 +var VALID_SCRATCH_DISK_SIZES_GB = []int{375, 3000, 3500, 7000, 14000} + +// FlattenAliasIpRangeHTTP replaces the legacy SDK-dependent flattenAliasIpRange. +// It operates directly on API JSON response maps, allowing all direct-HTTP compute resources to share it. +func FlattenAliasIpRangeHTTP(d *schema.ResourceData, ranges []interface{}, i int) []map[string]interface{} { + prefix := fmt.Sprintf("network_interface.%d", i) + + configData := []map[string]interface{}{} + for _, item := range d.Get(prefix + ".alias_ip_range").([]interface{}) { + configData = append(configData, item.(map[string]interface{})) + } + + apiData := make([]map[string]interface{}, 0, len(ranges)) + for _, raw := range ranges { + ipRange, ok := raw.(map[string]interface{}) + if !ok || ipRange == nil { + continue + } + + ipCidrRange, _ := ipRange["ipCidrRange"].(string) + subnetworkRangeName, _ := ipRange["subnetworkRangeName"].(string) + + apiData = append(apiData, map[string]interface{}{ + "ip_cidr_range": ipCidrRange, + "subnetwork_range_name": subnetworkRangeName, + }) + } + + // Preserve config ordering to prevent permadiffs + sorted, err := tpgresource.SortMapsByConfigOrder(configData, apiData, "ip_cidr_range") + if err != nil { + return apiData + } + return sorted +} + +func FlattenDisksHTTP(disks []interface{}, d *schema.ResourceData, defaultProject string) ([]map[string]interface{}, error) { + apiDisks := make([]map[string]interface{}, len(disks)) + for i, diskRaw := range disks { + disk := diskRaw.(map[string]interface{}) + configDisk := d.Get(fmt.Sprintf("disk.%d", i)).(map[string]any) + apiDisk, err := FlattenDiskHTTP(disk, configDisk, defaultProject) + if err != nil { + return nil, err + } + apiDisks[i] = apiDisk + } + return reorderDisks(d.Get("disk").([]interface{}), apiDisks), nil +} + +func FlattenDiskHTTP(disk map[string]interface{}, configDisk map[string]any, defaultProject string) (map[string]interface{}, error) { + diskMap := make(map[string]interface{}) + diskMap["source_image_encryption_key"] = configDisk["source_image_encryption_key"] + diskMap["source_snapshot"] = configDisk["source_snapshot"] + diskMap["source_snapshot_encryption_key"] = configDisk["source_snapshot_encryption_key"] + + if initParamsRaw, ok := disk["initializeParams"]; ok && initParamsRaw != nil { + initParams := initParamsRaw.(map[string]interface{}) + if srcImg, ok := initParams["sourceImage"].(string); ok && srcImg != "" { + path, err := resolveImageRefToRelativeURI(defaultProject, srcImg) + if err != nil { + return nil, err + } + diskMap["source_image"] = path + } else { + diskMap["source_image"] = "" + } + if v, ok := initParams["diskType"]; ok { + diskMap["disk_type"] = v + } + if v, ok := initParams["provisionedIops"]; ok { + diskMap["provisioned_iops"] = ParseIntHTTP(v) + } + if v, ok := initParams["provisionedThroughput"]; ok { + diskMap["provisioned_throughput"] = ParseIntHTTP(v) + } + if v, ok := initParams["diskName"]; ok { + diskMap["disk_name"] = v + } else { + diskMap["disk_name"] = "" + } + var diskLabels map[string]string + if lRaw, ok := initParams["labels"].(map[string]interface{}); ok { + diskLabels = make(map[string]string) + for k, v := range lRaw { + if str, ok := v.(string); ok { + diskLabels[k] = str + } + } + } + diskMap["labels"] = diskLabels + + var diskSizeGb int + if v, ok := disk["diskSizeGb"]; ok { + diskSizeGb = ParseIntHTTP(v) + } + var initDiskSizeGb int + if v, ok := initParams["diskSizeGb"]; ok { + initDiskSizeGb = ParseIntHTTP(v) + } + diskTypeStr, _ := disk["type"].(string) + + if diskSizeGb == 0 && initDiskSizeGb == 0 && diskTypeStr == "SCRATCH" { + diskMap["disk_size_gb"] = DEFAULT_SCRATCH_DISK_SIZE_GB + } else if diskSizeGb != 0 { + diskMap["disk_size_gb"] = diskSizeGb + } else { + diskMap["disk_size_gb"] = initDiskSizeGb + } + + var rPolicies []string + if rpRaw, ok := initParams["resourcePolicies"].([]interface{}); ok { + for _, v := range rpRaw { + if str, ok := v.(string); ok { + rPolicies = append(rPolicies, str) + } + } + } + diskMap["resource_policies"] = rPolicies + + var rmTags map[string]string + if rmtRaw, ok := initParams["resourceManagerTags"].(map[string]interface{}); ok { + rmTags = make(map[string]string) + for k, v := range rmtRaw { + if str, ok := v.(string); ok { + rmTags[k] = str + } + } + } + diskMap["resource_manager_tags"] = rmTags + if sp, ok := initParams["storagePool"].(string); ok && sp != "" { + diskMap["storage_pool"] = tpgresource.GetResourceNameFromSelfLink(sp) + } + } + + if encKeyRaw, ok := disk["diskEncryptionKey"]; ok && encKeyRaw != nil { + encKey := encKeyRaw.(map[string]interface{}) + encryption := make([]map[string]interface{}, 1) + encryption[0] = make(map[string]interface{}) + encryption[0]["kms_key_self_link"] = encKey["kmsKeyName"] + if diskEncryptionKey, ok := configDisk["disk_encryption_key"].([]interface{}); ok && len(diskEncryptionKey) > 0 { + if encryptionKeyMap, ok := diskEncryptionKey[0].(map[string]interface{}); ok { + if kmsSa, ok := encryptionKeyMap["kms_key_service_account"].(string); ok && kmsSa != "" { + encryption[0]["kms_key_service_account"] = kmsSa + } + } + } + diskMap["disk_encryption_key"] = encryption + } + + var guestOsFeaturesSlice []interface{} + if gofRaw, ok := disk["guestOsFeatures"].([]interface{}); ok { + for _, fRaw := range gofRaw { + if f, ok := fRaw.(map[string]interface{}); ok { + if typ, ok := f["type"].(string); ok && typ != "" { + guestOsFeaturesSlice = append(guestOsFeaturesSlice, map[string]interface{}{"type": typ}) + } + } + } + } + if v, ok := disk["autoDelete"]; ok { + diskMap["auto_delete"] = v + } else { + diskMap["auto_delete"] = false + } + if v, ok := disk["boot"]; ok { + diskMap["boot"] = v + } else { + diskMap["boot"] = false + } + if v, ok := disk["deviceName"]; ok { + diskMap["device_name"] = v + } else { + diskMap["device_name"] = "" + } + if v, ok := disk["interface"]; ok { + diskMap["interface"] = v + } else { + diskMap["interface"] = "" + } + if src, ok := disk["source"].(string); ok { + diskMap["source"] = tpgresource.ConvertSelfLinkToV1(src) + } else { + diskMap["source"] = "" + } + if v, ok := disk["mode"]; ok { + diskMap["mode"] = v + } else { + diskMap["mode"] = "" + } + if v, ok := disk["type"]; ok { + diskMap["type"] = v + } else { + diskMap["type"] = "" + } + diskMap["guest_os_features"] = flattenComputeInstanceGuestOsFeatures(guestOsFeaturesSlice) + diskMap["architecture"] = configDisk["architecture"] + + return diskMap, nil +} + +func FlattenSchedulingHTTP(resp map[string]interface{}) []map[string]interface{} { + schedulingMap := map[string]interface{}{} + v_ohm, _ := resp["onHostMaintenance"].(string) + schedulingMap["on_host_maintenance"] = v_ohm + v_p, _ := resp["preemptible"].(bool) + schedulingMap["preemptible"] = v_p + schedulingMap["min_node_cpus"] = ParseIntHTTP(resp["minNodeCpus"]) + v_pm, _ := resp["provisioningModel"].(string) + schedulingMap["provisioning_model"] = v_pm + v_ita, _ := resp["instanceTerminationAction"].(string) + schedulingMap["instance_termination_action"] = v_ita + schedulingMap["availability_domain"] = ParseIntHTTP(resp["availabilityDomain"]) + v_tt, _ := resp["terminationTime"].(string) + schedulingMap["termination_time"] = v_tt + if v, ok := resp["automaticRestart"]; ok { + schedulingMap["automatic_restart"] = v + } + v_sgos, _ := resp["skipGuestOsShutdown"].(bool) + schedulingMap["skip_guest_os_shutdown"] = v_sgos + if v, ok := resp["maintenanceInterval"]; ok { + schedulingMap["maintenance_interval"] = v + } + if v, ok := resp["hostErrorTimeoutSeconds"]; ok { + schedulingMap["host_error_timeout_seconds"] = ParseIntHTTP(v) + } + + if maxDurRaw, ok := resp["maxRunDuration"]; ok && maxDurRaw != nil { + maxDur := maxDurRaw.(map[string]interface{}) + schedulingMap["max_run_duration"] = []map[string]interface{}{ + { + "seconds": ParseIntHTTP(maxDur["seconds"]), + "nanos": ParseIntHTTP(maxDur["nanos"]), + }, + } + } + + if stopRaw, ok := resp["onInstanceStopAction"]; ok && stopRaw != nil { + stop := stopRaw.(map[string]interface{}) + schedulingMap["on_instance_stop_action"] = []map[string]interface{}{ + { + "discard_local_ssd": stop["discardLocalSsd"], + }, + } + } + + if timeoutRaw, ok := resp["localSsdRecoveryTimeout"]; ok && timeoutRaw != nil { + timeout := timeoutRaw.(map[string]interface{}) + schedulingMap["local_ssd_recovery_timeout"] = []map[string]interface{}{ + { + "seconds": ParseIntHTTP(timeout["seconds"]), + "nanos": ParseIntHTTP(timeout["nanos"]), + }, + } + } + if gracefulRaw, ok := resp["gracefulShutdown"]; ok && gracefulRaw != nil { + graceful := gracefulRaw.(map[string]interface{}) + graceMap := map[string]interface{}{ + "enabled": graceful["enabled"], + } + if maxDurRaw, ok := graceful["maxDuration"]; ok && maxDurRaw != nil { + maxDur := maxDurRaw.(map[string]interface{}) + graceMap["max_duration"] = []map[string]interface{}{ + { + "seconds": ParseIntHTTP(maxDur["seconds"]), + "nanos": ParseIntHTTP(maxDur["nanos"]), + }, + } + } + schedulingMap["graceful_shutdown"] = []map[string]interface{}{graceMap} + } + + if pndRaw, ok := resp["preemptionNoticeDuration"]; ok && pndRaw != nil { + pnd := pndRaw.(map[string]interface{}) + schedulingMap["preemption_notice_duration"] = []map[string]interface{}{ + { + "seconds": ParseIntHTTP(pnd["seconds"]), + "nanos": ParseIntHTTP(pnd["nanos"]), + }, + } + } + + if naRaw, ok := resp["nodeAffinities"].([]interface{}); ok && naRaw != nil { + nodeAffinities := make([]map[string]interface{}, len(naRaw)) + for i, naItem := range naRaw { + na := naItem.(map[string]interface{}) + nodeAffinity := map[string]interface{}{ + "key": na["key"], + "operator": na["operator"], + } + if valsRaw, ok := na["values"].([]interface{}); ok { + nodeAffinity["values"] = valsRaw + } + nodeAffinities[i] = nodeAffinity + } + schedulingMap["node_affinities"] = nodeAffinities + } + + return []map[string]interface{}{schedulingMap} +} + +func ParseIntHTTP(v interface{}) int { + if v == nil { + return 0 + } + switch val := v.(type) { + case string: + parsed, _ := strconv.Atoi(val) + return parsed + case float64: + return int(val) + case int: + return val + case int64: + return int(val) + default: + return 0 + } +} + +func FlattenWorkloadIdentityConfigHTTP(v interface{}) []map[string]interface{} { + if v == nil { + return nil + } + config := v.(map[string]interface{}) + return []map[string]interface{}{ + { + "identity": config["identity"], + "identity_certificate_enabled": config["identityCertificateEnabled"], + }, + } +} + +type diskCharacteristics struct { + mode string + diskType string + diskSizeGb string + autoDelete bool + sourceImage string + provisionedIops string + provisionedThroughput string +} + +func diskCharacteristicsFromMap(m map[string]interface{}) diskCharacteristics { + dc := diskCharacteristics{} + if v := m["mode"]; v == nil || v.(string) == "" { + // mode has an apply-time default of READ_WRITE + dc.mode = "READ_WRITE" + } else { + dc.mode = v.(string) + } + + if v := m["disk_type"]; v != nil { + dc.diskType = v.(string) + } + + if v := m["disk_size_gb"]; v != nil { + // Terraform and GCP return ints as different types (int vs int64), so just + // use strings to compare for simplicity. + dc.diskSizeGb = fmt.Sprintf("%v", v) + } + + if v := m["auto_delete"]; v != nil { + dc.autoDelete = v.(bool) + } + + if v := m["source_image"]; v != nil { + dc.sourceImage = v.(string) + } + + if v := m["provisioned_iops"]; v != nil { + // Terraform and GCP return ints as different types (int vs int64), so just + // use strings to compare for simplicity. + dc.provisionedIops = fmt.Sprintf("%v", v) + } + + if v := m["provisioned_throughput"]; v != nil { + // Terraform and GCP return ints as different types (int vs int64), so just + // use strings to compare for simplicity. + dc.provisionedThroughput = fmt.Sprintf("%v", v) + } + + return dc +} + +func reorderDisks(configDisks []interface{}, apiDisks []map[string]interface{}) []map[string]interface{} { + if len(apiDisks) != len(configDisks) { + // There are different numbers of disks in state and returned from the API, so it's not + // worth trying to reorder them since it'll be a diff anyway. + return apiDisks + } + + result := make([]map[string]interface{}, len(apiDisks)) + + /* + Disks aren't necessarily returned from the API in the same order they were sent, so gather + information about the ones in state that we can use to map it back. We can't do this by + just looping over all of the disks, because you could end up matching things in the wrong + order. For example, if the config disks contain the following disks: + disk 1: auto delete = false, size = 10 + disk 2: auto delete = false, size = 10, device name = "disk 2" + disk 3: type = scratch + And the disks returned from the API are: + disk a: auto delete = false, size = 10, device name = "disk 2" + disk b: auto delete = false, size = 10, device name = "disk 1" + disk c: type = scratch + Then disk a will match disk 1, disk b won't match any disk, and c will match 3, making the + final order a, c, b, which is wrong. To get disk a to match disk 2, we have to go in order + of fields most specifically able to identify a disk to least. + */ + disksByDeviceName := map[string]int{} + scratchDisksByInterface := map[string][]int{} + attachedDisksBySource := map[string]int{} + attachedDisksByDiskName := map[string]int{} + attachedDisksByCharacteristics := []int{} + + for i, d := range configDisks { + if i == 0 { + // boot disk + continue + } + disk := d.(map[string]interface{}) + if v := disk["device_name"]; v.(string) != "" { + disksByDeviceName[v.(string)] = i + } else if v := disk["type"]; v.(string) == "SCRATCH" { + iface := disk["interface"].(string) + scratchDisksByInterface[iface] = append(scratchDisksByInterface[iface], i) + } else if v := disk["source"]; v.(string) != "" { + attachedDisksBySource[v.(string)] = i + } else if v := disk["disk_name"]; v.(string) != "" { + attachedDisksByDiskName[v.(string)] = i + } else { + attachedDisksByCharacteristics = append(attachedDisksByCharacteristics, i) + } + } + + // Align the disks, going from the most specific criteria to the least. + for _, apiDisk := range apiDisks { + // 1. This resource only works if the boot disk is the first one (which should be fixed + // separately), so put the boot disk first. + if apiDisk["boot"].(bool) { + result[0] = apiDisk + + // 2. All disks have a unique device name + } else if i, ok := disksByDeviceName[apiDisk["device_name"].(string)]; ok { + result[i] = apiDisk + + // 3. Scratch disks are all the same except device name and interface, so match them by + // interface. + } else if apiDisk["type"].(string) == "SCRATCH" { + iface := apiDisk["interface"].(string) + indexes := scratchDisksByInterface[iface] + if len(indexes) > 0 { + result[indexes[0]] = apiDisk + scratchDisksByInterface[iface] = indexes[1:] + } else { + result = append(result, apiDisk) + } + + // 4. Each attached disk will have a different source, so match by that. + } else if i, ok := attachedDisksBySource[apiDisk["source"].(string)]; ok { + result[i] = apiDisk + + // 5. If a disk was created for this resource via initializeParams, it will have a + // unique name. + } else if v, ok := apiDisk["disk_name"]; ok && attachedDisksByDiskName[v.(string)] != 0 { + result[attachedDisksByDiskName[v.(string)]] = apiDisk + + // 6. If no unique keys exist on this disk, then use a combination of its remaining + // characteristics to see whether it matches exactly. + } else { + found := false + for arrayIndex, i := range attachedDisksByCharacteristics { + configDisk := configDisks[i].(map[string]interface{}) + stateDc := diskCharacteristicsFromMap(configDisk) + readDc := diskCharacteristicsFromMap(apiDisk) + if reflect.DeepEqual(stateDc, readDc) { + result[i] = apiDisk + attachedDisksByCharacteristics = append(attachedDisksByCharacteristics[:arrayIndex], attachedDisksByCharacteristics[arrayIndex+1:]...) + found = true + break + } + } + if !found { + result = append(result, apiDisk) + } + } + } + + // Remove nils from map in case there were disks that could not be matched + ds := []map[string]interface{}{} + for _, d := range result { + if d != nil { + ds = append(ds, d) + } + } + return ds +} diff --git a/tfplan2cai/converters/google/resources/services/compute/compute_region_backend_service.go b/tfplan2cai/converters/google/resources/services/compute/compute_region_backend_service.go index 350fdcce4a..16da45be5b 100644 --- a/tfplan2cai/converters/google/resources/services/compute/compute_region_backend_service.go +++ b/tfplan2cai/converters/google/resources/services/compute/compute_region_backend_service.go @@ -1840,6 +1840,20 @@ func expandComputeRegionBackendServiceLogConfig(v interface{}, d tpgresource.Ter transformed["optionalFields"] = transformedOptionalFields } + transformedRequestHeaders, err := expandComputeRegionBackendServiceLogConfigRequestHeaders(original["request_headers"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedRequestHeaders); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["loggingHttpRequestHeaders"] = transformedRequestHeaders + } + + transformedResponseHeaders, err := expandComputeRegionBackendServiceLogConfigResponseHeaders(original["response_headers"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedResponseHeaders); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["loggingHttpResponseHeaders"] = transformedResponseHeaders + } + return transformed, nil } @@ -1859,6 +1873,64 @@ func expandComputeRegionBackendServiceLogConfigOptionalFields(v interface{}, d t return v, nil } +func expandComputeRegionBackendServiceLogConfigRequestHeaders(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + if v == nil { + return nil, nil + } + l := v.([]interface{}) + req := make([]interface{}, 0, len(l)) + for _, raw := range l { + if raw == nil { + continue + } + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedHeaderName, err := expandComputeRegionBackendServiceLogConfigRequestHeadersHeaderName(original["header_name"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedHeaderName); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["headerName"] = transformedHeaderName + } + + req = append(req, transformed) + } + return req, nil +} + +func expandComputeRegionBackendServiceLogConfigRequestHeadersHeaderName(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandComputeRegionBackendServiceLogConfigResponseHeaders(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + if v == nil { + return nil, nil + } + l := v.([]interface{}) + req := make([]interface{}, 0, len(l)) + for _, raw := range l { + if raw == nil { + continue + } + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedHeaderName, err := expandComputeRegionBackendServiceLogConfigResponseHeadersHeaderName(original["header_name"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedHeaderName); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["headerName"] = transformedHeaderName + } + + req = append(req, transformed) + } + return req, nil +} + +func expandComputeRegionBackendServiceLogConfigResponseHeadersHeaderName(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + func expandComputeRegionBackendServiceNetwork(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { f, err := tpgresource.ParseGlobalFieldValue("networks", v.(string), "project", d, config, true) if err != nil { diff --git a/tfplan2cai/converters/google/resources/services/gkehub2/gkehub2_rollout_sequence.go b/tfplan2cai/converters/google/resources/services/gkehub2/gkehub2_rollout_sequence.go index e4899ea3b0..22b97a4ad9 100644 --- a/tfplan2cai/converters/google/resources/services/gkehub2/gkehub2_rollout_sequence.go +++ b/tfplan2cai/converters/google/resources/services/gkehub2/gkehub2_rollout_sequence.go @@ -49,6 +49,10 @@ import ( "google.golang.org/api/googleapi" ) +import ( + "github.com/hashicorp/go-version" +) + func parseDurationAsSeconds(v string) (int, bool) { if len(v) == 0 { return 0, false @@ -84,6 +88,150 @@ func rolloutSequenceDurationDiffSuppress(_, old, new string, _ *schema.ResourceD return oldSeconds == newSeconds } +// Compares two GKE versions using the standard go-version package. +// Returns true if minVer is strictly greater than targetVer. +// Returns true if targetVer is empty (representing a new rollout sequence). +// Returns false if minVer is empty (representing an unset min_*_version field). +func shouldUpgradeRolloutSequence(minVer, targetVer string) (bool, error) { + if minVer == "" { + return false, nil + } + minV, err := version.NewVersion(minVer) + if err != nil { + return false, fmt.Errorf("invalid min version format %q: %w", minVer, err) + } + + if targetVer == "" { + return true, nil + } + targetV, err := version.NewVersion(targetVer) + if err != nil { + return false, fmt.Errorf("invalid target version format %q: %w", targetVer, err) + } + + return minV.GreaterThan(targetV), nil +} + +// Polls the state of a RolloutSequence resource, until it enters a state other +// than INITIALIZING or until the 1h timeout passes. +func pollSequenceInitialization(d *schema.ResourceData, meta interface{}) error { + config := meta.(*transport_tpg.Config) + url, err := tpgresource.ReplaceVars(d, config, "{{GKEHub2BasePath}}projects/{{project}}/locations/global/rolloutSequences/{{rollout_sequence_id}}") + if err != nil { + return err + } + + project, err := tpgresource.GetProject(d, config) + if err != nil { + return fmt.Errorf("failed to fetch project for RolloutSequence: %w", err) + } + billingProject := project + if bp, err := tpgresource.GetBillingProject(d, config); err == nil { + billingProject = bp + } + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + if err != nil { + return err + } + + pollRead := func() (map[string]interface{}, error) { + return transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "GET", + Project: billingProject, + RawURL: url, + UserAgent: userAgent, + }) + } + + checkResponse := func(resp map[string]interface{}, respErr error) transport_tpg.PollResult { + if respErr != nil { + return transport_tpg.ErrorPollResult(respErr) + } + if resp == nil { + return transport_tpg.PendingStatusPollResult("nil response") + } + + opStateRaw, ok := resp["operationalState"] + if !ok || opStateRaw == nil { + return transport_tpg.PendingStatusPollResult("operationalState missing") + } + + opState, ok := opStateRaw.(map[string]interface{}) + if !ok { + return transport_tpg.ErrorPollResult(fmt.Errorf("operationalState is not a map")) + } + + stateRaw, ok := opState["state"] + if !ok || stateRaw == nil { + return transport_tpg.PendingStatusPollResult("state missing") + } + state, ok := stateRaw.(string) + if !ok { + return transport_tpg.ErrorPollResult(fmt.Errorf("state is not a string")) + } + + if state == "INITIALIZING" { + return transport_tpg.PendingStatusPollResult("INITIALIZING") + } + + return transport_tpg.SuccessPollResult() + } + + return transport_tpg.PollingWaitTime(pollRead, checkResponse, "Polling RolloutSequence initialization", 1*time.Hour, 1) +} + +// Fetches the current targetControlPlaneVersion and targetNodeVersion values of the RolloutSequence resource. +func fetchCurrentTargetVersions(d *schema.ResourceData, meta interface{}) (string, string, error) { + config := meta.(*transport_tpg.Config) + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + if err != nil { + return "", "", err + } + project, err := tpgresource.GetProject(d, config) + if err != nil { + return "", "", fmt.Errorf("failed to fetch project for RolloutSequence: %w", err) + } + billingProject := project + if bp, err := tpgresource.GetBillingProject(d, config); err == nil { + billingProject = bp + } + url, err := tpgresource.ReplaceVars(d, config, "{{GKEHub2BasePath}}projects/{{project}}/locations/global/rolloutSequences/{{rollout_sequence_id}}") + if err != nil { + return "", "", err + } + + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "GET", + Project: billingProject, + RawURL: url, + UserAgent: userAgent, + }) + if err != nil { + return "", "", fmt.Errorf("failed to fetch latest RolloutSequence state: %w", err) + } + + targetCPVer := "" + if v, ok := res["targetControlPlaneVersion"]; ok && v != nil { + if s, ok := v.(string); ok { + targetCPVer = s + } else { + return "", "", fmt.Errorf("expected targetControlPlaneVersion to be a string, got %T", v) + } + } + targetNodeVer := "" + if v, ok := res["targetNodeVersion"]; ok && v != nil { + if s, ok := v.(string); ok { + targetNodeVer = s + } else { + return "", "", fmt.Errorf("expected targetNodeVersion to be a string, got %T", v) + } + } + + return targetCPVer, targetNodeVer, nil +} + var ( _ = bytes.Clone _ = context.WithCancel @@ -325,7 +473,7 @@ func expandGKEHub2RolloutSequenceAutoUpgradeConfig(v interface{}, d tpgresource. transformedRolloutCreationScope, err := expandGKEHub2RolloutSequenceAutoUpgradeConfigRolloutCreationScope(original["rollout_creation_scope"], d, config) if err != nil { return nil, err - } else if val := reflect.ValueOf(transformedRolloutCreationScope); val.IsValid() && !tpgresource.IsEmptyValue(val) { + } else { transformed["rolloutCreationScope"] = transformedRolloutCreationScope } @@ -337,9 +485,14 @@ func expandGKEHub2RolloutSequenceAutoUpgradeConfigRolloutCreationScope(v interfa return nil, nil } l := v.([]interface{}) - if len(l) == 0 || l[0] == nil { + if len(l) == 0 { return nil, nil } + + if l[0] == nil { + transformed := make(map[string]interface{}) + return transformed, nil + } raw := l[0] original := raw.(map[string]interface{}) transformed := make(map[string]interface{}) @@ -347,7 +500,7 @@ func expandGKEHub2RolloutSequenceAutoUpgradeConfigRolloutCreationScope(v interfa transformedUpgradeTypes, err := expandGKEHub2RolloutSequenceAutoUpgradeConfigRolloutCreationScopeUpgradeTypes(original["upgrade_types"], d, config) if err != nil { return nil, err - } else if val := reflect.ValueOf(transformedUpgradeTypes); val.IsValid() && !tpgresource.IsEmptyValue(val) { + } else { transformed["upgradeTypes"] = transformedUpgradeTypes } diff --git a/tfplan2cai/converters/google/resources/services/modelarmor/modelarmor_template.go b/tfplan2cai/converters/google/resources/services/modelarmor/modelarmor_template.go index 7ab905bf55..739810cd72 100644 --- a/tfplan2cai/converters/google/resources/services/modelarmor/modelarmor_template.go +++ b/tfplan2cai/converters/google/resources/services/modelarmor/modelarmor_template.go @@ -477,6 +477,13 @@ func expandModelArmorTemplateTemplateMetadata(v interface{}, d tpgresource.Terra transformed["enforcementType"] = transformedEnforcementType } + transformedFilterVersionSelector, err := expandModelArmorTemplateTemplateMetadataFilterVersionSelector(original["filter_version_selector"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedFilterVersionSelector); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["filterVersionSelector"] = transformedFilterVersionSelector + } + return transformed, nil } @@ -538,6 +545,43 @@ func expandModelArmorTemplateTemplateMetadataEnforcementType(v interface{}, d tp return v, nil } +func expandModelArmorTemplateTemplateMetadataFilterVersionSelector(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + if v == nil { + return nil, nil + } + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedAlias, err := expandModelArmorTemplateTemplateMetadataFilterVersionSelectorAlias(original["alias"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedAlias); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["alias"] = transformedAlias + } + + transformedVersion, err := expandModelArmorTemplateTemplateMetadataFilterVersionSelectorVersion(original["version"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedVersion); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["version"] = transformedVersion + } + + return transformed, nil +} + +func expandModelArmorTemplateTemplateMetadataFilterVersionSelectorAlias(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandModelArmorTemplateTemplateMetadataFilterVersionSelectorVersion(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + func expandModelArmorTemplateEffectiveLabels(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (map[string]string, error) { if v == nil { return map[string]string{}, nil diff --git a/tfplan2cai/converters/google/resources/services/osconfigv2/osconfigv2_policy_orchestrator.go b/tfplan2cai/converters/google/resources/services/osconfigv2/osconfigv2_policy_orchestrator.go index b8833f993d..fa3911f83a 100644 --- a/tfplan2cai/converters/google/resources/services/osconfigv2/osconfigv2_policy_orchestrator.go +++ b/tfplan2cai/converters/google/resources/services/osconfigv2/osconfigv2_policy_orchestrator.go @@ -49,6 +49,45 @@ import ( "google.golang.org/api/googleapi" ) +func policyOrchestratorCustomizeDiff(_ context.Context, diff *schema.ResourceDiff, _ any) error { + v, ok := diff.GetOk("orchestration_scope.0.selectors") + if !ok { + return nil + } + selectors, ok := v.([]any) + if !ok { + return nil + } + for _, rawSelector := range selectors { + if rawSelector == nil { + continue + } + selector, ok := rawSelector.(map[string]any) + if !ok { + continue + } + + hasLocation := false + if val, ok := selector["location_selector"]; ok && val != nil { + if list, ok := val.([]any); ok && len(list) > 0 { + hasLocation = true + } + } + + hasHierarchy := false + if val, ok := selector["resource_hierarchy_selector"]; ok && val != nil { + if list, ok := val.([]any); ok && len(list) > 0 { + hasHierarchy = true + } + } + + if hasLocation && hasHierarchy { + return fmt.Errorf("only one of orchestration_scope.selectors.location_selector or orchestration_scope.selectors.resource_hierarchy_selector can be set") + } + } + return nil +} + var ( _ = bytes.Clone _ = context.WithCancel diff --git a/tfplan2cai/converters/google/resources/services/vectorsearch/vectorsearch_data_object.go b/tfplan2cai/converters/google/resources/services/vectorsearch/vectorsearch_data_object.go new file mode 100644 index 0000000000..639609b5d0 --- /dev/null +++ b/tfplan2cai/converters/google/resources/services/vectorsearch/vectorsearch_data_object.go @@ -0,0 +1,244 @@ +// ---------------------------------------------------------------------------- +// +// *** AUTO GENERATED CODE *** Type: MMv1 *** +// +// ---------------------------------------------------------------------------- +// +// This code is generated by Magic Modules using the following: +// +// Configuration: https://github.com/GoogleCloudPlatform/magic-modules/tree/main/mmv1/products/vectorsearch/DataObject.yaml +// Template: https://github.com/GoogleCloudPlatform/magic-modules/tree/main/mmv1/templates/tgc/resource_converter.go.tmpl +// +// DO NOT EDIT this file directly. Any changes made to this file will be +// overwritten during the next generation cycle. +// +// ---------------------------------------------------------------------------- + +package vectorsearch + +import ( + "bytes" + "context" + "encoding/base64" + "encoding/json" + "fmt" + "log" + "reflect" + "regexp" + "slices" + "sort" + "strconv" + "strings" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/id" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/logging" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/structure" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + + "github.com/GoogleCloudPlatform/terraform-google-conversion/v7/tfplan2cai/converters/google/resources/cai" + "github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport" + "github.com/hashicorp/terraform-provider-google-beta/google-beta/verify" + + "google.golang.org/api/googleapi" +) + +var ( + _ = bytes.Clone + _ = context.WithCancel + _ = base64.StdEncoding + _ = fmt.Sprintf + _ = json.Marshal + _ = log.Print + _ = reflect.ValueOf + _ = regexp.Match + _ = slices.Min([]int{1}) + _ = sort.IntSlice{} + _ = strconv.Atoi + _ = strings.Trim + _ = time.Now + _ = diag.Diagnostic{} + _ = customdiff.All + _ = id.UniqueId + _ = logging.LogLevel + _ = retry.Retry + _ = schema.Noop + _ = structure.ExpandJsonFromString + _ = validation.All + _ = terraform.State{} + _ = tpgresource.SetLabels + _ = transport_tpg.Config{} + _ = verify.ProjectRegex + _ = googleapi.Error{} +) + +const VectorSearchDataObjectAssetType string = "vectorsearch.googleapis.com/DataObject" + +func ResourceConverterVectorSearchDataObject() cai.ResourceConverter { + return cai.ResourceConverter{ + AssetType: VectorSearchDataObjectAssetType, + Convert: GetVectorSearchDataObjectCaiObject, + } +} + +func GetVectorSearchDataObjectCaiObject(d tpgresource.TerraformResourceData, config *transport_tpg.Config) ([]cai.Asset, error) { + name, err := cai.AssetName(d, config, "//vectorsearch.googleapis.com/projects/{{project}}/locations/{{location}}/collections/{{collection_id}}/dataObjects/{{data_object_id}}") + if err != nil { + return []cai.Asset{}, err + } + if obj, err := GetVectorSearchDataObjectApiObject(d, config); err == nil { + return []cai.Asset{{ + Name: name, + Type: VectorSearchDataObjectAssetType, + Resource: &cai.AssetResource{ + Version: "v1beta", + DiscoveryDocumentURI: "https://www.googleapis.com/discovery/v1/apis/vectorsearch/v1beta/rest", + DiscoveryName: "DataObject", + Data: obj, + }, + }}, nil + } else { + return []cai.Asset{}, err + } +} + +func GetVectorSearchDataObjectApiObject(d tpgresource.TerraformResourceData, config *transport_tpg.Config) (map[string]interface{}, error) { + obj := make(map[string]interface{}) + dataProp, err := expandVectorSearchDataObjectData(d.Get("data"), d, config) + if err != nil { + return nil, err + } else if v, ok := d.GetOkExists("data"); !tpgresource.IsEmptyValue(reflect.ValueOf(dataProp)) && (ok || !reflect.DeepEqual(v, dataProp)) { + obj["data"] = dataProp + } + vectorsProp, err := expandVectorSearchDataObjectVectors(d.Get("vectors"), d, config) + if err != nil { + return nil, err + } else if v, ok := d.GetOkExists("vectors"); !tpgresource.IsEmptyValue(reflect.ValueOf(vectorsProp)) && (ok || !reflect.DeepEqual(v, vectorsProp)) { + obj["vectors"] = vectorsProp + } + etagProp, err := expandVectorSearchDataObjectEtag(d.Get("etag"), d, config) + if err != nil { + return nil, err + } else if v, ok := d.GetOkExists("etag"); !tpgresource.IsEmptyValue(reflect.ValueOf(etagProp)) && (ok || !reflect.DeepEqual(v, etagProp)) { + obj["etag"] = etagProp + } + + return obj, nil +} + +func expandVectorSearchDataObjectData(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + b := []byte(v.(string)) + if len(b) == 0 { + return nil, nil + } + m := make(map[string]interface{}) + if err := json.Unmarshal(b, &m); err != nil { + return nil, err + } + return m, nil +} + +func expandVectorSearchDataObjectVectors(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (map[string]interface{}, error) { + if v == nil { + return map[string]interface{}{}, nil + } + m := make(map[string]interface{}) + for _, raw := range v.(*schema.Set).List() { + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedDense, err := expandVectorSearchDataObjectVectorsDense(original["dense"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedDense); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["dense"] = transformedDense + } + + transformedSparse, err := expandVectorSearchDataObjectVectorsSparse(original["sparse"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedSparse); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["sparse"] = transformedSparse + } + + transformedFieldName, err := tpgresource.ExpandString(original["field_name"], d, config) + if err != nil { + return nil, err + } + m[transformedFieldName] = transformed + } + return m, nil +} + +func expandVectorSearchDataObjectVectorsDense(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + if v == nil { + return nil, nil + } + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedValues, err := expandVectorSearchDataObjectVectorsDenseValues(original["values"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedValues); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["values"] = transformedValues + } + + return transformed, nil +} + +func expandVectorSearchDataObjectVectorsDenseValues(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandVectorSearchDataObjectVectorsSparse(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + if v == nil { + return nil, nil + } + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedValues, err := expandVectorSearchDataObjectVectorsSparseValues(original["values"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedValues); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["values"] = transformedValues + } + + transformedIndices, err := expandVectorSearchDataObjectVectorsSparseIndices(original["indices"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedIndices); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["indices"] = transformedIndices + } + + return transformed, nil +} + +func expandVectorSearchDataObjectVectorsSparseValues(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandVectorSearchDataObjectVectorsSparseIndices(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandVectorSearchDataObjectEtag(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} diff --git a/tfplan2cai/converters/google/resources/services/vertexai/vertexai_persistent_resource.go b/tfplan2cai/converters/google/resources/services/vertexai/vertexai_persistent_resource.go new file mode 100644 index 0000000000..6ad551a837 --- /dev/null +++ b/tfplan2cai/converters/google/resources/services/vertexai/vertexai_persistent_resource.go @@ -0,0 +1,548 @@ +// ---------------------------------------------------------------------------- +// +// *** AUTO GENERATED CODE *** Type: MMv1 *** +// +// ---------------------------------------------------------------------------- +// +// This code is generated by Magic Modules using the following: +// +// Configuration: https://github.com/GoogleCloudPlatform/magic-modules/tree/main/mmv1/products/vertexai/PersistentResource.yaml +// Template: https://github.com/GoogleCloudPlatform/magic-modules/tree/main/mmv1/templates/tgc/resource_converter.go.tmpl +// +// DO NOT EDIT this file directly. Any changes made to this file will be +// overwritten during the next generation cycle. +// +// ---------------------------------------------------------------------------- + +package vertexai + +import ( + "bytes" + "context" + "encoding/base64" + "encoding/json" + "fmt" + "log" + "reflect" + "regexp" + "slices" + "sort" + "strconv" + "strings" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/id" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/logging" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/structure" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + + "github.com/GoogleCloudPlatform/terraform-google-conversion/v7/tfplan2cai/converters/google/resources/cai" + "github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport" + "github.com/hashicorp/terraform-provider-google-beta/google-beta/verify" + + "google.golang.org/api/googleapi" +) + +var ( + _ = bytes.Clone + _ = context.WithCancel + _ = base64.StdEncoding + _ = fmt.Sprintf + _ = json.Marshal + _ = log.Print + _ = reflect.ValueOf + _ = regexp.Match + _ = slices.Min([]int{1}) + _ = sort.IntSlice{} + _ = strconv.Atoi + _ = strings.Trim + _ = time.Now + _ = diag.Diagnostic{} + _ = customdiff.All + _ = id.UniqueId + _ = logging.LogLevel + _ = retry.Retry + _ = schema.Noop + _ = structure.ExpandJsonFromString + _ = validation.All + _ = terraform.State{} + _ = tpgresource.SetLabels + _ = transport_tpg.Config{} + _ = verify.ProjectRegex + _ = googleapi.Error{} +) + +const VertexAIPersistentResourceAssetType string = "aiplatform.googleapis.com/PersistentResource" + +func ResourceConverterVertexAIPersistentResource() cai.ResourceConverter { + return cai.ResourceConverter{ + AssetType: VertexAIPersistentResourceAssetType, + Convert: GetVertexAIPersistentResourceCaiObject, + } +} + +func GetVertexAIPersistentResourceCaiObject(d tpgresource.TerraformResourceData, config *transport_tpg.Config) ([]cai.Asset, error) { + name, err := cai.AssetName(d, config, "//aiplatform.googleapis.com/projects/{{project}}/locations/{{location}}/persistentResources/{{name}}") + if err != nil { + return []cai.Asset{}, err + } + if obj, err := GetVertexAIPersistentResourceApiObject(d, config); err == nil { + return []cai.Asset{{ + Name: name, + Type: VertexAIPersistentResourceAssetType, + Resource: &cai.AssetResource{ + Version: "v1beta1", + DiscoveryDocumentURI: "https://www.googleapis.com/discovery/v1/apis/aiplatform/v1beta1/rest", + DiscoveryName: "PersistentResource", + Data: obj, + }, + }}, nil + } else { + return []cai.Asset{}, err + } +} + +func GetVertexAIPersistentResourceApiObject(d tpgresource.TerraformResourceData, config *transport_tpg.Config) (map[string]interface{}, error) { + obj := make(map[string]interface{}) + nameProp, err := expandVertexAIPersistentResourceName(d.Get("name"), d, config) + if err != nil { + return nil, err + } else if v, ok := d.GetOkExists("name"); !tpgresource.IsEmptyValue(reflect.ValueOf(nameProp)) && (ok || !reflect.DeepEqual(v, nameProp)) { + obj["name"] = nameProp + } + displayNameProp, err := expandVertexAIPersistentResourceDisplayName(d.Get("display_name"), d, config) + if err != nil { + return nil, err + } else if v, ok := d.GetOkExists("display_name"); !tpgresource.IsEmptyValue(reflect.ValueOf(displayNameProp)) && (ok || !reflect.DeepEqual(v, displayNameProp)) { + obj["displayName"] = displayNameProp + } + resourcePoolsProp, err := expandVertexAIPersistentResourceResourcePools(d.Get("resource_pools"), d, config) + if err != nil { + return nil, err + } else if v, ok := d.GetOkExists("resource_pools"); !tpgresource.IsEmptyValue(reflect.ValueOf(resourcePoolsProp)) && (ok || !reflect.DeepEqual(v, resourcePoolsProp)) { + obj["resourcePools"] = resourcePoolsProp + } + networkProp, err := expandVertexAIPersistentResourceNetwork(d.Get("network"), d, config) + if err != nil { + return nil, err + } else if v, ok := d.GetOkExists("network"); !tpgresource.IsEmptyValue(reflect.ValueOf(networkProp)) && (ok || !reflect.DeepEqual(v, networkProp)) { + obj["network"] = networkProp + } + pscInterfaceConfigProp, err := expandVertexAIPersistentResourcePscInterfaceConfig(d.Get("psc_interface_config"), d, config) + if err != nil { + return nil, err + } else if v, ok := d.GetOkExists("psc_interface_config"); !tpgresource.IsEmptyValue(reflect.ValueOf(pscInterfaceConfigProp)) && (ok || !reflect.DeepEqual(v, pscInterfaceConfigProp)) { + obj["pscInterfaceConfig"] = pscInterfaceConfigProp + } + encryptionSpecProp, err := expandVertexAIPersistentResourceEncryptionSpec(d.Get("encryption_spec"), d, config) + if err != nil { + return nil, err + } else if v, ok := d.GetOkExists("encryption_spec"); !tpgresource.IsEmptyValue(reflect.ValueOf(encryptionSpecProp)) && (ok || !reflect.DeepEqual(v, encryptionSpecProp)) { + obj["encryptionSpec"] = encryptionSpecProp + } + resourceRuntimeSpecProp, err := expandVertexAIPersistentResourceResourceRuntimeSpec(d.Get("resource_runtime_spec"), d, config) + if err != nil { + return nil, err + } else if v, ok := d.GetOkExists("resource_runtime_spec"); !tpgresource.IsEmptyValue(reflect.ValueOf(resourceRuntimeSpecProp)) && (ok || !reflect.DeepEqual(v, resourceRuntimeSpecProp)) { + obj["resourceRuntimeSpec"] = resourceRuntimeSpecProp + } + reservedIpRangesProp, err := expandVertexAIPersistentResourceReservedIpRanges(d.Get("reserved_ip_ranges"), d, config) + if err != nil { + return nil, err + } else if v, ok := d.GetOkExists("reserved_ip_ranges"); !tpgresource.IsEmptyValue(reflect.ValueOf(reservedIpRangesProp)) && (ok || !reflect.DeepEqual(v, reservedIpRangesProp)) { + obj["reservedIpRanges"] = reservedIpRangesProp + } + effectiveLabelsProp, err := expandVertexAIPersistentResourceEffectiveLabels(d.Get("effective_labels"), d, config) + if err != nil { + return nil, err + } else if v, ok := d.GetOkExists("effective_labels"); !tpgresource.IsEmptyValue(reflect.ValueOf(effectiveLabelsProp)) && (ok || !reflect.DeepEqual(v, effectiveLabelsProp)) { + obj["labels"] = effectiveLabelsProp + } + + return obj, nil +} + +func expandVertexAIPersistentResourceName(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandVertexAIPersistentResourceDisplayName(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandVertexAIPersistentResourceResourcePools(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + if v == nil { + return nil, nil + } + l := v.([]interface{}) + req := make([]interface{}, 0, len(l)) + for _, raw := range l { + if raw == nil { + continue + } + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedId, err := expandVertexAIPersistentResourceResourcePoolsId(original["id"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedId); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["id"] = transformedId + } + + transformedMachineSpec, err := expandVertexAIPersistentResourceResourcePoolsMachineSpec(original["machine_spec"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedMachineSpec); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["machineSpec"] = transformedMachineSpec + } + + transformedReplicaCount, err := expandVertexAIPersistentResourceResourcePoolsReplicaCount(original["replica_count"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedReplicaCount); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["replicaCount"] = transformedReplicaCount + } + + transformedUsedReplicaCount, err := expandVertexAIPersistentResourceResourcePoolsUsedReplicaCount(original["used_replica_count"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedUsedReplicaCount); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["usedReplicaCount"] = transformedUsedReplicaCount + } + + transformedDiskSpec, err := expandVertexAIPersistentResourceResourcePoolsDiskSpec(original["disk_spec"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedDiskSpec); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["diskSpec"] = transformedDiskSpec + } + + transformedAutoscalingSpec, err := expandVertexAIPersistentResourceResourcePoolsAutoscalingSpec(original["autoscaling_spec"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedAutoscalingSpec); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["autoscalingSpec"] = transformedAutoscalingSpec + } + + req = append(req, transformed) + } + return req, nil +} + +func expandVertexAIPersistentResourceResourcePoolsId(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandVertexAIPersistentResourceResourcePoolsMachineSpec(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + if v == nil { + return nil, nil + } + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedMachineType, err := expandVertexAIPersistentResourceResourcePoolsMachineSpecMachineType(original["machine_type"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedMachineType); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["machineType"] = transformedMachineType + } + + transformedAcceleratorType, err := expandVertexAIPersistentResourceResourcePoolsMachineSpecAcceleratorType(original["accelerator_type"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedAcceleratorType); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["acceleratorType"] = transformedAcceleratorType + } + + transformedAcceleratorCount, err := expandVertexAIPersistentResourceResourcePoolsMachineSpecAcceleratorCount(original["accelerator_count"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedAcceleratorCount); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["acceleratorCount"] = transformedAcceleratorCount + } + + return transformed, nil +} + +func expandVertexAIPersistentResourceResourcePoolsMachineSpecMachineType(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandVertexAIPersistentResourceResourcePoolsMachineSpecAcceleratorType(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandVertexAIPersistentResourceResourcePoolsMachineSpecAcceleratorCount(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandVertexAIPersistentResourceResourcePoolsReplicaCount(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandVertexAIPersistentResourceResourcePoolsUsedReplicaCount(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandVertexAIPersistentResourceResourcePoolsDiskSpec(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + if v == nil { + return nil, nil + } + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedBootDiskSizeGb, err := expandVertexAIPersistentResourceResourcePoolsDiskSpecBootDiskSizeGb(original["boot_disk_size_gb"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedBootDiskSizeGb); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["bootDiskSizeGb"] = transformedBootDiskSizeGb + } + + transformedBootDiskType, err := expandVertexAIPersistentResourceResourcePoolsDiskSpecBootDiskType(original["boot_disk_type"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedBootDiskType); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["bootDiskType"] = transformedBootDiskType + } + + return transformed, nil +} + +func expandVertexAIPersistentResourceResourcePoolsDiskSpecBootDiskSizeGb(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandVertexAIPersistentResourceResourcePoolsDiskSpecBootDiskType(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandVertexAIPersistentResourceResourcePoolsAutoscalingSpec(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + if v == nil { + return nil, nil + } + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedMinReplicaCount, err := expandVertexAIPersistentResourceResourcePoolsAutoscalingSpecMinReplicaCount(original["min_replica_count"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedMinReplicaCount); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["minReplicaCount"] = transformedMinReplicaCount + } + + transformedMaxReplicaCount, err := expandVertexAIPersistentResourceResourcePoolsAutoscalingSpecMaxReplicaCount(original["max_replica_count"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedMaxReplicaCount); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["maxReplicaCount"] = transformedMaxReplicaCount + } + + return transformed, nil +} + +func expandVertexAIPersistentResourceResourcePoolsAutoscalingSpecMinReplicaCount(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandVertexAIPersistentResourceResourcePoolsAutoscalingSpecMaxReplicaCount(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandVertexAIPersistentResourceNetwork(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandVertexAIPersistentResourcePscInterfaceConfig(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + if v == nil { + return nil, nil + } + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedNetworkAttachment, err := expandVertexAIPersistentResourcePscInterfaceConfigNetworkAttachment(original["network_attachment"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedNetworkAttachment); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["networkAttachment"] = transformedNetworkAttachment + } + + transformedDnsPeeringConfigs, err := expandVertexAIPersistentResourcePscInterfaceConfigDnsPeeringConfigs(original["dns_peering_configs"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedDnsPeeringConfigs); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["dnsPeeringConfigs"] = transformedDnsPeeringConfigs + } + + return transformed, nil +} + +func expandVertexAIPersistentResourcePscInterfaceConfigNetworkAttachment(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandVertexAIPersistentResourcePscInterfaceConfigDnsPeeringConfigs(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + if v == nil { + return nil, nil + } + l := v.([]interface{}) + req := make([]interface{}, 0, len(l)) + for _, raw := range l { + if raw == nil { + continue + } + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedDomain, err := expandVertexAIPersistentResourcePscInterfaceConfigDnsPeeringConfigsDomain(original["domain"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedDomain); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["domain"] = transformedDomain + } + + transformedTargetNetwork, err := expandVertexAIPersistentResourcePscInterfaceConfigDnsPeeringConfigsTargetNetwork(original["target_network"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedTargetNetwork); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["targetNetwork"] = transformedTargetNetwork + } + + transformedTargetProject, err := expandVertexAIPersistentResourcePscInterfaceConfigDnsPeeringConfigsTargetProject(original["target_project"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedTargetProject); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["targetProject"] = transformedTargetProject + } + + req = append(req, transformed) + } + return req, nil +} + +func expandVertexAIPersistentResourcePscInterfaceConfigDnsPeeringConfigsDomain(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandVertexAIPersistentResourcePscInterfaceConfigDnsPeeringConfigsTargetNetwork(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandVertexAIPersistentResourcePscInterfaceConfigDnsPeeringConfigsTargetProject(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandVertexAIPersistentResourceEncryptionSpec(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + if v == nil { + return nil, nil + } + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedKmsKeyName, err := expandVertexAIPersistentResourceEncryptionSpecKmsKeyName(original["kms_key_name"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedKmsKeyName); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["kmsKeyName"] = transformedKmsKeyName + } + + return transformed, nil +} + +func expandVertexAIPersistentResourceEncryptionSpecKmsKeyName(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandVertexAIPersistentResourceResourceRuntimeSpec(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + if v == nil { + return nil, nil + } + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedServiceAccountSpec, err := expandVertexAIPersistentResourceResourceRuntimeSpecServiceAccountSpec(original["service_account_spec"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedServiceAccountSpec); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["serviceAccountSpec"] = transformedServiceAccountSpec + } + + return transformed, nil +} + +func expandVertexAIPersistentResourceResourceRuntimeSpecServiceAccountSpec(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + if v == nil { + return nil, nil + } + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedEnableCustomServiceAccount, err := expandVertexAIPersistentResourceResourceRuntimeSpecServiceAccountSpecEnableCustomServiceAccount(original["enable_custom_service_account"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedEnableCustomServiceAccount); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["enableCustomServiceAccount"] = transformedEnableCustomServiceAccount + } + + return transformed, nil +} + +func expandVertexAIPersistentResourceResourceRuntimeSpecServiceAccountSpecEnableCustomServiceAccount(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandVertexAIPersistentResourceReservedIpRanges(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandVertexAIPersistentResourceEffectiveLabels(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (map[string]string, error) { + if v == nil { + return map[string]string{}, nil + } + m := make(map[string]string) + for k, val := range v.(map[string]interface{}) { + m[k] = val.(string) + } + return m, nil +} diff --git a/tfplan2cai/testdata/templates/example_compute_security_policy.json b/tfplan2cai/testdata/templates/example_compute_security_policy.json index b510426525..cb2b3327e8 100644 --- a/tfplan2cai/testdata/templates/example_compute_security_policy.json +++ b/tfplan2cai/testdata/templates/example_compute_security_policy.json @@ -12,30 +12,30 @@ "name": "my-policy", "rule": [ { - "action": "deny(403)", - "description": "Deny access to IPs in 9.9.9.0/24", + "action": "allow", + "description": "default rule", "match": { "config": { "srcIpRanges": [ - "9.9.9.0/24" + "*" ] }, "versionedExpr": "SRC_IPS_V1" }, - "priority": 1000 + "priority": 2147483647 }, { - "action": "allow", - "description": "default rule", + "action": "deny(403)", + "description": "Deny access to IPs in 9.9.9.0/24", "match": { "config": { "srcIpRanges": [ - "*" + "9.9.9.0/24" ] }, "versionedExpr": "SRC_IPS_V1" }, - "priority": 2147483647 + "priority": 1000 } ] }