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
13ddd39d
Commit
13ddd39d
authored
Jan 08, 2013
by
Jayson Vantuyl
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add with_sequence lookup plugin
Plugin allows you to do easy counts for items.
parent
b57b1f4c
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
273 additions
and
6 deletions
+273
-6
docsite/rst/playbooks2.rst
+49
-3
lib/ansible/runner/lookup_plugins/sequence.py
+202
-0
test/TestPlayBook.py
+3
-3
test/lookup_plugins.yml
+19
-0
No files found.
docsite/rst/playbooks2.rst
View file @
13ddd39d
...
...
@@ -415,8 +415,8 @@ More Loops
.. versionadded: 0.8
Various 'lookup plugins' allow additional ways to iterate over data. Ansible will have more of these
over time. In 0.8, the only lookup plugin
that comes stock is 'with_fileglob', but you can also write
your own.
over time. In 0.8, the only lookup plugin
s that comes stock are 'with_fileglob' and 'with_sequence', but
you
can also write you
r own.
'with_fileglob' matches all files in a single directory, non-recursively, that match a pattern. It can
be used like this::
...
...
@@ -433,6 +433,52 @@ be used like this::
- action: copy src=$item dest=/etc/fooapp/ owner=root mode=600
with_fileglob: /playbooks/files/fooapp/*
.. versionadded: 1.0
'with_sequence' generates a sequence of items in ascending numerical order. You
can specify a 'start', an 'end' value (inclusive), and a 'stride' value (to skip
some numbers of values), and a printf-style 'format' string. It accepts
arguments both as key-value pairs and in a shortcut of the form
"[start-]end[/stride][:format]". All numerical values can be specified in
hexadecimal (i.e. 0x3f8) or octal (i.e. 0644). Negative numbers are not
supported. Here is an example that leverages most of its features::
----
- hosts: all
tasks:
# create groups
- group: name=evens state=present
- group: name=odds state=present
# create 32 test users
- user: name=$item state=present groups=odds
with_sequence: 32/2:testuser%02x
- user: name=$item state=present groups=evens
with_sequence: 2-32/2:testuser%02x
# create a series of directories for some reason
- file: dest=/var/stuff/$item state=directory
with_sequence: start=4 end=16
The key-value form also supports a 'count' option, which always generates
'count' entries regardless of the stride. The count option is mostly useful for
avoiding off-by-one errors and errors calculating the number of entries in a
sequence when a stride is specified. The shortcut form cannot be used to
specify a count. As an example::
----
- hosts: all
tasks:
# create 4 groups
- group: name=group${item} state=present
with_sequence: count=4
Getting values from files
`````````````````````````
...
...
@@ -466,7 +512,7 @@ The following example shows how to template out a configuration file that was ve
- /srv/templates/myapp/${ansible_distribution}.conf
- /srv/templates/myapp/default.conf
first_available_file is only available to the copy and template modules.
first_available_file is only available to the copy and template modules.
Asynchronous Actions and Polling
````````````````````````````````
...
...
lib/ansible/runner/lookup_plugins/sequence.py
0 → 100644
View file @
13ddd39d
# (c) 2013, Jayson Vantuyl <jayson@aggressive.ly>
#
# This file is part of Ansible
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
from
ansible.errors
import
AnsibleError
from
ansible.utils
import
parse_kv
from
re
import
compile
as
re_compile
,
IGNORECASE
# shortcut format
NUM
=
"(0?x?[0-9a-f]+)"
SHORTCUT
=
re_compile
(
"^("
+
# Group 0
NUM
+
# Group 1: Start
"-)?"
+
NUM
+
# Group 2: End
"(/"
+
# Group 3
NUM
+
# Group 4: Stride
")?"
+
"(:(.+))?$"
,
# Group 5, Group 6: Format String
IGNORECASE
)
class
LookupModule
(
object
):
"""
sequence lookup module
Used to generate some sequence of items. Takes arguments in two forms.
The simple / shortcut form is:
[start-]end[/stride][:format]
As indicated by the brackets: start, stride, and format string are all
optional. The format string is in the style of printf. This can be used
to pad with zeros, format in hexadecimal, etc. All of the numerical values
can be specified in octal (i.e. 0664) or hexadecimal (i.e. 0x3f8).
Negative numbers are not supported.
Some examples:
5 -> ["1","2","3","4","5"]
5-8 -> ["5", "6", "7", "8"]
2-10/2 -> ["2", "4", "6", "8", "10"]
4:host
%02
d -> ["host01","host02","host03","host04"]
The standard Ansible key-value form is accepted as well. For example:
start=5 end=11 stride=2 format=0x
%02
x -> ["0x05","0x07","0x09","0x0a"]
This format takes an alternate form of "end" called "count", which counts
some number from the starting value. For example:
count=5 -> ["1", "2", "3", "4", "5"]
start=0x0f00 count=4 format=
%04
x -> ["0f00", "0f01", "0f02", "0f03"]
start=0 count=5 stride=2 -> ["0", "2", "4", "6", "8"]
start=1 count=5 stride=2 -> ["1", "3", "5", "7", "9"]
The count option is mostly useful for avoiding off-by-one errors and errors
calculating the number of entries in a sequence when a stride is specified.
"""
def
__init__
(
self
,
**
kwargs
):
"""absorb any keyword args"""
pass
def
reset
(
self
):
"""set sensible defaults"""
self
.
start
=
1
self
.
count
=
None
self
.
end
=
None
self
.
stride
=
1
self
.
format
=
"
%
d"
def
parse_kv_args
(
self
,
args
):
"""parse key-value style arguments"""
for
arg
in
[
"start"
,
"end"
,
"count"
,
"stride"
]:
try
:
arg_raw
=
args
.
pop
(
arg
,
None
)
if
arg_raw
is
None
:
continue
arg_cooked
=
int
(
arg_raw
,
0
)
setattr
(
self
,
arg
,
arg_cooked
)
except
ValueError
:
raise
AnsibleError
(
"can't parse arg
%
s=
%
r as integer"
%
(
arg
,
arg_raw
)
)
if
'format'
in
args
:
self
.
format
=
args
.
pop
(
"format"
)
if
args
:
raise
AnsibleError
(
"unrecognized arguments to with_sequence:
%
r"
%
args
.
keys
()
)
def
parse_simple_args
(
self
,
term
):
"""parse the shortcut forms, return True/False"""
match
=
SHORTCUT
.
match
(
term
)
if
not
match
:
return
False
_
,
start
,
end
,
_
,
stride
,
_
,
format
=
match
.
groups
()
if
start
is
not
None
:
try
:
start
=
int
(
start
,
0
)
except
ValueError
:
raise
AnsibleError
(
"can't parse start=
%
s as integer"
%
start
)
if
end
is
not
None
:
try
:
end
=
int
(
end
,
0
)
except
ValueError
:
raise
AnsibleError
(
"can't parse end=
%
s as integer"
%
end
)
if
stride
is
not
None
:
try
:
stride
=
int
(
stride
,
0
)
except
ValueError
:
raise
AnsibleError
(
"can't parse stride=
%
s as integer"
%
stride
)
if
start
is
not
None
:
self
.
start
=
start
if
end
is
not
None
:
self
.
end
=
end
if
stride
is
not
None
:
self
.
stride
=
stride
if
format
is
not
None
:
self
.
format
=
format
def
sanity_check
(
self
):
if
self
.
count
is
None
and
self
.
end
is
None
:
raise
AnsibleError
(
"must specify count or end in with_sequence"
)
elif
self
.
count
is
not
None
and
self
.
end
is
not
None
:
raise
AnsibleError
(
"can't specify both count and end in with_sequence"
)
elif
self
.
count
is
not
None
:
# convert count to end
self
.
end
=
self
.
start
+
self
.
count
*
self
.
stride
-
1
del
self
.
count
if
self
.
end
<
self
.
start
:
raise
AnsibleError
(
"can't count backwards"
)
if
self
.
format
.
count
(
'
%
'
)
!=
1
:
raise
AnsibleError
(
"bad formatting string:
%
s"
%
self
.
format
)
def
generate_sequence
(
self
):
numbers
=
xrange
(
self
.
start
,
self
.
end
+
1
,
self
.
stride
)
for
i
in
numbers
:
try
:
formatted
=
self
.
format
%
i
yield
formatted
except
(
ValueError
,
TypeError
):
raise
AnsibleError
(
"problem formatting
%
r with
%
r"
%
self
.
format
)
def
run
(
self
,
terms
,
**
kwargs
):
results
=
[]
if
isinstance
(
terms
,
basestring
):
terms
=
[
terms
]
for
term
in
terms
:
try
:
self
.
reset
()
# clear out things for this iteration
try
:
if
not
self
.
parse_simple_args
(
term
):
self
.
parse_kv_args
(
parse_kv
(
term
))
except
Exception
:
raise
AnsibleError
(
"unknown error parsing with_sequence arguments:
%
r"
%
term
)
self
.
sanity_check
()
results
.
extend
(
self
.
generate_sequence
())
except
AnsibleError
:
raise
except
Exception
:
raise
AnsibleError
(
"unknown error generating sequence"
)
return
results
test/TestPlayBook.py
View file @
13ddd39d
...
...
@@ -172,9 +172,9 @@ class TestPlaybook(unittest.TestCase):
print
utils
.
jsonify
(
actual
,
format
=
True
)
expected
=
{
"localhost"
:
{
"changed"
:
7
,
"changed"
:
9
,
"failures"
:
0
,
"ok"
:
9
,
"ok"
:
14
,
"skipped"
:
1
,
"unreachable"
:
0
}
...
...
@@ -185,7 +185,7 @@ class TestPlaybook(unittest.TestCase):
assert
utils
.
jsonify
(
expected
,
format
=
True
)
==
utils
.
jsonify
(
actual
,
format
=
True
)
print
"len(EVENTS) =
%
d"
%
len
(
EVENTS
)
assert
len
(
EVENTS
)
==
26
assert
len
(
EVENTS
)
==
60
def
test_includes
(
self
):
pb
=
os
.
path
.
join
(
self
.
test_dir
,
'playbook-includer.yml'
)
...
...
test/lookup_plugins.yml
View file @
13ddd39d
...
...
@@ -26,6 +26,25 @@
-
name
:
test LOOKUP and PIPE
action
:
command test "$LOOKUP(pipe, cat sample.j2)" = "$PIPE(cat sample.j2)"
-
name
:
test with_sequence, generate
command
:
touch /tmp/seq-${item}
with_sequence
:
0-16/2:%02x
-
name
:
test with_sequence, fenceposts 1
copy
:
src=/tmp/seq-00 dest=/tmp/seq-10
-
name
:
test with_sequence, fenceposts 2
file
:
dest=/tmp/seq-${item} state=absent
with_items
:
[
11
,
12
]
-
name
:
test with_sequence, missing
file
:
dest=/tmp/seq-${item} state=absent
with_sequence
:
0x10/02:%02x
-
name
:
test with_sequence,remove
file
:
dest=/tmp/seq-${item} state=absent
with_sequence
:
0-0x10/02:%02x
-
name
:
ensure test file doesnt exist
# command because file will return differently
action
:
command rm -f /tmp/ansible-test-with_lines-data
...
...
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