mirror of
https://github.com/ansible-collections/community.general.git
synced 2024-09-14 20:13:21 +02:00
Alphabetic inventory hostname patterns.
- Code, docs, tests. - Also added test of large range 000-142 to verify alpha range did not break this.
This commit is contained in:
parent
959a461080
commit
6603737e4d
5 changed files with 54 additions and 37 deletions
|
@ -48,8 +48,9 @@ Adding a lot of hosts? In 0.6 and later, if you have a lot of hosts following s
|
||||||
|
|
||||||
[webservers]
|
[webservers]
|
||||||
www[01:50].example.com
|
www[01:50].example.com
|
||||||
|
db-[a:f].example.com
|
||||||
|
|
||||||
Leading zeros can be included or removed, as desired, and the ranges are inclusive.
|
For numeric patterns, leading zeros can be included or removed, as desired. Ranges are inclusive.
|
||||||
|
|
||||||
Selecting Targets
|
Selecting Targets
|
||||||
+++++++++++++++++
|
+++++++++++++++++
|
||||||
|
|
|
@ -20,8 +20,8 @@
|
||||||
'''
|
'''
|
||||||
This module is for enhancing ansible's inventory parsing capability such
|
This module is for enhancing ansible's inventory parsing capability such
|
||||||
that it can deal with hostnames specified using a simple pattern in the
|
that it can deal with hostnames specified using a simple pattern in the
|
||||||
form of [beg:end], example: [1:5] where if beg is not specified, it
|
form of [beg:end], example: [1:5], [a:c], [D:G]. If beg is not specified,
|
||||||
defaults to 0.
|
it defaults to 0.
|
||||||
|
|
||||||
If beg is given and is left-zero-padded, e.g. '001', it is taken as a
|
If beg is given and is left-zero-padded, e.g. '001', it is taken as a
|
||||||
formatting hint when the range is expanded. e.g. [001:010] is to be
|
formatting hint when the range is expanded. e.g. [001:010] is to be
|
||||||
|
@ -30,6 +30,7 @@ expanded into 001, 002 ...009, 010.
|
||||||
Note that when beg is specified with left zero padding, then the length of
|
Note that when beg is specified with left zero padding, then the length of
|
||||||
end must be the same as that of beg, else a exception is raised.
|
end must be the same as that of beg, else a exception is raised.
|
||||||
'''
|
'''
|
||||||
|
import string
|
||||||
|
|
||||||
from ansible import errors
|
from ansible import errors
|
||||||
|
|
||||||
|
@ -81,17 +82,23 @@ def expand_hostname_range(line = None):
|
||||||
raise errors.AnsibleError("host range end value missing")
|
raise errors.AnsibleError("host range end value missing")
|
||||||
if beg[0] == '0' and len(beg) > 1:
|
if beg[0] == '0' and len(beg) > 1:
|
||||||
rlen = len(beg) # range length formatting hint
|
rlen = len(beg) # range length formatting hint
|
||||||
|
if rlen != len(end):
|
||||||
|
raise errors.AnsibleError("host range format incorrectly specified!")
|
||||||
|
fill = lambda _: str(_).zfill(rlen) # range sequence
|
||||||
else:
|
else:
|
||||||
rlen = None
|
fill = str
|
||||||
if rlen > 1 and rlen != len(end):
|
|
||||||
raise errors.AnsibleError("host range format incorrectly specified!")
|
|
||||||
|
|
||||||
for _ in range(int(beg), int(end)+1):
|
try:
|
||||||
if rlen:
|
i_beg = string.ascii_letters.index(beg)
|
||||||
rseq = str(_).zfill(rlen) # range sequence
|
i_end = string.ascii_letters.index(end)
|
||||||
else:
|
if i_beg > i_end:
|
||||||
rseq = str(_)
|
raise errors.AnsibleError("host range format incorrectly specified!")
|
||||||
hname = ''.join((head, rseq, tail))
|
seq = string.ascii_letters[i_beg:i_end+1]
|
||||||
|
except ValueError: # not a alpha range
|
||||||
|
seq = range(int(beg), int(end)+1)
|
||||||
|
|
||||||
|
for rseq in seq:
|
||||||
|
hname = ''.join((head, fill(rseq), tail))
|
||||||
all_hosts.append(hname)
|
all_hosts.append(hname)
|
||||||
|
|
||||||
return all_hosts
|
return all_hosts
|
||||||
|
|
|
@ -9,9 +9,10 @@ class TestInventory(unittest.TestCase):
|
||||||
self.cwd = os.getcwd()
|
self.cwd = os.getcwd()
|
||||||
self.test_dir = os.path.join(self.cwd, 'test')
|
self.test_dir = os.path.join(self.cwd, 'test')
|
||||||
|
|
||||||
self.inventory_file = os.path.join(self.test_dir, 'simple_hosts')
|
self.inventory_file = os.path.join(self.test_dir, 'simple_hosts')
|
||||||
self.complex_inventory_file = os.path.join(self.test_dir, 'complex_hosts')
|
self.large_range_inventory_file = os.path.join(self.test_dir, 'large_range')
|
||||||
self.inventory_script = os.path.join(self.test_dir, 'inventory_api.py')
|
self.complex_inventory_file = os.path.join(self.test_dir, 'complex_hosts')
|
||||||
|
self.inventory_script = os.path.join(self.test_dir, 'inventory_api.py')
|
||||||
|
|
||||||
os.chmod(self.inventory_script, 0755)
|
os.chmod(self.inventory_script, 0755)
|
||||||
|
|
||||||
|
@ -29,38 +30,36 @@ class TestInventory(unittest.TestCase):
|
||||||
def simple_inventory(self):
|
def simple_inventory(self):
|
||||||
return Inventory(self.inventory_file)
|
return Inventory(self.inventory_file)
|
||||||
|
|
||||||
|
def large_range_inventory(self):
|
||||||
|
return Inventory(self.large_range_inventory_file)
|
||||||
|
|
||||||
def script_inventory(self):
|
def script_inventory(self):
|
||||||
return Inventory(self.inventory_script)
|
return Inventory(self.inventory_script)
|
||||||
|
|
||||||
def complex_inventory(self):
|
def complex_inventory(self):
|
||||||
return Inventory(self.complex_inventory_file)
|
return Inventory(self.complex_inventory_file)
|
||||||
|
|
||||||
|
all_simple_hosts=['jupiter', 'saturn', 'zeus', 'hera',
|
||||||
|
'cerberus001','cerberus002','cerberus003',
|
||||||
|
'cottus99', 'cottus100',
|
||||||
|
'poseidon', 'thor', 'odin', 'loki',
|
||||||
|
'thrudgelmir0', 'thrudgelmir1', 'thrudgelmir2',
|
||||||
|
'thrudgelmir3', 'thrudgelmir4', 'thrudgelmir5',
|
||||||
|
'Hotep-a', 'Hotep-b', 'Hotep-c',
|
||||||
|
'BastC', 'BastD', ]
|
||||||
|
|
||||||
#####################################
|
#####################################
|
||||||
### Simple inventory format tests
|
### Simple inventory format tests
|
||||||
|
|
||||||
def test_simple(self):
|
def test_simple(self):
|
||||||
inventory = self.simple_inventory()
|
inventory = self.simple_inventory()
|
||||||
hosts = inventory.list_hosts()
|
hosts = inventory.list_hosts()
|
||||||
|
self.assertEqual(sorted(hosts), sorted(self.all_simple_hosts))
|
||||||
expected_hosts=['jupiter', 'saturn', 'zeus', 'hera',
|
|
||||||
'cerberus001','cerberus002','cerberus003',
|
|
||||||
'cottus99', 'cottus100',
|
|
||||||
'poseidon', 'thor', 'odin', 'loki',
|
|
||||||
'thrudgelmir0', 'thrudgelmir1', 'thrudgelmir2',
|
|
||||||
'thrudgelmir3', 'thrudgelmir4', 'thrudgelmir5']
|
|
||||||
assert sorted(hosts) == sorted(expected_hosts)
|
|
||||||
|
|
||||||
def test_simple_all(self):
|
def test_simple_all(self):
|
||||||
inventory = self.simple_inventory()
|
inventory = self.simple_inventory()
|
||||||
hosts = inventory.list_hosts('all')
|
hosts = inventory.list_hosts('all')
|
||||||
|
self.assertEqual(sorted(hosts), sorted(self.all_simple_hosts))
|
||||||
expected_hosts=['jupiter', 'saturn', 'zeus', 'hera',
|
|
||||||
'cerberus001','cerberus002','cerberus003',
|
|
||||||
'cottus99', 'cottus100',
|
|
||||||
'poseidon', 'thor', 'odin', 'loki',
|
|
||||||
'thrudgelmir0', 'thrudgelmir1', 'thrudgelmir2',
|
|
||||||
'thrudgelmir3', 'thrudgelmir4', 'thrudgelmir5']
|
|
||||||
assert sorted(hosts) == sorted(expected_hosts)
|
|
||||||
|
|
||||||
def test_simple_norse(self):
|
def test_simple_norse(self):
|
||||||
inventory = self.simple_inventory()
|
inventory = self.simple_inventory()
|
||||||
|
@ -132,6 +131,11 @@ class TestInventory(unittest.TestCase):
|
||||||
print expected
|
print expected
|
||||||
assert vars == expected
|
assert vars == expected
|
||||||
|
|
||||||
|
def test_large_range(self):
|
||||||
|
inventory = self.large_range_inventory()
|
||||||
|
hosts = inventory.list_hosts()
|
||||||
|
self.assertEqual(sorted(hosts), sorted('bob%03i' %i for i in range(0, 143)))
|
||||||
|
|
||||||
###################################################
|
###################################################
|
||||||
### INI file advanced tests
|
### INI file advanced tests
|
||||||
|
|
||||||
|
|
1
test/large_range
Normal file
1
test/large_range
Normal file
|
@ -0,0 +1 @@
|
||||||
|
bob[000:142]
|
|
@ -13,3 +13,7 @@ cottus[99:100]
|
||||||
thor
|
thor
|
||||||
odin
|
odin
|
||||||
loki
|
loki
|
||||||
|
|
||||||
|
[egyptian]
|
||||||
|
Hotep-[a:c]
|
||||||
|
Bast[C:D]
|
||||||
|
|
Loading…
Reference in a new issue