Skip to content

Commit 9065b5a

Browse files
nat-hendersondanawillow
authored andcommitted
Addition of create_subnetwork and other fields relevant for Alias IPs (#1921)
* Addition of create_subnetwork and use_ip_aliases. * add fields for [cluster|services]_ipv4_cidr_block and subnetwork_name
1 parent 9258781 commit 9065b5a

File tree

3 files changed

+219
-76
lines changed

3 files changed

+219
-76
lines changed

google/resource_container_cluster.go

+73-21
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ var (
4242
},
4343
},
4444
}
45+
46+
ipAllocationSubnetFields = []string{"ip_allocation_policy.0.create_subnetwork", "ip_allocation_policy.0.subnetwork_name"}
47+
ipAllocationCidrBlockFields = []string{"ip_allocation_policy.0.cluster_ipv4_cidr_block", "ip_allocation_policy.0.services_ipv4_cidr_block"}
48+
ipAllocationRangeFields = []string{"ip_allocation_policy.0.cluster_secondary_range_name", "ip_allocation_policy.0.services_secondary_range_name"}
4549
)
4650

4751
func resourceContainerCluster() *schema.Resource {
@@ -433,15 +437,52 @@ func resourceContainerCluster() *schema.Resource {
433437
MaxItems: 1,
434438
Elem: &schema.Resource{
435439
Schema: map[string]*schema.Schema{
440+
// GKE creates subnetwork automatically
441+
"create_subnetwork": {
442+
Type: schema.TypeBool,
443+
Optional: true,
444+
ForceNew: true,
445+
ConflictsWith: append(ipAllocationCidrBlockFields, ipAllocationRangeFields...),
446+
},
447+
"subnetwork_name": {
448+
Type: schema.TypeString,
449+
Optional: true,
450+
ForceNew: true,
451+
ConflictsWith: append(ipAllocationCidrBlockFields, ipAllocationRangeFields...),
452+
},
453+
454+
// GKE creates/deletes secondary ranges in VPC
455+
"cluster_ipv4_cidr_block": {
456+
Type: schema.TypeString,
457+
Optional: true,
458+
Computed: true,
459+
ForceNew: true,
460+
ConflictsWith: append(ipAllocationSubnetFields, ipAllocationRangeFields...),
461+
DiffSuppressFunc: cidrOrSizeDiffSuppress,
462+
},
463+
"services_ipv4_cidr_block": {
464+
Type: schema.TypeString,
465+
Optional: true,
466+
Computed: true,
467+
ForceNew: true,
468+
ConflictsWith: append(ipAllocationSubnetFields, ipAllocationRangeFields...),
469+
DiffSuppressFunc: cidrOrSizeDiffSuppress,
470+
},
471+
472+
// User manages secondary ranges manually
436473
"cluster_secondary_range_name": {
437-
Type: schema.TypeString,
438-
Optional: true,
439-
ForceNew: true,
474+
Type: schema.TypeString,
475+
Optional: true,
476+
Computed: true,
477+
ForceNew: true,
478+
ConflictsWith: append(ipAllocationSubnetFields, ipAllocationCidrBlockFields...),
440479
},
441480
"services_secondary_range_name": {
442-
Type: schema.TypeString,
443-
Optional: true,
444-
ForceNew: true,
481+
Type: schema.TypeString,
482+
Optional: true,
483+
Computed: true,
484+
ForceNew: true,
485+
ConflictsWith: append(ipAllocationSubnetFields, ipAllocationCidrBlockFields...),
445486
},
446487
},
447488
},
@@ -475,6 +516,11 @@ func resourceContainerCluster() *schema.Resource {
475516
}
476517
}
477518

519+
func cidrOrSizeDiffSuppress(k, old, new string, d *schema.ResourceData) bool {
520+
// If the user specified a size and the API returned a full cidr block, suppress.
521+
return strings.HasPrefix(new, "/") && strings.HasSuffix(old, new)
522+
}
523+
478524
func resourceContainerClusterCreate(d *schema.ResourceData, meta interface{}) error {
479525
config := meta.(*Config)
480526

@@ -1409,24 +1455,24 @@ func expandClusterAddonsConfig(configured interface{}) *containerBeta.AddonsConf
14091455
}
14101456

14111457
func expandIPAllocationPolicy(configured interface{}) (*containerBeta.IPAllocationPolicy, error) {
1412-
ap := &containerBeta.IPAllocationPolicy{}
14131458
l := configured.([]interface{})
1414-
if len(l) > 0 {
1415-
if config, ok := l[0].(map[string]interface{}); ok {
1416-
ap.UseIpAliases = true
1417-
if v, ok := config["cluster_secondary_range_name"]; ok {
1418-
ap.ClusterSecondaryRangeName = v.(string)
1419-
}
1420-
1421-
if v, ok := config["services_secondary_range_name"]; ok {
1422-
ap.ServicesSecondaryRangeName = v.(string)
1423-
}
1424-
} else {
1425-
return nil, fmt.Errorf("clusters using IP aliases must specify secondary ranges")
1426-
}
1459+
if len(l) == 0 {
1460+
return &containerBeta.IPAllocationPolicy{}, nil
14271461
}
1462+
config := l[0].(map[string]interface{})
1463+
1464+
return &containerBeta.IPAllocationPolicy{
1465+
UseIpAliases: true,
1466+
1467+
CreateSubnetwork: config["create_subnetwork"].(bool),
1468+
SubnetworkName: config["subnetwork_name"].(string),
1469+
1470+
ClusterIpv4CidrBlock: config["cluster_ipv4_cidr_block"].(string),
1471+
ServicesIpv4CidrBlock: config["services_ipv4_cidr_block"].(string),
14281472

1429-
return ap, nil
1473+
ClusterSecondaryRangeName: config["cluster_secondary_range_name"].(string),
1474+
ServicesSecondaryRangeName: config["services_secondary_range_name"].(string),
1475+
}, nil
14301476
}
14311477

14321478
func expandMaintenancePolicy(configured interface{}) *containerBeta.MaintenancePolicy {
@@ -1583,6 +1629,12 @@ func flattenIPAllocationPolicy(c *containerBeta.IPAllocationPolicy) []map[string
15831629
}
15841630
return []map[string]interface{}{
15851631
{
1632+
"create_subnetwork": c.CreateSubnetwork,
1633+
"subnetwork_name": c.SubnetworkName,
1634+
1635+
"cluster_ipv4_cidr_block": c.ClusterIpv4CidrBlock,
1636+
"services_ipv4_cidr_block": c.ServicesIpv4CidrBlock,
1637+
15861638
"cluster_secondary_range_name": c.ClusterSecondaryRangeName,
15871639
"services_secondary_range_name": c.ServicesSecondaryRangeName,
15881640
},

google/resource_container_cluster_test.go

+129-55
Original file line numberDiff line numberDiff line change
@@ -1093,7 +1093,7 @@ func TestAccContainerCluster_withMaintenanceWindow(t *testing.T) {
10931093
})
10941094
}
10951095

1096-
func TestAccContainerCluster_withIPAllocationPolicy(t *testing.T) {
1096+
func TestAccContainerCluster_withIPAllocationPolicy_existingSecondaryRanges(t *testing.T) {
10971097
t.Parallel()
10981098

10991099
cluster := fmt.Sprintf("cluster-test-%s", acctest.RandString(10))
@@ -1103,53 +1103,79 @@ func TestAccContainerCluster_withIPAllocationPolicy(t *testing.T) {
11031103
CheckDestroy: testAccCheckContainerClusterDestroy,
11041104
Steps: []resource.TestStep{
11051105
{
1106-
Config: testAccContainerCluster_withIPAllocationPolicy(
1107-
cluster,
1108-
map[string]string{
1109-
"pods": "10.1.0.0/16",
1110-
"services": "10.2.0.0/20",
1111-
},
1112-
map[string]string{
1113-
"cluster_secondary_range_name": "pods",
1114-
"services_secondary_range_name": "services",
1115-
},
1116-
),
1117-
Check: resource.ComposeTestCheckFunc(
1118-
resource.TestCheckResourceAttr("google_container_cluster.with_ip_allocation_policy",
1119-
"ip_allocation_policy.0.cluster_secondary_range_name", "pods"),
1120-
resource.TestCheckResourceAttr("google_container_cluster.with_ip_allocation_policy",
1121-
"ip_allocation_policy.0.services_secondary_range_name", "services"),
1122-
),
1106+
Config: testAccContainerCluster_withIPAllocationPolicy_existingSecondaryRanges(cluster),
11231107
},
11241108
{
11251109
ResourceName: "google_container_cluster.with_ip_allocation_policy",
11261110
ImportStateIdPrefix: "us-central1-a/",
11271111
ImportState: true,
11281112
ImportStateVerify: true,
11291113
},
1114+
},
1115+
})
1116+
}
1117+
1118+
func TestAccContainerCluster_withIPAllocationPolicy_specificIPRanges(t *testing.T) {
1119+
t.Parallel()
1120+
1121+
cluster := fmt.Sprintf("cluster-test-%s", acctest.RandString(10))
1122+
resource.Test(t, resource.TestCase{
1123+
PreCheck: func() { testAccPreCheck(t) },
1124+
Providers: testAccProviders,
1125+
CheckDestroy: testAccCheckContainerClusterDestroy,
1126+
Steps: []resource.TestStep{
1127+
{
1128+
Config: testAccContainerCluster_withIPAllocationPolicy_specificIPRanges(cluster),
1129+
},
11301130
{
1131-
Config: testAccContainerCluster_withIPAllocationPolicy(
1132-
cluster,
1133-
map[string]string{
1134-
"pods": "10.1.0.0/16",
1135-
"services": "10.2.0.0/20",
1136-
},
1137-
map[string]string{},
1138-
),
1139-
ExpectError: regexp.MustCompile("clusters using IP aliases must specify secondary ranges"),
1140-
},
1141-
{
1142-
Config: testAccContainerCluster_withIPAllocationPolicy(
1143-
cluster,
1144-
map[string]string{
1145-
"pods": "10.1.0.0/16",
1146-
},
1147-
map[string]string{
1148-
"cluster_secondary_range_name": "pods",
1149-
"services_secondary_range_name": "services",
1150-
},
1151-
),
1152-
ExpectError: regexp.MustCompile("secondary range \"services\" does not exist in network"),
1131+
ResourceName: "google_container_cluster.with_ip_allocation_policy",
1132+
ImportStateIdPrefix: "us-central1-a/",
1133+
ImportState: true,
1134+
ImportStateVerify: true,
1135+
},
1136+
},
1137+
})
1138+
}
1139+
1140+
func TestAccContainerCluster_withIPAllocationPolicy_specificSizes(t *testing.T) {
1141+
t.Parallel()
1142+
1143+
cluster := fmt.Sprintf("cluster-test-%s", acctest.RandString(10))
1144+
resource.Test(t, resource.TestCase{
1145+
PreCheck: func() { testAccPreCheck(t) },
1146+
Providers: testAccProviders,
1147+
CheckDestroy: testAccCheckContainerClusterDestroy,
1148+
Steps: []resource.TestStep{
1149+
{
1150+
Config: testAccContainerCluster_withIPAllocationPolicy_specificSizes(cluster),
1151+
},
1152+
{
1153+
ResourceName: "google_container_cluster.with_ip_allocation_policy",
1154+
ImportStateIdPrefix: "us-central1-a/",
1155+
ImportState: true,
1156+
ImportStateVerify: true,
1157+
},
1158+
},
1159+
})
1160+
}
1161+
1162+
func TestAccContainerCluster_withIPAllocationPolicy_createSubnetwork(t *testing.T) {
1163+
t.Parallel()
1164+
1165+
cluster := fmt.Sprintf("cluster-test-%s", acctest.RandString(10))
1166+
resource.Test(t, resource.TestCase{
1167+
PreCheck: func() { testAccPreCheck(t) },
1168+
Providers: testAccProviders,
1169+
CheckDestroy: testAccCheckContainerClusterDestroy,
1170+
Steps: []resource.TestStep{
1171+
{
1172+
Config: testAccContainerCluster_withIPAllocationPolicy_createSubnetwork(cluster),
1173+
},
1174+
{
1175+
ResourceName: "google_container_cluster.with_ip_allocation_policy",
1176+
ImportStateIdPrefix: "us-central1-a/",
1177+
ImportState: true,
1178+
ImportStateVerify: true,
11531179
},
11541180
},
11551181
})
@@ -2233,23 +2259,59 @@ resource "google_container_cluster" "with_maintenance_window" {
22332259
}`, clusterName, maintenancePolicy)
22342260
}
22352261

2236-
func testAccContainerCluster_withIPAllocationPolicy(cluster string, ranges, policy map[string]string) string {
2262+
func testAccContainerCluster_withIPAllocationPolicy_existingSecondaryRanges(cluster string) string {
2263+
return fmt.Sprintf(`
2264+
resource "google_compute_network" "container_network" {
2265+
name = "container-net-%s"
2266+
auto_create_subnetworks = false
2267+
}
22372268
2238-
var secondaryRanges bytes.Buffer
2239-
for rangeName, cidr := range ranges {
2240-
secondaryRanges.WriteString(fmt.Sprintf(`
2269+
resource "google_compute_subnetwork" "container_subnetwork" {
2270+
name = "${google_compute_network.container_network.name}"
2271+
network = "${google_compute_network.container_network.name}"
2272+
ip_cidr_range = "10.0.0.0/24"
2273+
region = "us-central1"
2274+
2275+
secondary_ip_range {
2276+
range_name = "pods"
2277+
ip_cidr_range = "10.1.0.0/16"
2278+
}
22412279
secondary_ip_range {
2242-
range_name = "%s"
2243-
ip_cidr_range = "%s"
2244-
}`, rangeName, cidr))
2280+
range_name = "services"
2281+
ip_cidr_range = "10.2.0.0/20"
2282+
}
2283+
}
2284+
2285+
resource "google_container_cluster" "with_ip_allocation_policy" {
2286+
name = "%s"
2287+
zone = "us-central1-a"
2288+
2289+
network = "${google_compute_network.container_network.name}"
2290+
subnetwork = "${google_compute_subnetwork.container_subnetwork.name}"
2291+
2292+
initial_node_count = 1
2293+
ip_allocation_policy {
2294+
cluster_secondary_range_name = "pods"
2295+
services_secondary_range_name = "services"
22452296
}
2297+
}`, cluster, cluster)
2298+
}
22462299

2247-
var ipAllocationPolicy bytes.Buffer
2248-
for key, value := range policy {
2249-
ipAllocationPolicy.WriteString(fmt.Sprintf(`
2250-
%s = "%s"`, key, value))
2300+
func testAccContainerCluster_withIPAllocationPolicy_specificIPRanges(cluster string) string {
2301+
return fmt.Sprintf(`
2302+
resource "google_container_cluster" "with_ip_allocation_policy" {
2303+
name = "%s"
2304+
zone = "us-central1-a"
2305+
2306+
initial_node_count = 1
2307+
ip_allocation_policy {
2308+
cluster_ipv4_cidr_block = "10.90.0.0/19"
2309+
services_ipv4_cidr_block = "10.40.0.0/19"
22512310
}
2311+
}`, cluster)
2312+
}
22522313

2314+
func testAccContainerCluster_withIPAllocationPolicy_specificSizes(cluster string) string {
22532315
return fmt.Sprintf(`
22542316
resource "google_compute_network" "container_network" {
22552317
name = "container-net-%s"
@@ -2261,8 +2323,6 @@ resource "google_compute_subnetwork" "container_subnetwork" {
22612323
network = "${google_compute_network.container_network.name}"
22622324
ip_cidr_range = "10.0.0.0/24"
22632325
region = "us-central1"
2264-
2265-
%s
22662326
}
22672327
22682328
resource "google_container_cluster" "with_ip_allocation_policy" {
@@ -2274,9 +2334,23 @@ resource "google_container_cluster" "with_ip_allocation_policy" {
22742334
22752335
initial_node_count = 1
22762336
ip_allocation_policy {
2277-
%s
2337+
cluster_ipv4_cidr_block = "/16"
2338+
services_ipv4_cidr_block = "/22"
2339+
}
2340+
}`, cluster, cluster)
2341+
}
2342+
2343+
func testAccContainerCluster_withIPAllocationPolicy_createSubnetwork(cluster string) string {
2344+
return fmt.Sprintf(`
2345+
resource "google_container_cluster" "with_ip_allocation_policy" {
2346+
name = "%s"
2347+
zone = "us-central1-a"
2348+
2349+
initial_node_count = 1
2350+
ip_allocation_policy {
2351+
create_subnetwork = true
22782352
}
2279-
}`, acctest.RandString(10), secondaryRanges.String(), cluster, ipAllocationPolicy.String())
2353+
}`, cluster)
22802354
}
22812355

22822356
func testAccContainerCluster_withPodSecurityPolicy(clusterName string, enabled bool) string {

website/docs/r/container_cluster.html.markdown

+17
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,23 @@ The `ip_allocation_policy` block supports:
238238
ClusterIPs. This must be an existing secondary range associated with the cluster
239239
subnetwork.
240240

241+
* `cluster_ipv4_cidr_block` - (Optional) The IP address range for the cluster pod IPs.
242+
Set to blank to have a range chosen with the default size. Set to /netmask (e.g. /14)
243+
to have a range chosen with a specific netmask. Set to a CIDR notation (e.g. 10.96.0.0/14)
244+
from the RFC-1918 private networks (e.g. 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16) to
245+
pick a specific range to use.
246+
247+
* `services_ipv4_cidr_block` - (Optional) The IP address range of the services IPs in this cluster.
248+
Set to blank to have a range chosen with the default size. Set to /netmask (e.g. /14)
249+
to have a range chosen with a specific netmask. Set to a CIDR notation (e.g. 10.96.0.0/14)
250+
from the RFC-1918 private networks (e.g. 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16) to
251+
pick a specific range to use.
252+
253+
* `create_subnetwork`- (Optional) Whether a new subnetwork will be created automatically for the cluster.
254+
255+
* `subnetwork_name` - (Optional) A custom subnetwork name to be used if create_subnetwork is true.
256+
If this field is empty, then an automatic name will be chosen for the new subnetwork.
257+
241258
The `master_auth` block supports:
242259

243260
* `password` - (Required) The password to use for HTTP basic authentication when accessing

0 commit comments

Comments
 (0)