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!

  • 2019-01-16 Victor Bocharsky

    Hey Norman,

    No problem, I'm glad it works for you. But I would be happy about your feedback ;)

    Cheers!

  • 2019-01-15 Norman Dilthey

    Thanks for checking!
    Seems like I messed up somewhere. Will check and get back to you if I find it :)

  • 2019-01-15 Victor Bocharsky

    Hey Norman,

    Hm, it's weird. I just double checked and it works well for me, so I don't need to pass that extra "code_changed=code_changed". Hm, probably you mistype something, or you don't have this "set_fact" task before:

        - name: Register code_changed variable
    set_fact:
    code_changed: repo_code.changed

    I also have the latest Ansible 2.7.5, so, I don't think we should tweak anything in this tutorial's code.

    Anyway, I'm glad you found the correct solution for you.

    Cheers!

  • 2019-01-14 Norman Dilthey

    Hey Victor,
    Ansible version: 2.7.5.

    I copied the code from the course code final folder actually. I only adjusted my paths and removed the AWS stuff.

  • 2019-01-14 Victor Bocharsky

    Hey Norman

    Thanks for sharing this with others! Btw, what Ansible version do you use so that you can't access code_changed variable inside of included task?

    Cheers!

  • 2019-01-13 Norman Dilthey

    For those coming here from the future ;)

    Make sure to pass the variable code_changed to the include file, otherwise you will get code_changed undefined errors.

    # Bootstrap Symfony app
    - include: ./includes/symfony-bootstrap.yml code_changed=code_changed

  • 2018-05-14 Victor Bocharsky

    Hey toporovvv ,

    Ah, good point! It's probably exactly that subtle difference between include_tasks and import_tasks. And probably we need to use import_tasks in this screencast because we do want to filter by tags here. Thanks for letting us know, I'll tweak the note in order to suggest import_tasks instead.

    Cheers!

  • 2018-05-11 toporovvv

    include_tasks didn't play tasks with "-t deploy" tags (on ansible 2.5.1). In my case import_task did the job done.

  • 2018-03-20 Victor Bocharsky

    Hey gstanto ,

    Thanks for letting us know! Yeah, "includes" is deprecated and will be removed in 2.8. Anyway, time to add a note about it.

    Cheers!

  • 2018-03-19 gstanto

    Just a heads up: I'm getting "includes" deprecated notice, change to "import_tasks"