Skip to content

Latest commit

 

History

History
424 lines (313 loc) · 7.87 KB

templates.md

File metadata and controls

424 lines (313 loc) · 7.87 KB

Templates

Templates define a single application configuration template. Templates are stored under the /etc/confd/templates directory by default.

Templates are written in Go's text/template.

Template Functions

base

Alias for the path.Base function.

{{with get "/key"}}
    key: {{base .Key}}
    value: {{.Value}}
{{end}}

exists

Checks if the key exists. Return false if key is not found.

{{if exists "/key"}}
    value: {{getv "/key"}}
{{end}}

get

Returns the KVPair where key matches its argument. Returns an error if key is not found.

{{with get "/key"}}
    key: {{.Key}}
    value: {{.Value}}
{{end}}

cget

Returns the KVPair where key matches its argument and the value has been encrypted. Returns an error if key is not found.

{{with cget "/key"}}
    key: {{.Key}}
    value: {{.Value}}
{{end}}

gets

Returns all KVPair, []KVPair, where key matches its argument. Returns an error if key is not found.

{{range gets "/*"}}
    key: {{.Key}}
    value: {{.Value}}
{{end}}

cgets

Returns all KVPair, []KVPair, where key matches its argument and the values have been encrypted. Returns an error if key is not found.

{{range cgets "/*"}}
    key: {{.Key}}
    value: {{.Value}}
{{end}}

getv

Returns the value as a string where key matches its argument. Returns an error if key is not found.

value: {{getv "/key"}}

cgetv

Returns the encrypted value as a string where key matches its argument. Returns an error if key is not found.

value: {{cgetv "/key"}}

getvs

Returns all values, []string, where key matches its argument. Returns an error if key is not found.

{{range getvs "/*"}}
    value: {{.}}
{{end}}

cgetvs

Returns all encrypted values, []string, where key matches its argument. Returns an error if key is not found.

{{range cgetvs "/*"}}
    value: {{.}}
{{end}}

getenv

Alias for os.Getenv

export HOSTNAME=`hostname`
hostname: {{getenv "HOSTNAME"}}

datetime

Alias for time.Now

# Generated by confd {{datetime}}

Outputs:

# Generated by confd 2015-01-23 13:34:56.093250283 -0800 PST
# Generated by confd {datetime.Format("Jan 2, 2006 at 3:04pm (MST)")}

Outputs:

# Generated by confd Jan 23, 2015 at 1:34pm (EST)

See the time package for more usage: http://golang.org/pkg/time/

split

Wrapper for strings.Split. Splits the input string on the separating string and returns a slice of substrings.

{{ $url := split (getv "/deis/service") ":" }}
    host: {{index $url 0}}
    port: {{index $url 1}}

toUpper

Alias for strings.ToUpper Returns uppercased string.

key: {{toUpper "value"}}

toLower

Alias for strings.ToLower. Returns lowercased string.

key: {{toLower "Value"}}

json

Returns an map[string]interface{} of the json value.

Add keys to etcd

etcdctl set /services/zookeeper/host1 '{"Id":"host1", "IP":"192.168.10.11"}'
etcdctl set /services/zookeeper/host2 '{"Id":"host2", "IP":"192.168.10.12"}'

Create the template resource

[template]
src = "services.conf.tmpl"
dest = "/tmp/services.conf"
keys = [
  "/services/zookeeper/"
]

Create the template

{{range gets "/services/zookeeper/*"}}
{{$data := json .Value}}
  id: {{$data.Id}}
  ip: {{$data.IP}}
{{end}}

Advanced Map Traversals

Once you have parsed the JSON, it is possible to traverse it with normal Go template functions such as index.

A more advanced structure, like this:

{
  "animals": [
    {"type": "dog", "name": "Fido"},
    {"type": "cat", "name": "Misse"}
  ]
}

It can be traversed like this:

{{$data := json (getv "/test/data/")}}
type: {{ (index $data.animals 1).type }}
name: {{ (index $data.animals 1).name }}
{{range $data.animals}}
{{.name}}
{{end}}

jsonArray

Returns a []interface{} from a json array such as ["a", "b", "c"].

{{range jsonArray (getv "/services/data/")}}
val: {{.}}
{{end}}

ls

Returns all subkeys, []string, where path matches its argument. Returns an empty list if path is not found.

{{range ls "/deis/services"}}
   value: {{.}}
{{end}}

lsdir

Returns all subkeys, []string, where path matches its argument. It only returns subkeys that also have subkeys. Returns an empty list if path is not found.

{{range lsdir "/deis/services"}}
   value: {{.}}
{{end}}

dir

Returns the parent directory of a given key.

{{with dir "/services/data/url"}}
dir: {{.}}
{{end}}

join

Alias for the strings.Join function.

{{$services := getvs "/services/elasticsearch/*"}}
services: {{join $services ","}}

Example Usage

etcdctl set /nginx/domain 'example.com'
etcdctl set /nginx/root '/var/www/example_dotcom'
etcdctl set /nginx/worker_processes '2'
etcdctl set /app/upstream/app1 "10.0.1.100:80"
etcdctl set /app/upstream/app2 "10.0.1.101:80"

/etc/confd/templates/nginx.conf.tmpl

worker_processes {{getv "/nginx/worker_processes"}};

upstream app {
{{range getvs "/app/upstream/*"}}
    server {{.}};
{{end}}
}

server {
    listen 80;
    server_name www.{{getv "/nginx/domain"}};
    access_log /var/log/nginx/{{getv "/nginx/domain"}}.access.log;
    error_log /var/log/nginx/{{getv "/nginx/domain"}}.log;

    location / {
        root              {{getv "/nginx/root"}};
        index             index.html index.htm;
		proxy_pass        http://app;
        proxy_redirect    off;
        proxy_set_header  Host             $host;
        proxy_set_header  X-Real-IP        $remote_addr;
        proxy_set_header  X-Forwarded-For  $proxy_add_x_forwarded_for;
    }
}

Output: /etc/nginx/nginx.conf

worker_processes 2;

upstream app {
    server 10.0.1.100:80;
    server 10.0.1.101:80;
}

server {
    listen 80;
    server_name www.example.com;
    access_log /var/log/nginx/example.com.access.log;
    error_log /var/log/nginx/example.com.error.log;

    location / {
        root              /var/www/example_dotcom;
        index             index.html index.htm;
        proxy_pass        http://app;
        proxy_redirect    off;
        proxy_set_header  Host             $host;
        proxy_set_header  X-Real-IP        $remote_addr;
        proxy_set_header  X-Forwarded-For  $proxy_add_x_forwarded_for;
    }
}

Complex example

This examples show how to use a combination of the templates functions to do nested iteration.

Add keys to etcd

etcdctl mkdir /services/web/cust1/
etcdctl mkdir /services/web/cust2/
etcdctl set /services/web/cust1/2 '{"IP": "10.0.0.2"}'
etcdctl set /services/web/cust2/2 '{"IP": "10.0.0.4"}'
etcdctl set /services/web/cust2/1 '{"IP": "10.0.0.3"}'
etcdctl set /services/web/cust1/1 '{"IP": "10.0.0.1"}'

Create the template resource

[template]
src = "services.conf.tmpl"
dest = "/tmp/services.conf"
keys = [
  "/services/web"
]

Create the template

{{range $dir := lsdir "/services/web"}}
upstream {{base $dir}} {
    {{$custdir := printf "/services/web/%s/*" $dir}}{{range gets $custdir}}
    server {{$data := json .Value}}{{$data.IP}}:80;
    {{end}}
}

server {
    server_name {{base $dir}}.example.com;
    location / {
        proxy_pass {{base $dir}};
    }
}
{{end}}

Output:/tmp/services.conf

upstream cust1 {
    server 10.0.0.1:80;
    server 10.0.0.2:80;
}

server {
    server_name cust1.example.com;
    location / {
        proxy_pass cust1;
    }
}

upstream cust2 {
    server 10.0.0.3:80;
    server 10.0.0.4:80;
}

server {
    server_name cust2.example.com;
    location / {
        proxy_pass cust2;
    }
}

Go's text/template package is very powerful. For more details on it's capabilities see its documentation.