@@ -22,17 +22,23 @@ import (
2222var (
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 {
6874 "addons_config.0.gke_backup_agent_config" ,
6975 }
7076
77+ privateClusterConfigKeys = []string {
78+ "private_cluster_config.0.enable_private_endpoint" ,
79+ "private_cluster_config.0.enable_private_nodes" ,
80+ "private_cluster_config.0.master_ipv4_cidr_block" ,
81+ "private_cluster_config.0.private_endpoint_subnetwork" ,
82+ "private_cluster_config.0.master_global_access_config" ,
83+ }
84+
7185 forceNewClusterNodeConfigFields = []string {
7286 "workload_metadata_config" ,
7387 }
@@ -1061,8 +1075,9 @@ func resourceContainerCluster() *schema.Resource {
10611075 "master_authorized_networks_config" : {
10621076 Type : schema .TypeList ,
10631077 Optional : true ,
1078+ Computed : true ,
10641079 MaxItems : 1 ,
1065- Elem : networkConfig ,
1080+ Elem : masterAuthorizedNetworksConfig ,
10661081 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).` ,
10671082 },
10681083
@@ -1303,17 +1318,23 @@ func resourceContainerCluster() *schema.Resource {
13031318 Description : `Configuration for private clusters, clusters with private nodes.` ,
13041319 Elem : & schema.Resource {
13051320 Schema : map [string ]* schema.Schema {
1321+ // enable_private_endpoint is orthogonal to private_endpoint_subnetwork.
1322+ // User can create a private_cluster_config block without including
1323+ // either one of those two fields. Both fields are optional.
1324+ // At the same time, we use 'AtLeastOneOf' to prevent an empty block
1325+ // like 'private_cluster_config{}'
13061326 "enable_private_endpoint" : {
13071327 Type : schema .TypeBool ,
1308- Required : true ,
1309- ForceNew : true ,
1328+ Optional : true ,
1329+ AtLeastOneOf : privateClusterConfigKeys ,
13101330 DiffSuppressFunc : containerClusterPrivateClusterConfigSuppress ,
13111331 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.` ,
13121332 },
13131333 "enable_private_nodes" : {
13141334 Type : schema .TypeBool ,
13151335 Optional : true ,
13161336 ForceNew : true ,
1337+ AtLeastOneOf : privateClusterConfigKeys ,
13171338 DiffSuppressFunc : containerClusterPrivateClusterConfigSuppress ,
13181339 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.` ,
13191340 },
@@ -1322,6 +1343,7 @@ func resourceContainerCluster() *schema.Resource {
13221343 Computed : true ,
13231344 Optional : true ,
13241345 ForceNew : true ,
1346+ AtLeastOneOf : privateClusterConfigKeys ,
13251347 ValidateFunc : orEmpty (validation .IsCIDRNetwork (28 , 28 )),
13261348 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.` ,
13271349 },
@@ -1335,17 +1357,26 @@ func resourceContainerCluster() *schema.Resource {
13351357 Computed : true ,
13361358 Description : `The internal IP address of this cluster's master endpoint.` ,
13371359 },
1360+ "private_endpoint_subnetwork" : {
1361+ Type : schema .TypeString ,
1362+ Optional : true ,
1363+ ForceNew : true ,
1364+ AtLeastOneOf : privateClusterConfigKeys ,
1365+ DiffSuppressFunc : compareSelfLinkOrResourceName ,
1366+ Description : `Subnetwork in cluster's network where master's endpoint will be provisioned.` ,
1367+ },
13381368 "public_endpoint" : {
13391369 Type : schema .TypeString ,
13401370 Computed : true ,
13411371 Description : `The external IP address of this cluster's master endpoint.` ,
13421372 },
13431373 "master_global_access_config" : {
1344- Type : schema .TypeList ,
1345- MaxItems : 1 ,
1346- Optional : true ,
1347- Computed : true ,
1348- Description : "Controls cluster master global access settings." ,
1374+ Type : schema .TypeList ,
1375+ MaxItems : 1 ,
1376+ Optional : true ,
1377+ Computed : true ,
1378+ AtLeastOneOf : privateClusterConfigKeys ,
1379+ Description : "Controls cluster master global access settings." ,
13491380 Elem : & schema.Resource {
13501381 Schema : map [string ]* schema.Schema {
13511382 "enabled" : {
@@ -1759,7 +1790,7 @@ func resourceContainerClusterCreate(d *schema.ResourceData, meta interface{}) er
17591790 Name : clusterName ,
17601791 InitialNodeCount : int64 (d .Get ("initial_node_count" ).(int )),
17611792 MaintenancePolicy : expandMaintenancePolicy (d , meta ),
1762- MasterAuthorizedNetworksConfig : expandMasterAuthorizedNetworksConfig (d .Get ("master_authorized_networks_config" )),
1793+ MasterAuthorizedNetworksConfig : expandMasterAuthorizedNetworksConfig (d .Get ("master_authorized_networks_config" ), d ),
17631794 InitialClusterVersion : d .Get ("min_master_version" ).(string ),
17641795 ClusterIpv4Cidr : d .Get ("cluster_ipv4_cidr" ).(string ),
17651796 Description : d .Get ("description" ).(string ),
@@ -2353,7 +2384,7 @@ func resourceContainerClusterUpdate(d *schema.ResourceData, meta interface{}) er
23532384 c := d .Get ("master_authorized_networks_config" )
23542385 req := & container.UpdateClusterRequest {
23552386 Update : & container.ClusterUpdate {
2356- DesiredMasterAuthorizedNetworksConfig : expandMasterAuthorizedNetworksConfig (c ),
2387+ DesiredMasterAuthorizedNetworksConfig : expandMasterAuthorizedNetworksConfig (c , d ),
23572388 },
23582389 }
23592390
@@ -2417,6 +2448,24 @@ func resourceContainerClusterUpdate(d *schema.ResourceData, meta interface{}) er
24172448 log .Printf ("[INFO] GKE cluster %s's binary authorization has been updated to %v" , d .Id (), enabled )
24182449 }
24192450
2451+ if d .HasChange ("private_cluster_config.0.enable_private_endpoint" ) {
2452+ enabled := d .Get ("private_cluster_config.0.enable_private_endpoint" ).(bool )
2453+ req := & container.UpdateClusterRequest {
2454+ Update : & container.ClusterUpdate {
2455+ DesiredEnablePrivateEndpoint : enabled ,
2456+ ForceSendFields : []string {"DesiredEnablePrivateEndpoint" },
2457+ },
2458+ }
2459+
2460+ updateF := updateFunc (req , "updating enable private endpoint" )
2461+ // Call update serially.
2462+ if err := lockedCall (lockKey , updateF ); err != nil {
2463+ return err
2464+ }
2465+
2466+ log .Printf ("[INFO] GKE cluster %s's enable private endpoint has been updated to %v" , d .Id (), enabled )
2467+ }
2468+
24202469 if d .HasChange ("binary_authorization" ) {
24212470 req := & container.UpdateClusterRequest {
24222471 Update : & container.ClusterUpdate {
@@ -3954,7 +4003,7 @@ func expandMasterAuth(configured interface{}) *container.MasterAuth {
39544003 return result
39554004}
39564005
3957- func expandMasterAuthorizedNetworksConfig (configured interface {}) * container.MasterAuthorizedNetworksConfig {
4006+ func expandMasterAuthorizedNetworksConfig (configured interface {}, d * schema. ResourceData ) * container.MasterAuthorizedNetworksConfig {
39584007 l := configured .([]interface {})
39594008 if len (l ) == 0 {
39604009 return & container.MasterAuthorizedNetworksConfig {
@@ -3976,6 +4025,10 @@ func expandMasterAuthorizedNetworksConfig(configured interface{}) *container.Mas
39764025 })
39774026 }
39784027 }
4028+ if v , ok := d .GetOkExists ("master_authorized_networks_config.0.gcp_public_cidrs_access_enabled" ); ok {
4029+ result .GcpPublicCidrsAccessEnabled = v .(bool )
4030+ result .ForceSendFields = []string {"GcpPublicCidrsAccessEnabled" }
4031+ }
39794032 }
39804033 return result
39814034}
@@ -4003,11 +4056,12 @@ func expandPrivateClusterConfig(configured interface{}) *container.PrivateCluste
40034056 }
40044057 config := l [0 ].(map [string ]interface {})
40054058 return & container.PrivateClusterConfig {
4006- EnablePrivateEndpoint : config ["enable_private_endpoint" ].(bool ),
4007- EnablePrivateNodes : config ["enable_private_nodes" ].(bool ),
4008- MasterIpv4CidrBlock : config ["master_ipv4_cidr_block" ].(string ),
4009- MasterGlobalAccessConfig : expandPrivateClusterConfigMasterGlobalAccessConfig (config ["master_global_access_config" ]),
4010- ForceSendFields : []string {"EnablePrivateEndpoint" , "EnablePrivateNodes" , "MasterIpv4CidrBlock" , "MasterGlobalAccessConfig" },
4059+ EnablePrivateEndpoint : config ["enable_private_endpoint" ].(bool ),
4060+ EnablePrivateNodes : config ["enable_private_nodes" ].(bool ),
4061+ MasterIpv4CidrBlock : config ["master_ipv4_cidr_block" ].(string ),
4062+ MasterGlobalAccessConfig : expandPrivateClusterConfigMasterGlobalAccessConfig (config ["master_global_access_config" ]),
4063+ PrivateEndpointSubnetwork : config ["private_endpoint_subnetwork" ].(string ),
4064+ ForceSendFields : []string {"EnablePrivateEndpoint" , "EnablePrivateNodes" , "MasterIpv4CidrBlock" , "MasterGlobalAccessConfig" },
40114065 }
40124066}
40134067
@@ -4548,6 +4602,7 @@ func flattenPrivateClusterConfig(c *container.PrivateClusterConfig) []map[string
45484602 "master_global_access_config" : flattenPrivateClusterConfigMasterGlobalAccessConfig (c .MasterGlobalAccessConfig ),
45494603 "peering_name" : c .PeeringName ,
45504604 "private_endpoint" : c .PrivateEndpoint ,
4605+ "private_endpoint_subnetwork" : c .PrivateEndpointSubnetwork ,
45514606 "public_endpoint" : c .PublicEndpoint ,
45524607 },
45534608 }
@@ -4815,16 +4870,15 @@ func flattenMasterAuthorizedNetworksConfig(c *container.MasterAuthorizedNetworks
48154870 return nil
48164871 }
48174872 result := make (map [string ]interface {})
4818- if c .Enabled {
4819- cidrBlocks := make ([]interface {}, 0 , len (c .CidrBlocks ))
4820- for _ , v := range c .CidrBlocks {
4821- cidrBlocks = append (cidrBlocks , map [string ]interface {}{
4822- "cidr_block" : v .CidrBlock ,
4823- "display_name" : v .DisplayName ,
4824- })
4825- }
4826- result ["cidr_blocks" ] = schema .NewSet (schema .HashResource (cidrBlockConfig ), cidrBlocks )
4873+ cidrBlocks := make ([]interface {}, 0 , len (c .CidrBlocks ))
4874+ for _ , v := range c .CidrBlocks {
4875+ cidrBlocks = append (cidrBlocks , map [string ]interface {}{
4876+ "cidr_block" : v .CidrBlock ,
4877+ "display_name" : v .DisplayName ,
4878+ })
48274879 }
4880+ result ["cidr_blocks" ] = schema .NewSet (schema .HashResource (cidrBlockConfig ), cidrBlocks )
4881+ result ["gcp_public_cidrs_access_enabled" ] = c .GcpPublicCidrsAccessEnabled
48284882 return []map [string ]interface {}{result }
48294883}
48304884
@@ -5094,12 +5148,15 @@ func containerClusterPrivateClusterConfigSuppress(k, old, new string, d *schema.
50945148 o , n = d .GetChange ("private_cluster_config.0.enable_private_nodes" )
50955149 suppressNodes := ! o .(bool ) && ! n .(bool )
50965150
5151+ // Do not suppress diffs when private_endpoint_subnetwork is configured
5152+ _ , hasSubnet := d .GetOk ("private_cluster_config.0.private_endpoint_subnetwork" )
5153+
50975154 if k == "private_cluster_config.0.enable_private_endpoint" {
5098- return suppressEndpoint
5155+ return suppressEndpoint && ! hasSubnet
50995156 } else if k == "private_cluster_config.0.enable_private_nodes" {
5100- return suppressNodes
5157+ return suppressNodes && ! hasSubnet
51015158 } else if k == "private_cluster_config.#" {
5102- return suppressEndpoint && suppressNodes
5159+ return suppressEndpoint && suppressNodes && ! hasSubnet
51035160 }
51045161 return false
51055162}
0 commit comments