-
Notifications
You must be signed in to change notification settings - Fork 260
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
🐛 Don't make unnecessary REST API calls in getServerNetworks #994
🐛 Don't make unnecessary REST API calls in getServerNetworks #994
Conversation
✔️ Deploy Preview for kubernetes-sigs-cluster-api-openstack ready! 🔨 Explore the source changes: 357e525 🔍 Inspect the deploy log: https://app.netlify.com/sites/kubernetes-sigs-cluster-api-openstack/deploys/614b3c00a8f3b70008f6f850 😎 Browse the preview: https://deploy-preview-994--kubernetes-sigs-cluster-api-openstack.netlify.app |
5007a9b
to
85fe929
Compare
// Don't lookup subnet if it was specified explicitly by UUID | ||
if subnet.UUID != "" { | ||
addSubnet(netID, subnet.UUID) | ||
continue |
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.
nit pick, IMO continue is just a more confusing way to write if {} else {}, but its a very minor nit pick
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.
Yeah. Sometimes it's worth it if the following block is longer, but I agree an else block would have been clearer here.
I'll change this if I have to update the patch for any other reason.
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 updated this.
overall, LGTM. Really appreciate the tests to cover this code. |
for _, subnet := range networkParam.Subnets { | ||
// Don't lookup subnet if it was specified explicitly by UUID | ||
if subnet.UUID != "" { | ||
addSubnet(netID, subnet.UUID) |
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 think you should validate if netID
is also not an empty string.
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.
Or don't we need the network ID here, as the subnet ID is sufficient?
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.
You are right. There are 2 ways we can go here:
- Fetch the subnet and therefore the network
- Return a validation error
I'm inclined to return the error as this is most efficiently fixed by the caller.
/hold
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.
Thinking out loud:
Q: How is this different to specifying a subnet filter without a network?
A: A UUID implies the caller already has the details of a specific resource. We are already trusting the caller if they specify a UUID (we use it without further validation): they will get a server create error instead if it was incorrect.
IOW if the caller specifies a network or subnet by UUID, we are explicitly delegating the validation of those UUIDs to the caller. If the caller specifies a filter we execute it for them and let them know if something was wrong (i.e. it was empty).
Is that a good enough argument? If so, should we codify it in the docs?
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 think your assumption is correct. We should also document this behavior, I agree.
We don't have to make any code changes then. But it might be helpful to add a small comment. WDYT?
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. I will:
- update to return a validation here. If it's not sufficiently obvious from the validation error I'll also add a comment.
- add a unit test to cover this error.
- try to find some documentation to update.
On the last point, I want to make the following explicit in the docs:
- The controller will not validate an explicit network or subnet UUID.
- An invalid network or subnet UUID will result in a server create error.
- When specifying subnet UUID, network UUID must also be specified.
1e51cf8
to
82780b2
Compare
/hold cancel |
That looks much better! Thanks :) /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.
The test cases are exhaustive so I can see what's going on and the implementation looks good to me. It's also useful from the tests to see that when specifying UUIDs for networks explicitly, then no OpenStack calls are made. (I expect if UUID is incorrect, then we fail at getOrCreatePort time.)
Something I was reminded of: when a network has multiple subnets and we choose that network with a filter that matches multiple subnets, we end up with a port on every subnet of that network, which is a little bit surprising to me, but it's the way this has always worked. It's good to see the tests cover that too.
UUID string `json:"uuid,omitempty"` | ||
|
||
// Filters for optional network query | ||
// Filters for optional subnet query |
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.
So you can search for a subnet by ID (your use case), you just have to do it in the SubnetFilter. Makes sense.
t.Errorf("Service.getServerNetworks() error = %+v, wantErr %+v", err, tt.wantErr) | ||
return | ||
} | ||
if !reflect.DeepEqual(got, tt.want) { |
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.
Minor point / nit: I've noticed the tests don't use Gomega for pattern matching.
The Cluster API book suggests we should use Gomega for testing (https://cluster-api.sigs.k8s.io/developer/testing.html#gomega):
In Cluster API all the test MUST use Gomega assertions.
You get a bit nicer output on errors if you use Gomega. An example of how to use Gomega for matching test assertions is here:
cluster-api-provider-openstack/pkg/cloud/services/networking/floatingip_test.go
Lines 83 to 84 in 6aa7494
g.Expect(err).ShouldNot(HaveOccurred()) | |
g.Expect(got).To(Equal(tt.want)) |
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.
As it's trivial and MUST is in caps I updated it.
When specifying a subnet filter without a network filter we would first execute a network list with no filter, which returns all networks, then execute the subnet filter for each network. With this change we: * Don't filter subnets by network if there is no network filter * Don't execute a network query if we have a network uuid * Don't execute a subnet query if we have a subnet uuid The changes to unit tests are: * Don't expect gophercloud calls which we no longer make * "Subnet without network" now returns subnets instead of error
82780b2
to
357e525
Compare
/test all |
/lgtm |
lgtm |
/approve |
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: hidekazuna, macaptain, 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 |
What this PR does / why we need it:
If we specify a network with a subnet filter but no network filter, we now execute a single subnet query rather than executing one for every network. We also no longer execute queries at all when the user has specified a uuid explicitly.
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 #993
Special notes for your reviewer:
This PR is intentionally structured in 2 commits:
The first adds unit tests for getServerNetworks (ironically using the excellent work in #935, which also happened to be the commit which introduced the regression). The second fixes getServerNetworks and makes the necessary changes to the unit tests.
The purpose of doing this is to highlight functional changes introduced by the second commit. These can be clearly seen in the unit test changes:
Apart from the target case, we can see that the output of the test cases are unaffected.