如何在 vars 中使用已注册 ansible 变量的字典? [英] How to use a dictionary of registered ansible variables in vars?

查看:22
本文介绍了如何在 vars 中使用已注册 ansible 变量的字典?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用 vars 将多个变量传递给任务.目前,我正在这样做

I want to pass multiple variables to a task using vars. Currently, I am doing it like below

vars:
    var1_name: "var1_value"
    var2_name: "var2_value"

随着变量数量的增加,我更愿意使用 vars 将变量字典传递给任务.我已经构建了一个像下面这样的变量字典

As the number of variables can grow in size, I'd rather prefer to pass the dictionary of variables to the task using vars. I have constructed a dictionary of variables like below

- name: set fact
  hosts: localhost
  tasks:
  - set_fact:
      variables: "{{ variables|default({}) | combine( {item.variable: item.value} ) }}"
    with_items:
    - variable: var1_name
      value: "var1_value"
    - variable: var2_name
      value: "var2_name"

字典看起来像这样:

"variables": {
    "var1_name": "var1_value",
    "var2_name": "var2_value",
}

现在,我想让这个字典中的变量可用于在其他主机上执行的角色.

Now, I want to make variables in this dictionary available to roles executing on other hosts.

但是,当我尝试将字典传递给 vars 如下

But, when I tried to pass dictionary to vars like below

vars: "{{ variables }}"

Ansible 抛出错误:

Ansible throws the error:

ERROR! Vars in a Play must be specified as a dictionary, or a list of dictionaries

如何在vars中传递字典变量?

How to pass a dictionary variable in vars?

推荐答案

在对 Ansible 源代码进行了一些搜索后,看起来这甚至是 Ansible 的开发人员都面临的问题.在一些集成测试中,有一些特定的测试会因为同样的错误而被注释掉.

After doing some searching through the Ansible source code, it looks like this is an issue even the developers of Ansible face. In some integration tests, there are specific tests that are commented out because of this same error.

https:///github.com/ansible/ansible/blob/devel/test/integration/targets/include_import/role/test_include_role.yml#L96

## FIXME Currently failing with
## ERROR! Vars in a IncludeRole must be specified as a dictionary, or a list of dictionaries
# - name: Pass all variables in a variable to role
#   include_role:
#     name: role1
#     tasks_from: vartest.yml
#   vars: "{{ role_vars }}"

我还发现这是被调用以包含变量的基础函数:

I also found out that this is the underlying function that is being called to include the variables:

https://github.com/ansible/ansible/blob/devel/lib/ansible/playbook/base.py#L681

    def _load_vars(self, attr, ds):
        '''
        Vars in a play can be specified either as a dictionary directly, or
        as a list of dictionaries. If the later, this method will turn the
        list into a single dictionary.
        '''

        def _validate_variable_keys(ds):
            for key in ds:
                if not isidentifier(key):
                    raise TypeError("'%s' is not a valid variable name" % key)

        try:
            if isinstance(ds, dict):
                _validate_variable_keys(ds)
                return combine_vars(self.vars, ds)
            elif isinstance(ds, list):
                all_vars = self.vars
                for item in ds:
                    if not isinstance(item, dict):
                        raise ValueError
                    _validate_variable_keys(item)
                    all_vars = combine_vars(all_vars, item)
                return all_vars
            elif ds is None:
                return {}
            else:
                raise ValueError
        except ValueError as e:
            raise AnsibleParserError("Vars in a %s must be specified as a dictionary, or a list of dictionaries" % self.__class__.__name__,
                                     obj=ds, orig_exc=e)
        except TypeError as e:
            raise AnsibleParserError("Invalid variable name in vars specified for %s: %s" % (self.__class__.__name__, e), obj=ds, orig_exc=e)

好像从{{}}"开始实际上只是一个 YAML 字符串,Ansible 不会将其识别为 dict,这意味着 vars 属性不会通过 Jinja2 引擎传递,而是根据它的实际情况进行评估.

Seems as if since "{{ }}" is actually just a YAML string, Ansible doesn't recognize it as a dict, meaning that the vars attribute isn't being passed through the Jinja2 engine but instead being evaluated for what it actually is.

传递 YAML 对象的唯一方法是使用锚点,但是这需要完整定义对象而不是动态定义.

The only way to pass YAML objects around would be to use anchors, however this would require that the object be defined in whole instead of dynamically.

    var: &_anchored_var 
      attr1: "test"
      att2: "bar"
    
    vars:
      <<: *_anchored_var

这篇关于如何在 vars 中使用已注册 ansible 变量的字典?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆