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 regional GKE clusters in google_container_cluster #1181

Merged

Conversation

ashish-amarnath
Copy link
Contributor

This is a work in progress PR.
An initial set of changes to share and get feedback on the approach.

Copy link
Contributor

@danawillow danawillow left a comment

Choose a reason for hiding this comment

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

Thanks @ashish-amarnath for taking on this feature! Here are some initial comments.

@@ -393,7 +412,13 @@ func resourceContainerCluster() *schema.Resource {
}

func resourceContainerClusterCreate(d *schema.ResourceData, meta interface{}) error {
containerApiVersion := getContainerApiVersion(d, ContainerClusterBaseApiVersion, ContainerClusterVersionedFeatures)
_, isRegionalCluster := d.GetOk("region")
if isRegionalCluster {
Copy link
Contributor

Choose a reason for hiding this comment

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

This block isn't necessary- you can just add the feature to the var as defined at the top of the file. The name of it should be the name of the field in the schema, so "region"

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Got it! Thanks.

@@ -447,19 +472,35 @@ func resourceContainerClusterCreate(d *schema.ResourceData, meta interface{}) er
}

if v, ok := d.GetOk("additional_zones"); ok {
if isRegionalCluster {
return fmt.Errorf("'additional_zones' is incompatible with regional clusters")
Copy link
Contributor

Choose a reason for hiding this comment

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

This should be doable with ConflictsWith in the schema

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thank you. That should simplify this.

Elem: &schema.Schema{Type: schema.TypeString},
},

"num_nodes": {
Copy link
Contributor

Choose a reason for hiding this comment

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

This doesn't seem to get used anywhere

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 see that this is not a new field added to support regional clusters. So this is not relevant to this PR. Removing this. But we'll have to add this later.

}
}
locations = append(locations, zoneName)
cluster.Locations = locations
}

if isRegionalCluster {
locations := []string{}
locations = append(locations, d.Get("region").(string))
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 the locations field is still supposed to be just a list of zones- this will likely still work without this entire block (and the node_locations field)

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 see that this is not a new field added to support regional clusters. So this is not relevant to this PR. Removing this. But we'll have to add this later. As additional_zones is getting deprecated.

@@ -797,7 +797,7 @@ func flattenPreemptibleInstanceGroupConfig(d *schema.ResourceData, icg *dataproc
func flattenInstanceGroupConfig(d *schema.ResourceData, icg *dataproc.InstanceGroupConfig) []map[string]interface{} {
disk := map[string]interface{}{}
data := map[string]interface{}{
//"instance_names": []string{},
//"instance_names": []string{},
Copy link
Contributor

Choose a reason for hiding this comment

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

this can be reverted, it's not really relevant here

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Reverted.

@ashish-amarnath
Copy link
Contributor Author

@danawillow I took another stab at this and I need some help to update the vendor/google.golang.org/api/container/v1beta1/container-gen.go file with a field for region and also use the right API to create regional clusters so that the unit test can pass.

@danawillow
Copy link
Contributor

The API as it is in the vendor directory should work. Instead of .Projects.Zones you'll want.Projects.Locations and then call the API as documented at https://cloud.google.com/kubernetes-engine/docs/reference/rest/v1beta1/projects.locations.clusters/create
(actual code at https://github.com/terraform-providers/terraform-provider-google/blob/master/vendor/google.golang.org/api/container/v1beta1/container-gen.go#L3623)

@ashish-amarnath
Copy link
Contributor Author

Thanks for those pointers. I should be able to make more progress with this.

@ashish-amarnath ashish-amarnath force-pushed the gke-regional-clusters-support branch from fc3d5d8 to d7734e6 Compare March 20, 2018 23:49
@ashish-amarnath
Copy link
Contributor Author

The test is now able to create regional GKE clusters.
POST /v1beta1/projects/nordstrom-k8s-dev/locations/us-central1/clusters?alt=json HTTP/1.1 Host: container.googleapis.com User-Agent: google-api-go-client/0.5 (darwin amd64) Terraform/0.11.3-dev Content-Length: 464 Content-Type: application/json Accept-Encoding: gzip
this request is successful. The test however, still fails when trying to
---[ REQUEST ]--------------------------------------- GET /v1/projects/nordstrom-k8s-dev/zones//operations/operation-1521589157203-edadd8b8?alt=json HTTP/1.1 Host: container.googleapis.com User-Agent: google-api-go-client/0.5 (darwin amd64) Terraform/0.11.3-dev Accept-Encoding: gzip

This is most likely because the support is only implemented to create regional clusters but not to update, read or destroy. Next step: Make this work!

@Stono
Copy link

Stono commented Mar 21, 2018

@ashish-amarnath I just wanted to say thanks for your efforts with this, I don't know enough golang to help out with the implementation but if i (we - people on my team) can help with testing in any way just ask

@ashish-amarnath
Copy link
Contributor Author

@Stono Thanks for offering to help! I will surely ask for help validating this change. Right now I am trying to a checkpoint where this is can spin-up and teardown regional clusters. This is not the top priority for us right now so I am trying to backfill my time working on this. For that reason, and my unfamiliarity with this codebase are the reasons for the slow progress. I am not blocked. @danawillow has been super helpful in unblocking me :)

@ashish-amarnath
Copy link
Contributor Author

ashish-amarnath commented Mar 22, 2018

Made more progress on this. I now have code and unit test to successfully create and destroy regional GKE clusters. Next, I need to work on the Update operation and then there are merge conflicts that I have to resolve, of course.

@ashish-amarnath ashish-amarnath force-pushed the gke-regional-clusters-support branch 4 times, most recently from 47050ab to 6d1bc50 Compare March 23, 2018 05:34
@ashish-amarnath
Copy link
Contributor Author

@danawillow this PR is ready for more feedback. I need to add some more tests. Suggestions are welcome :)
@Stono Feel free to take a look and make comments.

if err != nil {
return err

if isRegionalCluster {
Copy link
Contributor

Choose a reason for hiding this comment

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

Since the location could also be the zone, I don't think we actually need this conditional- it should be fine to just always do the Projects.Locations call

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 made sense. But didn't what that change to have unknown side-effects. I will give that a try.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed.

}

cluster := &containerBeta.Cluster{}
var clust interface{}
Copy link
Contributor

Choose a reason for hiding this comment

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

Did this work for you when you tested it? I've tried this approach (just doing the Convert from an interface at the end) in the past and it failed for me because Convert needed the parameter passed to be a struct of a certain type (so it can recurse through the fields).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Well.. It compiled right and the tests passed. From that, I figured it works. Any other tests I can run to be doubly sure?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@danawillow What did you to break this? I'd like to make sure this will not break later.

Copy link
Contributor

Choose a reason for hiding this comment

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

Looks like it works! I must have done something slightly differently when I tried doing it this way in the past.

switch containerAPIVersion {
case v1:
op, err = config.clientContainer.Projects.Zones.Clusters.Update(
project, zoneName, clusterName, req).Do()
Copy link
Contributor

Choose a reason for hiding this comment

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

This change makes me nervous- it feels a bit brittle to me to have this depending on what the value of req is at the time this function gets called. If you'd like to refactor it out, I think wrapping it in another function that takes in req as a parameter and returns this func would be a safer choice.

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 agree. For that exact reason, I tried going the function route but quickly realised that that number of args to that function became too many and that made me a little uncomfortable. That function would need config, project, zone, region, isRegionalCluster, request, clusterName, timeout, apiVersion.
Total of 9 args. But, collapsing zone and region into location that number could go down to 8.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah yeah, I was more just thinking that only req would be the parameter since it's the only thing that would change between requests.

@@ -1001,15 +1031,33 @@ func resourceContainerClusterUpdate(d *schema.ResourceData, meta interface{}) er
}

updateF := func() error {
log.Println("[DEBUG] emilyye updating enable_legacy_abac")
op, err := config.clientContainer.Projects.Zones.Clusters.LegacyAbac(project, zoneName, clusterName, req).Do()
log.Println("[DEBUG] updating enable_legacy_abac")
Copy link
Contributor

Choose a reason for hiding this comment

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

thanks :)

Steps: []resource.TestStep{
{
Config: testAccContainerCluster_regional(clusterName),
},
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you add another test step that does an import? There are a bunch of examples elsewhere in this file.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Will do.

var zoneName string
locations := []string{}
regionName, isRegionalCluster := d.GetOk("region")
if !isRegionalCluster {
Copy link
Contributor

Choose a reason for hiding this comment

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

Here's an idea- what if instead of separate "region" and "zone" fields, we just had a "location" field? Then once regional clusters have gone GA we can deprecate zone. I'm not totally set on this, but it does seem like it would simplify the logic. What do you think?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thought about that. But because that would increase the surface area of this change I decided against it. I'll do this if that is not too bad. If that makes sense :)

Copy link
Contributor

Choose a reason for hiding this comment

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

Yup, that's fair. I do think that having it as two separate fields probably makes it a bit clearer to users what to put, so I'm fine with that.

@ashish-amarnath ashish-amarnath force-pushed the gke-regional-clusters-support branch from 8e4f9c7 to fc27105 Compare March 23, 2018 22:49
@ashish-amarnath
Copy link
Contributor Author

I've had other things taking up my time and haven't had a chance to work on this for a while. Just so you don't think I've vanished off the face of the Earth!

@Stono
Copy link

Stono commented Apr 3, 2018

Hey,
If there is anything we can do to help progress this please let us know!

@drubin
Copy link
Contributor

drubin commented Apr 3, 2018

@ashish-amarnath @danawillow Thanks for all the hard work on this.

I am very interested in this PR but since there is no upgrade path from zone-based clusters to regional ones and I have to set up a few clusters in the near future, I am curious what might be the best approach to take in terms of getting them into terraform after?

I see 2 options.

  1. Use the branch in its current state and hope we don't make breaking changes to the state management, (this looks pretty stable but I don't think this is a great option)
  2. Hope we get a release in the next 2 weeks? (This also feels wrong any thing could happen)
  3. Create the regional clusters with gcloud CLI and hopefully import them later?

Any recommendations or even timelines? Even if this was merged how often does the provider get released? Or do you need any help testing this?

@danawillow
Copy link
Contributor

@ashish-amarnath, I think there were just a few small changes that were remaining, right? I don't mind making them and pushing them to your branch if you're all right with that. Seems like people are pretty eager for this :)

@drubin, we usually aim to release every 2 weeks or so, with one aimed for the next few days. So if this gets in today it'll be in the next release, if not probably not. Even though I think the schema for this is set, I'm also pretty hesitant about solution 1. If this doesn't make it into the next release, then I think solution 3 will be totally fine.

* implement operation wait for v1beta1 api
* implement container clusters get for regional clusters
* implement container clusters delete for regional cluster
* implement container clusters update for regional cluster
* simplify logic by using generic 'location' instead of 'zone' and 'region'
* implement a method to generate the update function and refactor
* rebase and fix
@ashish-amarnath ashish-amarnath force-pushed the gke-regional-clusters-support branch from fc27105 to 1e1ace0 Compare April 3, 2018 23:23
@ashish-amarnath
Copy link
Contributor Author

I haven't had the time to pick-up where I left off on this.
@danawillow If you want to pick this up I would totally be OK with it. I don't want to hold this up for everyone. The last bit that was left on this was adding a test step that does an import. I remember taking an initial stab at it but somewhere while executing the test it would fail trying to use a v1 API to access the test cluster. I had to figure out where and why and then fix it.

@danawillow danawillow changed the title [WIP] Add support for regional GKE clusters in google_container_cluster Add support for regional GKE clusters in google_container_cluster Apr 4, 2018
@danawillow danawillow requested a review from rosbo April 5, 2018 01:01
@danawillow
Copy link
Contributor

hey @rosbo, since the changes I made are non-trivial I wouldn't mind having you look at this as well if you don't mind

Copy link
Contributor

@rosbo rosbo left a comment

Choose a reason for hiding this comment

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

Only one small comment.

locations = append(locations, location)
if location == zoneName {
return fmt.Errorf("additional_zones should not contain the original 'zone'.")
loc := v.(string)
Copy link
Contributor

Choose a reason for hiding this comment

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

Consider simplifying this by using convertStringSet and schema.Set#Contains.

Also I am not sure why we have this block below:

if isZone(location) {
   locations = append(locations, location)
}

Why are we adding the "main" zone to the list of additional zones... Consider adding a comment to clarify this.

@danawillow danawillow merged commit f488a6e into hashicorp:master Apr 5, 2018
@ashish-amarnath ashish-amarnath deleted the gke-regional-clusters-support branch April 10, 2018 18:05
chrisst pushed a commit to chrisst/terraform-provider-google that referenced this pull request Nov 9, 2018
…shicorp#1181)

* Add support for regional GKE clusters in google_container_cluster:

* implement operation wait for v1beta1 api
* implement container clusters get for regional clusters
* implement container clusters delete for regional cluster
* implement container clusters update for regional cluster
* simplify logic by using generic 'location' instead of 'zone' and 'region'
* implement a method to generate the update function and refactor
* rebase and fix

* reorder container_operation fns

* cleanup

* add import support and docs

* additional locations cleanup
@ghost
Copy link

ghost commented Nov 19, 2018

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 👉 [email protected]. Thanks!

@ghost ghost locked and limited conversation to collaborators Nov 19, 2018
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.

5 participants