Skip to content

Commit e7eba87

Browse files
authored
Add preemptible as an option to node config (hashicorp#341)
* Add preemptible as an option to node config * Check for preemptible in test matching functions * Move flattenClusterNodeConfig to node_config * Handle bools properly when comparing in cluster and node pool tests * Use a supported image_type in cluster tests
1 parent 5a6d4c3 commit e7eba87

7 files changed

+66
-26
lines changed

google/node_config.go

+30
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,13 @@ var schemaNodeConfig = &schema.Schema{
8484
ForceNew: true,
8585
Elem: &schema.Schema{Type: schema.TypeString},
8686
},
87+
88+
"preemptible": {
89+
Type: schema.TypeBool,
90+
Optional: true,
91+
ForceNew: true,
92+
Default: false,
93+
},
8794
},
8895
},
8996
}
@@ -148,7 +155,30 @@ func expandNodeConfig(v interface{}) *container.NodeConfig {
148155
}
149156
nc.Tags = tags
150157
}
158+
// Preemptible Is Optional+Default, so it always has a value
159+
nc.Preemptible = nodeConfig["preemptible"].(bool)
151160

152161
return nc
162+
}
163+
164+
func flattenNodeConfig(c *container.NodeConfig) []map[string]interface{} {
165+
config := []map[string]interface{}{
166+
{
167+
"machine_type": c.MachineType,
168+
"disk_size_gb": c.DiskSizeGb,
169+
"local_ssd_count": c.LocalSsdCount,
170+
"service_account": c.ServiceAccount,
171+
"metadata": c.Metadata,
172+
"image_type": c.ImageType,
173+
"labels": c.Labels,
174+
"tags": c.Tags,
175+
"preemptible": c.Preemptible,
176+
},
177+
}
178+
179+
if len(c.OauthScopes) > 0 {
180+
config[0]["oauth_scopes"] = c.OauthScopes
181+
}
153182

183+
return config
154184
}

google/resource_container_cluster.go

+2-23
Original file line numberDiff line numberDiff line change
@@ -494,7 +494,7 @@ func resourceContainerClusterRead(d *schema.ResourceData, meta interface{}) erro
494494
d.Set("monitoring_service", cluster.MonitoringService)
495495
d.Set("network", d.Get("network").(string))
496496
d.Set("subnetwork", cluster.Subnetwork)
497-
d.Set("node_config", flattenClusterNodeConfig(cluster.NodeConfig))
497+
d.Set("node_config", flattenNodeConfig(cluster.NodeConfig))
498498
nps, err := flattenClusterNodePools(d, config, cluster.NodePools)
499499
if err != nil {
500500
return err
@@ -733,27 +733,6 @@ func getInstanceGroupUrlsFromManagerUrls(config *Config, igmUrls []string) ([]st
733733
return instanceGroupURLs, nil
734734
}
735735

736-
func flattenClusterNodeConfig(c *container.NodeConfig) []map[string]interface{} {
737-
config := []map[string]interface{}{
738-
{
739-
"machine_type": c.MachineType,
740-
"disk_size_gb": c.DiskSizeGb,
741-
"local_ssd_count": c.LocalSsdCount,
742-
"service_account": c.ServiceAccount,
743-
"metadata": c.Metadata,
744-
"image_type": c.ImageType,
745-
"labels": c.Labels,
746-
"tags": c.Tags,
747-
},
748-
}
749-
750-
if len(c.OauthScopes) > 0 {
751-
config[0]["oauth_scopes"] = c.OauthScopes
752-
}
753-
754-
return config
755-
}
756-
757736
func flattenClusterNodePools(d *schema.ResourceData, config *Config, c []*container.NodePool) ([]map[string]interface{}, error) {
758737
nodePools := make([]map[string]interface{}, 0, len(c))
759738

@@ -776,7 +755,7 @@ func flattenClusterNodePools(d *schema.ResourceData, config *Config, c []*contai
776755
"name_prefix": d.Get(fmt.Sprintf("node_pool.%d.name_prefix", i)),
777756
"initial_node_count": np.InitialNodeCount,
778757
"node_count": size / len(np.InstanceGroupUrls),
779-
"node_config": flattenClusterNodeConfig(np.Config),
758+
"node_config": flattenNodeConfig(np.Config),
780759
}
781760
nodePools = append(nodePools, nodePool)
782761
}

google/resource_container_cluster_test.go

+20-2
Original file line numberDiff line numberDiff line change
@@ -449,6 +449,7 @@ func testAccCheckContainerCluster(n string) resource.TestCheckFunc {
449449
{"node_config.0.image_type", cluster.NodeConfig.ImageType},
450450
{"node_config.0.labels", cluster.NodeConfig.Labels},
451451
{"node_config.0.tags", cluster.NodeConfig.Tags},
452+
{"node_config.0.preemptible", cluster.NodeConfig.Preemptible},
452453
{"node_version", cluster.CurrentNodeVersion},
453454
}
454455

@@ -535,6 +536,10 @@ func checkMatch(attributes map[string]string, attr string, gcp interface{}) stri
535536
if gcpMap, ok := gcp.(map[string]string); ok {
536537
return checkMapMatch(attributes, attr, gcpMap)
537538
}
539+
if gcpBool, ok := gcp.(bool); ok {
540+
return checkBoolMatch(attributes, attr, gcpBool)
541+
}
542+
538543
tf := attributes[attr]
539544
if tf != gcp {
540545
return matchError(attr, tf, gcp)
@@ -602,6 +607,18 @@ func checkMapMatch(attributes map[string]string, attr string, gcpMap map[string]
602607
return ""
603608
}
604609

610+
func checkBoolMatch(attributes map[string]string, attr string, gcpBool bool) string {
611+
tf, err := strconv.ParseBool(attributes[attr])
612+
if err != nil {
613+
return fmt.Sprintf("Error converting attribute %s to boolean: value is %s", attr, attributes[attr])
614+
}
615+
if tf != gcpBool {
616+
return matchError(attr, tf, gcpBool)
617+
}
618+
619+
return ""
620+
}
621+
605622
func matchError(attr, tf interface{}, gcp interface{}) string {
606623
return fmt.Sprintf("Cluster has mismatched %s.\nTF State: %+v\nGCP State: %+v", attr, tf, gcp)
607624
}
@@ -762,11 +779,12 @@ resource "google_container_cluster" "with_node_config" {
762779
metadata {
763780
foo = "bar"
764781
}
765-
image_type = "CONTAINER_VM"
782+
image_type = "COS"
766783
labels {
767784
foo = "bar"
768785
}
769786
tags = ["foo", "bar"]
787+
preemptible = true
770788
}
771789
}`, acctest.RandString(10))
772790

@@ -1018,7 +1036,7 @@ resource "google_container_cluster" "with_node_pool_node_config" {
10181036
metadata {
10191037
foo = "bar"
10201038
}
1021-
image_type = "CONTAINER_VM"
1039+
image_type = "COS"
10221040
labels {
10231041
foo = "bar"
10241042
}

google/resource_container_node_pool.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ func resourceContainerNodePoolRead(d *schema.ResourceData, meta interface{}) err
174174

175175
d.Set("name", nodePool.Name)
176176
d.Set("initial_node_count", nodePool.InitialNodeCount)
177-
d.Set("node_config", flattenClusterNodeConfig(nodePool.Config))
177+
d.Set("node_config", flattenNodeConfig(nodePool.Config))
178178

179179
autoscaling := []map[string]interface{}{}
180180
if nodePool.Autoscaling != nil && nodePool.Autoscaling.Enabled {

google/resource_container_node_pool_test.go

+5
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ func testAccCheckContainerNodePoolMatches(n string) resource.TestCheckFunc {
154154
{"node_config.0.image_type", nodepool.Config.ImageType},
155155
{"node_config.0.labels", nodepool.Config.Labels},
156156
{"node_config.0.tags", nodepool.Config.Tags},
157+
{"node_config.0.preemptible", nodepool.Config.Preemptible},
157158
}
158159

159160
for _, attrs := range nodepoolTests {
@@ -261,6 +262,9 @@ func nodepoolCheckMatch(attributes map[string]string, attr string, gcp interface
261262
if gcpMap, ok := gcp.(map[string]string); ok {
262263
return nodepoolCheckMapMatch(attributes, attr, gcpMap)
263264
}
265+
if gcpBool, ok := gcp.(bool); ok {
266+
return checkBoolMatch(attributes, attr, gcpBool)
267+
}
264268
tf := attributes[attr]
265269
if tf != gcp {
266270
return nodepoolMatchError(attr, tf, gcp)
@@ -356,6 +360,7 @@ resource "google_container_node_pool" "np_with_node_config" {
356360
"https://www.googleapis.com/auth/logging.write",
357361
"https://www.googleapis.com/auth/monitoring"
358362
]
363+
preemptible = true
359364
}
360365
}`, acctest.RandString(10), acctest.RandString(10))
361366

website/docs/r/container_cluster.html.markdown

+4
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,10 @@ which the cluster's instances are launched
153153
* `tags` - (Optional) The list of instance tags applied to all nodes. Tags are used to identify
154154
valid sources or targets for network firewalls.
155155

156+
* `preemptible` - (Optional) A boolean that represents whether or not the underlying node VMs
157+
are preemptible. See the [official documentation](https://cloud.google.com/container-engine/docs/preemptible-vm)
158+
for more information. Defaults to false.
159+
156160
**Addons Config** supports the following addons:
157161

158162
* `http_load_balancing` - (Optional) The status of the HTTP Load Balancing

website/docs/r/container_node_pool.html.markdown

+4
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,10 @@ resource "google_container_cluster" "primary" {
105105

106106
* `image_type` - (Optional) The image type to use for this node.
107107

108+
* `preemptible` - (Optional) A boolean that represents whether or not the underlying node VMs
109+
are preemptible. See the [official documentation](https://cloud.google.com/container-engine/docs/preemptible-vm)
110+
for more information. Defaults to false.
111+
108112
The `autoscaling` block supports:
109113

110114
* `minNodeCount` - (Required) Minimum number of nodes in the NodePool. Must be >=1 and

0 commit comments

Comments
 (0)