Ansible earns a place among languages because it forces a question the others do not: what kind of language is a configuration tool? You write YAML that describes a desired end state, not a sequence of steps, and the engine reconciles the machine toward that state. Yet each declarative module is imperative Python underneath, so the declarative surface is a thin skin over ordinary procedural code. That tension, declared intent over imperative mechanism, plus idempotence as the property that makes re-running safe, is what the comparative notes examine.
It is also the section’s control case in the opposite direction from Racket. Ansible has no generics because it has no type system, no functions, and no compile step, so the problem generics solve never arises. The folder says that plainly rather than stretching an analogy, then goes looking for what does the work instead: an implicit loop over hosts, a role with parameters and defaults, and a library of Jinja2 filters that behave like the functions the language refuses to have.
The language surface
What you actually write, and what decides what it means.
- Playbooks, Plays, and Tasks - three structural levels, task-major execution, and where handlers fit
- YAML as a Programming Surface - a data format doing the job of a syntax, and the two things that bought
- Inventory and Host Patterns - static and dynamic sources, groups, and a pattern that resolves as a set expression
- Variables and Precedence - the twenty-two-slot order, and the inventory merge that runs before it
- Jinja2 Templating and Facts - control-node rendering, which is what lets one host’s configuration depend on another host’s reality
The absence, and what stands in for it
- Why Ansible Has No Generics - no types, no functions, no compile step, so the problem never arises
- Roles and Reuse - a directory layout as a loading convention, and per-play deduplication that behaves like memoization
- Role Parameters and Defaults as an Interface - the closest thing to a typed interface, checked on the way in and discarded on the way out
- Loops and the item Abstraction -
itemas a shared name rather than a binding - Filters and Tests as Transformations - the nearest thing to a function library, all of it running on the control node
- Collections as the Packaging Unit - namespaces, fully qualified names, and one installed version at a time
The execution model
What actually happens when a play runs, which explains most of the surprises above.
- The Execution Model and Module Transfer - a zipfile shipped over the connection, imported as
__main__, answered with one JSON document - Strategies, linear, free, and forks - the scheduler: every task a barrier, a worker pool capped at five, and what
orderrefuses to promise - Handlers and notify Semantics - one global name-keyed table drained at section boundaries, not an event subscription
- Delegation, run_once, and Local Actions - changing where a task runs without changing whose task it is
- Fact Gathering and Caching - a cache coherence decision dressed as a configuration setting
Control flow in a language that claims not to have any
- Conditionals and Fact-Based Branching - a per-host predicate, the
omitsentinel, and skipped as a third outcome - Blocks, Rescue, and Always - grouped error handling with no exception objects, and the four ways it diverges from try and catch
- Error Handling: failed_when and changed_when - redefining failure and change, and the keyword idempotence claims actually rest on
- Tags and Selective Execution - inheritance as a preprocessing pass, and why arbitrary subsetting is unsound by construction
- Check Mode and Diff - dry run as a flag each module chooses to honor, so a clean run is partly a report about tasks never evaluated
The plugin surface
Ansible is small and its plugin taxonomy is large. This is where the extensibility actually lives.
- Module and Plugin Types - the taxonomy sorted by one question: does this run on the control node or the target
- Dynamic Inventory and Inventory Plugins - inventory as a program, and caching that turns the host list into a stale read
- Connection Plugins and Transports - three operations rather than a protocol, which is why a container works as a transport
- Callback Plugins and Output - no print statement, only a rendering of an event stream
Secrets, testing, and judgment
- Vault and Secret Management - what it encrypts, the boundary it refuses to defend, and the key problem it moves up a level
- no_log and Output Redaction - a display filter attached to a task, and the three places the value still reaches a human
- Testing with Molecule and Assertions - converging twice, and what a test means when the program’s job is to make a claim true
- Ansible against Terraform and Puppet - push against pull and ordered tasks against a dependency graph, as two independent axes
Read from the comparative layer
Ansible anchors the configuration-and-tooling end of the Common Concerns cluster:
- Declarative Models and Idempotence - desired state and idempotence over imperative Python modules
- Build Systems and Dependency Management - the declared-graph-with-an-engine shape Ansible shares with package managers
- Software Supply Chain and Provenance - provenance and reproducibility for the artifacts a run deploys
- Packaging, Wheels, and Environments - Ansible is Python underneath, and inherits that supply chain
Any pages placed under this folder are auto-listed below by Quartz.