-
Notifications
You must be signed in to change notification settings - Fork 261
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
🐛 loadbalancer: resolve ControlPlaneEndpoint.Host when needed #1738
Conversation
✅ Deploy Preview for kubernetes-sigs-cluster-api-openstack ready!
To edit notification comments on pull requests, go to your Netlify site configuration. |
/assign mdbooth |
134c6ce
to
f4aa951
Compare
/lgtm |
c2428d4
to
1c44a80
Compare
ips, err := lookupHost(openStackCluster.Spec.ControlPlaneEndpoint.Host) | ||
if err != nil { | ||
return false, fmt.Errorf("lookup host: %w", err) | ||
} | ||
fixedIPAddress = ips[0] | ||
if net.ParseIP(fixedIPAddress) == nil { | ||
s.scope.Logger().Info("ControlPlaneEndpoint.Host is not an IP address, using the first resolved IP address", "host", openStackCluster.Spec.ControlPlaneEndpoint.Host, "ip", fixedIPAddress) | ||
} |
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.
This code block feels slightly too long to be duplicated below. Could we DRY this somehow?
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've put it into a constant. Let me know if that works.
@@ -46,16 +47,32 @@ const ( | |||
|
|||
const loadBalancerProvisioningStatusActive = "ACTIVE" | |||
|
|||
// We wrap the net.LookupHost function in a variable to allow overriding it in unit tests. |
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.
Eww, but I don't personally know of a cleaner way to do this. I'll let it pass, but if anybody else knows better... @pierreprinetti maybe?
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 alternative that pops to mind is dependency injection: If ReconcileLoadBalancer
can accept a resolver as an additional argument, I'd inject the resolver from the controller. This lookupHost
woud then be defined inside the controller, rather than being a global var (which can be dangerous). However, my solution doesn't work if you want to unit-test the controller this way.
If that's what you're looking for:
type Resolver func(string) ([]string, error)
func (s *Service) ReconcileLoadBalancer(openStackCluster *infrav1.OpenStackCluster, clusterName string, apiServerPort int, lookupHost Resolver) (bool, error) {
and in openstackcluster_controller.go
:
resolver := func(host string) ([]string, error) {
ctx, cancel := context.WithTimeout(context.TODO(), 30*time.Second)
defer cancel()
return net.DefaultResolver.LookupHost(ctx, host)
}
terminalFailure, err := loadBalancerService.ReconcileLoadBalancer(openStackCluster, clusterName, apiServerPort, resolver)
Not really a game changer.
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.
Thanks Pierre for your analysis. I think the PR is then ready.
@mdbooth are we good now or do you expect me to change something else? |
// | ||
//nolint:gocritic | ||
var lookupHost = func(host string) ([]string, error) { | ||
return net.LookupHost(host) |
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.
A few things here:
This should probably use Resolver.LookupHost() as documented in net.LookupHost(), but we can't because we don't currently pass the context into this ReconcileLoadBalancer. We should most likely also do that.
I seem to recall we have a forcing function coming soon which will require us to use Context everywhere. So we don't miss this one, which isn't obvious without reading the godocs, could we update it to use Resolver.LookupHost anyway and create a context explicitly to pass in?
Secondly, does this have the correct behaviour when given an IP address? Either way, I wonder if we should check if it's an IP address before calling the resolver and just return it.
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.
-
Using
net.DefaultResolver.LookupHost
: I agree, consider it done in the next patchset. -
Does this have the correct behaviour when given an IP address? yes:
// LookupHost looks up the given host using the local resolver.
// It returns a slice of that host's addresses.
func (r *Resolver) LookupHost(ctx context.Context, host string) (addrs []string, err error) {
// Make sure that no matter what we do later, host=="" is rejected.
if host == "" {
return nil, &DNSError{Err: errNoSuchHost.Error(), Name: host, IsNotFound: true}
}
if _, err := netip.ParseAddr(host); err == nil { <----------- HERE
return []string{host}, nil
}
return r.lookupHost(ctx, host)
}
e30cc4c
to
7ccdd65
Compare
can someone review it again please? |
/lgtm |
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.
/approve
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: EmilienM, mdbooth The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
`ControlPlaneEndpoint.Host` is not guaranteed to be an IP address, it can also be an hostname. Now we'll try to lookup the hostname if it's not an IP and set that for the LB VipAddress.
/lgtm |
What this PR does / why we need it:
ControlPlaneEndpoint.Host
is not guaranteed to be an IP address, itcan also be an hostname.
Now we'll try to lookup the hostname if it's not an IP and set that for
the LB VipAddress.
Which issue(s) this PR fixes (optional, in
fixes #<issue number>(, fixes #<issue_number>, ...)
format, will close the issue(s) when PR gets merged):Fixes #1714
Special notes for your reviewer:
Unit tests are tricky. We stub the call to net.LookupHost to avoid actual DNS lookups.