# How to do macro-like templating with parameters in dynamic configuration?

**URL:** <https://community.traefik.io/t/how-to-do-macro-like-templating-with-parameters-in-dynamic-configuration/13994>\
**Category:** Traefik v2\
**Tags:** file\
**Created:** [March 31, 2022, 5:48pm UTC](https://community.traefik.io/t/how-to-do-macro-like-templating-with-parameters-in-dynamic-configuration/13994 "2022-03-31T17:48:38Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![NReilingh](https://sea2.discourse-cdn.com/flex020/user_avatar/community.traefik.io/nreilingh/32/5116_2.png) [@NReilingh](https://community.traefik.io/u/NReilingh)\
**Post date:** [March 31, 2022, 5:48pm UTC](https://community.traefik.io/t/how-to-do-macro-like-templating-with-parameters-in-dynamic-configuration/13994/1 "2022-03-31T17:48:38Z")

</div>

In Apache, one can do something like the following in a config file using the [Macro directive](https://httpd.apache.org/docs/2.4/mod/mod_macro.html):

```auto
<Macro AliasHost $zone $alias $target>
  <VirtualHost *:80>
      ServerName $alias
      ServerAlias www.$alias

      Redirect permanent / $target
  </VirtualHost>

  <VirtualHost *:443>
      ServerName $alias
      ServerAlias www.$alias

      Redirect permanent / $target

      Include conf/includes/$zone-ssl-config.conf
  </VirtualHost>
</Macro>

Use AliasHost example sub.example.com https://target.example.com/

```

I am led to believe that [Go templating](https://doc.traefik.io/traefik/providers/file/#go-templating) in Traefik's dynamic file config should offer me the same or similar functionality, however I have been unable to get this style of templating using `{{define}}` and `{{template}}` to work with multiple parameters in a similar manner. The [Go docs for text/template](https://pkg.go.dev/text/template) are a bit too dense for me; I haven't written any Go before so I really just need a working example to copy.

I have been successful at producing a working minimal example with one unnamed parameter as follows:

```yaml
{{define "proxrouter"}}
    prox-{{ . }}:
      rule: Host(`prox.{{ env "DNS_ZONE" }}`) && PathPrefix(`/{{ . }}`)
      middlewares:
        - proxyChain
      service: svcprox-{{ . }}
{{end}}

http:
  routers:
{{template "proxrouter" "test"}}

```

However I have been unable to figure out how to pass named or multiple parameters, for example:

### Named parameter (made-up example):

```yaml
{{define "proxrouter"}}
    prox-{{ $name }}:
      rule: Host(`prox.{{ env "DNS_ZONE" }}`) && PathPrefix(`/{{ $name }}`)
      middlewares:
        - proxyChain
      service: svcprox-{{ $name }}
{{end}}

http:
  routers:
{{template "proxrouter" ???}}

```

### Multiple parameters (made-up example):

```yaml
{{define "proxrouter"}}
    prox-{{ .Name }}:
      rule: Host(`prox.{{ env "DNS_ZONE" }}`) && PathPrefix(`/{{ .Path }}`)
      middlewares:
        - proxyChain
      service: svcprox-{{ .Name }}
{{end}}

http:
  routers:
{{template "proxrouter" ???}}

```

I really don't understand the Go template "pipeline", but this seems like it should be trivially possible. Unfortunately all of my googling results in information about rendering a template from a Go program.

I have tried a few things to fill the `???` slots above in this Go playground:

> **[Go Playground - The Go Programming Language](https://go.dev/play/p/-RHUvh0ohFs)**

... but they all fail with a nil pointer dereference error, which in Traefik appears to present as log output similar to the following:

`time="2022-03-31T02:57:18Z" level=error msg="Error occurred during watcher callback: /etc/traefik/conf/dynamic/proxy.yml: unsupported simple value type: invalid" providerName=file`  
`time="2022-03-31T03:06:34Z" level=error msg="Error occurred during watcher callback: /etc/traefik/conf/dynamic/proxy.yml: template: :19:36: executing \"\" at <.Key>: can't evaluate field Key in type bool" providerName=file`

For the multiparam option I was trying to follow the suggestion here:

> <https://stackoverflow.com/questions/18276173/calling-a-template-with-several-pipeline-parameters/18276968#18276968>

---

<div class="post-metadata">

**Author:** ![NReilingh](https://sea2.discourse-cdn.com/flex020/user_avatar/community.traefik.io/nreilingh/32/5116_2.png) [@NReilingh](https://community.traefik.io/u/NReilingh)\
**Post date:** [April 3, 2022, 6:22pm UTC](https://community.traefik.io/t/how-to-do-macro-like-templating-with-parameters-in-dynamic-configuration/13994/2 "2022-04-03T18:22:48Z")

</div>

I think I figured this out on my own. The StackOverflow answer I referenced requires outside code, but this `dict` function is actually provided by the Sprig functions which are included by Traefik. So this playground works:

> **[Better Go Playground](https://goplay.tools/snippet/1_IGUfM9xpa)**
>
> Better Go Playground with syntax highlight support

(Note you can use this to play with Traefik template style, however backticks are not allowed or escapable within a go raw string literal so either remove them or use the hacky workaround shown in the playground example.)

My understanding of how the "pipeline" works when providing an argument to `{{template}}` is that this argument by definition has to be anonymous/unnamed. So if you want to call something by name within your `{{define}}`d template, you have two options:

1. Give the pipeline value a name within the `{{define}}` block

```auto
{{define "proxrouter"}}
    {{ $name := . }}
    prox-{{ $name }}:
      rule: Host(`prox.{{ env "DNS_ZONE" }}`) && PathPrefix(`/{{ $name }}`)
      middlewares:
        - proxyChain
      service: svcprox-{{ $name }}
{{end}}

http:
  routers:
{{template "proxrouter" "pipeline_value"}}

```

1. Use the `dict` Sprig function

```auto
{{define "proxrouter"}}
    prox-{{ .Name }}:
      rule: Host(`prox.{{ env "DNS_ZONE" }}`) && PathPrefix(`/{{ .Name }}`)
      middlewares:
        - proxyChain
      service: svcprox-{{ .Name }}
{{end}}

http:
  routers:
{{template "proxrouter" dict "Name" "dict_value"}}

```

Multiple parameters are accomplished simply by adding further name-value pairs as arguments to `dict` per the docs:

> **[Dictionaries and Dict Functions](https://masterminds.github.io/sprig/dicts.html)**
>
> Useful template functions for Go templates.

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/flex020/uploads/containo/original/2X/b/bd81ebdb578656e76e56ff3cc3eed021d3ba132d.png) [@system](https://community.traefik.io/u/system)\
**Post date:** [April 6, 2022, 6:23pm UTC](https://community.traefik.io/t/how-to-do-macro-like-templating-with-parameters-in-dynamic-configuration/13994/3 "2022-04-06T18:23:08Z")

</div>

This topic was automatically closed 3 days after the last reply. New replies are no longer allowed.
