Skip to content

Commit

Permalink
Setting ForceNew to false in the taint block of the GKE nodepool node…
Browse files Browse the repository at this point in the history
…_config resource (#9248) (#6536)

* Removing ForceNew from taint in change in a nodepool node_config

The context for this, even if I didn't find that API doc, is that gcloud and the Console UI do not require the node_pool recreation.

* Update resource_container_node_pool.go.erb

* Nodepool NodeConfig Taint update func

* TestAccContainerNodePool_withTaintsUpdate

* Update resource_container_node_pool_test.go.erb

* Update resource_container_node_pool_test.go.erb

* update ForceNew fields as per the review
[upstream:cd09f0916518907c6ebe72b6054f2f7add79552e]

Signed-off-by: Modular Magician <[email protected]>
  • Loading branch information
modular-magician authored Oct 19, 2023
1 parent fa267db commit fad4935
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 4 deletions.
3 changes: 3 additions & 0 deletions .changelog/9248.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:enhancement
container: added update support for `google_container_node_pool.node_config.taint`
```
4 changes: 0 additions & 4 deletions google-beta/services/container/node_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -404,26 +404,22 @@ func schemaNodeConfig() *schema.Schema {
"taint": {
Type: schema.TypeList,
Optional: true,
ForceNew: true,
Description: `List of Kubernetes taints to be applied to each node.`,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"key": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
Description: `Key for taint.`,
},
"value": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
Description: `Value for taint.`,
},
"effect": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validation.StringInSlice([]string{"NO_SCHEDULE", "PREFER_NO_SCHEDULE", "NO_EXECUTE"}, false),
Description: `Effect for taint.`,
},
Expand Down
56 changes: 56 additions & 0 deletions google-beta/services/container/resource_container_node_pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -1376,6 +1376,62 @@ func nodePoolUpdate(d *schema.ResourceData, meta interface{}, nodePoolInfo *Node
}
}

if d.HasChange(prefix + "node_config.0.taint") {
req := &container.UpdateNodePoolRequest{
Name: name,
}
if v, ok := d.GetOk(prefix + "node_config.0.taint"); ok {
taintsList := v.([]interface{})
taints := make([]*container.NodeTaint, 0, len(taintsList))
for _, v := range taintsList {
if v != nil {
data := v.(map[string]interface{})
taint := &container.NodeTaint{
Key: data["key"].(string),
Value: data["value"].(string),
Effect: data["effect"].(string),
}
taints = append(taints, taint)
}
}
ntaints := &container.NodeTaints{
Taints: taints,
}
req.Taints = ntaints
}

if req.Taints == nil {
taints := make([]*container.NodeTaint, 0, 0)
ntaints := &container.NodeTaints{
Taints: taints,
}
req.Taints = ntaints
}

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 taints", userAgent,
timeout)
}

if err := retryWhileIncompatibleOperation(timeout, npLockKey, updateF); err != nil {
return err
}
log.Printf("[INFO] Updated taints for Node Pool %s", d.Id())
}

if d.HasChange(prefix + "node_config.0.tags") {
req := &container.UpdateNodePoolRequest{
Name: name,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,40 @@ func TestAccContainerNodePool_withNodeConfig(t *testing.T) {
})
}

func TestAccContainerNodePool_withTaintsUpdate(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))

acctest.VcrTest(t, resource.TestCase{
PreCheck: func() { acctest.AccTestPreCheck(t) },
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
CheckDestroy: testAccCheckContainerNodePoolDestroyProducer(t),
Steps: []resource.TestStep{
{
Config: testAccContainerNodePool_basic(cluster, nodePool),
},
{
ResourceName: "google_container_node_pool.np",
ImportState: true,
ImportStateVerify: true,
},
{
Config: testAccContainerNodePool_withTaintsUpdate(cluster, nodePool),
},
{
ResourceName: "google_container_node_pool.np",
ImportState: true,
ImportStateVerify: true,
// autoscaling.# = 0 is equivalent to no autoscaling at all,
// but will still cause an import diff
ImportStateVerifyIgnore: []string{"autoscaling.#", "node_config.0.taint"},
},
},
})
}

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

Expand Down Expand Up @@ -2365,6 +2399,40 @@ resource "google_container_node_pool" "np_with_node_config" {
`, cluster, nodePool)
}

func testAccContainerNodePool_withTaintsUpdate(cluster, np string) string {
return fmt.Sprintf(`
provider "google" {
alias = "user-project-override"
user_project_override = true
}
resource "google_container_cluster" "cluster" {
provider = google.user-project-override
name = "%s"
location = "us-central1-a"
initial_node_count = 3
deletion_protection = false
}
resource "google_container_node_pool" "np" {
provider = google.user-project-override
name = "%s"
location = "us-central1-a"
cluster = google_container_cluster.cluster.name
initial_node_count = 2
node_config {
taint {
key = "taint_key"
value = "taint_value"
effect = "PREFER_NO_SCHEDULE"
}
}
}
`, cluster, np)
}

func testAccContainerNodePool_withReservationAffinity(cluster, np string) string {
return fmt.Sprintf(`
data "google_container_engine_versions" "central1a" {
Expand Down

0 comments on commit fad4935

Please sign in to comment.