web-dev-qa-db-ja.com

アンシブル。単一の辞書キーを上書きする

私はansibleを使用して、プロダクションとバガントボックスの構成を管理しています。デフォルト値のファイルがあります:group_vars/all

---
env: prod
wwwuser: www-data

db:
    root_pwd: root_pwd
    pdo_driver: pdo_mysql
    Host: localhost
    name: test
    user: test
    pwd: test
    charset: utf8

domain: somedomain
projectdir: /var/www/application
webrootdir: "{{ projectdir }}/web"

Host_vars/vagrantboxのようにしたい:

db:
    root_pwd: super_easy_password

しかし、これは完全にdb dictrionaryをオーバーライドしていますが、単一のキーをオーバーライドしたいのです。それを達成する方法は?

UPDATE 1ansible.cfgでチェックしたところ:

[defaults]
Host_key_checking=false
hash_behaviour=merge

groups_vars/all

db:
    root_pwd: some_strong_pwd
    pdo_driver: pdo_mysql
    Host: localhost
    name: dbname
    user: dbuser
    pwd: some password
    charset: utf8

Host_vars/vagrantbox

db:
    root_pwd: root

次のエラーが発生します。

One or more undefined variables: 'dict object' has no attribute 'name'

私は何を間違っていますか?

26
Jevgeni Smirnov

デフォルトでは、Ansibleは最初のレベルで変数をオーバーライドします。辞書をマージできるようにするには、ansible.cfgファイルを変更して次のように設定する必要があります。

hash_behaviour=merge

(デフォルト値はreplaceです)。

Ansibleチーム これはお勧めしません に注意してください(ただし、理由は説明しません)。これは、ユーザー間の実際の分割設定だと思います。一度に行われる一種の決定:この機能の使用を開始すると、戻ることはできず、おそらくreplaceタイプの人とプレイブックを共有することはできません。

しかし、あなたはまだそこにあるプレイブックから利益を得ることができます(私は、プレイブックがreplace動作を「機能」として使用しているとは思いません)。それは、AB血液型を持っている、ユニバーサルレシーバーのようなものですが、魔法は通常、タスクやテンプレートの内部ではなく、変数の解決で発生するため、変更なしで役割を共有できることが多いと思います。

たとえば、ロールパラメータから単一のキーをオーバーライドする必要がある場合は、複雑な方法でパラメータを渡す必要があります。

たとえば、特定の役割のpost_max_size辞書のupload_max_sizeキーとphp5キーをオーバーライドするには、次のようにする必要があります。

- { role: php5-fpm, php5: { post_max_size: 40M,
                            upload_max_filesize: 20M }}

そうは言っても、私は最初からmerge動作を使用しており、私はそれに非常に満足しています。変数を整理しておくと非常に便利です。

17
leucos

Ansible 2.0以降では、Jinja2 combineフィルターを使用して、hash_behavior=mergeをグローバルレベルでansible.cfgファイルに設定する必要なく、YAMLハッシュ/辞書をマージできます。

関連ドキュメント: http://docs.ansible.com/ansible/playbooks_filters.html#combining-hashes-dictionaries

14
Jeff Widman

私が見つけた最良の方法は、変数を辞書項目の値として使用し、それをオーバーライドすることです。これにより、Ansibleの変数の順序に関して、シンプルで強力な変数の優先順位が可能になります。

role/parent/defaults/main.yml

---
root_pw_value: ParentPassword

parent_dict:
  - root_pw: "{{ root_pw_value }}"

role/child/defaults/main.yml

注:role/child/meta/main.ymlにはdependencies: - { role: parent }が含まれています

---
root_pw_value: ChildPassword

play-me.yml

---
  - hosts: all
    roles:
      - child

roles/parent/tasks/main.yml&roles/child/tasks/main.yml

- debug: var=parent_dict

ansible -i localhost, --connection="local" play-me.ymlを実行すると、次の出力が得られます。

PLAY [all] ******************************************************************** 

GATHERING FACTS *************************************************************** 
ok: [localhost]

TASK: [parent | debug var=parent_dict] **************************************** 
ok: [localhost] => {
    "var": {
        "parent_dict": [
            {
                "root_pw": "ParentPassword"
            }
        ]
    }
}

TASK: [child | debug var=parent_dict] ***************************************** 
ok: [localhost] => {
    "var": {
        "parent_dict": [
            {
                "root_pw": "ChildPassword"
            }
        ]
    }
}

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

そして、これらはデフォルトです。インベントリグループ/ホスト変数、ロール変数、コマンドラインのextra_vars、または優先順位[0]からの優先順位など、より具体的な優先レベルでroot_pw_valueを指定すると、それらを取得できます。

[0] http://docs.ansible.com/ansible/playbooks_variables.html#variable-precedence-where-should-i-put-a-variable

5
MeanderingCode

Ansible 1.9.3で試したところ、問題なく動作しました。確かではありませんが、group_varsディレクトリの名前にタイプミスがあるようです(groups_varsではありません)。

0
Borys Borysenko