> For the complete documentation index, see [llms.txt](https://isurus.gitbook.io/infrastructure-and-platform-notes/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://isurus.gitbook.io/infrastructure-and-platform-notes/ansible-5/06-playbooks-example.md).

# Playbook Example

* In here I will examile a real use case example by creating and executing Ansible playbooks. I will install Nginx in all hosts and explore the different options for targeting OS variations with Ansible packages.
* Use Ansible to install and configure project website, taking into account variances between the linux distributions of Nginx on both CentOS and Ubuntu.
* Use Jinja2 templates to customise the website.

Let's first create our ansible config file `ansible.cfg`:

```
[defaults]
inventory = hosts
host_key_checking = False
```

Next our group vars for centos and ubuntu hosts:

`group_vars/centos`:

```
---
ansible_user: root
...
```

`group_vars/ubuntu`:

```
---
ansible_user: root
...
```

Next our host file `hosts`:

```
[control]
ubuntu-c

[centos]
centos[1:3]

[ubuntu]
ubuntu[1:3]

[linux:children]
centos
ubuntu
```

Next our playbook itself for installing EPEL on CentOS hosts:

```
---
# YAML documents begin with the document separator ---

# The minus in YAML this indicates a list item.  The playbook contains a list
# of plays, with each play being a dictionary
-

  # Hosts: where our play will run and options it will run with
  hosts: linux

  # Vars: variables that will apply to the play, on all target systems

  # Tasks: the list of tasks that will be executed within the play, this section
  # can also be used for pre and post tasks
  tasks:
    - name: Install EPEL
      yum:
        name: epel-release
        update_cache: yes
        state: latest
      when: ansible_distribution == 'CentOS'

  # Handlers: the list of handlers that are executed as a notify key from a task

# Three dots indicate the end of a YAML document
...
```

Now we can execute the playbook:

```
$ ansible-playbook nginx_playbook.yaml 

PLAY [linux] *****************************************************************************************************************

TASK [Gathering Facts] ******************************************************************************************************************************
ok: [centos2]
ok: [centos1]
ok: [centos3]
ok: [ubuntu1]
ok: [ubuntu2]
ok: [ubuntu3]

TASK [Install EPEL] ******************************************************************************************************************************
skipping: [ubuntu1]
skipping: [ubuntu2]
skipping: [ubuntu3]
changed: [centos1]
changed: [centos3]
changed: [centos2]

PLAY RECAP *******************************************************************************************************************
centos1                    : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
centos2                    : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
centos3                    : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
ubuntu1                    : ok=1    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0   
ubuntu2                    : ok=1    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0   
ubuntu3                    : ok=1    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0
```

Now let's install Nginx in all hosts by slightly modifying the playbook `nginx_playbook.yaml`:

```
---
# YAML documents begin with the document separator ---

# The minus in YAML this indicates a list item.  The playbook contains a list
# of plays, with each play being a dictionary
-

  # Hosts: where our play will run and options it will run with
  hosts: linux

  # Vars: variables that will apply to the play, on all target systems

  # Tasks: the list of tasks that will be executed within the play, this section
  # can also be used for pre and post tasks
  tasks:
    - name: Install EPEL
      yum:
        name: epel-release
        update_cache: yes
        state: latest
      when: ansible_distribution == 'CentOS'

    - name: Install Nginx CentOS
      yum:
        name: nginx
        update_cache: yes
        state: latest
      when: ansible_distribution == 'CentOS'

    - name: Install Nginx Ubuntu
      apt:
        name: nginx
        update_cache: yes
        state: latest
      when: ansible_distribution == 'Ubuntu'

  # Handlers: the list of handlers that are executed as a notify key from a task

# Three dots indicate the end of a YAML document
...
```

Once we execute it, the output should be something similar to below:

```
$ ansible-playbook nginx_playbook.yaml

PLAY RECAP *******************************************************************************************************************
centos1                    : ok=3    changed=2    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0   
centos2                    : ok=3    changed=2    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0   
centos3                    : ok=3    changed=2    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0   
ubuntu1                    : ok=2    changed=1    unreachable=0    failed=0    skipped=2    rescued=0    ignored=0   
ubuntu2                    : ok=2    changed=1    unreachable=0    failed=0    skipped=2    rescued=0    ignored=0   
ubuntu3                    : ok=2    changed=1    unreachable=0    failed=0    skipped=2    rescued=0    ignored=0
```

or we can simply use Nginx module for that like below in `nginx_playbook.yaml`:

```
---
# YAML documents begin with the document separator ---

# The minus in YAML this indicates a list item.  The playbook contains a list
# of plays, with each play being a dictionary
-

  # Hosts: where our play will run and options it will run with
  hosts: linux

  # Vars: variables that will apply to the play, on all target systems

  # Tasks: the list of tasks that will be executed within the play, this section
  # can also be used for pre and post tasks
  tasks:
    - name: Install EPEL
      yum:
        name: epel-release
        update_cache: yes
        state: latest
      when: ansible_distribution == 'CentOS'

    - name: Install Nginx
      package:
        name: nginx
        state: latest

  # Handlers: the list of handlers that are executed as a notify key from a task

# Three dots indicate the end of a YAML document
...
```

Next let's add a task to restart Nginx in our playbook:

```
---
# YAML documents begin with the document separator ---

# The minus in YAML this indicates a list item.  The playbook contains a list
# of plays, with each play being a dictionary
-

  # Hosts: where our play will run and options it will run with
  hosts: linux

  # Vars: variables that will apply to the play, on all target systems

  # Tasks: the list of tasks that will be executed within the play, this section
  # can also be used for pre and post tasks
  tasks:
    - name: Install EPEL
      yum:
        name: epel-release
        update_cache: yes
        state: latest
      when: ansible_distribution == 'CentOS'

    - name: Install Nginx
      package:
        name: nginx
        state: latest

    - name: Restart nginx
      service:
        name: nginx
        state: restarted

  # Handlers: the list of handlers that are executed as a notify key from a task

# Three dots indicate the end of a YAML document
...
```

Now let's had a handler to add a http health check to make sure Nginx is running:

```
---
# YAML documents begin with the document separator ---

# The minus in YAML this indicates a list item.  The playbook contains a list
# of plays, with each play being a dictionary
-

  # Hosts: where our play will run and options it will run with
  hosts: linux

  # Vars: variables that will apply to the play, on all target systems

  # Tasks: the list of tasks that will be executed within the play, this section
  # can also be used for pre and post tasks
  tasks:
    - name: Install EPEL
      yum:
        name: epel-release
        update_cache: yes
        state: latest
      when: ansible_distribution == 'CentOS'

    - name: Install Nginx
      package:
        name: nginx
        state: latest

    - name: Restart nginx
      service:
        name: nginx
        state: restarted
      notify: Check HTTP Service

  # Handlers: the list of handlers that are executed as a notify key from a task
  handlers:
    - name: Check HTTP Service
      uri:
        url: http://{{ ansible_default_ipv4.address }}
        status_code: 200 

# Three dots indicate the end of a YAML document
...
```

Next let's create group vars for HTML location for Nginx in different hosts, and create a jinja template for HTML.

First let's nodify the playbook to deploy the HTML file inside Nginx:

```
---
# YAML documents begin with the document separator ---

# The minus in YAML this indicates a list item.  The playbook contains a list
# of plays, with each play being a dictionary
-

  # Hosts: where our play will run and options it will run with
  hosts: linux

  # Vars: variables that will apply to the play, on all target systems

  # Tasks: the list of tasks that will be executed within the play, this section
  # can also be used for pre and post tasks
  tasks:
    - name: Install EPEL
      yum:
        name: epel-release
        update_cache: yes
        state: latest
      when: ansible_distribution == 'CentOS'

    - name: Install Nginx
      package:
        name: nginx
        state: latest

    - name: Restart nginx
      service:
        name: nginx
        state: restarted
      notify: Check HTTP Service

    - name: Template index.html-base.j2 to index.html on target
      template:
        src: index.html-base.j2
        dest: "{{ nginx_root_location }}/index.html"
        mode: 0644

  # Handlers: the list of handlers that are executed as a notify key from a task
  handlers:
    - name: Check HTTP Service
      uri:
        url: http://{{ ansible_default_ipv4.address }}
        status_code: 200 

# Three dots indicate the end of a YAML document
...
```

Next our group vars for centos and ubuntu hosts:

`group_vars/centos`:

```
---
ansible_user: root
nginx_root_location: /usr/share/nginx/html
...
```

`group_vars/ubuntu`:

```
---
ansible_user: root
nginx_root_location: /var/www/html
...
```

Now let's add the `ansible_managed` variable in the `ansible.cfg`:

```
[defaults]
inventory = hosts
host_key_checking = False
ansible_managed = Managed by Ansible - file:{file} - host:{host} - uid:{uid}
```

Now we can use the `ansible_managed` variable inside any of our templates.

Now let's load out variables in the playbook.

```
---
# YAML documents begin with the document separator ---

# The minus in YAML this indicates a list item.  The playbook contains a list
# of plays, with each play being a dictionary
-

  # Hosts: where our play will run and options it will run with
  hosts: linux

  # Vars: variables that will apply to the play, on all target systems
  vars_files:
    - vars/logos.yaml

  # Tasks: the list of tasks that will be executed within the play, this section
  # can also be used for pre and post tasks
  tasks:
    - name: Install EPEL
      yum:
        name: epel-release
        update_cache: yes
        state: latest
      when: ansible_distribution == 'CentOS'

    - name: Install Nginx
      package:
        name: nginx
        state: latest

    - name: Restart nginx
      service:
        name: nginx
        state: restarted
      notify: Check HTTP Service

    - name: Template index.html-logos.j2 to index.html on target
      template:
        src: index.html-logos.j2
        dest: "{{ nginx_root_location }}/index.html"
        mode: 0644

  # Handlers: the list of handlers that are executed as a notify key from a task
  handlers:
    - name: Check HTTP Service
      uri:
        url: http://{{ ansible_default_ipv4.address }}
        status_code: 200 

# Three dots indicate the end of a YAML document
...
```

Add unarchive task in the playbook to unarchive the code of our hidden game.

```
    - name: Unarchive playbook stacker game
      unarchive:
        src: playbook_stacker.zip
        dest: "{{ nginx_root_location }}"
        mode: 0755
```
