consul-template: process once if tag filter exists

1,786 views
Skip to first unread message

DJ Enriquez

unread,
Sep 15, 2015, 10:29:42 PM9/15/15
to Consul
Hello,

I'm trying to set up a template that will handle filtering a service based on multiple tags.

For example: We have 7 services named "Foo" registered in Consul. They are tagged accordingly:

  1. dev, proxied, ab
  2. dev, proxied
  3. test, ab
  4. test, proxied, ab
  5. test, proxied, ab
  6. test, proxied, ab
  7. prod, proxied

How do I set up a template to filter all "Foo"s to check if any are tagged "test", "proxied", and "ab"? And if so, to process something ONLY ONCE.

{{range services}}
{{range service .Name}}
{{if .Tags.Contains "proxied"}}{{if and (.Tags.Contains "test) (.Tags.Contains "proxied)}}
//{{.Name}}: YOU HAVE A SERVICE TAGGED "test" "proxied" and "ab"!!
{{end}}{{end}}
{{end}}
{{end}}

The template above will produce the following

//Foo: YOU HAVE A SERVICE TAGGED "test" "proxied" and "ab"!!
//Foo: YOU HAVE A SERVICE TAGGED "test" "proxied" and "ab"!!
//Foo: YOU HAVE A SERVICE TAGGED "test" "proxied" and "ab"!!

It produced it three times because there are three instances of Foo tagged "test" "proxied" and "ab". How do i get this to do it once??

Michael Fischer

unread,
Sep 15, 2015, 11:14:48 PM9/15/15
to consu...@googlegroups.com
You can set variables in templates - maybe something like this?

{{range services}}
{{$found := "no"}}
{{range service .Name}}
{{if and ($found eq "no") (.Tags.Contains "test") (.Tags.Contains "proxied") (.Tags.Contains "ab")}}
//{{.Name}}: YOU HAVE A SERVICE TAGGED "test" "proxied" and "ab"!!
{{$found := "yes"}}
{{end}}
{{end}}
{{end}}

--
This mailing list is governed under the HashiCorp Community Guidelines - https://www.hashicorp.com/community-guidelines.html. Behavior in violation of those guidelines may result in your removal from this mailing list.
 
GitHub Issues: https://github.com/hashicorp/consul/issues
IRC: #consul on Freenode
---
You received this message because you are subscribed to the Google Groups "Consul" group.
To unsubscribe from this group and stop receiving emails from it, send an email to consul-tool...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/consul-tool/490d79eb-81bd-4496-a351-7c4216c437b2%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

DJ Enriquez

unread,
Sep 16, 2015, 1:09:33 PM9/16/15
to Consul
Thanks for the reply Michael, that solution works great in the scope of that problem. However, realistically, I need an ELSE clause that happens if NONE of the services satisfy that requirement, and I need that ELSE statement to write once.

Pseudo-code may explain it better:

for(int i = 0; i < serviceFoo.Length; i++)
{
     if(service.Foo[i].Contains("test" and "proxied" and "ab"))
     {
           log("Found it!");
           break;
     }
     if(i == serviceFoo.Length -1) //Were at the last item and it was not found
     {
           log("This does not exist");
     }
}

So this would write just one entry. Is this possible in go-templating?

Michael Fischer

unread,
Sep 16, 2015, 5:37:58 PM9/16/15
to consu...@googlegroups.com
I think you can do it using the "$found" variable by comparing its value after the range iteration completes.  Have you tried it?

I'm afraid that's about the best you can go with Go templates - there are sadly no "break" or "continue" operators to rely on.

--Michael

Message has been deleted

DJ Enriquez

unread,
Sep 16, 2015, 6:58:29 PM9/16/15
to Consul
Thanks Michael. I did try this and it will not work because setting $found inside {{range}} only changes the value within the scope of {{range}}. Once you exit out of {{range}}, $found goes right back to "no".

Here is a real example created by consul-template for a service I have called hello-world:

{{range services}}
  {{$found := "no"}}
  {{range service .Name}}
    {{if and (eq $found "no") (.Tags.Contains "lbc") (.Tags.Contains $app_env) (.Tags.Contains "ab")}}
    #{{.Name}} is "ab" and {{$app_env}}
    {{$found := "yes"}}
    {{end}}
  {{end}}
  {{if eq $found "no"}}
    #Did not find "ab" and {{ $app_env }}: {{.Name}}
  {{end}}
{{end}}

This template outputs:

    #hello-world is "ab" and dev

    #Did not find "ab" and dev: hello-world


As you can see, it found it, then it goes writes the case if $found = "no".

Reply all
Reply to author
Forward
0 new messages