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

Allow overriding the port used for healthchecks #1567

Merged
merged 1 commit into from
May 19, 2017

Conversation

bakins
Copy link
Contributor

@bakins bakins commented May 9, 2017

Some services use a different port for auxiliary functions such as healthchecks and metrics. Traefik itself does this. This PR allows overriding the port used per backend.

@ldez ldez added the kind/enhancement a new or improved feature. label May 9, 2017
}
u.Path = u.Path + backend.Path

req := &http.Request{
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm inclined to say we should just call http.NewRequest to be on the safe side, especially if more fields are added over time that might be important for us but would likely be left behind.

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.

It seems inefficient to me to start with a URL, convert it to a string, and then have NewRequest parse it back into a URL. In this code path, it probably doesn't matter. I can change to NewRequest.

Copy link
Contributor

Choose a reason for hiding this comment

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

(I saw you made the change.)

Yeah it seems a bit cumbersome; personally though, I'd like to err on the side of safety and stability.

Path: "/path",
Interval: healthCheckInterval,
LB: lb,
for _, withPort := range []bool{false, true} {
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think we need to test all permutations here. I suggest we write a test for the newly created newRequest method instead where we won't need to jump through as many hoops (as we do in this test).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That makes sense. I'll just write a test for newRequest.

@bakins
Copy link
Contributor Author

bakins commented May 9, 2017

@timoreimann I've made the requested changes. PTAL when you have a chance.

Thanks for the feedback!

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.

Thanks -- some more comments.

resp, err := client.Get(serverURL.String() + backend.Path)
req, err := backend.newRequest(serverURL)
if err != nil {
return false
Copy link
Contributor

Choose a reason for hiding this comment

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

Could you please add a log message here. I'm inclined to say it should be of level ERROR since we should apparently only run into this case if we have a logic error in our code.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure.

}

for _, test := range tests {
backend := NewBackendHealthCheck(
Copy link
Contributor

Choose a reason for hiding this comment

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

Please use parallelized sub-tests here. See one of the existing tests for what needs to be changed for this (in a nutshell:

  • test := test
  • t.Run(...)
  • t.Parallel()

)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure. I wasn't sure it was worth the effort, but I can make it match the others.

}

req, err := backend.newRequest(u)

Copy link
Contributor

Choose a reason for hiding this comment

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

Nit-pick: I'd prefer no blank line here.

req, err := backend.newRequest(u)

if err != nil {
t.Errorf("failed to create new backend request for %s", u.String())
Copy link
Contributor

Choose a reason for hiding this comment

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

Once we use sub-tests, it's safe (and appropriate) to do t.Fatalf here.

}

actual := req.URL.String()
if test.expected != actual {
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit-pick: Put actual on the left-hand and expected on the right-hand side to match the order in the error message on the following line.

req, err := backend.newRequest(u)

if err != nil {
t.Errorf("failed to create new backend request for %s", u.String())
Copy link
Contributor

Choose a reason for hiding this comment

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

Please include all test case-identifying input parameters and the error message in the output, e.g.:

"URL=%s/%s port=%d: failed to create new backend request: %s", u.String(), test.path, test.port, err)

req, err := backend.newRequest(u)

if err != nil {
t.Errorf("failed to create new backend request for %s", u.String())
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we need the .String() part in u.String()? Is the formatter possibly "smart enough" to figure it out from u alone?


actual := req.URL.String()
if test.expected != actual {
t.Errorf("got %s for healthcheck URL, wanted %s", actual, test.expected)
Copy link
Contributor

Choose a reason for hiding this comment

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

Include test-case identifiers here too.

Since we need it at two spots, it seems reasonable to me to extract them into a variable.

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 tiny little bit remaining. (Apologies, I might not have been clear enough in my previous comment.)


req, err := backend.newRequest(u)
testCase := fmt.Sprintf("URL=%s/%s port=%d", u, test.path, test.port)
Copy link
Contributor

Choose a reason for hiding this comment

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

Now that you've added a description to each test case and injected that into the t.Run() call, we don't need the prefix anymore. :-)

Would you mind removing just that part again?

@bakins
Copy link
Contributor Author

bakins commented May 10, 2017

@timoreimann changes made. Let me know when it looks okay and I can squash and repush, if you want.

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.

LGTM 👍

@bakins, I think it's squash time. :-)

@bakins
Copy link
Contributor Author

bakins commented May 10, 2017

@timoreimann it's all in one commit now. Not the normal way I'd squash things, but it's done :)

@timoreimann
Copy link
Contributor

@bakins I actually like my commits squashed to atomic scale. ;-)

@emilevauge @vdemeester your review turn.

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 @bakins !
A minor typo, but other than that, LGTM!

docs/basics.md Outdated
@@ -278,7 +278,8 @@ as long as it keeps returning HTTP status codes other than 200 OK to HTTP GET
requests periodically carried out by Traefik. The check is defined by a path
appended to the backend URL and an interval (given in a format understood by [time.ParseDuration](https://golang.org/pkg/time/#ParseDuration)) specifying how
often the health check should be executed (the default being 30 seconds). Each
backend must respond to the health check within 5 seconds.
backend must respond to the health check within 5 seconds. By default, the port
of the backend sever is used, however, this may be overridden.
Copy link
Member

Choose a reason for hiding this comment

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

sed/sever/server 🤓

@ldez ldez merged commit 13e8a87 into traefik:master May 19, 2017
@ldez ldez added this to the 1.4 milestone May 19, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants