After some positive feedback regarding the concept of declarative primitives I would like to elaborate about it.
Defining declarative primitives
Declarative primitives is just a description of existing techniques. I gave it a name because I’m not aware of any other term describing these techniques. The idea behind declarative approach is to describe the desired state or result and not particular command or operations to achieve it.
mkdir -p dir1/dir2/dir3
The outcome of the command does not depend on current state (whether the directory exists or not). You describe the desired state: directories dir1, dir2 and dir3 should exist after the command is run. Note that
mkdir dir1/dir2/dir3 does not have the same effect: it fails if dir1 does not exist or dir2 does not exist or if dir3 exists.
The phrase declarative primitives emphasizes granularity. Existing declarative tools for the cloud operate on many described resources, build dependency graphs and run in order that they decide. Declarative primitives provide a very flexible way to control a single resource or a group of few resources of the same type. The flexibility comes from granularity. You decide how you combine the resources. You can easily integrate existing resources. You can modify just the properties of your interest on the resources you choose. This approach is ideal of scripting in my opinion.
Where are declarative primitives for the cloud?
I believe that when writing a script, using
mkdir -p should be similar to using
AwsElb(...).converge() for example. I’m working on implementing it (as a library for the Next Generation Shell) and I’m not aware of any other project that does it.
There are many projects for managing the cloud, how are they different?
Here are the solutions that I’m aware of and how familiar I am with each one:
- CloudFormation – using frequently (I prefer YAML syntax for it)
- Terraform – I’ve read the documentation and bits of source code
- Cloudify – familiar with the product, made modules for it
- Puppet – was using it intensively on few different projects
- Chef – was using it intensively in many projects
- Ansible – unfamiliar with this one (only took a look at documentation) so not reviewing it below
- All take the declarative approach. You describe many resources or the entire system and feed the description to the tool which in turn does all the work. None of these solutions was designed to provide you with the primitives that could be easily used in your scripts. These tools just don’t match my view regarding scripting.
- These tools can do a rollback on error for example. They can do that precisely because they have the description of the entire system or big parts of it. It will take some additional work to implement rolling back using declarative primitives. The question is whether you need the rollback functionality …
- Some of these tools can be made to work with different clouds relatively easily. Working with different clouds easily may also possible with declarative primitives but the library I’m currently working on does not have such goal.
- Except for Chef, the tools in the list above use formats or DSLs not based on real programming languages. This means that except for trivial cases you will be using some additional tool to generate the descriptions of desired states. Limited DSLs do not work. See Puppet and Ansible that started with simple description languages and now they are almost real programming languages … which where never designed as programming languages, which has consequences.
- I’m not aware of any option in the tools above that lets you view definitions of existing resources, which prevents you from starting managing existing resources with these tools and from cloning existing resources. I have started implementing the functionality that lets you generate the script that would build an existing resource:
SomeResource(...).code(). This will allow easy modification or cloning.
- A feature missing both from these tools and from my library is generating a code to start with for a given resource type (say security group or load balancer). Writing CloudFormation definition for a type with many properties is a nightmare. Nobody should start from scratch. Apache or Nginx configuration files are good example of starting points. Similar should be done for the cloud resources.
- Note that Chef and Puppet were originally designed to manage servers. I don’t have any experience using them for managing the cloud but I can guess it would be less optimal than dedicated tools (the first three tools).
Scripting the cloud – time to do it right!