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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Substitute hardcoded "<namespace>/<name>" with k8s ListerGetter #3470

Merged

Conversation

yue9944882
Copy link
Contributor

@yue9944882 yue9944882 commented Jun 11, 2018

What does this PR do?

Small refactor for kubernetes provider.

Remove those hardcoded <namespace>/<name> index and use common functions of ListerGetter 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 by GetEndpoints,GetService,GetSecret will only be:

  • Endpoints/Service/Secret, true, nil
  • nil, false, "Not Found Error"

Motivation

For better human readability

More

  • Added/updated tests
  • Added/updated documentation

Additional Notes

Copy link
Contributor

@dtomcej dtomcej left a comment

Choose a reason for hiding this comment

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

LGTM
:shipit:

@yue9944882 yue9944882 force-pushed the chore-listergetter-funcs-to-get-resource branch from f0a249a to 402ef53 Compare June 11, 2018 18:12
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
Copy link
Contributor

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.

Copy link
Contributor Author

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. 馃榾

@timoreimann
Copy link
Contributor

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.

@yue9944882 yue9944882 force-pushed the chore-listergetter-funcs-to-get-resource branch from 9399736 to c8b0256 Compare June 22, 2018 09:17
@yue9944882
Copy link
Contributor Author

yue9944882 commented Jun 22, 2018

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.

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馃

@timoreimann
Copy link
Contributor

timoreimann commented Jun 22, 2018

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.

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

if kubeerror.IsNotFound(err) {
return nil, false, nil
}
return nil, false, err
Copy link
Contributor

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.

@yue9944882 yue9944882 force-pushed the chore-listergetter-funcs-to-get-resource branch from c8b0256 to 0724af9 Compare June 24, 2018 13:13
@mmatur mmatur added this to the 1.7 milestone Jul 2, 2018
@@ -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)
Copy link
Contributor

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
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 think about just doing

return service, translateNotFoundError(err)

here and elsewhere too?

Copy link
Contributor Author

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?

Copy link
Member

Choose a reason for hiding this comment

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

it's not supported

Copy link
Contributor

Choose a reason for hiding this comment

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

true, my bad.

return false, err
}
return true, nil
}
Copy link
Contributor

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?

return false, err
}
return true, nil
}
Copy link
Contributor

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.


func TestTranslateNotFoundError(t *testing.T) {
testCases := []struct {
err error
Copy link
Member

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.

},
}
for _, testCase := range testCases {
exists, err := translateNotFoundError(testCase.err)
Copy link
Member

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

}
log.Infof("Updated status on ingress %s", keyName)
log.Infof("Updated status on ingress %s", namespace+"/"+name)
Copy link
Member

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)

@@ -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)
Copy link
Member

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)

}
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)
Copy link
Member

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)

"github.com/stretchr/testify/assert"
kubeerror "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/runtime/schema"
"testing"
Copy link
Member

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

Copy link
Member

@ldez ldez left a comment

Choose a reason for hiding this comment

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

LGTM

@traefiker traefiker force-pushed the chore-listergetter-funcs-to-get-resource branch from e918bf7 to 37b9698 Compare July 4, 2018 14:46
@traefiker traefiker merged commit b1f1a5b into traefik:master Jul 4, 2018
@ldez ldez changed the title Substitude hardcoded "<namespace>/<name>" with k8s ListerGetter Substitute hardcoded "<namespace>/<name>" with k8s ListerGetter Mar 31, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants