{"id":2131,"date":"2017-10-18T19:48:08","date_gmt":"2017-10-19T00:48:08","guid":{"rendered":"http:\/\/osric.com\/chris\/accidental-developer\/?p=2131"},"modified":"2017-10-21T18:23:34","modified_gmt":"2017-10-21T23:23:34","slug":"ansible-conditional-check-failed","status":"publish","type":"post","link":"https:\/\/osric.com\/chris\/accidental-developer\/2017\/10\/ansible-conditional-check-failed\/","title":{"rendered":"Ansible conditional check failed"},"content":{"rendered":"<p>I wanted to add a check to one of my <a href=\"https:\/\/www.ansible.com\/\">Ansible<\/a> roles so that an application source would be copied and the source recompiled only if no current version existed or if the existing version did not match the expected version:<\/p>\n<pre><code>- name: Check to see if app is installed and the expected version\r\n  command: \/usr\/local\/app\/bin\/app --version\r\n  register: version_check\r\n  ignore_errors: True\r\n  changed_when: \"version_check.rc != 0 or {{ target_version }} not in version_check.stdout\"\r\n\r\n- name: include app install\r\n  include: tasks\/install.yml\r\n  when: \"version_check.rc != 0 or {{ target_version }} not in version_check.stdout\"<\/code><\/pre>\n<p>I defined the target version in my role&#8217;s <code>defaults\/main.yml<\/code>:<\/p>\n<pre><code>---\r\ntarget_version: \"2.5.2\"\r\n...<\/code><\/pre>\n<p>The first time I ran it, I encountered an error:<\/p>\n<pre><code>fatal: [trinculo.osric.net]: FAILED! =&gt; {\"failed\": true, \"msg\": \"The conditional check 'version_check.rc != 0 or {{ target_version }} not in version_check.stdout' failed. The error was: error while evaluating conditional (version_check.rc != 0 or {{ target_version }} not in version_check.stdout): Unable to look up a name or access an attribute in template string ({% if version_check.rc != 0 or 2.5.2 not in version_check.stdout %} True {% else %} False {% endif %}).\\nMake sure your variable name does not contain invalid characters like '-': coercing to Unicode: need string or buffer, StrictUndefined found\"}<\/code><\/pre>\n<p>It&#8217;s a little unclear what is wrong, so I figured it was likely an issue with quotes or a lack of parentheses.<\/p>\n<p>First I tried parentheses:<\/p>\n<pre><code>changed_when: \"version_check.rc != 0 or ({{ target_version }} not in version_check.stdout)\"<\/code><\/pre>\n<p>No luck.<\/p>\n<pre><code>changed_when: \"version_check.rc != 0 or !('{{ target_version }}' in version_check.stdout)\"<\/code><\/pre>\n<p>You know, trying to google <em>and<\/em> or <em>not<\/em> or <em>or<\/em> or <em>is<\/em> is tricky. Even if you add terms like <em>Boolean logic<\/em> or <em>propositional calculus<\/em>.<\/p>\n<p>I tried to break it down into smaller parts:<\/p>\n<pre><code>changed_when: \"version_check.rc != 0\"<\/code><\/pre>\n<p>That worked.<\/p>\n<pre><code>changed_when: \"!('{{ target_version }}' in version_check.stdout)\"<\/code><\/pre>\n<p>A different error appeared:<\/p>\n<pre><code>template error while templating string: unexpected char u'!'<\/code><\/pre>\n<p>OK, that&#8217;s getting somewhere! Try a variation:<\/p>\n<pre><code>changed_when: \"'{{ target_version }}' not in version_check.stdout\"<\/code><\/pre>\n<p>It worked! But with a warning:<\/p>\n<pre><code>[WARNING]: when statements should not include jinja2 templating delimiters\r\nsuch as {{ }} or {% %}. Found: ('{{ target_version }}' not in version_check.stdout)<\/code><\/pre>\n<p>Next try:<\/p>\n<pre><code>changed_when: \"target_version not in version_check.stdout\"<\/code><\/pre>\n<p>That worked, and without any warnings. I put the <em>or<\/em> back in:<\/p>\n<pre><code>changed_when: \"version_check.rc != 0 or target_version not in version_check.stdout\"<\/code><\/pre>\n<p>That worked! It was the <a href=\"http:\/\/jinja.pocoo.org\/docs\/2.9\/\">jinja2<\/a> delimiters the whole time. The value of the <code>changed_when<\/code> key is already interpreted as jinja2 apparently, so the delimiters were redundant. Even though it succeeded (with a warning) in a single propositional statement, it failed when the logical disjunction was added. It was an important reminder: error messages aren&#8217;t perfect.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>While  working with Ansible I encountered &#8220;error while evaluating conditional&#8221; &#8212; this post describes the many things I tried that didn&#8217;t work, as well as what I tried that did work.<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[439],"tags":[423,469,470],"class_list":["post-2131","post","type-post","status-publish","format-standard","hentry","category-ansible","tag-ansible","tag-jinja2","tag-yaml"],"_links":{"self":[{"href":"https:\/\/osric.com\/chris\/accidental-developer\/wp-json\/wp\/v2\/posts\/2131","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/osric.com\/chris\/accidental-developer\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/osric.com\/chris\/accidental-developer\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/osric.com\/chris\/accidental-developer\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/osric.com\/chris\/accidental-developer\/wp-json\/wp\/v2\/comments?post=2131"}],"version-history":[{"count":8,"href":"https:\/\/osric.com\/chris\/accidental-developer\/wp-json\/wp\/v2\/posts\/2131\/revisions"}],"predecessor-version":[{"id":2165,"href":"https:\/\/osric.com\/chris\/accidental-developer\/wp-json\/wp\/v2\/posts\/2131\/revisions\/2165"}],"wp:attachment":[{"href":"https:\/\/osric.com\/chris\/accidental-developer\/wp-json\/wp\/v2\/media?parent=2131"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/osric.com\/chris\/accidental-developer\/wp-json\/wp\/v2\/categories?post=2131"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/osric.com\/chris\/accidental-developer\/wp-json\/wp\/v2\/tags?post=2131"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}