diff --git a/mmv1/third_party/terraform/services/container/node_config.go.erb b/mmv1/third_party/terraform/services/container/node_config.go.erb index 702fb6319d02..546661a54e3e 100644 --- a/mmv1/third_party/terraform/services/container/node_config.go.erb +++ b/mmv1/third_party/terraform/services/container/node_config.go.erb @@ -28,6 +28,56 @@ var defaultOauthScopes = []string{ "https://www.googleapis.com/auth/trace.append", } +func schemaContainerdConfig() *schema.Schema { + return &schema.Schema{ + Type: schema.TypeList, + Optional: true, + Description: "Parameters for containerd configuration.", + MaxItems: 1, + Elem: &schema.Resource{Schema: map[string]*schema.Schema{ + "private_registry_access_config": &schema.Schema{ + Type: schema.TypeList, + Optional: true, + Description: "Parameters for private container registries configuration.", + MaxItems: 1, + Elem: &schema.Resource{Schema: map[string]*schema.Schema{ + "enabled": &schema.Schema{ + Type: schema.TypeBool, + Required: true, + Description: "Whether or not private registries are configured.", + }, + "certificate_authority_domain_config": &schema.Schema{ + Type: schema.TypeList, + Optional: true, + Description: "Parameters for configuring CA certificate and domains.", + Elem: &schema.Resource{Schema: map[string]*schema.Schema{ + "fqdns": &schema.Schema{ + Type: schema.TypeList, + Required: true, + Description: "List of fully-qualified-domain-names. IPv4s and port specification are supported.", + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "gcp_secret_manager_certificate_config": &schema.Schema{ + Type: schema.TypeList, + Required: true, + Description: "Parameters for configuring a certificate hosted in GCP SecretManager.", + MaxItems: 1, + Elem: &schema.Resource{Schema: map[string]*schema.Schema{ + "secret_uri": &schema.Schema{ + Type: schema.TypeString, + Required: true, + Description: "URI for the secret that hosts a certificate. Must be in the format 'projects/PROJECT_NUM/secrets/SECRET_NAME/versions/VERSION_OR_LATEST'.", + }, + }}, + }, + }}, + }, + }}, + }, + }}, + } +} + func schemaLoggingVariant() *schema.Schema { return &schema.Schema{ Type: schema.TypeString, @@ -68,6 +118,7 @@ func schemaNodeConfig() *schema.Schema { MaxItems: 1, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ + "containerd_config": schemaContainerdConfig(), "disk_size_gb": { Type: schema.TypeInt, Optional: true, @@ -729,6 +780,7 @@ func expandNodeConfigDefaults(configured interface{}) *container.NodeConfigDefau config := configs[0].(map[string]interface{}) nodeConfigDefaults := &container.NodeConfigDefaults{} + nodeConfigDefaults.ContainerdConfig = expandContainerdConfig(config["containerd_config"]) if variant, ok := config["logging_variant"]; ok { nodeConfigDefaults.LoggingConfig = &container.NodePoolLoggingConfig{ VariantConfig: &container.LoggingVariantConfig{ @@ -759,6 +811,10 @@ func expandNodeConfig(v interface{}) *container.NodeConfig { nodeConfig := nodeConfigs[0].(map[string]interface{}) + if v, ok := nodeConfig["containerd_config"]; ok { + nc.ContainerdConfig = expandContainerdConfig(v) + } + if v, ok := nodeConfig["machine_type"]; ok { nc.MachineType = v.(string) } @@ -1137,6 +1193,92 @@ func expandCgroupMode(cfg map[string]interface{}) string { return cgroupMode.(string) } +func expandContainerdConfig(v interface{}) *container.ContainerdConfig { + if v == nil { + return nil + } + ls := v.([]interface{}) + if len(ls) == 0 { + return nil + } + if ls[0] == nil { + return &container.ContainerdConfig{} + } + cfg := ls[0].(map[string]interface{}) + + cc := &container.ContainerdConfig{} + cc.PrivateRegistryAccessConfig = expandPrivateRegistryAccessConfig(cfg["private_registry_access_config"]) + return cc +} + +func expandPrivateRegistryAccessConfig(v interface{}) *container.PrivateRegistryAccessConfig { + if v == nil { + return nil + } + ls := v.([]interface{}) + if len(ls) == 0 { + return nil + } + if ls[0] == nil { + return &container.PrivateRegistryAccessConfig{} + } + cfg := ls[0].(map[string]interface{}) + + pracc := &container.PrivateRegistryAccessConfig{} + if enabled, ok := cfg["enabled"]; ok { + pracc.Enabled = enabled.(bool) + } + if caCfgRaw, ok := cfg["certificate_authority_domain_config"]; ok { + ls := caCfgRaw.([]interface{}) + pracc.CertificateAuthorityDomainConfig = make([]*container.CertificateAuthorityDomainConfig, len(ls)) + for i, caCfg := range ls { + pracc.CertificateAuthorityDomainConfig[i] = expandCADomainConfig(caCfg) + } + } + + return pracc +} + +func expandCADomainConfig(v interface{}) *container.CertificateAuthorityDomainConfig { + if v == nil { + return nil + } + cfg := v.(map[string]interface{}) + + caConfig := &container.CertificateAuthorityDomainConfig{} + if v, ok := cfg["fqdns"]; ok { + fqdns := v.([]interface{}) + caConfig.Fqdns = make([]string, len(fqdns)) + for i, dn := range fqdns { + caConfig.Fqdns[i] = dn.(string) + } + } + + caConfig.GcpSecretManagerCertificateConfig = expandGCPSecretManagerCertificateConfig(cfg["gcp_secret_manager_certificate_config"]) + + return caConfig +} + +func expandGCPSecretManagerCertificateConfig(v interface{}) *container.GCPSecretManagerCertificateConfig { + if v == nil { + return nil + } + ls := v.([]interface{}) + if len(ls) == 0 { + return nil + } + if ls[0] == nil { + return &container.GCPSecretManagerCertificateConfig{} + } + cfg := ls[0].(map[string]interface{}) + + gcpSMConfig := &container.GCPSecretManagerCertificateConfig{} + if v, ok := cfg["secret_uri"]; ok { + gcpSMConfig.SecretUri = v.(string) + } + return gcpSMConfig +} + func expandSoleTenantConfig(v interface{}) *container.SoleTenantConfig { if v == nil { return nil @@ -1204,6 +1346,8 @@ func flattenNodeConfigDefaults(c *container.NodeConfigDefaults) []map[string]int result = append(result, map[string]interface{}{}) + result[0]["containerd_config"] = flattenContainerdConfig(c.ContainerdConfig) + result[0]["logging_variant"] = flattenLoggingVariant(c.LoggingConfig) <% unless version == 'ga' -%> @@ -1232,6 +1376,7 @@ func flattenNodeConfig(c *container.NodeConfig, v interface{}) []map[string]inte config = append(config, map[string]interface{}{ "machine_type": c.MachineType, + "containerd_config": flattenContainerdConfig(c.ContainerdConfig), "disk_size_gb": c.DiskSizeGb, "disk_type": c.DiskType, "guest_accelerator": flattenContainerGuestAccelerators(c.Accelerators), @@ -1559,6 +1704,74 @@ func flattenLinuxNodeConfig(c *container.LinuxNodeConfig) []map[string]interface return result } +func flattenContainerdConfig(c *container.ContainerdConfig) []map[string]interface{} { + result := []map[string]interface{}{} + if c == nil { + return result + } + r := map[string]interface{}{} + if c.PrivateRegistryAccessConfig != nil { + r["private_registry_access_config"] = flattenPrivateRegistryAccessConfig(c.PrivateRegistryAccessConfig) + } + return append(result, r) +} + +func flattenPrivateRegistryAccessConfig(c *container.PrivateRegistryAccessConfig) []map[string]interface{} { + result := []map[string]interface{}{} + if c == nil { + return result + } + r := map[string]interface{}{ + "enabled": c.Enabled, + } + if c.CertificateAuthorityDomainConfig != nil { + caConfigs := make([]interface{}, len(c.CertificateAuthorityDomainConfig)) + for i, caCfg := range c.CertificateAuthorityDomainConfig { + caConfigs[i] = flattenCADomainConfig(caCfg) + } + r["certificate_authority_domain_config"] = caConfigs + } + return append(result, r) +} + +// func flattenCADomainConfig(c *container.CertificateAuthorityDomainConfig) []map[string]interface{} { +// result := []map[string]interface{}{} +// if c == nil { +// return result +// } +// r := map[string]interface{}{ +// "fqdns": c.Fqdns, +// } +// if c.GcpSecretManagerCertificateConfig != nil { +// r["gcp_secret_manager_certificate_config"] = flattenGCPSecretManagerCertificateConfig(c.GcpSecretManagerCertificateConfig) +// } +// return append(result, r) +// } + +func flattenCADomainConfig(c *container.CertificateAuthorityDomainConfig) map[string]interface{} { + if c == nil { + return nil + } + r := map[string]interface{}{ + "fqdns": c.Fqdns, + } + if c.GcpSecretManagerCertificateConfig != nil { + r["gcp_secret_manager_certificate_config"] = flattenGCPSecretManagerCertificateConfig(c.GcpSecretManagerCertificateConfig) + } + return r +} + +func flattenGCPSecretManagerCertificateConfig(c *container.GCPSecretManagerCertificateConfig) []map[string]interface{} { + result := []map[string]interface{}{} + if c == nil { + return result + } + r := map[string]interface{}{ + "secret_uri": c.SecretUri, + } + return append(result, r) +} + func flattenConfidentialNodes(c *container.ConfidentialNodes) []map[string]interface{} { result := []map[string]interface{}{} if c != nil { diff --git a/mmv1/third_party/terraform/services/container/resource_container_cluster.go.erb b/mmv1/third_party/terraform/services/container/resource_container_cluster.go.erb index f82c7581e18d..bb99d27067da 100644 --- a/mmv1/third_party/terraform/services/container/resource_container_cluster.go.erb +++ b/mmv1/third_party/terraform/services/container/resource_container_cluster.go.erb @@ -148,6 +148,7 @@ func clusterSchemaNodePoolDefaults() *schema.Schema { MaxItems: 1, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ + "containerd_config": schemaContainerdConfig(), <% unless version == 'ga' -%> "gcfs_config": schemaGcfsConfig(false), <% end -%> @@ -4189,6 +4190,21 @@ func resourceContainerClusterUpdate(d *schema.ResourceData, meta interface{}) er log.Printf("[INFO] GKE cluster %s Security Posture Config has been updated to %#v", d.Id(), req.Update.DesiredSecurityPostureConfig) } + if d.HasChange("node_pool_defaults") && d.HasChange("node_pool_defaults.0.node_config_defaults.0.containerd_config") { + if v, ok := d.GetOk("node_pool_defaults.0.node_config_defaults.0.containerd_config"); ok { + req := &container.UpdateClusterRequest{ + Update: &container.ClusterUpdate{ + DesiredContainerdConfig: expandContainerdConfig(v), + }, + } + updateF := updateFunc(req, "updating GKE cluster containerd config") + if err := transport_tpg.LockedCall(lockKey, updateF); err != nil { + return err + } + log.Printf("[INFO] GKE cluster %s containerd config has been updated to %#v", d.Id(), req.Update.DesiredContainerdConfig) + } + } + if d.HasChange("node_pool_auto_config.0.network_tags.0.tags") { tags := d.Get("node_pool_auto_config.0.network_tags.0.tags").([]interface{}) diff --git a/mmv1/third_party/terraform/services/container/resource_container_cluster_test.go.erb b/mmv1/third_party/terraform/services/container/resource_container_cluster_test.go.erb index 6773dbb94436..792bf1fd1a4b 100644 --- a/mmv1/third_party/terraform/services/container/resource_container_cluster_test.go.erb +++ b/mmv1/third_party/terraform/services/container/resource_container_cluster_test.go.erb @@ -10502,3 +10502,285 @@ resource "google_container_cluster" "with_autopilot" { } `, projectID, randomSuffix, clusterName, networkName, subnetworkName) } + +func TestAccContainerCluster_privateRegistry(t *testing.T) { + t.Parallel() + + clusterName := fmt.Sprintf("tf-test-cluster-%s", acctest.RandString(t, 10)) + nodePoolName := fmt.Sprintf("tf-test-nodepool-%s", acctest.RandString(t, 10)) + secretID := fmt.Sprintf("tf-test-secret-%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{ + resource.TestStep{ + Config: testAccContainerCluster_privateRegistryEnabled(secretID, clusterName, networkName, subnetworkName), + 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", + "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.#", + "2", + ), + // First CA config + 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", + ), + // Second CA config + 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.1.fqdns.0", + "10.1.2.32", + ), + ), + }, + { + ResourceName: "google_container_cluster.primary", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, + }, + { + Config: testAccContainerCluster_privateRegistryDisabled(clusterName, networkName, subnetworkName), + 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", + ), + 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", + ), + ), + }, + resource.TestStep{ + Config: testAccContainerCluster_withNodePoolPrivateRegistry(secretID, clusterName, nodePoolName, networkName, subnetworkName), + }, + { + ResourceName: "google_container_cluster.primary", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, + }, + resource.TestStep{ + Config: testAccContainerCluster_withNodeConfigPrivateRegistry(secretID, clusterName, networkName, subnetworkName), + }, + { + ResourceName: "google_container_cluster.primary", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, + }, + }, + }) +} + +func testAccContainerCluster_privateRegistryEnabled(secretID, clusterName, networkName, subnetworkName string) string { + return fmt.Sprintf(` +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" "primary" { + name = "%s" + location = "us-central1-a" + initial_node_count = 1 + deletion_protection = false + network = "%s" + subnetwork = "%s" + + node_pool_defaults { + node_config_defaults { + containerd_config { + private_registry_access_config { + enabled = true + certificate_authority_domain_config { + fqdns = [ "my.custom.domain" ] + gcp_secret_manager_certificate_config { + secret_uri = google_secret_manager_secret_version.secret-version-basic.name + } + } + 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 + } + } + } + } + } + } +} +`, secretID, clusterName, networkName, subnetworkName) +} + +func testAccContainerCluster_privateRegistryDisabled(clusterName, networkName, subnetworkName string) string { + return fmt.Sprintf(` +resource "google_container_cluster" "primary" { + name = "%s" + location = "us-central1-a" + initial_node_count = 1 + deletion_protection = false + network = "%s" + subnetwork = "%s" + + node_pool_defaults { + node_config_defaults { + containerd_config { + private_registry_access_config { + enabled = false + } + } + } + } +} +`, clusterName, networkName, subnetworkName) +} + +func testAccContainerCluster_withNodePoolPrivateRegistry(secretID, clusterName, nodePoolName, networkName, subnetworkName string) string { + return fmt.Sprintf(` +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" "primary" { + name = "%s" + location = "us-central1-a" + + node_pool { + 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 + } + } + } + } +} +} + deletion_protection = false + network = "%s" + subnetwork = "%s" +} +`, secretID, clusterName, nodePoolName, networkName, subnetworkName) +} + +func testAccContainerCluster_withNodeConfigPrivateRegistry(secretID, clusterName, networkName, subnetworkName string) string { + return fmt.Sprintf(` +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" "primary" { + name = "%s" + location = "us-central1-a" + 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 + } + } + } + } +} + deletion_protection = false + network = "%s" + subnetwork = "%s" +} +`, secretID, clusterName, networkName, subnetworkName) +} diff --git a/mmv1/third_party/terraform/services/container/resource_container_node_pool_test.go.erb b/mmv1/third_party/terraform/services/container/resource_container_node_pool_test.go.erb index 612c40a36a86..612f66e0d713 100644 --- a/mmv1/third_party/terraform/services/container/resource_container_node_pool_test.go.erb +++ b/mmv1/third_party/terraform/services/container/resource_container_node_pool_test.go.erb @@ -4734,3 +4734,119 @@ resource "google_container_node_pool" "primary_nodes" { } `, projectID, randomSuffix, clusterName, networkName, subnetworkName) } + +func TestAccContainerNodePool_privateRegistry(t *testing.T) { + t.Parallel() + + cluster := fmt.Sprintf("tf-test-cluster-%s", acctest.RandString(t, 10)) + nodepool := fmt.Sprintf("tf-test-nodepool-%s", acctest.RandString(t, 10)) + secretID := fmt.Sprintf("tf-test-secret-%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: testAccCheckContainerNodePoolDestroyProducer(t), + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccContainerNodePool_privateRegistryEnabled(secretID, cluster, nodepool, networkName, subnetworkName), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr( + "google_container_node_pool.np", + "node_config.0.containerd_config.0.private_registry_access_config.0.enabled", + "true", + ), + resource.TestCheckResourceAttr( + "google_container_node_pool.np", + "node_config.0.containerd_config.0.private_registry_access_config.0.certificate_authority_domain_config.#", + "2", + ), + // First CA config + 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", + ), + // Second CA config + resource.TestCheckResourceAttr( + "google_container_node_pool.np", + "node_config.0.containerd_config.0.private_registry_access_config.0.certificate_authority_domain_config.1.fqdns.0", + "10.1.2.32", + ), + ), + }, + }, + }) +} + +func testAccContainerNodePool_privateRegistryEnabled(secretID, cluster, nodepool, network, subnetwork string) string { + return fmt.Sprintf(` +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", + ] + 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 + } + } + 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 + } + } + } + } + } +} +`, secretID, cluster, network, subnetwork, nodepool) +} 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 254eec9bdb6e..005e828892ed 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 @@ -940,6 +940,8 @@ kubelet_config { * `linux_node_config` - (Optional) Parameters that can be configured on Linux nodes. Structure is [documented below](#nested_linux_node_config). +* `containerd_config` - (Optional) Parameters to customize containerd runtime. Structure is [documented below](#nested_containerd_config). + * `node_group` - (Optional) Setting this field will assign instances of this pool to run on the specified node group. This is useful for running workloads on [sole tenant nodes](https://cloud.google.com/compute/docs/nodes/sole-tenant-nodes). * `sole_tenant_config` (Optional) Allows specifying multiple [node affinities](https://cloud.google.com/compute/docs/nodes/sole-tenant-nodes#node_affinity_and_anti-affinity) useful for running workloads on [sole tenant nodes](https://cloud.google.com/kubernetes-engine/docs/how-to/sole-tenancy). `node_affinity` structure is [documented below](#nested_node_affinity). @@ -1281,6 +1283,26 @@ linux_node_config { * `CGROUP_MODE_V1`: CGROUP_MODE_V1 specifies to use cgroupv1 for the cgroup configuration on the node image. * `CGROUP_MODE_V2`: CGROUP_MODE_V2 specifies to use cgroupv2 for the cgroup configuration on the node image. +The `containerd_config` block supports: + +* `private_registry_access_config` (Optional) - Configuration for private container registries. There are two fields in this config: + + * `enabled` (Required) - Enables private registry config. If set to false, all other fields in this object must not be set. + + * `certificate_authority_domain_config` (Optional) - List of configuration objects for CA and domains. Each object identifies a certificate and its assigned domains. See [how to configure for private container registries](https://cloud.google.com/kubernetes-engine/docs/how-to/access-private-registries-private-certificates) for more detail. Example: + ```hcl + certificate_authority_domain_config { + fqdns = [ + "my.custom.domain", + "10.4.5.6", + "127.0.0.1:8888", + ] + gcp_secret_manager_certificate_config { + secret_uri = "projects/99999/secrets/my-ca-cert/versions/1" + } + } + ``` + The `vertical_pod_autoscaling` block supports: * `enabled` (Required) - Enables vertical pod autoscaling