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

Ignore ErrNotFound when delete LB resources #46181

Merged
merged 1 commit into from
Jun 23, 2017

Conversation

FengyunPan
Copy link

IsNotFound error is fine since that means the object is
deleted already, so let's check it before return error.

@k8s-ci-robot k8s-ci-robot added the cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. label May 21, 2017
@k8s-ci-robot
Copy link
Contributor

Hi @FengyunPan. 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 @k8s-bot 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.

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. I understand the commands that are listed here.

@k8s-ci-robot k8s-ci-robot added the needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. label May 21, 2017
@k8s-github-robot k8s-github-robot added size/L Denotes a PR that changes 100-499 lines, ignoring generated files. release-note-label-needed labels May 21, 2017
@FengyunPan
Copy link
Author

/release-note-none

@k8s-ci-robot k8s-ci-robot added release-note-none Denotes a PR that doesn't merit a release note. and removed release-note-label-needed labels May 21, 2017
@@ -140,9 +140,6 @@ func getFloatingIPByPortID(client *gophercloud.ServiceClient, portID string) (*f
return false, err
}
floatingIPList = append(floatingIPList, f...)
if len(floatingIPList) > 1 {
Copy link
Member

Choose a reason for hiding this comment

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

This means the loop might keep going, only to error out later (which is fine and I agree it's an error case not worth optimising for).

Perhaps the final return line (L146) could become:

  return len(floatingIPList) <= 1, nil

And this would achieve the same early-exit-on-multiple-results but with far less visual overhead.


Since this loop is such a common pattern in the openstack provider, an alternative that I've been meaning to do for a while would be to replace the whole lot with some sort of generic code that takes an extraction function (like floatingips.ExtractFloatingIPs), does this generic "build a list, and abort if you get more than one result" logic, and just returns a single (interface{}, error). Again, I wish golang had parameterised types :(

Copy link
Author

Choose a reason for hiding this comment

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

@anguslees Thank for your review very much.
My modify just prevent it from checking {len(floatingIPList) > 1} again, and I see your comment, I will check it in loop and don't check it at line 157.

@@ -285,6 +273,9 @@ func getListenersByLoadBalancerID(client *gophercloud.ServiceClient, id string)
return true, nil
})
if err != nil {
if isNotFound(err) {
Copy link
Member

Choose a reason for hiding this comment

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

What's the benefit of pushing this down here (and similar elsewhere), rather than have the caller use isNotFound(...)? From experience I'm nervous about ensuring that all functions correctly convert Openstack not-found errors into ErrNotFound - we've certainly had places where this was missed in the past.

Copy link
Author

Choose a reason for hiding this comment

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

Yeah, I know it, when len(...) is 0, K8S will return ErrNotFound and caller can't use isNotFound(...). Ennn, I will pick one.

continue
} else {
return nil, fmt.Errorf("Error getting address for node %s: %v", node.Name, err)
if !isNotFound(err) && members != nil {
Copy link
Member

Choose a reason for hiding this comment

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

You have changed this code to separately use both a literal err == ErrNotFound and isNotFound(err). You should pick one :)

I suggest leaving this to use isNotFound() and remove all the places above where you've pushed this logic into the getFooByBar functions - because it's going to be a lot more fragile to rely on everyone returning just the ErrNotFound value.

Copy link
Author

Choose a reason for hiding this comment

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

You are right, I will update it.

return fmt.Errorf("Error getting pool for listener %s: %v", listener.ID, err)
}
if err == ErrNotFound {
// Unknown error, retry later
continue
Copy link
Member

Choose a reason for hiding this comment

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

Will this function be retried if it does not return an error? It's been a while since I read the calling code, but I thought we had to return an error in order to be retried ...

Copy link
Author

Choose a reason for hiding this comment

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

Sorry, this description is incorrect. I will update it.

for _, node := range nodes {
addr, err := nodeAddressForLB(node)
if err != nil {
if err == ErrNoAddressFound {
Copy link
Member

Choose a reason for hiding this comment

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

I think this ErrNotFound -> ErrNoAddressFound and the additional "ignore if not found" check around this foreach-node loop are the behavioural changes in this PR, and the rest is refactoring. Is that correct or did I miss any others?

Copy link
Author

Choose a reason for hiding this comment

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

The nodeAddressForLB() can return ErrNoAddressFound, not ErrNotFound.
I do not know if it is correct, I will check it later.

@NickrenREN
Copy link
Contributor

@anguslees @FengyunPan Maybe we should keep consistent style to define Not Found Err.
Function return or caller check ?

@FengyunPan
Copy link
Author

@NickrenREN Ok.

@FengyunPan FengyunPan force-pushed the ignore-LBnotfound branch 2 times, most recently from 39650d9 to c22b083 Compare May 22, 2017 07:56
return nil, err
}

if len(listenerPools) == 0 {
return nil, ErrNotFound
} else if len(listenerPools) > 1 {
return nil, ErrMultipleResults
Copy link
Contributor

Choose a reason for hiding this comment

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

if len(listenerPools) >1 , do not return err ?

Copy link
Author

Choose a reason for hiding this comment

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

ListenerID is unique, can't get { len(listenerPools) >1}.
The getPoolByListenerID() just return Found or notFound, the check of 'if len(listenerPools) > 1' is useless.

Copy link
Member

Choose a reason for hiding this comment

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

I agree the check should never fire, but I'm nervous about trusting the OpenStack API to always do what we expect :)

On the other hand, I agree these additional checks add visual noise - so I only have a weak preference for keeping them.

Copy link
Author

Choose a reason for hiding this comment

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

Done

continue
} else {
return nil, fmt.Errorf("Error getting address for node %s: %v", node.Name, err)
if !lbaas.IsNotFound(err) && members != nil {
Copy link
Contributor

Choose a reason for hiding this comment

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

Why this ? if members != nil and of course err returned is nil and do we really need this?

Copy link
Author

Choose a reason for hiding this comment

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

You are right, I delete it soon.

@@ -1203,10 +1188,26 @@ func (lbaas *LbaasV2) EnsureLoadBalancerDeleted(clusterName string, service *v1.
return nil
}

func (lbaas *LbaasV2) IsNotFound(err error) bool {
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this needed (and so is the similar function below)?

Copy link
Author

Choose a reason for hiding this comment

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

Yes, caller don't know getxxxx() return ErrNotFound or isNotFound err, we can use IsNotFound() to check err.

Copy link
Member

Choose a reason for hiding this comment

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

Just move this into the real isNotFound() - in fact I thought I had already extended that to check ErrNotFound some time ago, but apparently not...

Copy link
Author

Choose a reason for hiding this comment

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

Done

Copy link
Member

@anguslees anguslees left a comment

Choose a reason for hiding this comment

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

(Thanks for your persistence @FengyunPan :)

@@ -346,13 +323,19 @@ func getMembersByPoolID(client *gophercloud.ServiceClient, id string) ([]v2pools
return false, err
}
members = append(members, membersList...)

if len(members) > 1 {
Copy link
Member

Choose a reason for hiding this comment

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

This particular function is intended to return multiple results - see pluralised name and array return type.

Copy link
Author

Choose a reason for hiding this comment

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

Done

@@ -288,6 +268,10 @@ func getListenersByLoadBalancerID(client *gophercloud.ServiceClient, id string)
return nil, err
}

if len(existingListeners) == 0 {
Copy link
Member

Choose a reason for hiding this comment

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

This function is intended to return a (possibly empty) list of results - ie: I think it's up to the caller to decide if len() == 0 is an error.

Copy link
Author

Choose a reason for hiding this comment

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

Done

return nil, err
}

if len(listenerPools) == 0 {
return nil, ErrNotFound
} else if len(listenerPools) > 1 {
return nil, ErrMultipleResults
Copy link
Member

Choose a reason for hiding this comment

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

I agree the check should never fire, but I'm nervous about trusting the OpenStack API to always do what we expect :)

On the other hand, I agree these additional checks add visual noise - so I only have a weak preference for keeping them.

return true, nil
})
if err != nil {
return nil, err
}

if len(members) == 0 {
Copy link
Member

Choose a reason for hiding this comment

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

Ditto - anything declared as returning a list is fine to return an empty list.

Copy link
Author

Choose a reason for hiding this comment

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

Done

@@ -406,13 +388,19 @@ func getSecurityGroupRules(client *gophercloud.ServiceClient, opts rules.ListOpt
return false, err
}
securityRules = append(securityRules, ruleList...)
if len(securityRules) > 1 {
Copy link
Member

Choose a reason for hiding this comment

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

Same list return comments as above

Copy link
Author

Choose a reason for hiding this comment

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

Done

@@ -1203,10 +1188,26 @@ func (lbaas *LbaasV2) EnsureLoadBalancerDeleted(clusterName string, service *v1.
return nil
}

func (lbaas *LbaasV2) IsNotFound(err error) bool {
Copy link
Member

Choose a reason for hiding this comment

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

Just move this into the real isNotFound() - in fact I thought I had already extended that to check ErrNotFound some time ago, but apparently not...

@k8s-github-robot k8s-github-robot added size/S Denotes a PR that changes 10-29 lines, ignoring generated files. and removed size/L Denotes a PR that changes 100-499 lines, ignoring generated files. labels May 27, 2017
IsNotFound error is fine since that means the object is
deleted already, so let's check it before return error.
@k8s-github-robot k8s-github-robot added size/XS Denotes a PR that changes 0-9 lines, ignoring generated files. and removed size/S Denotes a PR that changes 10-29 lines, ignoring generated files. labels May 27, 2017
@FengyunPan
Copy link
Author

@ anguslees Hi, I keep them and just ignore ErrNotFound when deleting LB resources.

@dims
Copy link
Member

dims commented Jun 1, 2017

@k8s-bot ok to test

@k8s-ci-robot k8s-ci-robot removed the needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. label Jun 1, 2017
@dims
Copy link
Member

dims commented Jun 1, 2017

/assign

@dims
Copy link
Member

dims commented Jun 1, 2017

/lgtm

@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Jun 1, 2017
@dims
Copy link
Member

dims commented Jun 1, 2017

@k8s-bot pull-kubernetes-federation-e2e-gce test this

@fejta
Copy link
Contributor

fejta commented Jun 1, 2017

@k8s-bot pull-kubernetes-federation-e2e-gce test this
ref kubernetes/test-infra#2931

@fejta
Copy link
Contributor

fejta commented Jun 1, 2017

@k8s-bot pull-kubernetes-federation-e2e-gce test this

@NickrenREN
Copy link
Contributor

@k8s-bot pull-kubernetes-kubemark-e2e-gce test this
@k8s-bot pull-kubernetes-federation-e2e-gce test this

@NickrenREN
Copy link
Contributor

/approve

@k8s-github-robot k8s-github-robot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Jun 2, 2017
@FengyunPan
Copy link
Author

@k8s-bot pull-kubernetes-federation-e2e-gce test this

@k8s-github-robot k8s-github-robot removed the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Jun 5, 2017
@wojtek-t
Copy link
Member

wojtek-t commented Jun 6, 2017

/approve no issue

@wojtek-t
Copy link
Member

wojtek-t commented Jun 6, 2017

/approve no-issue

@k8s-github-robot
Copy link

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: FengyunPan, NickrenREN, dims, wojtek-t

Associated issue requirement bypassed by: wojtek-t

The full list of commands accepted by this bot can be found here.

Needs approval from an approver in each of these OWNERS Files:

You can indicate your approval by writing /approve in a comment
You can cancel your approval by writing /approve cancel in a comment

@k8s-github-robot k8s-github-robot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Jun 6, 2017
@FengyunPan
Copy link
Author

@k8s-bot pull-kubernetes-federation-e2e-gce test this
@k8s-bot pull-kubernetes-e2e-gce-etcd3 test this

@FengyunPan
Copy link
Author

/test pull-kubernetes-federation-e2e-gce

@k8s-github-robot
Copy link

Automatic merge from submit-queue

@k8s-github-robot k8s-github-robot merged commit 72cb080 into kubernetes:master Jun 23, 2017
dims pushed a commit to dims/kubernetes that referenced this pull request Feb 8, 2018
Automatic merge from submit-queue

Ignore ErrNotFound when delete LB resources

IsNotFound error is fine since that means the object is
deleted already, so let's check it before return error.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved Indicates a PR has been approved by an approver from all required OWNERS files. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. lgtm "Looks good to me", indicates that a PR is ready to be merged. release-note-none Denotes a PR that doesn't merit a release note. size/XS Denotes a PR that changes 0-9 lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

8 participants