How to use a Python expression instead of a Jinja expression in changed_when?

Hello,

changed_when is extremely useful and a very nice addition to Ansible!

I’m wondering how to use a Python expression instead of a Jinja expression in changed_when?

On a more general level, the documentation is not very explicit about the kind of expression (Python and/or Jinja) accepted by Ansible playbooks.

I’m curious to know what are the reasons for pushing the Jinja more restricted syntax over the Python syntax?

Nicolas

You can only use Jinja2 expressions.

Why? We don’t want playbooks to become arbitrary Python hackjobs. Ansible is not a Python tool – something that is only appealing to Python developers. Rather, it’s a tool that is written in Python.

Jinja2 templating allows us direct access to all of our variables with reasonable constrains without allowing you to do things like “os.system()” in the middle of an operation.

You can only use Jinja2 expressions.

Thank you Michael for this confirmation.

Why? We don't want playbooks to become arbitrary Python hackjobs.

Ansible is not a Python tool -- something that is only appealing to Python
developers. Rather, it's a tool that is written in Python.

Ansible is not a Python tool, but it's neither a Jinja tool :slight_smile:

I would argue that very few developers outside the Python ecosystem know
Jinja, which makes playbooks with Jinja expressions even more "Pythonesque"
than playbooks with Python expressions.

It definitely makes sense to restrict Python to Ansible internals as much
as possible, and not let it "bleed" into the public API. (It was the reason
behind the pull request I made a few months ago to remove Python specific
quoting from Ansible playbooks.)

Yet, playbooks still need an expression language, and whatever syntax is
used, Jinja or Python's one, they are both a "foreign" syntax into Ansible
playbooks. I'm not sure to understand why a Ruby or a Perl developer would
be more comfortable with Jinja's syntax than Python's one:
- Jinja's syntax is less documented than Python's syntax which has
excellent documentation.
- Jinja's syntax is perfect for a templating engine, but I doubt it's a
good fit for an orchestration tool. Python's syntax is more general and
closer to what people use in mainstream languages (Java, C, JavaScript,
Ruby, Perl, PHP, etc.).

Jinja2 templating allows us direct access to all of our variables with

reasonable constrains without allowing you to do things like "os.system()"
in the middle of an operation.

I understand this argument in theory. But is it a problem in practice (i.e.
having someone abusing the playbook expressions and breaking Ansible
expected behavior)?

it’s only a problem if you try to program in your playbooks, which is against the entire aesthetic of Ansible.

If there are cases where you think we need to document things more, the documentation is an open source project that is easy to contribute to:

docsite/latest/rst/*.rst in the checkout.

It should only be used for simple expressions.

Hello Michael,

Yep, Jinja2 expressions are basically Python unless you’re trying to do any kind of advanced Python.

I’d rather explain what they look like than for people to have to think they need to learn a lot of details of the templating system.

<http://www.vocationcity.com/&gt;
Would you accept a pull request that replaces:

*"This is easy to do in Ansible, with the when clause, which actually is a
Python expression."

Sure!

It should also give some examples, but I think it already does.

when: foo == 12

when: foo == “cat”

Note: things like list comprehensions, a Python programming feature, are not supported

etc

Hello Michael,

Pull request here: https://github.com/ansible/ansible/pull/4040

:slight_smile:

Given this (and perhaps I'm not familiar enough with Jinja2), how do you
craft a play that takes into account, say, the presence of a row in a
database? In salt I'd do something like:

psql -c "create extension if not exists adminpack":
  cmd.run:
    - onlyif: "[ $(psql -tc \"select count(*)
                                from pg_extension
                               where extname='adminpack'\") == 0 ]"

Is there an Ansible analog?

(I do realize that the test isn't absolutely necessary in this
particular example but I hope the intention is clear.)

k.

I’d be very inclined to use a register statement to make the test and then use the when statement.

Let’s not mention that other tool here, least I tell you what I really think of it :slight_smile:

you can use a shell/command task +registered variable or even the pipe
lookup plugin

How do you escape single quotes?