ansible 从文件中读取参数值

ansible read parameter value from file

我有一个看起来类似的文件:

# some comment
foo/variable1 = value1
bar/variable2 = value2

等等

我一直在尝试想出一种可靠的逻辑来从此文件中查找一个感兴趣的特定变量。 例如,如果我需要在 ansible 中将 value2 分配给 myvar。

首先尝试了 lineinfile,如下所示:

- name: taskname
  lineinfile:
    path: /path/to/file
    regexp: '^bar/variable2.*$'
    line: dummy
  register: myvar
  check_mode: yes

没用。我还尝试转义正则表达式模式中的 / 字符,但这不是问题所在。然后我尝试查找 ini 文件,例如:

vars: 
  myvar: "{{ lookup('ini', 'bar/variable2 file=/path/to/file') }}"

但是文件没有节,所以这也失败了。

我也尝试过以不同的方式使用 regex_search,但我似乎无法让它工作。如果有人可以帮助我,我将不胜感激。我希望查找 ini 文件有一个版本,其中该部分是可选的。有一些参数文件遵循非常相似的格式,只是它们中没有节。

ini 查找似乎工作正常,只要您有兼容的文件格式(具体来说,您需要 headers 部分)。例如,如果我有一个文件 data.ini,其中包含:

[global]
# some comment
foo/variable1 = value1
bar/variable2 = value2

然后这有效:

- hosts: localhost
  gather_facts: false
  tasks:
    - debug:
        msg: "{{ lookup('ini', 'bar/variable2', file='data.ini') }}"

这导致:

TASK [debug] ********************************************************************************************
ok: [localhost] => {
    "msg": "value2"
}

如果你不想修改你的输入文件,你可以用正则表达式来做:

- hosts: localhost
  gather_facts: false
  vars:
    config: "{{ lookup('file', 'data.ini') }}"
  tasks:
    - debug:
        msg: >-
          {{
              config |
              regex_search('^foo/variable1 *= *.*', multiline=True) |
              regex_replace('.*= *(.*)$', '')
          }}

这导致:

TASK [debug] ********************************************************************************************
ok: [localhost] => {
    "msg": "value1"
}

针对您的评论进行的一些更新:

What is peculiar about the line breaks that made it working?

几乎没有。换行符只是为了使其更易于阅读。你就像这样很容易地写它:

    - debug:
        msg: "{{ config | regex_search('^foo/variable1 *= *.*', multiline=True) | regex_replace('.*= *(.*)$', '\1') }}"

这里唯一的技巧是在 double-quoted 字符串中,您需要写 \1 而不是 </code>。如果我们在外面使用单引号,那将是相同的:</p> <pre><code> - debug: msg: '{{ config | regex_search("^foo/variable1 *= *.*", multiline=True) | regex_replace(".*= *(.*)$", "") }}'


Second, I am trying to understand the regex_replace part.

regex_search 的输出将是配置文件中的一行,类似于:

foo/variable1 = value1

我们只需要 = 符号后的位。正则表达式替换捕获它,然后用捕获组 () 的值替换整个字符串。可能有更优化的方法来做到这一点,但这是我想到的。

恕我直言,没有可用的 ini 解析器。模块 ini_file 和查找 ini 插件(参见 shell> ansible-doc -t lookup ini)都不能读取整个 ini 文件。

但是,您可以自己解析它。例如

    - set_fact:
        myvars: "{{ myvars|d({})|combine({_key: _val}) }}"
      loop: "{{ lookup('file', 'data.ini').split('\n') }}"
      when: item is match('(?!\s*#).*=.*')
      vars:
        _arr: "{{ item.split('=') }}"
        _key: "{{ _arr.0|trim|regex_replace('[^\w]', '_') }}"
        _val: "{{ _arr.1|trim }}"

给予

  myvars:
    bar_variable2: value2
    foo_variable1: value1

备注:

  • 潜在部分(例如[默认])将被忽略
  • 变量的名称将被固定。参见 Creating valid variable names
  • 如果您不想更改变量的名称,请从表达式中删除 regex_replace 过滤器。有效 Ansible 变量名称的规则不适用于字典键。