Skip to content

Commit

Permalink
container: fix updates for node_config.gcfs_config and make optional (
Browse files Browse the repository at this point in the history
#11717) (#19512)

[upstream:20ac9f9559b3c12d6d637ff4e5f46f029d86997d]

Signed-off-by: Modular Magician <[email protected]>
  • Loading branch information
modular-magician authored and shuyama1 committed Sep 20, 2024
1 parent 2cf98b3 commit 7cad934
Show file tree
Hide file tree
Showing 6 changed files with 222 additions and 10 deletions.
6 changes: 6 additions & 0 deletions .changelog/11717.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
```release-note:bug
container: fixed the in-place update for `node_config.gcfs_config` in `google_container_cluster` and `google_container_node_pool`
```
```release-note:bug
container: fixed a permadiff on `node_config.gcfs_config` in `google_container_cluster` and `google_container_node_pool`
```
1 change: 1 addition & 0 deletions google/services/container/node_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ func schemaGcfsConfig() *schema.Schema {
return &schema.Schema{
Type: schema.TypeList,
Optional: true,
Computed: true,
MaxItems: 1,
Description: `GCFS configuration for this node.`,
Elem: &schema.Resource{
Expand Down
49 changes: 49 additions & 0 deletions google/services/container/resource_container_cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -3571,6 +3571,55 @@ func resourceContainerClusterUpdate(d *schema.ResourceData, meta interface{}) er
log.Printf("[INFO] GKE cluster %s: default-pool setting for insecure_kubelet_readonly_port_enabled updated to %s", d.Id(), it)
}
}

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)
}

}

if d.HasChange("notification_config") {
Expand Down
119 changes: 119 additions & 0 deletions google/services/container/resource_container_cluster_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1320,6 +1320,83 @@ func TestAccContainerCluster_withNodeConfig(t *testing.T) {
})
}

func TestAccContainerCluster_withNodeConfigGcfsConfig(t *testing.T) {
t.Parallel()
clusterName := fmt.Sprintf("tf-test-cluster-%s", acctest.RandString(t, 10))
networkName := acctest.BootstrapSharedTestNetwork(t, "gke-cluster")
subnetworkName := acctest.BootstrapSubnet(t, "gke-cluster", networkName)

acctest.VcrTest(t, resource.TestCase{
PreCheck: func() { acctest.AccTestPreCheck(t) },
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
CheckDestroy: testAccCheckContainerClusterDestroyProducer(t),
Steps: []resource.TestStep{
{
Config: testAccContainerCluster_withNodeConfigGcfsConfig(clusterName, networkName, subnetworkName, false),
ConfigPlanChecks: resource.ConfigPlanChecks{
PreApply: []plancheck.PlanCheck{
acctest.ExpectNoDelete(),
},
},
},
{
ResourceName: "google_container_cluster.with_node_config_gcfs_config",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"deletion_protection"},
},
{
Config: testAccContainerCluster_withNodeConfigGcfsConfig(clusterName, networkName, subnetworkName, true),
ConfigPlanChecks: resource.ConfigPlanChecks{
PreApply: []plancheck.PlanCheck{
acctest.ExpectNoDelete(),
},
},
},
{
ResourceName: "google_container_cluster.with_node_config_gcfs_config",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"deletion_protection"},
},
},
})
}

// Note: Updates for these are currently known to be broken (b/361634104), and
// so are not tested here.
// They can probably be made similar to, or consolidated with,
// TestAccContainerCluster_withInsecureKubeletReadonlyPortEnabledInNodeConfigUpdates
// after that's resolved.
func TestAccContainerCluster_withNodeConfigKubeletConfigSettings(t *testing.T) {
t.Parallel()
clusterName := fmt.Sprintf("tf-test-cluster-%s", acctest.RandString(t, 10))
networkName := acctest.BootstrapSharedTestNetwork(t, "gke-cluster")
subnetworkName := acctest.BootstrapSubnet(t, "gke-cluster", networkName)

acctest.VcrTest(t, resource.TestCase{
PreCheck: func() { acctest.AccTestPreCheck(t) },
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
CheckDestroy: testAccCheckContainerClusterDestroyProducer(t),
Steps: []resource.TestStep{
{
Config: testAccContainerCluster_withNodeConfigKubeletConfigSettings(clusterName, networkName, subnetworkName),
ConfigPlanChecks: resource.ConfigPlanChecks{
PreApply: []plancheck.PlanCheck{
acctest.ExpectNoDelete(),
},
},
},
{
ResourceName: "google_container_cluster.with_node_config_kubelet_config_settings",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"deletion_protection"},
},
},
})
}

// This is for node_config.kubelet_config, which affects the default node-pool
// (default-pool) when created via the google_container_cluster resource
func TestAccContainerCluster_withInsecureKubeletReadonlyPortEnabledInNodeConfigUpdates(t *testing.T) {
Expand Down Expand Up @@ -5925,6 +6002,48 @@ resource "google_container_cluster" "with_node_config" {
`, clusterName, networkName, subnetworkName)
}

func testAccContainerCluster_withNodeConfigGcfsConfig(clusterName, networkName, subnetworkName string, enabled bool) string {
return fmt.Sprintf(`
resource "google_container_cluster" "with_node_config_gcfs_config" {
name = "%s"
location = "us-central1-f"
initial_node_count = 1
node_config {
gcfs_config {
enabled = %t
}
}
deletion_protection = false
network = "%s"
subnetwork = "%s"
}
`, clusterName, enabled, networkName, subnetworkName)
}

func testAccContainerCluster_withNodeConfigKubeletConfigSettings(clusterName, networkName, subnetworkName string) string {
return fmt.Sprintf(`
resource "google_container_cluster" "with_node_config_kubelet_config_settings" {
name = "%s"
location = "us-central1-f"
initial_node_count = 1
node_config {
kubelet_config {
cpu_manager_policy = "static"
cpu_cfs_quota = true
cpu_cfs_quota_period = "100ms"
pod_pids_limit = 2048
}
}
deletion_protection = false
network = "%s"
subnetwork = "%s"
}
`, clusterName, networkName, subnetworkName)
}

func testAccContainerCluster_withInsecureKubeletReadonlyPortEnabledInNodeConfig(clusterName, networkName, subnetworkName, insecureKubeletReadonlyPortEnabled string) string {
return fmt.Sprintf(`
resource "google_container_cluster" "with_insecure_kubelet_readonly_port_enabled_in_node_config" {
Expand Down
33 changes: 33 additions & 0 deletions google/services/container/resource_container_node_pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -1770,6 +1770,39 @@ func nodePoolUpdate(d *schema.ResourceData, meta interface{}, nodePoolInfo *Node
log.Printf("[INFO] Updated workload_metadata_config for node pool %s", name)
}

if d.HasChange(prefix + "node_config.0.gcfs_config") {
gcfsEnabled := bool(d.Get(prefix + "node_config.0.gcfs_config.0.enabled").(bool))
req := &container.UpdateNodePoolRequest{
NodePoolId: name,
GcfsConfig: &container.GcfsConfig{
Enabled: gcfsEnabled,
},
}
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 gcfs_config", userAgent,
timeout)
}

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

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

if d.HasChange(prefix + "node_config.0.kubelet_config") {
req := &container.UpdateNodePoolRequest{
NodePoolId: name,
Expand Down
24 changes: 14 additions & 10 deletions google/services/container/resource_container_node_pool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1593,9 +1593,9 @@ resource "google_container_node_pool" "np" {
node_config {
machine_type = "n1-standard-8"
image_type = "COS_CONTAINERD"
gcfs_config {
enabled = true
}
gcfs_config {
enabled = true
}
secondary_boot_disks {
disk_image = ""
mode = "CONTAINER_IMAGE_CACHE"
Expand All @@ -1612,9 +1612,9 @@ resource "google_container_node_pool" "np-no-mode" {
node_config {
machine_type = "n1-standard-8"
image_type = "COS_CONTAINERD"
gcfs_config {
enabled = true
}
gcfs_config {
enabled = true
}
secondary_boot_disks {
disk_image = ""
}
Expand All @@ -1638,10 +1638,14 @@ func TestAccContainerNodePool_gcfsConfig(t *testing.T) {
Steps: []resource.TestStep{
{
Config: testAccContainerNodePool_gcfsConfig(cluster, np, networkName, subnetworkName, true),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("google_container_node_pool.np",
"node_config.0.gcfs_config.0.enabled", "true"),
),
},
{
ResourceName: "google_container_node_pool.np",
ImportState: true,
ImportStateVerify: true,
},
{
Config: testAccContainerNodePool_gcfsConfig(cluster, np, networkName, subnetworkName, false),
},
{
ResourceName: "google_container_node_pool.np",
Expand Down

0 comments on commit 7cad934

Please sign in to comment.