diff --git a/.changelog/8758.txt b/.changelog/8758.txt new file mode 100644 index 00000000000..b11b8d4acab --- /dev/null +++ b/.changelog/8758.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +container: added `node_config.confidential_compute` field to `google_container_node_pool` resource +``` diff --git a/google/services/container/node_config.go b/google/services/container/node_config.go index 8b2c4cbd4ea..4d6e318052e 100644 --- a/google/services/container/node_config.go +++ b/google/services/container/node_config.go @@ -571,6 +571,24 @@ func schemaNodeConfig() *schema.Schema { }, }, }, + "confidential_nodes": { + Type: schema.TypeList, + Optional: true, + Computed: true, + ForceNew: true, + MaxItems: 1, + Description: `Configuration for the confidential nodes feature, which makes nodes run on confidential VMs. Warning: This configuration can't be changed (or added/removed) after pool creation without deleting and recreating the entire pool.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enabled": { + Type: schema.TypeBool, + Required: true, + ForceNew: true, + Description: `Whether Confidential Nodes feature is enabled for all nodes in this pool.`, + }, + }, + }, + }, }, }, } @@ -824,6 +842,10 @@ func expandNodeConfig(v interface{}) *container.NodeConfig { nc.SoleTenantConfig = expandSoleTenantConfig(v) } + if v, ok := nodeConfig["confidential_nodes"]; ok { + nc.ConfidentialNodes = expandConfidentialNodes(v) + } + return nc } @@ -922,6 +944,17 @@ func expandSoleTenantConfig(v interface{}) *container.SoleTenantConfig { } } +func expandConfidentialNodes(configured interface{}) *container.ConfidentialNodes { + l := configured.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil + } + config := l[0].(map[string]interface{}) + return &container.ConfidentialNodes{ + Enabled: config["enabled"].(bool), + } +} + func flattenNodeConfigDefaults(c *container.NodeConfigDefaults) []map[string]interface{} { result := make([]map[string]interface{}, 0, 1) @@ -967,6 +1000,7 @@ func flattenNodeConfig(c *container.NodeConfig) []map[string]interface{} { "shielded_instance_config": flattenShieldedInstanceConfig(c.ShieldedInstanceConfig), "taint": flattenTaints(c.Taints), "workload_metadata_config": flattenWorkloadMetadataConfig(c.WorkloadMetadataConfig), + "confidential_nodes": flattenConfidentialNodes(c.ConfidentialNodes), "boot_disk_kms_key": c.BootDiskKmsKey, "kubelet_config": flattenKubeletConfig(c.KubeletConfig), "linux_node_config": flattenLinuxNodeConfig(c.LinuxNodeConfig), @@ -1136,6 +1170,16 @@ func flattenLinuxNodeConfig(c *container.LinuxNodeConfig) []map[string]interface return result } +func flattenConfidentialNodes(c *container.ConfidentialNodes) []map[string]interface{} { + result := []map[string]interface{}{} + if c != nil { + result = append(result, map[string]interface{}{ + "enabled": c.Enabled, + }) + } + return result +} + func flattenSoleTenantConfig(c *container.SoleTenantConfig) []map[string]interface{} { result := []map[string]interface{}{} if c == nil { diff --git a/google/services/container/resource_container_cluster.go b/google/services/container/resource_container_cluster.go index b09ed2375c8..ed86abbbaaa 100644 --- a/google/services/container/resource_container_cluster.go +++ b/google/services/container/resource_container_cluster.go @@ -4277,17 +4277,6 @@ func expandBinaryAuthorization(configured interface{}, legacy_enabled bool) *con } } -func expandConfidentialNodes(configured interface{}) *container.ConfidentialNodes { - l := configured.([]interface{}) - if len(l) == 0 || l[0] == nil { - return nil - } - config := l[0].(map[string]interface{}) - return &container.ConfidentialNodes{ - Enabled: config["enabled"].(bool), - } -} - func expandMasterAuth(configured interface{}) *container.MasterAuth { l := configured.([]interface{}) if len(l) == 0 || l[0] == nil { @@ -4735,16 +4724,6 @@ func flattenBinaryAuthorization(c *container.BinaryAuthorization) []map[string]i return result } -func flattenConfidentialNodes(c *container.ConfidentialNodes) []map[string]interface{} { - result := []map[string]interface{}{} - if c != nil { - result = append(result, map[string]interface{}{ - "enabled": c.Enabled, - }) - } - return result -} - func flattenNetworkPolicy(c *container.NetworkPolicy) []map[string]interface{} { result := []map[string]interface{}{} if c != nil { diff --git a/google/services/container/resource_container_node_pool_test.go b/google/services/container/resource_container_node_pool_test.go index 60c3978e03e..7ba56391e2f 100644 --- a/google/services/container/resource_container_node_pool_test.go +++ b/google/services/container/resource_container_node_pool_test.go @@ -2858,3 +2858,100 @@ resource "google_container_node_pool" "with_sole_tenant_config" { } `, cluster, np) } + +func TestAccContainerNodePool_withConfidentialNodes(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)) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckContainerClusterDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccContainerNodePool_withConfidentialNodes(clusterName, np), + }, + { + ResourceName: "google_container_node_pool.np", + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccContainerNodePool_disableConfidentialNodes(clusterName, np), + }, + { + ResourceName: "google_container_node_pool.np", + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccContainerNodePool_withConfidentialNodes(clusterName, np), + }, + { + ResourceName: "google_container_node_pool.np", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccContainerNodePool_withConfidentialNodes(clusterName string, np string) string { + return fmt.Sprintf(` +resource "google_container_cluster" "cluster" { + name = "%s" + location = "asia-east1-c" + initial_node_count = 1 + node_config { + confidential_nodes { + enabled = false + } + machine_type = "n2-standard-2" + } +} + +resource "google_container_node_pool" "np" { + name = "%s" + location = "asia-east1-c" + cluster = google_container_cluster.cluster.name + initial_node_count = 1 + node_config { + machine_type = "n2d-standard-2" // can't be e2 because Confidential Nodes require AMD CPUs + confidential_nodes { + enabled = true + } + } +} +`, clusterName, np) +} + +func testAccContainerNodePool_disableConfidentialNodes(clusterName string, np string) string { + return fmt.Sprintf(` +resource "google_container_cluster" "cluster" { + name = "%s" + location = "asia-east1-c" + initial_node_count = 1 + node_config { + confidential_nodes { + enabled = false + } + machine_type = "n2-standard-2" + } +} + +resource "google_container_node_pool" "np" { + name = "%s" + location = "asia-east1-c" + cluster = google_container_cluster.cluster.name + initial_node_count = 1 + node_config { + machine_type = "n2d-standard-2" // can't be e2 because Confidential Nodes require AMD CPUs + confidential_nodes { + enabled = false + } + } +} +`, clusterName, np) +}