Skip to content

Commit 525b1e5

Browse files
rileykarsonmodular-magician
authored andcommitted
Add location / node_locations fields to GKE
Signed-off-by: Modular Magician <[email protected]>
1 parent 7bb5003 commit 525b1e5

11 files changed

+245
-88
lines changed

google/data_source_google_container_cluster.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ func dataSourceGoogleContainerCluster() *schema.Resource {
1212
addRequiredFieldsToSchema(dsSchema, "name")
1313

1414
// Set 'Optional' schema elements
15-
addOptionalFieldsToSchema(dsSchema, "project", "zone", "region")
15+
addOptionalFieldsToSchema(dsSchema, "project", "zone", "region", "location")
1616

1717
return &schema.Resource{
1818
Read: datasourceContainerClusterRead,

google/data_source_google_container_cluster_test.go

+9-9
Original file line numberDiff line numberDiff line change
@@ -110,18 +110,18 @@ func testAccContainerClusterDatasource_zonal() string {
110110
return fmt.Sprintf(`
111111
resource "google_container_cluster" "kubes" {
112112
name = "cluster-test-%s"
113-
zone = "us-central1-a"
113+
location = "us-central1-a"
114114
initial_node_count = 1
115-
115+
116116
master_auth {
117117
username = "mr.yoda"
118118
password = "adoy.rm.123456789"
119119
}
120120
}
121-
121+
122122
data "google_container_cluster" "kubes" {
123-
name = "${google_container_cluster.kubes.name}"
124-
zone = "${google_container_cluster.kubes.zone}"
123+
name = "${google_container_cluster.kubes.name}"
124+
location = "${google_container_cluster.kubes.zone}"
125125
}
126126
`, acctest.RandString(10))
127127
}
@@ -130,13 +130,13 @@ func testAccContainerClusterDatasource_regional() string {
130130
return fmt.Sprintf(`
131131
resource "google_container_cluster" "kubes" {
132132
name = "cluster-test-%s"
133-
region = "us-central1"
133+
location = "us-central1"
134134
initial_node_count = 1
135135
}
136-
136+
137137
data "google_container_cluster" "kubes" {
138-
name = "${google_container_cluster.kubes.name}"
139-
region = "${google_container_cluster.kubes.region}"
138+
name = "${google_container_cluster.kubes.name}"
139+
location = "${google_container_cluster.kubes.region}"
140140
}
141141
`, acctest.RandString(10))
142142
}

google/data_source_google_container_engine_versions.go

+12-4
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,22 @@ func dataSourceGoogleContainerEngineVersions() *schema.Resource {
1515
Type: schema.TypeString,
1616
Optional: true,
1717
},
18+
"location": {
19+
Type: schema.TypeString,
20+
Optional: true,
21+
ConflictsWith: []string{"zone", "region"},
22+
},
1823
"zone": {
19-
Type: schema.TypeString,
20-
Optional: true,
24+
Type: schema.TypeString,
25+
Optional: true,
26+
Deprecated: "Use location instead",
27+
ConflictsWith: []string{"region", "location"},
2128
},
2229
"region": {
2330
Type: schema.TypeString,
2431
Optional: true,
25-
ConflictsWith: []string{"zone"},
32+
Deprecated: "Use location instead",
33+
ConflictsWith: []string{"zone", "location"},
2634
},
2735
"default_cluster_version": {
2836
Type: schema.TypeString,
@@ -63,7 +71,7 @@ func dataSourceGoogleContainerEngineVersionsRead(d *schema.ResourceData, meta in
6371
return err
6472
}
6573
if len(location) == 0 {
66-
return fmt.Errorf("Cannot determine location: set zone or region in this data source or at provider-level")
74+
return fmt.Errorf("Cannot determine location: set location, zone, or region in this data source or at provider-level")
6775
}
6876

6977
location = fmt.Sprintf("projects/%s/locations/%s", project, location)

google/data_source_google_container_engine_versions_test.go

+10
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ func TestAccContainerEngineVersions_basic(t *testing.T) {
2020
{
2121
Config: testAccCheckGoogleContainerEngineVersionsConfig,
2222
Check: resource.ComposeTestCheckFunc(
23+
testAccCheckGoogleContainerEngineVersionsMeta("data.google_container_engine_versions.location"),
2324
testAccCheckGoogleContainerEngineVersionsMeta("data.google_container_engine_versions.versions"),
2425
),
2526
},
@@ -37,6 +38,7 @@ func TestAccContainerEngineVersions_regional(t *testing.T) {
3738
{
3839
Config: testAccCheckGoogleContainerEngineVersionsRegionalConfig,
3940
Check: resource.ComposeTestCheckFunc(
41+
testAccCheckGoogleContainerEngineVersionsMeta("data.google_container_engine_versions.location"),
4042
testAccCheckGoogleContainerEngineVersionsMeta("data.google_container_engine_versions.versions"),
4143
),
4244
},
@@ -115,12 +117,20 @@ func testAccCheckGoogleContainerEngineVersionsMeta(n string) resource.TestCheckF
115117
}
116118

117119
var testAccCheckGoogleContainerEngineVersionsConfig = `
120+
data "google_container_engine_versions" "location" {
121+
location = "us-central1-b"
122+
}
123+
118124
data "google_container_engine_versions" "versions" {
119125
zone = "us-central1-b"
120126
}
121127
`
122128

123129
var testAccCheckGoogleContainerEngineVersionsRegionalConfig = `
130+
data "google_container_engine_versions" "location" {
131+
location = "us-central1"
132+
}
133+
124134
data "google_container_engine_versions" "versions" {
125135
region = "us-central1"
126136
}

google/regional_utils.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@ func isZone(location string) bool {
1414
}
1515

1616
func getLocation(d *schema.ResourceData, config *Config) (string, error) {
17-
if v, isRegionalCluster := d.GetOk("region"); isRegionalCluster {
17+
if v, ok := d.GetOk("location"); ok {
18+
return v.(string), nil
19+
} else if v, isRegionalCluster := d.GetOk("region"); isRegionalCluster {
1820
return v.(string), nil
1921
} else {
2022
// If region is not explicitly set, use "zone" (or fall back to the provider-level zone).

google/resource_container_cluster.go

+103-12
Original file line numberDiff line numberDiff line change
@@ -96,29 +96,47 @@ func resourceContainerCluster() *schema.Resource {
9696
},
9797
},
9898

99+
"location": {
100+
Type: schema.TypeString,
101+
Optional: true,
102+
Computed: true,
103+
ForceNew: true,
104+
ConflictsWith: []string{"zone", "region"},
105+
},
106+
99107
"region": {
100108
Type: schema.TypeString,
101109
Optional: true,
102110
Computed: true,
103111
ForceNew: true,
104-
ConflictsWith: []string{"zone"},
112+
Deprecated: "Use location instead",
113+
ConflictsWith: []string{"zone", "location"},
105114
},
106115

107116
"zone": {
108117
Type: schema.TypeString,
109118
Optional: true,
110119
Computed: true,
111120
ForceNew: true,
112-
ConflictsWith: []string{"region"},
121+
Deprecated: "Use location instead",
122+
ConflictsWith: []string{"region", "location"},
113123
},
114124

115-
"additional_zones": {
125+
"node_locations": {
116126
Type: schema.TypeSet,
117127
Optional: true,
118128
Computed: true,
119129
Elem: &schema.Schema{Type: schema.TypeString},
120130
},
121131

132+
"additional_zones": {
133+
Type: schema.TypeSet,
134+
Optional: true,
135+
Computed: true,
136+
Deprecated: "Use node_locations instead",
137+
Elem: &schema.Schema{Type: schema.TypeString},
138+
},
139+
122140
"addons_config": {
123141
Type: schema.TypeList,
124142
Optional: true,
@@ -666,14 +684,29 @@ func resourceContainerClusterCreate(d *schema.ResourceData, meta interface{}) er
666684
}
667685
}
668686

669-
if v, ok := d.GetOk("additional_zones"); ok {
687+
if v, ok := d.GetOk("node_locations"); ok {
670688
locationsSet := v.(*schema.Set)
671689
if locationsSet.Contains(location) {
672-
return fmt.Errorf("additional_zones should not contain the original 'zone'")
690+
return fmt.Errorf("when using a multi-zonal cluster, additional_zones should not contain the original 'zone'")
691+
}
692+
693+
// GKE requires a full list of node locations
694+
// but when using a multi-zonal cluster our schema only asks for the
695+
// additional zones, so append the cluster location if it's a zone
696+
if isZone(location) {
697+
locationsSet.Add(location)
698+
}
699+
cluster.Locations = convertStringSet(locationsSet)
700+
} else if v, ok := d.GetOk("additional_zones"); ok {
701+
locationsSet := v.(*schema.Set)
702+
if locationsSet.Contains(location) {
703+
return fmt.Errorf("when using a multi-zonal cluster, additional_zones should not contain the original 'zone'")
673704
}
705+
706+
// GKE requires a full list of node locations
707+
// but when using a multi-zonal cluster our schema only asks for the
708+
// additional zones, so append the cluster location if it's a zone
674709
if isZone(location) {
675-
// GKE requires a full list of locations (including the original zone),
676-
// but our schema only asks for additional zones, so append the original.
677710
locationsSet.Add(location)
678711
}
679712
cluster.Locations = convertStringSet(locationsSet)
@@ -804,10 +837,17 @@ func resourceContainerClusterRead(d *schema.ResourceData, meta interface{}) erro
804837
if err := d.Set("network_policy", flattenNetworkPolicy(cluster.NetworkPolicy)); err != nil {
805838
return err
806839
}
807-
d.Set("zone", cluster.Zone)
840+
841+
d.Set("location", cluster.Location)
842+
if isZone(cluster.Location) {
843+
d.Set("zone", cluster.Location)
844+
} else {
845+
d.Set("region", cluster.Location)
846+
}
808847

809848
locations := schema.NewSet(schema.HashString, convertStringArrToInterface(cluster.Locations))
810849
locations.Remove(cluster.Zone) // Remove the original zone since we only store additional zones
850+
d.Set("node_locations", locations)
811851
d.Set("additional_zones", locations)
812852

813853
d.Set("endpoint", cluster.Endpoint)
@@ -975,6 +1015,9 @@ func resourceContainerClusterUpdate(d *schema.ResourceData, meta interface{}) er
9751015
d.SetPartial("maintenance_policy")
9761016
}
9771017

1018+
// we can only ever see a change to one of additional_zones and node_locations; because
1019+
// thy conflict with each other and are each computed, Terraform will suppress the diff
1020+
// on one of them even when migrating from one to the other.
9781021
if d.HasChange("additional_zones") {
9791022
azSetOldI, azSetNewI := d.GetChange("additional_zones")
9801023
azSetNew := azSetNewI.(*schema.Set)
@@ -996,7 +1039,7 @@ func resourceContainerClusterUpdate(d *schema.ResourceData, meta interface{}) er
9961039
},
9971040
}
9981041

999-
updateF := updateFunc(req, "updating GKE cluster locations")
1042+
updateF := updateFunc(req, "updating GKE cluster node locations")
10001043
// Call update serially.
10011044
if err := lockedCall(lockKey, updateF); err != nil {
10021045
return err
@@ -1012,16 +1055,63 @@ func resourceContainerClusterUpdate(d *schema.ResourceData, meta interface{}) er
10121055
},
10131056
}
10141057

1015-
updateF := updateFunc(req, "updating GKE cluster locations")
1058+
updateF := updateFunc(req, "updating GKE cluster node locations")
10161059
// Call update serially.
10171060
if err := lockedCall(lockKey, updateF); err != nil {
10181061
return err
10191062
}
10201063
}
10211064

1022-
log.Printf("[INFO] GKE cluster %s locations have been updated to %v", d.Id(), azSet.List())
1065+
log.Printf("[INFO] GKE cluster %s node locations have been updated to %v", d.Id(), azSet.List())
10231066

10241067
d.SetPartial("additional_zones")
1068+
} else if d.HasChange("node_locations") {
1069+
azSetOldI, azSetNewI := d.GetChange("node_locations")
1070+
azSetNew := azSetNewI.(*schema.Set)
1071+
azSetOld := azSetOldI.(*schema.Set)
1072+
if azSetNew.Contains(location) {
1073+
return fmt.Errorf("for multi-zonal clusters, node_locations should not contain the primary 'zone'")
1074+
}
1075+
// Since we can't add & remove zones in the same request, first add all the
1076+
// zones, then remove the ones we aren't using anymore.
1077+
azSet := azSetOld.Union(azSetNew)
1078+
1079+
if isZone(location) {
1080+
azSet.Add(location)
1081+
}
1082+
1083+
req := &containerBeta.UpdateClusterRequest{
1084+
Update: &containerBeta.ClusterUpdate{
1085+
DesiredLocations: convertStringSet(azSet),
1086+
},
1087+
}
1088+
1089+
updateF := updateFunc(req, "updating GKE cluster node locations")
1090+
// Call update serially.
1091+
if err := lockedCall(lockKey, updateF); err != nil {
1092+
return err
1093+
}
1094+
1095+
if isZone(location) {
1096+
azSetNew.Add(location)
1097+
}
1098+
if !azSet.Equal(azSetNew) {
1099+
req = &containerBeta.UpdateClusterRequest{
1100+
Update: &containerBeta.ClusterUpdate{
1101+
DesiredLocations: convertStringSet(azSetNew),
1102+
},
1103+
}
1104+
1105+
updateF := updateFunc(req, "updating GKE cluster node locations")
1106+
// Call update serially.
1107+
if err := lockedCall(lockKey, updateF); err != nil {
1108+
return err
1109+
}
1110+
}
1111+
1112+
log.Printf("[INFO] GKE cluster %s node locations have been updated to %v", d.Id(), azSet.List())
1113+
1114+
d.SetPartial("node_locations")
10251115
}
10261116

10271117
if d.HasChange("enable_legacy_abac") {
@@ -1796,7 +1886,7 @@ func resourceContainerClusterStateImporter(d *schema.ResourceData, meta interfac
17961886
location = parts[1]
17971887
clusterName = parts[2]
17981888
default:
1799-
return nil, fmt.Errorf("Invalid container cluster specifier. Expecting {zone}/{name} or {project}/{zone}/{name}")
1889+
return nil, fmt.Errorf("Invalid container cluster specifier. Expecting {location}/{name} or {project}/{location}/{name}")
18001890
}
18011891

18021892
if len(project) > 0 {
@@ -1809,6 +1899,7 @@ func resourceContainerClusterStateImporter(d *schema.ResourceData, meta interfac
18091899
}
18101900
}
18111901

1902+
d.Set("location", location)
18121903
if isZone(location) {
18131904
d.Set("zone", location)
18141905
} else {

0 commit comments

Comments
 (0)