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

kv: Ignore backend servers with no url #1196

Merged
merged 4 commits into from Apr 6, 2017
Merged

kv: Ignore backend servers with no url #1196

merged 4 commits into from Apr 6, 2017

Conversation

klausenbusk
Copy link
Contributor

Currently with a kv tree like:
/traefik/backends/b1/servers/ẁeb1
/traefik/backends/b1/servers/web2
/traefik/backends/b1/servers/web2/url
Traefik would try to forward traffic to web1, which is impossible as
traefik doesn't know the url of web1.

This commit solve that, by ignoring backend server with no url "key"
when generating the config.

This is very useful, for people who use etcd TTL feature. They can then
just "renew" the url key every X second, and if the server goes down, it
is automatic removed from traefik after the TTL.

Copy link
Contributor

@timoreimann timoreimann left a comment

Choose a reason for hiding this comment

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

Could we have a quick test please? :)

provider/kv.go Outdated
@@ -162,6 +162,9 @@ func (provider *Kv) list(keys ...string) []string {
func (provider *Kv) listServers(backend string) []string {
serverNames := provider.list(backend, "/servers/")
return fun.Filter(func(serverName string) bool {
if _, err := provider.kvclient.Get(fmt.Sprint(serverName, "/url")); 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.

First time getting in touch with our k/v store interfaces and libkv in general, so behold. :-)

Looking at https://godoc.org/github.com/docker/libkv/store#pkg-variables, it seems like we should be able to distinguish between ErrKeyNotFound and other errors. If that's feasible, I think we should at least log unexpected errors.

WDYT?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If that's feasible, I think we should at least log unexpected errors.

Yes, that is properly best. Something like log.Debugf("Unexpected error %s", err)? or what do you think the error sentence should be? Naming stuff and so on is hard :)

Could we have a quick test please? :)

Of course, should be pretty straight forward. :)

Copy link
Contributor

Choose a reason for hiding this comment

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

Re: error message: I'd use something like:

log.Errorf("Failed to retrieve value for key %s: %s", key, err)

key can be an extracted variable because we might need it up to two times (once for the Get and then again for the error message).

@klausenbusk
Copy link
Contributor Author

@timoreimann could you take a look now?

@klausenbusk
Copy link
Contributor Author

Rebased

{
Key: "traefik/backends/backend.with.dot.too/servers/server.with.dot.without.url/weight",
Value: []byte("0"),
},
Copy link
Contributor

Choose a reason for hiding this comment

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

Shouldn't we also have added a test where we encounter a "true" error and make sure we filter?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Can you elaborate a bit? I'm not sure what you mean.

Copy link
Contributor

Choose a reason for hiding this comment

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

In the new production code, we have added two paths: One where we encounter a "not found" error and another one where we encounter a critical, "true" error. Both paths should do the same, which is to return false.

You have changed the mock to return the "not found" error if Get cannot find a given key among the configured ones. That's great because there's now also a test case to execute that path. However, for the "true" error path to happen, we'd need to configure the mock to return an error by another test case. However, I don't see any new test case with the error switch being set.

So I'm thinking that we might be missing a test case here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hmm, I'm not sure how it can/should be implemented. We can't rely on the Mock Error bool, as that cause List to error out.

I think we need to crate our own KVPair type with a error "field", but that seems kind of messy. Do you have a simpler idea?

Copy link
Contributor

Choose a reason for hiding this comment

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

I'd change the Mock struct to separate the currently single error into one for Get and one for List calls. We'll then have to adjust all tests that test error cases, but I think it's worth it: We have to improve our test coverage in the future anyway, and more fine-grained error distinctions are most likely going to be needed.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'd change the Mock struct to separate the currently single error into one for Get and one for List calls.

Done, see last commit. I will look on a listServers test when I get some more time.

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

@timoreimann timoreimann left a comment

Choose a reason for hiding this comment

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

One test still missing, but I think this is good enough for now.

LGTM.

Copy link
Member

@emilevauge emilevauge left a comment

Choose a reason for hiding this comment

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

Thanks @klausenbusk
LGTM

Currently with a kv tree like:
/traefik/backends/b1/servers/ẁeb1
/traefik/backends/b1/servers/web2
/traefik/backends/b1/servers/web2/url
Traefik would try to forward traffic to web1, which is impossible as
traefik doesn't know the url of web1.

This commit solve that, by ignoring backend server with no url "key"
when generating the config.

This is very useful, for people who use etcd TTL feature. They can then
just "renew" the url key every X second, and if the server goes down, it
is automatic removed from traefik after the TTL.
@emilevauge emilevauge added this to the 1.3 milestone Apr 6, 2017
@emilevauge emilevauge merged commit e1aa16a into traefik:master Apr 6, 2017
@ldez ldez added the kind/enhancement a new or improved feature. label Apr 29, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/provider/kv kind/enhancement a new or improved feature.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants