Flag of Ukraine
SymfonyCasts stands united with the people of Ukraine

Tagging Tasks

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

Sometimes - especially when debugging - you just want to run only some of your playbook. Because... our playbook is getting so awesome... that, honestly, it takes some serious time to run!

For example, in my VM, I'm going to change the permissions on the var/ directory:

sudo chmod -R 555 var/

Definitely use sudo. Then, I'll remove the cache files:

sudo rm -rf var/cache/*

If you try the page now, it explodes! Ok, I don't expect my permissions to suddenly change like this under normal conditions. But, suppose that we had just hit this permission error for the first time and then added the "Fix var permissions" task. In that case, we would know that re-running the entire playbook should fix things.

But... couldn't we run just this one task? Yep! And a great way to do that is via tags.

Below the task, add tags, and then permissions:

---
- hosts: vb
... lines 3 - 10
tasks:
... lines 12 - 144
- name: Fix var directory permissions
... lines 146 - 150
tags:
- permissions
... lines 153 - 176

Now, from the command line, tell Ansible to only execute tasks with this tag: -t permissions:

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

It still goes through its setup but then... yep! Only one task! Refresh the page. Permissions fixed!

Tagging for Deployment

Here's another example. Right now, our playbook has tasks for two separate jobs. Some tasks setup the server - making sure PHP, Nginx and other stuff is installed and configured. But others are really more about code deployment: making sure the project directory exists, cloning the code, installing composer dependencies, and setting up the database.

In the future - when we make changes to the code - we might want to just deploy that code... without going through all the server setup tasks. Let's add a new tag - deploy - to every step involved in deployment. See the task that creates the project directory? Yep, give it the deploy tag. Add it to "Checkout Git Repository" and also to the three tasks that install Composer:

---
- hosts: vb
... lines 3 - 10
tasks:
... lines 12 - 111
- name: Create project directory and set its permissions
... lines 113 - 119
tags:
- deploy
- name: Checkout Git repository
... lines 124 - 127
tags:
- deploy
- name: Download Composer
... line 132
tags:
- deploy
- name: Move Composer globally
... lines 137 - 138
tags:
- deploy
- name: Set permissions on Composer
... lines 143 - 146
tags:
- deploy
- name: Install Composer's dependencies
... lines 151 - 153
tags:
- deploy
... lines 156 - 195

Actually, this is debatable: you might consider Composer as a "Server setup" task, not deployment. It's up to you.

Keep going! I'll add the task to everything that I want to run for each code update. It's not an exact science:

---
- hosts: vb
... lines 3 - 10
tasks:
... lines 12 - 111
- name: Create project directory and set its permissions
... lines 113 - 119
tags:
- deploy
- name: Checkout Git repository
... lines 124 - 127
tags:
- deploy
- name: Download Composer
... line 132
tags:
- deploy
- name: Move Composer globally
... lines 137 - 138
tags:
- deploy
- name: Set permissions on Composer
... lines 143 - 146
tags:
- deploy
- name: Install Composer's dependencies
... lines 151 - 153
tags:
- deploy
- name: Fix var directory permissions
... lines 158 - 162
tags:
- permissions
- deploy
# Symfony console commands
- name: Create DB if not exists
... line 169
tags:
- deploy
- name: Execute migrations
... line 174
tags:
- deploy
- name: Load data fixtures
... line 179
tags:
- deploy
... lines 182 - 195

Let's see if it works! In the virtual machine, I'm going to manually edit a file:

vim app/Resources/views/default/index.html.twig

Let's add a few exclamation points to be really excited. Then hit escape, :wq to save. In the browser, that won't show up immediately - because we're in Symfony's prod environment. But if you add app_dev.php to the URL... yep! "Filter by Tag!".

By the way, going to app_dev.php only works because I've already modified some security logic in that file to allow me to access it:

33 lines web/app_dev.php
... lines 1 - 10
// This check prevents access to debug front controllers that are deployed by accident to production servers.
// Feel free to remove this, extend it, or make something more sophisticated.
if (isset($_SERVER['HTTP_CLIENT_IP'])
|| isset($_SERVER['HTTP_X_FORWARDED_FOR'])
|| !(in_array(@$_SERVER['REMOTE_ADDR'], ['127.0.0.1', 'fe80::1', '::1', '192.168.33.1']) || php_sapi_name() === 'cli-server' || strpos($_SERVER['REMOTE_ADDR'], '192.168.') === 0)
) {
header('HTTP/1.0 403 Forbidden');
exit('You are not allowed to access this file. Check '.basename(__FILE__).' for more information.');
}
... lines 20 - 33

Ok, back in our local machine, run the playbook... this time with -t deploy:

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

Oh, much, much faster! Try the browser! Code deployed! You can also use --skip-tags if you want to get crazy and do the opposite:

ansible-playbook ansible/playbook.yml -i ansible/hosts.ini --skip-tags deploy

Next, let's talk about how we can "fix" the fact that some tasks say "Changed" every time we run them. Eventually, this will help us speed up our playbook.

Leave a comment!

8
Login or Register to join the conversation
Default user avatar
Default user avatar Дмитрий Политов | posted 4 years ago

Hi guys, I've modified 'app/Resources/views/default/index.html.twig' in VM, then I run `ansible-playbook ansible/playbook.yml -i ansible/hosts.ini -t deploy` and my changes have gone (file 'app/Resources/views/default/index.html.twig' does not contain changes). What am I doing wrong? Looks like ansible deploy task ('Checkout Git repository') returns it to its original state
Suppose, in theory, I should commit and push changes in repo before run this task?

Reply

Hey Dmitriy,

Sure, you should avoid uncommitted changes in your repo before running playbooks that have Git module. Or you need to improve your playbook to skip Git checkout if there's uncommitted changes, but this I'd not recommend because you would need to double check if Git was checked or no manually. So, I think better to commit changes first and then run the playbook. And I think it makes sense, you probably want to deploy only when all the changes you made are committed into the repo to deliver it to host.

Cheers!

Reply

Ansible fails constantly on this command:

$ ansible-playbook ansible/playbook.yml -i ansible/hosts.ini -t permissions

PLAY [vb] ***********************************************************************************************

TASK [Gathering Facts] **********************************************************************************
ok: [192.168.33.10]

TASK [Fix var directory permissions] ********************************************************************
fatal: [192.168.33.10]: FAILED! => {"changed": false, "module_stderr": "Shared connection to 192.168.33.10 closed.\r\n", "module_stdout": "Traceback (most recent call last):\r\n  File \"/home/vagrant/.ansible/tmp/ansible-tmp-1539374113.5349424-162400146138678/AnsiballZ_file.py\", line 113, in <module>\r\n    _ansiballz_main()\r\n  File \"/home/vagrant/.ansible/tmp/ansible-tmp-1539374113.5349424-162400146138678/AnsiballZ_file.py\", line 105, in _ansiballz_main\r\n    invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)\r\n  File \"/home/vagrant/.ansible/tmp/ansible-tmp-1539374113.5349424-162400146138678/AnsiballZ_file.py\", line 48, in invoke_module\r\n    imp.load_module('__main__', mod, module, MOD_DESC)\r\n  File \"/tmp/ansible_file_payload_rBkmeP/__main__.py\", line 863, in <module>\r\n  File \"/tmp/ansible_file_payload_rBkmeP/__main__.py\", line 849, in main\r\n  File \"/tmp/ansible_file_payload_rBkmeP/__main__.py\", line 571, in ensure_directory\r\n  File \"/tmp/ansible_file_payload_rBkmeP/__main__.py\", line 289, in recursive_set_attributes\r\n  File \"/tmp/ansible_file_payload_rBkmeP/ansible_file_payload.zip/ansible/module_utils/basic.py\", line 1546, in set_fs_attributes_if_different\r\n  File \"/tmp/ansible_file_payload_rBkmeP/ansible_file_payload.zip/ansible/module_utils/basic.py\", line 1313, in set_mode_if_different\r\nOSError: [Errno 1] Operation not permitted: '/var/www/project/var/sessions/prod'\r\n", "msg": "MODULE FAILURE\nSee stdout/stderr for the exact error", "rc": 1}
	to retry, use: --limit @/home/ivan/learn/SymfonyCasts/mootube/ansible/playbook.retry

PLAY RECAP **********************************************************************************************
192.168.33.10              : ok=1    changed=0    unreachable=0    failed=1```

But it does look like the permissions were partially changed back:

vagrant@vagrant-ubuntu-trusty-64:/var/www/project$ ls -ld var
drwxrwxrwx 5 vagrant vagrant 4096 Oct 12 19:51 var
vagrant@vagrant-ubuntu-trusty-64:/var/www/project$ ls -lR var
var:
total 104
-rwxrwxrwx 1 vagrant vagrant 55029 Oct 12 19:51 bootstrap.php.cache
drwxrwxrwx 2 vagrant vagrant 4096 Oct 12 19:53 cache
drwxrwxrwx 2 vagrant vagrant 4096 Oct 12 19:51 logs
drwxrwxrwx 4 vagrant vagrant 4096 Oct 12 19:51 sessions
-rwxrwxrwx 1 vagrant vagrant 34155 Oct 12 19:51 SymfonyRequirements.php

var/cache:
total 0

var/logs:
total 12
-r-xr-xr-x 1 vagrant vagrant 9772 Oct 12 19:51 dev.log

var/sessions:
total 8
drwxrwxrwx 2 vagrant vagrant 4096 Oct 12 19:51 dev
dr-xr-xr-x 2 www-data www-data 4096 Oct 12 19:51 prod

var/sessions/dev:
total 0

var/sessions/prod:
total 0`

Edit: nevermind, I see the problem: var/cache/prod was somewhen generated by the web server...

Reply

Hey Ivan,

Yes, files generated with web server will have different permissions. Btw, how did you fix the problem?

Cheers!

Reply

> how did you fix the problem?

I simply removed the folders owned by www-data :)

Reply

Hey Ivan,

Great, thanks for reaching back! I think it might be useful for other users.

Cheers!

Reply
Default user avatar
Default user avatar jian su | posted 5 years ago

Hi guys: why would you tags deploy for Move Compose globally when you just want to deploy your new code to server? Is this a one time thing when you install composer? I think most of time u just need to run composer install when you deploy ur new code to server.

Reply

Hey Jian,

Good question :) Actually, as Ryan said, this is debatable: you might consider Composer as a "Server setup" task, not deployment. It's up to you. But yeah, there's no a good reason to do it, especially if you're installing Composer globally. But it makes more sense if you do not want to install composer globally, i.e. just download composer.phar, use it and then remove it from the server at all. So fell free to remove deploy tag from tasks which install Composer and move it globally.

Cheers!

Reply
Cat in space

"Houston: no signs of life"
Start the conversation!

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
        "composer/package-versions-deprecated": "^1.11" // 1.11.99
    },
    "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
    }
}
userVoice