Ansible :: looping aninhado avançado

1

Eu tenho que processar a saída do CloudFormation Outputs , ou seja:

Código anível que produz esta saída:

- debug: 
  var: stack.stack_outputs

Saída:

ok: [localhost] => {
  "stack.stack_outputs": {
    "Roles": "webserver balancer dbserver",
    "dbserver": "54.0.1.1 54.0.1.2",
    "balancer": "54.0.2.3",
    "webserver": "54.0.2.5 54.0.2.7 54.0.3.1"
}}

Com isso, quero criar três grupos (número dinâmico!) nomeados de acordo com os IPs apropriados.

Código Ansível com o qual desejo ajudar:

- name: fill roles with proper hosts
  local_action: add_host hostname={{item}} groupname={{role}}
  with_whatever: ?...?

No python pseudo-ansible, ficaria assim:

for role in stack.stack_outputs.Roles.split():                           # Python
  for ip in stack.stack_outputs[role].split():                           # Python
    local_action: add_host hostname={{ip}} groupname={{role}}            # Ansible

Nota:

A maneira de fazer isso para esses três papéis estaticamente é obviamente:

- name: fill role WEBSERVER
  local_action: add_host hostname={{item}} groupname=webserver
  with_items: stack.stack_outputs.webserver.split()
- name: fill role DBSERVER
  local_action: add_host hostname={{item}} groupname=dbserver
  with_items: stack.stack_outputs.dbserver.split()
- name: fill role BALANCER
  local_action: add_host hostname={{item}} groupname=balancer
  with_items: stack.stack_outputs.balancer.split()

Eu quero fazer dinamicamente , isso é possível no Ansible?
Sim, eu posso usar shell module para cortá-lo colocando tudo em um arquivo temporário e, em seguida, passando por cima disso; mas existe uma solução melhor?

Obrigado por qualquer sugestão.

    
por DinGODzilla 07.02.2015 / 23:40

2 respostas

1

Lógica complicada não deveria existir em um playbook ou lista de tarefas. Considere o uso de inventários dinâmicos , para que você possa escrever um script que retorne o JSON completo com informações de associação ao grupo. Se você realmente deseja manipular os dados em um playbook, pode usar um filtro personalizado , que ainda limpa significativamente a cartilha.

    
por 13.08.2015 / 22:48
1

Isso pode ser feito usando loops aninhados e inclui, exemplo de script de trabalho test.yml :

---
- hosts: localhost
  vars:
  - stack:
      stack_outputs:
        Roles: "webserver balancer dbserver"
        dbserver: "54.0.1.1 54.0.1.2"
        balancer: "54.0.2.3"
        webserver: "54.0.2.5 54.0.2.7 54.0.3.1"

  tasks:
  - debug: var=stack.stack_outputs

  - include: dynamic.yml
      host_group={{ item.key }}
      group_ips={{ item.value }}
    with_dict: "{{ stack.stack_outputs }}"

dynamic.yml :

---
- debug:
    msg="Group is {{ host_group }} and ip is {{ item2 }}"
  when: item2|ipaddr
  with_items: "{{ group_ips.split() }}"
  loop_control:
    loop_var: item2

Exemplo de execução usando ansible-playbook 2.1.2.0 :

ansible-playbook test.yml 
 [WARNING]: provided hosts list is empty, only localhost is available


PLAY [localhost] ***************************************************************

TASK [setup] *******************************************************************
ok: [localhost]

TASK [debug] *******************************************************************
ok: [localhost] => {
    "stack.stack_outputs": {
        "Roles": "webserver balancer dbserver", 
        "balancer": "54.0.2.3", 
        "dbserver": "54.0.1.1 54.0.1.2", 
        "webserver": "54.0.2.5 54.0.2.7 54.0.3.1"
    }
}

TASK [include] *****************************************************************
included: /home/say/tmp/ansible/dynamic.yml for localhost
included: /home/say/tmp/ansible/dynamic.yml for localhost
included: /home/say/tmp/ansible/dynamic.yml for localhost
included: /home/say/tmp/ansible/dynamic.yml for localhost

TASK [debug] *******************************************************************
ok: [localhost] => (item=None) => {
    "item_foo": "54.0.2.5", 
    "msg": "Group is webserver and ip is 54.0.2.5"
}
ok: [localhost] => (item=None) => {
    "item_foo": "54.0.2.7", 
    "msg": "Group is webserver and ip is 54.0.2.7"
}
ok: [localhost] => (item=None) => {
    "item_foo": "54.0.3.1", 
    "msg": "Group is webserver and ip is 54.0.3.1"
}

TASK [debug] *******************************************************************
ok: [localhost] => (item=None) => {
    "item_foo": "54.0.2.3", 
    "msg": "Group is balancer and ip is 54.0.2.3"
}

TASK [debug] *******************************************************************
skipping: [localhost] => (item=None) 
skipping: [localhost] => (item=None) 
skipping: [localhost] => (item=None) 

TASK [debug] *******************************************************************
ok: [localhost] => (item=None) => {
    "item_foo": "54.0.1.1", 
    "msg": "Group is dbserver and ip is 54.0.1.1"
}
ok: [localhost] => (item=None) => {
    "item_foo": "54.0.1.2", 
    "msg": "Group is dbserver and ip is 54.0.1.2"
}

PLAY RECAP *********************************************************************
localhost                  : ok=9    changed=0    unreachable=0    failed=0 

Você precisa Ansible 2.1 ou acima para executá-lo.

    
por 10.01.2017 / 19:23

Tags