Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 95 additions & 0 deletions mmv1/third_party/terraform/services/container/node_config.go.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,25 @@ func schemaGcfsConfig() *schema.Schema {
}
}

func schemaTaintConfig() *schema.Schema {
return &schema.Schema{
Type: schema.TypeList,
Optional: true,
MaxItems: 1,
Description: `Taint configuration for this node.`,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"architecture_taint_behavior": {
Type: schema.TypeString,
Required: true,
Description: `Architecture taint behavior. Controls, how we apply taints based on the node architecture.`,
ValidateFunc: validation.StringInSlice([]string{"ARCHITECTURE_TAINT_BEHAVIOR_UNSPECIFIED", "NONE", "ARM"}, false),
},
},
},
}
}

func schemaNodeConfig() *schema.Schema {
return &schema.Schema{
Type: schema.TypeList,
Expand All @@ -254,6 +273,7 @@ func schemaNodeConfig() *schema.Schema {
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"taint_config": schemaTaintConfig(),
"containerd_config": schemaContainerdConfig(),
"disk_size_gb": {
Type: schema.TypeInt,
Expand Down Expand Up @@ -1541,6 +1561,10 @@ func expandNodeConfig(d *schema.ResourceData, prefix string, v interface{}) *con

nodeConfig := nodeConfigs[0].(map[string]interface{})

if v, ok := nodeConfig["taint_config"]; ok {
nc.TaintConfig = expandTaintConfig(v)
}

if v, ok := nodeConfig["containerd_config"]; ok {
nc.ContainerdConfig = expandContainerdConfig(v)
}
Expand Down Expand Up @@ -2763,6 +2787,28 @@ func expandSoleTenantConfig(v interface{}) *container.SoleTenantConfig {
return stConfig
}

func expandTaintConfig(v interface{}) *container.TaintConfig {
if v == nil {
return nil
}
ls := v.([]interface{})
if len(ls) == 0 {
return nil
}
if ls[0] == nil {
return &container.TaintConfig{}
}
cfg := ls[0].(map[string]interface{})

taintConfig := &container.TaintConfig{}

if v, ok := cfg["architecture_taint_behavior"]; ok {
taintConfig.ArchitectureTaintBehavior = v.(string)
}

return taintConfig
}

{{ if ne $.TargetVersionName `ga` -}}
func expandHostMaintenancePolicy(v interface{}) *container.HostMaintenancePolicy {
if v == nil {
Expand Down Expand Up @@ -2834,6 +2880,7 @@ func flattenNodeConfig(c *container.NodeConfig, v interface{}) []map[string]inte

config = append(config, map[string]interface{}{
"machine_type": c.MachineType,
"taint_config": flattenTaintConfig(c.TaintConfig),
"containerd_config": flattenContainerdConfig(c.ContainerdConfig),
"disk_size_gb": c.DiskSizeGb,
"disk_type": c.DiskType,
Expand Down Expand Up @@ -3496,6 +3543,17 @@ func flattenNodeKernelModuleLoading(c *container.NodeKernelModuleLoading) []map[
return result
}

func flattenTaintConfig(c *container.TaintConfig) []map[string]interface{} {
result := []map[string]interface{}{}
if c == nil {
return result
}
r := map[string]interface{}{
"architecture_taint_behavior": c.ArchitectureTaintBehavior,
}
return append(result, r)
}

func flattenContainerdConfig(c *container.ContainerdConfig) []map[string]interface{} {
result := []map[string]interface{}{}
if c == nil {
Expand Down Expand Up @@ -3763,6 +3821,43 @@ func nodePoolNodeConfigUpdate(d *schema.ResourceData, config *transport_tpg.Conf
}
}

if d.HasChange(prefix + "node_config.0.taint_config") {
if _, ok := d.GetOk(prefix + "node_config.0.taint_config"); ok {
req := &container.UpdateNodePoolRequest{
Name: name,
TaintConfig: expandTaintConfig(d.Get(prefix + "node_config.0.taint_config")),
}
if req.TaintConfig == nil {
req.TaintConfig = &container.TaintConfig{}
req.ForceSendFields = []string{"TaintConfig"}
}

updateF := func() error {
clusterNodePoolsUpdateCall := NewClient(config, 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 taint_config", userAgent,
timeout)
}

if err := retryWhileIncompatibleOperation(timeout, npLockKey, updateF); err != nil {
return err
}

log.Printf("[INFO] Updated taint_config for node pool %s", name)
}
}

if d.HasChange(prefix + "node_config.0.containerd_config") {
if _, ok := d.GetOk(prefix + "node_config.0.containerd_config"); ok {
req := &container.UpdateNodePoolRequest{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,7 @@ fields:
api_field: 'nodeConfig.taints.key'
- field: 'node_config.taint.value'
api_field: 'nodeConfig.taints.value'
- api_field: 'nodeConfig.taintConfig.architectureTaintBehavior'
- api_field: 'nodeConfig.windowsNodeConfig.osVersion'
field: 'node_config.windows_node_config.osversion'
- api_field: 'nodeConfig.workloadMetadataConfig.mode'
Expand Down Expand Up @@ -757,6 +758,8 @@ fields:
api_field: 'nodePools.config.taints.key'
- field: 'node_pool.node_config.taint.value'
api_field: 'nodePools.config.taints.value'
- field: 'node_pool.node_config.taint_config.architecture_taint_behavior'
api_field: 'nodePools.config.taintConfig.architectureTaintBehavior'
- field: 'node_pool.node_config.windows_node_config.osversion'
api_field: 'nodePools.config.windowsNodeConfig.osVersion'
- field: 'node_pool.node_config.workload_metadata_config.mode'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18416,3 +18416,191 @@ resource "google_container_cluster" "with_slurm_config" {
}
`, clusterName, networkName, subnetworkName, enabled)
}

func TestAccContainerCluster_withTaintConfig(t *testing.T) {
t.Parallel()

cluster := fmt.Sprintf("tf-test-cluster-%s", acctest.RandString(t, 10))
networkName := tpgcompute.BootstrapSharedTestNetwork(t, "gke-cluster")
subnetworkName := tpgcompute.BootstrapSubnet(t, "gke-cluster", networkName)
importIgnore := []string{"min_master_version", "deletion_protection"}

acctest.VcrTest(t, resource.TestCase{
PreCheck: func() { acctest.AccTestPreCheck(t) },
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
CheckDestroy: testAccCheckContainerClusterDestroyProducer(t),
Steps: []resource.TestStep{
// Default enum value means adding arm taint to nodes (same as ARM)
{
Config: testAccContainerCluster_withTaintConfig(cluster, networkName, subnetworkName, "ARCHITECTURE_TAINT_BEHAVIOR_UNSPECIFIED"),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("google_container_cluster.cluster", "node_config.0.taint_config.0.architecture_taint_behavior", "ARCHITECTURE_TAINT_BEHAVIOR_UNSPECIFIED"),
resource.TestCheckResourceAttr("google_container_cluster.cluster", "node_config.0.effective_taints.#", "1"),
resource.TestCheckResourceAttr("google_container_cluster.cluster", "node_config.0.effective_taints.0.key", "kubernetes.io/arch"),
resource.TestCheckResourceAttr("google_container_cluster.cluster", "node_config.0.effective_taints.0.value", "arm64"),
resource.TestCheckResourceAttr("google_container_cluster.cluster", "node_config.0.effective_taints.0.effect", "NO_SCHEDULE"),
),
},
{
ResourceName: "google_container_cluster.cluster",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: importIgnore,
},
// NONE variant means no architecture taint will be applied
{
Config: testAccContainerCluster_withTaintConfig(cluster, networkName, subnetworkName, "NONE"),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("google_container_cluster.cluster", "node_config.0.taint_config.0.architecture_taint_behavior", "NONE"),
resource.TestCheckResourceAttr("google_container_cluster.cluster", "node_config.0.effective_taints.#", "0"),
),
},
{
ResourceName: "google_container_cluster.cluster",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: importIgnore,
},
// ARM is a default behavior right now, same as ARCHITECTURE_TAINT_BEHAVIOR_UNSPECIFIED
{
Config: testAccContainerCluster_withTaintConfig(cluster, networkName, subnetworkName, "ARM"),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("google_container_cluster.cluster", "node_config.0.taint_config.0.architecture_taint_behavior", "ARM"),
resource.TestCheckResourceAttr("google_container_cluster.cluster", "node_config.0.effective_taints.#", "1"),
resource.TestCheckResourceAttr("google_container_cluster.cluster", "node_config.0.effective_taints.0.key", "kubernetes.io/arch"),
resource.TestCheckResourceAttr("google_container_cluster.cluster", "node_config.0.effective_taints.0.value", "arm64"),
resource.TestCheckResourceAttr("google_container_cluster.cluster", "node_config.0.effective_taints.0.effect", "NO_SCHEDULE"),
),
},
{
ResourceName: "google_container_cluster.cluster",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: importIgnore,
},
},
})
}

func testAccContainerCluster_withTaintConfig(cluster, networkName, subnetworkName, behavior string) string {
return fmt.Sprintf(`
data "google_container_engine_versions" "central1a" {
location = "us-central1-a"
}

resource "google_container_cluster" "cluster" {
name = "%s"
location = "us-central1-a"
initial_node_count = 1
min_master_version = data.google_container_engine_versions.central1a.release_channel_latest_version["RAPID"]

network = "%s"
subnetwork = "%s"

node_config {
machine_type = "t2a-standard-2"
taint_config {
architecture_taint_behavior = "%s"
}
}

deletion_protection = false
}
`, cluster, networkName, subnetworkName, behavior)
}

func TestAccContainerCluster_withNodePoolTaintConfig(t *testing.T) {
t.Parallel()

cluster := fmt.Sprintf("tf-test-cluster-%s", acctest.RandString(t, 10))
networkName := tpgcompute.BootstrapSharedTestNetwork(t, "gke-cluster")
subnetworkName := tpgcompute.BootstrapSubnet(t, "gke-cluster", networkName)
importIgnore := []string{"min_master_version", "deletion_protection"}

acctest.VcrTest(t, resource.TestCase{
PreCheck: func() { acctest.AccTestPreCheck(t) },
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
CheckDestroy: testAccCheckContainerClusterDestroyProducer(t),
Steps: []resource.TestStep{
// Default enum value means adding arm taint to nodes (same as ARM)
{
Config: testAccContainerCluster_withNodePoolTaintConfig(cluster, networkName, subnetworkName, "ARCHITECTURE_TAINT_BEHAVIOR_UNSPECIFIED"),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("google_container_cluster.cluster", "node_pool.0.node_config.0.taint_config.0.architecture_taint_behavior", "ARCHITECTURE_TAINT_BEHAVIOR_UNSPECIFIED"),
resource.TestCheckResourceAttr("google_container_cluster.cluster", "node_pool.0.node_config.0.effective_taints.#", "1"),
resource.TestCheckResourceAttr("google_container_cluster.cluster", "node_pool.0.node_config.0.effective_taints.0.key", "kubernetes.io/arch"),
resource.TestCheckResourceAttr("google_container_cluster.cluster", "node_pool.0.node_config.0.effective_taints.0.value", "arm64"),
resource.TestCheckResourceAttr("google_container_cluster.cluster", "node_pool.0.node_config.0.effective_taints.0.effect", "NO_SCHEDULE"),
),
},
{
ResourceName: "google_container_cluster.cluster",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: importIgnore,
},
},
})
}

func TestAccContainerCluster_withNodePoolTaintConfig_none(t *testing.T) {
t.Parallel()

cluster := fmt.Sprintf("tf-test-cluster-%s", acctest.RandString(t, 10))
networkName := tpgcompute.BootstrapSharedTestNetwork(t, "gke-cluster")
subnetworkName := tpgcompute.BootstrapSubnet(t, "gke-cluster", networkName)
importIgnore := []string{"min_master_version", "deletion_protection"}

acctest.VcrTest(t, resource.TestCase{
PreCheck: func() { acctest.AccTestPreCheck(t) },
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
CheckDestroy: testAccCheckContainerClusterDestroyProducer(t),
Steps: []resource.TestStep{
// NONE variant means no architecture taint will be applied
{
Config: testAccContainerCluster_withNodePoolTaintConfig(cluster, networkName, subnetworkName, "NONE"),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("google_container_cluster.cluster", "node_pool.0.node_config.0.taint_config.0.architecture_taint_behavior", "NONE"),
resource.TestCheckResourceAttr("google_container_cluster.cluster", "node_pool.0.node_config.0.effective_taints.#", "0"),
),
},
{
ResourceName: "google_container_cluster.cluster",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: importIgnore,
},
},
})
}

func testAccContainerCluster_withNodePoolTaintConfig(cluster, networkName, subnetworkName, behavior string) string {
return fmt.Sprintf(`
data "google_container_engine_versions" "central1a" {
location = "us-central1-a"
}

resource "google_container_cluster" "cluster" {
name = "%s"
location = "us-central1-a"
min_master_version = data.google_container_engine_versions.central1a.release_channel_latest_version["RAPID"]

network = "%s"
subnetwork = "%s"

node_pool {
name = "custom-pool"
initial_node_count = 1

node_config {
machine_type = "n4a-standard-2"
taint_config {
architecture_taint_behavior = "%s"
}
}
}

deletion_protection = false
}
`, cluster, networkName, subnetworkName, behavior)
}
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,8 @@ fields:
api_field: 'config.taints.key'
- field: 'node_config.taint.value'
api_field: 'config.taints.value'
- field: 'node_config.taint_config.architecture_taint_behavior'
api_field: 'config.taintConfig.architectureTaintBehavior'
- field: 'node_config.windows_node_config.osversion'
api_field: 'config.windowsNodeConfig.osVersion'
- field: 'node_config.workload_metadata_config.mode'
Expand Down
Loading
Loading