【问题标题】:Override group_vars by external source通过外部源覆盖 group_vars
【发布时间】:2021-01-11 14:43:52
【问题描述】:

我有一个试点项目,在group_vars 中保留了许多常见变量。

group_vars/
  group1.yml
  group2.yml
  group3.yml 

对于不同的实现(通常是每个客户端),我想保留覆盖group_vars 内容的保留文件,其中该文件的内容可能具有以下格式,即client1.yml

group1:
  var11_to_override: "foo"
  var12_to_override: "bar"
group2:
  var21_to_override: "foo"
  var22_to_override: "bar"

是否可以简单地告诉 Ansible 文件 client1.yml 覆盖 group_vars 内容?

include_vars 模块当然可以与set_facts 在一个循环中一起使用,但它可能需要复杂的 jinja2 过滤器表达式...

我要写一个新模块或过滤器更新hostvars吗?

【问题讨论】:

  • docs.ansible.com/ansible/latest/user_guide/…。乍一看,我会将您当前的文件保存在库存group_vars 文件夹中,并在剧本group_vars 文件夹中逐组添加覆盖文件。
  • @Zeitounator 不幸的是,我必须保持client1.yml 文件的格式,并且不能与group_vars 文件放在同一个文件夹中。在这个项目的未来,我应该能够从 REST API 获得相同的内容。
  • 在这种情况下什么是“客户”?它是由 Ansible 管理的系统,还是您的客户,以便client1.yml 保存客户特定的数据?
  • @Jack 对于每个客户端,group_vars 中的一些值会发生变化,但主要部分仍然相同;这就是为什么我们要维护一种覆盖文件,覆盖一些默认值,而不是替换 group_vars 文件夹中的整个文件。
  • @ibt23sec5 这不能回答我的问题。 “客户”是由 Ansible 管理的系统,还是“客户”是您的客户?

标签: ansible yaml ansible-inventory ansible-facts


【解决方案1】:

使用此线程中给出的示例,我提出了自己的解决方案:

  1. 使用 --extra-vars "@" 在库存项目中提供“外部来源”。文件内容本身作为base64编码的内容上传,然后解码/写入fs。

  2. 外部文件具有每个角色/组的覆盖列表,如下所示:

         role_overrides: [{
           "groups": [
               "my-group"
           ],
           "overrides": {
               "foo": "value",
               "bar": "value",
           }
       },
    

但随后显然 jsonified...

  1. 过滤模块

    #!/usr/bin/env python

类过滤器模块(对象): def过滤器(自我): 返回 { “filter_hostvars_overrides”:self.filter_hostvars_overrides, }

def filter_hostvars_overrides(self, role_overrides, group_names):
    """
    filter the overrides for the ones to apply for this host

    [
      {
          "groups": [
              "my-group"
          ],
          "overrides": {
              "foo: 42,
          }
      },

    :param group_names: List of groups this host is member of
    :param role_overrides: document with all overrides; to be filtered using groups_names
    :return: items to be set
    """
    overrides = {}
    for idx, per_group_overrides in enumerate(role_overrides):
        groups = per_group_overrides.get("groups", [])
        if set(groups).intersection(set(group_names)):
            overrides.update(per_group_overrides.get("overrides", {}))
    return overrides
  1. 播放代码:

         - name: Apply group overrides
          set_fact:
            "{{ item.key }}": "{{ item.value }}"
          with_dict: "{{ role_overrides | filter_hostvars_overrides(group_names) }}"
    

【讨论】:

    【解决方案2】:

    最终通过自定义过滤器更新另一个字典来解决:

    filter_plugins/vars_update.py

    import copy
    import collections
    
    class FilterModule(object):
        def update_hostvars(self, _origin, overlay):
            origin = copy.deepcopy(_origin)
            for k, v in overlay.items():
                if isinstance(v, collections.Mapping):
                    origin[k] = self.update_hostvars(origin.get(k, {}), v)
                else:
                    origin[k] = v 
            return origin
    
        def filters(self):
            return {"update_hostvars": self.update_hostvars}
    

    .. 并在更新所有变量时使用此过滤器:

    - name: Include client file
      include_vars:
        file: "{{ client_file_path }}"
        name: client_overlay
    
    - name: Update group_vars by template client
      set_fact:
        "{{ item.key }}": "{{ hostvars[inventory_hostname][item.key] | update_hostvars(item.value) }}"
      with_dict: "{{ client_overlay }}"
    

    【讨论】:

      猜你喜欢
      • 2015-03-08
      • 2020-03-04
      • 2015-07-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-26
      • 2021-06-26
      • 2012-10-01
      相关资源
      最近更新 更多