Ansible - 动态变量内容

问题描述 投票:0回答:3

我有一个包含 3 个盒子的环境,部分安装作业创建一个备份脚本和一个关联的 cron 作业来运行该脚本。目前,该作业仅进入 01 实例并每小时运行一次。

- name: Create Backup script cron job
  cron:
    name: "S3 Backup"
    minute: "0"
    hour: "{{ backup_frequency }}"
    job: "{{ app_home_dir }}/tools/aws_s3_backup.sh"
  when: inventory_hostname in groups['admin']
  become: true

我希望拥有它,以便脚本可以运行到所有 3 个实例上,并在所有三个实例上创建 cronjob,但相应的框仅每 3 小时运行一次...

Box 1 ... hour : 01,04,07,10,13,16,19,22
Box 2 ... hour : 02,05,08,11,14,17,20,23
Box 3 ... hour : 03,06,09,12,15,18,21,00

我知道获取相关时间的数学理论 - 即获取盒子编号,然后在计数器上对 0-23 进行模 3 循环,看看它是否等于 {box num},如果是,则将其包含在小时列表中盒子。

但是,我不知道这是否需要通过 Jinja 完成,还是可以直接在 Ansible 代码本身中完成?然后怎么办?

如有任何帮助,我们将不胜感激!

ansible yaml jinja2
3个回答
1
投票

假设您的主机名类似于

box-1
box-2
等,您可以执行以下操作:

- hosts: all
  gather_facts: false
  tasks:
    - set_fact:
        backup_frequency: >-
          {{ range(box_num|int, 25, 3)|join(", ") }}
      vars:
        box_num: >-
          {{ inventory_hostname.split('-')[1]|int }}

    - debug:
        var: backup_frequency

这个 几乎 可以工作并为

backup_frequency
生成如下所示的值:

ok: [box-1] => {
    "backup_frequency": "1, 4, 7, 10, 13, 16, 19, 22"
}
ok: [box-2] => {
    "backup_frequency": "2, 5, 8, 11, 14, 17, 20, 23"
}
ok: [box-3] => {
    "backup_frequency": "3, 6, 9, 12, 15, 18, 21, 24"
}

请注意,最后的

24
是错误的
box-3
。如果 Ansible 有
modulo
函数,我们可以解决这个问题……它没有,但我们可以通过将以下代码放入
filter_plugins/filters.py
中来提供一个:

def filter_modulo(v, mod):
    return v % mod

class FilterModule:
    def filters(self):
        return {
                'modulo': filter_modulo,
                }

这让我们可以写:

- hosts: all
  gather_facts: false
  tasks:
    - set_fact:
        backup_frequency: >-
          {{ range(box_num|int, 25, 3)|map('modulo', 24)|join(", ") }}
      vars:
        box_num: >-
          {{ inventory_hostname.split('-')[1]|int }}

    - debug:
        var: backup_frequency

产生:

ok: [box-1] => {
    "backup_frequency": "1, 4, 7, 10, 13, 16, 19, 22"
}
ok: [box-2] => {
    "backup_frequency": "2, 5, 8, 11, 14, 17, 20, 23"
}
ok: [box-3] => {
    "backup_frequency": "3, 6, 9, 12, 15, 18, 21, 0"
}

...这就是你想要的。


0
投票

大括号内发生的逻辑,采用 jinja 语法。

看起来像伪的

hour: {{ box_name | regex'[0-9]'| to_int | modulo(3) }}


0
投票

设置频率,获取小时范围并重新排列列表

  freq: "{{ ansible_play_hosts_all|length }}"
  ranges: |
    [{% for start in range(0, freq|int) %}
    {{ range(start|int, 24, freq|int) }},
    {% endfor %}]
  ranges0: "{{ ranges[1:] + [ranges.0] }}"

给予

  ranges0:
    - [1, 4, 7, 10, 13, 16, 19, 22]
    - [2, 5, 8, 11, 14, 17, 20, 23]
    - [0, 3, 6, 9, 12, 15, 18, 21]

获取索引

  index: "{{ ansible_play_hosts_all.index(inventory_hostname) }}"

并设置时间

    - debug:
        msg: "hour: {{ ranges0[index|int]|join(',') }}"

给予

ok: [box-1] => 
  msg: 'hour: 1,4,7,10,13,16,19,22'
ok: [box-2] => 
  msg: 'hour: 2,5,8,11,14,17,20,23'
ok: [box-3] => 
  msg: 'hour: 0,3,6,9,12,15,18,21'

用于测试的完整剧本示例

- hosts: box-1,box-2,box-3

  vars:

    freq: "{{ ansible_play_hosts_all|length }}"
    ranges: |
      [{% for start in range(0, freq|int) %}
      {{ range(start|int, 24, freq|int) }},
      {% endfor %}]
    ranges0: "{{ ranges[1:] + [ranges.0] }}"
    index: "{{ ansible_play_hosts_all.index(inventory_hostname) }}"

  tasks:

    - debug:
        var: ranges0|to_yaml
      run_once: true

    - debug:
        msg: "hour: {{ ranges0[index|int]|join(',') }}"
© www.soinside.com 2019 - 2024. All rights reserved.