web-dev-qa-db-fra.com

Manière correcte de créer des listes dynamiques dans Ansible

Je cherche des conseils. Le code suivant crée une liste dynamique que je pourrai ensuite utiliser dans un modèle.

Ceci est une copie du code de test que j'ai constitué - pour le rôle réel, je viens d'ajouter la variable admins | regex_replace dans le modèle j2.

    ---

  - hosts: localhost
    gather_facts: false

    vars:
      # define empty admins var first so ansible doesn't complain
      admins:

      admin_accounts:
      - name: john
        uid: 1000
        group: sysadmin
        Shell: /bin/bash
        comment: "Unix Administrator"
      - name: paul
        uid: 1001
        group: sysadmin
        Shell: /bin/bash
        comment: "Unix Administrator"
      - name: george
        uid: 1002
        group: sysadmin
        Shell: /bin/bash
        comment: "Unix Administrator"
      - name: ringo
        uid: 1003
        group: sysadmin
        Shell: /bin/bash
        comment: "Unix Administrator"

    tasks:

      - name: build array of admin user names
        set_fact: admins="{{ admins}} {{ item.name }}"
        with_items: "{{ admin_accounts }}"

      # print out the fact piping through two jinja2 filters
      # careful with Word wrapping
      - debug: msg={{ admins | regex_replace( '\s+',', ' ) | regex_replace`(',\s(.*)','\\1') }}`

Cela me donne ce qui suit:

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

TASK [build array of admin user names] *****************************************
ok: [localhost] => (item={u'comment': u'Unix Administrator', u'Shell': u'/bin/bash', u'group': u'sysadmin', u'name': u'john', u'uid': 1000})
ok: [localhost] => (item={u'comment': u'Unix Administrator', u'Shell': u'/bin/bash', u'group': u'sysadmin', u'name': u'paul', u'uid': 1001})
ok: [localhost] => (item={u'comment': u'Unix Administrator', u'Shell': u'/bin/bash', u'group': u'sysadmin', u'name': u'george', u'uid': 1002})
ok: [localhost] => (item={u'comment': u'Unix Administrator', u'Shell': u'/bin/bash', u'group': u'sysadmin', u'name': u'ringo', u'uid': 1003})

TASK [debug] *******************************************************************
ok: [localhost] => {
    "msg": "john, paul, george, ringo"
}

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

Alors… j'ai ce dont j'ai besoin, mais est-ce que j'y vais de la bonne façon?

La version d'Ansible est la version 2.0.2.0 fonctionnant sous Centos 7.2.

Merci d'avance.


Edit: Le filtre résultant a fini par ressembler à ceci:

  - name: build list of admin user names
    set_fact:
      admin_list: "{{ admin_accounts | selectattr('state', 'equalto', 'present') | map(attribute='name') | join(', ') }}"
  - debug: msg={{ admin_list }}

Après avoir ajouté un autre paramètre au yaml:

state: absent

Ringo a été laissé de côté, comme souhaité.

6
Rowley

Les filtres opéreront sur des listes, donc avec with_items est vraiment une perte de temps, et les regex sont assez obtus pour ce que vous faites. Voulez-vous vraiment une chaîne séparée par des virgules ou voulez-vous simplement une liste des noms d'utilisateur extraits de la liste admin_accounts?

Si vous voulez juste la liste, pourquoi pas:

set_fact:
  admin_usernames: "{{ admin_accounts | map(attribute='name') | list }}"

... et si vous voulez vraiment que la liste séparée par des virgules soit une chaîne plate, ajoutez simplement un filtre de jointure:

set_fact:
  admin_usernames: "{{ admin_accounts | map(attribute='name') | join(', ') }}"

Si votre cible ultime est un modèle, cependant, je suggérerais de le faire dans le modèle, car cela semble plutôt lié au formatage par rapport à la logique (sauf si vous ne faites que simplifier à des fins de débordement de pile) ...

7
nitzmahone

Quand il est nécessaire d’ajouter un préfixe et un suffixe (et en faisant tout une liste), regardez:

  set_fact:
    extended_etcd_endpoints_list: "{{ groups['etcd'] | map('extract', hostvars, ['ansible_default_ipv4','address']) | map('regex_replace', '^(.*)$','https://\\1:2379') | list  }}"

What is does: prend la liste de toutes les machines du groupe etcd, extrait l'adresse ipv4, ajoute un préfixe 'https: //' et un suffixe ': 2379'. À la fin, tout est transformé en liste.

1
ReSearchIT Eng