Consul-template "index .ServiceMeta" throws error

Hi,
I’m quite new to consul, but trying to get into it. While playing around with services and changes on time with consul-template, we try to use added meta data to the service. The key/value pairs are correctly viewable within the service catalog details, but even with the easiest way to access the meta data an error is thrown:

2023/02/20 17:35:36.135590 [ERR] (cli) /tmp/test.tpl: execute: template: :4:42: executing "" at <.ServiceMeta>: can't evaluate field ServiceMeta in type *dependency.HealthService

The ctmpl is as easy as it can be:

{{- range services }}
# {{- .Name }}
  {{- range service .Name }}
    {{ .Node }} - {{ .Port }} - {{ index .ServiceMeta "serviceUrl" }}
  {{- end }}
{{- end }}

The service catalog show the values correctly:

ServiceMeta":{"external-source":"nomad","servicePath":"/","serviceUrl":"proxy-test"}

What’s wrong here?

Does noone have any idea? :fearful:

It makes perfect sense that this template would error, as it is written to depend on every service registered in Consul having serviceUrl in the metadata - and they won’t all have that, as consul itself does not.

1 Like

Thank you very much for your kind reply, it makes absolut sense, yes … but:
Even if I limit the result set to those services containing the ServiceMeta stuff, I get the error.

I added

{{- $allowedTags := parseJSON `["myservice","expose"]` -}}
{{ range services }}
  {{- if (containsAny $allowedTags .Tags) }}
    {{ range service .Name }}

to get only the service(s) containing ServiceMeta entries but still get the same error message.

We also tried now a different way we found to access some ServiceMeta:

{{ range service "ent-123456" }}
  {{ with .ServiceMeta }}
       {{ .serviceUrl }}
  {{ end }}
{{ end }}

But this results also in the same error message:

[ERR] (cli) service2.tpl: execute: template: :2:11: executing "" at <.ServiceMeta>: can't evaluate field ServiceMeta in type *dependency.HealthService

Even in
curl http://127.0.0.1:8500/v1/health/service/ent-123456
we can see the correct Service Meta key/value pairs

Btw. I’m calling the template as follows:

consul-template -template "service2.tpl:out.txt" -once

It’s a bit frustrating …

You should change your template to just print a stringified form of the entire ServiceMeta map:

{{ .ServiceMeta }}

and then you’ll be able to look at your actual data, and think about why it doesn’t have a serviceUrl.

Hi maxb, thanks again for your kind reply. It seems, even from the error message, that the whole map “ServiceMeta” is not “accessable”, although I can see the entries within the json when calling the consul service catalog details.

0
ID 959ea52f-7a5f-2146-935f-eb514c6fc904
Node at-vie-1-node01
Address 10.0.55.40
Datacenter at-vie-1-dev01
ServiceMeta
external-source nomad
servicePath /
serviceUrl proxy-test
ServicePort 80

When trying the same stuff with .NodeMeta, everything is working fine (but not feasable for our requirements here)

All I can tell you is that it works fine for me…

$ consul-template -dry -once -template input.ctmpl:dummy-output-name
> dummy-output-name

#consul
    examplehostname - 8300 - map[non_voter:false raft_version:3 read_replica:false serf_protocol_current:2 serf_protocol_max:5 serf_protocol_min:1 version:1.13.2]
$ cat input.ctmpl 
{{- range services }}
# {{- .Name }}
  {{- range service .Name }}
    {{ .Node }} - {{ .Port }} - {{ .ServiceMeta }}
  {{- end }}
{{- end }}

I have to apologize for all the time you’ve spent … we just found that for some reason on the dev node a VERY old version (0.19.5) of consul-table was installed :man_facepalming: So, .ServiceMeta was not yet implemented. So sorry for that!