Skip to content

Commit

Permalink
container: fix missing updates for `google_container_cluster.node_con…
Browse files Browse the repository at this point in the history
…fig` subfields (#12014) (#8522)

[upstream:34dd74df5c9291629ca1b215636294ca56aaa6ee]

Signed-off-by: Modular Magician <[email protected]>
  • Loading branch information
modular-magician authored Oct 25, 2024
1 parent 051461b commit 7c2e778
Show file tree
Hide file tree
Showing 4 changed files with 318 additions and 181 deletions.
6 changes: 6 additions & 0 deletions .changelog/12014.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
```release-note:bug
container: fixed missing in-place updates for some `google_container_cluster.node_config` subfields
```
```release-note:enhancement
container: added in-place update support for `labels`, `resource_manager_tags` and `workload_metadata_config` in `google_container_cluster.node_config`
```
149 changes: 6 additions & 143 deletions google-beta/services/container/resource_container_cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,12 +100,6 @@ var (
"private_cluster_config.0.master_global_access_config",
}

forceNewClusterNodeConfigFields = []string{
"labels",
"workload_metadata_config",
"resource_manager_tags",
}

suppressDiffForAutopilot = schema.SchemaDiffSuppressFunc(func(k, oldValue, newValue string, d *schema.ResourceData) bool {
if v, _ := d.Get("enable_autopilot").(bool); v {
return true
Expand All @@ -122,19 +116,6 @@ var (
})
)

// This uses the node pool nodeConfig schema but sets
// node-pool-only updatable fields to ForceNew
func clusterSchemaNodeConfig() *schema.Schema {
nodeConfigSch := schemaNodeConfig()
schemaMap := nodeConfigSch.Elem.(*schema.Resource).Schema
for _, k := range forceNewClusterNodeConfigFields {
if sch, ok := schemaMap[k]; ok {
tpgresource.ChangeFieldSchemaToForceNew(sch)
}
}
return nodeConfigSch
}

// Defines default nodel pool settings for the entire cluster. These settings are
// overridden if specified on the specific NodePool object.
func clusterSchemaNodePoolDefaults() *schema.Schema {
Expand Down Expand Up @@ -1455,7 +1436,7 @@ func ResourceContainerCluster() *schema.Resource {
},
},

"node_config": clusterSchemaNodeConfig(),
"node_config": schemaNodeConfig(),

"node_pool": {
Type: schema.TypeList,
Expand Down Expand Up @@ -3760,133 +3741,15 @@ func resourceContainerClusterUpdate(d *schema.ResourceData, meta interface{}) er
}

if d.HasChange("node_config") {
if d.HasChange("node_config.0.image_type") {
it := d.Get("node_config.0.image_type").(string)
req := &container.UpdateClusterRequest{
Update: &container.ClusterUpdate{
DesiredImageType: it,
},
}

updateF := func() error {
name := containerClusterFullName(project, location, clusterName)
clusterUpdateCall := config.NewContainerClient(userAgent).Projects.Locations.Clusters.Update(name, req)
if config.UserProjectOverride {
clusterUpdateCall.Header().Add("X-Goog-User-Project", project)
}
op, err := clusterUpdateCall.Do()
if err != nil {
return err
}

// Wait until it's updated
return ContainerOperationWait(config, op, project, location, "updating GKE image type", userAgent, d.Timeout(schema.TimeoutUpdate))
}

// Call update serially.
if err := transport_tpg.LockedCall(lockKey, updateF); err != nil {
return err
}

log.Printf("[INFO] GKE cluster %s: image type has been updated to %s", d.Id(), it)
}

if d.HasChange("node_config.0.kubelet_config") {

defaultPool := "default-pool"

timeout := d.Timeout(schema.TimeoutCreate)

nodePoolInfo, err := extractNodePoolInformationFromCluster(d, config, clusterName)
if err != nil {
return err
}

// Acquire write-lock on nodepool.
npLockKey := nodePoolInfo.nodePoolLockKey(defaultPool)

// Still should be further consolidated / DRYed up
// See b/361634104
it := d.Get("node_config.0.kubelet_config")

// While we're getting the value from fields in
// node_config.kubelet_config, the actual setting that needs to be
// updated is on the default nodepool.
req := &container.UpdateNodePoolRequest{
Name: defaultPool,
KubeletConfig: expandKubeletConfig(it),
}
defaultPool := "default-pool"

updateF := func() error {
clusterNodePoolsUpdateCall := config.NewContainerClient(userAgent).Projects.Locations.Clusters.NodePools.Update(nodePoolInfo.fullyQualifiedName(defaultPool), 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 kubelet_config", userAgent, timeout)
}

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

log.Printf("[INFO] GKE cluster %s: kubelet_config updated", d.Id())
}

if d.HasChange("node_config.0.gcfs_config") {

defaultPool := "default-pool"

timeout := d.Timeout(schema.TimeoutCreate)

nodePoolInfo, err := extractNodePoolInformationFromCluster(d, config, clusterName)
if err != nil {
return err
}

// Acquire write-lock on nodepool.
npLockKey := nodePoolInfo.nodePoolLockKey(defaultPool)

gcfsEnabled := d.Get("node_config.0.gcfs_config.0.enabled").(bool)

// While we're getting the value from the drepcated field in
// node_config.kubelet_config, the actual setting that needs to be updated
// is on the default nodepool.
req := &container.UpdateNodePoolRequest{
Name: defaultPool,
GcfsConfig: &container.GcfsConfig{
Enabled: gcfsEnabled,
},
}

updateF := func() error {
clusterNodePoolsUpdateCall := config.NewContainerClient(userAgent).Projects.Locations.Clusters.NodePools.Update(nodePoolInfo.fullyQualifiedName(defaultPool), 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 gcfs_config", userAgent, timeout)
}

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

log.Printf("[INFO] GKE cluster %s: %s setting for gcfs_config updated to %t", d.Id(), defaultPool, gcfsEnabled)
nodePoolInfo, err := extractNodePoolInformationFromCluster(d, config, clusterName)
if err != nil {
return err
}

nodePoolNodeConfigUpdate(d, config, nodePoolInfo, "", defaultPool, d.Timeout(schema.TimeoutUpdate))
}

if d.HasChange("notification_config") {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1181,7 +1181,7 @@ func resourceContainerClusterResourceV1() *schema.Resource {
},
},

"node_config": clusterSchemaNodeConfig(),
"node_config": schemaNodeConfig(),

"node_pool": {
Type: schema.TypeList,
Expand Down
Loading

0 comments on commit 7c2e778

Please sign in to comment.