
Show HN: Interactive Ansible Tutorial - erkanerol
https://github.com/turkenh/ansible-interactive-tutorial
======
jasim
I wish there was a server provisioning "library" written in an ML-ish
language.

The trouble with even a simple, well-made tool like Ansible is its dynamic
DSL. The YAML file is essentially code, but modules like "file" and "apt"
written as configuration entries give a declarative feel to it. But they are
just procedures that strive to be idempotent, and its YAML file is just a
series of procedure calls, sprinkled with some facility for organizing
hierarchies and sharing code between them.

YAML the format is also not a great way to encode systems data. Thankfully
Ansible has documented the gotchas with its space-indentation and need for
explicit quoting in
[http://docs.ansible.com/ansible/latest/YAMLSyntax.html#gotch...](http://docs.ansible.com/ansible/latest/YAMLSyntax.html#gotchas).
But that is just an attempt to band-aid over the unsuitability of YAML for
this purpose.

Chef's configuration on the other hand can be done in Ruby, but you're still
constrained to its DSLs. The shape and structure of Chef's objects can only
gleaned by reading reams of documentation, and worse, by running the cookbooks
with debug statements.

The problem is compounded when you upgrade these tools and things stop working
silently. The community solution for this unsurprisingly is unit tests. I'm
still grappling with that idea.

But what if we could write our own provisioning code in Haskell or
OCaml/Reason, with library functions that help install packages, returns
errors in neat sum types which we can confidently handle and doesn't leave us
to worry about the known unknowns that we haven't enumerated and handled, and
a compiler with exhaustive pattern matching that helpfully tells us about all
the record types and their structure within a fast edit-compile cycle, ...

~~~
crdoconnor
>The YAML file is essentially code

YAML is not turing complete and is hence not "code". That is a large part of
what makes ansible such a powerful tool - it enforces a strict separation of
concerns between the definition of server configuration and its execution and
keeps one in a language that is deliberately _not able_ to be made more
complex than is needed, is thus kept readable and straightforward to maintain.

By contrast, turing complete languages are veritable _magnets_ for technical
debt, which is why a bad chef playbook will always be worse than a bad ansible
playbook. Haskell, being turing complete, would suffer the same issue albeit
not to the same degree as ruby.

>YAML the format is also not a great way to encode systems data. Thankfully
Ansible has documented the gotchas with its space-indentation and need for
explicit quoting in
[http://docs.ansible.com/ansible/latest/YAMLSyntax.html#gotch...](http://docs.ansible.com/ansible/latest/YAMLSyntax.html#gotch...).
But that is just an attempt to band-aid over the unsuitability of YAML for
this purpose.

YAML has a few oblique gotchas but they don't affect the fundamental
suitability of it for this purpose. Once you get used to it, space indentation
becomes a feature, not a bug.

~~~
jasim
Any sufficiently complicated configuration language contains an ad hoc,
informally-specified, bug-ridden, slow implementation of a Turing complete
programming language.

Ansible playbooks have variables, loops, conditionals, scoping rules,
inheritance, and you can even extend it by writing custom modules in Python,
which is a Turing complete language.

The problem with not using a real programming language when you're trying to
essentially "program" is that you're expressing complex programs without any
of the abstractions and tooling support that a real language has.

Despite all that I like Ansible's constrained format and the resulting
simplicity compared to Chef. But I think we can take those design aesthetics
and apply it in a statically typed library and maybe get something more
sturdy.

~~~
crdoconnor
>Ansible playbooks have variables, loops, conditionals, scoping rules,
inheritance

As far as I am aware, variables, scoping rules and inheritance don't imply
turing completeness and the way it does loops and conditionals could really
more be characterized as configuration for loops/conditionals further down the
stack (e.g. as seen here
[http://docs.ansible.com/ansible/latest/playbooks_loops.html#...](http://docs.ansible.com/ansible/latest/playbooks_loops.html#loops-
and-includes-in-2-0) )

>you can even extend it by writing custom modules in Python, which is a Turing
complete language.

Yes, the idea is that you have the power to break into a (good) turing
complete language when it is necessary but you can keep that code - and by
extension _the technical debt it would attract_ \- to an absolute minimum.
I've personally never felt the need to write a custom module in python when
using ansible despite using it a lot, so for me, minimum is zero. I'm sure I'm
not alone either.

>The problem with not using a real programming language when you're trying to
essentially "program" is that you're expressing complex programs without any
of the abstractions and tooling support that a real language has.

Yes, this is a problem if you're trying to work within a problem space that is
not heavily constrained. If almost every time I used ansible I felt the need
to write a python module to do almost everything I would agree that it is a
fundamentally unsuitable task. I feel this issue when writing _build scripts_
which I think absolutely have to be kept turing complete, but never server
orchestration.

~~~
leg100
> As far as I am aware, variables, scoping rules and inheritance don't imply
> turing completeness and the way it does loops and conditionals could really
> more be characterized as configuration for loops/conditionals further down
> the stack (e.g. as seen here
> [http://docs.ansible.com/ansible/latest/playbooks_loops.html#...](http://docs.ansible.com/ansible/latest/playbooks_loops.html#..).
> )

Then what does _imply_ turing completeness?

According to the wikipedia article [1]:

"To show that something is Turing complete, it is enough to show that it can
be used to simulate some Turing complete system. For example, an imperative
language is Turing complete if it has conditional branching (e.g., "if" and
"goto" statements, or a "branch if zero" instruction; see one instruction set
computer) and the ability to change an arbitrary amount of memory (e.g., the
ability to maintain an arbitrary number of variables). Since this is almost
always the case, most if not all imperative languages are Turing complete if
the limitations of finite memory are ignored."

[1]
[https://en.wikipedia.org/wiki/Turing_completeness](https://en.wikipedia.org/wiki/Turing_completeness)

~~~
crdoconnor
>Then what does imply turing completeness?

If it did arbitrary branching and if you could mutate a variable and then
reuse it later on in a playbook.

~~~
Spivak
The branching is a given. Variable mutation is totally possible with set_fact.

------
ben_jones
A couple years ago I was working at a start-up on a team of about 3
developers. I was 20 years old and knew nothing about configuration
management, but we needed it, so I bought a book ("x for devops" \- trying not
to advertise), and got an automation pipeline in place that got the job done.

Cannot stress enough to new developers how you should have one of Ansible,
Puppet, etc., framework under your belt to improve your ability to build
software products. I'd recommend picking one that works equally good with old
legacy systems, rather then just whatever is new like Kubernetes, because it
will seriously broaden your career options and make you an asset to almost
every software company.

EDIT: to clarify, k8s can obviously be used with legacy software applications.
But the idea was that if you get hired by $some_old_PHP_shop throwing Ansible
into the mix may have significantly less friction then convincing whoever is
in charge to start maintaining k8s clusters.

~~~
kkoppenhaver
"hired by $some_old_PHP_shop throwing Ansible into the mix"

Wholeheartedly agree. Got brought on board and Ansible was the first tool I
reached for (there was previously nothing like this in place). The new tech is
great, but something more broad in scope that can work with different kinds of
systems can really come in handy if you're not working on new tech or
greenfield projects.

------
ffdixon1
OK, have to say this is pretty cool. Reading about how to do something is
good, but ephemeral. Applying what you are learning (and making mistakes and
figure out what went wrong) is a far better way to learn. Kudos to the author
of this tutorial.

------
collyw
For me the hardest part about Ansible was getting the ssh setup correct to
connect to a remote machine. Having a quick browse of this tutorial I can't
see much about that (maybe I missed it). That would be useful if you plan to
update the tutorial.

~~~
tokenizerrr
As far as I know all you have to do is configure your ~/.ssh/config properly,
and then use the hostnames set there. Same as regular old OpenSSH.

Just don't opt into the Paramiko control scheme, which isn't used by default
except on RHEL6 anyway.

You can also set ssh_args in the config file to enable ControlMaster, etc.
[http://docs.ansible.com/ansible/latest/intro_configuration.h...](http://docs.ansible.com/ansible/latest/intro_configuration.html#openssh-
specific-settings)

------
sideshowb
It's a trap, Ender, this is not a tutorial!

------
minusf
[https://pyinfra.readthedocs.io/](https://pyinfra.readthedocs.io/)

------
angarg12
I like how Ansible shows how sometimes technology can come full circle.

Ansible started as a more organized way to manage infrastructure beyond hacks
and handmade scripts. As technology matured and infrastructure become more
complex, the simplicity of Ansible fell short, and tools like Puppet and Chef
came into scene.

But technology kept pushing forward, and these tools evolved to become
increasingly complex until they become behemoths with towering ecosystems
around them.

Enter containers and container orchestration. Suddenly many of the problems
that configuration managers were trying to solve aren't there anymore. And
suddenly Ansible simplicity, which became its weakness, has become its
strength.

~~~
FooBarWidget
> As technology matured and infrastructure become more complex, the simplicity
> of Ansible fell short, and tools like Puppet and Chef came into scene.

Wait what? I'm pretty sure Ansible came after Puppet and Chef, not the other
way around.

~~~
oblio
CFEngine 1993 (for completeness)

Puppet 2005

Chef 2009

Salt 2011 (also for completeness)

Ansible 2012

OP's timeline is a bit off :)

~~~
dullgiulio
Before CFEngine, people used the 'm4' macro processor to generate
configuration files. It was very common for sendmail ones, but also for fast
replication with minimal differences.

