web-dev-qa-db-ja.com

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バージョンは、Centos 7.2で実行されている2.0.2.0です。

前もって感謝します。


編集:結果のフィルターは次のようになります。

  - 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

望み通りにリンゴは省かれました。

11
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(', ') }}"

ただし、最終的なターゲットがテンプレートの場合は、これをテンプレート内で実行することをお勧めします。これは、ロジック関連ではなく書式設定関連に見えるためです(スタックオーバーフローの目的で単純化している場合を除きます)。

14
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」のサフィックスを追加します。最後に、すべてがリストに変換されます。

2
ReSearchIT Eng