質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.59%

Ansible with_listで渡した配列をモジュールの中でループに使用するには

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 687

score 8

前提・実現したいこと

Ansibleの自作モジュールをpythonで作成しています。

業務都合によりyumの使用が封印されている状況で、rpmを利用するモジュールを作成しています。
そこで以下のように配列で渡したパラメータを利用してモジュール内でforループを行いたいと考えています。

- name: rpm install (replacefiles)
  rpm:  # 自作モジュールの名前
    pkgs: "{{ item }}"
  with_list:
    - [ 'file_a','file_b' ] # ココにいくつ渡されるかは決まっていない

例えばdebugモジュールのmsgを使うと以下のようにリストで渡されてい(るように見え)ます。

$ ansible-playbook -i test_grp -l test_srv -u root test.yml
ok: [192.168.56.104] => (item=[u'aaa', u'bbb', u'ccc']) => {
    "msg": [
        "aaa",
        "bbb",
        "ccc"
    ]
}

そこで自作モジュールにてpkgsをループ条件にしてfile_afile_bそれぞれに同じ処理を行いたいです。
試しに受け取ったリストをexit_jsonに渡すだけにしてみたのですがpkgsがリストではなく文字列として認識されているように見えます。

#!/usr/bin/python
# -*- coding: utf-8 -*-

from ansible.module_utils.basic import AnsibleModule

# メイン処理
#-----------------------------------------------------------
def main():
    # AnsibleModuleクラス: moduleを作成
    module = AnsibleModule({})
        # 引数受け取り
        argument_spec=dict(
            pkgs=dict(),
        ),
    )
    # 処理終了
    module.exit_json(pkgs = module.params['pkgs'])

if __name__ == '__main__':
    main()
$ ansible-playbook -i test_grp -l test_srv -u root test.yml -vvv
TASK [test : rpm install ] ***************************************************************
:#(省略)
ok: [192.168.56.104] => (item=[u'file_a', u'file_b']) => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "ansible_loop_var": "item",
    "changed": false,
    "invocation": {
        "module_args": {
            "pkgs": "['file_a', 'file_b']"  #ダブルクォートで囲まれている = 1つの文字列?
        }
    },
    "item": [
        "file_a",   #こっちはリストっぽい
        "file_b"
    ],
    "pkgs": "['file_a', 'file_b']",  # 結果を見るとやっぱり1つの文字列?
    "warnings": [
        "The value ['file_a', 'file_b'] (type list) in a string field was converted to u\"['file_a', 'file_b']\" (type string). If this does not look like what you expect, quote the entire value to ensure it does not change."
    ]
}

このまま例えば以下のようにループに使おうとしても"num" : 20が返り、これは['file_a', 'file_b']の文字数に一致します。

    num = 0
    for pkg in module.params['pkgs']:
        num += 1
    module.exit_json(num = num)

どうしたらAnsibleの自作モジュールで配列を受け取り、forループ処理を行うことができるでしょうか。
よろしくお願いいたします。

発生している問題・エラーメッセージ

原因のヒントはwarningsのメッセージだとは目星をつけています。

"warnings": [
        "The value ['file_a', 'file_b'] (type list) in a string field was converted to u\"['file_a', 'file_b']\" (type string). If this does not look like what you expect, quote the entire value to ensure it does not change."
    ]

例えば結果は変わりませんが、以下のように{{ item | string }}にするとこの警告はでなくなります。
しかし私はコレがどういった意味を示すのか理解できていません。

- name: rpm install (replacefiles)
  rpm:
    pkgs: "{{ item | string}}" # ココ
  with_list:
    - [ 'file_a','file_b' ]

補足情報(FW/ツールのバージョンなど)

$ ansible --version
ansible 2.9.7
  config file = /etc/ansible/ansible.cfg
  configured module search path = [u'/home/ansi/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python2.7/site-packages/ansible
  executable location = /usr/bin/ansible
  python version = 2.7.5 (default, Aug  7 2019, 00:51:29) [GCC 4.8.5 20150623 (Red Hat 4.8.5-39)]

$ cat /etc/redhat-release
CentOS Linux release 7.7.1908 (Core)
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

check解決した方法

0

自己解決しました。
引数受取時にtype = listを指定するだけでよかったです。

    # AnsibleModuleクラス: moduleを作成
    module = AnsibleModule(
        argument_spec=dict(
            message=dict(type=list)
        )
    )
    msg = module.params['message']
    num = 0
    for pkg in msg:
        num += 1
    # 処理終了
    module.exit_json(msg = num)
- name: rpm install
  rpm:
    message: "{{ item }}"
  with_list:
    - [ 'file_a','file_b' ]
$ ansible-playbook -i test_grp -l test_srv -u root test.yml -vvv
:#(省略)
ok: [192.168.56.104] => (item=[u'file_a', u'file_b']) => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "ansible_loop_var": "item",
    "changed": false,
    "invocation": {
        "module_args": {
            "message": [
                "file_a",
                "file_b"
            ]
        }
    },
    "item": [
        "file_a",
        "file_b"
    ],
    "msg": 2
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.59%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る