Skip to content

Commit 7cad934

Browse files
modular-magicianshuyama1
authored andcommitted
container: fix updates for node_config.gcfs_config and make optional (#11717) (#19512)
[upstream:20ac9f9559b3c12d6d637ff4e5f46f029d86997d] Signed-off-by: Modular Magician <[email protected]>
1 parent 2cf98b3 commit 7cad934

6 files changed

+222
-10
lines changed

.changelog/11717.txt

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
```release-note:bug
2+
container: fixed the in-place update for `node_config.gcfs_config` in `google_container_cluster` and `google_container_node_pool`
3+
```
4+
```release-note:bug
5+
container: fixed a permadiff on `node_config.gcfs_config` in `google_container_cluster` and `google_container_node_pool`
6+
```

google/services/container/node_config.go

+1
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ func schemaGcfsConfig() *schema.Schema {
9797
return &schema.Schema{
9898
Type: schema.TypeList,
9999
Optional: true,
100+
Computed: true,
100101
MaxItems: 1,
101102
Description: `GCFS configuration for this node.`,
102103
Elem: &schema.Resource{

google/services/container/resource_container_cluster.go

+49
Original file line numberDiff line numberDiff line change
@@ -3571,6 +3571,55 @@ func resourceContainerClusterUpdate(d *schema.ResourceData, meta interface{}) er
35713571
log.Printf("[INFO] GKE cluster %s: default-pool setting for insecure_kubelet_readonly_port_enabled updated to %s", d.Id(), it)
35723572
}
35733573
}
3574+
3575+
if d.HasChange("node_config.0.gcfs_config") {
3576+
3577+
defaultPool := "default-pool"
3578+
3579+
timeout := d.Timeout(schema.TimeoutCreate)
3580+
3581+
nodePoolInfo, err := extractNodePoolInformationFromCluster(d, config, clusterName)
3582+
if err != nil {
3583+
return err
3584+
}
3585+
3586+
// Acquire write-lock on nodepool.
3587+
npLockKey := nodePoolInfo.nodePoolLockKey(defaultPool)
3588+
3589+
gcfsEnabled := d.Get("node_config.0.gcfs_config.0.enabled").(bool)
3590+
3591+
// While we're getting the value from the drepcated field in
3592+
// node_config.kubelet_config, the actual setting that needs to be updated
3593+
// is on the default nodepool.
3594+
req := &container.UpdateNodePoolRequest{
3595+
Name: defaultPool,
3596+
GcfsConfig: &container.GcfsConfig{
3597+
Enabled: gcfsEnabled,
3598+
},
3599+
}
3600+
3601+
updateF := func() error {
3602+
clusterNodePoolsUpdateCall := config.NewContainerClient(userAgent).Projects.Locations.Clusters.NodePools.Update(nodePoolInfo.fullyQualifiedName(defaultPool), req)
3603+
if config.UserProjectOverride {
3604+
clusterNodePoolsUpdateCall.Header().Add("X-Goog-User-Project", nodePoolInfo.project)
3605+
}
3606+
op, err := clusterNodePoolsUpdateCall.Do()
3607+
if err != nil {
3608+
return err
3609+
}
3610+
3611+
// Wait until it's updated
3612+
return ContainerOperationWait(config, op, nodePoolInfo.project, nodePoolInfo.location,
3613+
"updating GKE node pool gcfs_config", userAgent, timeout)
3614+
}
3615+
3616+
if err := retryWhileIncompatibleOperation(timeout, npLockKey, updateF); err != nil {
3617+
return err
3618+
}
3619+
3620+
log.Printf("[INFO] GKE cluster %s: %s setting for gcfs_config updated to %t", d.Id(), defaultPool, gcfsEnabled)
3621+
}
3622+
35743623
}
35753624

35763625
if d.HasChange("notification_config") {

google/services/container/resource_container_cluster_test.go

+119
Original file line numberDiff line numberDiff line change
@@ -1320,6 +1320,83 @@ func TestAccContainerCluster_withNodeConfig(t *testing.T) {
13201320
})
13211321
}
13221322

1323+
func TestAccContainerCluster_withNodeConfigGcfsConfig(t *testing.T) {
1324+
t.Parallel()
1325+
clusterName := fmt.Sprintf("tf-test-cluster-%s", acctest.RandString(t, 10))
1326+
networkName := acctest.BootstrapSharedTestNetwork(t, "gke-cluster")
1327+
subnetworkName := acctest.BootstrapSubnet(t, "gke-cluster", networkName)
1328+
1329+
acctest.VcrTest(t, resource.TestCase{
1330+
PreCheck: func() { acctest.AccTestPreCheck(t) },
1331+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
1332+
CheckDestroy: testAccCheckContainerClusterDestroyProducer(t),
1333+
Steps: []resource.TestStep{
1334+
{
1335+
Config: testAccContainerCluster_withNodeConfigGcfsConfig(clusterName, networkName, subnetworkName, false),
1336+
ConfigPlanChecks: resource.ConfigPlanChecks{
1337+
PreApply: []plancheck.PlanCheck{
1338+
acctest.ExpectNoDelete(),
1339+
},
1340+
},
1341+
},
1342+
{
1343+
ResourceName: "google_container_cluster.with_node_config_gcfs_config",
1344+
ImportState: true,
1345+
ImportStateVerify: true,
1346+
ImportStateVerifyIgnore: []string{"deletion_protection"},
1347+
},
1348+
{
1349+
Config: testAccContainerCluster_withNodeConfigGcfsConfig(clusterName, networkName, subnetworkName, true),
1350+
ConfigPlanChecks: resource.ConfigPlanChecks{
1351+
PreApply: []plancheck.PlanCheck{
1352+
acctest.ExpectNoDelete(),
1353+
},
1354+
},
1355+
},
1356+
{
1357+
ResourceName: "google_container_cluster.with_node_config_gcfs_config",
1358+
ImportState: true,
1359+
ImportStateVerify: true,
1360+
ImportStateVerifyIgnore: []string{"deletion_protection"},
1361+
},
1362+
},
1363+
})
1364+
}
1365+
1366+
// Note: Updates for these are currently known to be broken (b/361634104), and
1367+
// so are not tested here.
1368+
// They can probably be made similar to, or consolidated with,
1369+
// TestAccContainerCluster_withInsecureKubeletReadonlyPortEnabledInNodeConfigUpdates
1370+
// after that's resolved.
1371+
func TestAccContainerCluster_withNodeConfigKubeletConfigSettings(t *testing.T) {
1372+
t.Parallel()
1373+
clusterName := fmt.Sprintf("tf-test-cluster-%s", acctest.RandString(t, 10))
1374+
networkName := acctest.BootstrapSharedTestNetwork(t, "gke-cluster")
1375+
subnetworkName := acctest.BootstrapSubnet(t, "gke-cluster", networkName)
1376+
1377+
acctest.VcrTest(t, resource.TestCase{
1378+
PreCheck: func() { acctest.AccTestPreCheck(t) },
1379+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
1380+
CheckDestroy: testAccCheckContainerClusterDestroyProducer(t),
1381+
Steps: []resource.TestStep{
1382+
{
1383+
Config: testAccContainerCluster_withNodeConfigKubeletConfigSettings(clusterName, networkName, subnetworkName),
1384+
ConfigPlanChecks: resource.ConfigPlanChecks{
1385+
PreApply: []plancheck.PlanCheck{
1386+
acctest.ExpectNoDelete(),
1387+
},
1388+
},
1389+
},
1390+
{
1391+
ResourceName: "google_container_cluster.with_node_config_kubelet_config_settings",
1392+
ImportState: true,
1393+
ImportStateVerify: true,
1394+
ImportStateVerifyIgnore: []string{"deletion_protection"},
1395+
},
1396+
},
1397+
})
1398+
}
1399+
13231400
// This is for node_config.kubelet_config, which affects the default node-pool
13241401
// (default-pool) when created via the google_container_cluster resource
13251402
func TestAccContainerCluster_withInsecureKubeletReadonlyPortEnabledInNodeConfigUpdates(t *testing.T) {
@@ -5925,6 +6002,48 @@ resource "google_container_cluster" "with_node_config" {
59256002
`, clusterName, networkName, subnetworkName)
59266003
}
59276004

6005+
func testAccContainerCluster_withNodeConfigGcfsConfig(clusterName, networkName, subnetworkName string, enabled bool) string {
6006+
return fmt.Sprintf(`
6007+
resource "google_container_cluster" "with_node_config_gcfs_config" {
6008+
name = "%s"
6009+
location = "us-central1-f"
6010+
initial_node_count = 1
6011+
6012+
node_config {
6013+
gcfs_config {
6014+
enabled = %t
6015+
}
6016+
}
6017+
6018+
deletion_protection = false
6019+
network = "%s"
6020+
subnetwork = "%s"
6021+
}
6022+
`, clusterName, enabled, networkName, subnetworkName)
6023+
}
6024+
6025+
func testAccContainerCluster_withNodeConfigKubeletConfigSettings(clusterName, networkName, subnetworkName string) string {
6026+
return fmt.Sprintf(`
6027+
resource "google_container_cluster" "with_node_config_kubelet_config_settings" {
6028+
name = "%s"
6029+
location = "us-central1-f"
6030+
initial_node_count = 1
6031+
6032+
node_config {
6033+
kubelet_config {
6034+
cpu_manager_policy = "static"
6035+
cpu_cfs_quota = true
6036+
cpu_cfs_quota_period = "100ms"
6037+
pod_pids_limit = 2048
6038+
}
6039+
}
6040+
deletion_protection = false
6041+
network = "%s"
6042+
subnetwork = "%s"
6043+
}
6044+
`, clusterName, networkName, subnetworkName)
6045+
}
6046+
59286047
func testAccContainerCluster_withInsecureKubeletReadonlyPortEnabledInNodeConfig(clusterName, networkName, subnetworkName, insecureKubeletReadonlyPortEnabled string) string {
59296048
return fmt.Sprintf(`
59306049
resource "google_container_cluster" "with_insecure_kubelet_readonly_port_enabled_in_node_config" {

google/services/container/resource_container_node_pool.go

+33
Original file line numberDiff line numberDiff line change
@@ -1770,6 +1770,39 @@ func nodePoolUpdate(d *schema.ResourceData, meta interface{}, nodePoolInfo *Node
17701770
log.Printf("[INFO] Updated workload_metadata_config for node pool %s", name)
17711771
}
17721772

1773+
if d.HasChange(prefix + "node_config.0.gcfs_config") {
1774+
gcfsEnabled := bool(d.Get(prefix + "node_config.0.gcfs_config.0.enabled").(bool))
1775+
req := &container.UpdateNodePoolRequest{
1776+
NodePoolId: name,
1777+
GcfsConfig: &container.GcfsConfig{
1778+
Enabled: gcfsEnabled,
1779+
},
1780+
}
1781+
updateF := func() error {
1782+
clusterNodePoolsUpdateCall := config.NewContainerClient(userAgent).Projects.Locations.Clusters.NodePools.Update(nodePoolInfo.fullyQualifiedName(name), req)
1783+
if config.UserProjectOverride {
1784+
clusterNodePoolsUpdateCall.Header().Add("X-Goog-User-Project", nodePoolInfo.project)
1785+
}
1786+
op, err := clusterNodePoolsUpdateCall.Do()
1787+
if err != nil {
1788+
return err
1789+
}
1790+
1791+
// Wait until it's updated
1792+
return ContainerOperationWait(config, op,
1793+
nodePoolInfo.project,
1794+
nodePoolInfo.location,
1795+
"updating GKE node pool gcfs_config", userAgent,
1796+
timeout)
1797+
}
1798+
1799+
if err := retryWhileIncompatibleOperation(timeout, npLockKey, updateF); err != nil {
1800+
return err
1801+
}
1802+
1803+
log.Printf("[INFO] Updated gcfs_config for node pool %s", name)
1804+
}
1805+
17731806
if d.HasChange(prefix + "node_config.0.kubelet_config") {
17741807
req := &container.UpdateNodePoolRequest{
17751808
NodePoolId: name,

google/services/container/resource_container_node_pool_test.go

+14-10
Original file line numberDiff line numberDiff line change
@@ -1593,9 +1593,9 @@ resource "google_container_node_pool" "np" {
15931593
node_config {
15941594
machine_type = "n1-standard-8"
15951595
image_type = "COS_CONTAINERD"
1596-
gcfs_config {
1597-
enabled = true
1598-
}
1596+
gcfs_config {
1597+
enabled = true
1598+
}
15991599
secondary_boot_disks {
16001600
disk_image = ""
16011601
mode = "CONTAINER_IMAGE_CACHE"
@@ -1612,9 +1612,9 @@ resource "google_container_node_pool" "np-no-mode" {
16121612
node_config {
16131613
machine_type = "n1-standard-8"
16141614
image_type = "COS_CONTAINERD"
1615-
gcfs_config {
1616-
enabled = true
1617-
}
1615+
gcfs_config {
1616+
enabled = true
1617+
}
16181618
secondary_boot_disks {
16191619
disk_image = ""
16201620
}
@@ -1638,10 +1638,14 @@ func TestAccContainerNodePool_gcfsConfig(t *testing.T) {
16381638
Steps: []resource.TestStep{
16391639
{
16401640
Config: testAccContainerNodePool_gcfsConfig(cluster, np, networkName, subnetworkName, true),
1641-
Check: resource.ComposeTestCheckFunc(
1642-
resource.TestCheckResourceAttr("google_container_node_pool.np",
1643-
"node_config.0.gcfs_config.0.enabled", "true"),
1644-
),
1641+
},
1642+
{
1643+
ResourceName: "google_container_node_pool.np",
1644+
ImportState: true,
1645+
ImportStateVerify: true,
1646+
},
1647+
{
1648+
Config: testAccContainerNodePool_gcfsConfig(cluster, np, networkName, subnetworkName, false),
16451649
},
16461650
{
16471651
ResourceName: "google_container_node_pool.np",

0 commit comments

Comments
 (0)