Skip to content

Commit

Permalink
add auto_provisioning_defaults to `google_container_cluster.cluster…
Browse files Browse the repository at this point in the history
…_autoscaling`
  • Loading branch information
megan07 authored Nov 26, 2019
2 parents c9f75bd + a399651 commit b58ab1d
Show file tree
Hide file tree
Showing 8 changed files with 355 additions and 57 deletions.
3 changes: 2 additions & 1 deletion google/node_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,8 @@ var schemaNodeConfig = &schema.Schema{
return canonicalizeServiceScope(v.(string))
},
},
Set: stringScopeHashcode,
DiffSuppressFunc: containerClusterAddedScopesSuppress,
Set: stringScopeHashcode,
},

"preemptible": {
Expand Down
26 changes: 0 additions & 26 deletions google/resource_compute_network_peering.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"fmt"
"log"
"sort"
"strings"

"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
computeBeta "google.golang.org/api/compute/v0.beta"
Expand All @@ -19,9 +18,6 @@ func resourceComputeNetworkPeering() *schema.Resource {
Create: resourceComputeNetworkPeeringCreate,
Read: resourceComputeNetworkPeeringRead,
Delete: resourceComputeNetworkPeeringDelete,
Importer: &schema.ResourceImporter{
State: resourceComputeNetworkPeeringImport,
},

Schema: map[string]*schema.Schema{
"name": {
Expand Down Expand Up @@ -185,25 +181,3 @@ func getNetworkPeeringLockName(networkName, peerNetworkName string) string {

return fmt.Sprintf("network_peering/%s/%s", networks[0], networks[1])
}

func resourceComputeNetworkPeeringImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
config := meta.(*Config)
splits := strings.Split(d.Id(), "/")
if len(splits) != 3 {
return nil, fmt.Errorf("Error parsing network peering import format, expected: {project}/{network}/{name}")
}

// Build the template for the network self_link
urlTemplate, err := replaceVars(d, config, "{{ComputeBasePath}}projects/%s/global/networks/%s")
if err != nil {
return nil, err
}
d.Set("network", ConvertSelfLinkToV1(fmt.Sprintf(urlTemplate, splits[0], splits[1])))
d.Set("name", splits[2])

// Replace import id for the resource id
id := fmt.Sprintf("%s/%s", splits[1], splits[2])
d.SetId(id)

return []*schema.ResourceData{d}, nil
}
30 changes: 10 additions & 20 deletions google/resource_compute_network_peering_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,30 +15,20 @@ func TestAccComputeNetworkPeering_basic(t *testing.T) {
t.Parallel()
var peering_beta computeBeta.NetworkPeering

primaryNetworkName := acctest.RandomWithPrefix("network-test-1")
peeringName := acctest.RandomWithPrefix("peering-test-1")
importId := fmt.Sprintf("%s/%s/%s", getTestProjectFromEnv(), primaryNetworkName, peeringName)

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccComputeNetworkPeeringDestroy,
Steps: []resource.TestStep{
{
Config: testAccComputeNetworkPeering_basic(primaryNetworkName, peeringName),
Config: testAccComputeNetworkPeering_basic(),
Check: resource.ComposeTestCheckFunc(
testAccCheckComputeNetworkPeeringExist("google_compute_network_peering.foo", &peering_beta),
testAccCheckComputeNetworkPeeringAutoCreateRoutes(true, &peering_beta),
testAccCheckComputeNetworkPeeringExist("google_compute_network_peering.bar", &peering_beta),
testAccCheckComputeNetworkPeeringAutoCreateRoutes(true, &peering_beta),
),
},
{
ResourceName: "google_compute_network_peering.foo",
ImportState: true,
ImportStateVerify: true,
ImportStateId: importId,
},
},
})

Expand Down Expand Up @@ -107,30 +97,30 @@ func testAccCheckComputeNetworkPeeringAutoCreateRoutes(v bool, peering *computeB
}
}

func testAccComputeNetworkPeering_basic(primaryNetworkName, peeringName string) string {
func testAccComputeNetworkPeering_basic() string {
s := `
resource "google_compute_network" "network1" {
name = "%s"
name = "network-test-1-%s"
auto_create_subnetworks = false
}
resource "google_compute_network_peering" "foo" {
name = "%s"
network = google_compute_network.network1.self_link
peer_network = google_compute_network.network2.self_link
}
resource "google_compute_network" "network2" {
name = "network-test-2-%s"
auto_create_subnetworks = false
}
resource "google_compute_network_peering" "foo" {
name = "peering-test-1-%s"
network = google_compute_network.network1.self_link
peer_network = google_compute_network.network2.self_link
}
resource "google_compute_network_peering" "bar" {
network = google_compute_network.network2.self_link
peer_network = google_compute_network.network1.self_link
name = "peering-test-2-%s"
`

s = s + `}`
return fmt.Sprintf(s, primaryNetworkName, peeringName, acctest.RandString(10), acctest.RandString(10))
return fmt.Sprintf(s, acctest.RandString(10), acctest.RandString(10), acctest.RandString(10), acctest.RandString(10))
}
169 changes: 167 additions & 2 deletions google/resource_container_cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,9 @@ func resourceContainerCluster() *schema.Resource {
"cluster_autoscaling": {
Type: schema.TypeList,
MaxItems: 1,
Removed: "This field is in beta. Use it in the the google-beta provider instead. See https://terraform.io/docs/providers/google/guides/provider_versions.html for more details.",
// This field is Optional + Computed because we automatically set the
// enabled value to false if the block is not returned in API responses.
Optional: true,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
Expand Down Expand Up @@ -243,6 +245,35 @@ func resourceContainerCluster() *schema.Resource {
},
},
},
"auto_provisioning_defaults": {
Type: schema.TypeList,
MaxItems: 1,
Optional: true,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"oauth_scopes": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
DiffSuppressFunc: containerClusterAddedScopesSuppress,
ExactlyOneOf: []string{
"cluster_autoscaling.0.auto_provisioning_defaults.0.oauth_scopes",
"cluster_autoscaling.0.auto_provisioning_defaults.0.service_account",
},
},
"service_account": {
Type: schema.TypeString,
Optional: true,
Default: "default",
ExactlyOneOf: []string{
"cluster_autoscaling.0.auto_provisioning_defaults.0.oauth_scopes",
"cluster_autoscaling.0.auto_provisioning_defaults.0.service_account",
},
},
},
},
},
},
},
},
Expand Down Expand Up @@ -762,6 +793,7 @@ func resourceContainerClusterCreate(d *schema.ResourceData, meta interface{}) er
EnableKubernetesAlpha: d.Get("enable_kubernetes_alpha").(bool),
IpAllocationPolicy: expandIPAllocationPolicy(d.Get("ip_allocation_policy")),
PodSecurityPolicyConfig: expandPodSecurityPolicyConfig(d.Get("pod_security_policy_config")),
Autoscaling: expandClusterAutoscaling(d.Get("cluster_autoscaling"), d),
MasterAuth: expandMasterAuth(d.Get("master_auth")),
ResourceLabels: expandStringMap(d, "resource_labels"),
}
Expand Down Expand Up @@ -966,7 +998,7 @@ func resourceContainerClusterRead(d *schema.ResourceData, meta interface{}) erro
d.Set("monitoring_service", cluster.MonitoringService)
d.Set("network", cluster.NetworkConfig.Network)
d.Set("subnetwork", cluster.NetworkConfig.Subnetwork)
if err := d.Set("cluster_autoscaling", nil); err != nil {
if err := d.Set("cluster_autoscaling", flattenClusterAutoscaling(cluster.Autoscaling)); err != nil {
return err
}
if err := d.Set("authenticator_groups_config", flattenAuthenticatorGroupsConfig(cluster.AuthenticatorGroupsConfig)); err != nil {
Expand Down Expand Up @@ -1087,6 +1119,23 @@ func resourceContainerClusterUpdate(d *schema.ResourceData, meta interface{}) er
}
}

if d.HasChange("cluster_autoscaling") {
req := &containerBeta.UpdateClusterRequest{
Update: &containerBeta.ClusterUpdate{
DesiredClusterAutoscaling: expandClusterAutoscaling(d.Get("cluster_autoscaling"), d),
}}

updateF := updateFunc(req, "updating GKE cluster autoscaling")
// Call update serially.
if err := lockedCall(lockKey, updateF); err != nil {
return err
}

log.Printf("[INFO] GKE cluster %s's cluster-wide autoscaling has been updated", d.Id())

d.SetPartial("cluster_autoscaling")
}

if d.HasChange("maintenance_policy") {
req := &containerBeta.SetMaintenancePolicyRequest{
MaintenancePolicy: expandMaintenancePolicy(d, meta),
Expand Down Expand Up @@ -1691,6 +1740,59 @@ func expandMaintenancePolicy(d *schema.ResourceData, meta interface{}) *containe
return nil
}

func expandClusterAutoscaling(configured interface{}, d *schema.ResourceData) *containerBeta.ClusterAutoscaling {
l, ok := configured.([]interface{})
if !ok || l == nil || len(l) == 0 || l[0] == nil {
return &containerBeta.ClusterAutoscaling{
EnableNodeAutoprovisioning: false,
ForceSendFields: []string{"EnableNodeAutoprovisioning"},
}
}

config := l[0].(map[string]interface{})

// Conditionally provide an empty list to preserve a legacy 2.X behaviour
// when `enabled` is false and resource_limits is unset, allowing users to
// explicitly disable the feature. resource_limits don't work when node
// auto-provisioning is disabled at time of writing. This may change API-side
// in the future though, as the feature is intended to apply to both node
// auto-provisioning and node autoscaling.
var resourceLimits []*containerBeta.ResourceLimit
if limits, ok := config["resource_limits"]; ok {
resourceLimits = make([]*containerBeta.ResourceLimit, 0)
if lmts, ok := limits.([]interface{}); ok {
for _, v := range lmts {
limit := v.(map[string]interface{})
resourceLimits = append(resourceLimits,
&containerBeta.ResourceLimit{
ResourceType: limit["resource_type"].(string),
// Here we're relying on *not* setting ForceSendFields for 0-values.
Minimum: int64(limit["minimum"].(int)),
Maximum: int64(limit["maximum"].(int)),
})
}
}
}
return &containerBeta.ClusterAutoscaling{
EnableNodeAutoprovisioning: config["enabled"].(bool),
ResourceLimits: resourceLimits,
AutoprovisioningNodePoolDefaults: expandAutoProvisioningDefaults(config["auto_provisioning_defaults"], d),
}
}

func expandAutoProvisioningDefaults(configured interface{}, d *schema.ResourceData) *containerBeta.AutoprovisioningNodePoolDefaults {
l, ok := configured.([]interface{})
if !ok || l == nil || len(l) == 0 || l[0] == nil {
return &containerBeta.AutoprovisioningNodePoolDefaults{}
}
config := l[0].(map[string]interface{})

return &containerBeta.AutoprovisioningNodePoolDefaults{
OauthScopes: convertStringArr(config["oauth_scopes"].([]interface{})),
ServiceAccount: config["service_account"].(string),
}
}

func expandAuthenticatorGroupsConfig(configured interface{}) *containerBeta.AuthenticatorGroupsConfig {
l := configured.([]interface{})
if len(l) == 0 {
Expand Down Expand Up @@ -1954,6 +2056,34 @@ func flattenMasterAuth(ma *containerBeta.MasterAuth) []map[string]interface{} {
return masterAuth
}

func flattenClusterAutoscaling(a *containerBeta.ClusterAutoscaling) []map[string]interface{} {
r := make(map[string]interface{})
if a == nil || !a.EnableNodeAutoprovisioning {
r["enabled"] = false
} else {
resourceLimits := make([]interface{}, 0, len(a.ResourceLimits))
for _, rl := range a.ResourceLimits {
resourceLimits = append(resourceLimits, map[string]interface{}{
"resource_type": rl.ResourceType,
"minimum": rl.Minimum,
"maximum": rl.Maximum,
})
}
r["resource_limits"] = resourceLimits
r["enabled"] = true
r["auto_provisioning_defaults"] = flattenAutoProvisioningDefaults(a.AutoprovisioningNodePoolDefaults)
}
return []map[string]interface{}{r}
}

func flattenAutoProvisioningDefaults(a *containerBeta.AutoprovisioningNodePoolDefaults) []map[string]interface{} {
r := make(map[string]interface{})
r["oauth_scopes"] = a.OauthScopes
r["service_account"] = a.ServiceAccount

return []map[string]interface{}{r}
}

func flattenMasterAuthorizedNetworksConfig(c *containerBeta.MasterAuthorizedNetworksConfig) []map[string]interface{} {
if c == nil || !c.Enabled {
return nil
Expand Down Expand Up @@ -2031,6 +2161,41 @@ func cidrOrSizeDiffSuppress(k, old, new string, d *schema.ResourceData) bool {
return strings.HasPrefix(new, "/") && strings.HasSuffix(old, new)
}

// Suppress unremovable default scope values from GCP.
// If the default service account would not otherwise have it, the `monitoring.write` scope
// is added to a GKE cluster's scopes regardless of what the user provided.
// monitoring.write is inherited from monitoring (rw) and cloud-platform, so it won't always
// be present.
// Enabling Stackdriver features through logging_service and monitoring_service may enable
// monitoring or logging.write. We've chosen not to suppress in those cases because they're
// removable by disabling those features.
func containerClusterAddedScopesSuppress(k, old, new string, d *schema.ResourceData) bool {
o, n := d.GetChange("cluster_autoscaling.0.auto_provisioning_defaults.0.oauth_scopes")

addedScopes := []string{
"https://www.googleapis.com/auth/monitoring.write",
}

// combine what the default scopes are with what was passed
m := golangSetFromStringSlice(append(addedScopes, convertStringArr(n.([]interface{}))...))
combined := stringSliceFromGolangSet(m)

// compare if the combined new scopes and default scopes differ from the old scopes
if len(combined) != len(convertStringArr(o.([]interface{}))) {
return false
}

for _, i := range combined {
if stringInSlice(convertStringArr(o.([]interface{})), i) {
continue
}

return false
}

return true
}

// We want to suppress diffs for empty/disabled private cluster config.
func containerClusterPrivateClusterConfigSuppress(k, old, new string, d *schema.ResourceData) bool {
o, n := d.GetChange("private_cluster_config.0.enable_private_endpoint")
Expand Down
Loading

0 comments on commit b58ab1d

Please sign in to comment.