Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

using variables in ansible hosts targetting in playbook

I am trying to write a very flexible playbook that targets hosts based on environment they are in. I am using as many variables as possible, so the playbook can be reused for other projects/environments with minimal changes.

I have a single application.yml

---
- name: Prepare app-server for "The app"
  hosts: "{{'env'}}_super_app"
  vars:
  vars_files:
  - "environments/{{env}}.yml"
  sudo: yes
  tasks:
    - command: echo {{env}}
  roles:
    - common
    - nginx
    - php5-fpm
    - nodejs
    - newrelic
    - users
    - composer

- name: Install and configure mysql for "The super app"
  hosts:
  - "{{env}}_super_db"
  vars:
  vars_files:
  - "environments/{{env}}.yml"
  sudo: yes
  roles:
    - common
    - mysql
    - newrelic

Here is the playbook directory structure:

├── environments
│   ├── prod.yml       << environment specific vars
│   ├── stag.yml       << environment specific vars
│   └── uat.yml        << environment specific vars
├── roles
│   ├── common
│   ├── composer
│   ├── mysql
│   ├── newrelic
│   ├── nginx
│   ├── nodejs
│   ├── php5-fpm
│   └── users
├── users
│   └── testo.yml
├── prod              << inventory file for production
├── README.md
├── application.yml   << application playbook
├── stag              << inventory file for staging
├── uat               << inventory file for uat

Here are the contents of the uat inventory file:

[uat_super_app]
10.10.10.4
[uat_super_db]
10.10.10.5

When I run my playbook, I pass the environment as an extra variable:

ansible-playbook -K -i uat application.yml -e="env=uat" --check

The idea being: If {{env}} is set to uat, then the environments/uat.yml vars will be used, AND hosts [uat_super_app] will be targeted based on {{env}}_super_app.

If I or anyone makes a mistake and tries to run the uat vars against a production inventory, the hosts will not match, and ansible will not run the playbook.

ansible-playbook -K -i prod application.yml -e="env=uat" --check

This playbook works when I do not use variables in hosts targeting. The problem is that no hosts match either way:

ansible-playbook -K -i uat application.yml -e="env=uat" --check -vvvv

SUDO password: 
PLAY [Prepare app-server for "The app"] ******************************* 
skipping: no hosts matched

PLAY [Install and configure mysql for "The app"] ********************** 
skipping: no hosts matched

PLAY RECAP ******************************************************************** 
like image 786
Egidijus Avatar asked Oct 19 '22 14:10

Egidijus


2 Answers

hosts: "{{'env'}}_super_app"

That looks like you are using the string env, not the variable, which evaluates to env_super_app. I think you meant:

hosts: "{{ env }}_super_app"
like image 200
udondan Avatar answered Oct 22 '22 06:10

udondan


Thanks udondan, but that didn't work.

The solution was to pass the vars in a similar way that the playbook expects to see them.

If I were specifying the env in the playbook I would have:

---
- name: Prepare app-server for "The app"
  hosts: uat_super_app
  vars:
    - env: uat

So the correct way of passing the variable is:

ansible-playbook -K -i uat application.yml -e='vars: env=uat'

To test this I used the --list-hosts option:

ansible-playbook -K -i uat application.yml -e='vars: env=uat' --list-hosts

playbook: application.yml

  play #1 (Prepare app-server for "The super app"): host count=1
    10.10.10.4

  play #2 (Install and configure mysql for "The super app"): host count=1
    10.10.10.5
like image 45
Egidijus Avatar answered Oct 22 '22 08:10

Egidijus