-
Notifications
You must be signed in to change notification settings - Fork 1.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for google_container_node_pool
management
#669
Changes from all commits
becccdf
043ff50
9d99eb6
84e54e1
f1800ea
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -85,6 +85,28 @@ var schemaNodePool = map[string]*schema.Schema{ | |
Deprecated: "Use node_count instead", | ||
}, | ||
|
||
"management": { | ||
Type: schema.TypeList, | ||
Optional: true, | ||
Computed: true, | ||
MaxItems: 1, | ||
Elem: &schema.Resource{ | ||
Schema: map[string]*schema.Schema{ | ||
"auto_repair": { | ||
Type: schema.TypeBool, | ||
Optional: true, | ||
Default: false, | ||
}, | ||
|
||
"auto_upgrade": { | ||
Type: schema.TypeBool, | ||
Optional: true, | ||
Default: false, | ||
}, | ||
}, | ||
}, | ||
}, | ||
|
||
"name": &schema.Schema{ | ||
Type: schema.TypeString, | ||
Optional: true, | ||
|
@@ -301,6 +323,19 @@ func expandNodePool(d *schema.ResourceData, prefix string) (*container.NodePool, | |
} | ||
} | ||
|
||
if v, ok := d.GetOk(prefix + "management"); ok { | ||
managementConfig := v.([]interface{})[0].(map[string]interface{}) | ||
np.Management = &container.NodeManagement{} | ||
|
||
if v, ok := managementConfig["auto_repair"]; ok { | ||
np.Management.AutoRepair = v.(bool) | ||
} | ||
|
||
if v, ok := managementConfig["auto_upgrade"]; ok { | ||
np.Management.AutoUpgrade = v.(bool) | ||
} | ||
} | ||
|
||
return np, nil | ||
} | ||
|
||
|
@@ -335,6 +370,13 @@ func flattenNodePool(d *schema.ResourceData, config *Config, np *container.NodeP | |
} | ||
} | ||
|
||
nodePool["management"] = []map[string]interface{}{ | ||
{ | ||
"auto_repair": np.Management.AutoRepair, | ||
"auto_upgrade": np.Management.AutoUpgrade, | ||
}, | ||
} | ||
|
||
return nodePool, nil | ||
} | ||
|
||
|
@@ -412,6 +454,37 @@ func nodePoolUpdate(d *schema.ResourceData, meta interface{}, clusterName, prefi | |
} | ||
} | ||
|
||
if d.HasChange(prefix + "management") { | ||
management := &container.NodeManagement{} | ||
if v, ok := d.GetOk(prefix + "management"); ok { | ||
managementConfig := v.([]interface{})[0].(map[string]interface{}) | ||
management.AutoRepair = managementConfig["auto_repair"].(bool) | ||
management.AutoUpgrade = managementConfig["auto_upgrade"].(bool) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. since this api is There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done. |
||
management.ForceSendFields = []string{"AutoRepair", "AutoUpgrade"} | ||
} | ||
req := &container.SetNodePoolManagementRequest{ | ||
Management: management, | ||
} | ||
op, err := config.clientContainer.Projects.Zones.Clusters.NodePools.SetManagement( | ||
project, zone, clusterName, npName, req).Do() | ||
|
||
if err != nil { | ||
return err | ||
} | ||
|
||
// Wait until it's updated | ||
waitErr := containerOperationWait(config, op, project, zone, "updating GKE node pool management", timeoutInMinutes, 2) | ||
if waitErr != nil { | ||
return waitErr | ||
} | ||
|
||
log.Printf("[INFO] Updated management in Node Pool %s", npName) | ||
|
||
if prefix == "" { | ||
d.SetPartial("management") | ||
} | ||
} | ||
|
||
return nil | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this actually computed? (note: it might be! it's just sometimes hard to tell from looking at the api, so I usually ask)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm obviously somewhat fuzzy on the exact meaning of
computed
and when exactly to use it / not use it (especially in the context of new attributes withForceNew: true
being added to resources that are already out in the wild, though this is not that case), if you don't mind giving me a one-time clarification. In this context, the field is always passed back from the API and both values are false if unspecified. Based on my current understanding, I'd think that means the field isoptional
+computed
, but that could be totally incorrect. I can do a bit of testing on my own to get a better grasp.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The way I like to think about
Computed
is that it doesn't cause a diff if the value is set in state but not in the config. For a simple case, takename
. We allow the user to set this field to empty, which means that terraform will generate a name for you, which we then store in state. Since we don't want the next run ofterraform plan
to show a diff (since you aren't actually trying to set the name to empty), we havename
asComputed
so that when it's empty, nothing happens.So in this case, if management is always returned from the api, then it will always get set in state via the flatten fn, so
Computed
is indeed the correct choice. A good example of the opposite is autoscaling- if it isn't enabled, then it doesn't get returned from the API at all (sonp.Autoscaling
gives nil), meaning we don't want it to get set in state.The reason I like to double-check that a field needs to be
Computed
is that this empty-means-no-diff-behavior means that removing the field from your config doesn't set it to the default value, as might be expected. So for example, if we completely remove theautoscaling
block, terraform will notice there's a diff between what's in state (autoscaling enabled) and what's in the config (no autoscaling) and will call update appropriately. For management, if (say)auto_repair
is set to true in state, and then I remove the entiremanagement
block in the hopes of "removing" management, terraform won't see that as a diff and so nothing will be updated.The way I usually handle this when developing is to just set nothing to Computed and see what fails in testing. In this particular case, since
Management
is returned from the API, I think you should leave it asComputed
but set the two properties to beDefault: false
. That way, if they are set to true in the schema and then removed, terraform will see that it needs to set it back to false. It'll just work for those individual fields, not the full management block, but I think it's still better than nothing.I hope that makes sense! It's taken me a long time to get to my current level of understanding so feel free to ask any more questions you might have :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rad! Thanks so much for the great, thorough explanation. That makes complete sense. I'll make that change and re-test now.