Ansible 2.8 角色 - 使用 vars/main 目录

Posted

技术标签:

【中文标题】Ansible 2.8 角色 - 使用 vars/main 目录【英文标题】:Ansible 2.8 Roles - using the vars/main directory 【发布时间】:2020-02-03 10:37:35 【问题描述】:

我正在尝试将我的 Ansible 角色变量拆分为多个文件 - 根据 this answer,应该可以创建一个 vars/main 目录,并且应该自动加载该目录中的所有 .yml 文件。

然而,这似乎并没有发生在我的案例中。

我的目录结构:

vars
└── main
    ├── gce_settings.yml
    ├── vsphere_settings.yml
    └── vsphere_zone.yml

但是,当我尝试使用在 vsphere_settings.yml 中定义的变量时,Ansible 抱怨该变量未定义: "msg": "The task includes an option with an undefined variable. The error was: 'vsphere_user' is undefined

如果我将变量声明移动到vars/main.yml,一切都会按预期进行。但是,当然,我更愿意将我的变量分成多个文件。

我在 Ansible 官方文档中找不到对这个“功能”的任何引用,我不知道如何解决它。谁能指出我正确的方向?

我的 ansible 版本: ansible 2.8.5 在 Ubuntu 16.04 上

在你问之前:是的,我确实在尝试加载 vars/main/*.yml 时确保 main.yml 不存在...

【问题讨论】:

如果我下面的示例对您不起作用,请发布详细信息。让它mcve. 谢谢你,弗拉基米尔 - 我已经为问题添加了更多细节,并且我还在我的回答中发布了另一个示例(带有重现步骤)。 【参考方案1】:

TL;DR 版本:这是 ansible 中的一个错误,由 vars/main 中存在空的 .yml 文件引起。已经有一个 PR 了。看 here 。

实际结果(如 cmets 中所述)实际上取决于文件的处理顺序(默认情况下,我的 Ansible 似乎按字母顺序处理它们 - 但这可能取决于版本或底层操作系统) :

如果先处理空文件,则会收到错误消息:ERROR! failed to combine variables, expected dicts but got a 'NoneType' and a 'AnsibleMapping' 如果空文件在其他文件之后处理,没有错误信息,但是此时已经设置的所有变量都被销毁了

更多细节:因为我不知道如何在 Ansible 中解决这个问题,所以我去代码并开始添加 print 语句以查看发生了什么。

在我的例子中,我在 vars/main 目录中有一些空的 .yml 文件(我计划稍后填充的文件。嗯......看起来当代码遇到这样一个空文件时,它会破坏到目前为止它已经建立的整个字典。

要么我遗漏了一些非常重要的东西,要么这是一个错误......重现步骤:

创建角色 创建vars/main 目录,并用一些 .yml 文件填充它 添加一个空的 .yml 文件(命名以便在其他文件之后对其进行处理) 尝试打印第一个文件中的变量
    ansible# tree roles 
    roles
    +-- test
        +-- tasks
        ¦   +-- main.yml
        +-- vars
            +-- main
                +-- correct_vars.yml

    4 directories, 2 files

    ansible# cat roles/test/vars/main/correct_vars.yml  myname: bogd

    ansible# ansible-playbook -i inventory.yml test.yml 
    ... 
    ok: [localhost] => 
        "myname": "bogd"  
    ...

    ansible# echo > roles/test/vars/main/emptyfile.yml

    ansible# ansible-playbook -i inventory.yml test.yml 
    ... ok: [localhost] => 
        "myname": "VARIABLE IS NOT DEFINED!"  
    ...

稍后编辑:是的,这是一个错误...见here。

【讨论】:

你应该在你的问题中编辑这个,而不是发布一个答案 @β.εηοιτ.βε - 因为这正式解决了我的问题(“这是一个错误,并且已经有一个 PR”),所以我决定用它来回答。希望这将帮助其他遇到同样问题的人。我将编辑答案并将最终结果(“这是一个错误”)移到顶部,以使事情更清楚。 这是无关的,不是错误。您在问题中所指的是 role vars 您所缺少的是 myrdd 在链接答案中所说的所有路径实际上都与角色文件夹相关。 链接的问题确实是指剧本 - 但它是相同的代码路径和相同的行为(当 new_data 为 None 时,combine_vars 会破坏字典)。而且,事实上,甚至 bcoca 也关闭了一个角色问题 (github.com/ansible/ansible/issues/54915),作为我链接的那个的欺骗。 @β.εηοιτ.βε - 抱歉,我错过了您评论的第二部分。当然,我上面测试的所有内容都与角色文件夹相关(答案应该清楚)。但是当您说“这不是错误”时,您的依据是什么?我错过了什么?因为我已经链接了两个似乎说是bug的github问题...【参考方案2】:

下面的例子

$ cat play.yml 
- hosts: localhost
  roles:
    - role1

$ cat roles/role1/tasks/main.yml 
- debug:
    var: var1

$ cat roles/role1/vars/main/var1.yml 
var1: test_var1

给予

"var1": "test_var1"

【讨论】:

谢谢你——的确,事情应该是这样的。看来我偶然发现了一个由空的 .yml 文件引起的错误。详情见我的回答。

以上是关于Ansible 2.8 角色 - 使用 vars/main 目录的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Ansible 角色中包含很多 var

Ansible 2.8:访问列表对象元素

Ansible 角色中的默认值和变量有什​​么区别?

Ansible角色

06Ansible角色

Ansible 剧本与角色