【问题标题】:Ansible: Merge item variable that's been used multiple timesAnsible:合并多次使用的项目变量
【发布时间】:2020-05-14 15:47:47
【问题描述】:

我为 ansible 编写了一个 nftables 角色,它为我的服务器打开了端口。我想要某种等级制度。我想定义应在每个主机上打开的规则,但有些规则只能应用于一组主机。

库存

---
myservers:
  hosts:
    server1:
    server2:
    server3:
    server4:
groupa:
  hosts:
    server1:
    server2:
groupb:
  hosts:
    server3:
    server4:

这些是我的 group_vars: 我的服务器.yml

---
nftablesopen:
  - dport: "22"
    comment: "SSH"
    proto: tcp

groupa.yml

---
nftablesopen:
  - dport: "123"
    comment: "NTP"
    proto: "udp"

groupb.yml

---
nftablesopen:
  - dport: "80"
    comment: "HTTP"
    proto: "udp"

当我运行剧本时,可变的优先级开始起作用,并且只有我定义的一部分被应用。 Ansible 中处理此问题的最佳方法是什么? 我宁愿不要将大量不同的变量合并为一个变量,因为我不想在添加一组新主机时更新我的​​任务。我不能像在不同的编程语言中那样将项目附加到现有的项目列表中吗?

【问题讨论】:

    标签: ansible


    【解决方案1】:

    我建议创建一个包含组的字典并让主机extract 进行配置。例如

    shell> cat hosts
    [myservers]
    test_01
    test_02
    
    [groupa]
    test_01
    
    [groupb]
    test_02
    
    nftablesopen:
      myservers:
        - dport: "22"
          comment: "SSH"
          proto: tcp
      groupa:
        - dport: "123"
          comment: "NTP"
          proto: "udp"
      groupb:
        - dport: "80"
          comment: "HTTP"
          proto: "udp"
    
    - set_fact:
        my_open: "{{ group_names|
                     map('extract',nftablesopen)|
                     list|flatten }}"
    - debug:
        var: my_open
    

    ok: [test_01] => {
        "my_open": [
            {
                "comment": "NTP",
                "dport": "123",
                "proto": "udp"
            },
            {
                "comment": "SSH",
                "dport": "22",
                "proto": "tcp"
            }
        ]
    }
    ok: [test_02] => {
        "my_open": [
            {
                "comment": "HTTP",
                "dport": "80",
                "proto": "udp"
            },
            {
                "comment": "SSH",
                "dport": "22",
                "proto": "tcp"
            }
        ]
    }
    

    问:“如果有我没有在 nftabblesopen 中指定的组名怎么办?”

    答:intersect 键和组的列表。例如

        - set_fact:
            my_open: "{{ nftablesopen.keys()|
                         list|
                         intersect(group_names)|
                         map('extract',nftablesopen)|
                         list|flatten }}"
    

    使用三个主机运行 playbook

    shell> cat hosts
    [myservers]
    test_01
    test_02
    
    [groupa]
    test_01
    
    [groupb]
    test_02
    
    [groupc]
    test_03
    
    - hosts: test_01, test_02, test_03
    

    给予

    ok: [test_02] => {
        "my_open": [
            {
                "comment": "SSH",
                "dport": "22",
                "proto": "tcp"
            },
            {
                "comment": "HTTP",
                "dport": "80",
                "proto": "udp"
            }
        ]
    }
    ok: [test_01] => {
        "my_open": [
            {
                "comment": "SSH",
                "dport": "22",
                "proto": "tcp"
            },
            {
                "comment": "NTP",
                "dport": "123",
                "proto": "udp"
            }
        ]
    }
    ok: [test_03] => {
        "my_open": []
    }
    

    问:“(这种方式)我需要通过显式命名来与组相关联,而不是仅仅将变量放入相应的组中。”

    A:将项目的常用变量放入目录,例如:全局变量

    shell> cat global_vars/nftablesopen.yml 
    nftablesopen:
      myservers:
        - dport: "22"
          comment: "SSH"
          proto: tcp
      groupa:
        - dport: "123"
          comment: "NTP"
          proto: "udp"
      groupb:
        - dport: "80"
          comment: "HTTP"
          proto: "udp"
    

    将此目录链接到项目的每个 host_vars。例如

    shell> tree host_vars/
    host_vars/
    ├── test_01
    │   └── global_vars -> ../../global_vars
    ├── test_02
    │   └── global_vars -> ../../global_vars
    └── test_03
        └── global_vars -> ../../global_vars
    

    更改配置意味着修改目录中的单个文件。

    【讨论】:

    • 感谢您的回答。如果有我没有指定 nftabblesopen 的组名怎么办?这将抛出错误:任务执行期间发生异常。要查看完整的回溯,请使用 -vvv。错误是: KeyError: 'groupf' fatal: [test_01]: FAILED! => {"msg": "模块执行期间意外失败。", "stdout": ""}
    • 使用intersect 过滤器选择组。查看更新的答案。
    • 对不起,我花了很长时间来测试这个。它确实有效。你的方式我需要通过明确命名它们而不是仅仅将变量放入相应的组来与组相关,但我可以接受。
    • 您可以利用它。创建一个新目录 global_vars 并将其链接到项目中的每个 host_vars 目录。这可以很容易地自动化。将这些变量放入 global_vars 中的文件中。这样您就可以合并项目的公共变量并将它们放在一个目录中。
    猜你喜欢
    • 1970-01-01
    • 2019-05-10
    • 2022-07-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-11
    • 1970-01-01
    • 2015-01-02
    相关资源
    最近更新 更多