Skip to content

Ansible

This is about ansible standalone, you could also run this via vagrant (provision), see vagrant doc for that. This can also be done with python itself. That actually gives you much more control but of course less pre-cooked installation tasks. See the lang repository for a complete install script using python only.

installation

install
apt-get install ansible

osx installation

Since there are plenty of problems occurring in various versions it would be easy to switch between versions rather quickly. Therefore installation with pip looks like the easiest way. Also install yolk to see which versions are available:

yolk
sudo pip install yolk
yolk -V ansible 

if you get this error while running yolk :

error
1
2
3
4
yolk -l 

...
UnicodeEncodeError: 'ascii' codec can't encode character u'u2014' in position 1189: ordinal not in range(128)

It seems to be a bug, upgrading yolk might help :

upgrade
pip install --upgrade yolk3k

The last command will show something like :

list versions
1
2
3
4
5
6
7
8
ansible 2.1.0.0
ansible 2.0.2.0
ansible 2.0.1.0
ansible 2.0.0.2
ansible 2.0.0.1
ansible 1.9.6
ansible 1.9.5
ansible 1.9.4

Sadly at the time of writing yolk crashed on execution, but you could get a similar list if you invoke pip with a non-existent version of the package you want :

pip
1
2
3
4
5
sudo pip install ansible==3.0

Collecting ansible==4.0
Could not find a version that satisfies the requirement ansible==4.0 (from versions: 1.0, 1.1, 1.2, 1.2.1, 1.2.2, 1.2.3, 1.3.0, 1.3.1, 1.3.2, 1.3.3, 1.3.4, 1.4, 1.4.1, 1.4.2, 1.4.3, 1.4.4, 1.4.5, 1.5, 1.5.1, 1.5.2, 1.5.3, 1.5.4, 1.5.5, 1.6, 1.6.1, 1.6.2, 1.6.3, 1.6.4, 1.6.5, 1.6.6, 1.6.7, 1.6.8, 1.6.9, 1.6.10, 1.7, 1.7.1, 1.7.2, 1.8, 1.8.1, 1.8.2, 1.8.3, 1.8.4, 1.9.0.1, 1.9.1, 1.9.2, 1.9.3, 1.9.4, 1.9.5, 1.9.6, 2.0.0.0, 2.0.0.1, 2.0.0.2, 2.0.1.0, 2.0.2.0, 2.1.0.0, 2.1.1.0, 2.1.2.0, 2.1.3.0, 2.1.4.0, 2.1.5.0, 2.2.0.0, 2.2.1.0, 2.2.2.0)
No matching distribution found for ansible==4.0

So take you pick.. AND skip 2.2.0.0 , it does not work correctly.

install with pip
sudo pip install ansible==2.2.2.0

yaml

The base language used : see http://www.yaml.org/spec/1.2/spec.html

The yaml syntax is quite simple, here is a quick cheatsheet found here http://cheat.readthedocs.io/en/latest/yaml.html

A value:

value
value

value named "foo":

value
foo: value

List:

list
1
2
3
- 1
- 2
- 'a string'

A list named "bar":

named list
1
2
3
4
bar:
  - 1
  - 2
  - 'a string'

Alternate list syntax ("Flow style"):

array form list
bar: [1, 2, 'a string']

Dictionary:

dictionary
1
2
3
key1: val1
key2: val2
key3: val3

A dictionary named "joe":

named dictionary
1
2
3
4
joe:
  key1: val1
  key2: val2
  key3: val3

Dictionary in flow style:

flow style dictionary
joe: {key1: val1, key2: val2, key3: val3}

A list of dictionaries:

list of dictionaries
1
2
3
4
5
children:
  -   name: Jimmy Smith
      age: 15
  -   name: Jenny Smith
      age 12

inventory

Also known as hosts file, it is advertised to be /etc/ansible/hosts, but on my mac it just can't find that, so use the -i option. It contains the ip's of all hosts you added with ssh-copy-id above.

inventory
ansible -i hosts

You can add a line to the ansible.cfg file to run without -i hosts. I added some more useful directives as well :

ansible.cfg
1
2
3
role_path = ../../:roles #take dev roles before current directory
inventory = hosts
retry_files_enabled = False # do NOT make a playbook.retry

debugging

Some tricks to use when debugging ansible scripts.

dumping the Facts

A very neat one, also to see if you might want to use some variables there:

host info
ansible all -m setup -i hosts

Or any host instead of all, it will dump the complete Facts db so better redirect it into some file.

debug messages

These can be used throughout the playbooks and roles, simply to display a message or dump a variable, this next example gets the result of a shell command and displays it :

debugging
1
2
3
4
- shell: grep nameserver /etc/resolv.conf | wc -l
  register: resolv_conf_filled

- debug: var=resolv_conf_filled

output (when resolv.conf is empty)

output
TASK: [common | debug var=resolv_conf_filled] *********************************  
ok: [10.10.7.23] => {     
    "resolv_conf_filled": {         
        "changed": true,          
        "cmd": "grep nameserver /etc/resolv.conf | wc -l",          
        "delta": "0:00:00.005865",          
        "end": "2015-02-26 09:19:03.848714",          
        "invocation": {             
            "module_args": "grep nameserver /etc/resolv.conf | wc -l",              
            "module_name": "shell"         
        },          
        "rc": 0,          
        "start": "2015-02-26 09:19:03.842849",          
        "stderr": "grep: /etc/resolv.conf: No such file or directory",          
        "stdout": "0",          
        "stdout_lines": [             "0"         ],          
        "warnings": []     
    } 
}

You could also shorten it to :

debug
- debug: msg="var needed is {{resolv_conf_filled.stdout}} "

keeping the scripts on the target

To keep the command files that ansible creates on the remote host, set this environment variable:

inspect scripts
export ANSIBLE_KEEP_REMOTE_FILES=1

The files will be places in /root/.ansible/tmp, and you can view what is attempted to execute. Also use -vvvv option of ansible-playbook to see which files are created.

speed up development playbooks

Mostly the scripts at RINIS require double login for each run: one for the user and one for the vault. At least one of these can be skipped when developing. We use vagrant to create the base VM's so we can use the insecure_private_key it uses by setting insert_key off :

use insecure key
config.ssh.insert_key = false;

If this setting is true (the default) vagrant will try to replace the insecure_private_key with a less insecure one and use that for login. That's exactly what we don't want, so set it to false.

The key is normally stored in your home directory : ~/.vagrant.d/insecure_private_key To use it ansible use this section in you playbook :

sudo
1
2
3
remote_user: vagrant
become: yes
become_user: root

This will cause ansible to login as vagrant and after that become root (don't forget become or you will just stay 'vagrant' !)

Now you could run with the --private-key option :

provide private key
ansible-playbook Rinis_Bootstrap.yml --private-key=~/.vagrant.d/insecure_private_key --extra-vars="target=vbox"

But that's actually more typing than the password, so place it in ansible.cfg :

ansible.cfg
private_key_file    = ~/.vagrant.d/insecure_private_key

Of course editing the Playbook and replacing {{target}} with development will leave you with :

passwordless call
ansible-playbook Rinis_Bootstrap.yml

To also have the vault password filled in for you, place it in a plain-text file and then add that filename to ansible.cfg

ansible.cfg
vault_password_file = plain-text

detecting system

Sometimes you want to know what system you are running on, for instance detecting if this is a VM or a real machine. You can use this command to get some info about your system.

sys_vendor
cat /sys/devices/virtual/dmi/id/sys_vendor

On my workstation this says :

Note

Gigabyte Technology Co., Ltd.

On a Virtualbox VM it will say :

Note

innotek GmbH

Innotek was probably the creator of VirtualBox since it was acquired in 2008 by SUN Microsystems which in turn was acquired by Oracle in 2010. To test these values with ansible you need the variable "ansible_system_vendor" for instance look for it in the output of :

host info
ansible -i hosts development -m setup -u root

Shell vs. Command

A typical example are the Ansible modules Shell and Command. In the most use cases both modules lead to the same goal. Here are the main differences between these modules.

  • With the Command module the command will be executed without being proceeded through a shell. As a consequence some variables like $HOME are not available. And also stream operations like <, >, | and & will not work.
  • The Shell module runs a command through a shell, by default /bin/sh. This can be changed with the option executable. Piping and redirection are here therefor available.
  • The command module is more secure, because it will not be affected by the user's environment.

Important

Command is more secure.. Shell will work more often. I would say start with command, and revert to shell when it does not work.