Add preemptible as an option to node config (#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
This commit is contained in:
Joe Selman 2017-09-01 13:02:26 -07:00 committed by GitHub
parent 9bd35d7d4a
commit 0605638885
7 changed files with 67 additions and 27 deletions

View File

@ -84,6 +84,13 @@ var schemaNodeConfig = &schema.Schema{
ForceNew: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"preemptible": {
Type: schema.TypeBool,
Optional: true,
ForceNew: true,
Default: false,
},
},
},
}
@ -148,7 +155,30 @@ func expandNodeConfig(v interface{}) *container.NodeConfig {
}
nc.Tags = tags
}
// Preemptible Is Optional+Default, so it always has a value
nc.Preemptible = nodeConfig["preemptible"].(bool)
return nc
}
func flattenNodeConfig(c *container.NodeConfig) []map[string]interface{} {
config := []map[string]interface{}{
{
"machine_type": c.MachineType,
"disk_size_gb": c.DiskSizeGb,
"local_ssd_count": c.LocalSsdCount,
"service_account": c.ServiceAccount,
"metadata": c.Metadata,
"image_type": c.ImageType,
"labels": c.Labels,
"tags": c.Tags,
"preemptible": c.Preemptible,
},
}
if len(c.OauthScopes) > 0 {
config[0]["oauth_scopes"] = c.OauthScopes
}
return config
}

View File

@ -494,7 +494,7 @@ func resourceContainerClusterRead(d *schema.ResourceData, meta interface{}) erro
d.Set("monitoring_service", cluster.MonitoringService)
d.Set("network", d.Get("network").(string))
d.Set("subnetwork", cluster.Subnetwork)
d.Set("node_config", flattenClusterNodeConfig(cluster.NodeConfig))
d.Set("node_config", flattenNodeConfig(cluster.NodeConfig))
nps, err := flattenClusterNodePools(d, config, cluster.NodePools)
if err != nil {
return err
@ -733,27 +733,6 @@ func getInstanceGroupUrlsFromManagerUrls(config *Config, igmUrls []string) ([]st
return instanceGroupURLs, nil
}
func flattenClusterNodeConfig(c *container.NodeConfig) []map[string]interface{} {
config := []map[string]interface{}{
{
"machine_type": c.MachineType,
"disk_size_gb": c.DiskSizeGb,
"local_ssd_count": c.LocalSsdCount,
"service_account": c.ServiceAccount,
"metadata": c.Metadata,
"image_type": c.ImageType,
"labels": c.Labels,
"tags": c.Tags,
},
}
if len(c.OauthScopes) > 0 {
config[0]["oauth_scopes"] = c.OauthScopes
}
return config
}
func flattenClusterNodePools(d *schema.ResourceData, config *Config, c []*container.NodePool) ([]map[string]interface{}, error) {
nodePools := make([]map[string]interface{}, 0, len(c))
@ -776,7 +755,7 @@ func flattenClusterNodePools(d *schema.ResourceData, config *Config, c []*contai
"name_prefix": d.Get(fmt.Sprintf("node_pool.%d.name_prefix", i)),
"initial_node_count": np.InitialNodeCount,
"node_count": size / len(np.InstanceGroupUrls),
"node_config": flattenClusterNodeConfig(np.Config),
"node_config": flattenNodeConfig(np.Config),
}
nodePools = append(nodePools, nodePool)
}

View File

@ -449,6 +449,7 @@ func testAccCheckContainerCluster(n string) resource.TestCheckFunc {
{"node_config.0.image_type", cluster.NodeConfig.ImageType},
{"node_config.0.labels", cluster.NodeConfig.Labels},
{"node_config.0.tags", cluster.NodeConfig.Tags},
{"node_config.0.preemptible", cluster.NodeConfig.Preemptible},
{"node_version", cluster.CurrentNodeVersion},
}
@ -535,6 +536,10 @@ func checkMatch(attributes map[string]string, attr string, gcp interface{}) stri
if gcpMap, ok := gcp.(map[string]string); ok {
return checkMapMatch(attributes, attr, gcpMap)
}
if gcpBool, ok := gcp.(bool); ok {
return checkBoolMatch(attributes, attr, gcpBool)
}
tf := attributes[attr]
if tf != gcp {
return matchError(attr, tf, gcp)
@ -602,6 +607,18 @@ func checkMapMatch(attributes map[string]string, attr string, gcpMap map[string]
return ""
}
func checkBoolMatch(attributes map[string]string, attr string, gcpBool bool) string {
tf, err := strconv.ParseBool(attributes[attr])
if err != nil {
return fmt.Sprintf("Error converting attribute %s to boolean: value is %s", attr, attributes[attr])
}
if tf != gcpBool {
return matchError(attr, tf, gcpBool)
}
return ""
}
func matchError(attr, tf interface{}, gcp interface{}) string {
return fmt.Sprintf("Cluster has mismatched %s.\nTF State: %+v\nGCP State: %+v", attr, tf, gcp)
}
@ -762,11 +779,12 @@ resource "google_container_cluster" "with_node_config" {
metadata {
foo = "bar"
}
image_type = "CONTAINER_VM"
image_type = "COS"
labels {
foo = "bar"
}
tags = ["foo", "bar"]
preemptible = true
}
}`, acctest.RandString(10))
@ -1018,7 +1036,7 @@ resource "google_container_cluster" "with_node_pool_node_config" {
metadata {
foo = "bar"
}
image_type = "CONTAINER_VM"
image_type = "COS"
labels {
foo = "bar"
}

View File

@ -174,7 +174,7 @@ func resourceContainerNodePoolRead(d *schema.ResourceData, meta interface{}) err
d.Set("name", nodePool.Name)
d.Set("initial_node_count", nodePool.InitialNodeCount)
d.Set("node_config", flattenClusterNodeConfig(nodePool.Config))
d.Set("node_config", flattenNodeConfig(nodePool.Config))
autoscaling := []map[string]interface{}{}
if nodePool.Autoscaling != nil && nodePool.Autoscaling.Enabled {

View File

@ -154,6 +154,7 @@ func testAccCheckContainerNodePoolMatches(n string) resource.TestCheckFunc {
{"node_config.0.image_type", nodepool.Config.ImageType},
{"node_config.0.labels", nodepool.Config.Labels},
{"node_config.0.tags", nodepool.Config.Tags},
{"node_config.0.preemptible", nodepool.Config.Preemptible},
}
for _, attrs := range nodepoolTests {
@ -261,6 +262,9 @@ func nodepoolCheckMatch(attributes map[string]string, attr string, gcp interface
if gcpMap, ok := gcp.(map[string]string); ok {
return nodepoolCheckMapMatch(attributes, attr, gcpMap)
}
if gcpBool, ok := gcp.(bool); ok {
return checkBoolMatch(attributes, attr, gcpBool)
}
tf := attributes[attr]
if tf != gcp {
return nodepoolMatchError(attr, tf, gcp)
@ -356,6 +360,7 @@ resource "google_container_node_pool" "np_with_node_config" {
"https://www.googleapis.com/auth/logging.write",
"https://www.googleapis.com/auth/monitoring"
]
preemptible = true
}
}`, acctest.RandString(10), acctest.RandString(10))

View File

@ -153,6 +153,10 @@ which the cluster's instances are launched
* `tags` - (Optional) The list of instance tags applied to all nodes. Tags are used to identify
valid sources or targets for network firewalls.
* `preemptible` - (Optional) A boolean that represents whether or not the underlying node VMs
are preemptible. See the [official documentation](https://cloud.google.com/container-engine/docs/preemptible-vm)
for more information. Defaults to false.
**Addons Config** supports the following addons:
* `http_load_balancing` - (Optional) The status of the HTTP Load Balancing

View File

@ -105,6 +105,10 @@ resource "google_container_cluster" "primary" {
* `image_type` - (Optional) The image type to use for this node.
* `preemptible` - (Optional) A boolean that represents whether or not the underlying node VMs
are preemptible. See the [official documentation](https://cloud.google.com/container-engine/docs/preemptible-vm)
for more information. Defaults to false.
The `autoscaling` block supports:
* `minNodeCount` - (Required) Minimum number of nodes in the NodePool. Must be >=1 and