From 8aad24de3aa61344205299b4331e26696ff32ffd Mon Sep 17 00:00:00 2001 From: Sarah French <15078782+SarahFrench@users.noreply.github.com> Date: Tue, 5 Nov 2024 16:07:29 +0000 Subject: [PATCH 001/105] Use TF v1.10.0-beta1 in FEATURE-BRANCH-ephemeral-resource (#12206) --- .../feature_branches/FEATURE-BRANCH-ephemeral-resource.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mmv1/third_party/terraform/.teamcity/components/projects/feature_branches/FEATURE-BRANCH-ephemeral-resource.kt b/mmv1/third_party/terraform/.teamcity/components/projects/feature_branches/FEATURE-BRANCH-ephemeral-resource.kt index 777a1c1d71fd..a17f54efd05c 100644 --- a/mmv1/third_party/terraform/.teamcity/components/projects/feature_branches/FEATURE-BRANCH-ephemeral-resource.kt +++ b/mmv1/third_party/terraform/.teamcity/components/projects/feature_branches/FEATURE-BRANCH-ephemeral-resource.kt @@ -23,7 +23,7 @@ import vcs_roots.ModularMagicianVCSRootBeta import vcs_roots.ModularMagicianVCSRootGa const val featureBranchEphemeralResources = "FEATURE-BRANCH-ephemeral-resource" -const val EphemeralResourcesTfCoreVersion = "1.10.0-alpha20241023" +const val EphemeralResourcesTfCoreVersion = "1.10.0-beta1" // featureBranchEphemeralResourcesSubProject creates a project just for testing ephemeral resources. // We know that all ephemeral resources we're adding are part of the Resource Manager service, so we only include those builds. @@ -99,4 +99,4 @@ fun featureBranchEphemeralResourcesSubProject(allConfig: AllContextParameters): readOnlySettings() } } -} \ No newline at end of file +} From f97d7e0c4c85b9be5450986e088fc24b57e7c067 Mon Sep 17 00:00:00 2001 From: Tomoya <5311731+entertvl@users.noreply.github.com> Date: Wed, 6 Nov 2024 01:47:39 +0900 Subject: [PATCH 002/105] fix(apigee): Added in-place update of `google_apigee_environment` resource (#12178) --- mmv1/products/apigee/Environment.yaml | 4 +- ...resource_apigee_environment_update_test.go | 114 ++++++++++++++++++ 2 files changed, 116 insertions(+), 2 deletions(-) create mode 100644 mmv1/third_party/terraform/services/apigee/resource_apigee_environment_update_test.go diff --git a/mmv1/products/apigee/Environment.yaml b/mmv1/products/apigee/Environment.yaml index 03433c147ff0..16275a2d9467 100644 --- a/mmv1/products/apigee/Environment.yaml +++ b/mmv1/products/apigee/Environment.yaml @@ -114,13 +114,13 @@ properties: description: | Display name of the environment. required: false - immutable: true + immutable: false - name: 'description' type: String description: | Description of the environment. required: false - immutable: true + immutable: false - name: 'deploymentType' type: Enum description: | diff --git a/mmv1/third_party/terraform/services/apigee/resource_apigee_environment_update_test.go b/mmv1/third_party/terraform/services/apigee/resource_apigee_environment_update_test.go new file mode 100644 index 000000000000..106da737aed5 --- /dev/null +++ b/mmv1/third_party/terraform/services/apigee/resource_apigee_environment_update_test.go @@ -0,0 +1,114 @@ +package apigee_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + + "github.com/hashicorp/terraform-provider-google/google/acctest" + "github.com/hashicorp/terraform-provider-google/google/envvar" +) + +func TestAccApigeeEnvironment_apigeeEnvironmentUpdateTest(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "billing_account": envvar.GetTestBillingAccountFromEnv(t), + "org_id": envvar.GetTestOrgFromEnv(t), + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckApigeeEnvironmentDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccApigeeEnvironment_apigeeEnvironmentBasicTestExample(context), + }, + { + ResourceName: "google_apigee_environment.apigee_environment", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"org_id"}, + }, + { + Config: testAccApigeeEnvironment_apigeeEnvironmentUpdateTest(context), + }, + { + ResourceName: "google_apigee_environment.apigee_environment", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"org_id"}, + }, + }, + }) +} + +func testAccApigeeEnvironment_apigeeEnvironmentUpdateTest(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_project" "project" { + project_id = "tf-test%{random_suffix}" + name = "tf-test%{random_suffix}" + org_id = "%{org_id}" + billing_account = "%{billing_account}" + deletion_policy = "DELETE" +} + +resource "google_project_service" "apigee" { + project = google_project.project.project_id + service = "apigee.googleapis.com" +} + +resource "google_project_service" "servicenetworking" { + project = google_project.project.project_id + service = "servicenetworking.googleapis.com" + depends_on = [google_project_service.apigee] +} + +resource "google_project_service" "compute" { + project = google_project.project.project_id + service = "compute.googleapis.com" + depends_on = [google_project_service.servicenetworking] +} + +resource "google_compute_network" "apigee_network" { + name = "apigee-network" + project = google_project.project.project_id + depends_on = [google_project_service.compute] +} + +resource "google_compute_global_address" "apigee_range" { + name = "apigee-range" + purpose = "VPC_PEERING" + address_type = "INTERNAL" + prefix_length = 16 + network = google_compute_network.apigee_network.id + project = google_project.project.project_id +} + +resource "google_service_networking_connection" "apigee_vpc_connection" { + network = google_compute_network.apigee_network.id + service = "servicenetworking.googleapis.com" + reserved_peering_ranges = [google_compute_global_address.apigee_range.name] + depends_on = [google_project_service.servicenetworking] +} + +resource "google_apigee_organization" "apigee_org" { + analytics_region = "us-central1" + project_id = google_project.project.project_id + authorized_network = google_compute_network.apigee_network.id + depends_on = [ + google_service_networking_connection.apigee_vpc_connection, + google_project_service.apigee, + ] +} + +resource "google_apigee_environment" "apigee_environment" { + org_id = google_apigee_organization.apigee_org.id + name = "tf-test%{random_suffix}" + description = "Updated Apigee Environment Description" + display_name = "environment-1-updated" +} +`, context) +} From 6a7b4f08423dcc7ee189f269fd4bff52f33dfb4e Mon Sep 17 00:00:00 2001 From: "Stephen Lewis (Burrows)" Date: Tue, 5 Nov 2024 08:50:35 -0800 Subject: [PATCH 003/105] Update enrolled_teams.yml (#12242) --- .../issue-labeler/labeler/enrolled_teams.yml | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/tools/issue-labeler/labeler/enrolled_teams.yml b/tools/issue-labeler/labeler/enrolled_teams.yml index b5bb5cec47b0..560a70c0f809 100755 --- a/tools/issue-labeler/labeler/enrolled_teams.yml +++ b/tools/issue-labeler/labeler/enrolled_teams.yml @@ -162,7 +162,7 @@ service/compute-instances: - google_compute_instance_template - google_compute_region_instance_template - google_compute_project_metadata.* - - google_compute_resource_policy + - google_compute_resource_policy.* service/compute-interconnect: resources: - google_compute_interconnect.* @@ -180,9 +180,9 @@ service/compute-l7-load-balancer: - google_compute_backend_service_signed_url_key - google_compute_region_backend_service - google_compute_global_forwarding_rule - - google_compute_forwarding_rule - - google_compute_url_map - - google_compute_region_url_map + - google_compute_forwarding_rule.* + - google_compute_url_map.* + - google_compute_region_url_map.* - google_compute_ssl_policy - google_compute_region_ssl_policy - google_compute_target_tcp_proxy @@ -203,7 +203,7 @@ service/compute-managed: - google_compute_resize_request.* service/compute-nat: resources: - - google_compute_router_nat + - google_compute_router_nat.* service/compute-network-peering: resources: - google_compute_network_peering.* @@ -250,6 +250,7 @@ service/compute-security-policy: - google_compute_network_edge_security_service - google_compute_region_security_policy.* - google_compute_security_policy.* + - google_compute_project_cloud_armor_tier service/compute-sole-tenancy: resources: - google_compute_node_group @@ -308,6 +309,9 @@ service/deploymentmanager: resources: - google_deployment_manager_.* - google_runtimeconfig_.* +service/developerconnect: + resources: + - google_developer_connect_.* service/dialogflow: resources: - google_dialogflow_.* @@ -519,7 +523,7 @@ service/oslogin: - google_os_login_.* service/parallelstore: resources: - - google_parallestore_.* + - google_parallelstore_.* service/policy-based-routing: resources: - google_network_connectivity_policy_based_route @@ -555,6 +559,7 @@ service/redis-cluster: service/redis-instance: resources: - google_redis_instance + - google_memorystore_instance service/regional-endpoints: resources: - google_network_connectivity_regional_endpoint @@ -576,8 +581,7 @@ service/securityposture: - google_securityposture_.* service/service-networking: resources: - - google_service_networking_connection - - google_service_networking_peered_dns_domain + - google_service_networking_.* service/servicedirectory: resources: - google_service_directory_.* From c6e460de8cef5f79f307c65095447b04f859e1d5 Mon Sep 17 00:00:00 2001 From: Chris Gonterman Date: Tue, 5 Nov 2024 10:00:19 -0800 Subject: [PATCH 004/105] Add support for GKE DNS-based endpoints (#12195) --- .../resource_container_cluster.go.tmpl | 328 +++++++++++------- .../resource_container_cluster_test.go.tmpl | 186 ++++++---- .../docs/r/container_cluster.html.markdown | 15 + 3 files changed, 329 insertions(+), 200 deletions(-) diff --git a/mmv1/third_party/terraform/services/container/resource_container_cluster.go.tmpl b/mmv1/third_party/terraform/services/container/resource_container_cluster.go.tmpl index 11ec2ae1880d..c82a92ddc8b6 100644 --- a/mmv1/third_party/terraform/services/container/resource_container_cluster.go.tmpl +++ b/mmv1/third_party/terraform/services/container/resource_container_cluster.go.tmpl @@ -56,6 +56,12 @@ var ( Computed: true, Description: `Whether Kubernetes master is accessible via Google Compute Engine Public IPs.`, }, + "private_endpoint_enforcement_enabled": { + Type: schema.TypeBool, + Optional: true, + Computed: true, + Description: `Whether authorized networks is enforced on the private endpoint or not. Defaults to false.`, + }, }, } cidrBlockConfig = &schema.Resource{ @@ -1720,6 +1726,40 @@ func ResourceContainerCluster() *schema.Resource { ConflictsWith: []string{"enable_autopilot"}, }, + "control_plane_endpoints_config": { + Type: schema.TypeList, + MaxItems: 1, + Computed: true, + Optional: true, + Description: `Configuration for all of the cluster's control plane endpoints. Currently supports only DNS endpoint configuration, IP endpoint configuration is available in private_cluster_config.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "dns_endpoint_config": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Computed: true, + Description: `DNS endpoint configuration.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "endpoint": { + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: `The cluster's DNS endpoint.`, + }, + "allow_external_traffic": { + Type: schema.TypeBool, + Optional: true, + Description: `Controls whether user traffic is allowed over this endpoint. Note that GCP-managed services may still use the endpoint even if this is false.`, + }, + }, + }, + }, + }, + }, + }, + "private_cluster_config": { Type: schema.TypeList, MaxItems: 1, @@ -2402,7 +2442,7 @@ func resourceContainerClusterCreate(d *schema.ResourceData, meta interface{}) er Name: clusterName, InitialNodeCount: int64(d.Get("initial_node_count").(int)), MaintenancePolicy: expandMaintenancePolicy(d, meta), - MasterAuthorizedNetworksConfig: expandMasterAuthorizedNetworksConfig(d.Get("master_authorized_networks_config"), d), + ControlPlaneEndpointsConfig: expandControlPlaneEndpointsConfig(d), InitialClusterVersion: d.Get("min_master_version").(string), ClusterIpv4Cidr: d.Get("cluster_ipv4_cidr").(string), Description: d.Get("description").(string), @@ -2442,6 +2482,7 @@ func resourceContainerClusterCreate(d *schema.ResourceData, meta interface{}) er DnsConfig: expandDnsConfig(d.Get("dns_config")), GatewayApiConfig: expandGatewayApiConfig(d.Get("gateway_api_config")), EnableMultiNetworking: d.Get("enable_multi_networking").(bool), + DefaultEnablePrivateNodes: expandDefaultEnablePrivateNodes(d), {{- if ne $.TargetVersionName "ga" }} EnableFqdnNetworkPolicy: d.Get("enable_fqdn_network_policy").(bool), {{- end }} @@ -2540,8 +2581,8 @@ func resourceContainerClusterCreate(d *schema.ResourceData, meta interface{}) er cluster.AuthenticatorGroupsConfig = expandAuthenticatorGroupsConfig(v) } - if v, ok := d.GetOk("private_cluster_config"); ok { - cluster.PrivateClusterConfig = expandPrivateClusterConfig(v) + if v, ok := d.GetOk("private_cluster_config.0.master_ipv4_cidr_block"); ok { + cluster.PrivateClusterConfig = expandPrivateClusterConfigMasterIpv4CidrBlock(v, cluster) } if v, ok := d.GetOk("vertical_pod_autoscaling"); ok { @@ -2598,10 +2639,6 @@ func resourceContainerClusterCreate(d *schema.ResourceData, meta interface{}) er return err } - if err := validatePrivateClusterConfig(cluster); err != nil { - return err - } - if v, ok := d.GetOk("security_posture_config"); ok { cluster.SecurityPostureConfig = expandSecurityPostureConfig(v) } @@ -2892,8 +2929,11 @@ func resourceContainerClusterRead(d *schema.ResourceData, meta interface{}) erro if err := d.Set("master_auth", flattenMasterAuth(cluster.MasterAuth)); err != nil { return err } - if err := d.Set("master_authorized_networks_config", flattenMasterAuthorizedNetworksConfig(cluster.MasterAuthorizedNetworksConfig)); err != nil { - return err + if cluster.ControlPlaneEndpointsConfig != nil && + cluster.ControlPlaneEndpointsConfig.IpEndpointsConfig != nil { + if err := d.Set("master_authorized_networks_config", flattenMasterAuthorizedNetworksConfig(cluster.ControlPlaneEndpointsConfig.IpEndpointsConfig.AuthorizedNetworksConfig)); err != nil { + return err + } } if err := d.Set("initial_node_count", cluster.InitialNodeCount); err != nil { return fmt.Errorf("Error setting initial_node_count: %s", err) @@ -3029,7 +3069,11 @@ func resourceContainerClusterRead(d *schema.ResourceData, meta interface{}) erro return err } - if err := d.Set("private_cluster_config", flattenPrivateClusterConfig(cluster.PrivateClusterConfig)); err != nil { + if err := d.Set("control_plane_endpoints_config", flattenControlPlaneEndpointsConfig(cluster.ControlPlaneEndpointsConfig)); err != nil { + return err + } + + if err := d.Set("private_cluster_config", flattenPrivateClusterConfig(cluster.ControlPlaneEndpointsConfig, cluster.PrivateClusterConfig, cluster.NetworkConfig)); err != nil { return err } @@ -3183,19 +3227,39 @@ func resourceContainerClusterUpdate(d *schema.ResourceData, meta interface{}) er // The ClusterUpdate object that we use for most of these updates only allows updating one field at a time, // so we have to make separate calls for each field that we want to update. The order here is fairly arbitrary- // if the order of updating fields does matter, it is called out explicitly. - if d.HasChange("master_authorized_networks_config") { - c := d.Get("master_authorized_networks_config") + if d.HasChange("control_plane_endpoints_config") || + d.HasChange("master_authorized_networks_config") || + d.HasChange("private_cluster_config.0.enable_private_endpoint") || + d.HasChange("private_cluster_config.0.master_global_access_config") { + req := &container.UpdateClusterRequest{ + Update: &container.ClusterUpdate{ + DesiredControlPlaneEndpointsConfig: expandControlPlaneEndpointsConfig(d), + }, + } + + updateF := updateFunc(req, "updating GKE control plane endpoints config") + if err := transport_tpg.LockedCall(lockKey, updateF); err != nil { + return err + } + log.Printf("[INFO] GKE cluster %s control plane endpoints config has been updated", d.Id()) + } + + if d.HasChange("network_config") || d.HasChange("private_cluster_config.0.enable_private_nodes"){ + enabled := expandDefaultEnablePrivateNodes(d) req := &container.UpdateClusterRequest{ Update: &container.ClusterUpdate{ - DesiredMasterAuthorizedNetworksConfig: expandMasterAuthorizedNetworksConfig(c, d), + DesiredDefaultEnablePrivateNodes: enabled, + ForceSendFields: []string{"DesiredDefaultEnablePrivateNodes"}, }, } - updateF := updateFunc(req, "updating GKE cluster master authorized networks") + updateF := updateFunc(req, "updating default enable private nodes") + // Call update serially. if err := transport_tpg.LockedCall(lockKey, updateF); err != nil { return err } - log.Printf("[INFO] GKE cluster %s master authorized networks config has been updated", d.Id()) + + log.Printf("[INFO] GKE cluster %s's default enable private nodes has been updated to %v", d.Id(), enabled) } if d.HasChange("addons_config") { @@ -3266,44 +3330,6 @@ func resourceContainerClusterUpdate(d *schema.ResourceData, meta interface{}) er log.Printf("[INFO] GKE cluster %s's autopilot workload policy config allow_net_admin has been set to %v", d.Id(), allowed) } - if d.HasChange("private_cluster_config.0.enable_private_endpoint") { - enabled := d.Get("private_cluster_config.0.enable_private_endpoint").(bool) - req := &container.UpdateClusterRequest{ - Update: &container.ClusterUpdate{ - DesiredEnablePrivateEndpoint: enabled, - ForceSendFields: []string{"DesiredEnablePrivateEndpoint"}, - }, - } - - updateF := updateFunc(req, "updating enable private endpoint") - // Call update serially. - if err := transport_tpg.LockedCall(lockKey, updateF); err != nil { - return err - } - - log.Printf("[INFO] GKE cluster %s's enable private endpoint has been updated to %v", d.Id(), enabled) - } - - if d.HasChange("private_cluster_config") && d.HasChange("private_cluster_config.0.master_global_access_config") { - config := d.Get("private_cluster_config.0.master_global_access_config") - req := &container.UpdateClusterRequest{ - Update: &container.ClusterUpdate{ - DesiredPrivateClusterConfig: &container.PrivateClusterConfig{ - MasterGlobalAccessConfig: expandPrivateClusterConfigMasterGlobalAccessConfig(config), - ForceSendFields: []string{"MasterGlobalAccessConfig"}, - }, - }, - } - - updateF := updateFunc(req, "updating master global access config") - // Call update serially. - if err := transport_tpg.LockedCall(lockKey, updateF); err != nil { - return err - } - - log.Printf("[INFO] GKE cluster %s's master global access config has been updated to %v", d.Id(), config) - } - if d.HasChange("binary_authorization") { req := &container.UpdateClusterRequest{ Update: &container.ClusterUpdate{ @@ -5304,32 +5330,49 @@ func expandMasterAuth(configured interface{}) *container.MasterAuth { return result } -func expandMasterAuthorizedNetworksConfig(configured interface{}, d *schema.ResourceData) *container.MasterAuthorizedNetworksConfig { - l := configured.([]interface{}) - if len(l) == 0 { + +func expandMasterAuthorizedNetworksConfig(d *schema.ResourceData) *container.MasterAuthorizedNetworksConfig { + v := d.Get("master_authorized_networks_config").([]interface{}) + if len(v) == 0 { + // TF doesn't have an explicit enabled field for authorized networks, it is assumed to be enabled based + // on whether the master_authorized_networks_conifg is present at all. The GKE API pays attention to the + // field presence of authorized_networks_config, so it's important to explicitly include enabled = false + // to allow disabling this during updates. return &container.MasterAuthorizedNetworksConfig{ Enabled: false, } } + result := &container.MasterAuthorizedNetworksConfig{ Enabled: true, } - if config, ok := l[0].(map[string]interface{}); ok { - if _, ok := config["cidr_blocks"]; ok { - cidrBlocks := config["cidr_blocks"].(*schema.Set).List() - result.CidrBlocks = make([]*container.CidrBlock, 0) - for _, v := range cidrBlocks { - cidrBlock := v.(map[string]interface{}) - result.CidrBlocks = append(result.CidrBlocks, &container.CidrBlock{ - CidrBlock: cidrBlock["cidr_block"].(string), - DisplayName: cidrBlock["display_name"].(string), - }) - } - } - if v, ok := d.GetOkExists("master_authorized_networks_config.0.gcp_public_cidrs_access_enabled"); ok { - result.GcpPublicCidrsAccessEnabled = v.(bool) - result.ForceSendFields = []string{"GcpPublicCidrsAccessEnabled"} - } + if v, ok := d.GetOk("master_authorized_networks_config.0.cidr_blocks"); ok { + result.CidrBlocks = expandManCidrBlocks(v) + } + if v, ok := d.GetOkExists("master_authorized_networks_config.0.gcp_public_cidrs_access_enabled"); ok { + result.GcpPublicCidrsAccessEnabled = v.(bool) + result.ForceSendFields = append(result.ForceSendFields, "GcpPublicCidrsAccessEnabled") + } + if v, ok := d.GetOkExists("master_authorized_networks_config.0.private_endpoint_enforcement_enabled"); ok { + result.PrivateEndpointEnforcementEnabled = v.(bool) + result.ForceSendFields = append(result.ForceSendFields, "PrivateEndpointEnforcementEnabled") + } + return result +} + +func expandManCidrBlocks(configured interface{}) []*container.CidrBlock { + config, ok := configured.(*schema.Set) + if !ok { + return nil + } + cidrBlocks := config.List() + result := make([]*container.CidrBlock, 0) + for _, v := range cidrBlocks { + cidrBlock := v.(map[string]interface{}) + result = append(result, &container.CidrBlock{ + CidrBlock: cidrBlock["cidr_block"].(string), + DisplayName: cidrBlock["display_name"].(string), + }) } return result } @@ -5373,31 +5416,60 @@ func isEnablePDCSI(cluster *container.Cluster) bool { return cluster.AddonsConfig.GcePersistentDiskCsiDriverConfig.Enabled } -func expandPrivateClusterConfig(configured interface{}) *container.PrivateClusterConfig { - l := configured.([]interface{}) - if len(l) == 0 { - return nil - } - config := l[0].(map[string]interface{}) +// Most of the contents of PrivateClusterConfig have been deprecated in the underlying API and replaced by ControlPlaneEndpointsConfig. +// This function primarily handles the sole remaining undeprecated field, master_ipv4_cidr_block. +// Unfortunately, since the private_cluster_config.enable_private_nodes proto field is not marked optional, we can't just leave it +// unset, as that would implicitly use the value false, and it must match the value of network_config.default_enable_private_nodes. +// This function is intended to be called only during cluster creation, after the network_config field is been configured. +// This is possible because master_ipv4_cidr_block is immutable. +func expandPrivateClusterConfigMasterIpv4CidrBlock(configured interface{}, c *container.Cluster) *container.PrivateClusterConfig { + v := configured.(string) + return &container.PrivateClusterConfig{ - EnablePrivateEndpoint: config["enable_private_endpoint"].(bool), - EnablePrivateNodes: config["enable_private_nodes"].(bool), - MasterIpv4CidrBlock: config["master_ipv4_cidr_block"].(string), - MasterGlobalAccessConfig: expandPrivateClusterConfigMasterGlobalAccessConfig(config["master_global_access_config"]), - PrivateEndpointSubnetwork: config["private_endpoint_subnetwork"].(string), - ForceSendFields: []string{"EnablePrivateEndpoint", "EnablePrivateNodes", "MasterIpv4CidrBlock", "MasterGlobalAccessConfig"}, + MasterIpv4CidrBlock: v, + EnablePrivateNodes: c.NetworkConfig.DefaultEnablePrivateNodes, + ForceSendFields: []string{"MasterIpv4CidrBlock"}, } } -func expandPrivateClusterConfigMasterGlobalAccessConfig(configured interface{}) *container.PrivateClusterMasterGlobalAccessConfig { - l := configured.([]interface{}) - if len(l) == 0 { - return nil +func expandDefaultEnablePrivateNodes(d *schema.ResourceData) bool { + b, ok := d.GetOk("private_cluster_config.0.enable_private_nodes") + if ok { + v, _ := b.(bool) + return v } - config := l[0].(map[string]interface{}) - return &container.PrivateClusterMasterGlobalAccessConfig{ - Enabled: config["enabled"].(bool), - ForceSendFields: []string{"Enabled"}, + return false +} + +func expandControlPlaneEndpointsConfig(d *schema.ResourceData) *container.ControlPlaneEndpointsConfig { + dns := &container.DNSEndpointConfig{} + if v := d.Get("control_plane_endpoints_config.0.dns_endpoint_config.0.allow_external_traffic"); v != nil { + dns.AllowExternalTraffic = v.(bool) + dns.ForceSendFields = []string{"AllowExternalTraffic"} + } + + ip := &container.IPEndpointsConfig{ + // There isn't yet a config field to disable IP endpoints, so this is hardcoded to be enabled for the time being. + Enabled: true, + ForceSendFields: []string{"Enabled"}, + } + if v := d.Get("private_cluster_config.0.enable_private_endpoint"); v != nil { + ip.EnablePublicEndpoint = !v.(bool) + ip.ForceSendFields = append(ip.ForceSendFields, "EnablePublicEndpoint") + } + if v := d.Get("private_cluster_config.0.private_endpoint_subnetwork"); v != nil { + ip.PrivateEndpointSubnetwork = v.(string) + ip.ForceSendFields = append(ip.ForceSendFields, "PrivateEndpointSubnetwork") + } + if v := d.Get("private_cluster_config.0.master_global_access_config.0.enabled"); v != nil { + ip.GlobalAccess = v.(bool) + ip.ForceSendFields = append(ip.ForceSendFields, "GlobalAccess") + } + ip.AuthorizedNetworksConfig = expandMasterAuthorizedNetworksConfig(d) + + return &container.ControlPlaneEndpointsConfig{ + DnsEndpointConfig: dns, + IpEndpointsConfig: ip, } } @@ -6073,35 +6145,60 @@ func flattenAuthenticatorGroupsConfig(c *container.AuthenticatorGroupsConfig) [] } } -func flattenPrivateClusterConfig(c *container.PrivateClusterConfig) []map[string]interface{} { +func flattenControlPlaneEndpointsConfig(c *container.ControlPlaneEndpointsConfig) []map[string]interface{} { if c == nil { return nil } return []map[string]interface{}{ { - "enable_private_endpoint": c.EnablePrivateEndpoint, - "enable_private_nodes": c.EnablePrivateNodes, - "master_ipv4_cidr_block": c.MasterIpv4CidrBlock, - "master_global_access_config": flattenPrivateClusterConfigMasterGlobalAccessConfig(c.MasterGlobalAccessConfig), - "peering_name": c.PeeringName, - "private_endpoint": c.PrivateEndpoint, - "private_endpoint_subnetwork": c.PrivateEndpointSubnetwork, - "public_endpoint": c.PublicEndpoint, + "dns_endpoint_config": flattenDnsEndpointConfig(c.DnsEndpointConfig), }, } } -// Like most GKE blocks, this is not returned from the API at all when false. This causes trouble -// for users who've set enabled = false in config as they will get a permadiff. Always setting the -// field resolves that. We can assume if it was not returned, it's false. -func flattenPrivateClusterConfigMasterGlobalAccessConfig(c *container.PrivateClusterMasterGlobalAccessConfig) []map[string]interface{} { +func flattenDnsEndpointConfig(dns *container.DNSEndpointConfig) []map[string]interface{} { + if dns == nil { + return nil + } return []map[string]interface{}{ { - "enabled": c != nil && c.Enabled, + "endpoint": dns.Endpoint, + "allow_external_traffic": dns.AllowExternalTraffic, }, } } +// Most of PrivateClusterConfig has moved to ControlPlaneEndpointsConfig. +func flattenPrivateClusterConfig(cpec *container.ControlPlaneEndpointsConfig, pcc *container.PrivateClusterConfig, nc *container.NetworkConfig) []map[string]interface{} { + if cpec == nil && pcc == nil && nc == nil { + return nil + } + + r := map[string]interface{}{} + if cpec != nil { + // Note the change in semantics from private to public endpoint. + r["enable_private_endpoint"] = !cpec.IpEndpointsConfig.EnablePublicEndpoint + r["private_endpoint"] = cpec.IpEndpointsConfig.PrivateEndpoint + r["private_endpoint_subnetwork"] = cpec.IpEndpointsConfig.PrivateEndpointSubnetwork + r["public_endpoint"] = cpec.IpEndpointsConfig.PublicEndpoint + r["master_global_access_config"] = []map[string]interface{}{ + { + "enabled": cpec.IpEndpointsConfig.GlobalAccess, + }, + } + } + // This is the only field that is canonically still in the PrivateClusterConfig message. + if pcc != nil { + r["peering_name"] = pcc.PeeringName + r["master_ipv4_cidr_block"] = pcc.MasterIpv4CidrBlock + } + if nc != nil { + r["enable_private_nodes"] = nc.DefaultEnablePrivateNodes + } + + return []map[string]interface{}{r} +} + func flattenVerticalPodAutoscaling(c *container.VerticalPodAutoscaling) []map[string]interface{} { if c == nil { return nil @@ -6429,6 +6526,7 @@ func flattenMasterAuthorizedNetworksConfig(c *container.MasterAuthorizedNetworks } result["cidr_blocks"] = schema.NewSet(schema.HashResource(cidrBlockConfig), cidrBlocks) result["gcp_public_cidrs_access_enabled"] = c.GcpPublicCidrsAccessEnabled + result["private_endpoint_enforcement_enabled"] = c.PrivateEndpointEnforcementEnabled return []map[string]interface{}{result} } @@ -6845,24 +6943,6 @@ func containerClusterPrivateClusterConfigSuppress(k, old, new string, d *schema. return false } -func validatePrivateClusterConfig(cluster *container.Cluster) error { - if cluster == nil || cluster.PrivateClusterConfig == nil { - return nil - } - if !cluster.PrivateClusterConfig.EnablePrivateNodes && len(cluster.PrivateClusterConfig.MasterIpv4CidrBlock) > 0 { - return fmt.Errorf("master_ipv4_cidr_block can only be set if enable_private_nodes is true") - } - if cluster.PrivateClusterConfig.EnablePrivateNodes && len(cluster.PrivateClusterConfig.MasterIpv4CidrBlock) == 0 { - if len(cluster.PrivateClusterConfig.PrivateEndpointSubnetwork) > 0 { - return nil - } - if cluster.Autopilot == nil || !cluster.Autopilot.Enabled { - return fmt.Errorf("master_ipv4_cidr_block must be set if enable_private_nodes is true") - } - } - return nil -} - // Autopilot clusters have preconfigured defaults: https://cloud.google.com/kubernetes-engine/docs/concepts/autopilot-overview#comparison. // This function modifies the diff so users can see what these will be during plan time. func containerClusterAutopilotCustomizeDiff(_ context.Context, d *schema.ResourceDiff, meta interface{}) error { diff --git a/mmv1/third_party/terraform/services/container/resource_container_cluster_test.go.tmpl b/mmv1/third_party/terraform/services/container/resource_container_cluster_test.go.tmpl index cb4361681f15..20e762df541f 100644 --- a/mmv1/third_party/terraform/services/container/resource_container_cluster_test.go.tmpl +++ b/mmv1/third_party/terraform/services/container/resource_container_cluster_test.go.tmpl @@ -1208,6 +1208,61 @@ resource "google_container_cluster" "with_gcp_public_cidrs_access_enabled" { `, clusterName, networkName, subnetworkName) } +func TestAccContainerCluster_withAuthorizedNetworkPrivateEnforcementToggle(t *testing.T) { + t.Parallel() + + clusterName := fmt.Sprintf("tf-test-cluster-%s", acctest.RandString(t, 10)) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckContainerClusterDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccContainerCluster_withAuthorizedNetworkPrivateEnforcementToggle(clusterName, false), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("google_container_cluster.primary", + "master_authorized_networks_config.0.private_endpoint_enforcement_enabled", "false"), + ), + }, + { + ResourceName: "google_container_cluster.primary", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, + }, + { + Config: testAccContainerCluster_withAuthorizedNetworkPrivateEnforcementToggle(clusterName, true), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("google_container_cluster.primary", + "master_authorized_networks_config.0.private_endpoint_enforcement_enabled", "true"), + ), + }, + { + ResourceName: "google_container_cluster.primary", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, + }, + }, + }) +} + +func testAccContainerCluster_withAuthorizedNetworkPrivateEnforcementToggle(clusterName string, enabled bool) string { + return fmt.Sprintf(` +resource "google_container_cluster" "primary" { + name = "%s" + location = "us-central1-a" + initial_node_count = 1 + deletion_protection = false + + master_authorized_networks_config { + private_endpoint_enforcement_enabled = %t + } +} +`, clusterName, enabled) +} + func TestAccContainerCluster_regional(t *testing.T) { t.Parallel() @@ -1355,49 +1410,6 @@ func TestAccContainerCluster_withPrivateClusterConfigBasic(t *testing.T) { }) } -func TestAccContainerCluster_withPrivateClusterConfigMissingCidrBlock(t *testing.T) { - t.Parallel() - - clusterName := fmt.Sprintf("tf-test-cluster-%s", acctest.RandString(t, 10)) - containerNetName := fmt.Sprintf("tf-test-container-net-%s", acctest.RandString(t, 10)) - - acctest.VcrTest(t, resource.TestCase{ - PreCheck: func() { acctest.AccTestPreCheck(t) }, - ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), - CheckDestroy: testAccCheckContainerClusterDestroyProducer(t), - Steps: []resource.TestStep{ - { - Config: testAccContainerCluster_withPrivateClusterConfigMissingCidrBlock(containerNetName, clusterName, "us-central1-a", false), - ExpectError: regexp.MustCompile("master_ipv4_cidr_block must be set if enable_private_nodes is true"), - }, - }, - }) -} - -func TestAccContainerCluster_withPrivateClusterConfigMissingCidrBlock_withAutopilot(t *testing.T) { - t.Parallel() - - clusterName := fmt.Sprintf("tf-test-cluster-%s", acctest.RandString(t, 10)) - containerNetName := fmt.Sprintf("tf-test-container-net-%s", acctest.RandString(t, 10)) - - acctest.VcrTest(t, resource.TestCase{ - PreCheck: func() { acctest.AccTestPreCheck(t) }, - ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), - CheckDestroy: testAccCheckContainerClusterDestroyProducer(t), - Steps: []resource.TestStep{ - { - Config: testAccContainerCluster_withPrivateClusterConfigMissingCidrBlock(containerNetName, clusterName, "us-central1", true), - }, - { - ResourceName: "google_container_cluster.with_private_cluster", - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"deletion_protection"}, - }, - }, - }) -} - func TestAccContainerCluster_withPrivateClusterConfigGlobalAccessEnabledOnly(t *testing.T) { t.Parallel() @@ -5014,23 +5026,6 @@ func TestAccContainerCluster_withIncompatibleMasterVersionNodeVersion(t *testing }) } -func TestAccContainerCluster_withIPv4Error(t *testing.T) { - t.Parallel() - - clusterName := fmt.Sprintf("tf-test-cluster-%s", acctest.RandString(t, 10)) - acctest.VcrTest(t, resource.TestCase{ - PreCheck: func() { acctest.AccTestPreCheck(t) }, - ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), - CheckDestroy: testAccCheckContainerClusterDestroyProducer(t), - Steps: []resource.TestStep{ - { - Config: testAccContainerCluster_withIPv4Error(clusterName), - ExpectError: regexp.MustCompile("master_ipv4_cidr_block can only be set if"), - }, - }, - }) -} - func TestAccContainerCluster_withDNSConfig(t *testing.T) { t.Parallel() @@ -10357,22 +10352,6 @@ resource "google_container_cluster" "primary" { `, cluster, networkName, subnetworkName) } -func testAccContainerCluster_withIPv4Error(name string) string { - return fmt.Sprintf(` -resource "google_container_cluster" "primary" { - name = "%s" - location = "us-central1-a" - initial_node_count = 1 - private_cluster_config { - enable_private_endpoint = true - enable_private_nodes = false - master_ipv4_cidr_block = "10.42.0.0/28" - } - deletion_protection = false -} -`, name) -} - func testAccContainerCluster_withAutopilot(projectID string, containerNetName string, clusterName string, location string, enabled bool, withNetworkTag bool, serviceAccount string) string { config := "" clusterAutoscaling := "" @@ -12615,3 +12594,58 @@ resource "google_container_cluster" "with_autopilot_gcp_filestore" { } `, name) } + +func TestAccContainerCluster_withDnsEndpoint(t *testing.T) { + t.Parallel() + + clusterName := fmt.Sprintf("tf-test-cluster-%s", acctest.RandString(t, 10)) + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckContainerClusterDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccContainerCluster_withDnsEndpoint(clusterName, false), + Check: resource.ComposeAggregateTestCheckFunc( + // The DNS endpoint should always be set, even if allow_external_traffic is false. + resource.TestCheckResourceAttrSet("google_container_cluster.primary", "control_plane_endpoints_config.0.dns_endpoint_config.0.endpoint"), + resource.TestCheckResourceAttr("google_container_cluster.primary", "control_plane_endpoints_config.0.dns_endpoint_config.0.allow_external_traffic", "false"), + ), + }, + { + ResourceName: "google_container_cluster.primary", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, + }, + { + Config: testAccContainerCluster_withDnsEndpoint(clusterName, true), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttrSet("google_container_cluster.primary", "control_plane_endpoints_config.0.dns_endpoint_config.0.endpoint"), + resource.TestCheckResourceAttr("google_container_cluster.primary", "control_plane_endpoints_config.0.dns_endpoint_config.0.allow_external_traffic", "true"), + ), + }, + { + ResourceName: "google_container_cluster.primary", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, + }, + }, + }) +} + +func testAccContainerCluster_withDnsEndpoint(name string, enabled bool) string { + return fmt.Sprintf(` +resource "google_container_cluster" "primary" { + name = "%s" + location = "us-central1-a" + initial_node_count = 1 + deletion_protection = false + control_plane_endpoints_config { + dns_endpoint_config { + allow_external_traffic = %t + } + } +}`, name, enabled) +} diff --git a/mmv1/third_party/terraform/website/docs/r/container_cluster.html.markdown b/mmv1/third_party/terraform/website/docs/r/container_cluster.html.markdown index 5f1a2961a4f9..229241d93a9d 100644 --- a/mmv1/third_party/terraform/website/docs/r/container_cluster.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/container_cluster.html.markdown @@ -300,6 +300,9 @@ region are guaranteed to support the same version. [Google Groups for GKE](https://cloud.google.com/kubernetes-engine/docs/how-to/role-based-access-control#groups-setup-gsuite) feature. Structure is [documented below](#nested_authenticator_groups_config). +* `control_plane_endpoints_config` - (Optional) Configuration for all of the cluster's control plane endpoints. + Structure is [documented below](#nested_control_plane_endpoints_config). + * `private_cluster_config` - (Optional) Configuration for [private clusters](https://cloud.google.com/kubernetes-engine/docs/how-to/private-clusters), clusters with private nodes. Structure is [documented below](#nested_private_cluster_config). @@ -817,6 +820,8 @@ The `master_authorized_networks_config.cidr_blocks` block supports: * `display_name` - (Optional) Field for users to identify CIDR blocks. +* `private_endpoint_enforcement_enabled` - (Optional) Whether authorized networks is enforced on the private endpoint or not. + The `network_policy` block supports: * `provider` - (Optional) The selected network policy provider. Defaults to PROVIDER_UNSPECIFIED. @@ -1166,6 +1171,16 @@ notification_config { * `enabled` (Required) - Enable the Secret Manager add-on for this cluster. +The `control_plane_endpoints_config` block supports: + +* `dns_endpoint_config` - (Optional) DNS endpoint configuration. + +The `control_plane_endpoints_config.dns_endpoint_config` block supports: + +* `endpoint` - (Output) The cluster's DNS endpoint. + +* `allow_external_traffic` - (Optional) Controls whether user traffic is allowed over this endpoint. Note that GCP-managed services may still use the endpoint even if this is false. + The `private_cluster_config` block supports: * `enable_private_nodes` (Optional) - Enables the private cluster feature, From 1e79ce7e1fd460fd68397a6706e8f5ab91bb2123 Mon Sep 17 00:00:00 2001 From: Will Yardley Date: Tue, 5 Nov 2024 10:05:37 -0800 Subject: [PATCH 005/105] cloudsql: fixed typo in `google_sql_database_instance` (#12247) --- .../website/docs/r/sql_database_instance.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mmv1/third_party/terraform/website/docs/r/sql_database_instance.html.markdown b/mmv1/third_party/terraform/website/docs/r/sql_database_instance.html.markdown index 6469d2373385..f69adc6e2c8c 100644 --- a/mmv1/third_party/terraform/website/docs/r/sql_database_instance.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/sql_database_instance.html.markdown @@ -525,7 +525,7 @@ exported: * `connection_name` - The connection name of the instance to be used in connection strings. For example, when connecting with [Cloud SQL Proxy](https://cloud.google.com/sql/docs/mysql/connect-admin-proxy). -* `dsn_name` - The DNS name of the instance. See [Connect to an instance using Private Service Connect](https://cloud.google.com/sql/docs/mysql/configure-private-service-connect#view-summary-information-cloud-sql-instances-psc-enabled) for more details. +* `dns_name` - The DNS name of the instance. See [Connect to an instance using Private Service Connect](https://cloud.google.com/sql/docs/mysql/configure-private-service-connect#view-summary-information-cloud-sql-instances-psc-enabled) for more details. * `service_account_email_address` - The service account email address assigned to the instance. From 92224148914b1c96000cb1b84cd8dffb196a5a9d Mon Sep 17 00:00:00 2001 From: Niharika <35183015+niharika-98@users.noreply.github.com> Date: Tue, 5 Nov 2024 23:43:00 +0530 Subject: [PATCH 006/105] Adding google_backup_dr_backup_plan_association resource and datasource (#12159) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: William Yardley Co-authored-by: Sarah French <15078782+SarahFrench@users.noreply.github.com> Co-authored-by: varshatumburu <54908599+varshatumburu@users.noreply.github.com> Co-authored-by: kautikdk <144651627+kautikdk@users.noreply.github.com> Co-authored-by: bestefreund <81525627+bestefreund@users.noreply.github.com> Co-authored-by: Will Yardley Co-authored-by: Ahmet Salih Aksakal <32795193+aymat13@users.noreply.github.com> Co-authored-by: Matheus Guilherme Souza Aleixo <82680416+matheusaleixo-cit@users.noreply.github.com> Co-authored-by: haiyanmeng Co-authored-by: Thomas Rodgers Co-authored-by: Philip Sabri Co-authored-by: Chris Hawk Co-authored-by: Strahinja Kustudic Co-authored-by: bindermuehle Co-authored-by: wj-chen Co-authored-by: bbonafil <139291060+bbonafil@users.noreply.github.com> Co-authored-by: bryan0515 Co-authored-by: Zhenhua Li Co-authored-by: Julia Matuszewska <47438768+JumiDeluxe@users.noreply.github.com> Co-authored-by: Shuya Ma <87669292+shuyama1@users.noreply.github.com> Co-authored-by: Abhijeet Jha Co-authored-by: Hossein Golestani Co-authored-by: Alexander Thomas Co-authored-by: karolgorc Co-authored-by: dorianverna Co-authored-by: Uriel Guzmán Co-authored-by: gfxcc Co-authored-by: Taahir Ahmed Co-authored-by: Benyamin Bashari Co-authored-by: himanikh Co-authored-by: apichick Co-authored-by: Nick Elliot Co-authored-by: Rokas Petraitis Co-authored-by: Stephen Lewis (Burrows) Co-authored-by: NickChittle Co-authored-by: Stephen Lewis (Burrows) Co-authored-by: chayan kumar roy Co-authored-by: Scott Suarez Co-authored-by: Mauricio Alvarez Leon <65101411+BBBmau@users.noreply.github.com> Co-authored-by: Lei (Jerry) Ding Co-authored-by: Jerry Ding Co-authored-by: Sam Levenick Co-authored-by: Ryan Oaks Co-authored-by: Jirka Korejtko Co-authored-by: Cameron Thornton --- .../backupdr/BackupPlanAssociation.yaml | 133 ++++++++++++++++++ .../terraform/examples/backup_dr_bpa.tf.tmpl | 74 ++++++++++ .../provider/provider_mmv1_resources.go.tmpl | 1 + ..._backup_dr_backup_plan_association.go.tmpl | 48 +++++++ ...up_dr_backup_plan_association_test.go.tmpl | 131 +++++++++++++++++ ...p_dr_backup_plan_association.html.markdown | 34 +++++ 6 files changed, 421 insertions(+) create mode 100644 mmv1/products/backupdr/BackupPlanAssociation.yaml create mode 100644 mmv1/templates/terraform/examples/backup_dr_bpa.tf.tmpl create mode 100644 mmv1/third_party/terraform/services/backupdr/data_source_backup_dr_backup_plan_association.go.tmpl create mode 100644 mmv1/third_party/terraform/services/backupdr/data_source_backup_dr_backup_plan_association_test.go.tmpl create mode 100644 mmv1/third_party/terraform/website/docs/d/backup_dr_backup_plan_association.html.markdown diff --git a/mmv1/products/backupdr/BackupPlanAssociation.yaml b/mmv1/products/backupdr/BackupPlanAssociation.yaml new file mode 100644 index 000000000000..54d12de17cad --- /dev/null +++ b/mmv1/products/backupdr/BackupPlanAssociation.yaml @@ -0,0 +1,133 @@ +# Copyright 2024 Google Inc. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +name: 'BackupPlanAssociation' +min_version: beta +base_url: projects/{{project}}/locations/{{location}}/backupPlanAssociations +create_url: projects/{{project}}/locations/{{location}}/backupPlanAssociations/?backup_plan_association_id={{backup_plan_association_id}} +self_link: projects/{{project}}/locations/{{location}}/backupPlanAssociations/{{backup_plan_association_id}} +immutable: true +delete_url: projects/{{project}}/locations/{{location}}/backupPlanAssociations/{{backup_plan_association_id}} +description: A Backup and DR BackupPlanAssociation. +import_format: + - 'projects/{{project}}/locations/{{location}}/backupPlanAssociations/{{backup_plan_association_id}}' +references: + guides: + 'Official Documentation': 'https://cloud.google.com/backup-disaster-recovery/docs' + api: 'https://cloud.google.com/backup-disaster-recovery/docs/reference/rest' +autogen_async: true +timeouts: + insert_minutes: 60 + delete_minutes: 60 +examples: + - min_version: beta + name: 'backup_dr_bpa' + primary_resource_id: 'my-backup-plan-association' + vars: + backup_plan_association_id: "my-bpa" + compute-name: "test-instance" + backup_vault_id: "bv-bpa" + backup_plan_id: "bp-bpa-test" + account_id: "my-custom" + test_env_vars: + project: "PROJECT_NAME" +parameters: + - name: 'location' + type: String + required: true + url_param_only: true + description: | + The location for the backupplan association + - name: 'backup_plan_association_id' + type: String + required: true + url_param_only: true + description: |- + The id of backupplan association +properties: + - name: 'resource' + type: String + description: | + The resource for which BPA needs to be created + required: true + ignore_read: true + - name: 'name' + type: String + description: | + The name of backup plan association resource created + output: true + - name: 'backupPlan' + type: String + description: | + The BP with which resource needs to be created + required: true + diff_suppress_func: 'tpgresource.ProjectNumberDiffSuppress' + - name: 'resourceType' + type: String + description: | + The resource type of workload on which backupplan is applied + required: true + - name: 'createTime' + type: String + description: | + The time when the instance was created + output: true + - name: 'updateTime' + type: String + description: | + The time when the instance was updated. + output: true + - name: 'dataSource' + type: String + description: | + Resource name of data source which will be used as storage location for backups taken + output: true + - name: 'rulesConfigInfo' + type: Array + output: true + description: | + Message for rules config info + item_type: + type: NestedObject + properties: + - name: 'ruleId' + type: String + description: Backup Rule id fetched from backup plan. + output: true + - name: 'lastBackupState' + type: Enum + description: State of last backup taken. + enum_values: + - :LAST_BACKUP_STATE_UNSPECIFIED + - :FIRST_BACKUP_PENDING + - :PERMISSION_DENIED + - :SUCCEEDED + - :FAILED + output: true + - name: 'lastBackupError' + type: NestedObject + description: google.rpc.Status object to store the last backup error + output: true + properties: + - name: 'code' + type: Double + output: true + description: The status code, which should be an enum value of [google.rpc.Code] + - name: 'message' + type: String + description: A developer-facing error message, which should be in English. + output: true + - name: 'lastSuccessfulBackupConsistencyTime' + type: String + description: The point in time when the last successful backup was captured from the source + output: true diff --git a/mmv1/templates/terraform/examples/backup_dr_bpa.tf.tmpl b/mmv1/templates/terraform/examples/backup_dr_bpa.tf.tmpl new file mode 100644 index 000000000000..467d2de52477 --- /dev/null +++ b/mmv1/templates/terraform/examples/backup_dr_bpa.tf.tmpl @@ -0,0 +1,74 @@ + resource "google_service_account" "mySA" { + provider = google-beta + account_id = "{{index $.Vars "account_id"}}" + display_name = "Custom SA for VM Instance" +} + +resource "google_compute_instance" "myinstance" { + provider = google-beta + name = "{{index $.Vars "compute-name"}}" + machine_type = "n2-standard-2" + zone = "us-central1-a" + boot_disk { + initialize_params { + image = "debian-cloud/debian-11" + labels = { + my_label = "value" + } + } + } + // Local SSD disk + scratch_disk { + interface = "NVME" + } + network_interface { + network = "default" + access_config { + // Ephemeral public IP + } + } + service_account { + email = google_service_account.mySA.email + scopes = ["cloud-platform"] + } +} + +resource "google_backup_dr_backup_vault" "bv1" { + provider = google-beta + location = "us-central1" + backup_vault_id = "{{index $.Vars "backup_vault_id"}}" + backup_minimum_enforced_retention_duration = "100000s" + force_delete = "true" +} + +resource "google_backup_dr_backup_plan" "bp1" { + provider = google-beta + location = "us-central1" + backup_plan_id = "{{index $.Vars "backup_plan_id"}}" + resource_type = "compute.googleapis.com/Instance" + backup_vault = google_backup_dr_backup_vault.bv1.id + + backup_rules { + rule_id = "rule-1" + backup_retention_days = 2 + + standard_schedule { + recurrence_type = "HOURLY" + hourly_frequency = 6 + time_zone = "UTC" + + backup_window { + start_hour_of_day = 12 + end_hour_of_day = 18 + } + } + } +} +resource "google_backup_dr_backup_plan_association" "{{$.PrimaryResourceId}}" { + provider = google-beta + location = "us-central1" + resource_type= "compute.googleapis.com/Instance" + backup_plan_association_id = "{{index $.Vars "backup_plan_association_id"}}" + resource = google_compute_instance.myinstance.id + backup_plan = google_backup_dr_backup_plan.bp1.name +} diff --git a/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.tmpl b/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.tmpl index 1ea130a607f1..3508200e16b8 100644 --- a/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.tmpl +++ b/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.tmpl @@ -35,6 +35,7 @@ var handwrittenDatasources = map[string]*schema.Resource{ "google_apphub_discovered_service": apphub.DataSourceApphubDiscoveredService(), {{- if ne $.TargetVersionName "ga" }} "google_backup_dr_management_server": backupdr.DataSourceGoogleCloudBackupDRService(), + "google_backup_dr_backup_plan_association": backupdr.DataSourceGoogleCloudBackupDRBackupPlanAssociation(), "google_backup_dr_backup_plan": backupdr.DataSourceGoogleCloudBackupDRBackupPlan(), {{- end }} "google_beyondcorp_app_connection": beyondcorp.DataSourceGoogleBeyondcorpAppConnection(), diff --git a/mmv1/third_party/terraform/services/backupdr/data_source_backup_dr_backup_plan_association.go.tmpl b/mmv1/third_party/terraform/services/backupdr/data_source_backup_dr_backup_plan_association.go.tmpl new file mode 100644 index 000000000000..a7d74cbe0a32 --- /dev/null +++ b/mmv1/third_party/terraform/services/backupdr/data_source_backup_dr_backup_plan_association.go.tmpl @@ -0,0 +1,48 @@ +package backupdr +{{- if ne $.TargetVersionName "ga" }} + +import ( + "fmt" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-provider-google/google/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" +) + +func DataSourceGoogleCloudBackupDRBackupPlanAssociation() *schema.Resource { + + dsSchema := tpgresource.DatasourceSchemaFromResourceSchema(ResourceBackupDRBackupPlanAssociation().Schema) + // Set 'Required' schema elements + tpgresource.AddRequiredFieldsToSchema(dsSchema, "backup_plan_association_id", "location") + + // Set 'Optional' schema elements + tpgresource.AddOptionalFieldsToSchema(dsSchema, "project") + return &schema.Resource{ + Read: dataSourceGoogleCloudBackupDRBackupPlanAssociationRead, + Schema: dsSchema, + } +} + +func dataSourceGoogleCloudBackupDRBackupPlanAssociationRead(d *schema.ResourceData, meta interface{}) error { + config := meta.(*transport_tpg.Config) + project, err := tpgresource.GetProject(d, config) + if err != nil { + return err + } + + location, err := tpgresource.GetLocation(d, config) + if err != nil { + return err + } + backup_plan_association_id := d.Get("backup_plan_association_id").(string) + id := fmt.Sprintf("projects/%s/locations/%s/backupPlanAssociations/%s", project, location, backup_plan_association_id) + d.SetId(id) + err = resourceBackupDRBackupPlanAssociationRead(d, meta) + if err != nil { + return err + } + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + return nil +} +{{- end }} diff --git a/mmv1/third_party/terraform/services/backupdr/data_source_backup_dr_backup_plan_association_test.go.tmpl b/mmv1/third_party/terraform/services/backupdr/data_source_backup_dr_backup_plan_association_test.go.tmpl new file mode 100644 index 000000000000..0e1e7a5f4551 --- /dev/null +++ b/mmv1/third_party/terraform/services/backupdr/data_source_backup_dr_backup_plan_association_test.go.tmpl @@ -0,0 +1,131 @@ +package backupdr_test +{{- if ne $.TargetVersionName "ga" }} + +import ( + "testing" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-provider-google/google/acctest" +) + +func TestAccDataSourceGoogleBackupDRBackupPlanAssociation_basic(t *testing.T) { + t.Parallel() + context := map[string]interface{}{ + "random_suffix": acctest.RandString(t, 10), + } + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t), + Steps: []resource.TestStep{ + { + Config: testAccDataSourceGoogleBackupDRBackupPlanAssociation_basic(context), + Check: resource.ComposeTestCheckFunc( + acctest.CheckDataSourceStateMatchesResourceStateWithIgnores("data.google_backup_dr_backup_plan_association.bpa-test", "google_backup_dr_backup_plan_association.bpa",map[string]struct{}{ + "resource": {}, + }, + ), + ), + }, + }, + }) +} + +func testAccDataSourceGoogleBackupDRBackupPlanAssociation_basic(context map[string]interface{}) string { +return acctest.Nprintf(` + +resource "google_service_account" "default" { + provider = google-beta + account_id = "tf-test-my-custom-%{random_suffix}" + display_name = "Custom SA for VM Instance" +} + +resource "google_compute_instance" "default" { + provider = google-beta + name = "tf-test-compute-instance-%{random_suffix}" + machine_type = "n2-standard-2" + zone = "us-central1-a" + tags = ["foo", "bar"] + boot_disk { + initialize_params { + image = "debian-cloud/debian-11" + labels = { + my_label = "value" + } + } + } + // Local SSD disk + scratch_disk { + interface = "NVME" + } + network_interface { + network = "default" + access_config { + // Ephemeral public IP + } + } + service_account { + # Google recommends custom service accounts that have cloud-platform scope and permissions granted via IAM Roles. + email = google_service_account.default.email + scopes = ["cloud-platform"] + } +} +resource "google_backup_dr_backup_vault" "my-backup-vault" { + provider = google-beta + location ="us-central1" + backup_vault_id = "tf-test-bv-%{random_suffix}" + description = "This is a second backup vault built by Terraform." + backup_minimum_enforced_retention_duration = "100000s" + labels = { + foo = "bar1" + bar = "baz1" + } + annotations = { + annotations1 = "bar1" + annotations2 = "baz1" + } + force_update = "true" + force_delete = "true" + allow_missing = "true" +} + +resource "google_backup_dr_backup_plan" "foo" { + provider = google-beta + location = "us-central1" + backup_plan_id = "tf-test-bp-test-%{random_suffix}" + resource_type = "compute.googleapis.com/Instance" + backup_vault = google_backup_dr_backup_vault.my-backup-vault.name + + backup_rules { + rule_id = "rule-1" + backup_retention_days = 2 + + standard_schedule { + recurrence_type = "HOURLY" + hourly_frequency = 6 + time_zone = "UTC" + + backup_window { + start_hour_of_day = 12 + end_hour_of_day = 18 + } + } + } +} + +resource "google_backup_dr_backup_plan_association" "bpa" { + provider = google-beta + location = "us-central1" + backup_plan_association_id = "tf-test-bpa-test-%{random_suffix}" + resource = google_compute_instance.default.id + resource_type= "compute.googleapis.com/Instance" + backup_plan = google_backup_dr_backup_plan.foo.name +} + +data "google_backup_dr_backup_plan_association" "bpa-test" { + provider = google-beta + location = "us-central1" + backup_plan_association_id="tf-test-bpa-test-%{random_suffix}" + depends_on= [ google_backup_dr_backup_plan_association.bpa ] + } +`, context) +} +{{- end }} \ No newline at end of file diff --git a/mmv1/third_party/terraform/website/docs/d/backup_dr_backup_plan_association.html.markdown b/mmv1/third_party/terraform/website/docs/d/backup_dr_backup_plan_association.html.markdown new file mode 100644 index 000000000000..096b6a102752 --- /dev/null +++ b/mmv1/third_party/terraform/website/docs/d/backup_dr_backup_plan_association.html.markdown @@ -0,0 +1,34 @@ +--- +subcategory: "Backup and DR BackupPlanAssociation" +description: |- + Get information about a Backupdr BackupPlanAssociation. +--- + +# google_backup_dr_backup_plan_association + +A Backup and DR BackupPlanAssociation. + +~> **Warning:** This resource is in beta, and should be used with the terraform-provider-google-beta provider. +See [Provider Versions](https://terraform.io/docs/providers/google/guides/provider_versions.html) for more details on beta resources. + +## Example Usage + +```hcl +data "google_backup_dr_backup_plan_association" "my-backupplan-association" { + location = "us-central1" + backup_plan_association_id="bpa-id" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `location` - (Required) The location in which the Backupplan association resource belongs. +* `backup_plan_association_id` - (Required) The id of Backupplan association resource. + +- - - + +## Attributes Reference + +See [google_backup_dr_backup_plan_association](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/backup_dr_backup_plan_association) resource for details of the available attributes. From 4eb884bf855479aa799f47e2757d7161f331cb8b Mon Sep 17 00:00:00 2001 From: Will Yardley Date: Tue, 5 Nov 2024 11:05:31 -0800 Subject: [PATCH 007/105] looker: required `oauth_config` in `google_looker_instance` (#12214) --- mmv1/products/looker/Instance.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/mmv1/products/looker/Instance.yaml b/mmv1/products/looker/Instance.yaml index 35f569e30cfa..099675827187 100644 --- a/mmv1/products/looker/Instance.yaml +++ b/mmv1/products/looker/Instance.yaml @@ -390,6 +390,7 @@ properties: description: | Looker Instance OAuth login settings. ignore_read: true + required: true properties: - name: 'clientId' type: String From 9c562c5132b1eb36452ea2810e416cd245532f10 Mon Sep 17 00:00:00 2001 From: derekchu-google Date: Tue, 5 Nov 2024 11:10:18 -0800 Subject: [PATCH 008/105] add `google_iam_principal_access_boundary_policy` resource (#12044) Co-authored-by: Sarah French <15078782+SarahFrench@users.noreply.github.com> --- .../iam3/PrincipalAccessBoundaryPolicy.yaml | 161 ++++++++++++++++++ mmv1/products/iam3/product.yaml | 21 +++ ...m_principal_access_boundary_policy.tf.tmpl | 7 + .../components/inputs/services_beta.kt | 5 + .../components/inputs/services_ga.kt | 5 + ...ncipal_access_boundary_policy_test.go.tmpl | 88 ++++++++++ 6 files changed, 287 insertions(+) create mode 100644 mmv1/products/iam3/PrincipalAccessBoundaryPolicy.yaml create mode 100644 mmv1/products/iam3/product.yaml create mode 100644 mmv1/templates/terraform/examples/iam_principal_access_boundary_policy.tf.tmpl create mode 100644 mmv1/third_party/terraform/services/iam3/resource_iam_principal_access_boundary_policy_test.go.tmpl diff --git a/mmv1/products/iam3/PrincipalAccessBoundaryPolicy.yaml b/mmv1/products/iam3/PrincipalAccessBoundaryPolicy.yaml new file mode 100644 index 000000000000..37c47fec2230 --- /dev/null +++ b/mmv1/products/iam3/PrincipalAccessBoundaryPolicy.yaml @@ -0,0 +1,161 @@ +# Copyright 2024 Google Inc. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- +name: 'PrincipalAccessBoundaryPolicy' +description: An IAM Principal Access Boundary Policy resource +references: + guides: + 'Create and apply Principal Access Boundaries': 'https://cloud.google.com/iam/docs/principal-access-boundary-policies-create' + api: 'https://cloud.google.com/iam/docs/reference/rest/v3beta/organizations.locations.principalAccessBoundaryPolicies' +min_version: 'beta' +id_format: 'organizations/{{organization}}/locations/{{location}}/principalAccessBoundaryPolicies/{{principal_access_boundary_policy_id}}' +base_url: 'organizations/{{organization}}/locations/{{location}}/principalAccessBoundaryPolicies' +self_link: 'organizations/{{organization}}/locations/{{location}}/principalAccessBoundaryPolicies/{{principal_access_boundary_policy_id}}' +create_url: 'organizations/{{organization}}/locations/{{location}}/principalAccessBoundaryPolicies?principalAccessBoundaryPolicyId={{principal_access_boundary_policy_id}}' +update_verb: 'PATCH' +update_mask: true +import_format: + - 'organizations/{{organization}}/locations/{{location}}/principalAccessBoundaryPolicies/{{principal_access_boundary_policy_id}}' +timeouts: + insert_minutes: 20 + update_minutes: 20 + delete_minutes: 20 +autogen_async: true +async: + actions: ['create', 'delete', 'update'] + type: 'OpAsync' + operation: + base_url: '{{op_id}}' + path: 'name' + wait_ms: 1000 + result: + path: 'response' + resource_inside_response: true + error: + path: 'error' + message: 'message' +examples: + - name: 'iam_principal_access_boundary_policy' + min_version: 'beta' + primary_resource_id: 'my-pab-policy' + test_env_vars: + org_id: 'ORG_ID' + vars: + display_name: 'test pab policy' + pab_id: 'test-pab-policy' +parameters: + - name: 'organization' + type: String + description: | + The parent organization of the principal access boundary policy. + url_param_only: true + required: true + immutable: true + - name: 'location' + type: String + description: | + The location the principal access boundary policy is in. + url_param_only: true + required: true + immutable: true + - name: 'principalAccessBoundaryPolicyId' + type: String + description: | + The ID to use to create the principal access boundary policy. + This value must start with a lowercase letter followed by up to 62 lowercase letters, numbers, hyphens, or dots. Pattern, /a-z{2,62}/. + url_param_only: true + required: true + immutable: true +properties: + - name: 'name' + type: String + description: | + Identifier. The resource name of the principal access boundary policy. The following format is supported: + `organizations/{organization_id}/locations/{location}/principalAccessBoundaryPolicies/{policy_id}` + output: true + - name: 'uid' + type: String + description: | + Output only. The globally unique ID of the principal access boundary policy. + output: true + - name: 'etag' + type: String + description: | + The etag for the principal access boundary. If this is provided on update, it must match the server's etag. + output: true + - name: 'displayName' + type: String + description: | + The description of the principal access boundary policy. Must be less than or equal to 63 characters. + - name: 'annotations' + type: KeyValueAnnotations + description: | + User defined annotations. See https://google.aip.dev/148#annotations + for more details such as format and size limitations + - name: 'createTime' + type: String + description: | + Output only. The time when the principal access boundary policy was created. + output: true + - name: 'updateTime' + type: String + description: | + Output only. The time when the principal access boundary policy was most recently updated. + output: true + - name: 'details' + type: NestedObject + description: | + Principal access boundary policy details + default_from_api: true + properties: + - name: 'rules' + type: Array + description: | + A list of principal access boundary policy rules. The number of rules in a policy is limited to 500. + required: true + item_type: + type: NestedObject + properties: + - name: 'description' + type: String + description: | + The description of the principal access boundary policy rule. Must be less than or equal to 256 characters. + - name: 'resources' + type: Array + description: | + A list of Cloud Resource Manager resources. The resource + and all the descendants are included. The number of resources in a policy + is limited to 500 across all rules. + The following resource types are supported: + * Organizations, such as `//cloudresourcemanager.googleapis.com/organizations/123`. + * Folders, such as `//cloudresourcemanager.googleapis.com/folders/123`. + * Projects, such as `//cloudresourcemanager.googleapis.com/projects/123` + or `//cloudresourcemanager.googleapis.com/projects/my-project-id`. + required: true + item_type: + type: String + - name: 'effect' + type: String + description: | + The access relationship of principals to the resources in this rule. + Possible values: ALLOW + required: true + - name: 'enforcementVersion' + type: String + description: | + The version number that indicates which Google Cloud services + are included in the enforcement (e.g. \"latest\", \"1\", ...). If empty, the + PAB policy version will be set to the current latest version, and this version + won't get updated when new versions are released. + default_from_api: true diff --git a/mmv1/products/iam3/product.yaml b/mmv1/products/iam3/product.yaml new file mode 100644 index 000000000000..1ca1d7d66f38 --- /dev/null +++ b/mmv1/products/iam3/product.yaml @@ -0,0 +1,21 @@ +# Copyright 2024 Google Inc. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +name: 'IAM3' +legacy_name: 'iam' +display_name: 'Cloud IAM' +versions: + - name: 'beta' + base_url: 'https://iam.googleapis.com/v3beta/' +scopes: + - 'https://www.googleapis.com/auth/iam' diff --git a/mmv1/templates/terraform/examples/iam_principal_access_boundary_policy.tf.tmpl b/mmv1/templates/terraform/examples/iam_principal_access_boundary_policy.tf.tmpl new file mode 100644 index 000000000000..0eb3adf7b293 --- /dev/null +++ b/mmv1/templates/terraform/examples/iam_principal_access_boundary_policy.tf.tmpl @@ -0,0 +1,7 @@ +resource "google_iam_principal_access_boundary_policy" "{{$.PrimaryResourceId}}" { + provider = google-beta + organization = "{{index $.TestEnvVars "org_id"}}" + location = "global" + display_name = "{{index $.Vars "display_name"}}" + principal_access_boundary_policy_id = "{{index $.Vars "pab_id"}}" +} diff --git a/mmv1/third_party/terraform/.teamcity/components/inputs/services_beta.kt b/mmv1/third_party/terraform/.teamcity/components/inputs/services_beta.kt index b378b86de26c..b025568eac6d 100644 --- a/mmv1/third_party/terraform/.teamcity/components/inputs/services_beta.kt +++ b/mmv1/third_party/terraform/.teamcity/components/inputs/services_beta.kt @@ -446,6 +446,11 @@ var ServicesListBeta = mapOf( "displayName" to "Iam2", "path" to "./google-beta/services/iam2" ), + "iam3" to mapOf( + "name" to "iam3", + "displayName" to "Iam3", + "path" to "./google-beta/services/iam3" + ), "iambeta" to mapOf( "name" to "iambeta", "displayName" to "Iambeta", diff --git a/mmv1/third_party/terraform/.teamcity/components/inputs/services_ga.kt b/mmv1/third_party/terraform/.teamcity/components/inputs/services_ga.kt index f9da8cffa168..5087bad11881 100644 --- a/mmv1/third_party/terraform/.teamcity/components/inputs/services_ga.kt +++ b/mmv1/third_party/terraform/.teamcity/components/inputs/services_ga.kt @@ -441,6 +441,11 @@ var ServicesListGa = mapOf( "displayName" to "Iam2", "path" to "./google/services/iam2" ), + "iam3" to mapOf( + "name" to "iam3", + "displayName" to "Iam3", + "path" to "./google/services/iam3" + ), "iambeta" to mapOf( "name" to "iambeta", "displayName" to "Iambeta", diff --git a/mmv1/third_party/terraform/services/iam3/resource_iam_principal_access_boundary_policy_test.go.tmpl b/mmv1/third_party/terraform/services/iam3/resource_iam_principal_access_boundary_policy_test.go.tmpl new file mode 100644 index 000000000000..39bd480e9cc6 --- /dev/null +++ b/mmv1/third_party/terraform/services/iam3/resource_iam_principal_access_boundary_policy_test.go.tmpl @@ -0,0 +1,88 @@ +package iam3_test +{{- if ne $.TargetVersionName "ga" }} + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-provider-google/google/acctest" + "github.com/hashicorp/terraform-provider-google/google/envvar" +) + +func TestAccIAM3PrincipalAccessBoundaryPolicy_iam3PrincipalAccessBoundaryPolicyExample_update(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "org_id": envvar.GetTestOrgFromEnv(t), + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t), + CheckDestroy: testAccCheckIAM3PrincipalAccessBoundaryPolicyDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccIAM3PrincipalAccessBoundaryPolicy_iam3PrincipalAccessBoundaryPolicyExample_full(context), + }, + { + ResourceName: "google_iam_principal_access_boundary_policy.my-pab-policy", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"annotations", "location", "organization", "principal_access_boundary_policy_id", "etag"}, + }, + { + Config: testAccIAM3PrincipalAccessBoundaryPolicy_iam3PrincipalAccessBoundaryPolicyExample_update(context), + }, + { + ResourceName: "google_iam_principal_access_boundary_policy.my-pab-policy", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"annotations", "location", "organization", "principal_access_boundary_policy_id", "etag"}, + }, + }, + }) +} + +func testAccIAM3PrincipalAccessBoundaryPolicy_iam3PrincipalAccessBoundaryPolicyExample_full(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_iam_principal_access_boundary_policy" "my-pab-policy" { + provider = google-beta + organization = "%{org_id}" + location = "global" + display_name = "test pab policy%{random_suffix}" + principal_access_boundary_policy_id = "test-pab-policy%{random_suffix}" +} +`, context) +} + +func testAccIAM3PrincipalAccessBoundaryPolicy_iam3PrincipalAccessBoundaryPolicyExample_update(context map[string]interface{}) string { + return acctest.Nprintf(` + +resource "google_project" "project" { + provider = google-beta + project_id = "tf-test%{random_suffix}" + name = "tf-test%{random_suffix}" + org_id = "%{org_id}" + deletion_policy = "DELETE" +} + +resource "google_iam_principal_access_boundary_policy" "my-pab-policy" { + provider = google-beta + organization = "%{org_id}" + location = "global" + display_name = "test pab policy%{random_suffix}" + principal_access_boundary_policy_id = "test-pab-policy%{random_suffix}" + annotations = {"foo": "bar"} + details { + rules { + description = "PAB rule%{random_suffix}" + effect = "ALLOW" + resources = ["//cloudresourcemanager.googleapis.com/projects/${google_project.project.project_id}"] + } + enforcement_version = "1" + } +} +`, context) +} +{{- end }} From e4f5b0e092d8cb402a699d95e7d737608715dcde Mon Sep 17 00:00:00 2001 From: sahsagar-google <126025352+sahsagar-google@users.noreply.github.com> Date: Tue, 5 Nov 2024 15:50:42 -0800 Subject: [PATCH 009/105] =?UTF-8?q?Resolving=20test=20failure:=20adding=20?= =?UTF-8?q?the=20pre-update=20scope=20in=20the=20updated=20sc=E2=80=A6=20(?= =?UTF-8?q?#12252)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../gkehub2/resource_gke_hub_membership_binding_test.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mmv1/third_party/terraform/services/gkehub2/resource_gke_hub_membership_binding_test.go b/mmv1/third_party/terraform/services/gkehub2/resource_gke_hub_membership_binding_test.go index 9d3cc36caea2..9f8b0530e171 100644 --- a/mmv1/third_party/terraform/services/gkehub2/resource_gke_hub_membership_binding_test.go +++ b/mmv1/third_party/terraform/services/gkehub2/resource_gke_hub_membership_binding_test.go @@ -114,6 +114,10 @@ resource "google_gke_hub_membership" "example" { depends_on = [google_container_cluster.primary] } +resource "google_gke_hub_scope" "example" { + scope_id = "tf-test-scope%{random_suffix}" +} + resource "google_gke_hub_scope" "example2" { scope_id = "tf-test-scope2%{random_suffix}" } From e8a9b97048f37ad92d777ec5ab705471fa4664ba Mon Sep 17 00:00:00 2001 From: Philip Jonany <72227955+Philip-Jonany@users.noreply.github.com> Date: Tue, 5 Nov 2024 19:34:18 -0800 Subject: [PATCH 010/105] Support SQL Server Switchover (after resolving email rebase conflicts) (#12241) Co-authored-by: Philip Jonany --- .../resource_sql_database_instance.go.tmpl | 119 +++++++- .../resource_sql_database_instance_test.go | 261 +++++++++++++++++- .../sql_instance_switchover.html.markdown | 86 ++++++ .../r/sql_database_instance.html.markdown | 44 ++- 4 files changed, 493 insertions(+), 17 deletions(-) create mode 100644 mmv1/third_party/terraform/website/docs/guides/sql_instance_switchover.html.markdown diff --git a/mmv1/third_party/terraform/services/sql/resource_sql_database_instance.go.tmpl b/mmv1/third_party/terraform/services/sql/resource_sql_database_instance.go.tmpl index 08da2c84defc..88e812273422 100644 --- a/mmv1/third_party/terraform/services/sql/resource_sql_database_instance.go.tmpl +++ b/mmv1/third_party/terraform/services/sql/resource_sql_database_instance.go.tmpl @@ -6,6 +6,7 @@ import ( "fmt" "log" "reflect" + "slices" "strings" "time" @@ -89,6 +90,7 @@ var ( } replicaConfigurationKeys = []string{ + "replica_configuration.0.cascadable_replica", "replica_configuration.0.ca_certificate", "replica_configuration.0.client_certificate", "replica_configuration.0.client_key", @@ -136,7 +138,13 @@ func ResourceSqlDatabaseInstance() *schema.Resource { CustomizeDiff: customdiff.All( tpgresource.DefaultProviderProject, customdiff.ForceNewIfChange("settings.0.disk_size", compute.IsDiskShrinkage), - customdiff.ForceNewIfChange("master_instance_name", isMasterInstanceNameSet), + customdiff.ForceNewIf("master_instance_name", func(_ context.Context, d *schema.ResourceDiff, meta interface{}) bool { + // If we set master but this is not the new master of a switchover, require replacement and warn user. + return !isSwitchoverFromOldPrimarySide(d) + }), + customdiff.ForceNewIf("replica_configuration.0.cascadable_replica", func(_ context.Context, d *schema.ResourceDiff, meta interface{}) bool { + return !isSwitchoverFromOldPrimarySide(d) + }), customdiff.IfValueChange("instance_type", isReplicaPromoteRequested, checkPromoteConfigurationsAndUpdateDiff), privateNetworkCustomizeDiff, pitrSupportDbCustomizeDiff, @@ -801,6 +809,12 @@ is set to true. Defaults to ZONAL.`, AtLeastOneOf: replicaConfigurationKeys, Description: `PEM representation of the trusted CA's x509 certificate.`, }, + "cascadable_replica": { + Type: schema.TypeBool, + Optional: true, + AtLeastOneOf: replicaConfigurationKeys, + Description: `Specifies if a SQL Server replica is a cascadable replica. A cascadable replica is a SQL Server cross region replica that supports replica(s) under it.`, + }, "client_certificate": { Type: schema.TypeString, Optional: true, @@ -876,6 +890,15 @@ is set to true. Defaults to ZONAL.`, }, Description: `The configuration for replication.`, }, + "replica_names": { + Type: schema.TypeList, + Computed: true, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + Description: `The replicas of the instance.`, + }, "server_ca_cert": { Type: schema.TypeList, Computed: true, @@ -1318,6 +1341,7 @@ func expandReplicaConfiguration(configured []interface{}) *sqladmin.ReplicaConfi _replicaConfiguration := configured[0].(map[string]interface{}) return &sqladmin.ReplicaConfiguration{ + CascadableReplica: _replicaConfiguration["cascadable_replica"].(bool), FailoverTarget: _replicaConfiguration["failover_target"].(bool), // MysqlReplicaConfiguration has been flattened in the TF schema, so @@ -1646,6 +1670,10 @@ func resourceSqlDatabaseInstanceRead(d *schema.ResourceData, meta interface{}) e if err := d.Set("replica_configuration", flattenReplicaConfiguration(instance.ReplicaConfiguration, d)); err != nil { log.Printf("[WARN] Failed to set SQL Database Instance Replica Configuration") } + + if err := d.Set("replica_names", instance.ReplicaNames); err != nil { + return fmt.Errorf("Error setting replica_names: %w", err) + } ipAddresses := flattenIpAddresses(instance.IpAddresses) if err := d.Set("ip_address", ipAddresses); err != nil { log.Printf("[WARN] Failed to set SQL Database Instance IP Addresses") @@ -1700,6 +1728,14 @@ func resourceSqlDatabaseInstanceRead(d *schema.ResourceData, meta interface{}) e return nil } +type replicaDRKind int + +const ( + replicaDRNone replicaDRKind = iota + replicaDRByPromote + replicaDRBySwitchover +) + func resourceSqlDatabaseInstanceUpdate(d *schema.ResourceData, meta interface{}) error { config := meta.(*transport_tpg.Config) userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) @@ -1716,17 +1752,20 @@ func resourceSqlDatabaseInstanceUpdate(d *schema.ResourceData, meta interface{}) maintenance_version = v.(string) } - promoteReadReplicaRequired := false + replicaDRKind := replicaDRNone if d.HasChange("instance_type") { oldInstanceType, newInstanceType := d.GetChange("instance_type") if isReplicaPromoteRequested(nil, oldInstanceType, newInstanceType, nil) { - err = checkPromoteConfigurations(d) - if err != nil { - return err + if isSwitchoverRequested(d) { + replicaDRKind = replicaDRBySwitchover + } else { + err = checkPromoteConfigurations(d) + if err != nil { + return err + } + replicaDRKind = replicaDRByPromote } - - promoteReadReplicaRequired = true } } @@ -1874,12 +1913,25 @@ func resourceSqlDatabaseInstanceUpdate(d *schema.ResourceData, meta interface{}) } } - if promoteReadReplicaRequired { - err = transport_tpg.Retry(transport_tpg.RetryOptions{ - RetryFunc: func() (rerr error) { + if replicaDRKind != replicaDRNone { + var retryFunc func() (rerr error) + switch replicaDRKind { + case replicaDRByPromote: + retryFunc = func() (rerr error) { op, rerr = config.NewSqlAdminClient(userAgent).Instances.PromoteReplica(project, d.Get("name").(string)).Do() return rerr - }, + } + case replicaDRBySwitchover: + retryFunc = func() (rerr error) { + op, rerr = config.NewSqlAdminClient(userAgent).Instances.Switchover(project, d.Get("name").(string)).Do() + return rerr + } + default: + return fmt.Errorf("unknown replica DR scenario: %v", replicaDRKind) + } + + err = transport_tpg.Retry(transport_tpg.RetryOptions{ + RetryFunc: retryFunc, Timeout: d.Timeout(schema.TimeoutUpdate), ErrorRetryPredicates: []transport_tpg.RetryErrorPredicateFunc{transport_tpg.IsSqlOperationInProgressError}, }) @@ -2340,6 +2392,7 @@ func flattenReplicaConfiguration(replicaConfiguration *sqladmin.ReplicaConfigura if replicaConfiguration != nil { data := map[string]interface{}{ + "cascadable_replica": replicaConfiguration.CascadableReplica, "failover_target": replicaConfiguration.FailoverTarget, // Don't attempt to assign anything from replicaConfiguration.MysqlReplicaConfiguration, @@ -2527,6 +2580,20 @@ func isMasterInstanceNameSet(_ context.Context, oldMasterInstanceName interface{ return true } +func isSwitchoverRequested(d *schema.ResourceData) bool { + originalPrimaryName, _ := d.GetChange("master_instance_name") + _, newReplicaNames := d.GetChange("replica_names") + if !slices.Contains(newReplicaNames.([]interface{}), originalPrimaryName) { + return false + } + dbVersion := d.Get("database_version") + if !strings.HasPrefix(dbVersion.(string), "SQLSERVER") { + log.Printf("[WARN] Switchover is only supported for SQL Server %q", dbVersion) + return false + } + return true +} + func isReplicaPromoteRequested(_ context.Context, oldInstanceType interface{}, newInstanceType interface{}, _ interface{}) bool { oldInstanceType = oldInstanceType.(string) newInstanceType = newInstanceType.(string) @@ -2538,6 +2605,34 @@ func isReplicaPromoteRequested(_ context.Context, oldInstanceType interface{}, n return false } +// Check if this resource change is the manual update done on old primary after a switchover. If true, no replacement is needed. +func isSwitchoverFromOldPrimarySide(d *schema.ResourceDiff) bool { + dbVersion := d.Get("database_version") + if !strings.HasPrefix(dbVersion.(string), "SQLSERVER") { + log.Printf("[WARN] Switchover is only supported for SQL Server %q", dbVersion) + return false + } + oldInstanceType, newInstanceType := d.GetChange("instance_type") + oldReplicaNames, newReplicaNames := d.GetChange("replica_names") + _, newMasterInstanceName := d.GetChange("master_instance_name") + _, newReplicaConfiguration := d.GetChange("replica_configuration") + if len(newReplicaConfiguration.([]interface{})) != 1 || newReplicaConfiguration.([]interface{})[0] == nil{ + return false; + } + replicaConfiguration := newReplicaConfiguration.([]interface{})[0].(map[string]interface{}) + cascadableReplica, cascadableReplicaFieldExists := replicaConfiguration["cascadable_replica"] + + instanceTypeChangedFromPrimaryToReplica := oldInstanceType.(string) == "CLOUD_SQL_INSTANCE" && newInstanceType.(string) == "READ_REPLICA_INSTANCE" + newMasterInOldReplicaNames := slices.Contains(oldReplicaNames.([]interface{}), newMasterInstanceName) + newMasterNotInNewReplicaNames := !slices.Contains(newReplicaNames.([]interface{}), newMasterInstanceName) + isCascadableReplica := cascadableReplicaFieldExists && cascadableReplica.(bool) + + return newMasterInstanceName != nil && + instanceTypeChangedFromPrimaryToReplica && + newMasterInOldReplicaNames && newMasterNotInNewReplicaNames && + isCascadableReplica +} + func checkPromoteConfigurations(d *schema.ResourceData) error { masterInstanceName := d.GetRawConfig().GetAttr("master_instance_name") replicaConfiguration := d.GetRawConfig().GetAttr("replica_configuration").AsValueSlice() @@ -2575,4 +2670,4 @@ func validatePromoteConfigurations(masterInstanceName cty.Value, replicaConfigur return fmt.Errorf("Replica promote configuration check failed. Please remove replica_configuration and try again.") } return nil -} +} \ No newline at end of file diff --git a/mmv1/third_party/terraform/services/sql/resource_sql_database_instance_test.go b/mmv1/third_party/terraform/services/sql/resource_sql_database_instance_test.go index 0cf6813466d7..53d975ec08fa 100644 --- a/mmv1/third_party/terraform/services/sql/resource_sql_database_instance_test.go +++ b/mmv1/third_party/terraform/services/sql/resource_sql_database_instance_test.go @@ -19,6 +19,8 @@ import ( // Fields that should be ignored in import tests because they aren't returned // from GCP (and thus can't be imported) var ignoredReplicaConfigurationFields = []string{ + "deletion_protection", + "root_password", "replica_configuration.0.ca_certificate", "replica_configuration.0.client_certificate", "replica_configuration.0.client_key", @@ -29,7 +31,7 @@ var ignoredReplicaConfigurationFields = []string{ "replica_configuration.0.ssl_cipher", "replica_configuration.0.username", "replica_configuration.0.verify_server_certificate", - "deletion_protection", + "replica_configuration.0.failover_target", } func TestAccSqlDatabaseInstance_basicInferredName(t *testing.T) { @@ -2423,6 +2425,69 @@ func TestAccSqlDatabaseInstance_ReplicaPromoteSkippedWithNoMasterInstanceNameAnd }) } +// Switchover between primary and cascadable replica sunny case +func TestAccSqlDatabaseInstance_SwitchoverSuccess(t *testing.T) { + t.Parallel() + primaryName := "tf-test-sql-instance-" + acctest.RandString(t, 10) + replicaName := "tf-test-sql-instance-replica-" + acctest.RandString(t, 10) + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccSqlDatabaseInstanceDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testGoogleSqlDatabaseInstanceConfig_SqlServerwithCascadableReplica(primaryName, replicaName), + }, + { + ResourceName: "google_sql_database_instance.original-primary", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: ignoredReplicaConfigurationFields, + }, + { + ResourceName: "google_sql_database_instance.original-replica", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: ignoredReplicaConfigurationFields, + }, + { + // Split into two configs because current TestStep implementation checks diff before refreshing. + Config: googleSqlDatabaseInstance_switchoverOnReplica(primaryName, replicaName), + }, + { + Config: googleSqlDatabaseInstance_updatePrimaryAfterSwitchover(primaryName, replicaName), + }, + { + RefreshState: true, + Check: resource.ComposeTestCheckFunc(resource.TestCheckTypeSetElemAttr("google_sql_database_instance.original-replica", "replica_names.*", primaryName), checkSwitchoverOriginalReplicaConfigurations("google_sql_database_instance.original-replica"), checkSwitchoverOriginalPrimaryConfigurations("google_sql_database_instance.original-primary", replicaName)), + }, + { + ResourceName: "google_sql_database_instance.original-primary", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: ignoredReplicaConfigurationFields, + }, + { + ResourceName: "google_sql_database_instance.original-replica", + ImportState: true, + ImportStateVerify: true, + // original-replica is no longer a replica, but replica_configuration is O + C and cannot be unset + ImportStateVerifyIgnore: []string{"replica_configuration", "deletion_protection", "root_password"}, + }, + { + // Delete replica first so PostTestDestroy doesn't fail when deleting instances which have replicas. We've already validated switchover behavior, the remaining steps are cleanup + Config: googleSqlDatabaseInstance_deleteReplicasAfterSwitchover(primaryName, replicaName), + // We delete replica, but haven't updated the master's replica_names + ExpectNonEmptyPlan: true, + }, + { + // Remove replica from primary's resource + Config: googleSqlDatabaseInstance_removeReplicaFromPrimaryAfterSwitchover(replicaName), + }, + }, + }) +} + func TestAccSqlDatabaseInstance_updateSslOptionsForPostgreSQL(t *testing.T) { t.Parallel() @@ -2746,7 +2811,7 @@ resource "google_sql_database_instance" "instance" { settings { tier = "%s" edition = "%s" - backup_configuration { + backup_configuration { transaction_log_retention_days = 7 } } @@ -3161,6 +3226,147 @@ resource "google_sql_database_instance" "instance-failover" { `, instanceName, failoverName) } +// Create SQL server primary with cascadable replica +func testGoogleSqlDatabaseInstanceConfig_SqlServerwithCascadableReplica(primaryName string, replicaName string) string { + return fmt.Sprintf(` +resource "google_sql_database_instance" "original-primary" { + name = "%s" + region = "us-east1" + database_version = "SQLSERVER_2019_ENTERPRISE" + deletion_protection = false + + root_password = "sqlserver1" + settings { + tier = "db-perf-optimized-N-2" + edition = "ENTERPRISE_PLUS" + } +} + +resource "google_sql_database_instance" "original-replica" { + name = "%s" + region = "us-west2" + database_version = "SQLSERVER_2019_ENTERPRISE" + master_instance_name = google_sql_database_instance.original-primary.name + deletion_protection = false + root_password = "sqlserver1" + replica_configuration { + cascadable_replica = true + } + + settings { + tier = "db-perf-optimized-N-2" + edition = "ENTERPRISE_PLUS" + } +} +`, primaryName, replicaName) +} + +func googleSqlDatabaseInstance_switchoverOnReplica(primaryName string, replicaName string) string { + return fmt.Sprintf(` +resource "google_sql_database_instance" "original-primary" { + name = "%s" + region = "us-east1" + database_version = "SQLSERVER_2019_ENTERPRISE" + deletion_protection = false + + root_password = "sqlserver1" + settings { + tier = "db-perf-optimized-N-2" + edition = "ENTERPRISE_PLUS" + } +} + +resource "google_sql_database_instance" "original-replica" { + name = "%s" + region = "us-west2" + database_version = "SQLSERVER_2019_ENTERPRISE" + deletion_protection = false + root_password = "sqlserver1" + instance_type = "CLOUD_SQL_INSTANCE" + replica_names = [google_sql_database_instance.original-primary.name] + settings { + tier = "db-perf-optimized-N-2" + edition = "ENTERPRISE_PLUS" + } +} +`, primaryName, replicaName) +} + +func googleSqlDatabaseInstance_updatePrimaryAfterSwitchover(primaryName string, replicaName string) string { + return fmt.Sprintf(` +resource "google_sql_database_instance" "original-primary" { + name = "%s" + region = "us-east1" + database_version = "SQLSERVER_2019_ENTERPRISE" + deletion_protection = false + root_password = "sqlserver1" + instance_type = "READ_REPLICA_INSTANCE" + master_instance_name = "%s" + replica_configuration { + cascadable_replica = true + } + replica_names = [] + settings { + tier = "db-perf-optimized-N-2" + edition = "ENTERPRISE_PLUS" + } +} + + resource "google_sql_database_instance" "original-replica" { + name = "%s" + region = "us-west2" + database_version = "SQLSERVER_2019_ENTERPRISE" + deletion_protection = false + root_password = "sqlserver1" + instance_type = "CLOUD_SQL_INSTANCE" + replica_names = [google_sql_database_instance.original-primary.name] + settings { + tier = "db-perf-optimized-N-2" + edition = "ENTERPRISE_PLUS" + } +} +`, primaryName, replicaName, replicaName) +} + +// After a switchover, the original-primary is now the replica and must be removed first. +func googleSqlDatabaseInstance_deleteReplicasAfterSwitchover(primaryName, replicaName string) string { + return fmt.Sprintf(` +resource "google_sql_database_instance" "original-replica" { + name = "%s" + region = "us-west2" + database_version = "SQLSERVER_2019_ENTERPRISE" + deletion_protection = false + root_password = "sqlserver1" + instance_type = "CLOUD_SQL_INSTANCE" + replica_names = ["%s"] + settings { + tier = "db-perf-optimized-N-2" + edition = "ENTERPRISE_PLUS" + } +} + +`, replicaName, primaryName) +} + +// Update original-replica replica_names after deleting original-primary +func googleSqlDatabaseInstance_removeReplicaFromPrimaryAfterSwitchover(replicaName string) string { + return fmt.Sprintf(` +resource "google_sql_database_instance" "original-replica" { + name = "%s" + region = "us-west2" + database_version = "SQLSERVER_2019_ENTERPRISE" + deletion_protection = false + root_password = "sqlserver1" + instance_type = "CLOUD_SQL_INSTANCE" + replica_names = [] + settings { + tier = "db-perf-optimized-N-2" + edition = "ENTERPRISE_PLUS" + } +} +`, replicaName) +} + func testAccSqlDatabaseInstance_basicInstanceForPsc(instanceName string, projectId string, orgId string, billingAccount string) string { return fmt.Sprintf(` resource "google_project" "testproject" { @@ -4386,7 +4592,58 @@ func checkPromoteReplicaConfigurations(resourceName string) func(*terraform.Stat if ok && replicaConfiguration != "" { return fmt.Errorf("Error in replica promotion. replica_configuration should not be present in %s state.", resourceName) } + return nil + } +} +// Check that original-replica is now the primary +func checkSwitchoverOriginalReplicaConfigurations(replicaResourceName string) func(*terraform.State) error { + return func(s *terraform.State) error { + replicaResource, ok := s.RootModule().Resources[replicaResourceName] + if !ok { + return fmt.Errorf("Can't find %s in state", replicaResourceName) + } + replicaResourceAttributes := replicaResource.Primary.Attributes + + replicaInstanceType, ok := replicaResourceAttributes["instance_type"] + if !ok { + return fmt.Errorf("Instance type is not present in state for %s", replicaResourceName) + } + if replicaInstanceType != "CLOUD_SQL_INSTANCE" { + return fmt.Errorf("Error in switchover. Original replica instance_type is %s, it should be CLOUD_SQL_INSTANCE.", replicaInstanceType) + } + + replicaMasterInstanceName, ok := replicaResourceAttributes["master_instance_name"] + if ok && replicaMasterInstanceName != "" { + return fmt.Errorf("Error in switchover. master_instance_name should not be set on new primary") + } + return nil + } +} + +// Check that original-primary is now a replica +func checkSwitchoverOriginalPrimaryConfigurations(primaryResourceName string, replicaName string) func(*terraform.State) error { + return func(s *terraform.State) error { + primaryResource, ok := s.RootModule().Resources[primaryResourceName] + if !ok { + return fmt.Errorf("Can't find %s in state", primaryResourceName) + } + primaryResourceAttributes := primaryResource.Primary.Attributes + primaryInstanceType, ok := primaryResourceAttributes["instance_type"] + if !ok { + return fmt.Errorf("Instance type is not present in state for %s", primaryResourceName) + } + if primaryInstanceType != "READ_REPLICA_INSTANCE" { + return fmt.Errorf("Error in switchover. Original primary instance_type is %s, it should be READ_REPLICA_INSTANCE.", primaryInstanceType) + } + + primaryMasterInstanceName, ok := primaryResourceAttributes["master_instance_name"] + if !ok { + return fmt.Errorf("Master instance name is not present in state for %s", primaryResourceName) + } + if primaryMasterInstanceName != replicaName { + return fmt.Errorf("Error in switchover. master_instance_name should be %s", replicaName) + } return nil } } diff --git a/mmv1/third_party/terraform/website/docs/guides/sql_instance_switchover.html.markdown b/mmv1/third_party/terraform/website/docs/guides/sql_instance_switchover.html.markdown new file mode 100644 index 000000000000..07623519a9ed --- /dev/null +++ b/mmv1/third_party/terraform/website/docs/guides/sql_instance_switchover.html.markdown @@ -0,0 +1,86 @@ +--- +page_title: "Performing a SQL Instance Switchover" +description: |- + A walkthrough for performing a SQL instance switchover through terraform +--- + +# Performing a SQL Instance Switchover +This page is a brief walkthrough of performing a switchover through terraform. + + ~> **NOTE:** Only supported for SQL Server. + +1. Create a **cross-region** primary and cascadable replica. It is recommended to use deletion_protection to prevent accidental deletions. +``` +resource "google_sql_database_instance" "original-primary" { +name = "p1" +region = "us-central1" +deletion_protection = true +instance_type = "CLOUD_SQL_INSTANCE" +replica_names = ["p1-r1"] + ... +} +resource "google_sql_database_instance" "original-replica" { +name = "p1-r1" +region = "us-east1" +deletion_protection = true +instance_type = "READ_REPLICA_INSTANCE" +master_instance_name = "p1" +replica_configuration { + cascadable_replica = true +} +... +} +``` + +2. Invoke switchover on the replica \ +a. Change `instance_type` from `READ_REPLICA_INSTANCE` to `CLOUD_SQL_INSTANCE` \ +b. Remove `master_instance_name` \ +c. Remove `replica_configuration` \ +d. Add current primary's name to the replica's `replica_names` list + +```diff +resource "google_sql_database_instance" "original-replica" { + name = "p1-r1" + region = "us-east1" +- instance_type = "READ_REPLICA_INSTANCE" ++ instance_type = "CLOUD_SQL_INSTANCE" + +- master_instance_name = "p1" +- replica_configuration { +- cascadable_replica = true +- } ++ replica_names = ["p1"] + ... +} +``` + +3. Update the old primary and run `terraform plan` \ +a. Change `instance_type` from `CLOUD_SQL_INSTANCE` to `READ_REPLICA_INSTANCE` \ +b. Set `master_instance_name` to the new primary (original replica) \ +c. Set `replica_configuration` and indicate this is a `cascadable-replica` \ +d. Remove old replica from `replica_names` \ + ~> **NOTE**: Do **not** delete the replica_names field, even if it has no replicas remaining. Set replica_names = [ ] to indicate it having no replicas. \ +e. Run `terraform plan` and verify that everything is done in-place (or data will be lost) + +```diff +resource "google_sql_database_instance" "original-primary" { + name = "p1" + region="us-central1" +- instance_type = "CLOUD_SQL_INSTANCE" ++ instance_type = "READ_REPLICA_INSTANCE" ++ master_instance_name = "p1-r1" ++ replica_configuration ++ cascadable_replica = true ++ } +- replica_names = ["p1-r1"] ++ replica_names = [] + ... +} +``` + +#### Plan and verify that: +- `terraform plan` outputs **"0 to add, 0 to destroy"** +- `terraform plan` does not say **"must be replaced"** for any resource +- Every resource **"will be updated in-place"** +- Only the 2 instances involved in switchover have planned changes +- (Recommended) Use `deletion_protection` on instances as a safety measure \ No newline at end of file diff --git a/mmv1/third_party/terraform/website/docs/r/sql_database_instance.html.markdown b/mmv1/third_party/terraform/website/docs/r/sql_database_instance.html.markdown index f69adc6e2c8c..0346b9a2e62c 100644 --- a/mmv1/third_party/terraform/website/docs/r/sql_database_instance.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/sql_database_instance.html.markdown @@ -234,7 +234,9 @@ includes an up-to-date reference of supported versions. is not provided, the provider project is used. * `replica_configuration` - (Optional) The configuration for replication. The - configuration is detailed below. Valid only for MySQL instances. + configuration is detailed below. + +* `replica_names` - (Optional, Computed) List of replica names. Can be updated. * `root_password` - (Optional) Initial root password. Can be updated. Required for MS SQL Server. @@ -451,11 +453,15 @@ The optional `settings.password_validation_policy` subblock for instances declar The optional `replica_configuration` block must have `master_instance_name` set to work, cannot be updated and supports: --> **Note:** `replica_configuration` field is not meant to be used if the master +~> **Note:** `replica_configuration` field is not meant to be used if the master instance is a source representation instance. The configuration provided by this field can be set on the source representation instance directly. If this field is present when the master instance is a source representation instance, `dump_file_path` must be provided. +* `cascadable_replica` - (Optional) Specifies if the replica is a cascadable replica. If true, instance must be in different region from primary. + + ~> **NOTE:** Only supported for SQL Server database. + * `ca_certificate` - (Optional) PEM representation of the trusted CA's x509 certificate. @@ -578,6 +584,38 @@ performing filtering in a Terraform config. * `server_ca_cert.0.sha1_fingerprint` - SHA Fingerprint of the CA Cert. +## Switchover (SQL Server Only) +Users can perform a switchover on any direct `cascadable` replica by following the steps below. + + ~>**WARNING:** Failure to follow these steps can lead to data loss (You will be warned during plan stage). To prevent data loss during a switchover, please verify your plan with the checklist below. + +For a more in-depth walkthrough with example code, see the [Switchover Guide](../guides/sql_instance_switchover.html.markdown) + +### Steps to Invoke Switchover + +Create a `cascadable` replica in a different region from the primary (`cascadable_replica` is set to true in `replica_configuration`) + +#### Invoking switchover in the replica resource: +1. Change instance_type from `READ_REPLICA_INSTANCE` to `CLOUD_SQL_INSTANCE` +2. Remove `master_instance_name` +3. Remove `replica_configuration` +4. Add current primary's name to the replica's `replica_names` list + +#### Updating the primary resource: +1. Change `instance_type` from `CLOUD_SQL_INSTANCE` to `READ_REPLICA_INSTANCE` +2. Set `master_instance_name` to the original replica (which will be primary after switchover) +3. Set `replica_configuration` and set `cascadable_replica` to `true` +4. Remove original replica from `replica_names` + + ~> **NOTE**: Do **not** delete the replica_names field, even if it has no replicas remaining. Set replica_names = [ ] to indicate it having no replicas. + +#### Plan and verify that: +- `terraform plan` outputs **"0 to add, 0 to destroy"** +- `terraform plan` does not say **"must be replaced"** for any resource +- Every resource **"will be updated in-place"** +- Only the 2 instances involved in switchover have planned changes +- (Recommended) Use `deletion_protection` on instances as a safety measure + ## Timeouts `google_sql_database_instance` provides the following @@ -615,4 +653,4 @@ $ terraform import google_sql_database_instance.default {{name}} ~> **NOTE:** Some fields (such as `replica_configuration`) won't show a diff if they are unset in config and set on the server. When importing, double-check that your config has all the fields set that you expect- just seeing -no diff isn't sufficient to know that your config could reproduce the imported resource. +no diff isn't sufficient to know that your config could reproduce the imported resource. \ No newline at end of file From cacf5f480bf39b933c30666293e70c83276386bb Mon Sep 17 00:00:00 2001 From: Ryan Oaks Date: Wed, 6 Nov 2024 09:27:59 -0500 Subject: [PATCH 011/105] Add docs for custom retry handling (#12248) --- docs/content/develop/custom-code.md | 22 ++++++++++++++++++++++ docs/content/develop/resource-reference.md | 18 ++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/docs/content/develop/custom-code.md b/docs/content/develop/custom-code.md index 536861f33c21..b769ce1bf83f 100644 --- a/docs/content/develop/custom-code.md +++ b/docs/content/develop/custom-code.md @@ -206,6 +206,28 @@ The parameters the function receives are: - `d`: Terraform resource data. Use `d.Get("field_name")` to get a field's current value. - `meta`: Can be cast to a Config object (which can make API calls) using `meta.(*transport_tpg.Config)` +### Custom retry handling + +```yaml +error_retry_predicates: + - 'transport_tpg.IamMemberMissing' + +error_abort_predicates: + - 'transport_tpg.Is429QuotaError' +``` + +Use `error_retry_predicates` or `error_abort_predicates` functions to retry or abort when encountering certain error responses. By default, errors are retried using [this list](https://github.com/GoogleCloudPlatform/magic-modules/blob/main/mmv1/third_party/terraform/transport/error_retry_predicates.go#L23) of retry predicates. `error_retry_predicates` can be used to make more errors retryable, while `error_abort_predicates` can be used to prevent errors from being retried. + +Both functions use the following signature: + +```go +func (err error) (bool, string) {} +``` + +The function takes an error and returns: +- `bool`: whether the error should be retried/aborted +- `string`: a reason that will be logged + ## Replace entire CRUD methods ```yaml diff --git a/docs/content/develop/resource-reference.md b/docs/content/develop/resource-reference.md index 39836c27ee19..a00786d1ffd4 100644 --- a/docs/content/develop/resource-reference.md +++ b/docs/content/develop/resource-reference.md @@ -239,6 +239,24 @@ async: resource_inside_response: true ``` +### `error_retry_predicates` + +An array of function names that determine whether an error is retryable. + +```yaml +error_retry_predicates: + - 'transport_tpg.IamMemberMissing' +``` + +### `error_abort_predicates` + +An array of function names that determine whether an error is not retryable. + +```yaml +error_abort_predicates: + - 'transport_tpg.Is429QuotaError' +``` + ## IAM resources ### `iam_policy` From b5c5e3c449fb3f4c3d245b118c6aed0fe3be8cec Mon Sep 17 00:00:00 2001 From: Will Yardley Date: Wed, 6 Nov 2024 08:18:59 -0800 Subject: [PATCH 012/105] spanner: updated docs for database name regex (#12246) --- mmv1/products/spanner/Database.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mmv1/products/spanner/Database.yaml b/mmv1/products/spanner/Database.yaml index ad4a0c45ecbd..6185b2db1561 100644 --- a/mmv1/products/spanner/Database.yaml +++ b/mmv1/products/spanner/Database.yaml @@ -103,8 +103,8 @@ properties: - name: 'name' type: String description: | - A unique identifier for the database, which cannot be changed after - the instance is created. Values are of the form [a-z][-a-z0-9]*[a-z0-9]. + A unique identifier for the database, which cannot be changed after the + instance is created. Values are of the form `[a-z][-_a-z0-9]*[a-z0-9]`. required: true immutable: true custom_flatten: 'templates/terraform/custom_flatten/name_from_self_link.tmpl' From 3e09d05e67d70ec85eb9c774911e2e19f39be343 Mon Sep 17 00:00:00 2001 From: Nick Elliot Date: Wed, 6 Nov 2024 09:29:47 -0800 Subject: [PATCH 013/105] Hard-configuring machine type of dataproc cluster in nodeaffinity test (#12215) --- .../dataproc/resource_dataproc_cluster_test.go.tmpl | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/mmv1/third_party/terraform/services/dataproc/resource_dataproc_cluster_test.go.tmpl b/mmv1/third_party/terraform/services/dataproc/resource_dataproc_cluster_test.go.tmpl index 1bc233926119..5a7f8cccbc5f 100644 --- a/mmv1/third_party/terraform/services/dataproc/resource_dataproc_cluster_test.go.tmpl +++ b/mmv1/third_party/terraform/services/dataproc/resource_dataproc_cluster_test.go.tmpl @@ -1655,6 +1655,12 @@ resource "google_dataproc_cluster" "basic" { region = "us-central1" cluster_config { + master_config { + machine_type = "n1-standard-2" + } + worker_config { + machine_type = "n1-standard-2" + } software_config { image_version = "2.0.35-debian10" } From bbf308f4f1b078c65953fa32dff04f504e080511 Mon Sep 17 00:00:00 2001 From: Matt Ng Date: Wed, 6 Nov 2024 13:59:50 -0500 Subject: [PATCH 014/105] Add data_source_backup_dr_data_source_.go.tmpl and test file (#11935) --- .../provider/provider_mmv1_resources.go.tmpl | 1 + .../data_source_backup_dr_data_source.go.tmpl | 622 ++++++++++++++++++ ..._source_backup_dr_data_source_test.go.tmpl | 57 ++ 3 files changed, 680 insertions(+) create mode 100644 mmv1/third_party/terraform/services/backupdr/data_source_backup_dr_data_source.go.tmpl create mode 100644 mmv1/third_party/terraform/services/backupdr/data_source_backup_dr_data_source_test.go.tmpl diff --git a/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.tmpl b/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.tmpl index 3508200e16b8..b208877c2f2f 100644 --- a/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.tmpl +++ b/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.tmpl @@ -37,6 +37,7 @@ var handwrittenDatasources = map[string]*schema.Resource{ "google_backup_dr_management_server": backupdr.DataSourceGoogleCloudBackupDRService(), "google_backup_dr_backup_plan_association": backupdr.DataSourceGoogleCloudBackupDRBackupPlanAssociation(), "google_backup_dr_backup_plan": backupdr.DataSourceGoogleCloudBackupDRBackupPlan(), + "google_backup_dr_data_source": backupdr.DataSourceGoogleCloudBackupDRDataSource(), {{- end }} "google_beyondcorp_app_connection": beyondcorp.DataSourceGoogleBeyondcorpAppConnection(), "google_beyondcorp_app_connector": beyondcorp.DataSourceGoogleBeyondcorpAppConnector(), diff --git a/mmv1/third_party/terraform/services/backupdr/data_source_backup_dr_data_source.go.tmpl b/mmv1/third_party/terraform/services/backupdr/data_source_backup_dr_data_source.go.tmpl new file mode 100644 index 000000000000..32e498c5244f --- /dev/null +++ b/mmv1/third_party/terraform/services/backupdr/data_source_backup_dr_data_source.go.tmpl @@ -0,0 +1,622 @@ +package backupdr +{{- if ne $.TargetVersionName "ga" }} + +import ( + "fmt" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-provider-google/google/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" +) + +func DataSourceGoogleCloudBackupDRDataSource() *schema.Resource { + dsSchema := map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Computed: true, + Description: `Name of the datasource to create. + It must have the format "projects/{project}/locations/{location}/backupVaults/{backupvault}/dataSources/{datasource}". + '{datasource}' cannot be changed after creation. It must be between 3-63 characters long and must be unique within the backup vault.`, + }, + "state": { + Type: schema.TypeString, + Computed: true, + Description: `The DataSource resource instance state.`, + }, + "labels": { + Type: schema.TypeMap, + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Description: `Resource labels to represent user provided metadata.`, + }, + "create_time": { + Type: schema.TypeString, + Computed: true, + Description: `The time when the instance was created.`, + }, + "update_time": { + Type: schema.TypeString, + Computed: true, + Description: `The time when the instance was updated.`, + }, + "backup_count": { + Type: schema.TypeString, + Computed: true, + Description: `Number of backups in the data source.`, + }, + "etag": { + Type: schema.TypeString, + Computed: true, + Description: `Server specified ETag for the ManagementServer resource to prevent simultaneous updates from overwiting each other.`, + }, + "total_stored_bytes": { + Type: schema.TypeString, + Computed: true, + Description: `The number of bytes (metadata and data) stored in this datasource.`, + }, + "config_state": { + Type: schema.TypeString, + Computed: true, + Description: `The backup configuration state.`, + }, + "backup_config_info": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "last_backup_state": { + Type: schema.TypeString, + Computed: true, + Description: `LastBackupstate tracks whether the last backup was not yet started, successful, failed, or could not be run because of the lack of permissions.`, + }, + "last_successful_backup_consistency_time": { + Type: schema.TypeString, + Computed: true, + Description: `If the last backup were successful, this field has the consistency date.`, + }, + "last_backup_error": { + Type: schema.TypeMap, + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Description: `If the last backup failed, this field has the error message.`, + }, + "gcp_backup_config": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "backup_plan": { + Type: schema.TypeString, + Computed: true, + Description: `The name of the backup plan.`, + }, + "backup_plan_description": { + Type: schema.TypeString, + Computed: true, + Description: `The description of the backup plan.`, + }, + "backup_plan_association": { + Type: schema.TypeString, + Computed: true, + Description: `The name of the backup plan association.`, + }, + "backup_plan_rules": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Description: `The names of the backup plan rules which point to this backupvault`, + }, + }, + }, + Description: `Configuration for a Google Cloud resource.`, + }, + "backup_appliance_backup_config": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "backup_appliance_name": { + Type: schema.TypeString, + Computed: true, + Description: `The name of the backup appliance.`, + }, + "backup_appliance_id": { + Type: schema.TypeString, + Computed: true, + Description: `The ID of the backup appliance.`, + }, + "sla_id": { + Type: schema.TypeString, + Computed: true, + Description: `The ID of the SLA of this application.`, + }, + "application_name": { + Type: schema.TypeString, + Computed: true, + Description: `The name of the application.`, + }, + "host_name": { + Type: schema.TypeString, + Computed: true, + Description: `The name of the host where the application is running.`, + }, + "slt_name": { + Type: schema.TypeString, + Computed: true, + Description: `The name of the SLT associated with the application.`, + }, + "slp_name": { + Type: schema.TypeString, + Computed: true, + Description: `The name of the SLP associated with the application.`, + }, + }, + }, + Description: `Configuration for an application backed up by a Backup Appliance.`, + }, + }, + }, + Description: `Details of how the resource is configured for backup.`, + }, + "data_source_gcp_resource": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "gcp_resourcename": { + Type: schema.TypeString, + Computed: true, + Description: `Full resource pathname URL of the source Google Cloud resource.`, + }, + "location": { + Type: schema.TypeString, + Computed: true, + Description: `Location of the resource: //"global"/"unspecified".`, + }, + "type": { + Type: schema.TypeString, + Computed: true, + Description: `The type of the Google Cloud resource. Use the Unified Resource Type, + eg. compute.googleapis.com/Instance.`, + }, + "compute_instance_data_source_properties": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Computed: true, + Description: `Name of the compute instance backed up by the datasource.`, + }, + "description": { + Type: schema.TypeString, + Computed: true, + Description: `The description of the Compute Engine instance.`, + }, + "machine_type": { + Type: schema.TypeString, + Computed: true, + Description: `The machine type of the instance.`, + }, + "total_disk_count": { + Type: schema.TypeString, + Computed: true, + Description: `The total number of disks attached to the Instance.`, + }, + "total_disk_size_gb": { + Type: schema.TypeString, + Computed: true, + Description: `The sum of all the disk sizes.`, + }, + }, + }, + Description: `ComputeInstanceDataSourceProperties has a subset of Compute Instance properties that are useful at the Datasource level.`, + }, + }, + }, + Description: `The backed up resource is a Google Cloud resource. + The word 'DataSource' was included in the names to indicate that this is + the representation of the Google Cloud resource used within the + DataSource object.`, + }, + "data_source_backup_appliance_application": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "application_name": { + Type: schema.TypeString, + Computed: true, + Description: `The name of the Application as known to the Backup Appliance.`, + }, + "backup_appliance": { + Type: schema.TypeString, + Computed: true, + Description: `Appliance name.`, + }, + "appliance_id": { + Type: schema.TypeString, + Computed: true, + Description: `Appliance Id of the Backup Appliance.`, + }, + "type": { + Type: schema.TypeString, + Computed: true, + Description: `The type of the application. e.g. VMBackup`, + }, + "application_id": { + Type: schema.TypeString, + Computed: true, + Description: `The appid field of the application within the Backup Appliance.`, + }, + "hostname": { + Type: schema.TypeString, + Computed: true, + Description: `Hostname of the host where the application is running.`, + }, + "host_id": { + Type: schema.TypeString, + Computed: true, + Description: `Hostid of the application host.`, + }, + }, + }, + Description: `The backed up resource is a backup appliance application.`, + }, + "location": { + Type: schema.TypeString, + Required: true, + }, + "project": { + Type: schema.TypeString, + Required: true, + }, + "data_source_id": { + Type: schema.TypeString, + Required: true, + }, + "backup_vault_id": { + Type: schema.TypeString, + Required: true, + }, + } + + return &schema.Resource{ + Read: DataSourceGoogleCloudBackupDRDataSourceRead, + Schema: dsSchema, + } +} + +func DataSourceGoogleCloudBackupDRDataSourceRead(d *schema.ResourceData, meta interface{}) 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 err + } + + location, err := tpgresource.GetLocation(d, config) + if err != nil { + return err + } + if len(location) == 0 { + return fmt.Errorf("Cannot determine location: set location in this data source or at provider-level") + } + + billingProject := project + url, err := tpgresource.ReplaceVars(d, config, "{{"{{"}}BackupDRBasePath{{"}}"}}projects/{{"{{"}}project{{"}}"}}/locations/{{"{{"}}location{{"}}"}}/backupVaults/{{"{{"}}backup_vault_id{{"}}"}}/dataSources/{{"{{"}}data_source_id{{"}}"}}") + + if err != nil { + return err + } + + if bp, err := tpgresource.GetBillingProject(d, config); err == nil { + billingProject = bp + } + + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "GET", + Project: billingProject, + RawURL: url, + UserAgent: userAgent, + }) + + if err != nil { + return fmt.Errorf("Error reading BackupVault: %s", err) + } + + if err := d.Set("name", flattenDataSourceBackupDRDataSourceName(res["name"], d, config)); err != nil { + return fmt.Errorf("Error reading DataSource: %s", err) + } + + if err := d.Set("create_time", flattenDataSourceBackupDRDataSourceCreateTime(res["createTime"], d, config)); err != nil { + return fmt.Errorf("Error reading DataSource: %s", err) + } + + if err := d.Set("update_time", flattenDataSourceBackupDRDataSourceUpdateTime(res["updateTime"], d, config)); err != nil { + return fmt.Errorf("Error reading DataSource: %s", err) + } + + if err := d.Set("backup_count", flattenDataSourceBackupDRDataSourceBackupCount(res["backupCount"], d, config)); err != nil { + return fmt.Errorf("Error reading DataSource: %s", err) + } + + if err := d.Set("etag", flattenDataSourceBackupDRDataSourceEtag(res["etag"], d, config)); err != nil { + return fmt.Errorf("Error reading DataSource: %s", err) + } + + if err := d.Set("state", flattenDataSourceBackupDRDataSourceState(res["state"], d, config)); err != nil { + return fmt.Errorf("Error reading DataSource: %s", err) + } + + if err := d.Set("total_stored_bytes", flattenDataSourceBackupDRDataSourceTotalStoredBytes(res["totalStoredBytes"], d, config)); err != nil { + return fmt.Errorf("Error reading DataSource: %s", err) + } + + if err := d.Set("backup_config_info", flattenDataSourceBackupDRDataSourceBackupConfigInfo(res["backupConfigInfo"], d, config)); err != nil { + return fmt.Errorf("Error reading DataSource: %s", err) + } + + if err := d.Set("data_source_gcp_resource", flattenBackupDRDataSourceDataSourceGCPResource(res["dataSourceGcpResource"], d, config)); err != nil { + return fmt.Errorf("Error reading DataSource: %s", err) + } + + if err := d.Set("data_source_backup_appliance_application", flattenBackupDRDataSourceDataSourceBackupApplianceApplication(res["dataSourceBackupApplianceApplication"], d, config)); err != nil { + return fmt.Errorf("Error reading DataSource: %s", err) + } + + d.SetId(res["name"].(string)) + + return nil +} + +func flattenDataSourceBackupDRDataSourceName(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenDataSourceBackupDRDataSourceCreateTime(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenDataSourceBackupDRDataSourceUpdateTime(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenDataSourceBackupDRDataSourceBackupCount(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenDataSourceBackupDRDataSourceEtag(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenDataSourceBackupDRDataSourceState(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenDataSourceBackupDRDataSourceTotalStoredBytes(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenDataSourceBackupDRDataSourceBackupConfigInfo(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return v + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["last_backup_state"] = flattenDataSourceBackupDRDataSourceConfigInfoLastBackupState(original["lastBackupState"], d, config) + transformed["last_successful_backup_consistency_time"] = flattenDataSourceBackupDRDataSourceConfigInfoLastSuccessfulBackupConsistencyTime(original["lastSuccessfulBackupConsistencyTime"], d, config) + transformed["last_backup_error"] = flattenDataSourceBackupDRDataSourceConfigInfoLastBackupError(original["lastBackupError"], d, config) + transformed["gcp_backup_config"] = flattenBackupDRDataSourceConfigInfoGCPBackupConfig(original["gcpBackupConfig"], d, config) + transformed["backup_appliance_backup_config"] = flattenBackupDRDataSourceConfigInfoBackupApplianceBackupConfig(original["backupApplianceBackupConfig"], d, config) + + return []interface{}{transformed} +} + +func flattenDataSourceBackupDRDataSourceConfigInfoLastBackupState(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenDataSourceBackupDRDataSourceConfigInfoLastSuccessfulBackupConsistencyTime(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenDataSourceBackupDRDataSourceConfigInfoLastBackupError(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenBackupDRDataSourceConfigInfoBackupApplianceBackupConfig(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return v + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["backup_appliance_name"] = flattenBackupDRDataSourceConfigInfoGCPBackupConfigBackupApplianceBackupConfigBackupApplianceName(original["backupApplianceName"], d, config) + transformed["backup_appliance_id"] = flattenBackupDRDataSourceConfigInfoGCPBackupConfigBackupApplianceBackupConfigBackupApplianceId(original["backupApplianceId"], d, config) + transformed["sla_id"] = flattenBackupDRDataSourceConfigInfoGCPBackupConfigBackupApplianceBackupConfigSlaId(original["slaId"], d, config) + transformed["application_name"] = flattenBackupDRDataSourceConfigInfoGCPBackupConfigBackupApplianceBackupConfigApplicationName(original["applicationName"], d, config) + transformed["slt_name"] = flattenBackupDRDataSourceConfigInfoGCPBackupConfigBackupApplianceBackupConfigSltName(original["sltName"], d, config) + transformed["slp_name"] = flattenBackupDRDataSourceConfigInfoGCPBackupConfigBackupApplianceBackupConfigSlpName(original["slpName"], d, config) + + return []interface{}{transformed} +} + +func flattenBackupDRDataSourceConfigInfoGCPBackupConfig(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return v + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["backup_plan"] = flattenBackupDRDataSourceConfigInfoGCPBackupConfigBackupPlan(original["backupPlan"], d, config) + transformed["backup_plan_description"] = flattenBackupDRDataSourceConfigInfoGCPBackupConfigBackupPlanDescription(original["backupPlanDescription"], d, config) + transformed["backup_plan_association"] = flattenBackupDRDataSourceConfigInfoGCPBackupConfigBackupPlanAssociation(original["backupPlanAssociation"], d, config) + transformed["backup_plan_rules"] = flattenBackupDRDataSourceConfigInfoGCPBackupConfigBackupPlanRules(original["backupPlanRules"], d, config) + + return []interface{}{transformed} +} + +func flattenBackupDRDataSourceConfigInfoGCPBackupConfigBackupPlan(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenBackupDRDataSourceConfigInfoGCPBackupConfigBackupPlanDescription(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenBackupDRDataSourceConfigInfoGCPBackupConfigBackupPlanAssociation(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenBackupDRDataSourceConfigInfoGCPBackupConfigBackupPlanRules(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenBackupDRDataSourceConfigInfoGCPBackupConfigBackupApplianceBackupConfigBackupApplianceName(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenBackupDRDataSourceConfigInfoGCPBackupConfigBackupApplianceBackupConfigBackupApplianceId(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenBackupDRDataSourceConfigInfoGCPBackupConfigBackupApplianceBackupConfigSlaId(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenBackupDRDataSourceConfigInfoGCPBackupConfigBackupApplianceBackupConfigApplicationName(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenBackupDRDataSourceConfigInfoGCPBackupConfigBackupApplianceBackupConfigSltName(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenBackupDRDataSourceConfigInfoGCPBackupConfigBackupApplianceBackupConfigSlpName(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenBackupDRDataSourceDataSourceGCPResource(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return v + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["gcp_resourcename"] = flattenBackupDRDataSourceDataSourceGCPResourceGCPResourceName(original["gcpResourcename"], d, config) + transformed["location"] = flattenBackupDRDataSourceDataSourceGCPResourceLocation(original["location"], d, config) + transformed["compute_instance_data_source_properties"] = flattenBackupDRDataSourceDataSourceGCPResourceComputeInstanceDataSourceProperties(original["computeInstanceDatasourceProperties"], d, config) + + return []interface{}{transformed} +} + +func flattenBackupDRDataSourceDataSourceGCPResourceGCPResourceName(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenBackupDRDataSourceDataSourceGCPResourceLocation(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenBackupDRDataSourceDataSourceGCPResourceComputeInstanceDataSourceProperties(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["name"] = flattenBackupDRDataSourceDataSourceGCPResourceComputeInstanceDataSourcePropertiesName(original["name"], d, config) + transformed["description"] = flattenBackupDRDataSourceDataSourceGCPResourceComputeInstanceDataSourcePropertiesDescription(original["description"], d, config) + transformed["machine_type"] = flattenBackupDRDataSourceDataSourceGCPResourceComputeInstanceDataSourcePropertiesMachineType(original["machineType"], d, config) + transformed["total_disk_count"] = flattenBackupDRDataSourceDataSourceGCPResourceComputeInstanceDataSourcePropertiesTotalDiskCount(original["totalDiskCount"], d, config) + transformed["total_disk_size_gb"] = flattenBackupDRDataSourceDataSourceGCPResourceComputeInstanceDataSourcePropertiesTotalDiskSizeGb(original["totalDiskSizeGb"], d, config) + + return []interface{}{transformed} +} + +func flattenBackupDRDataSourceDataSourceGCPResourceComputeInstanceDataSourcePropertiesName(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenBackupDRDataSourceDataSourceGCPResourceComputeInstanceDataSourcePropertiesDescription(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenBackupDRDataSourceDataSourceGCPResourceComputeInstanceDataSourcePropertiesMachineType(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenBackupDRDataSourceDataSourceGCPResourceComputeInstanceDataSourcePropertiesTotalDiskCount(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenBackupDRDataSourceDataSourceGCPResourceComputeInstanceDataSourcePropertiesTotalDiskSizeGb(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenBackupDRDataSourceDataSourceBackupApplianceApplication(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return v + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["application_name"] = flattenBackupDRDataSourceDataSourceBackupApplianceApplicationApplicationName(original["applicationName"], d, config) + transformed["backup_appliance"] = flattenBackupDRDataSourceDataSourceBackupApplianceApplicationBackupAppliance(original["backupAppliance"], d, config) + transformed["appliance_id"] = flattenBackupDRDataSourceDataSourceBackupApplianceApplicationApplianceId(original["applianceId"], d, config) + transformed["type"] = flattenBackupDRDataSourceDataSourceBackupApplianceApplicationType(original["type"], d, config) + transformed["application_id"] = flattenBackupDRDataSourceDataSourceBackupApplianceApplicationApplicationId(original["applicationId"], d, config) + transformed["hostname"] = flattenBackupDRDataSourceDataSourceBackupApplianceApplicationApplicationHostname(original["hostname"], d, config) + transformed["host_id"] = flattenBackupDRDataSourceDataSourceBackupApplianceApplicationApplicationHostId(original["hostId"], d, config) + + return []interface{}{transformed} +} + +func flattenBackupDRDataSourceDataSourceBackupApplianceApplicationApplicationName(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenBackupDRDataSourceDataSourceBackupApplianceApplicationBackupAppliance(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenBackupDRDataSourceDataSourceBackupApplianceApplicationApplianceId(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenBackupDRDataSourceDataSourceBackupApplianceApplicationType(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenBackupDRDataSourceDataSourceBackupApplianceApplicationApplicationId(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenBackupDRDataSourceDataSourceBackupApplianceApplicationApplicationHostname(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenBackupDRDataSourceDataSourceBackupApplianceApplicationApplicationHostId(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} +{{- end }} \ No newline at end of file diff --git a/mmv1/third_party/terraform/services/backupdr/data_source_backup_dr_data_source_test.go.tmpl b/mmv1/third_party/terraform/services/backupdr/data_source_backup_dr_data_source_test.go.tmpl new file mode 100644 index 000000000000..dd08709e42c9 --- /dev/null +++ b/mmv1/third_party/terraform/services/backupdr/data_source_backup_dr_data_source_test.go.tmpl @@ -0,0 +1,57 @@ +package backupdr_test +{{- if ne $.TargetVersionName "ga" }} + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-provider-google/google/acctest" + "github.com/hashicorp/terraform-provider-google/google/envvar" +) + +func TestAccDataSourceGoogleCloudBackupDRDataSource_basic(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(t, 10), + } + + stepChecks := func(wantName string, wantState string) []resource.TestCheckFunc { + stepCheck := []resource.TestCheckFunc{ + resource.TestCheckResourceAttr("data.google_backup_dr_data_source.foo", "name", wantName), + resource.TestCheckResourceAttr("data.google_backup_dr_data_source.foo", "state", wantState), + } + return stepCheck + } + project := envvar.GetTestProjectFromEnv() + expectedName := fmt.Sprintf("projects/%s/locations/us-central1/backupVaults/bv-test/dataSources/ds-test", project) + expectedState := "ACTIVE" + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Steps: []resource.TestStep{ + { + Config: testAccDataSourceGoogleCloudBackupDRDataSource_basic(context), + Check: resource.ComposeTestCheckFunc(stepChecks(expectedName, expectedState)...), + }, + }, + }) +} + +func testAccDataSourceGoogleCloudBackupDRDataSource_basic(context map[string]interface{}) string { + return acctest.Nprintf(` +data "google_project" "project" { +} + +data "google_backup_dr_data_source" "foo" { + project = data.google_project.project.project_id + location = "us-central1" + backup_vault_id = "bv-test" + data_source_id = "ds-test" +} + +`, context) +} +{{- end }} \ No newline at end of file From 857ed0e0fa848f9f72d070e7ca8aef041f7aa732 Mon Sep 17 00:00:00 2001 From: nityaravi <32396647+nityaravi@users.noreply.github.com> Date: Wed, 6 Nov 2024 14:30:24 -0500 Subject: [PATCH 015/105] Update README.md (#12262) --- docs/README.md | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/docs/README.md b/docs/README.md index a73f37b50479..07d5aa99adfc 100644 --- a/docs/README.md +++ b/docs/README.md @@ -2,13 +2,37 @@ The docsite is generated using [Hugo](https://gohugo.io/) and hosted using Githu To view locally: -1. Install Hugo v0.136.5 +1. Ensure you've installed [Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git), + [Go](https://go.dev/doc/install), and [Dart Sass](https://gohugo.io/hugo-pipes/transpile-sass-to-css/#dart-sass). + You require these prerequisites for installing Hugo. + +1. Install Hugo v0.136.5: ```bash CGO_ENABLED=1 go install -tags extended github.com/gohugoio/hugo@v0.136.5 ``` -2. Run `hugo server` inside the `docs` directory -3. Visit http://localhost:1313/magic-modules/ to view the docs +1. Restart your terminal. + +1. Clone the `magic-modules` GitHub repository: + ```bash + git clone https://github.com/GoogleCloudPlatform/magic-modules.git + ``` +1. Navigate to the `docs` directory inside the `magic-modules` repository: + ```bash + cd magic-modules/docs/ + ``` + +1. Start Hugo's development server to view the Magic Modules site: + ```bash + hugo server + ``` + +1. View the docs by visiting the following URL in a browser window: + ```bash + http://localhost:1313/magic-modules/ + ``` + +You can press `Ctrl+C` to stop Hugo's development server. If you are having deployment issues, try to reset your hugo module cache. * `hugo mod clean` From a3ffd4e196c5e93a506d53f83464004474bc69f4 Mon Sep 17 00:00:00 2001 From: Zach Fewtrell Date: Wed, 6 Nov 2024 13:36:18 -0800 Subject: [PATCH 016/105] Add RDB & AOF Persistence support to Memorystore for Redis Cluster (#12219) --- mmv1/products/redis/Cluster.yaml | 92 +++++++++++++++++++ .../examples/redis_cluster_aof.tf.tmpl | 63 +++++++++++++ .../examples/redis_cluster_rdb.tf.tmpl | 64 +++++++++++++ .../redis/resource_redis_cluster_test.go.tmpl | 57 +++++++++++- 4 files changed, 273 insertions(+), 3 deletions(-) create mode 100644 mmv1/templates/terraform/examples/redis_cluster_aof.tf.tmpl create mode 100644 mmv1/templates/terraform/examples/redis_cluster_rdb.tf.tmpl diff --git a/mmv1/products/redis/Cluster.yaml b/mmv1/products/redis/Cluster.yaml index 9376815a1b0b..c068ab9f1346 100644 --- a/mmv1/products/redis/Cluster.yaml +++ b/mmv1/products/redis/Cluster.yaml @@ -63,6 +63,30 @@ examples: 'deletion_protection_enabled': 'false' oics_vars_overrides: 'deletion_protection_enabled': 'false' + - name: "redis_cluster_rdb" + primary_resource_id: "cluster-rdb" + vars: + cluster_name: "rdb-cluster" + policy_name: "mypolicy" + subnet_name: "mysubnet" + network_name: "mynetwork" + deletion_protection_enabled: 'true' + test_vars_overrides: + 'deletion_protection_enabled': 'false' + oics_vars_overrides: + 'deletion_protection_enabled': 'false' + - name: "redis_cluster_aof" + primary_resource_id: "cluster-aof" + vars: + cluster_name: "aof-cluster" + policy_name: "mypolicy" + subnet_name: "mysubnet" + network_name: "mynetwork" + deletion_protection_enabled: 'true' + test_vars_overrides: + 'deletion_protection_enabled': 'false' + oics_vars_overrides: + 'deletion_protection_enabled': 'false' parameters: - name: 'name' type: String @@ -286,6 +310,74 @@ properties: Configure Redis Cluster behavior using a subset of native Redis configuration parameters. Please check Memorystore documentation for the list of supported parameters: https://cloud.google.com/memorystore/docs/cluster/supported-instance-configurations + - name: 'persistenceConfig' + type: NestedObject + description: Persistence config (RDB, AOF) for the cluster. + default_from_api: true + properties: + - name: 'mode' + type: Enum + description: | + Optional. Controls whether Persistence features are enabled. If not provided, the existing value will be used. + + - DISABLED: Persistence (both backup and restore) is disabled for the cluster. + - RDB: RDB based Persistence is enabled. + - AOF: AOF based Persistence is enabled. + enum_values: + - 'PERSISTENCE_MODE_UNSPECIFIED' + - 'DISABLED' + - 'RDB' + - 'AOF' + default_from_api: true + - name: 'rdbConfig' + type: NestedObject + description: | + RDB configuration. This field will be ignored if mode is not RDB. + default_from_api: true + properties: + - name: 'rdbSnapshotPeriod' + type: Enum + default_from_api: true + description: | + Optional. Available snapshot periods for scheduling. + + - ONE_HOUR: Snapshot every 1 hour. + - SIX_HOURS: Snapshot every 6 hours. + - TWELVE_HOURS: Snapshot every 12 hours. + - TWENTY_FOUR_HOURS: Snapshot every 24 hours. + enum_values: + - 'SNAPSHOT_PERIOD_UNSPECIFIED' + - 'ONE_HOUR' + - 'SIX_HOURS' + - 'TWELVE_HOURS' + - 'TWENTY_FOUR_HOURS' + - name: 'rdbSnapshotStartTime' + type: Time + description: | + The time that the first snapshot was/will be attempted, and to which + future snapshots will be aligned. + If not provided, the current time will be used. + default_from_api: true + - name: 'aofConfig' + type: NestedObject + description: | + AOF configuration. This field will be ignored if mode is not AOF. + default_from_api: true + properties: + - name: 'appendFsync' + type: Enum + default_from_api: true + description: | + Optional. Available fsync modes. + + - NO - Do not explicilty call fsync(). Rely on OS defaults. + - EVERYSEC - Call fsync() once per second in a background thread. A balance between performance and durability. + - ALWAYS - Call fsync() for earch write command. + enum_values: + - 'APPEND_FSYNC_UNSPECIFIED' + - 'NO' + - 'EVERYSEC' + - 'ALWAYS' - name: 'maintenancePolicy' type: NestedObject description: Maintenance policy for a cluster diff --git a/mmv1/templates/terraform/examples/redis_cluster_aof.tf.tmpl b/mmv1/templates/terraform/examples/redis_cluster_aof.tf.tmpl new file mode 100644 index 000000000000..27531978cc21 --- /dev/null +++ b/mmv1/templates/terraform/examples/redis_cluster_aof.tf.tmpl @@ -0,0 +1,63 @@ +resource "google_redis_cluster" "{{$.PrimaryResourceId}}" { + name = "{{index $.Vars "cluster_name"}}" + shard_count = 3 + psc_configs { + network = google_compute_network.producer_net.id + } + region = "us-central1" + replica_count = 0 + node_type = "REDIS_SHARED_CORE_NANO" + transit_encryption_mode = "TRANSIT_ENCRYPTION_MODE_DISABLED" + authorization_mode = "AUTH_MODE_DISABLED" + redis_configs = { + maxmemory-policy = "volatile-ttl" + } + deletion_protection_enabled = {{index $.Vars "deletion_protection_enabled"}} + + zone_distribution_config { + mode = "MULTI_ZONE" + } + maintenance_policy { + weekly_maintenance_window { + day = "MONDAY" + start_time { + hours = 1 + minutes = 0 + seconds = 0 + nanos = 0 + } + } + } + persistence_config { + mode = "AOF" + aof_config { + append_fsync = "EVERYSEC" + } + } + depends_on = [ + google_network_connectivity_service_connection_policy.default + ] +} + +resource "google_network_connectivity_service_connection_policy" "default" { + name = "{{index $.Vars "policy_name"}}" + location = "us-central1" + service_class = "gcp-memorystore-redis" + description = "my basic service connection policy" + network = google_compute_network.producer_net.id + psc_config { + subnetworks = [google_compute_subnetwork.producer_subnet.id] + } +} + +resource "google_compute_subnetwork" "producer_subnet" { + name = "{{index $.Vars "subnet_name"}}" + ip_cidr_range = "10.0.0.248/29" + region = "us-central1" + network = google_compute_network.producer_net.id +} + +resource "google_compute_network" "producer_net" { + name = "{{index $.Vars "network_name"}}" + auto_create_subnetworks = false +} diff --git a/mmv1/templates/terraform/examples/redis_cluster_rdb.tf.tmpl b/mmv1/templates/terraform/examples/redis_cluster_rdb.tf.tmpl new file mode 100644 index 000000000000..2cb28b8eac99 --- /dev/null +++ b/mmv1/templates/terraform/examples/redis_cluster_rdb.tf.tmpl @@ -0,0 +1,64 @@ +resource "google_redis_cluster" "{{$.PrimaryResourceId}}" { + name = "{{index $.Vars "cluster_name"}}" + shard_count = 3 + psc_configs { + network = google_compute_network.producer_net.id + } + region = "us-central1" + replica_count = 0 + node_type = "REDIS_SHARED_CORE_NANO" + transit_encryption_mode = "TRANSIT_ENCRYPTION_MODE_DISABLED" + authorization_mode = "AUTH_MODE_DISABLED" + redis_configs = { + maxmemory-policy = "volatile-ttl" + } + deletion_protection_enabled = {{index $.Vars "deletion_protection_enabled"}} + + zone_distribution_config { + mode = "MULTI_ZONE" + } + maintenance_policy { + weekly_maintenance_window { + day = "MONDAY" + start_time { + hours = 1 + minutes = 0 + seconds = 0 + nanos = 0 + } + } + } + persistence_config { + mode = "RDB" + rdb_config { + rdb_snapshot_period = "ONE_HOUR" + rdb_snapshot_start_time = "2024-10-02T15:01:23Z" + } + } + depends_on = [ + google_network_connectivity_service_connection_policy.default + ] +} + +resource "google_network_connectivity_service_connection_policy" "default" { + name = "{{index $.Vars "policy_name"}}" + location = "us-central1" + service_class = "gcp-memorystore-redis" + description = "my basic service connection policy" + network = google_compute_network.producer_net.id + psc_config { + subnetworks = [google_compute_subnetwork.producer_subnet.id] + } +} + +resource "google_compute_subnetwork" "producer_subnet" { + name = "{{index $.Vars "subnet_name"}}" + ip_cidr_range = "10.0.0.248/29" + region = "us-central1" + network = google_compute_network.producer_net.id +} + +resource "google_compute_network" "producer_net" { + name = "{{index $.Vars "network_name"}}" + auto_create_subnetworks = false +} diff --git a/mmv1/third_party/terraform/services/redis/resource_redis_cluster_test.go.tmpl b/mmv1/third_party/terraform/services/redis/resource_redis_cluster_test.go.tmpl index 960e6cce3250..02839714e679 100644 --- a/mmv1/third_party/terraform/services/redis/resource_redis_cluster_test.go.tmpl +++ b/mmv1/third_party/terraform/services/redis/resource_redis_cluster_test.go.tmpl @@ -260,6 +260,55 @@ func TestAccRedisCluster_createUpdateDeletionProtection(t *testing.T) { }) } + +// Validate that persistence is updated for the cluster +func TestAccRedisCluster_persistenceUpdate(t *testing.T) { + t.Parallel() + + name := fmt.Sprintf("tf-test-%d", acctest.RandInt(t)) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t), + CheckDestroy: testAccCheckRedisClusterDestroyProducer(t), + Steps: []resource.TestStep{ + { + // create cluster with AOF enabled + Config: createOrUpdateRedisCluster(&ClusterParams{name: name, replicaCount: 0, shardCount: 3, nodeType: "REDIS_STANDARD_SMALL", zoneDistributionMode: "MULTI_ZONE", persistenceBlock: "persistence_config {\nmode = \"AOF\"\naof_config{\nappend_fsync = \"EVERYSEC\"\n}\n}"}), + }, + { + ResourceName: "google_redis_cluster.test", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"psc_configs"}, + }, + { + // disable AOF + Config: createOrUpdateRedisCluster(&ClusterParams{name: name, replicaCount: 0, shardCount: 3, nodeType: "REDIS_STANDARD_SMALL", zoneDistributionMode: "MULTI_ZONE", persistenceBlock: "persistence_config {\nmode = \"DISABLED\"\n}"}), + }, + { + ResourceName: "google_redis_cluster.test", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"psc_configs"}, + }, { + // update persistence to RDB + Config: createOrUpdateRedisCluster(&ClusterParams{name: name, replicaCount: 0, shardCount: 3, nodeType: "REDIS_STANDARD_SMALL", zoneDistributionMode: "MULTI_ZONE", persistenceBlock: "persistence_config {\nmode = \"RDB\"\nrdb_config {\nrdb_snapshot_period = \"ONE_HOUR\"\nrdb_snapshot_start_time = \"2024-10-02T15:01:23Z\"\n}\n}"}), + }, + { + ResourceName: "google_redis_cluster.test", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"psc_configs"}, + }, + { + // clean up the resource + Config: createOrUpdateRedisCluster(&ClusterParams{name: name, replicaCount: 0, shardCount: 3, nodeType: "REDIS_STANDARD_SMALL", zoneDistributionMode: "MULTI_ZONE", persistenceBlock: "persistence_config {\nmode = \"RDB\"\nrdb_config {\nrdb_snapshot_period = \"ONE_HOUR\"\nrdb_snapshot_start_time = \"2024-10-02T15:01:23Z\"\n}\n}"}), + }, + }, + }) +} + type ClusterParams struct { name string replicaCount int @@ -274,12 +323,13 @@ type ClusterParams struct { maintenanceMinutes int maintenanceSeconds int maintenanceNanos int + persistenceBlock string } func createOrUpdateRedisCluster(params *ClusterParams) string { - var strBuilder strings.Builder + var redsConfigsStrBuilder strings.Builder for key, value := range params.redisConfigs { - strBuilder.WriteString(fmt.Sprintf("%s = \"%s\"\n", key, value)) + redsConfigsStrBuilder.WriteString(fmt.Sprintf("%s = \"%s\"\n", key, value)) } zoneDistributionConfigBlock := `` @@ -325,6 +375,7 @@ resource "google_redis_cluster" "test" { %s } %s + %s %s depends_on = [ google_network_connectivity_service_connection_policy.default @@ -356,7 +407,7 @@ resource "google_compute_network" "producer_net" { name = "%s" auto_create_subnetworks = false } -`, params.name, params.replicaCount, params.shardCount, params.nodeType, params.deletionProtectionEnabled, strBuilder.String(), zoneDistributionConfigBlock, maintenancePolicyBlock, params.name, params.name, params.name) +`, params.name, params.replicaCount, params.shardCount, params.nodeType, params.deletionProtectionEnabled, redsConfigsStrBuilder.String(), zoneDistributionConfigBlock, maintenancePolicyBlock, params.persistenceBlock, params.name, params.name, params.name) } {{ end }} From b551152e1e2375ddd6208b18c1970292b8ff583c Mon Sep 17 00:00:00 2001 From: rahul2393 Date: Thu, 7 Nov 2024 03:15:50 +0530 Subject: [PATCH 017/105] feat(spanner): add support for defaultBackupScheduleType in spanner instance (#12254) --- mmv1/products/spanner/Instance.yaml | 10 ++++++++++ .../terraform/encoders/spanner_instance_update.go.tmpl | 3 +++ .../terraform/examples/spanner_instance_basic.tf.tmpl | 1 + .../services/spanner/resource_spanner_instance_test.go | 2 ++ 4 files changed, 16 insertions(+) diff --git a/mmv1/products/spanner/Instance.yaml b/mmv1/products/spanner/Instance.yaml index cc1258aeebbe..bfaada78f130 100644 --- a/mmv1/products/spanner/Instance.yaml +++ b/mmv1/products/spanner/Instance.yaml @@ -272,3 +272,13 @@ properties: - 'STANDARD' - 'ENTERPRISE' - 'ENTERPRISE_PLUS' + - name: 'defaultBackupScheduleType' + type: Enum + description: | + Controls the default backup behavior for new databases within the instance. + Note that `AUTOMATIC` is not permitted for free instances, as backups and backup schedules are not allowed for free instances. + if unset or NONE, no default backup schedule will be created for new databases within the instance. + default_from_api: true + enum_values: + - 'NONE' + - 'AUTOMATIC' diff --git a/mmv1/templates/terraform/encoders/spanner_instance_update.go.tmpl b/mmv1/templates/terraform/encoders/spanner_instance_update.go.tmpl index 50dbdc8e414e..997a83a2d026 100644 --- a/mmv1/templates/terraform/encoders/spanner_instance_update.go.tmpl +++ b/mmv1/templates/terraform/encoders/spanner_instance_update.go.tmpl @@ -9,6 +9,9 @@ updateMask := make([]string, 0) if d.HasChange("edition") { updateMask = append(updateMask, "edition") } +if d.HasChange("default_backup_schedule_type") { + updateMask = append(updateMask, "defaultBackupScheduleType") +} if d.HasChange("num_nodes") { updateMask = append(updateMask, "nodeCount") } diff --git a/mmv1/templates/terraform/examples/spanner_instance_basic.tf.tmpl b/mmv1/templates/terraform/examples/spanner_instance_basic.tf.tmpl index 47d5b58aa963..7071dc6a975c 100644 --- a/mmv1/templates/terraform/examples/spanner_instance_basic.tf.tmpl +++ b/mmv1/templates/terraform/examples/spanner_instance_basic.tf.tmpl @@ -3,6 +3,7 @@ resource "google_spanner_instance" "example" { display_name = "Test Spanner Instance" num_nodes = 2 edition = "STANDARD" + default_backup_schedule_type = "AUTOMATIC" labels = { "foo" = "bar" } diff --git a/mmv1/third_party/terraform/services/spanner/resource_spanner_instance_test.go b/mmv1/third_party/terraform/services/spanner/resource_spanner_instance_test.go index 2343a09815c3..59ed840dc7c2 100644 --- a/mmv1/third_party/terraform/services/spanner/resource_spanner_instance_test.go +++ b/mmv1/third_party/terraform/services/spanner/resource_spanner_instance_test.go @@ -367,6 +367,7 @@ resource "google_spanner_instance" "basic" { display_name = "%s-dname" num_nodes = 1 edition = "ENTERPRISE" + default_backup_schedule_type = "NONE" } `, name, name) } @@ -460,6 +461,7 @@ resource "google_spanner_instance" "basic" { } } edition = "ENTERPRISE" + default_backup_schedule_type = "AUTOMATIC" } `, name, name, maxProcessingUnits, minProcessingUnits, cupUtilizationPercent, storageUtilizationPercent) } From 3850a583f7d4839598b5bd5e73bbb3163df398c8 Mon Sep 17 00:00:00 2001 From: Samir Ribeiro <42391123+Samir-Cit@users.noreply.github.com> Date: Wed, 6 Nov 2024 19:02:04 -0300 Subject: [PATCH 018/105] Migrate google_compute_firewall_policy_association resource from DCL to MMv1 (#11358) Co-authored-by: Zhenhua Li --- .../compute/FirewallPolicyAssociation.yaml | 82 ++++++++++++++ ...ompute_firewall_policy_association.go.tmpl | 7 ++ .../firewall_policy_association.tf.tmpl | 17 +++ ...ewall_policy_association_operation.go.tmpl | 11 ++ ...ewall_policy_association_operation.go.tmpl | 11 ++ ...ompute_firewall_policy_association_test.go | 50 ++++++++ ..._firewall_policy_association.html.markdown | 107 ------------------ .../beta/firewall_policy_association.yaml | 4 - .../compute/firewall_policy_association.yaml | 2 +- 9 files changed, 179 insertions(+), 112 deletions(-) create mode 100644 mmv1/products/compute/FirewallPolicyAssociation.yaml create mode 100644 mmv1/templates/terraform/custom_expand/compute_firewall_policy_association.go.tmpl create mode 100644 mmv1/templates/terraform/examples/firewall_policy_association.tf.tmpl create mode 100644 mmv1/templates/terraform/post_create/compute_firewall_policy_association_operation.go.tmpl create mode 100644 mmv1/templates/terraform/post_delete/compute_firewall_policy_association_operation.go.tmpl delete mode 100644 mmv1/third_party/terraform/website/docs/r/compute_firewall_policy_association.html.markdown delete mode 100644 tpgtools/overrides/compute/beta/firewall_policy_association.yaml diff --git a/mmv1/products/compute/FirewallPolicyAssociation.yaml b/mmv1/products/compute/FirewallPolicyAssociation.yaml new file mode 100644 index 000000000000..0114bfc578ba --- /dev/null +++ b/mmv1/products/compute/FirewallPolicyAssociation.yaml @@ -0,0 +1,82 @@ +# Copyright 2024 Google Inc. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- +name: 'FirewallPolicyAssociation' +kind: 'compute#firewallPolicyAssociation' +description: | + Allows associating hierarchical firewall policies with the target where they are applied. This allows creating policies and rules in a different location than they are applied. + For more information on applying hierarchical firewall policies see the [official documentation](https://cloud.google.com/firewall/docs/firewall-policies#managing_hierarchical_firewall_policy_resources) +min_version: 'beta' +references: + guides: + api: 'https://cloud.google.com/compute/docs/reference/rest/v1/firewallPolicies/addAssociation' +docs: +id_format: 'locations/global/firewallPolicies/{{firewall_policy}}/associations/{{name}}' +base_url: 'locations/global/firewallPolicies/{{firewall_policy}}' +self_link: 'locations/global/firewallPolicies/{{firewall_policy}}/getAssociation?name={{name}}' +create_url: 'locations/global/firewallPolicies/{{firewall_policy}}/addAssociation' +delete_url: 'locations/global/firewallPolicies/{{firewall_policy}}/removeAssociation?name={{name}}' +delete_verb: 'POST' +immutable: true +import_format: + - 'locations/global/firewallPolicies/{{firewall_policy}}/associations/{{name}}' + - '{{firewall_policy}}/{{name}}' +timeouts: + insert_minutes: 20 + update_minutes: 20 + delete_minutes: 20 +custom_code: + post_create: 'templates/terraform/post_create/compute_firewall_policy_association_operation.go.tmpl' + post_delete: 'templates/terraform/post_delete/compute_firewall_policy_association_operation.go.tmpl' +custom_diff: + - 'tpgresource.DefaultProviderProject' +examples: + - name: 'firewall_policy_association' + primary_resource_id: 'default' + vars: + policy_name: 'my-policy' + association_name: 'my-association' + folder_name: 'my-folder' + test_env_vars: + org_id: 'ORG_ID' + exclude_test: true +parameters: + - name: 'firewallPolicy' + type: ResourceRef + description: | + The firewall policy of the resource. + ignore_read: true + required: true + immutable: true + diff_suppress_func: 'tpgresource.CompareResourceNames' + custom_expand: 'templates/terraform/custom_expand/compute_firewall_policy_association.go.tmpl' + resource: 'FirewallPolicy' + imports: 'name' +properties: + - name: 'name' + type: String + description: | + The name for an association. + required: true + - name: 'attachmentTarget' + type: String + description: | + The target that the firewall policy is attached to. + required: true + diff_suppress_func: 'tpgresource.CompareSelfLinkOrResourceName' + - name: 'shortName' + type: String + description: | + The short name of the firewall policy of the association. + output: true diff --git a/mmv1/templates/terraform/custom_expand/compute_firewall_policy_association.go.tmpl b/mmv1/templates/terraform/custom_expand/compute_firewall_policy_association.go.tmpl new file mode 100644 index 000000000000..7b3a6e343f90 --- /dev/null +++ b/mmv1/templates/terraform/custom_expand/compute_firewall_policy_association.go.tmpl @@ -0,0 +1,7 @@ +func expand{{$.GetPrefix}}{{$.TitlelizeProperty}}(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + firewallPolicyId := tpgresource.GetResourceNameFromSelfLink(v.(string)) + if err := d.Set("firewall_policy", firewallPolicyId); err != nil { + return nil, fmt.Errorf("Error setting firewall_policy: %s", err) + } + return firewallPolicyId, nil +} \ No newline at end of file diff --git a/mmv1/templates/terraform/examples/firewall_policy_association.tf.tmpl b/mmv1/templates/terraform/examples/firewall_policy_association.tf.tmpl new file mode 100644 index 000000000000..5ae7625e741c --- /dev/null +++ b/mmv1/templates/terraform/examples/firewall_policy_association.tf.tmpl @@ -0,0 +1,17 @@ +resource "google_folder" "folder" { + display_name = "{{index $.Vars "folder_name"}}" + parent = "organizations/{{index $.TestEnvVars "org_id"}}" + deletion_protection = false +} + +resource "google_compute_firewall_policy" "policy" { + parent = "organizations/{{index $.TestEnvVars "org_id"}}" + short_name = "{{index $.Vars "policy_name"}}" + description = "Example Resource" +} + +resource "google_compute_firewall_policy_association" "{{$.PrimaryResourceId}}" { + firewall_policy = google_compute_firewall_policy.policy.id + attachment_target = google_folder.folder.name + name = "{{index $.Vars "association_name"}}" +} \ No newline at end of file diff --git a/mmv1/templates/terraform/post_create/compute_firewall_policy_association_operation.go.tmpl b/mmv1/templates/terraform/post_create/compute_firewall_policy_association_operation.go.tmpl new file mode 100644 index 000000000000..0953b637e026 --- /dev/null +++ b/mmv1/templates/terraform/post_create/compute_firewall_policy_association_operation.go.tmpl @@ -0,0 +1,11 @@ +parent := d.Get("firewall_policy").(string) +var opRes map[string]interface{} +err = ComputeOrgOperationWaitTimeWithResponse( + config, res, &opRes, parent, "Creating FirewallPolicyAssociation", userAgent, + d.Timeout(schema.TimeoutCreate)) + +if err != nil { + // The resource didn't actually create + d.SetId("") + return fmt.Errorf("Error waiting to create FirewallPolicyAssociation: %s", err) +} \ No newline at end of file diff --git a/mmv1/templates/terraform/post_delete/compute_firewall_policy_association_operation.go.tmpl b/mmv1/templates/terraform/post_delete/compute_firewall_policy_association_operation.go.tmpl new file mode 100644 index 000000000000..45ef4fbfe655 --- /dev/null +++ b/mmv1/templates/terraform/post_delete/compute_firewall_policy_association_operation.go.tmpl @@ -0,0 +1,11 @@ +parent := d.Get("firewall_policy").(string) +var opRes map[string]interface{} +err = ComputeOrgOperationWaitTimeWithResponse( + config, res, &opRes, parent, "Deleting FirewallPolicyAssociation", userAgent, + d.Timeout(schema.TimeoutCreate)) + +if err != nil { + // The resource didn't actually create + d.SetId("") + return fmt.Errorf("Error waiting to delete FirewallPolicyAssociation: %s", err) +} \ No newline at end of file diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_firewall_policy_association_test.go b/mmv1/third_party/terraform/services/compute/resource_compute_firewall_policy_association_test.go index 12e8f78881a7..5845c149221f 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_firewall_policy_association_test.go +++ b/mmv1/third_party/terraform/services/compute/resource_compute_firewall_policy_association_test.go @@ -62,3 +62,53 @@ resource "google_compute_firewall_policy_association" "default" { } `, context) } + +func TestAccComputeFirewallPolicyAssociation_organization(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(t, 10), + "org_name": fmt.Sprintf("organizations/%s", envvar.GetTestOrgFromEnv(t)), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + ExternalProviders: map[string]resource.ExternalProvider{ + "time": {}, + }, + Steps: []resource.TestStep{ + { + Config: testAccComputeFirewallPolicyAssociation_organization(context), + }, + { + ResourceName: "google_compute_firewall_policy_association.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"firewall_policy"}, + }, + }, + }) +} + +func testAccComputeFirewallPolicyAssociation_organization(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_folder" "folder" { + display_name = "tf-test-my-folder-%{random_suffix}" + parent = "%{org_name}" + deletion_protection = false +} + +resource "google_compute_firewall_policy" "policy" { + parent = "%{org_name}" + short_name = "tf-test-my-policy-%{random_suffix}" + description = "Example Resource" +} + +resource "google_compute_firewall_policy_association" "default" { + firewall_policy = google_compute_firewall_policy.policy.id + attachment_target = google_folder.folder.name + name = "tf-test-my-association-%{random_suffix}" +} +`, context) +} diff --git a/mmv1/third_party/terraform/website/docs/r/compute_firewall_policy_association.html.markdown b/mmv1/third_party/terraform/website/docs/r/compute_firewall_policy_association.html.markdown deleted file mode 100644 index cfe4cc3fdcd9..000000000000 --- a/mmv1/third_party/terraform/website/docs/r/compute_firewall_policy_association.html.markdown +++ /dev/null @@ -1,107 +0,0 @@ ---- -# ---------------------------------------------------------------------------- -# -# *** AUTO GENERATED CODE *** Type: DCL *** -# -# ---------------------------------------------------------------------------- -# -# This file is managed by Magic Modules (https:#github.com/GoogleCloudPlatform/magic-modules) -# and is based on the DCL (https:#github.com/GoogleCloudPlatform/declarative-resource-client-library). -# Changes will need to be made to the DCL or Magic Modules instead of here. -# -# We are not currently able to accept contributions to this file. If changes -# are required, please file an issue at https:#github.com/hashicorp/terraform-provider-google/issues/new/choose -# -# ---------------------------------------------------------------------------- -subcategory: "Compute Engine" -description: |- - Applies a hierarchical firewall policy to a target resource ---- - -# google_compute_firewall_policy_association - -Allows associating hierarchical firewall policies with the target where they are applied. This allows creating policies and rules in a different location than they are applied. - -For more information on applying hierarchical firewall policies see the [official documentation](https://cloud.google.com/vpc/docs/firewall-policies#managing_hierarchical_firewall_policy_resources) - -## Example Usage - -```hcl -resource "google_compute_firewall_policy" "default" { - parent = "organizations/12345" - short_name = "my-policy" - description = "Example Resource" -} - -resource "google_compute_firewall_policy_association" "default" { - firewall_policy = google_compute_firewall_policy.default.id - attachment_target = google_folder.folder.name - name = "my-association" -} -``` - - -## Argument Reference - -The following arguments are supported: - -* `attachment_target` - - (Required) - The target that the firewall policy is attached to. - -* `firewall_policy` - - (Required) - The firewall policy ID of the association. - -* `name` - - (Required) - The name for an association. - - - -- - - - - - -## Attributes Reference - -In addition to the arguments listed above, the following computed attributes are exported: - -* `id` - an identifier for the resource with format `locations/global/firewallPolicies/{{firewall_policy}}/associations/{{name}}` - -* `short_name` - - The short name of the firewall policy of the association. - -## Timeouts - -This resource provides the following -[Timeouts](https://developer.hashicorp.com/terraform/plugin/sdkv2/resources/retries-and-customizable-timeouts) configuration options: configuration options: - -- `create` - Default is 20 minutes. -- `delete` - Default is 20 minutes. - -## Import - -FirewallPolicyAssociation can be imported using any of these accepted formats: - -* `locations/global/firewallPolicies/{{firewall_policy}}/associations/{{name}}` -* `{{firewall_policy}}/{{name}}` - -In Terraform v1.5.0 and later, use an [`import` block](https://developer.hashicorp.com/terraform/language/import) to import FirewallPolicyAssociation using one of the formats above. For example: - -```tf -import { - id = "locations/global/firewallPolicies/{{firewall_policy}}/associations/{{name}}" - to = google_compute_firewall_policy_association.default -} -``` - -When using the [`terraform import` command](https://developer.hashicorp.com/terraform/cli/commands/import), FirewallPolicyAssociation can be imported using one of the formats above. For example: - -``` -$ terraform import google_compute_firewall_policy_association.default locations/global/firewallPolicies/{{firewall_policy}}/associations/{{name}} -$ terraform import google_compute_firewall_policy_association.default {{firewall_policy}}/{{name}} -``` - - - diff --git a/tpgtools/overrides/compute/beta/firewall_policy_association.yaml b/tpgtools/overrides/compute/beta/firewall_policy_association.yaml deleted file mode 100644 index af851d79a0c9..000000000000 --- a/tpgtools/overrides/compute/beta/firewall_policy_association.yaml +++ /dev/null @@ -1,4 +0,0 @@ -- type: CUSTOMIZE_DIFF - details: - functions: - - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/compute/firewall_policy_association.yaml b/tpgtools/overrides/compute/firewall_policy_association.yaml index af851d79a0c9..ba8d27aa31cc 100644 --- a/tpgtools/overrides/compute/firewall_policy_association.yaml +++ b/tpgtools/overrides/compute/firewall_policy_association.yaml @@ -1,4 +1,4 @@ - type: CUSTOMIZE_DIFF details: functions: - - tpgresource.DefaultProviderProject + - tpgresource.DefaultProviderProject \ No newline at end of file From 2e085f2aa60800cf0f72d10a96423d3c5bcf55a9 Mon Sep 17 00:00:00 2001 From: Abhijeet Dargude <144316709+dargudear-google@users.noreply.github.com> Date: Thu, 7 Nov 2024 04:10:47 +0530 Subject: [PATCH 019/105] [FIX] Use workload identity while enabling secret manager (#12257) --- .../resource_container_cluster_test.go.tmpl | 56 +++++++++++++------ 1 file changed, 40 insertions(+), 16 deletions(-) diff --git a/mmv1/third_party/terraform/services/container/resource_container_cluster_test.go.tmpl b/mmv1/third_party/terraform/services/container/resource_container_cluster_test.go.tmpl index 20e762df541f..cdbe59ad610d 100644 --- a/mmv1/third_party/terraform/services/container/resource_container_cluster_test.go.tmpl +++ b/mmv1/third_party/terraform/services/container/resource_container_cluster_test.go.tmpl @@ -3760,13 +3760,14 @@ func TestAccContainerCluster_withSecretManagerConfig(t *testing.T) { clusterName := fmt.Sprintf("tf-test-cluster-%s", acctest.RandString(t, 10)) networkName := acctest.BootstrapSharedTestNetwork(t, "gke-cluster") subnetworkName := acctest.BootstrapSubnet(t, "gke-cluster", networkName) + pid := envvar.GetTestProjectFromEnv() acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), CheckDestroy: testAccCheckContainerClusterDestroyProducer(t), Steps: []resource.TestStep{ { - Config: testAccContainerCluster_basic(clusterName, networkName, subnetworkName), + Config: testAccContainerCluster_forSecretManagerConfig(pid, clusterName, networkName, subnetworkName), }, { ResourceName: "google_container_cluster.primary", @@ -3775,7 +3776,7 @@ func TestAccContainerCluster_withSecretManagerConfig(t *testing.T) { ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { - Config: testAccContainerCluster_withSecretManagerConfigEnabled(clusterName, networkName, subnetworkName), + Config: testAccContainerCluster_withSecretManagerConfigEnabled(pid, clusterName, networkName, subnetworkName), }, { ResourceName: "google_container_cluster.primary", @@ -3784,16 +3785,7 @@ func TestAccContainerCluster_withSecretManagerConfig(t *testing.T) { ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { - Config: testAccContainerCluster_withSecretManagerConfigUpdated(clusterName, networkName, subnetworkName), - }, - { - ResourceName: "google_container_cluster.primary", - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"deletion_protection"}, - }, - { - Config: testAccContainerCluster_basic(clusterName, networkName, subnetworkName), + Config: testAccContainerCluster_withSecretManagerConfigUpdated(pid, clusterName, networkName, subnetworkName), }, { ResourceName: "google_container_cluster.primary", @@ -5965,6 +5957,26 @@ resource "google_container_cluster" "primary" { `, name, networkName, subnetworkName) } +func testAccContainerCluster_forSecretManagerConfig(projectID, name, networkName, subnetworkName string) string { + return fmt.Sprintf(` +data "google_project" "project" { + project_id = "%s" +} +resource "google_container_cluster" "primary" { + name = "%s" + location = "us-central1-a" + initial_node_count = 1 + network = "%s" + subnetwork = "%s" + + deletion_protection = false + workload_identity_config { + workload_pool = "${data.google_project.project.project_id}.svc.id.goog" + } +} +`, projectID, name, networkName, subnetworkName) +} + func testAccContainerCluster_networkingModeRoutes(firstName, secondName string) string { return fmt.Sprintf(` resource "google_container_cluster" "primary" { @@ -10518,8 +10530,11 @@ resource "google_container_cluster" "primary" { `, name, networkName, subnetworkName) } -func testAccContainerCluster_withSecretManagerConfigEnabled(name, networkName, subnetworkName string) string { +func testAccContainerCluster_withSecretManagerConfigEnabled(projectID, name, networkName, subnetworkName string) string { return fmt.Sprintf(` +data "google_project" "project" { + project_id = "%s" +} resource "google_container_cluster" "primary" { name = "%s" location = "us-central1-a" @@ -10530,12 +10545,18 @@ resource "google_container_cluster" "primary" { deletion_protection = false network = "%s" subnetwork = "%s" + workload_identity_config { + workload_pool = "${data.google_project.project.project_id}.svc.id.goog" + } } -`, name, networkName, subnetworkName) +`, projectID, name, networkName, subnetworkName) } -func testAccContainerCluster_withSecretManagerConfigUpdated(name, networkName, subnetworkName string) string { +func testAccContainerCluster_withSecretManagerConfigUpdated(projectID, name, networkName, subnetworkName string) string { return fmt.Sprintf(` +data "google_project" "project" { + project_id = "%s" +} resource "google_container_cluster" "primary" { name = "%s" location = "us-central1-a" @@ -10547,8 +10568,11 @@ resource "google_container_cluster" "primary" { deletion_protection = false network = "%s" subnetwork = "%s" + workload_identity_config { + workload_pool = "${data.google_project.project.project_id}.svc.id.goog" + } } -`, name, networkName, subnetworkName) +`, projectID, name, networkName, subnetworkName) } func testAccContainerCluster_withLoggingConfigEnabled(name, networkName, subnetworkName string) string { From 8ba278ec6b9c43e8d0a65211cc40d4d02168cb91 Mon Sep 17 00:00:00 2001 From: yaelbarak Date: Thu, 7 Nov 2024 13:03:44 +0200 Subject: [PATCH 020/105] Add performance config field to Filestore instance (#12245) --- mmv1/products/filestore/Instance.yaml | 36 +++++ .../resource_filestore_instance_test.go | 124 ++++++++++++++++++ 2 files changed, 160 insertions(+) diff --git a/mmv1/products/filestore/Instance.yaml b/mmv1/products/filestore/Instance.yaml index 9470ebcdf9b0..bac39a7befc5 100644 --- a/mmv1/products/filestore/Instance.yaml +++ b/mmv1/products/filestore/Instance.yaml @@ -292,3 +292,39 @@ properties: type: String description: | The reason for enabling deletion protection. + - name: 'performanceConfig' + type: NestedObject + description: | + Performance configuration for the instance. If not provided, + the default performance settings will be used. + properties: + - name: 'iopsPerTb' + type: NestedObject + description: | + The instance provisioned IOPS will change dynamically + based on the capacity of the instance. + conflicts: + - fixed_iops + properties: + - name: 'maxIopsPerTb' + type: Integer + description: | + The instance max IOPS will be calculated by multiplying + the capacity of the instance (TB) by max_iops_per_tb, + and rounding to the nearest 1000. The instance max IOPS + will be changed dynamically based on the instance + capacity. + - name: 'fixedIops' + type: NestedObject + description: | + The instance will have a fixed provisioned IOPS value, + which will remain constant regardless of instance + capacity. + conflicts: + - iops_per_tb + properties: + - name: 'maxIops' + type: Integer + description: | + The number of IOPS to provision for the instance. + max_iops must be in multiple of 1000. diff --git a/mmv1/third_party/terraform/services/filestore/resource_filestore_instance_test.go b/mmv1/third_party/terraform/services/filestore/resource_filestore_instance_test.go index 1894b154c58a..c5a2b7098cc9 100644 --- a/mmv1/third_party/terraform/services/filestore/resource_filestore_instance_test.go +++ b/mmv1/third_party/terraform/services/filestore/resource_filestore_instance_test.go @@ -285,3 +285,127 @@ resource "google_filestore_instance" "instance" { } `, name, location, tier, deletionProtection, deletionProtectionReason) } + +func TestAccFilestoreInstance_performanceConfig(t *testing.T) { + t.Parallel() + + name := fmt.Sprintf("tf-test-%d", acctest.RandInt(t)) + location := "us-central1" + tier := "REGIONAL" + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckFilestoreInstanceDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccFilestoreInstance_fixedIopsPerformanceConfig(name, location, tier), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("google_filestore_instance.instance", "performance_config.0.fixed_iops.0.max_iops", "17000"), + ), + }, + { + ResourceName: "google_filestore_instance.instance", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"zone"}, + }, + { + Config: testAccFilestoreInstance_iopsPerTbPerformanceConfig(name, location, tier), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("google_filestore_instance.instance", "performance_config.0.iops_per_tb.0.max_iops_per_tb", "17000"), + ), + }, + { + ResourceName: "google_filestore_instance.instance", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"zone"}, + }, + { + Config: testAccFilestoreInstance_defaultConfig(name, location, tier), + }, + { + ResourceName: "google_filestore_instance.instance", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"zone"}, + }, + }, + }) +} + +func testAccFilestoreInstance_fixedIopsPerformanceConfig(name, location, tier string) string { + return fmt.Sprintf(` +resource "google_filestore_instance" "instance" { + name = "%s" + location = "%s" + tier = "%s" + description = "An instance created during testing." + + file_shares { + capacity_gb = 1024 + name = "share" + } + + networks { + network = "default" + modes = ["MODE_IPV4"] + } + + performance_config { + fixed_iops { + max_iops = 17000 + } + } +} +`, name, location, tier) +} + +func testAccFilestoreInstance_iopsPerTbPerformanceConfig(name, location, tier string) string { + return fmt.Sprintf(` +resource "google_filestore_instance" "instance" { + name = "%s" + zone = "%s" + tier = "%s" + description = "An instance created during testing." + + file_shares { + capacity_gb = 1024 + name = "share" + } + + networks { + network = "default" + modes = ["MODE_IPV4"] + } + + performance_config { + iops_per_tb { + max_iops_per_tb = 17000 + } + } +} +`, name, location, tier) +} + +func testAccFilestoreInstance_defaultConfig(name, location, tier string) string { + return fmt.Sprintf(` +resource "google_filestore_instance" "instance" { + name = "%s" + zone = "%s" + tier = "%s" + description = "An instance created during testing." + + file_shares { + capacity_gb = 1024 + name = "share" + } + + networks { + network = "default" + modes = ["MODE_IPV4"] + } +} +`, name, location, tier) +} From 343132cfcaa07a03a385461bfe261580d4624ac4 Mon Sep 17 00:00:00 2001 From: coder-221 <185867912+coder-221@users.noreply.github.com> Date: Thu, 7 Nov 2024 07:04:51 -0800 Subject: [PATCH 021/105] Fix identity type comparison for service perimeters (#12267) --- .../ServicePerimeter.yaml | 5 ++ .../ServicePerimeterDryRunEgressPolicy.yaml | 1 + .../ServicePerimeterDryRunIngressPolicy.yaml | 1 + .../ServicePerimeterEgressPolicy.yaml | 1 + .../ServicePerimeterIngressPolicy.yaml | 1 + .../constants/access_context_manager.go.tmpl | 10 +++- ...ext_manager_service_perimeter_test.go.tmpl | 58 +++++++++++++++++++ 7 files changed, 76 insertions(+), 1 deletion(-) diff --git a/mmv1/products/accesscontextmanager/ServicePerimeter.yaml b/mmv1/products/accesscontextmanager/ServicePerimeter.yaml index be1850412e89..b179efdbf905 100644 --- a/mmv1/products/accesscontextmanager/ServicePerimeter.yaml +++ b/mmv1/products/accesscontextmanager/ServicePerimeter.yaml @@ -69,6 +69,7 @@ async: path: 'error' message: 'message' custom_code: + constants: 'templates/terraform/constants/access_context_manager.go.tmpl' encoder: 'templates/terraform/encoders/access_level_never_send_parent.go.tmpl' custom_import: 'templates/terraform/custom_import/set_access_policy_parent_from_self_link.go.tmpl' # Skipping the sweeper due to the non-standard base_url @@ -256,6 +257,7 @@ properties: - 'ANY_IDENTITY' - 'ANY_USER_ACCOUNT' - 'ANY_SERVICE_ACCOUNT' + diff_suppress_func: AccessContextManagerServicePerimeterIdentityTypeDiffSupressFunc - name: 'identities' type: Array description: | @@ -376,6 +378,7 @@ properties: - 'ANY_IDENTITY' - 'ANY_USER_ACCOUNT' - 'ANY_SERVICE_ACCOUNT' + diff_suppress_func: AccessContextManagerServicePerimeterIdentityTypeDiffSupressFunc - name: 'sources' type: Array description: 'Sources that this EgressPolicy authorizes access from.' @@ -564,6 +567,7 @@ properties: - 'ANY_IDENTITY' - 'ANY_USER_ACCOUNT' - 'ANY_SERVICE_ACCOUNT' + diff_suppress_func: AccessContextManagerServicePerimeterIdentityTypeDiffSupressFunc - name: 'identities' type: Array description: | @@ -681,6 +685,7 @@ properties: - 'ANY_IDENTITY' - 'ANY_USER_ACCOUNT' - 'ANY_SERVICE_ACCOUNT' + diff_suppress_func: AccessContextManagerServicePerimeterIdentityTypeDiffSupressFunc - name: 'sources' type: Array description: 'Sources that this EgressPolicy authorizes access from.' diff --git a/mmv1/products/accesscontextmanager/ServicePerimeterDryRunEgressPolicy.yaml b/mmv1/products/accesscontextmanager/ServicePerimeterDryRunEgressPolicy.yaml index 547a4f1210ef..fbd5951f1a23 100644 --- a/mmv1/products/accesscontextmanager/ServicePerimeterDryRunEgressPolicy.yaml +++ b/mmv1/products/accesscontextmanager/ServicePerimeterDryRunEgressPolicy.yaml @@ -108,6 +108,7 @@ properties: - 'ANY_IDENTITY' - 'ANY_USER_ACCOUNT' - 'ANY_SERVICE_ACCOUNT' + diff_suppress_func: AccessContextManagerServicePerimeterIdentityTypeDiffSupressFunc - name: 'identities' type: Array description: | diff --git a/mmv1/products/accesscontextmanager/ServicePerimeterDryRunIngressPolicy.yaml b/mmv1/products/accesscontextmanager/ServicePerimeterDryRunIngressPolicy.yaml index c947bc53299f..a88b19d8fb52 100644 --- a/mmv1/products/accesscontextmanager/ServicePerimeterDryRunIngressPolicy.yaml +++ b/mmv1/products/accesscontextmanager/ServicePerimeterDryRunIngressPolicy.yaml @@ -110,6 +110,7 @@ properties: - 'ANY_IDENTITY' - 'ANY_USER_ACCOUNT' - 'ANY_SERVICE_ACCOUNT' + diff_suppress_func: AccessContextManagerServicePerimeterIdentityTypeDiffSupressFunc - name: 'identities' type: Array description: | diff --git a/mmv1/products/accesscontextmanager/ServicePerimeterEgressPolicy.yaml b/mmv1/products/accesscontextmanager/ServicePerimeterEgressPolicy.yaml index ba3f48750add..bcd05a39ec54 100644 --- a/mmv1/products/accesscontextmanager/ServicePerimeterEgressPolicy.yaml +++ b/mmv1/products/accesscontextmanager/ServicePerimeterEgressPolicy.yaml @@ -105,6 +105,7 @@ properties: - 'ANY_IDENTITY' - 'ANY_USER_ACCOUNT' - 'ANY_SERVICE_ACCOUNT' + diff_suppress_func: AccessContextManagerServicePerimeterIdentityTypeDiffSupressFunc - name: 'identities' type: Array description: | diff --git a/mmv1/products/accesscontextmanager/ServicePerimeterIngressPolicy.yaml b/mmv1/products/accesscontextmanager/ServicePerimeterIngressPolicy.yaml index d9b370dced59..6fd8a3df51ff 100644 --- a/mmv1/products/accesscontextmanager/ServicePerimeterIngressPolicy.yaml +++ b/mmv1/products/accesscontextmanager/ServicePerimeterIngressPolicy.yaml @@ -107,6 +107,7 @@ properties: - 'ANY_IDENTITY' - 'ANY_USER_ACCOUNT' - 'ANY_SERVICE_ACCOUNT' + diff_suppress_func: AccessContextManagerServicePerimeterIdentityTypeDiffSupressFunc - name: 'identities' type: Array description: | diff --git a/mmv1/templates/terraform/constants/access_context_manager.go.tmpl b/mmv1/templates/terraform/constants/access_context_manager.go.tmpl index 476f59f98a52..6d999edf1ebb 100644 --- a/mmv1/templates/terraform/constants/access_context_manager.go.tmpl +++ b/mmv1/templates/terraform/constants/access_context_manager.go.tmpl @@ -38,4 +38,12 @@ func {{$.ResourceName}}IngressToResourcesDiffSupressFunc(_, _, _ string, d *sche sort.Strings(newResources) return slices.Equal(oldResources, newResources) -} \ No newline at end of file +} + +func {{$.ResourceName}}IdentityTypeDiffSupressFunc(_, old, new string, _ *schema.ResourceData) bool { + if old == "" && new == "IDENTITY_TYPE_UNSPECIFIED" { + return true + } + + return old == new +} diff --git a/mmv1/third_party/terraform/services/accesscontextmanager/resource_access_context_manager_service_perimeter_test.go.tmpl b/mmv1/third_party/terraform/services/accesscontextmanager/resource_access_context_manager_service_perimeter_test.go.tmpl index a896226b53ff..38271404e07d 100644 --- a/mmv1/third_party/terraform/services/accesscontextmanager/resource_access_context_manager_service_perimeter_test.go.tmpl +++ b/mmv1/third_party/terraform/services/accesscontextmanager/resource_access_context_manager_service_perimeter_test.go.tmpl @@ -7,6 +7,7 @@ import ( "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-plugin-testing/terraform" + "github.com/hashicorp/terraform-provider-google/google/services/accesscontextmanager" "github.com/hashicorp/terraform-provider-google/google/acctest" "github.com/hashicorp/terraform-provider-google/google/envvar" "github.com/hashicorp/terraform-provider-google/google/tpgresource" @@ -410,3 +411,60 @@ resource "google_access_context_manager_service_perimeter" "test-access" { `, org, policyTitle, levelTitleName, levelTitleName, perimeterTitleName, perimeterTitleName) } + +type IdentityTypeDiffSupressFuncDiffSuppressTestCase struct { + Name string + AreEqual bool + Before string + After string +} + + +var identityTypeDiffSuppressTestCases = []IdentityTypeDiffSupressFuncDiffSuppressTestCase{ + { + AreEqual: false, + Before: "A", + After: "B", + }, + { + AreEqual: true, + Before: "A", + After: "A", + }, + { + AreEqual: false, + Before: "", + After: "A", + }, + { + AreEqual: false, + Before: "A", + After: "", + }, + { + AreEqual: true, + Before: "", + After: "IDENTITY_TYPE_UNSPECIFIED", + }, + { + AreEqual: false, + Before: "IDENTITY_TYPE_UNSPECIFIED", + After: "", + }, +} + +func TestUnitAccessContextManagerServicePerimeter_identityTypeDiff(t *testing.T) { + for _, tc := range identityTypeDiffSuppressTestCases { + tc.Test(t) + } +} + + +func (tc *IdentityTypeDiffSupressFuncDiffSuppressTestCase) Test(t *testing.T) { + actual := accesscontextmanager.AccessContextManagerServicePerimeterIdentityTypeDiffSupressFunc("", tc.Before, tc.After, nil) + if actual != tc.AreEqual { + t.Errorf( + "Unexpected difference found. Before: \"%s\", after: \"%s\", actual: %t, expected: %t", + tc.Before, tc.After, actual, tc.AreEqual) + } +} From 27812e087aaf4250c076b5d572b3934c1a013e2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sven=20H=C3=B6xter?= <24830816+hoexter@users.noreply.github.com> Date: Thu, 7 Nov 2024 17:46:29 +0100 Subject: [PATCH 022/105] privateca: update certificate authority samples with more realistic values (#12259) Signed-off-by: Sven Hoexter --- ...vateca_certificate_authority_basic.tf.tmpl | 22 +++--------- ...teca_certificate_authority_byo_key.tf.tmpl | 2 -- ...a_certificate_authority_custom_ski.tf.tmpl | 20 ++--------- ..._certificate_authority_subordinate.tf.tmpl | 34 ++++++------------- 4 files changed, 18 insertions(+), 60 deletions(-) diff --git a/mmv1/templates/terraform/examples/privateca_certificate_authority_basic.tf.tmpl b/mmv1/templates/terraform/examples/privateca_certificate_authority_basic.tf.tmpl index ed24575b3c9b..e4eb51d3b870 100644 --- a/mmv1/templates/terraform/examples/privateca_certificate_authority_basic.tf.tmpl +++ b/mmv1/templates/terraform/examples/privateca_certificate_authority_basic.tf.tmpl @@ -8,40 +8,28 @@ resource "google_privateca_certificate_authority" "{{$.PrimaryResourceId}}" { config { subject_config { subject { - organization = "HashiCorp" + organization = "ACME" common_name = "my-certificate-authority" } - subject_alt_name { - dns_names = ["hashicorp.com"] - } } x509_config { ca_options { + # is_ca *MUST* be true for certificate authorities is_ca = true - max_issuer_path_length = 10 } key_usage { base_key_usage { - digital_signature = true - content_commitment = true - key_encipherment = false - data_encipherment = true - key_agreement = true + # cert_sign and crl_sign *MUST* be true for certificate authorities cert_sign = true crl_sign = true - decipher_only = true } extended_key_usage { - server_auth = true - client_auth = false - email_protection = true - code_signing = true - time_stamping = true } } } } - lifetime = "86400s" + # valid for 10 years + lifetime = "${10 * 365 * 24 * 3600}s" key_spec { algorithm = "RSA_PKCS1_4096_SHA256" } diff --git a/mmv1/templates/terraform/examples/privateca_certificate_authority_byo_key.tf.tmpl b/mmv1/templates/terraform/examples/privateca_certificate_authority_byo_key.tf.tmpl index 2c93253cbb2a..505e9a4e0852 100644 --- a/mmv1/templates/terraform/examples/privateca_certificate_authority_byo_key.tf.tmpl +++ b/mmv1/templates/terraform/examples/privateca_certificate_authority_byo_key.tf.tmpl @@ -37,7 +37,6 @@ resource "google_privateca_certificate_authority" "{{$.PrimaryResourceId}}" { ca_options { # is_ca *MUST* be true for certificate authorities is_ca = true - max_issuer_path_length = 10 } key_usage { base_key_usage { @@ -46,7 +45,6 @@ resource "google_privateca_certificate_authority" "{{$.PrimaryResourceId}}" { crl_sign = true } extended_key_usage { - server_auth = false } } name_constraints { diff --git a/mmv1/templates/terraform/examples/privateca_certificate_authority_custom_ski.tf.tmpl b/mmv1/templates/terraform/examples/privateca_certificate_authority_custom_ski.tf.tmpl index 757455779e18..8a05eabf8339 100644 --- a/mmv1/templates/terraform/examples/privateca_certificate_authority_custom_ski.tf.tmpl +++ b/mmv1/templates/terraform/examples/privateca_certificate_authority_custom_ski.tf.tmpl @@ -8,12 +8,9 @@ resource "google_privateca_certificate_authority" "{{$.PrimaryResourceId}}" { config { subject_config { subject { - organization = "HashiCorp" + organization = "ACME" common_name = "my-certificate-authority" } - subject_alt_name { - dns_names = ["hashicorp.com"] - } } subject_key_id { key_id = "4cf3372289b1d411b999dbb9ebcd44744b6b2fca" @@ -21,30 +18,19 @@ resource "google_privateca_certificate_authority" "{{$.PrimaryResourceId}}" { x509_config { ca_options { is_ca = true - max_issuer_path_length = 10 } key_usage { base_key_usage { - digital_signature = true - content_commitment = true - key_encipherment = false - data_encipherment = true - key_agreement = true cert_sign = true crl_sign = true - decipher_only = true } extended_key_usage { - server_auth = true - client_auth = false - email_protection = true - code_signing = true - time_stamping = true } } } } - lifetime = "86400s" + # valid for 10 years + lifetime = "${10 * 365 * 24 * 3600}s" key_spec { cloud_kms_key_version = "{{index $.Vars "kms_key_name"}}/cryptoKeyVersions/1" } diff --git a/mmv1/templates/terraform/examples/privateca_certificate_authority_subordinate.tf.tmpl b/mmv1/templates/terraform/examples/privateca_certificate_authority_subordinate.tf.tmpl index e43ce2111cb7..754d1f26c065 100644 --- a/mmv1/templates/terraform/examples/privateca_certificate_authority_subordinate.tf.tmpl +++ b/mmv1/templates/terraform/examples/privateca_certificate_authority_subordinate.tf.tmpl @@ -5,12 +5,9 @@ resource "google_privateca_certificate_authority" "root-ca" { config { subject_config { subject { - organization = "HashiCorp" + organization = "ACME" common_name = "my-certificate-authority" } - subject_alt_name { - dns_names = ["hashicorp.com"] - } } x509_config { ca_options { @@ -24,7 +21,6 @@ resource "google_privateca_certificate_authority" "root-ca" { crl_sign = true } extended_key_usage { - server_auth = false } } } @@ -52,43 +48,33 @@ resource "google_privateca_certificate_authority" "{{$.PrimaryResourceId}}" { config { subject_config { subject { - organization = "HashiCorp" + organization = "ACME" common_name = "my-subordinate-authority" } - subject_alt_name { - dns_names = ["hashicorp.com"] - } } x509_config { ca_options { is_ca = true - # Force the sub CA to only issue leaf certs - max_issuer_path_length = 0 + # Force the sub CA to only issue leaf certs. + # Use e.g. + # max_issuer_path_length = 1 + # if you need to chain more subordinates. + zero_max_issuer_path_length = true } key_usage { base_key_usage { - digital_signature = true - content_commitment = true - key_encipherment = false - data_encipherment = true - key_agreement = true cert_sign = true crl_sign = true - decipher_only = true } extended_key_usage { - server_auth = true - client_auth = false - email_protection = true - code_signing = true - time_stamping = true } } } } - lifetime = "86400s" + # valid for 5 years + lifetime = "${5 * 365 * 24 * 3600}s" key_spec { - algorithm = "RSA_PKCS1_4096_SHA256" + algorithm = "RSA_PKCS1_2048_SHA256" } type = "SUBORDINATE" } From 3db026ca076c34e112178ab9c5e5a6a7fb251e8b Mon Sep 17 00:00:00 2001 From: yu-xin-li Date: Thu, 7 Nov 2024 16:22:13 -0800 Subject: [PATCH 023/105] Fixes https://github.com/hashicorp/terraform-provider-google/issues/19540 (#12253) --- .../accesscontextmanager/ServicePerimeter.yaml | 16 ++++++++++------ .../ServicePerimeterDryRunEgressPolicy.yaml | 8 +++++--- .../ServicePerimeterDryRunIngressPolicy.yaml | 8 +++++--- .../ServicePerimeterEgressPolicy.yaml | 8 +++++--- .../ServicePerimeterIngressPolicy.yaml | 8 +++++--- .../accesscontextmanager/ServicePerimeters.yaml | 8 +++++--- 6 files changed, 35 insertions(+), 21 deletions(-) diff --git a/mmv1/products/accesscontextmanager/ServicePerimeter.yaml b/mmv1/products/accesscontextmanager/ServicePerimeter.yaml index b179efdbf905..8ca2e4ae5f81 100644 --- a/mmv1/products/accesscontextmanager/ServicePerimeter.yaml +++ b/mmv1/products/accesscontextmanager/ServicePerimeter.yaml @@ -261,9 +261,11 @@ properties: - name: 'identities' type: Array description: | - A list of identities that are allowed access through this ingress policy. - Should be in the format of email address. The email address should represent - individual user or service account only. + Identities can be an individual user, service account, Google group, + or third-party identity. For third-party identity, only single identities + are supported and other identity types are not supported.The v1 identities + that have the prefix user, group and serviceAccount in + https://cloud.google.com/iam/docs/principal-identifiers#v1 are supported. is_set: true item_type: type: String @@ -398,9 +400,11 @@ properties: - name: 'identities' type: Array description: | - A list of identities that are allowed access through this `EgressPolicy`. - Should be in the format of email address. The email address should - represent individual user or service account only. + Identities can be an individual user, service account, Google group, + or third-party identity. For third-party identity, only single identities + are supported and other identity types are not supported.The v1 identities + that have the prefix user, group and serviceAccount in + https://cloud.google.com/iam/docs/principal-identifiers#v1 are supported. is_set: true item_type: type: String diff --git a/mmv1/products/accesscontextmanager/ServicePerimeterDryRunEgressPolicy.yaml b/mmv1/products/accesscontextmanager/ServicePerimeterDryRunEgressPolicy.yaml index fbd5951f1a23..2def63b66f4f 100644 --- a/mmv1/products/accesscontextmanager/ServicePerimeterDryRunEgressPolicy.yaml +++ b/mmv1/products/accesscontextmanager/ServicePerimeterDryRunEgressPolicy.yaml @@ -112,9 +112,11 @@ properties: - name: 'identities' type: Array description: | - A list of identities that are allowed access through this `EgressPolicy`. - Should be in the format of email address. The email address should - represent individual user or service account only. + Identities can be an individual user, service account, Google group, + or third-party identity. For third-party identity, only single identities + are supported and other identity types are not supported.The v1 identities + that have the prefix user, group and serviceAccount in + https://cloud.google.com/iam/docs/principal-identifiers#v1 are supported. item_type: type: String - name: 'sources' diff --git a/mmv1/products/accesscontextmanager/ServicePerimeterDryRunIngressPolicy.yaml b/mmv1/products/accesscontextmanager/ServicePerimeterDryRunIngressPolicy.yaml index a88b19d8fb52..d012a7986984 100644 --- a/mmv1/products/accesscontextmanager/ServicePerimeterDryRunIngressPolicy.yaml +++ b/mmv1/products/accesscontextmanager/ServicePerimeterDryRunIngressPolicy.yaml @@ -114,9 +114,11 @@ properties: - name: 'identities' type: Array description: | - A list of identities that are allowed access through this ingress policy. - Should be in the format of email address. The email address should represent - individual user or service account only. + Identities can be an individual user, service account, Google group, + or third-party identity. For third-party identity, only single identities + are supported and other identity types are not supported.The v1 identities + that have the prefix user, group and serviceAccount in + https://cloud.google.com/iam/docs/principal-identifiers#v1 are supported. item_type: type: String - name: 'sources' diff --git a/mmv1/products/accesscontextmanager/ServicePerimeterEgressPolicy.yaml b/mmv1/products/accesscontextmanager/ServicePerimeterEgressPolicy.yaml index bcd05a39ec54..aa134684c045 100644 --- a/mmv1/products/accesscontextmanager/ServicePerimeterEgressPolicy.yaml +++ b/mmv1/products/accesscontextmanager/ServicePerimeterEgressPolicy.yaml @@ -109,9 +109,11 @@ properties: - name: 'identities' type: Array description: | - A list of identities that are allowed access through this `EgressPolicy`. - Should be in the format of email address. The email address should - represent individual user or service account only. + Identities can be an individual user, service account, Google group, + or third-party identity. For third-party identity, only single identities + are supported and other identity types are not supported.The v1 identities + that have the prefix user, group and serviceAccount in + https://cloud.google.com/iam/docs/principal-identifiers#v1 are supported. item_type: type: String - name: 'sources' diff --git a/mmv1/products/accesscontextmanager/ServicePerimeterIngressPolicy.yaml b/mmv1/products/accesscontextmanager/ServicePerimeterIngressPolicy.yaml index 6fd8a3df51ff..4512d903033a 100644 --- a/mmv1/products/accesscontextmanager/ServicePerimeterIngressPolicy.yaml +++ b/mmv1/products/accesscontextmanager/ServicePerimeterIngressPolicy.yaml @@ -111,9 +111,11 @@ properties: - name: 'identities' type: Array description: | - A list of identities that are allowed access through this ingress policy. - Should be in the format of email address. The email address should represent - individual user or service account only. + Identities can be an individual user, service account, Google group, + or third-party identity. For third-party identity, only single identities + are supported and other identity types are not supported.The v1 identities + that have the prefix user, group and serviceAccount in + https://cloud.google.com/iam/docs/principal-identifiers#v1 are supported. item_type: type: String - name: 'sources' diff --git a/mmv1/products/accesscontextmanager/ServicePerimeters.yaml b/mmv1/products/accesscontextmanager/ServicePerimeters.yaml index f7a4d16b79b7..0d0c4e97a441 100644 --- a/mmv1/products/accesscontextmanager/ServicePerimeters.yaml +++ b/mmv1/products/accesscontextmanager/ServicePerimeters.yaml @@ -662,9 +662,11 @@ properties: - name: 'identities' type: Array description: | - A list of identities that are allowed access through this `EgressPolicy`. - Should be in the format of email address. The email address should - represent individual user or service account only. + Identities can be an individual user, service account, Google group, + or third-party identity. For third-party identity, only single identities + are supported and other identity types are not supported.The v1 identities + that have the prefix user, group and serviceAccount in + https://cloud.google.com/iam/docs/principal-identifiers#v1 are supported. is_set: true item_type: type: String From 069cde81fbc480835d0a37637460995cdbab1e1e Mon Sep 17 00:00:00 2001 From: Liyun Huang Date: Fri, 8 Nov 2024 08:35:05 -0500 Subject: [PATCH 024/105] Added controlled-vault feature to backupdr-backupvault (#12239) --- mmv1/products/backupdr/BackupVault.yaml | 13 +++++++++++++ .../examples/backup_dr_backup_vault_full.tf.tmpl | 1 + .../resource_backup_dr_backup_vault_test.go.tmpl | 6 ++++-- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/mmv1/products/backupdr/BackupVault.yaml b/mmv1/products/backupdr/BackupVault.yaml index ff9d3d876290..f5a61e8cedc9 100644 --- a/mmv1/products/backupdr/BackupVault.yaml +++ b/mmv1/products/backupdr/BackupVault.yaml @@ -198,3 +198,16 @@ properties: description: "Optional. User annotations. See https://google.aip.dev/128#annotations\nStores small amounts of arbitrary data. " min_version: 'beta' + - name: 'accessRestriction' + type: Enum + description: | + Access restriction for the backup vault. Default value is `WITHIN_ORGANIZATION` if not provided during creation. + min_version: 'beta' + immutable: true + default_value: "WITHIN_ORGANIZATION" + enum_values: + - 'ACCESS_RESTRICTION_UNSPECIFIED' + - 'WITHIN_PROJECT' + - 'WITHIN_ORGANIZATION' + - 'UNRESTRICTED' + - 'WITHIN_ORG_BUT_UNRESTRICTED_FOR_BA' diff --git a/mmv1/templates/terraform/examples/backup_dr_backup_vault_full.tf.tmpl b/mmv1/templates/terraform/examples/backup_dr_backup_vault_full.tf.tmpl index df66d96f3005..d26aae4b3177 100644 --- a/mmv1/templates/terraform/examples/backup_dr_backup_vault_full.tf.tmpl +++ b/mmv1/templates/terraform/examples/backup_dr_backup_vault_full.tf.tmpl @@ -13,6 +13,7 @@ resource "google_backup_dr_backup_vault" "{{$.PrimaryResourceId}}" { annotations2 = "baz1" } force_update = "true" + access_restriction = "WITHIN_ORGANIZATION" ignore_inactive_datasources = "true" ignore_backup_plan_references = "true" allow_missing = "true" diff --git a/mmv1/third_party/terraform/services/backupdr/resource_backup_dr_backup_vault_test.go.tmpl b/mmv1/third_party/terraform/services/backupdr/resource_backup_dr_backup_vault_test.go.tmpl index 9e3973db22f5..53d7f084cbf8 100644 --- a/mmv1/third_party/terraform/services/backupdr/resource_backup_dr_backup_vault_test.go.tmpl +++ b/mmv1/third_party/terraform/services/backupdr/resource_backup_dr_backup_vault_test.go.tmpl @@ -32,7 +32,7 @@ func TestAccBackupDRBackupVault_fullUpdate(t *testing.T) { ResourceName: "google_backup_dr_backup_vault.backup-vault-test", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"allow_missing", "annotations", "backup_vault_id", "force_delete", "force_update", "ignore_backup_plan_references", "ignore_inactive_datasources", "labels", "location", "terraform_labels"}, + ImportStateVerifyIgnore: []string{"allow_missing", "annotations", "backup_vault_id", "force_delete", "force_update", "ignore_backup_plan_references", "ignore_inactive_datasources", "access_restriction", "labels", "location", "terraform_labels"}, }, { Config: testAccBackupDRBackupVault_fullUpdate(context), @@ -41,7 +41,7 @@ func TestAccBackupDRBackupVault_fullUpdate(t *testing.T) { ResourceName: "google_backup_dr_backup_vault.backup-vault-test", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"allow_missing", "annotations", "backup_vault_id", "force_delete", "force_update", "ignore_backup_plan_references", "ignore_inactive_datasources", "labels", "location", "terraform_labels"}, + ImportStateVerifyIgnore: []string{"allow_missing", "annotations", "backup_vault_id", "force_delete", "force_update", "ignore_backup_plan_references", "ignore_inactive_datasources", "access_restriction", "labels", "location", "terraform_labels"}, }, }, }) @@ -66,6 +66,7 @@ resource "google_backup_dr_backup_vault" "backup-vault-test" { } force_update = "true" ignore_inactive_datasources = "true" + access_restriction = "WITHIN_ORGANIZATION" ignore_backup_plan_references = "true" allow_missing = "true" } @@ -90,6 +91,7 @@ resource "google_backup_dr_backup_vault" "backup-vault-test" { annotations2 = "baz1" } force_update = "true" + access_restriction = "WITHIN_ORGANIZATION" ignore_inactive_datasources = "true" ignore_backup_plan_references = "true" allow_missing = "true" From b90cb18cb5c92f81447329607b7b5eec5a6ee8e3 Mon Sep 17 00:00:00 2001 From: Will Yardley Date: Fri, 8 Nov 2024 09:39:05 -0800 Subject: [PATCH 025/105] spanner: updated tests to allow VCR (#12280) --- .../data_source_spanner_instance_test.go | 18 +++---- .../resource_spanner_database_test.go.tmpl | 8 ++-- .../spanner/resource_spanner_instance_test.go | 47 ++++++++++--------- 3 files changed, 39 insertions(+), 34 deletions(-) diff --git a/mmv1/third_party/terraform/services/spanner/data_source_spanner_instance_test.go b/mmv1/third_party/terraform/services/spanner/data_source_spanner_instance_test.go index f6ae6c175bae..04b86a377392 100644 --- a/mmv1/third_party/terraform/services/spanner/data_source_spanner_instance_test.go +++ b/mmv1/third_party/terraform/services/spanner/data_source_spanner_instance_test.go @@ -8,8 +8,6 @@ import ( ) func TestAccDataSourceSpannerInstance_basic(t *testing.T) { - // Randomness from spanner instance - acctest.SkipIfVcr(t) t.Parallel() context := map[string]interface{}{ @@ -34,16 +32,18 @@ func TestAccDataSourceSpannerInstance_basic(t *testing.T) { func testAccDataSourceSpannerInstanceBasic(context map[string]interface{}) string { return acctest.Nprintf(` resource "google_spanner_instance" "bar" { - config = "regional-us-central1" - display_name = "Test Spanner Instance" - num_nodes = 2 - labels = { - "foo" = "bar" - } + name = "tf-test-%{random_suffix}" + display_name = "Test Spanner Instance" + config = "regional-us-central1" + + processing_units = 100 + labels = { + "foo" = "bar" + } } data "google_spanner_instance" "foo" { - name = google_spanner_instance.bar.name + name = google_spanner_instance.bar.name } `, context) } diff --git a/mmv1/third_party/terraform/services/spanner/resource_spanner_database_test.go.tmpl b/mmv1/third_party/terraform/services/spanner/resource_spanner_database_test.go.tmpl index c3b5ef0862b6..c5ba7eecf981 100644 --- a/mmv1/third_party/terraform/services/spanner/resource_spanner_database_test.go.tmpl +++ b/mmv1/third_party/terraform/services/spanner/resource_spanner_database_test.go.tmpl @@ -289,8 +289,8 @@ func TestAccSpannerDatabase_versionRetentionPeriod(t *testing.T) { // Test that when the above config is reapplied: // - changes the value (reverts to set value of `version_retention_period`, 2h) // - is stable; no further conflict - Config: testAccSpannerDatabase_versionRetentionPeriodUpdate3(instanceName, databaseName), //same as previous step - ExpectNonEmptyPlan: false, // is stable + Config: testAccSpannerDatabase_versionRetentionPeriodUpdate3(instanceName, databaseName), // same as previous step + ExpectNonEmptyPlan: false, // is stable Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttrSet("google_spanner_database.basic", "state"), resource.TestCheckResourceAttr("google_spanner_database.basic", "version_retention_period", "2h"), @@ -465,7 +465,6 @@ resource "google_spanner_database" "basic" { } func TestAccSpannerDatabase_deletionProtection(t *testing.T) { - acctest.SkipIfVcr(t) t.Parallel() context := map[string]interface{}{ @@ -501,8 +500,9 @@ func TestAccSpannerDatabase_deletionProtection(t *testing.T) { func testAccSpannerDatabase_deletionProtection(context map[string]interface{}) string { return acctest.Nprintf(` resource "google_spanner_instance" "main" { - config = "regional-europe-west1" + name = "tf-test-%{random_suffix}" display_name = "main-instance" + config = "regional-europe-west1" num_nodes = 1 } diff --git a/mmv1/third_party/terraform/services/spanner/resource_spanner_instance_test.go b/mmv1/third_party/terraform/services/spanner/resource_spanner_instance_test.go index 59ed840dc7c2..6643921dd708 100644 --- a/mmv1/third_party/terraform/services/spanner/resource_spanner_instance_test.go +++ b/mmv1/third_party/terraform/services/spanner/resource_spanner_instance_test.go @@ -15,7 +15,7 @@ import ( func TestAccSpannerInstance_basic(t *testing.T) { t.Parallel() - idName := fmt.Sprintf("spanner-test-%s", acctest.RandString(t, 10)) + idName := fmt.Sprintf("tf-test-%s", acctest.RandString(t, 10)) acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), @@ -39,7 +39,7 @@ func TestAccSpannerInstance_basic(t *testing.T) { func TestAccSpannerInstance_noNodeCountSpecified(t *testing.T) { t.Parallel() - idName := fmt.Sprintf("spanner-test-%s", acctest.RandString(t, 10)) + idName := fmt.Sprintf("tf-test-%s", acctest.RandString(t, 10)) acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), @@ -54,11 +54,12 @@ func TestAccSpannerInstance_noNodeCountSpecified(t *testing.T) { } func TestAccSpannerInstance_basicWithAutogenName(t *testing.T) { - // Randomness + // Since we're testing the autogenerated name specifically here, we can't use VCR. This shouldn't be copy / + // pasted to other configs, though. acctest.SkipIfVcr(t) t.Parallel() - displayName := fmt.Sprintf("spanner-test-%s-dname", acctest.RandString(t, 10)) + displayName := fmt.Sprintf("tf-test-%s-dname", acctest.RandString(t, 10)) acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), @@ -80,19 +81,21 @@ func TestAccSpannerInstance_basicWithAutogenName(t *testing.T) { } func TestAccSpannerInstance_update(t *testing.T) { - // Randomness - acctest.SkipIfVcr(t) t.Parallel() - dName1 := fmt.Sprintf("spanner-dname1-%s", acctest.RandString(t, 10)) - dName2 := fmt.Sprintf("spanner-dname2-%s", acctest.RandString(t, 10)) + // Update display name, but keep real name consistent, as it cannot be + // updated after creation. + name := fmt.Sprintf("tf-test-%s", acctest.RandString(t, 10)) + dName1 := fmt.Sprintf("tf-test-dname1-%s", acctest.RandString(t, 10)) + dName2 := fmt.Sprintf("tf-test-dname2-%s", acctest.RandString(t, 10)) + acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), CheckDestroy: testAccCheckSpannerInstanceDestroyProducer(t), Steps: []resource.TestStep{ { - Config: testAccSpannerInstance_update(dName1, 1, false), + Config: testAccSpannerInstance_update(name, dName1, 1, false), }, { ResourceName: "google_spanner_instance.updater", @@ -101,7 +104,7 @@ func TestAccSpannerInstance_update(t *testing.T) { ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { - Config: testAccSpannerInstance_update(dName2, 2, true), + Config: testAccSpannerInstance_update(name, dName2, 2, true), }, { ResourceName: "google_spanner_instance.updater", @@ -114,11 +117,9 @@ func TestAccSpannerInstance_update(t *testing.T) { } func TestAccSpannerInstance_virtualUpdate(t *testing.T) { - // Randomness - acctest.SkipIfVcr(t) t.Parallel() - dName := fmt.Sprintf("spanner-dname1-%s", acctest.RandString(t, 10)) + dName := fmt.Sprintf("tf-test-dname1-%s", acctest.RandString(t, 10)) acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), @@ -145,7 +146,7 @@ func TestAccSpannerInstance_virtualUpdate(t *testing.T) { func TestAccSpannerInstance_basicWithAutoscalingUsingProcessingUnitConfig(t *testing.T) { t.Parallel() - displayName := fmt.Sprintf("spanner-test-%s-dname", acctest.RandString(t, 10)) + displayName := fmt.Sprintf("tf-test-%s-dname", acctest.RandString(t, 10)) acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), @@ -230,7 +231,7 @@ func TestAccSpannerInstance_basicWithAutoscalingUsingProcessingUnitConfigUpdate( func TestAccSpannerInstance_basicWithAutoscalingUsingNodeConfig(t *testing.T) { t.Parallel() - displayName := fmt.Sprintf("spanner-test-%s-dname", acctest.RandString(t, 10)) + displayName := fmt.Sprintf("tf-test-%s-dname", acctest.RandString(t, 10)) acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), @@ -365,8 +366,9 @@ resource "google_spanner_instance" "basic" { name = "%s" config = "regional-us-central1" display_name = "%s-dname" - num_nodes = 1 - edition = "ENTERPRISE" + + processing_units = 100 + edition = "ENTERPRISE" default_backup_schedule_type = "NONE" } `, name, name) @@ -387,12 +389,13 @@ func testAccSpannerInstance_basicWithAutogenName(name string) string { resource "google_spanner_instance" "basic" { config = "regional-us-central1" display_name = "%s" - num_nodes = 1 + + processing_units = 100 } `, name) } -func testAccSpannerInstance_update(name string, nodes int, addLabel bool) string { +func testAccSpannerInstance_update(name, dname string, nodes int, addLabel bool) string { extraLabel := "" if addLabel { extraLabel = "\"key2\" = \"value2\"" @@ -400,6 +403,7 @@ func testAccSpannerInstance_update(name string, nodes int, addLabel bool) string return fmt.Sprintf(` resource "google_spanner_instance" "updater" { config = "regional-us-central1" + name = "%s" display_name = "%s" num_nodes = %d @@ -408,15 +412,16 @@ resource "google_spanner_instance" "updater" { %s } } -`, name, nodes, extraLabel) +`, name, dname, nodes, extraLabel) } func testAccSpannerInstance_virtualUpdate(name, virtual string) string { return fmt.Sprintf(` resource "google_spanner_instance" "basic" { name = "%s" - config = "regional-us-central1" display_name = "%s" + config = "regional-us-central1" + processing_units = 100 force_destroy = "%s" } From a8a545fe5d66b53f6ec872743137bfb426669232 Mon Sep 17 00:00:00 2001 From: Jesse DeJong Date: Fri, 8 Nov 2024 12:44:45 -0500 Subject: [PATCH 026/105] Promoting Managed Kafka Cluster and Topic resources to GA (#12264) --- mmv1/products/managedkafka/Cluster.yaml | 19 ------------------- mmv1/products/managedkafka/Topic.yaml | 9 --------- mmv1/products/managedkafka/product.yaml | 2 ++ .../managedkafka_cluster_basic.tf.tmpl | 3 --- .../examples/managedkafka_topic_basic.tf.tmpl | 5 ----- ...esource_managed_kafka_cluster_test.go.tmpl | 12 +----------- .../resource_managed_kafka_topic_test.go.tmpl | 16 +--------------- 7 files changed, 4 insertions(+), 62 deletions(-) diff --git a/mmv1/products/managedkafka/Cluster.yaml b/mmv1/products/managedkafka/Cluster.yaml index 50ff950ab7ec..46d31473056d 100644 --- a/mmv1/products/managedkafka/Cluster.yaml +++ b/mmv1/products/managedkafka/Cluster.yaml @@ -14,7 +14,6 @@ --- name: 'Cluster' description: A Managed Service for Apache Kafka cluster. Apache Kafka is a trademark owned by the Apache Software Foundation. -min_version: 'beta' docs: id_format: 'projects/{{project}}/locations/{{location}}/clusters/{{cluster_id}}' base_url: 'projects/{{project}}/locations/{{location}}/clusters' @@ -46,7 +45,6 @@ custom_code: examples: - name: 'managedkafka_cluster_basic' primary_resource_id: 'example' - min_version: 'beta' vars: cluster_id: 'my-cluster' key_name: 'example-key' @@ -65,7 +63,6 @@ parameters: description: "ID of the location of the Kafka resource. See https://cloud.google.com/managed-kafka/docs/locations for a list of supported locations." - min_version: 'beta' url_param_only: true required: true immutable: true @@ -75,7 +72,6 @@ parameters: component of the cluster's name. The ID must be 1-63 characters long, and match the regular expression `[a-z]([-a-z0-9]*[a-z0-9])?` to comply with RFC 1035. This value is structured like: `my-cluster-id`." - min_version: 'beta' url_param_only: true required: true immutable: true @@ -83,13 +79,11 @@ properties: - name: 'gcpConfig' type: NestedObject description: "Configuration properties for a Kafka cluster deployed to Google Cloud Platform." - min_version: 'beta' required: true properties: - name: 'accessConfig' type: NestedObject description: "The configuration of access to the Kafka cluster." - min_version: 'beta' required: true properties: - name: 'networkConfigs' @@ -98,7 +92,6 @@ properties: cluster are allocated. To make the cluster available in a VPC, you must specify at least one subnet per network. You must specify between 1 and 10 subnets. Additional subnets may be specified with additional `network_configs` blocks." - min_version: 'beta' required: true item_type: type: NestedObject @@ -110,7 +103,6 @@ properties: in the subnet. The subnet must be located in the same region as the cluster. The project may differ. The name of the subnet must be in the format `projects/PROJECT_ID/regions/REGION/subnetworks/SUBNET`." - min_version: 'beta' required: true diff_suppress_func: 'tpgresource.ProjectNumberDiffSuppress' - name: 'kmsKey' @@ -118,23 +110,19 @@ properties: description: "The Cloud KMS Key name to use for encryption. The key must be located in the same region as the cluster and cannot be changed. Must be in the format `projects/PROJECT_ID/locations/LOCATION/keyRings/KEY_RING/cryptoKeys/KEY`." - min_version: 'beta' immutable: true diff_suppress_func: 'tpgresource.ProjectNumberDiffSuppress' - name: 'name' type: String description: "The name of the cluster. Structured like: `projects/PROJECT_ID/locations/LOCATION/clusters/CLUSTER_ID`." - min_version: 'beta' output: true - name: 'createTime' type: String description: "The time when the cluster was created." - min_version: 'beta' output: true - name: 'updateTime' type: String description: "The time when the cluster was last updated." - min_version: 'beta' output: true - name: 'labels' type: KeyValueLabels @@ -142,36 +130,29 @@ properties: character and contain only hyphens (-), underscores (\_), lowercase characters, and numbers. Values must contain only hyphens (-), underscores (\_), lowercase characters, and numbers." - min_version: 'beta' - name: 'capacityConfig' type: NestedObject description: "A capacity configuration of a Kafka cluster." - min_version: 'beta' required: true properties: - name: 'vcpuCount' type: String description: "The number of vCPUs to provision for the cluster. The minimum is 3." - min_version: 'beta' required: true - name: 'memoryBytes' type: String description: "The memory to provision for the cluster in bytes. The value must be between 1 GiB and 8 GiB per vCPU. Ex. 1024Mi, 4Gi." - min_version: 'beta' required: true - name: 'rebalanceConfig' type: NestedObject description: "Defines rebalancing behavior of a Kafka cluster." - min_version: 'beta' properties: - name: 'mode' type: String description: "The rebalance behavior for the cluster. When not specified, defaults to `NO_REBALANCE`. Possible values: `MODE_UNSPECIFIED`, `NO_REBALANCE`, `AUTO_REBALANCE_ON_SCALE_UP`." - min_version: 'beta' - name: 'state' type: String description: "The current state of the cluster. Possible values: `STATE_UNSPECIFIED`, `CREATING`, `ACTIVE`, `DELETING`." - min_version: 'beta' output: true diff --git a/mmv1/products/managedkafka/Topic.yaml b/mmv1/products/managedkafka/Topic.yaml index ced93a66f1da..37bd27a9e976 100644 --- a/mmv1/products/managedkafka/Topic.yaml +++ b/mmv1/products/managedkafka/Topic.yaml @@ -14,7 +14,6 @@ --- name: 'Topic' description: A Managed Service for Apache Kafka topic. Apache Kafka is a trademark owned by the Apache Software Foundation. -min_version: 'beta' docs: id_format: 'projects/{{project}}/locations/{{location}}/clusters/{{cluster}}/topics/{{topic_id}}' base_url: 'projects/{{project}}/locations/{{location}}/clusters/{{cluster}}/topics' @@ -33,7 +32,6 @@ custom_code: examples: - name: 'managedkafka_topic_basic' primary_resource_id: 'example' - min_version: 'beta' vars: cluster_id: 'my-cluster' topic_id: 'my-topic' @@ -43,14 +41,12 @@ parameters: description: "ID of the location of the Kafka resource. See https://cloud.google.com/managed-kafka/docs/locations for a list of supported locations." - min_version: 'beta' url_param_only: true required: true immutable: true - name: 'cluster' type: String description: "The cluster name." - min_version: 'beta' url_param_only: true required: true immutable: true @@ -58,7 +54,6 @@ parameters: type: String description: "The ID to use for the topic, which will become the final component of the topic's name. This value is structured like: `my-topic-name`." - min_version: 'beta' url_param_only: true required: true immutable: true @@ -67,19 +62,16 @@ properties: type: String description: "The name of the topic. The `topic` segment is used when connecting directly to the cluster. Must be in the format `projects/PROJECT_ID/locations/LOCATION/clusters/CLUSTER_ID/topics/TOPIC_ID`." - min_version: 'beta' output: true - name: 'partitionCount' type: Integer description: "The number of partitions in a topic. You can increase the partition count for a topic, but you cannot decrease it. Increasing partitions for a topic that uses a key might change how messages are distributed." - min_version: 'beta' - name: 'replicationFactor' type: Integer description: "The number of replicas of each partition. A replication factor of 3 is recommended for high availability." - min_version: 'beta' required: true immutable: true - name: 'configs' @@ -87,4 +79,3 @@ properties: description: "Configuration for the topic that are overridden from the cluster defaults. The key of the map is a Kafka topic property name, for example: `cleanup.policy=compact`, `compression.type=producer`." - min_version: 'beta' diff --git a/mmv1/products/managedkafka/product.yaml b/mmv1/products/managedkafka/product.yaml index 4f040da57b65..2328006035a9 100644 --- a/mmv1/products/managedkafka/product.yaml +++ b/mmv1/products/managedkafka/product.yaml @@ -15,6 +15,8 @@ name: 'ManagedKafka' display_name: 'Managed Kafka' versions: + - name: 'ga' + base_url: 'https://managedkafka.googleapis.com/v1/' - name: 'beta' base_url: 'https://managedkafka.googleapis.com/v1/' scopes: diff --git a/mmv1/templates/terraform/examples/managedkafka_cluster_basic.tf.tmpl b/mmv1/templates/terraform/examples/managedkafka_cluster_basic.tf.tmpl index 7b85bb69ef83..bf6cd7ea885a 100644 --- a/mmv1/templates/terraform/examples/managedkafka_cluster_basic.tf.tmpl +++ b/mmv1/templates/terraform/examples/managedkafka_cluster_basic.tf.tmpl @@ -18,10 +18,7 @@ resource "google_managed_kafka_cluster" "{{$.PrimaryResourceId}}" { labels = { key = "value" } - - provider = google-beta } data "google_project" "project" { - provider = google-beta } diff --git a/mmv1/templates/terraform/examples/managedkafka_topic_basic.tf.tmpl b/mmv1/templates/terraform/examples/managedkafka_topic_basic.tf.tmpl index bf9c86760633..d9429d584d60 100644 --- a/mmv1/templates/terraform/examples/managedkafka_topic_basic.tf.tmpl +++ b/mmv1/templates/terraform/examples/managedkafka_topic_basic.tf.tmpl @@ -12,8 +12,6 @@ resource "google_managed_kafka_cluster" "cluster" { } } } - - provider = google-beta } resource "google_managed_kafka_topic" "{{$.PrimaryResourceId}}" { @@ -25,10 +23,7 @@ resource "google_managed_kafka_topic" "{{$.PrimaryResourceId}}" { configs = { "cleanup.policy" = "compact" } - - provider = google-beta } data "google_project" "project" { - provider = google-beta } diff --git a/mmv1/third_party/terraform/services/managedkafka/resource_managed_kafka_cluster_test.go.tmpl b/mmv1/third_party/terraform/services/managedkafka/resource_managed_kafka_cluster_test.go.tmpl index ffc95546c2c4..472a90c4bad8 100644 --- a/mmv1/third_party/terraform/services/managedkafka/resource_managed_kafka_cluster_test.go.tmpl +++ b/mmv1/third_party/terraform/services/managedkafka/resource_managed_kafka_cluster_test.go.tmpl @@ -1,5 +1,4 @@ package managedkafka_test -{{- if ne $.TargetVersionName "ga" }} import ( "testing" @@ -17,7 +16,7 @@ func TestAccManagedKafkaCluster_update(t *testing.T) { acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, - ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), CheckDestroy: testAccCheckManagedKafkaClusterDestroyProducer(t), Steps: []resource.TestStep{ { @@ -64,12 +63,9 @@ resource "google_managed_kafka_cluster" "example" { labels = { key = "value" } - - provider = google-beta } data "google_project" "project" { - provider = google-beta } `, context) } @@ -96,15 +92,9 @@ resource "google_managed_kafka_cluster" "example" { labels = { key = "new-value" } - - provider = google-beta } data "google_project" "project" { - provider = google-beta } `, context) } -{{- else }} -// Magic Modules doesn't let us remove files - blank out beta-only common-compile files for now. -{{- end }} diff --git a/mmv1/third_party/terraform/services/managedkafka/resource_managed_kafka_topic_test.go.tmpl b/mmv1/third_party/terraform/services/managedkafka/resource_managed_kafka_topic_test.go.tmpl index 49cb6c23f4fc..2723b5acfbf9 100644 --- a/mmv1/third_party/terraform/services/managedkafka/resource_managed_kafka_topic_test.go.tmpl +++ b/mmv1/third_party/terraform/services/managedkafka/resource_managed_kafka_topic_test.go.tmpl @@ -1,5 +1,4 @@ package managedkafka_test -{{- if ne $.TargetVersionName "ga" }} import ( "testing" @@ -17,7 +16,7 @@ func TestAccManagedKafkaTopic_update(t *testing.T) { acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, - ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), CheckDestroy: testAccCheckManagedKafkaTopicDestroyProducer(t), Steps: []resource.TestStep{ { @@ -58,8 +57,6 @@ resource "google_managed_kafka_cluster" "example" { } } } - - provider = google-beta } resource "google_managed_kafka_topic" "example" { @@ -71,12 +68,9 @@ resource "google_managed_kafka_topic" "example" { configs = { "cleanup.policy" = "compact" } - - provider = google-beta } data "google_project" "project" { - provider = google-beta } `, context) } @@ -97,8 +91,6 @@ resource "google_managed_kafka_cluster" "example" { } } } - - provider = google-beta } resource "google_managed_kafka_topic" "example" { @@ -110,15 +102,9 @@ resource "google_managed_kafka_topic" "example" { configs = { "cleanup.policy" = "compact" } - - provider = google-beta } data "google_project" "project" { - provider = google-beta } `, context) } -{{- else }} -// Magic Modules doesn't let us remove files - blank out beta-only common-compile files for now. -{{- end }} From 228229d06b5e09c97f99655f89c5264f91262a61 Mon Sep 17 00:00:00 2001 From: Salome Papiashvili Date: Fri, 8 Nov 2024 19:04:45 +0100 Subject: [PATCH 027/105] in-place upgrade for minor and patch versions is in GA - update doc (#12258) --- .../website/docs/r/composer_environment.html.markdown | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/mmv1/third_party/terraform/website/docs/r/composer_environment.html.markdown b/mmv1/third_party/terraform/website/docs/r/composer_environment.html.markdown index e82b80921d4e..35740d97bcb9 100644 --- a/mmv1/third_party/terraform/website/docs/r/composer_environment.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/composer_environment.html.markdown @@ -1030,8 +1030,7 @@ The following arguments are supported: version number or 'latest'. The Apache Airflow portion of the image version is a full semantic version that points to one of the supported Apache Airflow versions, or an alias in the form of only major or major.minor versions specified. - **Important**: In-place upgrade is only available using `google-beta` provider. It's because updating the - `image_version` is still in beta. Using `google-beta` provider, you can upgrade in-place between minor or + **Important**: In-place upgrade is only available between minor or patch versions of Cloud Composer or Apache Airflow. For example, you can upgrade your environment from `composer-1.16.x` to `composer-1.17.x`, or from `airflow-2.1.x` to `airflow-2.2.x`. You cannot upgrade between major Cloud Composer or Apache Airflow versions (from `1.x.x` to `2.x.x`). To do so, create a new environment. @@ -1461,7 +1460,10 @@ The following arguments are supported: `composer-(([0-9]+)(\.[0-9]+\.[0-9]+(-preview\.[0-9]+)?)?|latest)-airflow-(([0-9]+)((\.[0-9]+)(\.[0-9]+)?)?(-build\.[0-9]+)?)` Example: composer-3-airflow-2.6.3-build.4 - **Important**: In-place upgrade for Composer 3 is not yet supported. + **Important**: In-place upgrade in Composer 3 is only available between minor or patch versions of Apache Airflow. + You can also upgrade to a different Airflow build within the same version by specifying the build number. + For example, you can upgrade your environment from composer-3-airflow-2.6.x to composer-3-airflow-2.9.x, + or from composer-3-airflow-2.9.3-build.4 to composer-3-airflow-2.9.3-build.5. * `cloud_data_lineage_integration` - (Optional, Cloud Composer environments in versions composer-2.1.2-airflow-*.*.* and later) From 25fe858a04f7610857396702254eed6d22fb09dd Mon Sep 17 00:00:00 2001 From: Elie CHARRA Date: Fri, 8 Nov 2024 19:17:47 +0100 Subject: [PATCH 028/105] doc: fix wrong iam auth flag for sql_user (#12282) --- .../terraform/website/docs/r/sql_user.html.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mmv1/third_party/terraform/website/docs/r/sql_user.html.markdown b/mmv1/third_party/terraform/website/docs/r/sql_user.html.markdown index e6847a79f6fd..cefb6d1a4320 100644 --- a/mmv1/third_party/terraform/website/docs/r/sql_user.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/sql_user.html.markdown @@ -53,7 +53,7 @@ resource "google_sql_database_instance" "main" { tier = "db-f1-micro" database_flags { - name = "cloudsql_iam_authentication" + name = "cloudsql.iam_authentication" value = "on" } } @@ -202,4 +202,4 @@ $ terraform import google_sql_user.default {{project_id}}/{{instance}}/{{host}}/ # PostgreSQL database $ terraform import google_sql_user.default {{project_id}}/{{instance}}/{{name}} -``` \ No newline at end of file +``` From 43b84b7308128de70332e50ff85c5f3713f66c1b Mon Sep 17 00:00:00 2001 From: Will Yardley Date: Fri, 8 Nov 2024 10:18:17 -0800 Subject: [PATCH 029/105] compute: used `net.IP.Equal` vs `bytes.Equal` for IP comparison (#12279) --- .../terraform/constants/compute_forwarding_rule.go.tmpl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mmv1/templates/terraform/constants/compute_forwarding_rule.go.tmpl b/mmv1/templates/terraform/constants/compute_forwarding_rule.go.tmpl index 19580c9b79b3..83c5a738e7f3 100644 --- a/mmv1/templates/terraform/constants/compute_forwarding_rule.go.tmpl +++ b/mmv1/templates/terraform/constants/compute_forwarding_rule.go.tmpl @@ -51,7 +51,7 @@ func InternalIpDiffSuppress(_, old, new string, _ *schema.ResourceData) bool { addr_equality = true } else { // old and new are IP addresses - addr_equality = bytes.Equal(addr_old, addr_new) + addr_equality = net.IP.Equal(addr_old, addr_new) } } @@ -64,4 +64,4 @@ func InternalIpDiffSuppress(_, old, new string, _ *schema.ResourceData) bool { } return addr_equality && netmask_equality -} \ No newline at end of file +} From f954b7c9dab564bf88a97b24f94e9d795889faaf Mon Sep 17 00:00:00 2001 From: "Lei (Jerry) Ding" Date: Fri, 8 Nov 2024 10:52:47 -0800 Subject: [PATCH 030/105] adds support for the Dataproc on GDC SparkApplication resource (#12237) Co-authored-by: Jerry Ding --- .../dataprocgdc/SparkApplication.yaml | 332 ++++++++++++++++++ .../dataprocgdc_sparkapplication.tf.tmpl | 32 ++ ...dataprocgdc_sparkapplication_basic.tf.tmpl | 12 + ...taprocgdc_sparkapplication_pyspark.tf.tmpl | 17 + ...ataprocgdc_sparkapplication_sparkr.tf.tmpl | 14 + ...aprocgdc_sparkapplication_sparksql.tf.tmpl | 17 + ...arkapplication_sparksql_query_file.tf.tmpl | 15 + 7 files changed, 439 insertions(+) create mode 100644 mmv1/products/dataprocgdc/SparkApplication.yaml create mode 100644 mmv1/templates/terraform/examples/dataprocgdc_sparkapplication.tf.tmpl create mode 100644 mmv1/templates/terraform/examples/dataprocgdc_sparkapplication_basic.tf.tmpl create mode 100644 mmv1/templates/terraform/examples/dataprocgdc_sparkapplication_pyspark.tf.tmpl create mode 100644 mmv1/templates/terraform/examples/dataprocgdc_sparkapplication_sparkr.tf.tmpl create mode 100644 mmv1/templates/terraform/examples/dataprocgdc_sparkapplication_sparksql.tf.tmpl create mode 100644 mmv1/templates/terraform/examples/dataprocgdc_sparkapplication_sparksql_query_file.tf.tmpl diff --git a/mmv1/products/dataprocgdc/SparkApplication.yaml b/mmv1/products/dataprocgdc/SparkApplication.yaml new file mode 100644 index 000000000000..55024aac6f31 --- /dev/null +++ b/mmv1/products/dataprocgdc/SparkApplication.yaml @@ -0,0 +1,332 @@ +# Copyright 2024 Google Inc. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- +name: SparkApplication +description: A Spark application is a single Spark workload run on a GDC cluster. +references: + guides: + 'Dataproc Intro': 'https://cloud.google.com/dataproc/' + api: 'https://cloud.google.com/dataproc-gdc/docs/reference/rest/v1/projects.locations.serviceInstances.sparkApplications' +parameters: + - name: location + type: String + description: 'The location of the spark application.' + url_param_only: true + required: true + immutable: true + - name: serviceinstance + type: String + description: 'The id of the service instance to which this spark application belongs.' + url_param_only: true + required: true + immutable: true + - name: sparkApplicationId + type: String + description: 'The id of the application ' + url_param_only: true + required: true + immutable: true +async: + actions: ['create', 'delete'] + type: OpAsync + operation: + base_url: "{{op_id}}" +immutable: true +examples: + - name: "dataprocgdc_sparkapplication_basic" + primary_resource_id: "spark-application" + vars: + spark_application_id: "tf-e2e-spark-app-basic" + project: "my-project" + test_vars_overrides: + 'project': '"gdce-cluster-monitoring"' + - name: "dataprocgdc_sparkapplication" + primary_resource_id: "spark-application" + vars: + spark_application_id: "tf-e2e-spark-app" + application_environment_id: "tf-e2e-spark-app-env" + project: "my-project" + test_vars_overrides: + 'project': '"gdce-cluster-monitoring"' + - name: "dataprocgdc_sparkapplication_pyspark" + primary_resource_id: "spark-application" + vars: + spark_application_id: "tf-e2e-pyspark-app" + project: "my-project" + test_vars_overrides: + 'project': '"gdce-cluster-monitoring"' + - name: "dataprocgdc_sparkapplication_sparkr" + primary_resource_id: "spark-application" + vars: + spark_application_id: "tf-e2e-sparkr-app" + project: "my-project" + test_vars_overrides: + 'project': '"gdce-cluster-monitoring"' + - name: "dataprocgdc_sparkapplication_sparksql" + primary_resource_id: "spark-application" + vars: + spark_application_id: "tf-e2e-sparksql-app" + project: "my-project" + test_vars_overrides: + 'project': '"gdce-cluster-monitoring"' + - name: "dataprocgdc_sparkapplication_sparksql_query_file" + primary_resource_id: "spark-application" + vars: + spark_application_id: "tf-e2e-sparksql-app" + project: "my-project" + test_vars_overrides: + 'project': '"gdce-cluster-monitoring"' +base_url: projects/{{project}}/locations/{{location}}/serviceInstances/{{serviceinstance}}/sparkApplications +create_url: projects/{{project}}/locations/{{location}}/serviceInstances/{{serviceinstance}}/sparkApplications?sparkApplicationId={{spark_application_id}} +self_link: projects/{{project}}/locations/{{location}}/serviceInstances/{{serviceinstance}}/sparkApplications/{{spark_application_id}} +id_format: projects/{{project}}/locations/{{location}}/serviceInstances/{{serviceinstance}}/sparkApplications/{{spark_application_id}} +import_format: + - projects/{{project}}/locations/{{location}}/serviceInstances/{{serviceinstance}}/sparkApplications/{{spark_application_id}} +autogen_async: true +properties: + - name: pysparkApplicationConfig + type: NestedObject + exactly_one_of: + - 'pyspark_application_config' + - 'spark_application_config' + - 'spark_sql_application_config' + - 'spark_r_application_config' + properties: + - name: mainPythonFileUri + type: String + description: "The HCFS URI of the main Python file to use as the driver. + Must be a .py file. " + required: true + - name: args + type: Array + item_type: + type: String + description: "The arguments to pass to the driver. Do not include arguments, such + as `--conf`, that can be set as job properties, since a collision may occur + that causes an incorrect job submission. " + - name: pythonFileUris + type: Array + item_type: + type: String + description: "HCFS file URIs of Python files to pass to the PySpark framework. + Supported file types: .py, .egg, and .zip. " + - name: jarFileUris + type: Array + item_type: + type: String + description: "HCFS URIs of jar files to add to the CLASSPATHs of the Python + driver and tasks. " + - name: fileUris + type: Array + item_type: + type: String + description: "HCFS URIs of files to be placed in the working directory + of each executor. Useful for naively parallel tasks. " + - name: archiveUris + type: Array + item_type: + type: String + description: "HCFS URIs of archives to be extracted into the working + directory of each executor. Supported file types: .jar, .tar, .tar.gz, .tgz, + and .zip. " + description: 'Represents the PySparkApplicationConfig. ' + - name: sparkApplicationConfig + type: NestedObject + exactly_one_of: + - 'pyspark_application_config' + - 'spark_application_config' + - 'spark_sql_application_config' + - 'spark_r_application_config' + properties: + - name: mainJarFileUri + type: String + description: 'The HCFS URI of the jar file that contains the main class. ' + - name: mainClass + type: String + description: "The name of the driver main class. The jar file that contains the + class must be in the classpath or specified in `jar_file_uris`. " + - name: args + type: Array + item_type: + type: String + description: "The arguments to pass to the driver. Do not include arguments that + can be set as application properties, such as `--conf`, since a collision can + occur that causes an incorrect application submission. " + - name: jarFileUris + type: Array + item_type: + type: String + description: "HCFS URIs of jar files to add to the classpath of the Spark + driver and tasks. " + - name: fileUris + type: Array + item_type: + type: String + description: "HCFS URIs of files to be placed in the working directory + of each executor. " + - name: archiveUris + type: Array + item_type: + type: String + description: "HCFS URIs of archives to be extracted into the working + directory of each executor. Supported file types: `.jar`, `.tar`, `.tar.gz`, + `.tgz`, and `.zip`. " + description: 'Represents the SparkApplicationConfig. ' + - name: sparkRApplicationConfig + type: NestedObject + exactly_one_of: + - 'pyspark_application_config' + - 'spark_application_config' + - 'spark_sql_application_config' + - 'spark_r_application_config' + properties: + - name: mainRFileUri + type: String + description: "The HCFS URI of the main R file to use as the driver. Must + be a .R file. " + required: true + - name: args + type: Array + item_type: + type: String + description: "The arguments to pass to the driver. Do not include arguments, such + as `--conf`, that can be set as job properties, since a collision may occur + that causes an incorrect job submission. " + - name: fileUris + type: Array + item_type: + type: String + description: "HCFS URIs of files to be placed in the working directory + of each executor. Useful for naively parallel tasks. " + - name: archiveUris + type: Array + item_type: + type: String + description: "HCFS URIs of archives to be extracted into the working + directory of each executor. Supported file types: .jar, .tar, .tar.gz, .tgz, + and .zip. " + description: 'Represents the SparkRApplicationConfig. ' + - name: sparkSqlApplicationConfig + type: NestedObject + exactly_one_of: + - 'pyspark_application_config' + - 'spark_application_config' + - 'spark_sql_application_config' + - 'spark_r_application_config' + properties: + - name: queryFileUri + type: String + description: 'The HCFS URI of the script that contains SQL queries. ' + - name: queryList + type: NestedObject + properties: + - name: queries + type: Array + item_type: + type: String + description: 'The queries to run.' + required: true + description: 'Represents a list of queries. ' + - name: scriptVariables + type: KeyValuePairs + description: "Mapping of query variable names to values (equivalent + to the Spark SQL command: SET `name=\"value\";`). " + - name: jarFileUris + type: Array + item_type: + type: String + description: 'HCFS URIs of jar files to be added to the Spark CLASSPATH. ' + description: 'Represents the SparkRApplicationConfig. ' + - name: name + type: String + description: "Identifier. The name of the application. Format: projects/{project}/locations/{location}/serviceInstances/{service_instance}/sparkApplications/{application} " + output: true + - name: uid + type: String + description: "System generated unique identifier for this application, + formatted as UUID4. " + output: true + - name: displayName + type: String + description: 'User-provided human-readable name to be used in user interfaces. ' + - name: createTime + type: String + description: 'The timestamp when the resource was created. ' + output: true + - name: updateTime + type: String + description: 'The timestamp when the resource was most recently updated. ' + output: true + - name: state + type: String + description: | + The current state. + Possible values: + * `STATE_UNSPECIFIED` + * `PENDING` + * `RUNNING` + * `CANCELLING` + * `CANCELLED` + * `SUCCEEDED` + * `FAILED` + output: true + - name: reconciling + type: Boolean + description: "Whether the application is currently reconciling. True + if the current state of the resource does not match the intended state, and the + system is working to reconcile them, whether or not the change was user initiated." + output: true + - name: labels + type: KeyValueLabels + description: "The labels to associate with this application. Labels may + be used for filtering and billing tracking. " + - name: annotations + type: KeyValueAnnotations + description: "The annotations to associate with this application. Annotations + may be used to store client information, but are not used by the server. " + - name: outputUri + type: String + description: "An HCFS URI pointing to the location of stdout and stdout + of the application Mainly useful for Pantheon and gcloud Not in scope for private GA " + output: true + - name: monitoringEndpoint + type: String + description: "URL for a monitoring UI for this application (for eventual + Spark PHS/UI support) Out of scope for private GA " + output: true + - name: properties + type: KeyValuePairs + description: 'application-specific properties. ' + - name: stateMessage + type: String + description: 'A message explaining the current state. ' + output: true + - name: version + type: String + description: 'The Dataproc version of this application. ' + - name: applicationEnvironment + type: String + description: 'An ApplicationEnvironment from which to inherit configuration + properties. ' + - name: namespace + type: String + description: "The Kubernetes namespace in which to create the application. This + namespace must already exist on the cluster. " + - name: dependencyImages + type: Array + item_type: + type: String + description: "List of container image uris for additional file dependencies. Dependent + files are sequentially copied from each image. If a file with the same name exists + in 2 images then the file from later image is used. " diff --git a/mmv1/templates/terraform/examples/dataprocgdc_sparkapplication.tf.tmpl b/mmv1/templates/terraform/examples/dataprocgdc_sparkapplication.tf.tmpl new file mode 100644 index 000000000000..8a04d341d7f0 --- /dev/null +++ b/mmv1/templates/terraform/examples/dataprocgdc_sparkapplication.tf.tmpl @@ -0,0 +1,32 @@ +resource "google_dataproc_gdc_application_environment" "app_env" { + application_environment_id = "{{index $.Vars "application_environment_id"}}" + serviceinstance = "do-not-delete-dataproc-gdc-instance" + project = "{{index $.Vars "project"}}" + location = "us-west2" + namespace = "default" +} + +resource "google_dataproc_gdc_spark_application" "{{$.PrimaryResourceId}}" { + spark_application_id = "{{index $.Vars "spark_application_id"}}" + serviceinstance = "do-not-delete-dataproc-gdc-instance" + project = "{{index $.Vars "project"}}" + location = "us-west2" + namespace = "default" + labels = { + "test-label": "label-value" + } + annotations = { + "an_annotation": "annotation_value" + } + properties = { + "spark.executor.instances": "2" + } + application_environment = google_dataproc_gdc_application_environment.app_env.name + version = "1.2" + spark_application_config { + main_jar_file_uri = "file:///usr/lib/spark/examples/jars/spark-examples.jar" + jar_file_uris = ["file:///usr/lib/spark/examples/jars/spark-examples.jar"] + archive_uris = ["file://usr/lib/spark/examples/spark-examples.jar"] + file_uris = ["file:///usr/lib/spark/examples/jars/spark-examples.jar"] + } +} \ No newline at end of file diff --git a/mmv1/templates/terraform/examples/dataprocgdc_sparkapplication_basic.tf.tmpl b/mmv1/templates/terraform/examples/dataprocgdc_sparkapplication_basic.tf.tmpl new file mode 100644 index 000000000000..b7a0ee81bc78 --- /dev/null +++ b/mmv1/templates/terraform/examples/dataprocgdc_sparkapplication_basic.tf.tmpl @@ -0,0 +1,12 @@ +resource "google_dataproc_gdc_spark_application" "{{$.PrimaryResourceId}}" { + spark_application_id = "{{index $.Vars "spark_application_id"}}" + serviceinstance = "do-not-delete-dataproc-gdc-instance" + project = "{{index $.Vars "project"}}" + location = "us-west2" + namespace = "default" + spark_application_config { + main_class = "org.apache.spark.examples.SparkPi" + jar_file_uris = ["file:///usr/lib/spark/examples/jars/spark-examples.jar"] + args = ["10000"] + } +} \ No newline at end of file diff --git a/mmv1/templates/terraform/examples/dataprocgdc_sparkapplication_pyspark.tf.tmpl b/mmv1/templates/terraform/examples/dataprocgdc_sparkapplication_pyspark.tf.tmpl new file mode 100644 index 000000000000..c109c3d35f07 --- /dev/null +++ b/mmv1/templates/terraform/examples/dataprocgdc_sparkapplication_pyspark.tf.tmpl @@ -0,0 +1,17 @@ +resource "google_dataproc_gdc_spark_application" "{{$.PrimaryResourceId}}" { + spark_application_id = "{{index $.Vars "spark_application_id"}}" + serviceinstance = "do-not-delete-dataproc-gdc-instance" + project = "{{index $.Vars "project"}}" + location = "us-west2" + namespace = "default" + display_name = "A Pyspark application for a Terraform create test" + dependency_images = ["gcr.io/some/image"] + pyspark_application_config { + main_python_file_uri = "gs://goog-dataproc-initialization-actions-us-west2/conda/test_conda.py" + jar_file_uris = ["file:///usr/lib/spark/examples/jars/spark-examples.jar"] + python_file_uris = ["gs://goog-dataproc-initialization-actions-us-west2/conda/get-sys-exec.py"] + file_uris = ["file://usr/lib/spark/examples/spark-examples.jar"] + archive_uris = ["file://usr/lib/spark/examples/spark-examples.jar"] + args = ["10"] + } +} \ No newline at end of file diff --git a/mmv1/templates/terraform/examples/dataprocgdc_sparkapplication_sparkr.tf.tmpl b/mmv1/templates/terraform/examples/dataprocgdc_sparkapplication_sparkr.tf.tmpl new file mode 100644 index 000000000000..74da21a7872e --- /dev/null +++ b/mmv1/templates/terraform/examples/dataprocgdc_sparkapplication_sparkr.tf.tmpl @@ -0,0 +1,14 @@ +resource "google_dataproc_gdc_spark_application" "{{$.PrimaryResourceId}}" { + spark_application_id = "{{index $.Vars "spark_application_id"}}" + serviceinstance = "do-not-delete-dataproc-gdc-instance" + project = "{{index $.Vars "project"}}" + location = "us-west2" + namespace = "default" + display_name = "A SparkR application for a Terraform create test" + spark_r_application_config { + main_r_file_uri = "gs://some-bucket/something.R" + file_uris = ["file://usr/lib/spark/examples/spark-examples.jar"] + archive_uris = ["file://usr/lib/spark/examples/spark-examples.jar"] + args = ["10"] + } +} \ No newline at end of file diff --git a/mmv1/templates/terraform/examples/dataprocgdc_sparkapplication_sparksql.tf.tmpl b/mmv1/templates/terraform/examples/dataprocgdc_sparkapplication_sparksql.tf.tmpl new file mode 100644 index 000000000000..86bff7241908 --- /dev/null +++ b/mmv1/templates/terraform/examples/dataprocgdc_sparkapplication_sparksql.tf.tmpl @@ -0,0 +1,17 @@ +resource "google_dataproc_gdc_spark_application" "{{$.PrimaryResourceId}}" { + spark_application_id = "{{index $.Vars "spark_application_id"}}" + serviceinstance = "do-not-delete-dataproc-gdc-instance" + project = "{{index $.Vars "project"}}" + location = "us-west2" + namespace = "default" + display_name = "A SparkSql application for a Terraform create test" + spark_sql_application_config { + jar_file_uris = ["file:///usr/lib/spark/examples/jars/spark-examples.jar"] + query_list { + queries = ["show tables;"] + } + script_variables = { + "MY_VAR": "1" + } + } +} \ No newline at end of file diff --git a/mmv1/templates/terraform/examples/dataprocgdc_sparkapplication_sparksql_query_file.tf.tmpl b/mmv1/templates/terraform/examples/dataprocgdc_sparkapplication_sparksql_query_file.tf.tmpl new file mode 100644 index 000000000000..22c7034b4e18 --- /dev/null +++ b/mmv1/templates/terraform/examples/dataprocgdc_sparkapplication_sparksql_query_file.tf.tmpl @@ -0,0 +1,15 @@ +resource "google_dataproc_gdc_spark_application" "{{$.PrimaryResourceId}}" { + spark_application_id = "{{index $.Vars "spark_application_id"}}" + serviceinstance = "do-not-delete-dataproc-gdc-instance" + project = "{{index $.Vars "project"}}" + location = "us-west2" + namespace = "default" + display_name = "A SparkSql application for a Terraform create test" + spark_sql_application_config { + jar_file_uris = ["file:///usr/lib/spark/examples/jars/spark-examples.jar"] + query_file_uri = "gs://some-bucket/something.sql" + script_variables = { + "MY_VAR": "1" + } + } +} \ No newline at end of file From c3885741c9b1c21ba3ccd0c4128818891791952f Mon Sep 17 00:00:00 2001 From: Pavan Shankar Date: Fri, 8 Nov 2024 20:51:45 +0000 Subject: [PATCH 031/105] Fix plan for google_identity_platform_config always showing a change for phone_number.enabled=false and email.enabled=false (#12255) --- mmv1/products/identityplatform/Config.yaml | 13 ++++++++ .../identity_platform_config_email.go.tmpl | 21 ++++++++++++ ...ntity_platform_config_phone_number.go.tmpl | 21 ++++++++++++ ..._platform_config_with_false_values.tf.tmpl | 32 +++++++++++++++++++ 4 files changed, 87 insertions(+) create mode 100644 mmv1/templates/terraform/custom_flatten/identity_platform_config_email.go.tmpl create mode 100644 mmv1/templates/terraform/custom_flatten/identity_platform_config_phone_number.go.tmpl create mode 100644 mmv1/templates/terraform/examples/identity_platform_config_with_false_values.tf.tmpl diff --git a/mmv1/products/identityplatform/Config.yaml b/mmv1/products/identityplatform/Config.yaml index 462f7e227b16..57a574c05edf 100644 --- a/mmv1/products/identityplatform/Config.yaml +++ b/mmv1/products/identityplatform/Config.yaml @@ -71,6 +71,17 @@ examples: - 'client.0.api_key' - 'client.0.firebase_subdomain' exclude_docs: true + - name: 'identity_platform_config_with_false_values' + primary_resource_id: 'default' + vars: + project_id: 'my-project-2' + test_env_vars: + org_id: 'ORG_ID' + billing_acct: 'BILLING_ACCT' + ignore_read_extra: + - 'client.0.api_key' + - 'client.0.firebase_subdomain' + exclude_docs: true parameters: properties: - name: 'name' @@ -92,6 +103,7 @@ properties: type: NestedObject description: | Configuration options related to authenticating a user by their email address. + custom_flatten: 'templates/terraform/custom_flatten/identity_platform_config_email.go.tmpl' properties: - name: 'enabled' type: Boolean @@ -108,6 +120,7 @@ properties: type: NestedObject description: | Configuration options related to authenticated a user by their phone number. + custom_flatten: 'templates/terraform/custom_flatten/identity_platform_config_phone_number.go.tmpl' properties: - name: 'enabled' type: Boolean diff --git a/mmv1/templates/terraform/custom_flatten/identity_platform_config_email.go.tmpl b/mmv1/templates/terraform/custom_flatten/identity_platform_config_email.go.tmpl new file mode 100644 index 000000000000..23e1c6620ab9 --- /dev/null +++ b/mmv1/templates/terraform/custom_flatten/identity_platform_config_email.go.tmpl @@ -0,0 +1,21 @@ +func flatten{{$.GetPrefix}}{{$.TitlelizeProperty}}(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + transformed := make(map[string]interface{}) + + if v == nil { + transformed["enabled"] = false + } else { + original := v.(map[string]interface{}) + + if original["enabled"] == nil { + transformed["enabled"] = false + } else { + transformed["enabled"] = original["enabled"] + } + + if original["passwordRequired"] != nil { + transformed["password_required"] = original["passwordRequired"] + } + } + + return []interface{}{transformed} +} \ No newline at end of file diff --git a/mmv1/templates/terraform/custom_flatten/identity_platform_config_phone_number.go.tmpl b/mmv1/templates/terraform/custom_flatten/identity_platform_config_phone_number.go.tmpl new file mode 100644 index 000000000000..95137873b579 --- /dev/null +++ b/mmv1/templates/terraform/custom_flatten/identity_platform_config_phone_number.go.tmpl @@ -0,0 +1,21 @@ +func flatten{{$.GetPrefix}}{{$.TitlelizeProperty}}(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + transformed := make(map[string]interface{}) + + if v == nil { + transformed["enabled"] = false + } else { + original := v.(map[string]interface{}) + + if original["enabled"] == nil { + transformed["enabled"] = false + } else { + transformed["enabled"] = original["enabled"] + } + + if original["testPhoneNumbers"] != nil { + transformed["test_phone_numbers"] = original["testPhoneNumbers"] + } + } + + return []interface{}{transformed} +} \ No newline at end of file diff --git a/mmv1/templates/terraform/examples/identity_platform_config_with_false_values.tf.tmpl b/mmv1/templates/terraform/examples/identity_platform_config_with_false_values.tf.tmpl new file mode 100644 index 000000000000..c3c4198e4f2a --- /dev/null +++ b/mmv1/templates/terraform/examples/identity_platform_config_with_false_values.tf.tmpl @@ -0,0 +1,32 @@ +resource "google_project" "default" { + project_id = "{{index $.Vars "project_id"}}" + name = "{{index $.Vars "project_id"}}" + org_id = "{{index $.TestEnvVars "org_id"}}" + billing_account = "{{index $.TestEnvVars "billing_acct"}}" + deletion_policy = "DELETE" + labels = { + firebase = "enabled" + } +} + +resource "google_project_service" "identitytoolkit" { + project = google_project.default.project_id + service = "identitytoolkit.googleapis.com" +} + +resource "google_identity_platform_config" "default" { + project = google_project.default.project_id + autodelete_anonymous_users = false + sign_in { + + anonymous { + enabled = false + } + email { + enabled = false + } + phone_number { + enabled = false + } + } +} From f1195ea345722ec1ee5ddc1db5d3021a78ac9e5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Norbert=20Kami=C5=84ski?= Date: Fri, 8 Nov 2024 22:57:12 +0100 Subject: [PATCH 032/105] Add IDPF support for the google_compute_instance and google_compute_image.guest_os_features (#12256) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Norbert Kamiński --- mmv1/products/compute/Image.yaml | 1 + .../services/compute/resource_compute_instance.go.tmpl | 4 ++-- .../terraform/website/docs/r/compute_instance.html.markdown | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/mmv1/products/compute/Image.yaml b/mmv1/products/compute/Image.yaml index bdaffea3863d..b78abce38088 100644 --- a/mmv1/products/compute/Image.yaml +++ b/mmv1/products/compute/Image.yaml @@ -146,6 +146,7 @@ properties: - 'VIRTIO_SCSI_MULTIQUEUE' - 'WINDOWS' - 'GVNIC' + - 'IDPF' - 'SEV_LIVE_MIGRATABLE' - 'SEV_SNP_CAPABLE' - 'SUSPEND_RESUME_COMPATIBLE' diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_instance.go.tmpl b/mmv1/third_party/terraform/services/compute/resource_compute_instance.go.tmpl index c0bea3818dc7..83ca4470dede 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_instance.go.tmpl +++ b/mmv1/third_party/terraform/services/compute/resource_compute_instance.go.tmpl @@ -465,8 +465,8 @@ func ResourceComputeInstance() *schema.Resource { Type: schema.TypeString, Optional: true, ForceNew: true, - ValidateFunc: validation.StringInSlice([]string{"GVNIC", "VIRTIO_NET"}, false), - Description: `The type of vNIC to be used on this interface. Possible values:GVNIC, VIRTIO_NET`, + ValidateFunc: validation.StringInSlice([]string{"GVNIC", "VIRTIO_NET", "IDPF"}, false), + Description: `The type of vNIC to be used on this interface. Possible values:GVNIC, VIRTIO_NET, IDPF`, }, "access_config": { Type: schema.TypeList, diff --git a/mmv1/third_party/terraform/website/docs/r/compute_instance.html.markdown b/mmv1/third_party/terraform/website/docs/r/compute_instance.html.markdown index ccd6d6b7b446..1521b7ee2cdb 100644 --- a/mmv1/third_party/terraform/website/docs/r/compute_instance.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/compute_instance.html.markdown @@ -395,7 +395,7 @@ is desired, you will need to modify your state file manually using array of alias IP ranges for this network interface. Can only be specified for network interfaces on subnet-mode networks. Structure [documented below](#nested_alias_ip_range). -* `nic_type` - (Optional) The type of vNIC to be used on this interface. Possible values: GVNIC, VIRTIO_NET. +* `nic_type` - (Optional) The type of vNIC to be used on this interface. Possible values: GVNIC, VIRTIO_NET, IDPF. * `network_attachment` - (Optional) [Beta](https://terraform.io/docs/providers/google/guides/provider_versions.html) The URL of the network attachment that this interface should connect to in the following format: `projects/{projectNumber}/regions/{region_name}/networkAttachments/{network_attachment_name}`. From 61269cf1023057d2a5ba80fa6a1b6e408e4d57a1 Mon Sep 17 00:00:00 2001 From: abheda-crest <105624942+abheda-crest@users.noreply.github.com> Date: Sat, 9 Nov 2024 03:58:23 +0530 Subject: [PATCH 033/105] Make type assertions more defensive on the secret manager datasources (#11990) --- ...ta_source_secret_manager_secret_version.go | 49 +++++++++------ ...ce_secret_manager_secret_version_access.go | 41 ++++++++----- ..._secret_manager_regional_secret_version.go | 61 +++++++++++-------- ..._manager_regional_secret_version_access.go | 2 +- 4 files changed, 96 insertions(+), 57 deletions(-) diff --git a/mmv1/third_party/terraform/services/secretmanager/data_source_secret_manager_secret_version.go b/mmv1/third_party/terraform/services/secretmanager/data_source_secret_manager_secret_version.go index 70156caf6fc3..d656eae35b07 100644 --- a/mmv1/third_party/terraform/services/secretmanager/data_source_secret_manager_secret_version.go +++ b/mmv1/third_party/terraform/services/secretmanager/data_source_secret_manager_secret_version.go @@ -68,19 +68,27 @@ func dataSourceSecretManagerSecretVersionRead(d *schema.ResourceData, meta inter return err } - fv, err := tpgresource.ParseProjectFieldValue("secrets", d.Get("secret").(string), "project", d, config, false) + dSecret, ok := d.Get("secret").(string) + if !ok { + return fmt.Errorf("wrong type for secret field (%T), expected string", d.Get("secret")) + } + + fv, err := tpgresource.ParseProjectFieldValue("secrets", dSecret, "project", d, config, false) if err != nil { return err } - if d.Get("project").(string) != "" && d.Get("project").(string) != fv.Project { - return fmt.Errorf("The project set on this secret version (%s) is not equal to the project where this secret exists (%s).", d.Get("project").(string), fv.Project) - } project := fv.Project + if dProject, ok := d.Get("project").(string); !ok { + return fmt.Errorf("wrong type for project (%T), expected string", d.Get("project")) + } else if dProject != "" && dProject != project { + return fmt.Errorf("project field value (%s) does not match project of secret (%s).", dProject, project) + } + if err := d.Set("project", project); err != nil { - return fmt.Errorf("Error setting project: %s", err) + return fmt.Errorf("error setting project: %s", err) } if err := d.Set("secret", fv.Name); err != nil { - return fmt.Errorf("Error setting secret: %s", err) + return fmt.Errorf("error setting secret: %s", err) } var url string @@ -107,21 +115,26 @@ func dataSourceSecretManagerSecretVersionRead(d *schema.ResourceData, meta inter UserAgent: userAgent, }) if err != nil { - return fmt.Errorf("Error retrieving available secret manager secret versions: %s", err.Error()) + return fmt.Errorf("error retrieving available secret manager secret versions: %s", err.Error()) } secretVersionRegex := regexp.MustCompile("projects/(.+)/secrets/(.+)/versions/(.+)$") - parts := secretVersionRegex.FindStringSubmatch(version["name"].(string)) + nameValue, ok := version["name"] + if !ok { + return fmt.Errorf("read response didn't contain critical fields. Read may not have succeeded.") + } + + parts := secretVersionRegex.FindStringSubmatch(nameValue.(string)) // should return [full string, project number, secret name, version number] if len(parts) != 4 { - panic(fmt.Sprintf("secret name, %s, does not match format, projects/{{project}}/secrets/{{secret}}/versions/{{version}}", version["name"].(string))) + return fmt.Errorf("secret name, %s, does not match format, projects/{{project}}/secrets/{{secret}}/versions/{{version}}", nameValue.(string)) } log.Printf("[DEBUG] Received Google SecretManager Version: %q", version) if err := d.Set("version", parts[3]); err != nil { - return fmt.Errorf("Error setting version: %s", err) + return fmt.Errorf("error setting version: %s", err) } url = fmt.Sprintf("%s:access", url) @@ -133,22 +146,22 @@ func dataSourceSecretManagerSecretVersionRead(d *schema.ResourceData, meta inter UserAgent: userAgent, }) if err != nil { - return fmt.Errorf("Error retrieving available secret manager secret version access: %s", err.Error()) + return fmt.Errorf("error retrieving available secret manager secret version access: %s", err.Error()) } if err := d.Set("create_time", version["createTime"].(string)); err != nil { - return fmt.Errorf("Error setting create_time: %s", err) + return fmt.Errorf("error setting create_time: %s", err) } if version["destroyTime"] != nil { if err := d.Set("destroy_time", version["destroyTime"].(string)); err != nil { - return fmt.Errorf("Error setting destroy_time: %s", err) + return fmt.Errorf("error setting destroy_time: %s", err) } } - if err := d.Set("name", version["name"].(string)); err != nil { - return fmt.Errorf("Error setting name: %s", err) + if err := d.Set("name", nameValue.(string)); err != nil { + return fmt.Errorf("error setting name: %s", err) } if err := d.Set("enabled", true); err != nil { - return fmt.Errorf("Error setting enabled: %s", err) + return fmt.Errorf("error setting enabled: %s", err) } data := resp["payload"].(map[string]interface{}) @@ -163,9 +176,9 @@ func dataSourceSecretManagerSecretVersionRead(d *schema.ResourceData, meta inter secretData = string(payloadData) } if err := d.Set("secret_data", secretData); err != nil { - return fmt.Errorf("Error setting secret_data: %s", err) + return fmt.Errorf("error setting secret_data: %s", err) } - d.SetId(version["name"].(string)) + d.SetId(nameValue.(string)) return nil } diff --git a/mmv1/third_party/terraform/services/secretmanager/data_source_secret_manager_secret_version_access.go b/mmv1/third_party/terraform/services/secretmanager/data_source_secret_manager_secret_version_access.go index f60707b5ce89..705914a532cf 100644 --- a/mmv1/third_party/terraform/services/secretmanager/data_source_secret_manager_secret_version_access.go +++ b/mmv1/third_party/terraform/services/secretmanager/data_source_secret_manager_secret_version_access.go @@ -56,19 +56,28 @@ func dataSourceSecretManagerSecretVersionAccessRead(d *schema.ResourceData, meta return err } - fv, err := tpgresource.ParseProjectFieldValue("secrets", d.Get("secret").(string), "project", d, config, false) + dSecret, ok := d.Get("secret").(string) + if !ok { + return fmt.Errorf("wrong type for secret field (%T), expected string", d.Get("secret")) + } + + fv, err := tpgresource.ParseProjectFieldValue("secrets", dSecret, "project", d, config, false) if err != nil { return err } - if d.Get("project").(string) != "" && d.Get("project").(string) != fv.Project { - return fmt.Errorf("The project set on this secret version (%s) is not equal to the project where this secret exists (%s).", d.Get("project").(string), fv.Project) - } + project := fv.Project + if dProject, ok := d.Get("project").(string); !ok { + return fmt.Errorf("wrong type for project (%T), expected string", d.Get("project")) + } else if dProject != "" && dProject != project { + return fmt.Errorf("project field value (%s) does not match project of secret (%s).", dProject, project) + } + if err := d.Set("project", project); err != nil { - return fmt.Errorf("Error setting project: %s", err) + return fmt.Errorf("error setting project: %s", err) } if err := d.Set("secret", fv.Name); err != nil { - return fmt.Errorf("Error setting secret: %s", err) + return fmt.Errorf("error setting secret: %s", err) } var url string @@ -95,25 +104,29 @@ func dataSourceSecretManagerSecretVersionAccessRead(d *schema.ResourceData, meta UserAgent: userAgent, }) if err != nil { - return fmt.Errorf("Error retrieving available secret manager secret version access: %s", err.Error()) + return fmt.Errorf("error retrieving available secret manager secret version access: %s", err.Error()) } - if err := d.Set("name", resp["name"].(string)); err != nil { - return fmt.Errorf("Error setting name: %s", err) + nameValue, ok := resp["name"] + if !ok { + return fmt.Errorf("read response didn't contain critical fields. Read may not have succeeded.") + } + if err := d.Set("name", nameValue.(string)); err != nil { + return fmt.Errorf("error setting name: %s", err) } secretVersionRegex := regexp.MustCompile("projects/(.+)/secrets/(.+)/versions/(.+)$") - parts := secretVersionRegex.FindStringSubmatch(resp["name"].(string)) + parts := secretVersionRegex.FindStringSubmatch(nameValue.(string)) // should return [full string, project number, secret name, version number] if len(parts) != 4 { - panic(fmt.Sprintf("secret name, %s, does not match format, projects/{{project}}/secrets/{{secret}}/versions/{{version}}", resp["name"].(string))) + return fmt.Errorf("secret name, %s, does not match format, projects/{{project}}/secrets/{{secret}}/versions/{{version}}", nameValue.(string)) } log.Printf("[DEBUG] Received Google SecretManager Version: %q", parts[3]) if err := d.Set("version", parts[3]); err != nil { - return fmt.Errorf("Error setting version: %s", err) + return fmt.Errorf("error setting version: %s", err) } data := resp["payload"].(map[string]interface{}) @@ -128,9 +141,9 @@ func dataSourceSecretManagerSecretVersionAccessRead(d *schema.ResourceData, meta secretData = string(payloadData) } if err := d.Set("secret_data", secretData); err != nil { - return fmt.Errorf("Error setting secret_data: %s", err) + return fmt.Errorf("error setting secret_data: %s", err) } - d.SetId(resp["name"].(string)) + d.SetId(nameValue.(string)) return nil } diff --git a/mmv1/third_party/terraform/services/secretmanagerregional/data_source_secret_manager_regional_secret_version.go b/mmv1/third_party/terraform/services/secretmanagerregional/data_source_secret_manager_regional_secret_version.go index 0f7889b54736..a6b47dc58a22 100644 --- a/mmv1/third_party/terraform/services/secretmanagerregional/data_source_secret_manager_regional_secret_version.go +++ b/mmv1/third_party/terraform/services/secretmanagerregional/data_source_secret_manager_regional_secret_version.go @@ -86,7 +86,11 @@ func dataSourceSecretManagerRegionalRegionalSecretVersionRead(d *schema.Resource } secretRegex := regexp.MustCompile("projects/(.+)/locations/(.+)/secrets/(.+)$") - parts := secretRegex.FindStringSubmatch(d.Get("secret").(string)) + dSecret, ok := d.Get("secret").(string) + if !ok { + return fmt.Errorf("wrong type for secret field (%T), expected string", d.Get("secret")) + } + parts := secretRegex.FindStringSubmatch(dSecret) var project string @@ -94,30 +98,34 @@ func dataSourceSecretManagerRegionalRegionalSecretVersionRead(d *schema.Resource if len(parts) == 4 { // Store values of project to set in state project = parts[1] - if d.Get("project").(string) != "" && d.Get("project").(string) != parts[1] { - return fmt.Errorf("The project set on this secret version (%s) is not equal to the project where this secret exists (%s).", d.Get("project").(string), parts[1]) + if dProject, ok := d.Get("project").(string); !ok { + return fmt.Errorf("wrong type for project (%T), expected string", d.Get("project")) + } else if dProject != "" && dProject != project { + return fmt.Errorf("project field value (%s) does not match project of secret (%s).", dProject, project) } - if d.Get("location").(string) != "" && d.Get("location").(string) != parts[2] { - return fmt.Errorf("The location set on this secret version (%s) is not equal to the location where this secret exists (%s).", d.Get("location").(string), parts[2]) + if dLocation, ok := d.Get("location").(string); !ok { + return fmt.Errorf("wrong type for location (%T), expected string", d.Get("location")) + } else if dLocation != "" && dLocation != parts[2] { + return fmt.Errorf("location field value (%s) does not match location of secret (%s).", dLocation, parts[2]) } if err := d.Set("location", parts[2]); err != nil { - return fmt.Errorf("Error setting location: %s", err) + return fmt.Errorf("error setting location: %s", err) } if err := d.Set("secret", parts[3]); err != nil { - return fmt.Errorf("Error setting secret: %s", err) + return fmt.Errorf("error setting secret: %s", err) } } else { // if secret name is provided in the secret field // Store values of project to set in state project, err = tpgresource.GetProject(d, config) if err != nil { - return fmt.Errorf("Error fetching project for Secret: %s", err) + return fmt.Errorf("error fetching project for Secret: %s", err) } - if d.Get("location").(string) == "" { - return fmt.Errorf("Location must be set when providing only secret name") + if dLocation, ok := d.Get("location").(string); ok && dLocation == "" { + return fmt.Errorf("location must be set when providing only secret name") } } if err := d.Set("project", project); err != nil { - return fmt.Errorf("Error setting project: %s", err) + return fmt.Errorf("error setting project: %s", err) } var url string @@ -146,20 +154,25 @@ func dataSourceSecretManagerRegionalRegionalSecretVersionRead(d *schema.Resource }) if err != nil { - return fmt.Errorf("Error retrieving available secret manager regional secret versions: %s", err.Error()) + return fmt.Errorf("error retrieving available secret manager regional secret versions: %s", err.Error()) + } + + nameValue, ok := secretVersion["name"] + if !ok { + return fmt.Errorf("read response didn't contain critical fields. Read may not have succeeded.") } secretVersionRegex := regexp.MustCompile("projects/(.+)/locations/(.+)/secrets/(.+)/versions/(.+)$") - parts = secretVersionRegex.FindStringSubmatch(secretVersion["name"].(string)) + parts = secretVersionRegex.FindStringSubmatch(nameValue.(string)) if len(parts) != 5 { - return fmt.Errorf("secret name, %s, does not match format, projects/{{project}}/locations/{{location}}/secrets/{{secret}}/versions/{{version}}", secretVersion["name"].(string)) + return fmt.Errorf("secret name, %s, does not match format, projects/{{project}}/locations/{{location}}/secrets/{{secret}}/versions/{{version}}", nameValue.(string)) } log.Printf("[DEBUG] Received Google Secret Manager Regional Secret Version: %q", secretVersion) if err := d.Set("version", parts[4]); err != nil { - return fmt.Errorf("Error setting version: %s", err) + return fmt.Errorf("error setting version: %s", err) } url = fmt.Sprintf("%s:access", url) @@ -172,29 +185,29 @@ func dataSourceSecretManagerRegionalRegionalSecretVersionRead(d *schema.Resource }) if err != nil { - return fmt.Errorf("Error retrieving available secret manager regional secret version access: %s", err.Error()) + return fmt.Errorf("error retrieving available secret manager regional secret version access: %s", err.Error()) } if err := d.Set("customer_managed_encryption", flattenSecretManagerRegionalRegionalSecretVersionCustomerManagedEncryption(secretVersion["customerManagedEncryption"], d, config)); err != nil { - return fmt.Errorf("Error setting customer_managed_encryption: %s", err) + return fmt.Errorf("error setting customer_managed_encryption: %s", err) } if err := d.Set("create_time", secretVersion["createTime"].(string)); err != nil { - return fmt.Errorf("Error setting create_time: %s", err) + return fmt.Errorf("error setting create_time: %s", err) } if secretVersion["destroyTime"] != nil { if err := d.Set("destroy_time", secretVersion["destroyTime"].(string)); err != nil { - return fmt.Errorf("Error setting destroy_time: %s", err) + return fmt.Errorf("error setting destroy_time: %s", err) } } - if err := d.Set("name", secretVersion["name"].(string)); err != nil { - return fmt.Errorf("Error setting name: %s", err) + if err := d.Set("name", nameValue.(string)); err != nil { + return fmt.Errorf("error setting name: %s", err) } if err := d.Set("enabled", true); err != nil { - return fmt.Errorf("Error setting enabled: %s", err) + return fmt.Errorf("error setting enabled: %s", err) } data := resp["payload"].(map[string]interface{}) @@ -209,9 +222,9 @@ func dataSourceSecretManagerRegionalRegionalSecretVersionRead(d *schema.Resource secretData = string(payloadData) } if err := d.Set("secret_data", secretData); err != nil { - return fmt.Errorf("Error setting secret_data: %s", err) + return fmt.Errorf("error setting secret_data: %s", err) } - d.SetId(secretVersion["name"].(string)) + d.SetId(nameValue.(string)) return nil } diff --git a/mmv1/third_party/terraform/services/secretmanagerregional/data_source_secret_manager_regional_secret_version_access.go b/mmv1/third_party/terraform/services/secretmanagerregional/data_source_secret_manager_regional_secret_version_access.go index 734173a3b145..b90ae069e563 100644 --- a/mmv1/third_party/terraform/services/secretmanagerregional/data_source_secret_manager_regional_secret_version_access.go +++ b/mmv1/third_party/terraform/services/secretmanagerregional/data_source_secret_manager_regional_secret_version_access.go @@ -76,7 +76,7 @@ func dataSourceSecretManagerRegionalRegionalSecretVersionAccessRead(d *schema.Re if dProject, ok := d.Get("project").(string); !ok { return fmt.Errorf("wrong type for project (%T), expected string", d.Get("project")) } else if dProject != "" && dProject != project { - return fmt.Errorf("project field value (%s) does not match project of secret (%s).", d.Get("project").(string), project) + return fmt.Errorf("project field value (%s) does not match project of secret (%s).", dProject, project) } if dLocation, ok := d.Get("location").(string); !ok { return fmt.Errorf("wrong type for location (%T), expected string", d.Get("location")) From 34d0f43fba226a6b616465f0e667bd1c8ee3fc7f Mon Sep 17 00:00:00 2001 From: Jimmy xu Date: Mon, 11 Nov 2024 08:50:16 -0500 Subject: [PATCH 034/105] fix gle private test (#12238) --- .../cloudbuildv2/resource_cloudbuildv2_connection_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mmv1/third_party/terraform/services/cloudbuildv2/resource_cloudbuildv2_connection_test.go b/mmv1/third_party/terraform/services/cloudbuildv2/resource_cloudbuildv2_connection_test.go index b68965626248..5ac1ba961f1e 100644 --- a/mmv1/third_party/terraform/services/cloudbuildv2/resource_cloudbuildv2_connection_test.go +++ b/mmv1/third_party/terraform/services/cloudbuildv2/resource_cloudbuildv2_connection_test.go @@ -740,11 +740,11 @@ resource "google_cloudbuildv2_connection" "primary" { gitlab_config { authorizer_credential { - user_token_secret_version = "projects/407304063574/secrets/gle-private-api/versions/1" + user_token_secret_version = "projects/407304063574/secrets/gle-private-api/versions/latest" } read_authorizer_credential { - user_token_secret_version = "projects/407304063574/secrets/gle-private-read-token/versions/1" + user_token_secret_version = "projects/407304063574/secrets/gle-private-read-token/versions/latest" } webhook_secret_secret_version = "projects/407304063574/secrets/gle-webhook-secret/versions/latest" @@ -754,7 +754,7 @@ resource "google_cloudbuildv2_connection" "primary" { service = "projects/407304063574/locations/us-west1/namespaces/private-conn/services/gitlab-private" } - ssl_ca = "-----BEGIN CERTIFICATE-----\nMIIDcTCCAlmgAwIBAgIUbxJ3jxaRf5IPcUiQWRPRqpLL4s4wDQYJKoZIhvcNAQEL\nBQAwTjELMAkGA1UEBhMCVVMxGzAZBgNVBAoMEkdvb2dsZSBDbG91ZCBCdWlsZDEi\nMCAGA1UEAwwZZ2xlLXVzLmdsZS11cy1wcml2YXRlLmNvbTAeFw0yMzEwMjAxNjQ3\nNDJaFw0yNDEwMTkxNjQ3NDJaME4xCzAJBgNVBAYTAlVTMRswGQYDVQQKDBJHb29n\nbGUgQ2xvdWQgQnVpbGQxIjAgBgNVBAMMGWdsZS11cy5nbGUtdXMtcHJpdmF0ZS5j\nb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDRE84wKcuzc+beQ323\nIsNVVOF1+WZ975LvXpIt8Mw1bcYeYUcvgBXSXAByHGMtef8OBb9BUvLOVZdT3Xow\nCUbhCiK3zQy29pCn0rsneIvzGUXQgQRXK/Zap1N/hif4E7CIgjuvCN0Mn6BfDV/H\nXFm6EV3YUJrRPBr1rZik7doaYYwaJshCSTBtZxXZdvsG/OBuAXbJ9GB0B62EiTBz\n5g6yRdATut+PbgfzaWlPsgL3TTH+HPNCMO+ULnFupfZwRCtV+dJng76QYGs8fmFo\ntiWeElcsU8W7aqmjOkKRWcFsHpxPNXp8GG+jsZrVAnMOR3QeRLvowysSQD99IrGH\nAhwlAgMBAAGjRzBFMCQGA1UdEQQdMBuCGWdsZS11cy5nbGUtdXMtcHJpdmF0ZS5j\nb20wHQYDVR0OBBYEFKCIp5BruT4fpeDFQ2bKgdUvpfbWMA0GCSqGSIb3DQEBCwUA\nA4IBAQAQ4pUQmmd7eNIu9MQGna9lHYRFL0/G3mrK6Dcfm2As9qdcRw3dph8/iute\nxKDdBsnt6jDHrsjN0Na7Eq0040oBJrxG/NtqGX0zHNdpAT61bQ6j9reAT+KOrHys\nDJXH2lPuFW183AU7mmvcbXTEwkKex1i+DNoEdGYUbBfnWWeuhGzFog+/f9mtjoHL\nplcmx0VWHBQ5KO9Aq4OR/86DSg5QRPk76W9k3cM2ShXMm3TmTBZ+taJFfjZo5jP+\n7PLt2z9grSvFSXh2jnMyAs2yP4c+WezOXZLijqROr378AGBaksQK0CP+CYjZRpn1\nvndr1njLbvSjIypwKgZROb4P6XVa\n-----END CERTIFICATE-----\n" + ssl_ca = "-----BEGIN CERTIFICATE-----\nMIIFbjCCA1agAwIBAgIUH+nsWsqagMW9Ld8E9J71yPLPpD8wDQYJKoZIhvcNAQEL\nBQAwJDEiMCAGA1UEAwwZZ2xlLXVzLmdsZS11cy1wcml2YXRlLmNvbTAeFw0yNDEw\nMzExNjQzMjBaFw0zNDEwMjkxNjQzMjBaMCQxIjAgBgNVBAMMGWdsZS11cy5nbGUt\ndXMtcHJpdmF0ZS5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDL\n+dUU8MHo+Eskx4SSnI1thRIiljgsyJSzSOplaD4lqahFnrG0cB0ovKpyRL4A+0wM\nzVW7W1Pfi8DiEOxxfNo7pEj+0zrzJHHqnzW9kApIlRmO1TBBJ7i9HaVamJ1Od01b\n2WI/pnKFEvNfLQSDQBulhkHZ2McyauDhb1DxefKnVX8ac6qhxtc4IzrezIQuJ18N\nDPtNLUDD4rtU4mIX4lx1yBIplrgypAo1HDbJOwW8OR76MtjAY7ek3K6UCyduQtwy\nmfZ23b3Eg69W10HVMVTy6m5NaGKi/TWy2MJ71hKUQ1+tWIPH5SL7FzYPKL4XXw5W\np61LhIiBAd2tgD41b2cQxhUbVifc1qHtnwNz/tE77M9ySH37rEUIlExzr3D3JV+f\nXjXEXUr9as8GRnS5zhD/opKe7wKbwpYMHhylK1h6XH/sBO7dBajf5xCvpZZBDzrK\nkpTqwHspT7p40WF9d8odjEk/xZKn5LdcDG2I+4U7SVS5e8ud41HUQxJwQx56lKfh\n2WB+zs7nSyMfspTj4doY1OADEC1VQCyGrwlbclKTKmUWrgwQdm38KxDzW5Juyjmm\nzvfsWIlSMdnes0qVVo38N3Jz8/MHCLD79R2veWgA2fbqS3+4h2dRkR7htjaVlJMJ\nt7SwFiG39ic3OZpo+wTkaHlG4CBnbFDueUsOW2wEpQIDAQABo4GXMIGUMB0GA1Ud\nDgQWBBTExgzH2gz9+rJHvlTFPO0AvG88azAfBgNVHSMEGDAWgBTExgzH2gz9+rJH\nvlTFPO0AvG88azAPBgNVHRMBAf8EBTADAQH/MEEGA1UdEQQ6MDiCGWdsZS11cy5n\nbGUtdXMtcHJpdmF0ZS5jb22CGyouZ2xlLXVzLmdsZS11cy1wcml2YXRlLmNvbTAN\nBgkqhkiG9w0BAQsFAAOCAgEAjkd1ZNoekoWrmozD+Ta1OM0zWhv04eqhP8aYzhbd\nXRS+GyF6ifMwfWg9HogkH22ZPT5GszaL5DacSyOUqZgJ905Q6g1EFPnaKmFVHHeC\nzZAhg5oedAzcakZpYwZDSiLuPgsQfwgRnqWIYR8JcIM5bKRZNGyOg8eZ8cKu23A2\nPavL4B3Ra1l93KllKm21rigIhLPIPLoEyxEg9c9oTJF92r0+aRdf2Ln853260Fqf\ncEUWoXhqMGvDv/YEbqDjGQ/Kh7ZWdlIWhcKFOA0gluF7oExjt/MgSitukgg3aaic\n/eXXOrZDNYH7Ve610NUuNlhub1M47Tp7EgjUJVWlsKK84T8ZcZq7Hn4BzioUr95d\nHao6u19HWA/ISM8bwzHaYxscFI4u6phEL0HJzLf4EysEmS0rAnLxyol0apNx6znR\nhXsqxnSexKhXoLqnK1Vuhcg8DsvobXHqg68EGZ7BZ3ycPYaHSWU8Xh3l1gtYkcQ6\nzxXsKIijlpVKuYJvGA3EOMoZu6+2MYF8Tgp3N4sKMvPhqBhsmgxOYF5OkAbGlsUP\nyCYWFDBFHmbhvUu5JpbKuID2CPkBi16EetemvMQ9PGlLq/0fO/BBNkn6TYn9Kvg8\nAyvuONz54uFEAIKPCcZIosa3ml+5/pt+tBhtVzHA6vMxn18IYaNpuTwSxi/+M10K\nRjw=\n-----END CERTIFICATE-----\n" } project = "%{project_name}" From 91659eeff4a0c254719a9b5cdc9e4a9e484df66e Mon Sep 17 00:00:00 2001 From: Sam Levenick Date: Mon, 11 Nov 2024 09:04:30 -0500 Subject: [PATCH 035/105] Add .0 to go.mod version (#12294) --- mmv1/go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mmv1/go.mod b/mmv1/go.mod index 8575738d4ffd..59f63f05ecff 100644 --- a/mmv1/go.mod +++ b/mmv1/go.mod @@ -1,6 +1,6 @@ module github.com/GoogleCloudPlatform/magic-modules/mmv1 -go 1.23 +go 1.23.0 require ( golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 From 12341a5530da29c545e86875ee54c8e8fa7b02dd Mon Sep 17 00:00:00 2001 From: Sam Levenick Date: Mon, 11 Nov 2024 12:30:11 -0500 Subject: [PATCH 036/105] Add status tag for tracking autogen-created resources (#12293) --- mmv1/api/resource.go | 4 ++++ mmv1/openapi_generate/parser.go | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/mmv1/api/resource.go b/mmv1/api/resource.go index c6f9ec5e84bb..771c780bb48b 100644 --- a/mmv1/api/resource.go +++ b/mmv1/api/resource.go @@ -330,6 +330,10 @@ type Resource struct { ApiResourceTypeKind string `yaml:"api_resource_type_kind,omitempty"` ImportPath string `yaml:"-"` + + // Tag autogen resources so that we can track them. In the future this will + // control if a resource is continuously generated from public OpenAPI docs + AutogenStatus string `yaml:"autogen_status"` } func (r *Resource) UnmarshalYAML(unmarshal func(any) error) error { diff --git a/mmv1/openapi_generate/parser.go b/mmv1/openapi_generate/parser.go index 23a8c91a057a..3c2a63344e89 100644 --- a/mmv1/openapi_generate/parser.go +++ b/mmv1/openapi_generate/parser.go @@ -17,6 +17,7 @@ package openapi_generate import ( "context" + "encoding/base64" "fmt" "os" "path" @@ -259,6 +260,11 @@ func buildResource(filePath, resourcePath, resourceName string, root *openapi3.T resource.Examples = []r.Examples{example} + resourceNameBytes := []byte(resourceName) + // Write the status as an encoded string to flag when a YAML file has been + // copy and pasted without actually using this tool + resource.AutogenStatus = base64.StdEncoding.EncodeToString(resourceNameBytes) + return resource } From 4e161c23a0f8b3d0b8e89be02377d7998920c479 Mon Sep 17 00:00:00 2001 From: hao-nan-li <100219545+hao-nan-li@users.noreply.github.com> Date: Mon, 11 Nov 2024 09:35:03 -0800 Subject: [PATCH 037/105] Remove gke_hub as part of the DCL endpoints (#12287) --- tpgtools/templates/provider_dcl_endpoints.go.tmpl | 1 - 1 file changed, 1 deletion(-) diff --git a/tpgtools/templates/provider_dcl_endpoints.go.tmpl b/tpgtools/templates/provider_dcl_endpoints.go.tmpl index 43acf324260d..59bbbc4df714 100644 --- a/tpgtools/templates/provider_dcl_endpoints.go.tmpl +++ b/tpgtools/templates/provider_dcl_endpoints.go.tmpl @@ -99,7 +99,6 @@ func ProviderDCLConfigure(d *schema.ResourceData, config *Config) interface{} { config.CloudResourceManagerBasePath = "https://cloudresourcemanager.googleapis.com/" config.EventarcBasePath = "https://eventarc.googleapis.com/v1/" config.FirebaserulesBasePath = "https://firebaserules.googleapis.com/v1/" - config.GKEHubFeatureBasePath = "https://gkehub.googleapis.com/v1beta1/" config.RecaptchaEnterpriseBasePath = "https://recaptchaenterprise.googleapis.com/v1/" return config From ffb8349dbe3757183959dcedf7621d9c7b66c9b8 Mon Sep 17 00:00:00 2001 From: Umair Idris Date: Mon, 11 Nov 2024 12:59:58 -0500 Subject: [PATCH 038/105] =?UTF-8?q?Add=20workforce=20identity=20federation?= =?UTF-8?q?=20config=20to=20secure=20source=20manager=20ins=E2=80=A6=20(#1?= =?UTF-8?q?1951)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../securesourcemanager/Instance.yaml | 23 +++++++++++++++++++ ...ance_workforce_identity_federation.tf.tmpl | 13 +++++++++++ 2 files changed, 36 insertions(+) create mode 100644 mmv1/templates/terraform/examples/secure_source_manager_instance_workforce_identity_federation.tf.tmpl diff --git a/mmv1/products/securesourcemanager/Instance.yaml b/mmv1/products/securesourcemanager/Instance.yaml index 43b033939acc..3681f7765c1c 100644 --- a/mmv1/products/securesourcemanager/Instance.yaml +++ b/mmv1/products/securesourcemanager/Instance.yaml @@ -133,6 +133,16 @@ examples: oics_vars_overrides: 'prevent_destroy': 'false' external_providers: ["time"] + - name: 'secure_source_manager_instance_workforce_identity_federation' + primary_resource_id: 'default' + primary_resource_name: 'fmt.Sprintf("tf-test-my-instance%s", context["random_suffix"])' + vars: + instance_id: 'my-instance' + prevent_destroy: 'true' + test_vars_overrides: + 'prevent_destroy': 'false' + oics_vars_overrides: + 'prevent_destroy': 'false' parameters: - name: 'location' type: String @@ -244,3 +254,16 @@ properties: description: | Service Attachment for SSH, resource is in the format of `projects/{project}/regions/{region}/serviceAttachments/{service_attachment}`. output: true + - name: 'workforceIdentityFederationConfig' + type: NestedObject + description: | + Configuration for Workforce Identity Federation to support third party identity provider. + If unset, defaults to the Google OIDC IdP. + immutable: true + properties: + - name: 'enabled' + type: Boolean + description: | + 'Whether Workforce Identity Federation is enabled.' + required: true + immutable: true diff --git a/mmv1/templates/terraform/examples/secure_source_manager_instance_workforce_identity_federation.tf.tmpl b/mmv1/templates/terraform/examples/secure_source_manager_instance_workforce_identity_federation.tf.tmpl new file mode 100644 index 000000000000..a1702f85d64a --- /dev/null +++ b/mmv1/templates/terraform/examples/secure_source_manager_instance_workforce_identity_federation.tf.tmpl @@ -0,0 +1,13 @@ +resource "google_secure_source_manager_instance" "{{$.PrimaryResourceId}}" { + location = "us-central1" + instance_id = "{{index $.Vars "instance_id"}}" + + workforce_identity_federation_config { + enabled = true + } + + # Prevent accidental deletions. + lifecycle { + prevent_destroy = "{{index $.Vars "prevent_destroy"}}" + } +} From 1429328ff8391856a2cb8e427303ed65a1cbe85d Mon Sep 17 00:00:00 2001 From: Ryan Oaks Date: Mon, 11 Nov 2024 13:27:26 -0500 Subject: [PATCH 039/105] Serialize ACM IAM tests (#12284) Co-authored-by: Nick Elliot --- ...ccess_context_manager_access_policy_iam_test.go | 14 +++++++------- ...cess_context_manager_access_policy_test.go.tmpl | 3 +++ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/mmv1/third_party/terraform/services/accesscontextmanager/resource_access_context_manager_access_policy_iam_test.go b/mmv1/third_party/terraform/services/accesscontextmanager/resource_access_context_manager_access_policy_iam_test.go index ba5c68df2dfd..fd8681f00991 100644 --- a/mmv1/third_party/terraform/services/accesscontextmanager/resource_access_context_manager_access_policy_iam_test.go +++ b/mmv1/third_party/terraform/services/accesscontextmanager/resource_access_context_manager_access_policy_iam_test.go @@ -9,7 +9,7 @@ import ( "github.com/hashicorp/terraform-provider-google/google/envvar" ) -func TestAccAccessContextManagerAccessPolicyIamBinding(t *testing.T) { +func testAccAccessContextManagerAccessPolicyIamBinding(t *testing.T) { acctest.SkipIfVcr(t) org := envvar.GetTestOrgFromEnv(t) @@ -32,7 +32,7 @@ func TestAccAccessContextManagerAccessPolicyIamBinding(t *testing.T) { }) } -func TestAccAccessContextManagerAccessPolicyIamMember(t *testing.T) { +func testAccAccessContextManagerAccessPolicyIamMember(t *testing.T) { acctest.SkipIfVcr(t) org := envvar.GetTestOrgFromEnv(t) @@ -45,7 +45,7 @@ func TestAccAccessContextManagerAccessPolicyIamMember(t *testing.T) { Steps: []resource.TestStep{ { // Test IAM Binding creation - Config: testAccAccessContextManagerAccessPolicyIamMember(policy, account, role), + Config: testAccAccessContextManagerAccessPolicyIamMember_basic(policy, account, role), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr( "google_access_context_manager_access_policy_iam_member.member", "role", role), @@ -57,7 +57,7 @@ func TestAccAccessContextManagerAccessPolicyIamMember(t *testing.T) { }) } -func TestAccAccessContextManagerAccessPolicyIamPolicy(t *testing.T) { +func testAccAccessContextManagerAccessPolicyIamPolicy(t *testing.T) { acctest.SkipIfVcr(t) org := envvar.GetTestOrgFromEnv(t) @@ -70,7 +70,7 @@ func TestAccAccessContextManagerAccessPolicyIamPolicy(t *testing.T) { Steps: []resource.TestStep{ { // Test IAM Binding creation - Config: testAccAccessContextManagerAccessPolicyIamPolicy(policy, account, role), + Config: testAccAccessContextManagerAccessPolicyIamPolicy_basic(policy, account, role), }, }, }) @@ -93,7 +93,7 @@ resource google_access_context_manager_access_policy_iam_binding binding { `, account, role) } -func testAccAccessContextManagerAccessPolicyIamMember(policy, account, role string) string { +func testAccAccessContextManagerAccessPolicyIamMember_basic(policy, account, role string) string { return fmt.Sprintf(policy+` resource "google_service_account" "test-account" { account_id = "%s" @@ -109,7 +109,7 @@ resource google_access_context_manager_access_policy_iam_member member { `, account, role) } -func testAccAccessContextManagerAccessPolicyIamPolicy(policy, account, role string) string { +func testAccAccessContextManagerAccessPolicyIamPolicy_basic(policy, account, role string) string { return fmt.Sprintf(policy+` resource "google_service_account" "test-account" { account_id = "%s" diff --git a/mmv1/third_party/terraform/services/accesscontextmanager/resource_access_context_manager_access_policy_test.go.tmpl b/mmv1/third_party/terraform/services/accesscontextmanager/resource_access_context_manager_access_policy_test.go.tmpl index 33fa97849f1d..780b459d8533 100644 --- a/mmv1/third_party/terraform/services/accesscontextmanager/resource_access_context_manager_access_policy_test.go.tmpl +++ b/mmv1/third_party/terraform/services/accesscontextmanager/resource_access_context_manager_access_policy_test.go.tmpl @@ -18,6 +18,9 @@ func TestAccAccessContextManager(t *testing.T) { testCases := map[string]func(t *testing.T){ "access_policy": testAccAccessContextManagerAccessPolicy_basicTest, "access_policy_scoped": testAccAccessContextManagerAccessPolicy_scopedTest, + "access_policy_iam_binding": testAccAccessContextManagerAccessPolicyIamBinding, + "access_policy_iam_member": testAccAccessContextManagerAccessPolicyIamMember, + "access_policy_iam_policy": testAccAccessContextManagerAccessPolicyIamPolicy, "service_perimeter": testAccAccessContextManagerServicePerimeter_basicTest, "service_perimeter_update": testAccAccessContextManagerServicePerimeter_updateTest, "service_perimeter_resource": testAccAccessContextManagerServicePerimeterResource_basicTest, From e2eeb1aee0e504a837abc8bb123c813866d42a11 Mon Sep 17 00:00:00 2001 From: Will Yardley Date: Mon, 11 Nov 2024 11:05:32 -0800 Subject: [PATCH 040/105] Updated remaining tag key / value examples (#12276) --- ...pute_region_instance_template_test.go.tmpl | 4 +- ...a_loss_prevention_discovery_config_test.go | 2 +- ...le_tags_location_tag_binding.html.markdown | 48 +++++++++---------- 3 files changed, 27 insertions(+), 27 deletions(-) diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_template_test.go.tmpl b/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_template_test.go.tmpl index 4e49ac40ef46..0d6ce93175b3 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_template_test.go.tmpl +++ b/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_template_test.go.tmpl @@ -3860,12 +3860,12 @@ resource "google_compute_region_instance_template" "foobar" { boot = true resource_manager_tags = { - "tagKeys/${google_tags_tag_key.key.name}" = "tagValues/${google_tags_tag_value.value.name}" + (google_tags_tag_key.key.id) = google_tags_tag_value.value.id } } resource_manager_tags = { - "tagKeys/${google_tags_tag_key.key.name}" = "tagValues/${google_tags_tag_value.value.name}" + (google_tags_tag_key.key.id) = google_tags_tag_value.value.id } network_interface { diff --git a/mmv1/third_party/terraform/services/datalossprevention/resource_data_loss_prevention_discovery_config_test.go b/mmv1/third_party/terraform/services/datalossprevention/resource_data_loss_prevention_discovery_config_test.go index 78cd55847b1c..6251c9e3a41b 100644 --- a/mmv1/third_party/terraform/services/datalossprevention/resource_data_loss_prevention_discovery_config_test.go +++ b/mmv1/third_party/terraform/services/datalossprevention/resource_data_loss_prevention_discovery_config_test.go @@ -521,7 +521,7 @@ resource "google_tags_tag_key" "tag_key" { } resource "google_tags_tag_value" "tag_value" { - parent = "tagKeys/${google_tags_tag_key.tag_key.name}" + parent = google_tags_tag_key.tag_key.id short_name = "prod" } diff --git a/mmv1/third_party/terraform/website/docs/r/google_tags_location_tag_binding.html.markdown b/mmv1/third_party/terraform/website/docs/r/google_tags_location_tag_binding.html.markdown index 384cf46cc440..39904ac4b598 100644 --- a/mmv1/third_party/terraform/website/docs/r/google_tags_location_tag_binding.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/google_tags_location_tag_binding.html.markdown @@ -20,27 +20,27 @@ To bind a tag to a Cloud Run service: ```hcl resource "google_project" "project" { - project_id = "project_id" - name = "project_id" - org_id = "123456789" + project_id = "project_id" + name = "project_id" + org_id = "123456789" } resource "google_tags_tag_key" "key" { - parent = "organizations/123456789" - short_name = "keyname" - description = "For keyname resources." + parent = "organizations/123456789" + short_name = "keyname" + description = "For keyname resources." } resource "google_tags_tag_value" "value" { - parent = "tagKeys/${google_tags_tag_key.key.name}" - short_name = "valuename" - description = "For valuename resources." + parent = google_tags_tag_key.key.id + short_name = "valuename" + description = "For valuename resources." } resource "google_tags_location_tag_binding" "binding" { - parent = "//run.googleapis.com/projects/${data.google_project.project.number}/locations/${google_cloud_run_service.default.location}/services/${google_cloud_run_service.default.name}" - tag_value = "tagValues/${google_tags_tag_value.value.name}" - location = "us-central1" + parent = "//run.googleapis.com/projects/${data.google_project.project.number}/locations/${google_cloud_run_service.default.location}/services/${google_cloud_run_service.default.name}" + tag_value = google_tags_tag_value.value.id + location = "us-central1" } ``` @@ -48,27 +48,27 @@ resource "google_tags_location_tag_binding" "binding" { ```hcl resource "google_project" "project" { - project_id = "project_id" - name = "project_id" - org_id = "123456789" + project_id = "project_id" + name = "project_id" + org_id = "123456789" } resource "google_tags_tag_key" "key" { - parent = "organizations/123456789" - short_name = "keyname" - description = "For keyname resources." + parent = "organizations/123456789" + short_name = "keyname" + description = "For keyname resources." } resource "google_tags_tag_value" "value" { - parent = "tagKeys/${google_tags_tag_key.key.name}" - short_name = "valuename" - description = "For valuename resources." + parent = google_tags_tag_key.key.id + short_name = "valuename" + description = "For valuename resources." } resource "google_tags_location_tag_binding" "binding" { - parent = "//compute.googleapis.com/projects/${google_project.project.number}/zones/us-central1-a/instances/${google_compute_instance.instance.instance_id}" - tag_value = "tagValues/${google_tags_tag_value.value.name}" - location = "us-central1-a" + parent = "//compute.googleapis.com/projects/${google_project.project.number}/zones/us-central1-a/instances/${google_compute_instance.instance.instance_id}" + tag_value = google_tags_tag_value.value.id + location = "us-central1-a" } ``` From 5fc717a10c0cdb255a72089e8e925190feac5853 Mon Sep 17 00:00:00 2001 From: paridhishah18 <166548459+paridhishah18@users.noreply.github.com> Date: Mon, 11 Nov 2024 11:37:01 -0800 Subject: [PATCH 041/105] fix TestAccCloudRunService_cloudRunServiceMulticontainerExample (#12299) --- .../examples/cloud_run_service_multicontainer.tf.tmpl | 6 ------ 1 file changed, 6 deletions(-) diff --git a/mmv1/templates/terraform/examples/cloud_run_service_multicontainer.tf.tmpl b/mmv1/templates/terraform/examples/cloud_run_service_multicontainer.tf.tmpl index b7c4f9b9196a..018457894208 100644 --- a/mmv1/templates/terraform/examples/cloud_run_service_multicontainer.tf.tmpl +++ b/mmv1/templates/terraform/examples/cloud_run_service_multicontainer.tf.tmpl @@ -3,12 +3,6 @@ resource "google_cloud_run_service" "{{$.PrimaryResourceId}}" { location = "us-central1" provider = google-beta - metadata { - annotations = { - "run.googleapis.com/launch-stage" = "BETA" - } - } - template { metadata { annotations = { From 0616a35f4dddbca1857fbc0c1330bc5ea93cc7e5 Mon Sep 17 00:00:00 2001 From: Charles Leon Date: Mon, 11 Nov 2024 13:23:53 -0800 Subject: [PATCH 042/105] Use regular string sorting for custom access context manager ingress and egress flatteners (#12288) Co-authored-by: Charlesleonius --- ...egress_policy_resources_custom_flatten.go.tmpl | 15 ++++++++------- ...ngress_policy_resources_custom_flatten.go.tmpl | 15 ++++++++------- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/mmv1/templates/terraform/custom_flatten/accesscontextmanager_egress_policy_resources_custom_flatten.go.tmpl b/mmv1/templates/terraform/custom_flatten/accesscontextmanager_egress_policy_resources_custom_flatten.go.tmpl index d8508834b044..663c3a79c041 100644 --- a/mmv1/templates/terraform/custom_flatten/accesscontextmanager_egress_policy_resources_custom_flatten.go.tmpl +++ b/mmv1/templates/terraform/custom_flatten/accesscontextmanager_egress_policy_resources_custom_flatten.go.tmpl @@ -1,25 +1,26 @@ func flatten{{$.GetPrefix}}{{$.TitlelizeProperty}}(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { rawConfigValue := d.Get("egress_to.0.resources") - // Convert config value to []string configValue, err := tpgresource.InterfaceSliceToStringSlice(rawConfigValue) if err != nil { log.Printf("[ERROR] Failed to convert config value: %s", err) return v } + sortedConfigValue := append([]string{}, configValue...) + sort.Strings(sortedConfigValue) // Convert v to []string - apiStringValue, err := tpgresource.InterfaceSliceToStringSlice(v) + apiValue, err := tpgresource.InterfaceSliceToStringSlice(v) if err != nil { log.Printf("[ERROR] Failed to convert API value: %s", err) return v } + sortedApiValue := append([]string{}, apiValue...) + sort.Strings(sortedApiValue) - sortedStrings, err := tpgresource.SortStringsByConfigOrder(configValue, apiStringValue) - if err != nil { - log.Printf("[ERROR] Could not sort API response value: %s", err) - return v + if (slices.Equal(sortedApiValue, sortedConfigValue)) { + return configValue } - return sortedStrings + return apiValue } \ No newline at end of file diff --git a/mmv1/templates/terraform/custom_flatten/accesscontextmanager_ingress_policy_resources_custom_flatten.go.tmpl b/mmv1/templates/terraform/custom_flatten/accesscontextmanager_ingress_policy_resources_custom_flatten.go.tmpl index b7c1f0f7d499..6937ef10b1fc 100644 --- a/mmv1/templates/terraform/custom_flatten/accesscontextmanager_ingress_policy_resources_custom_flatten.go.tmpl +++ b/mmv1/templates/terraform/custom_flatten/accesscontextmanager_ingress_policy_resources_custom_flatten.go.tmpl @@ -1,25 +1,26 @@ func flatten{{$.GetPrefix}}{{$.TitlelizeProperty}}(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { rawConfigValue := d.Get("ingress_to.0.resources") - // Convert config value to []string configValue, err := tpgresource.InterfaceSliceToStringSlice(rawConfigValue) if err != nil { log.Printf("[ERROR] Failed to convert config value: %s", err) return v } + sortedConfigValue := append([]string{}, configValue...) + sort.Strings(sortedConfigValue) // Convert v to []string - apiStringValue, err := tpgresource.InterfaceSliceToStringSlice(v) + apiValue, err := tpgresource.InterfaceSliceToStringSlice(v) if err != nil { log.Printf("[ERROR] Failed to convert API value: %s", err) return v } + sortedApiValue := append([]string{}, apiValue...) + sort.Strings(sortedApiValue) - sortedStrings, err := tpgresource.SortStringsByConfigOrder(configValue, apiStringValue) - if err != nil { - log.Printf("[ERROR] Could not sort API response value: %s", err) - return v + if (slices.Equal(sortedApiValue, sortedConfigValue)) { + return configValue } - return sortedStrings + return apiValue } \ No newline at end of file From a5e30bb31f73651675f353913e40fa26a6f4ff19 Mon Sep 17 00:00:00 2001 From: coder-221 <185867912+coder-221@users.noreply.github.com> Date: Mon, 11 Nov 2024 14:16:48 -0800 Subject: [PATCH 043/105] Add datasource for ACM access policies (#12272) Co-authored-by: Riley Karson --- .../provider/provider_mmv1_resources.go.tmpl | 1 + ...ce_access_context_manager_access_policy.go | 133 ++++++++++++++++++ ...cess_context_manager_access_policy_test.go | 79 +++++++++++ ...ontext_manager_access_policy.html.markdown | 40 ++++++ 4 files changed, 253 insertions(+) create mode 100644 mmv1/third_party/terraform/services/accesscontextmanager/data_source_access_context_manager_access_policy.go create mode 100644 mmv1/third_party/terraform/services/accesscontextmanager/data_source_access_context_manager_access_policy_test.go create mode 100644 mmv1/third_party/terraform/website/docs/d/access_context_manager_access_policy.html.markdown diff --git a/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.tmpl b/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.tmpl index b208877c2f2f..9ac625153e69 100644 --- a/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.tmpl +++ b/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.tmpl @@ -23,6 +23,7 @@ var handwrittenDatasources = map[string]*schema.Resource{ "google_access_approval_folder_service_account": accessapproval.DataSourceAccessApprovalFolderServiceAccount(), "google_access_approval_organization_service_account": accessapproval.DataSourceAccessApprovalOrganizationServiceAccount(), "google_access_approval_project_service_account": accessapproval.DataSourceAccessApprovalProjectServiceAccount(), + "google_access_context_manager_access_policy": accesscontextmanager.DataSourceAccessContextManagerAccessPolicy(), "google_active_folder": resourcemanager.DataSourceGoogleActiveFolder(), "google_alloydb_locations": alloydb.DataSourceAlloydbLocations(), "google_alloydb_supported_database_flags": alloydb.DataSourceAlloydbSupportedDatabaseFlags(), diff --git a/mmv1/third_party/terraform/services/accesscontextmanager/data_source_access_context_manager_access_policy.go b/mmv1/third_party/terraform/services/accesscontextmanager/data_source_access_context_manager_access_policy.go new file mode 100644 index 000000000000..6b412bbf5f97 --- /dev/null +++ b/mmv1/third_party/terraform/services/accesscontextmanager/data_source_access_context_manager_access_policy.go @@ -0,0 +1,133 @@ +package accesscontextmanager + +import ( + "fmt" + "slices" + "strings" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-provider-google/google/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" +) + +func DataSourceAccessContextManagerAccessPolicy() *schema.Resource { + return &schema.Resource{ + Read: dataSourceAccessContextManagerAccessPolicyRead, + Schema: map[string]*schema.Schema{ + "parent": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "scopes": { + Type: schema.TypeList, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + Optional: true, + }, + "title": { + Type: schema.TypeString, + Computed: true, + }, + "name": { + Type: schema.TypeString, + Computed: true, + }, + }, + } +} + +func dataSourceAccessContextManagerAccessPolicyRead(d *schema.ResourceData, meta interface{}) error { + config := meta.(*transport_tpg.Config) + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + if err != nil { + return err + } + + url, err := tpgresource.ReplaceVars(d, config, "{{AccessContextManagerBasePath}}accessPolicies?parent={{parent}}") + if err != nil { + return err + } + + billingProject := "" + + // err == nil indicates that the billing_project value was found + if bp, err := tpgresource.GetBillingProject(d, config); err == nil { + billingProject = bp + } + + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "GET", + Project: billingProject, + RawURL: url, + UserAgent: userAgent, + }) + + if err != nil { + return transport_tpg.HandleDataSourceNotFoundError(err, d, fmt.Sprintf("AccessContextManagerAccessPolicy %q", d.Id()), url) + } + + if res == nil { + return fmt.Errorf("Error fetching policies: %s", err) + } + + policies, err := parse_policies_response(res) + if err != nil { + fmt.Errorf("Error parsing list policies response: %s", err) + } + + // Find the matching policy in the list of policies response. Both the parent and scopes + // should match + for _, fetched_policy := range policies { + scopes_match := compare_scopes(d.Get("scopes").([]interface{}), fetched_policy.Scopes) + if fetched_policy.Parent == d.Get("parent").(string) && scopes_match { + name_without_prefix := strings.Split(fetched_policy.Name, "accessPolicies/")[1] + d.SetId(name_without_prefix) + if err := d.Set("name", name_without_prefix); err != nil { + return fmt.Errorf("Error setting policy name: %s", err) + } + + if err := d.Set("title", fetched_policy.Title); err != nil { + return fmt.Errorf("Error setting policy title: %s", err) + } + + return nil + } + } + + return nil +} + +func parse_policies_response(res map[string]interface{}) ([]AccessPolicy, error) { + var policies []AccessPolicy + for _, res_policy := range res["accessPolicies"].([]interface{}) { + parsed_policy := &AccessPolicy{} + + err := tpgresource.Convert(res_policy, parsed_policy) + if err != nil { + return nil, err + } + + policies = append(policies, *parsed_policy) + } + return policies, nil +} + +func compare_scopes(config_scopes []interface{}, policy_scopes []string) bool { + // converts []interface{} to []string + var config_scopes_slice []string + for _, scope := range config_scopes { + config_scopes_slice = append(config_scopes_slice, scope.(string)) + } + + return slices.Equal(config_scopes_slice, policy_scopes) +} + +type AccessPolicy struct { + Name string `json:"name"` + Title string `json:"title"` + Parent string `json:"parent"` + Scopes []string `json:"scopes"` +} diff --git a/mmv1/third_party/terraform/services/accesscontextmanager/data_source_access_context_manager_access_policy_test.go b/mmv1/third_party/terraform/services/accesscontextmanager/data_source_access_context_manager_access_policy_test.go new file mode 100644 index 000000000000..daf517c560bb --- /dev/null +++ b/mmv1/third_party/terraform/services/accesscontextmanager/data_source_access_context_manager_access_policy_test.go @@ -0,0 +1,79 @@ +package accesscontextmanager_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + + "github.com/hashicorp/terraform-provider-google/google/acctest" + "github.com/hashicorp/terraform-provider-google/google/envvar" +) + +func TestAccDataSourceAccessContextManagerServicePerimeter_basicTest(t *testing.T) { + + org := envvar.GetTestOrgFromEnv(t) + policyTitle := "my title" + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Steps: []resource.TestStep{ + { + Config: testAccAccessContextManagerServicePerimeterDataSource_basic(org, policyTitle), + Check: resource.ComposeTestCheckFunc( + acctest.CheckDataSourceStateMatchesResourceState("data.google_access_context_manager_access_policy.policy", "google_access_context_manager_access_policy.policy"), + ), + }, + }, + }) +} + +func testAccAccessContextManagerServicePerimeterDataSource_basic(org, policyTitle string) string { + return acctest.Nprintf(` +resource "google_access_context_manager_access_policy" "policy" { + parent = "organizations/%{org}" + title = "%{policyTitle}" +} + +data "google_access_context_manager_access_policy" "policy" { + parent = "organizations/%{org}" + depends_on = [ google_access_context_manager_access_policy.policy ] +} +`, map[string]interface{}{"org": org, "policyTitle": policyTitle}) +} + +func TestAccDataSourceAccessContextManagerServicePerimeter_scopedPolicyTest(t *testing.T) { + + org := envvar.GetTestOrgFromEnv(t) + project := envvar.GetTestProjectNumberFromEnv() + policyTitle := "my title" + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Steps: []resource.TestStep{ + { + Config: testAccAccessContextManagerServicePerimeterDataSource_scopedPolicy(org, project, policyTitle), + Check: resource.ComposeTestCheckFunc( + acctest.CheckDataSourceStateMatchesResourceState("data.google_access_context_manager_access_policy.policy", "google_access_context_manager_access_policy.policy"), + ), + }, + }, + }) +} + +func testAccAccessContextManagerServicePerimeterDataSource_scopedPolicy(org, project, policyTitle string) string { + return acctest.Nprintf(` +resource "google_access_context_manager_access_policy" "policy" { + parent = "organizations/%{org}" + title = "%{policyTitle}" + scopes = ["projects/%{project}"] +} + +data "google_access_context_manager_access_policy" "policy" { + parent = "organizations/%{org}" + scopes = ["projects/%{project}"] + depends_on = [ google_access_context_manager_access_policy.policy ] +} +`, map[string]interface{}{"org": org, "policyTitle": policyTitle, "project": project}) +} diff --git a/mmv1/third_party/terraform/website/docs/d/access_context_manager_access_policy.html.markdown b/mmv1/third_party/terraform/website/docs/d/access_context_manager_access_policy.html.markdown new file mode 100644 index 000000000000..ba9e0c430362 --- /dev/null +++ b/mmv1/third_party/terraform/website/docs/d/access_context_manager_access_policy.html.markdown @@ -0,0 +1,40 @@ +--- +subcategory: "Access Context Manager (VPC Service Controls)" +description: |- + Fetches an AccessPolicy from Access Context Manager. +--- + +# google_access_context_manager_access_policy + +Get information about an Access Context Manager AccessPolicy. + +## Example Usage + +```tf +data "google_access_context_manager_access_policy" "policy-org" { + parent = "organizations/1234567" +} + +data "google_access_context_manager_access_policy" "policy-scoped" { + parent = "organizations/1234567" + scopes = ["projects/1234567"] +} + +``` + +## Argument Reference + +The following arguments are supported: + +* `parent` - (Required) The parent of this AccessPolicy in the Cloud Resource Hierarchy. Format: `organizations/{{organization_id}}` + +* `scopes` - (Optional) Folder or project on which this policy is applicable. Format: `folders/{{folder_id}}` or `projects/{{project_number}}` + + +## Attributes Reference + +In addition to the arguments listed above, the following attributes are exported: + +* `name` - Resource name of the AccessPolicy. + +* `title` - Human readable title. Does not affect behavior. From aebe93555584da9fb0d78672e4f2e74ccf230155 Mon Sep 17 00:00:00 2001 From: derekchu-google Date: Mon, 11 Nov 2024 15:48:34 -0800 Subject: [PATCH 044/105] add new resource iam_folders_policy_binding. addresses hashicorp/terraform-provider-google/issues/20198 (#12265) --- mmv1/products/iam3/FoldersPolicyBinding.yaml | 190 ++++++++++++++++++ .../iam_folders_policy_binding.tf.tmpl | 33 +++ .../terraform/post_delete/sleep.go.tmpl | 3 + ...ce_iam_folders_policy_binding_test.go.tmpl | 134 ++++++++++++ 4 files changed, 360 insertions(+) create mode 100644 mmv1/products/iam3/FoldersPolicyBinding.yaml create mode 100644 mmv1/templates/terraform/examples/iam_folders_policy_binding.tf.tmpl create mode 100644 mmv1/templates/terraform/post_delete/sleep.go.tmpl create mode 100644 mmv1/third_party/terraform/services/iam3/resource_iam_folders_policy_binding_test.go.tmpl diff --git a/mmv1/products/iam3/FoldersPolicyBinding.yaml b/mmv1/products/iam3/FoldersPolicyBinding.yaml new file mode 100644 index 000000000000..f4bd018dbada --- /dev/null +++ b/mmv1/products/iam3/FoldersPolicyBinding.yaml @@ -0,0 +1,190 @@ +# Copyright 2024 Google Inc. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- +name: 'FoldersPolicyBinding' +description: A policy binding to a folder +references: + guides: + 'Apply a policy binding': 'https://cloud.google.com/iam/docs/principal-access-boundary-policies-create#create_binding' + api: 'https://cloud.google.com/iam/docs/reference/rest/v3beta/folders.locations.policyBindings' +min_version: 'beta' +id_format: 'folders/{{folder}}/locations/{{location}}/policyBindings/{{policy_binding_id}}' +base_url: 'folders/{{folder}}/locations/{{location}}/policyBindings' +self_link: 'folders/{{folder}}/locations/{{location}}/policyBindings/{{policy_binding_id}}' +create_url: 'folders/{{folder}}/locations/{{location}}/policyBindings?policyBindingId={{policy_binding_id}}' +update_verb: 'PATCH' +update_mask: true +import_format: + - 'folders/{{folder}}/locations/{{location}}/policyBindings/{{policy_binding_id}}' +timeouts: + insert_minutes: 20 + update_minutes: 20 + delete_minutes: 20 +custom_code: + post_delete: 'templates/terraform/post_delete/sleep.go.tmpl' +autogen_async: true +async: + actions: ['create', 'delete', 'update'] + type: 'OpAsync' + operation: + base_url: '{{op_id}}' + path: 'name' + wait_ms: 1000 + result: + path: 'response' + resource_inside_response: true + error: + path: 'error' + message: 'message' +examples: + - name: 'iam_folders_policy_binding' + min_version: 'beta' + primary_resource_id: 'my-folder-binding' + test_env_vars: + org_id: 'ORG_ID' + vars: + pab_policy_id: 'my-pab-policy' + display_name: 'test folder binding' + folder_binding_id: 'test-folder-binding' + folder_name: 'test folder' + external_providers: ["time"] +parameters: + - name: 'folder' + type: String + description: | + The parent folder for the PolicyBinding. + url_param_only: true + required: true + immutable: true + - name: 'location' + type: String + description: | + The location of the PolicyBinding. + url_param_only: true + required: true + immutable: true + - name: 'policyBindingId' + type: String + description: | + The Policy Binding ID. + url_param_only: true + required: true + immutable: true +properties: + - name: 'name' + type: String + description: | + The name of the policy binding in the format `{binding_parent/locations/{location}/policyBindings/{policy_binding_id}` + output: true + - name: 'uid' + type: String + description: | + Output only. The globally unique ID of the policy binding. Assigned when the policy binding is created. + output: true + - name: 'etag' + type: String + description: | + Optional. The etag for the policy binding. If this is provided on update, it must match the server's etag. + output: true + - name: 'displayName' + type: String + description: | + Optional. The description of the policy binding. Must be less than or equal to 63 characters. + - name: 'annotations' + type: KeyValueAnnotations + description: | + Optional. User defined annotations. See https://google.aip.dev/148#annotations for more details such as format and size limitations + - name: 'target' + type: NestedObject + description: | + Target is the full resource name of the resource to which the policy will be bound. Immutable once set. + required: true + properties: + - name: 'principalSet' + type: String + description: | + Required. Immutable. The resource name of the policy to be bound. + The binding parent and policy must belong to the same Organization (or Project). + immutable: true + - name: 'policyKind' + type: String + description: | + Immutable. The kind of the policy to attach in this binding. This + field must be one of the following: - Left empty (will be automatically set + to the policy kind) - The input policy kind Possible values: POLICY_KIND_UNSPECIFIED PRINCIPAL_ACCESS_BOUNDARY ACCESS + immutable: true + - name: 'policy' + type: String + description: | + Required. Immutable. The resource name of the policy to be bound. The binding parent and policy must belong to the same Organization (or Project). + required: true + immutable: true + - name: 'policyUid' + type: String + description: | + Output only. The globally unique ID of the policy to be bound. + output: true + - name: 'condition' + type: NestedObject + description: | + Represents a textual expression in the Common Expression Language + (CEL) syntax. CEL is a C-like expression language. The syntax and semantics of + CEL are documented at https://github.com/google/cel-spec. + Example (Comparison): + title: \"Summary size limit\" + description: \"Determines if a summary is less than 100 chars\" + expression: \"document.summary.size() < 100\" + Example + (Equality): + title: \"Requestor is owner\" + description: \"Determines if requestor is the document owner\" + expression: \"document.owner == request.auth.claims.email\" Example + (Logic): + title: \"Public documents\" + description: \"Determine whether the document should be publicly visible\" + expression: \"document.type != 'private' && document.type != 'internal'\" + Example (Data Manipulation): + title: \"Notification string\" + description: \"Create a notification string with a timestamp.\" + expression: \"'New message received at ' + string(document.create_time)\" + The exact variables and functions that may be referenced within an expression are + determined by the service that evaluates it. See the service documentation for + additional information. + properties: + - name: 'expression' + type: String + description: | + Textual representation of an expression in Common Expression Language syntax. + - name: 'title' + type: String + description: | + Optional. Title for the expression, i.e. a short string describing its purpose. This can be used e.g. in UIs which allow to enter the expression. + - name: 'description' + type: String + description: | + Optional. Description of the expression. This is a longer text which describes the expression, e.g. when hovered over it in a UI. + - name: 'location' + type: String + description: | + Optional. String indicating the location of the expression for error reporting, e.g. a file name and a position in the file. + - name: 'createTime' + type: String + description: | + Output only. The time when the policy binding was created. + output: true + - name: 'updateTime' + type: String + description: | + Output only. The time when the policy binding was most recently updated. + output: true diff --git a/mmv1/templates/terraform/examples/iam_folders_policy_binding.tf.tmpl b/mmv1/templates/terraform/examples/iam_folders_policy_binding.tf.tmpl new file mode 100644 index 000000000000..499a0377014b --- /dev/null +++ b/mmv1/templates/terraform/examples/iam_folders_policy_binding.tf.tmpl @@ -0,0 +1,33 @@ +resource "google_iam_principal_access_boundary_policy" "pab_policy" { + provider = google-beta + organization = "{{index $.TestEnvVars "org_id"}}" + location = "global" + display_name = "{{index $.Vars "display_name"}}" + principal_access_boundary_policy_id = "{{index $.Vars "pab_policy_id"}}" +} + +resource "google_folder" "folder" { + provider = google-beta + display_name = "{{index $.Vars "folder_name"}}" + parent = "organizations/{{index $.TestEnvVars "org_id"}}" + deletion_protection = false +} + +resource "time_sleep" "wait_120s" { + depends_on = [google_folder.folder] + create_duration = "120s" +} + +resource "google_iam_folders_policy_binding" "{{$.PrimaryResourceId}}" { + provider = google-beta + folder = google_folder.folder.folder_id + location = "global" + display_name = "{{index $.Vars "display_name"}}" + policy_kind = "PRINCIPAL_ACCESS_BOUNDARY" + policy_binding_id = "{{index $.Vars "folder_binding_id"}}" + policy = "organizations/{{index $.TestEnvVars "org_id"}}/locations/global/principalAccessBoundaryPolicies/${google_iam_principal_access_boundary_policy.pab_policy.principal_access_boundary_policy_id}" + target { + principal_set = "//cloudresourcemanager.googleapis.com/folders/${google_folder.folder.folder_id}" + } + depends_on = [time_sleep.wait_120s] +} diff --git a/mmv1/templates/terraform/post_delete/sleep.go.tmpl b/mmv1/templates/terraform/post_delete/sleep.go.tmpl new file mode 100644 index 000000000000..c9b44c91ff05 --- /dev/null +++ b/mmv1/templates/terraform/post_delete/sleep.go.tmpl @@ -0,0 +1,3 @@ +// This is useful if the resource in question doesn't have a perfectly consistent API +// That is, if the deletion of a dependent resource has not propagated. +time.Sleep(5 * time.Second) \ No newline at end of file diff --git a/mmv1/third_party/terraform/services/iam3/resource_iam_folders_policy_binding_test.go.tmpl b/mmv1/third_party/terraform/services/iam3/resource_iam_folders_policy_binding_test.go.tmpl new file mode 100644 index 000000000000..c64a779ed07e --- /dev/null +++ b/mmv1/third_party/terraform/services/iam3/resource_iam_folders_policy_binding_test.go.tmpl @@ -0,0 +1,134 @@ +package iam3_test +{{- if ne $.TargetVersionName "ga" }} + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + + "github.com/hashicorp/terraform-provider-google/google/acctest" + "github.com/hashicorp/terraform-provider-google/google/envvar" +) + +func TestAccIAM3FoldersPolicyBinding_iamFoldersPolicyBindingExample_update(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "org_id": envvar.GetTestOrgFromEnv(t), + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t), + ExternalProviders: map[string]resource.ExternalProvider{ + "time": {}, + }, + CheckDestroy: testAccCheckIAM3FoldersPolicyBindingDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccIAM3FoldersPolicyBinding_iamFoldersPolicyBindingExample_full(context), + }, + { + ResourceName: "google_iam_folders_policy_binding.my-folder-binding", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"annotations", "folder", "location", "policy_binding_id"}, + }, + { + Config: testAccIAM3FoldersPolicyBinding_iamFoldersPolicyBindingExample_update(context), + }, + { + ResourceName: "google_iam_folders_policy_binding.my-folder-binding", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"annotations", "folder", "location", "policy_binding_id"}, + }, + }, + }) +} + +func testAccIAM3FoldersPolicyBinding_iamFoldersPolicyBindingExample_full(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_iam_principal_access_boundary_policy" "pab_policy" { + provider = google-beta + organization = "%{org_id}" + location = "global" + display_name = "test folder binding%{random_suffix}" + principal_access_boundary_policy_id = "tf-test-my-pab-policy%{random_suffix}" +} + +resource "google_folder" "folder" { + provider = google-beta + display_name = "test folder%{random_suffix}" + parent = "organizations/%{org_id}" + deletion_protection = false +} + +resource "time_sleep" "wait_120s" { + depends_on = [google_folder.folder] + create_duration = "120s" +} + +resource "google_iam_folders_policy_binding" "my-folder-binding" { + provider = google-beta + folder = google_folder.folder.folder_id + location = "global" + display_name = "test folder binding%{random_suffix}" + policy_kind = "PRINCIPAL_ACCESS_BOUNDARY" + policy_binding_id = "tf-test-folder-binding%{random_suffix}" + policy = "organizations/%{org_id}/locations/global/principalAccessBoundaryPolicies/${google_iam_principal_access_boundary_policy.pab_policy.principal_access_boundary_policy_id}" + target { + principal_set = "//cloudresourcemanager.googleapis.com/folders/${google_folder.folder.folder_id}" + } + depends_on = [time_sleep.wait_120s] +} +`, context) +} + +func testAccIAM3FoldersPolicyBinding_iamFoldersPolicyBindingExample_update(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_iam_principal_access_boundary_policy" "pab_policy" { + provider = google-beta + organization = "%{org_id}" + location = "global" + display_name = "test folder binding%{random_suffix}" + principal_access_boundary_policy_id = "tf-test-my-pab-policy%{random_suffix}" +} + +resource "google_folder" "folder" { + provider = google-beta + display_name = "test folder%{random_suffix}" + parent = "organizations/%{org_id}" + deletion_protection = false +} + +resource "time_sleep" "wait_120s" { + depends_on = [google_folder.folder] + create_duration = "120s" +} + +resource "google_iam_folders_policy_binding" "my-folder-binding" { + provider = google-beta + folder = google_folder.folder.folder_id + location = "global" + display_name = "test folder binding%{random_suffix}" + policy_kind = "PRINCIPAL_ACCESS_BOUNDARY" + policy_binding_id = "tf-test-folder-binding%{random_suffix}" + policy = "organizations/%{org_id}/locations/global/principalAccessBoundaryPolicies/${google_iam_principal_access_boundary_policy.pab_policy.principal_access_boundary_policy_id}" + annotations = {"foo": "bar"} + target { + principal_set = "//cloudresourcemanager.googleapis.com/folders/${google_folder.folder.folder_id}" + } + condition { + description = "test condition" + expression = "principal.subject == 'al@a.com'" + location = "test location" + title = "test title" + } + depends_on = [time_sleep.wait_120s] +} +`, context) +} + +{{- end }} \ No newline at end of file From c690cc889622ae323814a4a4979716c09ab6bea4 Mon Sep 17 00:00:00 2001 From: derekchu-google Date: Tue, 12 Nov 2024 02:26:41 -0800 Subject: [PATCH 045/105] add new resource `google_iam_organizations_policy_binding` (#12251) --- .../iam3/OrganizationsPolicyBinding.yaml | 188 ++++++++++++++++++ .../iam_organizations_policy_binding.tf.tmpl | 21 ++ .../terraform/post_delete/sleep.go.tmpl | 2 +- ..._organizations_policy_binding_test.go.tmpl | 105 ++++++++++ 4 files changed, 315 insertions(+), 1 deletion(-) create mode 100644 mmv1/products/iam3/OrganizationsPolicyBinding.yaml create mode 100644 mmv1/templates/terraform/examples/iam_organizations_policy_binding.tf.tmpl create mode 100644 mmv1/third_party/terraform/services/iam3/resource_iam_organizations_policy_binding_test.go.tmpl diff --git a/mmv1/products/iam3/OrganizationsPolicyBinding.yaml b/mmv1/products/iam3/OrganizationsPolicyBinding.yaml new file mode 100644 index 000000000000..bc2c103f2ed7 --- /dev/null +++ b/mmv1/products/iam3/OrganizationsPolicyBinding.yaml @@ -0,0 +1,188 @@ +# Copyright 2024 Google Inc. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- +name: 'OrganizationsPolicyBinding' +description: A policy binding to an organizations +references: + guides: + 'Apply a policy binding': 'https://cloud.google.com/iam/docs/principal-access-boundary-policies-create#create_binding' + api: 'https://cloud.google.com/iam/docs/reference/rest/v3beta/organizations.locations.policyBindings' +min_version: 'beta' +id_format: 'organizations/{{organization}}/locations/{{location}}/policyBindings/{{policy_binding_id}}' +base_url: 'organizations/{{organization}}/locations/{{location}}/policyBindings' +self_link: 'organizations/{{organization}}/locations/{{location}}/policyBindings/{{policy_binding_id}}' +create_url: 'organizations/{{organization}}/locations/{{location}}/policyBindings?policyBindingId={{policy_binding_id}}' +update_verb: 'PATCH' +update_mask: true +import_format: + - 'organizations/{{organization}}/locations/{{location}}/policyBindings/{{policy_binding_id}}' +timeouts: + insert_minutes: 20 + update_minutes: 20 + delete_minutes: 20 +custom_code: + post_delete: 'templates/terraform/post_delete/sleep.go.tmpl' +autogen_async: true +async: + actions: ['create', 'delete', 'update'] + type: 'OpAsync' + operation: + base_url: '{{op_id}}' + path: 'name' + wait_ms: 1000 + result: + path: 'response' + resource_inside_response: true + error: + path: 'error' + message: 'message' +examples: + - name: 'iam_organizations_policy_binding' + min_version: 'beta' + primary_resource_id: 'my-org-binding' + test_env_vars: + org_id: 'ORG_ID' + vars: + pab_policy_id: 'my-pab-policy' + display_name: 'test org binding' + org_binding_id: 'test-org-binding' +parameters: + - name: 'organization' + type: String + description: | + The parent organization of the Policy Binding. + url_param_only: true + required: true + immutable: true + - name: 'location' + type: String + description: | + The location of the Policy Binding + url_param_only: true + required: true + immutable: true + - name: 'policyBindingId' + type: String + description: | + The Policy Binding ID. + url_param_only: true + required: true + immutable: true +properties: + - name: 'name' + type: String + description: | + The name of the policy binding in the format `{binding_parent/locations/{location}/policyBindings/{policy_binding_id}` + output: true + - name: 'uid' + type: String + description: | + Output only. The globally unique ID of the policy binding. Assigned when the policy binding is created. + output: true + - name: 'etag' + type: String + description: | + Optional. The etag for the policy binding. If this is provided on update, it must match the server's etag. + output: true + - name: 'displayName' + type: String + description: | + Optional. The description of the policy binding. Must be less than or equal to 63 characters. + - name: 'annotations' + type: KeyValueAnnotations + description: | + Optional. User defined annotations. See https://google.aip.dev/148#annotations for more details such as format and size limitations + - name: 'target' + type: NestedObject + description: | + Target is the full resource name of the resource to which the policy will be bound. Immutable once set. + required: true + properties: + - name: 'principalSet' + type: String + description: | + Required. Immutable. The resource name of the policy to be bound. + The binding parent and policy must belong to the same Organization (or Project). + immutable: true + - name: 'policyKind' + type: String + description: | + Immutable. The kind of the policy to attach in this binding. This + field must be one of the following: - Left empty (will be automatically set + to the policy kind) - The input policy kind Possible values: POLICY_KIND_UNSPECIFIED PRINCIPAL_ACCESS_BOUNDARY ACCESS + immutable: true + - name: 'policy' + type: String + description: | + Required. Immutable. The resource name of the policy to be bound. The binding parent and policy must belong to the same Organization (or Project). + required: true + immutable: true + - name: 'policyUid' + type: String + description: | + Output only. The globally unique ID of the policy to be bound. + output: true + - name: 'condition' + type: NestedObject + description: | + Represents a textual expression in the Common Expression Language + (CEL) syntax. CEL is a C-like expression language. The syntax and semantics of + CEL are documented at https://github.com/google/cel-spec. + Example (Comparison): + title: \"Summary size limit\" + description: \"Determines if a summary is less than 100 chars\" + expression: \"document.summary.size() < 100\" + Example + (Equality): + title: \"Requestor is owner\" + description: \"Determines if requestor is the document owner\" + expression: \"document.owner == request.auth.claims.email\" Example + (Logic): + title: \"Public documents\" + description: \"Determine whether the document should be publicly visible\" + expression: \"document.type != 'private' && document.type != 'internal'\" + Example (Data Manipulation): + title: \"Notification string\" + description: \"Create a notification string with a timestamp.\" + expression: \"'New message received at ' + string(document.create_time)\" + The exact variables and functions that may be referenced within an expression are + determined by the service that evaluates it. See the service documentation for + additional information. + properties: + - name: 'expression' + type: String + description: | + Textual representation of an expression in Common Expression Language syntax. + - name: 'title' + type: String + description: | + Optional. Title for the expression, i.e. a short string describing its purpose. This can be used e.g. in UIs which allow to enter the expression. + - name: 'description' + type: String + description: | + Optional. Description of the expression. This is a longer text which describes the expression, e.g. when hovered over it in a UI. + - name: 'location' + type: String + description: | + Optional. String indicating the location of the expression for error reporting, e.g. a file name and a position in the file. + - name: 'createTime' + type: String + description: | + Output only. The time when the policy binding was created. + output: true + - name: 'updateTime' + type: String + description: | + Output only. The time when the policy binding was most recently updated. + output: true diff --git a/mmv1/templates/terraform/examples/iam_organizations_policy_binding.tf.tmpl b/mmv1/templates/terraform/examples/iam_organizations_policy_binding.tf.tmpl new file mode 100644 index 000000000000..92c60be8aa78 --- /dev/null +++ b/mmv1/templates/terraform/examples/iam_organizations_policy_binding.tf.tmpl @@ -0,0 +1,21 @@ +resource "google_iam_principal_access_boundary_policy" "pab_policy" { + provider = google-beta + organization = "{{index $.TestEnvVars "org_id"}}" + location = "global" + display_name = "{{index $.Vars "display_name"}}" + principal_access_boundary_policy_id = "{{index $.Vars "pab_policy_id"}}" +} + +resource "google_iam_organizations_policy_binding" "{{$.PrimaryResourceId}}" { + provider = google-beta + organization = "{{index $.TestEnvVars "org_id"}}" + location = "global" + display_name = "{{index $.Vars "display_name"}}" + policy_kind = "PRINCIPAL_ACCESS_BOUNDARY" + policy_binding_id = "{{index $.Vars "org_binding_id"}}" + policy = "organizations/{{index $.TestEnvVars "org_id"}}/locations/global/principalAccessBoundaryPolicies/${google_iam_principal_access_boundary_policy.pab_policy.principal_access_boundary_policy_id}" + target { + principal_set = "//cloudresourcemanager.googleapis.com/organizations/{{index $.TestEnvVars "org_id"}}" + } +} + diff --git a/mmv1/templates/terraform/post_delete/sleep.go.tmpl b/mmv1/templates/terraform/post_delete/sleep.go.tmpl index c9b44c91ff05..13b8a997b67a 100644 --- a/mmv1/templates/terraform/post_delete/sleep.go.tmpl +++ b/mmv1/templates/terraform/post_delete/sleep.go.tmpl @@ -1,3 +1,3 @@ // This is useful if the resource in question doesn't have a perfectly consistent API // That is, if the deletion of a dependent resource has not propagated. -time.Sleep(5 * time.Second) \ No newline at end of file +time.Sleep(5 * time.Second) diff --git a/mmv1/third_party/terraform/services/iam3/resource_iam_organizations_policy_binding_test.go.tmpl b/mmv1/third_party/terraform/services/iam3/resource_iam_organizations_policy_binding_test.go.tmpl new file mode 100644 index 000000000000..0c2d9564ed25 --- /dev/null +++ b/mmv1/third_party/terraform/services/iam3/resource_iam_organizations_policy_binding_test.go.tmpl @@ -0,0 +1,105 @@ +package iam3_test +{{- if ne $.TargetVersionName "ga" }} + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + + "github.com/hashicorp/terraform-provider-google/google/acctest" + "github.com/hashicorp/terraform-provider-google/google/envvar" +) + +func TestAccIAM3OrganizationsPolicyBinding_iam3OrganizationsPolicyBindingExample_update(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "org_id": envvar.GetTestOrgFromEnv(t), + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t), + CheckDestroy: testAccCheckIAM3OrganizationsPolicyBindingDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccIAM3OrganizationsPolicyBinding_iam3OrganizationsPolicyBindingExample_full(context), + }, + { + ResourceName: "google_iam_organizations_policy_binding.my_org_binding", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"annotations", "location", "organization", "policy_binding_id"}, + }, + + { + Config: testAccIAM3OrganizationsPolicyBinding_iam3OrganizationsPolicyBindingExample_update(context), + }, + { + ResourceName: "google_iam_organizations_policy_binding.my_org_binding", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"annotations", "location", "organization", "policy_binding_id"}, + }, + }, + }) +} + +func testAccIAM3OrganizationsPolicyBinding_iam3OrganizationsPolicyBindingExample_full(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_iam_principal_access_boundary_policy" "pab_policy" { + provider = google-beta + organization = "%{org_id}" + location = "global" + display_name = "test org binding%{random_suffix}" + principal_access_boundary_policy_id = "tf-test-my-pab-policy%{random_suffix}" +} + +resource "google_iam_organizations_policy_binding" "my_org_binding" { + provider = google-beta + organization = "%{org_id}" + location = "global" + display_name = "test org binding%{random_suffix}" + policy_kind = "PRINCIPAL_ACCESS_BOUNDARY" + policy_binding_id = "tf-test-test-org-binding%{random_suffix}" + policy = "organizations/%{org_id}/locations/global/principalAccessBoundaryPolicies/${google_iam_principal_access_boundary_policy.pab_policy.principal_access_boundary_policy_id}" + target { + principal_set = "//cloudresourcemanager.googleapis.com/organizations/%{org_id}" + } +} +`, context) +} + +func testAccIAM3OrganizationsPolicyBinding_iam3OrganizationsPolicyBindingExample_update(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_iam_principal_access_boundary_policy" "pab_policy" { + provider = google-beta + organization = "%{org_id}" + location = "global" + display_name = "test org binding%{random_suffix}" + principal_access_boundary_policy_id = "tf-test-my-pab-policy%{random_suffix}" +} + +resource "google_iam_organizations_policy_binding" "my_org_binding" { + provider = google-beta + organization = "%{org_id}" + location = "global" + display_name = "test org binding%{random_suffix}" + policy_kind = "PRINCIPAL_ACCESS_BOUNDARY" + policy_binding_id = "tf-test-test-org-binding%{random_suffix}" + policy = "organizations/%{org_id}/locations/global/principalAccessBoundaryPolicies/${google_iam_principal_access_boundary_policy.pab_policy.principal_access_boundary_policy_id}" + annotations = {"foo": "bar"} + target { + principal_set = "//cloudresourcemanager.googleapis.com/organizations/%{org_id}" + } + condition { + description = "test condition" + expression = "principal.subject == 'al@a.com'" + location = "test location" + title = "test title" + } +} +`, context) +} +{{- end }} \ No newline at end of file From 817990220aced261b121b0e32dca4ab160e72c55 Mon Sep 17 00:00:00 2001 From: joe miller Date: Tue, 12 Nov 2024 07:47:59 -0800 Subject: [PATCH 046/105] Support `common_repository` for `google_artifact_registry_repository` (#12290) --- .../products/artifactregistry/Repository.yaml | 37 +++++++++++++++++++ ...mote_common_repository_with_docker.tf.tmpl | 20 ++++++++++ 2 files changed, 57 insertions(+) create mode 100644 mmv1/templates/terraform/examples/artifact_registry_repository_remote_common_repository_with_docker.tf.tmpl diff --git a/mmv1/products/artifactregistry/Repository.yaml b/mmv1/products/artifactregistry/Repository.yaml index f5749bb71791..747d4c8f78bc 100644 --- a/mmv1/products/artifactregistry/Repository.yaml +++ b/mmv1/products/artifactregistry/Repository.yaml @@ -173,6 +173,17 @@ examples: # Ignore this field as it is INPUT_ONLY. AR will not return this in the # response. - 'remote_repository_config.0.disable_upstream_validation' + - name: 'artifact_registry_repository_remote_common_repository_with_docker' + primary_resource_id: 'my-repo' + vars: + repository_id: 'example-common-remote' + desc: 'example remote common repository with docker upstream' + upstream_repository_id: 'example-upstream-repo' + upstream_repository_desc: 'example upstream repository' + ignore_read_extra: + # Ignore this field as it is INPUT_ONLY. AR will not return this in the + # response. + - 'remote_repository_config.0.disable_upstream_validation' parameters: properties: - name: 'name' @@ -419,6 +430,7 @@ properties: - 'remoteRepositoryConfig.0.npm_repository' - 'remoteRepositoryConfig.0.python_repository' - 'remoteRepositoryConfig.0.yum_repository' + - 'remoteRepositoryConfig.0.common_repository' properties: - name: 'publicRepository' type: NestedObject @@ -453,6 +465,7 @@ properties: - 'remoteRepositoryConfig.0.npm_repository' - 'remoteRepositoryConfig.0.python_repository' - 'remoteRepositoryConfig.0.yum_repository' + - 'remoteRepositoryConfig.0.common_repository' properties: - name: 'publicRepository' type: Enum @@ -491,6 +504,7 @@ properties: - 'remoteRepositoryConfig.0.npm_repository' - 'remoteRepositoryConfig.0.python_repository' - 'remoteRepositoryConfig.0.yum_repository' + - 'remoteRepositoryConfig.0.common_repository' properties: - name: 'publicRepository' type: Enum @@ -529,6 +543,7 @@ properties: - 'remoteRepositoryConfig.0.npm_repository' - 'remoteRepositoryConfig.0.python_repository' - 'remoteRepositoryConfig.0.yum_repository' + - 'remoteRepositoryConfig.0.common_repository' properties: - name: 'publicRepository' type: Enum @@ -567,6 +582,7 @@ properties: - 'remoteRepositoryConfig.0.npm_repository' - 'remoteRepositoryConfig.0.python_repository' - 'remoteRepositoryConfig.0.yum_repository' + - 'remoteRepositoryConfig.0.common_repository' properties: - name: 'publicRepository' type: Enum @@ -605,6 +621,7 @@ properties: - 'remoteRepositoryConfig.0.npm_repository' - 'remoteRepositoryConfig.0.python_repository' - 'remoteRepositoryConfig.0.yum_repository' + - 'remoteRepositoryConfig.0.common_repository' properties: - name: 'publicRepository' type: NestedObject @@ -631,6 +648,26 @@ properties: Specific repository from the base, e.g. `"pub/rocky/9/BaseOS/x86_64/os"` required: true immutable: true + - name: 'commonRepository' + type: NestedObject + description: |- + Specific settings for an Artifact Registory remote repository. + immutable: true + exactly_one_of: + - 'remoteRepositoryConfig.0.apt_repository' + - 'remoteRepositoryConfig.0.docker_repository' + - 'remoteRepositoryConfig.0.maven_repository' + - 'remoteRepositoryConfig.0.npm_repository' + - 'remoteRepositoryConfig.0.python_repository' + - 'remoteRepositoryConfig.0.yum_repository' + - 'remoteRepositoryConfig.0.common_repository' + properties: + - name: 'uri' + type: String + description: |- + Specific uri to the Artifact Registory repository, e.g. `projects/UPSTREAM_PROJECT_ID/locations/REGION/repositories/UPSTREAM_REPOSITORY` + immutable: true + required: true - name: 'upstreamCredentials' type: NestedObject description: |- diff --git a/mmv1/templates/terraform/examples/artifact_registry_repository_remote_common_repository_with_docker.tf.tmpl b/mmv1/templates/terraform/examples/artifact_registry_repository_remote_common_repository_with_docker.tf.tmpl new file mode 100644 index 000000000000..4b3829f400c9 --- /dev/null +++ b/mmv1/templates/terraform/examples/artifact_registry_repository_remote_common_repository_with_docker.tf.tmpl @@ -0,0 +1,20 @@ +resource "google_artifact_registry_repository" "upstream_repo" { + location = "us-central1" + repository_id = "{{index $.Vars "upstream_repository_id"}}" + description = "{{index $.Vars "upstream_repository_desc"}}" + format = "DOCKER" +} + +resource "google_artifact_registry_repository" "{{$.PrimaryResourceId}}" { + location = "us-central1" + repository_id = "{{index $.Vars "repository_id"}}" + description = "{{index $.Vars "desc"}}" + format = "DOCKER" + mode = "REMOTE_REPOSITORY" + remote_repository_config { + description = "pull-through cache of another Artifact Registry repository" + common_repository { + uri = google_artifact_registry_repository.upstream_repo.id + } + } +} From 151435867d85bc67cc73d32365733313abf5b2de Mon Sep 17 00:00:00 2001 From: yyzou-bot Date: Tue, 12 Nov 2024 09:36:22 -0800 Subject: [PATCH 047/105] feat: support Cloud SQL\'s new field `psc_auto_connections`. (#12236) Signed-off-by: Julia Zou --- .../resource_sql_database_instance.go.tmpl | 53 +++++ .../resource_sql_database_instance_test.go | 187 +++++++++++++++++- .../r/sql_database_instance.html.markdown | 34 ++++ 3 files changed, 267 insertions(+), 7 deletions(-) diff --git a/mmv1/third_party/terraform/services/sql/resource_sql_database_instance.go.tmpl b/mmv1/third_party/terraform/services/sql/resource_sql_database_instance.go.tmpl index 88e812273422..1ffe1aed81d5 100644 --- a/mmv1/third_party/terraform/services/sql/resource_sql_database_instance.go.tmpl +++ b/mmv1/third_party/terraform/services/sql/resource_sql_database_instance.go.tmpl @@ -489,6 +489,25 @@ is set to true. Defaults to ZONAL.`, Set: schema.HashString, Description: `List of consumer projects that are allow-listed for PSC connections to this instance. This instance can be connected to with PSC from any network in these projects. Each consumer project in this list may be represented by a project number (numeric) or by a project id (alphanumeric).`, }, + "psc_auto_connections": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "consumer_service_project_id": { + Type: schema.TypeString, + Optional: true, + Description: `The project ID of consumer service project of this consumer endpoint.`, + }, + "consumer_network": { + Type: schema.TypeString, + Required: true, + Description: `The consumer network of this consumer endpoint. This must be a resource path that includes both the host project and the network name. The consumer host project of this network might be different from the consumer service project.`, + }, + }, + }, + Description: `A comma-separated list of networks or a comma-separated list of network-project pairs. Each project in this list is represented by a project number (numeric) or by a project ID (alphanumeric). This allows Private Service Connect connections to be created automatically for the specified networks.`, + }, }, }, }, @@ -1437,12 +1456,30 @@ func expandIpConfiguration(configured []interface{}, databaseVersion string) *sq } } +func expandPscAutoConnectionConfig(configured []interface{}) []*sqladmin.PscAutoConnectionConfig { + pscAutoConnections:= make([]*sqladmin.PscAutoConnectionConfig, 0, len(configured)) + + for _, _flag := range configured { + if _flag == nil { + continue + } + _entry := _flag.(map[string]interface{}) + + pscAutoConnections = append(pscAutoConnections, &sqladmin.PscAutoConnectionConfig { + ConsumerNetwork: _entry["consumer_network"].(string), + ConsumerProject: _entry["consumer_service_project_id"].(string), + }) + } + return pscAutoConnections +} + func expandPscConfig(configured []interface{}) *sqladmin.PscConfig { for _, _pscConfig := range configured { _entry := _pscConfig.(map[string]interface{}) return &sqladmin.PscConfig{ PscEnabled: _entry["psc_enabled"].(bool), AllowedConsumerProjects: tpgresource.ConvertStringArr(_entry["allowed_consumer_projects"].(*schema.Set).List()), + PscAutoConnections: expandPscAutoConnectionConfig(_entry["psc_auto_connections"].([]interface{})), } } @@ -2342,10 +2379,26 @@ func flattenIpConfiguration(ipConfiguration *sqladmin.IpConfiguration, d *schema return []map[string]interface{}{data} } +func flattenPscAutoConnections(pscAutoConnections []*sqladmin.PscAutoConnectionConfig) []map[string]interface{} { + flags := make([]map[string]interface{}, 0, len(pscAutoConnections)) + + for _, flag := range pscAutoConnections { + data := map[string]interface{}{ + "consumer_network": flag.ConsumerNetwork, + "consumer_service_project_id": flag.ConsumerProject, + } + + flags = append(flags, data) + } + + return flags +} + func flattenPscConfigs(pscConfig *sqladmin.PscConfig) interface{} { data := map[string]interface{}{ "psc_enabled": pscConfig.PscEnabled, "allowed_consumer_projects": schema.NewSet(schema.HashString, tpgresource.ConvertStringArrToInterface(pscConfig.AllowedConsumerProjects)), + "psc_auto_connections": flattenPscAutoConnections(pscConfig.PscAutoConnections), } return []map[string]interface{}{data} diff --git a/mmv1/third_party/terraform/services/sql/resource_sql_database_instance_test.go b/mmv1/third_party/terraform/services/sql/resource_sql_database_instance_test.go index 53d975ec08fa..b1abff5d5f7f 100644 --- a/mmv1/third_party/terraform/services/sql/resource_sql_database_instance_test.go +++ b/mmv1/third_party/terraform/services/sql/resource_sql_database_instance_test.go @@ -944,13 +944,69 @@ func TestAccSqlDatabaseInstance_withPSCEnabled_thenAddAllowedConsumerProjects_th }) } -func TestAccSqlDatabaseInstance_basicInstance_thenPSCEnabled(t *testing.T) { +func TestAccSqlDatabaseInstance_withPSCEnabled_withoutPscAutoConnections(t *testing.T) { t.Parallel() instanceName := "tf-test-" + acctest.RandString(t, 10) - projectId := "psctestproject" + acctest.RandString(t, 10) - orgId := envvar.GetTestOrgFromEnv(t) - billingAccount := envvar.GetTestBillingAccountFromEnv(t) + projectId := envvar.GetTestProjectFromEnv() + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccSqlDatabaseInstanceDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccSqlDatabaseInstance_withPSCEnabled_withoutPscAutoConnections(instanceName), + Check: resource.ComposeTestCheckFunc(verifyPscAutoConnectionsOperation("google_sql_database_instance.instance", true, true, false, "", "")), + }, + { + ResourceName: "google_sql_database_instance.instance", + ImportState: true, + ImportStateVerify: true, + ImportStateIdPrefix: fmt.Sprintf("%s/", projectId), + ImportStateVerifyIgnore: []string{"deletion_protection"}, + }, + }, + }) +} + +func TestAccSqlDatabaseInstance_withPSCEnabled_withPscAutoConnections(t *testing.T) { + t.Parallel() + + testId := "test-psc-auto-con" + acctest.RandString(t, 10) + instanceName := "tf-test-" + acctest.RandString(t, 10) + projectId := envvar.GetTestProjectFromEnv() + networkName := acctest.BootstrapSharedTestNetwork(t, testId) + network_short_link_name := fmt.Sprintf("projects/%s/global/networks/%s", projectId, networkName) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccSqlDatabaseInstanceDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccSqlDatabaseInstance_withPSCEnabled_withPscAutoConnections(instanceName, projectId, networkName), + Check: resource.ComposeTestCheckFunc(verifyPscAutoConnectionsOperation("google_sql_database_instance.instance", true, true, true, network_short_link_name, projectId)), + }, + { + ResourceName: "google_sql_database_instance.instance", + ImportState: true, + ImportStateVerify: true, + ImportStateIdPrefix: fmt.Sprintf("%s/", projectId), + ImportStateVerifyIgnore: []string{"deletion_protection"}, + }, + }, + }) +} + +func TestAccSqlDatabaseInstance_withPSCEnabled_thenAddPscAutoConnections_thenRemovePscAutoConnections(t *testing.T) { + t.Parallel() + + testId := "test-psc-auto-con" + acctest.RandString(t, 10) + instanceName := "tf-test-" + acctest.RandString(t, 10) + projectId := envvar.GetTestProjectFromEnv() + networkName := acctest.BootstrapSharedTestNetwork(t, testId) + network_short_link_name := fmt.Sprintf("projects/%s/global/networks/%s", projectId, networkName) acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, @@ -958,7 +1014,8 @@ func TestAccSqlDatabaseInstance_basicInstance_thenPSCEnabled(t *testing.T) { CheckDestroy: testAccSqlDatabaseInstanceDestroyProducer(t), Steps: []resource.TestStep{ { - Config: testAccSqlDatabaseInstance_basicInstanceForPsc(instanceName, projectId, orgId, billingAccount), + Config: testAccSqlDatabaseInstance_withPSCEnabled_withoutPscAutoConnections(instanceName), + Check: resource.ComposeTestCheckFunc(verifyPscAutoConnectionsOperation("google_sql_database_instance.instance", true, true, false, "", "")), }, { ResourceName: "google_sql_database_instance.instance", @@ -968,8 +1025,19 @@ func TestAccSqlDatabaseInstance_basicInstance_thenPSCEnabled(t *testing.T) { ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { - Config: testAccSqlDatabaseInstance_withPSCEnabled_withoutAllowedConsumerProjects(instanceName, projectId, orgId, billingAccount), - ExpectError: regexp.MustCompile("PSC connectivity can not be enabled"), + Config: testAccSqlDatabaseInstance_withPSCEnabled_withPscAutoConnections(instanceName, projectId, networkName), + Check: resource.ComposeTestCheckFunc(verifyPscAutoConnectionsOperation("google_sql_database_instance.instance", true, true, true, network_short_link_name, projectId)), + }, + { + ResourceName: "google_sql_database_instance.instance", + ImportState: true, + ImportStateVerify: true, + ImportStateIdPrefix: fmt.Sprintf("%s/", projectId), + ImportStateVerifyIgnore: []string{"deletion_protection"}, + }, + { + Config: testAccSqlDatabaseInstance_withPSCEnabled_withoutPscAutoConnections(instanceName), + Check: resource.ComposeTestCheckFunc(verifyPscAutoConnectionsOperation("google_sql_database_instance.instance", true, true, false, "", "")), }, }, }) @@ -3569,6 +3637,111 @@ func verifyPscOperation(resourceName string, isPscConfigExpected bool, expectedP } } +func verifyPscAutoConnectionsOperation(resourceName string, isPscConfigExpected bool, expectedPscEnabled bool, isPscAutoConnectionConfigExpected bool, expectedConsumerNetwork string, expectedConsumerProject string) func(*terraform.State) error { + return func(s *terraform.State) error { + resource, ok := s.RootModule().Resources[resourceName] + if !ok { + return fmt.Errorf("Can't find %s in state", resourceName) + } + + resourceAttributes := resource.Primary.Attributes + _, ok = resourceAttributes["settings.0.ip_configuration.#"] + if !ok { + return fmt.Errorf("settings.0.ip_configuration.# block is not present in state for %s", resourceName) + } + + if isPscConfigExpected { + _, ok := resourceAttributes["settings.0.ip_configuration.0.psc_config.#"] + if !ok { + return fmt.Errorf("settings.0.ip_configuration.0.psc_config property is not present or set in state of %s", resourceName) + } + + pscEnabledStr, ok := resourceAttributes["settings.0.ip_configuration.0.psc_config.0.psc_enabled"] + pscEnabled, err := strconv.ParseBool(pscEnabledStr) + if err != nil || pscEnabled != expectedPscEnabled { + return fmt.Errorf("settings.0.ip_configuration.0.psc_config.0.psc_enabled property value is not set as expected in state of %s, expected %v, actual %v", resourceName, expectedPscEnabled, pscEnabled) + } + + _, ok = resourceAttributes["settings.0.ip_configuration.0.psc_config.0.psc_auto_connections.#"] + if !ok { + return fmt.Errorf("settings.0.ip_configuration.0.psc_config.0.psc_auto_connections property is not present or set in state of %s", resourceName) + } + + if isPscAutoConnectionConfigExpected { + consumerNetwork, ok := resourceAttributes["settings.0.ip_configuration.0.psc_config.0.psc_auto_connections.0.consumer_network"] + if !ok || consumerNetwork != expectedConsumerNetwork { + return fmt.Errorf("settings.0.ip_configuration.0.psc_config.0.psc_auto_connections.0.consumer_network property is not present or set as expected in state of %s", resourceName) + } + + consumerProject, ok := resourceAttributes["settings.0.ip_configuration.0.psc_config.0.psc_auto_connections.0.consumer_service_project_id"] + if !ok || consumerProject != expectedConsumerProject { + return fmt.Errorf("settings.0.ip_configuration.0.psc_config.0.psc_auto_connections.0.consumer_service_project_id property is not present or set as expected in state of %s", resourceName) + } + } + } + + return nil + } +} + +func testAccSqlDatabaseInstance_withPSCEnabled_withoutPscAutoConnections(instanceName string) string { + return fmt.Sprintf(` +resource "google_sql_database_instance" "instance" { + name = "%s" + region = "us-west2" + database_version = "MYSQL_8_0" + deletion_protection = false + settings { + tier = "db-g1-small" + ip_configuration { + psc_config { + psc_enabled = true + } + ipv4_enabled = false + } + backup_configuration { + enabled = true + binary_log_enabled = true + } + availability_type = "REGIONAL" + } +} +`, instanceName) +} + +func testAccSqlDatabaseInstance_withPSCEnabled_withPscAutoConnections(instanceName string, projectId string, networkName string) string { + return fmt.Sprintf(` +data "google_compute_network" "testnetwork" { + name = "%s" +} + +resource "google_sql_database_instance" "instance" { + name = "%s" + region = "us-west2" + database_version = "MYSQL_8_0" + deletion_protection = false + settings { + tier = "db-g1-small" + ip_configuration { + psc_config { + psc_enabled = true + psc_auto_connections { + consumer_network = "projects/%s/global/networks/%s" + consumer_service_project_id = "%s" + } + } + ipv4_enabled = false + } + backup_configuration { + enabled = true + binary_log_enabled = true + } + availability_type = "REGIONAL" + } +} +`, networkName, instanceName, projectId, networkName, projectId) +} + func testAccSqlDatabaseInstance_withPrivateNetwork_withoutAllocatedIpRange(databaseName, networkName string, specifyPrivatePathOption bool, enablePrivatePath bool) string { privatePathOption := "" if specifyPrivatePathOption { diff --git a/mmv1/third_party/terraform/website/docs/r/sql_database_instance.html.markdown b/mmv1/third_party/terraform/website/docs/r/sql_database_instance.html.markdown index 0346b9a2e62c..5c70a7a4c1a2 100644 --- a/mmv1/third_party/terraform/website/docs/r/sql_database_instance.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/sql_database_instance.html.markdown @@ -197,6 +197,34 @@ resource "google_sql_database_instance" "main" { } ``` +### Cloud SQL Instance with PSC auto connections + +```hcl +resource "google_sql_database_instance" "main" { + name = "psc-enabled-main-instance" + database_version = "MYSQL_8_0" + settings { + tier = "db-f1-micro" + ip_configuration { + psc_config { + psc_enabled = true + allowed_consumer_projects = ["allowed-consumer-project-name"] + psc_auto_connections { + consumer_network = "network-name" + consumer_service_project_id = "project-id" + } + } + ipv4_enabled = false + } + backup_configuration { + enabled = true + binary_log_enabled = true + } + availability_type = "REGIONAL" + } +} +``` + ## Argument Reference The following arguments are supported: @@ -404,6 +432,12 @@ The optional `settings.ip_configuration.psc_config` sublist supports: * `allowed_consumer_projects` - (Optional) List of consumer projects that are allow-listed for PSC connections to this instance. This instance can be connected to with PSC from any network in these projects. Each consumer project in this list may be represented by a project number (numeric) or by a project id (alphanumeric). +* The optional `psc_config.psc_auto_connections` subblock - (Optional) A comma-separated list of networks or a comma-separated list of network-project pairs. Each project in this list is represented by a project number (numeric) or by a project ID (alphanumeric). This allows Private Service Connect connections to be created automatically for the specified networks. + +* `consumer_network` - "The consumer network of this consumer endpoint. This must be a resource path that includes both the host project and the network name. For example, `projects/project1/global/networks/network1`. The consumer host project of this network might be different from the consumer service project." + +* `consumer_service_project_id` - (Optional) The project ID of consumer service project of this consumer endpoint. + The optional `settings.location_preference` subblock supports: * `follow_gae_application` - (Optional) A GAE application whose zone to remain From 52cc2b95a830924aec414f43daa4e31af95e7ca2 Mon Sep 17 00:00:00 2001 From: Sarah French <15078782+SarahFrench@users.noreply.github.com> Date: Tue, 12 Nov 2024 19:52:23 +0000 Subject: [PATCH 048/105] Mark SarahFrench as on vacation until December (#12306) --- .ci/magician/github/membership_data.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.ci/magician/github/membership_data.go b/.ci/magician/github/membership_data.go index 5c388c2eb6c8..55735dc86b79 100644 --- a/.ci/magician/github/membership_data.go +++ b/.ci/magician/github/membership_data.go @@ -98,8 +98,8 @@ var ( }, { id: "SarahFrench", - startDate: newDate(2024, 11, 1, bstLoc), - endDate: newDate(2024, 11, 4, bstLoc), + startDate: newDate(2024, 11, 15, bstLoc), + endDate: newDate(2024, 12, 2, bstLoc), }, { id: "c2thorn", From c17d907f806a1cc95bed520c2e905a967fe8a122 Mon Sep 17 00:00:00 2001 From: Thomas Rodgers Date: Tue, 12 Nov 2024 12:07:13 -0800 Subject: [PATCH 049/105] Revert "Migrate google_compute_firewall_policy_association resource from DCL to MMv1" (#12308) --- .../compute/FirewallPolicyAssociation.yaml | 82 -------------- ...ompute_firewall_policy_association.go.tmpl | 7 -- .../firewall_policy_association.tf.tmpl | 17 --- ...ewall_policy_association_operation.go.tmpl | 11 -- ...ewall_policy_association_operation.go.tmpl | 11 -- ...ompute_firewall_policy_association_test.go | 50 -------- ..._firewall_policy_association.html.markdown | 107 ++++++++++++++++++ .../beta/firewall_policy_association.yaml | 4 + .../compute/firewall_policy_association.yaml | 2 +- 9 files changed, 112 insertions(+), 179 deletions(-) delete mode 100644 mmv1/products/compute/FirewallPolicyAssociation.yaml delete mode 100644 mmv1/templates/terraform/custom_expand/compute_firewall_policy_association.go.tmpl delete mode 100644 mmv1/templates/terraform/examples/firewall_policy_association.tf.tmpl delete mode 100644 mmv1/templates/terraform/post_create/compute_firewall_policy_association_operation.go.tmpl delete mode 100644 mmv1/templates/terraform/post_delete/compute_firewall_policy_association_operation.go.tmpl create mode 100644 mmv1/third_party/terraform/website/docs/r/compute_firewall_policy_association.html.markdown create mode 100644 tpgtools/overrides/compute/beta/firewall_policy_association.yaml diff --git a/mmv1/products/compute/FirewallPolicyAssociation.yaml b/mmv1/products/compute/FirewallPolicyAssociation.yaml deleted file mode 100644 index 0114bfc578ba..000000000000 --- a/mmv1/products/compute/FirewallPolicyAssociation.yaml +++ /dev/null @@ -1,82 +0,0 @@ -# Copyright 2024 Google Inc. -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - ---- -name: 'FirewallPolicyAssociation' -kind: 'compute#firewallPolicyAssociation' -description: | - Allows associating hierarchical firewall policies with the target where they are applied. This allows creating policies and rules in a different location than they are applied. - For more information on applying hierarchical firewall policies see the [official documentation](https://cloud.google.com/firewall/docs/firewall-policies#managing_hierarchical_firewall_policy_resources) -min_version: 'beta' -references: - guides: - api: 'https://cloud.google.com/compute/docs/reference/rest/v1/firewallPolicies/addAssociation' -docs: -id_format: 'locations/global/firewallPolicies/{{firewall_policy}}/associations/{{name}}' -base_url: 'locations/global/firewallPolicies/{{firewall_policy}}' -self_link: 'locations/global/firewallPolicies/{{firewall_policy}}/getAssociation?name={{name}}' -create_url: 'locations/global/firewallPolicies/{{firewall_policy}}/addAssociation' -delete_url: 'locations/global/firewallPolicies/{{firewall_policy}}/removeAssociation?name={{name}}' -delete_verb: 'POST' -immutable: true -import_format: - - 'locations/global/firewallPolicies/{{firewall_policy}}/associations/{{name}}' - - '{{firewall_policy}}/{{name}}' -timeouts: - insert_minutes: 20 - update_minutes: 20 - delete_minutes: 20 -custom_code: - post_create: 'templates/terraform/post_create/compute_firewall_policy_association_operation.go.tmpl' - post_delete: 'templates/terraform/post_delete/compute_firewall_policy_association_operation.go.tmpl' -custom_diff: - - 'tpgresource.DefaultProviderProject' -examples: - - name: 'firewall_policy_association' - primary_resource_id: 'default' - vars: - policy_name: 'my-policy' - association_name: 'my-association' - folder_name: 'my-folder' - test_env_vars: - org_id: 'ORG_ID' - exclude_test: true -parameters: - - name: 'firewallPolicy' - type: ResourceRef - description: | - The firewall policy of the resource. - ignore_read: true - required: true - immutable: true - diff_suppress_func: 'tpgresource.CompareResourceNames' - custom_expand: 'templates/terraform/custom_expand/compute_firewall_policy_association.go.tmpl' - resource: 'FirewallPolicy' - imports: 'name' -properties: - - name: 'name' - type: String - description: | - The name for an association. - required: true - - name: 'attachmentTarget' - type: String - description: | - The target that the firewall policy is attached to. - required: true - diff_suppress_func: 'tpgresource.CompareSelfLinkOrResourceName' - - name: 'shortName' - type: String - description: | - The short name of the firewall policy of the association. - output: true diff --git a/mmv1/templates/terraform/custom_expand/compute_firewall_policy_association.go.tmpl b/mmv1/templates/terraform/custom_expand/compute_firewall_policy_association.go.tmpl deleted file mode 100644 index 7b3a6e343f90..000000000000 --- a/mmv1/templates/terraform/custom_expand/compute_firewall_policy_association.go.tmpl +++ /dev/null @@ -1,7 +0,0 @@ -func expand{{$.GetPrefix}}{{$.TitlelizeProperty}}(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { - firewallPolicyId := tpgresource.GetResourceNameFromSelfLink(v.(string)) - if err := d.Set("firewall_policy", firewallPolicyId); err != nil { - return nil, fmt.Errorf("Error setting firewall_policy: %s", err) - } - return firewallPolicyId, nil -} \ No newline at end of file diff --git a/mmv1/templates/terraform/examples/firewall_policy_association.tf.tmpl b/mmv1/templates/terraform/examples/firewall_policy_association.tf.tmpl deleted file mode 100644 index 5ae7625e741c..000000000000 --- a/mmv1/templates/terraform/examples/firewall_policy_association.tf.tmpl +++ /dev/null @@ -1,17 +0,0 @@ -resource "google_folder" "folder" { - display_name = "{{index $.Vars "folder_name"}}" - parent = "organizations/{{index $.TestEnvVars "org_id"}}" - deletion_protection = false -} - -resource "google_compute_firewall_policy" "policy" { - parent = "organizations/{{index $.TestEnvVars "org_id"}}" - short_name = "{{index $.Vars "policy_name"}}" - description = "Example Resource" -} - -resource "google_compute_firewall_policy_association" "{{$.PrimaryResourceId}}" { - firewall_policy = google_compute_firewall_policy.policy.id - attachment_target = google_folder.folder.name - name = "{{index $.Vars "association_name"}}" -} \ No newline at end of file diff --git a/mmv1/templates/terraform/post_create/compute_firewall_policy_association_operation.go.tmpl b/mmv1/templates/terraform/post_create/compute_firewall_policy_association_operation.go.tmpl deleted file mode 100644 index 0953b637e026..000000000000 --- a/mmv1/templates/terraform/post_create/compute_firewall_policy_association_operation.go.tmpl +++ /dev/null @@ -1,11 +0,0 @@ -parent := d.Get("firewall_policy").(string) -var opRes map[string]interface{} -err = ComputeOrgOperationWaitTimeWithResponse( - config, res, &opRes, parent, "Creating FirewallPolicyAssociation", userAgent, - d.Timeout(schema.TimeoutCreate)) - -if err != nil { - // The resource didn't actually create - d.SetId("") - return fmt.Errorf("Error waiting to create FirewallPolicyAssociation: %s", err) -} \ No newline at end of file diff --git a/mmv1/templates/terraform/post_delete/compute_firewall_policy_association_operation.go.tmpl b/mmv1/templates/terraform/post_delete/compute_firewall_policy_association_operation.go.tmpl deleted file mode 100644 index 45ef4fbfe655..000000000000 --- a/mmv1/templates/terraform/post_delete/compute_firewall_policy_association_operation.go.tmpl +++ /dev/null @@ -1,11 +0,0 @@ -parent := d.Get("firewall_policy").(string) -var opRes map[string]interface{} -err = ComputeOrgOperationWaitTimeWithResponse( - config, res, &opRes, parent, "Deleting FirewallPolicyAssociation", userAgent, - d.Timeout(schema.TimeoutCreate)) - -if err != nil { - // The resource didn't actually create - d.SetId("") - return fmt.Errorf("Error waiting to delete FirewallPolicyAssociation: %s", err) -} \ No newline at end of file diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_firewall_policy_association_test.go b/mmv1/third_party/terraform/services/compute/resource_compute_firewall_policy_association_test.go index 5845c149221f..12e8f78881a7 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_firewall_policy_association_test.go +++ b/mmv1/third_party/terraform/services/compute/resource_compute_firewall_policy_association_test.go @@ -62,53 +62,3 @@ resource "google_compute_firewall_policy_association" "default" { } `, context) } - -func TestAccComputeFirewallPolicyAssociation_organization(t *testing.T) { - t.Parallel() - - context := map[string]interface{}{ - "random_suffix": acctest.RandString(t, 10), - "org_name": fmt.Sprintf("organizations/%s", envvar.GetTestOrgFromEnv(t)), - } - - acctest.VcrTest(t, resource.TestCase{ - PreCheck: func() { acctest.AccTestPreCheck(t) }, - ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), - ExternalProviders: map[string]resource.ExternalProvider{ - "time": {}, - }, - Steps: []resource.TestStep{ - { - Config: testAccComputeFirewallPolicyAssociation_organization(context), - }, - { - ResourceName: "google_compute_firewall_policy_association.default", - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"firewall_policy"}, - }, - }, - }) -} - -func testAccComputeFirewallPolicyAssociation_organization(context map[string]interface{}) string { - return acctest.Nprintf(` -resource "google_folder" "folder" { - display_name = "tf-test-my-folder-%{random_suffix}" - parent = "%{org_name}" - deletion_protection = false -} - -resource "google_compute_firewall_policy" "policy" { - parent = "%{org_name}" - short_name = "tf-test-my-policy-%{random_suffix}" - description = "Example Resource" -} - -resource "google_compute_firewall_policy_association" "default" { - firewall_policy = google_compute_firewall_policy.policy.id - attachment_target = google_folder.folder.name - name = "tf-test-my-association-%{random_suffix}" -} -`, context) -} diff --git a/mmv1/third_party/terraform/website/docs/r/compute_firewall_policy_association.html.markdown b/mmv1/third_party/terraform/website/docs/r/compute_firewall_policy_association.html.markdown new file mode 100644 index 000000000000..cfe4cc3fdcd9 --- /dev/null +++ b/mmv1/third_party/terraform/website/docs/r/compute_firewall_policy_association.html.markdown @@ -0,0 +1,107 @@ +--- +# ---------------------------------------------------------------------------- +# +# *** AUTO GENERATED CODE *** Type: DCL *** +# +# ---------------------------------------------------------------------------- +# +# This file is managed by Magic Modules (https:#github.com/GoogleCloudPlatform/magic-modules) +# and is based on the DCL (https:#github.com/GoogleCloudPlatform/declarative-resource-client-library). +# Changes will need to be made to the DCL or Magic Modules instead of here. +# +# We are not currently able to accept contributions to this file. If changes +# are required, please file an issue at https:#github.com/hashicorp/terraform-provider-google/issues/new/choose +# +# ---------------------------------------------------------------------------- +subcategory: "Compute Engine" +description: |- + Applies a hierarchical firewall policy to a target resource +--- + +# google_compute_firewall_policy_association + +Allows associating hierarchical firewall policies with the target where they are applied. This allows creating policies and rules in a different location than they are applied. + +For more information on applying hierarchical firewall policies see the [official documentation](https://cloud.google.com/vpc/docs/firewall-policies#managing_hierarchical_firewall_policy_resources) + +## Example Usage + +```hcl +resource "google_compute_firewall_policy" "default" { + parent = "organizations/12345" + short_name = "my-policy" + description = "Example Resource" +} + +resource "google_compute_firewall_policy_association" "default" { + firewall_policy = google_compute_firewall_policy.default.id + attachment_target = google_folder.folder.name + name = "my-association" +} +``` + + +## Argument Reference + +The following arguments are supported: + +* `attachment_target` - + (Required) + The target that the firewall policy is attached to. + +* `firewall_policy` - + (Required) + The firewall policy ID of the association. + +* `name` - + (Required) + The name for an association. + + + +- - - + + + +## Attributes Reference + +In addition to the arguments listed above, the following computed attributes are exported: + +* `id` - an identifier for the resource with format `locations/global/firewallPolicies/{{firewall_policy}}/associations/{{name}}` + +* `short_name` - + The short name of the firewall policy of the association. + +## Timeouts + +This resource provides the following +[Timeouts](https://developer.hashicorp.com/terraform/plugin/sdkv2/resources/retries-and-customizable-timeouts) configuration options: configuration options: + +- `create` - Default is 20 minutes. +- `delete` - Default is 20 minutes. + +## Import + +FirewallPolicyAssociation can be imported using any of these accepted formats: + +* `locations/global/firewallPolicies/{{firewall_policy}}/associations/{{name}}` +* `{{firewall_policy}}/{{name}}` + +In Terraform v1.5.0 and later, use an [`import` block](https://developer.hashicorp.com/terraform/language/import) to import FirewallPolicyAssociation using one of the formats above. For example: + +```tf +import { + id = "locations/global/firewallPolicies/{{firewall_policy}}/associations/{{name}}" + to = google_compute_firewall_policy_association.default +} +``` + +When using the [`terraform import` command](https://developer.hashicorp.com/terraform/cli/commands/import), FirewallPolicyAssociation can be imported using one of the formats above. For example: + +``` +$ terraform import google_compute_firewall_policy_association.default locations/global/firewallPolicies/{{firewall_policy}}/associations/{{name}} +$ terraform import google_compute_firewall_policy_association.default {{firewall_policy}}/{{name}} +``` + + + diff --git a/tpgtools/overrides/compute/beta/firewall_policy_association.yaml b/tpgtools/overrides/compute/beta/firewall_policy_association.yaml new file mode 100644 index 000000000000..af851d79a0c9 --- /dev/null +++ b/tpgtools/overrides/compute/beta/firewall_policy_association.yaml @@ -0,0 +1,4 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/compute/firewall_policy_association.yaml b/tpgtools/overrides/compute/firewall_policy_association.yaml index ba8d27aa31cc..af851d79a0c9 100644 --- a/tpgtools/overrides/compute/firewall_policy_association.yaml +++ b/tpgtools/overrides/compute/firewall_policy_association.yaml @@ -1,4 +1,4 @@ - type: CUSTOMIZE_DIFF details: functions: - - tpgresource.DefaultProviderProject \ No newline at end of file + - tpgresource.DefaultProviderProject From 8ff36d326452a6ae220d06ca5e5bfb51f839a5b5 Mon Sep 17 00:00:00 2001 From: Will Yardley Date: Tue, 12 Nov 2024 14:54:39 -0800 Subject: [PATCH 050/105] pubsub: additional test permissions fixes (#12311) --- ...bscription_push_bq_service_account.tf.tmpl | 13 +++++---- .../resource_pubsub_subscription_test.go | 29 ++++++------------- 2 files changed, 17 insertions(+), 25 deletions(-) diff --git a/mmv1/templates/terraform/examples/pubsub_subscription_push_bq_service_account.tf.tmpl b/mmv1/templates/terraform/examples/pubsub_subscription_push_bq_service_account.tf.tmpl index 01c15668a72b..4de6be02d567 100644 --- a/mmv1/templates/terraform/examples/pubsub_subscription_push_bq_service_account.tf.tmpl +++ b/mmv1/templates/terraform/examples/pubsub_subscription_push_bq_service_account.tf.tmpl @@ -11,24 +11,27 @@ resource "google_pubsub_subscription" "{{$.PrimaryResourceId}}" { service_account_email = google_service_account.bq_write_service_account.email } - depends_on = [google_service_account.bq_write_service_account, google_project_iam_member.viewer, google_project_iam_member.editor] + depends_on = [ + google_service_account.bq_write_service_account, + google_project_iam_member.bigquery_metadata_viewer, + google_project_iam_member.bigquery_data_editor + ] } -data "google_project" "project" { -} +data "google_project" "project" {} resource "google_service_account" "bq_write_service_account" { account_id = "{{index $.Vars "service_account_id"}}" display_name = "BQ Write Service Account" } -resource "google_project_iam_member" "viewer" { +resource "google_project_iam_member" "bigquery_metadata_viewer" { project = data.google_project.project.project_id role = "roles/bigquery.metadataViewer" member = "serviceAccount:${google_service_account.bq_write_service_account.email}" } -resource "google_project_iam_member" "editor" { +resource "google_project_iam_member" "bigquery_data_editor" { project = data.google_project.project.project_id role = "roles/bigquery.dataEditor" member = "serviceAccount:${google_service_account.bq_write_service_account.email}" diff --git a/mmv1/third_party/terraform/services/pubsub/resource_pubsub_subscription_test.go b/mmv1/third_party/terraform/services/pubsub/resource_pubsub_subscription_test.go index 9be5b447b8e4..3c03898bbcb0 100644 --- a/mmv1/third_party/terraform/services/pubsub/resource_pubsub_subscription_test.go +++ b/mmv1/third_party/terraform/services/pubsub/resource_pubsub_subscription_test.go @@ -683,6 +683,7 @@ resource "google_pubsub_subscription" "foo" { func testAccPubsubSubscriptionBigQuery_basic(dataset, table, topic, subscription string, useTableSchema bool, serviceAccountId string) string { serviceAccountEmailField := "" serviceAccountResource := "" + tfDependencies := "" if serviceAccountId != "" { serviceAccountResource = fmt.Sprintf(` resource "google_service_account" "bq_write_service_account" { @@ -690,34 +691,24 @@ resource "google_service_account" "bq_write_service_account" { display_name = "BQ Write Service Account" } -resource "google_project_iam_member" "viewer" { +resource "google_project_iam_member" "bigquery_metadata_viewer" { project = data.google_project.project.project_id role = "roles/bigquery.metadataViewer" member = "serviceAccount:${google_service_account.bq_write_service_account.email}" } -resource "google_project_iam_member" "editor" { +resource "google_project_iam_member" "bigquery_data_editor" { project = data.google_project.project.project_id role = "roles/bigquery.dataEditor" member = "serviceAccount:${google_service_account.bq_write_service_account.email}" }`, serviceAccountId) serviceAccountEmailField = "service_account_email = google_service_account.bq_write_service_account.email" + tfDependencies = ` google_project_iam_member.bigquery_metadata_viewer, + google_project_iam_member.bigquery_data_editor, + time_sleep.wait_30_seconds,` } else { - serviceAccountResource = fmt.Sprintf(` -resource "google_project_iam_member" "viewer" { - project = data.google_project.project.project_id - role = "roles/bigquery.metadataViewer" - member = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-pubsub.iam.gserviceaccount.com" -} - -resource "google_project_iam_member" "editor" { - project = data.google_project.project.project_id - role = "roles/bigquery.dataEditor" - member = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-pubsub.iam.gserviceaccount.com" -} - `) + tfDependencies = " time_sleep.wait_30_seconds," } - return fmt.Sprintf(` data "google_project" "project" {} @@ -763,12 +754,10 @@ resource "google_pubsub_subscription" "foo" { } depends_on = [ - google_project_iam_member.viewer, - google_project_iam_member.editor, - time_sleep.wait_30_seconds, + %s ] } - `, serviceAccountResource, dataset, table, topic, subscription, useTableSchema, serviceAccountEmailField) + `, serviceAccountResource, dataset, table, topic, subscription, useTableSchema, serviceAccountEmailField, tfDependencies) } func testAccPubsubSubscriptionCloudStorage_basic(bucket, topic, subscription, filenamePrefix, filenameSuffix, filenameDatetimeFormat string, maxBytes int, maxDuration string, maxMessages int, serviceAccountId, outputFormat string) string { From 9958bae3d4c3148a7ba864c31e3b56d0af66669a Mon Sep 17 00:00:00 2001 From: Ian Milligan Date: Tue, 12 Nov 2024 15:09:07 -0800 Subject: [PATCH 051/105] Add Cloud Run v2 Service urls field (#12194) --- mmv1/products/cloudrunv2/Service.yaml | 7 +++++++ .../data_source_google_cloud_run_v2_service_test.go | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/mmv1/products/cloudrunv2/Service.yaml b/mmv1/products/cloudrunv2/Service.yaml index a6339cedd5d4..38b8dc966d88 100644 --- a/mmv1/products/cloudrunv2/Service.yaml +++ b/mmv1/products/cloudrunv2/Service.yaml @@ -1117,6 +1117,13 @@ properties: description: | The main URI in which this Service is serving traffic. output: true + - name: 'urls' + type: Array + item_type: + type: String + description: |- + All URLs serving traffic for this Service. + output: true - name: 'reconciling' type: Boolean description: | diff --git a/mmv1/third_party/terraform/services/cloudrunv2/data_source_google_cloud_run_v2_service_test.go b/mmv1/third_party/terraform/services/cloudrunv2/data_source_google_cloud_run_v2_service_test.go index cb5921fa2567..770d90993ad5 100644 --- a/mmv1/third_party/terraform/services/cloudrunv2/data_source_google_cloud_run_v2_service_test.go +++ b/mmv1/third_party/terraform/services/cloudrunv2/data_source_google_cloud_run_v2_service_test.go @@ -2,6 +2,7 @@ package cloudrunv2_test import ( "fmt" + "regexp" "testing" "github.com/hashicorp/terraform-plugin-testing/helper/resource" @@ -17,6 +18,10 @@ func TestAccDataSourceGoogleCloudRunV2Service_basic(t *testing.T) { name := fmt.Sprintf("tf-test-cloud-run-v2-service-%d", acctest.RandInt(t)) location := "us-central1" id := fmt.Sprintf("projects/%s/locations/%s/services/%s", project, location, name) + deterministicURLRegex, err := regexp.Compile(fmt.Sprintf("https://%s-[0-9]+.%s.run.ap", name, location)) + if err != nil { + t.Fatalf("Failed to compile deterministic URL regex: %v", err) + } acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, @@ -28,6 +33,8 @@ func TestAccDataSourceGoogleCloudRunV2Service_basic(t *testing.T) { resource.TestCheckResourceAttr("data.google_cloud_run_v2_service.hello", "id", id), resource.TestCheckResourceAttr("data.google_cloud_run_v2_service.hello", "name", name), resource.TestCheckResourceAttr("data.google_cloud_run_v2_service.hello", "location", location), + resource.TestCheckResourceAttr("data.google_cloud_run_v2_service.hello", "urls.#", "2"), + resource.TestMatchResourceAttr("data.google_cloud_run_v2_service.hello", "urls.0", deterministicURLRegex), ), }, }, From 9a45aa9a44634ac33a3cd7a1024be660accd7647 Mon Sep 17 00:00:00 2001 From: "Stephen Lewis (Burrows)" Date: Tue, 12 Nov 2024 15:09:15 -0800 Subject: [PATCH 052/105] Made google_container_cluster.user_managed_keys_config not settable and fixed diff due to server-set values (#12309) --- .../resource_container_cluster.go.tmpl | 26 ++- ...ce_container_cluster_internal_test.go.tmpl | 164 +++++++++++++++++- 2 files changed, 175 insertions(+), 15 deletions(-) diff --git a/mmv1/third_party/terraform/services/container/resource_container_cluster.go.tmpl b/mmv1/third_party/terraform/services/container/resource_container_cluster.go.tmpl index c82a92ddc8b6..a661ffbc58d1 100644 --- a/mmv1/third_party/terraform/services/container/resource_container_cluster.go.tmpl +++ b/mmv1/third_party/terraform/services/container/resource_container_cluster.go.tmpl @@ -2250,6 +2250,7 @@ func ResourceContainerCluster() *schema.Resource { "user_managed_keys_config": { Type: schema.TypeList, Optional: true, + ForceNew: true, MaxItems: 1, Description: `The custom keys configuration of the cluster.`, Elem: &schema.Resource{ @@ -4294,20 +4295,6 @@ func resourceContainerClusterUpdate(d *schema.ResourceData, meta interface{}) er log.Printf("[INFO] GKE cluster %s fleet config has been updated", d.Id()) } - if d.HasChange("user_managed_keys_config") { - req := &container.UpdateClusterRequest{ - Update: &container.ClusterUpdate{ - UserManagedKeysConfig: expandUserManagedKeysConfig(d.Get("user_managed_keys_config")), - }, - } - updateF := updateFunc(req, "updating GKE cluster user managed keys config.") - if err := transport_tpg.LockedCall(lockKey, updateF); err != nil { - return err - } - - log.Printf("[INFO] GKE cluster %s user managed key config has been updated to %#v", d.Id(), req.Update.UserManagedKeysConfig) - } - if d.HasChange("enable_k8s_beta_apis") { log.Print("[INFO] Enable Kubernetes Beta APIs") if v, ok := d.GetOk("enable_k8s_beta_apis"); ok { @@ -6691,11 +6678,22 @@ func flattenUserManagedKeysConfig(c *container.UserManagedKeysConfig) []map[stri "control_plane_disk_encryption_key": c.ControlPlaneDiskEncryptionKey, "gkeops_etcd_backup_encryption_key": c.GkeopsEtcdBackupEncryptionKey, } + allEmpty := true + for _, v := range f { + if v.(string) != "" { + allEmpty = false + } + } if len(c.ServiceAccountSigningKeys) != 0 { f["service_account_signing_keys"] = schema.NewSet(schema.HashString, tpgresource.ConvertStringArrToInterface(c.ServiceAccountSigningKeys)) + allEmpty = false } if len(c.ServiceAccountVerificationKeys) != 0 { f["service_account_verification_keys"] = schema.NewSet(schema.HashString, tpgresource.ConvertStringArrToInterface(c.ServiceAccountVerificationKeys)) + allEmpty = false + } + if allEmpty { + return nil } return []map[string]interface{}{f} } diff --git a/mmv1/third_party/terraform/services/container/resource_container_cluster_internal_test.go.tmpl b/mmv1/third_party/terraform/services/container/resource_container_cluster_internal_test.go.tmpl index 52eb636947b2..6a1870ba2eb8 100644 --- a/mmv1/third_party/terraform/services/container/resource_container_cluster_internal_test.go.tmpl +++ b/mmv1/third_party/terraform/services/container/resource_container_cluster_internal_test.go.tmpl @@ -3,9 +3,13 @@ package container import ( "testing" + "github.com/google/go-cmp/cmp" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-provider-google/google/tpgresource" -{{- if ne $.TargetVersionName "ga" }} + +{{ if eq $.TargetVersionName `ga` }} + "google.golang.org/api/container/v1" +{{- else }} container "google.golang.org/api/container/v1beta1" {{- end }} ) @@ -295,3 +299,161 @@ func TestContainerCluster_NodeVersionCustomizeDiff(t* testing.T) { } } } + +func TestContainerCluster_flattenUserManagedKeysConfig(t *testing.T) { + t.Parallel() + + cases := []struct { + name string + config *container.UserManagedKeysConfig + want []map[string]interface{} + }{ + { + name: "nil", + }, + { + name: "empty", + config: &container.UserManagedKeysConfig{}, + }, + { + name: "cluster_ca", + config: &container.UserManagedKeysConfig{ + ClusterCa: "value", + }, + want: []map[string]interface{}{ + { + "cluster_ca": "value", + "etcd_api_ca": "", + "etcd_peer_ca": "", + "aggregation_ca": "", + "control_plane_disk_encryption_key": "", + "gkeops_etcd_backup_encryption_key": "", + }, + }, + }, + { + name: "etcd_api_ca", + config: &container.UserManagedKeysConfig{ + EtcdApiCa: "value", + }, + want: []map[string]interface{}{ + { + "cluster_ca": "", + "etcd_api_ca": "value", + "etcd_peer_ca": "", + "aggregation_ca": "", + "control_plane_disk_encryption_key": "", + "gkeops_etcd_backup_encryption_key": "", + }, + }, + }, + { + name: "etcd_peer_ca", + config: &container.UserManagedKeysConfig{ + EtcdPeerCa: "value", + }, + want: []map[string]interface{}{ + { + "cluster_ca": "", + "etcd_api_ca": "", + "etcd_peer_ca": "value", + "aggregation_ca": "", + "control_plane_disk_encryption_key": "", + "gkeops_etcd_backup_encryption_key": "", + }, + }, + }, + { + name: "aggregation_ca", + config: &container.UserManagedKeysConfig{ + AggregationCa: "value", + }, + want: []map[string]interface{}{ + { + "cluster_ca": "", + "etcd_api_ca": "", + "etcd_peer_ca": "", + "aggregation_ca": "value", + "control_plane_disk_encryption_key": "", + "gkeops_etcd_backup_encryption_key": "", + }, + }, + }, + { + name: "control_plane_disk_encryption_key", + config: &container.UserManagedKeysConfig{ + ControlPlaneDiskEncryptionKey: "value", + }, + want: []map[string]interface{}{ + { + "cluster_ca": "", + "etcd_api_ca": "", + "etcd_peer_ca": "", + "aggregation_ca": "", + "control_plane_disk_encryption_key": "value", + "gkeops_etcd_backup_encryption_key": "", + }, + }, + }, + { + name: "gkeops_etcd_backup_encryption_key", + config: &container.UserManagedKeysConfig{ + GkeopsEtcdBackupEncryptionKey: "value", + }, + want: []map[string]interface{}{ + { + "cluster_ca": "", + "etcd_api_ca": "", + "etcd_peer_ca": "", + "aggregation_ca": "", + "control_plane_disk_encryption_key": "", + "gkeops_etcd_backup_encryption_key": "value", + }, + }, + }, + { + name: "service_account_signing_keys", + config: &container.UserManagedKeysConfig{ + ServiceAccountSigningKeys: []string{"value"}, + }, + want: []map[string]interface{}{ + { + "cluster_ca": "", + "etcd_api_ca": "", + "etcd_peer_ca": "", + "aggregation_ca": "", + "control_plane_disk_encryption_key": "", + "gkeops_etcd_backup_encryption_key": "", + "service_account_signing_keys": schema.NewSet(schema.HashString, []interface{}{"value"}), + }, + }, + }, + { + name: "service_account_verification_keys", + config: &container.UserManagedKeysConfig{ + ServiceAccountVerificationKeys: []string{"value"}, + }, + want: []map[string]interface{}{ + { + "cluster_ca": "", + "etcd_api_ca": "", + "etcd_peer_ca": "", + "aggregation_ca": "", + "control_plane_disk_encryption_key": "", + "gkeops_etcd_backup_encryption_key": "", + "service_account_verification_keys": schema.NewSet(schema.HashString, []interface{}{"value"}), + }, + }, + }, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + got := flattenUserManagedKeysConfig(tc.config) + if diff := cmp.Diff(got, tc.want); diff != "" { + t.Errorf("flattenUserManagedKeysConfig(%s) returned unexpected diff. +got, -want:\n%s", tc.name, diff) + } + }) + } +} From acda2f0f71f92d1b4ff964acffc4de6f88cd585a Mon Sep 17 00:00:00 2001 From: Will Yardley Date: Tue, 12 Nov 2024 15:37:42 -0800 Subject: [PATCH 053/105] compute: forced recreation of `google_compute_security_policy` on `type` updates (#12233) --- .../resource_compute_security_policy.go.tmpl | 1 + ...ource_compute_security_policy_test.go.tmpl | 56 ++++++++++++++++--- 2 files changed, 50 insertions(+), 7 deletions(-) diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_security_policy.go.tmpl b/mmv1/third_party/terraform/services/compute/resource_compute_security_policy.go.tmpl index c175d8012ddb..df7961e3eebc 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_security_policy.go.tmpl +++ b/mmv1/third_party/terraform/services/compute/resource_compute_security_policy.go.tmpl @@ -81,6 +81,7 @@ func ResourceComputeSecurityPolicy() *schema.Resource { Type: schema.TypeString, Optional: true, Computed: true, + ForceNew: true, Description: `The type indicates the intended use of the security policy. CLOUD_ARMOR - Cloud Armor backend security policies can be configured to filter incoming HTTP requests targeting backend services. They filter requests before they hit the origin servers. CLOUD_ARMOR_EDGE - Cloud Armor edge security policies can be configured to filter incoming HTTP requests targeting backend services (including Cloud CDN-enabled) as well as backend buckets (Cloud Storage). They filter requests before the request is served from Google's cache.`, ValidateFunc: validation.StringInSlice([]string{"CLOUD_ARMOR", "CLOUD_ARMOR_EDGE", "CLOUD_ARMOR_INTERNAL_SERVICE"}, false), }, diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_security_policy_test.go.tmpl b/mmv1/third_party/terraform/services/compute/resource_compute_security_policy_test.go.tmpl index a479836e1e96..27d2c3755737 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_security_policy_test.go.tmpl +++ b/mmv1/third_party/terraform/services/compute/resource_compute_security_policy_test.go.tmpl @@ -6,6 +6,7 @@ import ( "testing" "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/plancheck" "github.com/hashicorp/terraform-plugin-testing/terraform" "github.com/hashicorp/terraform-provider-google/google/acctest" "github.com/hashicorp/terraform-provider-google/google/envvar" @@ -22,7 +23,48 @@ func TestAccComputeSecurityPolicy_basic(t *testing.T) { CheckDestroy: testAccCheckComputeSecurityPolicyDestroyProducer(t), Steps: []resource.TestStep{ { - Config: testAccComputeSecurityPolicy_basic(spName), + Config: testAccComputeSecurityPolicy_basic(spName, "CLOUD_ARMOR"), + }, + { + ResourceName: "google_compute_security_policy.policy", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccComputeSecurityPolicy_basicUpdate(t *testing.T) { + t.Parallel() + + spName := fmt.Sprintf("tf-test-%s", acctest.RandString(t, 10)) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckComputeSecurityPolicyDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccComputeSecurityPolicy_basic(spName, "CLOUD_ARMOR"), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("google_compute_security_policy.policy", "type", "CLOUD_ARMOR"), + ), + }, + { + ResourceName: "google_compute_security_policy.policy", + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccComputeSecurityPolicy_basic(spName, "CLOUD_ARMOR_EDGE"), + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction("google_compute_security_policy.policy", plancheck.ResourceActionDestroyBeforeCreate), + }, + }, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("google_compute_security_policy.policy", "type", "CLOUD_ARMOR_EDGE"), + ), }, { ResourceName: "google_compute_security_policy.policy", @@ -212,7 +254,7 @@ func TestAccComputeSecurityPolicy_withAdvancedOptionsConfig(t *testing.T) { CheckDestroy: testAccCheckComputeSecurityPolicyDestroyProducer(t), Steps: []resource.TestStep{ { - Config: testAccComputeSecurityPolicy_basic(spName), + Config: testAccComputeSecurityPolicy_basic(spName, "CLOUD_ARMOR"), }, { ResourceName: "google_compute_security_policy.policy", @@ -254,7 +296,7 @@ func TestAccComputeSecurityPolicy_withAdvancedOptionsConfig(t *testing.T) { ImportStateVerify: true, }, { - Config: testAccComputeSecurityPolicy_basic(spName), + Config: testAccComputeSecurityPolicy_basic(spName, "CLOUD_ARMOR"), }, { ResourceName: "google_compute_security_policy.policy", @@ -534,7 +576,7 @@ func TestAccComputeSecurityPolicy_withRecaptchaOptionsConfig(t *testing.T) { CheckDestroy: testAccCheckComputeSecurityPolicyDestroyProducer(t), Steps: []resource.TestStep{ { - Config: testAccComputeSecurityPolicy_basic(spName), + Config: testAccComputeSecurityPolicy_basic(spName, "CLOUD_ARMOR"), }, { ResourceName: "google_compute_security_policy.policy", @@ -782,14 +824,14 @@ func testAccCheckComputeSecurityPolicyDestroyProducer(t *testing.T) func(s *terr } } -func testAccComputeSecurityPolicy_basic(spName string) string { +func testAccComputeSecurityPolicy_basic(spName, policyType string) string { return fmt.Sprintf(` resource "google_compute_security_policy" "policy" { name = "%s" description = "basic security policy" - type = "CLOUD_ARMOR" + type = "%s" } -`, spName) +`, spName, policyType) } func testAccComputeSecurityPolicy_withRule(spName string) string { From 6e63cbb89c64d07ef24486ead904f0856159933e Mon Sep 17 00:00:00 2001 From: Sam Levenick Date: Wed, 13 Nov 2024 12:29:48 -0500 Subject: [PATCH 054/105] Add update method checking to autogen parser (#12317) --- mmv1/api/resource.go | 8 ++++---- mmv1/openapi_generate/parser.go | 21 +++++++++++++++++++++ 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/mmv1/api/resource.go b/mmv1/api/resource.go index 771c780bb48b..8cc2743787b4 100644 --- a/mmv1/api/resource.go +++ b/mmv1/api/resource.go @@ -296,6 +296,10 @@ type Resource struct { Async *Async + // Tag autogen resources so that we can track them. In the future this will + // control if a resource is continuously generated from public OpenAPI docs + AutogenStatus string `yaml:"autogen_status"` + // The three groups of []*Type fields are expected to be strictly ordered within a yaml file // in the sequence of Virtual Fields -> Parameters -> Properties @@ -330,10 +334,6 @@ type Resource struct { ApiResourceTypeKind string `yaml:"api_resource_type_kind,omitempty"` ImportPath string `yaml:"-"` - - // Tag autogen resources so that we can track them. In the future this will - // control if a resource is continuously generated from public OpenAPI docs - AutogenStatus string `yaml:"autogen_status"` } func (r *Resource) UnmarshalYAML(unmarshal func(any) error) error { diff --git a/mmv1/openapi_generate/parser.go b/mmv1/openapi_generate/parser.go index 3c2a63344e89..efc542837270 100644 --- a/mmv1/openapi_generate/parser.go +++ b/mmv1/openapi_generate/parser.go @@ -253,6 +253,13 @@ func buildResource(filePath, resourcePath, resourceName string, root *openapi3.T async.Result.ResourceInsideResponse = true resource.Async = async + if hasUpdate(resourceName, root) { + resource.UpdateVerb = "PATCH" + resource.UpdateMask = true + } else { + resource.Immutable = true + } + example := r.Examples{} example.Name = "name_of_example_file" example.PrimaryResourceId = "example" @@ -268,6 +275,20 @@ func buildResource(filePath, resourcePath, resourceName string, root *openapi3.T return resource } +func hasUpdate(resourceName string, root *openapi3.T) bool { + // Create and Update have different paths in the OpenAPI spec, so look + // through all paths to find one that matches the expected operation name + for _, pathValue := range root.Paths.Map() { + if pathValue.Patch == nil { + continue + } + if pathValue.Patch.OperationID == fmt.Sprintf("Update%s", resourceName) { + return true + } + } + return false +} + func parseOpenApi(resourcePath, resourceName string, root *openapi3.T) []any { returnArray := []any{} path := root.Paths.Find(resourcePath) From 7936dccef4c44adfed8cb11f41de80eb5ab575f8 Mon Sep 17 00:00:00 2001 From: Will Yardley Date: Wed, 13 Nov 2024 10:25:05 -0800 Subject: [PATCH 055/105] networkservices: increased `path_matcher` and `host_rule` limits (#12260) --- .../networkservices/EdgeCacheService.yaml | 4 +- ...etwork_services_edge_cache_service_test.go | 194 +++++++++--------- 2 files changed, 100 insertions(+), 98 deletions(-) diff --git a/mmv1/products/networkservices/EdgeCacheService.yaml b/mmv1/products/networkservices/EdgeCacheService.yaml index ccf534758f9a..8dc29e7098a5 100644 --- a/mmv1/products/networkservices/EdgeCacheService.yaml +++ b/mmv1/products/networkservices/EdgeCacheService.yaml @@ -191,7 +191,7 @@ properties: The name of the pathMatcher associated with this hostRule. required: true min_size: 1 - max_size: 10 + max_size: 50 - name: 'path_matcher' type: Array description: | @@ -891,7 +891,7 @@ properties: min_size: 1 max_size: 200 min_size: 1 - max_size: 10 + max_size: 50 - name: 'logConfig' type: NestedObject description: | diff --git a/mmv1/third_party/terraform/services/networkservices/resource_network_services_edge_cache_service_test.go b/mmv1/third_party/terraform/services/networkservices/resource_network_services_edge_cache_service_test.go index 350520a1c357..fadd14ede05c 100644 --- a/mmv1/third_party/terraform/services/networkservices/resource_network_services_edge_cache_service_test.go +++ b/mmv1/third_party/terraform/services/networkservices/resource_network_services_edge_cache_service_test.go @@ -37,107 +37,109 @@ func TestAccNetworkServicesEdgeCacheService_updateAndImport(t *testing.T) { }, }) } + func testAccNetworkServicesEdgeCacheService_update_0(bktName, originName, serviceName string) string { return fmt.Sprintf(` - resource "google_storage_bucket" "dest" { - name = "%s" - location = "US" - force_destroy = true - } - resource "google_network_services_edge_cache_origin" "instance" { - name = "%s" - origin_address = google_storage_bucket.dest.url - description = "The default bucket for media edge test" - max_attempts = 2 - timeout { - connect_timeout = "10s" - } - } - resource "google_network_services_edge_cache_service" "served" { - name = "%s" - description = "some description" - routing { - host_rule { - description = "host rule description" - hosts = ["sslcert.tf-test.club"] - path_matcher = "routes" - } - path_matcher { - name = "routes" - route_rule { - description = "a route rule to match against" - priority = 1 - match_rule { - prefix_match = "/" - } - origin = google_network_services_edge_cache_origin.instance.name - route_action { - cdn_policy { - cache_mode = "CACHE_ALL_STATIC" - default_ttl = "3600s" - } - } - header_action { - response_header_to_add { - header_name = "x-cache-status" - header_value = "{cdn_cache_status}" - } - } - } - } - } - } +resource "google_storage_bucket" "dest" { + name = "%s" + location = "US" + force_destroy = true +} +resource "google_network_services_edge_cache_origin" "instance" { + name = "%s" + origin_address = google_storage_bucket.dest.url + description = "The default bucket for media edge test" + max_attempts = 2 + timeout { + connect_timeout = "10s" + } +} +resource "google_network_services_edge_cache_service" "served" { + name = "%s" + description = "some description" + routing { + host_rule { + description = "host rule description" + hosts = ["sslcert.tf-test.club"] + path_matcher = "routes" + } + path_matcher { + name = "routes" + route_rule { + description = "a route rule to match against" + priority = 1 + match_rule { + prefix_match = "/" + } + origin = google_network_services_edge_cache_origin.instance.name + route_action { + cdn_policy { + cache_mode = "CACHE_ALL_STATIC" + default_ttl = "3600s" + } + } + header_action { + response_header_to_add { + header_name = "x-cache-status" + header_value = "{cdn_cache_status}" + } + } + } + } + } +} `, bktName, originName, serviceName) } + func testAccNetworkServicesEdgeCacheService_update_1(bktName, originName, serviceName string) string { return fmt.Sprintf(` - resource "google_storage_bucket" "dest" { - name = "%s" - location = "US" - force_destroy = true - } - resource "google_network_services_edge_cache_origin" "instance" { - name = "%s" - origin_address = google_storage_bucket.dest.url - description = "The default bucket for media edge test" - max_attempts = 2 - timeout { - connect_timeout = "10s" - } - } - resource "google_network_services_edge_cache_service" "served" { - name = "%s" - description = "some description" - routing { - host_rule { - description = "host rule description" - hosts = ["sslcert.tf-test.club"] - path_matcher = "routes" - } - path_matcher { - name = "routes" - route_rule { - description = "a route rule to match against" - priority = 1 - match_rule { - prefix_match = "/" - } - origin = google_network_services_edge_cache_origin.instance.name - route_action { - cdn_policy { - cache_mode = "CACHE_ALL_STATIC" - default_ttl = "3600s" - } - } - header_action { - response_header_to_add { - header_name = "x-cache-status" - header_value = "{cdn_cache_status}" - } - } - } - } - } - } +resource "google_storage_bucket" "dest" { + name = "%s" + location = "US" + force_destroy = true +} +resource "google_network_services_edge_cache_origin" "instance" { + name = "%s" + origin_address = google_storage_bucket.dest.url + description = "The default bucket for media edge test" + max_attempts = 2 + timeout { + connect_timeout = "10s" + } +} +resource "google_network_services_edge_cache_service" "served" { + name = "%s" + description = "some description" + routing { + host_rule { + description = "host rule description" + hosts = ["sslcert.tf-test.club"] + path_matcher = "routes" + } + path_matcher { + name = "routes" + route_rule { + description = "a route rule to match against" + priority = 1 + match_rule { + prefix_match = "/" + } + origin = google_network_services_edge_cache_origin.instance.name + route_action { + cdn_policy { + cache_mode = "CACHE_ALL_STATIC" + default_ttl = "3600s" + } + } + header_action { + response_header_to_add { + header_name = "x-cache-status" + header_value = "{cdn_cache_status}" + } + } + } + } + } +} `, bktName, originName, serviceName) } From a39b35536d101b5a79e24457fa81c3d6ceddeb2c Mon Sep 17 00:00:00 2001 From: Thomas Rodgers Date: Wed, 13 Nov 2024 11:36:31 -0800 Subject: [PATCH 056/105] Migrate compute firewall policy rule in GA (#12310) --- mmv1/products/compute/FirewallPolicyRule.yaml | 1 - .../terraform/examples/firewall_policy_rule.tf.tmpl | 8 -------- .../terraform/services/compute/compute_operation.go.tmpl | 9 --------- tpgtools/overrides/compute/firewall_policy_rule.yaml | 8 -------- 4 files changed, 26 deletions(-) delete mode 100644 tpgtools/overrides/compute/firewall_policy_rule.yaml diff --git a/mmv1/products/compute/FirewallPolicyRule.yaml b/mmv1/products/compute/FirewallPolicyRule.yaml index 28e3674a2911..1264e8cd3345 100644 --- a/mmv1/products/compute/FirewallPolicyRule.yaml +++ b/mmv1/products/compute/FirewallPolicyRule.yaml @@ -16,7 +16,6 @@ name: 'FirewallPolicyRule' kind: 'compute#firewallPolicyRule' description: | Represents a rule that describes one or more match conditions along with the action to be taken when traffic matches this condition (allow or deny). -min_version: 'beta' references: guides: api: 'https://cloud.google.com/compute/docs/reference/rest/v1/firewallPolicies/addRule' diff --git a/mmv1/templates/terraform/examples/firewall_policy_rule.tf.tmpl b/mmv1/templates/terraform/examples/firewall_policy_rule.tf.tmpl index 3309cb78d89e..5a8b09187625 100644 --- a/mmv1/templates/terraform/examples/firewall_policy_rule.tf.tmpl +++ b/mmv1/templates/terraform/examples/firewall_policy_rule.tf.tmpl @@ -1,6 +1,4 @@ resource "google_network_security_address_group" "basic_global_networksecurity_address_group" { - provider = google-beta - name = "{{index $.Vars "address"}}" parent = "organizations/{{index $.TestEnvVars "org_id"}}" description = "Sample global networksecurity_address_group" @@ -11,24 +9,18 @@ resource "google_network_security_address_group" "basic_global_networksecurity_a } resource "google_folder" "folder" { - provider = google-beta - display_name = "{{index $.Vars "folder"}}" parent = "organizations/{{index $.TestEnvVars "org_id"}}" deletion_protection = false } resource "google_compute_firewall_policy" "default" { - provider = google-beta - parent = google_folder.folder.id short_name = "{{index $.Vars "fw_policy"}}" description = "Resource created for Terraform acceptance testing" } resource "google_compute_firewall_policy_rule" "{{$.PrimaryResourceId}}" { - provider = google-beta - firewall_policy = google_compute_firewall_policy.default.name description = "Resource created for Terraform acceptance testing" priority = 9000 diff --git a/mmv1/third_party/terraform/services/compute/compute_operation.go.tmpl b/mmv1/third_party/terraform/services/compute/compute_operation.go.tmpl index 1c9b176575e5..1b0fe8319a8f 100644 --- a/mmv1/third_party/terraform/services/compute/compute_operation.go.tmpl +++ b/mmv1/third_party/terraform/services/compute/compute_operation.go.tmpl @@ -3,9 +3,7 @@ package compute import ( "bytes" "context" -{{- if ne $.TargetVersionName "ga" }} "encoding/json" -{{- end }} "errors" "fmt" "io" @@ -27,9 +25,7 @@ type ComputeOperationWaiter struct { Op *compute.Operation Context context.Context Project string -{{- if ne $.TargetVersionName "ga" }} Parent string -{{- end }} } func (w *ComputeOperationWaiter) State() string { @@ -86,10 +82,8 @@ func (w *ComputeOperationWaiter) QueryOp() (interface{}, error) { } else if w.Op.Region != "" { region := tpgresource.GetResourceNameFromSelfLink(w.Op.Region) return w.Service.RegionOperations.Get(w.Project, region, w.Op.Name).Do() -{{- if ne $.TargetVersionName "ga" }} } else if w.Parent != "" { return w.Service.GlobalOrganizationOperations.Get(w.Op.Name).ParentId(w.Parent).Do() -{{- end }} } return w.Service.GlobalOperations.Get(w.Project, w.Op.Name).Do() } @@ -130,7 +124,6 @@ func ComputeOperationWaitTime(config *transport_tpg.Config, res interface{}, pro return tpgresource.OperationWait(w, activity, timeout, config.PollInterval) } -{{ if ne $.TargetVersionName `ga` -}} func ComputeOrgOperationWaitTimeWithResponse(config *transport_tpg.Config, res interface{}, response *map[string]interface{}, parent, activity, userAgent string, timeout time.Duration) error { op := &compute.Operation{} err := tpgresource.Convert(res, op) @@ -157,8 +150,6 @@ func ComputeOrgOperationWaitTimeWithResponse(config *transport_tpg.Config, res i return json.Unmarshal(e, response) } -{{ end }} - // ComputeOperationError wraps compute.OperationError and implements the // error interface so it can be returned. type ComputeOperationError compute.OperationError diff --git a/tpgtools/overrides/compute/firewall_policy_rule.yaml b/tpgtools/overrides/compute/firewall_policy_rule.yaml deleted file mode 100644 index fb5004c97989..000000000000 --- a/tpgtools/overrides/compute/firewall_policy_rule.yaml +++ /dev/null @@ -1,8 +0,0 @@ -- type: DIFF_SUPPRESS_FUNC - field: target_resources - details: - diffsuppressfunc: tpgresource.CompareSelfLinkOrResourceName -- type: CUSTOMIZE_DIFF - details: - functions: - - tpgresource.DefaultProviderProject \ No newline at end of file From 4f92f5973c486d0bb16679e5f31352ebd5bf1019 Mon Sep 17 00:00:00 2001 From: Will Yardley Date: Wed, 13 Nov 2024 12:25:12 -0800 Subject: [PATCH 057/105] container: fix `TestAccContainerCluster_withFleetConfig` failure (#12307) --- .../services/container/resource_container_cluster_test.go.tmpl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mmv1/third_party/terraform/services/container/resource_container_cluster_test.go.tmpl b/mmv1/third_party/terraform/services/container/resource_container_cluster_test.go.tmpl index cdbe59ad610d..67d6655fa2ba 100644 --- a/mmv1/third_party/terraform/services/container/resource_container_cluster_test.go.tmpl +++ b/mmv1/third_party/terraform/services/container/resource_container_cluster_test.go.tmpl @@ -5232,7 +5232,8 @@ func TestAccContainerCluster_withFleetConfig(t *testing.T) { ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, { - Config: testAccContainerCluster_withFleetConfig(clusterName, "random-project", networkName, subnetworkName), + // This project must exist, though no permissions are needed on it. + Config: testAccContainerCluster_withFleetConfig(clusterName, "tdx-guest-images", networkName, subnetworkName), ExpectError: regexp.MustCompile(`changing existing fleet host project is not supported`), }, { From 4dc6dd682322acd250fcbf5c2f7950a71dc0f5af Mon Sep 17 00:00:00 2001 From: Zhenhua Li Date: Wed, 13 Nov 2024 12:27:10 -0800 Subject: [PATCH 058/105] Remove unused id list from ImportIdFormatsFromResource function (#12321) --- mmv1/api/resource.go | 5 ----- 1 file changed, 5 deletions(-) diff --git a/mmv1/api/resource.go b/mmv1/api/resource.go index 8cc2743787b4..3edcd10210c1 100644 --- a/mmv1/api/resource.go +++ b/mmv1/api/resource.go @@ -1007,11 +1007,6 @@ func (r Resource) TerraformName() string { } func (r Resource) ImportIdFormatsFromResource() []string { - - var ids []string - for _, id := range r.GetIdentity() { - ids = append(ids, google.Underscore(id.Name)) - } return ImportIdFormats(r.ImportFormat, r.Identity, r.BaseUrl) } From b27a58f8e22ee1e01f7e7914b21974e478437bd7 Mon Sep 17 00:00:00 2001 From: Iris Chen <10179943+iyabchen@users.noreply.github.com> Date: Wed, 13 Nov 2024 12:53:27 -0800 Subject: [PATCH 059/105] support skip_test option in yaml file (#12273) Co-authored-by: Stephen Lewis (Burrows) --- mmv1/api/resource/examples.go | 4 ++++ .../terraform/examples/base_configs/test_file.go.tmpl | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/mmv1/api/resource/examples.go b/mmv1/api/resource/examples.go index 7130c5b0d655..e01d1c48dc5c 100644 --- a/mmv1/api/resource/examples.go +++ b/mmv1/api/resource/examples.go @@ -149,6 +149,10 @@ type Examples struct { // Or a config with two fine grained resources that have a race condition during create SkipVcr bool `yaml:"skip_vcr,omitempty"` + // The reason to skip a test. For example, a link to a ticket explaining the issue that needs to be resolved before + // unskipping the test. If this is not empty, the test will be skipped. + SkipTest string `yaml:"skip_test,omitempty"` + // Specify which external providers are needed for the testcase. // Think before adding as there is latency and adds an external dependency to // your test so avoid if you can. diff --git a/mmv1/templates/terraform/examples/base_configs/test_file.go.tmpl b/mmv1/templates/terraform/examples/base_configs/test_file.go.tmpl index 140166e339db..197407eb4bcc 100644 --- a/mmv1/templates/terraform/examples/base_configs/test_file.go.tmpl +++ b/mmv1/templates/terraform/examples/base_configs/test_file.go.tmpl @@ -38,6 +38,10 @@ import ( ) {{ range $e := $.Res.TestExamples }} func TestAcc{{ $e.TestSlug $.Res.ProductMetadata.Name $.Res.Name }}(t *testing.T) { + {{- if $e.SkipTest }} + t.Skip("{{$e.SkipTest}}") + {{- end }} + {{- if $e.SkipVcr }} acctest.SkipIfVcr(t) {{- end }} From d1c06aec3336adcaca9cc0ffa12b090a9517d8fd Mon Sep 17 00:00:00 2001 From: nityaravi <32396647+nityaravi@users.noreply.github.com> Date: Thu, 14 Nov 2024 11:32:24 -0500 Subject: [PATCH 060/105] addressing b/378725229 (#12322) Co-authored-by: Nitya Ravi Co-authored-by: Stephen Lewis (Burrows) --- docs/content/_index.md | 104 ++++++++++++++++-- .../{get-started => }/contribution-process.md | 5 +- .../make-a-breaking-change.md | 2 +- docs/content/develop/custom-code.md | 2 +- docs/content/develop/promote-to-ga.md | 2 +- docs/content/develop/resource.md | 6 +- docs/content/develop/test/test.md | 2 +- .../content/get-started/generate-providers.md | 6 +- .../get-started/how-magic-modules-works.md | 59 ---------- 9 files changed, 110 insertions(+), 78 deletions(-) rename docs/content/{get-started => }/contribution-process.md (92%) delete mode 100644 docs/content/get-started/how-magic-modules-works.md diff --git a/docs/content/_index.md b/docs/content/_index.md index 294e44cb1440..ef60d84e8dc7 100644 --- a/docs/content/_index.md +++ b/docs/content/_index.md @@ -1,12 +1,16 @@ --- title: "Overview" +weight: 20 +aliases: + - /docs/how-to/types-of-resources + - /how-to/types-of-resources + - /get-started/how-magic-modules-works --- - # Magic Modules Magic Modules is a code generator and CI system that's used to develop the Terraform providers -for Google Platform, [`google`](https://github.com/hashicorp/terraform-provider-google) (or TPG) and +for Google Cloud, [`google`](https://github.com/hashicorp/terraform-provider-google) (or TPG) and [`google-beta`](https://github.com/hashicorp/terraform-provider-google-beta) (or TPGB). Magic Modules allows contributors to make changes against a single codebase and develop both @@ -15,13 +19,97 @@ provider versions simultaneously. After sending a pull request against this repo complete output, running presubmit tests, and updating the providers following your change. -## Getting started +## How Magic Modules works + +Magic Modules can be thought of as a source of truth for how to map a Google Cloud API resource +representation to a Terraform resource (or datasource) representation. Magic Modules uses that mapping +(and additional handwritten code where necessary) to generate "downstream" repositories - in particular, +the Terraform providers for Google Cloud: [`google`](https://github.com/hashicorp/terraform-provider-google) +(or TPG) and [`google-beta`](https://github.com/hashicorp/terraform-provider-google-beta) (or TPGB). + +Generation of the downstream repositories happens for every new commit in a PR (to a temporary branch owned by +the [`modular-magician`](https://github.com/modular-magician/) robot user) and on every merge into the main branch +(to the main branch of downstreams). Generation for PR commits allows contributors to manually examine the changes, +as well as allowing automatic running of unit tests, acceptance tests, and automated checks such as breaking change +detection. + +### Resource types + +There are three types of resources supported by Magic Modules: + ++ MMv1 ++ Handwritten ++ DCL/tpgtools + +The following sections describe these tools in detail. + +#### MMv1 + +MMv1 consists of a set of "products"; each product contains one or more "resources". + +Each product has a folder in +[`magic-modules/mmv1/products`](https://github.com/GoogleCloudPlatform/magic-modules/tree/main/mmv1/products). +The name of the folder is the "product name", which usually corresponds to the API subdomain covered by the +product (such as `compute.googleapis.com`). Each product folder contains a product configuration file +(`product.yaml`) and one or more resource configuration files (`ResourceName.yaml`). The actual name of a +`ResourceName.yaml` file usually matches the name of a GCP API resource in the product's subdomain. + +MMv1 resource configurations may reference handwritten code stored in +[`magic-modules/mmv1/templates/terraform`](https://github.com/GoogleCloudPlatform/magic-modules/tree/main/mmv1/templates/terraform), +which will be injected into the generated resource file. Many MMv1 resources also have one or more handwritten tests, +which are stored in the appropriate service folder inside +[`magic-modules/mmv1/third_party/terraform/services`](https://github.com/GoogleCloudPlatform/magic-modules/tree/main/mmv1/third_party/terraform/services). + +In the providers, MMv1-based resources are stored in `PROVIDER/services/PRODUCT/resource_PRODUCT_RESOURCE.go`, where `PROVIDER` +is `google` or `google-beta`, `PRODUCT` is the product name, and RESOURCE is the GCP API resource's name converted to +[snake case ↗](https://en.wikipedia.org/wiki/Snake_case). + +MMv1-based files start with the following header: + +``` +***     AUTO GENERATED CODE    ***    Type: MMv1     *** +``` + +#### Handwritten + +Handwritten resources and datasources are technically part of MMv1; however, they are not generated from YAML configurations. +Instead, they are written as Go code with minimal go template "version guards" to exclude beta-only features from the `google` +provider. + +Handwritten resources and datasources can be grouped by "service", which generally corresponds to the API subdomain the resource +or datasource interacts with. + +In addition to the core implementation, handwritten resources and datasources will also have documentation, tests, and sweepers +(which clean up stray resources left behind by tests). Each type of code is stored in the following locations: + ++ Resource & datasource implementation: In the appropriate service folder inside + [`magic-modules/mmv1/third_party/terraform/services`](https://github.com/GoogleCloudPlatform/magic-modules/tree/main/mmv1/third_party/terraform/services) ++ Resource documentation: + [`magic-modules/mmv1/third_party/terraform/website/docs/r`](https://github.com/GoogleCloudPlatform/magic-modules/tree/main/mmv1/third_party/terraform/website/docs/r) ++ Datasource documentation: + [`magic-modules/mmv1/third_party/terraform/website/docs/d`](https://github.com/GoogleCloudPlatform/magic-modules/tree/main/mmv1/third_party/terraform/website/docs/d) ++ Tests: In the appropriate service folder inside + [`magic-modules/mmv1/third_party/terraform/services`](https://github.com/GoogleCloudPlatform/magic-modules/tree/main/mmv1/third_party/terraform/services) ++ Sweepers: [`magic-modules/mmv1/third_party/terraform/utils`](https://github.com/GoogleCloudPlatform/magic-modules/tree/main/mmv1/third_party/terraform/utils) + +In the providers, handwritten resources and datasources are stored in `PROVIDER/services/SERVICE/FILENAME.go`, where `PROVIDER` +is `google` or `google-beta`, `SERVICE` is the service name, and `FILENAME` is the name of the handwritten file in magic-modules. +Handwritten files do not have an `AUTO GENERATED CODE` header. + +#### DCL aka tpgtools (maintenance mode) + +DCL / tpgtools is similar to MMv1; however, it is in maintenance mode, which means that new resources using the DCL are not being added. + +DCL-based files start with the following header: + +``` +***     AUTO GENERATED CODE    ***    Type: DCL     *** +``` -Check out the [setup guide]({{< ref "/get-started/generate-providers" >}}) for information on how to set up your environment. ## Other Resources -* [Extending Terraform](https://www.terraform.io/plugin) - * [How Terraform Works](https://www.terraform.io/plugin/how-terraform-works) - * [Writing Custom Providers / Calling APIs with Terraform Providers](https://learn.hashicorp.com/collections/terraform/providers?utm_source=WEBSITE&utm_medium=WEB_IO&utm_offer=ARTICLE_PAGE&utm_content=DOCS) -* [Terraform Glossary](https://www.terraform.io/docs/glossary) ++ [Extending Terraform](https://www.terraform.io/plugin) + + [How Terraform Works](https://www.terraform.io/plugin/how-terraform-works) + + [Writing Custom Providers / Calling APIs with Terraform Providers](https://learn.hashicorp.com/collections/terraform/providers?utm_source=WEBSITE&utm_medium=WEB_IO&utm_offer=ARTICLE_PAGE&utm_content=DOCS) ++ [Terraform Glossary](https://www.terraform.io/docs/glossary) diff --git a/docs/content/get-started/contribution-process.md b/docs/content/contribution-process.md similarity index 92% rename from docs/content/get-started/contribution-process.md rename to docs/content/contribution-process.md index bda0300dfbdd..89ff42a68ed0 100644 --- a/docs/content/get-started/contribution-process.md +++ b/docs/content/contribution-process.md @@ -1,14 +1,17 @@ --- title: "Contribution process" -weight: 50 +weight: 9 aliases: - /docs/getting-started/contributing - /getting-started/contributing - /get-started/contributing + - /get-started/contribution-process --- # Contribution process +This page explains how you can contribute code and documentation to the `magic-modules` repository. + ## Before you begin 1. Familiarize yourself with [GitHub flow](https://docs.github.com/en/get-started/quickstart/github-flow) diff --git a/docs/content/develop/breaking-changes/make-a-breaking-change.md b/docs/content/develop/breaking-changes/make-a-breaking-change.md index 47f3e09d227c..bb4e62499955 100644 --- a/docs/content/develop/breaking-changes/make-a-breaking-change.md +++ b/docs/content/develop/breaking-changes/make-a-breaking-change.md @@ -174,7 +174,7 @@ or resource. It is also great to log warnings at runtime if possible. When working on your breaking change, make sure that your base branch is `FEATURE-BRANCH-major-release-{{% param "majorVersion" %}}`. This means that you will follow the standard -[contribution process]({{< ref "/get-started/contribution-process" >}}) +[contribution process]({{< ref "/contribution-process" >}}) with the following changes: 1. Before you start, check out and sync your local `magic-modules` and provider diff --git a/docs/content/develop/custom-code.md b/docs/content/develop/custom-code.md index b769ce1bf83f..c5ae9dea9996 100644 --- a/docs/content/develop/custom-code.md +++ b/docs/content/develop/custom-code.md @@ -5,7 +5,7 @@ weight: 39 # Add custom resource code -This document covers how to add "custom code" to [MMv1 resources]({{< ref "/get-started/how-magic-modules-works#mmv1" >}}). Custom code can be used to add arbitrary logic to a resource while still generating most of the code; it allows for a balance between maintainability and supporting real-worlds APIs that deviate from what MMv1 can support. Custom code should only be added if the desired behavior can't be achieved otherwise. +This document covers how to add "custom code" to [MMv1 resources]({{< ref "/#mmv1" >}}). Custom code can be used to add arbitrary logic to a resource while still generating most of the code; it allows for a balance between maintainability and supporting real-worlds APIs that deviate from what MMv1 can support. Custom code should only be added if the desired behavior can't be achieved otherwise. Most custom code attributes are strings that contain a path to a template file relative to the `mmv1` directory. For example: diff --git a/docs/content/develop/promote-to-ga.md b/docs/content/develop/promote-to-ga.md index 91c64fb3252e..c03bcefcc83f 100644 --- a/docs/content/develop/promote-to-ga.md +++ b/docs/content/develop/promote-to-ga.md @@ -9,7 +9,7 @@ This document describes how to promote an existing resource or field that uses M Handwritten code (including `custom_code`) commonly uses "version guards" in the form of `{{- if ne $.TargetVersionName "ga" }}...{{- end }}` to wrap code that is beta-specific, which need to be removed during promotion. -For more information about types of resources and the generation process overall, see [How Magic Modules works]({{< ref "/get-started/how-magic-modules-works.md" >}}). +For more information about types of resources and the generation process overall, see [How Magic Modules works]({{< ref "/" >}}). ## Before you begin diff --git a/docs/content/develop/resource.md b/docs/content/develop/resource.md index c6ccb54ce843..eaf9dfe454c2 100644 --- a/docs/content/develop/resource.md +++ b/docs/content/develop/resource.md @@ -27,11 +27,11 @@ aliases: This page describes how to add a new resource to the `google` or `google-beta` Terraform provider using MMv1 and/or handwritten code. -For more information about types of resources and the generation process overall, see [How Magic Modules works]({{< ref "/get-started/how-magic-modules-works.md" >}}). +For more information about types of resources and the generation process overall, see [How Magic Modules works]({{< ref "/" >}}). ## Before you begin -1. Complete the [Generate the providers]({{< ref "/get-started/generate-providers" >}}) quickstart to set up your environment and your Google Cloud project. +1. Complete the steps in [Generate the providers]({{< ref "/get-started/generate-providers" >}}) to set up your environment and your Google Cloud project. 2. Ensure that your `magic-modules`, `terraform-provider-google`, and `terraform-provider-google-beta` repositories are up to date. ``` cd ~/magic-modules @@ -46,7 +46,7 @@ For more information about types of resources and the generation process overall {{< tabs "resource" >}} {{< tab "MMv1" >}} -1. Using an editor of your choice, in the appropriate [product folder]({{}}), create a file called `RESOURCE_NAME.yaml`. Replace `RESOURCE_NAME` with the name of the API resource you are adding support for. For example, a configuration file for [NatAddress](https://cloud.google.com/apigee/docs/reference/apis/apigee/rest/v1/organizations.instances.natAddresses) would be called `NatAddress.yaml`. +1. Using an editor of your choice, in the appropriate [product folder]({{}}), create a file called `RESOURCE_NAME.yaml`. Replace `RESOURCE_NAME` with the name of the API resource you are adding support for. For example, a configuration file for [NatAddress](https://cloud.google.com/apigee/docs/reference/apis/apigee/rest/v1/organizations.instances.natAddresses) would be called `NatAddress.yaml`. 2. Copy the following template into the new file: ```yaml # Copyright 2024 Google Inc. diff --git a/docs/content/develop/test/test.md b/docs/content/develop/test/test.md index 4d3bc2c6343b..d6e55784cf1b 100644 --- a/docs/content/develop/test/test.md +++ b/docs/content/develop/test/test.md @@ -26,7 +26,7 @@ For more information about testing, see the [official Terraform documentation](h ## Before you begin -1. Determine whether your resources is using [MMv1 generation or handwritten]({{}}). +1. Determine whether your resources is using [MMv1 generation or handwritten]({{}}). 2. If you are not adding tests to an in-progress PR, ensure that your `magic-modules`, `terraform-provider-google`, and `terraform-provider-google-beta` repositories are up to date. ```bash cd ~/magic-modules diff --git a/docs/content/get-started/generate-providers.md b/docs/content/get-started/generate-providers.md index 41beb7a57c3c..eaf0e1ae109e 100644 --- a/docs/content/get-started/generate-providers.md +++ b/docs/content/get-started/generate-providers.md @@ -192,6 +192,6 @@ gcloud auth revoke ## What's next -- [Learn about Magic Modules]({{< ref "/get-started/how-magic-modules-works.md" >}}) -- [Learn about the contribution process]({{< ref "/get-started/contribution-process.md" >}}) -- [Learn about make commands]({{< ref "/reference/make-commands.md" >}}) +- [Learn about Magic Modules]({{< ref "/" >}}) +- [Learn about the contribution process]({{< ref "/contribution-process.md" >}}) +- [Learn about make commands]({{< ref "/reference/make-commands.md" >}}) \ No newline at end of file diff --git a/docs/content/get-started/how-magic-modules-works.md b/docs/content/get-started/how-magic-modules-works.md deleted file mode 100644 index 520bf739eb70..000000000000 --- a/docs/content/get-started/how-magic-modules-works.md +++ /dev/null @@ -1,59 +0,0 @@ ---- -title: "How Magic Modules works" -weight: 20 -aliases: - - /docs/how-to/types-of-resources - - /how-to/types-of-resources ---- - -# How Magic Modules works - -Magic Modules can be thought of as a source of truth for how to map a GCP API resource representation to a Terraform resource (or datasource) representation. Magic Modules uses that mapping (and additional handwritten code where necessary) to generate "downstream" repositories - in particular, the Terraform providers for Google Cloud: [`google`](https://github.com/hashicorp/terraform-provider-google) (or TPG) and [`google-beta`](https://github.com/hashicorp/terraform-provider-google-beta) (or TPGB). - -Generation of the downstream repositories happens for every new commit in a PR (to a temporary branch owned by the [`modular-magician`](https://github.com/modular-magician/) robot user) and on every merge into the main branch (to the main branch of downstreams). Generation for PR commits allows contributors to manually examine the changes, as well as allowing automatic running of unit tests, acceptance tests, and automated checks such as breaking change detection. - -## Resource types - -There are three types of resources supported by Magic Modules: MMv1, Handwritten, and DCL/tpgtools. These are described in more detail in the following sections. - -### MMv1 - -MMv1 consists of a set of "products"; each product contains one or more "resources". - -Each product has a folder in [`magic-modules/mmv1/products`](https://github.com/GoogleCloudPlatform/magic-modules/tree/main/mmv1/products). The name of the folder is the "product name", which usually corresponds to the API subdomain covered by the product (such as `compute.googleapis.com`). Each product folder contains a product configuration file (`product.yaml`) and one or more resource configuration files (`ResourceName.yaml`). The actual name of a `ResourceName.yaml` file usually matches the name of a GCP API resource in the product's subdomain. - -MMv1 resource configurations may reference handwritten code stored in [`magic-modules/mmv1/templates/terraform`](https://github.com/GoogleCloudPlatform/magic-modules/tree/main/mmv1/templates/terraform), which will be injected into the generated resource file. Many MMv1 resources also have one or more handwritten tests, which are stored in the appropriate service folder inside [`magic-modules/mmv1/third_party/terraform/services`](https://github.com/GoogleCloudPlatform/magic-modules/tree/main/mmv1/third_party/terraform/services) - -In the providers, MMv1-based resources are stored in `PROVIDER/services/PRODUCT/resource_PRODUCT_RESOURCE.go`, where `PROVIDER` is `google` or `google-beta`, `PRODUCT` is the product name, and RESOURCE is the GCP API resource's name converted to [snake case ↗](https://en.wikipedia.org/wiki/Snake_case). - -MMv1-based files start with the following header: - -``` -*** AUTO GENERATED CODE *** Type: MMv1 *** -``` - -### Handwritten - -Handwritten resources and datasources are technically part of MMv1; however, they are not generated from YAML configurations. Instead, they are written as Go code with minimal go template "version guards" to exclude beta-only features from the `google` provider. - -Handwritten resources and datasources can be grouped by "service", which generally corresponds to the API subdomain the resource or datasource interacts with. - -In addition to the core implementation, handwritten resources and datasources will also have documentation, tests, and sweepers (which clean up stray resources left behind by tests). Each type of code is stored in the following locations: - -- Resource & datasource implementation: In the appropriate service folder inside [`magic-modules/mmv1/third_party/terraform/services`](https://github.com/GoogleCloudPlatform/magic-modules/tree/main/mmv1/third_party/terraform/services) -- Resource documentation: [`magic-modules/mmv1/third_party/terraform/website/docs/r`](https://github.com/GoogleCloudPlatform/magic-modules/tree/main/mmv1/third_party/terraform/website/docs/r) -- Datasource documentation: [`magic-modules/mmv1/third_party/terraform/website/docs/d`](https://github.com/GoogleCloudPlatform/magic-modules/tree/main/mmv1/third_party/terraform/website/docs/d) -- Tests: In the appropriate service folder inside [`magic-modules/mmv1/third_party/terraform/services`](https://github.com/GoogleCloudPlatform/magic-modules/tree/main/mmv1/third_party/terraform/services) -- Sweepers: [`magic-modules/mmv1/third_party/terraform/utils`](https://github.com/GoogleCloudPlatform/magic-modules/tree/main/mmv1/third_party/terraform/utils) - -In the providers, handwritten resources and datasources are stored in `PROVIDER/services/SERVICE/FILENAME.go`, where `PROVIDER` is `google` or `google-beta`, `SERVICE` is the service name, and `FILENAME` is the name of the handwritten file in magic-modules. Handwritten files do not have an `AUTO GENERATED CODE` header. - -### DCL aka tpgtools (maintenance mode) - -DCL / tpgtools is similar to MMv1; however, it is in maintenance mode, which means that new resources using the DCL are not being added. - -DCL-based files start with the following header: - -``` -*** AUTO GENERATED CODE *** Type: DCL *** -``` From 01701dc5ba715d63ec8ac50003dfcf3ffe776704 Mon Sep 17 00:00:00 2001 From: Sarah French <15078782+SarahFrench@users.noreply.github.com> Date: Thu, 14 Nov 2024 17:49:10 +0000 Subject: [PATCH 061/105] Make top-level immutable field more visible in the contribution guide (#12328) --- docs/content/develop/resource.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/develop/resource.md b/docs/content/develop/resource.md index eaf9dfe454c2..1e1e8107e2f4 100644 --- a/docs/content/develop/resource.md +++ b/docs/content/develop/resource.md @@ -92,7 +92,7 @@ For more information about types of resources and the generation process overall # If true, the resource and all its fields are considered immutable - that is, # only creatable, not updatable. Individual fields can override this if they # have a custom update method in the API. - # immutable: true + immutable: true # URL for the resource's standard Create method, including query parameters. # https://google.aip.dev/133 From 66325604d06fe60dadef5e71ef5f3985827735d1 Mon Sep 17 00:00:00 2001 From: Sarah French <15078782+SarahFrench@users.noreply.github.com> Date: Thu, 14 Nov 2024 18:03:02 +0000 Subject: [PATCH 062/105] Update `clean-provider` target in GNUmakefile to not remove TPG/TPGB CODEOWNERS files (#12274) --- GNUmakefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GNUmakefile b/GNUmakefile index 118b5aabe343..bc83284d3c00 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -75,7 +75,7 @@ tpgtools: clean-provider: cd $(OUTPUT_PATH);\ go mod download;\ - find . -type f -not -wholename "./.git*" -not -wholename "./.changelog*" -not -name ".travis.yml" -not -name ".golangci.yml" -not -name "CHANGELOG.md" -not -name "CHANGELOG_v*.md" -not -name "GNUmakefile" -not -name "docscheck.sh" -not -name "LICENSE" -not -name "README.md" -not -wholename "./examples*" -not -name ".go-version" -not -name ".hashibot.hcl" -print0 | xargs -0 git rm > /dev/null + find . -type f -not -wholename "./.git*" -not -wholename "./.changelog*" -not -name ".travis.yml" -not -name ".golangci.yml" -not -name "CHANGELOG.md" -not -name "CHANGELOG_v*.md" -not -name "GNUmakefile" -not -name "docscheck.sh" -not -name "LICENSE" -not -name "CODEOWNERS" -not -name "README.md" -not -wholename "./examples*" -not -name ".go-version" -not -name ".hashibot.hcl" -print0 | xargs -0 git rm > /dev/null clean-tgc: cd $(OUTPUT_PATH);\ From 77a08ce6aa3154dcaa7d855e05043b1fe38cd9df Mon Sep 17 00:00:00 2001 From: Sarah French <15078782+SarahFrench@users.noreply.github.com> Date: Thu, 14 Nov 2024 18:31:33 +0000 Subject: [PATCH 063/105] Update constants.kt (#12329) --- mmv1/third_party/terraform/.teamcity/components/constants.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mmv1/third_party/terraform/.teamcity/components/constants.kt b/mmv1/third_party/terraform/.teamcity/components/constants.kt index a3a97fcc9f33..bb1bca75d390 100644 --- a/mmv1/third_party/terraform/.teamcity/components/constants.kt +++ b/mmv1/third_party/terraform/.teamcity/components/constants.kt @@ -16,6 +16,7 @@ const val DefaultStartHour = 4 const val DefaultParallelism = 6 // specifies the default version of Terraform Core which should be used for testing +// this is updated semi-regularly const val DefaultTerraformCoreVersion = "1.8.3" // This represents a cron view of days of the week @@ -47,4 +48,4 @@ const val VcrRecordingProjectId = "VCRRecording" // Artifact rules controls which artifacts are uploaded to S3 // https://www.jetbrains.com/help/teamcity/2024.07/configuring-general-settings.html#Artifact+Paths // The value below lacks a file extension, to allow upload of individual .txt files or a single .tar.gz file -const val ArtifactRules = "%teamcity.build.checkoutDir%/debug*" \ No newline at end of file +const val ArtifactRules = "%teamcity.build.checkoutDir%/debug*" From ee0a468f6cffd4f3891b974ddddc068131ec4b7d Mon Sep 17 00:00:00 2001 From: Philipp Schneider <47689073+philipp-tailor@users.noreply.github.com> Date: Thu, 14 Nov 2024 21:32:06 +0100 Subject: [PATCH 064/105] Clarify `responseHeader` in `Bucket.yaml` (#12326) --- mmv1/products/storage/Bucket.yaml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/mmv1/products/storage/Bucket.yaml b/mmv1/products/storage/Bucket.yaml index 66a9a3ab5961..d19113caeebf 100644 --- a/mmv1/products/storage/Bucket.yaml +++ b/mmv1/products/storage/Bucket.yaml @@ -189,8 +189,9 @@ properties: - name: 'responseHeader' type: Array description: | - The list of HTTP headers other than the simple response headers - to give permission for the user-agent to share across domains. + The list of HTTP headers to give permission for the user-agent + to share across domains. A typical example would e.g. be to + allow the `Content-Type` header. item_type: type: String - name: 'defaultEventBasedHold' From 171b7b6a7cab20139942409c2a2b1b9c8c1fdcb8 Mon Sep 17 00:00:00 2001 From: unnatinadupalli <156947936+unnatinadupalli@users.noreply.github.com> Date: Thu, 14 Nov 2024 13:00:53 -0800 Subject: [PATCH 065/105] promoting `google_parallelstore_instance` to ga (#12271) Co-authored-by: Sarah French --- mmv1/products/parallelstore/Instance.yaml | 18 ------------------ mmv1/products/parallelstore/product.yaml | 2 ++ .../parallelstore_instance_basic.tf.tmpl | 4 ---- ...esource_parallelstore_instance_test.go.tmpl | 15 ++------------- 4 files changed, 4 insertions(+), 35 deletions(-) diff --git a/mmv1/products/parallelstore/Instance.yaml b/mmv1/products/parallelstore/Instance.yaml index 0fa94952c537..77e8e46fabe6 100644 --- a/mmv1/products/parallelstore/Instance.yaml +++ b/mmv1/products/parallelstore/Instance.yaml @@ -14,7 +14,6 @@ --- name: 'Instance' description: A Parallelstore Instance. -min_version: 'beta' docs: id_format: 'projects/{{project}}/locations/{{location}}/instances/{{instance_id}}' base_url: 'projects/{{project}}/locations/{{location}}/instances' @@ -46,7 +45,6 @@ custom_code: examples: - name: 'parallelstore_instance_basic' primary_resource_id: 'instance' - min_version: 'beta' vars: name: 'instance' network_name: 'network' @@ -56,7 +54,6 @@ parameters: type: String description: | Part of `parent`. See documentation of `projectsId`. - min_version: 'beta' url_param_only: true required: true immutable: true @@ -69,7 +66,6 @@ parameters: * Must be between 1-63 characters. * Must end with a number or a letter. * Must be unique within the customer project/ location - min_version: 'beta' url_param_only: true required: true immutable: true @@ -79,13 +75,11 @@ properties: description: | Identifier. The resource name of the instance, in the format `projects/{project}/locations/{location}/instances/{instance_id}` - min_version: 'beta' output: true - name: 'description' type: String description: | The description of the instance. 2048 characters or less. - min_version: 'beta' - name: 'state' type: String description: | @@ -97,19 +91,16 @@ properties: DELETING FAILED UPGRADING - min_version: 'beta' output: true - name: 'createTime' type: String description: | The time when the instance was created. - min_version: 'beta' output: true - name: 'updateTime' type: String description: | The time when the instance was updated. - min_version: 'beta' output: true - name: 'labels' type: KeyValueLabels @@ -135,26 +126,22 @@ properties: specific characters being disallowed. For example, representing labels as the string: `name + "_" + value` would prove problematic if we were to allow `"_"` in a future release. " - min_version: 'beta' - name: 'capacityGib' type: String description: | Required. Immutable. Storage capacity of Parallelstore instance in Gibibytes (GiB). - min_version: 'beta' required: true immutable: true - name: 'daosVersion' type: String description: | The version of DAOS software running in the instance. - min_version: 'beta' output: true - name: 'accessPoints' type: Array description: | Output only. List of access_points. Contains a list of IPv4 addresses used for client side configuration. - min_version: 'beta' output: true item_type: type: String @@ -163,7 +150,6 @@ properties: description: | Immutable. The name of the Google Compute Engine [VPC network](https://cloud.google.com/vpc/docs/vpc) to which the instance is connected. - min_version: 'beta' immutable: true - name: 'reservedIpRange' type: String @@ -172,7 +158,6 @@ properties: associated with the private service access connection for example, \"test-default\" associated with IP range 10.0.0.0/29. If no range id is provided all ranges will be considered. - min_version: 'beta' immutable: true - name: 'effectiveReservedIpRange' type: String @@ -181,7 +166,6 @@ properties: range associated with the private service access connection for example, \"test-default\" associated with IP range 10.0.0.0/29. This field is populated by the service and contains the value currently used by the service. - min_version: 'beta' immutable: true output: true - name: 'fileStripeLevel' @@ -195,7 +179,6 @@ properties: FILE_STRIPE_LEVEL_MIN FILE_STRIPE_LEVEL_BALANCED FILE_STRIPE_LEVEL_MAX - min_version: 'beta' - name: 'directoryStripeLevel' type: String description: | @@ -207,4 +190,3 @@ properties: DIRECTORY_STRIPE_LEVEL_MIN DIRECTORY_STRIPE_LEVEL_BALANCED DIRECTORY_STRIPE_LEVEL_MAX - min_version: 'beta' diff --git a/mmv1/products/parallelstore/product.yaml b/mmv1/products/parallelstore/product.yaml index fc6e94618fd2..607b093d7cd7 100644 --- a/mmv1/products/parallelstore/product.yaml +++ b/mmv1/products/parallelstore/product.yaml @@ -15,6 +15,8 @@ name: 'Parallelstore' display_name: 'Parallelstore' versions: + - name: 'ga' + base_url: 'https://parallelstore.googleapis.com/v1/' - name: 'beta' base_url: 'https://parallelstore.googleapis.com/v1beta/' scopes: diff --git a/mmv1/templates/terraform/examples/parallelstore_instance_basic.tf.tmpl b/mmv1/templates/terraform/examples/parallelstore_instance_basic.tf.tmpl index a7f67c16d9d3..9ef9378a1cf3 100644 --- a/mmv1/templates/terraform/examples/parallelstore_instance_basic.tf.tmpl +++ b/mmv1/templates/terraform/examples/parallelstore_instance_basic.tf.tmpl @@ -9,7 +9,6 @@ resource "google_parallelstore_instance" "{{$.PrimaryResourceId}}" { labels = { test = "value" } - provider = google-beta depends_on = [google_service_networking_connection.default] } @@ -17,7 +16,6 @@ resource "google_compute_network" "network" { name = "{{index $.Vars "network_name"}}" auto_create_subnetworks = true mtu = 8896 - provider = google-beta } # Create an IP address @@ -27,7 +25,6 @@ resource "google_compute_global_address" "private_ip_alloc" { address_type = "INTERNAL" prefix_length = 24 network = google_compute_network.network.id - provider = google-beta } # Create a private connection @@ -35,5 +32,4 @@ resource "google_service_networking_connection" "default" { network = google_compute_network.network.id service = "servicenetworking.googleapis.com" reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] - provider = google-beta } diff --git a/mmv1/third_party/terraform/services/parallelstore/resource_parallelstore_instance_test.go.tmpl b/mmv1/third_party/terraform/services/parallelstore/resource_parallelstore_instance_test.go.tmpl index 740f2f5dde37..87fb1e74fdee 100644 --- a/mmv1/third_party/terraform/services/parallelstore/resource_parallelstore_instance_test.go.tmpl +++ b/mmv1/third_party/terraform/services/parallelstore/resource_parallelstore_instance_test.go.tmpl @@ -18,7 +18,6 @@ package parallelstore_test -{{ if ne $.TargetVersionName `ga` -}} import ( "testing" @@ -35,7 +34,7 @@ func TestAccParallelstoreInstance_parallelstoreInstanceBasicExample_update(t *te acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, - ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), CheckDestroy: testAccCheckParallelstoreInstanceDestroyProducer(t), Steps: []resource.TestStep{ { @@ -75,7 +74,6 @@ resource "google_parallelstore_instance" "instance" { labels = { test = "value" } - provider = google-beta depends_on = [google_service_networking_connection.default] } @@ -83,7 +81,6 @@ resource "google_compute_network" "network" { name = "network%{random_suffix}" auto_create_subnetworks = true mtu = 8896 - provider = google-beta } @@ -95,7 +92,6 @@ resource "google_compute_global_address" "private_ip_alloc" { address_type = "INTERNAL" prefix_length = 24 network = google_compute_network.network.id - provider = google-beta } # Create a private connection @@ -103,7 +99,6 @@ resource "google_service_networking_connection" "default" { network = google_compute_network.network.id service = "servicenetworking.googleapis.com" reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] - provider = google-beta } `, context) } @@ -120,7 +115,6 @@ resource "google_parallelstore_instance" "instance" { labels = { test = "value23" } - provider = google-beta depends_on = [google_service_networking_connection.default] } @@ -128,7 +122,6 @@ resource "google_compute_network" "network" { name = "network%{random_suffix}" auto_create_subnetworks = true mtu = 8896 - provider = google-beta } @@ -140,7 +133,6 @@ resource "google_compute_global_address" "private_ip_alloc" { address_type = "INTERNAL" prefix_length = 24 network = google_compute_network.network.id - provider = google-beta } # Create a private connection @@ -148,9 +140,6 @@ resource "google_service_networking_connection" "default" { network = google_compute_network.network.id service = "servicenetworking.googleapis.com" reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] - provider = google-beta } `, context) -} - -{{ end }} +} \ No newline at end of file From ea78f58a5e7ce06446cec65cdb5e36fb3b8c5c7a Mon Sep 17 00:00:00 2001 From: "Stephen Lewis (Burrows)" Date: Thu, 14 Nov 2024 13:07:38 -0800 Subject: [PATCH 066/105] Update enrolled_teams.yml (#12304) --- .../issue-labeler/labeler/enrolled_teams.yml | 29 ++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/tools/issue-labeler/labeler/enrolled_teams.yml b/tools/issue-labeler/labeler/enrolled_teams.yml index 560a70c0f809..58ef76ea2edd 100755 --- a/tools/issue-labeler/labeler/enrolled_teams.yml +++ b/tools/issue-labeler/labeler/enrolled_teams.yml @@ -7,6 +7,9 @@ service/accessapproval: service/accesscontextmanager: resources: - google_access_context_manager_.* +service/aiplatform-colab-enterprise: + resources: + - google_vertex_ai_notebook_.* service/aiplatform-dataset: resources: - google_vertex_ai_dataset @@ -75,6 +78,9 @@ service/billingbudgets: service/binaryauthorization: resources: - google_binary_authorization_.* +service/blockchainnodeengine: + resources: + - google_blockchain_node_engine_.* service/certificatemanager: resources: - google_certificate_manager_.* @@ -137,6 +143,9 @@ service/cloudscheduler: service/cloudtasks: resources: - google_cloud_tasks_.* +service/cloudtrace: + resources: + - google_cloud_trace_.* service/composer: resources: - google_composer_.* @@ -153,6 +162,7 @@ service/compute-health: - google_compute_http_health_check - google_compute_https_health_check - google_compute_region_health_check + - google_network_services_service_lb_policies service/compute-instances: resources: - google_compute_instance @@ -244,6 +254,7 @@ service/compute-router: - google_compute_router - google_compute_router_interface - google_compute_router_peer + - google_compute_router_route_policy - google_compute_router_status service/compute-security-policy: resources: @@ -259,7 +270,7 @@ service/compute-vpc: resources: - google_compute_network - google_compute_route - - google_compute_subnetwork + - google_compute_subnetwork.* - google_compute_shared_vpc_host_project - google_compute_shared_vpc_service_project - google_compute_project_default_network_tier @@ -495,6 +506,10 @@ service/networksecurity-swp: service/networkservices-media-cdn: resources: - google_network_services_edge_cache_.* +service/networkservices-service-extensions: + resources: + - google_network_services_lb_route_extension + - google_network_services_lb_traffic_extension service/networkservices-traffic-director: resources: - google_network_services_endpoint_policy @@ -509,6 +524,9 @@ service/notebooks: resources: - google_notebooks_.* - google_workbench_.* +service/oracledatabase: + resources: + - google_oracle_database_.* service/orgpolicy: resources: - google_folder_organization_policy @@ -592,12 +610,18 @@ service/serviceusage-quota: resources: - google_cloud_quotas_.* - google_service_usage_consumer_quota_override +service/siteverification: + resources: + - google_site_verification_.* service/sourcerepo: resources: - google_sourcerepo_.* service/spanner: resources: - google_spanner_.* +service/speech: + resources: + - google_speech_to_text_.* service/sqladmin-cp: resources: - google_sql_database_instance @@ -624,6 +648,9 @@ service/storage: service/tpu: resources: - google_tpu_.* +service/transcoder: + resources: + - google_transcoder_.* service/vmwareengine: resources: - google_vmwareengine_.* From ce7327247d236feaaf57005763f55494cca727b2 Mon Sep 17 00:00:00 2001 From: Salome Papiashvili Date: Thu, 14 Nov 2024 22:10:21 +0100 Subject: [PATCH 067/105] Composer 3 GA (#12234) --- .../composer/UserWorkloadsConfigMap.yaml | 8 +-- ...er_user_workloads_config_map_basic.tf.tmpl | 2 - .../provider/provider_mmv1_resources.go.tmpl | 7 -- ...composer_user_workloads_config_map.go.tmpl | 2 - ...ser_user_workloads_config_map_test.go.tmpl | 2 - ...gle_composer_user_workloads_secret.go.tmpl | 2 - ...omposer_user_workloads_secret_test.go.tmpl | 2 - .../resource_composer_environment.go.tmpl | 65 +------------------ ...resource_composer_environment_test.go.tmpl | 6 +- ...ser_user_workloads_config_map_test.go.tmpl | 13 +--- ...rce_composer_user_workloads_secret.go.tmpl | 4 -- ...omposer_user_workloads_secret_test.go.tmpl | 4 -- ...er_user_workloads_config_map.html.markdown | 3 - ...mposer_user_workloads_secret.html.markdown | 3 - .../docs/r/composer_environment.html.markdown | 41 ++++++++++-- ...mposer_user_workloads_secret.html.markdown | 3 - 16 files changed, 42 insertions(+), 125 deletions(-) diff --git a/mmv1/products/composer/UserWorkloadsConfigMap.yaml b/mmv1/products/composer/UserWorkloadsConfigMap.yaml index 9835430077f0..4efc7c9ec7fe 100644 --- a/mmv1/products/composer/UserWorkloadsConfigMap.yaml +++ b/mmv1/products/composer/UserWorkloadsConfigMap.yaml @@ -16,11 +16,9 @@ name: 'UserWorkloadsConfigMap' description: | User workloads ConfigMap used by Airflow tasks that run with Kubernetes Executor or KubernetesPodOperator. Intended for Composer 3 Environments. -min_version: 'beta' references: guides: - # TODO: add v1 reference when this is moved to ga - api: 'https://cloud.google.com/composer/docs/reference/rest/v1beta1/projects.locations.environments.userWorkloadsConfigMaps' + api: 'https://cloud.google.com/composer/docs/reference/rest/v1/projects.locations.environments.userWorkloadsConfigMaps' docs: base_url: 'projects/{{project}}/locations/{{region}}/environments/{{environment}}/userWorkloadsConfigMaps' self_link: 'projects/{{project}}/locations/{{region}}/environments/{{environment}}/userWorkloadsConfigMaps/{{name}}' @@ -41,7 +39,6 @@ parameters: type: String description: | The location or Compute Engine region for the environment. - min_version: 'beta' url_param_only: true immutable: true default_from_api: true @@ -49,7 +46,6 @@ parameters: type: String description: | Environment where the Kubernetes ConfigMap will be stored and used. - min_version: 'beta' url_param_only: true required: true immutable: true @@ -60,7 +56,6 @@ properties: type: String description: | Name of the Kubernetes ConfigMap. - min_version: 'beta' required: true immutable: true custom_flatten: 'templates/terraform/custom_flatten/name_from_self_link.tmpl' @@ -72,5 +67,4 @@ properties: description: | The "data" field of Kubernetes ConfigMap, organized in key-value pairs. For details see: https://kubernetes.io/docs/concepts/configuration/configmap/ - min_version: 'beta' immutable: false diff --git a/mmv1/templates/terraform/examples/composer_user_workloads_config_map_basic.tf.tmpl b/mmv1/templates/terraform/examples/composer_user_workloads_config_map_basic.tf.tmpl index a2641c1bf801..5b53968aac54 100644 --- a/mmv1/templates/terraform/examples/composer_user_workloads_config_map_basic.tf.tmpl +++ b/mmv1/templates/terraform/examples/composer_user_workloads_config_map_basic.tf.tmpl @@ -1,5 +1,4 @@ resource "google_composer_environment" "environment" { - provider = google-beta name = "{{index $.Vars "environment_name"}}" region = "us-central1" config { @@ -10,7 +9,6 @@ resource "google_composer_environment" "environment" { } resource "google_composer_user_workloads_config_map" "{{$.PrimaryResourceId}}" { - provider = google-beta name = "{{index $.Vars "config_map_name"}}" region = "us-central1" environment = google_composer_environment.environment.name diff --git a/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.tmpl b/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.tmpl index 9ac625153e69..4950309f0d9c 100644 --- a/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.tmpl +++ b/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.tmpl @@ -7,9 +7,6 @@ import ( "github.com/hashicorp/terraform-provider-google/google/services/{{ $service }}" {{- end }} - {{ if eq $.TargetVersionName `ga` }} - "github.com/hashicorp/terraform-provider-google/google/services/composer" - {{- end }} "github.com/hashicorp/terraform-provider-google/google/services/container" "github.com/hashicorp/terraform-provider-google/google/services/containeraws" "github.com/hashicorp/terraform-provider-google/google/services/containerazure" @@ -67,10 +64,8 @@ var handwrittenDatasources = map[string]*schema.Resource{ "google_cloud_run_v2_job": cloudrunv2.DataSourceGoogleCloudRunV2Job(), "google_cloud_run_v2_service": cloudrunv2.DataSourceGoogleCloudRunV2Service(), "google_composer_environment": composer.DataSourceGoogleComposerEnvironment(), - {{- if ne $.TargetVersionName "ga" }} "google_composer_user_workloads_config_map": composer.DataSourceGoogleComposerUserWorkloadsConfigMap(), "google_composer_user_workloads_secret": composer.DataSourceGoogleComposerUserWorkloadsSecret(), - {{- end }} "google_composer_image_versions": composer.DataSourceGoogleComposerImageVersions(), "google_compute_address": compute.DataSourceGoogleComputeAddress(), "google_compute_addresses": compute.DataSourceGoogleComputeAddresses(), @@ -323,9 +318,7 @@ var handwrittenResources = map[string]*schema.Resource{ "google_billing_subaccount": resourcemanager.ResourceBillingSubaccount(), "google_cloudfunctions_function": cloudfunctions.ResourceCloudFunctionsFunction(), "google_composer_environment": composer.ResourceComposerEnvironment(), - {{- if ne $.TargetVersionName "ga" }} "google_composer_user_workloads_secret": composer.ResourceComposerUserWorkloadsSecret(), - {{- end }} "google_compute_attached_disk": compute.ResourceComputeAttachedDisk(), "google_compute_instance": compute.ResourceComputeInstance(), "google_compute_disk_async_replication": compute.ResourceComputeDiskAsyncReplication(), diff --git a/mmv1/third_party/terraform/services/composer/data_source_google_composer_user_workloads_config_map.go.tmpl b/mmv1/third_party/terraform/services/composer/data_source_google_composer_user_workloads_config_map.go.tmpl index 2f9ad0137118..a3aab2c8c184 100644 --- a/mmv1/third_party/terraform/services/composer/data_source_google_composer_user_workloads_config_map.go.tmpl +++ b/mmv1/third_party/terraform/services/composer/data_source_google_composer_user_workloads_config_map.go.tmpl @@ -1,6 +1,5 @@ package composer -{{ if ne $.TargetVersionName `ga` -}} import ( "fmt" @@ -48,4 +47,3 @@ func dataSourceGoogleComposerUserWorkloadsConfigMapRead(d *schema.ResourceData, return nil } -{{- end }} diff --git a/mmv1/third_party/terraform/services/composer/data_source_google_composer_user_workloads_config_map_test.go.tmpl b/mmv1/third_party/terraform/services/composer/data_source_google_composer_user_workloads_config_map_test.go.tmpl index eac26bfd11cb..ea8e664c2773 100644 --- a/mmv1/third_party/terraform/services/composer/data_source_google_composer_user_workloads_config_map_test.go.tmpl +++ b/mmv1/third_party/terraform/services/composer/data_source_google_composer_user_workloads_config_map_test.go.tmpl @@ -1,6 +1,5 @@ package composer_test -{{ if ne $.TargetVersionName `ga` -}} import ( "fmt" "testing" @@ -56,4 +55,3 @@ data "google_composer_user_workloads_config_map" "test" { } `, context) } -{{- end }} diff --git a/mmv1/third_party/terraform/services/composer/data_source_google_composer_user_workloads_secret.go.tmpl b/mmv1/third_party/terraform/services/composer/data_source_google_composer_user_workloads_secret.go.tmpl index 0acf758493bb..2e6575460548 100644 --- a/mmv1/third_party/terraform/services/composer/data_source_google_composer_user_workloads_secret.go.tmpl +++ b/mmv1/third_party/terraform/services/composer/data_source_google_composer_user_workloads_secret.go.tmpl @@ -1,6 +1,5 @@ package composer -{{ if ne $.TargetVersionName `ga` -}} import ( "fmt" @@ -60,4 +59,3 @@ func dataSourceGoogleComposerUserWorkloadsSecretRead(d *schema.ResourceData, met return nil } -{{- end }} diff --git a/mmv1/third_party/terraform/services/composer/data_source_google_composer_user_workloads_secret_test.go.tmpl b/mmv1/third_party/terraform/services/composer/data_source_google_composer_user_workloads_secret_test.go.tmpl index 3860a8e8c40f..2098a4aeb89e 100644 --- a/mmv1/third_party/terraform/services/composer/data_source_google_composer_user_workloads_secret_test.go.tmpl +++ b/mmv1/third_party/terraform/services/composer/data_source_google_composer_user_workloads_secret_test.go.tmpl @@ -1,6 +1,5 @@ package composer_test -{{ if ne $.TargetVersionName `ga` -}} import ( "errors" "fmt" @@ -99,4 +98,3 @@ data "google_composer_user_workloads_secret" "test" { } `, context) } -{{- end }} diff --git a/mmv1/third_party/terraform/services/composer/resource_composer_environment.go.tmpl b/mmv1/third_party/terraform/services/composer/resource_composer_environment.go.tmpl index e8da985580f1..7882a22c4566 100644 --- a/mmv1/third_party/terraform/services/composer/resource_composer_environment.go.tmpl +++ b/mmv1/third_party/terraform/services/composer/resource_composer_environment.go.tmpl @@ -56,9 +56,7 @@ var ( "config.0.software_config.0.python_version", "config.0.software_config.0.scheduler_count", "config.0.software_config.0.cloud_data_lineage_integration", -{{- if ne $.TargetVersionName "ga" }} "config.0.software_config.0.web_server_plugins_mode", -{{- end }} } composerConfigKeys = []string{ @@ -76,10 +74,8 @@ var ( "config.0.environment_size", "config.0.master_authorized_networks_config", "config.0.resilience_mode", -{{- if ne $.TargetVersionName "ga" }} "config.0.enable_private_environment", "config.0.enable_private_builds_only", -{{- end }} "config.0.data_retention_config", } @@ -92,9 +88,7 @@ var ( "config.0.workloads_config.0.triggerer", "config.0.workloads_config.0.web_server", "config.0.workloads_config.0.worker", -{{- if ne $.TargetVersionName "ga" }} "config.0.workloads_config.0.dag_processor", -{{- end }} } composerPrivateEnvironmentConfig = []string{ @@ -173,10 +167,8 @@ func ResourceComposerEnvironment() *schema.Resource { customdiff.ValidateChange("config.0.software_config.0.image_version", imageVersionChangeValidationFunc), versionValidationCustomizeDiffFunc, ), -{{- if ne $.TargetVersionName "ga" }} - customdiff.ForceNewIf("config.0.node_config.0.network", forceNewCustomDiff("config.0.node_config.0.network")), - customdiff.ForceNewIf("config.0.node_config.0.subnetwork", forceNewCustomDiff("config.0.node_config.0.subnetwork")), -{{- end }} + customdiff.ForceNewIf("config.0.node_config.0.network", forceNewIfNotComposer3CustomDiff("config.0.node_config.0.network")), + customdiff.ForceNewIf("config.0.node_config.0.subnetwork", forceNewIfNotComposer3CustomDiff("config.0.node_config.0.subnetwork")), ), Schema: map[string]*schema.Schema{ @@ -246,29 +238,18 @@ func ResourceComposerEnvironment() *schema.Resource { Type: schema.TypeString, Computed: true, Optional: true, -{{- if eq $.TargetVersionName "ga" }} - ForceNew: true, -{{- else }} - ForceNew: false, ConflictsWith: []string{"config.0.node_config.0.composer_network_attachment"}, -{{- end }} DiffSuppressFunc: tpgresource.CompareSelfLinkOrResourceName, Description: `The Compute Engine machine type used for cluster instances, specified as a name or relative resource name. For example: "projects/{project}/zones/{zone}/machineTypes/{machineType}". Must belong to the enclosing environment's project and region/zone. The network must belong to the environment's project. If unspecified, the "default" network ID in the environment's project is used. If a Custom Subnet Network is provided, subnetwork must also be provided.`, }, "subnetwork": { Type: schema.TypeString, Optional: true, -{{- if eq $.TargetVersionName "ga" }} - ForceNew: true, -{{- else }} - ForceNew: false, Computed: true, ConflictsWith: []string{"config.0.node_config.0.composer_network_attachment"}, -{{- end }} DiffSuppressFunc: tpgresource.CompareSelfLinkOrResourceName, Description: `The Compute Engine subnetwork to be used for machine communications, specified as a self-link, relative resource name (e.g. "projects/{project}/regions/{region}/subnetworks/{subnetwork}"), or by name. If subnetwork is provided, network must also be provided and the subnetwork must belong to the enclosing environment's project and region.`, }, -{{- if ne $.TargetVersionName "ga" }} "composer_network_attachment": { Type: schema.TypeString, Computed: true, @@ -276,7 +257,6 @@ func ResourceComposerEnvironment() *schema.Resource { ForceNew: false, Description: `PSC (Private Service Connect) Network entry point. Customers can pre-create the Network Attachment and point Cloud Composer environment to use. It is possible to share network attachment among many environments, provided enough IP addresses are available.`, }, -{{- end }} "disk_size_gb": { Type: schema.TypeInt, Computed: true, @@ -385,7 +365,6 @@ func ResourceComposerEnvironment() *schema.Resource { }, }, }, -{{- if ne $.TargetVersionName "ga" }} "composer_internal_ipv4_cidr_block": { Type: schema.TypeString, Computed: true, @@ -394,7 +373,6 @@ func ResourceComposerEnvironment() *schema.Resource { ValidateFunc: validateComposerInternalIpv4CidrBlock, Description: `IPv4 cidr range that will be used by Composer internal components.`, }, -{{- end }} }, }, }, @@ -513,7 +491,6 @@ func ResourceComposerEnvironment() *schema.Resource { }, }, }, -{{- if ne $.TargetVersionName "ga" }} "web_server_plugins_mode": { Type: schema.TypeString, Optional: true, @@ -523,7 +500,6 @@ func ResourceComposerEnvironment() *schema.Resource { ValidateFunc: validation.StringInSlice([]string{"ENABLED", "DISABLED"}, false), Description: `Should be either 'ENABLED' or 'DISABLED'. Defaults to 'ENABLED'. Used in Composer 3.`, }, -{{- end }} }, }, }, @@ -606,7 +582,6 @@ func ResourceComposerEnvironment() *schema.Resource { }, }, }, -{{- if ne $.TargetVersionName "ga" }} "enable_private_environment": { Type: schema.TypeBool, Computed: true, @@ -623,7 +598,6 @@ func ResourceComposerEnvironment() *schema.Resource { AtLeastOneOf: composerConfigKeys, Description: `Optional. If true, builds performed during operations that install Python packages have only private connectivity to Google services. If false, the builds also have access to the internet.`, }, -{{- end }} "web_server_network_access_control": { Type: schema.TypeList, Optional: true, @@ -933,7 +907,6 @@ func ResourceComposerEnvironment() *schema.Resource { }, }, }, -{{- if ne $.TargetVersionName "ga" }} "dag_processor": { Type: schema.TypeList, Optional: true, @@ -979,7 +952,6 @@ func ResourceComposerEnvironment() *schema.Resource { }, }, }, -{{- end }} }, }, }, @@ -1225,7 +1197,6 @@ func resourceComposerEnvironmentUpdate(d *schema.ResourceData, meta interface{}) return err } -{{ if ne $.TargetVersionName `ga` -}} noChangeErrorMessage := "Update request does not result in any change to the environment's configuration" if d.HasChange("config.0.node_config.0.network") || d.HasChange("config.0.node_config.0.subnetwork"){ // step 1: update with empty network and subnetwork @@ -1285,7 +1256,6 @@ func resourceComposerEnvironmentUpdate(d *schema.ResourceData, meta interface{}) } } } -{{- end }} if d.HasChange("config.0.software_config.0.image_version") { patchObj := &composer.Environment{ @@ -1387,7 +1357,6 @@ func resourceComposerEnvironmentUpdate(d *schema.ResourceData, meta interface{}) } } -{{ if ne $.TargetVersionName `ga` -}} if d.HasChange("config.0.enable_private_environment") { patchObj := &composer.Environment{ Config: &composer.EnvironmentConfig{ @@ -1429,7 +1398,6 @@ func resourceComposerEnvironmentUpdate(d *schema.ResourceData, meta interface{}) return err } } -{{- end }} if d.HasChange("config.0.node_count") { patchObj := &composer.Environment{Config: &composer.EnvironmentConfig{}} @@ -1689,12 +1657,10 @@ func flattenComposerEnvironmentConfig(envCfg *composer.EnvironmentConfig) interf if !isComposer3(imageVersion){ transformed["private_environment_config"] = flattenComposerEnvironmentConfigPrivateEnvironmentConfig(envCfg.PrivateEnvironmentConfig) } -{{- if ne $.TargetVersionName "ga" }} if isComposer3(imageVersion) && envCfg.PrivateEnvironmentConfig != nil { transformed["enable_private_environment"] = envCfg.PrivateEnvironmentConfig.EnablePrivateEnvironment transformed["enable_private_builds_only"] = envCfg.PrivateEnvironmentConfig.EnablePrivateBuildsOnly } -{{- end }} transformed["web_server_network_access_control"] = flattenComposerEnvironmentConfigWebServerNetworkAccessControl(envCfg.WebServerNetworkAccessControl) transformed["database_config"] = flattenComposerEnvironmentConfigDatabaseConfig(envCfg.DatabaseConfig) transformed["web_server_config"] = flattenComposerEnvironmentConfigWebServerConfig(envCfg.WebServerConfig) @@ -1837,17 +1803,13 @@ func flattenComposerEnvironmentConfigWorkloadsConfig(workloadsConfig *composer.W transformedTriggerer := make(map[string]interface{}) transformedWebServer := make(map[string]interface{}) transformedWorker := make(map[string]interface{}) -{{- if ne $.TargetVersionName "ga" }} transformedDagProcessor := make(map[string]interface{}) -{{- end }} wlCfgScheduler := workloadsConfig.Scheduler wlCfgTriggerer := workloadsConfig.Triggerer wlCfgWebServer := workloadsConfig.WebServer wlCfgWorker := workloadsConfig.Worker -{{- if ne $.TargetVersionName "ga" }} wlCfgDagProcessor := workloadsConfig.DagProcessor -{{- end }} if wlCfgScheduler == nil { transformedScheduler = nil @@ -1884,7 +1846,6 @@ func flattenComposerEnvironmentConfigWorkloadsConfig(workloadsConfig *composer.W transformedWorker["max_count"] = wlCfgWorker.MaxCount } -{{ if ne $.TargetVersionName `ga` -}} if wlCfgDagProcessor == nil { transformedDagProcessor = nil } else { @@ -1893,7 +1854,6 @@ func flattenComposerEnvironmentConfigWorkloadsConfig(workloadsConfig *composer.W transformedDagProcessor["storage_gb"] = wlCfgDagProcessor.StorageGb transformedDagProcessor["count"] = wlCfgDagProcessor.Count } -{{- end }} transformed["scheduler"] = []interface{}{transformedScheduler} if transformedTriggerer != nil { @@ -1901,12 +1861,9 @@ func flattenComposerEnvironmentConfigWorkloadsConfig(workloadsConfig *composer.W } transformed["web_server"] = []interface{}{transformedWebServer} transformed["worker"] = []interface{}{transformedWorker} -{{- if ne $.TargetVersionName "ga" }} if transformedDagProcessor != nil { transformed["dag_processor"] = []interface{}{transformedDagProcessor} } -{{- end }} - return []interface{}{transformed} } @@ -1942,9 +1899,7 @@ func flattenComposerEnvironmentConfigNodeConfig(nodeCfg *composer.NodeConfig) in transformed["machine_type"] = nodeCfg.MachineType transformed["network"] = nodeCfg.Network transformed["subnetwork"] = nodeCfg.Subnetwork -{{- if ne $.TargetVersionName "ga" }} transformed["composer_network_attachment"] = nodeCfg.ComposerNetworkAttachment -{{- end }} transformed["disk_size_gb"] = nodeCfg.DiskSizeGb transformed["service_account"] = nodeCfg.ServiceAccount transformed["oauth_scopes"] = flattenComposerEnvironmentConfigNodeConfigOauthScopes(nodeCfg.OauthScopes) @@ -1954,9 +1909,7 @@ func flattenComposerEnvironmentConfigNodeConfig(nodeCfg *composer.NodeConfig) in transformed["enable_ip_masq_agent"] = nodeCfg.EnableIpMasqAgent transformed["tags"] = flattenComposerEnvironmentConfigNodeConfigTags(nodeCfg.Tags) transformed["ip_allocation_policy"] = flattenComposerEnvironmentConfigNodeConfigIPAllocationPolicy(nodeCfg.IpAllocationPolicy) -{{- if ne $.TargetVersionName "ga" }} transformed["composer_internal_ipv4_cidr_block"] = nodeCfg.ComposerInternalIpv4CidrBlock -{{- end }} return []interface{}{transformed} } @@ -2000,7 +1953,6 @@ func flattenComposerEnvironmentConfigSoftwareConfig(softwareCfg *composer.Softwa transformed["env_variables"] = softwareCfg.EnvVariables transformed["scheduler_count"] = softwareCfg.SchedulerCount transformed["cloud_data_lineage_integration"] = flattenComposerEnvironmentConfigSoftwareConfigCloudDataLineageIntegration(softwareCfg.CloudDataLineageIntegration) -{{- if ne $.TargetVersionName "ga" }} if softwareCfg.WebServerPluginsMode == "PLUGINS_DISABLED"{ transformed["web_server_plugins_mode"] = "DISABLED" } else if softwareCfg.WebServerPluginsMode == "PLUGINS_ENABLED"{ @@ -2008,7 +1960,6 @@ func flattenComposerEnvironmentConfigSoftwareConfig(softwareCfg *composer.Softwa } else { transformed["web_server_plugins_mode"] = softwareCfg.WebServerPluginsMode } -{{- end }} return []interface{}{transformed} } @@ -2078,7 +2029,6 @@ func expandComposerEnvironmentConfig(v interface{}, d *schema.ResourceData, conf } transformed.PrivateEnvironmentConfig = transformedPrivateEnvironmentConfig -{{ if ne $.TargetVersionName `ga` -}} /* config.enable_private_environment in terraform maps to composer.PrivateEnvironmentConfig.EnablePrivateEnvironment in API. @@ -2094,7 +2044,6 @@ func expandComposerEnvironmentConfig(v interface{}, d *schema.ResourceData, conf transformed.PrivateEnvironmentConfig.EnablePrivateBuildsOnly = enablePrivateBuildsOnlyRaw.(bool) } } -{{- end }} transformedWebServerNetworkAccessControl, err := expandComposerEnvironmentConfigWebServerNetworkAccessControl(original["web_server_network_access_control"], d, config) if err != nil { @@ -2393,7 +2342,6 @@ func expandComposerEnvironmentConfigWorkloadsConfig(v interface{}, d *schema.Res } } -{{ if ne $.TargetVersionName `ga` -}} if v, ok := original["dag_processor"]; ok { if len(v.([]interface{})) > 0 && v.([]interface{})[0] != nil { transformedDagProcessor := &composer.DagProcessorResource{} @@ -2405,7 +2353,6 @@ func expandComposerEnvironmentConfigWorkloadsConfig(v interface{}, d *schema.Res transformed.DagProcessor = transformedDagProcessor } } -{{- end }} return transformed, nil } @@ -2562,11 +2509,9 @@ func expandComposerEnvironmentConfigNodeConfig(v interface{}, d *schema.Resource transformed.Subnetwork = transformedSubnetwork } -{{ if ne $.TargetVersionName `ga` -}} if v, ok := original["composer_network_attachment"]; ok { transformed.ComposerNetworkAttachment = v.(string) } -{{- end }} transformedIPAllocationPolicy, err := expandComposerEnvironmentIPAllocationPolicy(original["ip_allocation_policy"], d, config) if err != nil { @@ -2586,11 +2531,9 @@ func expandComposerEnvironmentConfigNodeConfig(v interface{}, d *schema.Resource } transformed.Tags = transformedTags -{{ if ne $.TargetVersionName `ga` -}} if transformedComposerInternalIpv4CidrBlock, ok := original["composer_internal_ipv4_cidr_block"]; ok { transformed.ComposerInternalIpv4CidrBlock = transformedComposerInternalIpv4CidrBlock.(string) } -{{- end }} return transformed, nil } @@ -2741,7 +2684,6 @@ func expandComposerEnvironmentConfigSoftwareConfig(v interface{}, d *schema.Reso } transformed.CloudDataLineageIntegration = transformedCloudDataLineageIntegration -{{ if ne $.TargetVersionName `ga` -}} if original["web_server_plugins_mode"].(string) == "DISABLED"{ transformed.WebServerPluginsMode = "PLUGINS_DISABLED" } else if original["web_server_plugins_mode"].(string) == "ENABLED"{ @@ -2749,7 +2691,6 @@ func expandComposerEnvironmentConfigSoftwareConfig(v interface{}, d *schema.Reso } else { transformed.WebServerPluginsMode = original["web_server_plugins_mode"].(string) } -{{- end }} return transformed, nil } @@ -3047,7 +2988,7 @@ func isComposer3(imageVersion string) bool { return strings.Contains(imageVersion, "composer-3") } -func forceNewCustomDiff(key string) customdiff.ResourceConditionFunc { +func forceNewIfNotComposer3CustomDiff(key string) customdiff.ResourceConditionFunc { return func(ctx context.Context, d *schema.ResourceDiff, meta interface{}) bool { old, new := d.GetChange(key) imageVersion := d.Get("config.0.software_config.0.image_version").(string) diff --git a/mmv1/third_party/terraform/services/composer/resource_composer_environment_test.go.tmpl b/mmv1/third_party/terraform/services/composer/resource_composer_environment_test.go.tmpl index 8fc8e27024b7..248cf1222c44 100644 --- a/mmv1/third_party/terraform/services/composer/resource_composer_environment_test.go.tmpl +++ b/mmv1/third_party/terraform/services/composer/resource_composer_environment_test.go.tmpl @@ -1191,7 +1191,6 @@ func TestAccComposerEnvironment_customBucketWithUrl(t *testing.T) { }) } -{{ if ne $.TargetVersionName `ga` -}} // Checks Composer 3 environment creation with new fields. func TestAccComposerEnvironmentComposer3_basic(t *testing.T) { t.Parallel() @@ -1548,7 +1547,6 @@ func TestAccComposerEnvironmentComposer3_usesUnsupportedField_expectError(t *tes }, }) } -{{- end }} func testAccComposerEnvironment_customBucket(bucketName, envName, network, subnetwork string) string { return fmt.Sprintf(` @@ -3233,7 +3231,6 @@ resource "google_project_iam_member" "composer-worker" { `, environment, network, subnetwork, serviceAccount) } -{{ if ne $.TargetVersionName `ga` -}} func testAccComposerEnvironmentComposer2_empty(name, network, subnetwork string) string { return fmt.Sprintf(` resource "google_composer_environment" "test" { @@ -3302,7 +3299,7 @@ resource "google_composer_environment" "test" { config { software_config { image_version = "composer-2-airflow-2" - web_server_plugins_mode = "ENABLED" + web_server_plugins_mode = "ENABLED" } } } @@ -3573,7 +3570,6 @@ resource "google_compute_subnetwork" "test" { } `, name, networkAttachment, network, subnetwork) } -{{- end }} // WARNING: This is not actually a check and is a terrible clean-up step because Composer Environments // have a bug that hasn't been fixed. Composer will add firewalls to non-default networks for environments diff --git a/mmv1/third_party/terraform/services/composer/resource_composer_user_workloads_config_map_test.go.tmpl b/mmv1/third_party/terraform/services/composer/resource_composer_user_workloads_config_map_test.go.tmpl index 312d8331f75b..37feb346b799 100644 --- a/mmv1/third_party/terraform/services/composer/resource_composer_user_workloads_config_map_test.go.tmpl +++ b/mmv1/third_party/terraform/services/composer/resource_composer_user_workloads_config_map_test.go.tmpl @@ -1,7 +1,5 @@ package composer_test -{{ if ne $.TargetVersionName `ga` -}} - import ( "fmt" "strings" @@ -22,7 +20,7 @@ func TestAccComposerUserWorkloadsConfigMap_composerUserWorkloadsConfigMapBasicEx acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, - ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), CheckDestroy: testAccCheckComposerUserWorkloadsConfigMapDestroyProducer(t), Steps: []resource.TestStep{ { @@ -58,7 +56,7 @@ func TestAccComposerUserWorkloadsConfigMap_composerUserWorkloadsConfigMapBasicEx acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, - ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), CheckDestroy: testAccCheckComposerUserWorkloadsConfigMapDestroyProducer(t), Steps: []resource.TestStep{ { @@ -82,7 +80,6 @@ func TestAccComposerUserWorkloadsConfigMap_composerUserWorkloadsConfigMapBasicEx func testAccComposerUserWorkloadsConfigMap_composerUserWorkloadsConfigMapBasicExample_basic(context map[string]interface{}) string { return acctest.Nprintf(` resource "google_composer_environment" "environment" { - provider = google-beta name = "tf-test-test-environment%{random_suffix}" region = "us-central1" config { @@ -93,7 +90,6 @@ resource "google_composer_environment" "environment" { } resource "google_composer_user_workloads_config_map" "config_map" { - provider = google-beta name = "tf-test-test-config-map%{random_suffix}" region = "us-central1" environment = google_composer_environment.environment.name @@ -107,7 +103,6 @@ resource "google_composer_user_workloads_config_map" "config_map" { func testAccComposerUserWorkloadsConfigMap_composerUserWorkloadsConfigMapBasicExample_update(context map[string]interface{}) string { return acctest.Nprintf(` resource "google_composer_environment" "environment" { - provider = google-beta name = "tf-test-test-environment%{random_suffix}" region = "us-central1" config { @@ -118,7 +113,6 @@ resource "google_composer_environment" "environment" { } resource "google_composer_user_workloads_config_map" "config_map" { - provider = google-beta name = "tf-test-test-config-map%{random_suffix}" region = "us-central1" environment = google_composer_environment.environment.name @@ -132,7 +126,6 @@ resource "google_composer_user_workloads_config_map" "config_map" { func testAccComposerUserWorkloadsConfigMap_composerUserWorkloadsConfigMapBasicExample_delete(context map[string]interface{}) string { return acctest.Nprintf(` resource "google_composer_environment" "environment" { - provider = google-beta name = "tf-test-test-environment%{random_suffix}" region = "us-central1" config { @@ -166,5 +159,3 @@ func testAccComposerUserWorkloadsConfigMapDestroyed(t *testing.T) func(s *terraf return nil } } - -{{ end }} diff --git a/mmv1/third_party/terraform/services/composer/resource_composer_user_workloads_secret.go.tmpl b/mmv1/third_party/terraform/services/composer/resource_composer_user_workloads_secret.go.tmpl index 94ebd8182ebc..9cea9a079dbb 100644 --- a/mmv1/third_party/terraform/services/composer/resource_composer_user_workloads_secret.go.tmpl +++ b/mmv1/third_party/terraform/services/composer/resource_composer_user_workloads_secret.go.tmpl @@ -1,7 +1,5 @@ package composer -{{ if ne $.TargetVersionName `ga` -}} - import ( "fmt" "log" @@ -267,5 +265,3 @@ func (n *UserWorkloadsSecretName) ResourceName() string { func (n *UserWorkloadsSecretName) ParentName() string { return fmt.Sprintf("projects/%s/locations/%s/environments/%s", n.Project, n.Region, n.Environment) } - -{{ end }} diff --git a/mmv1/third_party/terraform/services/composer/resource_composer_user_workloads_secret_test.go.tmpl b/mmv1/third_party/terraform/services/composer/resource_composer_user_workloads_secret_test.go.tmpl index 9008bfdc65df..cb83e29ce0d0 100644 --- a/mmv1/third_party/terraform/services/composer/resource_composer_user_workloads_secret_test.go.tmpl +++ b/mmv1/third_party/terraform/services/composer/resource_composer_user_workloads_secret_test.go.tmpl @@ -1,7 +1,5 @@ package composer_test -{{ if ne $.TargetVersionName `ga` -}} - import ( "fmt" "testing" @@ -179,5 +177,3 @@ func testAccComposerUserWorkloadsSecretDestroyed(t *testing.T) func(s *terraform return nil } } - -{{ end }} diff --git a/mmv1/third_party/terraform/website/docs/d/composer_user_workloads_config_map.html.markdown b/mmv1/third_party/terraform/website/docs/d/composer_user_workloads_config_map.html.markdown index f582d646df88..00e2a0d4a27f 100644 --- a/mmv1/third_party/terraform/website/docs/d/composer_user_workloads_config_map.html.markdown +++ b/mmv1/third_party/terraform/website/docs/d/composer_user_workloads_config_map.html.markdown @@ -8,9 +8,6 @@ description: |- Provides access to Kubernetes ConfigMap configuration for a given project, region and Composer Environment. -> **Warning:** This data source is in beta, and should be used with the terraform-provider-google-beta provider. -See [Provider Versions](https://terraform.io/docs/providers/google/guides/provider_versions.html) for more details on beta resources. - ## Example Usage ```hcl diff --git a/mmv1/third_party/terraform/website/docs/d/composer_user_workloads_secret.html.markdown b/mmv1/third_party/terraform/website/docs/d/composer_user_workloads_secret.html.markdown index 93f5356a781f..3b7f61b87562 100644 --- a/mmv1/third_party/terraform/website/docs/d/composer_user_workloads_secret.html.markdown +++ b/mmv1/third_party/terraform/website/docs/d/composer_user_workloads_secret.html.markdown @@ -8,9 +8,6 @@ description: |- Provides access to Kubernetes Secret configuration for a given project, region and Composer Environment. -~> **Warning:** This data source is in beta, and should be used with the terraform-provider-google-beta provider. -See [Provider Versions](https://terraform.io/docs/providers/google/guides/provider_versions.html) for more details on beta resources. - ## Example Usage ```hcl diff --git a/mmv1/third_party/terraform/website/docs/r/composer_environment.html.markdown b/mmv1/third_party/terraform/website/docs/r/composer_environment.html.markdown index 35740d97bcb9..8f560d4f662f 100644 --- a/mmv1/third_party/terraform/website/docs/r/composer_environment.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/composer_environment.html.markdown @@ -363,6 +363,35 @@ resource "google_composer_environment" "example" { } ``` +If you specify an existing network attachment that you also manage in Terraform, then Terraform will revert changes +to the attachment done by Cloud Composer when you apply configuration changes. As a result, the environment will no +longer use the attachment. To address this problem, make sure that Terraform ignores changes to the +`producer_accept_lists` parameter of the attachment, as follows: + +```hcl +resource "google_compute_network_attachment" "example" { + lifecycle { + ignore_changes = [producer_accept_lists] + } + + # ... other configuration parameters +} + +resource "google_composer_environment" "example" { + name = "example-environment" + region = "us-central1" + + config { + + node_config { + composer_network_attachment = google_compute_network_attachment.example.id + } + + # ... other configuration parameters + } +} +``` + ### With Software (Airflow) Config ```hcl @@ -1303,11 +1332,11 @@ The following arguments are supported: The configuration settings for software (Airflow) inside the environment. Structure is [documented below](#nested_software_config_c3). * `enable_private_environment` - - (Optional, [Beta](https://terraform.io/docs/providers/google/guides/provider_versions.html), Cloud Composer 3 only) + (Optional, Cloud Composer 3 only) If true, a private Composer environment will be created. * `enable_private_builds_only` - - (Optional, [Beta](https://terraform.io/docs/providers/google/guides/provider_versions.html), Cloud Composer 3 only) + (Optional, Cloud Composer 3 only) If true, builds performed during operations that install Python packages have only private connectivity to Google services. If false, the builds also have access to the internet. @@ -1377,7 +1406,7 @@ The following arguments are supported: network must also be provided and the subnetwork must belong to the enclosing environment's project and region. * `composer_network_attachment` - - (Optional, [Beta](https://terraform.io/docs/providers/google/guides/provider_versions.html), Cloud Composer 3 only) + (Optional, Cloud Composer 3 only) PSC (Private Service Connect) Network entry point. Customers can pre-create the Network Attachment and point Cloud Composer environment to use. It is possible to share network attachment among many environments, provided enough IP addresses are available. @@ -1398,7 +1427,7 @@ The following arguments are supported: Cannot be updated. * `composer_internal_ipv4_cidr_block` - - (Optional, [Beta](https://terraform.io/docs/providers/google/guides/provider_versions.html), Cloud Composer 3 only) + (Optional, Cloud Composer 3 only) /20 IPv4 cidr range that will be used by Composer internal components. Cannot be updated. @@ -1471,7 +1500,7 @@ The following arguments are supported: [documented below](#nested_cloud_data_lineage_integration_c3). * `web_server_plugins_mode` - - (Optional, [Beta](https://terraform.io/docs/providers/google/guides/provider_versions.html), Cloud Composer 3 only) + (Optional, Cloud Composer 3 only) Web server plugins configuration. Can be either 'ENABLED' or 'DISABLED'. Defaults to 'ENABLED'. The `cloud_data_lineage_integration` block supports: @@ -1523,7 +1552,7 @@ The `workloads_config` block supports: Configuration for resources used by Airflow workers. * `dag_processor` - - (Optional, [Beta](https://terraform.io/docs/providers/google/guides/provider_versions.html), Cloud Composer 3 only) + (Optional, Cloud Composer 3 only) Configuration for resources used by DAG processor. The `scheduler` block supports: diff --git a/mmv1/third_party/terraform/website/docs/r/composer_user_workloads_secret.html.markdown b/mmv1/third_party/terraform/website/docs/r/composer_user_workloads_secret.html.markdown index 797798867148..e07d8293d763 100644 --- a/mmv1/third_party/terraform/website/docs/r/composer_user_workloads_secret.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/composer_user_workloads_secret.html.markdown @@ -6,9 +6,6 @@ description: |- # google_composer_user_workloads_secret -~> **Warning:** These resources are in beta, and should be used with the terraform-provider-google-beta provider. -See [Provider Versions](https://terraform.io/docs/providers/google/guides/provider_versions.html) for more details on beta resources. - User workloads Secret used by Airflow tasks that run with Kubernetes Executor or KubernetesPodOperator. Intended for Composer 3 Environments. From e6c248fc140ae26ea42f6183d1ab425d2bca3c41 Mon Sep 17 00:00:00 2001 From: Will Yardley Date: Thu, 14 Nov 2024 13:11:38 -0800 Subject: [PATCH 068/105] transcoder: ignored `start_time` in `JobManifestsExample` test (#12220) --- mmv1/products/transcoder/Job.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/mmv1/products/transcoder/Job.yaml b/mmv1/products/transcoder/Job.yaml index ca7c95dec6f4..f80413ee7c0d 100644 --- a/mmv1/products/transcoder/Job.yaml +++ b/mmv1/products/transcoder/Job.yaml @@ -75,6 +75,7 @@ examples: bucket_name: 'transcoder-job' ignore_read_extra: - 'state' + - 'start_time' - 'end_time' parameters: - name: 'location' From ae71fc652e5736343fe238c04d6a2addc2780c0b Mon Sep 17 00:00:00 2001 From: cdunbar13 <139253655+cdunbar13@users.noreply.github.com> Date: Thu, 14 Nov 2024 17:15:11 -0500 Subject: [PATCH 069/105] Add RDMA features to google-beta provider (#12319) --- mmv1/products/compute/Network.yaml | 10 +++ ...ata_source_google_compute_network.go.tmpl} | 12 ++++ .../compute/resource_compute_instance.go.tmpl | 5 ++ ...resource_compute_instance_template.go.tmpl | 5 ++ .../resource_compute_network_test.go.tmpl | 68 +++++++++++++++++++ ...e_compute_region_instance_template.go.tmpl | 5 ++ .../docs/d/compute_network.html.markdown | 2 + .../docs/r/compute_instance.html.markdown | 2 +- .../r/compute_instance_template.html.markdown | 2 +- ...ute_region_instance_template.html.markdown | 2 +- 10 files changed, 110 insertions(+), 3 deletions(-) rename mmv1/third_party/terraform/services/compute/{data_source_google_compute_network.go => data_source_google_compute_network.go.tmpl} (87%) diff --git a/mmv1/products/compute/Network.yaml b/mmv1/products/compute/Network.yaml index 53d35d980a7a..4a722c4b3193 100644 --- a/mmv1/products/compute/Network.yaml +++ b/mmv1/products/compute/Network.yaml @@ -234,3 +234,13 @@ properties: enum_values: - 'BEFORE_CLASSIC_FIREWALL' - 'AFTER_CLASSIC_FIREWALL' + - name: 'networkProfile' + type: String + immutable: true + min_version: 'beta' + description: | + A full or partial URL of the network profile to apply to this network. + This field can be set only at resource creation time. For example, the + following are valid URLs: + * https://www.googleapis.com/compute/beta/projects/{projectId}/global/networkProfiles/{network_profile_name} + * projects/{projectId}/global/networkProfiles/{network_profile_name} diff --git a/mmv1/third_party/terraform/services/compute/data_source_google_compute_network.go b/mmv1/third_party/terraform/services/compute/data_source_google_compute_network.go.tmpl similarity index 87% rename from mmv1/third_party/terraform/services/compute/data_source_google_compute_network.go rename to mmv1/third_party/terraform/services/compute/data_source_google_compute_network.go.tmpl index f879884a931d..2e3d521ac945 100644 --- a/mmv1/third_party/terraform/services/compute/data_source_google_compute_network.go +++ b/mmv1/third_party/terraform/services/compute/data_source_google_compute_network.go.tmpl @@ -33,6 +33,13 @@ func DataSourceGoogleComputeNetwork() *schema.Resource { Computed: true, }, + {{- if ne $.TargetVersionName "ga" }} + "network_profile": { + Type: schema.TypeString, + Optional: true, + }, + {{- end }} + "self_link": { Type: schema.TypeString, Computed: true, @@ -77,6 +84,11 @@ func dataSourceGoogleComputeNetworkRead(d *schema.ResourceData, meta interface{} if err := d.Set("internal_ipv6_range", network.InternalIpv6Range); err != nil { return fmt.Errorf("Error setting internal_ipv6_range: %s", err) } + {{- if ne $.TargetVersionName "ga" }} + if err := d.Set("network_profile", network.NetworkProfile); err != nil { + return fmt.Errorf("Error setting network_profile: %s", err) + } + {{- end }} if err := d.Set("self_link", network.SelfLink); err != nil { return fmt.Errorf("Error setting self_link: %s", err) } diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_instance.go.tmpl b/mmv1/third_party/terraform/services/compute/resource_compute_instance.go.tmpl index 83ca4470dede..cb91f90c911a 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_instance.go.tmpl +++ b/mmv1/third_party/terraform/services/compute/resource_compute_instance.go.tmpl @@ -465,8 +465,13 @@ func ResourceComputeInstance() *schema.Resource { Type: schema.TypeString, Optional: true, ForceNew: true, + {{- if eq $.TargetVersionName `ga` }} ValidateFunc: validation.StringInSlice([]string{"GVNIC", "VIRTIO_NET", "IDPF"}, false), Description: `The type of vNIC to be used on this interface. Possible values:GVNIC, VIRTIO_NET, IDPF`, + {{- else }} + ValidateFunc: validation.StringInSlice([]string{"GVNIC", "VIRTIO_NET", "IDPF", "MRDMA", "IRDMA"}, false), + Description: `The type of vNIC to be used on this interface. Possible values:GVNIC, VIRTIO_NET, IDPF, MRDMA, and IRDMA`, + {{- end }} }, "access_config": { Type: schema.TypeList, diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_instance_template.go.tmpl b/mmv1/third_party/terraform/services/compute/resource_compute_instance_template.go.tmpl index d5af5e60f92c..5b2ab8d95d94 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_instance_template.go.tmpl +++ b/mmv1/third_party/terraform/services/compute/resource_compute_instance_template.go.tmpl @@ -486,8 +486,13 @@ Google Cloud KMS.`, Type: schema.TypeString, Optional: true, ForceNew: true, + {{- if eq $.TargetVersionName `ga` }} ValidateFunc: validation.StringInSlice([]string{"GVNIC", "VIRTIO_NET"}, false), Description: `The type of vNIC to be used on this interface. Possible values:GVNIC, VIRTIO_NET`, + {{- else }} + ValidateFunc: validation.StringInSlice([]string{"GVNIC", "VIRTIO_NET", "MRDMA", "IRDMA"}, false), + Description: `The type of vNIC to be used on this interface. Possible values:GVNIC, VIRTIO_NET, MRDMA, and IRDMA`, + {{- end }} }, "access_config": { Type: schema.TypeList, diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_network_test.go.tmpl b/mmv1/third_party/terraform/services/compute/resource_compute_network_test.go.tmpl index 823d20a2d1cb..87dd65016fc7 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_network_test.go.tmpl +++ b/mmv1/third_party/terraform/services/compute/resource_compute_network_test.go.tmpl @@ -218,6 +218,33 @@ func TestAccComputeNetwork_bgpInterRegionCostAndUpdate(t *testing.T) { }, }) } + +func TestAccComputeNetwork_networkProfile(t *testing.T) { + t.Parallel() + + var network compute.Network + suffixName := acctest.RandString(t, 10) + networkName := fmt.Sprintf("tf-network-profile-%s", suffixName) + projectId := envvar.GetTestProjectFromEnv() + profileURL := fmt.Sprintf("https://www.googleapis.com/compute/beta/projects/%s/global/networkProfiles/europe-west1-b-vpc-roce", projectId) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t), + CheckDestroy: testAccCheckComputeNetworkDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccComputeNetwork_network_profile(networkName, profileURL), + Check: resource.ComposeTestCheckFunc( + testAccCheckComputeNetworkExists( + t, "google_compute_network.acc_network_network_profile", &network), + testAccCheckComputeNetworkHasNetworkProfile( + t, "google_compute_network.acc_network_network_profile", &network, profileURL), + ), + }, + }, + }) +} {{- end }} func TestAccComputeNetwork_numericId(t *testing.T) { @@ -623,6 +650,35 @@ func testAccCheckComputeNetworkHasBgpInterRegionCost(t *testing.T, n string, net return nil } } + +func testAccCheckComputeNetworkHasNetworkProfile(t *testing.T, n string, network *compute.Network, networkProfile string) resource.TestCheckFunc { + return func(s *terraform.State) error { + config := acctest.GoogleProviderConfig(t) + + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + if rs.Primary.Attributes["network_profile"] == "" { + return fmt.Errorf("Network profile not found on resource") + } + + found, err := config.NewComputeClient(config.UserAgent).Networks.Get( + config.Project, network.Name).Do() + if err != nil { + return err + } + + foundNetworkProfile := found.NetworkProfile + + if foundNetworkProfile != networkProfile { + return fmt.Errorf("Expected Network Profile always compare med %s to match actual Network Profile always compare med %s", networkProfile, foundNetworkProfile) + } + + return nil + } +} {{- end }} func testAccCheckComputeNetworkHasNetworkFirewallPolicyEnforcementOrder(t *testing.T, n string, network *compute.Network, order string) resource.TestCheckFunc { @@ -735,6 +791,18 @@ resource "google_compute_network" "acc_network_bgp_inter_region_cost" { } `, networkName, bgpInterRegionCost) } + +func testAccComputeNetwork_network_profile(networkName, networkProfile string) string { + return fmt.Sprintf(` +resource "google_compute_network" "acc_network_network_profile" { + provider = google-beta + name = "%s" + routing_mode = "REGIONAL" + network_profile = "%s" + auto_create_subnetworks = false +} +`, networkName, networkProfile) +} {{- end }} func testAccComputeNetwork_deleteDefaultRoute(networkName string) string { diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_template.go.tmpl b/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_template.go.tmpl index f3888bbd2431..b9b46772dd08 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_template.go.tmpl +++ b/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_template.go.tmpl @@ -455,8 +455,13 @@ Google Cloud KMS.`, Type: schema.TypeString, Optional: true, ForceNew: true, + {{- if eq $.TargetVersionName `ga` }} ValidateFunc: validation.StringInSlice([]string{"GVNIC", "VIRTIO_NET"}, false), Description: `The type of vNIC to be used on this interface. Possible values:GVNIC, VIRTIO_NET`, + {{- else }} + ValidateFunc: validation.StringInSlice([]string{"GVNIC", "VIRTIO_NET", "MRDMA", "IRDMA"}, false), + Description: `The type of vNIC to be used on this interface. Possible values:GVNIC, VIRTIO_NET, MRDMA, and IRDMA`, + {{- end }} }, "access_config": { Type: schema.TypeList, diff --git a/mmv1/third_party/terraform/website/docs/d/compute_network.html.markdown b/mmv1/third_party/terraform/website/docs/d/compute_network.html.markdown index 2cf36ae51a98..7ed18f65fe4a 100644 --- a/mmv1/third_party/terraform/website/docs/d/compute_network.html.markdown +++ b/mmv1/third_party/terraform/website/docs/d/compute_network.html.markdown @@ -40,6 +40,8 @@ In addition to the arguments listed above, the following attributes are exported * `internal_ipv6_range` - The ula internal ipv6 range assigned to this network. +* `network_profile` - [Beta](https://terraform.io/docs/providers/google/guides/provider_versions.html) A full or partial URL of the network profile to apply to this network. + * `subnetworks_self_links` - the list of subnetworks which belong to the network * `self_link` - The URI of the resource. diff --git a/mmv1/third_party/terraform/website/docs/r/compute_instance.html.markdown b/mmv1/third_party/terraform/website/docs/r/compute_instance.html.markdown index 1521b7ee2cdb..ed5f5e4a3f60 100644 --- a/mmv1/third_party/terraform/website/docs/r/compute_instance.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/compute_instance.html.markdown @@ -395,7 +395,7 @@ is desired, you will need to modify your state file manually using array of alias IP ranges for this network interface. Can only be specified for network interfaces on subnet-mode networks. Structure [documented below](#nested_alias_ip_range). -* `nic_type` - (Optional) The type of vNIC to be used on this interface. Possible values: GVNIC, VIRTIO_NET, IDPF. +* `nic_type` - (Optional) The type of vNIC to be used on this interface. Possible values: GVNIC, VIRTIO_NET, IDPF. In the beta provider the additional values of MRDMA and IRDMA are supported. * `network_attachment` - (Optional) [Beta](https://terraform.io/docs/providers/google/guides/provider_versions.html) The URL of the network attachment that this interface should connect to in the following format: `projects/{projectNumber}/regions/{region_name}/networkAttachments/{network_attachment_name}`. diff --git a/mmv1/third_party/terraform/website/docs/r/compute_instance_template.html.markdown b/mmv1/third_party/terraform/website/docs/r/compute_instance_template.html.markdown index a2621e9d98f4..4e28fc3d1be5 100644 --- a/mmv1/third_party/terraform/website/docs/r/compute_instance_template.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/compute_instance_template.html.markdown @@ -561,7 +561,7 @@ The following arguments are supported: array of alias IP ranges for this network interface. Can only be specified for network interfaces on subnet-mode networks. Structure [documented below](#nested_alias_ip_range). -* `nic_type` - (Optional) The type of vNIC to be used on this interface. Possible values: GVNIC, VIRTIO_NET. +* `nic_type` - (Optional) The type of vNIC to be used on this interface. Possible values: GVNIC, VIRTIO_NET. In the beta provider the additional values of MRDMA and IRDMA are supported. * `stack_type` - (Optional) The stack type for this network interface to identify whether the IPv6 feature is enabled or not. Values are IPV4_IPV6 or IPV4_ONLY. If not specified, IPV4_ONLY will be used. diff --git a/mmv1/third_party/terraform/website/docs/r/compute_region_instance_template.html.markdown b/mmv1/third_party/terraform/website/docs/r/compute_region_instance_template.html.markdown index 316dd7ab257d..27bacc5e4bbb 100644 --- a/mmv1/third_party/terraform/website/docs/r/compute_region_instance_template.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/compute_region_instance_template.html.markdown @@ -527,7 +527,7 @@ The following arguments are supported: array of alias IP ranges for this network interface. Can only be specified for network interfaces on subnet-mode networks. Structure [documented below](#nested_alias_ip_range). -* `nic_type` - (Optional) The type of vNIC to be used on this interface. Possible values: GVNIC, VIRTIO_NET. +* `nic_type` - (Optional) The type of vNIC to be used on this interface. Possible values: GVNIC, VIRTIO_NET. In the beta provider the additional values of MRDMA and IRDMA are supported. * `stack_type` - (Optional) The stack type for this network interface to identify whether the IPv6 feature is enabled or not. Values are IPV4_IPV6 or IPV4_ONLY. If not specified, IPV4_ONLY will be used. From 9f76fadba2658320af041d1bdb968901ed1ffc9a Mon Sep 17 00:00:00 2001 From: Salome Papiashvili Date: Fri, 15 Nov 2024 18:15:44 +0100 Subject: [PATCH 070/105] Revert "Composer 3 GA" (#12336) --- .../composer/UserWorkloadsConfigMap.yaml | 8 ++- ...er_user_workloads_config_map_basic.tf.tmpl | 2 + .../provider/provider_mmv1_resources.go.tmpl | 7 ++ ...composer_user_workloads_config_map.go.tmpl | 2 + ...ser_user_workloads_config_map_test.go.tmpl | 2 + ...gle_composer_user_workloads_secret.go.tmpl | 2 + ...omposer_user_workloads_secret_test.go.tmpl | 2 + .../resource_composer_environment.go.tmpl | 65 ++++++++++++++++++- ...resource_composer_environment_test.go.tmpl | 6 +- ...ser_user_workloads_config_map_test.go.tmpl | 13 +++- ...rce_composer_user_workloads_secret.go.tmpl | 4 ++ ...omposer_user_workloads_secret_test.go.tmpl | 4 ++ ...er_user_workloads_config_map.html.markdown | 3 + ...mposer_user_workloads_secret.html.markdown | 3 + .../docs/r/composer_environment.html.markdown | 41 ++---------- ...mposer_user_workloads_secret.html.markdown | 3 + 16 files changed, 125 insertions(+), 42 deletions(-) diff --git a/mmv1/products/composer/UserWorkloadsConfigMap.yaml b/mmv1/products/composer/UserWorkloadsConfigMap.yaml index 4efc7c9ec7fe..9835430077f0 100644 --- a/mmv1/products/composer/UserWorkloadsConfigMap.yaml +++ b/mmv1/products/composer/UserWorkloadsConfigMap.yaml @@ -16,9 +16,11 @@ name: 'UserWorkloadsConfigMap' description: | User workloads ConfigMap used by Airflow tasks that run with Kubernetes Executor or KubernetesPodOperator. Intended for Composer 3 Environments. +min_version: 'beta' references: guides: - api: 'https://cloud.google.com/composer/docs/reference/rest/v1/projects.locations.environments.userWorkloadsConfigMaps' + # TODO: add v1 reference when this is moved to ga + api: 'https://cloud.google.com/composer/docs/reference/rest/v1beta1/projects.locations.environments.userWorkloadsConfigMaps' docs: base_url: 'projects/{{project}}/locations/{{region}}/environments/{{environment}}/userWorkloadsConfigMaps' self_link: 'projects/{{project}}/locations/{{region}}/environments/{{environment}}/userWorkloadsConfigMaps/{{name}}' @@ -39,6 +41,7 @@ parameters: type: String description: | The location or Compute Engine region for the environment. + min_version: 'beta' url_param_only: true immutable: true default_from_api: true @@ -46,6 +49,7 @@ parameters: type: String description: | Environment where the Kubernetes ConfigMap will be stored and used. + min_version: 'beta' url_param_only: true required: true immutable: true @@ -56,6 +60,7 @@ properties: type: String description: | Name of the Kubernetes ConfigMap. + min_version: 'beta' required: true immutable: true custom_flatten: 'templates/terraform/custom_flatten/name_from_self_link.tmpl' @@ -67,4 +72,5 @@ properties: description: | The "data" field of Kubernetes ConfigMap, organized in key-value pairs. For details see: https://kubernetes.io/docs/concepts/configuration/configmap/ + min_version: 'beta' immutable: false diff --git a/mmv1/templates/terraform/examples/composer_user_workloads_config_map_basic.tf.tmpl b/mmv1/templates/terraform/examples/composer_user_workloads_config_map_basic.tf.tmpl index 5b53968aac54..a2641c1bf801 100644 --- a/mmv1/templates/terraform/examples/composer_user_workloads_config_map_basic.tf.tmpl +++ b/mmv1/templates/terraform/examples/composer_user_workloads_config_map_basic.tf.tmpl @@ -1,4 +1,5 @@ resource "google_composer_environment" "environment" { + provider = google-beta name = "{{index $.Vars "environment_name"}}" region = "us-central1" config { @@ -9,6 +10,7 @@ resource "google_composer_environment" "environment" { } resource "google_composer_user_workloads_config_map" "{{$.PrimaryResourceId}}" { + provider = google-beta name = "{{index $.Vars "config_map_name"}}" region = "us-central1" environment = google_composer_environment.environment.name diff --git a/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.tmpl b/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.tmpl index 4950309f0d9c..9ac625153e69 100644 --- a/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.tmpl +++ b/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.tmpl @@ -7,6 +7,9 @@ import ( "github.com/hashicorp/terraform-provider-google/google/services/{{ $service }}" {{- end }} + {{ if eq $.TargetVersionName `ga` }} + "github.com/hashicorp/terraform-provider-google/google/services/composer" + {{- end }} "github.com/hashicorp/terraform-provider-google/google/services/container" "github.com/hashicorp/terraform-provider-google/google/services/containeraws" "github.com/hashicorp/terraform-provider-google/google/services/containerazure" @@ -64,8 +67,10 @@ var handwrittenDatasources = map[string]*schema.Resource{ "google_cloud_run_v2_job": cloudrunv2.DataSourceGoogleCloudRunV2Job(), "google_cloud_run_v2_service": cloudrunv2.DataSourceGoogleCloudRunV2Service(), "google_composer_environment": composer.DataSourceGoogleComposerEnvironment(), + {{- if ne $.TargetVersionName "ga" }} "google_composer_user_workloads_config_map": composer.DataSourceGoogleComposerUserWorkloadsConfigMap(), "google_composer_user_workloads_secret": composer.DataSourceGoogleComposerUserWorkloadsSecret(), + {{- end }} "google_composer_image_versions": composer.DataSourceGoogleComposerImageVersions(), "google_compute_address": compute.DataSourceGoogleComputeAddress(), "google_compute_addresses": compute.DataSourceGoogleComputeAddresses(), @@ -318,7 +323,9 @@ var handwrittenResources = map[string]*schema.Resource{ "google_billing_subaccount": resourcemanager.ResourceBillingSubaccount(), "google_cloudfunctions_function": cloudfunctions.ResourceCloudFunctionsFunction(), "google_composer_environment": composer.ResourceComposerEnvironment(), + {{- if ne $.TargetVersionName "ga" }} "google_composer_user_workloads_secret": composer.ResourceComposerUserWorkloadsSecret(), + {{- end }} "google_compute_attached_disk": compute.ResourceComputeAttachedDisk(), "google_compute_instance": compute.ResourceComputeInstance(), "google_compute_disk_async_replication": compute.ResourceComputeDiskAsyncReplication(), diff --git a/mmv1/third_party/terraform/services/composer/data_source_google_composer_user_workloads_config_map.go.tmpl b/mmv1/third_party/terraform/services/composer/data_source_google_composer_user_workloads_config_map.go.tmpl index a3aab2c8c184..2f9ad0137118 100644 --- a/mmv1/third_party/terraform/services/composer/data_source_google_composer_user_workloads_config_map.go.tmpl +++ b/mmv1/third_party/terraform/services/composer/data_source_google_composer_user_workloads_config_map.go.tmpl @@ -1,5 +1,6 @@ package composer +{{ if ne $.TargetVersionName `ga` -}} import ( "fmt" @@ -47,3 +48,4 @@ func dataSourceGoogleComposerUserWorkloadsConfigMapRead(d *schema.ResourceData, return nil } +{{- end }} diff --git a/mmv1/third_party/terraform/services/composer/data_source_google_composer_user_workloads_config_map_test.go.tmpl b/mmv1/third_party/terraform/services/composer/data_source_google_composer_user_workloads_config_map_test.go.tmpl index ea8e664c2773..eac26bfd11cb 100644 --- a/mmv1/third_party/terraform/services/composer/data_source_google_composer_user_workloads_config_map_test.go.tmpl +++ b/mmv1/third_party/terraform/services/composer/data_source_google_composer_user_workloads_config_map_test.go.tmpl @@ -1,5 +1,6 @@ package composer_test +{{ if ne $.TargetVersionName `ga` -}} import ( "fmt" "testing" @@ -55,3 +56,4 @@ data "google_composer_user_workloads_config_map" "test" { } `, context) } +{{- end }} diff --git a/mmv1/third_party/terraform/services/composer/data_source_google_composer_user_workloads_secret.go.tmpl b/mmv1/third_party/terraform/services/composer/data_source_google_composer_user_workloads_secret.go.tmpl index 2e6575460548..0acf758493bb 100644 --- a/mmv1/third_party/terraform/services/composer/data_source_google_composer_user_workloads_secret.go.tmpl +++ b/mmv1/third_party/terraform/services/composer/data_source_google_composer_user_workloads_secret.go.tmpl @@ -1,5 +1,6 @@ package composer +{{ if ne $.TargetVersionName `ga` -}} import ( "fmt" @@ -59,3 +60,4 @@ func dataSourceGoogleComposerUserWorkloadsSecretRead(d *schema.ResourceData, met return nil } +{{- end }} diff --git a/mmv1/third_party/terraform/services/composer/data_source_google_composer_user_workloads_secret_test.go.tmpl b/mmv1/third_party/terraform/services/composer/data_source_google_composer_user_workloads_secret_test.go.tmpl index 2098a4aeb89e..3860a8e8c40f 100644 --- a/mmv1/third_party/terraform/services/composer/data_source_google_composer_user_workloads_secret_test.go.tmpl +++ b/mmv1/third_party/terraform/services/composer/data_source_google_composer_user_workloads_secret_test.go.tmpl @@ -1,5 +1,6 @@ package composer_test +{{ if ne $.TargetVersionName `ga` -}} import ( "errors" "fmt" @@ -98,3 +99,4 @@ data "google_composer_user_workloads_secret" "test" { } `, context) } +{{- end }} diff --git a/mmv1/third_party/terraform/services/composer/resource_composer_environment.go.tmpl b/mmv1/third_party/terraform/services/composer/resource_composer_environment.go.tmpl index 7882a22c4566..e8da985580f1 100644 --- a/mmv1/third_party/terraform/services/composer/resource_composer_environment.go.tmpl +++ b/mmv1/third_party/terraform/services/composer/resource_composer_environment.go.tmpl @@ -56,7 +56,9 @@ var ( "config.0.software_config.0.python_version", "config.0.software_config.0.scheduler_count", "config.0.software_config.0.cloud_data_lineage_integration", +{{- if ne $.TargetVersionName "ga" }} "config.0.software_config.0.web_server_plugins_mode", +{{- end }} } composerConfigKeys = []string{ @@ -74,8 +76,10 @@ var ( "config.0.environment_size", "config.0.master_authorized_networks_config", "config.0.resilience_mode", +{{- if ne $.TargetVersionName "ga" }} "config.0.enable_private_environment", "config.0.enable_private_builds_only", +{{- end }} "config.0.data_retention_config", } @@ -88,7 +92,9 @@ var ( "config.0.workloads_config.0.triggerer", "config.0.workloads_config.0.web_server", "config.0.workloads_config.0.worker", +{{- if ne $.TargetVersionName "ga" }} "config.0.workloads_config.0.dag_processor", +{{- end }} } composerPrivateEnvironmentConfig = []string{ @@ -167,8 +173,10 @@ func ResourceComposerEnvironment() *schema.Resource { customdiff.ValidateChange("config.0.software_config.0.image_version", imageVersionChangeValidationFunc), versionValidationCustomizeDiffFunc, ), - customdiff.ForceNewIf("config.0.node_config.0.network", forceNewIfNotComposer3CustomDiff("config.0.node_config.0.network")), - customdiff.ForceNewIf("config.0.node_config.0.subnetwork", forceNewIfNotComposer3CustomDiff("config.0.node_config.0.subnetwork")), +{{- if ne $.TargetVersionName "ga" }} + customdiff.ForceNewIf("config.0.node_config.0.network", forceNewCustomDiff("config.0.node_config.0.network")), + customdiff.ForceNewIf("config.0.node_config.0.subnetwork", forceNewCustomDiff("config.0.node_config.0.subnetwork")), +{{- end }} ), Schema: map[string]*schema.Schema{ @@ -238,18 +246,29 @@ func ResourceComposerEnvironment() *schema.Resource { Type: schema.TypeString, Computed: true, Optional: true, +{{- if eq $.TargetVersionName "ga" }} + ForceNew: true, +{{- else }} + ForceNew: false, ConflictsWith: []string{"config.0.node_config.0.composer_network_attachment"}, +{{- end }} DiffSuppressFunc: tpgresource.CompareSelfLinkOrResourceName, Description: `The Compute Engine machine type used for cluster instances, specified as a name or relative resource name. For example: "projects/{project}/zones/{zone}/machineTypes/{machineType}". Must belong to the enclosing environment's project and region/zone. The network must belong to the environment's project. If unspecified, the "default" network ID in the environment's project is used. If a Custom Subnet Network is provided, subnetwork must also be provided.`, }, "subnetwork": { Type: schema.TypeString, Optional: true, +{{- if eq $.TargetVersionName "ga" }} + ForceNew: true, +{{- else }} + ForceNew: false, Computed: true, ConflictsWith: []string{"config.0.node_config.0.composer_network_attachment"}, +{{- end }} DiffSuppressFunc: tpgresource.CompareSelfLinkOrResourceName, Description: `The Compute Engine subnetwork to be used for machine communications, specified as a self-link, relative resource name (e.g. "projects/{project}/regions/{region}/subnetworks/{subnetwork}"), or by name. If subnetwork is provided, network must also be provided and the subnetwork must belong to the enclosing environment's project and region.`, }, +{{- if ne $.TargetVersionName "ga" }} "composer_network_attachment": { Type: schema.TypeString, Computed: true, @@ -257,6 +276,7 @@ func ResourceComposerEnvironment() *schema.Resource { ForceNew: false, Description: `PSC (Private Service Connect) Network entry point. Customers can pre-create the Network Attachment and point Cloud Composer environment to use. It is possible to share network attachment among many environments, provided enough IP addresses are available.`, }, +{{- end }} "disk_size_gb": { Type: schema.TypeInt, Computed: true, @@ -365,6 +385,7 @@ func ResourceComposerEnvironment() *schema.Resource { }, }, }, +{{- if ne $.TargetVersionName "ga" }} "composer_internal_ipv4_cidr_block": { Type: schema.TypeString, Computed: true, @@ -373,6 +394,7 @@ func ResourceComposerEnvironment() *schema.Resource { ValidateFunc: validateComposerInternalIpv4CidrBlock, Description: `IPv4 cidr range that will be used by Composer internal components.`, }, +{{- end }} }, }, }, @@ -491,6 +513,7 @@ func ResourceComposerEnvironment() *schema.Resource { }, }, }, +{{- if ne $.TargetVersionName "ga" }} "web_server_plugins_mode": { Type: schema.TypeString, Optional: true, @@ -500,6 +523,7 @@ func ResourceComposerEnvironment() *schema.Resource { ValidateFunc: validation.StringInSlice([]string{"ENABLED", "DISABLED"}, false), Description: `Should be either 'ENABLED' or 'DISABLED'. Defaults to 'ENABLED'. Used in Composer 3.`, }, +{{- end }} }, }, }, @@ -582,6 +606,7 @@ func ResourceComposerEnvironment() *schema.Resource { }, }, }, +{{- if ne $.TargetVersionName "ga" }} "enable_private_environment": { Type: schema.TypeBool, Computed: true, @@ -598,6 +623,7 @@ func ResourceComposerEnvironment() *schema.Resource { AtLeastOneOf: composerConfigKeys, Description: `Optional. If true, builds performed during operations that install Python packages have only private connectivity to Google services. If false, the builds also have access to the internet.`, }, +{{- end }} "web_server_network_access_control": { Type: schema.TypeList, Optional: true, @@ -907,6 +933,7 @@ func ResourceComposerEnvironment() *schema.Resource { }, }, }, +{{- if ne $.TargetVersionName "ga" }} "dag_processor": { Type: schema.TypeList, Optional: true, @@ -952,6 +979,7 @@ func ResourceComposerEnvironment() *schema.Resource { }, }, }, +{{- end }} }, }, }, @@ -1197,6 +1225,7 @@ func resourceComposerEnvironmentUpdate(d *schema.ResourceData, meta interface{}) return err } +{{ if ne $.TargetVersionName `ga` -}} noChangeErrorMessage := "Update request does not result in any change to the environment's configuration" if d.HasChange("config.0.node_config.0.network") || d.HasChange("config.0.node_config.0.subnetwork"){ // step 1: update with empty network and subnetwork @@ -1256,6 +1285,7 @@ func resourceComposerEnvironmentUpdate(d *schema.ResourceData, meta interface{}) } } } +{{- end }} if d.HasChange("config.0.software_config.0.image_version") { patchObj := &composer.Environment{ @@ -1357,6 +1387,7 @@ func resourceComposerEnvironmentUpdate(d *schema.ResourceData, meta interface{}) } } +{{ if ne $.TargetVersionName `ga` -}} if d.HasChange("config.0.enable_private_environment") { patchObj := &composer.Environment{ Config: &composer.EnvironmentConfig{ @@ -1398,6 +1429,7 @@ func resourceComposerEnvironmentUpdate(d *schema.ResourceData, meta interface{}) return err } } +{{- end }} if d.HasChange("config.0.node_count") { patchObj := &composer.Environment{Config: &composer.EnvironmentConfig{}} @@ -1657,10 +1689,12 @@ func flattenComposerEnvironmentConfig(envCfg *composer.EnvironmentConfig) interf if !isComposer3(imageVersion){ transformed["private_environment_config"] = flattenComposerEnvironmentConfigPrivateEnvironmentConfig(envCfg.PrivateEnvironmentConfig) } +{{- if ne $.TargetVersionName "ga" }} if isComposer3(imageVersion) && envCfg.PrivateEnvironmentConfig != nil { transformed["enable_private_environment"] = envCfg.PrivateEnvironmentConfig.EnablePrivateEnvironment transformed["enable_private_builds_only"] = envCfg.PrivateEnvironmentConfig.EnablePrivateBuildsOnly } +{{- end }} transformed["web_server_network_access_control"] = flattenComposerEnvironmentConfigWebServerNetworkAccessControl(envCfg.WebServerNetworkAccessControl) transformed["database_config"] = flattenComposerEnvironmentConfigDatabaseConfig(envCfg.DatabaseConfig) transformed["web_server_config"] = flattenComposerEnvironmentConfigWebServerConfig(envCfg.WebServerConfig) @@ -1803,13 +1837,17 @@ func flattenComposerEnvironmentConfigWorkloadsConfig(workloadsConfig *composer.W transformedTriggerer := make(map[string]interface{}) transformedWebServer := make(map[string]interface{}) transformedWorker := make(map[string]interface{}) +{{- if ne $.TargetVersionName "ga" }} transformedDagProcessor := make(map[string]interface{}) +{{- end }} wlCfgScheduler := workloadsConfig.Scheduler wlCfgTriggerer := workloadsConfig.Triggerer wlCfgWebServer := workloadsConfig.WebServer wlCfgWorker := workloadsConfig.Worker +{{- if ne $.TargetVersionName "ga" }} wlCfgDagProcessor := workloadsConfig.DagProcessor +{{- end }} if wlCfgScheduler == nil { transformedScheduler = nil @@ -1846,6 +1884,7 @@ func flattenComposerEnvironmentConfigWorkloadsConfig(workloadsConfig *composer.W transformedWorker["max_count"] = wlCfgWorker.MaxCount } +{{ if ne $.TargetVersionName `ga` -}} if wlCfgDagProcessor == nil { transformedDagProcessor = nil } else { @@ -1854,6 +1893,7 @@ func flattenComposerEnvironmentConfigWorkloadsConfig(workloadsConfig *composer.W transformedDagProcessor["storage_gb"] = wlCfgDagProcessor.StorageGb transformedDagProcessor["count"] = wlCfgDagProcessor.Count } +{{- end }} transformed["scheduler"] = []interface{}{transformedScheduler} if transformedTriggerer != nil { @@ -1861,9 +1901,12 @@ func flattenComposerEnvironmentConfigWorkloadsConfig(workloadsConfig *composer.W } transformed["web_server"] = []interface{}{transformedWebServer} transformed["worker"] = []interface{}{transformedWorker} +{{- if ne $.TargetVersionName "ga" }} if transformedDagProcessor != nil { transformed["dag_processor"] = []interface{}{transformedDagProcessor} } +{{- end }} + return []interface{}{transformed} } @@ -1899,7 +1942,9 @@ func flattenComposerEnvironmentConfigNodeConfig(nodeCfg *composer.NodeConfig) in transformed["machine_type"] = nodeCfg.MachineType transformed["network"] = nodeCfg.Network transformed["subnetwork"] = nodeCfg.Subnetwork +{{- if ne $.TargetVersionName "ga" }} transformed["composer_network_attachment"] = nodeCfg.ComposerNetworkAttachment +{{- end }} transformed["disk_size_gb"] = nodeCfg.DiskSizeGb transformed["service_account"] = nodeCfg.ServiceAccount transformed["oauth_scopes"] = flattenComposerEnvironmentConfigNodeConfigOauthScopes(nodeCfg.OauthScopes) @@ -1909,7 +1954,9 @@ func flattenComposerEnvironmentConfigNodeConfig(nodeCfg *composer.NodeConfig) in transformed["enable_ip_masq_agent"] = nodeCfg.EnableIpMasqAgent transformed["tags"] = flattenComposerEnvironmentConfigNodeConfigTags(nodeCfg.Tags) transformed["ip_allocation_policy"] = flattenComposerEnvironmentConfigNodeConfigIPAllocationPolicy(nodeCfg.IpAllocationPolicy) +{{- if ne $.TargetVersionName "ga" }} transformed["composer_internal_ipv4_cidr_block"] = nodeCfg.ComposerInternalIpv4CidrBlock +{{- end }} return []interface{}{transformed} } @@ -1953,6 +2000,7 @@ func flattenComposerEnvironmentConfigSoftwareConfig(softwareCfg *composer.Softwa transformed["env_variables"] = softwareCfg.EnvVariables transformed["scheduler_count"] = softwareCfg.SchedulerCount transformed["cloud_data_lineage_integration"] = flattenComposerEnvironmentConfigSoftwareConfigCloudDataLineageIntegration(softwareCfg.CloudDataLineageIntegration) +{{- if ne $.TargetVersionName "ga" }} if softwareCfg.WebServerPluginsMode == "PLUGINS_DISABLED"{ transformed["web_server_plugins_mode"] = "DISABLED" } else if softwareCfg.WebServerPluginsMode == "PLUGINS_ENABLED"{ @@ -1960,6 +2008,7 @@ func flattenComposerEnvironmentConfigSoftwareConfig(softwareCfg *composer.Softwa } else { transformed["web_server_plugins_mode"] = softwareCfg.WebServerPluginsMode } +{{- end }} return []interface{}{transformed} } @@ -2029,6 +2078,7 @@ func expandComposerEnvironmentConfig(v interface{}, d *schema.ResourceData, conf } transformed.PrivateEnvironmentConfig = transformedPrivateEnvironmentConfig +{{ if ne $.TargetVersionName `ga` -}} /* config.enable_private_environment in terraform maps to composer.PrivateEnvironmentConfig.EnablePrivateEnvironment in API. @@ -2044,6 +2094,7 @@ func expandComposerEnvironmentConfig(v interface{}, d *schema.ResourceData, conf transformed.PrivateEnvironmentConfig.EnablePrivateBuildsOnly = enablePrivateBuildsOnlyRaw.(bool) } } +{{- end }} transformedWebServerNetworkAccessControl, err := expandComposerEnvironmentConfigWebServerNetworkAccessControl(original["web_server_network_access_control"], d, config) if err != nil { @@ -2342,6 +2393,7 @@ func expandComposerEnvironmentConfigWorkloadsConfig(v interface{}, d *schema.Res } } +{{ if ne $.TargetVersionName `ga` -}} if v, ok := original["dag_processor"]; ok { if len(v.([]interface{})) > 0 && v.([]interface{})[0] != nil { transformedDagProcessor := &composer.DagProcessorResource{} @@ -2353,6 +2405,7 @@ func expandComposerEnvironmentConfigWorkloadsConfig(v interface{}, d *schema.Res transformed.DagProcessor = transformedDagProcessor } } +{{- end }} return transformed, nil } @@ -2509,9 +2562,11 @@ func expandComposerEnvironmentConfigNodeConfig(v interface{}, d *schema.Resource transformed.Subnetwork = transformedSubnetwork } +{{ if ne $.TargetVersionName `ga` -}} if v, ok := original["composer_network_attachment"]; ok { transformed.ComposerNetworkAttachment = v.(string) } +{{- end }} transformedIPAllocationPolicy, err := expandComposerEnvironmentIPAllocationPolicy(original["ip_allocation_policy"], d, config) if err != nil { @@ -2531,9 +2586,11 @@ func expandComposerEnvironmentConfigNodeConfig(v interface{}, d *schema.Resource } transformed.Tags = transformedTags +{{ if ne $.TargetVersionName `ga` -}} if transformedComposerInternalIpv4CidrBlock, ok := original["composer_internal_ipv4_cidr_block"]; ok { transformed.ComposerInternalIpv4CidrBlock = transformedComposerInternalIpv4CidrBlock.(string) } +{{- end }} return transformed, nil } @@ -2684,6 +2741,7 @@ func expandComposerEnvironmentConfigSoftwareConfig(v interface{}, d *schema.Reso } transformed.CloudDataLineageIntegration = transformedCloudDataLineageIntegration +{{ if ne $.TargetVersionName `ga` -}} if original["web_server_plugins_mode"].(string) == "DISABLED"{ transformed.WebServerPluginsMode = "PLUGINS_DISABLED" } else if original["web_server_plugins_mode"].(string) == "ENABLED"{ @@ -2691,6 +2749,7 @@ func expandComposerEnvironmentConfigSoftwareConfig(v interface{}, d *schema.Reso } else { transformed.WebServerPluginsMode = original["web_server_plugins_mode"].(string) } +{{- end }} return transformed, nil } @@ -2988,7 +3047,7 @@ func isComposer3(imageVersion string) bool { return strings.Contains(imageVersion, "composer-3") } -func forceNewIfNotComposer3CustomDiff(key string) customdiff.ResourceConditionFunc { +func forceNewCustomDiff(key string) customdiff.ResourceConditionFunc { return func(ctx context.Context, d *schema.ResourceDiff, meta interface{}) bool { old, new := d.GetChange(key) imageVersion := d.Get("config.0.software_config.0.image_version").(string) diff --git a/mmv1/third_party/terraform/services/composer/resource_composer_environment_test.go.tmpl b/mmv1/third_party/terraform/services/composer/resource_composer_environment_test.go.tmpl index 248cf1222c44..8fc8e27024b7 100644 --- a/mmv1/third_party/terraform/services/composer/resource_composer_environment_test.go.tmpl +++ b/mmv1/third_party/terraform/services/composer/resource_composer_environment_test.go.tmpl @@ -1191,6 +1191,7 @@ func TestAccComposerEnvironment_customBucketWithUrl(t *testing.T) { }) } +{{ if ne $.TargetVersionName `ga` -}} // Checks Composer 3 environment creation with new fields. func TestAccComposerEnvironmentComposer3_basic(t *testing.T) { t.Parallel() @@ -1547,6 +1548,7 @@ func TestAccComposerEnvironmentComposer3_usesUnsupportedField_expectError(t *tes }, }) } +{{- end }} func testAccComposerEnvironment_customBucket(bucketName, envName, network, subnetwork string) string { return fmt.Sprintf(` @@ -3231,6 +3233,7 @@ resource "google_project_iam_member" "composer-worker" { `, environment, network, subnetwork, serviceAccount) } +{{ if ne $.TargetVersionName `ga` -}} func testAccComposerEnvironmentComposer2_empty(name, network, subnetwork string) string { return fmt.Sprintf(` resource "google_composer_environment" "test" { @@ -3299,7 +3302,7 @@ resource "google_composer_environment" "test" { config { software_config { image_version = "composer-2-airflow-2" - web_server_plugins_mode = "ENABLED" + web_server_plugins_mode = "ENABLED" } } } @@ -3570,6 +3573,7 @@ resource "google_compute_subnetwork" "test" { } `, name, networkAttachment, network, subnetwork) } +{{- end }} // WARNING: This is not actually a check and is a terrible clean-up step because Composer Environments // have a bug that hasn't been fixed. Composer will add firewalls to non-default networks for environments diff --git a/mmv1/third_party/terraform/services/composer/resource_composer_user_workloads_config_map_test.go.tmpl b/mmv1/third_party/terraform/services/composer/resource_composer_user_workloads_config_map_test.go.tmpl index 37feb346b799..312d8331f75b 100644 --- a/mmv1/third_party/terraform/services/composer/resource_composer_user_workloads_config_map_test.go.tmpl +++ b/mmv1/third_party/terraform/services/composer/resource_composer_user_workloads_config_map_test.go.tmpl @@ -1,5 +1,7 @@ package composer_test +{{ if ne $.TargetVersionName `ga` -}} + import ( "fmt" "strings" @@ -20,7 +22,7 @@ func TestAccComposerUserWorkloadsConfigMap_composerUserWorkloadsConfigMapBasicEx acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, - ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t), CheckDestroy: testAccCheckComposerUserWorkloadsConfigMapDestroyProducer(t), Steps: []resource.TestStep{ { @@ -56,7 +58,7 @@ func TestAccComposerUserWorkloadsConfigMap_composerUserWorkloadsConfigMapBasicEx acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, - ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t), CheckDestroy: testAccCheckComposerUserWorkloadsConfigMapDestroyProducer(t), Steps: []resource.TestStep{ { @@ -80,6 +82,7 @@ func TestAccComposerUserWorkloadsConfigMap_composerUserWorkloadsConfigMapBasicEx func testAccComposerUserWorkloadsConfigMap_composerUserWorkloadsConfigMapBasicExample_basic(context map[string]interface{}) string { return acctest.Nprintf(` resource "google_composer_environment" "environment" { + provider = google-beta name = "tf-test-test-environment%{random_suffix}" region = "us-central1" config { @@ -90,6 +93,7 @@ resource "google_composer_environment" "environment" { } resource "google_composer_user_workloads_config_map" "config_map" { + provider = google-beta name = "tf-test-test-config-map%{random_suffix}" region = "us-central1" environment = google_composer_environment.environment.name @@ -103,6 +107,7 @@ resource "google_composer_user_workloads_config_map" "config_map" { func testAccComposerUserWorkloadsConfigMap_composerUserWorkloadsConfigMapBasicExample_update(context map[string]interface{}) string { return acctest.Nprintf(` resource "google_composer_environment" "environment" { + provider = google-beta name = "tf-test-test-environment%{random_suffix}" region = "us-central1" config { @@ -113,6 +118,7 @@ resource "google_composer_environment" "environment" { } resource "google_composer_user_workloads_config_map" "config_map" { + provider = google-beta name = "tf-test-test-config-map%{random_suffix}" region = "us-central1" environment = google_composer_environment.environment.name @@ -126,6 +132,7 @@ resource "google_composer_user_workloads_config_map" "config_map" { func testAccComposerUserWorkloadsConfigMap_composerUserWorkloadsConfigMapBasicExample_delete(context map[string]interface{}) string { return acctest.Nprintf(` resource "google_composer_environment" "environment" { + provider = google-beta name = "tf-test-test-environment%{random_suffix}" region = "us-central1" config { @@ -159,3 +166,5 @@ func testAccComposerUserWorkloadsConfigMapDestroyed(t *testing.T) func(s *terraf return nil } } + +{{ end }} diff --git a/mmv1/third_party/terraform/services/composer/resource_composer_user_workloads_secret.go.tmpl b/mmv1/third_party/terraform/services/composer/resource_composer_user_workloads_secret.go.tmpl index 9cea9a079dbb..94ebd8182ebc 100644 --- a/mmv1/third_party/terraform/services/composer/resource_composer_user_workloads_secret.go.tmpl +++ b/mmv1/third_party/terraform/services/composer/resource_composer_user_workloads_secret.go.tmpl @@ -1,5 +1,7 @@ package composer +{{ if ne $.TargetVersionName `ga` -}} + import ( "fmt" "log" @@ -265,3 +267,5 @@ func (n *UserWorkloadsSecretName) ResourceName() string { func (n *UserWorkloadsSecretName) ParentName() string { return fmt.Sprintf("projects/%s/locations/%s/environments/%s", n.Project, n.Region, n.Environment) } + +{{ end }} diff --git a/mmv1/third_party/terraform/services/composer/resource_composer_user_workloads_secret_test.go.tmpl b/mmv1/third_party/terraform/services/composer/resource_composer_user_workloads_secret_test.go.tmpl index cb83e29ce0d0..9008bfdc65df 100644 --- a/mmv1/third_party/terraform/services/composer/resource_composer_user_workloads_secret_test.go.tmpl +++ b/mmv1/third_party/terraform/services/composer/resource_composer_user_workloads_secret_test.go.tmpl @@ -1,5 +1,7 @@ package composer_test +{{ if ne $.TargetVersionName `ga` -}} + import ( "fmt" "testing" @@ -177,3 +179,5 @@ func testAccComposerUserWorkloadsSecretDestroyed(t *testing.T) func(s *terraform return nil } } + +{{ end }} diff --git a/mmv1/third_party/terraform/website/docs/d/composer_user_workloads_config_map.html.markdown b/mmv1/third_party/terraform/website/docs/d/composer_user_workloads_config_map.html.markdown index 00e2a0d4a27f..f582d646df88 100644 --- a/mmv1/third_party/terraform/website/docs/d/composer_user_workloads_config_map.html.markdown +++ b/mmv1/third_party/terraform/website/docs/d/composer_user_workloads_config_map.html.markdown @@ -8,6 +8,9 @@ description: |- Provides access to Kubernetes ConfigMap configuration for a given project, region and Composer Environment. +> **Warning:** This data source is in beta, and should be used with the terraform-provider-google-beta provider. +See [Provider Versions](https://terraform.io/docs/providers/google/guides/provider_versions.html) for more details on beta resources. + ## Example Usage ```hcl diff --git a/mmv1/third_party/terraform/website/docs/d/composer_user_workloads_secret.html.markdown b/mmv1/third_party/terraform/website/docs/d/composer_user_workloads_secret.html.markdown index 3b7f61b87562..93f5356a781f 100644 --- a/mmv1/third_party/terraform/website/docs/d/composer_user_workloads_secret.html.markdown +++ b/mmv1/third_party/terraform/website/docs/d/composer_user_workloads_secret.html.markdown @@ -8,6 +8,9 @@ description: |- Provides access to Kubernetes Secret configuration for a given project, region and Composer Environment. +~> **Warning:** This data source is in beta, and should be used with the terraform-provider-google-beta provider. +See [Provider Versions](https://terraform.io/docs/providers/google/guides/provider_versions.html) for more details on beta resources. + ## Example Usage ```hcl diff --git a/mmv1/third_party/terraform/website/docs/r/composer_environment.html.markdown b/mmv1/third_party/terraform/website/docs/r/composer_environment.html.markdown index 8f560d4f662f..35740d97bcb9 100644 --- a/mmv1/third_party/terraform/website/docs/r/composer_environment.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/composer_environment.html.markdown @@ -363,35 +363,6 @@ resource "google_composer_environment" "example" { } ``` -If you specify an existing network attachment that you also manage in Terraform, then Terraform will revert changes -to the attachment done by Cloud Composer when you apply configuration changes. As a result, the environment will no -longer use the attachment. To address this problem, make sure that Terraform ignores changes to the -`producer_accept_lists` parameter of the attachment, as follows: - -```hcl -resource "google_compute_network_attachment" "example" { - lifecycle { - ignore_changes = [producer_accept_lists] - } - - # ... other configuration parameters -} - -resource "google_composer_environment" "example" { - name = "example-environment" - region = "us-central1" - - config { - - node_config { - composer_network_attachment = google_compute_network_attachment.example.id - } - - # ... other configuration parameters - } -} -``` - ### With Software (Airflow) Config ```hcl @@ -1332,11 +1303,11 @@ The following arguments are supported: The configuration settings for software (Airflow) inside the environment. Structure is [documented below](#nested_software_config_c3). * `enable_private_environment` - - (Optional, Cloud Composer 3 only) + (Optional, [Beta](https://terraform.io/docs/providers/google/guides/provider_versions.html), Cloud Composer 3 only) If true, a private Composer environment will be created. * `enable_private_builds_only` - - (Optional, Cloud Composer 3 only) + (Optional, [Beta](https://terraform.io/docs/providers/google/guides/provider_versions.html), Cloud Composer 3 only) If true, builds performed during operations that install Python packages have only private connectivity to Google services. If false, the builds also have access to the internet. @@ -1406,7 +1377,7 @@ The following arguments are supported: network must also be provided and the subnetwork must belong to the enclosing environment's project and region. * `composer_network_attachment` - - (Optional, Cloud Composer 3 only) + (Optional, [Beta](https://terraform.io/docs/providers/google/guides/provider_versions.html), Cloud Composer 3 only) PSC (Private Service Connect) Network entry point. Customers can pre-create the Network Attachment and point Cloud Composer environment to use. It is possible to share network attachment among many environments, provided enough IP addresses are available. @@ -1427,7 +1398,7 @@ The following arguments are supported: Cannot be updated. * `composer_internal_ipv4_cidr_block` - - (Optional, Cloud Composer 3 only) + (Optional, [Beta](https://terraform.io/docs/providers/google/guides/provider_versions.html), Cloud Composer 3 only) /20 IPv4 cidr range that will be used by Composer internal components. Cannot be updated. @@ -1500,7 +1471,7 @@ The following arguments are supported: [documented below](#nested_cloud_data_lineage_integration_c3). * `web_server_plugins_mode` - - (Optional, Cloud Composer 3 only) + (Optional, [Beta](https://terraform.io/docs/providers/google/guides/provider_versions.html), Cloud Composer 3 only) Web server plugins configuration. Can be either 'ENABLED' or 'DISABLED'. Defaults to 'ENABLED'. The `cloud_data_lineage_integration` block supports: @@ -1552,7 +1523,7 @@ The `workloads_config` block supports: Configuration for resources used by Airflow workers. * `dag_processor` - - (Optional, Cloud Composer 3 only) + (Optional, [Beta](https://terraform.io/docs/providers/google/guides/provider_versions.html), Cloud Composer 3 only) Configuration for resources used by DAG processor. The `scheduler` block supports: diff --git a/mmv1/third_party/terraform/website/docs/r/composer_user_workloads_secret.html.markdown b/mmv1/third_party/terraform/website/docs/r/composer_user_workloads_secret.html.markdown index e07d8293d763..797798867148 100644 --- a/mmv1/third_party/terraform/website/docs/r/composer_user_workloads_secret.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/composer_user_workloads_secret.html.markdown @@ -6,6 +6,9 @@ description: |- # google_composer_user_workloads_secret +~> **Warning:** These resources are in beta, and should be used with the terraform-provider-google-beta provider. +See [Provider Versions](https://terraform.io/docs/providers/google/guides/provider_versions.html) for more details on beta resources. + User workloads Secret used by Airflow tasks that run with Kubernetes Executor or KubernetesPodOperator. Intended for Composer 3 Environments. From ab80e5eff2c6c9f9515622b93cdade13a4719e5c Mon Sep 17 00:00:00 2001 From: "Stephen Lewis (Burrows)" Date: Fri, 15 Nov 2024 09:44:46 -0800 Subject: [PATCH 071/105] Made traffic_split field use default_from_api (#12323) --- mmv1/products/vertexai/Endpoint.yaml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/mmv1/products/vertexai/Endpoint.yaml b/mmv1/products/vertexai/Endpoint.yaml index aaf985fced27..4a6bc362f498 100644 --- a/mmv1/products/vertexai/Endpoint.yaml +++ b/mmv1/products/vertexai/Endpoint.yaml @@ -367,15 +367,15 @@ properties: output: true - name: 'trafficSplit' type: String + default_from_api: true description: | A map from a DeployedModel's id to the percentage of this Endpoint's traffic that should be forwarded to that DeployedModel. If a DeployedModel's id is not listed in this map, then it receives no traffic. - The traffic percentage values must add up to 100, or map must be empty if the Endpoint is to not accept any traffic at a moment. - - ~> **Note:** The `traffic_split` setting only applies after a model has been deployed to the endpoint. Re-applying a `google_vertex_ai_endpoint` - resource without updating the `traffic_split` post-deployment may lead to your deployed `traffic_split` being lost; see + The traffic percentage values must add up to 100, or map must be empty if the Endpoint is to not accept any traffic at a moment. See the `deployModel` [example](https://cloud.google.com/vertex-ai/docs/general/deployment#deploy_a_model_to_an_endpoint) and - [documentation](https://cloud.google.com/vertex-ai/docs/reference/rest/v1beta1/projects.locations.endpoints/deployModel) for details. + [documentation](https://cloud.google.com/vertex-ai/docs/reference/rest/v1beta1/projects.locations.endpoints/deployModel) for more information. + + ~> **Note:** To set the map to empty, set `"{}"`, apply, and then remove the field from your config. state_func: 'func(v interface{}) string { s, _ := structure.NormalizeJsonString(v); return s }' custom_flatten: 'templates/terraform/custom_flatten/json_schema.tmpl' custom_expand: 'templates/terraform/custom_expand/json_schema.tmpl' From c7b7dc40571ddeb6e160035600d512d413dfbbb5 Mon Sep 17 00:00:00 2001 From: Ryan Oaks Date: Fri, 15 Nov 2024 13:53:52 -0500 Subject: [PATCH 072/105] Add resource metadata for dcl resources (#12266) --- mmv1/provider/template_data.go | 3 +++ mmv1/provider/terraform.go | 6 +++++- .../services/apikeys/resource_apikeys_key_meta.yaml | 5 +++++ .../resource_assured_workloads_workload_meta.yaml.tmpl | 9 +++++++++ .../cloudbuild/resource_cloudbuild_worker_pool_meta.yaml | 5 +++++ ...resource_clouddeploy_delivery_pipeline_meta copy.yaml | 5 +++++ .../clouddeploy/resource_clouddeploy_target_meta.yaml | 5 +++++ .../resource_compute_firewall_policy_meta.yaml.tmpl | 9 +++++++++ .../resource_container_aws_cluster_meta.yaml | 5 +++++ .../resource_container_aws_node_pool_meta.yaml | 5 +++++ .../resource_container_azure_client_meta.yaml | 5 +++++ .../resource_container_azure_cluster_meta.yaml | 5 +++++ .../resource_container_azure_node_pool_meta.yaml | 5 +++++ .../services/dataplex/resource_dataplex_asset_meta.yaml | 5 +++++ .../services/dataplex/resource_dataplex_lake_meta.yaml | 5 +++++ .../services/dataplex/resource_dataplex_zone_meta.yaml | 5 +++++ .../resource_dataproc_workflow_template_meta.yaml | 5 +++++ .../eventarc/resource_eventarc_channel_meta.yaml | 5 +++++ .../resource_eventarc_google_channel_config_meta.yaml | 5 +++++ .../eventarc/resource_eventarc_trigger_meta.yaml | 5 +++++ .../resource_firebaserules_release_meta.yaml | 5 +++++ .../resource_firebaserules_ruleset_meta.yaml | 5 +++++ .../resource_gke_hub_feature_membership_meta.yaml.tmpl | 9 +++++++++ .../resource_recaptcha_enterprise_key_meta.yaml | 5 +++++ 24 files changed, 130 insertions(+), 1 deletion(-) create mode 100644 mmv1/third_party/terraform/services/apikeys/resource_apikeys_key_meta.yaml create mode 100644 mmv1/third_party/terraform/services/assuredworkloads/resource_assured_workloads_workload_meta.yaml.tmpl create mode 100644 mmv1/third_party/terraform/services/cloudbuild/resource_cloudbuild_worker_pool_meta.yaml create mode 100644 mmv1/third_party/terraform/services/clouddeploy/resource_clouddeploy_delivery_pipeline_meta copy.yaml create mode 100644 mmv1/third_party/terraform/services/clouddeploy/resource_clouddeploy_target_meta.yaml create mode 100644 mmv1/third_party/terraform/services/compute/resource_compute_firewall_policy_meta.yaml.tmpl create mode 100644 mmv1/third_party/terraform/services/containeraws/resource_container_aws_cluster_meta.yaml create mode 100644 mmv1/third_party/terraform/services/containeraws/resource_container_aws_node_pool_meta.yaml create mode 100644 mmv1/third_party/terraform/services/containerazure/resource_container_azure_client_meta.yaml create mode 100644 mmv1/third_party/terraform/services/containerazure/resource_container_azure_cluster_meta.yaml create mode 100644 mmv1/third_party/terraform/services/containerazure/resource_container_azure_node_pool_meta.yaml create mode 100644 mmv1/third_party/terraform/services/dataplex/resource_dataplex_asset_meta.yaml create mode 100644 mmv1/third_party/terraform/services/dataplex/resource_dataplex_lake_meta.yaml create mode 100644 mmv1/third_party/terraform/services/dataplex/resource_dataplex_zone_meta.yaml create mode 100644 mmv1/third_party/terraform/services/dataproc/resource_dataproc_workflow_template_meta.yaml create mode 100644 mmv1/third_party/terraform/services/eventarc/resource_eventarc_channel_meta.yaml create mode 100644 mmv1/third_party/terraform/services/eventarc/resource_eventarc_google_channel_config_meta.yaml create mode 100644 mmv1/third_party/terraform/services/eventarc/resource_eventarc_trigger_meta.yaml create mode 100644 mmv1/third_party/terraform/services/firebaserules/resource_firebaserules_release_meta.yaml create mode 100644 mmv1/third_party/terraform/services/firebaserules/resource_firebaserules_ruleset_meta.yaml create mode 100644 mmv1/third_party/terraform/services/gkehub/resource_gke_hub_feature_membership_meta.yaml.tmpl create mode 100644 mmv1/third_party/terraform/services/recaptcha/resource_recaptcha_enterprise_key_meta.yaml diff --git a/mmv1/provider/template_data.go b/mmv1/provider/template_data.go index a7795c873054..6d1ea21a03a2 100644 --- a/mmv1/provider/template_data.go +++ b/mmv1/provider/template_data.go @@ -212,6 +212,9 @@ func (td *TemplateData) GenerateFile(filePath, templatePath string, input any, g } sourceByte := contents.Bytes() + if len(sourceByte) == 0 { + return + } if goFormat { formattedByte, err := format.Source(sourceByte) diff --git a/mmv1/provider/terraform.go b/mmv1/provider/terraform.go index 14aa6ddfaef9..0820c16caac2 100644 --- a/mmv1/provider/terraform.go +++ b/mmv1/provider/terraform.go @@ -488,6 +488,10 @@ func (t Terraform) CompileFileList(outputFolder string, files map[string]string, formatFile := filepath.Ext(targetFile) == ".go" fileTemplate.GenerateFile(targetFile, source, providerWithProducts, formatFile, templates...) + // continue to next file if no file was generated + if _, err := os.Stat(targetFile); errors.Is(err, os.ErrNotExist) { + continue + } t.replaceImportPath(outputFolder, target) t.addHashicorpCopyRightHeader(outputFolder, target) } @@ -510,7 +514,7 @@ func (t Terraform) addHashicorpCopyRightHeader(outputFolder, target string) { // The test-fixtures folder is not included here as it's copied as a whole, // not file by file ignoredFolders := []string{".release/", ".changelog/", "examples/", "scripts/", "META.d/"} - ignoredFiles := []string{"go.mod", ".goreleaser.yml", ".golangci.yml", "terraform-registry-manifest.json"} + ignoredFiles := []string{"go.mod", ".goreleaser.yml", ".golangci.yml", "terraform-registry-manifest.json", "_meta.yaml"} shouldAddHeader := true for _, folder := range ignoredFolders { // folder will be path leading to file diff --git a/mmv1/third_party/terraform/services/apikeys/resource_apikeys_key_meta.yaml b/mmv1/third_party/terraform/services/apikeys/resource_apikeys_key_meta.yaml new file mode 100644 index 000000000000..1470e1ae3812 --- /dev/null +++ b/mmv1/third_party/terraform/services/apikeys/resource_apikeys_key_meta.yaml @@ -0,0 +1,5 @@ +resource: 'google_apikeys_key' +generation_type: 'dcl' +api_service_name: 'apikeys.googleapis.com' +api_version: 'v2' +api_resource_type_kind: 'Key' diff --git a/mmv1/third_party/terraform/services/assuredworkloads/resource_assured_workloads_workload_meta.yaml.tmpl b/mmv1/third_party/terraform/services/assuredworkloads/resource_assured_workloads_workload_meta.yaml.tmpl new file mode 100644 index 000000000000..03d3b64eecc2 --- /dev/null +++ b/mmv1/third_party/terraform/services/assuredworkloads/resource_assured_workloads_workload_meta.yaml.tmpl @@ -0,0 +1,9 @@ +resource: 'google_assured_workloads_workload' +generation_type: 'dcl' +api_service_name: 'assuredworkloads.googleapis.com' +{{- if ne $.TargetVersionName "ga" }} +api_version: 'v1beta1' +{{- else }} +api_version: 'v1' +{{- end }} +api_resource_type_kind: 'Workload' diff --git a/mmv1/third_party/terraform/services/cloudbuild/resource_cloudbuild_worker_pool_meta.yaml b/mmv1/third_party/terraform/services/cloudbuild/resource_cloudbuild_worker_pool_meta.yaml new file mode 100644 index 000000000000..8229c42375a4 --- /dev/null +++ b/mmv1/third_party/terraform/services/cloudbuild/resource_cloudbuild_worker_pool_meta.yaml @@ -0,0 +1,5 @@ +resource: 'google_cloudbuild_worker_pool' +generation_type: 'dcl' +api_service_name: 'cloudbuild.googleapis.com' +api_version: 'v1' +api_resource_type_kind: 'WorkerPool' diff --git a/mmv1/third_party/terraform/services/clouddeploy/resource_clouddeploy_delivery_pipeline_meta copy.yaml b/mmv1/third_party/terraform/services/clouddeploy/resource_clouddeploy_delivery_pipeline_meta copy.yaml new file mode 100644 index 000000000000..825fbe8df525 --- /dev/null +++ b/mmv1/third_party/terraform/services/clouddeploy/resource_clouddeploy_delivery_pipeline_meta copy.yaml @@ -0,0 +1,5 @@ +resource: 'google_clouddeploy_delivery_pipeline' +generation_type: 'dcl' +api_service_name: 'clouddeploy.googleapis.com' +api_version: 'v1' +api_resource_type_kind: 'DeliveryPipeline' diff --git a/mmv1/third_party/terraform/services/clouddeploy/resource_clouddeploy_target_meta.yaml b/mmv1/third_party/terraform/services/clouddeploy/resource_clouddeploy_target_meta.yaml new file mode 100644 index 000000000000..9283431289bf --- /dev/null +++ b/mmv1/third_party/terraform/services/clouddeploy/resource_clouddeploy_target_meta.yaml @@ -0,0 +1,5 @@ +resource: 'google_clouddeploy_target' +generation_type: 'dcl' +api_service_name: 'clouddeploy.googleapis.com' +api_version: 'v1' +api_resource_type_kind: 'Target' diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_firewall_policy_meta.yaml.tmpl b/mmv1/third_party/terraform/services/compute/resource_compute_firewall_policy_meta.yaml.tmpl new file mode 100644 index 000000000000..e93899f2abda --- /dev/null +++ b/mmv1/third_party/terraform/services/compute/resource_compute_firewall_policy_meta.yaml.tmpl @@ -0,0 +1,9 @@ +resource: 'google_compute_firewall_policy' +generation_type: 'dcl' +api_service_name: 'compute.googleapis.com' +{{- if ne $.TargetVersionName "ga" }} +api_version: 'beta' +{{- else }} +api_version: 'v1' +{{- end }} +api_resource_type_kind: 'FirewallPolicy' diff --git a/mmv1/third_party/terraform/services/containeraws/resource_container_aws_cluster_meta.yaml b/mmv1/third_party/terraform/services/containeraws/resource_container_aws_cluster_meta.yaml new file mode 100644 index 000000000000..136d7b70c07e --- /dev/null +++ b/mmv1/third_party/terraform/services/containeraws/resource_container_aws_cluster_meta.yaml @@ -0,0 +1,5 @@ +resource: 'google_container_aws_cluster' +generation_type: 'dcl' +api_service_name: 'gkemulticloud.googleapis.com' +api_version: 'v1' +api_resource_type_kind: 'AwsCluster' diff --git a/mmv1/third_party/terraform/services/containeraws/resource_container_aws_node_pool_meta.yaml b/mmv1/third_party/terraform/services/containeraws/resource_container_aws_node_pool_meta.yaml new file mode 100644 index 000000000000..d56ecfa56e4b --- /dev/null +++ b/mmv1/third_party/terraform/services/containeraws/resource_container_aws_node_pool_meta.yaml @@ -0,0 +1,5 @@ +resource: 'google_container_aws_node_pool' +generation_type: 'dcl' +api_service_name: 'gkemulticloud.googleapis.com' +api_version: 'v1' +api_resource_type_kind: 'AwsNodePool' diff --git a/mmv1/third_party/terraform/services/containerazure/resource_container_azure_client_meta.yaml b/mmv1/third_party/terraform/services/containerazure/resource_container_azure_client_meta.yaml new file mode 100644 index 000000000000..64767424a28c --- /dev/null +++ b/mmv1/third_party/terraform/services/containerazure/resource_container_azure_client_meta.yaml @@ -0,0 +1,5 @@ +resource: 'google_container_azure_client' +generation_type: 'dcl' +api_service_name: 'gkemulticloud.googleapis.com' +api_version: 'v1' +api_resource_type_kind: 'AzureClient' diff --git a/mmv1/third_party/terraform/services/containerazure/resource_container_azure_cluster_meta.yaml b/mmv1/third_party/terraform/services/containerazure/resource_container_azure_cluster_meta.yaml new file mode 100644 index 000000000000..050efdd73bfb --- /dev/null +++ b/mmv1/third_party/terraform/services/containerazure/resource_container_azure_cluster_meta.yaml @@ -0,0 +1,5 @@ +resource: 'google_container_azure_node_pool' +generation_type: 'dcl' +api_service_name: 'gkemulticloud.googleapis.com' +api_version: 'v1' +api_resource_type_kind: 'AzureNodePool' diff --git a/mmv1/third_party/terraform/services/containerazure/resource_container_azure_node_pool_meta.yaml b/mmv1/third_party/terraform/services/containerazure/resource_container_azure_node_pool_meta.yaml new file mode 100644 index 000000000000..d56ecfa56e4b --- /dev/null +++ b/mmv1/third_party/terraform/services/containerazure/resource_container_azure_node_pool_meta.yaml @@ -0,0 +1,5 @@ +resource: 'google_container_aws_node_pool' +generation_type: 'dcl' +api_service_name: 'gkemulticloud.googleapis.com' +api_version: 'v1' +api_resource_type_kind: 'AwsNodePool' diff --git a/mmv1/third_party/terraform/services/dataplex/resource_dataplex_asset_meta.yaml b/mmv1/third_party/terraform/services/dataplex/resource_dataplex_asset_meta.yaml new file mode 100644 index 000000000000..8a368e8ea655 --- /dev/null +++ b/mmv1/third_party/terraform/services/dataplex/resource_dataplex_asset_meta.yaml @@ -0,0 +1,5 @@ +resource: 'google_dataplex_asset' +generation_type: 'dcl' +api_service_name: 'dataplex.googleapis.com' +api_version: 'v1' +api_resource_type_kind: 'Asset' diff --git a/mmv1/third_party/terraform/services/dataplex/resource_dataplex_lake_meta.yaml b/mmv1/third_party/terraform/services/dataplex/resource_dataplex_lake_meta.yaml new file mode 100644 index 000000000000..30f0bc819765 --- /dev/null +++ b/mmv1/third_party/terraform/services/dataplex/resource_dataplex_lake_meta.yaml @@ -0,0 +1,5 @@ +resource: 'google_dataplex_lake' +generation_type: 'dcl' +api_service_name: 'dataplex.googleapis.com' +api_version: 'v1' +api_resource_type_kind: 'Lake' diff --git a/mmv1/third_party/terraform/services/dataplex/resource_dataplex_zone_meta.yaml b/mmv1/third_party/terraform/services/dataplex/resource_dataplex_zone_meta.yaml new file mode 100644 index 000000000000..10cec64e04a1 --- /dev/null +++ b/mmv1/third_party/terraform/services/dataplex/resource_dataplex_zone_meta.yaml @@ -0,0 +1,5 @@ +resource: 'google_dataplex_zone' +generation_type: 'dcl' +api_service_name: 'dataplex.googleapis.com' +api_version: 'v1' +api_resource_type_kind: 'Zone' diff --git a/mmv1/third_party/terraform/services/dataproc/resource_dataproc_workflow_template_meta.yaml b/mmv1/third_party/terraform/services/dataproc/resource_dataproc_workflow_template_meta.yaml new file mode 100644 index 000000000000..e1524801d445 --- /dev/null +++ b/mmv1/third_party/terraform/services/dataproc/resource_dataproc_workflow_template_meta.yaml @@ -0,0 +1,5 @@ +resource: 'google_dataproc_workflow_template' +generation_type: 'dcl' +api_service_name: 'dataproc.googleapis.com' +api_version: 'v1' +api_resource_type_kind: 'WorkflowTemplate' diff --git a/mmv1/third_party/terraform/services/eventarc/resource_eventarc_channel_meta.yaml b/mmv1/third_party/terraform/services/eventarc/resource_eventarc_channel_meta.yaml new file mode 100644 index 000000000000..5a85e593fca1 --- /dev/null +++ b/mmv1/third_party/terraform/services/eventarc/resource_eventarc_channel_meta.yaml @@ -0,0 +1,5 @@ +resource: 'google_eventarc_channel' +generation_type: 'dcl' +api_service_name: 'eventarc.googleapis.com' +api_version: 'v1' +api_resource_type_kind: 'Channel' diff --git a/mmv1/third_party/terraform/services/eventarc/resource_eventarc_google_channel_config_meta.yaml b/mmv1/third_party/terraform/services/eventarc/resource_eventarc_google_channel_config_meta.yaml new file mode 100644 index 000000000000..f7a2801a2eb2 --- /dev/null +++ b/mmv1/third_party/terraform/services/eventarc/resource_eventarc_google_channel_config_meta.yaml @@ -0,0 +1,5 @@ +resource: 'google_eventarc_google_channel_config' +generation_type: 'dcl' +api_service_name: 'eventarc.googleapis.com' +api_version: 'v1' +api_resource_type_kind: 'GoogleChannelConfig' diff --git a/mmv1/third_party/terraform/services/eventarc/resource_eventarc_trigger_meta.yaml b/mmv1/third_party/terraform/services/eventarc/resource_eventarc_trigger_meta.yaml new file mode 100644 index 000000000000..c32ae3d26500 --- /dev/null +++ b/mmv1/third_party/terraform/services/eventarc/resource_eventarc_trigger_meta.yaml @@ -0,0 +1,5 @@ +resource: 'google_eventarc_trigger' +generation_type: 'dcl' +api_service_name: 'eventarc.googleapis.com' +api_version: 'v1' +api_resource_type_kind: 'Trigger' diff --git a/mmv1/third_party/terraform/services/firebaserules/resource_firebaserules_release_meta.yaml b/mmv1/third_party/terraform/services/firebaserules/resource_firebaserules_release_meta.yaml new file mode 100644 index 000000000000..aa64cff5f49f --- /dev/null +++ b/mmv1/third_party/terraform/services/firebaserules/resource_firebaserules_release_meta.yaml @@ -0,0 +1,5 @@ +resource: 'google_firebaserules_release' +generation_type: 'dcl' +api_service_name: 'firebaserules.googleapis.com' +api_version: 'v1' +api_resource_type_kind: 'Release' diff --git a/mmv1/third_party/terraform/services/firebaserules/resource_firebaserules_ruleset_meta.yaml b/mmv1/third_party/terraform/services/firebaserules/resource_firebaserules_ruleset_meta.yaml new file mode 100644 index 000000000000..d83f53f09153 --- /dev/null +++ b/mmv1/third_party/terraform/services/firebaserules/resource_firebaserules_ruleset_meta.yaml @@ -0,0 +1,5 @@ +resource: 'google_firebaserules_ruleset' +generation_type: 'dcl' +api_service_name: 'firebaserules.googleapis.com' +api_version: 'v1' +api_resource_type_kind: 'Ruleset' diff --git a/mmv1/third_party/terraform/services/gkehub/resource_gke_hub_feature_membership_meta.yaml.tmpl b/mmv1/third_party/terraform/services/gkehub/resource_gke_hub_feature_membership_meta.yaml.tmpl new file mode 100644 index 000000000000..c167160ba2b4 --- /dev/null +++ b/mmv1/third_party/terraform/services/gkehub/resource_gke_hub_feature_membership_meta.yaml.tmpl @@ -0,0 +1,9 @@ +resource: 'google_gke_hub_feature_membership' +generation_type: 'dcl' +api_service_name: 'gkehub.googleapis.com' +{{- if ne $.TargetVersionName "ga" }} +api_version: 'v1beta' +{{- else }} +api_version: 'v1' +{{- end }} +api_resource_type_kind: 'Feature' diff --git a/mmv1/third_party/terraform/services/recaptcha/resource_recaptcha_enterprise_key_meta.yaml b/mmv1/third_party/terraform/services/recaptcha/resource_recaptcha_enterprise_key_meta.yaml new file mode 100644 index 000000000000..d8540f7b4cc3 --- /dev/null +++ b/mmv1/third_party/terraform/services/recaptcha/resource_recaptcha_enterprise_key_meta.yaml @@ -0,0 +1,5 @@ +resource: 'google_recaptcha_enterprise_key' +generation_type: 'dcl' +api_service_name: 'recaptchaenterprise.googleapis.com' +api_version: 'v1' +api_resource_type_kind: 'Key' From 27bc9ea1a807ce259704399ba2287eaa6aa923b6 Mon Sep 17 00:00:00 2001 From: karolgorc Date: Fri, 15 Nov 2024 20:06:21 +0100 Subject: [PATCH 073/105] Support `advanced_machine_features.performance_monitoring_unit` for instance and templates (#12281) --- .../compute/compute_instance_helpers.go.tmpl | 2 + .../compute/resource_compute_instance.go.tmpl | 8 ++ ...resource_compute_instance_template.go.tmpl | 7 ++ ...rce_compute_instance_template_test.go.tmpl | 88 ++++++++++++++++++ .../resource_compute_instance_test.go.tmpl | 83 +++++++++++++++++ ...e_compute_region_instance_template.go.tmpl | 7 ++ ...pute_region_instance_template_test.go.tmpl | 90 +++++++++++++++++++ .../docs/r/compute_instance.html.markdown | 2 + .../r/compute_instance_template.html.markdown | 2 + ...ute_region_instance_template.html.markdown | 2 + 10 files changed, 291 insertions(+) diff --git a/mmv1/third_party/terraform/services/compute/compute_instance_helpers.go.tmpl b/mmv1/third_party/terraform/services/compute/compute_instance_helpers.go.tmpl index ecb1f5cc3c5f..24ab6bedb307 100644 --- a/mmv1/third_party/terraform/services/compute/compute_instance_helpers.go.tmpl +++ b/mmv1/third_party/terraform/services/compute/compute_instance_helpers.go.tmpl @@ -664,6 +664,7 @@ func expandAdvancedMachineFeatures(d tpgresource.TerraformResourceData) *compute ThreadsPerCore: int64(d.Get(prefix + ".threads_per_core").(int)), TurboMode: d.Get(prefix + ".turbo_mode").(string), VisibleCoreCount: int64(d.Get(prefix + ".visible_core_count").(int)), + PerformanceMonitoringUnit: d.Get(prefix + ".performance_monitoring_unit").(string), } } @@ -676,6 +677,7 @@ func flattenAdvancedMachineFeatures(AdvancedMachineFeatures *compute.AdvancedMac "threads_per_core": AdvancedMachineFeatures.ThreadsPerCore, "turbo_mode": AdvancedMachineFeatures.TurboMode, "visible_core_count": AdvancedMachineFeatures.VisibleCoreCount, + "performance_monitoring_unit": AdvancedMachineFeatures.PerformanceMonitoringUnit, {{"}}"}} } diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_instance.go.tmpl b/mmv1/third_party/terraform/services/compute/resource_compute_instance.go.tmpl index cb91f90c911a..245e3415b963 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_instance.go.tmpl +++ b/mmv1/third_party/terraform/services/compute/resource_compute_instance.go.tmpl @@ -59,6 +59,7 @@ var ( "advanced_machine_features.0.threads_per_core", "advanced_machine_features.0.turbo_mode", "advanced_machine_features.0.visible_core_count", + "advanced_machine_features.0.performance_monitoring_unit", } bootDiskKeys = []string{ @@ -1125,6 +1126,13 @@ be from 0 to 999,999,999 inclusive.`, AtLeastOneOf: advancedMachineFeaturesKeys, Description: `The number of physical cores to expose to an instance. Multiply by the number of threads per core to compute the total number of virtual CPUs to expose to the instance. If unset, the number of cores is inferred from the instance\'s nominal CPU count and the underlying platform\'s SMT width.`, }, + "performance_monitoring_unit": { + Type: schema.TypeString, + Optional: true, + AtLeastOneOf: advancedMachineFeaturesKeys, + ValidateFunc: validation.StringInSlice([]string{"STANDARD", "ENHANCED", "ARCHITECTURAL"}, false), + Description: `The PMU is a hardware component within the CPU core that monitors how the processor runs code. Valid values for the level of PMU are "STANDARD", "ENHANCED", and "ARCHITECTURAL".`, + }, }, }, }, diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_instance_template.go.tmpl b/mmv1/third_party/terraform/services/compute/resource_compute_instance_template.go.tmpl index 5b2ab8d95d94..ecff319cf83e 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_instance_template.go.tmpl +++ b/mmv1/third_party/terraform/services/compute/resource_compute_instance_template.go.tmpl @@ -981,6 +981,13 @@ be from 0 to 999,999,999 inclusive.`, ForceNew: true, Description: `The number of physical cores to expose to an instance. Multiply by the number of threads per core to compute the total number of virtual CPUs to expose to the instance. If unset, the number of cores is inferred from the instance\'s nominal CPU count and the underlying platform\'s SMT width.`, }, + "performance_monitoring_unit": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{"STANDARD", "ENHANCED", "ARCHITECTURAL"}, false), + Description: `The PMU is a hardware component within the CPU core that monitors how the processor runs code. Valid values for the level of PMU are "STANDARD", "ENHANCED", and "ARCHITECTURAL".`, + }, }, }, }, diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_instance_template_test.go.tmpl b/mmv1/third_party/terraform/services/compute/resource_compute_instance_template_test.go.tmpl index 9ed49cecd1f0..ab19e4c725b5 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_instance_template_test.go.tmpl +++ b/mmv1/third_party/terraform/services/compute/resource_compute_instance_template_test.go.tmpl @@ -901,6 +901,68 @@ func TestAccComputeInstanceTemplate_AdvancedMachineFeatures(t *testing.T) { }) } +func TestAccComputeInstanceTemplate_performanceMonitoringUnit(t *testing.T) { + t.Parallel() + + var instanceTemplate compute.InstanceTemplate + context_1 := map[string]interface{}{ + "instance_name": fmt.Sprintf("tf-test-instance-template-%s", acctest.RandString(t, 10)), + "performance_monitoring_unit": "STANDARD", + } + context_2 := map[string]interface{}{ + "instance_name": context_1["instance_name"].(string), + "performance_monitoring_unit": "ENHANCED", + } + context_3 := map[string]interface{}{ + "instance_name": context_1["instance_name"].(string), + "performance_monitoring_unit": "ARCHITECTURAL", + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckComputeInstanceTemplateDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccComputeInstanceTemplate_performanceMonitoringUnit(context_1), + Check: resource.ComposeTestCheckFunc( + testAccCheckComputeInstanceTemplateExists(t, "google_compute_instance_template.foobar", &instanceTemplate), + resource.TestCheckResourceAttr("google_compute_instance_template.foobar", "advanced_machine_features.0.performance_monitoring_unit", "STANDARD"), + ), + }, + { + ResourceName: "google_compute_instance_template.foobar", + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccComputeInstanceTemplate_performanceMonitoringUnit(context_2), + Check: resource.ComposeTestCheckFunc( + testAccCheckComputeInstanceTemplateExists(t, "google_compute_instance_template.foobar", &instanceTemplate), + resource.TestCheckResourceAttr("google_compute_instance_template.foobar", "advanced_machine_features.0.performance_monitoring_unit", "ENHANCED"), + ), + }, + { + ResourceName: "google_compute_instance_template.foobar", + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccComputeInstanceTemplate_performanceMonitoringUnit(context_3), + Check: resource.ComposeTestCheckFunc( + testAccCheckComputeInstanceTemplateExists(t, "google_compute_instance_template.foobar", &instanceTemplate), + resource.TestCheckResourceAttr("google_compute_instance_template.foobar", "advanced_machine_features.0.performance_monitoring_unit", "ARCHITECTURAL"), + ), + }, + { + ResourceName: "google_compute_instance_template.foobar", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + {{ if ne $.TargetVersionName `ga` -}} func TestAccComputeInstanceTemplate_enableDisplay(t *testing.T) { t.Parallel() @@ -3784,6 +3846,32 @@ resource "google_compute_instance_template" "foobar" { `, suffix) } +func testAccComputeInstanceTemplate_performanceMonitoringUnit(context map[string]interface{}) string { + return acctest.Nprintf(` +data "google_compute_image" "my_image" { + family = "ubuntu-2004-lts" + project = "ubuntu-os-cloud" +} + +resource "google_compute_instance_template" "foobar" { + name = "%{instance_name}" + machine_type = "c4-standard-96" + + disk { + source_image = data.google_compute_image.my_image.self_link + } + + network_interface { + network = "default" + } + + advanced_machine_features { + performance_monitoring_unit = "%{performance_monitoring_unit}" + } +} +`, context) +} + {{ if ne $.TargetVersionName `ga` -}} func testAccComputeInstanceTemplate_enableDisplay(suffix string) string { return fmt.Sprintf(` diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_instance_test.go.tmpl b/mmv1/third_party/terraform/services/compute/resource_compute_instance_test.go.tmpl index e9dda4bc81b8..66ff780220b1 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_instance_test.go.tmpl +++ b/mmv1/third_party/terraform/services/compute/resource_compute_instance_test.go.tmpl @@ -1468,6 +1468,58 @@ func TestAccComputeInstance_advancedMachineFeatures(t *testing.T) { }) } +func TestAccComputeInstance_performanceMonitoringUnit(t *testing.T) { + t.Parallel() + + var instance compute.Instance + context_1 := map[string]interface{}{ + "instance_name": fmt.Sprintf("tf-test-%s", acctest.RandString(t, 10)), + "performance_monitoring_unit": "STANDARD", + } + context_2 := map[string]interface{}{ + "instance_name": context_1["instance_name"].(string), + "performance_monitoring_unit": "ENHANCED", + } + context_3 := map[string]interface{}{ + "instance_name": context_1["instance_name"].(string), + "performance_monitoring_unit": "ARCHITECTURAL", + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckComputeInstanceDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccComputeInstance_performanceMonitoringUnit(context_1), + Check: resource.ComposeTestCheckFunc( + testAccCheckComputeInstanceExists( + t, "google_compute_instance.foobar", &instance), + resource.TestCheckResourceAttr("google_compute_instance.foobar", "advanced_machine_features.0.performance_monitoring_unit", "STANDARD"), + ), + }, + computeInstanceImportStep("us-central1-a", context_1["instance_name"].(string), []string{"allow_stopping_for_update"}), + { + Config: testAccComputeInstance_performanceMonitoringUnit(context_2), + Check: resource.ComposeTestCheckFunc( + testAccCheckComputeInstanceExists( + t, "google_compute_instance.foobar", &instance), + resource.TestCheckResourceAttr("google_compute_instance.foobar", "advanced_machine_features.0.performance_monitoring_unit", "ENHANCED"), + ), + }, + computeInstanceImportStep("us-central1-a", context_2["instance_name"].(string), []string{"allow_stopping_for_update"}), + { + Config: testAccComputeInstance_performanceMonitoringUnit(context_3), + Check: resource.ComposeTestCheckFunc( + testAccCheckComputeInstanceExists( + t, "google_compute_instance.foobar", &instance), + resource.TestCheckResourceAttr("google_compute_instance.foobar", "advanced_machine_features.0.performance_monitoring_unit", "ARCHITECTURAL"), + ), + }, + }, + }) +} + func TestAccComputeInstance_soleTenantNodeAffinities(t *testing.T) { t.Parallel() @@ -7177,6 +7229,37 @@ resource "google_compute_instance" "foobar" { `, instance) } +func testAccComputeInstance_performanceMonitoringUnit(context map[string]interface{}) string { + return acctest.Nprintf(` +data "google_compute_image" "my_image" { + family = "debian-12" + project = "debian-cloud" +} + +resource "google_compute_instance" "foobar" { + name = "%{instance_name}" + machine_type = "c4-standard-96" + zone = "us-central1-a" + + boot_disk { + initialize_params { + image = data.google_compute_image.my_image.self_link + } + } + + network_interface { + network = "default" + } + + advanced_machine_features { + performance_monitoring_unit = "%{performance_monitoring_unit}" + } + + allow_stopping_for_update = true +} +`, context) +} + func testAccComputeInstance_advancedMachineFeaturesUpdated(instance string) string { return fmt.Sprintf(` data "google_compute_image" "my_image" { diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_template.go.tmpl b/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_template.go.tmpl index b9b46772dd08..992ab0fb7b28 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_template.go.tmpl +++ b/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_template.go.tmpl @@ -933,6 +933,13 @@ be from 0 to 999,999,999 inclusive.`, ForceNew: true, Description: `The number of physical cores to expose to an instance. Multiply by the number of threads per core to compute the total number of virtual CPUs to expose to the instance. If unset, the number of cores is inferred from the instance\'s nominal CPU count and the underlying platform\'s SMT width.`, }, + "performance_monitoring_unit": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{"STANDARD", "ENHANCED", "ARCHITECTURAL"}, false), + Description: `The PMU is a hardware component within the CPU core that monitors how the processor runs code. Valid values for the level of PMU are "STANDARD", "ENHANCED", and "ARCHITECTURAL".`, + }, }, }, }, diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_template_test.go.tmpl b/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_template_test.go.tmpl index 0d6ce93175b3..ff9454170bab 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_template_test.go.tmpl +++ b/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_template_test.go.tmpl @@ -773,6 +773,69 @@ func TestAccComputeRegionInstanceTemplate_AdvancedMachineFeatures(t *testing.T) }) } +func TestAccComputeRegionInstanceTemplate_performanceMonitoringUnit(t *testing.T) { + t.Parallel() + + var instanceTemplate compute.InstanceTemplate + context_1 := map[string]interface{}{ + "instance_name": fmt.Sprintf("tf-test-instance-template-%s", acctest.RandString(t, 10)), + "performance_monitoring_unit": "STANDARD", + } + context_2 := map[string]interface{}{ + "instance_name": context_1["instance_name"].(string), + "performance_monitoring_unit": "ENHANCED", + } + context_3 := map[string]interface{}{ + "instance_name": context_1["instance_name"].(string), + "performance_monitoring_unit": "ARCHITECTURAL", + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckComputeInstanceTemplateDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccComputeRegionInstanceTemplate_performanceMonitoringUnit(context_1), + Check: resource.ComposeTestCheckFunc( + testAccCheckComputeRegionInstanceTemplateExists(t, "google_compute_region_instance_template.foobar", &instanceTemplate), + resource.TestCheckResourceAttr("google_compute_region_instance_template.foobar", "advanced_machine_features.0.performance_monitoring_unit", "STANDARD"), + ), + }, + { + ResourceName: "google_compute_region_instance_template.foobar", + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccComputeRegionInstanceTemplate_performanceMonitoringUnit(context_2), + Check: resource.ComposeTestCheckFunc( + testAccCheckComputeRegionInstanceTemplateExists(t, "google_compute_region_instance_template.foobar", &instanceTemplate), + resource.TestCheckResourceAttr("google_compute_region_instance_template.foobar", "advanced_machine_features.0.performance_monitoring_unit", "ENHANCED"), + ), + }, + { + ResourceName: "google_compute_region_instance_template.foobar", + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccComputeRegionInstanceTemplate_performanceMonitoringUnit(context_3), + Check: resource.ComposeTestCheckFunc( + testAccCheckComputeRegionInstanceTemplateExists(t, "google_compute_region_instance_template.foobar", &instanceTemplate), + resource.TestCheckResourceAttr("google_compute_region_instance_template.foobar", "advanced_machine_features.0.performance_monitoring_unit", "ARCHITECTURAL"), + ), + }, + { + ResourceName: "google_compute_region_instance_template.foobar", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + + {{ if ne $.TargetVersionName `ga` -}} func TestAccComputeRegionInstanceTemplate_enableDisplay(t *testing.T) { t.Parallel() @@ -3170,6 +3233,33 @@ resource "google_compute_region_instance_template" "foobar" { `, suffix) } +func testAccComputeRegionInstanceTemplate_performanceMonitoringUnit(context map[string]interface{}) string { + return acctest.Nprintf(` +data "google_compute_image" "my_image" { + family = "ubuntu-2004-lts" + project = "ubuntu-os-cloud" +} + +resource "google_compute_region_instance_template" "foobar" { + name = "%{instance_name}" + region = "us-central1" + machine_type = "c4-standard-96" + + disk { + source_image = data.google_compute_image.my_image.self_link + } + + network_interface { + network = "default" + } + + advanced_machine_features { + performance_monitoring_unit = "%{performance_monitoring_unit}" + } +} +`, context) +} + {{ if ne $.TargetVersionName `ga` -}} func testAccComputeRegionInstanceTemplate_enableDisplay(suffix string) string { return fmt.Sprintf(` diff --git a/mmv1/third_party/terraform/website/docs/r/compute_instance.html.markdown b/mmv1/third_party/terraform/website/docs/r/compute_instance.html.markdown index ed5f5e4a3f60..3c7fdb118027 100644 --- a/mmv1/third_party/terraform/website/docs/r/compute_instance.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/compute_instance.html.markdown @@ -573,6 +573,8 @@ specified, then this instance will have no external IPv6 Internet access. Struct * `visible_core_count` - (Optional) The number of physical cores to expose to an instance. [visible cores info (VC)](https://cloud.google.com/compute/docs/instances/customize-visible-cores). +* `performance_monitoring_unit` - (Optional) [The PMU](https://cloud.google.com/compute/docs/pmu-overview) is a hardware component within the CPU core that monitors how the processor runs code. Valid values for the level of PMU are `STANDARD`, `ENHANCED`, and `ARCHITECTURAL`. + The `reservation_affinity` block supports: * `type` - (Required) The type of reservation from which this instance can consume resources. diff --git a/mmv1/third_party/terraform/website/docs/r/compute_instance_template.html.markdown b/mmv1/third_party/terraform/website/docs/r/compute_instance_template.html.markdown index 4e28fc3d1be5..3b009c3e0db0 100644 --- a/mmv1/third_party/terraform/website/docs/r/compute_instance_template.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/compute_instance_template.html.markdown @@ -730,6 +730,8 @@ The `specific_reservation` block supports: * `visible_core_count` - (Optional) The number of physical cores to expose to an instance. [visible cores info (VC)](https://cloud.google.com/compute/docs/instances/customize-visible-cores). +* `performance_monitoring_unit` - (Optional) [The PMU](https://cloud.google.com/compute/docs/pmu-overview) is a hardware component within the CPU core that monitors how the processor runs code. Valid values for the level of PMU are `STANDARD`, `ENHANCED`, and `ARCHITECTURAL`. + ## Attributes Reference In addition to the arguments listed above, the following computed attributes are diff --git a/mmv1/third_party/terraform/website/docs/r/compute_region_instance_template.html.markdown b/mmv1/third_party/terraform/website/docs/r/compute_region_instance_template.html.markdown index 27bacc5e4bbb..83b6a421bb07 100644 --- a/mmv1/third_party/terraform/website/docs/r/compute_region_instance_template.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/compute_region_instance_template.html.markdown @@ -690,6 +690,8 @@ The `specific_reservation` block supports: * `visible_core_count` - (Optional) The number of physical cores to expose to an instance. [visible cores info (VC)](https://cloud.google.com/compute/docs/instances/customize-visible-cores). +* `performance_monitoring_unit` - (Optional) [The PMU](https://cloud.google.com/compute/docs/pmu-overview) is a hardware component within the CPU core that monitors how the processor runs code. Valid values for the level of PMU are `STANDARD`, `ENHANCED`, and `ARCHITECTURAL`. + ## Attributes Reference In addition to the arguments listed above, the following computed attributes are From e2d14e34fb3b7c98efadf7b2925eb2ac2218fe73 Mon Sep 17 00:00:00 2001 From: shaikatzz <139782053+shaikatzz@users.noreply.github.com> Date: Fri, 15 Nov 2024 23:39:41 +0200 Subject: [PATCH 074/105] Add creationTime to cloud identity group membership datasource (#12199) Co-authored-by: Chris Hawk --- .../data_source_cloud_identity_group_memberships.go.tmpl | 1 + 1 file changed, 1 insertion(+) diff --git a/mmv1/third_party/terraform/services/cloudidentity/data_source_cloud_identity_group_memberships.go.tmpl b/mmv1/third_party/terraform/services/cloudidentity/data_source_cloud_identity_group_memberships.go.tmpl index 39dd1fcf61b0..cf6f19d75819 100644 --- a/mmv1/third_party/terraform/services/cloudidentity/data_source_cloud_identity_group_memberships.go.tmpl +++ b/mmv1/third_party/terraform/services/cloudidentity/data_source_cloud_identity_group_memberships.go.tmpl @@ -78,6 +78,7 @@ func dataSourceGoogleCloudIdentityGroupMembershipsRead(d *schema.ResourceData, m "member_key": flattenCloudIdentityGroupsEntityKey(member.MemberKey), {{- end }} "preferred_member_key": flattenCloudIdentityGroupsEntityKey(member.PreferredMemberKey), + "create_time": member.CreateTime, }) } From ca99fc31c71400d6dd719e2212a8fc769952de8a Mon Sep 17 00:00:00 2001 From: Ryan Oaks Date: Fri, 15 Nov 2024 16:55:43 -0500 Subject: [PATCH 075/105] Modify recaptcha metadata to be beta-only (#12342) --- ...ta.yaml => resource_recaptcha_enterprise_key_meta.yaml.tmpl} | 2 ++ 1 file changed, 2 insertions(+) rename mmv1/third_party/terraform/services/recaptcha/{resource_recaptcha_enterprise_key_meta.yaml => resource_recaptcha_enterprise_key_meta.yaml.tmpl} (78%) diff --git a/mmv1/third_party/terraform/services/recaptcha/resource_recaptcha_enterprise_key_meta.yaml b/mmv1/third_party/terraform/services/recaptcha/resource_recaptcha_enterprise_key_meta.yaml.tmpl similarity index 78% rename from mmv1/third_party/terraform/services/recaptcha/resource_recaptcha_enterprise_key_meta.yaml rename to mmv1/third_party/terraform/services/recaptcha/resource_recaptcha_enterprise_key_meta.yaml.tmpl index d8540f7b4cc3..22f7e5e37b1a 100644 --- a/mmv1/third_party/terraform/services/recaptcha/resource_recaptcha_enterprise_key_meta.yaml +++ b/mmv1/third_party/terraform/services/recaptcha/resource_recaptcha_enterprise_key_meta.yaml.tmpl @@ -1,5 +1,7 @@ +{{ if ne $.TargetVersionName "ga" -}} resource: 'google_recaptcha_enterprise_key' generation_type: 'dcl' api_service_name: 'recaptchaenterprise.googleapis.com' api_version: 'v1' api_resource_type_kind: 'Key' +{{ end }} \ No newline at end of file From e7cf93b18ad0eca820b889cd4dae4b88cb5a9ddc Mon Sep 17 00:00:00 2001 From: Yuriy Gridasov Date: Fri, 15 Nov 2024 15:02:52 -0800 Subject: [PATCH 076/105] artifactregistry: fix comments, more examples for common remote repositories (#12312) Co-authored-by: Yury Gridasov Co-authored-by: Will Yardley Co-authored-by: Ian Milligan Co-authored-by: Stephen Lewis (Burrows) --- .../products/artifactregistry/Repository.yaml | 37 ++++++++++++++--- ...ository_with_artifact_registry_uri.tf.tmpl | 22 ++++++++++ ...on_repository_with_custom_upstream.tf.tmpl | 40 +++++++++++++++++++ 3 files changed, 94 insertions(+), 5 deletions(-) create mode 100644 mmv1/templates/terraform/examples/artifact_registry_repository_remote_common_repository_with_artifact_registry_uri.tf.tmpl create mode 100644 mmv1/templates/terraform/examples/artifact_registry_repository_remote_common_repository_with_custom_upstream.tf.tmpl diff --git a/mmv1/products/artifactregistry/Repository.yaml b/mmv1/products/artifactregistry/Repository.yaml index 747d4c8f78bc..9c1b513f0892 100644 --- a/mmv1/products/artifactregistry/Repository.yaml +++ b/mmv1/products/artifactregistry/Repository.yaml @@ -184,6 +184,30 @@ examples: # Ignore this field as it is INPUT_ONLY. AR will not return this in the # response. - 'remote_repository_config.0.disable_upstream_validation' + - name: 'artifact_registry_repository_remote_common_repository_with_artifact_registry_uri' + primary_resource_id: 'my-repo' + vars: + repository_id: 'example-common-remote' + desc: 'example remote common repository with docker upstream' + upstream_repository_id: 'example-upstream-repo' + upstream_repository_desc: 'example upstream repository' + ignore_read_extra: + # Ignore this field as it is INPUT_ONLY. AR will not return this in the + # response. + - 'remote_repository_config.0.disable_upstream_validation' + - name: 'artifact_registry_repository_remote_common_repository_with_custom_upstream' + primary_resource_id: 'my-repo' + vars: + repository_id: 'example-docker-custom-remote' + desc: 'example remote custom docker repository with credentials' + secret_id: 'example-secret' + secret_resource_id: 'example-remote-secret' + username: 'remote-username' + secret_data: 'remote-password' + ignore_read_extra: + # Ignore this field as it is INPUT_ONLY. AR will not return this in the + # response. + - 'remote_repository_config.0.disable_upstream_validation' parameters: properties: - name: 'name' @@ -482,7 +506,7 @@ properties: - name: 'customRepository' type: NestedObject description: |- - Settings for a remote repository with a custom uri. + [Deprecated, please use commonRepository instead] Settings for a remote repository with a custom uri. immutable: true conflicts: - remoteRepositoryConfig.0.docker_repository.0.public_repository @@ -521,7 +545,7 @@ properties: - name: 'customRepository' type: NestedObject description: |- - Settings for a remote repository with a custom uri. + [Deprecated, please use commonRepository instead] Settings for a remote repository with a custom uri. immutable: true conflicts: - remoteRepositoryConfig.0.maven_repository.0.public_repository @@ -560,7 +584,7 @@ properties: - name: 'customRepository' type: NestedObject description: |- - Settings for a remote repository with a custom uri. + [Deprecated, please use commonRepository instead] Settings for a remote repository with a custom uri. immutable: true conflicts: - remoteRepositoryConfig.0.npm_repository.0.public_repository @@ -599,7 +623,7 @@ properties: - name: 'customRepository' type: NestedObject description: |- - Settings for a remote repository with a custom uri. + [Deprecated, please use commonRepository instead] Settings for a remote repository with a custom uri. immutable: true conflicts: - remoteRepositoryConfig.0.python_repository.0.public_repository @@ -665,7 +689,10 @@ properties: - name: 'uri' type: String description: |- - Specific uri to the Artifact Registory repository, e.g. `projects/UPSTREAM_PROJECT_ID/locations/REGION/repositories/UPSTREAM_REPOSITORY` + One of: + a. Artifact Registry Repository resource, e.g. `projects/UPSTREAM_PROJECT_ID/locations/REGION/repositories/UPSTREAM_REPOSITORY` + b. URI to the registry, e.g. `"https://registry-1.docker.io"` + c. URI to Artifact Registry Repository, e.g. `"https://REGION-docker.pkg.dev/UPSTREAM_PROJECT_ID/UPSTREAM_REPOSITORY"` immutable: true required: true - name: 'upstreamCredentials' diff --git a/mmv1/templates/terraform/examples/artifact_registry_repository_remote_common_repository_with_artifact_registry_uri.tf.tmpl b/mmv1/templates/terraform/examples/artifact_registry_repository_remote_common_repository_with_artifact_registry_uri.tf.tmpl new file mode 100644 index 000000000000..25b574437859 --- /dev/null +++ b/mmv1/templates/terraform/examples/artifact_registry_repository_remote_common_repository_with_artifact_registry_uri.tf.tmpl @@ -0,0 +1,22 @@ +data "google_project" "project" {} + +resource "google_artifact_registry_repository" "upstream_repo" { + location = "us-central1" + repository_id = "{{index $.Vars "upstream_repository_id"}}" + description = "{{index $.Vars "upstream_repository_desc"}}" + format = "DOCKER" +} + +resource "google_artifact_registry_repository" "{{$.PrimaryResourceId}}" { + location = "us-central1" + repository_id = "{{index $.Vars "repository_id"}}" + description = "{{index $.Vars "desc"}}" + format = "DOCKER" + mode = "REMOTE_REPOSITORY" + remote_repository_config { + description = "pull-through cache of another Artifact Registry repository by URL" + common_repository { + uri = "https://us-central1-docker.pkg.dev/{{index $.TestEnvVars "project_id"}}/{{index $.Vars "upstream_repository_id"}}" + } + } +} diff --git a/mmv1/templates/terraform/examples/artifact_registry_repository_remote_common_repository_with_custom_upstream.tf.tmpl b/mmv1/templates/terraform/examples/artifact_registry_repository_remote_common_repository_with_custom_upstream.tf.tmpl new file mode 100644 index 000000000000..577160e80128 --- /dev/null +++ b/mmv1/templates/terraform/examples/artifact_registry_repository_remote_common_repository_with_custom_upstream.tf.tmpl @@ -0,0 +1,40 @@ +data "google_project" "project" {} + +resource "google_secret_manager_secret" "{{index $.Vars "secret_resource_id"}}" { + secret_id = "{{index $.Vars "secret_id"}}" + replication { + auto {} + } +} + +resource "google_secret_manager_secret_version" "{{index $.Vars "secret_resource_id"}}_version" { + secret = google_secret_manager_secret.{{index $.Vars "secret_resource_id"}}.id + secret_data = "{{index $.Vars "secret_data"}}" +} + +resource "google_secret_manager_secret_iam_member" "secret-access" { + secret_id = google_secret_manager_secret.{{index $.Vars "secret_resource_id"}}.id + role = "roles/secretmanager.secretAccessor" + member = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-artifactregistry.iam.gserviceaccount.com" +} + +resource "google_artifact_registry_repository" "{{$.PrimaryResourceId}}" { + location = "us-central1" + repository_id = "{{index $.Vars "repository_id"}}" + description = "{{index $.Vars "desc"}}" + format = "DOCKER" + mode = "REMOTE_REPOSITORY" + remote_repository_config { + description = "custom common docker remote with credentials" + disable_upstream_validation = true + common_repository { + uri = "https://registry-1.docker.io" + } + upstream_credentials { + username_password_credentials { + username = "{{index $.Vars "username"}}" + password_secret_version = google_secret_manager_secret_version.{{index $.Vars "secret_resource_id"}}_version.name + } + } + } +} From c09b3029dfcb6b8233e39ec11177a37801e45424 Mon Sep 17 00:00:00 2001 From: gurusai-voleti Date: Fri, 15 Nov 2024 23:37:29 +0000 Subject: [PATCH 077/105] fix: derive the project attribute from resource or compute api or fallback to provider (#12305) Co-authored-by: Chris Hawk --- .../storage/resource_storage_bucket.go.tmpl | 16 +++++++--------- .../website/docs/d/storage_bucket.html.markdown | 2 +- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/mmv1/third_party/terraform/services/storage/resource_storage_bucket.go.tmpl b/mmv1/third_party/terraform/services/storage/resource_storage_bucket.go.tmpl index b01e9c162bba..a79d34fe790a 100644 --- a/mmv1/third_party/terraform/services/storage/resource_storage_bucket.go.tmpl +++ b/mmv1/third_party/terraform/services/storage/resource_storage_bucket.go.tmpl @@ -1845,18 +1845,16 @@ func setStorageBucket(d *schema.ResourceData, config *transport_tpg.Config, res // block, or the resource or an environment variable, we use the compute API to lookup the projectID // from the projectNumber which is included in the bucket API response if d.Get("project") == "" { - project, _ := tpgresource.GetProject(d, config) - if err := d.Set("project", project); err != nil { - return fmt.Errorf("Error setting project: %s", err) - } - } - if d.Get("project") == "" { + projectName, _ := tpgresource.GetProject(d, config) proj, err := config.NewComputeClient(userAgent).Projects.Get(strconv.FormatUint(res.ProjectNumber, 10)).Do() if err != nil { - return err + log.Printf("[ERROR] Missing Compute API permissions, fallback to provider/resource default") + } + + if proj != nil && projectName != "" && projectName != proj.Name { + projectName = proj.Name } - log.Printf("[DEBUG] Bucket %v is in project number %v, which is project ID %s.\n", res.Name, res.ProjectNumber, proj.Name) - if err := d.Set("project", proj.Name); err != nil { + if err := d.Set("project", projectName); err != nil { return fmt.Errorf("Error setting project: %s", err) } } diff --git a/mmv1/third_party/terraform/website/docs/d/storage_bucket.html.markdown b/mmv1/third_party/terraform/website/docs/d/storage_bucket.html.markdown index 0745d8c02b3d..e32ff99cb750 100644 --- a/mmv1/third_party/terraform/website/docs/d/storage_bucket.html.markdown +++ b/mmv1/third_party/terraform/website/docs/d/storage_bucket.html.markdown @@ -26,7 +26,7 @@ The following arguments are supported: * `name` - (Required) The name of the bucket. -* `project` - (Optional) The ID of the project in which the resource belongs. If it is not provided, the provider project is used. If no value is supplied in the configuration or through provider defaults then the data source will use the Compute API to find the project id that corresponds to the project number returned from the Storage API. Supplying a value for `project` doesn't influence retrieving data about the bucket but it can be used to prevent use of the Compute API. If you do provide a `project` value ensure that it is the correct value for that bucket; the data source will not check that the project id and project number match. +* `project` - (Optional) The ID of the project in which the resource belongs. If it is not provided then the data source will use the Compute API to find the project id that corresponds to the project number returned from the Storage API, and if no Compute API permissions are available or if the Compute API is disabled it defaults to the provider value. Supplying a value for `project` doesn't influence retrieving data about the bucket but it can be used to prevent use of the Compute API. If you do provide a `project` value ensure that it is the correct value for that bucket; the data source will not check that the project id and project number match. ## Attributes Reference From 256cde2a74c8f3d2ae4ff2406e282e08ab3e887f Mon Sep 17 00:00:00 2001 From: halimsam Date: Fri, 15 Nov 2024 16:26:06 -0800 Subject: [PATCH 078/105] Update google.golang.org/api to v0.206.0 (#12343) --- mmv1/third_party/terraform/go.mod | 34 +++++++------- mmv1/third_party/terraform/go.sum | 74 +++++++++++++++---------------- 2 files changed, 54 insertions(+), 54 deletions(-) diff --git a/mmv1/third_party/terraform/go.mod b/mmv1/third_party/terraform/go.mod index adb1cfa63246..22a553717d8b 100644 --- a/mmv1/third_party/terraform/go.mod +++ b/mmv1/third_party/terraform/go.mod @@ -30,10 +30,10 @@ require ( github.com/stretchr/testify v1.9.0 go4.org/netipx v0.0.0-20231129151722-fdeea329fbba golang.org/x/exp v0.0.0-20240409090435-93d18d7e34b8 - golang.org/x/net v0.30.0 - golang.org/x/oauth2 v0.23.0 - google.golang.org/api v0.203.0 - google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 + golang.org/x/net v0.31.0 + golang.org/x/oauth2 v0.24.0 + google.golang.org/api v0.206.0 + google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 google.golang.org/grpc v1.67.1 google.golang.org/protobuf v1.35.1 ) @@ -42,12 +42,12 @@ require ( bitbucket.org/creachadair/stringset v0.0.8 // indirect cel.dev/expr v0.16.0 // indirect cloud.google.com/go v0.116.0 // indirect - cloud.google.com/go/auth v0.9.9 // indirect - cloud.google.com/go/auth/oauth2adapt v0.2.4 // indirect + cloud.google.com/go/auth v0.10.2 // indirect + cloud.google.com/go/auth/oauth2adapt v0.2.5 // indirect cloud.google.com/go/compute/metadata v0.5.2 // indirect - cloud.google.com/go/iam v1.2.1 // indirect - cloud.google.com/go/longrunning v0.6.1 // indirect - cloud.google.com/go/monitoring v1.21.1 // indirect + cloud.google.com/go/iam v1.2.2 // indirect + cloud.google.com/go/longrunning v0.6.2 // indirect + cloud.google.com/go/monitoring v1.21.2 // indirect github.com/ProtonMail/go-crypto v1.1.0-alpha.2 // indirect github.com/agext/levenshtein v1.2.2 // indirect github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect @@ -70,7 +70,7 @@ require ( github.com/google/s2a-go v0.1.8 // indirect github.com/google/uuid v1.6.0 // indirect github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect - github.com/googleapis/gax-go/v2 v2.13.0 // indirect + github.com/googleapis/gax-go/v2 v2.14.0 // indirect github.com/hashicorp/go-checkpoint v0.5.0 // indirect github.com/hashicorp/go-hclog v1.6.3 // indirect github.com/hashicorp/go-plugin v1.6.0 // indirect @@ -106,16 +106,16 @@ require ( go.opentelemetry.io/otel/sdk v1.29.0 // indirect go.opentelemetry.io/otel/sdk/metric v1.29.0 // indirect go.opentelemetry.io/otel/trace v1.29.0 // indirect - golang.org/x/crypto v0.28.0 // indirect + golang.org/x/crypto v0.29.0 // indirect golang.org/x/mod v0.17.0 // indirect - golang.org/x/sync v0.8.0 // indirect - golang.org/x/sys v0.26.0 // indirect - golang.org/x/text v0.19.0 // indirect - golang.org/x/time v0.7.0 // indirect + golang.org/x/sync v0.9.0 // indirect + golang.org/x/sys v0.27.0 // indirect + golang.org/x/text v0.20.0 // indirect + golang.org/x/time v0.8.0 // indirect golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect google.golang.org/appengine v1.6.8 // indirect - google.golang.org/genproto v0.0.0-20241015192408-796eee8c2d53 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20241007155032-5fefd90f89a9 // indirect + google.golang.org/genproto v0.0.0-20241104194629-dd2ea8efbc28 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/mmv1/third_party/terraform/go.sum b/mmv1/third_party/terraform/go.sum index 867ac9da20e4..fcc915d85ff6 100644 --- a/mmv1/third_party/terraform/go.sum +++ b/mmv1/third_party/terraform/go.sum @@ -5,20 +5,20 @@ cel.dev/expr v0.16.0/go.mod h1:TRSuuV7DlVCE/uwv5QbAiW/v8l5O8C4eEPHeu7gf7Sg= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.116.0 h1:B3fRrSDkLRt5qSHWe40ERJvhvnQwdZiHu0bJOpldweE= cloud.google.com/go v0.116.0/go.mod h1:cEPSRWPzZEswwdr9BxE6ChEn01dWlTaF05LiC2Xs70U= -cloud.google.com/go/auth v0.9.9 h1:BmtbpNQozo8ZwW2t7QJjnrQtdganSdmqeIBxHxNkEZQ= -cloud.google.com/go/auth v0.9.9/go.mod h1:xxA5AqpDrvS+Gkmo9RqrGGRh6WSNKKOXhY3zNOr38tI= -cloud.google.com/go/auth/oauth2adapt v0.2.4 h1:0GWE/FUsXhf6C+jAkWgYm7X9tK8cuEIfy19DBn6B6bY= -cloud.google.com/go/auth/oauth2adapt v0.2.4/go.mod h1:jC/jOpwFP6JBxhB3P5Rr0a9HLMC/Pe3eaL4NmdvqPtc= +cloud.google.com/go/auth v0.10.2 h1:oKF7rgBfSHdp/kuhXtqU/tNDr0mZqhYbEh+6SiqzkKo= +cloud.google.com/go/auth v0.10.2/go.mod h1:xxA5AqpDrvS+Gkmo9RqrGGRh6WSNKKOXhY3zNOr38tI= +cloud.google.com/go/auth/oauth2adapt v0.2.5 h1:2p29+dePqsCHPP1bqDJcKj4qxRyYCcbzKpFyKGt3MTk= +cloud.google.com/go/auth/oauth2adapt v0.2.5/go.mod h1:AlmsELtlEBnaNTL7jCj8VQFLy6mbZv0s4Q7NGBeQ5E8= cloud.google.com/go/bigtable v1.33.0 h1:2BDaWLRAwXO14DJL/u8crbV2oUbMZkIa2eGq8Yao1bk= cloud.google.com/go/bigtable v1.33.0/go.mod h1:HtpnH4g25VT1pejHRtInlFPnN5sjTxbQlsYBjh9t5l0= cloud.google.com/go/compute/metadata v0.5.2 h1:UxK4uu/Tn+I3p2dYWTfiX4wva7aYlKixAHn3fyqngqo= cloud.google.com/go/compute/metadata v0.5.2/go.mod h1:C66sj2AluDcIqakBq/M8lw8/ybHgOZqin2obFxa/E5k= -cloud.google.com/go/iam v1.2.1 h1:QFct02HRb7H12J/3utj0qf5tobFh9V4vR6h9eX5EBRU= -cloud.google.com/go/iam v1.2.1/go.mod h1:3VUIJDPpwT6p/amXRC5GY8fCCh70lxPygguVtI0Z4/g= -cloud.google.com/go/longrunning v0.6.1 h1:lOLTFxYpr8hcRtcwWir5ITh1PAKUD/sG2lKrTSYjyMc= -cloud.google.com/go/longrunning v0.6.1/go.mod h1:nHISoOZpBcmlwbJmiVk5oDRz0qG/ZxPynEGs1iZ79s0= -cloud.google.com/go/monitoring v1.21.1 h1:zWtbIoBMnU5LP9A/fz8LmWMGHpk4skdfeiaa66QdFGc= -cloud.google.com/go/monitoring v1.21.1/go.mod h1:Rj++LKrlht9uBi8+Eb530dIrzG/cU/lB8mt+lbeFK1c= +cloud.google.com/go/iam v1.2.2 h1:ozUSofHUGf/F4tCNy/mu9tHLTaxZFLOUiKzjcgWHGIA= +cloud.google.com/go/iam v1.2.2/go.mod h1:0Ys8ccaZHdI1dEUilwzqng/6ps2YB6vRsjIe00/+6JY= +cloud.google.com/go/longrunning v0.6.2 h1:xjDfh1pQcWPEvnfjZmwjKQEcHnpz6lHjfy7Fo0MK+hc= +cloud.google.com/go/longrunning v0.6.2/go.mod h1:k/vIs83RN4bE3YCswdXC5PFfWVILjm3hpEUlSko4PiI= +cloud.google.com/go/monitoring v1.21.2 h1:FChwVtClH19E7pJ+e0xUhJPGksctZNVOk2UhMmblmdU= +cloud.google.com/go/monitoring v1.21.2/go.mod h1:hS3pXvaG8KgWTSz+dAdyzPrGUYmi2Q+WFX8g2hqVEZU= dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= @@ -137,8 +137,8 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/enterprise-certificate-proxy v0.3.4 h1:XYIDZApgAnrN1c855gTgghdIA6Stxb52D5RnLI1SLyw= github.com/googleapis/enterprise-certificate-proxy v0.3.4/go.mod h1:YKe7cfqYXjKGpGvmSg28/fFvhNzinZQm8DGnaburhGA= -github.com/googleapis/gax-go/v2 v2.13.0 h1:yitjD5f7jQHhyDsnhKEBU52NdvvdSeGzlAnDPT0hH1s= -github.com/googleapis/gax-go/v2 v2.13.0/go.mod h1:Z/fvTZXF8/uw7Xu5GuslPw+bplx6SS338j1Is2S+B7A= +github.com/googleapis/gax-go/v2 v2.14.0 h1:f+jMrjBPl+DL9nI4IQzLUxMq7XrAqFYB7hBPqMNIe8o= +github.com/googleapis/gax-go/v2 v2.14.0/go.mod h1:lhBCnjdLrWRaPvLWhmc8IS24m9mr07qSYnHncrgo+zk= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= @@ -305,8 +305,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= -golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= +golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ= +golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20240409090435-93d18d7e34b8 h1:ESSUROHIBHg7USnszlcdmjBEwdMj9VUvU+OPk4yl2mc= golang.org/x/exp v0.0.0-20240409090435-93d18d7e34b8/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI= @@ -329,19 +329,19 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= -golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= +golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo= +golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs= -golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/oauth2 v0.24.0 h1:KTBBxWqUa0ykRPLtV69rRto9TLXcqYkeswu48x/gvNE= +golang.org/x/oauth2 v0.24.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= -golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ= +golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -359,21 +359,21 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= -golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= +golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= -golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= +golang.org/x/term v0.26.0 h1:WEQa6V3Gja/BhNxg540hBip/kkaYtRg3cxg4oXSw4AU= +golang.org/x/term v0.26.0/go.mod h1:Si5m1o57C5nBNQo5z1iq+XDijt21BDBDp2bK0QI8e3E= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= -golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= -golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ= -golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= +golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= +golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg= +golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -389,8 +389,8 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.203.0 h1:SrEeuwU3S11Wlscsn+LA1kb/Y5xT8uggJSkIhD08NAU= -google.golang.org/api v0.203.0/go.mod h1:BuOVyCSYEPwJb3npWvDnNmFI92f3GeRnHNkETneT3SI= +google.golang.org/api v0.206.0 h1:A27GClesCSheW5P2BymVHjpEeQ2XHH8DI8Srs2HI2L8= +google.golang.org/api v0.206.0/go.mod h1:BtB8bfjTYIrai3d8UyvPmV9REGgox7coh+ZRwm0b+W8= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= @@ -399,12 +399,12 @@ google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoA google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20241015192408-796eee8c2d53 h1:Df6WuGvthPzc+JiQ/G+m+sNX24kc0aTBqoDN/0yyykE= -google.golang.org/genproto v0.0.0-20241015192408-796eee8c2d53/go.mod h1:fheguH3Am2dGp1LfXkrvwqC/KlFq8F0nLq3LryOMrrE= -google.golang.org/genproto/googleapis/api v0.0.0-20241007155032-5fefd90f89a9 h1:T6rh4haD3GVYsgEfWExoCZA2o2FmbNyKpTuAxbEFPTg= -google.golang.org/genproto/googleapis/api v0.0.0-20241007155032-5fefd90f89a9/go.mod h1:wp2WsuBYj6j8wUdo3ToZsdxxixbvQNAHqVJrTgi5E5M= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 h1:X58yt85/IXCx0Y3ZwN6sEIKZzQtDEYaBWrDvErdXrRE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= +google.golang.org/genproto v0.0.0-20241104194629-dd2ea8efbc28 h1:KJjNNclfpIkVqrZlTWcgOOaVQ00LdBnoEaRfkUx760s= +google.golang.org/genproto v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:mt9/MofW7AWQ+Gy179ChOnvmJatV8YHUmrcedo9CIFI= +google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28 h1:M0KvPgPmDZHPlbRbaNU1APr28TvwvvdUPlSv7PUvy8g= +google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:dguCy7UOdZhTvLzDyt15+rOrawrpM4q7DD9dQ1P11P4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 h1:XVhgTWWV3kGQlwJHR3upFWZeTsei6Oks1apkZSeonIE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= @@ -441,4 +441,4 @@ gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= rsc.io/binaryregexp v0.2.0 h1:HfqmD5MEmC0zvwBuF187nq9mdnXjXsSivRiXN7SmRkE= -rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= \ No newline at end of file From 1f0d1a4a0e48ce20347c80dc35a954611280ec0a Mon Sep 17 00:00:00 2001 From: Mehul3217 <44620455+Mehul3217@users.noreply.github.com> Date: Mon, 18 Nov 2024 09:08:08 +0530 Subject: [PATCH 079/105] increase google cloud netapp create storagePool timeout to 45 mins (#12313) --- mmv1/products/netapp/StoragePool.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mmv1/products/netapp/StoragePool.yaml b/mmv1/products/netapp/StoragePool.yaml index 7e6061babea7..bf288ef502d8 100644 --- a/mmv1/products/netapp/StoragePool.yaml +++ b/mmv1/products/netapp/StoragePool.yaml @@ -53,7 +53,7 @@ delete_url: 'projects/{{project}}/locations/{{location}}/storagePools/{{name}}' import_format: - 'projects/{{project}}/locations/{{location}}/storagePools/{{name}}' timeouts: - insert_minutes: 20 + insert_minutes: 45 update_minutes: 20 delete_minutes: 20 autogen_async: true From e5c4adb8ea7a58fcdb6a61b800c0e07b022934fa Mon Sep 17 00:00:00 2001 From: Mishri Daga Date: Mon, 18 Nov 2024 03:25:40 -0500 Subject: [PATCH 080/105] Fix bug in Pub/Sub Subscription avroConfig which was not sending empty configurations. (#12108) --- mmv1/products/pubsub/Subscription.yaml | 4 +++ .../resource_pubsub_subscription_test.go | 27 +++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/mmv1/products/pubsub/Subscription.yaml b/mmv1/products/pubsub/Subscription.yaml index 8fdec6c05331..10abe7e0220e 100644 --- a/mmv1/products/pubsub/Subscription.yaml +++ b/mmv1/products/pubsub/Subscription.yaml @@ -235,15 +235,19 @@ properties: - 'NOT_FOUND' - name: 'avroConfig' type: NestedObject + send_empty_value: true + allow_empty_object: true description: | If set, message data will be written to Cloud Storage in Avro format. properties: - name: 'writeMetadata' type: Boolean + send_empty_value: true description: | When true, write the subscription name, messageId, publishTime, attributes, and orderingKey as additional fields in the output. - name: 'useTopicSchema' type: Boolean + send_empty_value: true description: | When true, the output Cloud Storage file will be serialized using the topic schema, if it exists. - name: 'serviceAccountEmail' diff --git a/mmv1/third_party/terraform/services/pubsub/resource_pubsub_subscription_test.go b/mmv1/third_party/terraform/services/pubsub/resource_pubsub_subscription_test.go index 3c03898bbcb0..d8ad8234b133 100644 --- a/mmv1/third_party/terraform/services/pubsub/resource_pubsub_subscription_test.go +++ b/mmv1/third_party/terraform/services/pubsub/resource_pubsub_subscription_test.go @@ -352,6 +352,31 @@ func TestAccPubsubSubscriptionCloudStorage_updateAvro(t *testing.T) { }) } +func TestAccPubsubSubscriptionCloudStorage_emptyAvroConfig(t *testing.T) { + t.Parallel() + + bucket := fmt.Sprintf("tf-test-bucket-%s", acctest.RandString(t, 10)) + topic := fmt.Sprintf("tf-test-topic-%s", acctest.RandString(t, 10)) + subscriptionShort := fmt.Sprintf("tf-test-sub-%s", acctest.RandString(t, 10)) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckPubsubSubscriptionDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccPubsubSubscriptionCloudStorage_basic(bucket, topic, subscriptionShort, "pre-", "-suffix", "YYYY-MM-DD/hh_mm_ssZ", 1000, "300s", 1000, "", "empty-avro"), + }, + { + ResourceName: "google_pubsub_subscription.foo", + ImportStateId: subscriptionShort, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + func TestAccPubsubSubscriptionCloudStorage_serviceAccount(t *testing.T) { t.Parallel() @@ -823,6 +848,8 @@ resource "google_storage_bucket_iam_member" "admin" { use_topic_schema = true } ` + } else if outputFormat == "empty-avro" { + outputFormatString = `avro_config {}` } return fmt.Sprintf(` data "google_project" "project" { } From aa87d479eb87bd885cf00688b2787a9cdc0a9a7b Mon Sep 17 00:00:00 2001 From: karolgorc Date: Mon, 18 Nov 2024 18:25:07 +0100 Subject: [PATCH 081/105] Support `IPV6_ONLY` configurations for compute API (#12283) --- mmv1/products/compute/Subnetwork.yaml | 1 + .../services/compute/resource_compute_instance.go.tmpl | 5 +++-- .../compute/resource_compute_instance_template.go.tmpl | 3 ++- .../resource_compute_region_instance_template.go.tmpl | 3 ++- .../terraform/website/docs/r/compute_instance.html.markdown | 2 +- .../website/docs/r/compute_instance_template.html.markdown | 2 +- .../docs/r/compute_region_instance_template.html.markdown | 2 +- 7 files changed, 11 insertions(+), 7 deletions(-) diff --git a/mmv1/products/compute/Subnetwork.yaml b/mmv1/products/compute/Subnetwork.yaml index 42b2f4262f78..0ddddb1e9c02 100644 --- a/mmv1/products/compute/Subnetwork.yaml +++ b/mmv1/products/compute/Subnetwork.yaml @@ -404,6 +404,7 @@ properties: enum_values: - 'IPV4_ONLY' - 'IPV4_IPV6' + - 'IPV6_ONLY' - name: 'ipv6AccessType' type: Enum description: | diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_instance.go.tmpl b/mmv1/third_party/terraform/services/compute/resource_compute_instance.go.tmpl index 245e3415b963..8e6b5383123e 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_instance.go.tmpl +++ b/mmv1/third_party/terraform/services/compute/resource_compute_instance.go.tmpl @@ -535,7 +535,7 @@ func ResourceComputeInstance() *schema.Resource { Type: schema.TypeString, Optional: true, Computed: true, - ValidateFunc: validation.StringInSlice([]string{"IPV4_ONLY", "IPV4_IPV6", ""}, false), + ValidateFunc: validation.StringInSlice([]string{"IPV4_ONLY", "IPV4_IPV6", "IPV6_ONLY", ""}, false), Description: `The stack type for this network interface to identify whether the IPv6 feature is enabled or not. If not specified, IPV4_ONLY will be used.`, }, @@ -547,7 +547,8 @@ func ResourceComputeInstance() *schema.Resource { "ipv6_access_config": { Type: schema.TypeList, - Optional: true, + Optional: true, + Computed: true, Description: `An array of IPv6 access configurations for this interface. Currently, only one IPv6 access config, DIRECT_IPV6, is supported. If there is no ipv6AccessConfig specified, then this instance will have no external IPv6 Internet access.`, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_instance_template.go.tmpl b/mmv1/third_party/terraform/services/compute/resource_compute_instance_template.go.tmpl index ecff319cf83e..0417877868e4 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_instance_template.go.tmpl +++ b/mmv1/third_party/terraform/services/compute/resource_compute_instance_template.go.tmpl @@ -555,7 +555,7 @@ Google Cloud KMS.`, Optional: true, Computed: true, ForceNew: true, - ValidateFunc: validation.StringInSlice([]string{"IPV4_ONLY", "IPV4_IPV6", ""}, false), + ValidateFunc: validation.StringInSlice([]string{"IPV4_ONLY", "IPV4_IPV6", "IPV6_ONLY", ""}, false), Description: `The stack type for this network interface to identify whether the IPv6 feature is enabled or not. If not specified, IPV4_ONLY will be used.`, }, @@ -569,6 +569,7 @@ Google Cloud KMS.`, "ipv6_access_config": { Type: schema.TypeList, Optional: true, + Computed: true, ForceNew: true, Description: `An array of IPv6 access configurations for this interface. Currently, only one IPv6 access config, DIRECT_IPV6, is supported. If there is no ipv6AccessConfig specified, then this instance will have no external IPv6 Internet access.`, Elem: &schema.Resource{ diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_template.go.tmpl b/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_template.go.tmpl index 992ab0fb7b28..273708aafe84 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_template.go.tmpl +++ b/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_template.go.tmpl @@ -524,7 +524,7 @@ Google Cloud KMS.`, Optional: true, Computed: true, ForceNew: true, - ValidateFunc: validation.StringInSlice([]string{"IPV4_ONLY", "IPV4_IPV6", ""}, false), + ValidateFunc: validation.StringInSlice([]string{"IPV4_ONLY", "IPV4_IPV6","IPV6_ONLY", ""}, false), Description: `The stack type for this network interface to identify whether the IPv6 feature is enabled or not. If not specified, IPV4_ONLY will be used.`, }, @@ -538,6 +538,7 @@ Google Cloud KMS.`, "ipv6_access_config": { Type: schema.TypeList, Optional: true, + Computed: true, ForceNew: true, Description: `An array of IPv6 access configurations for this interface. Currently, only one IPv6 access config, DIRECT_IPV6, is supported. If there is no ipv6AccessConfig specified, then this instance will have no external IPv6 Internet access.`, Elem: &schema.Resource{ diff --git a/mmv1/third_party/terraform/website/docs/r/compute_instance.html.markdown b/mmv1/third_party/terraform/website/docs/r/compute_instance.html.markdown index 3c7fdb118027..83ea8d38944b 100644 --- a/mmv1/third_party/terraform/website/docs/r/compute_instance.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/compute_instance.html.markdown @@ -399,7 +399,7 @@ is desired, you will need to modify your state file manually using * `network_attachment` - (Optional) [Beta](https://terraform.io/docs/providers/google/guides/provider_versions.html) The URL of the network attachment that this interface should connect to in the following format: `projects/{projectNumber}/regions/{region_name}/networkAttachments/{network_attachment_name}`. -* `stack_type` - (Optional) The stack type for this network interface to identify whether the IPv6 feature is enabled or not. Values are IPV4_IPV6 or IPV4_ONLY. If not specified, IPV4_ONLY will be used. +* `stack_type` - (Optional) The stack type for this network interface to identify whether the IPv6 feature is enabled or not. Values are IPV4_IPV6, IPV6_ONLY or IPV4_ONLY. If not specified, IPV4_ONLY will be used. * `ipv6_access_config` - (Optional) An array of IPv6 access configurations for this interface. Currently, only one IPv6 access config, DIRECT_IPV6, is supported. If there is no ipv6AccessConfig diff --git a/mmv1/third_party/terraform/website/docs/r/compute_instance_template.html.markdown b/mmv1/third_party/terraform/website/docs/r/compute_instance_template.html.markdown index 3b009c3e0db0..ef900aff1539 100644 --- a/mmv1/third_party/terraform/website/docs/r/compute_instance_template.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/compute_instance_template.html.markdown @@ -563,7 +563,7 @@ The following arguments are supported: * `nic_type` - (Optional) The type of vNIC to be used on this interface. Possible values: GVNIC, VIRTIO_NET. In the beta provider the additional values of MRDMA and IRDMA are supported. -* `stack_type` - (Optional) The stack type for this network interface to identify whether the IPv6 feature is enabled or not. Values are IPV4_IPV6 or IPV4_ONLY. If not specified, IPV4_ONLY will be used. +* `stack_type` - (Optional) The stack type for this network interface to identify whether the IPv6 feature is enabled or not. Values are IPV4_IPV6, IPV6_ONLY or IPV4_ONLY. If not specified, IPV4_ONLY will be used. * `ipv6_access_config` - (Optional) An array of IPv6 access configurations for this interface. Currently, only one IPv6 access config, DIRECT_IPV6, is supported. If there is no ipv6AccessConfig diff --git a/mmv1/third_party/terraform/website/docs/r/compute_region_instance_template.html.markdown b/mmv1/third_party/terraform/website/docs/r/compute_region_instance_template.html.markdown index 83b6a421bb07..12ba8874792c 100644 --- a/mmv1/third_party/terraform/website/docs/r/compute_region_instance_template.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/compute_region_instance_template.html.markdown @@ -529,7 +529,7 @@ The following arguments are supported: * `nic_type` - (Optional) The type of vNIC to be used on this interface. Possible values: GVNIC, VIRTIO_NET. In the beta provider the additional values of MRDMA and IRDMA are supported. -* `stack_type` - (Optional) The stack type for this network interface to identify whether the IPv6 feature is enabled or not. Values are IPV4_IPV6 or IPV4_ONLY. If not specified, IPV4_ONLY will be used. +* `stack_type` - (Optional) The stack type for this network interface to identify whether the IPv6 feature is enabled or not. Values are IPV4_IPV6, IPV6_ONLY or IPV4_ONLY. If not specified, IPV4_ONLY will be used. * `ipv6_access_config` - (Optional) An array of IPv6 access configurations for this interface. Currently, only one IPv6 access config, DIRECT_IPV6, is supported. If there is no ipv6AccessConfig From c91b09c2f3edc111f113f275c93e02c4300fdc42 Mon Sep 17 00:00:00 2001 From: Manjunath Ganga <54118884+manjunathganga@users.noreply.github.com> Date: Mon, 18 Nov 2024 09:57:03 -0800 Subject: [PATCH 082/105] Redis Cluster Cross Cluster Replication addition (#12300) Co-authored-by: Nick Elliot --- mmv1/products/redis/Cluster.yaml | 190 +++++++++++++++ .../examples/redis_cluster_secondary.tf.tmpl | 151 ++++++++++++ .../redis/resource_redis_cluster_test.go.tmpl | 228 +++++++++++++----- 3 files changed, 509 insertions(+), 60 deletions(-) create mode 100644 mmv1/templates/terraform/examples/redis_cluster_secondary.tf.tmpl diff --git a/mmv1/products/redis/Cluster.yaml b/mmv1/products/redis/Cluster.yaml index c068ab9f1346..6888932eca07 100644 --- a/mmv1/products/redis/Cluster.yaml +++ b/mmv1/products/redis/Cluster.yaml @@ -20,6 +20,80 @@ references: 'Official Documentation': 'https://cloud.google.com/memorystore/docs/cluster/' api: 'https://cloud.google.com/memorystore/docs/cluster/reference/rest/v1/projects.locations.clusters' docs: + note: | + For [Cross Region Replication](https://cloud.google.com/memorystore/docs/cluster/about-cross-region-replication), please follow the instructions below for performing certain update and failover (switchover and detach) operations + + **Cross Region Replication** + + **Settings updated on primary and propagated to secondaries** + + The settings listed [here](https://cloud.google.com/memorystore/docs/cluster/about-cross-region-replication#set_on_primary) + are only allowed to be updated on the primary cluster and the changes are automatically propagated to the secondary clusters. + To keep the Terraform configuration and state in sync for such settings, please follow the below steps to update them: + 1. Update the setting on the primary cluster: + * Update the setting to its new desired value in the Terraform configuration file. + * Execute `terraform apply` to apply the change and wait for it to complete. + 1. Detect configuration drift on the secondary cluster(s): + * Execute `terraform plan`. This should reveal a diff for the modified setting. The proposed value in the Terraform plan should align with the updated value applied to the primary cluster in the preceding step. + 1. Reconcile secondary cluster(s) configuration: + * Manually edit the Terraform configuration file(s) for the secondary cluster(s) to update the setting with the latest value from the state. + * Execute `terraform plan` once again. This should not generate any diff, confirming the configuration is in sync with the infrastructure. + + + **Switchover** + + To perform a [switchover](https://cloud.google.com/memorystore/docs/cluster/working-with-cross-region-replication#perform_a_switchover), please follow the below steps: + 1. Ensure that the Terraform configuration file for the secondary cluster that needs to become the new primary has the `cross_cluster_replication_config` field. If it is not present: + * Add the `cross_cluster_replication_config` field to the configuration file to match the latest value in the state. + * Execute `terraform plan`. This should not generate any diff, confirming the configuration is in sync with the infrastructure. + 1. Update the `cross_cluster_replication_config` field of the secondary that needs to become the new primary: + * Change `cross_cluster_replication_config.cluster_role` from `SECONDARY` to `PRIMARY`. + * Remove `cross_cluster_replication_config.primary_cluster` field. + * Set `cross_cluster_replication_config.secondary_clusters` list with the new secondaries. The new secondaries are the current primary and other secondary clusters(if any). + + -> You can refer to the current value of `cross_cluster_replication_config.membership` field to lookup the current primary and secondary clusters. + 1. Execute switchover: + * Execute`terraform apply` to apply the change and wait for it to complete. + 1. Fix any configuration drifts on the previous primary and other secondary clusters: + * Execute `terraform plan`. If any diffs are reported for `cross_cluster_replication_config` field: + * Manually update `cross_cluster_replication_config` field in the configuration file(s) for those clusters with the latest value from the state. + * Execute `terraform plan` once again. This should not generate any diff, confirming the configuration is in sync with the infrastructure. + + **Detach a secondary cluster** + + To [detach](https://cloud.google.com/memorystore/docs/cluster/working-with-cross-region-replication#detach_secondary_clusters_option_1) a secondary cluster, please follow the below steps: + 1. Ensure that the Terraform configuration file for the secondary cluster that needs to be detached has the `cross_cluster_replication_config` field. If it is not present: + * Add the `cross_cluster_replication_config` field to the configuration file to match the latest value in the state. + * Execute `terraform plan`. This should not generate any diff, confirming the configuration is in sync with the infrastructure. + 1. Update the `cross_cluster_replication_config` field of the secondary that needs to be detached: + * Change `cross_cluster_replication_config.cluster_role` from `SECONDARY` to `NONE`. + * Remove `cross_cluster_replication_config.primary_cluster`. + 1. Execute detach: + * Execute`terraform apply` to apply the change and wait for it to complete. + 1. Fix any configuration drifts on the primary cluster: + * Execute `terraform plan`. If any diff is reported for `cross_cluster_replication_config` field: + * Manually update `cross_cluster_replication_config` field in the configuration file with the latest value from the state. + * Execute `terraform plan` once again. This should not generate any diff, confirming the configuration is in sync with the infrastructure. + + **Detach secondary cluster(s) via primary cluster** + + To [detach](https://cloud.google.com/memorystore/docs/cluster/working-with-cross-region-replication#detach_secondary_clusters_option_2) secondary clusters via primary, please follow the below steps: + 1. Ensure that the Terraform configuration file for the primary cluster from which the secondary(ies) has(ve) to be detached has the `cross_cluster_replication_config` field. If it is not present: + * Add the `cross_cluster_replication_config` field to the configuration file to match the latest value in the state. + * Execute `terraform plan`. This should not generate any diff, confirming the configuration is in sync with the infrastructure. + 1. Update the `cross_cluster_replication_config` field of the primary cluster: + * If you are detaching all secondaries from the primary: + * Change `cross_cluster_replication_config.cluster_role` from `PRIMARY` to `NONE`. + * Remove `cross_cluster_replication_config.secondary_clusters` list field. + * If you are detaching a subset of secondaries: + * Update `cross_cluster_replication_config.secondary_clusters` list field to remove the secondary clusters that need to be detached. + 1. Execute detach: + * Execute `terraform apply` to apply the change and wait for it to complete. + 1. Fix any configuration drifts on the secondary cluster(s) that was detached: + * Execute `terraform plan`. If any diffs are reported for `cross_cluster_replication_config` field: + * Manually update `cross_cluster_replication_config` field in the configuration file(s) for those clusters with the latest value from the state. + * Execute `terraform plan` once again. This should not generate any diff, confirming the configuration is in sync with the infrastructure. + base_url: 'projects/{{project}}/locations/{{region}}/clusters' self_link: 'projects/{{project}}/locations/{{region}}/clusters/{{name}}' create_url: 'projects/{{project}}/locations/{{region}}/clusters?clusterId={{name}}' @@ -63,6 +137,24 @@ examples: 'deletion_protection_enabled': 'false' oics_vars_overrides: 'deletion_protection_enabled': 'false' + - name: 'redis_cluster_secondary' + primary_resource_id: 'secondary_cluster' + vars: + primary_cluster_name: 'my-primary-cluster' + primary_cluster_deletion_protection_enabled: 'true' + primary_cluster_policy_name: 'mypolicy-primary-cluster' + primary_cluster_subnet_name: 'mysubnet-primary-cluster' + secondary_cluster_name: 'my-secondary-cluster' + secondary_cluster_deletion_protection_enabled: 'true' + secondary_cluster_policy_name: 'mypolicy-secondary-cluster' + secondary_cluster_subnet_name: 'mysubnet-secondary-cluster' + network_name: 'mynetwork' + test_vars_overrides: + 'primary_cluster_deletion_protection_enabled': 'false' + 'secondary_cluster_deletion_protection_enabled': 'false' + oics_vars_overrides: + 'primary_cluster_deletion_protection_enabled': 'false' + 'secondary_cluster_deletion_protection_enabled': 'false' - name: "redis_cluster_rdb" primary_resource_id: "cluster-rdb" vars: @@ -497,3 +589,101 @@ properties: A timestamp in RFC3339 UTC "Zulu" format, with nanosecond resolution and up to nine fractional digits. output: true + - name: 'crossClusterReplicationConfig' + type: NestedObject + description: Cross cluster replication config + default_from_api: true + properties: + - name: 'clusterRole' + type: Enum + description: | + The role of the cluster in cross cluster replication. Supported values are: + + 1. `CLUSTER_ROLE_UNSPECIFIED`: This is an independent cluster that has never participated in cross cluster replication. It allows both reads and writes. + + 1. `NONE`: This is an independent cluster that previously participated in cross cluster replication(either as a `PRIMARY` or `SECONDARY` cluster). It allows both reads and writes. + + 1. `PRIMARY`: This cluster serves as the replication source for secondary clusters that are replicating from it. Any data written to it is automatically replicated to its secondary clusters. It allows both reads and writes. + + 1. `SECONDARY`: This cluster replicates data from the primary cluster. It allows only reads. + + enum_values: + - 'CLUSTER_ROLE_UNSPECIFIED' + - 'NONE' + - 'PRIMARY' + - 'SECONDARY' + - name: 'primaryCluster' + type: NestedObject + description: | + Details of the primary cluster that is used as the replication source for this secondary cluster. This is allowed to be set only for clusters whose cluster role is of type `SECONDARY`. + properties: + - name: 'cluster' + type: String + description: | + The full resource path of the primary cluster in the format: projects/{project}/locations/{region}/clusters/{cluster-id} + - name: 'uid' + type: String + description: | + The unique id of the primary cluster. + output: true + - name: 'secondaryClusters' + type: Array + description: | + List of secondary clusters that are replicating from this primary cluster. This is allowed to be set only for clusters whose cluster role is of type `PRIMARY`. + item_type: + type: NestedObject + properties: + - name: 'cluster' + type: String + description: | + The full resource path of the secondary cluster in the format: projects/{project}/locations/{region}/clusters/{cluster-id} + - name: 'uid' + type: String + description: | + The unique id of the secondary cluster. + output: true + - name: 'membership' + type: NestedObject + description: | + An output only view of all the member clusters participating in cross cluster replication. This field is populated for all the member clusters irrespective of their cluster role. + output: true + properties: + - name: 'primaryCluster' + type: NestedObject + description: | + Details of the primary cluster that is used as the replication source for all the secondary clusters. + output: true + properties: + - name: 'cluster' + type: String + description: | + The full resource path of the primary cluster in the format: projects/{project}/locations/{region}/clusters/{cluster-id} + output: true + - name: 'uid' + type: String + description: | + The unique id of the primary cluster. + output: true + - name: 'secondaryClusters' + type: Array + description: | + List of secondary clusters that are replicating from the primary cluster. + output: true + item_type: + type: NestedObject + properties: + - name: 'cluster' + type: String + description: | + The full resource path of the secondary cluster in the format: projects/{project}/locations/{region}/clusters/{cluster-id} + output: true + - name: 'uid' + type: String + description: | + The unique id of the secondary cluster. + output: true + - name: 'updateTime' + type: String + description: | + The last time cross cluster replication config was updated. + output: true diff --git a/mmv1/templates/terraform/examples/redis_cluster_secondary.tf.tmpl b/mmv1/templates/terraform/examples/redis_cluster_secondary.tf.tmpl new file mode 100644 index 000000000000..d2413d90334f --- /dev/null +++ b/mmv1/templates/terraform/examples/redis_cluster_secondary.tf.tmpl @@ -0,0 +1,151 @@ +// Primary cluster +resource "google_redis_cluster" "primary_cluster" { + name = "{{index $.Vars "primary_cluster_name"}}" + region = "us-east1" + psc_configs { + network = google_compute_network.producer_net.id + } + + // Settings that should match on primary and secondary clusters. + // If you define a setting here, ensure that the secondary clusters also define it with the same values. + // Please see https://cloud.google.com/memorystore/docs/cluster/about-cross-region-replication#settings_copied_from_the_primary_during_instance_creation for the complete list of such settings. + authorization_mode = "AUTH_MODE_DISABLED" + transit_encryption_mode = "TRANSIT_ENCRYPTION_MODE_DISABLED" + shard_count = 3 + redis_configs = { + maxmemory-policy = "volatile-ttl" + } + node_type = "REDIS_HIGHMEM_MEDIUM" + persistence_config { + mode = "RDB" + rdb_config { + rdb_snapshot_period = "ONE_HOUR" + rdb_snapshot_start_time = "2024-10-02T15:01:23Z" + } + } + + // Settings that can have different values on primary and secondary clusters. + // Please see https://cloud.google.com/memorystore/docs/cluster/about-cross-region-replication#override_allowed_during_instance_creation for the complete list of such settings. + zone_distribution_config { + mode = "MULTI_ZONE" + } + replica_count = 1 + maintenance_policy { + weekly_maintenance_window { + day = "MONDAY" + start_time { + hours = 1 + minutes = 0 + seconds = 0 + nanos = 0 + } + } + } + deletion_protection_enabled = {{index $.Vars "primary_cluster_deletion_protection_enabled"}} + + depends_on = [ + google_network_connectivity_service_connection_policy.primary_cluster_region_scp + ] +} + + +// Secondary cluster +resource "google_redis_cluster" "{{$.PrimaryResourceId}}" { + name = "{{index $.Vars "secondary_cluster_name"}}" + region = "europe-west1" + psc_configs { + network = google_compute_network.producer_net.id + } + + // Settings that should match on primary and secondary clusters. + // If you defined a setting here for primary, ensure the secondary clusters also define it with the same values. + // Please see https://cloud.google.com/memorystore/docs/cluster/about-cross-region-replication#settings_copied_from_the_primary_during_instance_creation for the complete list of such settings. + authorization_mode = "AUTH_MODE_DISABLED" + transit_encryption_mode = "TRANSIT_ENCRYPTION_MODE_DISABLED" + shard_count = 3 + redis_configs = { + maxmemory-policy = "volatile-ttl" + } + node_type = "REDIS_HIGHMEM_MEDIUM" + persistence_config { + mode = "RDB" + rdb_config { + rdb_snapshot_period = "ONE_HOUR" + rdb_snapshot_start_time = "2024-10-02T15:01:23Z" + } + } + + // Settings that can be different on primary and secondary clusters. + // Please see https://cloud.google.com/memorystore/docs/cluster/about-cross-region-replication#override_allowed_during_instance_creation for the complete list of such settings. + zone_distribution_config { + mode = "MULTI_ZONE" + } + replica_count = 2 + maintenance_policy { + weekly_maintenance_window { + day = "WEDNESDAY" + start_time { + hours = 1 + minutes = 0 + seconds = 0 + nanos = 0 + } + } + } + deletion_protection_enabled = {{index $.Vars "secondary_cluster_deletion_protection_enabled"}} + + // Cross cluster replication config + cross_cluster_replication_config { + cluster_role = "SECONDARY" + primary_cluster { + cluster = google_redis_cluster.primary_cluster.id + } + } + + depends_on = [ + google_network_connectivity_service_connection_policy.secondary_cluster_region_scp + ] +} + + +resource "google_network_connectivity_service_connection_policy" "primary_cluster_region_scp" { + name = "{{index $.Vars "primary_cluster_policy_name"}}" + location = "us-east1" + service_class = "gcp-memorystore-redis" + description = "Primary cluster service connection policy" + network = google_compute_network.producer_net.id + psc_config { + subnetworks = [google_compute_subnetwork.primary_cluster_producer_subnet.id] + } +} + +resource "google_compute_subnetwork" "primary_cluster_producer_subnet" { + name = "{{index $.Vars "primary_cluster_subnet_name"}}" + ip_cidr_range = "10.0.1.0/29" + region = "us-east1" + network = google_compute_network.producer_net.id +} + + +resource "google_network_connectivity_service_connection_policy" "secondary_cluster_region_scp" { + name = "{{index $.Vars "secondary_cluster_policy_name"}}" + location = "europe-west1" + service_class = "gcp-memorystore-redis" + description = "Secondary cluster service connection policy" + network = google_compute_network.producer_net.id + psc_config { + subnetworks = [google_compute_subnetwork.secondary_cluster_producer_subnet.id] + } +} + +resource "google_compute_subnetwork" "secondary_cluster_producer_subnet" { + name = "{{index $.Vars "secondary_cluster_subnet_name"}}" + ip_cidr_range = "10.0.2.0/29" + region = "europe-west1" + network = google_compute_network.producer_net.id +} + +resource "google_compute_network" "producer_net" { + name = "{{index $.Vars "network_name"}}" + auto_create_subnetworks = false +} \ No newline at end of file diff --git a/mmv1/third_party/terraform/services/redis/resource_redis_cluster_test.go.tmpl b/mmv1/third_party/terraform/services/redis/resource_redis_cluster_test.go.tmpl index 02839714e679..31a8759a32d2 100644 --- a/mmv1/third_party/terraform/services/redis/resource_redis_cluster_test.go.tmpl +++ b/mmv1/third_party/terraform/services/redis/resource_redis_cluster_test.go.tmpl @@ -309,24 +309,114 @@ func TestAccRedisCluster_persistenceUpdate(t *testing.T) { }) } +// Validate that deletion protection enabled/disabled cluster is created updated +func TestAccRedisCluster_switchoverAndDetachSecondary(t *testing.T) { + t.Parallel() + + pcName := fmt.Sprintf("tf-test-prim-%d", acctest.RandInt(t)) + scName := fmt.Sprintf("tf-test-sec-%d", acctest.RandInt(t)) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t), + CheckDestroy: testAccCheckRedisClusterDestroyProducer(t), + Steps: []resource.TestStep{ + { + // create primary and secondary clusters cluster + Config: createOrUpdateRedisCluster(&ClusterParams{name: pcName, replicaCount: 0, shardCount: 3, deletionProtectionEnabled: false, zoneDistributionMode: "MULTI_ZONE", shouldCreateSecondary: true, secondaryClusterName: scName, ccrRole: "SECONDARY"}), + }, + { + ResourceName: "google_redis_cluster.test_secondary", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"psc_configs"}, + }, + { + // // Switchover to secondary cluster + Config: createOrUpdateRedisCluster(&ClusterParams{name: pcName, replicaCount: 0, shardCount: 3, deletionProtectionEnabled: false, zoneDistributionMode: "MULTI_ZONE", shouldCreateSecondary: true, secondaryClusterName: scName, ccrRole: "PRIMARY"}), + }, + { + ResourceName: "google_redis_cluster.test_secondary", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"psc_configs"}, + }, + { + // Detach secondary cluster and delete the clusters + Config: createOrUpdateRedisCluster(&ClusterParams{name: pcName, replicaCount: 0, shardCount: 3, deletionProtectionEnabled: false, zoneDistributionMode: "MULTI_ZONE", shouldCreateSecondary: true, secondaryClusterName: scName, ccrRole: "NONE"}), + }, + }, + }) +} + type ClusterParams struct { - name string - replicaCount int - shardCount int + name string + replicaCount int + shardCount int deletionProtectionEnabled bool - nodeType string - redisConfigs map[string]string - zoneDistributionMode string - zone string - maintenanceDay string - maintenanceHours int - maintenanceMinutes int - maintenanceSeconds int - maintenanceNanos int - persistenceBlock string + nodeType string + redisConfigs map[string]string + zoneDistributionMode string + zone string + maintenanceDay string + maintenanceHours int + maintenanceMinutes int + maintenanceSeconds int + maintenanceNanos int + persistenceBlock string + shouldCreateSecondary bool + secondaryClusterName string + ccrRole string } func createOrUpdateRedisCluster(params *ClusterParams) string { + clusterResourceBlock := createRedisClusterResourceConfig(params, /*isSecondaryCluster*/false) + secClusterResourceBlock := `` + if params.shouldCreateSecondary { + secClusterResourceBlock = createRedisClusterResourceConfig(params, /*isSecondaryCluster*/true) + } + + return fmt.Sprintf(` + %s + %s + resource "google_network_connectivity_service_connection_policy" "default" { + provider = google-beta + name = "%s" + location = "us-central1" + service_class = "gcp-memorystore-redis" + description = "my basic service connection policy" + network = google_compute_network.producer_net.id + psc_config { + subnetworks = [google_compute_subnetwork.producer_subnet.id] + } + } + + resource "google_compute_subnetwork" "producer_subnet" { + provider = google-beta + name = "%s" + ip_cidr_range = "10.0.0.16/28" + region = "us-central1" + network = google_compute_network.producer_net.id + } + + resource "google_compute_network" "producer_net" { + provider = google-beta + name = "%s" + auto_create_subnetworks = false + } + `, + clusterResourceBlock, + secClusterResourceBlock, + params.name, + params.name, + params.name) +} + +func createRedisClusterResourceConfig(params *ClusterParams, isSecondaryCluster bool) string { + tfClusterResourceName := "test" + clusterName := params.name + dependsOnBlock := "google_network_connectivity_service_connection_policy.default" + var redsConfigsStrBuilder strings.Builder for key, value := range params.redisConfigs { redsConfigsStrBuilder.WriteString(fmt.Sprintf("%s = \"%s\"\n", key, value)) @@ -359,55 +449,73 @@ func createOrUpdateRedisCluster(params *ClusterParams) string { `, params.maintenanceDay, params.maintenanceHours, params.maintenanceMinutes, params.maintenanceSeconds, params.maintenanceNanos) } - return fmt.Sprintf(` -resource "google_redis_cluster" "test" { - provider = google-beta - name = "%s" - replica_count = %d - shard_count = %d - node_type = "%s" - deletion_protection_enabled = %v - region = "us-central1" - psc_configs { - network = google_compute_network.producer_net.id - } - redis_configs = { - %s - } - %s - %s - %s - depends_on = [ - google_network_connectivity_service_connection_policy.default - ] -} - -resource "google_network_connectivity_service_connection_policy" "default" { - provider = google-beta - name = "%s" - location = "us-central1" - service_class = "gcp-memorystore-redis" - description = "my basic service connection policy" - network = google_compute_network.producer_net.id - psc_config { - subnetworks = [google_compute_subnetwork.producer_subnet.id] + crossClusterReplicationConfigBlock := `` + if isSecondaryCluster { + tfClusterResourceName = "test_secondary" + clusterName = params.secondaryClusterName + dependsOnBlock = dependsOnBlock + ", google_redis_cluster.test" + + // Construct cross_cluster_replication_config block + pcBlock := `` + scsBlock := `` + if params.ccrRole == "SECONDARY" { + pcBlock = fmt.Sprintf(` + primary_cluster { + cluster = google_redis_cluster.test.id + } + `) + } else if params.ccrRole == "PRIMARY" { + scsBlock = fmt.Sprintf(` + secondary_clusters { + cluster = google_redis_cluster.test.id + } + `) + } + crossClusterReplicationConfigBlock = fmt.Sprintf(` + cross_cluster_replication_config { + cluster_role = "%s" + %s + %s + } + `, params.ccrRole, pcBlock, scsBlock) } -} - -resource "google_compute_subnetwork" "producer_subnet" { - provider = google-beta - name = "%s" - ip_cidr_range = "10.0.0.248/29" - region = "us-central1" - network = google_compute_network.producer_net.id -} -resource "google_compute_network" "producer_net" { - provider = google-beta - name = "%s" - auto_create_subnetworks = false -} -`, params.name, params.replicaCount, params.shardCount, params.nodeType, params.deletionProtectionEnabled, redsConfigsStrBuilder.String(), zoneDistributionConfigBlock, maintenancePolicyBlock, params.persistenceBlock, params.name, params.name, params.name) + return fmt.Sprintf(` + resource "google_redis_cluster" "%s" { + provider = google-beta + name = "%s" + replica_count = %d + shard_count = %d + node_type = "%s" + deletion_protection_enabled = %v + region = "us-central1" + psc_configs { + network = google_compute_network.producer_net.id + } + redis_configs = { + %s + } + %s + %s + %s + %s + depends_on = [ + %s + ] + } + `, + tfClusterResourceName, + clusterName, + params.replicaCount, + params.shardCount, + params.nodeType, + params.deletionProtectionEnabled, + redsConfigsStrBuilder.String(), + zoneDistributionConfigBlock, + maintenancePolicyBlock, + params.persistenceBlock, + crossClusterReplicationConfigBlock, + dependsOnBlock) } {{ end }} From c9744b21db0e636c5bfb5347a8cba56734a265ae Mon Sep 17 00:00:00 2001 From: Shuya Ma <87669292+shuyama1@users.noreply.github.com> Date: Mon, 18 Nov 2024 13:02:29 -0800 Subject: [PATCH 083/105] Fix backup vault tests in VCR (#12345) --- mmv1/products/backupdr/BackupPlan.yaml | 1 + .../terraform/examples/backup_dr_backup_plan_simple.tf.tmpl | 2 +- .../backupdr/resource_backup_dr_backup_vault_test.go.tmpl | 3 +++ 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/mmv1/products/backupdr/BackupPlan.yaml b/mmv1/products/backupdr/BackupPlan.yaml index e1b2505403e4..da5424e9f8f8 100644 --- a/mmv1/products/backupdr/BackupPlan.yaml +++ b/mmv1/products/backupdr/BackupPlan.yaml @@ -33,6 +33,7 @@ examples: min_version: 'beta' primary_resource_id: 'my-backup-plan-1' vars: + backup_vault_id: 'backup-vault-simple-test' backup_plan_id: 'backup-plan-simple-test' test_env_vars: project: :PROJECT_NAME diff --git a/mmv1/templates/terraform/examples/backup_dr_backup_plan_simple.tf.tmpl b/mmv1/templates/terraform/examples/backup_dr_backup_plan_simple.tf.tmpl index 81363b8ae98d..dd5ae57689f7 100644 --- a/mmv1/templates/terraform/examples/backup_dr_backup_plan_simple.tf.tmpl +++ b/mmv1/templates/terraform/examples/backup_dr_backup_plan_simple.tf.tmpl @@ -1,7 +1,7 @@ resource "google_backup_dr_backup_vault" "my_backup_vault" { provider = google-beta location = "us-central1" - backup_vault_id = "bv-bp-test" + backup_vault_id = "{{index $.Vars "backup_vault_id"}}" backup_minimum_enforced_retention_duration = "100000s" } diff --git a/mmv1/third_party/terraform/services/backupdr/resource_backup_dr_backup_vault_test.go.tmpl b/mmv1/third_party/terraform/services/backupdr/resource_backup_dr_backup_vault_test.go.tmpl index 53d7f084cbf8..19938ef52f76 100644 --- a/mmv1/third_party/terraform/services/backupdr/resource_backup_dr_backup_vault_test.go.tmpl +++ b/mmv1/third_party/terraform/services/backupdr/resource_backup_dr_backup_vault_test.go.tmpl @@ -10,6 +10,9 @@ import ( ) func TestAccBackupDRBackupVault_fullUpdate(t *testing.T) { + // Uses time.Now + acctest.SkipIfVcr(t) + t.Parallel() timeNow := time.Now().UTC() From eec9d040c11c93b9013d8891d000eb67f1e0b9d1 Mon Sep 17 00:00:00 2001 From: Suraj Naik Date: Tue, 19 Nov 2024 02:41:10 +0530 Subject: [PATCH 084/105] Fix TestAccDataprocCluster_withNetworkRefs (#12335) --- .../dataproc/resource_dataproc_cluster_test.go.tmpl | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/mmv1/third_party/terraform/services/dataproc/resource_dataproc_cluster_test.go.tmpl b/mmv1/third_party/terraform/services/dataproc/resource_dataproc_cluster_test.go.tmpl index 5a7f8cccbc5f..040f08ac4402 100644 --- a/mmv1/third_party/terraform/services/dataproc/resource_dataproc_cluster_test.go.tmpl +++ b/mmv1/third_party/terraform/services/dataproc/resource_dataproc_cluster_test.go.tmpl @@ -2351,14 +2351,15 @@ resource "google_dataproc_cluster" "with_net_ref_by_name" { } master_config { - machine_type = "e2-medium" + machine_type = "e2-standard-2" disk_config { boot_disk_size_gb = 35 } } gce_cluster_config { - network = google_compute_network.dataproc_network.name + network = google_compute_network.dataproc_network.name + internal_ip_only = false } } } @@ -2378,14 +2379,15 @@ resource "google_dataproc_cluster" "with_net_ref_by_url" { } master_config { - machine_type = "e2-medium" + machine_type = "e2-standard-2" disk_config { boot_disk_size_gb = 35 } } gce_cluster_config { - network = google_compute_network.dataproc_network.self_link + network = google_compute_network.dataproc_network.self_link + internal_ip_only = false } } } From 0e4f8103665a42efd12b0c474388d44f6ef112c5 Mon Sep 17 00:00:00 2001 From: Liyun Huang Date: Mon, 18 Nov 2024 16:54:14 -0500 Subject: [PATCH 085/105] Promote backupvault to GA (#12332) --- mmv1/products/backupdr/BackupVault.yaml | 25 ------------------- mmv1/products/backupdr/product.yaml | 2 ++ .../backup_dr_backup_vault_full.tf.tmpl | 9 +++---- ...source_backup_dr_backup_vault_test.go.tmpl | 8 ++---- 4 files changed, 8 insertions(+), 36 deletions(-) diff --git a/mmv1/products/backupdr/BackupVault.yaml b/mmv1/products/backupdr/BackupVault.yaml index f5a61e8cedc9..a4239f08fb2f 100644 --- a/mmv1/products/backupdr/BackupVault.yaml +++ b/mmv1/products/backupdr/BackupVault.yaml @@ -14,7 +14,6 @@ --- name: 'BackupVault' description: Container to store and organize immutable and indelible backups. -min_version: 'beta' docs: id_format: 'projects/{{project}}/locations/{{location}}/backupVaults/{{backup_vault_id}}' base_url: 'projects/{{project}}/locations/{{location}}/backupVaults' @@ -50,7 +49,6 @@ custom_code: examples: - name: 'backup_dr_backup_vault_full' primary_resource_id: 'backup-vault-test' - min_version: 'beta' vars: backup_vault_id: 'backup-vault-test' test_env_vars: @@ -59,14 +57,12 @@ parameters: - name: 'location' type: String description: "The GCP location for the backup vault. " - min_version: 'beta' url_param_only: true required: true immutable: true - name: 'backupVaultId' type: String description: "Required. ID of the requesting object." - min_version: 'beta' url_param_only: true required: true immutable: true @@ -77,7 +73,6 @@ parameters: the restriction against conflicting retention periods. This conflict may occur when the expiration schedule defined by the associated backup plan is shorter than the minimum retention set by the backup vault. - min_version: 'beta' url_param_only: true default_value: false - name: 'force_delete' @@ -86,7 +81,6 @@ parameters: If set, the following restrictions against deletion of the backup vault instance can be overridden: * deletion of a backup vault instance containing no backups, but still containing empty datasources. * deletion of a backup vault instance that is being referenced by an active backup plan. - min_version: 'beta' url_param_only: true default_value: false deprecation_message: '`force_delete` is deprecated and will be removed in a future major release. Use `ignore_inactive_datasources` instead.' @@ -97,7 +91,6 @@ parameters: description: | If set, the following restrictions against deletion of the backup vault instance can be overridden: * deletion of a backup vault instance containing no backups, but still containing empty datasources. - min_version: 'beta' url_param_only: true default_value: false conflicts: @@ -107,102 +100,84 @@ parameters: description: | If set, the following restrictions against deletion of the backup vault instance can be overridden: * deletion of a backup vault instance that is being referenced by an active backup plan. - min_version: 'beta' url_param_only: true default_value: false - name: 'allow_missing' type: Boolean description: | Allow idempotent deletion of backup vault. The request will still succeed in case the backup vault does not exist. - min_version: 'beta' url_param_only: true default_value: false properties: - name: 'name' type: String description: 'Output only. Identifier. The resource name. ' - min_version: 'beta' output: true - name: 'description' type: String description: 'Optional. The description of the BackupVault instance (2048 characters or less). ' - min_version: 'beta' - name: 'labels' type: KeyValueLabels description: "Optional. Resource labels to represent user provided metadata. " - min_version: 'beta' - name: 'createTime' type: String description: 'Output only. The time when the instance was created. ' - min_version: 'beta' output: true - name: 'updateTime' type: String description: 'Output only. The time when the instance was updated. ' - min_version: 'beta' output: true - name: 'backupMinimumEnforcedRetentionDuration' type: String description: "Required. The default and minimum enforced retention for each backup within the backup vault. The enforced retention for each backup can be extended. " - min_version: 'beta' required: true - name: 'deletable' type: Boolean description: 'Output only. Set to true when there are no backups nested under this resource. ' - min_version: 'beta' output: true - name: 'etag' type: String description: "Optional. Server specified ETag for the backup vault resource to prevent simultaneous updates from overwiting each other. " - min_version: 'beta' output: true - name: 'state' type: String description: "Output only. The BackupVault resource instance state. \n Possible values:\n STATE_UNSPECIFIED\n CREATING\n ACTIVE\n DELETING\n ERROR" - min_version: 'beta' output: true - name: 'effectiveTime' type: String description: 'Optional. Time after which the BackupVault resource is locked. ' - min_version: 'beta' - name: 'backupCount' type: String description: 'Output only. The number of backups in this backup vault. ' - min_version: 'beta' output: true - name: 'serviceAccount' type: String description: "Output only. Service account used by the BackupVault Service for this BackupVault. The user should grant this account permissions in their workload project to enable the service to run backups and restores there. " - min_version: 'beta' output: true - name: 'totalStoredBytes' type: String description: 'Output only. Total size of the storage used by all backup resources. ' - min_version: 'beta' output: true - name: 'uid' type: String description: "Output only. Output only Immutable after resource creation until resource deletion. " - min_version: 'beta' output: true - name: 'annotations' type: KeyValueAnnotations description: "Optional. User annotations. See https://google.aip.dev/128#annotations\nStores small amounts of arbitrary data. " - min_version: 'beta' - name: 'accessRestriction' type: Enum description: | Access restriction for the backup vault. Default value is `WITHIN_ORGANIZATION` if not provided during creation. - min_version: 'beta' immutable: true default_value: "WITHIN_ORGANIZATION" enum_values: diff --git a/mmv1/products/backupdr/product.yaml b/mmv1/products/backupdr/product.yaml index ca3302aadfdd..d668e8340ef9 100644 --- a/mmv1/products/backupdr/product.yaml +++ b/mmv1/products/backupdr/product.yaml @@ -15,6 +15,8 @@ name: 'BackupDR' display_name: 'Backup and DR Service' versions: + - name: 'ga' + base_url: 'https://backupdr.googleapis.com/v1/' - name: 'beta' base_url: 'https://backupdr.googleapis.com/v1/' scopes: diff --git a/mmv1/templates/terraform/examples/backup_dr_backup_vault_full.tf.tmpl b/mmv1/templates/terraform/examples/backup_dr_backup_vault_full.tf.tmpl index d26aae4b3177..f527cf9fa2f9 100644 --- a/mmv1/templates/terraform/examples/backup_dr_backup_vault_full.tf.tmpl +++ b/mmv1/templates/terraform/examples/backup_dr_backup_vault_full.tf.tmpl @@ -1,17 +1,16 @@ resource "google_backup_dr_backup_vault" "{{$.PrimaryResourceId}}" { - provider = google-beta location = "us-central1" backup_vault_id = "{{index $.Vars "backup_vault_id"}}" description = "This is a second backup vault built by Terraform." backup_minimum_enforced_retention_duration = "100000s" - labels = { - foo = "bar1" - bar = "baz1" - } annotations = { annotations1 = "bar1" annotations2 = "baz1" } + labels = { + foo = "bar1" + bar = "baz1" + } force_update = "true" access_restriction = "WITHIN_ORGANIZATION" ignore_inactive_datasources = "true" diff --git a/mmv1/third_party/terraform/services/backupdr/resource_backup_dr_backup_vault_test.go.tmpl b/mmv1/third_party/terraform/services/backupdr/resource_backup_dr_backup_vault_test.go.tmpl index 19938ef52f76..c851a5387309 100644 --- a/mmv1/third_party/terraform/services/backupdr/resource_backup_dr_backup_vault_test.go.tmpl +++ b/mmv1/third_party/terraform/services/backupdr/resource_backup_dr_backup_vault_test.go.tmpl @@ -1,5 +1,4 @@ package backupdr_test -{{- if ne $.TargetVersionName "ga" }} import ( "github.com/hashicorp/terraform-plugin-testing/helper/resource" @@ -26,7 +25,7 @@ func TestAccBackupDRBackupVault_fullUpdate(t *testing.T) { acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, - ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), Steps: []resource.TestStep{ { Config: testAccBackupDRBackupVault_fullCreate(context), @@ -53,7 +52,6 @@ func TestAccBackupDRBackupVault_fullUpdate(t *testing.T) { func testAccBackupDRBackupVault_fullCreate(context map[string]interface{}) string { return acctest.Nprintf(` resource "google_backup_dr_backup_vault" "backup-vault-test" { - provider = google-beta location = "us-central1" backup_vault_id = "tf-test-backup-vault-test%{random_suffix}" description = "This is a backup vault built by Terraform." @@ -79,7 +77,6 @@ resource "google_backup_dr_backup_vault" "backup-vault-test" { func testAccBackupDRBackupVault_fullUpdate(context map[string]interface{}) string { return acctest.Nprintf(` resource "google_backup_dr_backup_vault" "backup-vault-test" { - provider = google-beta location = "us-central1" backup_vault_id = "tf-test-backup-vault-test%{random_suffix}" description = "This is a second backup vault built by Terraform." @@ -100,5 +97,4 @@ resource "google_backup_dr_backup_vault" "backup-vault-test" { allow_missing = "true" } `, context) -} -{{- end }} \ No newline at end of file +} \ No newline at end of file From cab73525e01fb2ada73ae78520cf58ba1d45fc93 Mon Sep 17 00:00:00 2001 From: halimsam Date: Mon, 18 Nov 2024 14:57:07 -0800 Subject: [PATCH 086/105] Add TF support for LocalSsdEncryptionMode flag (#12249) --- mmv1/third_party/terraform/go.mod | 2 +- .../services/container/node_config.go.tmpl | 12 ++++ .../resource_container_cluster_test.go.tmpl | 52 ++++++++++++++++ .../resource_container_node_pool_test.go.tmpl | 59 +++++++++++++++++++ .../docs/r/container_cluster.html.markdown | 5 ++ .../docs/r/container_node_pool.html.markdown | 5 ++ 6 files changed, 134 insertions(+), 1 deletion(-) diff --git a/mmv1/third_party/terraform/go.mod b/mmv1/third_party/terraform/go.mod index 22a553717d8b..11c5e642481a 100644 --- a/mmv1/third_party/terraform/go.mod +++ b/mmv1/third_party/terraform/go.mod @@ -118,4 +118,4 @@ require ( google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect -) +) \ No newline at end of file diff --git a/mmv1/third_party/terraform/services/container/node_config.go.tmpl b/mmv1/third_party/terraform/services/container/node_config.go.tmpl index e5340a66546a..7bb8a65cb8c5 100644 --- a/mmv1/third_party/terraform/services/container/node_config.go.tmpl +++ b/mmv1/third_party/terraform/services/container/node_config.go.tmpl @@ -806,6 +806,13 @@ func schemaNodeConfig() *schema.Schema { ForceNew: true, Description: `If enabled boot disks are configured with confidential mode.`, }, + "local_ssd_encryption_mode": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{"STANDARD_ENCRYPTION", "EPHEMERAL_KEY_ENCRYPTION"}, false), + Description: `LocalSsdEncryptionMode specified the method used for encrypting the local SSDs attached to the node.`, + }, }, }, } @@ -1160,6 +1167,10 @@ func expandNodeConfig(v interface{}) *container.NodeConfig { nc.EnableConfidentialStorage = v.(bool) } + if v,ok := nodeConfig["local_ssd_encryption_mode"]; ok { + nc.LocalSsdEncryptionMode = v.(string) + } + {{ if ne $.TargetVersionName `ga` -}} if v, ok := nodeConfig["host_maintenance_policy"]; ok { nc.HostMaintenancePolicy = expandHostMaintenancePolicy(v) @@ -1550,6 +1561,7 @@ func flattenNodeConfig(c *container.NodeConfig, v interface{}) []map[string]inte "fast_socket": flattenFastSocket(c.FastSocket), "resource_manager_tags": flattenResourceManagerTags(c.ResourceManagerTags), "enable_confidential_storage": c.EnableConfidentialStorage, + "local_ssd_encryption_mode": c.LocalSsdEncryptionMode, }) if len(c.OauthScopes) > 0 { diff --git a/mmv1/third_party/terraform/services/container/resource_container_cluster_test.go.tmpl b/mmv1/third_party/terraform/services/container/resource_container_cluster_test.go.tmpl index 67d6655fa2ba..31611588ee24 100644 --- a/mmv1/third_party/terraform/services/container/resource_container_cluster_test.go.tmpl +++ b/mmv1/third_party/terraform/services/container/resource_container_cluster_test.go.tmpl @@ -415,6 +415,32 @@ func TestAccContainerCluster_withConfidentialNodes(t *testing.T) { }) } +func TestAccContainerCluster_withLocalSsdEncryptionMode(t *testing.T) { + t.Parallel() + + clusterName := fmt.Sprintf("tf-test-cluster-%s", acctest.RandString(t, 10)) + networkName := acctest.BootstrapSharedTestNetwork(t, "gke-cluster") + subnetworkName := acctest.BootstrapSubnet(t, "gke-cluster", networkName) + npName := fmt.Sprintf("tf-test-node-pool-%s", acctest.RandString(t, 10)) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckContainerClusterDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccContainerCluster_withLocalSsdEncryptionMode(clusterName, npName, networkName, subnetworkName, "EPHEMERAL_KEY_ENCRYPTION"), + }, + { + ResourceName: "google_container_cluster.local_ssd_encryption_mode", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, + }, + }, + }) +} + func TestAccContainerCluster_withILBSubsetting(t *testing.T) { t.Parallel() @@ -6461,6 +6487,32 @@ resource "google_container_cluster" "confidential_nodes" { `, clusterName, npName, networkName, subnetworkName) } +func testAccContainerCluster_withLocalSsdEncryptionMode(clusterName, npName, networkName, subnetworkName, mode string) string { + return fmt.Sprintf(` +resource "google_container_cluster" "local_ssd_encryption_mode" { + name = "%s" + location = "us-central1-a" + release_channel { + channel = "RAPID" + } + + node_pool { + name = "%s" + initial_node_count = 1 + node_config { + machine_type = "n1-standard-2" + local_ssd_count = 1 + local_ssd_encryption_mode = "%s" + } + } + + deletion_protection = false + network = "%s" + subnetwork = "%s" +} +`, clusterName, npName, mode, networkName, subnetworkName) +} + func testAccContainerCluster_withILBSubSetting(clusterName, npName, networkName, subnetworkName string) string { return fmt.Sprintf(` resource "google_container_cluster" "confidential_nodes" { diff --git a/mmv1/third_party/terraform/services/container/resource_container_node_pool_test.go.tmpl b/mmv1/third_party/terraform/services/container/resource_container_node_pool_test.go.tmpl index 999868c611e6..fe36360a2a68 100644 --- a/mmv1/third_party/terraform/services/container/resource_container_node_pool_test.go.tmpl +++ b/mmv1/third_party/terraform/services/container/resource_container_node_pool_test.go.tmpl @@ -4157,6 +4157,65 @@ resource "google_container_node_pool" "np" { `, clusterName, networkName, subnetworkName, np) } +func TestAccContainerNodePool_withLocalSsdEncryptionMode(t *testing.T) { + t.Parallel() + + clusterName := fmt.Sprintf("tf-test-cluster-%s", acctest.RandString(t, 10)) + np := fmt.Sprintf("tf-test-cluster-nodepool-%s", acctest.RandString(t, 10)) + networkName := acctest.BootstrapSharedTestNetwork(t, "gke-cluster") + subnetworkName := acctest.BootstrapSubnet(t, "gke-cluster", networkName) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckContainerClusterDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccContainerNodePool_withLocalSsdEncryptionMode(clusterName, np, networkName, subnetworkName, "EPHEMERAL_KEY_ENCRYPTION"), + }, + { + ResourceName: "google_container_node_pool.np", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccContainerNodePool_withLocalSsdEncryptionMode(clusterName, np, networkName, subnetworkName, mode string) string { + return fmt.Sprintf(` +resource "google_container_cluster" "cluster" { + name = "%s" + location = "us-central1-a" + initial_node_count = 1 + node_config { + local_ssd_encryption_mode = "%s" + machine_type = "n1-standard-1" + local_nvme_ssd_block_config { + local_ssd_count = 1 + } + } + deletion_protection = false + network = "%s" + subnetwork = "%s" +} + +resource "google_container_node_pool" "np" { + name = "%s" + location = "us-central1-a" + cluster = google_container_cluster.cluster.name + initial_node_count = 1 + node_config { + machine_type = "n1-standard-1" + local_ssd_encryption_mode = "%s" + local_nvme_ssd_block_config { + local_ssd_count = 1 + } + } +} +`, clusterName, mode, networkName, subnetworkName, np, mode) +} + func TestAccContainerNodePool_tpuTopology(t *testing.T) { t.Parallel() t.Skip("https://github.com/hashicorp/terraform-provider-google/issues/15254#issuecomment-1646277473") diff --git a/mmv1/third_party/terraform/website/docs/r/container_cluster.html.markdown b/mmv1/third_party/terraform/website/docs/r/container_cluster.html.markdown index 229241d93a9d..368c1b2a441d 100644 --- a/mmv1/third_party/terraform/website/docs/r/container_cluster.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/container_cluster.html.markdown @@ -840,6 +840,11 @@ The `master_authorized_networks_config.cidr_blocks` block supports: * `enable_confidential_storage` - (Optional) Enabling Confidential Storage will create boot disk with confidential mode. It is disabled by default. +* `local_ssd_encryption_mode` - (Optional) Possible Local SSD encryption modes: + Accepted values are: + * `STANDARD_ENCRYPTION`: The given node will be encrypted using keys managed by Google infrastructure and the keys wll be deleted when the node is deleted. + * `EPHEMERAL_KEY_ENCRYPTION`: The given node will opt-in for using ephemeral key for encrypting Local SSDs. The Local SSDs will not be able to recover data in case of node crash. + * `ephemeral_storage_config` - (Optional, [Beta](https://terraform.io/docs/providers/google/guides/provider_versions.html)) Parameters for the ephemeral storage filesystem. If unspecified, ephemeral storage is backed by the boot disk. Structure is [documented below](#nested_ephemeral_storage_config). ```hcl diff --git a/mmv1/third_party/terraform/website/docs/r/container_node_pool.html.markdown b/mmv1/third_party/terraform/website/docs/r/container_node_pool.html.markdown index 08759e68c1a2..9a2cc5411523 100644 --- a/mmv1/third_party/terraform/website/docs/r/container_node_pool.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/container_node_pool.html.markdown @@ -270,6 +270,11 @@ cluster. * `batch_node_count` - (Optional) Number of blue nodes to drain in a batch. * `batch_soak_duration` - (Optionial) Soak time after each batch gets drained. +* `local_ssd_encryption_mode` - (Optional) Possible Local SSD encryption modes: + Accepted values are: + * `STANDARD_ENCRYPTION`: The given node will be encrypted using keys managed by Google infrastructure and the keys wll be deleted when the node is deleted. + * `EPHEMERAL_KEY_ENCRYPTION`: The given node will opt-in for using ephemeral key for encrypting Local SSDs. The Local SSDs will not be able to recover data in case of node crash. + * `node_pool_soak_duration` - (Optional) Time needed after draining the entire blue pool. After this period, the blue pool will be cleaned up. From 2f6a08d1bf846c149d63e48adb5fa2ebe52002e3 Mon Sep 17 00:00:00 2001 From: chayan kumar roy Date: Tue, 19 Nov 2024 00:17:58 +0100 Subject: [PATCH 087/105] Promote InstanceFlexibilityPolicy to GA (#12244) --- ...e_compute_region_instance_group_manager.go.tmpl | 14 +------------- ...pute_region_instance_group_manager_test.go.tmpl | 5 +---- ...ute_region_instance_group_manager.html.markdown | 2 +- 3 files changed, 3 insertions(+), 18 deletions(-) diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_group_manager.go.tmpl b/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_group_manager.go.tmpl index 0afcf93719a0..f6db9cf7f694 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_group_manager.go.tmpl +++ b/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_group_manager.go.tmpl @@ -94,7 +94,6 @@ func ResourceComputeRegionInstanceGroupManager() *schema.Resource { }, }, - {{- if ne $.TargetVersionName "ga" }} "instance_flexibility_policy": { Type: schema.TypeList, Optional: true, @@ -134,7 +133,6 @@ func ResourceComputeRegionInstanceGroupManager() *schema.Resource { }, }, }, - {{- end }} "name": { Type: schema.TypeString, @@ -672,9 +670,7 @@ func resourceComputeRegionInstanceGroupManagerCreate(d *schema.ResourceData, met TargetSuspendedSize: int64(d.Get("target_suspended_size").(int)), TargetStoppedSize: int64(d.Get("target_stopped_size").(int)), {{- end }} - {{- if ne $.TargetVersionName "ga" }} InstanceFlexibilityPolicy: expandInstanceFlexibilityPolicy(d), - {{- end }} UpdatePolicy: expandRegionUpdatePolicy(d.Get("update_policy").([]interface{})), InstanceLifecyclePolicy: expandInstanceLifecyclePolicy(d.Get("instance_lifecycle_policy").([]interface{})), AllInstancesConfig: expandAllInstancesConfig(nil, d.Get("all_instances_config").([]interface{})), @@ -878,11 +874,9 @@ func resourceComputeRegionInstanceGroupManagerRead(d *schema.ResourceData, meta return fmt.Errorf("Error setting target_stopped_size: %s", err) } {{- end }} - {{- if ne $.TargetVersionName "ga" }} if err := d.Set("instance_flexibility_policy", flattenInstanceFlexibilityPolicy(manager.InstanceFlexibilityPolicy)); err != nil { return err } - {{- end }} if err := d.Set("update_policy", flattenRegionUpdatePolicy(manager.UpdatePolicy)); err != nil { return fmt.Errorf("Error setting update_policy in state: %s", err.Error()) } @@ -956,7 +950,6 @@ func resourceComputeRegionInstanceGroupManagerUpdate(d *schema.ResourceData, met change = true } - {{- if ne $.TargetVersionName "ga" }} var targetSizePatchUpdate bool if d.HasChange("instance_flexibility_policy") { updatedManager.InstanceFlexibilityPolicy = expandInstanceFlexibilityPolicy(d) @@ -969,7 +962,6 @@ func resourceComputeRegionInstanceGroupManagerUpdate(d *schema.ResourceData, met targetSizePatchUpdate = true } } - {{- end }} if d.HasChange("distribution_policy_target_shape") { updatedManager.DistributionPolicy = expandDistributionPolicyForUpdate(d) @@ -1060,7 +1052,7 @@ func resourceComputeRegionInstanceGroupManagerUpdate(d *schema.ResourceData, met } // target size should use resize - if d.HasChange("target_size") {{- if ne $.TargetVersionName "ga" }} && !targetSizePatchUpdate {{- end}} { + if d.HasChange("target_size") && !targetSizePatchUpdate { d.Partial(true) targetSize := int64(d.Get("target_size").(int)) op, err := config.NewComputeClient(userAgent).RegionInstanceGroupManagers.Resize( @@ -1210,7 +1202,6 @@ func flattenRegionUpdatePolicy(updatePolicy *compute.InstanceGroupManagerUpdateP return results } -{{- if ne $.TargetVersionName "ga" }} func expandInstanceFlexibilityPolicy(d *schema.ResourceData) *compute.InstanceGroupManagerInstanceFlexibilityPolicy { instanceFlexibilityPolicy := &compute.InstanceGroupManagerInstanceFlexibilityPolicy{} oldFlexibilityPolicy, newFlexibilityPolicy := d.GetChange("instance_flexibility_policy") @@ -1244,7 +1235,6 @@ func expandInstanceSelections(instanceSelections []any) map[string]compute.Insta } return instanceSelectionsMap } -{{- end }} func expandDistributionPolicyForUpdate(d *schema.ResourceData) *compute.DistributionPolicy { dpts := d.Get("distribution_policy_target_shape").(string) @@ -1281,7 +1271,6 @@ func expandDistributionPolicyForCreate(d *schema.ResourceData) *compute.Distribu return distributionPolicy } -{{- if ne $.TargetVersionName "ga" }} func flattenInstanceFlexibilityPolicy(instanceFlexibilityPolicy *compute.InstanceGroupManagerInstanceFlexibilityPolicy) []map[string]any { flattenedInstanceFlexibilityPolicy := []map[string]any{} if instanceFlexibilityPolicy != nil { @@ -1303,7 +1292,6 @@ func flattenInstanceSelections(instanceSelections map[string]compute.InstanceGro } return instanceSelectionsMap } -{{- end }} func flattenDistributionPolicy(distributionPolicy *compute.DistributionPolicy) []string { zones := make([]string, 0) diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_group_manager_test.go.tmpl b/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_group_manager_test.go.tmpl index bdf636e5a69e..9f6738d1790e 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_group_manager_test.go.tmpl +++ b/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_group_manager_test.go.tmpl @@ -431,7 +431,6 @@ func TestAccRegionInstanceGroupManager_stoppedSuspendedTargetSize(t *testing.T) } {{- end }} -{{- if ne $.TargetVersionName "ga" }} func TestAccRegionInstanceGroupManager_instanceFlexibilityPolicy(t *testing.T) { t.Parallel() @@ -474,7 +473,7 @@ func TestAccRegionInstanceGroupManager_instanceFlexibilityPolicy(t *testing.T) { }, }) } -{{- end }} + func TestAccRegionInstanceGroupManager_APISideListRecordering(t *testing.T) { t.Parallel() @@ -1969,7 +1968,6 @@ resource "google_compute_region_instance_group_manager" "sr-igm" { } {{- end }} -{{- if ne $.TargetVersionName "ga" }} func testAccRegionInstanceGroupManager_instanceFlexibilityPolicy(network, template, igm string) string { return fmt.Sprintf(` data "google_compute_image" "my_image" { @@ -2138,7 +2136,6 @@ resource "google_compute_region_instance_group_manager" "igm-basic" { } `, network, template, igm) } -{{- end }} {{- if ne $.TargetVersionName "ga" }} func testAccRegionInstanceGroupManager_resourceManagerTags(template_name, tag_name, igm_name, project_id string) string { diff --git a/mmv1/third_party/terraform/website/docs/r/compute_region_instance_group_manager.html.markdown b/mmv1/third_party/terraform/website/docs/r/compute_region_instance_group_manager.html.markdown index 465bfb373898..9becef0feddf 100644 --- a/mmv1/third_party/terraform/website/docs/r/compute_region_instance_group_manager.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/compute_region_instance_group_manager.html.markdown @@ -205,7 +205,7 @@ group. You can specify one or more values. For more information, see the [offici * `params` - (Optional [Beta](https://terraform.io/docs/providers/google/guides/provider_versions.html)) Input only additional params for instance group manager creation. Structure is [documented below](#nested_params). For more information, see [API](https://cloud.google.com/compute/docs/reference/rest/beta/instanceGroupManagers/insert). -* `instance_flexibility_policy` - (Optional [Beta](https://terraform.io/docs/providers/google/guides/provider_versions.html)) The flexibility policy for managed instance group. Instance flexibility allows managed instance group to create VMs from multiple types of machines. Instance flexibility configuration on managed instance group overrides instance template configuration. Structure is [documented below](#nested_instance_flexibility_policy). +* `instance_flexibility_policy` - (Optional) The flexibility policy for managed instance group. Instance flexibility allows managed instance group to create VMs from multiple types of machines. Instance flexibility configuration on managed instance group overrides instance template configuration. Structure is [documented below](#nested_instance_flexibility_policy). - - - The `standby_policy` block supports: From 5be6d053f6eecef46df4739bb57660321f7eb0aa Mon Sep 17 00:00:00 2001 From: Tomoya <5311731+entertvl@users.noreply.github.com> Date: Tue, 19 Nov 2024 09:20:00 +0900 Subject: [PATCH 088/105] fix(apigee): Error of update in google_apigee_developer (#12347) --- mmv1/products/apigee/Developer.yaml | 2 +- .../resource_apigee_developer_update_test.go | 123 ++++++++++++++++++ 2 files changed, 124 insertions(+), 1 deletion(-) create mode 100644 mmv1/third_party/terraform/services/apigee/resource_apigee_developer_update_test.go diff --git a/mmv1/products/apigee/Developer.yaml b/mmv1/products/apigee/Developer.yaml index 858a7f9cf884..e26a5ee6593e 100644 --- a/mmv1/products/apigee/Developer.yaml +++ b/mmv1/products/apigee/Developer.yaml @@ -24,7 +24,7 @@ base_url: "developers" self_link: "{{org_id}}/developers/{{email}}" create_url: "{{org_id}}/developers" delete_url: "{{org_id}}/developers/{{email}}" -update_mask: true +update_mask: false immutable: false import_format: - "{{org_id}}/developers/{{email}}" diff --git a/mmv1/third_party/terraform/services/apigee/resource_apigee_developer_update_test.go b/mmv1/third_party/terraform/services/apigee/resource_apigee_developer_update_test.go new file mode 100644 index 000000000000..0f5c19918bdf --- /dev/null +++ b/mmv1/third_party/terraform/services/apigee/resource_apigee_developer_update_test.go @@ -0,0 +1,123 @@ +package apigee_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + + "github.com/hashicorp/terraform-provider-google/google/acctest" + "github.com/hashicorp/terraform-provider-google/google/envvar" +) + +func TestAccApigeeDeveloper_apigeeDeveloperUpdateTest(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "billing_account": envvar.GetTestBillingAccountFromEnv(t), + "org_id": envvar.GetTestOrgFromEnv(t), + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckApigeeDeveloperDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccApigeeDeveloper_apigeeDeveloperBasicTestExample(context), + }, + { + ResourceName: "google_apigee_developer.apigee_developer", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"org_id"}, + }, + { + Config: testAccApigeeDeveloper_apigeeDeveloperUpdateTest(context), + }, + { + ResourceName: "google_apigee_developer.apigee_developer", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"org_id"}, + }, + }, + }) +} + +func testAccApigeeDeveloper_apigeeDeveloperUpdateTest(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_project" "project" { + project_id = "tf-test%{random_suffix}" + name = "tf-test%{random_suffix}" + org_id = "%{org_id}" + billing_account = "%{billing_account}" + deletion_policy = "DELETE" +} + +resource "google_project_service" "apigee" { + project = google_project.project.project_id + service = "apigee.googleapis.com" +} + +resource "google_project_service" "compute" { + project = google_project.project.project_id + service = "compute.googleapis.com" +} + +resource "google_project_service" "servicenetworking" { + project = google_project.project.project_id + service = "servicenetworking.googleapis.com" +} + +resource "google_compute_network" "apigee_network" { + name = "apigee-network" + project = google_project.project.project_id + depends_on = [google_project_service.compute] +} + +resource "google_compute_global_address" "apigee_range" { + name = "apigee-range" + purpose = "VPC_PEERING" + address_type = "INTERNAL" + prefix_length = 16 + network = google_compute_network.apigee_network.id + project = google_project.project.project_id +} + +resource "google_service_networking_connection" "apigee_vpc_connection" { + network = google_compute_network.apigee_network.id + service = "servicenetworking.googleapis.com" + reserved_peering_ranges = [google_compute_global_address.apigee_range.name] + depends_on = [google_project_service.servicenetworking] +} + +resource "google_apigee_organization" "apigee_org" { + analytics_region = "us-central1" + project_id = google_project.project.project_id + authorized_network = google_compute_network.apigee_network.id + depends_on = [ + google_service_networking_connection.apigee_vpc_connection, + google_project_service.apigee, + ] +} + +resource "google_apigee_instance" "apigee_instance" { + name = "tf-test%{random_suffix}" + location = "us-central1" + org_id = google_apigee_organization.apigee_org.id + peering_cidr_range = "SLASH_22" +} + +resource "google_apigee_developer" "apigee_developer" { + email = "tf-test%{random_suffix}@acme.com" + first_name = "Yamada" + last_name = "Taro" + user_name = "yamada.taro" + org_id = google_apigee_organization.apigee_org.id + depends_on = [ + google_apigee_instance.apigee_instance + ] +} +`, context) +} From 3fa84e2702fdf07958b347e07726288f50afed84 Mon Sep 17 00:00:00 2001 From: Shuya Ma <87669292+shuyama1@users.noreply.github.com> Date: Tue, 19 Nov 2024 08:54:33 -0800 Subject: [PATCH 089/105] update vacation for shuyama1 (#12349) --- .ci/magician/github/membership_data.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.ci/magician/github/membership_data.go b/.ci/magician/github/membership_data.go index 55735dc86b79..5b0bba634f60 100644 --- a/.ci/magician/github/membership_data.go +++ b/.ci/magician/github/membership_data.go @@ -116,5 +116,10 @@ var ( startDate: newDate(2024, 11, 1, pdtLoc), endDate: newDate(2024, 11, 11, pdtLoc), }, + { + id: "shuyama1", + startDate: newDate(2024, 11, 26, pdtLoc), + endDate: newDate(2024, 12, 4, pdtLoc), + }, } ) From 77315f8f88322e7bc019cc42437b56124448329c Mon Sep 17 00:00:00 2001 From: tulika-aakriti Date: Tue, 19 Nov 2024 22:33:46 +0530 Subject: [PATCH 090/105] Add deletion_protection field in cloudvmcluster resource (#12297) --- .../products/oracledatabase/CloudVmCluster.yaml | 17 +++++++++++++++++ ...oracledatabase_cloud_vmcluster_basic.tf.tmpl | 2 ++ .../oracledatabase_cloud_vmcluster_full.tf.tmpl | 2 ++ .../oracledatabase_cloud_vmcluster.go.tmpl | 3 +++ 4 files changed, 24 insertions(+) create mode 100644 mmv1/templates/terraform/pre_delete/oracledatabase_cloud_vmcluster.go.tmpl diff --git a/mmv1/products/oracledatabase/CloudVmCluster.yaml b/mmv1/products/oracledatabase/CloudVmCluster.yaml index ddc28f039c1e..e61c3e55295c 100644 --- a/mmv1/products/oracledatabase/CloudVmCluster.yaml +++ b/mmv1/products/oracledatabase/CloudVmCluster.yaml @@ -49,6 +49,8 @@ async: error: path: 'error' message: 'message' +custom_code: + pre_delete: 'templates/terraform/pre_delete/oracledatabase_cloud_vmcluster.go.tmpl' examples: - name: 'oracledatabase_cloud_vmcluster_basic' primary_resource_id: 'my_vmcluster' @@ -56,7 +58,11 @@ examples: project: 'my-project' cloud_vm_cluster_id: 'my-instance' cloud_exadata_infrastructure_id: 'my-exadata' + deletion_protection: 'true' + ignore_read_extra: + - 'deletion_protection' test_vars_overrides: + 'deletion_protection': 'false' 'project': '"oci-terraform-testing"' 'cloud_vm_cluster_id': '"ofake-vmcluster-basic"' 'cloud_exadata_infrastructure_id': '"ofake-exadata-for-vm-basic"' @@ -66,10 +72,21 @@ examples: project: 'my-project' cloud_vm_cluster_id: 'my-instance' cloud_exadata_infrastructure_id: 'my-exadata' + deletion_protection: 'true' + ignore_read_extra: + - 'deletion_protection' test_vars_overrides: + 'deletion_protection': 'false' 'project': '"oci-terraform-testing"' 'cloud_vm_cluster_id': '"ofake-vmcluster-full"' 'cloud_exadata_infrastructure_id': '"ofake-exadata-for-vm-full"' +virtual_fields: + - name: 'deletion_protection' + type: Boolean + default_value: true + description: 'Whether or not to allow Terraform to destroy the instance. + Unless this field is set to false in Terraform state, a terraform destroy + or terraform apply that would delete the instance will fail.' parameters: - name: 'location' type: String diff --git a/mmv1/templates/terraform/examples/oracledatabase_cloud_vmcluster_basic.tf.tmpl b/mmv1/templates/terraform/examples/oracledatabase_cloud_vmcluster_basic.tf.tmpl index bef49b1943e8..7ac2edfa9301 100644 --- a/mmv1/templates/terraform/examples/oracledatabase_cloud_vmcluster_basic.tf.tmpl +++ b/mmv1/templates/terraform/examples/oracledatabase_cloud_vmcluster_basic.tf.tmpl @@ -14,6 +14,8 @@ resource "google_oracle_database_cloud_vm_cluster" "{{$.PrimaryResourceId}}"{ gi_version = "19.0.0.0" hostname_prefix = "hostname1" } + + deletion_protection = "{{index $.Vars "deletion_protection"}}" } resource "google_oracle_database_cloud_exadata_infrastructure" "cloudExadataInfrastructures"{ diff --git a/mmv1/templates/terraform/examples/oracledatabase_cloud_vmcluster_full.tf.tmpl b/mmv1/templates/terraform/examples/oracledatabase_cloud_vmcluster_full.tf.tmpl index e33babc91b9d..3cfe225f6454 100644 --- a/mmv1/templates/terraform/examples/oracledatabase_cloud_vmcluster_full.tf.tmpl +++ b/mmv1/templates/terraform/examples/oracledatabase_cloud_vmcluster_full.tf.tmpl @@ -35,6 +35,8 @@ resource "google_oracle_database_cloud_vm_cluster" "{{$.PrimaryResourceId}}"{ } memory_size_gb = 60 } + + deletion_protection = "{{index $.Vars "deletion_protection"}}" } resource "google_oracle_database_cloud_exadata_infrastructure" "cloudExadataInfrastructures"{ diff --git a/mmv1/templates/terraform/pre_delete/oracledatabase_cloud_vmcluster.go.tmpl b/mmv1/templates/terraform/pre_delete/oracledatabase_cloud_vmcluster.go.tmpl new file mode 100644 index 000000000000..3e00631873ad --- /dev/null +++ b/mmv1/templates/terraform/pre_delete/oracledatabase_cloud_vmcluster.go.tmpl @@ -0,0 +1,3 @@ +if d.Get("deletion_protection").(bool) { + return fmt.Errorf("cannot destroy google_oracle_database_cloud_vm_cluster resource with id : %q without setting deletion_protection=false and running `terraform apply`", d.Id()) +} From 821357e87c510c090aabc8502fae4190152a5d99 Mon Sep 17 00:00:00 2001 From: skysarthak Date: Tue, 19 Nov 2024 10:03:29 -0800 Subject: [PATCH 091/105] =?UTF-8?q?Fix=20edition=20downgrade=20failure=20f?= =?UTF-8?q?or=20an=20ENTERPRISE=5FPLUS=20instance=20with=20da=E2=80=A6=20(?= =?UTF-8?q?#12289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Sarthak Tandon --- .../services/sql/resource_sql_database_instance.go.tmpl | 1 + .../services/sql/resource_sql_database_instance_test.go | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/mmv1/third_party/terraform/services/sql/resource_sql_database_instance.go.tmpl b/mmv1/third_party/terraform/services/sql/resource_sql_database_instance.go.tmpl index 1ffe1aed81d5..fee345035643 100644 --- a/mmv1/third_party/terraform/services/sql/resource_sql_database_instance.go.tmpl +++ b/mmv1/third_party/terraform/services/sql/resource_sql_database_instance.go.tmpl @@ -2024,6 +2024,7 @@ func resourceSqlDatabaseInstanceUpdate(d *schema.ResourceData, meta interface{}) instance.Settings.SettingsVersion = int64(_settings["version"].(int)) // Collation cannot be included in the update request instance.Settings.Collation = "" + instance.Settings.DataCacheConfig = expandDataCacheConfig(_settings["data_cache_config"].([]interface{})) // Lock on the master_instance_name just in case updating any replica // settings causes operations on the master. diff --git a/mmv1/third_party/terraform/services/sql/resource_sql_database_instance_test.go b/mmv1/third_party/terraform/services/sql/resource_sql_database_instance_test.go index b1abff5d5f7f..98e1614f4929 100644 --- a/mmv1/third_party/terraform/services/sql/resource_sql_database_instance_test.go +++ b/mmv1/third_party/terraform/services/sql/resource_sql_database_instance_test.go @@ -1879,7 +1879,6 @@ func TestAccSqlDatabaseInstance_Postgres_Edition_Upgrade(t *testing.T) { } func TestAccSqlDatabaseInstance_Edition_Downgrade(t *testing.T) { - t.Skip("https://github.com/hashicorp/terraform-provider-google/issues/20010") t.Parallel() enterprisePlusTier := "db-perf-optimized-N-2" enterpriseTier := "db-custom-2-13312" From d7777055cb7618648725abd16d3b05e5c138fc56 Mon Sep 17 00:00:00 2001 From: Ahzaz Hingora <5833893+ahzaz@users.noreply.github.com> Date: Wed, 20 Nov 2024 01:19:20 +0530 Subject: [PATCH 092/105] Add ProvisioningModelMix to InstanceFlexibilityPolicy for Dataproc cluster (#12327) --- .../dataproc/resource_dataproc_cluster.go | 63 ++++++++++++++++- .../resource_dataproc_cluster_test.go.tmpl | 67 +++++++++++++++++++ 2 files changed, 128 insertions(+), 2 deletions(-) diff --git a/mmv1/third_party/terraform/services/dataproc/resource_dataproc_cluster.go b/mmv1/third_party/terraform/services/dataproc/resource_dataproc_cluster.go index e6b7c6e27d1a..288b722f0a35 100644 --- a/mmv1/third_party/terraform/services/dataproc/resource_dataproc_cluster.go +++ b/mmv1/third_party/terraform/services/dataproc/resource_dataproc_cluster.go @@ -1183,6 +1183,7 @@ func ResourceDataprocCluster() *schema.Resource { ForceNew: true, AtLeastOneOf: []string{ "cluster_config.0.preemptible_worker_config.0.instance_flexibility_policy.0.instance_selection_list", + "cluster_config.0.preemptible_worker_config.0.instance_flexibility_policy.0.provisioning_model_mix", }, Description: `List of instance selection options that the group will use when creating new VMs.`, Elem: &schema.Resource{ @@ -1227,6 +1228,36 @@ func ResourceDataprocCluster() *schema.Resource { }, }, }, + "provisioning_model_mix": { + Type: schema.TypeList, + Optional: true, + ForceNew: true, + AtLeastOneOf: []string{ + "cluster_config.0.preemptible_worker_config.0.instance_flexibility_policy.0.instance_selection_list", + "cluster_config.0.preemptible_worker_config.0.instance_flexibility_policy.0.provisioning_model_mix", + }, + MaxItems: 1, + Description: `Defines how Dataproc should create VMs with a mixture of provisioning models.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "standard_capacity_base": { + Type: schema.TypeInt, + Optional: true, + ForceNew: true, + Description: `The base capacity that will always use Standard VMs to avoid risk of more preemption than the minimum capacity you need.`, + ValidateFunc: validation.IntAtLeast(0), + }, + + "standard_capacity_percent_above_base": { + Type: schema.TypeInt, + Optional: true, + ForceNew: true, + Description: `The percentage of target capacity that should use Standard VM. The remaining percentage will use Spot VMs.`, + ValidateFunc: validation.IntBetween(0, 100), + }, + }, + }, + }, }, }, }, @@ -2413,6 +2444,9 @@ func expandPreemptibleInstanceGroupConfig(cfg map[string]interface{}) *dataproc. if v, ok := flexibilityPolicy["instance_selection_list"]; ok { icg.InstanceFlexibilityPolicy.InstanceSelectionList = expandInstanceSelectionList(v) } + if v, ok := flexibilityPolicy["provisioning_model_mix"]; ok { + icg.InstanceFlexibilityPolicy.ProvisioningModelMix = expandProvisioningModelMix(v) + } } } @@ -2444,6 +2478,18 @@ func expandInstanceSelectionList(v interface{}) []*dataproc.InstanceSelection { return instanceSelections } +func expandProvisioningModelMix(v interface{}) *dataproc.ProvisioningModelMix { + pmm := v.([]interface{}) + if len(pmm) > 0 { + provisioningModelMix := pmm[0].(map[string]interface{}) + return &dataproc.ProvisioningModelMix{ + StandardCapacityBase: int64(provisioningModelMix["standard_capacity_base"].(int)), + StandardCapacityPercentAboveBase: int64(provisioningModelMix["standard_capacity_percent_above_base"].(int)), + } + } + return nil +} + func expandMasterInstanceGroupConfig(cfg map[string]interface{}) *dataproc.InstanceGroupConfig { icg := &dataproc.InstanceGroupConfig{} @@ -3184,8 +3230,13 @@ func flattenPreemptibleInstanceGroupConfig(d *schema.ResourceData, icg *dataproc disk["local_ssd_interface"] = icg.DiskConfig.LocalSsdInterface } if icg.InstanceFlexibilityPolicy != nil { - instanceFlexibilityPolicy["instance_selection_list"] = flattenInstanceSelectionList(icg.InstanceFlexibilityPolicy.InstanceSelectionList) - instanceFlexibilityPolicy["instance_selection_results"] = flattenInstanceSelectionResults(icg.InstanceFlexibilityPolicy.InstanceSelectionResults) + if icg.InstanceFlexibilityPolicy.InstanceSelectionList != nil { + instanceFlexibilityPolicy["instance_selection_list"] = flattenInstanceSelectionList(icg.InstanceFlexibilityPolicy.InstanceSelectionList) + instanceFlexibilityPolicy["instance_selection_results"] = flattenInstanceSelectionResults(icg.InstanceFlexibilityPolicy.InstanceSelectionResults) + } + if icg.InstanceFlexibilityPolicy.ProvisioningModelMix != nil { + instanceFlexibilityPolicy["provisioning_model_mix"] = flattenProvisioningModelMix(icg.InstanceFlexibilityPolicy.ProvisioningModelMix) + } } } @@ -3222,6 +3273,14 @@ func flattenInstanceSelectionResults(isr []*dataproc.InstanceSelectionResult) [] } +func flattenProvisioningModelMix(pmm *dataproc.ProvisioningModelMix) []map[string]interface{} { + provisioningModelMix := map[string]interface{}{} + provisioningModelMix["standard_capacity_base"] = pmm.StandardCapacityBase + provisioningModelMix["standard_capacity_percent_above_base"] = pmm.StandardCapacityPercentAboveBase + + return []map[string]interface{}{provisioningModelMix} +} + func flattenMasterInstanceGroupConfig(d *schema.ResourceData, icg *dataproc.InstanceGroupConfig) []map[string]interface{} { disk := map[string]interface{}{} data := map[string]interface{}{} diff --git a/mmv1/third_party/terraform/services/dataproc/resource_dataproc_cluster_test.go.tmpl b/mmv1/third_party/terraform/services/dataproc/resource_dataproc_cluster_test.go.tmpl index 040f08ac4402..2fe9b046a8ba 100644 --- a/mmv1/third_party/terraform/services/dataproc/resource_dataproc_cluster_test.go.tmpl +++ b/mmv1/third_party/terraform/services/dataproc/resource_dataproc_cluster_test.go.tmpl @@ -534,6 +534,29 @@ func TestAccDataprocCluster_spotWithInstanceFlexibilityPolicy(t *testing.T) { }) } +func TestAccDataprocCluster_spotOnDemandMixing(t *testing.T) { + t.Parallel() + + rnd := acctest.RandString(t, 10) + var cluster dataproc.Cluster + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckDataprocClusterDestroy(t), + Steps: []resource.TestStep{ + { + Config: testAccDataprocCluster_spotOnDemandMixing(rnd), + Check: resource.ComposeTestCheckFunc( + testAccCheckDataprocClusterExists(t, "google_dataproc_cluster.spot_mixing", &cluster), + resource.TestCheckResourceAttr("google_dataproc_cluster.spot_mixing", "cluster_config.0.preemptible_worker_config.0.preemptibility", "SPOT"), + resource.TestCheckResourceAttr("google_dataproc_cluster.spot_mixing", "cluster_config.0.preemptible_worker_config.0.instance_flexibility_policy.0.provisioning_model_mix.0.standard_capacity_base", "1"), + resource.TestCheckResourceAttr("google_dataproc_cluster.spot_mixing", "cluster_config.0.preemptible_worker_config.0.instance_flexibility_policy.0.provisioning_model_mix.0.standard_capacity_percent_above_base", "50"), + ), + }, + }, + }) +} + func TestAccDataprocCluster_spotWithAuxiliaryNodeGroups(t *testing.T) { t.Parallel() @@ -1955,6 +1978,50 @@ resource "google_dataproc_cluster" "spot_with_instance_flexibility_policy" { `, rnd) } +func testAccDataprocCluster_spotOnDemandMixing(rnd string) string { + return fmt.Sprintf(` +resource "google_dataproc_cluster" "spot_mixing" { + name = "tf-test-dproc-%s" + region = "us-central1" + + cluster_config { + gce_cluster_config { + internal_ip_only = false + } + master_config { + num_instances = "1" + machine_type = "e2-medium" + disk_config { + boot_disk_size_gb = 35 + } + } + + worker_config { + num_instances = "2" + machine_type = "e2-medium" + disk_config { + boot_disk_size_gb = 35 + } + } + + preemptible_worker_config { + num_instances = "3" + preemptibility = "SPOT" + disk_config { + boot_disk_size_gb = 35 + } + instance_flexibility_policy { + provisioning_model_mix { + standard_capacity_base = 1 + standard_capacity_percent_above_base = 50 + } + } + } + } +} + `, rnd) +} + func testAccDataprocCluster_withAuxiliaryNodeGroups(rnd string) string { return fmt.Sprintf(` resource "google_dataproc_cluster" "with_auxiliary_node_groups" { From c5cee4e16c45a09dd07e2c046b7a5a4ec21f68d7 Mon Sep 17 00:00:00 2001 From: Eric Gribkoff Date: Tue, 19 Nov 2024 13:42:17 -0800 Subject: [PATCH 093/105] Use project name for PSC allowlist (#12303) --- .../examples/vertex_ai_index_endpoint_with_psc.tf.tmpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mmv1/templates/terraform/examples/vertex_ai_index_endpoint_with_psc.tf.tmpl b/mmv1/templates/terraform/examples/vertex_ai_index_endpoint_with_psc.tf.tmpl index 792a18f9e750..37e8995870bf 100644 --- a/mmv1/templates/terraform/examples/vertex_ai_index_endpoint_with_psc.tf.tmpl +++ b/mmv1/templates/terraform/examples/vertex_ai_index_endpoint_with_psc.tf.tmpl @@ -9,7 +9,7 @@ resource "google_vertex_ai_index_endpoint" "{{$.PrimaryResourceId}}" { private_service_connect_config { enable_private_service_connect = true project_allowlist = [ - data.google_project.project.number, + data.google_project.project.name, ] } } From eb456f7c48191e6c2fbe393a5b7d7fccb1e92ecb Mon Sep 17 00:00:00 2001 From: Brandon Ha <107650670+brandonmichigangithub@users.noreply.github.com> Date: Tue, 19 Nov 2024 14:09:41 -0800 Subject: [PATCH 094/105] Remove unused test case (#12331) --- .../data_source_artifact_registry_docker_image_test.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/mmv1/third_party/terraform/services/artifactregistry/data_source_artifact_registry_docker_image_test.go b/mmv1/third_party/terraform/services/artifactregistry/data_source_artifact_registry_docker_image_test.go index f63f591f7598..9d11c3ed5e36 100644 --- a/mmv1/third_party/terraform/services/artifactregistry/data_source_artifact_registry_docker_image_test.go +++ b/mmv1/third_party/terraform/services/artifactregistry/data_source_artifact_registry_docker_image_test.go @@ -28,9 +28,6 @@ func TestAccDataSourceArtifactRegistryDockerImage(t *testing.T) { resource.TestCheckResourceAttrSet(resourceName+"Tag", "image_size_bytes"), validateTimeStamps(resourceName+"Tag"), - resource.TestCheckResourceAttrSet(resourceName+"Digest", "image_size_bytes"), - validateTimeStamps(resourceName+"Digest"), - // url safe docker name using a tag checkTaggedDataSources(resourceName+"UrlTag", "latest"), From 4e19bc58baf784584802d222f5b67d242bb7ecd7 Mon Sep 17 00:00:00 2001 From: nomi3 <42667020+nomi3@users.noreply.github.com> Date: Wed, 20 Nov 2024 07:11:13 +0900 Subject: [PATCH 095/105] =?UTF-8?q?Fix=20typo=20in=20documentation:=20?= =?UTF-8?q?=E2=80=9CBackendServiceor=E2=80=9D=20to=20=E2=80=9CBackendServi?= =?UTF-8?q?ce=20or=E2=80=9D=20(#12337)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mmv1/products/compute/UrlMap.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mmv1/products/compute/UrlMap.yaml b/mmv1/products/compute/UrlMap.yaml index faf41b8a315a..220e44837ec9 100644 --- a/mmv1/products/compute/UrlMap.yaml +++ b/mmv1/products/compute/UrlMap.yaml @@ -320,7 +320,7 @@ properties: - name: 'defaultCustomErrorResponsePolicy' type: NestedObject description: | - defaultCustomErrorResponsePolicy specifies how the Load Balancer returns error responses when BackendServiceor BackendBucket responds with an error. + defaultCustomErrorResponsePolicy specifies how the Load Balancer returns error responses when BackendService or BackendBucket responds with an error. This policy takes effect at the PathMatcher level and applies only when no policy has been defined for the error code at lower levels like RouteRule and PathRule within this PathMatcher. If an error code does not have a policy defined in defaultCustomErrorResponsePolicy, then a policy defined for the error code in UrlMap.defaultCustomErrorResponsePolicy takes effect. @@ -487,7 +487,7 @@ properties: - name: 'customErrorResponsePolicy' type: NestedObject description: | - customErrorResponsePolicy specifies how the Load Balancer returns error responses when BackendServiceor BackendBucket responds with an error. + customErrorResponsePolicy specifies how the Load Balancer returns error responses when BackendService or BackendBucket responds with an error. If a policy for an error code is not configured for the PathRule, a policy for the error code configured in pathMatcher.defaultCustomErrorResponsePolicy is applied. If one is not specified in pathMatcher.defaultCustomErrorResponsePolicy, the policy configured in UrlMap.defaultCustomErrorResponsePolicy takes effect. For example, consider a UrlMap with the following configuration: UrlMap.defaultCustomErrorResponsePolicy are configured with policies for 5xx and 4xx errors @@ -2102,7 +2102,7 @@ properties: - name: 'defaultCustomErrorResponsePolicy' type: NestedObject description: | - defaultCustomErrorResponsePolicy specifies how the Load Balancer returns error responses when BackendServiceor BackendBucket responds with an error. + defaultCustomErrorResponsePolicy specifies how the Load Balancer returns error responses when BackendService or BackendBucket responds with an error. This policy takes effect at the PathMatcher level and applies only when no policy has been defined for the error code at lower levels like RouteRule and PathRule within this PathMatcher. If an error code does not have a policy defined in defaultCustomErrorResponsePolicy, then a policy defined for the error code in UrlMap.defaultCustomErrorResponsePolicy takes effect. From b311e8aa22c2cf401fc54c12097734c727dc31c1 Mon Sep 17 00:00:00 2001 From: Scott Suarez Date: Tue, 19 Nov 2024 16:01:54 -0800 Subject: [PATCH 096/105] add server-side id for a few resources (#12351) --- mmv1/products/compute/GlobalForwardingRule.yaml | 6 ++++++ mmv1/products/compute/InstanceGroupManager.yaml | 6 ++++++ mmv1/products/compute/RegionHealthCheck.yaml | 6 ++++++ mmv1/products/compute/RegionInstanceGroupManager.yaml | 6 ++++++ mmv1/products/compute/RegionNetworkEndpoint.yaml | 6 ++++++ mmv1/products/compute/Subnetwork.yaml | 6 ++++++ ...source_compute_global_forwarding_rule_test.go.tmpl | 3 ++- .../resource_compute_instance_group_manager.go.tmpl | 11 +++++++++++ ...source_compute_instance_group_manager_test.go.tmpl | 3 +++ .../resource_compute_region_health_check_test.go.tmpl | 4 ++++ ...urce_compute_region_instance_group_manager.go.tmpl | 9 +++++++++ ...compute_region_instance_group_manager_test.go.tmpl | 3 +++ ...ource_compute_region_network_endpoint_test.go.tmpl | 4 ++++ .../compute/resource_compute_subnetwork_test.go.tmpl | 3 ++- 14 files changed, 74 insertions(+), 2 deletions(-) diff --git a/mmv1/products/compute/GlobalForwardingRule.yaml b/mmv1/products/compute/GlobalForwardingRule.yaml index 760bc472528f..8cc0bffb71c3 100644 --- a/mmv1/products/compute/GlobalForwardingRule.yaml +++ b/mmv1/products/compute/GlobalForwardingRule.yaml @@ -215,6 +215,12 @@ properties: description: | An optional description of this resource. Provide this property when you create the resource. + - name: 'forwardingRuleId' + type: Integer + description: | + The unique identifier number for the resource. This identifier is defined by the server. + api_name: id + output: true # This is a multi-resource resource reference (Address, GlobalAddress) - name: 'IPAddress' type: String diff --git a/mmv1/products/compute/InstanceGroupManager.yaml b/mmv1/products/compute/InstanceGroupManager.yaml index ec957fa1924e..814d41abd0e4 100644 --- a/mmv1/products/compute/InstanceGroupManager.yaml +++ b/mmv1/products/compute/InstanceGroupManager.yaml @@ -65,6 +65,12 @@ properties: hyphen and a random four-character string to the base instance name. The base instance name must comply with RFC1035. required: true + - name: 'instanceGroupManagerId' + type: Integer + description: | + The unique identifier number for the resource. This identifier is defined by the server. + api_name: id + output: true - name: 'creationTimestamp' type: Time description: | diff --git a/mmv1/products/compute/RegionHealthCheck.yaml b/mmv1/products/compute/RegionHealthCheck.yaml index 616491ff6558..88adaa7ec03f 100644 --- a/mmv1/products/compute/RegionHealthCheck.yaml +++ b/mmv1/products/compute/RegionHealthCheck.yaml @@ -141,6 +141,12 @@ properties: An optional description of this resource. Provide this property when you create the resource. send_empty_value: true + - name: 'healthCheckId' + type: Integer + description: | + The unique identifier number for the resource. This identifier is defined by the server. + api_name: id + output: true - name: 'healthyThreshold' type: Integer description: | diff --git a/mmv1/products/compute/RegionInstanceGroupManager.yaml b/mmv1/products/compute/RegionInstanceGroupManager.yaml index c80b73a6c148..ac4a36de2c9d 100644 --- a/mmv1/products/compute/RegionInstanceGroupManager.yaml +++ b/mmv1/products/compute/RegionInstanceGroupManager.yaml @@ -64,6 +64,12 @@ properties: hyphen and a random four-character string to the base instance name. The base instance name must comply with RFC1035. required: true + - name: 'instanceGroupManagerId' + type: Integer + description: | + The unique identifier number for the resource. This identifier is defined by the server. + api_name: id + output: true - name: 'creationTimestamp' type: Time description: | diff --git a/mmv1/products/compute/RegionNetworkEndpoint.yaml b/mmv1/products/compute/RegionNetworkEndpoint.yaml index 044805b852bb..94feb20a0368 100644 --- a/mmv1/products/compute/RegionNetworkEndpoint.yaml +++ b/mmv1/products/compute/RegionNetworkEndpoint.yaml @@ -128,6 +128,12 @@ properties: IPv4 address external endpoint. This can only be specified when network_endpoint_type of the NEG is INTERNET_IP_PORT. + - name: 'networkEndpointId' + type: Integer + description: | + The unique identifier number for the resource. This identifier is defined by the server. + api_name: id + output: true - name: 'fqdn' type: String description: | diff --git a/mmv1/products/compute/Subnetwork.yaml b/mmv1/products/compute/Subnetwork.yaml index 0ddddb1e9c02..cb97cf761167 100644 --- a/mmv1/products/compute/Subnetwork.yaml +++ b/mmv1/products/compute/Subnetwork.yaml @@ -153,6 +153,12 @@ properties: An optional description of this resource. Provide this property when you create the resource. This field can be set only at resource creation time. + - name: 'subnetworkId' + type: Integer + description: | + The unique identifier number for the resource. This identifier is defined by the server. + api_name: id + output: true - name: 'gatewayAddress' type: String description: | diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_global_forwarding_rule_test.go.tmpl b/mmv1/third_party/terraform/services/compute/resource_compute_global_forwarding_rule_test.go.tmpl index 25002bbfbd70..565f88130f62 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_global_forwarding_rule_test.go.tmpl +++ b/mmv1/third_party/terraform/services/compute/resource_compute_global_forwarding_rule_test.go.tmpl @@ -30,7 +30,8 @@ func TestAccComputeGlobalForwardingRule_updateTarget(t *testing.T) { Check: resource.ComposeTestCheckFunc( resource.TestMatchResourceAttr( "google_compute_global_forwarding_rule.forwarding_rule", "target", regexp.MustCompile(proxy + "$")), - ), + resource.TestCheckResourceAttrSet( + "google_compute_global_forwarding_rule.forwarding_rule", "forwarding_rule_id")), }, { ResourceName: "google_compute_global_forwarding_rule.forwarding_rule", diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_instance_group_manager.go.tmpl b/mmv1/third_party/terraform/services/compute/resource_compute_instance_group_manager.go.tmpl index 514c513b9d54..61e911f809b1 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_instance_group_manager.go.tmpl +++ b/mmv1/third_party/terraform/services/compute/resource_compute_instance_group_manager.go.tmpl @@ -119,6 +119,12 @@ func ResourceComputeInstanceGroupManager() *schema.Resource { Description: `An optional textual description of the instance group manager.`, }, + "instance_group_manager_id": { + Type: schema.TypeInt, + Computed: true, + Description: `The unique identifier number for the resource. This identifier is defined by the server.`, + }, + "fingerprint": { Type: schema.TypeString, Computed: true, @@ -839,6 +845,11 @@ func resourceComputeInstanceGroupManagerRead(d *schema.ResourceData, meta interf if err := d.Set("description", manager.Description); err != nil { return fmt.Errorf("Error setting description: %s", err) } + + if err := d.Set("instance_group_manager_id", manager.Id); err != nil { + return fmt.Errorf("Error setting description: %s", err) + } + if err := d.Set("project", project); err != nil { return fmt.Errorf("Error setting project: %s", err) } diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_instance_group_manager_test.go.tmpl b/mmv1/third_party/terraform/services/compute/resource_compute_instance_group_manager_test.go.tmpl index 029ed68659b9..eeb7e45cd581 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_instance_group_manager_test.go.tmpl +++ b/mmv1/third_party/terraform/services/compute/resource_compute_instance_group_manager_test.go.tmpl @@ -27,6 +27,9 @@ func TestAccInstanceGroupManager_basic(t *testing.T) { Steps: []resource.TestStep{ { Config: testAccInstanceGroupManager_basic(template, target, igm1, igm2), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet( + "google_compute_instance_group_manager.igm-no-tp", "instance_group_manager_id")), }, { ResourceName: "google_compute_instance_group_manager.igm-basic", diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_region_health_check_test.go.tmpl b/mmv1/third_party/terraform/services/compute/resource_compute_region_health_check_test.go.tmpl index 74905b822185..a0d12639dd3c 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_region_health_check_test.go.tmpl +++ b/mmv1/third_party/terraform/services/compute/resource_compute_region_health_check_test.go.tmpl @@ -21,6 +21,10 @@ func TestAccComputeRegionHealthCheck_tcp_update(t *testing.T) { Steps: []resource.TestStep{ { Config: testAccComputeRegionHealthCheck_tcp(hckName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet( + "google_compute_region_health_check.foobar", "health_check_id"), + ), }, { ResourceName: "google_compute_region_health_check.foobar", diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_group_manager.go.tmpl b/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_group_manager.go.tmpl index f6db9cf7f694..a6457ee97b32 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_group_manager.go.tmpl +++ b/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_group_manager.go.tmpl @@ -162,6 +162,12 @@ func ResourceComputeRegionInstanceGroupManager() *schema.Resource { Description: `An optional textual description of the instance group manager.`, }, + "instance_group_manager_id": { + Type: schema.TypeInt, + Computed: true, + Description: `The unique identifier number for the resource. This identifier is defined by the server.`, + }, + "fingerprint": { Type: schema.TypeString, Computed: true, @@ -826,6 +832,9 @@ func resourceComputeRegionInstanceGroupManagerRead(d *schema.ResourceData, meta if err := d.Set("description", manager.Description); err != nil { return fmt.Errorf("Error setting description: %s", err) } + if err := d.Set("instance_group_manager_id", manager.Id); err != nil { + return fmt.Errorf("Error setting description: %s", err) + } if err := d.Set("project", project); err != nil { return fmt.Errorf("Error setting project: %s", err) } diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_group_manager_test.go.tmpl b/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_group_manager_test.go.tmpl index 9f6738d1790e..7df6c05380d5 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_group_manager_test.go.tmpl +++ b/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_group_manager_test.go.tmpl @@ -28,6 +28,9 @@ func TestAccRegionInstanceGroupManager_basic(t *testing.T) { Steps: []resource.TestStep{ { Config: testAccRegionInstanceGroupManager_basic(template, target, igm1, igm2), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet( + "google_compute_region_instance_group_manager.igm-basic", "instance_group_manager_id")), }, { ResourceName: "google_compute_region_instance_group_manager.igm-basic", diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_region_network_endpoint_test.go.tmpl b/mmv1/third_party/terraform/services/compute/resource_compute_region_network_endpoint_test.go.tmpl index b9bfd4189e10..9e0f4988ec75 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_region_network_endpoint_test.go.tmpl +++ b/mmv1/third_party/terraform/services/compute/resource_compute_region_network_endpoint_test.go.tmpl @@ -31,6 +31,10 @@ func TestAccComputeRegionNetworkEndpoint_regionNetworkEndpointBasic(t *testing.T { // Create one endpoint Config: testAccComputeRegionNetworkEndpoint_regionNetworkEndpointBasic(context), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet( + "google_compute_region_network_endpoint.default", "network_endpoint_id"), + ), }, { ResourceName: "google_compute_region_network_endpoint.default", diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_subnetwork_test.go.tmpl b/mmv1/third_party/terraform/services/compute/resource_compute_subnetwork_test.go.tmpl index 2f298fdbc6ec..f9500747ee46 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_subnetwork_test.go.tmpl +++ b/mmv1/third_party/terraform/services/compute/resource_compute_subnetwork_test.go.tmpl @@ -78,7 +78,8 @@ func TestAccComputeSubnetwork_basic(t *testing.T) { t, "google_compute_subnetwork.network-ref-by-url", &subnetwork1), testAccCheckComputeSubnetworkExists( t, "google_compute_subnetwork.network-ref-by-name", &subnetwork2), - ), + resource.TestCheckResourceAttrSet( + "google_compute_subnetwork.network-ref-by-name", "subnetwork_id"), ), }, { ResourceName: "google_compute_subnetwork.network-ref-by-url", From 727c6c279f274b2668f6954604d36c6e7a2a6102 Mon Sep 17 00:00:00 2001 From: nityaravi <32396647+nityaravi@users.noreply.github.com> Date: Tue, 19 Nov 2024 19:03:10 -0500 Subject: [PATCH 097/105] Updategenproviders (#12350) Co-authored-by: Stephen Lewis (Burrows) --- docs/content/_index.md | 2 +- docs/content/contribution-process.md | 5 +- .../develop/add-handwritten-datasource.md | 4 +- docs/content/develop/custom-code.md | 4 +- docs/content/develop/diffs.md | 2 +- docs/content/develop/generate-providers.md | 96 +++++++++ docs/content/develop/promote-to-ga.md | 4 +- docs/content/develop/resource.md | 12 +- .../content/develop/set-up-dev-environment.md | 77 +++++++ docs/content/develop/test/run-tests.md | 4 +- docs/content/develop/test/test.md | 6 +- docs/content/develop/update-dependencies.md | 2 +- docs/content/get-started/_index.md | 4 - .../content/get-started/generate-providers.md | 197 ------------------ 14 files changed, 196 insertions(+), 223 deletions(-) create mode 100644 docs/content/develop/generate-providers.md create mode 100644 docs/content/develop/set-up-dev-environment.md delete mode 100644 docs/content/get-started/_index.md delete mode 100644 docs/content/get-started/generate-providers.md diff --git a/docs/content/_index.md b/docs/content/_index.md index ef60d84e8dc7..f85822683a53 100644 --- a/docs/content/_index.md +++ b/docs/content/_index.md @@ -1,6 +1,6 @@ --- title: "Overview" -weight: 20 +weight: 10 aliases: - /docs/how-to/types-of-resources - /how-to/types-of-resources diff --git a/docs/content/contribution-process.md b/docs/content/contribution-process.md index 89ff42a68ed0..5cff76fdbb2d 100644 --- a/docs/content/contribution-process.md +++ b/docs/content/contribution-process.md @@ -1,6 +1,6 @@ --- title: "Contribution process" -weight: 9 +weight: 11 aliases: - /docs/getting-started/contributing - /getting-started/contributing @@ -22,6 +22,7 @@ This page explains how you can contribute code and documentation to the `magic-m ## Contribute code +1. [Set up your development environment]({{< ref "/develop/set-up-dev-environment" >}}) 1. [Create a new branch for your change](https://docs.github.com/en/get-started/quickstart/github-flow#create-a-branch) 1. Make the code change. For example: - [Add or modify a resource]({{< ref "/develop/resource" >}}) @@ -29,7 +30,7 @@ This page explains how you can contribute code and documentation to the `magic-m - [Add a datasource]({{< ref "/develop/add-handwritten-datasource" >}}) - [Promote to GA]({{< ref "/develop/promote-to-ga" >}}) - [Make a breaking change]({{< ref "/develop/breaking-changes/make-a-breaking-change" >}}) -1. [Generate the providers]({{< ref "/get-started/generate-providers" >}}) that include your change. +1. [Generate the providers]({{< ref "/develop/generate-providers" >}}) that include your change. 1. [Run provider tests locally]({{< ref "/develop/test/run-tests" >}}) that are relevant to the change you made 1. [Create a pull request (PR)]({{< ref "/contribute/create-pr" >}}) 1. Make changes in response to [code review]({{< ref "/contribute/create-pr#code-review" >}}) diff --git a/docs/content/develop/add-handwritten-datasource.md b/docs/content/develop/add-handwritten-datasource.md index 2bc5800a50f4..c25081f5ebf3 100644 --- a/docs/content/develop/add-handwritten-datasource.md +++ b/docs/content/develop/add-handwritten-datasource.md @@ -1,7 +1,7 @@ --- title: "Add a datasource" summary: "Datasources are like terraform resources except they don't *create* anything." -weight: 40 +weight: 14 aliases: - /docs/how-to/add-handwritten-datasource - /how-to/add-handwritten-datasource @@ -52,5 +52,5 @@ library, or the raw HTTP client used in MMV1 through `SendRequest`. 1. Open the data source documentation in [`magic-modules/third_party/terraform/website/docs/d/`](https://github.com/GoogleCloudPlatform/magic-modules/tree/main/mmv1/third_party/terraform/website/docs/d) using an editor of your choice. - The name of the file is the name of the data source without a `google_` prefix. For example, for `google_compute_instance`, the file is called `compute_instance.html.markdown` 2. Modify the documentation as needed according to [Handwritten documentation style guide]({{< ref "/develop/handwritten-docs-style-guide" >}}). -4. [Generate the providers]({{< ref "/get-started/generate-providers.md" >}}) +4. [Generate the providers]({{< ref "/develop/generate-providers" >}}) 5. Copy and paste the generated documentation into the Hashicorp Registry's [Doc Preview Tool](https://registry.terraform.io/tools/doc-preview) to see how it is rendered. diff --git a/docs/content/develop/custom-code.md b/docs/content/develop/custom-code.md index c5ae9dea9996..298e59b66cb2 100644 --- a/docs/content/develop/custom-code.md +++ b/docs/content/develop/custom-code.md @@ -1,6 +1,6 @@ --- title: "Add custom resource code" -weight: 39 +weight: 15 --- # Add custom resource code @@ -17,7 +17,7 @@ custom_code: By convention, the template files are stored in a directory matching the type of custom code, and the name of the file includes the resource (and, if relevant, field) impacted by the custom code. Like handwritten resource and test code, custom code is written as go templates which render go code. -When in doubt about the behavior of custom code, write the custom code, [generate the providers]({{< ref "/get-started/generate-providers" >}}), and inspect what changed in the providers using `git diff`. +When in doubt about the behavior of custom code, write the custom code, [generate the providers]({{< ref "/develop/generate-providers" >}}), and inspect what changed in the providers using `git diff`. The following sections describe types of custom code in more detail. diff --git a/docs/content/develop/diffs.md b/docs/content/develop/diffs.md index 55d9c6e68b8f..a8785972636b 100644 --- a/docs/content/develop/diffs.md +++ b/docs/content/develop/diffs.md @@ -1,6 +1,6 @@ --- title: "Fix diffs" -weight: 60 +weight: 18 aliases: - /develop/permadiff --- diff --git a/docs/content/develop/generate-providers.md b/docs/content/develop/generate-providers.md new file mode 100644 index 000000000000..c581b8099feb --- /dev/null +++ b/docs/content/develop/generate-providers.md @@ -0,0 +1,96 @@ +--- +title: "Generate the providers" +weight: 19 +aliases: + - /docs/getting-started/setup + - /getting-started/setup + - /docs/getting-started/generate-providers + - /getting-started/generate-providers + - /get-started/generate-providers +--- + +# Generate `google` and `google-beta` providers + +After making a change to the Terraform providers for Google Cloud, you must +integrate your changes with the providers. This page explains how to generate +provider changes to the `google` and `google-beta` Terraform providers. + +## Before you begin + +1. [Set up your development environment]({{< ref "/develop/set-up-dev-environment" >}}). +1. Update `magic-modules` as needed. These updates could be any of the following changes: + + [Adding or modifying a resource]({{< ref "/develop/resource" >}}). + + [Adding a datasource]({{< ref "/develop/add-handwritten-datasource" >}}). + + [Adding custom resource code]({{< ref "/develop/custom-code" >}}). + + [Promoting a resource to GA]({{< ref "/develop/promote-to-ga" >}}). + +## Generate a provider change + +1. Clone the `google` and `google-beta` provider repositories with the following commands: + + ```bash + git clone https://github.com/hashicorp/terraform-provider-google.git $GOPATH/src/github.com/hashicorp/terraform-provider-google + git clone https://github.com/hashicorp/terraform-provider-google-beta.git $GOPATH/src/github.com/hashicorp/terraform-provider-google-beta + ``` +1. Generate changes for the `google` provider: + ```bash + make provider VERSION=ga OUTPUT_PATH="$GOPATH/src/github.com/hashicorp/terraform-provider-google" PRODUCT=[PRODUCT_NAME] + ``` + Where `[PRODUCT_NAME]` is one of the folder names in + https://github.com/GoogleCloudPlatform/magic-modules/tree/main/mmv1/products. + + For example, if your product is `bigqueryanalyticshub`, the command would be + the following: + + ```bash + make provider VERSION=ga OUTPUT_PATH="$GOPATH/src/github.com/hashicorp/terraform-provider-google" PRODUCT=bigqueryanalyticshub + ``` + +1. Generate changes for the `google-beta` provider: + ```bash + make provider VERSION=beta OUTPUT_PATH="$GOPATH/src/github.com/hashicorp/terraform-provider-google-beta" PRODUCT=[PRODUCT_NAME] + ``` + + Where `[PRODUCT_NAME]` is one of the folder names in https://github.com/GoogleCloudPlatform/magic-modules/tree/main/mmv1/products. + + For example, if your product name is `bigqueryanalyticshub`, the command would be the following: + + ```bash + make provider VERSION=beta OUTPUT_PATH="$GOPATH/src/github.com/hashicorp/terraform-provider-google-beta" PRODUCT=bigqueryanalyticshub + ``` + +1. Confirm that the expected changes were generated: + ```bash + cd $GOPATH/src/github.com/hashicorp/terraform-provider-google + git diff -U0 + cd $GOPATH/src/github.com/hashicorp/terraform-provider-google-beta + git diff -U0 + ``` + + + {{< hint info >}} + **Note**: There may be additional changes present due to specifying a + `PRODUCT=` value or due to the `magic-modules` repository being out of sync + with the provider repositories. + {{< /hint >}} + + +## Troubleshoot + +### Too many open files {#too-many-open-files} + +If you are getting “Too many open files” ulimit needs to be raised. + +{{< tabs "ulimit" >}} +{{< tab "Mac OS" >}} +```bash +ulimit -n 8192 +``` +{{< /tab >}} +{{< /tabs >}} + +## What's next + ++ [Learn how to add resource tests]({{< ref "/develop/test/test" >}}) ++ [Learn how to run tests]({{< ref "/develop/test/run-tests" >}}) ++ [Learn about `make` commands]({{< ref "/reference/make-commands" >}}) \ No newline at end of file diff --git a/docs/content/develop/promote-to-ga.md b/docs/content/develop/promote-to-ga.md index c03bcefcc83f..dbc9ac29b644 100644 --- a/docs/content/develop/promote-to-ga.md +++ b/docs/content/develop/promote-to-ga.md @@ -1,6 +1,6 @@ --- title: "Promote to GA" -weight: 50 +weight: 16 --- # Promote from beta to GA @@ -13,7 +13,7 @@ For more information about types of resources and the generation process overall ## Before you begin -1. Complete the [Generate the providers]({{< ref "/get-started/generate-providers" >}}) quickstart to set up your environment and your Google Cloud project. +1. Complete the steps in [Set up your development environment]({{< ref "/develop/set-up-dev-environment" >}}) to set up your environment and your Google Cloud project. 2. Ensure that your `magic-modules`, `terraform-provider-google`, and `terraform-provider-google-beta` repositories are up to date. ``` cd ~/magic-modules diff --git a/docs/content/develop/resource.md b/docs/content/develop/resource.md index 1e1e8107e2f4..e66cd8b75f18 100644 --- a/docs/content/develop/resource.md +++ b/docs/content/develop/resource.md @@ -1,6 +1,6 @@ --- title: "Add or modify a resource" -weight: 30 +weight: 13 aliases: - /docs/how-to/add-mmv1-resource - /how-to/add-mmv1-resource @@ -31,7 +31,7 @@ For more information about types of resources and the generation process overall ## Before you begin -1. Complete the steps in [Generate the providers]({{< ref "/get-started/generate-providers" >}}) to set up your environment and your Google Cloud project. +1. Complete the steps in [Set up your development environment]({{< ref "/develop/set-up-dev-environment" >}}) to set up your environment and your Google Cloud project. 2. Ensure that your `magic-modules`, `terraform-provider-google`, and `terraform-provider-google-beta` repositories are up to date. ``` cd ~/magic-modules @@ -151,7 +151,7 @@ For more information about types of resources and the generation process overall > **Warning:** Handwritten resources are more difficult to develop and maintain. New handwritten resources will only be accepted if implementing the resource in MMv1 would require entirely overriding two or more CRUD methods. 1. Add the resource in MMv1. -2. [Generate the beta provider]({{< ref "/get-started/generate-providers.md" >}}) +2. [Generate the beta provider]({{< ref "/develop/generate-providers.md" >}}) 3. From the beta provider, copy the files generated for the resource to the following locations: - Resource: Copy to the appropriate service folder inside [`magic-modules/mmv1/third_party/terraform/services`](https://github.com/GoogleCloudPlatform/magic-modules/tree/main/mmv1/third_party/terraform/services) - Documentation: [`magic-modules/mmv1/third_party/terraform/website/docs/r`](https://github.com/GoogleCloudPlatform/magic-modules/tree/main/mmv1/third_party/terraform/website/docs/r) @@ -420,7 +420,7 @@ iam_policy: ### Convert to handwritten (not usually necessary) -1. [Generate the beta provider]({{< ref "/get-started/generate-providers.md" >}}) +1. [Generate the beta provider]({{< ref "/develop/generate-providers.md" >}}) 2. From the beta provider, copy the files generated for the IAM resources to the following locations: - Resource: Copy to the appropriate service folder inside [`magic-modules/mmv1/third_party/terraform/services`](https://github.com/GoogleCloudPlatform/magic-modules/tree/main/mmv1/third_party/terraform/services) - Documentation: [`magic-modules/mmv1/third_party/terraform/website/docs/r`](https://github.com/GoogleCloudPlatform/magic-modules/tree/main/mmv1/third_party/terraform/website/docs/r) @@ -442,7 +442,7 @@ iam_policy: {{< tab "MMv1" >}} Documentation is autogenerated based on the resource and field configurations. To preview the documentation: -1. [Generate the providers]({{< ref "/get-started/generate-providers.md" >}}) +1. [Generate the providers]({{< ref "/develop/generate-providers.md" >}}) 2. Copy and paste the generated documentation into the Hashicorp Registry's [Doc Preview Tool](https://registry.terraform.io/tools/doc-preview) to see how it is rendered. {{< /tab >}} {{< tab "Handwritten" >}} @@ -451,7 +451,7 @@ Documentation is autogenerated based on the resource and field configurations. T 1. Open the resource documentation in [`magic-modules/third_party/terraform/website/docs/r/`](https://github.com/GoogleCloudPlatform/magic-modules/tree/main/mmv1/third_party/terraform/website/docs/r) using an editor of your choice. - The name of the file is the name of the resource without a `google_` prefix. For example, for `google_compute_instance`, the file is called `compute_instance.html.markdown` 2. Modify the documentation as needed according to [Handwritten documentation style guide]({{< ref "/develop/handwritten-docs-style-guide" >}}). -3. [Generate the providers]({{< ref "/get-started/generate-providers.md" >}}) +3. [Generate the providers]({{< ref "/develop/generate-providers.md" >}}) 4. Copy and paste the generated documentation into the Hashicorp Registry's [Doc Preview Tool](https://registry.terraform.io/tools/doc-preview) to see how it is rendered. {{< /tab >}} {{< /tabs >}} diff --git a/docs/content/develop/set-up-dev-environment.md b/docs/content/develop/set-up-dev-environment.md new file mode 100644 index 000000000000..f325c1865b50 --- /dev/null +++ b/docs/content/develop/set-up-dev-environment.md @@ -0,0 +1,77 @@ +--- +title: "Set up your development environment" +weight: 12 +--- + +# Set up your development environment + +Before you start adding or updating a Terraform resource using +[magic-modules]({{< ref "/" >}}), you must first set up your environment by +installing the necessary tools. This page explains the steps for setting up your +development environment. + +1. [Install the gcloud CLI.](https://cloud.google.com/sdk/docs/install) +1. In the Google Cloud console, on the project selector page, select or + [create a Google Cloud project](https://cloud.google.com/resource-manager/docs/creating-managing-projects). + {{< hint info >}} + + **Note:** If you don't already have a project to use for testing changes to + the Terraform providers, create a project instead of selecting an existing + poject. After you finish these steps, you can delete the project, removing + all resources associated with the project. + + {{< /hint >}} + {{< button href="https://console.cloud.google.com/projectselector2/home/dashboard" >}}Go to project selector{{< /button >}} +1. Make sure that billing is enabled for your Google Cloud project. Learn how to + [check if billing is enabled on a project](https://cloud.google.com/billing/docs/how-to/verify-billing-enabled). + + +1. [Install git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) +1. [Install go](https://go.dev/doc/install) +1. Add the following values to your environment settings such as `.bashrc`: + ```bash + # Add GOPATH variable for convenience + export GOPATH=$(go env GOPATH) + # Add Go binaries to PATH + export PATH=$PATH:$(go env GOPATH)/bin + ``` +1. Install goimports + ```bash + go install golang.org/x/tools/cmd/goimports@latest + ``` +1. [Install terraform](https://developer.hashicorp.com/terraform/tutorials/aws-get-started/install-cli) +1. Clone the `magic-modules` repository + ```bash + cd ~ + git clone https://github.com/GoogleCloudPlatform/magic-modules.git + ``` + +1. Run the following command from the root of your cloned `magic-modules` repository. + + ```bash + cd magic-modules + ./scripts/doctor + ``` + + Expected output if everything is installed properly: + + ``` + Check for go in path... + found! + Check for goimports in path... + found! + Check for git in path... + found! + Check for terraform in path... + found! + Check for make in path... + found! + ``` + +## What's next + ++ [Learn how to add or modify a resource]({{< ref "/develop/resource" >}}) ++ [Learn how to add custom resource code]({{< ref "/develop/custom-code" >}}) ++ [Learn how to add a datasource]({{< ref "/develop/add-handwritten-datasource" >}}) ++ [Learn how to promote a resource to GA]({{< ref "/develop/promote-to-ga" >}}) + diff --git a/docs/content/develop/test/run-tests.md b/docs/content/develop/test/run-tests.md index 85ec7e63685e..a75f38f81151 100644 --- a/docs/content/develop/test/run-tests.md +++ b/docs/content/develop/test/run-tests.md @@ -15,7 +15,7 @@ aliases: ## Before you begin -[Generate the modified provider(s)]({{< ref "/get-started/generate-providers" >}}) +[Generate the modified provider(s)]({{< ref "/develop/generate-providers" >}}) 1. Set up application default credentials for Terraform @@ -243,7 +243,7 @@ Configure Terraform to use locally-built binaries for `google` and `google-beta` ### Run manual tests -1. [Generate the provider(s) you want to test]({{< ref "/get-started/generate-providers" >}}) +1. [Generate the provider(s) you want to test]({{< ref "/develop/generate-providers" >}}) 2. Build the provider(s) you want to test ```bash diff --git a/docs/content/develop/test/test.md b/docs/content/develop/test/test.md index d6e55784cf1b..3e77aa9f5b7a 100644 --- a/docs/content/develop/test/test.md +++ b/docs/content/develop/test/test.md @@ -100,7 +100,7 @@ This section assumes you've used the [Add a resource]({{< ref "/develop/resource > **Note:** If not, you can create one now, or skip this guide and construct the test by hand. Writing tests by hand can sometimes be a better option if there is a similar test you can copy from. 1. Add the test in MMv1. Repeat for all the create tests you will need. -2. [Generate the beta provider]({{< ref "/get-started/generate-providers.md" >}}). +2. [Generate the beta provider]({{< ref "/develop/generate-providers.md" >}}). 3. From the beta provider, copy and paste the generated `*_generated_test.go` file into the appropriate service folder inside [`magic-modules/mmv1/third_party/terraform/services`](https://github.com/GoogleCloudPlatform/magic-modules/tree/main/mmv1/third_party/terraform/services/) as a new file call `*_test.go`. 4. Modify the tests as needed. - Replace all occurrences of `github.com/hashicorp/terraform-provider-google-beta/google-beta` with `github.com/hashicorp/terraform-provider-google/google` @@ -120,7 +120,7 @@ An update test is a test that creates the target resource and then makes updates {{< tabs "update" >}} {{< tab "MMv1" >}} -1. [Generate the beta provider]({{< ref "/get-started/generate-providers.md" >}}). +1. [Generate the beta provider]({{< ref "/develop/generate-providers" >}}). 2. From the beta provider, copy and paste the generated `*_generated_test.go` file into the appropriate service folder inside [`magic-modules/mmv1/third_party/terraform/services`](https://github.com/GoogleCloudPlatform/magic-modules/tree/main/mmv1/third_party/terraform/services) as a new file call `*_test.go`. 3. Using an editor of your choice, delete the `*DestroyProducer` function, and all but one test. The remaining test should be the "full" test, or if there is no "full" test, the "basic" test. This will be the starting point for your new update test. 4. Modify the `TestAcc*` *test function* to support updates. @@ -274,4 +274,4 @@ func TestSignatureAlgorithmDiffSuppress(t *testing.T) { ## What's next? -- [Run your tests]({{< ref "/develop/test/run-tests.md" >}}) +- [Run your tests]({{< ref "/develop/test/run-tests" >}}) diff --git a/docs/content/develop/update-dependencies.md b/docs/content/develop/update-dependencies.md index cca8822406bf..b50d31b5afe2 100644 --- a/docs/content/develop/update-dependencies.md +++ b/docs/content/develop/update-dependencies.md @@ -1,6 +1,6 @@ --- title: "Update dependencies" -weight: 300 +weight: 17 aliases: - /docs/update-dependencies --- diff --git a/docs/content/get-started/_index.md b/docs/content/get-started/_index.md deleted file mode 100644 index 3fad30cd2d2c..000000000000 --- a/docs/content/get-started/_index.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -title: "Get started" -weight: 10 ---- \ No newline at end of file diff --git a/docs/content/get-started/generate-providers.md b/docs/content/get-started/generate-providers.md deleted file mode 100644 index eaf0e1ae109e..000000000000 --- a/docs/content/get-started/generate-providers.md +++ /dev/null @@ -1,197 +0,0 @@ ---- -title: "Generate the providers" -weight: 10 -aliases: - - /docs/getting-started/setup - - /getting-started/setup - - /docs/getting-started/generate-providers - - /getting-started/generate-providers ---- - - -# Generate `google` and `google-beta` providers - -This quickstart guides you through setting up your development environment, making a change to `magic-modules`, generating provider changes to the `google` and `google-beta` Terraform providers, and running tests related to the change. - -## Before you begin - -1. [Install the gcloud CLI.](https://cloud.google.com/sdk/docs/install) -1. In the Google Cloud console, on the project selector page, select or [create a Google Cloud project](https://cloud.google.com/resource-manager/docs/creating-managing-projects). - {{< hint info >}} - **Note:** If you don't already have a project to use for testing changes to the Terraform providers, create a project instead of selecting an existing poject. After you finish these steps, you can delete the project, removing all resources associated with the project. - {{< /hint >}} - {{< button href="https://console.cloud.google.com/projectselector2/home/dashboard" >}}Go to project selector{{< /button >}} -1. Make sure that billing is enabled for your Google Cloud project. Learn how to [check if billing is enabled on a project](https://cloud.google.com/billing/docs/how-to/verify-billing-enabled). - -## Set up your development environment - -{{< hint warning >}} -If you are familiar with Docker or Podman, you may want to use the experimental [container-based environment]({{< ref "/reference/make-commands.md#container-based-environment" >}}) instead of this section. -{{< /hint >}} - -1. [Install git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) -1. [Install go](https://go.dev/doc/install) -1. Add the following values to your environment settings such as `.bashrc`: - ```bash - # Add GOPATH variable for convenience - export GOPATH=$(go env GOPATH) - # Add Go binaries to PATH - export PATH=$PATH:$(go env GOPATH)/bin - ``` -1. Install goimports - ```bash - go install golang.org/x/tools/cmd/goimports@latest - ``` -1. [Install terraform](https://developer.hashicorp.com/terraform/tutorials/aws-get-started/install-cli) -1. Clone the `magic-modules` repository - ```bash - cd ~ - git clone https://github.com/GoogleCloudPlatform/magic-modules.git - ``` -1. Run the following command from the root of your cloned `magic-modules` repository. - - ```bash - cd magic-modules - ./scripts/doctor - ``` - - Expected output if everything is installed properly: - - ``` - Check for go in path... - found! - Check for goimports in path... - found! - Check for git in path... - found! - Check for terraform in path... - found! - Check for make in path... - found! - ``` - -## Generate a provider change - -1. In your cloned magic-modules repository, edit `mmv1/products/bigqueryanalyticshub/DataExchange.yaml` to change the description for the `displayName` field: - ```yaml - - name: 'displayName' - type: NestedObject - description: | - UPDATED_DESCRIPTION - properties: - [] - ``` -1. Clone the `google` and `google-beta` provider repositories with the following commands: - - ```bash - git clone https://github.com/hashicorp/terraform-provider-google.git $GOPATH/src/github.com/hashicorp/terraform-provider-google - git clone https://github.com/hashicorp/terraform-provider-google-beta.git $GOPATH/src/github.com/hashicorp/terraform-provider-google-beta - ``` -1. Generate changes for the `google` provider - ```bash - make provider VERSION=ga OUTPUT_PATH="$GOPATH/src/github.com/hashicorp/terraform-provider-google" PRODUCT=bigqueryanalyticshub - ``` -1. Generate changes for the `google-beta` provider - ```bash - make provider VERSION=beta OUTPUT_PATH="$GOPATH/src/github.com/hashicorp/terraform-provider-google-beta" PRODUCT=bigqueryanalyticshub - ``` -1. Confirm that the expected changes were generated - ```bash - cd $GOPATH/src/github.com/hashicorp/terraform-provider-google - git diff -U0 - cd $GOPATH/src/github.com/hashicorp/terraform-provider-google-beta - git diff -U0 - ``` - - In both cases, the changes should include: - - ```diff - diff --git a/google/services/bigqueryanalyticshub/resource_bigquery_analytics_hudiff --git a/google/services/bigqueryanalyticshub/resource_bigquery_analytics_hub_data_exchange.go b/google/services/bigqueryanalyticshub/resource_bigquery_analytics_hub_data_exchange.go - --- a/google/services/bigqueryanalyticshub/resource_bigquery_analytics_hub_data_exchange.go - +++ b/google/services/bigqueryanalyticshub/resource_bigquery_analytics_hub_data_exchange.go - @@ -66 +66 @@ func ResourceBigqueryAnalyticsHubDataExchange() *schema.Resource { - - Description: `Human-readable display name of the data exchange. The display name must contain only Unicode letters, numbers (0-9), underscores (_), dashes (-), spaces ( ), and must not start or end with spaces.`, - + Description: `UPDATED_DESCRIPTION`, - diff --git a/website/docs/r/bigquery_analytics_hub_data_exchange.html.markdown b/website/docs/r/bigquery_analytics_hub_data_exchange.html.markdown - --- a/website/docs/r/bigquery_analytics_hub_data_exchange.html.markdown - +++ b/website/docs/r/bigquery_analytics_hub_data_exchange.html.markdown - @@ -63 +63 @@ The following arguments are supported: - - Human-readable display name of the data exchange. The display name must contain only Unicode letters, numbers (0-9), underscores (_), dashes (-), spaces ( ), and must not start or end with spaces. - + UPDATED_DESCRIPTION - ``` - - {{< hint info >}} - **Note**: There may be additional changes present due to specifying a `PRODUCT=` value or due to the `magic-modules` repository being out of sync with the provider repositories. This is okay as long as tests in the following section pass. - {{< /hint >}} - - -## Test changes - -1. Set up application default credentials for Terraform - ```bash - gcloud auth application-default login - export GOOGLE_USE_DEFAULT_CREDENTIALS=true - ``` -1. Set required environment variables - ```bash - export GOOGLE_PROJECT=PROJECT_ID - export GOOGLE_REGION=us-central1 - export GOOGLE_ZONE=us-central1-a - ``` - Replace `PROJECT_ID` with the ID of your Google Cloud project. - -1. Enable required APIs - ```bash - gcloud config set project $GOOGLE_PROJECT - gcloud services enable analyticshub.googleapis.com - ``` -1. Run all linters - ```bash - cd $GOPATH/src/github.com/hashicorp/terraform-provider-google - make lint - cd $GOPATH/src/github.com/hashicorp/terraform-provider-google-beta - make lint - ``` -1. Run all unit tests - ```bash - cd $GOPATH/src/github.com/hashicorp/terraform-provider-google - make test - cd $GOPATH/src/github.com/hashicorp/terraform-provider-google-beta - make test - ``` -1. Run acceptance tests for BigqueryAnalyticsHub DataExchange - - ```bash - cd $GOPATH/src/github.com/hashicorp/terraform-provider-google - make testacc TEST=./google/services/bigqueryanalyticshub TESTARGS='-run=TestAccBigqueryAnalyticsHubDataExchange_' - cd $GOPATH/src/github.com/hashicorp/terraform-provider-google-beta - make testacc TEST=./google-beta/services/bigqueryanalyticshub TESTARGS='-run=TestAccBigqueryAnalyticsHubDataExchange_' - ``` - -## Troubleshoot - -### Too many open files {#too-many-open-files} - -If you are getting “Too many open files” ulimit needs to be raised. - -{{< tabs "ulimit" >}} -{{< tab "Mac OS" >}} -```bash -ulimit -n 8192 -``` -{{< /tab >}} -{{< /tabs >}} - -## Cleanup - -1. Optional: Revoke credentials from the gcloud CLI. - -```bash -gcloud auth revoke -``` - -## What's next - -- [Learn about Magic Modules]({{< ref "/" >}}) -- [Learn about the contribution process]({{< ref "/contribution-process.md" >}}) -- [Learn about make commands]({{< ref "/reference/make-commands.md" >}}) \ No newline at end of file From d5e86ba02cb336a9d7819510a0b265de804c8757 Mon Sep 17 00:00:00 2001 From: Ryan Oaks Date: Wed, 20 Nov 2024 12:20:46 -0500 Subject: [PATCH 098/105] Add test infra for chronicle (#12370) --- .ci/infra/terraform/main.tf | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/.ci/infra/terraform/main.tf b/.ci/infra/terraform/main.tf index 2d8d435d96b6..b367dcb37618 100644 --- a/.ci/infra/terraform/main.tf +++ b/.ci/infra/terraform/main.tf @@ -57,6 +57,12 @@ resource "google_organization_iam_member" "sa_billing_viewer" { member = google_service_account.sa.member } +resource "google_organization_iam_member" "sa_chronicle_admin" { + org_id = data.google_organization.org.org_id + role = "roles/chronicle.admin" + member = google_service_account.sa.member +} + resource "google_organization_iam_member" "sa_cloudkms_admin" { org_id = data.google_organization.org.org_id role = "roles/cloudkms.admin" @@ -217,7 +223,8 @@ module "project-services" { "binaryauthorization.googleapis.com", "blockchainnodeengine.googleapis.com", "certificatemanager.googleapis.com", - "cloudaicompanion.googleapis.com" + "chronicle.googleapis.com", + "cloudaicompanion.googleapis.com", "cloudapis.googleapis.com", "cloudasset.googleapis.com", "cloudbilling.googleapis.com", From 37310e5ad8030ab802f85c34d56da0b8730c0875 Mon Sep 17 00:00:00 2001 From: Ahzaz Hingora <5833893+ahzaz@users.noreply.github.com> Date: Thu, 21 Nov 2024 00:01:02 +0530 Subject: [PATCH 099/105] Add `autotuning_config` and `cohort` fields for Dataproc batch (#12357) --- mmv1/products/dataproc/Batch.yaml | 40 +++++++++++++++++++ .../dataproc_batch_autotuning.tf.tmpl | 29 ++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 mmv1/templates/terraform/examples/dataproc_batch_autotuning.tf.tmpl diff --git a/mmv1/products/dataproc/Batch.yaml b/mmv1/products/dataproc/Batch.yaml index febffeeb45b8..b18fa791d81b 100644 --- a/mmv1/products/dataproc/Batch.yaml +++ b/mmv1/products/dataproc/Batch.yaml @@ -113,6 +113,19 @@ examples: 'prevent_destroy': 'false' ignore_read_extra: - 'runtime_config.0.properties' + - name: 'dataproc_batch_autotuning' + primary_resource_id: 'example_batch_autotuning' + primary_resource_name: 'fmt.Sprintf("tf-test-batch-autotuning%s", context["random_suffix"])' + vars: + subnetwork_name: 'default' + prevent_destroy: 'true' + test_env_vars: + project_name: 'PROJECT_NAME' + test_vars_overrides: + 'subnetwork_name': 'acctest.BootstrapSubnetWithFirewallForDataprocBatches(t, "dataproc-autotuning-test-network", "dataproc-autotuning-test-subnetwork")' + 'prevent_destroy': 'false' + ignore_read_extra: + - 'runtime_config.0.properties' parameters: - name: 'location' type: String @@ -278,6 +291,33 @@ properties: description: | A mapping of property names to values, which are used to configure workload execution. output: true + - name: 'autotuningConfig' + type: NestedObject + immutable: true + description: | + Optional. Autotuning configuration of the workload. + properties: + - name: 'scenarios' + type: Array + required_with: + - 'runtimeConfig.0.cohort' + description: | + Optional. Scenarios for which tunings are applied. + item_type: + type: Enum + description: | + Scenario represents a specific goal that autotuning will attempt to achieve by modifying workloads. + required: true + enum_values: + - 'SCALING' + - 'BROADCAST_HASH_JOIN' + - 'MEMORY' + - name: 'cohort' + type: String + description: | + Optional. Cohort identifier. Identifies families of the workloads having the same shape, e.g. daily ETL jobs. + immutable: true + required: false - name: 'environmentConfig' type: NestedObject description: | diff --git a/mmv1/templates/terraform/examples/dataproc_batch_autotuning.tf.tmpl b/mmv1/templates/terraform/examples/dataproc_batch_autotuning.tf.tmpl new file mode 100644 index 000000000000..5f70350df171 --- /dev/null +++ b/mmv1/templates/terraform/examples/dataproc_batch_autotuning.tf.tmpl @@ -0,0 +1,29 @@ +resource "google_dataproc_batch" "{{$.PrimaryResourceId}}" { + + batch_id = "tf-test-batch%{random_suffix}" + location = "us-central1" + labels = {"batch_test": "terraform"} + + runtime_config { + version = "2.2" + properties = { "spark.dynamicAllocation.enabled": "false", "spark.executor.instances": "2" } + cohort = "tf-dataproc-batch-example" + autotuning_config { + scenarios = ["SCALING", "MEMORY"] + } + } + + environment_config { + execution_config { + subnetwork_uri = "{{index $.Vars "subnetwork_name"}}" + ttl = "3600s" + } + } + + spark_batch { + main_class = "org.apache.spark.examples.SparkPi" + args = ["10"] + jar_file_uris = ["file:///usr/lib/spark/examples/jars/spark-examples.jar"] + } +} + From 318f4febb184cd6bbcbe9c957c396c042e67ba7b Mon Sep 17 00:00:00 2001 From: Scott Suarez Date: Wed, 20 Nov 2024 11:18:34 -0800 Subject: [PATCH 100/105] wait for SA to propagate on beyondcord app (#12365) --- mmv1/products/beyondcorp/AppConnection.yaml | 2 + .../beyondcorp_app_connection_basic.tf.tmpl | 11 ++ .../beyondcorp_app_connection_full.tf.tmpl | 10 ++ ...e_google_beyondcorp_app_connection_test.go | 101 +++++++++++------- ...resource_beyondcorp_app_connection_test.go | 14 ++- 5 files changed, 98 insertions(+), 40 deletions(-) diff --git a/mmv1/products/beyondcorp/AppConnection.yaml b/mmv1/products/beyondcorp/AppConnection.yaml index 8c84d05b3e8b..e6d6bfb68738 100644 --- a/mmv1/products/beyondcorp/AppConnection.yaml +++ b/mmv1/products/beyondcorp/AppConnection.yaml @@ -59,6 +59,7 @@ examples: account_id: 'my-account' app_connector_name: 'my-app-connector' app_connection_name: 'my-app-connection' + external_providers: ["time"] - name: 'beyondcorp_app_connection_full' primary_resource_id: 'app_connection' primary_resource_name: 'fmt.Sprintf("tf_test_my_app_connection%s", context["random_suffix"])' @@ -68,6 +69,7 @@ examples: app_connector_name: 'my-app-connector' app_connection_name: 'my-app-connection' display_name: 'some display name' + external_providers: ["time"] parameters: properties: - name: 'name' diff --git a/mmv1/templates/terraform/examples/beyondcorp_app_connection_basic.tf.tmpl b/mmv1/templates/terraform/examples/beyondcorp_app_connection_basic.tf.tmpl index 1a995efb4be7..4e605c2c8012 100644 --- a/mmv1/templates/terraform/examples/beyondcorp_app_connection_basic.tf.tmpl +++ b/mmv1/templates/terraform/examples/beyondcorp_app_connection_basic.tf.tmpl @@ -3,7 +3,18 @@ resource "google_service_account" "service_account" { display_name = "Test Service Account" } +# wait for service account to propagate -- can be needed due to +# SA eventual consistency issue +resource "time_sleep" "wait_120_seconds" { + depends_on = [google_service_account.service_account] + + create_duration = "120s" +} + + resource "google_beyondcorp_app_connector" "app_connector" { + depends_on = [time_sleep.wait_120_seconds] + name = "{{index $.Vars "app_connector_name"}}" principal_info { service_account { diff --git a/mmv1/templates/terraform/examples/beyondcorp_app_connection_full.tf.tmpl b/mmv1/templates/terraform/examples/beyondcorp_app_connection_full.tf.tmpl index 9224d30b34ef..88d1ea52403d 100644 --- a/mmv1/templates/terraform/examples/beyondcorp_app_connection_full.tf.tmpl +++ b/mmv1/templates/terraform/examples/beyondcorp_app_connection_full.tf.tmpl @@ -3,6 +3,14 @@ resource "google_service_account" "service_account" { display_name = "Test Service Account" } +# wait for service account to propagate -- can be needed due to +# SA eventual consistency issue +resource "time_sleep" "wait_120_seconds" { + depends_on = [google_service_account.service_account] + + create_duration = "120s" +} + resource "google_beyondcorp_app_gateway" "app_gateway" { name = "{{index $.Vars "app_gateway_name"}}" type = "TCP_PROXY" @@ -10,6 +18,8 @@ resource "google_beyondcorp_app_gateway" "app_gateway" { } resource "google_beyondcorp_app_connector" "app_connector" { + depends_on = [time_sleep.wait_120_seconds] + name = "{{index $.Vars "app_connector_name"}}" principal_info { service_account { diff --git a/mmv1/third_party/terraform/services/beyondcorp/data_source_google_beyondcorp_app_connection_test.go b/mmv1/third_party/terraform/services/beyondcorp/data_source_google_beyondcorp_app_connection_test.go index 49c4057c5b3d..426be7d9bbfa 100644 --- a/mmv1/third_party/terraform/services/beyondcorp/data_source_google_beyondcorp_app_connection_test.go +++ b/mmv1/third_party/terraform/services/beyondcorp/data_source_google_beyondcorp_app_connection_test.go @@ -18,7 +18,10 @@ func TestAccDataSourceGoogleBeyondcorpAppConnection_basic(t *testing.T) { acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), - CheckDestroy: testAccCheckBeyondcorpAppConnectionDestroyProducer(t), + ExternalProviders: map[string]resource.ExternalProvider{ + "time": {}, + }, + CheckDestroy: testAccCheckBeyondcorpAppConnectionDestroyProducer(t), Steps: []resource.TestStep{ { Config: testAccDataSourceGoogleBeyondcorpAppConnection_basic(context), @@ -40,7 +43,10 @@ func TestAccDataSourceGoogleBeyondcorpAppConnection_full(t *testing.T) { acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), - CheckDestroy: testAccCheckBeyondcorpAppConnectionDestroyProducer(t), + ExternalProviders: map[string]resource.ExternalProvider{ + "time": {}, + }, + CheckDestroy: testAccCheckBeyondcorpAppConnectionDestroyProducer(t), Steps: []resource.TestStep{ { Config: testAccDataSourceGoogleBeyondcorpAppConnection_full(context), @@ -55,34 +61,43 @@ func TestAccDataSourceGoogleBeyondcorpAppConnection_full(t *testing.T) { func testAccDataSourceGoogleBeyondcorpAppConnection_basic(context map[string]interface{}) string { return acctest.Nprintf(` resource "google_service_account" "service_account" { - account_id = "tf-test-my-account%{random_suffix}" - display_name = "Test Service Account" + account_id = "tf-test-my-account%{random_suffix}" + display_name = "Test Service Account" } +resource "time_sleep" "wait_120_seconds" { + depends_on = [google_service_account.service_account] + + create_duration = "120s" +} + + resource "google_beyondcorp_app_connector" "app_connector" { - name = "tf-test-appconnector-%{random_suffix}" - principal_info { - service_account { - email = google_service_account.service_account.email - } - } + depends_on = [time_sleep.wait_120_seconds] + + name = "tf-test-appconnector-%{random_suffix}" + principal_info { + service_account { + email = google_service_account.service_account.email + } + } } resource "google_beyondcorp_app_connection" "foo" { - name = "tf-test-my-app-connection-%{random_suffix}" - type = "TCP_PROXY" - application_endpoint { - host = "foo-host" - port = 8080 - } - connectors = [google_beyondcorp_app_connector.app_connector.id] - labels = { - my-label = "my-label-value" - } + name = "tf-test-my-app-connection-%{random_suffix}" + type = "TCP_PROXY" + application_endpoint { + host = "foo-host" + port = 8080 + } + connectors = [google_beyondcorp_app_connector.app_connector.id] + labels = { + my-label = "my-label-value" + } } data "google_beyondcorp_app_connection" "foo" { - name = google_beyondcorp_app_connection.foo.name + name = google_beyondcorp_app_connection.foo.name } `, context) } @@ -90,33 +105,41 @@ data "google_beyondcorp_app_connection" "foo" { func testAccDataSourceGoogleBeyondcorpAppConnection_full(context map[string]interface{}) string { return acctest.Nprintf(` resource "google_service_account" "service_account" { - account_id = "tf-test-my-account%{random_suffix}" - display_name = "Test Service Account" + account_id = "tf-test-my-account%{random_suffix}" + display_name = "Test Service Account" +} + +resource "time_sleep" "wait_120_seconds" { + depends_on = [google_service_account.service_account] + + create_duration = "120s" } resource "google_beyondcorp_app_connector" "app_connector" { - name = "tf-test-appconnector-%{random_suffix}" - principal_info { - service_account { - email = google_service_account.service_account.email - } - } + depends_on = [time_sleep.wait_120_seconds] + + name = "tf-test-appconnector-%{random_suffix}" + principal_info { + service_account { + email = google_service_account.service_account.email + } + } } resource "google_beyondcorp_app_connection" "foo" { - name = "tf-test-my-app-connection-%{random_suffix}" - type = "TCP_PROXY" - application_endpoint { - host = "foo-host" - port = 8080 - } - connectors = [google_beyondcorp_app_connector.app_connector.id] + name = "tf-test-my-app-connection-%{random_suffix}" + type = "TCP_PROXY" + application_endpoint { + host = "foo-host" + port = 8080 + } + connectors = [google_beyondcorp_app_connector.app_connector.id] } data "google_beyondcorp_app_connection" "foo" { - name = google_beyondcorp_app_connection.foo.name - project = google_beyondcorp_app_connection.foo.project - region = google_beyondcorp_app_connection.foo.region + name = google_beyondcorp_app_connection.foo.name + project = google_beyondcorp_app_connection.foo.project + region = google_beyondcorp_app_connection.foo.region } `, context) } diff --git a/mmv1/third_party/terraform/services/beyondcorp/resource_beyondcorp_app_connection_test.go b/mmv1/third_party/terraform/services/beyondcorp/resource_beyondcorp_app_connection_test.go index dc666edf0855..1a975d48eb40 100644 --- a/mmv1/third_party/terraform/services/beyondcorp/resource_beyondcorp_app_connection_test.go +++ b/mmv1/third_party/terraform/services/beyondcorp/resource_beyondcorp_app_connection_test.go @@ -17,7 +17,10 @@ func TestAccBeyondcorpAppConnection_beyondcorpAppConnectionUpdateExample(t *test acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), - CheckDestroy: testAccCheckBeyondcorpAppConnectionDestroyProducer(t), + ExternalProviders: map[string]resource.ExternalProvider{ + "time": {}, + }, + CheckDestroy: testAccCheckBeyondcorpAppConnectionDestroyProducer(t), Steps: []resource.TestStep{ { Config: testAccBeyondcorpAppConnection_beyondcorpAppConnectionBasicExample(context), @@ -51,7 +54,16 @@ resource "google_service_account" "service_account" { display_name = "Test Service Account" } +resource "time_sleep" "wait_120_seconds" { + depends_on = [google_service_account.service_account] + + create_duration = "120s" +} + + resource "google_beyondcorp_app_connector" "app_connector" { + depends_on = [time_sleep.wait_120_seconds] + name = "tf-test-my-app-connector%{random_suffix}" principal_info { service_account { From c48564ddc807c4923da30dfaa550b84cbf46c459 Mon Sep 17 00:00:00 2001 From: "Stephen Lewis (Burrows)" Date: Wed, 20 Nov 2024 13:11:37 -0800 Subject: [PATCH 101/105] Document requirement for vertex ai model presence (#12373) --- .ci/infra/terraform/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.ci/infra/terraform/README.md b/.ci/infra/terraform/README.md index 6ae724e1bb2c..a600ed2534cc 100644 --- a/.ci/infra/terraform/README.md +++ b/.ci/infra/terraform/README.md @@ -49,6 +49,8 @@ After applying this configuration: - Add Cloud Identity Premium Plan to the Google Workspace domain - Perform the Privileged Access Manager set-up https://pantheon.corp.google.com/iam-admin/pam/setup - (Org only) Enroll the org in the Premium tier of Security Control Center +- Upload a model with the name `tf-static-1` to the Vertex AI model registry + - This should only be necessary until uploading new models is supported in the provider. Quotas that will need to be adjusted to support all tests: - Project quota for the new service account From 8f71a420d4f4ae140cc42514aa7dbbf83f656290 Mon Sep 17 00:00:00 2001 From: Lingkai Shen Date: Wed, 20 Nov 2024 16:43:38 -0500 Subject: [PATCH 102/105] Make another example for Rules release to a non-default Firestore db (#12263) --- .../samples/release/firestore_release.tf.tmpl | 14 +++-------- .../samples/release/firestore_release.yaml | 6 ++--- .../firestore_release_additional.tf.tmpl | 16 ++++++++++++ .../release/firestore_release_additional.yaml | 25 +++++++++++++++++++ .../firebaserules/samples/release/meta.yaml | 7 ++++++ 5 files changed, 54 insertions(+), 14 deletions(-) create mode 100644 tpgtools/overrides/firebaserules/samples/release/firestore_release_additional.tf.tmpl create mode 100644 tpgtools/overrides/firebaserules/samples/release/firestore_release_additional.yaml diff --git a/tpgtools/overrides/firebaserules/samples/release/firestore_release.tf.tmpl b/tpgtools/overrides/firebaserules/samples/release/firestore_release.tf.tmpl index f88267b16a2e..83212f390aba 100644 --- a/tpgtools/overrides/firebaserules/samples/release/firestore_release.tf.tmpl +++ b/tpgtools/overrides/firebaserules/samples/release/firestore_release.tf.tmpl @@ -1,22 +1,16 @@ resource "google_firebaserules_release" "primary" { - name = "cloud.firestore/{{database}}" - ruleset_name = "projects/{{project}}/rulesets/${google_firebaserules_ruleset.firestore.name}" + name = "cloud.firestore" project = "{{project}}" - - lifecycle { - replace_triggered_by = [ - google_firebaserules_ruleset.firestore - ] - } + ruleset_name = "projects/{{project}}/rulesets/${google_firebaserules_ruleset.firestore.name}" } resource "google_firebaserules_ruleset" "firestore" { + project = "{{project}}" + source { files { content = "service cloud.firestore {match /databases/{database}/documents { match /{document=**} { allow read, write: if false; } } }" name = "firestore.rules" } } - - project = "{{project}}" } diff --git a/tpgtools/overrides/firebaserules/samples/release/firestore_release.yaml b/tpgtools/overrides/firebaserules/samples/release/firestore_release.yaml index 4a8a4112e96a..6e3bff6c0e67 100644 --- a/tpgtools/overrides/firebaserules/samples/release/firestore_release.yaml +++ b/tpgtools/overrides/firebaserules/samples/release/firestore_release.yaml @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. name: firestore_release -description: Creates a Firebase Rules Release to Cloud Firestore +description: Creates a Firebase Rules Release to the default Cloud Firestore instance type: release versions: - ga @@ -20,6 +20,4 @@ versions: resource: ./firestore_release.tf.tmpl variables: - name: project - type: project -- name: database - type: resource_name \ No newline at end of file + type: project \ No newline at end of file diff --git a/tpgtools/overrides/firebaserules/samples/release/firestore_release_additional.tf.tmpl b/tpgtools/overrides/firebaserules/samples/release/firestore_release_additional.tf.tmpl new file mode 100644 index 000000000000..4512e0d7b956 --- /dev/null +++ b/tpgtools/overrides/firebaserules/samples/release/firestore_release_additional.tf.tmpl @@ -0,0 +1,16 @@ +resource "google_firebaserules_release" "primary" { + name = "cloud.firestore/{{database}}" + project = "{{project}}" + ruleset_name = "projects/{{project}}/rulesets/${google_firebaserules_ruleset.firestore.name}" +} + +resource "google_firebaserules_ruleset" "firestore" { + project = "{{project}}" + + source { + files { + content = "service cloud.firestore {match /databases/{database}/documents { match /{document=**} { allow read, write: if false; } } }" + name = "firestore.rules" + } + } +} diff --git a/tpgtools/overrides/firebaserules/samples/release/firestore_release_additional.yaml b/tpgtools/overrides/firebaserules/samples/release/firestore_release_additional.yaml new file mode 100644 index 000000000000..7668f4f15616 --- /dev/null +++ b/tpgtools/overrides/firebaserules/samples/release/firestore_release_additional.yaml @@ -0,0 +1,25 @@ +# Copyright 2024 Google LLC. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +name: firestore_release_additional +description: Creates a Firebase Rules Release to an additional Cloud Firestore instance +type: release +versions: +- ga +- beta +resource: ./firestore_release_additional.tf.tmpl +variables: +- name: project + type: project +- name: database + type: resource_name \ No newline at end of file diff --git a/tpgtools/overrides/firebaserules/samples/release/meta.yaml b/tpgtools/overrides/firebaserules/samples/release/meta.yaml index e69de29bb2d1..a397c08240d4 100644 --- a/tpgtools/overrides/firebaserules/samples/release/meta.yaml +++ b/tpgtools/overrides/firebaserules/samples/release/meta.yaml @@ -0,0 +1,7 @@ +# meta.yaml +# this is a shared config file that all the tests merge with +# +# The firestore_release test uses the default Firestore instance, which can have an existing Rules deployment for whatever reason. +# However, the firestore_release_additional test was sufficient because Rules deployment doesn't care about whether it's the default Firestore instance +test_hide: + - firestore_release.tf.tmpl From 7ba622944ecb3e3649a82d64aa797b2e0be0059b Mon Sep 17 00:00:00 2001 From: Zeleena Kearney <12972510+zeleena@users.noreply.github.com> Date: Wed, 20 Nov 2024 14:32:13 -0800 Subject: [PATCH 103/105] Support V6E for type of accelerator_config in google_tpu_v2_vm (#12353) --- mmv1/products/tpuv2/Vm.yaml | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/mmv1/products/tpuv2/Vm.yaml b/mmv1/products/tpuv2/Vm.yaml index a81aaa0beec2..a88502ec6eeb 100644 --- a/mmv1/products/tpuv2/Vm.yaml +++ b/mmv1/products/tpuv2/Vm.yaml @@ -264,17 +264,12 @@ properties: - accelerator_type properties: - name: 'type' - type: Enum + type: String description: | - Type of TPU. + Type of TPU. Please select one of the allowed types: https://cloud.google.com/tpu/docs/reference/rest/v2/AcceleratorConfig#Type min_version: 'beta' required: true immutable: true - enum_values: - - 'V2' - - 'V3' - - 'V4' - - 'V5P' - name: 'topology' type: String description: | From a673e6a57ac3e3530bfec2259fec378ed9110101 Mon Sep 17 00:00:00 2001 From: Mauricio Alvarez Leon <65101411+BBBmau@users.noreply.github.com> Date: Thu, 21 Nov 2024 03:43:54 -0800 Subject: [PATCH 104/105] Use TF v1.10.0-rc2 in FEATURE-BRANCH-ephemeral-resource (#12374) --- .../feature_branches/FEATURE-BRANCH-ephemeral-resource.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mmv1/third_party/terraform/.teamcity/components/projects/feature_branches/FEATURE-BRANCH-ephemeral-resource.kt b/mmv1/third_party/terraform/.teamcity/components/projects/feature_branches/FEATURE-BRANCH-ephemeral-resource.kt index a17f54efd05c..16b262454858 100644 --- a/mmv1/third_party/terraform/.teamcity/components/projects/feature_branches/FEATURE-BRANCH-ephemeral-resource.kt +++ b/mmv1/third_party/terraform/.teamcity/components/projects/feature_branches/FEATURE-BRANCH-ephemeral-resource.kt @@ -23,7 +23,7 @@ import vcs_roots.ModularMagicianVCSRootBeta import vcs_roots.ModularMagicianVCSRootGa const val featureBranchEphemeralResources = "FEATURE-BRANCH-ephemeral-resource" -const val EphemeralResourcesTfCoreVersion = "1.10.0-beta1" +const val EphemeralResourcesTfCoreVersion = "1.10.0-rc2" // featureBranchEphemeralResourcesSubProject creates a project just for testing ephemeral resources. // We know that all ephemeral resources we're adding are part of the Resource Manager service, so we only include those builds. From 4760ae5c1899423a0b4a3c4984df853f5b65960d Mon Sep 17 00:00:00 2001 From: Sarah French <15078782+SarahFrench@users.noreply.github.com> Date: Thu, 21 Nov 2024 16:47:07 +0000 Subject: [PATCH 105/105] Refactor muxing 1 : Re-use same config to configure the SDK and PF providers, fix VCR testing (#11903) --- .../acctest/framework_test_utils.go.tmpl | 27 ------ .../terraform/acctest/provider_test_utils.go | 1 - .../terraform/acctest/test_utils.go.tmpl | 8 +- .../terraform/acctest/vcr_utils.go | 94 ++++--------------- ...source_provider_config_plugin_framework.go | 90 ++++++++++++------ .../fwprovider/framework_provider.go.tmpl | 35 ++++--- ...amework_provider_access_token_test.go.tmpl | 6 +- ...er_add_terraform_attribution_label_test.go | 6 +- ...work_provider_billing_project_test.go.tmpl | 2 +- .../framework_provider_internal_test.go | 5 +- .../framework_provider_project_test.go | 4 +- .../framework_provider_request_reason_test.go | 4 +- ...framework_provider_request_timeout_test.go | 15 ++- ...ttribution_label_addition_strategy_test.go | 6 +- .../framework_provider_test.go.tmpl | 48 +++------- ...rovider_user_project_override_test.go.tmpl | 2 +- .../fwprovider/framework_validators_test.go | 52 ++++++++++ .../terraform/fwresource/field_helpers.go | 4 +- .../fwresource/framework_location.go | 4 +- mmv1/third_party/terraform/main.go.tmpl | 8 +- .../terraform/provider/provider.go.tmpl | 3 + .../provider/provider_request_timeout_test.go | 2 + ...google_firebase_android_app_config.go.tmpl | 19 ++-- ...e_firebase_android_app_config_test.go.tmpl | 2 - ...e_google_firebase_apple_app_config.go.tmpl | 17 ++-- ...gle_firebase_apple_app_config_test.go.tmpl | 17 +--- ...rce_google_firebase_web_app_config.go.tmpl | 17 ++-- .../resource_firebase_web_app_test.go.tmpl | 2 - .../data_source_google_client_config.go | 34 +++++-- ...ta_source_google_client_openid_userinfo.go | 14 ++- .../terraform/transport/config.go.tmpl | 26 ++++- 31 files changed, 301 insertions(+), 273 deletions(-) delete mode 100644 mmv1/third_party/terraform/acctest/framework_test_utils.go.tmpl diff --git a/mmv1/third_party/terraform/acctest/framework_test_utils.go.tmpl b/mmv1/third_party/terraform/acctest/framework_test_utils.go.tmpl deleted file mode 100644 index 4d4f113343ca..000000000000 --- a/mmv1/third_party/terraform/acctest/framework_test_utils.go.tmpl +++ /dev/null @@ -1,27 +0,0 @@ -package acctest - -import ( - "context" - "log" - "testing" - - "github.com/hashicorp/terraform-plugin-framework/diag" -) - -func GetFwTestProvider(t *testing.T) *frameworkTestProvider { - configsLock.RLock() - fwProvider, ok := fwProviders[t.Name()] - configsLock.RUnlock() - if ok { - return fwProvider - } - - var diags diag.Diagnostics - p := NewFrameworkTestProvider(t.Name()) - configureApiClient(context.Background(), &p.FrameworkProvider, &diags) - if diags.HasError() { - log.Fatalf("%d errors when configuring test provider client: first is %s", diags.ErrorsCount(), diags.Errors()[0].Detail()) - } - - return p -} diff --git a/mmv1/third_party/terraform/acctest/provider_test_utils.go b/mmv1/third_party/terraform/acctest/provider_test_utils.go index f30086539c1d..81bc0fd80a1d 100644 --- a/mmv1/third_party/terraform/acctest/provider_test_utils.go +++ b/mmv1/third_party/terraform/acctest/provider_test_utils.go @@ -20,7 +20,6 @@ var testAccProvider *schema.Provider func init() { configs = make(map[string]*transport_tpg.Config) - fwProviders = make(map[string]*frameworkTestProvider) sources = make(map[string]VcrSource) testAccProvider = provider.Provider() TestAccProviders = map[string]*schema.Provider{ diff --git a/mmv1/third_party/terraform/acctest/test_utils.go.tmpl b/mmv1/third_party/terraform/acctest/test_utils.go.tmpl index 69d453d068ef..0a11711382b8 100644 --- a/mmv1/third_party/terraform/acctest/test_utils.go.tmpl +++ b/mmv1/third_party/terraform/acctest/test_utils.go.tmpl @@ -81,9 +81,13 @@ func CheckDataSourceStateMatchesResourceStateWithIgnores(dataSourceName, resourc func MuxedProviders(testName string) (func() tfprotov5.ProviderServer, error) { ctx := context.Background() + // primary is the SDKv2 implementation of the provider + // If tests are run in VCR mode, the provider will use a cached config specific to the test name + primary := GetSDKProvider(testName) + providers := []func() tfprotov5.ProviderServer{ - providerserver.NewProtocol5(NewFrameworkTestProvider(testName)), // framework provider - GetSDKProvider(testName).GRPCProvider, // sdk provider + primary.GRPCProvider, // sdk provider + providerserver.NewProtocol5(NewFrameworkTestProvider(testName, primary)), // framework provider } muxServer, err := tf5muxserver.NewMuxServer(ctx, providers...) diff --git a/mmv1/third_party/terraform/acctest/vcr_utils.go b/mmv1/third_party/terraform/acctest/vcr_utils.go index 6fe133a0c1d1..5e55ca88cb2d 100644 --- a/mmv1/third_party/terraform/acctest/vcr_utils.go +++ b/mmv1/third_party/terraform/acctest/vcr_utils.go @@ -21,7 +21,6 @@ import ( "testing" "time" - "github.com/hashicorp/terraform-provider-google/google/fwmodels" "github.com/hashicorp/terraform-provider-google/google/fwprovider" tpgprovider "github.com/hashicorp/terraform-provider-google/google/provider" "github.com/hashicorp/terraform-provider-google/google/tpgresource" @@ -30,12 +29,9 @@ import ( "github.com/dnaeon/go-vcr/cassette" "github.com/dnaeon/go-vcr/recorder" - "github.com/hashicorp/terraform-plugin-framework/attr" "github.com/hashicorp/terraform-plugin-framework/datasource" - fwDiags "github.com/hashicorp/terraform-plugin-framework/diag" "github.com/hashicorp/terraform-plugin-framework/provider" - "github.com/hashicorp/terraform-plugin-framework/types" "github.com/hashicorp/terraform-plugin-go/tfprotov5" "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" @@ -53,7 +49,6 @@ var configsLock = sync.RWMutex{} var sourcesLock = sync.RWMutex{} var configs map[string]*transport_tpg.Config -var fwProviders map[string]*frameworkTestProvider var sources map[string]VcrSource @@ -203,39 +198,6 @@ func closeRecorder(t *testing.T) { delete(sources, t.Name()) sourcesLock.Unlock() } - - configsLock.RLock() - fwProvider, fwOk := fwProviders[t.Name()] - configsLock.RUnlock() - if fwOk { - // We did not cache the config if it does not use VCR - if !t.Failed() && IsVcrEnabled() { - // If a test succeeds, write new seed/yaml to files - err := fwProvider.Client.Transport.(*recorder.Recorder).Stop() - if err != nil { - t.Error(err) - } - envPath := os.Getenv("VCR_PATH") - - sourcesLock.RLock() - vcrSource, ok := sources[t.Name()] - sourcesLock.RUnlock() - if ok { - err = writeSeedToFile(vcrSource.seed, vcrSeedFile(envPath, t.Name())) - if err != nil { - t.Error(err) - } - } - } - // Clean up test config - configsLock.Lock() - delete(fwProviders, t.Name()) - configsLock.Unlock() - - sourcesLock.Lock() - delete(sources, t.Name()) - sourcesLock.Unlock() - } } func isReleaseDiffEnabled() bool { @@ -319,6 +281,11 @@ func reformConfigWithProvider(config, provider string) string { return string(resourceHeader.ReplaceAll(configBytes, providerReplacementBytes)) } +// HandleVCRConfiguration configures the recorder (github.com/dnaeon/go-vcr/recorder) used in the VCR test +// This includes: +// - Setting the recording/replaying mode +// - Determining the path to the file API interactions will be recorded to/read from +// - Determining the logic used to match requests against recorded HTTP interactions (see rec.SetMatcher) func HandleVCRConfiguration(ctx context.Context, testName string, rndTripper http.RoundTripper, pollInterval time.Duration) (time.Duration, http.RoundTripper, fwDiags.Diagnostics) { var diags fwDiags.Diagnostics var vcrMode recorder.Mode @@ -402,18 +369,18 @@ func NewVcrMatcherFunc(ctx context.Context) func(r *http.Request, i cassette.Req // test versions of the provider that will call the same configure function, only append the VCR // configuration to it. -func NewFrameworkTestProvider(testName string) *frameworkTestProvider { +func NewFrameworkTestProvider(testName string, primary *schema.Provider) *frameworkTestProvider { return &frameworkTestProvider{ FrameworkProvider: fwprovider.FrameworkProvider{ Version: "test", + Primary: primary, }, TestName: testName, } } -// frameworkTestProvider is a test version of the plugin-framework version of the provider -// that embeds FrameworkProvider whose configure function we can use -// the Configure function is overwritten in the framework_provider_test file +// frameworkTestProvider is a test version of the plugin-framework version of the provider. +// This facilitates overwriting the Configure function that's used during acceptance tests. type frameworkTestProvider struct { fwprovider.FrameworkProvider TestName string @@ -421,26 +388,13 @@ type frameworkTestProvider struct { // Configure is here to overwrite the FrameworkProvider configure function for VCR testing func (p *frameworkTestProvider) Configure(ctx context.Context, req provider.ConfigureRequest, resp *provider.ConfigureResponse) { - p.FrameworkProvider.Configure(ctx, req, resp) - if IsVcrEnabled() { - if resp.Diagnostics.HasError() { - return - } - - var diags fwDiags.Diagnostics - p.PollInterval, p.Client.Transport, diags = HandleVCRConfiguration(ctx, p.TestName, p.Client.Transport, p.PollInterval) - if diags.HasError() { - resp.Diagnostics.Append(diags...) - return - } - configsLock.Lock() - fwProviders[p.TestName] = p - configsLock.Unlock() - return - } else { - tflog.Debug(ctx, "VCR_PATH or VCR_MODE not set, skipping VCR") - } + // When creating the frameworkTestProvider struct we took in a pointer to the the SDK provider. + // That SDK provider was configured using `GetSDKProvider` and `getCachedConfig`, so this framework provider will also + // use a cached client for the correct test name. + // No extra logic is required here, but in future when the SDK provider is removed this function will + // need to be updated with logic similar to that in `GetSDKProvider`. + p.FrameworkProvider.Configure(ctx, req, resp) } // DataSources overrides the provider's DataSources function so that we can append test-specific data sources to the list of data sources on the provider. @@ -451,21 +405,9 @@ func (p *frameworkTestProvider) DataSources(ctx context.Context) []func() dataso return ds } -func configureApiClient(ctx context.Context, p *fwprovider.FrameworkProvider, diags *fwDiags.Diagnostics) { - var data fwmodels.ProviderModel - var d fwDiags.Diagnostics - - // Set defaults if needed - the only attribute without a default is ImpersonateServiceAccountDelegates - // this is a bit of a hack, but we'll just initialize it here so that it's been initialized at least - data.ImpersonateServiceAccountDelegates, d = types.ListValue(types.StringType, []attr.Value{}) - diags.Append(d...) - if diags.HasError() { - return - } - p.LoadAndValidateFramework(ctx, &data, "test", diags, p.Version) -} - -// GetSDKProvider gets the SDK provider with an overwritten configure function to be called by MuxedProviders +// GetSDKProvider gets the SDK provider for use in acceptance tests +// If VCR is in use, the configure function is overwritten. +// See usage in MuxedProviders func GetSDKProvider(testName string) *schema.Provider { prov := tpgprovider.Provider() diff --git a/mmv1/third_party/terraform/fwprovider/data_source_provider_config_plugin_framework.go b/mmv1/third_party/terraform/fwprovider/data_source_provider_config_plugin_framework.go index 315d2dd093fc..21d0e5b89e6b 100644 --- a/mmv1/third_party/terraform/fwprovider/data_source_provider_config_plugin_framework.go +++ b/mmv1/third_party/terraform/fwprovider/data_source_provider_config_plugin_framework.go @@ -4,13 +4,14 @@ import ( "context" "fmt" + "github.com/hashicorp/terraform-plugin-framework/attr" "github.com/hashicorp/terraform-plugin-framework/datasource" "github.com/hashicorp/terraform-plugin-framework/datasource/schema" "github.com/hashicorp/terraform-plugin-framework/diag" "github.com/hashicorp/terraform-plugin-framework/types" "github.com/hashicorp/terraform-provider-google/google/fwmodels" "github.com/hashicorp/terraform-provider-google/google/fwresource" - "github.com/hashicorp/terraform-provider-google/google/fwtransport" + transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" ) // Ensure the data source satisfies the expected interfaces. @@ -25,15 +26,17 @@ func NewGoogleProviderConfigPluginFrameworkDataSource() datasource.DataSource { } type GoogleProviderConfigPluginFrameworkDataSource struct { - providerConfig *fwtransport.FrameworkProviderConfig + providerConfig *transport_tpg.Config } +// GoogleProviderConfigPluginFrameworkModel describes the data source and matches the schema. Its fields match those in a Config struct (google/transport/config.go) but uses a different type system. +// - In the original Config struct old SDK/Go primitives types are used, e.g. `string` +// - Here in the GoogleProviderConfigPluginFrameworkModel struct we need to use the terraform-plugin-framework/types type system, e.g. `types.String` +// - This is needed because the PF type system is 'baked into' how we define schemas. The schema will expect a nullable type. +// - See terraform-plugin-framework/datasource/schema#StringAttribute's CustomType: https://pkg.go.dev/github.com/hashicorp/terraform-plugin-framework@v1.7.0/datasource/schema#StringAttribute +// - Due to the different type systems of Config versus GoogleProviderConfigPluginFrameworkModel struct, we need to convert from primitive types to terraform-plugin-framework/types when we populate +// GoogleProviderConfigPluginFrameworkModel structs with data in this data source's Read method. type GoogleProviderConfigPluginFrameworkModel struct { - // Currently this reflects the FrameworkProviderConfig struct and ProviderModel in google/fwmodels/provider_model.go - // which means it uses the plugin-framework type system where values can be explicitly Null or Unknown. - // - // As part of future muxing fixes/refactoring we'll change this struct to reflect structs used in the SDK code, and will move to - // using the SDK type system. Credentials types.String `tfsdk:"credentials"` AccessToken types.String `tfsdk:"access_token"` ImpersonateServiceAccount types.String `tfsdk:"impersonate_service_account"` @@ -53,12 +56,12 @@ type GoogleProviderConfigPluginFrameworkModel struct { TerraformAttributionLabelAdditionStrategy types.String `tfsdk:"terraform_attribution_label_addition_strategy"` } -func (m *GoogleProviderConfigPluginFrameworkModel) GetLocationDescription(providerConfig *fwtransport.FrameworkProviderConfig) fwresource.LocationDescription { +func (m *GoogleProviderConfigPluginFrameworkModel) GetLocationDescription(providerConfig *transport_tpg.Config) fwresource.LocationDescription { return fwresource.LocationDescription{ RegionSchemaField: types.StringValue("region"), ZoneSchemaField: types.StringValue("zone"), - ProviderRegion: providerConfig.Region, - ProviderZone: providerConfig.Zone, + ProviderRegion: types.StringValue(providerConfig.Region), + ProviderZone: types.StringValue(providerConfig.Zone), } } @@ -172,11 +175,11 @@ func (d *GoogleProviderConfigPluginFrameworkDataSource) Configure(ctx context.Co return } - p, ok := req.ProviderData.(*fwtransport.FrameworkProviderConfig) + p, ok := req.ProviderData.(*transport_tpg.Config) if !ok { resp.Diagnostics.AddError( "Unexpected Data Source Configure Type", - fmt.Sprintf("Expected *fwtransport.FrameworkProviderConfig, got: %T. Please report this issue to the provider developers.", req.ProviderData), + fmt.Sprintf("Expected *transport_tpg.Config, got: %T. Please report this issue to the provider developers.", req.ProviderData), ) return } @@ -202,23 +205,54 @@ func (d *GoogleProviderConfigPluginFrameworkDataSource) Read(ctx context.Context } // Copy all values from the provider config into this data source + // - The 'meta' from the provider configuration process uses Go primitive types (e.g. `string`) but this data source needs to use the plugin-framework type system due to being PF-implemented + // - As a result we have to make conversions between type systems in the value assignments below + data.Credentials = types.StringValue(d.providerConfig.Credentials) + data.AccessToken = types.StringValue(d.providerConfig.AccessToken) + data.ImpersonateServiceAccount = types.StringValue(d.providerConfig.ImpersonateServiceAccount) - data.Credentials = d.providerConfig.Credentials - data.AccessToken = d.providerConfig.AccessToken - data.ImpersonateServiceAccount = d.providerConfig.ImpersonateServiceAccount - data.ImpersonateServiceAccountDelegates = d.providerConfig.ImpersonateServiceAccountDelegates - data.Project = d.providerConfig.Project - data.Region = d.providerConfig.Region - data.BillingProject = d.providerConfig.BillingProject - data.Zone = d.providerConfig.Zone - data.UniverseDomain = d.providerConfig.UniverseDomain - data.Scopes = d.providerConfig.Scopes - data.UserProjectOverride = d.providerConfig.UserProjectOverride - data.RequestReason = d.providerConfig.RequestReason - data.RequestTimeout = d.providerConfig.RequestTimeout - data.DefaultLabels = d.providerConfig.DefaultLabels - data.AddTerraformAttributionLabel = d.providerConfig.AddTerraformAttributionLabel - data.TerraformAttributionLabelAdditionStrategy = d.providerConfig.TerraformAttributionLabelAdditionStrategy + delegateAttrs := make([]attr.Value, len(d.providerConfig.ImpersonateServiceAccountDelegates)) + for i, delegate := range d.providerConfig.ImpersonateServiceAccountDelegates { + delegateAttrs[i] = types.StringValue(delegate) + } + delegates, di := types.ListValue(types.StringType, delegateAttrs) + if di.HasError() { + resp.Diagnostics.Append(di...) + } + data.ImpersonateServiceAccountDelegates = delegates + + data.Project = types.StringValue(d.providerConfig.Project) + data.Region = types.StringValue(d.providerConfig.Region) + data.BillingProject = types.StringValue(d.providerConfig.BillingProject) + data.Zone = types.StringValue(d.providerConfig.Zone) + data.UniverseDomain = types.StringValue(d.providerConfig.UniverseDomain) + + scopeAttrs := make([]attr.Value, len(d.providerConfig.Scopes)) + for i, scope := range d.providerConfig.Scopes { + scopeAttrs[i] = types.StringValue(scope) + } + scopes, di := types.ListValue(types.StringType, scopeAttrs) + if di.HasError() { + resp.Diagnostics.Append(di...) + } + data.Scopes = scopes + + data.UserProjectOverride = types.BoolValue(d.providerConfig.UserProjectOverride) + data.RequestReason = types.StringValue(d.providerConfig.RequestReason) + data.RequestTimeout = types.StringValue(d.providerConfig.RequestTimeout.String()) + + lbs := make(map[string]attr.Value, len(d.providerConfig.DefaultLabels)) + for k, v := range d.providerConfig.DefaultLabels { + lbs[k] = types.StringValue(v) + } + labels, di := types.MapValueFrom(ctx, types.StringType, lbs) + if di.HasError() { + resp.Diagnostics.Append(di...) + } + data.DefaultLabels = labels + + data.AddTerraformAttributionLabel = types.BoolValue(d.providerConfig.AddTerraformAttributionLabel) + data.TerraformAttributionLabelAdditionStrategy = types.StringValue(d.providerConfig.TerraformAttributionLabelAdditionStrategy) // Warn users against using this data source resp.Diagnostics.Append(diag.NewWarningDiagnostic( diff --git a/mmv1/third_party/terraform/fwprovider/framework_provider.go.tmpl b/mmv1/third_party/terraform/fwprovider/framework_provider.go.tmpl index 60e7cc1ac23e..8122183eccd1 100644 --- a/mmv1/third_party/terraform/fwprovider/framework_provider.go.tmpl +++ b/mmv1/third_party/terraform/fwprovider/framework_provider.go.tmpl @@ -3,6 +3,8 @@ package fwprovider import ( "context" + sdk_schema "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" "github.com/hashicorp/terraform-plugin-framework/datasource" "github.com/hashicorp/terraform-plugin-framework/function" @@ -16,7 +18,6 @@ import ( "github.com/hashicorp/terraform-provider-google/google/functions" "github.com/hashicorp/terraform-provider-google/google/fwmodels" - "github.com/hashicorp/terraform-provider-google/google/fwtransport" "github.com/hashicorp/terraform-provider-google/google/services/resourcemanager" "github.com/hashicorp/terraform-provider-google/version" {{- if ne $.TargetVersionName "ga" }} @@ -34,16 +35,17 @@ var ( ) // New is a helper function to simplify provider server and testing implementation. -func New() provider.ProviderWithMetaSchema { +func New(primary *sdk_schema.Provider) provider.ProviderWithMetaSchema { return &FrameworkProvider{ Version: version.ProviderVersion, + Primary: primary, } } // FrameworkProvider is the provider implementation. type FrameworkProvider struct { - fwtransport.FrameworkProviderConfig Version string + Primary *sdk_schema.Provider } // Metadata returns @@ -66,6 +68,9 @@ func (p *FrameworkProvider) MetaSchema(_ context.Context, _ provider.MetaSchemaR } // Schema defines the provider-level schema for configuration data. +// See: https://developer.hashicorp.com/terraform/plugin/framework/migrating/mux +// "The schema and configuration handling must exactly match between all underlying providers of the mux server" +// This schema matches the schema implemented with SDKv2 in google/provider/provider.go func (p *FrameworkProvider) Schema(_ context.Context, _ provider.SchemaRequest, resp *provider.SchemaResponse) { resp.Schema = schema.Schema{ Attributes: map[string]schema.Attribute{ @@ -131,6 +136,10 @@ func (p *FrameworkProvider) Schema(_ context.Context, _ provider.SchemaRequest, }, "request_timeout": schema.StringAttribute{ Optional: true, + Validators: []validator.String{ + NonEmptyStringValidator(), + NonNegativeDurationValidator(), + }, }, "request_reason": schema.StringAttribute{ Optional: true, @@ -259,16 +268,20 @@ func (p *FrameworkProvider) Configure(ctx context.Context, req provider.Configur return } - // Configuration values are now available. - p.LoadAndValidateFramework(ctx, &data, req.TerraformVersion, &resp.Diagnostics, p.Version) - if resp.Diagnostics.HasError() { - return - } + // Configuration values are now available. + // However we don't use them; for the plugin-framework implementation of the provider + // we take the configuration values from the SDK implementation of the provider. This avoids duplicated logic and inconsistencies in implementation. + // The trade off is that we don't benefit from the new type system that differentiates Null and Unknown values, which is especially useful for strings. + // This makes it necessary to write code that stops empty strings (etc) being passed from the Config struct to PF-implemented resources/datasources. + // E.g. GetProjectFramework treats Null and "" the same way : https://github.com/hashicorp/terraform-provider-google/blob/74c815ee4ad059453e06b84448af244d80490ec1/google/fwresource/field_helpers.go#L21-L36 + // See also, new approaches to handle this: https://github.com/GoogleCloudPlatform/magic-modules/pull/11925 + // This is how we make provider configuration info (configured clients, default project, etc) available to resources and data sources - // implemented using the plugin-framework. The resources' Configure functions receive this data in the ConfigureRequest argument. - resp.DataSourceData = &p.FrameworkProviderConfig - resp.ResourceData = &p.FrameworkProviderConfig + // implemented using the plugin-framework. The resources' Configure functions receive this data in the ConfigureRequest argument. + meta := p.Primary.Meta().(*transport_tpg.Config) + resp.DataSourceData = meta + resp.ResourceData = meta } diff --git a/mmv1/third_party/terraform/fwprovider/framework_provider_access_token_test.go.tmpl b/mmv1/third_party/terraform/fwprovider/framework_provider_access_token_test.go.tmpl index ccc304e8cad1..6794da8e9d1d 100644 --- a/mmv1/third_party/terraform/fwprovider/framework_provider_access_token_test.go.tmpl +++ b/mmv1/third_party/terraform/fwprovider/framework_provider_access_token_test.go.tmpl @@ -191,7 +191,7 @@ credentials = "%s" Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("data.google_provider_config_plugin_framework.default", "access_token", accessToken), // not set as ENV not used - resource.TestCheckNoResourceAttr("data.google_provider_config_plugin_framework.default", "credentials"), + resource.TestCheckResourceAttr("data.google_provider_config_plugin_framework.default", "credentials", ""), ), }, { @@ -204,7 +204,7 @@ credentials = "%s" Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("data.google_provider_config_sdk.default", "credentials", credentials), // not set, as ENV not used - resource.TestCheckNoResourceAttr("data.google_provider_config_sdk.default", "access_token"), + resource.TestCheckResourceAttr("data.google_provider_config_sdk.default", "access_token", ""), ), ExpectError: regexp.MustCompile("JSON credentials are not valid"), }, @@ -258,7 +258,7 @@ func testAccFwProvider_access_token_authInUse(t *testing.T) { Check: resource.ComposeAggregateTestCheckFunc( // Assert provider is using access_token argument for auth, not credentials resource.TestCheckResourceAttrSet("data.google_provider_config_plugin_framework.default", "access_token"), - resource.TestCheckNoResourceAttr("data.google_provider_config_plugin_framework.default", "credentials"), + resource.TestCheckResourceAttr("data.google_provider_config_plugin_framework.default", "credentials", ""), ), }, }, diff --git a/mmv1/third_party/terraform/fwprovider/framework_provider_add_terraform_attribution_label_test.go b/mmv1/third_party/terraform/fwprovider/framework_provider_add_terraform_attribution_label_test.go index d9eeb07ed5a2..e99a00e8a4f3 100644 --- a/mmv1/third_party/terraform/fwprovider/framework_provider_add_terraform_attribution_label_test.go +++ b/mmv1/third_party/terraform/fwprovider/framework_provider_add_terraform_attribution_label_test.go @@ -13,8 +13,8 @@ import ( func TestAccFwProvider_add_terraform_attribution_label(t *testing.T) { testCases := map[string]func(t *testing.T){ // Configuring the provider using inputs - "when add_terraform_attribution_label is set in the config, the value is set in the provider meta data": testAccFwProvider_add_terraform_attribution_label_configUsed, - "when add_terraform_attribution_label is unset in the config, the default value 'true' is NOT set on the provider meta data": testAccFwProvider_add_terraform_attribution_label_defaultValue, + "when add_terraform_attribution_label is set in the config, the value is set in the provider meta data": testAccFwProvider_add_terraform_attribution_label_configUsed, + "when add_terraform_attribution_label is unset in the config, the default value 'true' is set on the provider meta data": testAccFwProvider_add_terraform_attribution_label_defaultValue, } for name, tc := range testCases { @@ -71,7 +71,7 @@ func testAccFwProvider_add_terraform_attribution_label_defaultValue(t *testing.T { Config: testAccFwProvider_add_terraform_attribution_label_inEnvsOnly(context), Check: resource.ComposeTestCheckFunc( - resource.TestCheckNoResourceAttr("data.google_provider_config_plugin_framework.default", "add_terraform_attribution_label"), + resource.TestCheckResourceAttr("data.google_provider_config_plugin_framework.default", "add_terraform_attribution_label", "true"), ), }, }, diff --git a/mmv1/third_party/terraform/fwprovider/framework_provider_billing_project_test.go.tmpl b/mmv1/third_party/terraform/fwprovider/framework_provider_billing_project_test.go.tmpl index 37fcb7137fa7..a5d6f428d0b4 100644 --- a/mmv1/third_party/terraform/fwprovider/framework_provider_billing_project_test.go.tmpl +++ b/mmv1/third_party/terraform/fwprovider/framework_provider_billing_project_test.go.tmpl @@ -111,7 +111,7 @@ func testAccFwProvider_billing_project_precedenceOrderEnvironmentVariables(t *te }, Config: testAccFwProvider_billing_project_inEnvsOnly(context), Check: resource.ComposeAggregateTestCheckFunc( - resource.TestCheckNoResourceAttr("data.google_provider_config_plugin_framework.default", "billing_project"), + resource.TestCheckResourceAttr("data.google_provider_config_plugin_framework.default", "billing_project", ""), ), }, }, diff --git a/mmv1/third_party/terraform/fwprovider/framework_provider_internal_test.go b/mmv1/third_party/terraform/fwprovider/framework_provider_internal_test.go index 8c4eff047541..539498d423b3 100644 --- a/mmv1/third_party/terraform/fwprovider/framework_provider_internal_test.go +++ b/mmv1/third_party/terraform/fwprovider/framework_provider_internal_test.go @@ -5,8 +5,11 @@ import ( "github.com/hashicorp/terraform-plugin-framework/provider" "github.com/hashicorp/terraform-provider-google/google/fwprovider" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) func TestFrameworkProvider_impl(t *testing.T) { - var _ provider.ProviderWithMetaSchema = fwprovider.New() + primary := &schema.Provider{} + var _ provider.ProviderWithMetaSchema = fwprovider.New(primary) } diff --git a/mmv1/third_party/terraform/fwprovider/framework_provider_project_test.go b/mmv1/third_party/terraform/fwprovider/framework_provider_project_test.go index e7b41bcfc2cf..1f4c23eebc4f 100644 --- a/mmv1/third_party/terraform/fwprovider/framework_provider_project_test.go +++ b/mmv1/third_party/terraform/fwprovider/framework_provider_project_test.go @@ -87,9 +87,7 @@ func testAccFwProvider_project_precedenceOrderEnvironmentVariables(t *testing.T) }, Config: testAccFwProvider_projectInEnvsOnly(), Check: resource.ComposeTestCheckFunc( - // Differing behavior between SDK and PF; the attribute is NOT found here. - // This reflects the different type systems used in the SDKv2 and the plugin-framework - resource.TestCheckNoResourceAttr("data.google_provider_config_plugin_framework.default", "project"), + resource.TestCheckResourceAttr("data.google_provider_config_plugin_framework.default", "project", ""), ), }, { diff --git a/mmv1/third_party/terraform/fwprovider/framework_provider_request_reason_test.go b/mmv1/third_party/terraform/fwprovider/framework_provider_request_reason_test.go index c2845d24b382..5431ee81c218 100644 --- a/mmv1/third_party/terraform/fwprovider/framework_provider_request_reason_test.go +++ b/mmv1/third_party/terraform/fwprovider/framework_provider_request_reason_test.go @@ -18,7 +18,7 @@ func TestAccFwProvider_request_reason(t *testing.T) { // Schema-level validation // TODO: https://github.com/hashicorp/terraform-provider-google/issues/19643 - "when request_reason is set to an empty string in the config the value is not ignored, and there isn't any validation about this that raises an error": testAccFwProvider_request_reason_emptyStringValidation, + "when request_reason is set to an empty string in the config the value IS ignored, allowing environment values to be used": testAccFwProvider_request_reason_emptyStringValidation, // Usage // We cannot test the impact of this field in an acc test, as it sets the X-Goog-Request-Reason value for audit logging purposes in GCP @@ -116,7 +116,7 @@ func testAccFwProvider_request_reason_emptyStringValidation(t *testing.T) { Check: resource.ComposeAggregateTestCheckFunc( // Currently the PF provider uses empty strings, instead of providing validation feedback to users // See: https://github.com/hashicorp/terraform-provider-google/issues/19643 - resource.TestCheckResourceAttr("data.google_provider_config_plugin_framework.default", "request_reason", emptyString), + resource.TestCheckResourceAttr("data.google_provider_config_plugin_framework.default", "request_reason", envReason), ), }, }, diff --git a/mmv1/third_party/terraform/fwprovider/framework_provider_request_timeout_test.go b/mmv1/third_party/terraform/fwprovider/framework_provider_request_timeout_test.go index aa22b6a496f5..d17f26034676 100644 --- a/mmv1/third_party/terraform/fwprovider/framework_provider_request_timeout_test.go +++ b/mmv1/third_party/terraform/fwprovider/framework_provider_request_timeout_test.go @@ -14,8 +14,8 @@ import ( func TestAccFwProvider_request_timeout(t *testing.T) { testCases := map[string]func(t *testing.T){ // Configuring the provider using inputs - "a default value of 120s is used when there are no user inputs": testAccFwProvider_request_timeout_providerDefault, - "request_timeout can be set in config in different formats, are NOT normalized to full-length format": testAccFwProvider_request_timeout_setInConfig, + "a default value of 0s is used when there are no user inputs": testAccFwProvider_request_timeout_providerDefault, + "request_timeout can be set in config in different formats, are normalized to full-length format": testAccFwProvider_request_timeout_setInConfig, //no ENVs to test // Schema-level validation @@ -40,7 +40,7 @@ func TestAccFwProvider_request_timeout(t *testing.T) { func testAccFwProvider_request_timeout_providerDefault(t *testing.T) { acctest.SkipIfVcr(t) // Test doesn't interact with API - defaultValue := "120s" + defaultValue := "0s" acctest.VcrTest(t, resource.TestCase{ // No PreCheck for checking ENVs @@ -62,9 +62,8 @@ func testAccFwProvider_request_timeout_setInConfig(t *testing.T) { providerTimeout1 := "3m0s" providerTimeout2 := "3m" - // In the SDK version of the test expectedValue = "3m0s" only - expectedValue1 := "3m0s" - expectedValue2 := "3m" + // All inputs are normalised to this + expectedValue := "3m0s" context1 := map[string]interface{}{ "request_timeout": providerTimeout1, @@ -80,13 +79,13 @@ func testAccFwProvider_request_timeout_setInConfig(t *testing.T) { { Config: testAccFwProvider_request_timeout_inProviderBlock(context1), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("data.google_provider_config_plugin_framework.default", "request_timeout", expectedValue1), + resource.TestCheckResourceAttr("data.google_provider_config_plugin_framework.default", "request_timeout", expectedValue), ), }, { Config: testAccFwProvider_request_timeout_inProviderBlock(context2), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("data.google_provider_config_plugin_framework.default", "request_timeout", expectedValue2), + resource.TestCheckResourceAttr("data.google_provider_config_plugin_framework.default", "request_timeout", expectedValue), ), }, }, diff --git a/mmv1/third_party/terraform/fwprovider/framework_provider_terraform_attribution_label_addition_strategy_test.go b/mmv1/third_party/terraform/fwprovider/framework_provider_terraform_attribution_label_addition_strategy_test.go index 921edce47d38..b45a9d68bee4 100644 --- a/mmv1/third_party/terraform/fwprovider/framework_provider_terraform_attribution_label_addition_strategy_test.go +++ b/mmv1/third_party/terraform/fwprovider/framework_provider_terraform_attribution_label_addition_strategy_test.go @@ -13,8 +13,8 @@ import ( func TestAccFwProvider_terraform_attribution_label_addition_strategy(t *testing.T) { testCases := map[string]func(t *testing.T){ // Configuring the provider using inputs - "config sets terraform_attribution_label_addition_strategy values": testAccFwProvider_terraform_attribution_label_addition_strategy_configUsed, - "when terraform_attribution_label_addition_strategy is unset in the config, the default value'CREATION_ONLY' is NOT set in the provider meta data": testAccFwProvider_terraform_attribution_label_addition_strategy_defaultValue, + "config sets terraform_attribution_label_addition_strategy values": testAccFwProvider_terraform_attribution_label_addition_strategy_configUsed, + "when terraform_attribution_label_addition_strategy is unset in the config, the default value 'CREATION_ONLY' is set in the provider meta data": testAccFwProvider_terraform_attribution_label_addition_strategy_defaultValue, } for name, tc := range testCases { @@ -71,7 +71,7 @@ func testAccFwProvider_terraform_attribution_label_addition_strategy_defaultValu { Config: testAccFwProvider_terraform_attribution_label_addition_strategy_inEnvsOnly(context), Check: resource.ComposeTestCheckFunc( - resource.TestCheckNoResourceAttr("data.google_provider_config_plugin_framework.default", "terraform_attribution_label_addition_strategy"), + resource.TestCheckResourceAttr("data.google_provider_config_plugin_framework.default", "terraform_attribution_label_addition_strategy", "CREATION_ONLY"), ), }, }, diff --git a/mmv1/third_party/terraform/fwprovider/framework_provider_test.go.tmpl b/mmv1/third_party/terraform/fwprovider/framework_provider_test.go.tmpl index 0a910cabedaf..fe8a1d3677dc 100644 --- a/mmv1/third_party/terraform/fwprovider/framework_provider_test.go.tmpl +++ b/mmv1/third_party/terraform/fwprovider/framework_provider_test.go.tmpl @@ -11,14 +11,11 @@ import ( "github.com/hashicorp/terraform-provider-google/google/acctest" "github.com/hashicorp/terraform-provider-google/google/fwresource" - "github.com/hashicorp/terraform-provider-google/google/fwtransport" "github.com/hashicorp/terraform-provider-google/google/tpgresource" transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" ) func TestAccFrameworkProviderMeta_setModuleName(t *testing.T) { - // TODO: https://github.com/hashicorp/terraform-provider-google/issues/14158 - acctest.SkipIfVcr(t) t.Parallel() moduleName := "my-module" @@ -63,46 +60,22 @@ func TestAccFrameworkProviderBasePath_setInvalidBasePath(t *testing.T) { } func TestAccFrameworkProviderBasePath_setBasePath(t *testing.T) { - // TODO: https://github.com/hashicorp/terraform-provider-google/issues/14158 - acctest.SkipIfVcr(t) t.Parallel() acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, CheckDestroy: testAccCheckDNSManagedZoneDestroyProducerFramework(t), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), Steps: []resource.TestStep{ { - ExternalProviders: map[string]resource.ExternalProvider{ - "google": { - VersionConstraint: "4.58.0", - Source: "hashicorp/google{{- if ne $.TargetVersionName "ga" -}}-{{$.TargetVersionName}}{{- end }}", - }, - }, - Config: testAccFrameworkProviderBasePath_setBasePath("https://www.googleapis.com/dns/v1beta2/", acctest.RandString(t, 10)), - }, - { - ExternalProviders: map[string]resource.ExternalProvider{ - "google": { - VersionConstraint: "4.58.0", - Source: "hashicorp/google{{- if ne $.TargetVersionName "ga" -}}-{{$.TargetVersionName}}{{- end }}", - }, - }, - ResourceName: "google_dns_managed_zone.foo", - ImportState: true, - ImportStateVerify: true, - }, - { - ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), Config: testAccFrameworkProviderBasePath_setBasePath("https://www.googleapis.com/dns/v1beta2/", acctest.RandString(t, 10)), }, { - ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), ResourceName: "google_dns_managed_zone.foo", ImportState: true, ImportStateVerify: true, }, { - ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), Config: testAccFrameworkProviderBasePath_setBasePathstep3("https://www.googleapis.com/dns/v1beta2/", acctest.RandString(t, 10)), }, }, @@ -221,21 +194,28 @@ func testAccCheckDNSManagedZoneDestroyProducerFramework(t *testing.T) func(s *te continue } - p := acctest.GetFwTestProvider(t) + config := acctest.GoogleProviderConfig(t) - url, err := fwresource.ReplaceVarsForFrameworkTest(&p.FrameworkProvider.FrameworkProviderConfig, rs, "{{"{{"}}DNSBasePath{{"}}"}}projects/{{"{{"}}project{{"}}"}}/managedZones/{{"{{"}}name{{"}}"}}") + url, err := fwresource.ReplaceVarsForFrameworkTest(config, rs, "{{"{{"}}DNSBasePath{{"}}"}}projects/{{"{{"}}project{{"}}"}}/managedZones/{{"{{"}}name{{"}}"}}") if err != nil { return err } billingProject := "" - if !p.BillingProject.IsNull() && p.BillingProject.String() != "" { - billingProject = p.BillingProject.String() + if config.BillingProject != "" { + billingProject = config.BillingProject } - _, diags := fwtransport.SendFrameworkRequest(&p.FrameworkProvider.FrameworkProviderConfig, "GET", billingProject, url, p.UserAgent, nil) - if !diags.HasError() { + _, err = transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "GET", + Project: billingProject, + RawURL: url, + UserAgent: config.UserAgent, + }) + + if err == nil { return fmt.Errorf("DNSManagedZone still exists at %s", url) } } diff --git a/mmv1/third_party/terraform/fwprovider/framework_provider_user_project_override_test.go.tmpl b/mmv1/third_party/terraform/fwprovider/framework_provider_user_project_override_test.go.tmpl index 5576186241a8..1bdf6a8ea3b2 100644 --- a/mmv1/third_party/terraform/fwprovider/framework_provider_user_project_override_test.go.tmpl +++ b/mmv1/third_party/terraform/fwprovider/framework_provider_user_project_override_test.go.tmpl @@ -95,7 +95,7 @@ func testAccFwProvider_user_project_override_precedenceOrderEnvironmentVariables }, Config: testAccFwProvider_user_project_overrideInEnvsOnly(context), Check: resource.ComposeAggregateTestCheckFunc( - resource.TestCheckNoResourceAttr("data.google_provider_config_plugin_framework.default", "user_project_override"), + resource.TestCheckResourceAttr("data.google_provider_config_plugin_framework.default", "user_project_override", "false"), ), }, { diff --git a/mmv1/third_party/terraform/fwprovider/framework_validators_test.go b/mmv1/third_party/terraform/fwprovider/framework_validators_test.go index 6462f3af43b8..c1baad021621 100644 --- a/mmv1/third_party/terraform/fwprovider/framework_validators_test.go +++ b/mmv1/third_party/terraform/fwprovider/framework_validators_test.go @@ -65,3 +65,55 @@ func TestFrameworkProvider_CredentialsValidator(t *testing.T) { }) } } + +func TestFrameworkProvider_NonNegativeDurationValidator(t *testing.T) { + cases := map[string]struct { + ConfigValue types.String + ExpectedWarningCount int + ExpectedErrorCount int + }{ + "3m is a valid, non-negative duration": { + ConfigValue: types.StringValue("3m"), + }, + "3m0s is a valid, non-negative duration": { + ConfigValue: types.StringValue("3m0s"), + }, + "0s is a valid, non-negative duration": { + ConfigValue: types.StringValue("0s"), + }, + "-0s not valid, as it is a negative duration": { + ConfigValue: types.StringValue("-0s"), + ExpectedErrorCount: 1, + }, + "empty strings are not valid, non-negative durations": { + ConfigValue: types.StringValue(""), + ExpectedErrorCount: 1, + }, + } + + for tn, tc := range cases { + t.Run(tn, func(t *testing.T) { + // Arrange + req := validator.StringRequest{ + ConfigValue: tc.ConfigValue, + } + + resp := validator.StringResponse{ + Diagnostics: diag.Diagnostics{}, + } + + cv := fwprovider.NonNegativeDurationValidator() + + // Act + cv.ValidateString(context.Background(), req, &resp) + + // Assert + if resp.Diagnostics.WarningsCount() > tc.ExpectedWarningCount { + t.Errorf("Expected %d warnings, got %d", tc.ExpectedWarningCount, resp.Diagnostics.WarningsCount()) + } + if resp.Diagnostics.ErrorsCount() > tc.ExpectedErrorCount { + t.Errorf("Expected %d errors, got %d", tc.ExpectedErrorCount, resp.Diagnostics.ErrorsCount()) + } + }) + } +} diff --git a/mmv1/third_party/terraform/fwresource/field_helpers.go b/mmv1/third_party/terraform/fwresource/field_helpers.go index cfc09b5337a7..54788d8346e7 100644 --- a/mmv1/third_party/terraform/fwresource/field_helpers.go +++ b/mmv1/third_party/terraform/fwresource/field_helpers.go @@ -9,8 +9,8 @@ import ( "github.com/hashicorp/terraform-plugin-framework/diag" "github.com/hashicorp/terraform-plugin-framework/types" "github.com/hashicorp/terraform-plugin-testing/terraform" - "github.com/hashicorp/terraform-provider-google/google/fwtransport" "github.com/hashicorp/terraform-provider-google/google/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" ) // GetProject reads the "project" field from the given resource and falls @@ -69,7 +69,7 @@ func ParseProjectFieldValueFramework(resourceType, fieldValue, projectSchemaFiel // This function isn't a test of transport.go; instead, it is used as an alternative // to ReplaceVars inside tests. -func ReplaceVarsForFrameworkTest(prov *fwtransport.FrameworkProviderConfig, rs *terraform.ResourceState, linkTmpl string) (string, error) { +func ReplaceVarsForFrameworkTest(prov *transport_tpg.Config, rs *terraform.ResourceState, linkTmpl string) (string, error) { re := regexp.MustCompile("{{([[:word:]]+)}}") var project, region, zone string diff --git a/mmv1/third_party/terraform/fwresource/framework_location.go b/mmv1/third_party/terraform/fwresource/framework_location.go index 609ab65b98b1..565aa9089420 100644 --- a/mmv1/third_party/terraform/fwresource/framework_location.go +++ b/mmv1/third_party/terraform/fwresource/framework_location.go @@ -5,12 +5,12 @@ import ( "fmt" "github.com/hashicorp/terraform-plugin-framework/types" - "github.com/hashicorp/terraform-provider-google/google/fwtransport" "github.com/hashicorp/terraform-provider-google/google/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" ) type LocationDescriber interface { - GetLocationDescription(providerConfig *fwtransport.FrameworkProviderConfig) LocationDescription + GetLocationDescription(providerConfig *transport_tpg.Config) LocationDescription } type LocationDescription struct { diff --git a/mmv1/third_party/terraform/main.go.tmpl b/mmv1/third_party/terraform/main.go.tmpl index 8bb1fb9fd4de..928a117a33db 100644 --- a/mmv1/third_party/terraform/main.go.tmpl +++ b/mmv1/third_party/terraform/main.go.tmpl @@ -20,10 +20,12 @@ func main() { flag.BoolVar(&debug, "debug", false, "set to true to run the provider with support for debuggers like delve") flag.Parse() - // concat with sdkv2 provider + // primary is the SDKv2 implementation of the provider + primary := provider.Provider() + providers := []func() tfprotov5.ProviderServer{ - providerserver.NewProtocol5(fwprovider.New()), // framework provider - provider.Provider().GRPCProvider, // sdk provider + primary.GRPCProvider, // sdk provider + providerserver.NewProtocol5(fwprovider.New(primary)), // framework provider } // use the muxer diff --git a/mmv1/third_party/terraform/provider/provider.go.tmpl b/mmv1/third_party/terraform/provider/provider.go.tmpl index bece351a6b7f..066592474b49 100644 --- a/mmv1/third_party/terraform/provider/provider.go.tmpl +++ b/mmv1/third_party/terraform/provider/provider.go.tmpl @@ -29,6 +29,9 @@ func Provider() *schema.Provider { } provider := &schema.Provider{ + // See: https://developer.hashicorp.com/terraform/plugin/framework/migrating/mux + // "The schema and configuration handling must exactly match between all underlying providers of the mux server" + // This schema matches the schema implemented with the plugin-framework in google/fwprovider/framework_provider.go Schema: map[string]*schema.Schema{ "credentials": { Type: schema.TypeString, diff --git a/mmv1/third_party/terraform/provider/provider_request_timeout_test.go b/mmv1/third_party/terraform/provider/provider_request_timeout_test.go index cd57877a8bf4..b48802d07ce1 100644 --- a/mmv1/third_party/terraform/provider/provider_request_timeout_test.go +++ b/mmv1/third_party/terraform/provider/provider_request_timeout_test.go @@ -62,6 +62,8 @@ func testAccSdkProvider_request_timeout_setInConfig(t *testing.T) { providerTimeout1 := "3m0s" providerTimeout2 := "3m" + + // All inputs are normalised to this expectedValue := "3m0s" context1 := map[string]interface{}{ diff --git a/mmv1/third_party/terraform/services/firebase/data_source_google_firebase_android_app_config.go.tmpl b/mmv1/third_party/terraform/services/firebase/data_source_google_firebase_android_app_config.go.tmpl index cb8aef4a8a2d..0755b2f3740a 100644 --- a/mmv1/third_party/terraform/services/firebase/data_source_google_firebase_android_app_config.go.tmpl +++ b/mmv1/third_party/terraform/services/firebase/data_source_google_firebase_android_app_config.go.tmpl @@ -5,7 +5,7 @@ import ( "context" "fmt" - "google.golang.org/api/firebase/v1beta1" + firebase "google.golang.org/api/firebase/v1beta1" "github.com/hashicorp/terraform-plugin-framework/datasource" "github.com/hashicorp/terraform-plugin-framework/datasource/schema" @@ -13,8 +13,9 @@ import ( "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-provider-google/google/fwmodels" - "github.com/hashicorp/terraform-provider-google/google/fwtransport" "github.com/hashicorp/terraform-provider-google/google/fwresource" + "github.com/hashicorp/terraform-provider-google/google/fwtransport" + transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" ) // Ensure the implementation satisfies the expected interfaces @@ -29,8 +30,8 @@ func NewGoogleFirebaseAndroidAppConfigDataSource() datasource.DataSource { // GoogleFirebaseAndroidAppConfigDataSource defines the data source implementation type GoogleFirebaseAndroidAppConfigDataSource struct { - client *firebase.Service - project types.String + client *firebase.Service + providerConfig *transport_tpg.Config } type GoogleFirebaseAndroidAppConfigModel struct { @@ -91,20 +92,20 @@ func (d *GoogleFirebaseAndroidAppConfigDataSource) Configure(ctx context.Context return } - p, ok := req.ProviderData.(*fwtransport.FrameworkProviderConfig) + p, ok := req.ProviderData.(*transport_tpg.Config) if !ok { resp.Diagnostics.AddError( "Unexpected Data Source Configure Type", - fmt.Sprintf("Expected *fwtransport.FrameworkProviderConfig, got: %T. Please report this issue to the provider developers.", req.ProviderData), + fmt.Sprintf("Expected *transport_tpg.Config, got: %T. Please report this issue to the provider developers.", req.ProviderData), ) return } - d.client = p.NewFirebaseClient(p.UserAgent, &resp.Diagnostics) + d.client = p.NewFirebaseClient(ctx, p.UserAgent) if resp.Diagnostics.HasError() { return } - d.project = p.Project + d.providerConfig = p } func (d *GoogleFirebaseAndroidAppConfigDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { @@ -126,7 +127,7 @@ func (d *GoogleFirebaseAndroidAppConfigDataSource) Read(ctx context.Context, req // Use provider_meta to set User-Agent d.client.UserAgent = fwtransport.GenerateFrameworkUserAgentString(metaData, d.client.UserAgent) - data.Project = fwresource.GetProjectFramework(data.Project, d.project, &resp.Diagnostics) + data.Project = fwresource.GetProjectFramework(data.Project, types.StringValue(d.providerConfig.Project), &resp.Diagnostics) if resp.Diagnostics.HasError() { return } diff --git a/mmv1/third_party/terraform/services/firebase/data_source_google_firebase_android_app_config_test.go.tmpl b/mmv1/third_party/terraform/services/firebase/data_source_google_firebase_android_app_config_test.go.tmpl index dc799efdc85d..7280759962b9 100644 --- a/mmv1/third_party/terraform/services/firebase/data_source_google_firebase_android_app_config_test.go.tmpl +++ b/mmv1/third_party/terraform/services/firebase/data_source_google_firebase_android_app_config_test.go.tmpl @@ -11,8 +11,6 @@ import ( func TestAccDataSourceGoogleFirebaseAndroidAppConfig(t *testing.T) { t.Parallel() - // Framework-based resources and datasources don't work with VCR yet - acctest.SkipIfVcr(t) context := map[string]interface{}{ "project_id": envvar.GetTestProjectFromEnv(), diff --git a/mmv1/third_party/terraform/services/firebase/data_source_google_firebase_apple_app_config.go.tmpl b/mmv1/third_party/terraform/services/firebase/data_source_google_firebase_apple_app_config.go.tmpl index 69d1da3451ea..8dfdf61f9dc2 100644 --- a/mmv1/third_party/terraform/services/firebase/data_source_google_firebase_apple_app_config.go.tmpl +++ b/mmv1/third_party/terraform/services/firebase/data_source_google_firebase_apple_app_config.go.tmpl @@ -5,7 +5,7 @@ import ( "context" "fmt" - "google.golang.org/api/firebase/v1beta1" + firebase "google.golang.org/api/firebase/v1beta1" "github.com/hashicorp/terraform-plugin-framework/datasource" "github.com/hashicorp/terraform-plugin-framework/datasource/schema" @@ -15,6 +15,7 @@ import ( "github.com/hashicorp/terraform-provider-google/google/fwmodels" "github.com/hashicorp/terraform-provider-google/google/fwresource" "github.com/hashicorp/terraform-provider-google/google/fwtransport" + transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" ) // Ensure the implementation satisfies the expected interfaces @@ -29,8 +30,8 @@ func NewGoogleFirebaseAppleAppConfigDataSource() datasource.DataSource { // GoogleFirebaseAppleAppConfigDataSource defines the data source implementation type GoogleFirebaseAppleAppConfigDataSource struct { - client *firebase.Service - project types.String + client *firebase.Service + providerConfig *transport_tpg.Config } type GoogleFirebaseAppleAppConfigModel struct { @@ -91,20 +92,20 @@ func (d *GoogleFirebaseAppleAppConfigDataSource) Configure(ctx context.Context, return } - p, ok := req.ProviderData.(*fwtransport.FrameworkProviderConfig) + p, ok := req.ProviderData.(*transport_tpg.Config) if !ok { resp.Diagnostics.AddError( "Unexpected Data Source Configure Type", - fmt.Sprintf("Expected *fwtransport.FrameworkProviderConfig, got: %T. Please report this issue to the provider developers.", req.ProviderData), + fmt.Sprintf("Expected *transport_tpg.Config, got: %T. Please report this issue to the provider developers.", req.ProviderData), ) return } - d.client = p.NewFirebaseClient(p.UserAgent, &resp.Diagnostics) + d.client = p.NewFirebaseClient(ctx, p.UserAgent) if resp.Diagnostics.HasError() { return } - d.project = p.Project + d.providerConfig = p } func (d *GoogleFirebaseAppleAppConfigDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { @@ -126,7 +127,7 @@ func (d *GoogleFirebaseAppleAppConfigDataSource) Read(ctx context.Context, req d // Use provider_meta to set User-Agent d.client.UserAgent = fwtransport.GenerateFrameworkUserAgentString(metaData, d.client.UserAgent) - data.Project = fwresource.GetProjectFramework(data.Project, d.project, &resp.Diagnostics) + data.Project = fwresource.GetProjectFramework(data.Project, types.StringValue(d.providerConfig.Project), &resp.Diagnostics) if resp.Diagnostics.HasError() { return } diff --git a/mmv1/third_party/terraform/services/firebase/data_source_google_firebase_apple_app_config_test.go.tmpl b/mmv1/third_party/terraform/services/firebase/data_source_google_firebase_apple_app_config_test.go.tmpl index c71113abac3e..f94c796b6759 100644 --- a/mmv1/third_party/terraform/services/firebase/data_source_google_firebase_apple_app_config_test.go.tmpl +++ b/mmv1/third_party/terraform/services/firebase/data_source_google_firebase_apple_app_config_test.go.tmpl @@ -10,8 +10,6 @@ import ( ) func TestAccDataSourceGoogleFirebaseAppleAppConfig(t *testing.T) { - // TODO: https://github.com/hashicorp/terraform-provider-google/issues/14158 - acctest.SkipIfVcr(t) t.Parallel() context := map[string]interface{}{ @@ -23,20 +21,9 @@ func TestAccDataSourceGoogleFirebaseAppleAppConfig(t *testing.T) { } acctest.VcrTest(t, resource.TestCase{ - PreCheck: func() { acctest.AccTestPreCheck(t) }, + PreCheck: func() { acctest.AccTestPreCheck(t) }, + CheckDestroy: testAccCheckFirebaseAppleAppDestroyProducer(t), Steps: []resource.TestStep{ - { - ExternalProviders: map[string]resource.ExternalProvider{ - "google": { - VersionConstraint: "4.58.0", - Source: "hashicorp/google{{- if ne $.TargetVersionName "ga" -}}-{{$.TargetVersionName}}{{- end }}", - }, - }, - Config: testAccDataSourceGoogleFirebaseAppleAppConfig(context), - Check: resource.ComposeTestCheckFunc( - testAccDataSourceFirebaseAppleAppConfigCheck("data.google_firebase_apple_app_config.my_app_config"), - ), - }, { ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), Config: testAccDataSourceGoogleFirebaseAppleAppConfig(context), diff --git a/mmv1/third_party/terraform/services/firebase/data_source_google_firebase_web_app_config.go.tmpl b/mmv1/third_party/terraform/services/firebase/data_source_google_firebase_web_app_config.go.tmpl index 8782d08fdbc7..7626b3d5b902 100644 --- a/mmv1/third_party/terraform/services/firebase/data_source_google_firebase_web_app_config.go.tmpl +++ b/mmv1/third_party/terraform/services/firebase/data_source_google_firebase_web_app_config.go.tmpl @@ -5,7 +5,7 @@ import ( "context" "fmt" - "google.golang.org/api/firebase/v1beta1" + firebase "google.golang.org/api/firebase/v1beta1" "github.com/hashicorp/terraform-plugin-framework/datasource" "github.com/hashicorp/terraform-plugin-framework/datasource/schema" @@ -15,6 +15,7 @@ import ( "github.com/hashicorp/terraform-provider-google/google/fwmodels" "github.com/hashicorp/terraform-provider-google/google/fwresource" "github.com/hashicorp/terraform-provider-google/google/fwtransport" + transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" ) // Ensure the implementation satisfies the expected interfaces @@ -29,8 +30,8 @@ func NewGoogleFirebaseWebAppConfigDataSource() datasource.DataSource { // GoogleFirebaseWebAppConfigDataSource defines the data source implementation type GoogleFirebaseWebAppConfigDataSource struct { - client *firebase.Service - project types.String + client *firebase.Service + providerConfig *transport_tpg.Config } type GoogleFirebaseWebAppConfigModel struct { @@ -138,20 +139,20 @@ func (d *GoogleFirebaseWebAppConfigDataSource) Configure(ctx context.Context, re return } - p, ok := req.ProviderData.(*fwtransport.FrameworkProviderConfig) + p, ok := req.ProviderData.(*transport_tpg.Config) if !ok { resp.Diagnostics.AddError( "Unexpected Data Source Configure Type", - fmt.Sprintf("Expected *fwtransport.FrameworkProviderConfig, got: %T. Please report this issue to the provider developers.", req.ProviderData), + fmt.Sprintf("Expected *transport_tpg.Config, got: %T. Please report this issue to the provider developers.", req.ProviderData), ) return } - d.client = p.NewFirebaseClient(p.UserAgent, &resp.Diagnostics) + d.client = p.NewFirebaseClient(ctx, p.UserAgent) if resp.Diagnostics.HasError() { return } - d.project = p.Project + d.providerConfig = p } func (d *GoogleFirebaseWebAppConfigDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { @@ -173,7 +174,7 @@ func (d *GoogleFirebaseWebAppConfigDataSource) Read(ctx context.Context, req dat // Use provider_meta to set User-Agent d.client.UserAgent = fwtransport.GenerateFrameworkUserAgentString(metaData, d.client.UserAgent) - data.Project = fwresource.GetProjectFramework(data.Project, d.project, &resp.Diagnostics) + data.Project = fwresource.GetProjectFramework(data.Project, types.StringValue(d.providerConfig.Project), &resp.Diagnostics) if resp.Diagnostics.HasError() { return } diff --git a/mmv1/third_party/terraform/services/firebase/resource_firebase_web_app_test.go.tmpl b/mmv1/third_party/terraform/services/firebase/resource_firebase_web_app_test.go.tmpl index 8106154a2bff..8a932269376b 100644 --- a/mmv1/third_party/terraform/services/firebase/resource_firebase_web_app_test.go.tmpl +++ b/mmv1/third_party/terraform/services/firebase/resource_firebase_web_app_test.go.tmpl @@ -16,8 +16,6 @@ import ( ) func TestAccFirebaseWebApp_firebaseWebAppFull(t *testing.T) { - // TODO: https://github.com/hashicorp/terraform-provider-google/issues/14158 - acctest.SkipIfVcr(t) t.Parallel() context := map[string]interface{}{ diff --git a/mmv1/third_party/terraform/services/resourcemanager/data_source_google_client_config.go b/mmv1/third_party/terraform/services/resourcemanager/data_source_google_client_config.go index 4d4aae711fd0..da9de577aa66 100644 --- a/mmv1/third_party/terraform/services/resourcemanager/data_source_google_client_config.go +++ b/mmv1/third_party/terraform/services/resourcemanager/data_source_google_client_config.go @@ -9,7 +9,7 @@ import ( "github.com/hashicorp/terraform-plugin-framework/types" "github.com/hashicorp/terraform-provider-google/google/fwmodels" "github.com/hashicorp/terraform-provider-google/google/fwresource" - "github.com/hashicorp/terraform-provider-google/google/fwtransport" + transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" ) // Ensure the data source satisfies the expected interfaces. @@ -24,7 +24,7 @@ func NewGoogleClientConfigDataSource() datasource.DataSource { } type GoogleClientConfigDataSource struct { - providerConfig *fwtransport.FrameworkProviderConfig + providerConfig *transport_tpg.Config } type GoogleClientConfigModel struct { @@ -38,14 +38,14 @@ type GoogleClientConfigModel struct { DefaultLabels types.Map `tfsdk:"default_labels"` } -func (m *GoogleClientConfigModel) GetLocationDescription(providerConfig *fwtransport.FrameworkProviderConfig) fwresource.LocationDescription { +func (m *GoogleClientConfigModel) GetLocationDescription(providerConfig *transport_tpg.Config) fwresource.LocationDescription { return fwresource.LocationDescription{ RegionSchemaField: types.StringValue("region"), ZoneSchemaField: types.StringValue("zone"), ResourceRegion: m.Region, ResourceZone: m.Zone, - ProviderRegion: providerConfig.Region, - ProviderZone: providerConfig.Zone, + ProviderRegion: types.StringValue(providerConfig.Region), + ProviderZone: types.StringValue(providerConfig.Zone), } } @@ -102,11 +102,11 @@ func (d *GoogleClientConfigDataSource) Configure(ctx context.Context, req dataso return } - p, ok := req.ProviderData.(*fwtransport.FrameworkProviderConfig) + p, ok := req.ProviderData.(*transport_tpg.Config) if !ok { resp.Diagnostics.AddError( "Unexpected Data Source Configure Type", - fmt.Sprintf("Expected *fwtransport.FrameworkProviderConfig, got: %T. Please report this issue to the provider developers.", req.ProviderData), + fmt.Sprintf("Expected *transport_tpg.Config, got: %T. Please report this issue to the provider developers.", req.ProviderData), ) return } @@ -135,11 +135,25 @@ func (d *GoogleClientConfigDataSource) Read(ctx context.Context, req datasource. region, _ := locationInfo.GetRegion() zone, _ := locationInfo.GetZone() - data.Id = types.StringValue(fmt.Sprintf("projects/%s/regions/%s/zones/%s", d.providerConfig.Project.String(), region.String(), zone.String())) - data.Project = d.providerConfig.Project + data.Id = types.StringValue(fmt.Sprintf("projects/%s/regions/%s/zones/%s", d.providerConfig.Project, region.String(), zone.String())) + data.Project = types.StringValue(d.providerConfig.Project) data.Region = region data.Zone = zone - data.DefaultLabels = d.providerConfig.DefaultLabels + + // Convert default labels from SDK type system to plugin-framework data type + m := map[string]*string{} + for k, v := range d.providerConfig.DefaultLabels { + // m[k] = types.StringValue(v) + val := v + m[k] = &val + } + dls, diags := types.MapValueFrom(ctx, types.StringType, m) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + data.DefaultLabels = dls token, err := d.providerConfig.TokenSource.Token() if err != nil { diff --git a/mmv1/third_party/terraform/services/resourcemanager/data_source_google_client_openid_userinfo.go b/mmv1/third_party/terraform/services/resourcemanager/data_source_google_client_openid_userinfo.go index 18dcf080c04a..df809e557624 100644 --- a/mmv1/third_party/terraform/services/resourcemanager/data_source_google_client_openid_userinfo.go +++ b/mmv1/third_party/terraform/services/resourcemanager/data_source_google_client_openid_userinfo.go @@ -10,6 +10,7 @@ import ( "github.com/hashicorp/terraform-plugin-framework/types" "github.com/hashicorp/terraform-provider-google/google/fwmodels" "github.com/hashicorp/terraform-provider-google/google/fwtransport" + transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" ) // Ensure the data source satisfies the expected interfaces. @@ -23,7 +24,7 @@ func NewGoogleClientOpenIDUserinfoDataSource() datasource.DataSource { } type GoogleClientOpenIDUserinfoDataSource struct { - providerConfig *fwtransport.FrameworkProviderConfig + providerConfig *transport_tpg.Config } type GoogleClientOpenIDUserinfoModel struct { @@ -68,11 +69,11 @@ func (d *GoogleClientOpenIDUserinfoDataSource) Configure(ctx context.Context, re return } - p, ok := req.ProviderData.(*fwtransport.FrameworkProviderConfig) + p, ok := req.ProviderData.(*transport_tpg.Config) if !ok { resp.Diagnostics.AddError( "Unexpected Data Source Configure Type", - fmt.Sprintf("Expected *fwtransport.FrameworkProviderConfig, got: %T. Please report this issue to the provider developers.", req.ProviderData), + fmt.Sprintf("Expected *transport_tpg.Config, got: %T. Please report this issue to the provider developers.", req.ProviderData), ) return } @@ -99,8 +100,11 @@ func (d *GoogleClientOpenIDUserinfoDataSource) Read(ctx context.Context, req dat } userAgent := fwtransport.GenerateFrameworkUserAgentString(metaData, d.providerConfig.UserAgent) - email := fwtransport.GetCurrentUserEmailFramework(d.providerConfig, userAgent, &diags) - + email, err := transport_tpg.GetCurrentUserEmail(d.providerConfig, userAgent) + if err != nil { + diags.AddError("error retrieving userinfo for your provider credentials", err.Error()) + return + } data.Email = types.StringValue(email) data.Id = types.StringValue(email) diff --git a/mmv1/third_party/terraform/transport/config.go.tmpl b/mmv1/third_party/terraform/transport/config.go.tmpl index 94506f6230c9..0e778f5c701c 100644 --- a/mmv1/third_party/terraform/transport/config.go.tmpl +++ b/mmv1/third_party/terraform/transport/config.go.tmpl @@ -64,6 +64,9 @@ import ( dataflow "google.golang.org/api/dataflow/v1b3" "google.golang.org/api/dataproc/v1" "google.golang.org/api/dns/v1" +{{- if ne $.TargetVersionName "ga" }} + firebase "google.golang.org/api/firebase/v1beta1" +{{- end }} healthcare "google.golang.org/api/healthcare/v1" "google.golang.org/api/iam/v1" iamcredentials "google.golang.org/api/iamcredentials/v1" @@ -203,7 +206,7 @@ type Config struct { UserAgent string gRPCLoggingOptions []option.ClientOption - tokenSource oauth2.TokenSource + TokenSource oauth2.TokenSource {{ range $product := $.Products }} {{ $product.Name }}BasePath string @@ -431,7 +434,7 @@ func (c *Config) LoadAndValidate(ctx context.Context) error { return err } - c.tokenSource = tokenSource + c.TokenSource = tokenSource cleanCtx := context.WithValue(ctx, oauth2.HTTPClient, cleanhttp.DefaultClient()) @@ -660,6 +663,23 @@ func (c *Config) NewDnsClient(userAgent string) *dns.Service { return clientDns } +{{- if ne $.TargetVersionName "ga" }} +func (c *Config) NewFirebaseClient(ctx context.Context, userAgent string) *firebase.Service { + firebaseClientBasePath := RemoveBasePathVersion(c.FirebaseBasePath) + firebaseClientBasePath = strings.ReplaceAll(firebaseClientBasePath, "/firebase/", "") + log.Printf("[INFO] Instantiating Google Cloud firebase client for path %s", firebaseClientBasePath) + clientFirebase, err := firebase.NewService(c.Context, option.WithHTTPClient(c.Client)) + if err != nil { + log.Printf("[WARN] Error creating client firebase: %s", err) + return nil + } + clientFirebase.UserAgent = userAgent + clientFirebase.BasePath = firebaseClientBasePath + + return clientFirebase +} +{{- end }} + func (c *Config) NewKmsClientWithCtx(ctx context.Context, userAgent string) *cloudkms.Service { kmsClientBasePath := RemoveBasePathVersion(c.KMSBasePath) log.Printf("[INFO] Instantiating Google Cloud KMS client for path %s", kmsClientBasePath) @@ -1073,7 +1093,7 @@ func (c *Config) NewCloudIdentityClient(userAgent string) *cloudidentity.Service func (c *Config) BigTableClientFactory(userAgent string) *BigtableClientFactory { bigtableClientFactory := &BigtableClientFactory{ UserAgent: userAgent, - TokenSource: c.tokenSource, + TokenSource: c.TokenSource, gRPCLoggingOptions: c.gRPCLoggingOptions, BillingProject: c.BillingProject, UserProjectOverride: c.UserProjectOverride,