Encontrei esse problema em uma configuração em que precisei criar vários ambientes de implementação (ao vivo, demo, sandbox) para o mesmo servidor físico (não permitidas máquinas virtuais aqui) e um script para implantar repositórios svn arbitrários
Isso exigia uma árvore de diretórios de arquivos (opcionais) variable.yml, que se fundiriam ontop uns dos outros e não lançariam uma exceção se algum deles faltasse
Comece ativando a mesclagem de variáveis em ansible
- note que isso faz mesclagem superficial de hash (1 nível de profundidade) e não mesclagem profunda totalmente recursiva
ansible.cfg
[defaults]
hash_behaviour=merge ;; merge rather than replace dictionaries http://docs.ansible.com/ansible/intro_configuration.html###hash-behaviour
Layout de diretório anível
/group_vars
└── all.yml
/playbooks
├── boostrap.yml
├── demo.yml
├── live.yml
└── sandbox.yml
/roles/deploy/
├── files
├── tasks
│ ├── includes.yml
│ ├── main.yml
└── vars
├── main.yml
├── project_1.yml
├── project_2.yml
├── demo
│ ├── project_1.yml
│ ├── project_2.yml
│ └── main.yml
├── live
│ ├── project_1.yml
│ ├── project_2.yml
│ └── main.yml
└── sandbox
├── project_1.yml
├── project_2.yml
└── main.yml
roles / deploy / tasks / includes.yml
Esta é a principal lógica para uma árvore de diretórios de arquivos variáveis opcionais.
;; imports in this order:
;; - /roles/deploy/vars/main.yml
;; - /roles/deploy/vars/{{ project_name }}.yml
;; - /roles/deploy/vars/{{ project_name }}/main.yml
;; - /roles/deploy/vars/{{ project_name }}/{{ project_env }}.yml
- include_vars:
dir: 'vars'
files_matching: "{{ item }}"
depth: 1
with_items:
- "main.yml"
- "{{ project_name }}.yml"
- include_vars:
dir: 'vars/{{ env_name }}'
files_matching: "{{ item }}"
depth: 1
with_items:
- "main.yml"
- "{{ project_name }}.yml"
group_vars / all.yml
Configure variáveis padrão para o projeto e vários usuários e ambientes
project_users:
bootstrap:
env: bootstrap
user: ansible
group: ansible
mode: 755
root: /cs/ansible/
home: /cs/ansible/home/ansible/
directories:
- /cs/ansible/
- /cs/ansible/home/
live:
env: live
user: ansible-live
group: ansible
mode: 755
root: /cs/ansible/live/
home: /cs/ansible/home/ansible-live/
demo:
env: demo
user: ansible-demo
group: ansible
mode: 755
root: /cs/ansible/demo/
home: /cs/ansible/home/ansible-demo/
sandbox:
env: sandbox
user: ansible-sandbox
group: ansible
mode: 755
root: /cs/ansible/sandbox/
home: /cs/ansible/home/ansible-sandbox/
project_env: bootstrap
project_user: "{{ ansible_users[project_env] }}" ;; this will be retroactively updated if project_env is redefined later
roles / deploy / vars / main.yml
padrões de projeto
ansible_project:
node_env: development
node_port: 4200
nginx_port: 4400
roles / deploy / vars / project_1.yml
padrões para project_1
ansible_project:
node_port: 4201
nginx_port: 4401
roles / deploy / vars / live / main.yml
padrões para o ambiente ao vivo, sobrescreve os padrões do projeto
ansible_project:
node_env: production
roles / deploy / vars / live / project_1.yml
substituições finais para project_1 no ambiente ao vivo
ansible_project:
nginx_port: 80
playbooks / demo.yml
Configurar livros de exercícios separados para cada ambiente
- hosts: shared_server
remote_user: ansible-demo
vars:
project_env: demo
pre_tasks:
- debug: "msg='{{ facter_gid }}@{{ facter_fqdn }} ({{ server_pseudonym }})'"
- debug: var=project_ssh_user
roles:
- { role: deploy, project_name: project_1 }
AVISO: Como todos os ambientes residem em um único host, todos os playbooks devem ser executados individualmente, caso contrário, o Ansible tentará executar todos os scripts como o primeiro usuário ssh e usar as variáveis apenas para o primeiro usuário. Se você precisar executar todos os scripts sequencialmente, use xargs para executá-los como comandos separados.
find ./playbooks/*.yml | xargs -L1 time ansible-playbook