【问题标题】:Overriding Ansible module options defaults覆盖 Ansible 模块选项默认值
【发布时间】:2023-10-06 11:47:02
【问题描述】:

我正在努力找出如何在不使用变量手动滚动的情况下覆盖 Ansible 模块选项默认值。如果有一种方法可以仅针对一部分主机覆盖模块选项默认值,那就更好了。

说在几个主机上,Git 可以在/bin/git 获得,正如预期的那样。在其他几个主机上,Git 位于/usr/local/bin/git。如何覆盖后一组主机的 git 模块 executable 选项默认值?

目前我正在设置一个主机组变量,例如:

git_executable=/usr/local/bin/git

并在任何地方使用default(omit) 过滤器git 使用如下:

- git: "executable={{git_executable|default(omit)}} ..."

因此它在定义它的主机上被正确覆盖,而在其他主机上被忽略。

executable 可能不是这里最好的例子,因为它可以通过PATH 环境变量或其他东西来控制。那么,一般来说,我只想为某些主机覆盖但又回退到模块默认值的任何类型的模块选项呢?

由于在这个环境中存在更多这样的基本差异,因此在所有地方都使用变量散布这种 默认 查找非常繁琐,以防万一它在没有-默认设置。有没有办法更好地做到这一点?

【问题讨论】:

    标签: module default default-value ansible


    【解决方案1】:

    在这种特定情况下,git.executable 只要它在 PATH 或 '/sbin'、'/usr/sbin'、'/usr/local/sbin' 中,git 模块就会找到它,因为它使用了 @987654321 @

    在更大的话题上,我个人会选择你已经做过的事情。但是,如果您一心想要这样做,另一种可能的技巧是 [mis] 使用 include 语句为每个模块创建一个包装器,该包装器从某个变量中提供您想要的默认值。 显然,您必须自己在 group_vars 或 host/role/... vars 中指定路径。或者在剧本的vars 部分中定义的变量。

    $ cat my_echo.yml 
    
    - shell: "{{echo_exec}} '{{text}}'"
    
    $ cat playbook.yml
    - hosts: localhost
      tags: so
      gather_facts: False
      vars:
        echo_exec: echo
      tasks:
      - include: my_echo.yml text='some text'
        changed_when: False
    
    - hosts: localhost
      tags: so
      gather_facts: False
      vars:
        echo_exec: printf
      tasks:
      - include: my_echo.yml text='some text'
        changed_when: False
    
    $ ansible-playbook playbook.yml -t so -v
    
    PLAY [localhost] ************************************************************** 
    
    TASK: [shell {{echo_exec}} '{{text}}'] **************************************** 
    changed: [localhost] => {"changed": true, "cmd": "echo 'some text'", "delta": "0:00:00.003782", "end": "2015-03-20 17:45:58.352069", "rc": 0, "start": "2015-03-20 17:45:58.348287", "stderr": "", "stdout": "some text", "warnings": []}
    
    PLAY [localhost] ************************************************************** 
    
    TASK: [shell {{echo_exec}} '{{text}}'] **************************************** 
    changed: [localhost] => {"changed": true, "cmd": "printf 'some text'", "delta": "0:00:00.003705", "end": "2015-03-20 17:45:58.690657", "rc": 0, "start": "2015-03-20 17:45:58.686952", "stderr": "", "stdout": "some text", "warnings": []}
    
    PLAY RECAP ******************************************************************** 
    localhost                  : ok=2    changed=2    unreachable=0    failed=0   
    
    $ 
    

    【讨论】:

      【解决方案2】:

      我认为没有更好的选择。模块只知道你传递给他们的东西。除非您将其作为模块参数显式传递,否则它们无法访问全局变量、服务器事实或其他任何内容。

      如果这真的很重要并且您想投入一些时间,您可以创建自己的动作插件。动作插件是本地动作,因此可以访问 Ansible runnerc 类及其所有属性,包括事实等。因此您可以根据服务器事实在其中处理默认参数或可执行检测,然后以编程方式调用 git 或任何模块。我认为开销很大,但这取决于视图,并且可能对您来说是可行的。

      尽管小心,动作插件是 100% 未记录的。 Ansible 2.0 将在接下来的几天内发布。他们声称 100% 向后兼容,但如果这仅适用于记录的功能,我不会感到惊讶。

      【讨论】: