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
1ecf4a69
Commit
1ecf4a69
authored
Feb 17, 2013
by
Michael DeHaan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Working on complex argument support.
parent
5a918739
Hide whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
85 additions
and
27 deletions
+85
-27
lib/ansible/module_common.py
+5
-1
lib/ansible/playbook/__init__.py
+1
-1
lib/ansible/playbook/task.py
+6
-2
lib/ansible/runner/__init__.py
+48
-8
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
+1
-1
lib/ansible/runner/action_plugins/debug.py
+1
-1
lib/ansible/runner/action_plugins/fail.py
+1
-1
lib/ansible/runner/action_plugins/fetch.py
+1
-1
lib/ansible/runner/action_plugins/group_by.py
+1
-1
lib/ansible/runner/action_plugins/normal.py
+5
-2
lib/ansible/runner/action_plugins/pause.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
+2
-0
library/ping
+7
-2
No files found.
lib/ansible/module_common.py
View file @
1ecf4a69
...
...
@@ -18,6 +18,7 @@
REPLACER
=
"#<<INCLUDE_ANSIBLE_MODULE_COMMON>>"
REPLACER_ARGS
=
"<<INCLUDE_ANSIBLE_MODULE_ARGS>>"
REPLACER_LANG
=
"<<INCLUDE_ANSIBLE_MODULE_LANG>>"
REPLACER_COMPLEX
=
"<<INCLUDE_ANSIBLE_MODULE_COMPLEX_ARGS>>"
MODULE_COMMON
=
"""
...
...
@@ -25,6 +26,7 @@ MODULE_COMMON = """
MODULE_ARGS = <<INCLUDE_ANSIBLE_MODULE_ARGS>>
MODULE_LANG = <<INCLUDE_ANSIBLE_MODULE_LANG>>
MODULE_COMPLEX_ARGS = <<INCLUDE_ANSIBLE_MODULE_COMPLEX_ARGS>>
BOOLEANS_TRUE = ['yes', 'on', '1', 'true', 1]
BOOLEANS_FALSE = ['no', 'off', '0', 'false', 0]
...
...
@@ -559,7 +561,9 @@ class AnsibleModule(object):
except:
self.fail_json(msg="this module requires key=value arguments")
params[k] = v
return (params, args)
params2 = json.loads(MODULE_COMPLEX_ARGS)
params2.update(params)
return (params2, args)
def _log_invocation(self):
''' log that ansible ran the module '''
...
...
lib/ansible/playbook/__init__.py
View file @
1ecf4a69
...
...
@@ -273,7 +273,7 @@ class PlayBook(object):
conditional
=
task
.
only_if
,
callbacks
=
self
.
runner_callbacks
,
sudo
=
task
.
sudo
,
sudo_user
=
task
.
sudo_user
,
transport
=
task
.
transport
,
sudo_pass
=
task
.
sudo_pass
,
is_playbook
=
True
,
check
=
self
.
check
,
diff
=
self
.
diff
,
environment
=
task
.
environment
check
=
self
.
check
,
diff
=
self
.
diff
,
environment
=
task
.
environment
,
complex_args
=
task
.
args
)
if
task
.
async_seconds
==
0
:
...
...
lib/ansible/playbook/task.py
View file @
1ecf4a69
...
...
@@ -27,7 +27,7 @@ class Task(object):
'play'
,
'notified_by'
,
'tags'
,
'register'
,
'delegate_to'
,
'first_available_file'
,
'ignore_errors'
,
'local_action'
,
'transport'
,
'sudo'
,
'sudo_user'
,
'sudo_pass'
,
'items_lookup_plugin'
,
'items_lookup_terms'
,
'environment'
'items_lookup_plugin'
,
'items_lookup_terms'
,
'environment'
,
'args'
]
# to prevent typos and such
...
...
@@ -35,7 +35,7 @@ class Task(object):
'name'
,
'action'
,
'only_if'
,
'async'
,
'poll'
,
'notify'
,
'first_available_file'
,
'include'
,
'tags'
,
'register'
,
'ignore_errors'
,
'delegate_to'
,
'local_action'
,
'transport'
,
'sudo'
,
'sudo_user'
,
'sudo_pass'
,
'when'
,
'connection'
,
'environment'
'sudo_pass'
,
'when'
,
'connection'
,
'environment'
,
'args'
]
def
__init__
(
self
,
play
,
ds
,
module_vars
=
None
,
additional_conditions
=
None
):
...
...
@@ -82,6 +82,10 @@ class Task(object):
self
.
sudo
=
utils
.
boolean
(
ds
.
get
(
'sudo'
,
play
.
sudo
))
self
.
environment
=
ds
.
get
(
'environment'
,
{})
# rather than simple key=value args on the options line, these represent structured data and the values
# can be hashes and lists, not just scalars
self
.
args
=
ds
.
get
(
'args'
,
{})
if
self
.
sudo
:
self
.
sudo_user
=
ds
.
get
(
'sudo_user'
,
play
.
sudo_user
)
self
.
sudo_pass
=
ds
.
get
(
'sudo_pass'
,
play
.
playbook
.
sudo_pass
)
...
...
lib/ansible/runner/__init__.py
View file @
1ecf4a69
...
...
@@ -29,6 +29,7 @@ import socket
import
base64
import
sys
import
shlex
import
pipes
import
ansible.constants
as
C
import
ansible.inventory
...
...
@@ -120,9 +121,13 @@ class Runner(object):
subset
=
None
,
# subset pattern
check
=
False
,
# don't make any changes, just try to probe for potential changes
diff
=
False
,
# whether to show diffs for template files that change
environment
=
None
# environment variables (as dict) to use inside the command
environment
=
None
,
# environment variables (as dict) to use inside the command
complex_args
=
None
# structured data in addition to module_args, must be a dict
):
if
not
complex_args
:
complex_args
=
{}
# storage & defaults
self
.
check
=
check
self
.
diff
=
diff
...
...
@@ -151,6 +156,7 @@ class Runner(object):
self
.
sudo_pass
=
sudo_pass
self
.
is_playbook
=
is_playbook
self
.
environment
=
environment
self
.
complex_args
=
complex_args
# misc housekeeping
if
subset
and
self
.
inventory
.
_subset
is
None
:
...
...
@@ -168,6 +174,27 @@ class Runner(object):
# ensure we are using unique tmp paths
random
.
seed
()
# *****************************************************
def
_complex_args_hack
(
self
,
complex_args
,
module_args
):
"""
ansible-playbook both allows specifying key=value string arguments and complex arguments
however not all modules use our python common module system and cannot
access these. An example might be a Bash module. This hack allows users to still pass "args"
as a hash of simple scalars to those arguments and is short term. We could technically
just feed JSON to the module, but that makes it hard on Bash consumers. The way this is implemented
it does mean values in 'args' have LOWER priority than those on the key=value line, allowing
args to provide yet another way to have pluggable defaults.
"""
if
complex_args
is
None
:
return
module_args
if
type
(
complex_args
)
!=
dict
:
raise
errors
.
AnsibleError
(
"complex arguments are not a dictionary:
%
s"
%
complex_args
)
for
(
k
,
v
)
in
complex_args
.
iteritems
():
if
isinstance
(
v
,
basestring
):
module_args
=
"
%
s=
%
s
%
s"
%
(
k
,
pipes
.
quote
(
v
),
module_args
)
return
module_args
# *****************************************************
...
...
@@ -212,7 +239,7 @@ class Runner(object):
# *****************************************************
def
_execute_module
(
self
,
conn
,
tmp
,
module_name
,
args
,
async_jid
=
None
,
async_module
=
None
,
async_limit
=
None
,
inject
=
None
,
persist_files
=
False
):
async_jid
=
None
,
async_module
=
None
,
async_limit
=
None
,
inject
=
None
,
persist_files
=
False
,
complex_args
=
None
):
''' runs a module that has already been transferred '''
...
...
@@ -222,7 +249,7 @@ class Runner(object):
if
'port'
not
in
args
:
args
+=
" port=
%
s"
%
C
.
ZEROMQ_PORT
(
remote_module_path
,
is_new_style
,
shebang
)
=
self
.
_copy_module
(
conn
,
tmp
,
module_name
,
args
,
inject
)
(
remote_module_path
,
is_new_style
,
shebang
)
=
self
.
_copy_module
(
conn
,
tmp
,
module_name
,
args
,
inject
,
complex_args
)
environment_string
=
self
.
_compute_environment_string
(
inject
)
...
...
@@ -364,6 +391,7 @@ class Runner(object):
def
_executor_internal_inner
(
self
,
host
,
module_name
,
module_args
,
inject
,
port
,
is_chained
=
False
):
''' decides how to invoke a module '''
# allow module args to work as a dictionary
# though it is usually a string
new_args
=
""
...
...
@@ -374,6 +402,7 @@ class Runner(object):
module_name
=
utils
.
template
(
self
.
basedir
,
module_name
,
inject
)
module_args
=
utils
.
template
(
self
.
basedir
,
module_args
,
inject
)
if
module_name
in
utils
.
plugins
.
action_loader
:
if
self
.
background
!=
0
:
...
...
@@ -448,8 +477,8 @@ class Runner(object):
# all modules get a tempdir, action plugins get one unless they have NEEDS_TMPPATH set to False
if
getattr
(
handler
,
'NEEDS_TMPPATH'
,
True
):
tmp
=
self
.
_make_tmp_path
(
conn
)
result
=
handler
.
run
(
conn
,
tmp
,
module_name
,
module_args
,
inject
)
result
=
handler
.
run
(
conn
,
tmp
,
module_name
,
module_args
,
inject
,
self
.
complex_args
)
conn
.
close
()
...
...
@@ -558,9 +587,11 @@ class Runner(object):
# *****************************************************
def
_copy_module
(
self
,
conn
,
tmp
,
module_name
,
module_args
,
inject
):
def
_copy_module
(
self
,
conn
,
tmp
,
module_name
,
module_args
,
inject
,
complex_args
=
None
):
''' transfer a module over SFTP, does not run it '''
# FIXME if complex args is none, set to {}
if
module_name
.
startswith
(
"/"
):
raise
errors
.
AnsibleFileNotFound
(
"
%
s is not a module"
%
module_name
)
...
...
@@ -578,11 +609,17 @@ class Runner(object):
module_data
=
f
.
read
()
if
module_common
.
REPLACER
in
module_data
:
is_new_style
=
True
module_data
=
module_data
.
replace
(
module_common
.
REPLACER
,
module_common
.
MODULE_COMMON
)
complex_args_json
=
utils
.
jsonify
(
complex_args
)
encoded_args
=
"
\"\"\"
%
s
\"\"\"
"
%
module_args
.
replace
(
"
\"
"
,
"
\\\"
"
)
module_data
=
module_data
.
replace
(
module_common
.
REPLACER_ARGS
,
encoded_args
)
encoded_lang
=
"
\"\"\"
%
s
\"\"\"
"
%
C
.
DEFAULT_MODULE_LANG
encoded_complex
=
"
\"\"\"
%
s
\"\"\"
"
%
complex_args_json
module_data
=
module_data
.
replace
(
module_common
.
REPLACER
,
module_common
.
MODULE_COMMON
)
module_data
=
module_data
.
replace
(
module_common
.
REPLACER_ARGS
,
encoded_args
)
module_data
=
module_data
.
replace
(
module_common
.
REPLACER_LANG
,
encoded_lang
)
module_data
=
module_data
.
replace
(
module_common
.
REPLACER_COMPLEX
,
encoded_complex
)
if
is_new_style
:
facility
=
C
.
DEFAULT_SYSLOG_FACILITY
if
'ansible_syslog_facility'
in
inject
:
...
...
@@ -684,7 +721,9 @@ class Runner(object):
# run once per hostgroup, rather than pausing once per each
# host.
p
=
utils
.
plugins
.
action_loader
.
get
(
self
.
module_name
,
self
)
if
p
and
getattr
(
p
,
'BYPASS_HOST_LOOP'
,
None
):
# Expose the current hostgroup to the bypassing plugins
self
.
host_set
=
hosts
# We aren't iterating over all the hosts in this
...
...
@@ -697,6 +736,7 @@ class Runner(object):
results
=
[
ReturnData
(
host
=
h
,
result
=
result_data
,
comm_ok
=
True
)
\
for
h
in
hosts
]
del
self
.
host_set
elif
self
.
forks
>
1
:
try
:
results
=
self
.
_parallel_exec
(
hosts
)
...
...
lib/ansible/runner/action_plugins/add_host.py
View file @
1ecf4a69
...
...
@@ -34,7 +34,7 @@ class ActionModule(object):
def
__init__
(
self
,
runner
):
self
.
runner
=
runner
def
run
(
self
,
conn
,
tmp
,
module_name
,
module_args
,
inject
):
def
run
(
self
,
conn
,
tmp
,
module_name
,
module_args
,
inject
,
complex_args
=
None
,
**
kwargs
)
if
self
.
runner
.
check
:
return
ReturnData
(
conn
=
conn
,
comm_ok
=
True
,
result
=
dict
(
skipped
=
True
,
msg
=
'check mode not supported for this module'
))
...
...
lib/ansible/runner/action_plugins/async.py
View file @
1ecf4a69
...
...
@@ -22,7 +22,7 @@ class ActionModule(object):
def
__init__
(
self
,
runner
):
self
.
runner
=
runner
def
run
(
self
,
conn
,
tmp
,
module_name
,
module_args
,
inject
):
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 '''
if
self
.
runner
.
check
:
...
...
lib/ansible/runner/action_plugins/copy.py
View file @
1ecf4a69
...
...
@@ -26,7 +26,7 @@ class ActionModule(object):
def
__init__
(
self
,
runner
):
self
.
runner
=
runner
def
run
(
self
,
conn
,
tmp
,
module_name
,
module_args
,
inject
):
def
run
(
self
,
conn
,
tmp
,
module_name
,
module_args
,
inject
,
complex_args
=
None
,
**
kwargs
):
''' handler for file transfer operations '''
# load up options
...
...
lib/ansible/runner/action_plugins/debug.py
View file @
1ecf4a69
...
...
@@ -28,7 +28,7 @@ class ActionModule(object):
def
__init__
(
self
,
runner
):
self
.
runner
=
runner
def
run
(
self
,
conn
,
tmp
,
module_name
,
module_args
,
inject
):
def
run
(
self
,
conn
,
tmp
,
module_name
,
module_args
,
inject
,
complex_args
=
None
,
**
kwargs
):
args
=
utils
.
parse_kv
(
module_args
)
if
not
'msg'
in
args
:
args
[
'msg'
]
=
'Hello world!'
...
...
lib/ansible/runner/action_plugins/fail.py
View file @
1ecf4a69
...
...
@@ -28,7 +28,7 @@ class ActionModule(object):
def
__init__
(
self
,
runner
):
self
.
runner
=
runner
def
run
(
self
,
conn
,
tmp
,
module_name
,
module_args
,
inject
):
def
run
(
self
,
conn
,
tmp
,
module_name
,
module_args
,
inject
,
complex_args
=
None
,
**
kwargs
):
# note: the fail module does not need to pay attention to check mode
# it always runs.
...
...
lib/ansible/runner/action_plugins/fetch.py
View file @
1ecf4a69
...
...
@@ -33,7 +33,7 @@ class ActionModule(object):
def
__init__
(
self
,
runner
):
self
.
runner
=
runner
def
run
(
self
,
conn
,
tmp
,
module_name
,
module_args
,
inject
):
def
run
(
self
,
conn
,
tmp
,
module_name
,
module_args
,
inject
,
complex_args
=
None
,
**
kwargs
):
''' handler for fetch operations '''
if
self
.
runner
.
check
:
...
...
lib/ansible/runner/action_plugins/group_by.py
View file @
1ecf4a69
...
...
@@ -32,7 +32,7 @@ class ActionModule(object):
def
__init__
(
self
,
runner
):
self
.
runner
=
runner
def
run
(
self
,
conn
,
tmp
,
module_name
,
module_args
,
inject
):
def
run
(
self
,
conn
,
tmp
,
module_name
,
module_args
,
inject
,
complex_args
=
None
,
**
kwargs
):
# the group_by module does not need to pay attention to check mode.
# it always runs.
...
...
lib/ansible/runner/action_plugins/normal.py
View file @
1ecf4a69
...
...
@@ -33,9 +33,12 @@ class ActionModule(object):
def
__init__
(
self
,
runner
):
self
.
runner
=
runner
def
run
(
self
,
conn
,
tmp
,
module_name
,
module_args
,
inject
):
def
run
(
self
,
conn
,
tmp
,
module_name
,
module_args
,
inject
,
complex_args
=
None
,
**
kwargs
):
''' transfer & execute a module that is not 'copy' or 'template' '''
complex_args
=
utils
.
template
(
self
.
runner
.
basedir
,
complex_args
,
inject
)
module_args
=
self
.
runner
.
_complex_args_hack
(
complex_args
,
module_args
)
if
self
.
runner
.
check
:
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
))
...
...
@@ -49,6 +52,6 @@ class ActionModule(object):
module_args
+=
" #USE_SHELL"
vv
(
"REMOTE_MODULE
%
s
%
s"
%
(
module_name
,
module_args
),
host
=
conn
.
host
)
return
self
.
runner
.
_execute_module
(
conn
,
tmp
,
module_name
,
module_args
,
inject
=
inject
)
return
self
.
runner
.
_execute_module
(
conn
,
tmp
,
module_name
,
module_args
,
inject
=
inject
,
complex_args
=
complex_args
)
lib/ansible/runner/action_plugins/pause.py
View file @
1ecf4a69
...
...
@@ -46,7 +46,7 @@ class ActionModule(object):
'delta'
:
None
,
}
def
run
(
self
,
conn
,
tmp
,
module_name
,
module_args
,
inject
):
def
run
(
self
,
conn
,
tmp
,
module_name
,
module_args
,
inject
,
complex_args
=
None
,
**
kwargs
):
''' run the pause action module '''
# note: this module does not need to pay attention to the 'check'
...
...
lib/ansible/runner/action_plugins/raw.py
View file @
1ecf4a69
...
...
@@ -28,7 +28,7 @@ class ActionModule(object):
def
__init__
(
self
,
runner
):
self
.
runner
=
runner
def
run
(
self
,
conn
,
tmp
,
module_name
,
module_args
,
inject
):
def
run
(
self
,
conn
,
tmp
,
module_name
,
module_args
,
inject
,
complex_args
=
None
,
**
kwargs
):
if
self
.
runner
.
check
:
# in --check mode, always skip this module execution
...
...
lib/ansible/runner/action_plugins/script.py
View file @
1ecf4a69
...
...
@@ -28,7 +28,7 @@ class ActionModule(object):
def
__init__
(
self
,
runner
):
self
.
runner
=
runner
def
run
(
self
,
conn
,
tmp
,
module_name
,
module_args
,
inject
):
def
run
(
self
,
conn
,
tmp
,
module_name
,
module_args
,
inject
,
complex_args
=
None
,
**
kwargs
):
''' handler for file transfer operations '''
if
self
.
runner
.
check
:
...
...
lib/ansible/runner/action_plugins/template.py
View file @
1ecf4a69
...
...
@@ -27,7 +27,7 @@ class ActionModule(object):
def
__init__
(
self
,
runner
):
self
.
runner
=
runner
def
run
(
self
,
conn
,
tmp
,
module_name
,
module_args
,
inject
):
def
run
(
self
,
conn
,
tmp
,
module_name
,
module_args
,
inject
,
complex_args
=
None
,
**
kwargs
):
''' handler for template operations '''
# note: since this module just calls the copy module, the --check mode support
...
...
lib/ansible/utils/__init__.py
View file @
1ecf4a69
...
...
@@ -118,6 +118,8 @@ def exit(msg, rc=1):
def
jsonify
(
result
,
format
=
False
):
''' format JSON output (uncompressed or uncompressed) '''
if
result
is
None
:
return
{}
result2
=
result
.
copy
()
if
format
:
return
json
.
dumps
(
result2
,
sort_keys
=
True
,
indent
=
4
)
...
...
library/ping
View file @
1ecf4a69
...
...
@@ -36,10 +36,15 @@ author: Michael DeHaan
def
main
():
module
=
AnsibleModule
(
argument_spec
=
dict
(),
argument_spec
=
dict
(
data
=
dict
(
required
=
False
,
default
=
None
),
),
supports_check_mode
=
True
)
module
.
exit_json
(
ping
=
'pong'
)
result
=
dict
(
ping
=
'pong'
)
if
module
.
params
[
'data'
]:
result
[
'ping'
]
=
module
.
params
[
'data'
]
module
.
exit_json
(
**
result
)
# this is magic, see lib/ansible/module_common.py
#<<INCLUDE_ANSIBLE_MODULE_COMMON>>
...
...
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