From 61370a87fcc2c9f8f9040b692b728c6ba20077e4 Mon Sep 17 00:00:00 2001 From: himanikh Date: Wed, 30 Oct 2024 10:59:04 -0700 Subject: [PATCH 1/2] Promoting Memorystore to GA (#12112) --- mmv1/products/memorystore/Instance.yaml | 60 ------------------- mmv1/products/memorystore/product.yaml | 12 ++-- .../memorystore_instance_basic.tf.tmpl | 5 -- .../memorystore_instance_full.tf.tmpl | 5 -- ...morystore_instance_persistence_aof.tf.tmpl | 5 -- ... => resource_memorystore_instance_test.go} | 18 ++---- 6 files changed, 12 insertions(+), 93 deletions(-) rename mmv1/third_party/terraform/services/memorystore/{resource_memorystore_instance_test.go.tmpl => resource_memorystore_instance_test.go} (95%) diff --git a/mmv1/products/memorystore/Instance.yaml b/mmv1/products/memorystore/Instance.yaml index 7b71ba707a3e..113e01ca5820 100644 --- a/mmv1/products/memorystore/Instance.yaml +++ b/mmv1/products/memorystore/Instance.yaml @@ -14,7 +14,6 @@ --- name: 'Instance' description: A Google Cloud Memorystore instance. -min_version: 'beta' docs: id_format: 'projects/{{project}}/locations/{{location}}/instances/{{instance_id}}' base_url: 'projects/{{project}}/locations/{{location}}/instances' @@ -48,7 +47,6 @@ custom_code: examples: - name: 'memorystore_instance_basic' primary_resource_id: 'instance-basic' - min_version: 'beta' vars: instance_name: 'basic-instance' policy_name: 'my-policy' @@ -59,7 +57,6 @@ examples: 'prevent_destroy': 'false' - name: 'memorystore_instance_full' primary_resource_id: 'instance-full' - min_version: 'beta' vars: instance_name: 'full-instance' policy_name: 'my-policy' @@ -70,7 +67,6 @@ examples: 'prevent_destroy': 'false' - name: 'memorystore_instance_persistence_aof' primary_resource_id: 'instance-persistence-aof' - min_version: 'beta' vars: instance_name: 'aof-instance' policy_name: 'my-policy' @@ -108,7 +104,6 @@ parameters: "Resource ID segment making up resource `name`. It identifies the resource within its parent collection as described in https://google.aip.dev/122. See documentation for resource type `memorystore.googleapis.com/CertificateAuthority`. " - min_version: 'beta' url_param_only: true required: true immutable: true @@ -120,7 +115,6 @@ parameters: following restrictions:\n\n* Must be 4-63 characters in length\n* Must begin with a letter or digit\n* Must contain only lowercase letters, digits, and hyphens\n* Must not end with a hyphen\n* Must be unique within a location " - min_version: 'beta' url_param_only: true required: true immutable: true @@ -128,71 +122,59 @@ properties: - name: 'name' type: String description: "Identifier. Unique name of the instance.\nFormat: projects/{project}/locations/{location}/instances/{instance} " - min_version: 'beta' output: true - name: 'createTime' type: String description: "Output only. Creation timestamp of the instance. " - min_version: 'beta' output: true - name: 'updateTime' type: String description: "Output only. Latest update timestamp of the instance. " - min_version: 'beta' output: true - name: 'labels' type: KeyValueLabels description: "Optional. Labels to represent user-provided metadata. " - min_version: 'beta' - name: 'state' type: String description: "Output only. Current state of the instance. \n Possible values:\n CREATING\nACTIVE\nUPDATING\nDELETING" - min_version: 'beta' output: true - name: 'stateInfo' type: NestedObject description: "Additional information about the state of the instance. " - min_version: 'beta' output: true properties: - name: 'updateInfo' type: NestedObject description: "Represents information about instance with state UPDATING. " - min_version: 'beta' output: true properties: - name: 'targetShardCount' type: Integer description: "Output only. Target number of shards for the instance. " - min_version: 'beta' output: true - name: 'targetReplicaCount' type: Integer description: "Output only. Target number of replica nodes per shard for the instance. " - min_version: 'beta' output: true - name: 'uid' type: String description: "Output only. System assigned, unique identifier for the instance. " - min_version: 'beta' output: true - name: 'replicaCount' type: Integer description: "Optional. Number of replica nodes per shard. If omitted the default is 0 replicas. " - min_version: 'beta' default_from_api: true - name: 'authorizationMode' type: String description: "Optional. Immutable. Authorization mode of the instance. Possible values:\n AUTH_DISABLED\nIAM_AUTH" - min_version: 'beta' immutable: true default_from_api: true - name: 'transitEncryptionMode' @@ -200,20 +182,17 @@ properties: description: "Optional. Immutable. In-transit encryption mode of the instance. \n Possible values:\n TRANSIT_ENCRYPTION_DISABLED\nSERVER_AUTHENTICATION" - min_version: 'beta' immutable: true default_from_api: true - name: 'shardCount' type: Integer description: "Required. Number of shards for the instance. " - min_version: 'beta' required: true - name: 'discoveryEndpoints' type: Array description: "Output only. Endpoints clients can connect to the instance through. Currently only one\ndiscovery endpoint is supported. " - min_version: 'beta' output: true item_type: type: NestedObject @@ -223,38 +202,32 @@ properties: description: "Output only. IP address of the exposed endpoint clients connect to. " - min_version: 'beta' output: true - name: 'port' type: Integer description: "Output only. The port number of the exposed endpoint. " - min_version: 'beta' output: true - name: 'network' type: String description: "Output only. The network where the IP address of the discovery endpoint will be\nreserved, in the form of\nprojects/{network_project}/global/networks/{network_id}. " - min_version: 'beta' output: true - name: 'nodeType' type: String description: "Optional. Immutable. Machine type for individual nodes of the instance. \n Possible values:\n SHARED_CORE_NANO\nHIGHMEM_MEDIUM\nHIGHMEM_XLARGE\nSTANDARD_SMALL" - min_version: 'beta' immutable: true default_from_api: true - name: 'persistenceConfig' type: NestedObject description: "Represents persistence configuration for a instance. " - min_version: 'beta' default_from_api: true properties: - name: 'mode' type: Enum description: "Optional. Current persistence mode. \n Possible values:\nDISABLED\nRDB\nAOF" - min_version: 'beta' default_from_api: true enum_values: - 'DISABLED' @@ -263,7 +236,6 @@ properties: - name: 'rdbConfig' type: NestedObject description: "Configuration for RDB based persistence. " - min_version: 'beta' default_from_api: true properties: - name: 'rdbSnapshotPeriod' @@ -271,7 +243,6 @@ properties: description: "Optional. Period between RDB snapshots. \n Possible values:\n ONE_HOUR\nSIX_HOURS\nTWELVE_HOURS\nTWENTY_FOUR_HOURS" - min_version: 'beta' default_from_api: true - name: 'rdbSnapshotStartTime' type: String @@ -279,44 +250,36 @@ properties: "Optional. Time that the first snapshot was/will be attempted, and to which future\nsnapshots will be aligned. If not provided, the current time will be\nused. " - min_version: 'beta' default_from_api: true - name: 'aofConfig' type: NestedObject description: "Configuration for AOF based persistence. " - min_version: 'beta' default_from_api: true properties: - name: 'appendFsync' type: String description: "Optional. The fsync mode. \n Possible values:\n NEVER\nEVERY_SEC\nALWAYS" - min_version: 'beta' default_from_api: true - name: 'engineVersion' type: String description: "Optional. Immutable. Engine version of the instance. " - min_version: 'beta' immutable: true default_from_api: true - name: 'engineConfigs' type: KeyValuePairs description: "Optional. User-provided engine configurations for the instance. " - min_version: 'beta' - name: 'nodeConfig' type: NestedObject description: "Represents configuration for nodes of the instance. " - min_version: 'beta' output: true properties: - name: 'sizeGb' type: Double description: "Output only. Memory size in GB of the node. " - min_version: 'beta' output: true - name: 'zoneDistributionConfig' type: NestedObject description: "Zone distribution configuration for allocation of instance resources. " - min_version: 'beta' immutable: true default_from_api: true properties: @@ -325,14 +288,12 @@ properties: description: "Optional. Defines zone where all resources will be allocated with SINGLE_ZONE mode.\nIgnored for MULTI_ZONE mode. " - min_version: 'beta' immutable: true - name: 'mode' type: Enum description: "Optional. Current zone distribution mode. Defaults to MULTI_ZONE. \n Possible values:\n MULTI_ZONE\nSINGLE_ZONE" - min_version: 'beta' default_from_api: true enum_values: - 'MULTI_ZONE' @@ -340,12 +301,10 @@ properties: - name: 'deletionProtectionEnabled' type: Boolean description: "Optional. If set to true deletion of the instance will fail. " - min_version: 'beta' default_value: true - name: 'endpoints' type: Array description: "Endpoints for the instance." - min_version: 'beta' output: true item_type: type: Array @@ -358,47 +317,40 @@ properties: description: "Output only. The PSC connection id of the forwarding rule connected to the\nservice attachment. " - min_version: 'beta' output: true - name: 'ipAddress' type: String description: "Output only. The IP allocated on the consumer network for the PSC forwarding rule. " - min_version: 'beta' output: true - name: 'forwardingRule' type: String description: "Output only. The URI of the consumer side forwarding rule.\nFormat:\nprojects/{project}/regions/{region}/forwardingRules/{forwarding_rule} " - min_version: 'beta' output: true - name: 'projectId' type: String description: "Output only. The consumer project_id where the forwarding rule is created from. " - min_version: 'beta' output: true - name: 'network' type: String description: "Output only. The consumer network where the IP address resides, in the form of\nprojects/{project_id}/global/networks/{network_id}. " - min_version: 'beta' output: true - name: 'serviceAttachment' type: String description: "Output only. The service attachment which is the target of the PSC connection, in the form of projects/{project-id}/regions/{region}/serviceAttachments/{service-attachment-id}." - min_version: 'beta' output: true - name: 'pscConnectionStatus' type: Enum description: "Output Only. The status of the PSC connection: whether a connection exists and ACTIVE or it no longer exists. \n Possible values:\n ACTIVE \n NOT_FOUND" - min_version: 'beta' output: true enum_values: - 'ACTIVE' @@ -408,7 +360,6 @@ properties: description: "Output Only. Type of a PSC Connection. \n Possible values:\n CONNECTION_TYPE_DISCOVERY \n CONNECTION_TYPE_PRIMARY \n CONNECTION_TYPE_READER" - min_version: 'beta' output: true enum_values: - 'CONNECTION_TYPE_READER' @@ -419,7 +370,6 @@ properties: description: "Optional. Standalone or cluster. \n Possible values:\n CLUSTER\nSTANDALONE" - min_version: 'beta' default_from_api: true immutable: true enum_values: @@ -430,7 +380,6 @@ properties: description: "Output only. User inputs and resource details of the auto-created PSC connections. " - min_version: 'beta' output: true item_type: type: NestedObject @@ -440,47 +389,40 @@ properties: description: "Output only. The PSC connection id of the forwarding rule connected to the\nservice attachment. " - min_version: 'beta' output: true - name: 'ipAddress' type: String description: "Output only. The IP allocated on the consumer network for the PSC forwarding rule. " - min_version: 'beta' output: true - name: 'forwardingRule' type: String description: "Output only. The URI of the consumer side forwarding rule.\nFormat:\nprojects/{project}/regions/{region}/forwardingRules/{forwarding_rule} " - min_version: 'beta' output: true - name: 'projectId' type: String description: "Output only. The consumer project_id where the forwarding rule is created from. " - min_version: 'beta' output: true - name: 'network' type: String description: "Output only. The consumer network where the IP address resides, in the form of\nprojects/{project_id}/global/networks/{network_id}. " - min_version: 'beta' output: true - name: 'serviceAttachment' type: String description: "Output only. The service attachment which is the target of the PSC connection, in the form of projects/{project-id}/regions/{region}/serviceAttachments/{service-attachment-id}." - min_version: 'beta' output: true - name: 'pscConnectionStatus' type: Enum description: "Output Only. The status of the PSC connection: whether a connection exists and ACTIVE or it no longer exists. \n Possible values:\n ACTIVE \n NOT_FOUND" - min_version: 'beta' output: true enum_values: - 'ACTIVE' @@ -490,7 +432,6 @@ properties: description: "Output Only. Type of a PSC Connection. \n Possible values:\n CONNECTION_TYPE_DISCOVERY \n CONNECTION_TYPE_PRIMARY \n CONNECTION_TYPE_READER" - min_version: 'beta' output: true enum_values: - 'CONNECTION_TYPE_READER' @@ -501,4 +442,3 @@ properties: description: "Output only. Ports of the exposed endpoint." output: true - min_version: 'beta' diff --git a/mmv1/products/memorystore/product.yaml b/mmv1/products/memorystore/product.yaml index d84d25e33012..d76b6cacc2c9 100644 --- a/mmv1/products/memorystore/product.yaml +++ b/mmv1/products/memorystore/product.yaml @@ -12,10 +12,12 @@ # limitations under the License. --- -name: 'Memorystore' -display_name: 'Memorystore' +name: "Memorystore" +display_name: "Memorystore" versions: - - name: 'beta' - base_url: 'https://memorystore.googleapis.com/v1beta/' + - name: "beta" + base_url: "https://memorystore.googleapis.com/v1beta/" + - name: "ga" + base_url: "https://memorystore.googleapis.com/v1/" scopes: - - 'https://www.googleapis.com/auth/cloud-platform' + - "https://www.googleapis.com/auth/cloud-platform" diff --git a/mmv1/templates/terraform/examples/memorystore_instance_basic.tf.tmpl b/mmv1/templates/terraform/examples/memorystore_instance_basic.tf.tmpl index c8db3451c720..9ca41d5829c0 100644 --- a/mmv1/templates/terraform/examples/memorystore_instance_basic.tf.tmpl +++ b/mmv1/templates/terraform/examples/memorystore_instance_basic.tf.tmpl @@ -1,5 +1,4 @@ resource "google_memorystore_instance" "{{$.PrimaryResourceId}}" { - provider = google-beta instance_id = "{{index $.Vars "instance_name"}}" shard_count = 3 desired_psc_auto_connections { @@ -18,7 +17,6 @@ resource "google_memorystore_instance" "{{$.PrimaryResourceId}}" { } resource "google_network_connectivity_service_connection_policy" "default" { - provider = google-beta name = "{{index $.Vars "policy_name"}}" location = "us-central1" service_class = "gcp-memorystore" @@ -30,7 +28,6 @@ resource "google_network_connectivity_service_connection_policy" "default" { } resource "google_compute_subnetwork" "producer_subnet" { - provider = google-beta name = "{{index $.Vars "subnet_name"}}" ip_cidr_range = "10.0.0.248/29" region = "us-central1" @@ -38,11 +35,9 @@ resource "google_compute_subnetwork" "producer_subnet" { } resource "google_compute_network" "producer_net" { - provider = google-beta name = "{{index $.Vars "network_name"}}" auto_create_subnetworks = false } data "google_project" "project" { - provider = google-beta } diff --git a/mmv1/templates/terraform/examples/memorystore_instance_full.tf.tmpl b/mmv1/templates/terraform/examples/memorystore_instance_full.tf.tmpl index ad204cf2d40e..e8d72d6a859f 100644 --- a/mmv1/templates/terraform/examples/memorystore_instance_full.tf.tmpl +++ b/mmv1/templates/terraform/examples/memorystore_instance_full.tf.tmpl @@ -1,5 +1,4 @@ resource "google_memorystore_instance" "{{$.PrimaryResourceId}}" { - provider = google-beta instance_id = "{{index $.Vars "instance_name"}}" shard_count = 3 desired_psc_auto_connections { @@ -41,7 +40,6 @@ resource "google_memorystore_instance" "{{$.PrimaryResourceId}}" { } resource "google_network_connectivity_service_connection_policy" "default" { - provider = google-beta name = "{{index $.Vars "policy_name"}}" location = "us-central1" service_class = "gcp-memorystore" @@ -53,7 +51,6 @@ resource "google_network_connectivity_service_connection_policy" "default" { } resource "google_compute_subnetwork" "producer_subnet" { - provider = google-beta name = "{{index $.Vars "subnet_name"}}" ip_cidr_range = "10.0.0.248/29" region = "us-central1" @@ -61,11 +58,9 @@ resource "google_compute_subnetwork" "producer_subnet" { } resource "google_compute_network" "producer_net" { - provider = google-beta name = "{{index $.Vars "network_name"}}" auto_create_subnetworks = false } data "google_project" "project" { - provider = google-beta } \ No newline at end of file diff --git a/mmv1/templates/terraform/examples/memorystore_instance_persistence_aof.tf.tmpl b/mmv1/templates/terraform/examples/memorystore_instance_persistence_aof.tf.tmpl index 8bd11ec0f648..d4ec704a76dd 100644 --- a/mmv1/templates/terraform/examples/memorystore_instance_persistence_aof.tf.tmpl +++ b/mmv1/templates/terraform/examples/memorystore_instance_persistence_aof.tf.tmpl @@ -1,5 +1,4 @@ resource "google_memorystore_instance" "{{$.PrimaryResourceId}}" { - provider = google-beta instance_id = "{{index $.Vars "instance_name"}}" shard_count = 3 desired_psc_auto_connections { @@ -23,7 +22,6 @@ resource "google_memorystore_instance" "{{$.PrimaryResourceId}}" { } resource "google_network_connectivity_service_connection_policy" "default" { - provider = google-beta name = "{{index $.Vars "policy_name"}}" location = "us-central1" service_class = "gcp-memorystore" @@ -35,7 +33,6 @@ resource "google_network_connectivity_service_connection_policy" "default" { } resource "google_compute_subnetwork" "producer_subnet" { - provider = google-beta name = "{{index $.Vars "subnet_name"}}" ip_cidr_range = "10.0.0.248/29" region = "us-central1" @@ -43,11 +40,9 @@ resource "google_compute_subnetwork" "producer_subnet" { } resource "google_compute_network" "producer_net" { - provider = google-beta name = "{{index $.Vars "network_name"}}" auto_create_subnetworks = false } data "google_project" "project" { - provider = google-beta } \ No newline at end of file diff --git a/mmv1/third_party/terraform/services/memorystore/resource_memorystore_instance_test.go.tmpl b/mmv1/third_party/terraform/services/memorystore/resource_memorystore_instance_test.go similarity index 95% rename from mmv1/third_party/terraform/services/memorystore/resource_memorystore_instance_test.go.tmpl rename to mmv1/third_party/terraform/services/memorystore/resource_memorystore_instance_test.go index e0f4ae137354..e7d024a00db3 100644 --- a/mmv1/third_party/terraform/services/memorystore/resource_memorystore_instance_test.go.tmpl +++ b/mmv1/third_party/terraform/services/memorystore/resource_memorystore_instance_test.go @@ -1,5 +1,4 @@ package memorystore_test -{{- if ne $.TargetVersionName "ga" }} import ( "fmt" @@ -18,7 +17,7 @@ func TestAccMemorystoreInstance_updateReplicaCount(t *testing.T) { acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, - ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), CheckDestroy: testAccCheckMemorystoreInstanceDestroyProducer(t), Steps: []resource.TestStep{ { @@ -55,7 +54,7 @@ func TestAccMemorystoreInstance_updateShardCount(t *testing.T) { acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, - ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), CheckDestroy: testAccCheckMemorystoreInstanceDestroyProducer(t), Steps: []resource.TestStep{ { @@ -92,7 +91,7 @@ func TestAccMemorystoreInstance_updateRedisConfigs(t *testing.T) { acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, - ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), CheckDestroy: testAccCheckMemorystoreInstanceDestroyProducer(t), Steps: []resource.TestStep{ { @@ -152,7 +151,7 @@ func TestAccMemorystoreInstance_updateDeletionProtection(t *testing.T) { acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, - ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), CheckDestroy: testAccCheckMemorystoreInstanceDestroyProducer(t), Steps: []resource.TestStep{ { @@ -195,7 +194,7 @@ func TestAccMemorystoreInstance_updatePersistence(t *testing.T) { acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, - ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), CheckDestroy: testAccCheckMemorystoreInstanceDestroyProducer(t), Steps: []resource.TestStep{ { @@ -269,7 +268,6 @@ func createOrUpdateMemorystoreInstance(params *InstanceParams) string { } return fmt.Sprintf(` resource "google_memorystore_instance" "test" { - provider = google-beta instance_id = "%s" replica_count = %d shard_count = %d @@ -292,7 +290,6 @@ resource "google_memorystore_instance" "test" { } resource "google_network_connectivity_service_connection_policy" "default" { - provider = google-beta name = "%s" location = "europe-west1" service_class = "gcp-memorystore" @@ -304,7 +301,6 @@ resource "google_network_connectivity_service_connection_policy" "default" { } resource "google_compute_subnetwork" "producer_subnet" { - provider = google-beta name = "%s" ip_cidr_range = "10.0.0.248/29" region = "europe-west1" @@ -312,15 +308,11 @@ resource "google_compute_subnetwork" "producer_subnet" { } resource "google_compute_network" "producer_net" { - provider = google-beta name = "%s" auto_create_subnetworks = false } data "google_project" "project" { - provider = google-beta } `, params.name, params.replicaCount, params.shardCount, params.nodeType, params.deletionProtectionEnabled, strBuilder.String(), zoneDistributionConfigBlock, persistenceBlock, lifecycleBlock, params.name, params.name, params.name) } - -{{ end }} From 07118df4325b99355b62c9acdaeb95102dd935a2 Mon Sep 17 00:00:00 2001 From: Will Yardley Date: Wed, 30 Oct 2024 12:10:44 -0700 Subject: [PATCH 2/2] container: fix in-place updates for `node_config.containerd_config` (#12135) Signed-off-by: William Yardley --- .../services/container/node_config.go.tmpl | 36 +++ .../resource_container_cluster_test.go.tmpl | 272 ++++++++++-------- .../resource_container_node_pool_test.go.tmpl | 91 +++++- 3 files changed, 277 insertions(+), 122 deletions(-) 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 b98582509fde..e5340a66546a 100644 --- a/mmv1/third_party/terraform/services/container/node_config.go.tmpl +++ b/mmv1/third_party/terraform/services/container/node_config.go.tmpl @@ -2042,6 +2042,42 @@ func nodePoolNodeConfigUpdate(d *schema.ResourceData, config *transport_tpg.Conf } } + if d.HasChange(prefix + "node_config.0.containerd_config") { + if _, ok := d.GetOk(prefix + "node_config.0.containerd_config"); ok { + req := &container.UpdateNodePoolRequest{ + Name: name, + ContainerdConfig: expandContainerdConfig(d.Get(prefix + "node_config.0.containerd_config")), + } + if req.ContainerdConfig == nil { + req.ContainerdConfig = &container.ContainerdConfig{} + req.ForceSendFields = []string{"ContainerdConfig"} + } + updateF := func() error { + clusterNodePoolsUpdateCall := config.NewContainerClient(userAgent).Projects.Locations.Clusters.NodePools.Update(nodePoolInfo.fullyQualifiedName(name), req) + if config.UserProjectOverride { + clusterNodePoolsUpdateCall.Header().Add("X-Goog-User-Project", nodePoolInfo.project) + } + op, err := clusterNodePoolsUpdateCall.Do() + if err != nil { + return err + } + + // Wait until it's updated + return ContainerOperationWait(config, op, + nodePoolInfo.project, + nodePoolInfo.location, + "updating GKE node pool containerd_config", userAgent, + timeout) + } + + if err := retryWhileIncompatibleOperation(timeout, npLockKey, updateF); err != nil { + return err + } + + log.Printf("[INFO] Updated containerd_config for node pool %s", name) + } + } + if d.HasChange("node_config.0.disk_size_gb") || d.HasChange("node_config.0.disk_type") || d.HasChange("node_config.0.machine_type") || 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 023af48758d7..aea0d1015960 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 @@ -11802,6 +11802,7 @@ resource "google_container_cluster" "with_autopilot" { } func TestAccContainerCluster_privateRegistry(t *testing.T) { + // This test also checks containerd_config and its updates acctest.SkipIfVcr(t) t.Parallel() @@ -11832,7 +11833,7 @@ func TestAccContainerCluster_privateRegistry(t *testing.T) { resource.TestCheckResourceAttr( "google_container_cluster.primary", "node_pool_defaults.0.node_config_defaults.0.containerd_config.0.private_registry_access_config.0.certificate_authority_domain_config.0.fqdns.0", - "my.custom.domain", + "custom.example.com", ), // Second CA config resource.TestCheckResourceAttr( @@ -11850,21 +11851,56 @@ func TestAccContainerCluster_privateRegistry(t *testing.T) { }, { Config: testAccContainerCluster_privateRegistryDisabled(clusterName, networkName, subnetworkName), + // Don't check for no deletions here, since the secret etc. are getting destroyed. + Check: resource.TestCheckResourceAttr( + "google_container_cluster.primary", + "node_pool_defaults.0.node_config_defaults.0.containerd_config.0.private_registry_access_config.0.enabled", + "false", + ), + }, + // The above tests the default for _new_ node pools; this tests the configuration for default-pool if + // defined within the `container_cluster` resource + { + Config: testAccContainerCluster_withNodeConfigPrivateRegistry(secretID, clusterName, networkName, subnetworkName, "foo.example.com"), + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + acctest.ExpectNoDelete(), + }, + }, Check: resource.ComposeAggregateTestCheckFunc( resource.TestCheckResourceAttr( "google_container_cluster.primary", - "node_pool_defaults.0.node_config_defaults.0.containerd_config.0.private_registry_access_config.0.enabled", - "false", + "node_config.0.containerd_config.0.private_registry_access_config.0.enabled", + "true", ), resource.TestCheckResourceAttr( "google_container_cluster.primary", - "node_pool_defaults.0.node_config_defaults.0.containerd_config.0.private_registry_access_config.0.certificate_authority_domain_config.#", - "0", + "node_config.0.containerd_config.0.private_registry_access_config.0.certificate_authority_domain_config.#", + "1", ), ), }, + // We're already testing going from no `node_config` to having one in the previous step, but test updating + // anyway. { - Config: testAccContainerCluster_withNodePoolPrivateRegistry(secretID, clusterName, nodePoolName, networkName, subnetworkName), + Config: testAccContainerCluster_withNodeConfigPrivateRegistry(secretID, clusterName, networkName, subnetworkName, "bar.example.org"), + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + acctest.ExpectNoDelete(), + }, + }, + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr( + "google_container_cluster.primary", + "node_config.0.containerd_config.0.private_registry_access_config.0.enabled", + "true", + ), + resource.TestCheckResourceAttr( + "google_container_cluster.primary", + "node_config.0.containerd_config.0.private_registry_access_config.0.certificate_authority_domain_config.#", + "1", + ), + ), }, { ResourceName: "google_container_cluster.primary", @@ -11872,8 +11908,10 @@ func TestAccContainerCluster_privateRegistry(t *testing.T) { ImportStateVerify: true, ImportStateVerifyIgnore: []string{"deletion_protection"}, }, + // This last test *will* force recreation, and tests a (named) node pool defined in + // `google_container_cluster.node_pool`. Deletions are expected here too. { - Config: testAccContainerCluster_withNodeConfigPrivateRegistry(secretID, clusterName, networkName, subnetworkName), + Config: testAccContainerCluster_withNodePoolPrivateRegistry(secretID, clusterName, nodePoolName, networkName, subnetworkName), }, { ResourceName: "google_container_cluster.primary", @@ -11887,39 +11925,38 @@ func TestAccContainerCluster_privateRegistry(t *testing.T) { func testAccContainerCluster_privateRegistryEnabled(secretID, clusterName, networkName, subnetworkName string) string { return fmt.Sprintf(` -data "google_project" "test_project" { - } +data "google_project" "test_project" {} -resource "google_secret_manager_secret" "secret-basic" { - secret_id = "%s" - replication { - user_managed { - replicas { - location = "us-central1" - } - } - } +resource "google_secret_manager_secret" "secret_basic" { + secret_id = "%s" + replication { + user_managed { + replicas { + location = "us-central1" + } + } + } } -resource "google_secret_manager_secret_version" "secret-version-basic" { - secret = google_secret_manager_secret.secret-basic.id - secret_data = "dummypassword" - } +resource "google_secret_manager_secret_version" "secret_version_basic" { + secret = google_secret_manager_secret.secret_basic.id + secret_data = "dummypassword" +} resource "google_secret_manager_secret_iam_member" "secret_iam" { - secret_id = google_secret_manager_secret.secret-basic.id - role = "roles/secretmanager.admin" - member = "serviceAccount:${data.google_project.test_project.number}-compute@developer.gserviceaccount.com" - depends_on = [google_secret_manager_secret_version.secret-version-basic] - } + secret_id = google_secret_manager_secret.secret_basic.id + role = "roles/secretmanager.admin" + member = "serviceAccount:${data.google_project.test_project.number}-compute@developer.gserviceaccount.com" + depends_on = [google_secret_manager_secret_version.secret_version_basic] +} resource "google_container_cluster" "primary" { - name = "%s" - location = "us-central1-a" - initial_node_count = 1 + name = "%s" + location = "us-central1-a" + initial_node_count = 1 deletion_protection = false - network = "%s" - subnetwork = "%s" + network = "%s" + subnetwork = "%s" node_config { oauth_scopes = [ @@ -11932,15 +11969,15 @@ resource "google_container_cluster" "primary" { private_registry_access_config { enabled = true certificate_authority_domain_config { - fqdns = [ "my.custom.domain" ] + fqdns = ["custom.example.com"] gcp_secret_manager_certificate_config { - secret_uri = google_secret_manager_secret_version.secret-version-basic.name + secret_uri = google_secret_manager_secret_version.secret_version_basic.name } } - certificate_authority_domain_config { - fqdns = [ "10.1.2.32" ] + certificate_authority_domain_config { + fqdns = ["10.1.2.32"] gcp_secret_manager_certificate_config { - secret_uri = google_secret_manager_secret_version.secret-version-basic.name + secret_uri = google_secret_manager_secret_version.secret_version_basic.name } } } @@ -11961,6 +11998,11 @@ resource "google_container_cluster" "primary" { network = "%s" subnetwork = "%s" + node_config { + oauth_scopes = [ + "https://www.googleapis.com/auth/cloud-platform", + ] + } node_pool_defaults { node_config_defaults { containerd_config { @@ -11976,117 +12018,113 @@ resource "google_container_cluster" "primary" { func testAccContainerCluster_withNodePoolPrivateRegistry(secretID, clusterName, nodePoolName, networkName, subnetworkName string) string { return fmt.Sprintf(` -data "google_project" "test_project" { - } +data "google_project" "test_project" {} -resource "google_secret_manager_secret" "secret-basic" { - secret_id = "%s" - replication { - user_managed { - replicas { - location = "us-central1" - } - } - } -} -resource "google_secret_manager_secret_version" "secret-version-basic" { - secret = google_secret_manager_secret.secret-basic.id - secret_data = "dummypassword" +resource "google_secret_manager_secret" "secret_basic" { + secret_id = "%s" + replication { + user_managed { + replicas { + location = "us-central1" + } + } } +} +resource "google_secret_manager_secret_version" "secret_version_basic" { + secret = google_secret_manager_secret.secret_basic.id + secret_data = "dummypassword" +} resource "google_secret_manager_secret_iam_member" "secret_iam" { - secret_id = google_secret_manager_secret.secret-basic.id - role = "roles/secretmanager.admin" - member = "serviceAccount:${data.google_project.test_project.number}-compute@developer.gserviceaccount.com" - depends_on = [google_secret_manager_secret_version.secret-version-basic] - } + secret_id = google_secret_manager_secret.secret_basic.id + role = "roles/secretmanager.admin" + member = "serviceAccount:${data.google_project.test_project.number}-compute@developer.gserviceaccount.com" + depends_on = [google_secret_manager_secret_version.secret_version_basic] +} resource "google_container_cluster" "primary" { - name = "%s" - location = "us-central1-a" + name = "%s" + location = "us-central1-a" node_pool { - name = "%s" - initial_node_count = 1 + name = "%s" + initial_node_count = 1 node_config { - oauth_scopes = [ - "https://www.googleapis.com/auth/cloud-platform", - ] - machine_type = "n1-standard-8" - image_type = "COS_CONTAINERD" - containerd_config { - private_registry_access_config { - enabled = true - certificate_authority_domain_config { - fqdns = [ "my.custom.domain", "10.0.0.127:8888" ] - gcp_secret_manager_certificate_config { - secret_uri = google_secret_manager_secret_version.secret-version-basic.name - } - } - } + oauth_scopes = [ + "https://www.googleapis.com/auth/cloud-platform", + ] + containerd_config { + private_registry_access_config { + enabled = true + certificate_authority_domain_config { + fqdns = ["custom.example.com", "10.0.0.127:8888"] + gcp_secret_manager_certificate_config { + secret_uri = google_secret_manager_secret_version.secret_version_basic.name + } + } + } + } } -} -} - deletion_protection = false + } network = "%s" - subnetwork = "%s" + subnetwork = "%s" + + deletion_protection = false } `, secretID, clusterName, nodePoolName, networkName, subnetworkName) } -func testAccContainerCluster_withNodeConfigPrivateRegistry(secretID, clusterName, networkName, subnetworkName string) string { +func testAccContainerCluster_withNodeConfigPrivateRegistry(secretID, clusterName, networkName, subnetworkName, customDomain string) string { return fmt.Sprintf(` -data "google_project" "test_project" { - } +data "google_project" "test_project" {} -resource "google_secret_manager_secret" "secret-basic" { - secret_id = "%s" - replication { - user_managed { - replicas { - location = "us-central1" - } - } - } -} -resource "google_secret_manager_secret_version" "secret-version-basic" { - secret = google_secret_manager_secret.secret-basic.id - secret_data = "dummypassword" +resource "google_secret_manager_secret" "secret_basic" { + secret_id = "%s" + replication { + user_managed { + replicas { + location = "us-central1" + } + } } +} +resource "google_secret_manager_secret_version" "secret_version_basic" { + secret = google_secret_manager_secret.secret_basic.id + secret_data = "dummypassword" +} resource "google_secret_manager_secret_iam_member" "secret_iam" { - secret_id = google_secret_manager_secret.secret-basic.id - role = "roles/secretmanager.admin" - member = "serviceAccount:${data.google_project.test_project.number}-compute@developer.gserviceaccount.com" - depends_on = [google_secret_manager_secret_version.secret-version-basic] - } + secret_id = google_secret_manager_secret.secret_basic.id + role = "roles/secretmanager.admin" + member = "serviceAccount:${data.google_project.test_project.number}-compute@developer.gserviceaccount.com" + depends_on = [google_secret_manager_secret_version.secret_version_basic] +} resource "google_container_cluster" "primary" { name = "%s" location = "us-central1-a" initial_node_count = 1 node_config { - oauth_scopes = [ + oauth_scopes = [ "https://www.googleapis.com/auth/cloud-platform", ] - machine_type = "n1-standard-8" - image_type = "COS_CONTAINERD" containerd_config { - private_registry_access_config { - enabled = true - certificate_authority_domain_config { - fqdns = [ "my.custom.domain", "10.0.0.127:8888" ] - gcp_secret_manager_certificate_config { - secret_uri = google_secret_manager_secret_version.secret-version-basic.name - } - } - } + private_registry_access_config { + enabled = true + certificate_authority_domain_config { + fqdns = ["%s", "10.0.0.127:8888"] + gcp_secret_manager_certificate_config { + secret_uri = google_secret_manager_secret_version.secret_version_basic.name + } + } + } } -} - deletion_protection = false + } network = "%s" - subnetwork = "%s" + subnetwork = "%s" + + deletion_protection = false } -`, secretID, clusterName, networkName, subnetworkName) +`, secretID, clusterName, customDomain, networkName, subnetworkName) } func TestAccContainerCluster_withProviderDefaultLabels(t *testing.T) { 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 544af3b762be..999868c611e6 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 @@ -4786,7 +4786,7 @@ func TestAccContainerNodePool_privateRegistry(t *testing.T) { CheckDestroy: testAccCheckContainerNodePoolDestroyProducer(t), Steps: []resource.TestStep{ { - Config: testAccContainerNodePool_privateRegistryEnabled(secretID, cluster, nodepool, networkName, subnetworkName), + Config: testAccContainerNodePool_privateRegistryEnabled(secretID, cluster, nodepool, networkName, subnetworkName, "custom.example.com"), Check: resource.ComposeAggregateTestCheckFunc( resource.TestCheckResourceAttr( "google_container_node_pool.np", @@ -4802,7 +4802,7 @@ func TestAccContainerNodePool_privateRegistry(t *testing.T) { resource.TestCheckResourceAttr( "google_container_node_pool.np", "node_config.0.containerd_config.0.private_registry_access_config.0.certificate_authority_domain_config.0.fqdns.0", - "my.custom.domain", + "custom.example.com", ), // Second CA config resource.TestCheckResourceAttr( @@ -4812,11 +4812,35 @@ func TestAccContainerNodePool_privateRegistry(t *testing.T) { ), ), }, + { + // Make sure in-place updates work + Config: testAccContainerNodePool_privateRegistryEnabled(secretID, cluster, nodepool, networkName, subnetworkName, "foo.example.org"), + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + acctest.ExpectNoDelete(), + }, + }, + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr( + "google_container_node_pool.np", + "node_config.0.containerd_config.0.private_registry_access_config.0.certificate_authority_domain_config.0.fqdns.0", + "foo.example.org", + ), + ), + }, + { + Config: testAccContainerNodePool_privateRegistryDisabled(secretID, cluster, nodepool, networkName, subnetworkName), + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + acctest.ExpectNoDelete(), + }, + }, + }, }, }) } -func testAccContainerNodePool_privateRegistryEnabled(secretID, cluster, nodepool, network, subnetwork string) string { +func testAccContainerNodePool_privateRegistryEnabled(secretID, cluster, nodepool, network, subnetwork, customDomain string) string { return fmt.Sprintf(` data "google_project" "test_project" {} @@ -4862,13 +4886,12 @@ resource "google_container_node_pool" "np" { oauth_scopes = [ "https://www.googleapis.com/auth/cloud-platform", ] - machine_type = "n1-standard-8" image_type = "COS_CONTAINERD" containerd_config { private_registry_access_config { enabled = true certificate_authority_domain_config { - fqdns = ["my.custom.domain", "10.0.0.127:8888"] + fqdns = ["%s", "10.0.0.127:8888"] gcp_secret_manager_certificate_config { secret_uri = google_secret_manager_secret_version.secret-version-basic.name } @@ -4883,6 +4906,64 @@ resource "google_container_node_pool" "np" { } } } +`, secretID, cluster, network, subnetwork, nodepool, customDomain) +} + +func testAccContainerNodePool_privateRegistryDisabled(secretID, cluster, nodepool, network, subnetwork string) string { + return fmt.Sprintf(` +# Leave these unneeded resources in-place so we don't show a deletion in the plan +data "google_project" "test_project" {} + +resource "google_secret_manager_secret" "secret-basic" { + secret_id = "%s" + replication { + user_managed { + replicas { + location = "us-central1" + } + } + } +} + +resource "google_secret_manager_secret_version" "secret-version-basic" { + secret = google_secret_manager_secret.secret-basic.id + secret_data = "dummypassword" +} + +resource "google_secret_manager_secret_iam_member" "secret_iam" { + secret_id = google_secret_manager_secret.secret-basic.id + role = "roles/secretmanager.admin" + member = "serviceAccount:${data.google_project.test_project.number}-compute@developer.gserviceaccount.com" + depends_on = [google_secret_manager_secret_version.secret-version-basic] +} + +resource "google_container_cluster" "cluster" { + name = "%s" + location = "us-central1-a" + initial_node_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 { + oauth_scopes = [ + "https://www.googleapis.com/auth/cloud-platform", + ] + image_type = "COS_CONTAINERD" + containerd_config { + private_registry_access_config { + enabled = false + } + } + } +} `, secretID, cluster, network, subnetwork, nodepool) }