Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
A
ansible
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
OpenEdx
ansible
Commits
157b697a
Commit
157b697a
authored
Aug 22, 2013
by
James Cammarata
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'always_run-6' of
https://github.com/stoned/ansible
into stoned-always_run-6
parents
abac7202
f0743fc3
Show whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
136 additions
and
13 deletions
+136
-13
docsite/latest/rst/playbooks2.rst
+23
-0
lib/ansible/playbook/task.py
+6
-3
lib/ansible/runner/__init__.py
+15
-0
lib/ansible/runner/action_plugins/add_host.py
+1
-1
lib/ansible/runner/action_plugins/async.py
+1
-1
lib/ansible/runner/action_plugins/copy.py
+2
-2
lib/ansible/runner/action_plugins/fetch.py
+1
-1
lib/ansible/runner/action_plugins/normal.py
+1
-1
lib/ansible/runner/action_plugins/raw.py
+1
-1
lib/ansible/runner/action_plugins/script.py
+1
-1
lib/ansible/runner/action_plugins/template.py
+1
-1
lib/ansible/utils/__init__.py
+4
-1
test/TestPlayBook.py
+31
-0
test/playbook-always-run.yml
+48
-0
No files found.
docsite/latest/rst/playbooks2.rst
View file @
157b697a
...
@@ -1060,6 +1060,29 @@ Example::
...
@@ -1060,6 +1060,29 @@ Example::
ansible-playbook foo.yml --check
ansible-playbook foo.yml --check
Running a task in check mode
````````````````````````````
.. versionadded:: 1.3
Sometimes you may want to have a task to be executed even in check
mode. To achieve this use the `always_run` clause on the task. Its
value is a Python expression, just like the `when` clause. In simple
cases a boolean YAML value would be sufficient as a value.
Example::
tasks:
- name: this task is run even in check mode
command: /something/to/run --even-in-check-mode
always_run: yes
As a reminder, a task with a `when` clause evaluated to false, will
still be skipped even if it has a `always_run` clause evaluated to
true.
Showing Differences with --diff
Showing Differences with --diff
```````````````````````````````
```````````````````````````````
...
...
lib/ansible/playbook/task.py
View file @
157b697a
...
@@ -29,7 +29,7 @@ class Task(object):
...
@@ -29,7 +29,7 @@ class Task(object):
'delegate_to'
,
'first_available_file'
,
'ignore_errors'
,
'delegate_to'
,
'first_available_file'
,
'ignore_errors'
,
'local_action'
,
'transport'
,
'sudo'
,
'sudo_user'
,
'sudo_pass'
,
'local_action'
,
'transport'
,
'sudo'
,
'sudo_user'
,
'sudo_pass'
,
'items_lookup_plugin'
,
'items_lookup_terms'
,
'environment'
,
'args'
,
'items_lookup_plugin'
,
'items_lookup_terms'
,
'environment'
,
'args'
,
'any_errors_fatal'
,
'changed_when'
'any_errors_fatal'
,
'changed_when'
,
'always_run'
]
]
# to prevent typos and such
# to prevent typos and such
...
@@ -38,7 +38,7 @@ class Task(object):
...
@@ -38,7 +38,7 @@ class Task(object):
'first_available_file'
,
'include'
,
'tags'
,
'register'
,
'ignore_errors'
,
'first_available_file'
,
'include'
,
'tags'
,
'register'
,
'ignore_errors'
,
'delegate_to'
,
'local_action'
,
'transport'
,
'sudo'
,
'sudo_user'
,
'delegate_to'
,
'local_action'
,
'transport'
,
'sudo'
,
'sudo_user'
,
'sudo_pass'
,
'when'
,
'connection'
,
'environment'
,
'args'
,
'sudo_pass'
,
'when'
,
'connection'
,
'environment'
,
'args'
,
'any_errors_fatal'
,
'changed_when'
'any_errors_fatal'
,
'changed_when'
,
'always_run'
]
]
def
__init__
(
self
,
play
,
ds
,
module_vars
=
None
,
additional_conditions
=
None
):
def
__init__
(
self
,
play
,
ds
,
module_vars
=
None
,
additional_conditions
=
None
):
...
@@ -178,6 +178,8 @@ class Task(object):
...
@@ -178,6 +178,8 @@ class Task(object):
self
.
ignore_errors
=
ds
.
get
(
'ignore_errors'
,
False
)
self
.
ignore_errors
=
ds
.
get
(
'ignore_errors'
,
False
)
self
.
any_errors_fatal
=
ds
.
get
(
'any_errors_fatal'
,
play
.
any_errors_fatal
)
self
.
any_errors_fatal
=
ds
.
get
(
'any_errors_fatal'
,
play
.
any_errors_fatal
)
self
.
always_run
=
ds
.
get
(
'always_run'
,
False
)
# action should be a string
# action should be a string
if
not
isinstance
(
self
.
action
,
basestring
):
if
not
isinstance
(
self
.
action
,
basestring
):
raise
errors
.
AnsibleError
(
"action is of type '
%
s' and not a string in task. name:
%
s"
%
(
type
(
self
.
action
)
.
__name__
,
self
.
name
))
raise
errors
.
AnsibleError
(
"action is of type '
%
s' and not a string in task. name:
%
s"
%
(
type
(
self
.
action
)
.
__name__
,
self
.
name
))
...
@@ -216,10 +218,11 @@ class Task(object):
...
@@ -216,10 +218,11 @@ class Task(object):
# allow runner to see delegate_to option
# allow runner to see delegate_to option
self
.
module_vars
[
'delegate_to'
]
=
self
.
delegate_to
self
.
module_vars
[
'delegate_to'
]
=
self
.
delegate_to
# make
ignore_errors accessa
ble to Runner code
# make
some task attributes accessi
ble to Runner code
self
.
module_vars
[
'ignore_errors'
]
=
self
.
ignore_errors
self
.
module_vars
[
'ignore_errors'
]
=
self
.
ignore_errors
self
.
module_vars
[
'register'
]
=
self
.
register
self
.
module_vars
[
'register'
]
=
self
.
register
self
.
module_vars
[
'changed_when'
]
=
self
.
changed_when
self
.
module_vars
[
'changed_when'
]
=
self
.
changed_when
self
.
module_vars
[
'always_run'
]
=
self
.
always_run
# tags allow certain parts of a playbook to be run without running the whole playbook
# tags allow certain parts of a playbook to be run without running the whole playbook
apply_tags
=
ds
.
get
(
'tags'
,
None
)
apply_tags
=
ds
.
get
(
'tags'
,
None
)
...
...
lib/ansible/runner/__init__.py
View file @
157b697a
...
@@ -37,6 +37,7 @@ import ansible.constants as C
...
@@ -37,6 +37,7 @@ import ansible.constants as C
import
ansible.inventory
import
ansible.inventory
from
ansible
import
utils
from
ansible
import
utils
from
ansible.utils
import
template
from
ansible.utils
import
template
from
ansible.utils
import
check_conditional
from
ansible
import
errors
from
ansible
import
errors
from
ansible
import
module_common
from
ansible
import
module_common
import
poller
import
poller
...
@@ -156,6 +157,7 @@ class Runner(object):
...
@@ -156,6 +157,7 @@ class Runner(object):
self
.
inventory
=
utils
.
default
(
inventory
,
lambda
:
ansible
.
inventory
.
Inventory
(
host_list
))
self
.
inventory
=
utils
.
default
(
inventory
,
lambda
:
ansible
.
inventory
.
Inventory
(
host_list
))
self
.
module_vars
=
utils
.
default
(
module_vars
,
lambda
:
{})
self
.
module_vars
=
utils
.
default
(
module_vars
,
lambda
:
{})
self
.
always_run
=
None
self
.
connector
=
connection
.
Connection
(
self
)
self
.
connector
=
connection
.
Connection
(
self
)
self
.
conditional
=
conditional
self
.
conditional
=
conditional
self
.
module_name
=
module_name
self
.
module_name
=
module_name
...
@@ -941,3 +943,16 @@ class Runner(object):
...
@@ -941,3 +943,16 @@ class Runner(object):
self
.
background
=
time_limit
self
.
background
=
time_limit
results
=
self
.
run
()
results
=
self
.
run
()
return
results
,
poller
.
AsyncPoller
(
results
,
self
)
return
results
,
poller
.
AsyncPoller
(
results
,
self
)
# *****************************************************
def
noop_on_check
(
self
,
inject
):
''' Should the runner run in check mode or not ? '''
# initialize self.always_run on first call
if
self
.
always_run
is
None
:
self
.
always_run
=
self
.
module_vars
.
get
(
'always_run'
,
False
)
self
.
always_run
=
check_conditional
(
self
.
always_run
,
self
.
basedir
,
inject
,
fail_on_undefined
=
True
,
jinja2
=
True
)
return
(
self
.
check
and
not
self
.
always_run
)
lib/ansible/runner/action_plugins/add_host.py
View file @
157b697a
...
@@ -36,7 +36,7 @@ class ActionModule(object):
...
@@ -36,7 +36,7 @@ class ActionModule(object):
def
run
(
self
,
conn
,
tmp
,
module_name
,
module_args
,
inject
,
complex_args
=
None
,
**
kwargs
):
def
run
(
self
,
conn
,
tmp
,
module_name
,
module_args
,
inject
,
complex_args
=
None
,
**
kwargs
):
if
self
.
runner
.
check
:
if
self
.
runner
.
noop_on_check
(
inject
)
:
return
ReturnData
(
conn
=
conn
,
comm_ok
=
True
,
result
=
dict
(
skipped
=
True
,
msg
=
'check mode not supported for this module'
))
return
ReturnData
(
conn
=
conn
,
comm_ok
=
True
,
result
=
dict
(
skipped
=
True
,
msg
=
'check mode not supported for this module'
))
args
=
{}
args
=
{}
...
...
lib/ansible/runner/action_plugins/async.py
View file @
157b697a
...
@@ -25,7 +25,7 @@ class ActionModule(object):
...
@@ -25,7 +25,7 @@ class ActionModule(object):
def
run
(
self
,
conn
,
tmp
,
module_name
,
module_args
,
inject
,
complex_args
=
None
,
**
kwargs
):
def
run
(
self
,
conn
,
tmp
,
module_name
,
module_args
,
inject
,
complex_args
=
None
,
**
kwargs
):
''' transfer the given module name, plus the async module, then run it '''
''' transfer the given module name, plus the async module, then run it '''
if
self
.
runner
.
check
:
if
self
.
runner
.
noop_on_check
(
inject
)
:
return
ReturnData
(
conn
=
conn
,
comm_ok
=
True
,
result
=
dict
(
skipped
=
True
,
msg
=
'check mode not supported for this module'
))
return
ReturnData
(
conn
=
conn
,
comm_ok
=
True
,
result
=
dict
(
skipped
=
True
,
msg
=
'check mode not supported for this module'
))
# shell and command module are the same
# shell and command module are the same
...
...
lib/ansible/runner/action_plugins/copy.py
View file @
157b697a
...
@@ -126,7 +126,7 @@ class ActionModule(object):
...
@@ -126,7 +126,7 @@ class ActionModule(object):
else
:
else
:
diff
=
{}
diff
=
{}
if
self
.
runner
.
check
:
if
self
.
runner
.
noop_on_check
(
inject
)
:
if
content
is
not
None
:
if
content
is
not
None
:
os
.
remove
(
tmp_content
)
os
.
remove
(
tmp_content
)
return
ReturnData
(
conn
=
conn
,
result
=
dict
(
changed
=
True
),
diff
=
diff
)
return
ReturnData
(
conn
=
conn
,
result
=
dict
(
changed
=
True
),
diff
=
diff
)
...
@@ -172,7 +172,7 @@ class ActionModule(object):
...
@@ -172,7 +172,7 @@ class ActionModule(object):
# don't send down raw=no
# don't send down raw=no
module_args
.
pop
(
'raw'
)
module_args
.
pop
(
'raw'
)
module_args
=
"
%
s src=
%
s"
%
(
module_args
,
pipes
.
quote
(
tmp_src
))
module_args
=
"
%
s src=
%
s"
%
(
module_args
,
pipes
.
quote
(
tmp_src
))
if
self
.
runner
.
check
:
if
self
.
runner
.
noop_on_check
(
inject
)
:
module_args
=
"
%
s CHECKMODE=True"
%
module_args
module_args
=
"
%
s CHECKMODE=True"
%
module_args
return
self
.
runner
.
_execute_module
(
conn
,
tmp
,
'file'
,
module_args
,
inject
=
inject
,
complex_args
=
complex_args
)
return
self
.
runner
.
_execute_module
(
conn
,
tmp
,
'file'
,
module_args
,
inject
=
inject
,
complex_args
=
complex_args
)
...
...
lib/ansible/runner/action_plugins/fetch.py
View file @
157b697a
...
@@ -36,7 +36,7 @@ class ActionModule(object):
...
@@ -36,7 +36,7 @@ class ActionModule(object):
def
run
(
self
,
conn
,
tmp
,
module_name
,
module_args
,
inject
,
complex_args
=
None
,
**
kwargs
):
def
run
(
self
,
conn
,
tmp
,
module_name
,
module_args
,
inject
,
complex_args
=
None
,
**
kwargs
):
''' handler for fetch operations '''
''' handler for fetch operations '''
if
self
.
runner
.
check
:
if
self
.
runner
.
noop_on_check
(
inject
)
:
return
ReturnData
(
conn
=
conn
,
comm_ok
=
True
,
result
=
dict
(
skipped
=
True
,
msg
=
'check mode not (yet) supported for this module'
))
return
ReturnData
(
conn
=
conn
,
comm_ok
=
True
,
result
=
dict
(
skipped
=
True
,
msg
=
'check mode not (yet) supported for this module'
))
# load up options
# load up options
...
...
lib/ansible/runner/action_plugins/normal.py
View file @
157b697a
...
@@ -38,7 +38,7 @@ class ActionModule(object):
...
@@ -38,7 +38,7 @@ class ActionModule(object):
module_args
=
self
.
runner
.
_complex_args_hack
(
complex_args
,
module_args
)
module_args
=
self
.
runner
.
_complex_args_hack
(
complex_args
,
module_args
)
if
self
.
runner
.
check
:
if
self
.
runner
.
noop_on_check
(
inject
)
:
if
module_name
in
[
'shell'
,
'command'
]:
if
module_name
in
[
'shell'
,
'command'
]:
return
ReturnData
(
conn
=
conn
,
comm_ok
=
True
,
result
=
dict
(
skipped
=
True
,
msg
=
'check mode not supported for
%
s'
%
module_name
))
return
ReturnData
(
conn
=
conn
,
comm_ok
=
True
,
result
=
dict
(
skipped
=
True
,
msg
=
'check mode not supported for
%
s'
%
module_name
))
# else let the module parsing code decide, though this will only be allowed for AnsibleModuleCommon using
# else let the module parsing code decide, though this will only be allowed for AnsibleModuleCommon using
...
...
lib/ansible/runner/action_plugins/raw.py
View file @
157b697a
...
@@ -30,7 +30,7 @@ class ActionModule(object):
...
@@ -30,7 +30,7 @@ class ActionModule(object):
def
run
(
self
,
conn
,
tmp
,
module_name
,
module_args
,
inject
,
complex_args
=
None
,
**
kwargs
):
def
run
(
self
,
conn
,
tmp
,
module_name
,
module_args
,
inject
,
complex_args
=
None
,
**
kwargs
):
if
self
.
runner
.
check
:
if
self
.
runner
.
noop_on_check
(
inject
)
:
# in --check mode, always skip this module execution
# in --check mode, always skip this module execution
return
ReturnData
(
conn
=
conn
,
comm_ok
=
True
,
result
=
dict
(
skipped
=
True
))
return
ReturnData
(
conn
=
conn
,
comm_ok
=
True
,
result
=
dict
(
skipped
=
True
))
...
...
lib/ansible/runner/action_plugins/script.py
View file @
157b697a
...
@@ -32,7 +32,7 @@ class ActionModule(object):
...
@@ -32,7 +32,7 @@ class ActionModule(object):
def
run
(
self
,
conn
,
tmp
,
module_name
,
module_args
,
inject
,
complex_args
=
None
,
**
kwargs
):
def
run
(
self
,
conn
,
tmp
,
module_name
,
module_args
,
inject
,
complex_args
=
None
,
**
kwargs
):
''' handler for file transfer operations '''
''' handler for file transfer operations '''
if
self
.
runner
.
check
:
if
self
.
runner
.
noop_on_check
(
inject
)
:
# in check mode, always skip this module
# in check mode, always skip this module
return
ReturnData
(
conn
=
conn
,
comm_ok
=
True
,
result
=
dict
(
skipped
=
True
,
msg
=
'check mode not supported for this module'
))
return
ReturnData
(
conn
=
conn
,
comm_ok
=
True
,
result
=
dict
(
skipped
=
True
,
msg
=
'check mode not supported for this module'
))
...
...
lib/ansible/runner/action_plugins/template.py
View file @
157b697a
...
@@ -117,7 +117,7 @@ class ActionModule(object):
...
@@ -117,7 +117,7 @@ class ActionModule(object):
# run the copy module
# run the copy module
module_args
=
"
%
s src=
%
s dest=
%
s original_basename=
%
s"
%
(
module_args
,
pipes
.
quote
(
xfered
),
pipes
.
quote
(
dest
),
pipes
.
quote
(
os
.
path
.
basename
(
source
)))
module_args
=
"
%
s src=
%
s dest=
%
s original_basename=
%
s"
%
(
module_args
,
pipes
.
quote
(
xfered
),
pipes
.
quote
(
dest
),
pipes
.
quote
(
os
.
path
.
basename
(
source
)))
if
self
.
runner
.
check
:
if
self
.
runner
.
noop_on_check
(
inject
)
:
return
ReturnData
(
conn
=
conn
,
comm_ok
=
True
,
result
=
dict
(
changed
=
True
),
diff
=
dict
(
before_header
=
dest
,
after_header
=
source
,
before
=
dest_contents
,
after
=
resultant
))
return
ReturnData
(
conn
=
conn
,
comm_ok
=
True
,
result
=
dict
(
changed
=
True
),
diff
=
dict
(
before_header
=
dest
,
after_header
=
source
,
before
=
dest_contents
,
after
=
resultant
))
else
:
else
:
res
=
self
.
runner
.
_execute_module
(
conn
,
tmp
,
'copy'
,
module_args
,
inject
=
inject
,
complex_args
=
complex_args
)
res
=
self
.
runner
.
_execute_module
(
conn
,
tmp
,
'copy'
,
module_args
,
inject
=
inject
,
complex_args
=
complex_args
)
...
...
lib/ansible/utils/__init__.py
View file @
157b697a
...
@@ -155,7 +155,10 @@ def is_changed(result):
...
@@ -155,7 +155,10 @@ def is_changed(result):
return
(
result
.
get
(
'changed'
,
False
)
in
[
True
,
'True'
,
'true'
])
return
(
result
.
get
(
'changed'
,
False
)
in
[
True
,
'True'
,
'true'
])
def
check_conditional
(
conditional
,
basedir
,
inject
,
fail_on_undefined
=
False
):
def
check_conditional
(
conditional
,
basedir
,
inject
,
fail_on_undefined
=
False
,
jinja2
=
False
):
if
jinja2
:
conditional
=
"jinja2_compare
%
s"
%
conditional
if
conditional
.
startswith
(
"jinja2_compare"
):
if
conditional
.
startswith
(
"jinja2_compare"
):
conditional
=
conditional
.
replace
(
"jinja2_compare "
,
""
)
conditional
=
conditional
.
replace
(
"jinja2_compare "
,
""
)
...
...
test/TestPlayBook.py
View file @
157b697a
...
@@ -474,6 +474,37 @@ class TestPlaybook(unittest.TestCase):
...
@@ -474,6 +474,37 @@ class TestPlaybook(unittest.TestCase):
assert
utils
.
jsonify
(
expected
,
format
=
True
)
==
utils
.
jsonify
(
actual
,
format
=
True
)
assert
utils
.
jsonify
(
expected
,
format
=
True
)
==
utils
.
jsonify
(
actual
,
format
=
True
)
def
test_playbook_always_run
(
self
):
test_callbacks
=
TestCallbacks
()
playbook
=
ansible
.
playbook
.
PlayBook
(
playbook
=
os
.
path
.
join
(
self
.
test_dir
,
'playbook-always-run.yml'
),
host_list
=
'test/ansible_hosts'
,
stats
=
ans_callbacks
.
AggregateStats
(),
callbacks
=
test_callbacks
,
runner_callbacks
=
test_callbacks
,
check
=
True
)
actual
=
playbook
.
run
()
# if different, this will output to screen
print
"**ACTUAL**"
print
utils
.
jsonify
(
actual
,
format
=
True
)
expected
=
{
"localhost"
:
{
"changed"
:
4
,
"failures"
:
0
,
"ok"
:
4
,
"skipped"
:
8
,
"unreachable"
:
0
}
}
print
"**EXPECTED**"
print
utils
.
jsonify
(
expected
,
format
=
True
)
assert
utils
.
jsonify
(
expected
,
format
=
True
)
==
utils
.
jsonify
(
actual
,
format
=
True
)
def
_compare_file_output
(
self
,
filename
,
expected_lines
):
def
_compare_file_output
(
self
,
filename
,
expected_lines
):
actual_lines
=
[]
actual_lines
=
[]
with
open
(
filename
)
as
f
:
with
open
(
filename
)
as
f
:
...
...
test/playbook-always-run.yml
0 → 100644
View file @
157b697a
---
-
hosts
:
all
connection
:
local
gather_facts
:
False
vars
:
var_true
:
True
var_false
:
False
var_empty_str
:
"
''"
var_null
:
~
tasks
:
-
action
:
command echo ping
always_run
:
yes
-
action
:
command echo pong 1
-
action
:
command echo pong 2
always_run
:
no
-
action
:
command echo pong 3
always_run
:
1 + 1
-
action
:
command echo pong 4
always_run
:
"
''"
-
action
:
command echo pong 5
always_run
:
False
-
action
:
command echo pong 6
always_run
:
True
-
action
:
command echo pong 7
always_run
:
var_true
-
action
:
command echo pong 8
always_run
:
var_false
-
action
:
command echo pong 9
always_run
:
var_empty_str
-
action
:
command echo pong 10
always_run
:
var_null
# this will never run...
-
action
:
command echo pong 11
always_run
:
yes
when
:
no
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment