Skip to content

Hello World

Pre-req

  1. Git setup on test server
  2. Ansible Skeleton setup
  3. Run the following command in your home directory

./standard_playbook_skel.sh iac-test - Run tree and you should have the following directory structure layout

tree

├── ansible.cfg
├── playbooks
└── roles
    └── iac-test
        ├── defaults
           └── main.yml
        ├── handlers
           └── main.yml
        ├── Jenkinsfile
        ├── meta
           └── main.yml
        ├── molecule
           └── default
               ├── ansible-lint.yml
               ├── Dockerfile.j2
               ├── INSTALL.rst
               ├── molecule.yml
               ├── playbook.yml
               ├── requirements.yml
               ├── tests
                  ├── __pycache__
                     └── test_default.cpython-27-PYTEST.pyc
                  ├── test_default.py
                  └── test_default.pyc
               └── yaml-lint.yml
        ├── README.md
        ├── tasks
           └── main.yml
        ├── templates
        └── vars
            └── main.yml

Hello World

  1. Open the ansible/playbooks/test.yml file
    cd ansible
    vi playbooks/test.yml
    
  2. Add the following information to the file
    ---
    - hosts: localhost
      gather_facts: False
      roles:
        - iac-test
    ...
    
  3. Open the ansible/roles/iac-test/tasks/main.yml file
    vi roles/iac-test/tasks/main.yml
    
  4. Add the following information to the file
    ---
    - debug:
        msg: "Hello World, we love yaml here"
    ...
    
  5. Run the playbooks/test.yml file
    ansible-playbook playbooks/test.yml
    

Example Hello World Output

$cd ansible
$vi playbooks/test.yml

---
- hosts: localhost
  gather_facts: False
  roles:
    - iac-test
...
:wq (saves file)


$vi roles/iac-test/tasks/main.yml

---
- debug:
    msg: "Hello World, we love yaml here"
...
:wq (saves file)

$ansible-playbook playbooks/test.yml

Variables

There are many different ways that we can use variables. It's often asked, "where is the right place to define my variables in Ansible?" Let's explore the multiple ways that we can call them, so that you can decide what is best for you. Though I dare say, if you can call variables in the vars/ then you should do it there. However, it's not always possible.

A variable is a value that can change upon outside circumstances. Such as something that may be passed from Json/Yaml that we want to use in our playbooks that can change on different configurations.

Let's explore the vars/main.yml Our command might look something like

ansible-playbook playbooks/test.yml

  1. View the ansible/roles/iac-test/vars/main.yml file
    cd ansible
    vi roles/iac-test/vars/main.yml
    
  2. Add the following information to the file
    foo: bar
    tree:
      fruit: apple
      nut: walnut
    
  3. View the ansible/roles/iac-test/tasks/main.yml file and call the variables in ansible and manipulate the data
    vi roles/iac-test/tasks/main.yml
    
  4. Add the following information to the file
    ---
    - name: print our variable
      debug:
        var: foo
    
    - debug:
        var: tree
    
    - debug:
        var: tree.nut
    
  5. Run the ansible playbook
    cd ~/ansible
    ansible-playbook playbooks/test.yml
    

Example Output for Variables

$vi roles/iac-test/vars/main.yml
---
foo: bar
tree:
  fruit: apple
  nut: walnut

$vi roles/iac-test/tasks/main.yml
---
- name: print our variable
  debug:
    var: foo

- debug:
    var: tree

- debug:
    var: tree.nut

$ansible-playbook playbooks/test.yml

JSON Input

We can include JSON or YAML to our playbooks at runtime and use it as variables. The below is a very simple json, so let's see what it looks like when we declare this in our vars file.

  1. View the following json information
    {
      "tree": {
          "fruit": "apple"
      }
    }
    
  2. How would we get the 'apple' information from this json?
    variable: "{{ tree.fruit }}"
    
  3. Notice the usage of quotes, curly braces, and spaces. This is very important and this format needs to be copied. The below are incorrect formatting.
    variable: {{ tree.fruit }}
    variable: "{{tree.fruit}}"
    variable: "{ tree.fruit }"
    

Set Fact

This is an ansible module that allows you to set a fact inside of your playbook or role. Sometimes it is necessary to set a fact as it's not available to just define in our vars/main.yml file. It could be part of another variable or something that we have to look up in our playbook. So here are a couple of examples.

Note: if you create multiple facts in one play, you cannot use one of those to create another. As shown as the last example

---
- name: setting a fact
  set_fact:
    tree: "Apple"

- set_fact:
    foo: "bar"
    tree: "apple"

#this is a bad set fact, as we are trying to alter one of the facts that we are setting.  This will break.
- set_fact:
    foo: "bar"
    tree: "{{ foo[:1] }}"

Jinja

Filters in Ansible are from Jinja2, and are used for transforming data inside a template expression.

So lets take a look at some examples. We will share some of our most used, however, there are too many to cover them all.

Below, we see 2 filters being used. First, the split filter, and we are showing that we want to split by the . in the url. You are able to use anything for the split. Then second, we are using 1 inside of the brackets to indicate the second part of the split. Just like Jinja, it follows 0,1,2,3...

On the final example in this block, we will look at string slicing. If we set the fact "notasfun" and we want to get "as" out we need to have the first value of 3 to grab the 4th letter, then 5 to only grab to the 6th, try it out and have some fun.

Note: Ansible follows the typical standard of setting [0] as the first object in an iterative list.

---
- name: set url fact
  set_fact:
    url1: "www.nowhere.com"

- name: debug domain from url
  debug:
    msg: "{{ url.split('.')[1] }}"

######################### string slicing
---
- name: set fact
  set_fact:
    foo: "notasfun"

- name: slice the value
  debug:
    msg: "{{ foo[3:5] }}"

.J2 file templating

With the Ansible module "template" we can create a template for a config file, or anything else to move to a server with variable's setup. This is a great feature of Ansible that most teams find very useful. Let's first take a look at a template file that would could be a /etc/rsync.conf.j2. So, in our vars dir, or with a json that we call, we would be providing the user, chroot, max_connections and timeout so that we could provide those values and when it copies it over, it puts in the provided value.

# /etc/rsyncd: configuration file for rsync daemon mode

# See rsyncd.conf man page for more options.

# configuration example:

uid = {{ user }}
gid = {{ user }}
use chroot = {{ chroot }}
max connections = {{ max_connections }}
pid file = /var/run/rsyncd.pid
exclude = lost+found/
transfer logging = yes
timeout = {{ timeout }}
ignore nonreadable = yes
#don't compress   = *.gz *.tgz *.zip *.z *.Z *.rpm *.deb *.bz2

[ftp]
path = /home/ftp
comment = ftp export area

Now we would setup our task to call it like this

---
- name: rsync config template
  template:
    src: templates/rsync.conf.j2
    dest: /etc/rsync.conf
    owner: root
    group: root
    mode: '0644'

Here is the Json file that we would provide

{
  "config": {
    "user_name": "bob",
    "timeout": 800,
    "max_connections": 50
  }
}

And our vars/main.yml to make to shorten the vars that we include

---
user: "{{ config.user_name }}"
timeout: "{{ config.timeout }}"
max_connections: "{{ config.max_connections }}"

Tips and Tricks

Running a task against a specific host

---
- copy:
    src: /tmp/nothing
    dest: /tmp/somewhere
  when: ansible_host == 'hostname'