
What if Ansible used XML for configuration management? - xpe
http://djwonk.tumblr.com/post/87548491694/what-if-ansible-used-xml
======
gecko
This post is ridiculous.

A very valid complaint would be that Ansible isn't idempotent, which I think
is what the author was trying to get at. Nixos would be a great example of an
idempotent system, and you might be able to convince me that Docker would
qualify, too. As much as I like Ansible, its lack of true idempotence is a
weakness.

But that has _nothing_ to do with yaml v. XML v. anything else. You could
trivially write an idempotent description language in XML, and you can
trivially write a horrible state-based system in a Haskell DSL or Prolog. As
far as I can tell, the author is complaining that people _think_ that Ansible
is idempotent because it has yaml. That is incorrect, but I don't think that
it'd be better or worse if they'd pick something else; merely more verbose.
(Look at Maven and Gradle for an example.)

~~~
dj-wonk
Yes, the post is somewhat ridiculous. I can take the blame for that. Still, I
think the choice of language for these tools matters a lot. With so many
experiments in configuration tools, my goal was to raise the point in a light-
hearted way.

I'm really interested to see if or how a community with diverse preferences
(developers and system administrators) might agree on a small number of
configuration management tools. Or are we destined to have these tools
splinter across languages?

~~~
peteretep

        > I think the choice of language for these tools matters
        > a lot
    

I read the post, and still don't know _why_ you think it matters, when
comparing two data-interchange languages.

~~~
dj-wonk
I'm saying that using a data interchange language (whether it be XML or YAML)
is no substitute for a programming language.

------
rdtsc
Good points.

Ansible playbooks are not always declarative. There is often stuff that looks
like this:

\---

    
    
       ---
    
       # Launch Job to count occurance of a word.
    
       - hosts: $server
         user: root
         tasks:
          - name: copy the file 
            copy: src=inputfile dest=/tmp/inputfile 
     
          - name: upload the file
            shell: ...
          
          <more names and shell pairs ...>

\---

That is just specifying a set of steps. So then it calls for for loops, if
conditions, and so on.

I noticed that pattern in examples when looking at Ansible and kind of shook
my head.

But oh well, I guess, it depends on how you arrived at Ansible. I think if you
view it as "better than SSH-ing and running shell scripts". Ok it looks nice.
But if you want a more mature declarative based configuration system, then
maybe you'll start to see various flaws or design issues with it.

Chef seems more powerful. Also played with saltstack. I like saltstack better
so far but aside from playing with it still use shell scripts and OS packaging
pre-/post- install scripts to handle tasks like these.

~~~
btgeekboy
You say that they're not always declarative like it's a bad thing. Personally,
I find it nice that we have the playbooks to build out our infrastructure and
the playbooks that perform a rolling upgrade of our application using the same
syntax, variables, and inventories. If you keep your declarative playbooks
separate from your procedural ones, you get more power than a declarative
system alone can provide. (FWIW, we chose it not just for this, but because of
its lack of an agent - we can use our configuration management to deploy
software to customers' infrastructure without colliding with their own CM.)

Further, this (using a data language as a programming language) isn't without
precedent. Both XSL and Ant have standard conditionals, loops, etc available
for use.

~~~
jimbokun
XSL and Ant are the poster children for why this is a bad idea.

------
yen223
People don't necessarily hate XML, but man do we hate tags. One huge feature
of YAML is its clever use of whitespace to eliminate a lot of cruft from the
syntax.

That said, I'm starting to warm to the fact that Django uses straight Python
for its settings. If you're going to use a Turing-complete language to write
your config file, might as well use a familiar one.

~~~
crdoconnor
I hate XML. It's unnecessarily complicated, it breaks easily and it's verbose.

YAML is kind of sucky as a data transfer format (chopped up YAML is still
valid which leads to all kinds of screwed up behavior), but its mirror
equivalent JSON is good for that. Equally, JSON sucks for declarative
configuration but YAML really shines.

Django's settings file is also one of the thornier bits of django. I'm not
sure if should necessarily have become declarative, but making it a monolithic
python file causes a lot of headaches with integrating modules, state changes,
etc. The fact that you can often move a bit of config from one end of the file
to the other and change the behavior completely is a bit screwed up. I think
it would work better if it were a bit more ansible-y.

~~~
yen223
I never did like using JSON as a configuration format (I'm looking at you,
Sublime Text). But it's still miles ahead of using XML as a config format.

I can see where you're coming from regarding Django's settings file. Lord
knows how many hours I've wasted hunting down stray configurations thanks to
frameworks which abuse inheritance for its settings config (I'm looking at
you, Mezzanine). Still, the fact that it is Python, and can therefore be
debugged like any other Python script instead of obeying its own special
syntax, is a plus in my books.

~~~
crdoconnor
I was actually thinking of mezzanine when I wrote that (and django-cms is
worse!). Both packages gave me a real headache while setting up settings.py.
There was no clean separation between code and declarative configuration.

------
vezzy-fnord
The author's complaint isn't really related to YAML or XML, it's his disdain
that Ansible uses a data serialization language, instead of a full-blown
programming language.

~~~
rdtsc
Another way to look at it though is the author wouldn't mind using either YAML
or XML if Ansible scripts were fully declarative. Once the need for if
conditions and for loops comes about, any configuration file language (or data
transport) language is going to be a little awkward.

~~~
yen223
"Once the need for if conditions and for loops comes about, any configuration
file language (or data transport) language is going to be a little awkward."

Occasionally, it would spawn a whole new language:
[http://www.lua.org/](http://www.lua.org/)

------
lost-theory
This wraps up my feelings about CM tools very well. They all seem to follow
this "language agnostic" / "it's not really programming!" model, whether it's
chef's ruby DSL or ansible's YAML. I don't understand what's so special about
this field that it requires a totally different paradigm.

In chef's case, I would rather write simple classes & functions in plain ruby
than use the DSL and write "Lightweight Resource Providers".

In ansible's case, I even did a little experiment to show what it would look
like to use & call ansible modules as normal python code:

[https://github.com/lost-
theory/ansible/blob/module_experimen...](https://github.com/lost-
theory/ansible/blob/module_experiment/demo.py)

[https://groups.google.com/d/topic/ansible-
project/Zv3Veo77gP...](https://groups.google.com/d/topic/ansible-
project/Zv3Veo77gPQ/discussion)

I would love to see a CM tool that embraced plain python or plain ruby and not
try to go the pseudo-"declarative" route, which ends up being IMO too
constraining for not much benefit and needlessly reinventing a bunch of wheels
(e.g. looping & conditionals, as the article mentions).

~~~
stonith
I think the intention is to appeal to traditional sysadmins with limited
development experience, who don't know ruby, and more importantly don't _want_
to know ruby.

I haven't worked with Chef so I can't comment, but I work extensively on the
puppet-openstack project and my experience is that this aversion to actual
languages is part of a pipe dream. The only people who are able to work with
the modules in any meaningful way are the ones that understand the Puppet DSL
and runtime in its entirety, and it's not much simpler than the Ruby language
it's based on.

Honestly I don't know what the solution is: part of the DevOps movement is
introducing development practices to the management of systems, but that
brings with it an inherent requirement that the operators actually embrace the
development practices. A quick example of where this can easily fall down is
if you maintain a puppet environment of any complexity, you'll end up keeping
both the data inputs and the modules in git repos, but if your sysadmins
aren't comfortable with git, the adoption simply won't happen.

~~~
stormbrew
> A quick example of where this can easily fall down is if you maintain a
> puppet environment of any complexity, you'll end up keeping both the data
> inputs and the modules in git repos, but if your sysadmins aren't
> comfortable with git, the adoption simply won't happen.

As someone who is traditionally more dev side, but has done a lot of casual
system administration, this part of things like chef and puppet drives me
nuts. I don't want to version my infrastructure in git and then throw it, with
no versioning context, up to a server and have it version it again in its own
unique, quirky, and honestly haphazard way.

------
bryanlarsen
Of course, Ansible doesn't really use YAML. It uses a YAML parser, but each
individual command goes through quite a bit of parsing inside ansible as well.
An ansible command like this:

    
    
       - command: chdir=/foo echo {{ bar }}
         when: bar is defined
    

Really parses down to something like:

    
    
        - action:
          - module: command
          - arguments:
             - chdir: /foo
             - command: echo {{ bar }}
          - when: bar is defined
    

More parsing is done by ansible than is done by YAML. I'm not necessarily
saying it's bad, but it definitely leads to some gotchas and weirdnesses.

How it mixes in Jinja2 is also strange. In the above example, there are two
expressions: {{ bar }} and 'bar is defined'. Normally if you paired a
templating language with a text format, you would expect the templating
language to apply to the whole file. Ansible applies it afterwards, and
selectively. That's the right thing to do, but it does make it confusing.

Many people choose ansible because they don't want to learn Ruby as well as a
CM tool; ansible isn't much simpler. I'm not a huge fan of ansible, it's just
better than everything else I've encountered so far.

------
tdicola
I've been using Ansible a bit recently (and _really_ enjoying it) and agree
that YAML can be a little wonky at times, like having to escape any template
line with :{ in quotes because YAML interprets it as a dictionary. However I
don't think Ansible wants you to code all your logic in YAML. You can easily
write a plugin with Python and have all the proper syntax and capabilities of
a programming language.

Where Ansible really shines is giving you a huge library of quality
plugins/components and a simple YAML-based DSL for composing those plugins.
Want to spin up an EC2 instance, copy over your code, and ensure a service is
started? No problem, it's a 4 or 5 line Ansible script. When you want to do
something more advanced, look at the extension points Ansible provides to
plugin your own code:
[http://docs.ansible.com/developing_plugins.html](http://docs.ansible.com/developing_plugins.html)

~~~
doxcf434
Right, if you need more complex logic, then you write a module in a normal
programming language. The YAML is intended to keep the intention and
orchestration logic simple and readable.

~~~
dj-wonk
Does this work well in practice? I'm new to Ansible.

~~~
walrus
It works okay. One shortcoming, as mentioned at
[https://news.ycombinator.com/item?id=7831680](https://news.ycombinator.com/item?id=7831680),
is that there is no clear model for state transitions. Let's say that on day
1, you want to use Apache:

    
    
      - apt: name=apache2 state=present
    

Then, on day 2, you realize that Apache isn't hip, so you switch to nginx
instead:

    
    
      - apt: name=apache2 state=absent
      - apt: name=nginx state=present
    

It works, but you're stuck with entries in your playbook that are there for
purely historical reasons.

~~~
doxcf434
It depends on your deployment model to a degree. In the case where you build a
new image for your web server on every deployment, then this isn't an issue.
For longer running systems, like databases, it would still be an annoyance.

I think that Ansible is still a transitional glue tech though, and projects
like flynn.io may move things forward by making the CM part of the
infrastructure a developer task vs. a devops one.

------
akoumjian
One of the things I like about Saltstack is that you can build your formulas
using any renderers you like. You can try to remain strictly declarative in
YAML, or if you like build your states completely dynamically in Python or a
Python-DSL. The default uses an inbetween that takes YAML buts lets you
template that YAML with Jinja.

[[http://docs.saltstack.com/en/latest/ref/renderers/](http://docs.saltstack.com/en/latest/ref/renderers/)]

------
mavelikara
Build tools also had a similar evolution. Ant's XML syntax first started out
as all declarative, but then later on had to add more control structures (ant-
contrib, IIRC). The currently popular build tools - Gradle, Rake, Grunt etc -
all use a dynamically typed full-blown programing language for specifying
tasks and their dependencies.

~~~
dj-wonk
As another example, Leiningen is largely declarative, but since Clojure code
is also data, it is possible to insert code alongside. See line 211 in the
sample project.clj.

[https://github.com/technomancy/leiningen/blob/stable/sample....](https://github.com/technomancy/leiningen/blob/stable/sample.project.clj#L211)

------
benatkin
I find YAML to be code shoehorned into YAML and think it's ambiguous whether
under the GPL (the license itself, not AnsibleWorks' interpretation of it) the
YAML is subject to the GPL. It seems to be class declaration, iteration, and
function calls (to GPLed functions) to me.

------
crdoconnor
The part of ansible that really kind of bugs me isn't the YAML, it's the
default JSON output of commands.

I ended up integrating this into all my projects:

[http://blog.cliffano.com/2014/04/06/human-readable-
ansible-p...](http://blog.cliffano.com/2014/04/06/human-readable-ansible-
playbook-log-output-using-callback-plugin/)

Which fixes the problem (sort of), but I really don't understand why the
default isn't looking something like that.

It's a real pain parsing through some JSON with a ton of \n...\n...\n...\n's
in order to find the source of the errors.

------
rmrfrmrf
I'd say leave the programming languages to modules and compose them together
with a data language. Forced simplicity for configuration is a good thing.

~~~
dj-wonk
You'd prefer to allow composability in the middle and bottom layers (the
modules) but have a different language on top?

I have to admit that I'm a fan of turtles -- the same kind of turtles -- all
the way down. Many of the abstractions I see in configuration management tools
seem to be fancy names for modules. I don't see why a role, a playbook, a
play, and a task really need to be different things at all. Why is the
hierarchy necessary?

~~~
rmrfrmrf
> You'd prefer to allow composability in the middle and bottom layers (the
> modules) but have a different language on top?

Absolutely. IMO, the top layer should be a summary of what the configuration
manager will be doing and should have the project-specific data in it. The
rest should be reusable modules. When you let a full program language into the
top layer, you inevitably get people trying to put smaller routines in the top
level itself mixed in with reusable modules, which results in bloated
spaghetti.

------
jimbokun
Any Java programmers here?

Thank God IntelliJ treats Spring XML as Java code, because so much logic and
conditionals and variables live in those files. The actual program can be very
different than what you would expect only looking at the Java files.

It pains me to see other tools make the same foolish mistake, even if I don't
happen to use it.

------
mwsherman
I suspect that Web Components will evolve this way as well, declarative
language used imperatively. [http://clipperhouse.com/2014/03/31/web-
components-have-we-no...](http://clipperhouse.com/2014/03/31/web-components-
have-we-not-been-here-before/)

------
fleitz
Yeah, why not use a language like bash that we use everyday for config
management instead of reinventing the wheel in YAML.

This is pretty much why I love fucking shell scripts.
[http://fuckingshellscripts.org/](http://fuckingshellscripts.org/)

~~~
Sae5waip
Because modern configuration management tools like Ansible (or Puppet, or
Salt, or whatever) allow you to do more things more easily.

Also, because Bash is a particularly horrible language. I have a lot of
experience writing bash scripts, and I hate bash.

------
shiven
Please! Not that horrible, horrid poop called XML. Keep it away from my
beloved deployment/management tool. The world has plenty of other bloated
packages that will gladly not care if they are bogged down with XML, just
leave ansible alone!

I have a visceral hatred, _a la_ Erik Naggum, towards XML. His arguments
against XML capture a lot of my feelings, so I won't rehash them here.

