mirror of
https://github.com/letic/terraform-provider-google.git
synced 2024-10-03 01:01:06 +00:00
Add support for node pool autoscaling (#157)
* add node pool autoscaling * docs for node pool autoscaling * remove enabled attribute * remove enabled from docs
This commit is contained in:
parent
95570b1ed0
commit
42a898dbd0
@ -14,6 +14,7 @@ func resourceContainerNodePool() *schema.Resource {
|
||||
return &schema.Resource{
|
||||
Create: resourceContainerNodePoolCreate,
|
||||
Read: resourceContainerNodePoolRead,
|
||||
Update: resourceContainerNodePoolUpdate,
|
||||
Delete: resourceContainerNodePoolDelete,
|
||||
Exists: resourceContainerNodePoolExists,
|
||||
|
||||
@ -55,6 +56,41 @@ func resourceContainerNodePool() *schema.Resource {
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
|
||||
"autoscaling": &schema.Schema{
|
||||
Type: schema.TypeList,
|
||||
Optional: true,
|
||||
MaxItems: 1,
|
||||
Elem: &schema.Resource{
|
||||
Schema: map[string]*schema.Schema{
|
||||
"min_node_count": &schema.Schema{
|
||||
Type: schema.TypeInt,
|
||||
Required: true,
|
||||
ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) {
|
||||
value := v.(int)
|
||||
|
||||
if value < 1 {
|
||||
errors = append(errors, fmt.Errorf("%q must be >=1", k))
|
||||
}
|
||||
return
|
||||
},
|
||||
},
|
||||
|
||||
"max_node_count": &schema.Schema{
|
||||
Type: schema.TypeInt,
|
||||
Required: true,
|
||||
ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) {
|
||||
value := v.(int)
|
||||
|
||||
if value < 1 {
|
||||
errors = append(errors, fmt.Errorf("%q must be >=1", k))
|
||||
}
|
||||
return
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -85,6 +121,15 @@ func resourceContainerNodePoolCreate(d *schema.ResourceData, meta interface{}) e
|
||||
InitialNodeCount: int64(nodeCount),
|
||||
}
|
||||
|
||||
if v, ok := d.GetOk("autoscaling"); ok {
|
||||
autoscaling := v.([]interface{})[0].(map[string]interface{})
|
||||
nodePool.Autoscaling = &container.NodePoolAutoscaling{
|
||||
Enabled: true,
|
||||
MinNodeCount: int64(autoscaling["min_node_count"].(int)),
|
||||
MaxNodeCount: int64(autoscaling["max_node_count"].(int)),
|
||||
}
|
||||
}
|
||||
|
||||
req := &container.CreateNodePoolRequest{
|
||||
NodePool: nodePool,
|
||||
}
|
||||
@ -130,9 +175,70 @@ func resourceContainerNodePoolRead(d *schema.ResourceData, meta interface{}) err
|
||||
d.Set("name", nodePool.Name)
|
||||
d.Set("initial_node_count", nodePool.InitialNodeCount)
|
||||
|
||||
autoscaling := []map[string]interface{}{}
|
||||
if nodePool.Autoscaling != nil && nodePool.Autoscaling.Enabled {
|
||||
autoscaling = []map[string]interface{}{
|
||||
map[string]interface{}{
|
||||
"min_node_count": nodePool.Autoscaling.MinNodeCount,
|
||||
"max_node_count": nodePool.Autoscaling.MaxNodeCount,
|
||||
},
|
||||
}
|
||||
}
|
||||
d.Set("autoscaling", autoscaling)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func resourceContainerNodePoolUpdate(d *schema.ResourceData, meta interface{}) error {
|
||||
config := meta.(*Config)
|
||||
|
||||
project, err := getProject(d, config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
zone := d.Get("zone").(string)
|
||||
name := d.Get("name").(string)
|
||||
cluster := d.Get("cluster").(string)
|
||||
|
||||
if d.HasChange("autoscaling") {
|
||||
update := &container.ClusterUpdate{
|
||||
DesiredNodePoolId: name,
|
||||
}
|
||||
if v, ok := d.GetOk("autoscaling"); ok {
|
||||
autoscaling := v.([]interface{})[0].(map[string]interface{})
|
||||
update.DesiredNodePoolAutoscaling = &container.NodePoolAutoscaling{
|
||||
Enabled: true,
|
||||
MinNodeCount: int64(autoscaling["min_node_count"].(int)),
|
||||
MaxNodeCount: int64(autoscaling["max_node_count"].(int)),
|
||||
}
|
||||
} else {
|
||||
update.DesiredNodePoolAutoscaling = &container.NodePoolAutoscaling{
|
||||
Enabled: false,
|
||||
}
|
||||
}
|
||||
|
||||
req := &container.UpdateClusterRequest{
|
||||
Update: update,
|
||||
}
|
||||
op, err := config.clientContainer.Projects.Zones.Clusters.Update(
|
||||
project, zone, cluster, req).Do()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Wait until it's updated
|
||||
waitErr := containerOperationWait(config, op, project, zone, "updating GKE node pool", 10, 2)
|
||||
if waitErr != nil {
|
||||
return waitErr
|
||||
}
|
||||
|
||||
log.Printf("[INFO] Updated autoscaling in Node Pool %s", d.Id())
|
||||
}
|
||||
|
||||
return resourceContainerNodePoolRead(d, meta)
|
||||
}
|
||||
|
||||
func resourceContainerNodePoolDelete(d *schema.ResourceData, meta interface{}) error {
|
||||
config := meta.(*Config)
|
||||
|
||||
|
@ -11,13 +11,47 @@ import (
|
||||
)
|
||||
|
||||
func TestAccContainerNodePool_basic(t *testing.T) {
|
||||
cluster := fmt.Sprintf("tf-nodepool-test-%s", acctest.RandString(10))
|
||||
np := fmt.Sprintf("tf-nodepool-test-%s", acctest.RandString(10))
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Providers: testAccProviders,
|
||||
CheckDestroy: testAccCheckContainerNodePoolDestroy,
|
||||
Steps: []resource.TestStep{
|
||||
resource.TestStep{
|
||||
Config: testAccContainerNodePool_basic,
|
||||
Config: testAccContainerNodePool_basic(cluster, np),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckContainerNodePoolMatches("google_container_node_pool.np"),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestAccContainerNodePool_autoscaling(t *testing.T) {
|
||||
cluster := fmt.Sprintf("tf-nodepool-test-%s", acctest.RandString(10))
|
||||
np := fmt.Sprintf("tf-nodepool-test-%s", acctest.RandString(10))
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Providers: testAccProviders,
|
||||
CheckDestroy: testAccCheckContainerNodePoolDestroy,
|
||||
Steps: []resource.TestStep{
|
||||
resource.TestStep{
|
||||
Config: testAccContainerNodePool_autoscaling(cluster, np),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckContainerNodePoolMatches("google_container_node_pool.np"),
|
||||
),
|
||||
},
|
||||
resource.TestStep{
|
||||
Config: testAccContainerNodePool_updateAutoscaling(cluster, np),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckContainerNodePoolMatches("google_container_node_pool.np"),
|
||||
),
|
||||
},
|
||||
resource.TestStep{
|
||||
Config: testAccContainerNodePool_basic(cluster, np),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckContainerNodePoolMatches("google_container_node_pool.np"),
|
||||
),
|
||||
@ -77,13 +111,32 @@ func testAccCheckContainerNodePoolMatches(n string) resource.TestCheckFunc {
|
||||
return fmt.Errorf("Mismatched initialNodeCount. TF State: %s. GCP State: %d",
|
||||
attributes["initial_node_count"], found.InitialNodeCount)
|
||||
}
|
||||
|
||||
tfAS := attributes["autoscaling.#"] == "1"
|
||||
if gcpAS := found.Autoscaling != nil && found.Autoscaling.Enabled == true; tfAS != gcpAS {
|
||||
return fmt.Errorf("Mismatched autoscaling status. TF State: %t. GCP State: %t", tfAS, gcpAS)
|
||||
}
|
||||
if tfAS {
|
||||
if tf := attributes["autoscaling.0.min_node_count"]; strconv.FormatInt(found.Autoscaling.MinNodeCount, 10) != tf {
|
||||
return fmt.Errorf("Mismatched Autoscaling.MinNodeCount. TF State: %s. GCP State: %d",
|
||||
tf, found.Autoscaling.MinNodeCount)
|
||||
}
|
||||
|
||||
if tf := attributes["autoscaling.0.max_node_count"]; strconv.FormatInt(found.Autoscaling.MaxNodeCount, 10) != tf {
|
||||
return fmt.Errorf("Mismatched Autoscaling.MaxNodeCount. TF State: %s. GCP State: %d",
|
||||
tf, found.Autoscaling.MaxNodeCount)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
var testAccContainerNodePool_basic = fmt.Sprintf(`
|
||||
func testAccContainerNodePool_basic(cluster, np string) string {
|
||||
return fmt.Sprintf(`
|
||||
resource "google_container_cluster" "cluster" {
|
||||
name = "tf-cluster-nodepool-test-%s"
|
||||
name = "%s"
|
||||
zone = "us-central1-a"
|
||||
initial_node_count = 3
|
||||
|
||||
@ -94,8 +147,59 @@ resource "google_container_cluster" "cluster" {
|
||||
}
|
||||
|
||||
resource "google_container_node_pool" "np" {
|
||||
name = "tf-nodepool-test-%s"
|
||||
name = "%s"
|
||||
zone = "us-central1-a"
|
||||
cluster = "${google_container_cluster.cluster.name}"
|
||||
initial_node_count = 2
|
||||
}`, acctest.RandString(10), acctest.RandString(10))
|
||||
}`, cluster, np)
|
||||
}
|
||||
|
||||
func testAccContainerNodePool_autoscaling(cluster, np string) string {
|
||||
return fmt.Sprintf(`
|
||||
resource "google_container_cluster" "cluster" {
|
||||
name = "%s"
|
||||
zone = "us-central1-a"
|
||||
initial_node_count = 3
|
||||
|
||||
master_auth {
|
||||
username = "mr.yoda"
|
||||
password = "adoy.rm"
|
||||
}
|
||||
}
|
||||
|
||||
resource "google_container_node_pool" "np" {
|
||||
name = "%s"
|
||||
zone = "us-central1-a"
|
||||
cluster = "${google_container_cluster.cluster.name}"
|
||||
initial_node_count = 2
|
||||
autoscaling {
|
||||
min_node_count = 1
|
||||
max_node_count = 3
|
||||
}
|
||||
}`, cluster, np)
|
||||
}
|
||||
|
||||
func testAccContainerNodePool_updateAutoscaling(cluster, np string) string {
|
||||
return fmt.Sprintf(`
|
||||
resource "google_container_cluster" "cluster" {
|
||||
name = "%s"
|
||||
zone = "us-central1-a"
|
||||
initial_node_count = 3
|
||||
|
||||
master_auth {
|
||||
username = "mr.yoda"
|
||||
password = "adoy.rm"
|
||||
}
|
||||
}
|
||||
|
||||
resource "google_container_node_pool" "np" {
|
||||
name = "%s"
|
||||
zone = "us-central1-a"
|
||||
cluster = "${google_container_cluster.cluster.name}"
|
||||
initial_node_count = 2
|
||||
autoscaling {
|
||||
min_node_count = 1
|
||||
max_node_count = 5
|
||||
}
|
||||
}`, cluster, np)
|
||||
}
|
||||
|
@ -67,3 +67,13 @@ resource "google_container_cluster" "primary" {
|
||||
|
||||
* `name_prefix` - (Optional) Creates a unique name for the node pool beginning
|
||||
with the specified prefix. Conflicts with `name`.
|
||||
|
||||
* `autoscaling` - (Optional) Configuration required by cluster autoscaler to adjust
|
||||
the size of the node pool to the current cluster usage. Structure is documented below.
|
||||
|
||||
The `autoscaling` block supports:
|
||||
|
||||
* `minNodeCount` - (Required) Minimum number of nodes in the NodePool. Must be >=1 and
|
||||
<= `maxNodeCount`.
|
||||
|
||||
* `maxNodeCount` - (Required) Maximum number of nodes in the NodePool. Must be >= minNodeCount.
|
Loading…
Reference in New Issue
Block a user