How to switch the execution target with ansible

We have multiple environments such as production environment, verification environment, development environment, etc. I think that it is common that servers and settings are different for each environment.

Since there are multiple ways to switch these targets with ansible, I would like to introduce it.

If the server is different but the settings are the same

In this case, I think that it is better to switch the group by using the inventory file.

[stg:children]
stg_Web
stg_DB

[prod:children]
prod_Web
prod_DB

[stg_web]
stg_web_01

[stg_DB]
stg_db_01

[prod_web]
prod_web_01

[prod_DB]
prod_db_01

It is written as follows,

% ansible-playbook -l prod something.yml

In feeling that -l should I switch the group. Groups can also be nested like the example above, so there can be no problems if there are multiple groups in one environment.

Switch execution task

I think that there is a possibility to switch only one last task. In that case, when you can switch between using.

- name: 本番環境用ファイルをコピー
  copy: src=config.ini.prod dest=/etc/config.ini
  when: target == 'prod'

- name: 検証環境用ファイルをコピー
  copy: src=config.ini.stg dest=/etc/config.ini
  when: target == 'stg'

If so, as before

% ansible-playbook -l prod something.yml

, The file corresponding to the execution target is copied.

Here, the target is entered in target.

I want to switch with tags

The Ansible --tags can be tagged at runtime options.

- name: 本番環境用ファイルをコピー
  copy: src=config.ini.prod dest=/etc/config.ini
  tags:
    - prod

- name: 検証環境用ファイルをコピー
  copy: src=config.ini.stg dest=/etc/config.ini
  tags:
    - stg

If you do,

% ansible-playbook -l stg -t prod something.yml

, You can copy the file for the production environment to the verification environment, which could not be done with inventory alone, for example. Well, occasionally it may make sense.

Toggle switch with include

In past examples, it was necessary to tag with task unit. However, it will be hard if there are many tasks that I want to switch.

Different tasks are cut out,

- include: prod.yml  tags=prod
- include: stg.yml  tags=stg

Ya

- include: prod.yml when: target == 'prod'
- include: stg.yml  when: target == 'stg'

You can also toggle by include at the same time, as in.

Switch by role

As you get a bit bigger it is better to isolate the role, so I think that some people are cutting to role.

Since you can also apply when to role,

roles:
  - { role: prod, when: target == 'prod' }
  - { role: stg, when: target == 'stg' }

It is also possible to do. However, since we need to create two roles called prod and stg, we will normally define variables. I will try to be able to switch by tag at the same time.

roles:
  - { role: something, port:80, tags: ['prod'] }
  - { role: something, port:8080, tags: ['stg'] }

Switch vars

If you cut out the variable in the first place, you just need to replace vars. But vars can not write when, etc.

In and say if you want to, include_vars モジュール use.

tasks:
  - include_vars: vars_prod.yml
    when: target == "prod"
  - include_vars: vars_stg.yml
    when: target == "stg"

  - debug: msg=" port is {{ port }}"

Note

I tried it with 1.6.2 and when I combined it with tags, it seems that the subsequent task will not be executed. I'll chase a bit later.

This and the vars_prompt The combination of

---
- hosts: all
  gather_facts: no
  vars_prompt:
    env: "What is your target env?"
  tasks:
    - include_vars: vars_prod.yml
      when: env == "prod"
    - include_vars: vars_stg.yml
      when: env == "stg"
    - debug: msg="port is {{ port }}"

When asked "What is your target env?" When asked when playbook is running, if you enter, the specified vars file will be loaded. Well, it does not make much sense, is it so ...

Summary

I think that it is common when you want to change the target. I introduced some methods that I can use at that time.

There are several ways, but there is nothing to be particularly particular about. Strongly speaking, it will be more convenient to use roles and variables later, but there is nothing to do with this. I think that you should take a method suitable for the environment you want to use.