Parsing playbooks with full Jinja templating

101 views
Skip to first unread message

Anand Buddhdev

unread,
Feb 1, 2015, 7:15:48 PM2/1/15
to ansible...@googlegroups.com
Hi Ansible developers,

I've been wondering about something. Ansible's syntax for module arguments is key=value parameters, all on a single line. This then needs to be parsed, and the key=value elements properly separated.

Wouldn't it be much nicer if the module parameters were also just written in YAML syntax? For example:

- hosts: all
  tasks:
    - name: blah
      yum:
        - name: package
        - state: installed

And it might even be an idea to pass the playbook through Jinja first, allowing things like:

- name: blah
   yum:
{% for pkg in packages %}
    - name: "{{ pkg }}"
    - state: installed
{% endfor %}

We would not need the "when:" conditional, or the shlex module to split key=value pairs. This would allow taking full advantage of Jinja's templating features.

Could this be an idea for Ansible 2.0?

Regards,
Anand

Tom Bamford

unread,
Feb 1, 2015, 7:25:10 PM2/1/15
to ansible...@googlegroups.com

Hi Anand

You actually can (and I prefer to) write your playbooks with that kind of plain YAML syntax. e.g.

- hosts: localhost
  tasks:
    - name: blah
      yum:
        name:
          - mypackage
          - otherpackage
        state: present
    - name: blurh
      copy:
        src: myfile
        dest: /tmp/myfile
        mode: 0640
        owner: me

It gets more interesting with the shell and command modules

- hosts: localhost
  tasks:
    - name: run this
      shell: mycommand
      args:
        creates: /tmp/artefact
        chdir: /path/to/dir
        executable: /bin/bash

--
You received this message because you are subscribed to the Google Groups "Ansible Project" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ansible-proje...@googlegroups.com.
To post to this group, send email to ansible...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/ansible-project/34adf7d7-5d32-459d-a3a3-8fe02d049271%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Anand Buddhdev

unread,
Feb 1, 2015, 7:33:57 PM2/1/15
to ansible...@googlegroups.com
Thanks Tom! I didn't realise it was already possible! So I can also use Jinja functions in a playbook to include/exclude some parameters based on facts?
You received this message because you are subscribed to a topic in the Google Groups "Ansible Project" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/ansible-project/dGJRlrohfmY/unsubscribe.
To unsubscribe from this group and all its topics, send an email to ansible-proje...@googlegroups.com.

To post to this group, send email to ansible...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/ansible-project/CAAnNz0NnD0x08r0ODROxGEf8sQtFFKKe2ACVux6EXysgvC7uzQ%40mail.gmail.com.

Giovanni Tirloni

unread,
Feb 1, 2015, 7:34:10 PM2/1/15
to ansible...@googlegroups.com
On Mon, 02 Feb 2015 02:24 +0200, Tom Bamford <t...@atpla.net> wrote:
> You actually can (and I prefer to) write your playbooks with that kind of plain YAML syntax. e.g.

Same here. Otherwise I've found sometimes I have to decide which one to
use, where to put quotes, etc. I just go 100% YAML and the INI files.

Ansible's syntax with the equal signs is more concise but I don't mind
the extra lines with YAML.

Giovanni

Anand Buddhdev

unread,
Feb 2, 2015, 4:58:37 AM2/2/15
to ansible...@googlegroups.com
Hi Tom,

I just tried the syntax you suggested.

My very simple playbook is:

- hosts: myhost
  tasks:
    - name: install packages
       yum:
         name:
           - screen
           - tmux
         state: installed

However, when I run this, I get an errors:

SUDO-SUCCESS-ziubbkxxzglhrtsmdmekoixffubflanc
Traceback (most recent call last):
  File "/tmp/ansible-tmp-1422870182.84-7050423984136/yum", line 2402, in <module>
    main()
  File "/tmp/ansible-tmp-1422870182.84-7050423984136/yum", line 832, in main
    disablerepo, disable_gpg_check)
  File "/tmp/ansible-tmp-1422870182.84-7050423984136/yum", line 717, in ensure
    items = pkgspec.split(',')
AttributeError: 'list' object has no attribute 'split'


Are you certain that plain YAML syntax works for modules?


--
You received this message because you are subscribed to a topic in the Google Groups "Ansible Project" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/ansible-project/dGJRlrohfmY/unsubscribe.
To unsubscribe from this group and all its topics, send an email to ansible-proje...@googlegroups.com.

To post to this group, send email to ansible...@googlegroups.com.

Giovanni Tirloni

unread,
Feb 2, 2015, 5:10:38 AM2/2/15
to ansible...@googlegroups.com
On Mon, 02 Feb 2015 10:58 +0100, Anand Buddhdev <arh...@gmail.com>
wrote:
> Hi Tom,
>
> I just tried the syntax you suggested.
>
> My very simple playbook is:
>
> - hosts: myhost
>   tasks:
>     - name: install packages
>        yum:
>          name:
>            - screen
>            - tmux
>          state: installed
>

- hosts: myhost
tasks:
- name: install packages
yum:
name: "{{ item }}"
state: latest
with_items:
- screen
- tmux


Useful reading:
http://docs.ansible.com/playbooks_loops.html

Giovanni

Anand Buddhdev

unread,
Feb 2, 2015, 5:34:34 AM2/2/15
to ansible...@googlegroups.com
Hi Giovanni,

Your suggestion works. But I think what I was trying to say is that Ansible's playbook syntax is mixed. Wouldn't it be cool if it were pure YAML, with Jinja templating? Then it would allow something like:

- hosts: myhost
  tasks:
    - name: install packages
       yum:
         name:
           - tmux
           - screen
{% if ansible_distribution_major_version == '6' %}
           - lsof
{% endif %}

Instead of inventing ansible-specific loops, we could just use the power of Jinja templating.

--
You received this message because you are subscribed to a topic in the Google Groups "Ansible Project" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/ansible-project/dGJRlrohfmY/unsubscribe.
To unsubscribe from this group and all its topics, send an email to ansible-proje...@googlegroups.com.
To post to this group, send email to ansible...@googlegroups.com.

Giovanni Tirloni

unread,
Feb 2, 2015, 6:19:16 AM2/2/15
to ansible...@googlegroups.com
On Mon, 02 Feb 2015 11:34 +0100, Anand Buddhdev <arh...@gmail.com>
wrote:
> Hi Giovanni,
>
> Your suggestion works. But I think what I was trying to say is that
> Ansible's playbook syntax is mixed. Wouldn't it be cool if it were pure
> YAML, with Jinja templating? Then it would allow something like:
>
> - hosts: myhost
> tasks:
> - name: install packages
> yum:
> name:
> - tmux
> - screen
> {% if ansible_distribution_major_version == '6' %}
> - lsof
> {% endif %}
>
> Instead of inventing ansible-specific loops, we could just use the power
> of
> Jinja templating.

As an Ansible newbie, I have struggled with understanding where it's
Ansible or Jinja2 doing the parsing. So I can surely related to that. On
the other hand, Ansible tries to be simple and the looping constructs,
IMHO, are easy to work with and have a concise syntax.

I don't have enough experience with Ansible to suggest where it should
go next.

In my so far very limited knowledge of Ansible, I would suggest
encapsulating these things in different roles (e.g. common_debian,
common_centos6, common_centos7). It seems more idiomatic in Ansible,
based on the examples I've seen so far.


Giovanni

Tom Bamford

unread,
Feb 2, 2015, 6:48:44 AM2/2/15
to ansible...@googlegroups.com

Hi Anand

Are you sure your indenting is correct? Here’s an example from one of my role task files, known working with Ansible v1.8.2 (packages trimmed for brevity)

---
- name: Install packages (apt)
  apt:
    pkg:
      - bash-completion
      - bind9utils
      - vim-nox
      - zsh
    state: present
  when: ansible_os_family == 'Debian'

- name: Install packages (yum)
  yum:
    name:
      - bind-utils
      - byobu
      - vim-enhanced
      - zsh
    state: present
  when: ansible_os_family == 'RedHat'

--
You received this message because you are subscribed to the Google Groups "Ansible Project" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ansible-proje...@googlegroups.com.

To post to this group, send email to ansible...@googlegroups.com.

Tom Bamford

unread,
Feb 2, 2015, 6:52:52 AM2/2/15
to ansible...@googlegroups.com

Jinja templating doesn’t work in playbooks in that way. Lots of variable constructs are actually parsed with jinja2, so you can do stuff like

- set_fact:
    myvar: "{% if something %}this{% else %}that{% endif %}"

As Giovanni mentioned, there are numerous looping constructs for things like task repetition. Playbooks are declarative, so it wouldn’t really be right to build them from a template.

--
You received this message because you are subscribed to the Google Groups "Ansible Project" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ansible-proje...@googlegroups.com.

To post to this group, send email to ansible...@googlegroups.com.

Anand Buddhdev

unread,
Feb 2, 2015, 10:13:08 AM2/2/15
to ansible...@googlegroups.com
Hello Tom,

I am certain that my syntax and indentation is correct. I have created a test role, called packages, and in the main.yml file of the tasks directory of this role, I have:

---

- name: install packages

  yum:

    name:

      - screen

      - tmux

      - lsof

    state: present

However, running this role results in:

SUDO-SUCCESS-fwkqifljtkdcrlzyrnukmprtmiczpknk

Traceback (most recent call last):
  File "/tmp/ansible-tmp-1422889693.47-234739679264274/yum", line 2402, in <module>
    main()
  File "/tmp/ansible-tmp-1422889693.47-234739679264274/yum", line 832, in main
    disablerepo, disable_gpg_check)
  File "/tmp/ansible-tmp-1422889693.47-234739679264274/yum", line 717, in ensure

    items = pkgspec.split(',')
AttributeError: 'list' object has no attribute 'split'


$ ansible --version

ansible 1.8.2

  configured module search path = None

Anand Buddhdev

unread,
Feb 2, 2015, 10:17:23 AM2/2/15
to ansible...@googlegroups.com
On 2 February 2015 at 12:19, Giovanni Tirloni <g...@gtirloni.com> wrote:

As an Ansible newbie, I have struggled with understanding where it's
Ansible or Jinja2 doing the parsing. So I can surely related to that. On
the other hand, Ansible tries to be simple and the looping constructs,
IMHO, are easy to work with and have a concise syntax.

Hi Giovanni,

My thinking is similar. Ansible playbooks are parsed in a strange way. Some parts of it are plain YAML, whereas other parts are run through the Jinja2 templating engine. This is confusing.

I was reading Salt documentation, and saw that Salt's state files are just plain YAML, but the entire YAML file is passed through Jinja2, so that any loops and other variable things are done by Jinja2, and this is conceptually neater than Ansible's current mix of Jinja2 and Ansible's own declarative language.

Anand Buddhdev

unread,
Feb 2, 2015, 10:21:38 AM2/2/15
to ansible...@googlegroups.com
On 2 February 2015 at 12:52, Tom Bamford <t...@atpla.net> wrote:

Hi Tom,

Jinja templating doesn’t work in playbooks in that way. Lots of variable constructs are actually parsed with jinja2, so you can do stuff like

- set_fact:
    myvar: "{% if something %}this{% else %}that{% endif %}"

As Giovanni mentioned, there are numerous looping constructs for things like task repetition. Playbooks are declarative, so it wouldn’t really be right to build them from a template.

I understand this, and it is exactly what I am trying to discuss here. Why can't one build a playbook from a template? I think plain YAML is just fine for declarative statements. Or am I missing a use case?
Reply all
Reply to author
Forward
0 new messages