-
Notifications
You must be signed in to change notification settings - Fork 781
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
Create a work-around to allow the setting of variables #399
Comments
Hi @jdelic Thank you for opening an issue. I'm not sure I understand the use case here. You want to override the advertised service port based off of a tag? That seems like an anti-pattern as the Consul API should be the source of truth for which port a service is accessible. |
This is just an example for a haproxy template from the system we're working on. The use-case specifically here is that a developer can override the external port a service will be made available at, but I only used it because that's one that I had open in IntelliJ when I wrote the ticket. The service's port will still be used in the haproxy backend clause which I didn't include. Basically: A developer can deploy a service definition in a service's .deb package that will include tags which But the larger point is this:
would be immensely useful. |
Hi @jdelic Would the following work for you? {{ if .Tags | contains "usessl" }}
# ...
{{ end }} Go's templating language is intentionally not as functional as something like Ruby's ERB. At first this really bothered me as well. However, in working with the templating language and Consul Template, I have found that wanting the ability to "map-reduce" or perform complex operations in the template is an anti-pattern. It makes the template more difficult to reason about and is often an indication that there exists a problem at a higher level (like in the way the data is structured in Consul itself). |
Ok, that solves indeed the second use-case, but not the first. I would really like to parse data out of tags or to be able to implement a default value. Another example: We spawn a per-customer backend instance that registers with our loadbalancer using consul/consul-template using docker-registrator. If the customer paid for a custom hostname, the service definition will include a tag "host:[fqdn]", otherwise "host:customer.domain.com". It's super-easy to put that information in the environment of the docker container and basically impossible to put it on the loadbalancer. How would I read this information and use it in a template without proper variables? |
Btw, this would also allow us to find the intersection of tags in templates. Is there any way to do that from the |
Hey @jdelic If you are able to put that information into the Docker container's environment variables, can you use the For the use case you described, I would recommend writing a Consul Template plugin instead. I agree that Go's templating language is incredibly limiting, but I find that to be an asset more than a hinderance. Tags are not a first-class thing in Consul (like you cannot query by a tag), so I think they may not be the best way to store this type of data. The template would be much simpler if you mapped the service to a value in the KV store and then you could use a simple Even if we solve this particular problem, you will undoubtably hit another roadblock because of the way your data is structured. I think you'll save some headaches if you either restructure your data or write custom plugins instead 😄. |
No, those are separate servers.
Hmm, I don't agree. Having the ability to set a variable across two nested scopes in a template would fix all of the current problems that I'm having with consul-template 😕.
From reading the docs, I could write a plugin that given a
results in
How would I get to the service catalog for a plug-in? (Sorry, this is now terribly off topic from the original ticket 😞, but I really appreciate the help!) |
Hi @jdelic It looks like plugins only currently work with
I understand your frustration there, but there is a reason Go's templating language does not expose that functionality. I really trust the Go authors and think they have the right opinion that templates should not be mutating or mapping the data they receive. I do not have a good solution or workaround. Consul Template operates on the assumption that your data is structured in a semantic way. If you're operating outside the bounds of those assumptions, Consul Template may not be the right tool for your job. You're more than welcome to submit a PR for this "scratch" functionality, but I do not think this is something we will be implementing ourselves. The watcher and dependency libraries are also entirely open source and separate from Consul Template. You could easily build your own tool that satisfies your exact use case without duplicating a ton of logic. There are a number of community projects that leverage the packages in this repo outside the scope of Consul Template including envconsul, consul-replicate, and fsconsul 😄. I would be happy to revisit this if there is a serious demand, but that has not been the case so far. Thanks! |
Thanks for the discussion and the references, though, I really appreciate it. Just for the record: I think the Golang devs got that one wrong, just like Django templates and numerous other template languages before them, but we'll see :). I guess we might use consul-template to render a Jinja template and then use the "command" portion of the |
@sethvargo here's another example of where variables or plugins everywhere would be useful: We have X application servers and Y data servers (HTTP protocol, idempotent). The haproxy configuration we want on each application server is:
In other words, pick one data server as the stable primary but fail over to the rest if the primary In a external plugin this is not hard, but we apparently can't use plugins against a |
Here's the current template code, but that doesn't do what we need. The list is not sorted or rotated per application server so everyone will hit an unpredictable data server and the haproxy configuration will be rewritten if the list order changes. I may be misunderstanding something fundamental, so please let me know if so.
(btw the data service is Elastic Search but I'm trying to keep the example abstract :) |
@tzz Perhaps you're interested: We now render a Python script from
|
@jdelic oh that's clever. I would use |
I'm trying to build up some dynamics urls based on tags provided by the service. It uses a few conditionals based on tags. I can build up the url just fine, all though that line is a little long and hairy. Now the problem is: I need that in 6-7 places, so assigning all that to a variable would be a lot more DRY and maintainable |
As a workaround, I'm using a macro right now. See |
Sorry for commenting on this long-closed issue, but people might come here through Google. I have since published the above work-around in consul-smartstack. |
golang/go#10608 is unfortunately marked as Unplanned. This severly limits
consul-template
s usecases with service tags. I would love to do something like this:Where a tag can override the service's port on the loadbalancer in my example. It would be awesome if consul-template would add something along the lines of http://gohugo.io/extras/scratch to support the above. Or is there another work-around that I don't know about?
The text was updated successfully, but these errors were encountered: