Hello World
Pre-req¶
- Git setup on test server
- Ansible Skeleton setup
- 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¶
- Open the
ansible/playbooks/test.yml
filecd ansible vi playbooks/test.yml
- Add the following information to the file
--- - hosts: localhost gather_facts: False roles: - iac-test ...
- Open the
ansible/roles/iac-test/tasks/main.yml
filevi roles/iac-test/tasks/main.yml
- Add the following information to the file
--- - debug: msg: "Hello World, we love yaml here" ...
- Run the
playbooks/test.yml
fileansible-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
- View the
ansible/roles/iac-test/vars/main.yml
filecd ansible vi roles/iac-test/vars/main.yml
- Add the following information to the file
foo: bar tree: fruit: apple nut: walnut
- View the
ansible/roles/iac-test/tasks/main.yml
file and call the variables in ansible and manipulate the datavi roles/iac-test/tasks/main.yml
- Add the following information to the file
--- - name: print our variable debug: var: foo - debug: var: tree - debug: var: tree.nut
- 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.
- View the following json information
{ "tree": { "fruit": "apple" } }
- How would we get the 'apple' information from this json?
variable: "{{ tree.fruit }}"
- 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'