c7b7169c79
The dist-sort module has been updated to ensure its execution is effective, fast, and nonintrusive. There are cases where the rounds made by the module take an excessive amount of time to complete. This change ensures that the module is limiting its rounds to a known index and the iterable is processed using a generator. Change-Id: I03d1f70cb6cd17f38ef37b4d8371a8982beca29e Signed-off-by: Kevin Carter <kevin.carter@rackspace.com>
174 lines
5.1 KiB
Python
174 lines
5.1 KiB
Python
#!/usr/bin/env python
|
|
# (c) 2014, Kevin Carter <kevin.carter@rackspace.com>
|
|
#
|
|
# Copyright 2014, Rackspace US, Inc.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
|
|
|
|
# import module snippets
|
|
from ansible.module_utils.basic import *
|
|
|
|
|
|
DOCUMENTATION = """
|
|
---
|
|
module: dist_sort
|
|
version_added: "1.6.6"
|
|
short_description:
|
|
- Deterministically sort a list to distribute the elements in the list
|
|
evenly. Based on external values such as host or static modifier. Returns
|
|
a string as named key ``sorted_list``.
|
|
description:
|
|
- This module returns a list of servers uniquely sorted based on a index
|
|
from a look up value location within a group. The group should be an
|
|
existing ansible inventory group. This will module returns the sorted
|
|
list as a delimited string.
|
|
options:
|
|
src_list:
|
|
description:
|
|
- list in the form of a string separated by a delimiter.
|
|
required: True
|
|
ref_list:
|
|
description:
|
|
- list to lookup value_to_lookup against to return index number
|
|
This should be a pre-determined ansible group containing the
|
|
``value_to_lookup``.
|
|
required: False
|
|
value_to_lookup:
|
|
description:
|
|
- value is looked up against ref_list to get index number.
|
|
required: False
|
|
sort_modifier:
|
|
description:
|
|
- add a static int into the sort equation to weight the output.
|
|
type: int
|
|
default: 0
|
|
delimiter:
|
|
description:
|
|
- delimiter used to parse ``src_list`` with.
|
|
default: ','
|
|
author:
|
|
- Kevin Carter
|
|
- Sam Yaple
|
|
"""
|
|
|
|
|
|
EXAMPLES = """
|
|
- dist_sort:
|
|
value_to_lookup: "Hostname-in-ansible-group_name"
|
|
ref_list: "{{ groups['group_name'] }}"
|
|
src_list: "Server1,Server2,Server3"
|
|
register: test_var
|
|
|
|
# With a pre-set delimiter
|
|
- dist_sort:
|
|
value_to_lookup: "Hostname-in-ansible-group_name"
|
|
ref_list: "{{ groups['group_name'] }}"
|
|
src_list: "Server1|Server2|Server3"
|
|
delimiter: '|'
|
|
register: test_var
|
|
|
|
# With a set modifier
|
|
- dist_sort:
|
|
value_to_lookup: "Hostname-in-ansible-group_name"
|
|
ref_list: "{{ groups['group_name'] }}"
|
|
src_list: "Server1#Server2#Server3"
|
|
delimiter: '#'
|
|
sort_modifier: 5
|
|
register: test_var
|
|
"""
|
|
|
|
|
|
class DistSort(object):
|
|
def __init__(self, module):
|
|
"""Deterministically sort a list of servers.
|
|
|
|
:param module: The active ansible module.
|
|
:type module: ``class``
|
|
"""
|
|
self.module = module
|
|
self.params = self.module.params
|
|
self.return_data = self._runner()
|
|
|
|
def _runner(self):
|
|
"""Return the sorted list of servers.
|
|
|
|
Based on the modulo of index of a *value_to_lookup* from an ansible
|
|
group this function will return a comma "delimiter" separated list of
|
|
items.
|
|
|
|
:returns: ``str``
|
|
"""
|
|
try:
|
|
index = self.params['ref_list'].index(
|
|
self.params['value_to_lookup']
|
|
)
|
|
except ValueError:
|
|
index = 0
|
|
|
|
src_list = self.params['src_list'].split(self.params['delimiter'])
|
|
index += self.params['sort_modifier']
|
|
for _ in xrange(index % len(src_list)):
|
|
src_list.append(src_list.pop(0))
|
|
|
|
return self.params['delimiter'].join(src_list)
|
|
|
|
|
|
def main():
|
|
"""Run the main app."""
|
|
module = AnsibleModule(
|
|
argument_spec=dict(
|
|
value_to_lookup=dict(
|
|
required=True,
|
|
type='str'
|
|
),
|
|
ref_list=dict(
|
|
required=True,
|
|
type='list'
|
|
),
|
|
src_list=dict(
|
|
required=True,
|
|
type='str'
|
|
),
|
|
delimiter=dict(
|
|
required=False,
|
|
type='str',
|
|
default=','
|
|
),
|
|
sort_modifier=dict(
|
|
required=False,
|
|
type='str',
|
|
default='0'
|
|
)
|
|
),
|
|
supports_check_mode=False
|
|
)
|
|
try:
|
|
# This is done so that the failure can be parsed and does not cause
|
|
# ansible to fail if a non-int is passed.
|
|
module.params['sort_modifier'] = int(module.params['sort_modifier'])
|
|
_ds = DistSort(module=module)
|
|
if _ds.return_data == module.params['src_list']:
|
|
_changed = False
|
|
else:
|
|
_changed = True
|
|
except Exception as exp:
|
|
resp = {'stderr': str(exp)}
|
|
resp.update(module.params)
|
|
module.fail_json(msg='Failed Process', **resp)
|
|
else:
|
|
module.exit_json(changed=_changed, **{'sorted_list': _ds.return_data})
|
|
|
|
if __name__ == '__main__':
|
|
main()
|