<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Ansible on Backend Engineering Strategy Tools</title><link>https://backend-engineering-strategy-tools.github.io/site/tags/ansible/</link><description>Recent content in Ansible on Backend Engineering Strategy Tools</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><lastBuildDate>Wed, 03 Jun 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://backend-engineering-strategy-tools.github.io/site/tags/ansible/index.xml" rel="self" type="application/rss+xml"/><item><title>Infrastructure Testing — Molecule, Test Kitchen, InSpec, Chainsaw</title><link>https://backend-engineering-strategy-tools.github.io/site/public-notes/infra-as-code/infra-testing/</link><pubDate>Wed, 03 Jun 2026 00:00:00 +0000</pubDate><guid>https://backend-engineering-strategy-tools.github.io/site/public-notes/infra-as-code/infra-testing/</guid><description>&lt;p&gt;Infrastructure code needs testing like application code does. The tools here cover different layers: role testing, integration testing, compliance checking, and Kubernetes end-to-end testing.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="molecule--ansible-role-testing"&gt;Molecule — Ansible role testing
&lt;/h2&gt;&lt;p&gt;Molecule is the standard testing framework for Ansible roles and playbooks. It manages the full test lifecycle: spin up instances, apply the role, verify the result, tear everything down.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Stages:&lt;/strong&gt;&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;molecule create # spin up test instances (Docker, Podman, EC2, etc.)
molecule converge # apply the role/playbook
molecule verify # run assertions
molecule destroy # clean up
molecule test # full cycle in sequence
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;Drivers&lt;/strong&gt; control where instances run — Docker or Podman for local development, EC2 or other cloud providers for closer-to-production testing.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Verifiers&lt;/strong&gt; run assertions after converge. The default is Ansible itself (run a playbook of assertions), but &lt;a class="link" href="https://testinfra.readthedocs.io/" target="_blank" rel="noopener"
 &gt;Testinfra&lt;/a&gt; (pytest-based) and &lt;a class="link" href="https://github.com/goss-org/goss" target="_blank" rel="noopener"
 &gt;Goss&lt;/a&gt; are popular alternatives.&lt;/p&gt;
&lt;p&gt;A minimal &lt;code&gt;molecule/default/molecule.yml&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;driver&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;docker&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;platforms&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;instance&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;image&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;ubuntu:22.04&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;provisioner&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;ansible&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;verifier&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;ansible&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Wire into CI: &lt;code&gt;molecule test&lt;/code&gt; runs the full cycle and exits non-zero on failure.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="test-kitchen--integration-testing-for-infrastructure"&gt;Test Kitchen — integration testing for infrastructure
&lt;/h2&gt;&lt;p&gt;Test Kitchen (kitchen.ci) is an integration testing framework originally built for Chef but now multi-platform. It creates instances, applies configuration, runs a verifier, and destroys.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Drivers&lt;/strong&gt;: Docker, Vagrant, and cloud providers (EC2, GCP, Azure). Plugins also exist for Ansible (&lt;code&gt;kitchen-ansible&lt;/code&gt;) and Terraform (&lt;code&gt;kitchen-terraform&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Verifiers&lt;/strong&gt;: InSpec (most common), Busser.&lt;/p&gt;
&lt;p&gt;A &lt;code&gt;kitchen.yml&lt;/code&gt; for a Chef cookbook:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;driver&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;docker&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;provisioner&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;chef_zero&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;verifier&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;inspec&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;platforms&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;ubuntu-22.04&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;suites&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;default&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;verifier&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;inspec_tests&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;test/integration/default&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;kitchen list &lt;span style="color:#75715e"&gt;# show instance state&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;kitchen converge &lt;span style="color:#75715e"&gt;# apply provisioner&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;kitchen verify &lt;span style="color:#75715e"&gt;# run verifier&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;kitchen test &lt;span style="color:#75715e"&gt;# full cycle&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Test Kitchen is less commonly adopted outside Chef shops, but the multi-platform support means it can be useful for testing across providers in one framework.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="inspec--compliance-testing-as-code"&gt;InSpec — compliance testing as code
&lt;/h2&gt;&lt;p&gt;InSpec (now Progress Chef InSpec) is a compliance testing framework. You write assertions about the state of a system — packages installed, ports listening, file permissions, user accounts — in a Ruby DSL. InSpec executes them locally, over SSH, against Docker containers, or against cloud APIs.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;describe package(&lt;span style="color:#e6db74"&gt;&amp;#39;nginx&amp;#39;&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; it { should be_installed }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;describe service(&lt;span style="color:#e6db74"&gt;&amp;#39;nginx&amp;#39;&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; it { should be_running }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; it { should be_enabled }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;describe port(&lt;span style="color:#ae81ff"&gt;80&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; it { should be_listening }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;describe file(&lt;span style="color:#e6db74"&gt;&amp;#39;/etc/nginx/nginx.conf&amp;#39;&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; its(&lt;span style="color:#e6db74"&gt;&amp;#39;mode&amp;#39;&lt;/span&gt;) { should cmp &lt;span style="color:#e6db74"&gt;&amp;#39;0644&amp;#39;&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Profiles&lt;/strong&gt; are the distributable unit — a collection of controls with metadata. The InSpec community maintains profiles for CIS benchmarks, DISA STIGs, and other compliance standards.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Where it fits&lt;/strong&gt;: compliance auditing, security baselines, post-deploy verification. Wired into CI as a final gate or run on a schedule against production.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;inspec exec path/to/profile --target ssh://user@host
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;inspec exec path/to/profile --target docker://container-id
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="chainsaw--kubernetes-e2e-testing"&gt;Chainsaw — Kubernetes e2e testing
&lt;/h2&gt;&lt;p&gt;Chainsaw is a declarative end-to-end testing framework for Kubernetes. Originally from the Kyverno project, now standalone. Write test scenarios in YAML — apply manifests, assert on resource state, clean up — without writing Go or any test framework code.&lt;/p&gt;
&lt;p&gt;Particularly useful for testing Kubernetes operators, controllers, and admission webhooks: the things that are hard to unit test because they depend on the Kubernetes API.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;apiVersion&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;chainsaw.kyverno.io/v1alpha1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;kind&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;Test&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;metadata&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;basic-deployment&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;spec&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;steps&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;create deployment&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;try&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;apply&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;resource&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;apiVersion&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;apps/v1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;kind&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;Deployment&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;metadata&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;test-app&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;spec&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;replicas&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;# ...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;assert&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;resource&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;apiVersion&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;apps/v1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;kind&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;Deployment&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;metadata&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;test-app&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;status&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;readyReplicas&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;cleanup&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;try&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;delete&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;ref&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;apiVersion&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;apps/v1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;kind&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;Deployment&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;test-app&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;chainsaw test ./tests/
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;vs Terratest for Kubernetes&lt;/strong&gt;: Terratest requires Go code; Chainsaw is YAML. For testing Kubernetes resources and operators specifically, Chainsaw is simpler to write and maintain.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="terratest--go-based-infrastructure-testing"&gt;Terratest — Go-based infrastructure testing
&lt;/h2&gt;&lt;p&gt;Covered in the &lt;a class="link" href="../terraform/#testing-and-validation" &gt;Terraform page&lt;/a&gt;. The short version: Go tests that deploy real infrastructure, run assertions via cloud SDKs, then tear it down. The most complete integration testing approach for Terraform modules — and the highest cost in setup and test execution time.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="choosing"&gt;Choosing
&lt;/h2&gt;&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Tool&lt;/th&gt;
 &lt;th&gt;Best for&lt;/th&gt;
 &lt;th&gt;Language&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;Molecule&lt;/td&gt;
 &lt;td&gt;Ansible role testing&lt;/td&gt;
 &lt;td&gt;YAML + Python/Ansible&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Test Kitchen&lt;/td&gt;
 &lt;td&gt;Multi-platform integration testing&lt;/td&gt;
 &lt;td&gt;YAML + Ruby (InSpec)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;InSpec&lt;/td&gt;
 &lt;td&gt;Compliance assertions, security baselines&lt;/td&gt;
 &lt;td&gt;Ruby DSL&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Chainsaw&lt;/td&gt;
 &lt;td&gt;Kubernetes operators and controllers&lt;/td&gt;
 &lt;td&gt;YAML&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Terratest&lt;/td&gt;
 &lt;td&gt;Terraform module integration testing&lt;/td&gt;
 &lt;td&gt;Go&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;</description></item><item><title>Ansible</title><link>https://backend-engineering-strategy-tools.github.io/site/public-notes/infra-as-code/ansible/</link><pubDate>Mon, 01 Jan 2024 00:00:00 +0000</pubDate><guid>https://backend-engineering-strategy-tools.github.io/site/public-notes/infra-as-code/ansible/</guid><description>&lt;p&gt;Ansible is an open-source automation tool for configuration management, application deployment, and orchestration. The key selling point: it&amp;rsquo;s agentless — you push from a control machine over SSH, no daemon running on managed hosts.&lt;/p&gt;
&lt;h2 id="why-ansible"&gt;Why Ansible
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Free and open source&lt;/strong&gt; — Red Hat maintains it, commercially supported via Ansible Automation Platform (formerly Tower)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Agentless&lt;/strong&gt; — no software to install on managed nodes; plain SSH is enough&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Simple&lt;/strong&gt; — playbooks are YAML, readable without special knowledge&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Flexible&lt;/strong&gt; — works on servers, cloud platforms, network devices, and bare-metal&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="what-it-does"&gt;What it does
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Configuration management&lt;/strong&gt; — define what state a system should be in; Ansible gets it there and keeps it there.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Application deployment&lt;/strong&gt; — deploy multi-tier applications with a playbook; let Ansible figure out the ordering and state transitions.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Orchestration&lt;/strong&gt; — coordinate complex workflows across databases, networks, front-end and back-end services in the right order.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Security and compliance&lt;/strong&gt; — enforce firewall rules, user policies, and security baselines across all hosts from a single playbook run.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Cloud provisioning&lt;/strong&gt; — provision infrastructure on AWS, Azure, GCP, OpenStack, or bare-metal with the same tooling.&lt;/p&gt;
&lt;h2 id="architecture"&gt;Architecture
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Modules&lt;/strong&gt; — small programs pushed to nodes over SSH, executed, then removed. Ansible ships with 750+ modules for packages, services, files, cloud APIs, and more.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Plugins&lt;/strong&gt; — extend Ansible&amp;rsquo;s core: connection types, callbacks, caching, filtering. Write your own or use community plugins.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Inventory&lt;/strong&gt; — a file (INI or YAML) listing all managed hosts, their IPs, groups, and variables. Can also pull dynamic inventory from AWS, GCP, Azure, etc.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Playbooks&lt;/strong&gt; — YAML files describing tasks to run on which hosts. The core unit of work. Each play maps a group of hosts to a set of tasks; each task calls a module.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;APIs&lt;/strong&gt; — extend connection transports beyond SSH (WinRM for Windows, network device APIs, etc.).&lt;/p&gt;
&lt;h2 id="ansible-automation-platform"&gt;Ansible Automation Platform
&lt;/h2&gt;&lt;p&gt;Red Hat&amp;rsquo;s commercial wrapper around Ansible. Adds a web UI, RBAC, job scheduling, audit logging, and a workflow editor. Worth it once you have multiple teams running automation.&lt;/p&gt;
&lt;h2 id="where-ansible-still-excels"&gt;Where Ansible still excels
&lt;/h2&gt;&lt;p&gt;Network device configuration is the clearest remaining stronghold. Ansible has mature modules for switches, routers, and firewalls (Cisco IOS, Arista EOS, Juniper JunOS, and many others) and the agentless SSH model works well for network gear that can&amp;rsquo;t run an agent. For network automation, Ansible is still state of the art.&lt;/p&gt;
&lt;p&gt;For server configuration management — the original use case — most teams should consider moving to other models. Terraform manages provisioning, container images handle application configuration (immutable infrastructure), and Kubernetes operators handle runtime state. The gap Ansible used to fill is smaller.&lt;/p&gt;
&lt;h2 id="the-configuration-management-landscape"&gt;The configuration management landscape
&lt;/h2&gt;&lt;p&gt;Ansible is one of several tools in this space. The others worth knowing:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Salt&lt;/strong&gt; (SaltStack) — agent-based, event-driven, fast for large fleets. More complex than Ansible.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Puppet&lt;/strong&gt; — agent-based, declarative DSL, strong in enterprise. Puppet Forge has a large module library.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Chef&lt;/strong&gt; — agent-based, Ruby DSL, infrastructure as code before the term was common. Less common now.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;See &lt;a class="link" href="../config-management/" &gt;Configuration Management — Puppet, Chef, Salt&lt;/a&gt; for a full comparison.&lt;/p&gt;
&lt;p&gt;All four predate the Kubernetes era. Ansible has survived best because it is agentless and YAML-based — lower barrier. The others are still found in large enterprise environments with long-lived infrastructure.&lt;/p&gt;
&lt;h2 id="resources"&gt;Resources
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://docs.ansible.com/" target="_blank" rel="noopener"
 &gt;docs.ansible.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.ansible.com/" target="_blank" rel="noopener"
 &gt;ansible.com&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item></channel></rss>