web-dev-qa-db-ja.com

Ansible-with_dict:辞書-他の辞書に依存する各辞書で定義された変数の使用方法

環境は次のとおりです:Ansible 1.9.2、CentOS 6.5

Artifactoryから3つの異なるJavaバージョンのJava(。tar.gz)アーティファクトファイルをダウンロードするロールを作成しました。Ansibleのwith_dictを使用しようとしています。機能(with_itemsを使用する代わりに)。

次のファイルを作成しました。

$ catroles/Java/defaults/main.yml

---
Java_versions:
  Java7_60:
    version: 1.7.60
    group_path: com/Oracle/jdk
    classifier: linux-x64
    ext: tar.gz
    dist_file: "jdk-{{ version }}-{{ classifier }}-{{ ext }}"
#    dist_file: "jdk-{{item.value.version }}-{{ item.value.classifier }}-{{ item.value.ext }}"
    dist_url: "{{ artifactory_url }}/{{ group_path }}/{{ version }}/{{ dist_file }}"
#    dist_url: "{{ artifactory_url }}/{{ item.value.group_path }}/{{ item.value.version }}/{{ dist_file }}"

  Java7_67:
    version: 1.7.67
    group_path: com/Oracle/jdk
    classifier: linux-x64
    ext: tar.gz
    dist_file: "jdk-{{item.value.version }}-{{ item.value.classifier }}-{{ item.value.ext }}"
    dist_url: "{{ artifactory_url }}/{{ item.value.group_path }}/{{ item.value.version }}/{{ dist_file }}"
  Java8_45:
    version: 1.8.45
    group_path: com/Oracle/jdk
    classifier: linux-x64
    ext: tar.gz
    dist_file: "jdk-{{item.value.version }}-{{ item.value.classifier }}-{{ item.value.ext }}"
    dist_url: "{{ artifactory_url }}/{{ item.value.group_path }}/{{ item.value.version }}/{{ dist_file }}"

同じKEYで定義された他の変数に依存するdist_fileまたはdist_url変数を設定または使用するにはどうすればよいですか(KEYJava7_60)?

現在、現在のdist_file変数またはdist_url変数のいずれかを試しているとき[〜#〜]または[〜#〜]コメントアウトされた行の設定方法(つまり、item.valueを使用)、これら2つの変数の値を希望どおりに設定していません。つまり、他の変数version、group_path、classifier、ext、およびに依存しています。 )artifactory_url(これは別の一般的なロールのdefaults/main.ymlファイルで定義されています))。

With_dict:を使用するには、プレイブック/タスク内で{{item.value。variable_name}}を使用する必要があることがわかりましたが、どのように定義できますか辞書の同じKEYセクション内の他の変数に依存する変数。

次のタスクで上記の辞書を使用しているときに表示されるエラーメッセージは次のとおりです。

$ catロール/Java/tasks/main.yml

- name: Download Java/JDK Versions
  command: wget -q "{{ item.value.dist_url }}"
    chdir="{{ common_download_dir }}"
    creates="{{ common_download_dir }}/{{ item.value.dist_file }}"
  with_dict: "{{ Java_versions }}"
  become_user: "{{ build_user }}"

エラーメッセージ dist_file/dist_urlを使用した場合(現在の設定はroles/Java/defaults/main.ymlにあります):

TASK: [Java | Download Java/JDK Versions] *************************************
failed: [server01.poc.jenkins] => (item={'key': 'Java7_60', 'value': {'dist_file': u'jdk-{# version #}-{# classifier #}-{# ext #}', 'ext': 'tar.gz', 'version': '1.7.60', 'dist_url': u'{# artifactory_ur #}/{# group_path #}/{# version #}/{# dist_file #}', 'group_path': 'com/Oracle/jdk', 'classifier': 'linux-x64'}}) => {"changed": true, "cmd": ["wget", "-q", "{# artifactory_url #}/{# group_path #}/{# version }/{# dist_file #}"], "delta": "0:00:00.006081", "end": "2015-11-23 12:50:18.383728", "item": {"key": "Java7_60", "value": {"classifier": "linux-x64", "dist_file": "jdk-{# version #}-{# classifier #}-{# ext #}, "dist_url": "{# artifactory_url #}/{# group_path #}/{# version #}/{# dist_file #}", "ext": "tar.gz", "group_path": "com/Oracle/jdk", "version": "1.7.60"}}, "rc": 4, "start": "2015-11-23 12:50:18.377647", "wrnings": ["Consider using get_url module rather than running wget"]}

エラーメッセージ dist_file/dist_urlを使用した場合(現在コメントアウトされている roles/Java/defaults/main.yml内の行):

TASK: [Java | Download Java/JDK Versions] *************************************
failed: [server01.poc.jenkins] => (item={'key': 'Java7_60', 'value': {'dist_file': u'jdk-{#item.value.version #}-{# item.value.classifier #}-{# item.value.ext #}', 'ext': 'tar.gz', 'version': '1.7.60' , 'dist_url': u'{# artifactory_url #}/{# item.value.group_path #}/{# item.value.version #}/{# dist_file #}', 'group_path': 'com/Oracle/jdk', 'classifier': 'linux-x64'}}) => {"changed": true, "cmd": ["wget",  "-q", "{# artifactory_url #}/{# item.value.group_path #}/{# item.value.version #}/{# dist_file #}"], "delta": "0:00:00.005900", "end": "2015-11-23 12:36:24.131327", "item": {"key": "Java7_60", "value": {"cla ssifier": "linux-x64", "dist_file": "jdk-{#item.value.version #}-{# item.value.classifier #}-{# item.value.ext #}", "dist_url": "{# artifactory_url #}/{# item.value.group_path #}/{# item.value.version #}/{#  dist_file #}", "ext": "tar.gz", "group_path": "com/Oracle/jdk", "version": "1.7.60"}}, "rc": 4, "start": "2015-11-23 12:36:24.125427", "warnings": ["Consider using get_url module rather than running wget"]}
6
Arun Sangal

(ループ変数がそれ自体を参照できるとは思わないので)あなたが望むことを行う最良の方法は、あなたのタスクを次のようにすることだと思います。

- name: Download Java/JDK Versions
  command: wget -q "{{ artifactory_url }}/{{ item.value.group_path }}/{{ item.value.version }}/jdk-{{item.value.version }}-{{ item.value.classifier }}-{{ item.value.ext }}"
    chdir="{{ common_download_dir }}"
    creates="{{ common_download_dir }}/jdk-{{item.value.version }}-{{ item.value.classifier }}-{{ item.value.ext }}"
  with_dict: "{{ Java_versions }}"
  become_user: "{{ build_user }}"

基本的に手動で変数をタスクに挿入します。

複数のタスクに変数を使用する必要がある場合はきれいではありませんが、ansible 1.xでは、きれいにする方法はないと思います。 Ansible 2.0にはブロックがあり、これを使用してdictで複数のタスクを一緒にループでき、そのブロック内のすべてのタスクが使用する変数を定義できます。

2
Sepehr Nazari

私はこれに興味があったので少し掘り下げました、そしてそうすることで私は出くわしました この同様の答え 。しかし、それはあなたの場合の解決策の一部にすぎません。

Ansibleでは、変数を独自の定義から参照できないようです。完全に定義されていないため、これは理にかなっていると思います。したがって、このようなものは機能せず、実際、変数が参照されると、やや紛らわしいエラーがスローされます。

---
myvar:
    param1: foo
    param2: "{{ myvar['foo'] }} bar"

また、あなた自身の例から、Ansibleでは変数内のitem構造を使用して他の複雑な変数を参照することはできないようです。 Ansibleは、変数が参照される実行時ではなく、変数が定義されるときに変数内のjinja2構造を解決するように見えるので、この種の意味があります。

したがって、これはまさにあなたが探していたものではありませんが、変数を2つの部分に分割すると、次のように実行することでこれを機能させることができると思います。

---
artifactory_url: "http://path.to.jarfile"
Java_versions:
  Java7_60:
    version: 1.7.60
    group_path: com/Oracle/jdk
    classifier: linux-x64
    ext: tar.gz

Java_downloads:
  Java7_60:
    dist_url: "{{ artifactory_url }}/{{ Java_versions['Java7_60']['group_path'] }}/{{ Java_versions['Java7_60']['version'] }}/jdk-{{ Java_versions['Java7_60']['version'] }}-{{ Java_versions['Java7_60']['classifier'] }}.{{ Java_versions['Java7_60']['ext'] }}"

デバッグするときJava_downloadsこのようにして、探している完全なURLを取得します。

TASK: [debug var=item] ********************************************************
ok: [localhost] => (item={'key': 'Java7_60', 'value': {'dist_url': u'http://path.to.jarfile/com/Oracle/jdk/1.7.60/jdk-1.7.60-linux-x64.tar.gz'}}) => {
    "item": {
        "key": "Java7_60",
        "value": {
            "dist_url": "http://path.to.jarfile/com/Oracle/jdk/1.7.60/jdk-1.7.60-linux-x64.tar.gz"
        }
    },
    "var": {
        "item": {
            "key": "Java7_60",
            "value": {
                "dist_url": "http://path.to.jarfile/com/Oracle/jdk/1.7.60/jdk-1.7.60-linux-x64.tar.gz"
            }
        }
    }
} 
4
Bruce P

BrucePとSepehrNに感謝します。彼らの回答から解決策/ヒントを得た後、私は次のことを行いました。現在、私のタスクは複数のツール(jdk、mvn、gradle、mavenなど)で機能しており、ファイルへの変更は最小限で、(2番目の辞書定義)を必要とせずに複数のバージョンがあります。

私がしたこと:

トップレベル/いくつかの一般的なロールのdefault/main.ymlには、次のものがあります。

$ catroles/some_common_global_role/defaults/main.yml

---
a_var: giga
other_var: fifa

dist_file: "{{ item.value.tool }}-{{item.value.version }}-{{ item.value.classifier }}.{{ item.value.ext }}"
dist_url: "{{ artifactory_url }}/{{ item.value.group_path }}/{{ item.value.version }}/{{ dist_file }}"

$ catroles/Java/defaults/main.yml

---
tool: jdk

Java_versions:
  Java7_60:
    version: 1.7.60
    group_path: com/Oracle/jdk
    classifier: linux-x64
    ext: tar.gz
  Java7_67:
    version: 1.7.67
    group_path: com/Oracle/jdk
    classifier: linux-x64
    ext: tar.gz
  Java8_45:
    version: 1.8.45
    group_path: com/Oracle/jdk
    classifier: linux-x64
    ext: tar.gz

個々のツールのroles/default/main.ymlで、同じ辞書とツール変数を設定し、複数のツール/バージョンをダウンロードします。この場合、いくつかの一般的なレベルのロールのdefault /main.ymlは次のようになります。

---
dist_file: "{{ tool }}-{{item.value.version }}-{{ item.value.classifier }}.{{ item.value.ext }}"
dist_url: "{{ artifactory_url }}/{{ item.value.group_path }}/{{ item.value.version }}/{{ dist_file }}"

上記のアプローチを使用すると、特定のroles // defaults/main.ymlタスクレベルで「tool」変数を定義でき、dist_file/dist_urlで使用できるようになります。

また、コマンドwget -q "..."を使用する代わりに、Ansibleでget_url(モジュール)を使用できます。

- name: Download Java/JDK Versions
#  command: wget -q "{{ dist_url }}"
#    chdir="{{ common_download_dir }}"
#    creates="{{ common_download_dir }}/{{ dist_file }}"
  get_url: url="{{ dist_url }}" dest="{{ common_download_dir }}"
  become_user: "{{ build_user }}"
  with_dict: "{{ Java_versions }}"

rEMOTEマシンからArtifactoryサーバーにpingできることを確認し(ping ....または/etc/resolv.confファイルで検索/ネームサーバーエントリを確認してください)、すべて問題がなければ、ここに掲載されているソリューションが機能します。

私は個人的にtool変数(ロール/タスク)レベル(したがって、定義ツールの使用を否定する:辞書レベル)を渡すためのソリューションが好きでした個々のレベルの_dist_file/dist_url変数を定義する必要があります。

2
Arun Sangal