<?xml version='1.0' encoding='utf-8'?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title>Radek Sprta (Posts about ansible)</title><link>https://radeksprta.eu/</link><description/><atom:link href="https://radeksprta.eu/categories/ansible.xml" rel="self" type="application/rss+xml"/><language>en</language><copyright>© 2025 &lt;a href="mailto:mail@radeksprta.eu"&gt;Radek Sprta&lt;/a&gt; 
&lt;a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/"&gt;CC BY-SA 4.0&lt;/a&gt;
</copyright><lastBuildDate>Thu, 27 Nov 2025 13:10:11 GMT</lastBuildDate><generator>Nikola (getnikola.com)</generator><docs>http://blogs.law.harvard.edu/tech/rss</docs><item><title>Level Up Your YAML: Tips For Advanced Usage</title><link>https://radeksprta.eu/posts/level-up-your-yaml/</link><dc:creator>Radek Sprta</dc:creator><description>&lt;div&gt;&lt;p&gt;Leveraged by tools such Ansible &amp;amp; Kubernetes, YAML has become a ubiqitous configuration format over the last decade. It owes its high adoption
rate can be attributed to its simple design. It is consise yet readable, thanks to its minimal use of syntactical marks. However, under the 
surface it is surprisingly complex. This post aims to introduce some of its features you might not be aware of.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://radeksprta.eu/posts/level-up-your-yaml/"&gt;Read more…&lt;/a&gt; (3 min remaining to read)&lt;/p&gt;&lt;/div&gt;</description><category>ansible</category><category>configuration</category><category>kubernetes</category><category>yaml</category><guid>https://radeksprta.eu/posts/level-up-your-yaml/</guid><pubDate>Fri, 29 Dec 2023 22:19:42 GMT</pubDate></item><item><title>ansible_user Is Undefined on Localhost</title><link>https://radeksprta.eu/posts/ansible_user-is-undefined-on-localhost/</link><dc:creator>Radek Sprta</dc:creator><description>&lt;div&gt;&lt;p&gt;I rely on Ansible for &lt;a href="https://radeksprta.eu/posts/automatically-setup-computer-ansible-playbook/"&gt;configuring my workstation&lt;/a&gt;, so I can easily synchronize it across multiple computer. However, I recently ran into an intriguing issue when my playbook failed with the following error after adding a third-party role:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;'ansible_user' is undefined&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;This puzzled me, because by default all &lt;code&gt;ansible_*&lt;/code&gt; variables should be automatically populated, unless gather_facts has been explicitly disabled.
It turns out that this behavior does not apply for &lt;code&gt;ansible_user&lt;/code&gt;, if you run the playbook on localhost with a local connection instead of SSH.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://radeksprta.eu/posts/ansible_user-is-undefined-on-localhost/"&gt;Read more…&lt;/a&gt; (1 min remaining to read)&lt;/p&gt;&lt;/div&gt;</description><category>ansible</category><category>error</category><category>localhost</category><guid>https://radeksprta.eu/posts/ansible_user-is-undefined-on-localhost/</guid><pubDate>Wed, 21 Jun 2023 23:33:55 GMT</pubDate></item><item><title>Start AWX Job Via API</title><link>https://radeksprta.eu/posts/start-awx-job-via-api/</link><dc:creator>Radek Sprta</dc:creator><description>&lt;p&gt;If you are using Ansible, there is high change you are also using &lt;a href="https://github.com/ansible/awx"&gt;AWX&lt;/a&gt; (or Ansible Tower) to orchestrate your jobs. And you might want trigger AWX jobs externally in some cases, such as from your CI pipeline. Luckily, AWX has an &lt;a href="https://docs.ansible.com/ansible-tower/latest/html/towerapi/api_ref.html"&gt;API&lt;/a&gt; that allows you to do just that.&lt;/p&gt;
&lt;p&gt;To run AWX jobs remotely, you will need to make 3 API calls. One to start the job itself, another one to monitor its progress and lastly a request to print the output. You can see sample code to do that in bash shell below. In order to keep things simple, it uses authentication token, but you could also use OAuth 2.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;POLLING_SLEEP=30

function&lt;span class="w"&gt; &lt;/span&gt;print_job_output()&lt;span class="w"&gt; &lt;/span&gt;{
&lt;span class="w"&gt;  &lt;/span&gt;api_request&lt;span class="w"&gt; &lt;/span&gt;GET&lt;span class="w"&gt; &lt;/span&gt;"/jobs/&lt;span class="cp"&gt;${&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="cp"&gt;}&lt;/span&gt;/stdout/?format=txt"
}

response=$(
&lt;span class="w"&gt;  &lt;/span&gt;curl&lt;span class="w"&gt; &lt;/span&gt;-s&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;-o&lt;span class="w"&gt; &lt;/span&gt;-&lt;span class="w"&gt; &lt;/span&gt;"&lt;span class="cp"&gt;${&lt;/span&gt;&lt;span class="n"&gt;AWX_API&lt;/span&gt;&lt;span class="cp"&gt;}&lt;/span&gt;/job_templates/&lt;span class="cp"&gt;${&lt;/span&gt;&lt;span class="n"&gt;TEMPLATE_ID&lt;/span&gt;&lt;span class="cp"&gt;}&lt;/span&gt;/launch/"&lt;span class="w"&gt; &lt;/span&gt;\
&lt;span class="w"&gt;    &lt;/span&gt;-H&lt;span class="w"&gt; &lt;/span&gt;"Authorization:&lt;span class="w"&gt; &lt;/span&gt;Bearer&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;${&lt;/span&gt;&lt;span class="n"&gt;API_TOKEN&lt;/span&gt;&lt;span class="cp"&gt;}&lt;/span&gt;"&lt;span class="w"&gt; &lt;/span&gt;\
&lt;span class="w"&gt;    &lt;/span&gt;-H&lt;span class="w"&gt; &lt;/span&gt;"Content-Type:&lt;span class="w"&gt; &lt;/span&gt;application/json"&lt;span class="w"&gt; &lt;/span&gt;\
&lt;span class="w"&gt;    &lt;/span&gt;-XPOST
)

http_status=$(head&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;1&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt;"&lt;span class="cp"&gt;${&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="cp"&gt;}&lt;/span&gt;"&lt;span class="w"&gt; &lt;/span&gt;|&lt;span class="w"&gt; &lt;/span&gt;awk&lt;span class="w"&gt; &lt;/span&gt;'{print&lt;span class="w"&gt; &lt;/span&gt;$2}')
body=$(grep&lt;span class="w"&gt; &lt;/span&gt;'^{'&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt;"&lt;span class="cp"&gt;${&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="cp"&gt;}&lt;/span&gt;")

if&lt;span class="w"&gt; &lt;/span&gt;[[&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;${&lt;/span&gt;&lt;span class="n"&gt;http_status&lt;/span&gt;&lt;span class="cp"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;!=&lt;span class="w"&gt; &lt;/span&gt;201&lt;span class="w"&gt; &lt;/span&gt;]];&lt;span class="w"&gt; &lt;/span&gt;then
&lt;span class="w"&gt;  &lt;/span&gt;echo&lt;span class="w"&gt; &lt;/span&gt;"AWX&lt;span class="w"&gt; &lt;/span&gt;returned&lt;span class="w"&gt; &lt;/span&gt;error."
&lt;span class="w"&gt;  &lt;/span&gt;exit&lt;span class="w"&gt; &lt;/span&gt;1
fi

id=$(jq&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt;"&lt;span class="cp"&gt;${&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="cp"&gt;}&lt;/span&gt;"&lt;span class="w"&gt; &lt;/span&gt;'.id')
echo&lt;span class="w"&gt; &lt;/span&gt;"Monitoring&lt;span class="w"&gt; &lt;/span&gt;job&lt;span class="w"&gt; &lt;/span&gt;ID:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;${&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="cp"&gt;}&lt;/span&gt;"
while&lt;span class="w"&gt; &lt;/span&gt;true;&lt;span class="w"&gt; &lt;/span&gt;do
&lt;span class="w"&gt;  &lt;/span&gt;echo&lt;span class="w"&gt; &lt;/span&gt;"Sleeping&lt;span class="w"&gt; &lt;/span&gt;for&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;${&lt;/span&gt;&lt;span class="n"&gt;POLLING_SLEEP&lt;/span&gt;&lt;span class="cp"&gt;}&lt;/span&gt;s"
&lt;span class="w"&gt;  &lt;/span&gt;sleep&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$POLLING_SLEEP&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;response="$(api_request&lt;span class="w"&gt; &lt;/span&gt;GET&lt;span class="w"&gt; &lt;/span&gt;"/jobs/&lt;span class="cp"&gt;${&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="cp"&gt;}&lt;/span&gt;/"&lt;span class="w"&gt; &lt;/span&gt;-i)"

&lt;span class="w"&gt;  &lt;/span&gt;http_status=$(head&lt;span class="w"&gt; &lt;/span&gt;-n&lt;span class="w"&gt; &lt;/span&gt;1&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt;"&lt;span class="cp"&gt;${&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="cp"&gt;}&lt;/span&gt;"&lt;span class="w"&gt; &lt;/span&gt;|&lt;span class="w"&gt; &lt;/span&gt;awk&lt;span class="w"&gt; &lt;/span&gt;'{print&lt;span class="w"&gt; &lt;/span&gt;$2}')
&lt;span class="w"&gt;  &lt;/span&gt;body=$(grep&lt;span class="w"&gt; &lt;/span&gt;'^{'&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt;"&lt;span class="cp"&gt;${&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="cp"&gt;}&lt;/span&gt;")
&lt;span class="w"&gt;  &lt;/span&gt;if&lt;span class="w"&gt; &lt;/span&gt;[[&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;${&lt;/span&gt;&lt;span class="n"&gt;http_status&lt;/span&gt;&lt;span class="cp"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;!=&lt;span class="w"&gt; &lt;/span&gt;200&lt;span class="w"&gt; &lt;/span&gt;]];&lt;span class="w"&gt; &lt;/span&gt;then
&lt;span class="w"&gt;    &lt;/span&gt;echo&lt;span class="w"&gt; &lt;/span&gt;"AWX&lt;span class="w"&gt; &lt;/span&gt;returned&lt;span class="w"&gt; &lt;/span&gt;error."
&lt;span class="w"&gt;    &lt;/span&gt;exit&lt;span class="w"&gt; &lt;/span&gt;1
&lt;span class="w"&gt;  &lt;/span&gt;fi

&lt;span class="w"&gt;  &lt;/span&gt;status="$(jq&lt;span class="w"&gt; &lt;/span&gt;-r&lt;span class="w"&gt; &lt;/span&gt;'.status'&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt;"&lt;span class="cp"&gt;${&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="cp"&gt;}&lt;/span&gt;")"
&lt;span class="w"&gt;  &lt;/span&gt;if&lt;span class="w"&gt; &lt;/span&gt;[[&lt;span class="w"&gt; &lt;/span&gt;"&lt;span class="cp"&gt;${&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="cp"&gt;}&lt;/span&gt;"&lt;span class="w"&gt; &lt;/span&gt;==&lt;span class="w"&gt; &lt;/span&gt;"failed"&lt;span class="w"&gt; &lt;/span&gt;]];&lt;span class="w"&gt; &lt;/span&gt;then
&lt;span class="w"&gt;    &lt;/span&gt;echo&lt;span class="w"&gt; &lt;/span&gt;"Job&lt;span class="w"&gt; &lt;/span&gt;failed."
&lt;span class="w"&gt;    &lt;/span&gt;print_job_output
&lt;span class="w"&gt;    &lt;/span&gt;exit&lt;span class="w"&gt; &lt;/span&gt;1
&lt;span class="w"&gt;  &lt;/span&gt;elif&lt;span class="w"&gt; &lt;/span&gt;[[&lt;span class="w"&gt; &lt;/span&gt;"&lt;span class="cp"&gt;${&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="cp"&gt;}&lt;/span&gt;"&lt;span class="w"&gt; &lt;/span&gt;==&lt;span class="w"&gt; &lt;/span&gt;"successful"&lt;span class="w"&gt; &lt;/span&gt;]];&lt;span class="w"&gt; &lt;/span&gt;then
&lt;span class="w"&gt;    &lt;/span&gt;echo&lt;span class="w"&gt; &lt;/span&gt;"Job&lt;span class="w"&gt; &lt;/span&gt;has&lt;span class="w"&gt; &lt;/span&gt;finished&lt;span class="w"&gt; &lt;/span&gt;successfully."
&lt;span class="w"&gt;    &lt;/span&gt;print_job_output
&lt;span class="w"&gt;    &lt;/span&gt;exit&lt;span class="w"&gt; &lt;/span&gt;0
&lt;span class="w"&gt;  &lt;/span&gt;fi
done
&lt;/pre&gt;&lt;/div&gt;</description><category>ansible</category><category>api</category><category>awx</category><category>ci</category><guid>https://radeksprta.eu/posts/start-awx-job-via-api/</guid><pubDate>Sat, 03 Dec 2022 21:18:22 GMT</pubDate></item><item><title>Control Whitespace in Ansible Templates</title><link>https://radeksprta.eu/posts/control-whitespace-in-ansible-templates/</link><dc:creator>Radek Sprta</dc:creator><description>&lt;div&gt;&lt;p&gt;Ansible uses the powerful Jinja templating engine. However, the way it handles whitespace in templates is not ideal. Specifically, the fact that it preserves leading whitespace around Jinja blocks. So, you can either not indent Jinja syntax, making the templates hard to comprehend, or accept broken indentation in the resulting file (not an option with whitespace-sensitive formats such as yaml).&lt;/p&gt;
&lt;p&gt;Luckily, there is a third option. Jinja has two configuration options regarding whitespace:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://radeksprta.eu/posts/control-whitespace-in-ansible-templates/"&gt;Read more…&lt;/a&gt; (1 min remaining to read)&lt;/p&gt;&lt;/div&gt;</description><category>ansible</category><category>jinja</category><category>template</category><category>whitespace</category><guid>https://radeksprta.eu/posts/control-whitespace-in-ansible-templates/</guid><pubDate>Sat, 02 Jan 2021 11:13:38 GMT</pubDate></item><item><title>Modify All Items in Ansible List</title><link>https://radeksprta.eu/posts/modify-all-items-in-ansible-list/</link><dc:creator>Radek Sprta</dc:creator><description>&lt;p&gt;Ansible lets you easily interpolate list items within values (like &lt;code&gt;interpolated_{{ item }}_value&lt;/code&gt;). However, sometimes you need a more powerful transformation. This is where the map filter comes to rescue again. You can use it to perform regular expression replace on each item in a list. As you can see, the syntax is relatively simple:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="nb"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'regex_replace'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;REGEX_PATTERN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;OUTPUT&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;For a concrete example, let us say you want to extract network mask from a list of IP addresses (&lt;code&gt;192.168.0.100/24&lt;/code&gt; for example). Assuming this list is stored in the &lt;code&gt;ip_addresses&lt;/code&gt; variable, the regex replace would look like this:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="n"&gt;ip_addresses&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'regex_replace'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'.*/([0-9]{1,2})'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s1"&gt;1'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Of course, you can easily use it as a part of longer jinja2 pipelines. If you also want to learn how to &lt;a href="https://radeksprta.eu/posts/loop-over-dictionary-attribute-in-ansible/"&gt;loop over dictionary attribute&lt;/a&gt;, or see other Ansible tips, take a look &lt;a href="https://radeksprta.eu/categories/ansible/"&gt;here&lt;/a&gt;.&lt;/p&gt;</description><category>ansible</category><category>automation</category><category>filter</category><guid>https://radeksprta.eu/posts/modify-all-items-in-ansible-list/</guid><pubDate>Sat, 08 Aug 2020 06:58:40 GMT</pubDate></item><item><title>Loop Over Dictionary Attribute in Ansible</title><link>https://radeksprta.eu/posts/loop-over-dictionary-attribute-in-ansible/</link><dc:creator>Radek Sprta</dc:creator><description>&lt;p&gt;Working with variables can sometimes get tricky in Ansible. Say, you have a dictionary where you want loop over a certain attribute, not all values. For example, when your variables are declared like this:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="nt"&gt;interfaces&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;eth0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ip&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;10.0.0.10&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;mask&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;16&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;eth1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;ip&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;192.168.1.100&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;mask&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;24&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;How do you just loop over all the IP addresses? This is where the map filter comes in:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="nt"&gt;vars&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;ip_addresses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;interfaces.values()&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;|&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;map(attribute='container')&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;|&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;list&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}"&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The snippet takes all values from the &lt;code&gt;interfaces&lt;/code&gt; dictionary (&lt;code&gt;eth0&lt;/code&gt;, &lt;code&gt;eth1&lt;/code&gt;) and then extracts the &lt;code&gt;ip&lt;/code&gt; attribute from them. Finally, it casts the result into list.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://docs.ansible.com/ansible/latest/user_guide/playbooks_filters.html"&gt;Ansible filters&lt;/a&gt; are a very powerful tool, so I would recommend you take some time to read it thoroughly. If you are looking for more Ansible tips, such as &lt;a href="https://radeksprta.eu/posts/make-ansible-playbook-distribution-agnostic"&gt;how to make a playbook distribution agnostic&lt;/a&gt; or &lt;a href="https://radeksprta.eu/posts/automatically-setup-computer-ansible-playbook"&gt;setup your laptop with Ansible&lt;/a&gt;, look &lt;a href="https://radeksprta.eu/categories/ansible/"&gt;here&lt;/a&gt;.&lt;/p&gt;</description><category>ansible</category><category>automation</category><category>filter</category><guid>https://radeksprta.eu/posts/loop-over-dictionary-attribute-in-ansible/</guid><pubDate>Sat, 04 Jul 2020 08:13:50 GMT</pubDate></item><item><title>Make Ansible Playbook Distribution Agnostic</title><link>https://radeksprta.eu/posts/make-ansible-playbook-distribution-agnostic/</link><dc:creator>Radek Sprta</dc:creator><description>&lt;div&gt;&lt;p&gt;I've been thinking about switching to a rolling distribution on my working
machine for quite some time. Because the packages in Ubuntu repositories are
just too outdated for my needs and I want to save myself the headache of PPAs.
And when &lt;a href="https://insights.ubuntu.com/2017/04/05/growing-ubuntu-for-cloud-and-iot-rather-than-phone-and-convergence/"&gt;Ubuntu announced dropping Unity in favor of
Gnome&lt;/a&gt;,
my mind was made up. I would use a
rolling distro on my main computer and Ubuntu 16.04 elsewhere.&lt;/p&gt;
&lt;h3&gt;Unify package installation&lt;/h3&gt;
&lt;p&gt;In the end, I decided to go for OpenSuse. Since I use an &lt;a href="https://radeksprta.eu/posts/automatically-setup-computer-ansible-playbook/"&gt;Ansible playbook to
setup my machines&lt;/a&gt;,
it would take no time to have it up an running. Or so I
thought. However, there was a little caveat. As my playbook used the apt
module to install software, it would obviously not run on OpenSuse. Luckily,
since the version 2.0, Ansible provides a platform-agnostic package manager
module. It is called simply &lt;code&gt;package&lt;/code&gt;. As a result, installing packages across
different distributions is as easy as running:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Install packages&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;become&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;yes&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;package&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;git&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;present&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Or is it?
While it may work in the case of Git, not all packages have a same name in
different Linux distributions. So you have to set up variables for those:
First of all, defaults in &lt;code&gt;vars/default.yml&lt;/code&gt;:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="nt"&gt;apache_package&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;apache2&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then, for Debian family &lt;code&gt;vars/Debian.yml&lt;/code&gt;&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="nt"&gt;apache_package&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;apache2&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And for Redhat family &lt;code&gt;vars/Redhat.yml&lt;/code&gt;&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="nt"&gt;apache_package&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;httpd&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Afterwards, just include
them in your tasks:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;include_vars&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;item&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}"&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nt"&gt;with_first_found&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;ansible_os_family&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}.yml"&lt;/span&gt;
&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"default.yml"&lt;/span&gt;

&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Install Apache&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nt"&gt;become&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;yes&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nt"&gt;package: name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;apache_package&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}"&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nt"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;present&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://radeksprta.eu/posts/make-ansible-playbook-distribution-agnostic/"&gt;Read more…&lt;/a&gt; (1 min remaining to read)&lt;/p&gt;&lt;/div&gt;</description><category>ansible</category><category>automation</category><category>cross-platform</category><category>orchestration</category><category>packages</category><category>setup</category><guid>https://radeksprta.eu/posts/make-ansible-playbook-distribution-agnostic/</guid><pubDate>Tue, 25 Jul 2017 16:53:27 GMT</pubDate></item><item><title>Automatically Setup Your Computer with Ansible Playbook</title><link>https://radeksprta.eu/posts/automatically-setup-computer-ansible-playbook/</link><dc:creator>Radek Sprta</dc:creator><description>&lt;div&gt;&lt;p&gt;Setting up a computer can be a major annoyance. Being 'the tech guy', I still
have vivid nightmares of spending every other weekend reinstalling friends'
and family members' Windows boxes that have come to a crawl. Now, most of us
know enough to backup the important data and that makes the process easier.
(If you don't have backups, go setup
&lt;a href="https://radeksprta.eu/installing-nextcloud-on-raspberry-pi/"&gt;Nextcloud&lt;/a&gt;,
&lt;a href="https://syncthing.net/"&gt;Syncthing&lt;/a&gt;, or some other automatic system.
Seriously, it's gonna come back to bite you sooner or later.) But there is
still the matter of installing and configuring all your software. Some people
have tackled that by writing install scripts. However, there is a better way -
Ansible playbook.  Let me introduce Ansible. Ansible is a software for
computer provisioning. In computing, provisioning means automated installation
and configuration of software and services. Provisioning tools, such as
Ansible, Chef and Puppet, help you cut down the setup time from hours to mere
minutes. Their main advantage over custom scripts is that they are idempotent.
That means they only makes the necessary changes. So, if a task fails (for
example because ou forgot to connect your Ethernet cable, oops), you can just
run it again without any worries. The reason I chose to use Ansible, is that
the tasks are easily configurable using yaml files. It is also written in
Python, which makes it easy to write your own module for it, in case of need.
So what is Ansible playbook? It is the collection of yaml files, describing
the tasks to be executed. You can find an introduction to its syntax in
&lt;a href="https://docs.ansible.com/ansible/latest/user_guide/playbooks_intro.html#about-playbooks"&gt;Ansible documentation&lt;/a&gt;.
I will demonstrate how you can setup your computers using an Ansible playbook,
using mine as an example. You can find it at &lt;a href="https://gitlab.com/radek-sprta/ansible-personal"&gt;my Gitlab
page&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://radeksprta.eu/posts/automatically-setup-computer-ansible-playbook/"&gt;Read more…&lt;/a&gt; (3 min remaining to read)&lt;/p&gt;&lt;/div&gt;</description><category>ansible</category><category>automation</category><category>provisioning</category><category>setup</category><guid>https://radeksprta.eu/posts/automatically-setup-computer-ansible-playbook/</guid><pubDate>Sun, 08 Jan 2017 21:50:54 GMT</pubDate></item></channel></rss>