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

Enhanced flexibility in Consul Catalog configuration #1565

Merged
merged 1 commit into from
Jun 12, 2017

Conversation

aantono
Copy link
Contributor

@aantono aantono commented May 8, 2017

Description

Enhanced Consul Catalog configuration by adding the following:

  • Ability to configure default FrontEndRule using Go Template
  • Ability to use all tags for constraint filtering
  • Ability to have empty/no prefix
  • Added getTag and hasTag functions to be used in advanced custom configuration template

Copy link
Contributor

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

Thanks for the contribution.

could you also edit traefik.sample.toml?

@@ -202,22 +231,46 @@ func (p *CatalogProvider) getBackendName(node *api.ServiceEntry, index int) stri
}

func (p *CatalogProvider) getAttribute(name string, tags []string, defaultValue string) string {
//for _, tag := range tags {
Copy link
Contributor

Choose a reason for hiding this comment

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

could your remove the comment block?

var buffer bytes.Buffer
t.Execute(&buffer, templateObjects)

//return "Host:" + service.ServiceName + "." + p.Domain
Copy link
Contributor

Choose a reason for hiding this comment

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

could your remove the comment?

FrontEndRule string `description:"Frontend rule used for Consul services"`
AllTagsConstraintFiltering bool `description:"Should use all tags for constraint filtering"`
client *api.Client
FrontEndRuleTemplate *template.Template
Copy link
Contributor

Choose a reason for hiding this comment

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

move up this line and add the description.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@ldez The FrontEndRuleTemplate is the actual Template object that is not provided via configuration, but initialized from FrontEndRule value. So I see it being similar to api.Client kind. Guess it should probably be made lower-cased name frontEndRuleTemplate instead to clearly indicate that, correct?

Copy link
Contributor

Choose a reason for hiding this comment

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

yes it's the way 😃

Copy link
Contributor Author

@aantono aantono May 10, 2017

Choose a reason for hiding this comment

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

Awesome... I've made the change in the last update to this PR along with adding content to the traefik.sample.toml file, and also rebased it on top of the latest changes in master. Let me know if anything else needs changing or correcting.

@aantono aantono force-pushed the master branch 3 times, most recently from 43a6b6e to d271e2a Compare May 10, 2017 20:43
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 @aantono for your contribution :)
Few comments but overall looks great!

}

func (p *CatalogProvider) hasTag(name string, tags []string) bool {
tag := p.getTag(name, tags, "=!=") // Very-very unlikely that a Consul tag would ever start with '=!='
Copy link
Member

Choose a reason for hiding this comment

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

@aantono Could you explain why you need =!= here?

Copy link
Contributor Author

@aantono aantono May 19, 2017

Choose a reason for hiding this comment

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

This is my internal dummy "default" value (because getTag function wants a default) which is unlikely to be seen in the real world (who would tag their service with =!=... :) )
The logic is this: if getTag(...) returns =!=, then there is no name tag in existence, otherwise we would get a different value.

Domain string `description:"Default domain used"`
Prefix string `description:"Prefix used for Consul catalog tags"`
FrontEndRule string `description:"Frontend rule used for Consul services"`
AllTagsConstraintFiltering bool `description:"Should use all tags for constraint filtering"`
Copy link
Member

Choose a reason for hiding this comment

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

Not fan of the naming of AllTagsConstraintFiltering. Could you explain why you added this option in a use case?

Copy link
Contributor Author

@aantono aantono May 19, 2017

Choose a reason for hiding this comment

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

The use-case here is to enable the ability to filter (use tag constraints) on the existing Consul tags, not only the ones that are defined in traefik.tags Many places with existing Consul infrastructure already have quite an elaborate tagging setup for their service registrations, so being able to leverage those for filtering is a big plus. For example, each Spring Boot application that uses sping-cloud-consul module, will automatically register the management endpoint using management tag. Because it might not be desired to expose LB routes to management endpoints, one might want to create a constraint rule like constraints = ["tag!=management"], and when coupled with AllTagsConstraintFiltering=true, it will use the "raw" management tag value, instead of only the values provided by traefik.tags tag. Does this make things clearer?

P.S. I'm not a big fan of the name either, just couldn't really come up with anything reasonably short and yet more descriptive, so any suggestions are welcomed! :)

if kv := strings.SplitN(tag[len(p.Prefix+"."):], "=", 2); len(kv) == 2 && strings.ToLower(kv[0]) == strings.ToLower(name) {
return kv[1]
if strings.Index(strings.ToLower(tag), strings.ToLower(name)) == 0 {
if kv := strings.SplitN(tag, "=", 2); strings.ToLower(kv[0]) == strings.ToLower(name) {
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 some comments ? This block is a bit hard to read ;)

if strings.Index(strings.ToLower(tag), p.Prefix+".tags=") == 0 {
splitedTags := strings.Split(tag[len(p.Prefix+".tags="):], ",")
if strings.Index(strings.ToLower(tag), p.getPrefixedName("tags=")) == 0 {
splitedTags := strings.Split(tag[len(p.getPrefixedName("tags=")):], ",")
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 some comments ? This block is a bit hard to read ;)

docs/toml.md Outdated
#
# Optional
#
frontEndRule = "{{.ServiceName}}.{{Domain}}"
Copy link
Member

Choose a reason for hiding this comment

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

Shouldn't it be Host:{{.ServiceName}}.{{Domain}} instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, indeed it should. Great catch!

#
# Optional
#
#frontEndRule = "{{.ServiceName}}.{{Domain}}"
Copy link
Member

Choose a reason for hiding this comment

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

Same as in traefik.sample.toml

docs/toml.md Outdated
# Default frontEnd Rule for Consul services
# - The format is a Go Template with ".ServiceName", ".Domain" and ".Attributes" available
# -- "getTag(name, tags, defaultValue)", "hasTag(name, tags)" and "getAttribute(name, tags, defaultValue)" functions are available
# --- "getAttribute(...)" function uses prefixed tag names based on "prefix" value
Copy link
Member

Choose a reason for hiding this comment

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

Could explain why you added in the comments ?

-
--
---

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No reason, just to help with indentation... Removed.

@aantono aantono force-pushed the master branch 5 times, most recently from e9da784 to b0b4085 Compare May 23, 2017 18:10
# echo "Building binary for $OS/$ARCH..."
# GOARCH=$ARCH GOOS=$OS CGO_ENABLED=0 $GO_BUILD_CMD "$GO_BUILD_OPT" -o "dist/traefik_$OS-$ARCH" ./cmd/traefik/
# done
#done
Copy link
Member

Choose a reason for hiding this comment

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

I don't think that's what we want ^^

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oops, my bad... accidentally committed something that should not have been... will revert ASAP

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 @aantono
LGTM

@aantono aantono force-pushed the master branch 2 times, most recently from 8fe4b9a to d39e7d2 Compare June 12, 2017 18:37
@ldez ldez added this to the 1.4 milestone Jun 12, 2017
Copy link
Contributor

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

Thanks!

LGTM

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