Commit 1c81ddf8 by Michael DeHaan

add the limit option, which can be used to further confine the patterns selected…

add the limit option, which can be used to further confine the patterns selected by "hosts:" in ansible-playbooks
to an additional pattern (a subset) specified on the command line.  For instance, a playbook could be reusable
and target "webservers" and "dbservers", but you want to test only in the stage environment, or a few boxes at a time.
parent 05a128c2
...@@ -28,6 +28,7 @@ Ansible Changes By Release ...@@ -28,6 +28,7 @@ Ansible Changes By Release
* make remote_md5 internal function work with non-bash shells * make remote_md5 internal function work with non-bash shells
* allow user to be passed in via --extra-vars (regression) * allow user to be passed in via --extra-vars (regression)
* add ability to store the result of any command in a register (see examples/playbooks/register_logic.yml) * add ability to store the result of any command in a register (see examples/playbooks/register_logic.yml)
* add --limit option, which can be used to further confine the pattern given in ansible-playbooks
0.6 "Cabo" -- August 6, 2012 0.6 "Cabo" -- August 6, 2012
......
...@@ -52,7 +52,7 @@ def main(args): ...@@ -52,7 +52,7 @@ def main(args):
# create parser for CLI options # create parser for CLI options
usage = "%prog playbook.yml" usage = "%prog playbook.yml"
parser = utils.base_parser(constants=C, usage=usage, connect_opts=True, runas_opts=True) parser = utils.base_parser(constants=C, usage=usage, connect_opts=True, runas_opts=True, subset_opts=True)
parser.add_option('-e', '--extra-vars', dest="extra_vars", default=None, parser.add_option('-e', '--extra-vars', dest="extra_vars", default=None,
help="set additional key=value variables from the CLI") help="set additional key=value variables from the CLI")
parser.add_option('-t', '--tags', dest='tags', default='all', parser.add_option('-t', '--tags', dest='tags', default='all',
...@@ -102,6 +102,7 @@ def main(args): ...@@ -102,6 +102,7 @@ def main(args):
extra_vars=extra_vars, extra_vars=extra_vars,
private_key_file=options.private_key_file, private_key_file=options.private_key_file,
only_tags=only_tags, only_tags=only_tags,
subset=options.subset,
) )
try: try:
......
...@@ -35,4 +35,5 @@ DEFAULT_SUDO_USER = os.environ.get('ANSIBLE_SUDO_USER','root') ...@@ -35,4 +35,5 @@ DEFAULT_SUDO_USER = os.environ.get('ANSIBLE_SUDO_USER','root')
DEFAULT_REMOTE_PORT = 22 DEFAULT_REMOTE_PORT = 22
DEFAULT_TRANSPORT = os.environ.get('ANSIBLE_TRANSPORT','paramiko') DEFAULT_TRANSPORT = os.environ.get('ANSIBLE_TRANSPORT','paramiko')
DEFAULT_TRANSPORT_OPTS = ['local', 'paramiko', 'ssh'] DEFAULT_TRANSPORT_OPTS = ['local', 'paramiko', 'ssh']
DEFAULT_SUBSET = None
...@@ -34,7 +34,7 @@ class Inventory(object): ...@@ -34,7 +34,7 @@ class Inventory(object):
Host inventory for ansible. Host inventory for ansible.
""" """
__slots__ = [ 'host_list', 'groups', '_restriction', '_is_script', __slots__ = [ 'host_list', 'groups', '_restriction', '_subset', '_is_script',
'parser', '_vars_per_host', '_vars_per_group', '_hosts_cache' ] 'parser', '_vars_per_host', '_vars_per_group', '_hosts_cache' ]
def __init__(self, host_list=C.DEFAULT_HOST_LIST): def __init__(self, host_list=C.DEFAULT_HOST_LIST):
...@@ -55,6 +55,7 @@ class Inventory(object): ...@@ -55,6 +55,7 @@ class Inventory(object):
# a list of host(names) to contain current inquiries to # a list of host(names) to contain current inquiries to
self._restriction = None self._restriction = None
self._subset = None
# whether the inventory file is a script # whether the inventory file is a script
self._is_script = False self._is_script = False
...@@ -103,7 +104,9 @@ class Inventory(object): ...@@ -103,7 +104,9 @@ class Inventory(object):
inverted = False inverted = False
for group in groups: for group in groups:
for host in group.get_hosts(): for host in group.get_hosts():
if self._match(group.name, pat) or pat == 'all' or self._match(host.name, pat): if self._subset and host.name not in self._subset:
continue
if pat == 'all' or self._match(group.name, pat) or self._match(host.name, pat):
# must test explicitly for None because [] means no hosts allowed # must test explicitly for None because [] means no hosts allowed
if self._restriction==None or host.name in self._restriction: if self._restriction==None or host.name in self._restriction:
if inverted: if inverted:
...@@ -187,12 +190,28 @@ class Inventory(object): ...@@ -187,12 +190,28 @@ class Inventory(object):
def get_restriction(self): def get_restriction(self):
return self._restriction return self._restriction
def restrict_to(self, restriction, append_missing=False): def restrict_to(self, restriction):
""" Restrict list operations to the hosts given in restriction """ """
Restrict list operations to the hosts given in restriction. This is used
to exclude failed hosts in main playbook code, don't use this for other
reasons.
"""
if type(restriction) != list: if type(restriction) != list:
restriction = [ restriction ] restriction = [ restriction ]
self._restriction = restriction self._restriction = restriction
def subset(self, subset_pattern):
"""
Limits inventory results to a subset of inventory that matches a given
pattern, such as to select a given geographic of numeric slice amongst
a previous 'hosts' selection that only select roles, or vice versa.
Corresponds to --limit parameter to ansible-playbook
"""
if subset_pattern is None:
self._subset = None
else:
self._subset = self.list_hosts(subset_pattern)
def lift_restriction(self): def lift_restriction(self):
""" Do not restrict list operations """ """ Do not restrict list operations """
......
...@@ -57,7 +57,8 @@ class PlayBook(object): ...@@ -57,7 +57,8 @@ class PlayBook(object):
sudo = False, sudo = False,
sudo_user = C.DEFAULT_SUDO_USER, sudo_user = C.DEFAULT_SUDO_USER,
extra_vars = None, extra_vars = None,
only_tags = None): only_tags = None,
subset = C.DEFAULT_SUBSET):
""" """
playbook: path to a playbook file playbook: path to a playbook file
...@@ -104,7 +105,8 @@ class PlayBook(object): ...@@ -104,7 +105,8 @@ class PlayBook(object):
self.private_key_file = private_key_file self.private_key_file = private_key_file
self.only_tags = only_tags self.only_tags = only_tags
self.inventory = ansible.inventory.Inventory(host_list) self.inventory = ansible.inventory.Inventory(host_list)
self.inventory.subset(subset)
if not self.inventory._is_script: if not self.inventory._is_script:
self.global_vars.update(self.inventory.get_group_variables('all')) self.global_vars.update(self.inventory.get_group_variables('all'))
......
...@@ -336,7 +336,8 @@ def increment_debug(option, opt, value, parser): ...@@ -336,7 +336,8 @@ def increment_debug(option, opt, value, parser):
global VERBOSITY global VERBOSITY
VERBOSITY += 1 VERBOSITY += 1
def base_parser(constants=C, usage="", output_opts=False, runas_opts=False, async_opts=False, connect_opts=False): def base_parser(constants=C, usage="", output_opts=False, runas_opts=False,
async_opts=False, connect_opts=False, subset_opts=False):
''' create an options parser for any ansible script ''' ''' create an options parser for any ansible script '''
parser = SortedOptParser(usage, version=version("%prog")) parser = SortedOptParser(usage, version=version("%prog"))
...@@ -357,6 +358,11 @@ def base_parser(constants=C, usage="", output_opts=False, runas_opts=False, asyn ...@@ -357,6 +358,11 @@ def base_parser(constants=C, usage="", output_opts=False, runas_opts=False, asyn
parser.add_option('-M', '--module-path', dest='module_path', parser.add_option('-M', '--module-path', dest='module_path',
help="specify path(s) to module library (default=%s)" % constants.DEFAULT_MODULE_PATH, help="specify path(s) to module library (default=%s)" % constants.DEFAULT_MODULE_PATH,
default=constants.DEFAULT_MODULE_PATH) default=constants.DEFAULT_MODULE_PATH)
if subset_opts:
parser.add_option('-l', '--limit', default=constants.DEFAULT_SUBSET, dest='subset',
help='further limit selected hosts to an additional pattern')
parser.add_option('-T', '--timeout', default=constants.DEFAULT_TIMEOUT, type='int', parser.add_option('-T', '--timeout', default=constants.DEFAULT_TIMEOUT, type='int',
dest='timeout', dest='timeout',
help="override the SSH timeout in seconds (default=%s)" % constants.DEFAULT_TIMEOUT) help="override the SSH timeout in seconds (default=%s)" % constants.DEFAULT_TIMEOUT)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment