Ansible:根据目标库存切换/覆盖变量
我正在考虑使用Ansible在三种不同环境(prod/stag/dev)的主机上部署rails应用程序。但为每台主机设置不同的Ansible:根据目标库存切换/覆盖变量,ansible,Ansible,我正在考虑使用Ansible在三种不同环境(prod/stag/dev)的主机上部署rails应用程序。但为每台主机设置不同的RAILS\u ENV却举步维艰 我尝试了以下设置 目录结构: . ├── group_vars │ └── app1.yml ├── inventories │ ├── develop │ │ └── group_vars │ │ └── app1.yml │ ├── production │ └── staging └── r
RAILS\u ENV
却举步维艰
我尝试了以下设置
目录结构:
.
├── group_vars
│ └── app1.yml
├── inventories
│ ├── develop
│ │ └── group_vars
│ │ └── app1.yml
│ ├── production
│ └── staging
└── roles
组变量/app1.yml
(用于跨环境的通用变量)
存货/develope/group_vars/app1.yml
(针对特定存货的VAR)
在判断变量是否已经定义时,Ansible似乎只查看顶层的键。因此,第二个文件中的RAILS\u ENV
被无意中忽略。
(不确定为什么库存变量的优先级较低,我认为应该较高,因为它更具体?)
有什么干净的方法可以做到这一点吗?正如Ansible文档的hash behavior一文所建议的:
默认\u散列\u行为
说明:此设置控制变量如何在Ansible中合并。默认情况下,Ansible将按照特定的优先顺序覆盖变量,如变量中所述。当一个优先级较高的变量获胜时,它将替换另一个值。一些用户更喜欢合并散列变量(Python术语中称为“字典”)。此设置称为“合并”。这不是默认行为,也不会影响值为标量(整数、字符串)或数组的变量。我们通常建议不要使用此设置,除非您认为您绝对需要它,并且官方示例中的剧本REPO在版本2.0中不使用此设置。添加了combine
filter,以允许对特定变量(在Filters中描述)执行此操作
来源:实现这一点的推荐方法是使用过滤器 这就是说,您的词典中确实有一个列表,这将使它成为一项相当复杂的任务。
换成字典可以减轻痛苦:
服务:
应用程序:
环境:
RAILS_ENV:开发
可重写的变量:foo
db:
福:酒吧
如果我理解正确的话,您是在尝试采用Ansible最佳实践 如果是这种情况,这里可能有一个与您的用例相匹配的解决方案,因为您可以在字典中的
服务
中转置您的列表,如上所述:
服务
字典键的前缀,例如开发服务
development\u服务:
应用程序:
环境:
RAILS_ENV:开发
可覆盖的变量:从库存组变量开发
pre_任务
,将服务
字典与与您的环境相匹配的字典结合,您可以将其作为路径的一部分:
pre_任务:
-设定事实:
服务:{{services}combine(vars[inventory_file.split('/')[-2]~''u services'],recursive=True)}
.
├── group_vars
│ └── app1.yml
├── inventories
│ ├── develop
│ │ ├── group_vars
│ │ │ └── app1.yml
│ │ └── hosts
│ └── staging
│ ├── group_vars
│ │ └── app1.yml
│ └── hosts
└── play.yml
组变量/app1.yml
服务:
应用程序:
环境:
酒吧:福
可重写的变量:来自根组变量
不覆盖:来自根组变量
db:
引擎:博士后
清单/开发/主机
全部:
儿童:
附录1:
主持人:
应用程序:
存货/开发/集团变量/app1.yml
development\u服务:
应用程序:
环境:
RAILS_ENV:开发
可覆盖的变量:从库存组变量开发
库存/暂存/主机
全部:
儿童:
附录1:
主持人:
应用程序:
库存/暂存/组变量/app1.yml
staging\u服务:
应用程序:
环境:
RAILS_ENV:暂存
可覆盖的变量:从库存组变量暂存
play.yml
-主机:所有
收集事实:不
学前任务:
-设定事实:
服务:{{services}combine(vars[inventory_file.split('/')[-2]~''u services'],recursive=True)}
任务:
-调试:
msg:“{{services}}”
为develope
运行它将提供以下概述:
$ ansible-playbook play.yml -i inventories/develop
PLAY [all] *********************************************************************************************************
TASK [set_fact] ****************************************************************************************************
ok: [app]
TASK [debug] *******************************************************************************************************
ok: [app] => {
"msg": {
"app": {
"environment": {
"RAILS_ENV": "development",
"bar": "foo",
"do_not_override_me": "from root group_vars",
"overridable_var": "develop from inventories group_vars"
}
},
"db": {
"engine": "postgres"
}
}
}
PLAY RECAP *********************************************************************************************************
app : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
$ ansible-playbook play.yml -i inventories/staging
PLAY [all] *********************************************************************************************************
TASK [set_fact] ****************************************************************************************************
ok: [app]
TASK [debug] *******************************************************************************************************
ok: [app] => {
"msg": {
"app": {
"environment": {
"RAILS_ENV": "staging",
"bar": "foo",
"do_not_override_me": "from root group_vars",
"overridable_var": "staging from inventories group_vars"
}
},
"db": {
"engine": "postgres"
}
}
}
PLAY RECAP *********************************************************************************************************
app : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
为登台运行它将提供重述:
$ ansible-playbook play.yml -i inventories/develop
PLAY [all] *********************************************************************************************************
TASK [set_fact] ****************************************************************************************************
ok: [app]
TASK [debug] *******************************************************************************************************
ok: [app] => {
"msg": {
"app": {
"environment": {
"RAILS_ENV": "development",
"bar": "foo",
"do_not_override_me": "from root group_vars",
"overridable_var": "develop from inventories group_vars"
}
},
"db": {
"engine": "postgres"
}
}
}
PLAY RECAP *********************************************************************************************************
app : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
$ ansible-playbook play.yml -i inventories/staging
PLAY [all] *********************************************************************************************************
TASK [set_fact] ****************************************************************************************************
ok: [app]
TASK [debug] *******************************************************************************************************
ok: [app] => {
"msg": {
"app": {
"environment": {
"RAILS_ENV": "staging",
"bar": "foo",
"do_not_override_me": "from root group_vars",
"overridable_var": "staging from inventories group_vars"
}
},
"db": {
"engine": "postgres"
}
}
}
PLAY RECAP *********************************************************************************************************
app : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
另一个注意事项:请注意,这不允许playbook同时在两个环境中运行,正如使用文档的多个库存源一节下的注意事项所指出的:
请记住,如果库存中存在可变冲突,则根据和中描述的规则解决冲突。合并顺序由库存源参数的顺序控制。如果暂存库存中的[all:vars]
定义了myvar=1
,但生产库存定义了myvar=2
,则将使用myvar=2
运行剧本。如果使用-i production-i staging
运行playbook,则结果将相反
来源:您是否可以选择使用主机变量?
?您可能正在寻找Ansible的和文档。因此,Ansible主张使用,以实现您所寻找的。稍后将添加一个示例。您在服务
中有一个列表而不是dict有什么具体原因吗?即。另外,在环境
之后,您的问题中是否存在缩进问题?i、 e.@souser我认为主机变量
在优先级方面落后于组变量
,因此它无论如何都会被覆盖@β.εηοιτ.βε有问题的固定缩进不幸的是,我无法将服务
更改为dict,因为许多其他剧本都提到了这一点。但是我认为你的回答看起来是实现我想要做的事情的最好方式。如果有一天我有机会修改所有的代码库,我可能会试试这个。谢谢