[英]How to get an Ansible check to run only once in a playbook?
As a safeguard against using an outdated playbook, I'd like to ensure that I have an updated copy of the git checkout before Ansible is allowed to modify anything on the servers.为了防止使用过时的剧本,我想确保在 Ansible 被允许修改服务器上的任何内容之前,我有一个更新的 git checkout 副本。
This is how I've attempted to do it.这就是我尝试这样做的方式。 This action is located in a file included by all play books:
此操作位于所有剧本都包含的文件中:
- name: Ensure local git repository is up-to-date
local_action: git pull
register: command_result
failed_when: "'Updating' in command_result.stdout"
The problem is that this command is run once for each node Ansible connects to, instead of only once for each playbook run.问题是这个命令为 Ansible 连接的每个节点运行一次,而不是每个 playbook 运行只运行一次。 How can I avoid that?
我怎样才能避免这种情况?
When I fist wrote my answer (2014-02-27), Ansible had no built-in support for running a task only once per playbook, not once per affected host that the playbook was run on.当我开始写我的答案 (2014-02-27) 时,Ansible 没有内置支持每个剧本只运行一次任务,而不是每个运行剧本的受影响主机一次。 However, as tlo writes , support for this was introduced with
run_once: true
in Ansible version 1.7.0 (released on 2014-08-06).然而,正如tlo 所写,在 Ansible 1.7.0 版(2014 年 8 月 6 日发布)中通过
run_once: true
引入了run_once: true
支持。 With this feature, the example task definition from the question should be changed to使用此功能,问题中的示例任务定义应更改为
- name: Ensure local git repository is up-to-date
local_action: git pull
run_once: true
register: command_result
failed_when: "'Updating' in command_result.stdout"
to accomplish what is asked for.完成所要求的事情。
[The following answer was my suggested solution for the particular problem of making sure that the local git branch is updated before Ansible runs the tasks of a playbook.] [对于确保在 Ansible 运行剧本任务之前更新本地 git 分支的特定问题,以下答案是我建议的解决方案。]
I wrote the following Ansible callback plugin that will avoid playbook execution if the current git branch is out of sync (is either behind or has diverged) with the remote branch.我编写了以下 Ansible 回调插件,如果当前 git 分支与远程分支不同步(落后于或已经发散),它将避免剧本执行。 To use it, place the following code in a file like
callback_plugins/require_updated_git_branch.py
in your top-level Ansible playbook directory:要使用它,请将以下代码放入顶级 Ansible 剧本目录中的
callback_plugins/require_updated_git_branch.py
文件中:
#! /usr/bin/env python
# -*- coding: utf-8 -*-
import os
import re
import subprocess
import sys
from ansible.callbacks import display, banner
class CallbackModule(object):
"""Makes Ansible require that the current git branch is up to date.
"""
env_var_name = 'IGNORE_OUTDATED_GIT_BRANCH'
msg = 'OUTDATED GIT BRANCH: Your git branch is out of sync with the ' \
'remote branch. Please update your branch (git pull) before ' \
'continuing, or skip this test by setting the environment ' \
'variable {0}=yes.'.format(env_var_name)
out_of_sync_re = re.compile(r'Your branch (is behind|and .* have diverged)',
re.MULTILINE)
def __init__(self, *args, **kwargs):
if os.getenv(self.env_var_name, 'no') == 'yes':
self.disabled = True
def playbook_on_start(self):
subprocess.call(['git', 'fetch'])
if self.out_of_sync_re.search(subprocess.check_output([
'git', 'status', '--untracked-files=no'])):
display(banner(self.msg), color='bright purple')
sys.exit(1)
For example, when the local branch is behind the remote branch, the command ansible-playbook site.yml
halts early with the following output:例如,当本地分支在远程分支后面时,命令
ansible-playbook site.yml
停止并显示以下输出:
__________________________________________________________
/ OUTDATED GIT BRANCH: Your git branch is out of sync with \
| the remote branch. Please update your branch (git pull) |
| before continuing, or skip this test by setting the |
\ environment variable IGNORE_OUTDATED_GIT_BRANCH=yes. /
----------------------------------------------------------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
And, as the cow suggests, to turn off this check you can run the command like:而且,正如牛建议的那样,要关闭此检查,您可以运行以下命令:
$ IGNORE_OUTDATED_GIT_BRANCH=yes ansible-playbook site.yml
This solution does not solve the general problem of avoiding to run any Ansible task more than once regardless of the number of hosts involved, but it ensures that outdated playbooks are not executed, and it handles the concern that you mentioned regarding my alias-based suggestion .此解决方案不能解决避免多次运行任何 Ansible 任务而不管所涉及的主机数量如何的一般问题,但它确保不执行过时的剧本,并且它处理了您提到的关于我的基于别名的建议的问题.
从 Ansible 1.7 版开始,您可以使用run_once: true
仅在一台主机上运行一次任务。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.