From 4c0956ff00be40476b27a96f1b3a2a2ef5e1ab32 Mon Sep 17 00:00:00 2001
From: Ross Nicoll <rnicoll@google.com>
Date: Thu, 24 Aug 2023 17:55:09 +0000
Subject: [PATCH] Add confidential nodes support to node pools

---
 .../services/container/node_config.go.erb     | 49 +++++++++-
 .../resource_container_cluster.go.erb         | 21 ----
 .../resource_container_node_pool_test.go.erb  | 98 +++++++++++++++++++
 3 files changed, 145 insertions(+), 23 deletions(-)

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 38ab42fa33e7..bbae9ce00888 100644
--- a/mmv1/third_party/terraform/services/container/node_config.go.erb
+++ b/mmv1/third_party/terraform/services/container/node_config.go.erb
@@ -624,6 +624,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.`,
+							},
+						},
+					},
+				},
 			},
 		},
 	}
@@ -907,6 +925,11 @@ func expandNodeConfig(v interface{}) *container.NodeConfig {
 		nc.HostMaintenancePolicy = expandHostMaintenancePolicy(v)
 	}
 	<% end -%>
+
+	if v, ok := nodeConfig["confidential_nodes"]; ok {
+		nc.ConfidentialNodes = expandConfidentialNodes(v)
+	}
+
 	return nc
 }
 
@@ -1024,6 +1047,17 @@ func expandHostMaintenancePolicy(v interface{}) *container.HostMaintenancePolicy
 }
 <% end -%>
 
+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)
 
@@ -1077,8 +1111,9 @@ func flattenNodeConfig(c *container.NodeConfig) []map[string]interface{} {
 		"workload_metadata_config": flattenWorkloadMetadataConfig(c.WorkloadMetadataConfig),
 <% unless version == 'ga' -%>
 		"sandbox_config": 			 flattenSandboxConfig(c.SandboxConfig),
-		"host_maintenance_policy": flattenHostMaintenancePolicy(c.HostMaintenancePolicy),
+		"host_maintenance_policy":  flattenHostMaintenancePolicy(c.HostMaintenancePolicy),
 <% end -%>
+		"confidential_nodes":       flattenConfidentialNodes(c.ConfidentialNodes),
 		"boot_disk_kms_key": 		c.BootDiskKmsKey,
 		"kubelet_config":            flattenKubeletConfig(c.KubeletConfig),
 		"linux_node_config":         flattenLinuxNodeConfig(c.LinuxNodeConfig),
@@ -1387,6 +1422,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 {
@@ -1416,4 +1461,4 @@ func flattenHostMaintenancePolicy(c *container.HostMaintenancePolicy) []map[stri
 
 	return result
 }
-<% end -%>
\ No newline at end of file
+<% end -%>
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 84fe1b0fbfc4..1fea5706f99f 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
@@ -4819,17 +4819,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 {
@@ -5362,16 +5351,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/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 72997080aede..cb3ceb60ef5c 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
@@ -3280,6 +3280,103 @@ 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))
+	npName := 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, npName),
+			},
+			{
+				ResourceName:            "google_container_node_pool.confidential_nodes",
+				ImportState:             true,
+				ImportStateVerify:       true,
+			},
+			{
+				Config: testAccContainerNodePool_disableConfidentialNodes(clusterName, npName),
+			},
+			{
+				ResourceName:            "google_container_node_pool.confidential_nodes",
+				ImportState:             true,
+				ImportStateVerify:       true,
+			},
+			{
+				Config: testAccContainerNodePool_withConfidentialNodes(clusterName, npName),
+			},
+			{
+				ResourceName:            "google_container_node_pool.confidential_nodes",
+				ImportState:             true,
+				ImportStateVerify:       true,
+			},
+		},
+	})
+}
+
+func testAccContainerNodePool_withConfidentialNodes(clusterName string, npName string) string {
+	return fmt.Sprintf(`
+resource "google_container_cluster" "cluster" {
+  name               = "%s"
+  location           = "asia-east1-c"
+  initial_node_count = 1
+  node_config {
+    host_maintenance_policy {
+		maintenance_interval = "PERIODIC"
+	}
+    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, npName)
+}
+
+func testAccContainerNodePool_disableConfidentialNodes(clusterName string, npName string) string {
+	return fmt.Sprintf(`
+resource "google_container_cluster" "cluster" {
+  name               = "%s"
+  location           = "asia-east1-c"
+  initial_node_count = 1
+  node_config {
+    host_maintenance_policy {
+		maintenance_interval = "PERIODIC"
+	}
+    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, npName)
+}
+
 <% unless version == 'ga' -%>
 func TestAccContainerNodePool_tpuTopology(t *testing.T) {
 	t.Parallel()
@@ -3401,4 +3498,5 @@ resource "google_container_node_pool" "np" {
 }
 `, cluster, np)
 }
+
 <% end -%>