Skip to content
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 master authorized networks in google_container_cluster #626

Merged

Conversation

davidquarles
Copy link
Contributor

@davidquarles davidquarles commented Oct 24, 2017

Fixes #619.

  • Update container/v1 API (handled independently in Update container/v1 API #624)
  • Add support for master_authorized_networks in google_container_cluster
$ make testacc TEST=./google TESTARGS='-run=TestAccContainerCluster_withMasterAuthorizedNetworks'
==> Checking that code complies with gofmt requirements...
TF_ACC=1 go test ./google -v -run=TestAccContainerCluster_withMasterAuthorizedNetworks -timeout 120m
=== RUN   TestAccContainerCluster_withMasterAuthorizedNetworksConfig
--- PASS: TestAccContainerCluster_withMasterAuthorizedNetworksConfig (390.52s)
PASS
ok  	github.com/terraform-providers/terraform-provider-google/google	390.539s

@davidquarles davidquarles force-pushed the master-authorized-networks branch from b09279c to f299bbf Compare October 24, 2017 11:13
Schema: map[string]*schema.Schema{
"enabled": {
Type: schema.TypeBool,
Required: true,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wasn't entirely sure what made sense here for Optional / Computed / Required / Default. In the end, Required: true made the most sense to me, but only marginally so. I'll test upstream for implicit requirements/defaults tomorrow.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd actually recommend not having an enabled field at all, and instead just relying on the presence of any master_authorized_networks_configs to determine what that value should be, similar to how we do autoscaling. The reason for this is that when enabled is false, GCP won't return anything for cidrBlocks:

"masterAuthorizedNetworksConfig": {},

This means that a config like this:

  master_authorized_networks_config {
    enabled     = false
    cidr_blocks = ["172.16.0.0/12", "10.0.0.0/8"]
  }

is equivalent to:

  master_authorized_networks_config {
    enabled     = false
  }

Because we want to set the state based on what's actually true in GCP, the state will always resemble the second config above, and thus planning immediately after applying with the first config will show a diff.

"But wait!" you might ask, "I added a test for the enabled=false case and it passed!" Ah yes, and this tripped me up for a while too. I'll explain in a comment below.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Totally, I almost did that, but wasn't sure and opted for mimicking the API. I'll follow that pattern elsewhere.

@danawillow danawillow self-requested a review October 26, 2017 22:12
@davidquarles davidquarles force-pushed the master-authorized-networks branch 2 times, most recently from 17745c1 to 49c51bc Compare October 31, 2017 00:05
@davidquarles
Copy link
Contributor Author

the two failures below happen on master as well. I'm guessing this is a known issue?

$ make testacc TEST=./google TESTARGS='-run=TestAccContainerCluster'
==> Checking that code complies with gofmt requirements...
TF_ACC=1 go test ./google -v -run=TestAccContainerCluster -timeout 120m
=== RUN   TestAccContainerCluster_import
=== RUN   TestAccContainerCluster_basic
=== RUN   TestAccContainerCluster_withTimeout
=== RUN   TestAccContainerCluster_withAddons
=== RUN   TestAccContainerCluster_withMasterAuth
=== RUN   TestAccContainerCluster_withMasterAuthorizedNetworksConfig
=== RUN   TestAccContainerCluster_withAdditionalZones
=== RUN   TestAccContainerCluster_withLegacyAbac
=== RUN   TestAccContainerCluster_withVersion
=== RUN   TestAccContainerCluster_updateVersion
=== RUN   TestAccContainerCluster_withNodeConfig
=== RUN   TestAccContainerCluster_withNodeConfigScopeAlias
=== RUN   TestAccContainerCluster_network
=== RUN   TestAccContainerCluster_backend
=== RUN   TestAccContainerCluster_withLogging
=== RUN   TestAccContainerCluster_withMonitoring
=== RUN   TestAccContainerCluster_withNodePoolBasic
=== RUN   TestAccContainerCluster_withNodePoolResize
=== RUN   TestAccContainerCluster_withNodePoolAutoscaling
=== RUN   TestAccContainerCluster_withNodePoolNamePrefix
=== RUN   TestAccContainerCluster_withNodePoolMultiple
=== RUN   TestAccContainerCluster_withNodePoolConflictingNameFields
=== RUN   TestAccContainerCluster_withNodePoolNodeConfig
--- PASS: TestAccContainerCluster_withVersion (358.25s)
--- PASS: TestAccContainerCluster_withNodePoolNodeConfig (406.36s)
--- PASS: TestAccContainerCluster_withNodeConfigScopeAlias (408.32s)
--- PASS: TestAccContainerCluster_import (478.31s)
--- PASS: TestAccContainerCluster_withAdditionalZones (483.29s)
--- PASS: TestAccContainerCluster_withLegacyAbac (625.03s)
--- FAIL: TestAccContainerCluster_network (714.98s)
	testing.go:494: Error destroying resource! WARNING: Dangling resources
		may exist. The full state and error is shown below.

		Error: Error applying: 1 error(s) occurred:

		* google_compute_network.container_network (destroy): 1 error(s) occurred:

		* google_compute_network.container_network: Error waiting for Deleting Network: timeout while waiting for state to become 'DONE' (last state: 'RUNNING', timeout: 4m0s)

		State: google_compute_network.container_network:
		  ID = container-net-izw2yl82rx
		  auto_create_subnetworks = true
		  gateway_ipv4 =
		  name = container-net-izw2yl82rx
		  self_link = https://www.googleapis.com/compute/v1/projects/nordstrom-k8s/global/networks/container-net-izw2yl82rx
--- PASS: TestAccContainerCluster_withNodePoolConflictingNameFields (559.19s)
--- PASS: TestAccContainerCluster_updateVersion (933.94s)
--- PASS: TestAccContainerCluster_withNodePoolNamePrefix (526.78s)
--- FAIL: TestAccContainerCluster_withNodePoolMultiple (529.43s)
	testing.go:434: Step 0 error: Check failed: Check 1/1 error: Cluster has mismatched node_pool.1.node_config.0.oauth_scopes[0].
		TF State:
		GCP State: https://www.googleapis.com/auth/logging.write
--- PASS: TestAccContainerCluster_withNodeConfig (345.72s)
--- PASS: TestAccContainerCluster_withNodePoolBasic (417.79s)
--- PASS: TestAccContainerCluster_withNodePoolResize (663.22s)
--- PASS: TestAccContainerCluster_withNodePoolAutoscaling (834.72s)
--- PASS: TestAccContainerCluster_basic (356.24s)
--- PASS: TestAccContainerCluster_backend (392.66s)
--- PASS: TestAccContainerCluster_withTimeout (395.95s)
--- PASS: TestAccContainerCluster_withMasterAuth (406.47s)
--- PASS: TestAccContainerCluster_withLogging (615.11s)
--- PASS: TestAccContainerCluster_withMonitoring (645.08s)
--- PASS: TestAccContainerCluster_withMasterAuthorizedNetworksConfig (418.33s)
--- PASS: TestAccContainerCluster_withAddons (584.49s)
FAIL
exit status 1
FAIL	github.com/terraform-providers/terraform-provider-google/google	1897.568s
make: *** [testacc] Error 1

Optional: true,
Computed: true,
ForceNew: true,
ValidateFunc: validation.CIDRNetwork(11, 19),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where did the numbers 11 and 19 come from? (I want to make sure we don't break any existing configs with this change)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call – I was extrapolating API-level constraints based on my experience with the console/UI, which requires a mask in that range, but now that I'm hitting the API directly, you're right -- it doesn't seem to be a thing! RFC1918 is a strict requirement here, though, and I added logic specifically to validate this attribute against those ranges, then lost it on rebase. I'll add it back + remove this constraint.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Optional: true,
Computed: true,
MaxItems: 10,
Elem: &schema.Schema{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you think anyone would want to set the displayName field inside of cidr block?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For sure, I'll add that now.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Schema: map[string]*schema.Schema{
"enabled": {
Type: schema.TypeBool,
Required: true,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd actually recommend not having an enabled field at all, and instead just relying on the presence of any master_authorized_networks_configs to determine what that value should be, similar to how we do autoscaling. The reason for this is that when enabled is false, GCP won't return anything for cidrBlocks:

"masterAuthorizedNetworksConfig": {},

This means that a config like this:

  master_authorized_networks_config {
    enabled     = false
    cidr_blocks = ["172.16.0.0/12", "10.0.0.0/8"]
  }

is equivalent to:

  master_authorized_networks_config {
    enabled     = false
  }

Because we want to set the state based on what's actually true in GCP, the state will always resemble the second config above, and thus planning immediately after applying with the first config will show a diff.

"But wait!" you might ask, "I added a test for the enabled=false case and it passed!" Ah yes, and this tripped me up for a while too. I'll explain in a comment below.

result := []map[string]interface{}{
map[string]interface{}{
"enabled": c.Enabled,
"cidr_blocks": cidrBlocks,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Turns out, if flattenMasterAuthorizedNetworksConfig returns something that looks like this:

result: [map[enabled:false cidr_blocks:[]]]

d.Set will actually return an error: Invalid address to set: []string{"master_authorized_networks_config", "0", "cidr_blocks"} This is fairly cryptic, but it basically just means that you can't set an empty slice in config, you have to just set no slice at all.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hrmmmmm, alright. I'll add that as a test case, too.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@@ -514,6 +536,30 @@ func resourceContainerClusterUpdate(d *schema.ResourceData, meta interface{}) er

d.Partial(true)

if d.HasChange("master_authorized_networks_config") {
if c, ok := d.GetOk("master_authorized_networks_config"); ok {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This means that if a user removes the master_authorized_networks_config block from their config, nothing actually changes. Is that intentional? I'd assume it would remove the configuration.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That was definitely not intentional, and is now fixed.

@davidquarles davidquarles force-pushed the master-authorized-networks branch 2 times, most recently from af411e0 to b362224 Compare November 1, 2017 09:03
@davidquarles
Copy link
Contributor Author

@danawillow I worked through your comments, and left this second round of changes is in a separate commit for now. I can squash/rebase once everything's ready to merge.

Do you think it makes sense to collapse the schema a bit, as below? I've basically translated the upstream structure, and the result feels a bit verbose to me. I know how painful backwards compatibility issues can be, though. I'll defer to you.

resource "google_container_cluster" "foo" {
    master_authorized_network {
        cidr_block = "1.2.3.4/32"
    }
    master_authorized_network {
        cidr_block = "5.6.7.8/32"
    }
}

Test output:

$ make testacc TEST=./google TESTARGS='-run=TestAccContainerCluster_withMasterAuthorized'
==> Checking that code complies with gofmt requirements...
TF_ACC=1 go test ./google -v -run=TestAccContainerCluster_withMasterAuthorized -timeout 120m
=== RUN   TestAccContainerCluster_withMasterAuthorizedNetworksConfig
--- PASS: TestAccContainerCluster_withMasterAuthorizedNetworksConfig (390.30s)
PASS
ok  	github.com/terraform-providers/terraform-provider-google/google	390.340s

@@ -31,3 +39,25 @@ func validateRegexp(re string) schema.SchemaValidateFunc {
return
}
}

func validateRFC1918Network(min, max int) schema.SchemaValidateFunc {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This validation has enough logic in it that I wouldn't mind seeing a unit test.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.


master_authorized_networks_config {
%s
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: indentation

Config: testAccContainerCluster_withMasterAuthorizedNetworksConfig(clusterName, []string{"8.8.8.8/32"}),
Check: resource.ComposeTestCheckFunc(
testAccCheckContainerCluster("google_container_cluster.with_master_authorized_networks"),
resource.TestCheckNoResourceAttr("google_container_cluster.with_master_authorized_networks",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you want to check that the block is there though, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right. Fixed.

"display_name": v.DisplayName,
})
}
// now does this adhere to the schema?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not quite sure what this comment is for

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, that definitely wasn't supposed to make it in. 😺

@danawillow
Copy link
Contributor

I'm fine with the schema as-is.

Also feel free to just always do separate commits- I default to "squash and merge" for the final merge :)

- remove `google_container_cluster.master_authorized_networks_config.enabled`
- add `display_name` and restructure schema as follows:
    master_authorized_networks_config {
        cidr_blocks {
            cidr_block   = "0.0.0.0/0"
            display_name = "foo"
        }
    }
- amend tests
@davidquarles davidquarles force-pushed the master-authorized-networks branch from b362224 to edd19a7 Compare November 2, 2017 08:43
@danawillow
Copy link
Contributor

$ make testacc TEST=./google TESTARGS='-run=TestAccContainerCluster_withMasterAuthorizedN'
==> Checking that code complies with gofmt requirements...
TF_ACC=1 go test ./google -v -run=TestAccContainerCluster_withMasterAuthorizedN -timeout 120m
=== RUN   TestAccContainerCluster_withMasterAuthorizedNetworksConfig
--- PASS: TestAccContainerCluster_withMasterAuthorizedNetworksConfig (404.72s)
PASS
ok  	github.com/terraform-providers/terraform-provider-google/google	404.944s
$ make testacc TEST=./google TESTARGS='-run=TestValidateRFC'
==> Checking that code complies with gofmt requirements...
TF_ACC=1 go test ./google -v -run=TestValidateRFC -timeout 120m
=== RUN   TestValidateRFC1918Network
--- PASS: TestValidateRFC1918Network (0.00s)
PASS
ok  	github.com/terraform-providers/terraform-provider-google/google	0.201s

Thanks @davidquarles! Looks good!

@danawillow danawillow merged commit ca7551c into hashicorp:master Nov 2, 2017
chrisst pushed a commit to chrisst/terraform-provider-google that referenced this pull request Nov 9, 2018
…er` (hashicorp#626)

* Add support for master authorized networks in `google_container_cluster`

* [review] remove enabled flag / restructure schema

- remove `google_container_cluster.master_authorized_networks_config.enabled`
- add `display_name` and restructure schema as follows:
    master_authorized_networks_config {
        cidr_blocks {
            cidr_block   = "0.0.0.0/0"
            display_name = "foo"
        }
    }
- amend tests

* [review] add test for validateRFC1918Network, fix acc test
luis-silva pushed a commit to luis-silva/terraform-provider-google that referenced this pull request May 21, 2019
Signed-off-by: Modular Magician <magic-modules@google.com>
@ghost
Copy link

ghost commented Mar 30, 2020

I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues.

If you feel this issue should be reopened, we encourage creating a new issue linking back to this one for added context. If you feel I made an error 🤖 🙉 , please reach out to my human friends 👉 hashibot-feedback@hashicorp.com. Thanks!

@ghost ghost locked and limited conversation to collaborators Mar 30, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add support for master authorized networks to google_container_cluster
2 participants