Skip to content

Commit 7189bc4

Browse files
Add support for flexible clusters - public/private clusters toggle (#6780) (#13128)
Signed-off-by: Modular Magician <[email protected]> Signed-off-by: Modular Magician <[email protected]>
1 parent d02c5c7 commit 7189bc4

7 files changed

+671
-44
lines changed

.changelog/6780.txt

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
```release-note:enhancement
2+
container: added field `gcp_public_cidrs_access_enabled` and `private_endpoint_subnetwork` to `google_container_cluster`
3+
```
4+
```release-note:enhancement
5+
container: added update support for `enable_private_endpoint` and `enable_private_nodes` in `google_container_cluster`
6+
```
7+
```release-note:enhancement
8+
container: promoted `network_config` in `google_container_node_pool` to GA.
9+
```
10+
```release-note:enhancement
11+
container: added field `enable_private_nodes` in `network_config` to `google_container_node_pool`
12+
```

google/resource_container_cluster.go

+88-31
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,23 @@ import (
2222
var (
2323
instanceGroupManagerURL = regexp.MustCompile(fmt.Sprintf("projects/(%s)/zones/([a-z0-9-]*)/instanceGroupManagers/([^/]*)", ProjectRegex))
2424

25-
networkConfig = &schema.Resource{
25+
masterAuthorizedNetworksConfig = &schema.Resource{
2626
Schema: map[string]*schema.Schema{
2727
"cidr_blocks": {
2828
Type: schema.TypeSet,
29-
// Despite being the only entry in a nested block, this should be kept
30-
// Optional. Expressing the parent with no entries and omitting the
29+
// This should be kept Optional. Expressing the
30+
// parent with no entries and omitting the
3131
// parent entirely are semantically different.
3232
Optional: true,
3333
Elem: cidrBlockConfig,
3434
Description: `External networks that can access the Kubernetes cluster master through HTTPS.`,
3535
},
36+
"gcp_public_cidrs_access_enabled": {
37+
Type: schema.TypeBool,
38+
Optional: true,
39+
Computed: true,
40+
Description: `Whether master is accessbile via Google Compute Engine Public IP addresses.`,
41+
},
3642
},
3743
}
3844
cidrBlockConfig = &schema.Resource{
@@ -64,6 +70,14 @@ var (
6470
"addons_config.0.gce_persistent_disk_csi_driver_config",
6571
}
6672

73+
privateClusterConfigKeys = []string{
74+
"private_cluster_config.0.enable_private_endpoint",
75+
"private_cluster_config.0.enable_private_nodes",
76+
"private_cluster_config.0.master_ipv4_cidr_block",
77+
"private_cluster_config.0.private_endpoint_subnetwork",
78+
"private_cluster_config.0.master_global_access_config",
79+
}
80+
6781
forceNewClusterNodeConfigFields = []string{
6882
"workload_metadata_config",
6983
}
@@ -918,8 +932,9 @@ func resourceContainerCluster() *schema.Resource {
918932
"master_authorized_networks_config": {
919933
Type: schema.TypeList,
920934
Optional: true,
935+
Computed: true,
921936
MaxItems: 1,
922-
Elem: networkConfig,
937+
Elem: masterAuthorizedNetworksConfig,
923938
Description: `The desired configuration options for master authorized networks. Omit the nested cidr_blocks attribute to disallow external access (except the cluster node IPs, which GKE automatically whitelists).`,
924939
},
925940

@@ -1114,17 +1129,23 @@ func resourceContainerCluster() *schema.Resource {
11141129
Description: `Configuration for private clusters, clusters with private nodes.`,
11151130
Elem: &schema.Resource{
11161131
Schema: map[string]*schema.Schema{
1132+
// enable_private_endpoint is orthogonal to private_endpoint_subnetwork.
1133+
// User can create a private_cluster_config block without including
1134+
// either one of those two fields. Both fields are optional.
1135+
// At the same time, we use 'AtLeastOneOf' to prevent an empty block
1136+
// like 'private_cluster_config{}'
11171137
"enable_private_endpoint": {
11181138
Type: schema.TypeBool,
1119-
Required: true,
1120-
ForceNew: true,
1139+
Optional: true,
1140+
AtLeastOneOf: privateClusterConfigKeys,
11211141
DiffSuppressFunc: containerClusterPrivateClusterConfigSuppress,
11221142
Description: `When true, the cluster's private endpoint is used as the cluster endpoint and access through the public endpoint is disabled. When false, either endpoint can be used. This field only applies to private clusters, when enable_private_nodes is true.`,
11231143
},
11241144
"enable_private_nodes": {
11251145
Type: schema.TypeBool,
11261146
Optional: true,
11271147
ForceNew: true,
1148+
AtLeastOneOf: privateClusterConfigKeys,
11281149
DiffSuppressFunc: containerClusterPrivateClusterConfigSuppress,
11291150
Description: `Enables the private cluster feature, creating a private endpoint on the cluster. In a private cluster, nodes only have RFC 1918 private addresses and communicate with the master's private endpoint via private networking.`,
11301151
},
@@ -1133,6 +1154,7 @@ func resourceContainerCluster() *schema.Resource {
11331154
Computed: true,
11341155
Optional: true,
11351156
ForceNew: true,
1157+
AtLeastOneOf: privateClusterConfigKeys,
11361158
ValidateFunc: orEmpty(validation.IsCIDRNetwork(28, 28)),
11371159
Description: `The IP range in CIDR notation to use for the hosted master network. This range will be used for assigning private IP addresses to the cluster master(s) and the ILB VIP. This range must not overlap with any other ranges in use within the cluster's network, and it must be a /28 subnet. See Private Cluster Limitations for more details. This field only applies to private clusters, when enable_private_nodes is true.`,
11381160
},
@@ -1146,17 +1168,26 @@ func resourceContainerCluster() *schema.Resource {
11461168
Computed: true,
11471169
Description: `The internal IP address of this cluster's master endpoint.`,
11481170
},
1171+
"private_endpoint_subnetwork": {
1172+
Type: schema.TypeString,
1173+
Optional: true,
1174+
ForceNew: true,
1175+
AtLeastOneOf: privateClusterConfigKeys,
1176+
DiffSuppressFunc: compareSelfLinkOrResourceName,
1177+
Description: `Subnetwork in cluster's network where master's endpoint will be provisioned.`,
1178+
},
11491179
"public_endpoint": {
11501180
Type: schema.TypeString,
11511181
Computed: true,
11521182
Description: `The external IP address of this cluster's master endpoint.`,
11531183
},
11541184
"master_global_access_config": {
1155-
Type: schema.TypeList,
1156-
MaxItems: 1,
1157-
Optional: true,
1158-
Computed: true,
1159-
Description: "Controls cluster master global access settings.",
1185+
Type: schema.TypeList,
1186+
MaxItems: 1,
1187+
Optional: true,
1188+
Computed: true,
1189+
AtLeastOneOf: privateClusterConfigKeys,
1190+
Description: "Controls cluster master global access settings.",
11601191
Elem: &schema.Resource{
11611192
Schema: map[string]*schema.Schema{
11621193
"enabled": {
@@ -1535,7 +1566,7 @@ func resourceContainerClusterCreate(d *schema.ResourceData, meta interface{}) er
15351566
Name: clusterName,
15361567
InitialNodeCount: int64(d.Get("initial_node_count").(int)),
15371568
MaintenancePolicy: expandMaintenancePolicy(d, meta),
1538-
MasterAuthorizedNetworksConfig: expandMasterAuthorizedNetworksConfig(d.Get("master_authorized_networks_config")),
1569+
MasterAuthorizedNetworksConfig: expandMasterAuthorizedNetworksConfig(d.Get("master_authorized_networks_config"), d),
15391570
InitialClusterVersion: d.Get("min_master_version").(string),
15401571
ClusterIpv4Cidr: d.Get("cluster_ipv4_cidr").(string),
15411572
Description: d.Get("description").(string),
@@ -2098,7 +2129,7 @@ func resourceContainerClusterUpdate(d *schema.ResourceData, meta interface{}) er
20982129
c := d.Get("master_authorized_networks_config")
20992130
req := &container.UpdateClusterRequest{
21002131
Update: &container.ClusterUpdate{
2101-
DesiredMasterAuthorizedNetworksConfig: expandMasterAuthorizedNetworksConfig(c),
2132+
DesiredMasterAuthorizedNetworksConfig: expandMasterAuthorizedNetworksConfig(c, d),
21022133
},
21032134
}
21042135

@@ -2162,6 +2193,24 @@ func resourceContainerClusterUpdate(d *schema.ResourceData, meta interface{}) er
21622193
log.Printf("[INFO] GKE cluster %s's binary authorization has been updated to %v", d.Id(), enabled)
21632194
}
21642195

2196+
if d.HasChange("private_cluster_config.0.enable_private_endpoint") {
2197+
enabled := d.Get("private_cluster_config.0.enable_private_endpoint").(bool)
2198+
req := &container.UpdateClusterRequest{
2199+
Update: &container.ClusterUpdate{
2200+
DesiredEnablePrivateEndpoint: enabled,
2201+
ForceSendFields: []string{"DesiredEnablePrivateEndpoint"},
2202+
},
2203+
}
2204+
2205+
updateF := updateFunc(req, "updating enable private endpoint")
2206+
// Call update serially.
2207+
if err := lockedCall(lockKey, updateF); err != nil {
2208+
return err
2209+
}
2210+
2211+
log.Printf("[INFO] GKE cluster %s's enable private endpoint has been updated to %v", d.Id(), enabled)
2212+
}
2213+
21652214
if d.HasChange("binary_authorization") {
21662215
req := &container.UpdateClusterRequest{
21672216
Update: &container.ClusterUpdate{
@@ -3537,7 +3586,7 @@ func expandMasterAuth(configured interface{}) *container.MasterAuth {
35373586
return result
35383587
}
35393588

3540-
func expandMasterAuthorizedNetworksConfig(configured interface{}) *container.MasterAuthorizedNetworksConfig {
3589+
func expandMasterAuthorizedNetworksConfig(configured interface{}, d *schema.ResourceData) *container.MasterAuthorizedNetworksConfig {
35413590
l := configured.([]interface{})
35423591
if len(l) == 0 {
35433592
return &container.MasterAuthorizedNetworksConfig{
@@ -3559,6 +3608,10 @@ func expandMasterAuthorizedNetworksConfig(configured interface{}) *container.Mas
35593608
})
35603609
}
35613610
}
3611+
if v, ok := d.GetOkExists("master_authorized_networks_config.0.gcp_public_cidrs_access_enabled"); ok {
3612+
result.GcpPublicCidrsAccessEnabled = v.(bool)
3613+
result.ForceSendFields = []string{"GcpPublicCidrsAccessEnabled"}
3614+
}
35623615
}
35633616
return result
35643617
}
@@ -3586,11 +3639,12 @@ func expandPrivateClusterConfig(configured interface{}) *container.PrivateCluste
35863639
}
35873640
config := l[0].(map[string]interface{})
35883641
return &container.PrivateClusterConfig{
3589-
EnablePrivateEndpoint: config["enable_private_endpoint"].(bool),
3590-
EnablePrivateNodes: config["enable_private_nodes"].(bool),
3591-
MasterIpv4CidrBlock: config["master_ipv4_cidr_block"].(string),
3592-
MasterGlobalAccessConfig: expandPrivateClusterConfigMasterGlobalAccessConfig(config["master_global_access_config"]),
3593-
ForceSendFields: []string{"EnablePrivateEndpoint", "EnablePrivateNodes", "MasterIpv4CidrBlock", "MasterGlobalAccessConfig"},
3642+
EnablePrivateEndpoint: config["enable_private_endpoint"].(bool),
3643+
EnablePrivateNodes: config["enable_private_nodes"].(bool),
3644+
MasterIpv4CidrBlock: config["master_ipv4_cidr_block"].(string),
3645+
MasterGlobalAccessConfig: expandPrivateClusterConfigMasterGlobalAccessConfig(config["master_global_access_config"]),
3646+
PrivateEndpointSubnetwork: config["private_endpoint_subnetwork"].(string),
3647+
ForceSendFields: []string{"EnablePrivateEndpoint", "EnablePrivateNodes", "MasterIpv4CidrBlock", "MasterGlobalAccessConfig"},
35943648
}
35953649
}
35963650

@@ -4020,6 +4074,7 @@ func flattenPrivateClusterConfig(c *container.PrivateClusterConfig) []map[string
40204074
"master_global_access_config": flattenPrivateClusterConfigMasterGlobalAccessConfig(c.MasterGlobalAccessConfig),
40214075
"peering_name": c.PeeringName,
40224076
"private_endpoint": c.PrivateEndpoint,
4077+
"private_endpoint_subnetwork": c.PrivateEndpointSubnetwork,
40234078
"public_endpoint": c.PublicEndpoint,
40244079
},
40254080
}
@@ -4263,16 +4318,15 @@ func flattenMasterAuthorizedNetworksConfig(c *container.MasterAuthorizedNetworks
42634318
return nil
42644319
}
42654320
result := make(map[string]interface{})
4266-
if c.Enabled {
4267-
cidrBlocks := make([]interface{}, 0, len(c.CidrBlocks))
4268-
for _, v := range c.CidrBlocks {
4269-
cidrBlocks = append(cidrBlocks, map[string]interface{}{
4270-
"cidr_block": v.CidrBlock,
4271-
"display_name": v.DisplayName,
4272-
})
4273-
}
4274-
result["cidr_blocks"] = schema.NewSet(schema.HashResource(cidrBlockConfig), cidrBlocks)
4321+
cidrBlocks := make([]interface{}, 0, len(c.CidrBlocks))
4322+
for _, v := range c.CidrBlocks {
4323+
cidrBlocks = append(cidrBlocks, map[string]interface{}{
4324+
"cidr_block": v.CidrBlock,
4325+
"display_name": v.DisplayName,
4326+
})
42754327
}
4328+
result["cidr_blocks"] = schema.NewSet(schema.HashResource(cidrBlockConfig), cidrBlocks)
4329+
result["gcp_public_cidrs_access_enabled"] = c.GcpPublicCidrsAccessEnabled
42764330
return []map[string]interface{}{result}
42774331
}
42784332

@@ -4491,12 +4545,15 @@ func containerClusterPrivateClusterConfigSuppress(k, old, new string, d *schema.
44914545
o, n = d.GetChange("private_cluster_config.0.enable_private_nodes")
44924546
suppressNodes := !o.(bool) && !n.(bool)
44934547

4548+
// Do not suppress diffs when private_endpoint_subnetwork is configured
4549+
_, hasSubnet := d.GetOk("private_cluster_config.0.private_endpoint_subnetwork")
4550+
44944551
if k == "private_cluster_config.0.enable_private_endpoint" {
4495-
return suppressEndpoint
4552+
return suppressEndpoint && !hasSubnet
44964553
} else if k == "private_cluster_config.0.enable_private_nodes" {
4497-
return suppressNodes
4554+
return suppressNodes && !hasSubnet
44984555
} else if k == "private_cluster_config.#" {
4499-
return suppressEndpoint && suppressNodes
4556+
return suppressEndpoint && suppressNodes && !hasSubnet
45004557
}
45014558
return false
45024559
}

0 commit comments

Comments
 (0)