it-swarm.com.ru

Правильный способ создания динамических списков в Ansible

Я ищу совет. У меня есть следующий код, который динамически создает список, который я затем могу использовать в шаблоне. 

Это копия тестового кода, который я собрал - для фактической роли я только что добавил переменную admins | regex_replace в шаблон 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') }}`

Это дает мне следующее:

    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

Итак ... Я получаю то, что мне нужно, но правильно ли я поступаю?

Ansible версия 2.0.2.0 работает на Centos 7.2.

Заранее спасибо.


Правка: результирующий фильтр в конечном итоге выглядит так:

  - 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 }}

Добавив еще один параметр в yaml:

state: absent

Ринго был опущен, как хотелось бы.

6
Rowley

Фильтры будут работать со списками, поэтому with_items действительно бесполезен, а регулярные выражения довольно тупые для того, что вы делаете. Вы действительно хотите использовать строку, разделенную запятыми, или вам просто нужен список имен пользователей, извлеченных из списка admin_accounts?

Если вы просто хотите список, почему бы и нет:

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

... и если вы действительно хотите, чтобы список через запятую представлял собой плоскую строку, просто добавьте фильтр объединения:

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

Однако если вашей конечной целью является шаблон, я бы предложил сделать это внутри шаблона, поскольку это выглядит довольно связанным с форматированием, а не с логикой (если только вы не упрощаете для целей переполнения стека) ...

7
nitzmahone

Когда необходимо добавить префикс и суффикс (и сделать все списком), посмотрите на:

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

Что делает: берет список всех машин в группе etcd, извлекает адрес ipv4, добавляет префикс 'https: //' и суффикс ': 2379' . В конце все преобразуется в список.

1
ReSearchIT Eng