Personally, I use Fabric for automation, and it's got all the problems the author says; if you get the machine into an unknown state, you're better off just wiping it and starting fresh.
However, with the rise of virtual machines, that's a trivial operation in many cases. Even on bare metal hardware it's not a big deal, as long as you can tolerate a box disappearing for an hour (and if you can't, your architecture is a ticking time bomb).
In fact, starting from a clean slate each time basically makes Fabric scripts a declarative description of the system state at rest... if you squint hard enough.
I've used Fabric this way as well, and found the same thing. If you start from a known-good state and apply a deterministic transformation to it, you've got another known-good state.
The problem is that running commands via SSH isn't really a deterministic process. It's fairly predictable, but it relies on a lot of inputs that can change unexpectedly. So it mostly works, but building a server has to be cheap and easy, because you throw them away a lot.
I think my ideal system would be sort of a cross between this and NixOS. We build servers with NixOS-style stateless declarative configuration. But then instead of using NixOS mechanisms for functionally/deterministically modifying the running system, we treat running servers as immutable and disposable and build new ones whenever we need to change something.
That seems like it would give maximum maintainability and robustness.
Yeah, it's pretty close. It seems to want to modify instances in place, though. On NixOS, that's a lot safer than other distributions, but I think I'd still prefer to handle application deployment the same way as scaling and fault management. That is, bring up new servers with the new version, gradually move traffic over to them, then shut down the old servers.
I'm also wondering if NixOps can build AMIs the same way Aminator does, by mounting a volume on a builder instance, writing files to the volume, then snapshotting and making an AMI based on the snapshot. (In contrast to snapshotting a running system.) That would be truly awesome.
I've only been playing with NixOps a short while, maybe there's already a way to do these things, or they're easy to implement on top of NixOps. Looks very cool, though.
if you have to start from scratch, it's not declarative.
The author majorly misses out on what chef and puppet are, since both are declarative, while chef feels procedural because you are writing ruby.
These tools are based on the idea of declaring how the system should be, and a way to get there. They also have the advantage of allowing for a design that applies to multiple machines.
Maybe some of the ideas expressed are novel and will shape the future, but mostly I see a lot of hand-waving and complaining about things that are Pretty Good Ideas(tm) like FHS, which most people still don't understand.
At the end of the day, he's essentially proposing static compilation for everything. That creates an amusing amount of attack surface, but I'll surely find myself taking a look at Nix and maybe what the OP is talking about will iterate toward something sensible.
That we should want something for our desktop which is a strict match for what we want in server farms is kind of silly, IMO. See Pets v. Cattle.
It's not technically declarative, but in the limited circumstances for which it makes sense, it feels declarative as you're thinking in terms of what needs to be there without worrying at all about the current state.
While we're analogizing, it's like stocking up your fridge to an exact state. Recipe A is:
* Check shelf for residue, clean if exists
* For each existing egg, if egg is off, throw out
* If egg carton contains yolk from broken egg, obtain new carton, transfer each egg
* While egg count less than 12, purchase and add eggs
However, if we just throw out the entire old fridge and buy a new one, we get the recipe:
* Purchase a dozen eggs. Place on shelf.
If you can afford a new fridge each time you go shopping, I don't think it's a bad algorithm.
> For each node a list of recipes is applied. Within a recipe, resources are applied in the order in which they are listed.
So it reads in a declarative fashion, but it doesn't actually build a dependency graph (and a static representation of config) like Puppet does.
Anybody who's done enough systems programming can put together something similar to Chef--it's the same old imperative stuff everybody else has written, except with an idempotent sugar-coating and a client/server model to distribute the script^H^H^H^H^H^Hcookbooks. ;-)
I'm not putting chef down--the fact that it's plain old ruby instead of a slightly-odd DSL is a definite advantage in some cases, but I don't think that anything else out there is really in the same category as Puppet.
Of course, there are things about Puppet that bug me, but I really think that it's the Right Thing at its core. The idea that it's not "good enough" seems like a consequence of incorrectly conflating Puppet with the systems that it manages.
I disagree with your first assertion. The poster-child for declarative programming is pure functional languages, which conceptually start from scratch at every call. In a certain ideal sense we'd like system state to be a pure function of configuration; this is certainly where NixOS is aiming. In both these cases, mutating existing state is merely an optimization.
However, with the rise of virtual machines, that's a trivial operation in many cases. Even on bare metal hardware it's not a big deal, as long as you can tolerate a box disappearing for an hour (and if you can't, your architecture is a ticking time bomb).
In fact, starting from a clean slate each time basically makes Fabric scripts a declarative description of the system state at rest... if you squint hard enough.