使用多个配置变量验证行

  • 本文关键字:变量 验证 配置 ansible
  • 更新时间 :
  • 英文 :


我正在学习ansible,无法用asnible简单地解决这个问题。

我有一个文件,其中包含:

net.ifnames=0 dwc_otg.lpm_enable=0 console=serial0,115200 console=tty1 root=LABEL=writable rootfstype=ext4 elevator=deadline rootwait fixrtc cgroup_memory=1 cgroup_enable=memory

这是一行,例如,我想检查cgroup_memory是否设置为1,如果没有设置为1以及是否缺少整个设置,请将其追加到行的末尾。

我知道如何用bash和sed做这件事的非常简单的方法,但我无法理解ansible";正确的";方法,不使用线内野和替换整个线。。。如前所述,lineinfile正在使用整条线,所以我认为这并不理想。。我研究的下一个模块是可能工作的替换,但我不能只寻找";cgroup_memory=1";正如它所看到的";cgroup_memory=0";并被评价为不是";cgroup_memory=1";最后我在一个文件中得到了cgroup_memory=1 cgroup_mediary=0。。。不知何故,我需要提取值,比较并替换值(保持整行完整(,如果不存在,则附加到行的末尾。。。

以下是我想要的ansible中的bash版本:https://pastebin.com/1TCz30Nq

这是我最接近我需要的东西:

- name: "Check for cgroup_memory"
  shell: grep -v '^[[:space:]]*#' /tmp/cmdline.txt_old | grep -icP "cgroup_memory=-?d+[[:space:]]" || true
  register: grep_value
  changed_when: False
- debug:
    var: grep_value
- name: "Variable Missing: Add cgroup_memory=1 to end of line"
  become: true
  replace: dest=/tmp/cmdline.txt_old regexp='(s+)$' replace=' cgroup_memory=1'
  when: grep_value.stdout == "0"
- name: "Variable Exist: Set cgroup_memory=1"
  become: true
  replace: dest=/tmp/cmdline.txt_old regexp='cgroup_memory=d+' replace='cgroup_memory=1'
  when: grep_value.stdout == "1"

然而,这并没有忽略#lines,所以替换会很高兴地更改注释中的值,这很糟糕。同样,这并没有评估价值,但我想我可以在确定它在那里后进一步拆分。。我不想抱怨,但ansible被宣传为非常适合配置管理,我通过shell脚本做的第一件简单的事情并没有那么简单。。。(如果我不想使用外壳模块(

确保cgroup_memory设置为1的一种方法是使用Ansible替换模块。替换模块可以匹配regexp,并将其替换为我们想要的。

示例:

  tasks:
  - name: set cgroup_memory to 1
    replace:
      path: /path/to/file
      regexp: 'cgroup_memory=d+'
      replace: 'cgroup_memory=1'

如果有多行具有此表达式,则将替换所有出现的行。我们可以在上述任务中使用beforeafter参数来针对特定的参数。

或者我们可以使用lineinfile模块来确保整条线都存在。

  tasks:
  - name: ensure line with cgroup_memory is present in file
    lineinfile:
      path: /path/to/file
      regexp: 'cgroup_memory=d+'
      line: "net.ifnames=0 dwc_otg.lpm_enable=0 console=serial0,115200 console=tty1 root=LABEL=writable rootfstype=ext4 elevator=deadline rootwait fixrtc cgroup_memory=1 cgroup_enable=memory"

最好的选项IMHO是blockinfile。给定下方的配置文件

shell> cat test.cfg
line1
line2
net.ifnames=0 dwc_otg.lpm_enable=0 console=serial0,115200 console=tty1 root=LABEL=writable rootfstype=ext4 elevator=deadline rootwait fixrtc cgroup_memory=1 cgroup_enable=memory
line4
line5

先划线blockinfile需要标记来找到块(在这种情况下是一条线(。例如

    - lineinfile:
        path: test.cfg
        insertbefore: "^net.ifnames(.*)$"
        line: "# BEGIN ANSIBLE MANAGED BLOCK my_block_01"
    - lineinfile:
        path: test.cfg
        insertafter: "^net.ifnames(.*)$"
        line: "# END ANSIBLE MANAGED BLOCK my_block_01"

给出

shell> cat test.cfg
line1
line2
# BEGIN ANSIBLE MANAGED BLOCK my_block_01
net.ifnames=0 dwc_otg.lpm_enable=0 console=serial0,115200 console=tty1 root=LABEL=writable rootfstype=ext4 elevator=deadline rootwait=fixrtc cgroup_memory=1 cgroup_enable=memory 
# END ANSIBLE MANAGED BLOCK my_block_01
line4
line5

上面的lineinfile任务是幂等的。然后使用配置创建一个变量。例如

shell> cat net_cfg.yml 
net_cfg_01:
  - {key: 'net.ifnames', val: 0}
  - {key: 'dwc_otg.lpm_enable', val: 0}
  - {key: 'console', val: 'serial0,115200'}
  - {key: 'console', val: 'tty1'}
  - {key: 'root', val: 'LABEL=writable'}
  - {key: 'rootfstype', val: 'ext4'}
  - {key: 'elevator', val: 'deadline'}
  - {key: 'rootwait', val: 'fixrtc'}
  - {key: 'cgroup_memory', val: 1}
  - {key: 'cgroup_enable', val: 'memory'}

必须使用列表,而不是更简单的字典,因为键不是唯一的。创建模板。例如

shell> cat templates/net_cfg_01.j2
{% for i in net_cfg_01 %}{{i.key}}={{i.val}} {% endfor %}

现在,您可以在文件中包含变量并配置行

    - include_vars: net_cfg.yml
    - blockinfile:
        path: test.cfg
        block: "{{ lookup('template', 'net_cfg_01.j2') }}"
        marker: "# {mark} ANSIBLE MANAGED BLOCK my_block_01"

钞票

  • 根据您的需要和文件的注释格式调整标记
  • 模板在行尾之前留下一个空白。如有必要,请使用loop.last进行修复
  • 所有任务都是幂等的

如何使用它

关于如何使用上述框架,有很多选择。例如,将配置变量放入列表

shell> cat net_cfg.yml
net_cfg_01:
  ... 
  - {key: 'cgroup_memory', val: {{ my_cgroup_memory }}}

然后下面的命令将确保文件配置正确

shell> ansible-playbook playbook.yml -e 'my_cgroup_memory=1'