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 ansible
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:

install ansible
sudo pip install yolk
yolk -V ansible 

if you get this error while running yolk :

error
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 :

output
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 :

forcing version list
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

setup ssh key

The simplest way ?

command
ssh-copy-id root@server

It will fix all details for you, create ~/.ssh/authorized_keys with the right(s) and it can cross-install keys, so you can install the key of yourself as root on the other machine. So :

root example
kees@localhost> ssh-copy-id root@server
...
kees@localhost> ssh root@server
root@server>

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:

yaml value
value

value named "foo":

yaml value
foo: value

List:

yaml list
- 1
- 2
- 'a string'

A list named "bar":

yaml named list
bar:
  - 1
  - 2
  - 'a string'

Alternative list syntax ("Flow style"):

yaml alternative list
bar: [1, 2, 'a string']

Dictionary:

yaml dictionary
key1: val1
key2: val2
key3: val3

A dictionary named "joe":

yaml dictionary
joe:
  key1: val1
  key2: val2
  key3: val3

Dictionary in flow style:

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

A list of dictionaries:

yaml list of dictionaries
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.

ansible 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 inventory
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:

hosts information
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
- shell: grep nameserver /etc/resolv.conf | wc -l
  register: resolv_conf_filled

- debug: var=resolv_conf_filled

output (when resolv.conf is empty)

debug 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 :

shorter
- 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:

preserve scripts on the host
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 :

don't insert ssh 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
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 :

login with the insecure vagrant key for development
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

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.

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

On my workstation this says :

Gigabyte Technology Co., Ltd.

On a Virtualbox VM it will say :

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 :

ansible command
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.