Organizing with include

Keep on Learning!

If you liked what you've learned so far, dive in!
Subscribe to get access to this tutorial plus
video, code and script downloads.

Start your All-Access Pass
Buy just this tutorial for $10.00

Our playbook is a mess: there's just a lot of tasks in one file. Let's get organized!

There are a few "categories" of things in the playbook. One category deals with "Bootstrapping Symfony", like installing the composer dependencies, fixing the var directory permissions and all of our Symfony console commands:

---
- hosts: vb
... lines 3 - 26
tasks:
... lines 28 - 188
- name: Install Composer's dependencies
composer:
working_dir: "{{ symfony_root_dir }}"
no_dev: "{{ 'yes' if ('prod' == symfony_env) else 'no' }}"
tags:
- deploy
when: code_changed
- name: Fix var directory permissions
file:
path: "{{ symfony_var_dir }}"
state: directory
mode: 0777
recurse: yes
changed_when: false
tags:
- permissions
- deploy
# Symfony console commands
- name: Create DB if not exists
command: '{{ symfony_console_path }} doctrine:database:create --if-not-exists'
register: db_create_result
changed_when: "not db_create_result.stdout|search('already exists. Skipped')"
tags:
- deploy
- name: Execute migrations
command: '{{ symfony_console_path }} doctrine:migrations:migrate --no-interaction'
register: db_migrations_result
changed_when: "not db_migrations_result.stdout|search('No migrations to execute')"
tags:
- deploy
when: code_changed
- name: Load data fixtures
command: '{{ symfony_console_path }} hautelook_alice:doctrine:fixtures:load --no-interaction'
when: symfony_env != "prod"
changed_when: false
tags:
- deploy
- name: Clear cache
command: '{{ symfony_console_path }} cache:clear --env={{ symfony_env }}'
changed_when: false
tags:
- deploy
when: code_changed
... lines 237 - 250

Using include()

I'd like to isolate these tasks into their own file. And... there are 2 good ways to do that. The first is.... just to include it. Create a new directory inside ansible called includes/, and inside there, a new file called symfony-bootstrap.yml. Start with the --- on top:

---
... lines 2 - 50

Now, let's move some tasks here! Grab "Install Composer Dependencies" and move it. We also want "Fix var directory permissions" all the way down to the end: "Clear Cache". Delete all of it and paste it into symfony-bootstrap.yml:

---
- name: Install Composer's dependencies
composer:
working_dir: "{{ symfony_root_dir }}"
no_dev: "{{ 'yes' if ('prod' == symfony_env) else 'no' }}"
tags:
- deploy
when: code_changed
- name: Fix var directory permissions
file:
path: "{{ symfony_var_dir }}"
state: directory
mode: 0777
recurse: yes
changed_when: false
tags:
- permissions
- deploy
# Symfony console commands
- name: Create DB if not exists
command: '{{ symfony_console_path }} doctrine:database:create --if-not-exists'
register: db_create_result
changed_when: "not db_create_result.stdout|search('already exists. Skipped')"
tags:
- deploy
- name: Execute migrations
command: '{{ symfony_console_path }} doctrine:migrations:migrate --no-interaction'
register: db_migrations_result
changed_when: "not db_migrations_result.stdout|search('No migrations to execute')"
tags:
- deploy
when: code_changed
- name: Load data fixtures
command: '{{ symfony_console_path }} hautelook_alice:doctrine:fixtures:load --no-interaction'
when: symfony_env != "prod"
changed_when: false
tags:
- deploy
- name: Clear cache
command: '{{ symfony_console_path }} cache:clear --env={{ symfony_env }}'
changed_when: false
tags:
- deploy
when: code_changed

Now that these are in their own file, they should not be indented: so un-indent them twice.

In the playbook, to bring those in - it's really cool: where you would normally put a module, say include: ./includes/symfony-bootstrap.yml:

---
- hosts: vb
... lines 3 - 26
tasks:
... lines 28 - 188
# Bootstrap Symfony app
- include: ./includes/symfony-bootstrap.yml
handlers:
... lines 193 - 204

Tip

include module is deprecated since 2.4 and will be removed in version 2.8, use import_tasks module instead.

The tasks will run in a slightly different order than they did before, but it won't make any difference for us. But, to be sure try the playbook with -t deploy:

ansible-playbook ansible/playbook.yml -i ansible/hosts.ini -t deploy

All good! Including a file is the easiest way to organize and re-use tasks. But, there's a better, cooler, more robust, more hipster way. It's called roles.

Leave a comment!

This tutorial is built using an older version of Symfony, but the core concepts of Ansible are still valid. New versions of Ansible may contain some features that we don't use here.

What PHP libraries does this tutorial use?

// composer.json
{
    "require": {
        "php": ">=5.5.9",
        "symfony/symfony": "3.1.*", // v3.1.4
        "doctrine/orm": "^2.5", // v2.7.2
        "doctrine/doctrine-bundle": "^1.6", // 1.6.4
        "doctrine/doctrine-cache-bundle": "^1.2", // 1.3.0
        "symfony/swiftmailer-bundle": "^2.3", // v2.3.11
        "symfony/monolog-bundle": "^2.8", // 2.11.1
        "symfony/polyfill-apcu": "^1.0", // v1.2.0
        "sensio/distribution-bundle": "^5.0", // v5.0.12
        "sensio/framework-extra-bundle": "^3.0.2", // v3.0.16
        "incenteev/composer-parameter-handler": "^2.0", // v2.1.2
        "doctrine/doctrine-migrations-bundle": "^1.2", // v1.2.0
        "snc/redis-bundle": "^2.0", // 2.0.0
        "predis/predis": "^1.1" // v1.1.1
    },
    "require-dev": {
        "sensio/generator-bundle": "^3.0", // v3.0.8
        "symfony/phpunit-bridge": "^3.0", // v3.1.4
        "doctrine/data-fixtures": "^1.1", // 1.3.3
        "hautelook/alice-bundle": "^1.3" // v1.4.1
    }
}