-
Notifications
You must be signed in to change notification settings - Fork 5.1k
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
Substitute hardcoded "<namespace>/<name>" with k8s ListerGetter #3470
Substitute hardcoded "<namespace>/<name>" with k8s ListerGetter #3470
Conversation
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.
LGTM
f0a249a
to
402ef53
Compare
provider/kubernetes/client.go
Outdated
endpoint = item.(*corev1.Endpoints) | ||
endpoint, err := c.factories[c.lookupNamespace(namespace)].Core().V1().Endpoints().Lister().Endpoints(namespace).Get(name) | ||
if err != nil { | ||
return nil, !kubeerror.IsNotFound(err), 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.
IIUC, we will now return a non-nil error even if this is just about a missing object. However, our call site still considers non-nil errors as triggers to end Ingress parsing prematurely and back off as there is some presumed issue with the Kubernetes API connection.
I think we still need to translate not found errors into a nil, false, nil
triple (or move the distinction to the call site).
Similar for other changes you have made.
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 move the distinction to the call site)
In order to narrow the scope of changes, I'd prefer the former solution. 😀
Even though upstream returns not found errors only right now, I'd still implement processing of the return value such that any other, additional error values introduced in the future are handled properly. |
9399736
to
c8b0256
Compare
Agree with that. IMHO, handling error values would be better to be done in the call site. Or just returning double (object, error) would be even better to me🧐 |
Agree to differentiating at the call site as long as we are still able to tell the "not found" and "other error" cases apart where we need to (which is at the point where we decide to either log a warning and continue processing, or log an error and back of). |
provider/kubernetes/client.go
Outdated
if kubeerror.IsNotFound(err) { | ||
return nil, false, nil | ||
} | ||
return nil, false, 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.
You only did the distinction for the endpoints now, but we need it for services and all other objects as well where we eventually treat absence and general errors differently with regards to Ingress processing.
c8b0256
to
0724af9
Compare
provider/kubernetes/client.go
Outdated
@@ -171,15 +172,11 @@ func (c *clientImpl) GetIngresses() []*extensionsv1beta1.Ingress { | |||
func (c *clientImpl) UpdateIngressStatus(namespace, name, ip, hostname string) error { | |||
keyName := namespace + "/" + name | |||
|
|||
item, exists, err := c.factories[c.lookupNamespace(namespace)].Extensions().V1beta1().Ingresses().Informer().GetStore().GetByKey(keyName) | |||
ing, err := c.factories[c.lookupNamespace(namespace)].Extensions().V1beta1().Ingresses().Lister().Ingresses(namespace).Get(name) | |||
if err != nil { | |||
return fmt.Errorf("failed to get ingress %s with error: %v", keyName, 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.
I think we should omit the with error
part now. It used to be necessary to distinguish between the "missing" and "true error" cases, but now the upstream error will include this information.
return service, exists, err | ||
service, err := c.factories[c.lookupNamespace(namespace)].Core().V1().Services().Lister().Services(namespace).Get(name) | ||
exist, err := translateNotFoundError(err) | ||
return service, exist, 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.
What do you think about just doing
return service, translateNotFoundError(err)
here and elsewhere too?
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.
@timoreimann I'm afraid my IDE is not allowing me to do so. Is this syntax supported by golang?
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's not supported
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.
true, my bad.
provider/kubernetes/client.go
Outdated
return false, err | ||
} | ||
return true, 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.
I wonder if this is more or less readable:
func translateNotFoundError(err error) (bool, error) {
if kubeerror.IsNotFound(err) {
return false, nil
}
return err == nil, err
}
WDYT?
provider/kubernetes/client.go
Outdated
return false, err | ||
} | ||
return true, 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.
I think we should add a quick unit test for this function... it's easy to get some boolean wrong while the test should be easy to write.
provider/kubernetes/client_test.go
Outdated
|
||
func TestTranslateNotFoundError(t *testing.T) { | ||
testCases := []struct { | ||
err 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.
could you add desc
and put a description of each case.
provider/kubernetes/client_test.go
Outdated
}, | ||
} | ||
for _, testCase := range testCases { | ||
exists, err := translateNotFoundError(testCase.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.
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
exists, err := translateNotFoundError(test.err)
assert.Equal(t, test.expectedExists, exists)
assert.Equal(t, test.expectedError, err)
})
}
provider/kubernetes/client.go
Outdated
} | ||
log.Infof("Updated status on ingress %s", keyName) | ||
log.Infof("Updated status on ingress %s", namespace+"/"+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.
log.Infof("Updated status on ingress %s/%s", namespace,name)
provider/kubernetes/client.go
Outdated
@@ -192,40 +187,31 @@ func (c *clientImpl) UpdateIngressStatus(namespace, name, ip, hostname string) e | |||
|
|||
_, err = c.clientset.ExtensionsV1beta1().Ingresses(ingCopy.Namespace).UpdateStatus(ingCopy) | |||
if err != nil { | |||
return fmt.Errorf("failed to update ingress status %s with error: %v", keyName, err) | |||
return fmt.Errorf("failed to update ingress status %s: %v", namespace+"/"+name, 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.
return fmt.Errorf("failed to update ingress status %s/%s: %v", namespace, name, err)
provider/kubernetes/client.go
Outdated
} | ||
if !exists { | ||
return fmt.Errorf("failed to update ingress %s because it does not exist", keyName) | ||
return fmt.Errorf("failed to get ingress %s: %v", namespace+"/"+name, 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.
return fmt.Errorf("failed to get ingress %s/%s: %v", namespace, name, err)
provider/kubernetes/client_test.go
Outdated
"github.com/stretchr/testify/assert" | ||
kubeerror "k8s.io/apimachinery/pkg/api/errors" | ||
"k8s.io/apimachinery/pkg/runtime/schema" | ||
"testing" |
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.
import (
"fmt"
"testing"
"github.com/stretchr/testify/assert"
kubeerror "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/runtime/schema"
)
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.
LGTM
e918bf7
to
37b9698
Compare
What does this PR do?
Small refactor for kubernetes provider.
Remove those hardcoded
<namespace>/<name>
index and use common functions ofListerGetter
provided by kubernetes informers. Or developers might get confused by previous code. 🤔Note that according to current implementations of kubernetes informers on master branch which haven't been changed for a long time, the error returned by
ListerGetter
can only be "Not Found" error. So, with this PR, the return value byGetEndpoints
,GetService
,GetSecret
will only be:Motivation
For better human readability
More
Additional Notes