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
c83a8337
Commit
c83a8337
authored
Oct 08, 2014
by
James Cammarata
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
New v2 ModuleArgsParser code and fixing up tests/other task code
parent
bbd9921d
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
91 additions
and
89 deletions
+91
-89
test/v2/parsing/test_mod_args.py
+30
-28
test/v2/playbook/test_task.py
+5
-4
v2/ansible/parsing/mod_args.py
+0
-0
v2/ansible/parsing/splitter.py
+31
-4
v2/ansible/playbook/task.py
+25
-53
No files found.
test/v2/parsing/test_mod_args.py
View file @
c83a8337
...
@@ -13,67 +13,69 @@ class TestModArgsDwim(unittest.TestCase):
...
@@ -13,67 +13,69 @@ class TestModArgsDwim(unittest.TestCase):
pass
pass
def
test_action_to_shell
(
self
):
def
test_action_to_shell
(
self
):
mod
,
args
,
to
=
self
.
m
.
parse
(
'action'
,
'shell echo hi'
)
mod
,
args
,
to
=
self
.
m
.
parse
(
dict
(
action
=
'shell echo hi'
)
)
assert
mod
==
'
shell
'
assert
mod
==
'
command
'
assert
args
==
dict
(
assert
args
==
dict
(
free_form
=
'echo hi'
,
_raw_params
=
'echo hi'
,
use_shell
=
True
_uses_shell
=
True
,
)
)
assert
to
is
None
assert
to
is
None
def
test_basic_shell
(
self
):
def
test_basic_shell
(
self
):
mod
,
args
,
to
=
self
.
m
.
parse
(
'shell'
,
'echo hi'
)
mod
,
args
,
to
=
self
.
m
.
parse
(
dict
(
shell
=
'echo hi'
)
)
assert
mod
==
'
shell
'
assert
mod
==
'
command
'
assert
args
==
dict
(
assert
args
==
dict
(
free_form
=
'echo hi'
,
_raw_params
=
'echo hi'
,
use_shell
=
True
_uses_shell
=
True
,
)
)
assert
to
is
None
assert
to
is
None
def
test_basic_command
(
self
):
def
test_basic_command
(
self
):
mod
,
args
,
to
=
self
.
m
.
parse
(
'command'
,
'echo hi'
)
mod
,
args
,
to
=
self
.
m
.
parse
(
dict
(
command
=
'echo hi'
)
)
assert
mod
==
'command'
assert
mod
==
'command'
assert
args
==
dict
(
assert
args
==
dict
(
free_form
=
'echo hi'
,
_raw_params
=
'echo hi'
,
use_shell
=
False
)
)
assert
to
is
None
assert
to
is
None
def
test_shell_with_modifiers
(
self
):
def
test_shell_with_modifiers
(
self
):
mod
,
args
,
to
=
self
.
m
.
parse
(
'shell'
,
'/bin/foo creates=/tmp/baz removes=/tmp/bleep'
)
mod
,
args
,
to
=
self
.
m
.
parse
(
dict
(
shell
=
'/bin/foo creates=/tmp/baz removes=/tmp/bleep'
)
)
assert
mod
==
'
shell
'
assert
mod
==
'
command
'
assert
args
==
dict
(
assert
args
==
dict
(
free_form
=
'echo hi
'
,
creates
=
'/tmp/baz
'
,
use_shell
=
False
,
removes
=
'/tmp/bleep'
,
creates
=
'/tmp/baz
'
,
_raw_params
=
'/bin/foo
'
,
removes
=
'/tmp/bleep'
_uses_shell
=
True
,
)
)
assert
to
is
None
assert
to
is
None
def
test_normal_usage
(
self
):
def
test_normal_usage
(
self
):
mod
,
args
,
to
=
self
.
m
.
parse
(
'copy'
,
'src=a dest=b'
)
mod
,
args
,
to
=
self
.
m
.
parse
(
dict
(
copy
=
'src=a dest=b'
)
)
assert
mod
==
'copy'
assert
mod
==
'copy'
assert
args
==
dict
(
src
=
'a'
,
dest
=
'b'
)
assert
args
==
dict
(
src
=
'a'
,
dest
=
'b'
)
assert
to
is
None
assert
to
is
None
def
test_complex_args
(
self
):
def
test_complex_args
(
self
):
mod
,
args
,
to
=
self
.
m
.
parse
(
'copy'
,
dict
(
src
=
a
,
dest
=
b
))
mod
,
args
,
to
=
self
.
m
.
parse
(
dict
(
copy
=
dict
(
src
=
'a'
,
dest
=
'b'
)
))
assert
mod
==
'copy'
assert
mod
==
'copy'
assert
args
==
dict
(
src
=
'a'
,
dest
=
'b'
)
assert
args
==
dict
(
src
=
'a'
,
dest
=
'b'
)
assert
to
is
None
assert
to
is
None
def
test_action_with_complex
(
self
):
def
test_action_with_complex
(
self
):
mod
,
args
,
to
=
self
.
m
.
parse
(
'action'
,
dict
(
module
=
'copy'
,
src
=
'a'
,
dest
=
'b'
))
mod
,
args
,
to
=
self
.
m
.
parse
(
dict
(
action
=
dict
(
module
=
'copy'
,
src
=
'a'
,
dest
=
'b'
)))
assert
mod
==
'action'
assert
mod
==
'copy'
assert
args
==
dict
(
src
=
'a'
,
dest
=
'b'
)
assert
args
==
dict
(
src
=
'a'
,
dest
=
'b'
)
assert
to
is
None
def
test_action_with_complex_and_complex_args
(
self
):
mod
,
args
,
to
=
self
.
m
.
parse
(
dict
(
action
=
dict
(
module
=
'copy'
,
args
=
dict
(
src
=
'a'
,
dest
=
'b'
))))
assert
mod
==
'copy'
assert
args
==
dict
(
src
=
'a'
,
dest
=
'b'
)
assert
to
is
None
assert
to
is
None
def
test_local_action_string
(
self
):
def
test_local_action_string
(
self
):
mod
,
args
,
to
=
self
.
m
.
parse
(
'local_action'
,
'copy src=a dest=b'
)
mod
,
args
,
to
=
self
.
m
.
parse
(
dict
(
local_action
=
'copy src=a dest=b'
)
)
assert
mod
==
'copy'
assert
mod
==
'copy'
assert
args
==
dict
(
src
=
a
,
dest
=
b
)
assert
args
==
dict
(
src
=
'a'
,
dest
=
'b'
)
assert
to
is
'localhost'
assert
to
is
'localhost'
test/v2/playbook/test_task.py
View file @
c83a8337
...
@@ -36,13 +36,14 @@ class TestTask(unittest.TestCase):
...
@@ -36,13 +36,14 @@ class TestTask(unittest.TestCase):
t
=
Task
.
load
(
basic_shell_task
)
t
=
Task
.
load
(
basic_shell_task
)
assert
t
is
not
None
assert
t
is
not
None
assert
t
.
name
==
basic_shell_task
[
'name'
]
assert
t
.
name
==
basic_shell_task
[
'name'
]
assert
t
.
action
==
'
shell
'
assert
t
.
action
==
'
command
'
assert
t
.
args
==
'echo hi'
assert
t
.
args
==
dict
(
_raw_params
=
'echo hi'
,
_uses_shell
=
True
)
def
test_load_task_kv_form
(
self
):
def
test_load_task_kv_form
(
self
):
t
=
Task
.
load
(
kv_shell_task
)
t
=
Task
.
load
(
kv_shell_task
)
assert
t
.
action
==
'shell'
print
"task action is
%
s"
%
t
.
action
#assert t.args == 'echo hi'
assert
t
.
action
==
'command'
assert
t
.
args
==
dict
(
_raw_params
=
'echo hi'
,
_uses_shell
=
True
)
def
test_task_auto_name
(
self
):
def
test_task_auto_name
(
self
):
assert
'name'
not
in
kv_shell_task
assert
'name'
not
in
kv_shell_task
...
...
v2/ansible/parsing/mod_args.py
View file @
c83a8337
This diff is collapsed.
Click to expand it.
v2/ansible/parsing/splitter.py
View file @
c83a8337
...
@@ -15,8 +15,14 @@
...
@@ -15,8 +15,14 @@
# You should have received a copy of the GNU General Public License
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
def
parse_kv
(
args
):
def
parse_kv
(
args
,
check_raw
=
False
):
''' convert a string of key/value items to a dict '''
'''
Convert a string of key/value items to a dict. If any free-form params
are found and the check_raw option is set to True, they will be added
to a new parameter called '_raw_params'. If check_raw is not enabled,
they will simply be ignored.
'''
options
=
{}
options
=
{}
if
args
is
not
None
:
if
args
is
not
None
:
try
:
try
:
...
@@ -26,10 +32,31 @@ def parse_kv(args):
...
@@ -26,10 +32,31 @@ def parse_kv(args):
raise
errors
.
AnsibleError
(
"error parsing argument string, try quoting the entire line."
)
raise
errors
.
AnsibleError
(
"error parsing argument string, try quoting the entire line."
)
else
:
else
:
raise
raise
raw_params
=
[]
for
x
in
vargs
:
for
x
in
vargs
:
if
"="
in
x
:
if
"="
in
x
:
k
,
v
=
x
.
split
(
"="
,
1
)
k
,
v
=
x
.
split
(
"="
,
1
)
options
[
k
.
strip
()]
=
unquote
(
v
.
strip
())
# only internal variables can start with an underscore, so
# we don't allow users to set them directy in arguments
if
k
.
startswith
(
'_'
):
raise
AnsibleError
(
"invalid parameter specified: '
%
s'"
%
k
)
# FIXME: make the retrieval of this list of shell/command
# options a function, so the list is centralized
if
check_raw
and
k
not
in
(
'creates'
,
'removes'
,
'chdir'
,
'executable'
,
'warn'
):
raw_params
.
append
(
x
)
else
:
options
[
k
.
strip
()]
=
unquote
(
v
.
strip
())
else
:
raw_params
.
append
(
x
)
# recombine the free-form params, if any were found, and assign
# them to a special option for use later by the shell/command module
if
len
(
raw_params
)
>
0
:
options
[
'_raw_params'
]
=
' '
.
join
(
raw_params
)
return
options
return
options
def
_get_quote_state
(
token
,
quote_char
):
def
_get_quote_state
(
token
,
quote_char
):
...
...
v2/ansible/playbook/task.py
View file @
c83a8337
...
@@ -18,13 +18,10 @@
...
@@ -18,13 +18,10 @@
from
ansible.playbook.base
import
Base
from
ansible.playbook.base
import
Base
from
ansible.playbook.attribute
import
Attribute
,
FieldAttribute
from
ansible.playbook.attribute
import
Attribute
,
FieldAttribute
# from ansible.playbook.conditional import Conditional
from
ansible.errors
import
AnsibleError
from
ansible.errors
import
AnsibleError
# TODO: it would be fantastic (if possible) if a task new where in the YAML it was defined for describing
# it in error conditions
from
ansible.parsing.splitter
import
parse_kv
from
ansible.parsing.splitter
import
parse_kv
from
ansible.parsing.mod_args
import
ModuleArgsParser
from
ansible.plugins
import
module_finder
,
lookup_finder
from
ansible.plugins
import
module_finder
,
lookup_finder
class
Task
(
Base
):
class
Task
(
Base
):
...
@@ -45,7 +42,6 @@ class Task(Base):
...
@@ -45,7 +42,6 @@ class Task(Base):
# validate_<attribute_name>
# validate_<attribute_name>
# will be used if defined
# will be used if defined
# might be possible to define others
# might be possible to define others
_args
=
FieldAttribute
(
isa
=
'dict'
)
_args
=
FieldAttribute
(
isa
=
'dict'
)
_action
=
FieldAttribute
(
isa
=
'string'
)
_action
=
FieldAttribute
(
isa
=
'string'
)
...
@@ -60,9 +56,6 @@ class Task(Base):
...
@@ -60,9 +56,6 @@ class Task(Base):
_first_available_file
=
FieldAttribute
(
isa
=
'list'
)
_first_available_file
=
FieldAttribute
(
isa
=
'list'
)
_ignore_errors
=
FieldAttribute
(
isa
=
'bool'
)
_ignore_errors
=
FieldAttribute
(
isa
=
'bool'
)
# FIXME: this should not be a Task
# include = FieldAttribute(isa='string')
_loop
=
FieldAttribute
(
isa
=
'string'
,
private
=
True
)
_loop
=
FieldAttribute
(
isa
=
'string'
,
private
=
True
)
_loop_args
=
FieldAttribute
(
isa
=
'list'
,
private
=
True
)
_loop_args
=
FieldAttribute
(
isa
=
'list'
,
private
=
True
)
_local_action
=
FieldAttribute
(
isa
=
'string'
)
_local_action
=
FieldAttribute
(
isa
=
'string'
)
...
@@ -102,16 +95,19 @@ class Task(Base):
...
@@ -102,16 +95,19 @@ class Task(Base):
elif
self
.
name
:
elif
self
.
name
:
return
self
.
name
return
self
.
name
else
:
else
:
return
"
%
s
%
s"
%
(
self
.
action
,
self
.
_merge_kv
(
self
.
args
))
flattened_args
=
self
.
_merge_kv
(
self
.
args
)
return
"
%
s
%
s"
%
(
self
.
action
,
flattened_args
)
def
_merge_kv
(
self
,
ds
):
def
_merge_kv
(
self
,
ds
):
if
ds
is
None
:
if
ds
is
None
:
return
""
return
""
elif
isinstance
(
ds
,
basestring
):
elif
isinstance
(
ds
,
basestring
):
return
ds
return
ds
elif
instance
(
ds
,
dict
):
elif
i
si
nstance
(
ds
,
dict
):
buf
=
""
buf
=
""
for
(
k
,
v
)
in
ds
.
iteritems
():
for
(
k
,
v
)
in
ds
.
iteritems
():
if
k
.
startswith
(
'_'
):
continue
buf
=
buf
+
"
%
s=
%
s "
%
(
k
,
v
)
buf
=
buf
+
"
%
s=
%
s "
%
(
k
,
v
)
buf
=
buf
.
strip
()
buf
=
buf
.
strip
()
return
buf
return
buf
...
@@ -125,27 +121,6 @@ class Task(Base):
...
@@ -125,27 +121,6 @@ class Task(Base):
''' returns a human readable representation of the task '''
''' returns a human readable representation of the task '''
return
"TASK:
%
s"
%
self
.
get_name
()
return
"TASK:
%
s"
%
self
.
get_name
()
def
_parse_old_school_action
(
self
,
v
):
''' given a action/local_action line, return the module and args '''
tokens
=
v
.
split
()
if
len
(
tokens
)
<
2
:
return
[
v
,{}]
else
:
if
v
not
in
[
'command'
,
'shell'
]:
joined
=
" "
.
join
(
tokens
[
1
:])
return
[
tokens
[
0
],
parse_kv
(
joined
)]
else
:
return
[
tokens
[
0
],
joined
]
def
_munge_action
(
self
,
ds
,
new_ds
,
k
,
v
):
''' take a module name and split into action and args '''
if
self
.
_action
.
value
is
not
None
or
'action'
in
ds
or
'local_action'
in
ds
:
raise
AnsibleError
(
"duplicate action in task:
%
s"
%
k
)
new_ds
[
'action'
]
=
k
new_ds
[
'args'
]
=
v
def
_munge_loop
(
self
,
ds
,
new_ds
,
k
,
v
):
def
_munge_loop
(
self
,
ds
,
new_ds
,
k
,
v
):
''' take a lookup plugin name and store it correctly '''
''' take a lookup plugin name and store it correctly '''
...
@@ -154,22 +129,6 @@ class Task(Base):
...
@@ -154,22 +129,6 @@ class Task(Base):
new_ds
[
'loop'
]
=
k
new_ds
[
'loop'
]
=
k
new_ds
[
'loop_args'
]
=
v
new_ds
[
'loop_args'
]
=
v
def
_munge_action2
(
self
,
ds
,
new_ds
,
k
,
v
,
local
=
False
):
''' take an old school action/local_action and reformat it '''
if
isinstance
(
v
,
basestring
):
tokens
=
self
.
_parse_old_school_action
(
v
)
new_ds
[
'action'
]
=
tokens
[
0
]
if
'args'
in
ds
:
raise
AnsibleError
(
"unexpected and redundant 'args'"
)
new_ds
[
'args'
]
=
args
if
local
:
if
'delegate_to'
in
ds
:
raise
AnsbileError
(
"local_action and action conflict"
)
new_ds
[
'delegate_to'
]
=
'localhost'
else
:
raise
AnsibleError
(
"unexpected use of 'action'"
)
def
munge
(
self
,
ds
):
def
munge
(
self
,
ds
):
'''
'''
tasks are especially complex arguments so need pre-processing.
tasks are especially complex arguments so need pre-processing.
...
@@ -178,18 +137,31 @@ class Task(Base):
...
@@ -178,18 +137,31 @@ class Task(Base):
assert
isinstance
(
ds
,
dict
)
assert
isinstance
(
ds
,
dict
)
# the new, cleaned datastructure, which will have legacy
# items reduced to a standard structure suitable for the
# attributes of the task class
new_ds
=
dict
()
new_ds
=
dict
()
# use the args parsing class to determine the action, args,
# and the delegate_to value from the various possible forms
# supported as legacy
args_parser
=
ModuleArgsParser
()
(
action
,
args
,
delegate_to
)
=
args_parser
.
parse
(
ds
)
new_ds
[
'action'
]
=
action
new_ds
[
'args'
]
=
args
new_ds
[
'delegate_to'
]
=
delegate_to
for
(
k
,
v
)
in
ds
.
iteritems
():
for
(
k
,
v
)
in
ds
.
iteritems
():
if
k
in
module_finder
:
if
k
in
(
'action'
,
'local_action'
,
'args'
,
'delegate_to'
)
or
k
==
action
:
self
.
_munge_action
(
ds
,
new_ds
,
k
,
v
)
# we don't want to re-assign these values, which were
# determined by the ModuleArgsParser() above
continue
elif
"with_
%
s"
%
k
in
lookup_finder
:
elif
"with_
%
s"
%
k
in
lookup_finder
:
self
.
_munge_loop
(
ds
,
new_ds
,
k
,
v
)
self
.
_munge_loop
(
ds
,
new_ds
,
k
,
v
)
elif
k
==
'action'
:
self
.
_munge_action2
(
ds
,
new_ds
,
k
,
v
)
elif
k
==
'local_action'
:
self
.
_munge_action2
(
ds
,
new_ds
,
k
,
v
,
local
=
True
)
else
:
else
:
new_ds
[
k
]
=
v
new_ds
[
k
]
=
v
return
new_ds
return
new_ds
...
...
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