首页 文章

Ansible - with_dict:dictionary - 如何使用每个字典中定义的变量,这些变量依赖于其他字典

提问于
浏览
5

环境是:Ansible 1.9.2,CentOS 6.5

我创建了一个角色,可以从Artifactory下载3种不同JAVA版本的JAVA(.tar.gz)工件文件 . 我正在尝试使用Ansible的with_dict功能(而不是使用with_items) .

创建了以下文件:

$ cat roles/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_filedist_url 变量(比如在KEY java7_60中)?

现在,当我尝试当前的dist_file或dist_url变量 OR 注释掉的行设置它们的方式(即使用item.value . )时,它不是根据需要设置这两个变量的值,即取决于其他变量版本,group_path,classifier,ext和artifactory_url(在另一个公共角色的默认值/ main.yml文件中定义)) .

我看到在playbook / task中使用with_dict:我必须使用{}但是如何定义一个依赖于字典的同一个KEY部分中的其他变量的变量 .

我在以下任务中使用上述字典时得到的错误消息是:

$ cat roles/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 }}"

Error message 使用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"]}

Error message 使用dist_file / dist_url(使用roles / java / defaults / main.yml中的行 which are currently commented out ):

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

3 回答

  • 3

    我相信做你想做的最好的方法(因为我不相信循环变量可以自己引用)将是你的任务:

    - 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上循环多个任务,并且您将能够为该块中的所有任务定义变量以供使用 .

  • 1

    感谢Bruce P和Sepehr N.我在回答他们的解决方案/提示后做了以下事情 . 现在,我的任务是为多个工具(jdk,mvn,gradle,maven等)工作,这些工具具有多个版本,对文件进行的更改很少,而且不需要(第二个字典定义) .

    What I did:

    在顶级/一些常见角色的默认/ main.yml我将有以下内容:

    $ cat roles/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 }}"
    

    $ cat roles/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
    

    在单个工具的角色/ default / main.yml中,我将设置相同的字典和工具变量,它将下载多个工具/版本 . 在这种情况下,您的某些常见级别角色的默认/ 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 }}"
    

    如果我使用上面的方法,我可以在给定的角色// 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机器上ping您的Artifactory服务器(检查ping ....或/etc/resolv.conf文件中的搜索/名称服务器条目),如果一切看起来都不错,那么这里发布的解决方案将工作!

    我个人喜欢传递工具变量(在角色/任务)级别的解决方案(因此,否定使用定义工具:在字典级别)并且不需要定义单独的级别_dist_file / dist_url变量 .

  • 2

    我很好奇这个,所以我做了一些挖掘,在这样做的时候我遇到了this similar answer . 尽管如此,这只是解决方案的一部分 .

    似乎Ansible不会让你从它自己的定义中引用一个变量,我认为它是有意义的,因为它没有完全定义 . 所以这样的东西不起作用,实际上在引用变量时会引起一些有点混乱的错误:

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

    从您自己的示例中看,Ansible也不允许您在变量中使用 item 构造来引用其他复杂变量 . 这种方式对我来说很有意义,因为似乎Ansible在定义变量时解析变量中的jinja2构造,而不是在引用变量时在运行时 .

    因此,尽管这并不是您想要的,但我认为如果您将变量拆分为两部分,您可以通过以下方式执行此操作来实现此目的:

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

相关问题