108

How can I look up the value of a map by using a variable key without iterating?

So one can lookup a constant key on variable map $x with $x.key1, but is it possible to do amap.$key?

David Maze
  • 130,717
  • 29
  • 175
  • 215
Kyle Brandt
  • 26,938
  • 37
  • 124
  • 165

2 Answers2

193

You use the index function:

{{index .Amap "key1"}}
index
    Returns the result of indexing its first argument by the
    following arguments. Thus "index x 1 2 3" is, in Go syntax,
    x[1][2][3]. Each indexed item must be a map, slice, or array.

https://golang.org/pkg/text/template#hdr-Functions

Zombo
  • 1
  • 62
  • 391
  • 407
OneOfOne
  • 95,033
  • 20
  • 184
  • 185
  • This works, I had tried it but was using it with a slice when I thought I was using it with a map. – Kyle Brandt Oct 01 '14 at 23:15
  • @KyleBrandt I wrote the answer then I actually had to double check to make sure. – OneOfOne Oct 01 '14 at 23:18
  • 1
    Does this work inside a pipeline? Can you give an example of how to use this as part of `{{template "name" how_to_index_here?}}` – chakrit Jul 28 '15 at 09:06
  • 5
    @chakrit: Yes, wrap the pipeline in parens: `{{template "name" (index .Amap "key1")}}` It should be noted that the simpler syntax of accessing map keys directly from dot also works: `{{template "name" .Amap.key1}}` – Jonah Braun Jul 26 '16 at 01:37
  • 3
    Is it also possible if the resulting value is a struct to select a field? `{{index .Amap "key1"}}.Myfield` – Gert Cuykens Sep 15 '17 at 12:24
  • 23
    @GertCuykens after searching for exactly that answer all day and coming up with nothing, here is what I figured out: ```{{ with (index .Amap "key1") }}{{ .Myfield }}{{ end }}``` – JoeLinux Sep 28 '17 at 19:34
  • 2
    @JoeLinux, that's a great solution. Works well with keys that are more than alphanumeric, e.g. `{{ with (index .Amap "key-with-hyphens") }} {{ .Myfield }} {{ end }}` – Kenny Trytek Sep 26 '18 at 18:38
  • Note both args can be variables: `{{ index .Amap .var2.username }}` and if you want a specific child of the result (say Amap[var2.username] is itself yaml instead of a value), you can use `{{ (index .Amap .var2.username).some_field }}` – Oliver Jan 20 '20 at 22:59
  • Thanks this works for getting a key with dots, e.g. "{{index .data "key.with.dots"}} `kubectl get configmap myMap --template='{{index .data "foo.bar"}}` – Neon Feb 22 '21 at 23:05
  • If i have a $var holding a field name. will .Values.mykey.($var) or .Values.mykey.(index .Amap "var") work ? – Vijayendar Gururaja Oct 16 '21 at 19:35
  • Adding a note here for folks using packer. We wanted to add a tag to a new AMI that would indicate the source AMI of the source AMI. We know the source AMI is tagged with "source-ami-id", and we can access the .SourceAMITags, but I wasn't sure how to access this particular tag, since its key has "-" in it. Packer uses golang templates, so I was able to make it work with this syntax: `tags = { "upstream-source-ami-id" = "{{ index .SourceAMITags \"source-ami-id\" }}" }` – Jason Priebe Jul 21 '22 at 16:12
14

A simpler way would be to do: {{.Amap.key1}}. However, this will only work if the key is alphanumeric. If not, you'll need to access it using index.

From the documentation:

- The name of a key of the data, which must be a map, preceded
  by a period, such as
    .Key
  The result is the map element value indexed by the key.
  Key invocations may be chained and combined with fields to any
  depth:
    .Field1.Key1.Field2.Key2
  Although the key must be an alphanumeric identifier, unlike with
  field names they do not need to start with an upper case letter.
  Keys can also be evaluated on variables, including chaining:
    $x.key1.key2
  • This is very use full while the template is a JSON text. For JSON text, to keep syntax ok, the form of `{{index .Amap "key1"}}` must write as `{{index .Amap \"key1\"}}` in string value, and the latter format not working under template. – coanor Jun 15 '23 at 10:03