Infrastructure as code is a declarative language at its core. You define how the system should be – this file goes here, this package needs installing, this service must be running – and the system converges to that state over multiple runs. Idempotence is the key concept: run the same code again on a system already in the desired state, and nothing changes. Simple idea, but it is the first thing that trips people up when converting traditional scripts.
The language landscape at the time was CFEngine, Puppet, Chef, Ansible, and Pallet. Puppet uses a restrictive DSL by design – limited vocabulary makes it easy to adopt but hard when you need expressiveness. Chef mixes its DSL with Ruby, so any Ruby construct is available. This creates a natural split: people with no development background tend toward Puppet’s boxed approach, while those wanting more power lean toward Chef. A fundamental difference is execution model – Puppet builds a directed graph of dependencies (where unspecified order means random execution), while Chef runs sequentially like Ruby code. The graph gives you predictability and metadata; sequential gives you simplicity.
The tooling story was embarrassingly familiar to any Java developer. It took the community years to build linting tools for coding style. Input validation of class parameters was an afterthought. Dependency management – something Maven solved ages ago – took two to three years to arrive. Extracting configuration from code, reverse engineering existing servers, IDE support through Geppetto for Eclipse – all of these came slowly as a community of admins discovered practices that developers had taken for granted.
Testing followed the same pattern of gradual discovery. Unit tests using rspec to validate logic (not to test whether Puppet or Chef does its job – that is testing the library, not your code). Smoke tests running on real VMs via Vagrant. Guard-style watchers that rerun tests on every file save, getting you close to a TDD cycle. Linux containers for fast boot times. And the CI integration was straightforward – rake tasks producing JUnit XML through ci_reporter.
The development workflow with Vagrant was the breakthrough. Define your OS, run your code against it, destroy and recreate. VeeWee for building base boxes from ISO. The Vagrant Eclipse integration arriving at Devoxx itself. As infrastructure scales, you hit optimization problems: too many roles, too many OS versions, too many combinations to test naively. Puppet’s directed graph lets you query which roles depend on a changed module, dramatically reducing test runs.
The conclusion was honest: it is code, but not quite as we know it. Close but no cigar. The community of admins was learning and going through the same evolutionary curve that programming languages went through. The ask to Java developers: join the community and bring your practices, because infrastructure as code benefits enormously from development rigor.
Watch on YouTube – available on the jedi4ever channel
This summary was generated using AI based on the auto-generated transcript.