是否有一种紧凑的方法来检查是否安装了某些东西,必要时进行安装然后再次检查?目前我有这个冗长的混乱:
- name: check whether X is installed.
shell: is_installed >/dev/null || echo nope
register: thing_is_installed
- name: install something
shell: install_thing
when: thing_is_installed=="nope"
- name: check that the install succeeded
shell: is_installed
对于任意函数install_thing
和is_installed
?最大的问题是is_installed发生了两次,所以由于疏忽,疏忽或任何其他原因,有人会修改一个函数调用但不修改另一个函数调用。壳只是一个例子。您可能会认识到这种模式 - 它是idenpotent构建函数的核心构建块。 is_installed
定义了所需的状态,install_thing
定义了如何进入所需的状态。我希望有一个看起来像这样的表单,我无法找到它:
- name: Install boondoggle
shell:
check: is_installed
install: install_thing
或者这个,它的优点是它可以用于任何数量的测试,而不仅仅是shell:
- name: Install bongle
check:
shell: is_installed
install:
shell: install_thing
答案 0 :(得分:2)
如果您要使用许多预先存在的shell脚本,那么您的选项是有限的。特别是如果参数和返回值不一致。
在Ansible中使用shell模块是最后的选择。有时您必须使用它,但首先考虑“package”和“pip”之类的模块。同时检查ansible-galaxy以获取可能满足您需求的完整角色。尝试完成这一切很容易,但有时候工作已经由其他人完成,即使它只是你需要的50%。那还有时间。
使用shell选项,有一个“creates”选项。这将检查已知由shell脚本创建的文件的存在,并可用于代替“check” - > 'do' - >在某些情况下'检查'。该文档还提供了有用的test strategies的更多详细信息。显然这一切都取决于您的特殊需求。
如果shell脚本是统一的,另一个替代方法是write your own包装模块。有了一点蟒蛇知识,这很容易做到。再一次,可以找到open source examples并从一个类似于你需要的东西开始工作,而不是从头开始。模块的内部过程仍需要进行检查 - >修复 - >检查,但在Ansible剧本中,代码将非常整洁并避免重新定位。
答案 1 :(得分:1)
缺少noop模式(即,您报告失败但不的模式,如果您还没有达到预期,请执行任何安装你也可以将两者结合起来。我倾向于使用类似于以下的模式:
- name: "enforce-foo"
command: /path/to/enforce-foo-script
register: enforce_foo
failed_when: "(enforce_foo.rc != 0) and (enforce_foo.rc != 2)"
changed_when: "enforce_foo.rc != 2"
...在这里,我们使用退出状态0来表示我们退出而无需执行任何操作,并退出状态2以指示我们进行了更改。