-
Notifications
You must be signed in to change notification settings - Fork 68
kubemci list command: look for relevant global forwarding rules. #91
Conversation
Hi @G-Harmon. Thanks for your PR. I'm waiting for a kubernetes member to verify that this patch is reasonable to test. If it is, they should reply with I understand the commands that are listed here. Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. |
This can't be merged until kubernetes/ingress-gce#78 is merged, |
/ok-to-test |
The test failure is expected here, since it doesn't have the updates I made to ingress-gce. |
@@ -67,3 +68,8 @@ func (f *FakeForwardingRuleSyncer) GetLoadBalancerStatus(lbName string) (*status | |||
} | |||
return nil, fmt.Errorf("load balancer %s does not exist", lbName) | |||
} | |||
|
|||
func (f *FakeForwardingRuleSyncer) ListForwardingRules() (string, error) { | |||
glog.Errorf("ListForwardingRules not implemented.") |
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.
Add a TODO to implement it?
Or just return the list of load balancer names from EnsuredForwardingRules?
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.
done. (implemented)
return "[No loadbalancers found]", nil | ||
} | ||
var result string = "List of multicluster loadbalancers created:\nName; IP; Clusters\n" | ||
for _, item := range rules.Items { |
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.
not in this PR, but eventually we should reuse kubectl printers: https://github.com/kubernetes/kubernetes/blob/44f24d219f9d28121eb1f16863312f790e144882/pkg/printers/printers.go#L123:13
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.
added a TODO.
var result string = "List of multicluster loadbalancers created:\nName; IP; Clusters\n" | ||
for _, item := range rules.Items { | ||
if strings.HasPrefix(item.Name, "mci1") { | ||
result += "Name: " + item.Name |
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 will print the forwarding rule name. User will expect to see the load balancer name (what they can use with create, delete, get-status)
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.
done!
|
||
} | ||
} | ||
result = strings.Trim(result, "\n") |
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.
It can still happen that there were forwarding rules in the project, but none with mci1 prefix.
The output for no forwarding rules and that should be same.
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.
good point, done.
if lbStatus, err := status.FromString(item.Description); err != nil { | ||
fmt.Println("Error decoding load balancer status:", err) | ||
} else { | ||
result += "\tIP: " + lbStatus.IPAddress |
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 would suggest splitting this into 2 methods:
- One that lists the forwarding rules, checks the prefix, parses status and computes the list.
- Second that formats the given list for printing. This can later be replaced by directly calling kubectl printer.
This will enable easy unit testing of the first method
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.
Also to clarify, the public method will still be one - which will call these 2 private members
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 we discussed, done.
t.Fatalf("expected no error in ensuring forwarding rule, actual: %v", err) | ||
} | ||
|
||
list, err := frs.ListForwardingRules() |
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.
If we split the code as suggested above, I would love to see more test cases such as:
- No forwarding rule exists
- Forwarding rules exist but none with the right prefix
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.
okay, I added those 2 test cases.
@@ -383,7 +387,7 @@ PortLoop: | |||
} | |||
|
|||
if port == nil { | |||
return ingressbe.ServicePort{}, fmt.Errorf("could not find matching nodeport for backend %v and service %s/%s. Looking for port %v in %v", be, namespace, be.ServiceName, be.ServicePort, svc.Spec.Ports) | |||
return ingressbe.ServicePort{}, fmt.Errorf("Could not find matching nodeport for backend %+v and service %s/%s. Looking for port %+v in %v", be, namespace, be.ServiceName, be.ServicePort, svc.Spec.Ports) |
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.
Libraries are supposed to return errors starting with smaller case so that the caller can prepend context
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.
ah, I didn't realize. done.
func (s *ForwardingRuleSyncer) ListForwardingRules() (string, error) { | ||
var rules *compute.ForwardingRuleList | ||
var err error | ||
if rules, err = s.frp.ListGlobalForwardingRules(); err != nil { |
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.
Depending on which PR goes in first, we will need to update this to handle HTTPS ingresses.
HTTPS ingresses create 2 forwarding rules: one for HTTP and one for HTTPS.
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.
okay, added a TODO! let's see which one goes first.
@@ -28,4 +28,6 @@ type ForwardingRuleSyncerInterface interface { | |||
DeleteForwardingRules() error | |||
// GetLoadBalancerStatus returns the struct describing the status of the given load balancer. | |||
GetLoadBalancerStatus(lbName string) (*status.LoadBalancerStatus, error) | |||
// ListForwardingRules returns all forwarding rules used by MCI. | |||
ListForwardingRules() (string, error) |
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.
Comparing it with GetLoadBalancerStatus, I see that this assumes that the result is to be printed and hence formats it for printing. GetLoadBalancerStatus, on the other hand, just returns structured data and then its upto the caller on how to use it.
Wondering if we should do the same here?
(am still thinking about it, so feel free to push back or discuss before making changes)
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.
done.
e667b74
to
c0505dd
Compare
Changes Unknown when pulling c0505dd on G-Harmon:mciList into ** on GoogleCloudPlatform:master**. |
for _, item := range rules.Items { | ||
if strings.HasPrefix(item.Name, "mci1") { | ||
if lbStatus, err := status.FromString(item.Description); err != nil { | ||
fmt.Println("Error decoding load balancer status:", err) |
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.
Shouldnt we return this error as well?
result := []status.LoadBalancerStatus{} | ||
// TODO: When we have HTTPS ingresses, check for those as well. | ||
if rules, err = s.frp.ListGlobalForwardingRules(); err != nil { | ||
fmt.Println("Error getting global forwarding rules:", err) |
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.
Returned error and printed error should be same?
err = fmt.Errorf("Error getting global forwarding rules: %s", err)
fmt.Println(err)
return err
fmt.Println("Error getting global forwarding rules:", err) | ||
return result, err | ||
} | ||
// TODO: Should we check for nil rules? |
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.
What do you mean? Filter out nil rules?
@@ -115,6 +115,106 @@ func TestEnsureHttpForwardingRule(t *testing.T) { | |||
} | |||
} | |||
|
|||
func TestListLoadBalancers(t *testing.T) { |
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 meant TestGetForwardingRules?
} | ||
for _, rule := range list { | ||
if rule.LoadBalancerName != lbName { | ||
t.Errorf("Bad name.") |
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.
"unexpected name, expected: %s, actual: %s"
t.Errorf("unexpected error listing load balancers:%v", err) | ||
} | ||
if len(list) != 0 { | ||
t.Errorf("Expected no fowarding rules. Actual:%v", list) |
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: add space after :
@@ -28,4 +28,6 @@ type ForwardingRuleSyncerInterface interface { | |||
DeleteForwardingRules() error | |||
// GetLoadBalancerStatus returns the struct describing the status of the given load balancer. | |||
GetLoadBalancerStatus(lbName string) (*status.LoadBalancerStatus, error) | |||
// GetForwardingRules returns all forwarding rules used by MCI. | |||
GetForwardingRules() ([]status.LoadBalancerStatus, error) |
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.
How about calling this ListLoadBalancerStatuses?
From GetForwardingRules, I expect it to return compute.ForwardingRule.
@@ -219,6 +220,29 @@ func (l *LoadBalancerSyncer) PrintStatus() (string, error) { | |||
return fmt.Sprintf("Load balancer %s has IPAddress %s and is spread across %d clusters (%s)", l.lbName, sd.IPAddress, len(sd.Clusters), strings.Join(sd.Clusters, ",")), nil | |||
} | |||
|
|||
func formatForwardingRules(rules []status.LoadBalancerStatus) (string, error) { |
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.
how about calling this formatLoadBalancersList? This method does not know that load balancer statuses came from forwarding rules and hence should have nothing to do with forwarding rules.
// TODO: Should reuse printers in kubernetes/pkg/printers/printers.go | ||
var result string = "List of multicluster loadbalancers created:\nName; IP; Clusters\n" | ||
for _, lbStatus := range rules { | ||
fmt.Println("name:", lbStatus.LoadBalancerName) |
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.
unintended?
@@ -219,6 +220,29 @@ func (l *LoadBalancerSyncer) PrintStatus() (string, error) { | |||
return fmt.Sprintf("Load balancer %s has IPAddress %s and is spread across %d clusters (%s)", l.lbName, sd.IPAddress, len(sd.Clusters), strings.Join(sd.Clusters, ",")), nil | |||
} | |||
|
|||
func formatForwardingRules(rules []status.LoadBalancerStatus) (string, error) { | |||
// TODO: Should reuse printers in kubernetes/pkg/printers/printers.go | |||
var result string = "List of multicluster loadbalancers created:\nName; IP; Clusters\n" |
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.
call it multicluster ingresses instead of multicluster loadbalancers (since we call them mci's everywhere)?
PTAL. sorry it was a little messy, I was a bit rushed last night. I wanted to get your review comments, so thanks for looking at it! Review status: 0 of 10 files reviewed at latest revision, 12 unresolved discussions. app/kubemci/pkg/gcp/forwardingrule/forwardingrulesyncer.go, line 133 at r1 (raw file): Previously, nikhiljindal (Nikhil Jindal) wrote…
I kind of go back and forth on this point, but I think you're right. (The only downside is that we will likely print the exact same error twice. That's probably better than printing 2 slightly different messages for the same problem.) app/kubemci/pkg/gcp/forwardingrule/forwardingrulesyncer.go, line 136 at r1 (raw file): Previously, nikhiljindal (Nikhil Jindal) wrote…
When I first started using the Fake, I had the Fake's ListGlobalForwardingRules returning nil. That crashed this code. I haven't seen a nil return from the real one. app/kubemci/pkg/gcp/forwardingrule/forwardingrulesyncer.go, line 141 at r1 (raw file): Previously, nikhiljindal (Nikhil Jindal) wrote…
sure. (I was thinking better to get partial status than none.) Now I return "result" and the error. Is that an okay pattern? app/kubemci/pkg/gcp/forwardingrule/forwardingrulesyncer_test.go, line 118 at r1 (raw file): Previously, nikhiljindal (Nikhil Jindal) wrote…
now it's TestListLoadBalancerStatuses. app/kubemci/pkg/gcp/forwardingrule/forwardingrulesyncer_test.go, line 139 at r1 (raw file): Previously, nikhiljindal (Nikhil Jindal) wrote…
oops, I meant to come back to these Errorfs, but forgot! Done. app/kubemci/pkg/gcp/forwardingrule/forwardingrulesyncer_test.go, line 142 at r1 (raw file): Previously, nikhiljindal (Nikhil Jindal) wrote…
Done. app/kubemci/pkg/gcp/forwardingrule/forwardingrulesyncer_test.go, line 211 at r1 (raw file): Previously, nikhiljindal (Nikhil Jindal) wrote…
Done. app/kubemci/pkg/gcp/forwardingrule/forwardingrulesyncer_test.go, line 214 at r1 (raw file): Previously, nikhiljindal (Nikhil Jindal) wrote…
Done. app/kubemci/pkg/gcp/forwardingrule/interfaces.go, line 32 at r1 (raw file): Previously, nikhiljindal (Nikhil Jindal) wrote…
yea, done. app/kubemci/pkg/gcp/loadbalancer/loadbalancersyncer.go, line 223 at r1 (raw file): Previously, nikhiljindal (Nikhil Jindal) wrote…
Done. makes sense. app/kubemci/pkg/gcp/loadbalancer/loadbalancersyncer.go, line 225 at r1 (raw file): Previously, nikhiljindal (Nikhil Jindal) wrote…
right :) app/kubemci/pkg/gcp/loadbalancer/loadbalancersyncer.go, line 227 at r1 (raw file): Previously, nikhiljindal (Nikhil Jindal) wrote…
Done. (removed) Comments from Reviewable |
Changes Unknown when pulling 58c3812 on G-Harmon:mciList into ** on GoogleCloudPlatform:master**. |
fmt.Println(err) | ||
return result, err | ||
} | ||
// TODO: Should we check for nil rules? |
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 would say there is no harm in being extra cautious and checking for nil.
Add a check or remove the TODO?
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.
done.
if lbStatus, err := status.FromString(item.Description); err != nil { | ||
err = fmt.Errorf("Error decoding load balancer status: %s", err) | ||
fmt.Println(err) | ||
return result, err |
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.
How about aggregating the errors and returning all of them together?
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.
done.
Thanks for the fixes, looks great! |
test failed due to trivial merge conflict. I fixed it and pushed an update. |
Changes Unknown when pulling 6dcc5b2 on G-Harmon:mciList into ** on GoogleCloudPlatform:master**. |
/lgtm, thanks! |
cc @nikhiljindal @csbell @madhusudancs
This change is