【问题标题】:ansible with dictionary based defaults variablesansible 与基于字典的默认变量
【发布时间】:2018-12-11 11:30:03
【问题描述】:

我的 Ansible 角色中有一些默认变量

sysproperties:
 java_awt_headless:
   key: "java.awt.headless"
   value: "true"
   enabled: "true"
 java_iccprofile_path:
   key: "java.iccprofile.path"
   value: "image/iccprofiles"
   enabled: "true"
...
...

它们最终应该是一个基于 jinja2 模板的 XML 文件

{% for key, value in sysproperties.items() %}
<sysproperty key="{{ value.key }}" value="{{ value.value }}" enabled="{{ value.enabled }}"/>
{% endfor %}

要更改其中一个默认值,我实际上希望它可以像这样简单:

---
- name: run this
  hosts: myTestHost
  vars:
     sysproperties.java_iccprofile_path.value: "somewhere/else"
  roles:
    - role: myRole

但到目前为止,我只是发现我需要一个额外的任务,只是为了改变这个设置

  pre_tasks:
    - set_fact:
        sysproperties: "{{ sysproperties | combine(new_item, recursive=true) }}"
      vars:
        new_item: "{ 'java_iccprofile_path': { 'value': 'somewhere/else' } }"
      with_dict: "{{ sysproperties }}"

所以我的问题是:有没有更简单的方法呢?我是否应该安排我的默认值有点不同,以便更容易更改?

[编辑] 为了更清楚我的实际问题是什么:

我将设置存储在列表/字典中,以通过模板模块将它们写入 XML 文件。 我喜欢任何使用我的角色能够轻松更改或添加设置的人。这样做的最佳实践方法是什么?我现在运行 pre_task 的方式是正确的还是有更好的方法来做到这一点?

【问题讨论】:

    标签: ansible jinja2 ansible-template


    【解决方案1】:

    您可以做的一件事是在调用角色时覆盖该变量。你可以在你的剧本中这样做:

    ---
    - hosts: localhost
      roles:
        - {role: "myRole", sysproperties.java_iccprofile_path.value: "somwhere/else"}
    ...
    

    希望这会有所帮助。

    更新 唔。有趣的。这是我的测试设置:

    myRole
    + tasks
    | + main.yml
    + vars
    | + main.yml
    + testrole.yml
    

    这里是myRole/tasks/main.yml的内容

    ---
    - name: Debugging
      debug: var=foo
    ...
    

    这里是myRole/vars/main.yml的内容

    ---
    foo: "blah"
    ...
    

    这里是testrole.yml的内容

    ---
    - hosts: localhost
      roles:
        - myRole
    ...
    

    如果我跑步

    ansible-playbook ./testrole.yml
    

    我明白了

    PLAY [localhost] ***************************************************************
    
    TASK [Gathering Facts] *********************************************************
    ok: [localhost]
    
    TASK [defaults : Debugging] ****************************************************
    ok: [localhost] => {
        "foo": "blah"
    }
    
    PLAY RECAP *********************************************************************
    localhost                  : ok=2    changed=0    unreachable=0    failed=0   
    

    如果我将 testrole.yml 更新为以下内容:

    ---
    - hosts: localhost
      roles:
        - {role: "myRole", foo: "yuck"}
    ...
    

    我明白了

    PLAY [localhost] ***************************************************************
    
    TASK [Gathering Facts] *********************************************************
    ok: [localhost]
    
    TASK [defaults : Debugging] ****************************************************
    ok: [localhost] => {
        "foo": "yuck"
    }
    
    PLAY RECAP *********************************************************************
    localhost                  : ok=2    changed=0    unreachable=0    failed=0   
    

    所以,我尝试使用字典。

    myRole/vars/main.yml:

    ---
    sysproperties:
      java_something_else:
        key: "path"
      java_iccprofile_path:
        value: "i/am/here"
    ...
    

    如果我将 sysproperties.java_iccprofile_path.value: "some/where/else" 放入 testrole.yml,它会失败。如果我在 testrole.yml 中有以下内容,它会起作用:

    ---
    - hosts: localhost
      roles:
        - {role: "myRole", sysproperties: {java_iccprofile_path: {value: "yuck"}}}
    ...
    

    上面的输出是

    PLAY [localhost] ***************************************************************
    
    TASK [Gathering Facts] *********************************************************
    ok: [localhost]
    
    TASK [defaults : Debugging] ****************************************************
    ok: [localhost] => {
        "sysproperties": {
            "java_iccprofile_path": {
                "value": "yuck"
            }
        }
    }
    
    PLAY RECAP *********************************************************************
    localhost                  : ok=2    changed=0    unreachable=0    failed=0   
    

    如您所见,它替换了值,但也删除了其他值。

    我发现here,将 hash_behavior 的值更改为在 ansible.cfg 文件中合并将保留旧内容,并且只会覆盖您告诉它要覆盖的内容。

    PLAY [localhost] ***************************************************************
    
    TASK [Gathering Facts] *********************************************************
    ok: [localhost]
    
    TASK [defaults : Debugging] ****************************************************
    ok: [localhost] => {
        "sysproperties": {
            "java_iccprofile_path": {
                "value": "yuck"
            }, 
            "java_something_else": {
                "key": "path"
            }
        }
    }
    
    PLAY RECAP *********************************************************************
    localhost                  : ok=2    changed=0    unreachable=0    failed=0   
    

    【讨论】:

    • 不,如果我这样做,仍然使用默认值。
    • 感谢您的广泛测试!但我不想为我的角色改变 ansible 标准行为。它现在可以很好地与剧本中的这个 pre_tasks 一起工作。实际上,我想知道是否有不同的或其他最佳实践方式来做我喜欢的事情。我的问题是我的模板中有一个我喜欢的设置列表,使用此角色的任何人都应该能够轻松地调整和更改这些设置。
    • 我的第一个想法是不要使用字典。如果您只有简单的键/值对,那么我最初的工作方式无需修改 ansible.cfg 文件。
    • 如果我将我所有的 sysproperties 放到键/值变量中,我怎么能做这样的事情:{% for key, value in sysproperties.items() %} &lt;sysproperty key="{{ value.key }}" value="{{ value.value }}" enabled="{{ value.enabled }}"/&gt; {% endfor %} 并添加/删除 sysproperties?就目前而言,我认为我现在的做法是唯一的出路……
    猜你喜欢
    • 1970-01-01
    • 2015-05-07
    • 2011-06-29
    • 1970-01-01
    • 1970-01-01
    • 2021-11-10
    • 1970-01-01
    • 2013-01-17
    相关资源
    最近更新 更多