passing variables from sls files to jinja templates

6,030 views
Skip to first unread message

schlag

unread,
Nov 30, 2012, 12:37:02 PM11/30/12
to salt-...@googlegroups.com
i have a state to manage nginx conf files where i use a for loop to cycle through a pillar value, applying jinja templates to each managed config file.  i am having trouble with passing the variable from the for loop in the state file into the jinja template.  

pillar value:
--snip
nginx_sites:             testdomain1.com testdomain2.com
--snip


nginx.sls:

--snip
{% for nginx_site in pillar['nginx_sites'], %}

/etc/nginx/sites-enabled/{{ nginx_site }}.conf:
  file.managed:
    - template: jinja
    - source:   salt://environments/prod/web/location1/files/nginx.conf.jinja
    - user:     root
    - group:    root
    - mode:     644
    - require:
      - pkg:    nginx-full

{% endfor %}
--snip


jinja template:

--snip
server {
listen 443;
server_name {{ nginx_site }} *.{{ nginx_site }} 

ssl on;
ssl_certificate /etc/nginx/ssl/wildcard.{{ nginx_site }}.chained.crt;
ssl_certificate_key /etc/nginx/ssl/{{ nginx_site }}.key;

        if ($request_uri !~ ^/(wp-|order-page))
        {
                rewrite ^ http://$host$request_uri? permanent;
        }

location / {
proxy_pass http://127.0.0.1:80;
proxy_redirect off;
proxy_buffering 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;
proxy_set_header X-Forwarded-Proto $scheme;
}
        location /nginx_status {
                stub_status on;
                access_log   off;
                allow all; 
                deny all;
        }
}
--snip


salt-call output:

--snip
    State: - file
    Name:      /etc/nginx/sites-enabled/testdomain1.com.conf
    Function:  managed
        Result:    False
        Comment:   Traceback (most recent call last):
  File "/usr/lib/python2.6/dist-packages/salt/utils/templates.py", line 99, in jinja
    data = template.render(**passthrough)
  File "/usr/lib/pymodules/python2.6/jinja2/environment.py", line 891, in render
    return self.environment.handle_exception(exc_info, True)
  File "/var/cache/salt/files/base/environments/prod/web/location1/files/nginx.conf.jinja", line 7, in top-level template code
    ssl_certificate_key /etc/nginx/ssl/{{ nginx_site }}.key;
UndefinedError: 'nginx_site' is undefined
--snip

is there a way to pass the value of "nginx_site" to the jinja template?  could this be done with a context setting or something?


thanks in advance


schlag

unread,
Nov 30, 2012, 12:42:07 PM11/30/12
to salt-...@googlegroups.com
i answered my own question :)   i was able to accomplish this by adding a context line to the sls.  is this a good way to do it, or might there be a better way?  i dont have my head around context 100% yet.

--snip
{% for nginx_site in pillar['nginx_sites'], %}

/etc/nginx/sites-enabled/{{ nginx_site }}.conf:
  file.managed:
    - template: jinja
    - source:   salt://environments/prod/web/location1/files/nginx.conf.jinja
    - user:     root
    - group:    root
    - mode:     644
    - require:
      - pkg:    nginx-full
    - context:
      nginx_site:     {{ nginx_site }}

{% endfor %}
--snip

schlag

unread,
Nov 30, 2012, 1:02:55 PM11/30/12
to salt-...@googlegroups.com
hm, so while adding context worked for passing the var to jinja template, the for loop doesn't seem to read in pillar values with multiple values, and cycle iteratively through them.  is this a bug, feature request or could i be doing it wrong?  thanks again

    State: - file
    Name:      /etc/nginx/sites-enabled/testdomain1.com testdomain2.com.conf
    Function:  managed
        Result:    True
        Comment:   File /etc/nginx/sites-enabled/testdomain1.com testdomain2.com.conf updated
        Changes:   diff: New file


ls -lac /etc/nginx/sites-enabled/
-rw-r--r-- 1 root root  835 Nov 30 12:58 testdomain1.com testdomain2.com.conf

Thomas S Hatch

unread,
Nov 30, 2012, 2:51:59 PM11/30/12
to salt-...@googlegroups.com
I think you might be ding something wrong, since I iterate over pillar values all the time. maybe a syntax issue?

schlag

unread,
Dec 13, 2012, 3:04:46 PM12/13/12
to salt-...@googlegroups.com
yeah, so after seeing another salt-users post, i discovered that what i wanted in pillar was actually something like this:

nginx_sites:            
  - testdomain2.com

instead of:

nginx_sites:     testdomain1.com testdomain2.com


works great

Thomas S Hatch

unread,
Dec 13, 2012, 3:52:23 PM12/13/12
to salt-...@googlegroups.com
Glad you figured it out! Thanks for posting the solution!

schlag

unread,
Dec 13, 2012, 3:55:29 PM12/13/12
to salt-...@googlegroups.com
argh, so i'm back to my original problem, which was passing values from state files to jinja templates.  while i can now iterate through pillar values, the jinja templates don't see to be inheriting the values. 


pillar top.sls:

--snip
nginx_sites:             
----------
    State: - file
    Name:      /etc/nginx/sites-enabled/testdomain1.conf
    Function:  managed
        Result:    False
        Comment:   An exception occured in this state: Traceback (most recent call last):
  File "/usr/lib/python2.6/dist-packages/salt/state.py", line 883, in call
    *cdata['args'], **cdata['kwargs'])
  File "/usr/lib/python2.6/dist-packages/salt/states/file.py", line 673, in managed
    **kwargs
  File "/usr/lib/python2.6/dist-packages/salt/modules/file.py", line 933, in get_managed
    context_dict.update(context)
AttributeError: 'list' object has no attribute 'update'

        Changes:   
----------
--snip


i've tried adding context & default values to the nginx.sls like so to no avail. 

nginx.sls:

--snip
{% for nginx_site in pillar['nginx_sites'], %}

/etc/nginx/sites-enabled/{{ nginx_site }}.conf:
  file.managed:
    - template: jinja
    - source:   salt://environments/prod/web/location1/files/nginx.conf.jinja
    - user:     root
    - group:    root
    - mode:     644
    - require:
      - pkg:    nginx-full
    - context:
      - site:    {{ nginx_site }}
    - defaults:
     - site:     {{ nginx_site }}

{% endfor %}
--snip


schlag

unread,
Dec 13, 2012, 4:34:26 PM12/13/12
to salt-...@googlegroups.com
my jinja template somehow went awol in my last update

--snip
server {
listen 443;
server_name {{ nginx_site }} *.{{ nginx_site }} 

ssl on;
ssl_certificate /etc/nginx/ssl/{{ nginx_site }}.chained.crt;

Denis Generalov

unread,
Dec 13, 2012, 7:02:21 PM12/13/12
to salt-...@googlegroups.com, schlag
> proxy_pass http://127.0.0.1:80 <http://127.0.0.1/>;
Try to remove minus before "site:"
context is a dictionary to my mind

> - defaults:
> - site: {{ nginx_site }}
>
> {% endfor %}
> --snip
>
>


--
Denis Generalov <gian...@gmail.com>

schlag

unread,
Dec 17, 2012, 9:55:00 AM12/17/12
to salt-...@googlegroups.com, schlag

yep! that did it.  thank you. 

so now the value of nginx_site is passed to the jinja template, the only problem is that it's being processed as the value of each domain along with quotes & brackets (eg ['domain1.com']) and is producing files like this:

file name:  /etc/nginx/sites-enabled/['fooldomain1.com']

file contents:

--snip
server {
listen 443;
server_name ['domain1.com'] *.['domain1.com'] 

ssl on;
ssl_certificate /etc/nginx/ssl/['domain1.com'].chained.crt;
ssl_certificate_key /etc/nginx/ssl/['domain1.com'].key;

        if ($request_uri !~ ^/(wp-|order-page))
        {
                rewrite ^ http://$host$request_uri? permanent;
        }

location / {
proxy_pass http://127.0.0.1:80;
proxy_redirect off;
proxy_buffering 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;
proxy_set_header X-Forwarded-Proto $scheme;
}
        location /nginx_status {
                stub_status on;
                access_log   off;
                allow all; 
                deny all;
        }
}
--snip

is there a way to cleanse the value of nginx_site by removing the single quotes & brackets, without having to build in knowledge of every single domain in the pillar list into the template?  (something like sed or tr)

thanks again

Jack Kuan

unread,
Dec 17, 2012, 10:09:46 AM12/17/12
to salt-...@googlegroups.com
Could you post the relevant section of your pillar file and sls file? It's likely that 'nginx_site' is defined as a list in yaml that's why you get ['domain1.com'].

-- 
Jack Kuan


This email and any files transmitted with it are confidential and intended solely for the recipient(s). If you are not the named addressee you should not disseminate, distribute, copy or alter this email. Any views or opinions presented in this email are solely those of the author and might not represent those of theScore, Inc. or any of its affiliates. Warning: Although theScore, Inc. has taken reasonable precautions to ensure no viruses are present in this email, the company cannot accept responsibility for any loss or damage arising from the use of this email or attachments.
Reply all
Reply to author
Forward
0 new messages