Skip to content
This repository has been archived by the owner on Jan 3, 2023. It is now read-only.

kubemci list command: look for relevant global forwarding rules. #91

Merged
merged 1 commit into from
Dec 12, 2017

Conversation

G-Harmon
Copy link
Contributor

@G-Harmon G-Harmon commented Dec 6, 2017

cc @nikhiljindal @csbell @madhusudancs


This change is Reviewable

@k8s-ci-robot
Copy link

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 /ok-to-test on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work. Regular contributors should join the org to skip this step.

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.

@G-Harmon
Copy link
Contributor Author

G-Harmon commented Dec 6, 2017

This can't be merged until kubernetes/ingress-gce#78 is merged,
AND we re-vendor that commit into this repo.

@nikhiljindal
Copy link
Contributor

/ok-to-test

@G-Harmon
Copy link
Contributor Author

G-Harmon commented Dec 6, 2017

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.")
Copy link
Contributor

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?

Copy link
Contributor Author

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 {
Copy link
Contributor

Choose a reason for hiding this comment

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

Copy link
Contributor Author

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
Copy link
Contributor

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)

Copy link
Contributor Author

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")
Copy link
Contributor

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.

Copy link
Contributor Author

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
Copy link
Contributor

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

Copy link
Contributor

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

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 we discussed, done.

t.Fatalf("expected no error in ensuring forwarding rule, actual: %v", err)
}

list, err := frs.ListForwardingRules()
Copy link
Contributor

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

Copy link
Contributor Author

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)
Copy link
Contributor

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

Copy link
Contributor Author

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 {
Copy link
Contributor

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.

Copy link
Contributor Author

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)
Copy link
Contributor

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)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done.

@nikhiljindal
Copy link
Contributor

nikhiljindal commented Dec 9, 2017

Thanks @G-Harmon
looks great, main comment is about who should do formatting for printing.

Also needs rebase with #93

@G-Harmon G-Harmon force-pushed the mciList branch 3 times, most recently from e667b74 to c0505dd Compare December 12, 2017 01:42
@coveralls
Copy link

Coverage Status

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)
Copy link
Contributor

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)
Copy link
Contributor

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?
Copy link
Contributor

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) {
Copy link
Contributor

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.")
Copy link
Contributor

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)
Copy link
Contributor

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)
Copy link
Contributor

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) {
Copy link
Contributor

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)
Copy link
Contributor

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"
Copy link
Contributor

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)?

@G-Harmon
Copy link
Contributor Author

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…

Returned error and printed error should be same?

err = fmt.Errorf("Error getting global forwarding rules: %s", err)
fmt.Println(err)
return err

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…

What do you mean? Filter out nil rules?

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…

Shouldnt we return this error as well?

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…

You meant TestGetForwardingRules?

now it's TestListLoadBalancerStatuses.


app/kubemci/pkg/gcp/forwardingrule/forwardingrulesyncer_test.go, line 139 at r1 (raw file):

Previously, nikhiljindal (Nikhil Jindal) wrote…

"unexpected name, expected: %s, actual: %s"

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…

same as above

Done.


app/kubemci/pkg/gcp/forwardingrule/forwardingrulesyncer_test.go, line 211 at r1 (raw file):

Previously, nikhiljindal (Nikhil Jindal) wrote…

load balancers -> forwarding rules :)

Done.


app/kubemci/pkg/gcp/forwardingrule/forwardingrulesyncer_test.go, line 214 at r1 (raw file):

Previously, nikhiljindal (Nikhil Jindal) wrote…

nit: add space after :

Done.


app/kubemci/pkg/gcp/forwardingrule/interfaces.go, line 32 at r1 (raw file):

Previously, nikhiljindal (Nikhil Jindal) wrote…

How about calling this ListLoadBalancerStatuses?
From GetForwardingRules, I expect it to return compute.ForwardingRule.

yea, done.


app/kubemci/pkg/gcp/loadbalancer/loadbalancersyncer.go, line 223 at r1 (raw file):

Previously, nikhiljindal (Nikhil Jindal) wrote…

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.

Done. makes sense.


app/kubemci/pkg/gcp/loadbalancer/loadbalancersyncer.go, line 225 at r1 (raw file):

Previously, nikhiljindal (Nikhil Jindal) wrote…

call it multicluster ingresses instead of multicluster loadbalancers (since we call them mci's everywhere)?

right :)


app/kubemci/pkg/gcp/loadbalancer/loadbalancersyncer.go, line 227 at r1 (raw file):

Previously, nikhiljindal (Nikhil Jindal) wrote…

unintended?

Done. (removed)


Comments from Reviewable

@coveralls
Copy link

Coverage Status

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?
Copy link
Contributor

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?

Copy link
Contributor Author

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
Copy link
Contributor

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?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done.

@nikhiljindal
Copy link
Contributor

Thanks for the fixes, looks great!
Added 2 comments

@G-Harmon
Copy link
Contributor Author

test failed due to trivial merge conflict. I fixed it and pushed an update.

@coveralls
Copy link

Coverage Status

Changes Unknown when pulling 6dcc5b2 on G-Harmon:mciList into ** on GoogleCloudPlatform:master**.

@nikhiljindal
Copy link
Contributor

/lgtm, thanks!

@nikhiljindal nikhiljindal merged commit 935762c into GoogleCloudPlatform:master Dec 12, 2017
@G-Harmon G-Harmon deleted the mciList branch December 12, 2017 21:21
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.

4 participants