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

feat(gce): Add GCP internal http(s) load balancer. #4725

Merged
merged 10 commits into from
Aug 7, 2020

Conversation

takaaki7
Copy link
Contributor

@takaaki7 takaaki7 commented Jul 7, 2020

Added GCP Internal HTTP(S) load balancer support. spinnaker/spinnaker#5042
PR for deck: spinnaker/deck#8397

Many parts are copy and pasted from HTTP Load Balancer implementation.
Differences are:

  • It is regional
  • It has a network and subnet
  • It doesn't have legacy http(s) health checks
  • etc

@spinnakerbot
Copy link
Contributor

We prefer that non-test backend code be written in Java or Kotlin, rather than Groovy. The following files have been added and written in Groovy:

  • clouddriver-google/src/main/groovy/com/netflix/spinnaker/clouddriver/google/deploy/ops/loadbalancer/DeleteGoogleInternalHttpLoadBalancerAtomicOperation.groovy

  • clouddriver-google/src/main/groovy/com/netflix/spinnaker/clouddriver/google/deploy/ops/loadbalancer/UpsertGoogleInternalHttpLoadBalancerAtomicOperation.groovy

  • clouddriver-google/src/main/groovy/com/netflix/spinnaker/clouddriver/google/model/loadbalancing/GoogleInternalHttpLoadBalancer.groovy

  • clouddriver-google/src/main/groovy/com/netflix/spinnaker/clouddriver/google/provider/agent/GoogleInternalHttpLoadBalancerCachingAgent.groovy

See our server-side commit conventions here.

@takaaki7 takaaki7 changed the title Add GCP internal http(s) load balancer. feat(gce): Add GCP internal http(s) load balancer. Jul 7, 2020
@maggieneterval
Copy link
Contributor

@takaaki7 Let's hold off on merging the corresponding Deck PR until this PR is merged. Per @spinnakerbot's comment, could you please ensure that any new files are added in Java rather than Groovy before we review this? Would be great if @plumpy could take a look as well since he is most familiar with the Clouddriver GCE implementation. 🙏 🍡

@takaaki7
Copy link
Contributor Author

takaaki7 commented Jul 8, 2020

Thanks for comment! I'll fix it.

@plumpy plumpy self-requested a review July 9, 2020 12:56
@takaaki7
Copy link
Contributor Author

takaaki7 commented Jul 9, 2020

I converted groovy to Java. @plumpy Could you review this?

Actually I just want deployment feature of internal http lb for my project. No need Upsert,Delete feature because I can manage loadbalancers by terraform.

And I noticed, this PR might be split into two part. (deploy and Upser, Delete)

If PR for only deployment feature is acceptable (and if merging this large PR is hard), I'll try to split.

@@ -220,7 +221,7 @@ class GoogleClusterProvider implements ClusterProvider<GoogleCluster.View> {
serverGroupData.each { CacheData serverGroupCacheData ->
GoogleServerGroup serverGroup = serverGroupFromCacheData(serverGroupCacheData, clusterView.accountName, instances, securityGroups, loadBalancers)
clusterView.serverGroups << serverGroup.view
clusterView.loadBalancers.addAll(serverGroup.loadBalancers*.view)
clusterView.loadBalancers.addAll(serverGroup.loadBalancers)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Referencing nonexistent property GoogleLoadBalancerView.view.
Using java, this line causes exception.

@takaaki7
Copy link
Contributor Author

How is the progress?

@plumpy
Copy link
Member

plumpy commented Jul 13, 2020

Sorry for the delay, but the PR build is failing because of a Groovy compilation error, so I was waiting for that to be resolved before I looked at it... if you don't know how to fix it, I can try to figure it out, I guess...

It's going to take me a little bit to review this since it's quite a lot of code and I don't know much about the internal HTTP load balancers, so I'll need to research and play around with those, but I'm hoping to get to it this week.

@takaaki7
Copy link
Contributor Author

I was waiting for that to be resolved before I looked at it...

Oh, sorry for that.

I looked at it but I couldn't figure it out...
I can run ./gradlew -PenableCrossCompilerPlugin=true build on local machine without error.

And the line causing the error seems no problem for me..
import com.netflix.spinnaker.clouddriver.security.ProviderVersion;

I’d like to ask you for your help.

@maggieneterval
Copy link
Contributor

@takaaki7 ProviderVersion was recently deprecated and removed. I'll add a comment inline where you need to remove this.

@takaaki7
Copy link
Contributor Author

Is it going to take a little longer? I know this PR is large, so I can consider different approach if prefered. But I want to hear your opinion at first.

Copy link
Member

@plumpy plumpy left a comment

Choose a reason for hiding this comment

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

Sorry this is taking so long. This code is just so messy that it's hard to understand what's going on. (The existing GCE code, not your changes.) I'm trying to focus mostly on the parts that will affect users who aren't using internal HTTP load balancers, to make sure this doesn't cause any new bugs for them.

I really appreciate you sending this PR and I'm sorry I'm taking so long to get it reviewed. I'll make sure we get it wrapped up and submitted next week.

@@ -488,7 +492,7 @@ class BasicGoogleDeployHandler implements DeployHandler<BasicGoogleDeployDescrip
.setTargetPools(targetPools)
.setAutoHealingPolicies(autoHealingPolicy)

if (hasBackendServices && (description?.loadBalancingPolicy || description?.source?.serverGroupName)) {
if (!internalLoadBalancers && (description?.loadBalancingPolicy || description?.source?.serverGroupName)) {
Copy link
Member

Choose a reason for hiding this comment

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

I'm curious about this change... it feels significant and risky, but it's hard to figure out what's happening in the middle of a 500-line method, with a variable defined 300 lines away 😨 Can you explain what this change does?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

As it's written, lbs that isn't internal (= external http/tcp/ssl , and internal HTTP) requires namedPorts handling.
Because hasBackendServices is false when internal HTTP loadbalancers exists, now it's not appropriate here. (hasBackendServices should be renamed to hasGlobalBackendServices)

This condition can be written as following way to reduce the change impact, but I think it's not clean.
if ((hasBackendServices || internalHttpLoadBalancers) && (description?.loadBalancingPolicy || description?.source?.serverGroupName))

Copy link
Member

Choose a reason for hiding this comment

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

Thanks for the explanation! Isn't it possible that we have internalLoadBalancers and tcpLoadsBalancers (i.e. two types of load balancers for this server group)? In which case we need to configure the named ports, but as it's written here we won't?

Copy link
Contributor Author

@takaaki7 takaaki7 Aug 7, 2020

Choose a reason for hiding this comment

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

Wow that's right.

  • fix

Copy link
Member

@plumpy plumpy left a comment

Choose a reason for hiding this comment

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

Okay, I think this is all I have, nothing very major.

Thanks again for doing all this work, just clean up these smallish things and then I'll happily merge it. I really appreciate you doing this work (especially since you didn't even need all of it). 🍡

Comment on lines 27 to 28
@ToString(includeSuper = true)
@groovy.transform.EqualsAndHashCode(callSuper = true)
Copy link
Member

Choose a reason for hiding this comment

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

You can replace these with lombok:

Suggested change
@ToString(includeSuper = true)
@groovy.transform.EqualsAndHashCode(callSuper = true)
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)

Then:

  1. mark type and loadBalancingScheme as final
  2. delete all the getters and setters (except getView)

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 for detailed instruction! It's very helpful.

return new InternalHttpLbView();
}

@EqualsAndHashCode(callSuper = false)
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
@EqualsAndHashCode(callSuper = false)
@Value
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)

Then delete the serverGroups field and all the methods.

import static com.netflix.spinnaker.clouddriver.google.deploy.GCEUtil.GLOBAL_LOAD_BALANCER_NAMES;
import static com.netflix.spinnaker.clouddriver.google.deploy.GCEUtil.LOAD_BALANCING_POLICY;
import static com.netflix.spinnaker.clouddriver.google.deploy.GCEUtil.REGIONAL_LOAD_BALANCER_NAMES;
import static com.netflix.spinnaker.clouddriver.google.deploy.GCEUtil.*;
Copy link
Member

Choose a reason for hiding this comment

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

don't use wildcard imports

healthCheckUrls.addAll(backendService.getHealthChecks());
}

DefaultGroovyMethods.unique(healthCheckUrls);
Copy link
Member

Choose a reason for hiding this comment

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

Probably you can just make healthCheckUrls into a Set?

if (healthCheck.getTcpHealthCheck() != null) {
port = healthCheck.getTcpHealthCheck().getPort();
hcType = GoogleHealthCheck.HealthCheckType.TCP;
} else if (DefaultGroovyMethods.asBoolean(healthCheck.getSslHealthCheck())) {
Copy link
Member

Choose a reason for hiding this comment

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

All these DefaultGroovyMethods.asBoolean can just be != null, right?

@takaaki7
Copy link
Contributor Author

takaaki7 commented Aug 7, 2020

I've addressed your comments.

@plumpy
Copy link
Member

plumpy commented Aug 7, 2020

Thanks again, I appreciate your contribution! And sorry again for the long delay...

@plumpy plumpy added the ready to merge Approved and ready for a merge label Aug 7, 2020
@mergify mergify bot added the auto merged Merged automatically by a bot label Aug 7, 2020
@mergify mergify bot merged commit a34b951 into spinnaker:master Aug 7, 2020
@takaaki7
Copy link
Contributor Author

takaaki7 commented Aug 8, 2020

Thank you for merging! When will this feature be released?

@maggieneterval
Copy link
Contributor

The next release is Spinnaker 1.22, for which the branches will be cut next week. You can subscribe to the Spinnaker release calendar or #spinnaker-releases Slack channel to see upcoming releases, and can also check the target-release label that spinnakerbot adds to PRs to determine for which release they're slated. Thanks!

@takaaki7
Copy link
Contributor Author

I see, thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
auto merged Merged automatically by a bot ready to merge Approved and ready for a merge target-release/1.22
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants