<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Proxmox &#8211; Made For Cloud</title>
	<atom:link href="https://madeforcloud.com/category/proxmox/feed/" rel="self" type="application/rss+xml" />
	<link>https://madeforcloud.com</link>
	<description>Just another WordPress site</description>
	<lastBuildDate>Sat, 06 Jun 2026 01:40:20 +0000</lastBuildDate>
	<language>en-AU</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.0</generator>
	<item>
		<title>Ansible Data Manipulation with Modules</title>
		<link>https://madeforcloud.com/2026/06/06/ansible-data-manipulation-with-a-module/</link>
					<comments>https://madeforcloud.com/2026/06/06/ansible-data-manipulation-with-a-module/#comments</comments>
		
		<dc:creator><![CDATA[gocallag]]></dc:creator>
		<pubDate>Sat, 06 Jun 2026 01:45:00 +0000</pubDate>
				<category><![CDATA[Ansible]]></category>
		<category><![CDATA[Proxmox]]></category>
		<guid isPermaLink="false">https://madeforcloud.com/?p=294</guid>

					<description><![CDATA[Ansible loves to pretend that YAML is a programming language. It isn’t. And every engineer who has ever tried to munge data inside a playbook knows the pain. You have filters everywhere, Jinja spaghetti, and tasks that look like they were written during a period of sleep deprivation. How do I know, guilty as charged.&#8230;<p><a class="more-link" href="https://madeforcloud.com/2026/06/06/ansible-data-manipulation-with-a-module/" title="Continue reading &#8216;Ansible Data Manipulation with Modules&#8217;">Continue reading <span class="meta-nav">&#8594;</span></a></p>]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Ansible loves to pretend that YAML is a programming language. It isn’t. And every engineer who has ever tried to munge data inside a playbook knows the pain. You have filters everywhere, Jinja spaghetti, and tasks that look like they were written during a period of sleep deprivation. How do I know, guilty as charged.</p>



<h3 class="wp-block-heading"><strong>Just to be clear, what i&#8217;m saying is YAML and Jinja are not intended to be a Data‑Processing stack</strong></h3>



<p class="wp-block-paragraph">The usual Ansible talking point is that “Ansible is declarative, not imperative”. Sure. But then I immediately need to write imperative logic in Jinja because the playbook layer simply isn’t built for data transformation. I do it, you do it, we&#8217;ve all done it.  It&#8217;s usually quick, and depending on the use case, relatively painless, but at some point, you&#8217;ve taken it too far. I know I have, so I&#8217;m talking about it now. Automation should be declarative, but you need imperative to achieve declarative &#8211; stuff needs to be queried and computed to achieve a desired state. Ansible provides all the batteries needed to achieve this.</p>



<p class="wp-block-paragraph">The pain points you run into are real, you end up with:</p>



<ul class="wp-block-list">
<li>Complex list/dict transformations</li>



<li>Conditional logic that becomes unreadable in YAML</li>



<li>Repeated filter chains that break the moment your data shape changes</li>



<li>Playbooks that become untestable because the logic is embedded in templates</li>
</ul>



<p class="wp-block-paragraph"><strong>Fundamentally</strong>, <strong>if you’re doing anything non‑trivial with data, YAML based tasks and Jinja are the wrong tool.</strong></p>



<h3 class="wp-block-heading">Ansible does have a s<strong>olution: Move the logic into a module</strong></h3>



<p class="wp-block-paragraph"><strong>Stop abusing filters, YAML, Jinja. Write a module.</strong> <strong>If your playbook contains more than two chained filters, or chains of set_facts, or complex jinja, you probably should have written a module.</strong></p>



<p class="wp-block-paragraph">I&#8217;ve written my fair share of modules, they aren&#8217;t that difficult, but my mindset has always gone to the convoluted set_fact, conditional, filter, jinja fiasco &#8211; because somehow it seems easier at the time. Perhaps it is when you&#8217;re trying to capture that initial thought process. But at some point, you need to give yourself a reality check, and maybe it&#8217;s just simpler to start with modules than convert later. That&#8217;s the thought experiment i&#8217;d like you to consider. A module gives you:</p>



<ul class="wp-block-list">
<li>Real programming constructs</li>



<li>Real error handling</li>



<li>Real testability</li>



<li>Real maintainability</li>



<li>Real version control and reuse</li>
</ul>



<h3 class="wp-block-heading"><strong>Why is this a better Pattern</strong>?</h3>



<p class="wp-block-paragraph"><strong>Input validation &#8211; YAML doesn’t. Playbooks don&#8217;t, (don&#8217;t say assert to me as i&#8217;ve abused that as well).  Jinja definitely doesn’t.</strong></p>



<p class="wp-block-paragraph">Modules let you validate input before you do your thing with it.</p>



<p class="wp-block-paragraph"><strong>Modules are testable</strong></p>



<p class="wp-block-paragraph">You can unit test a module. You cannot unit test a Jinja filter chain inside a task, and when your processing is a sequence of knitted tasks full of set_facts and recursive playbook calls, you&#8217;ve crossed the line into prayer-based testing.</p>



<p class="wp-block-paragraph"><strong>Modules are reusable across roles and playbooks</strong></p>



<p class="wp-block-paragraph">Copy‑pasting filter chains, or jinja compute, or those wonderful blocks of set_facts and conditionals is how outages happen.</p>



<p class="wp-block-paragraph"><strong>Modules reduce cognitive load</strong></p>



<p class="wp-block-paragraph">A 20‑line Python function is easier to understand than a 20‑line set_fact, conditional, jinja monstrosity.</p>



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph">The summary is <strong>Playbooks orchestrate.</strong> <strong>Modules compute.</strong> This is how Ansible should always have been used.</p>



<h3 class="wp-block-heading">So, what is my example problem and how do I fix it with modules. </h3>



<p class="wp-block-paragraph">My ansible role was running Proxmox backups in my home lab. I was only backing up systems in my lab that had been powered on since the last backup, either daily or weekly. My pve_backup role was doing all of the following in YAML:</p>



<ul class="wp-block-list">
<li>Multi‑node API discovery</li>



<li>Cross‑node VM enumeration</li>



<li>Tag parsing and normalization</li>



<li>Per‑VM filtering</li>



<li>Per‑VM state evaluation</li>



<li>Time‑window logic</li>



<li>Task‑history correlation</li>



<li>Backup triggering</li>



<li>UPID polling</li>



<li>Error handling</li>
</ul>



<p class="wp-block-paragraph">This is <strong>imperative logic</strong>. YAML + Jinja is <strong>not</strong> an imperative language. I had effectively built a Python program using a markup language.  Yay me!</p>



<p class="wp-block-paragraph">Based on my thought process that I describe above, I could identify many &#8216;code smells&#8217;:</p>



<p class="wp-block-paragraph"><strong>Excessive </strong><code>set_fact</code></p>



<p class="wp-block-paragraph">This is always a sign the playbook is doing computation, not orchestration.</p>



<p class="wp-block-paragraph"><strong>Nested loops + sub elements</strong></p>



<p class="wp-block-paragraph">This is a red flag that the data model is too complex for YAML.</p>



<p class="wp-block-paragraph"><strong>Repeated REST calls with identical headers</strong></p>



<p class="wp-block-paragraph">Modules handle this cleanly; playbooks do not.</p>



<p class="wp-block-paragraph"><strong>Per‑VM include files</strong></p>



<p class="wp-block-paragraph">This is a workaround for the fact that YAML cannot express real logic.</p>



<p class="wp-block-paragraph"><strong>State accumulation (</strong><code>vms_powered_on_last_week</code><strong>)</strong></p>



<p class="wp-block-paragraph">This is business logic, not orchestration.</p>



<p class="wp-block-paragraph"><strong>UPID polling in YAML</strong></p>



<p class="wp-block-paragraph">This is the worst possible place to do it.</p>



<p class="wp-block-paragraph"><strong>Debug statements everywhere</strong></p>



<p class="wp-block-paragraph">Because debugging YAML logic is hell.</p>



<p class="wp-block-paragraph">My role wasn&#8217;t bad in the terms that it did &#8216;work&#8217;. It’s simply doing something <strong>Ansible playbooks were never designed to do</strong>.</p>



<h3 class="wp-block-heading">How did I refactor this mess?</h3>



<p class="wp-block-paragraph">A good module model I use is:</p>



<p class="wp-block-paragraph"><strong>One module = one conceptual operation</strong></p>



<p class="wp-block-paragraph">My conceptual operations are:</p>



<p class="wp-block-paragraph"><strong>“Given a Proxmox cluster, return the list of VMIDs that should be backed up.”</strong></p>



<p class="wp-block-paragraph"><strong>“Given a VMID, run vzdump and wait for completion.”</strong></p>



<p class="wp-block-paragraph">That’s it. Two modules replace ~300 lines of gnarly YAML.</p>



<h3 class="wp-block-heading">Why this is objectively better (oh and I simply feel better about it)</h3>



<p class="wp-block-paragraph"><strong>Testable</strong></p>



<p class="wp-block-paragraph">You can unit‑test the module logic without running Ansible.</p>



<p class="wp-block-paragraph"><strong>Faster</strong></p>



<p class="wp-block-paragraph">Fewer tasks, leading to fewer forks, leading to fewer HTTP sessions.</p>



<p class="wp-block-paragraph"><strong>Maintainable</strong></p>



<p class="wp-block-paragraph">No more Jinja filter soup.</p>



<p class="wp-block-paragraph"><strong>Debuggable</strong></p>



<p class="wp-block-paragraph">You can print structured Python objects, not YAML hacks.</p>



<p class="wp-block-paragraph"><strong>Reusable</strong></p>



<p class="wp-block-paragraph">Other roles can use the same modules.</p>



<p class="wp-block-paragraph"><strong>Correct abstraction</strong></p>



<p class="wp-block-paragraph">Playbooks orchestrate. Modules compute.</p>



<h2 class="wp-block-heading">In summary</h2>



<p class="wp-block-paragraph">Think of your future self now <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>



<p class="wp-block-paragraph">Train yourself to spot the above code smells sooner rather than later.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://madeforcloud.com/2026/06/06/ansible-data-manipulation-with-a-module/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>Proxmox &#8211; No device with valid iso found</title>
		<link>https://madeforcloud.com/2025/08/20/proxmox-no-device-with-valid-iso-found/</link>
					<comments>https://madeforcloud.com/2025/08/20/proxmox-no-device-with-valid-iso-found/#respond</comments>
		
		<dc:creator><![CDATA[gocallag]]></dc:creator>
		<pubDate>Wed, 20 Aug 2025 05:35:16 +0000</pubDate>
				<category><![CDATA[Proxmox]]></category>
		<guid isPermaLink="false">https://madeforcloud.com/?p=267</guid>

					<description><![CDATA[You&#8217;ve probably tried to build a bootable USB drive and it hasn&#8217;t copied the image correctly. I highly recommend using rufus in DD mode. This has always worked for me.]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph">You&#8217;ve probably tried to build a bootable USB drive and it hasn&#8217;t copied the image correctly.</p>



<p class="wp-block-paragraph">I highly recommend using rufus in <strong>DD</strong> mode.  This has always worked for me.</p>



<p class="wp-block-paragraph"></p>
]]></content:encoded>
					
					<wfw:commentRss>https://madeforcloud.com/2025/08/20/proxmox-no-device-with-valid-iso-found/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
