#!/usr/bin/python # -*- coding: utf-8 -*- # Copyright Ansible Project # GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt) # SPDX-License-Identifier: GPL-3.0-or-later from __future__ import absolute_import, division, print_function __metaclass__ = type DOCUMENTATION = ''' --- module: rax_scaling_policy short_description: Manipulate Rackspace Cloud Autoscale Scaling Policy description: - Manipulate Rackspace Cloud Autoscale Scaling Policy attributes: check_mode: support: none diff_mode: support: none options: at: type: str description: - The UTC time when this policy will be executed. The time must be formatted according to C(yyyy-MM-dd'T'HH:mm:ss.SSS) such as C(2013-05-19T08:07:08Z) change: type: int description: - The change, either as a number of servers or as a percentage, to make in the scaling group. If this is a percentage, you must set I(is_percent) to C(true) also. cron: type: str description: - The time when the policy will be executed, as a cron entry. For example, if this is parameter is set to C(1 0 * * *) cooldown: type: int description: - The period of time, in seconds, that must pass before any scaling can occur after the previous scaling. Must be an integer between 0 and 86400 (24 hrs). default: 300 desired_capacity: type: int description: - The desired server capacity of the scaling the group; that is, how many servers should be in the scaling group. is_percent: description: - Whether the value in I(change) is a percent value default: false type: bool name: type: str description: - Name to give the policy required: true policy_type: type: str description: - The type of policy that will be executed for the current release. choices: - webhook - schedule required: true scaling_group: type: str description: - Name of the scaling group that this policy will be added to required: true state: type: str description: - Indicate desired state of the resource choices: - present - absent default: present author: "Matt Martz (@sivel)" extends_documentation_fragment: - community.general.rackspace - community.general.rackspace.openstack - community.general.attributes ''' EXAMPLES = ''' --- - hosts: localhost gather_facts: false connection: local tasks: - community.general.rax_scaling_policy: credentials: ~/.raxpub region: ORD at: '2013-05-19T08:07:08Z' change: 25 cooldown: 300 is_percent: true name: ASG Test Policy - at policy_type: schedule scaling_group: ASG Test register: asps_at - community.general.rax_scaling_policy: credentials: ~/.raxpub region: ORD cron: '1 0 * * *' change: 25 cooldown: 300 is_percent: true name: ASG Test Policy - cron policy_type: schedule scaling_group: ASG Test register: asp_cron - community.general.rax_scaling_policy: credentials: ~/.raxpub region: ORD cooldown: 300 desired_capacity: 5 name: ASG Test Policy - webhook policy_type: webhook scaling_group: ASG Test register: asp_webhook ''' try: import pyrax HAS_PYRAX = True except ImportError: HAS_PYRAX = False from ansible.module_utils.basic import AnsibleModule from ansible_collections.community.general.plugins.module_utils.rax import (UUID, rax_argument_spec, rax_required_together, rax_to_dict, setup_rax_module) def rax_asp(module, at=None, change=0, cron=None, cooldown=300, desired_capacity=0, is_percent=False, name=None, policy_type=None, scaling_group=None, state='present'): changed = False au = pyrax.autoscale if not au: module.fail_json(msg='Failed to instantiate client. This ' 'typically indicates an invalid region or an ' 'incorrectly capitalized region name.') try: UUID(scaling_group) except ValueError: try: sg = au.find(name=scaling_group) except Exception as e: module.fail_json(msg='%s' % e.message) else: try: sg = au.get(scaling_group) except Exception as e: module.fail_json(msg='%s' % e.message) if state == 'present': policies = filter(lambda p: name == p.name, sg.list_policies()) if len(policies) > 1: module.fail_json(msg='No unique policy match found by name') if at: args = dict(at=at) elif cron: args = dict(cron=cron) else: args = None if not policies: try: policy = sg.add_policy(name, policy_type=policy_type, cooldown=cooldown, change=change, is_percent=is_percent, desired_capacity=desired_capacity, args=args) changed = True except Exception as e: module.fail_json(msg='%s' % e.message) else: policy = policies[0] kwargs = {} if policy_type != policy.type: kwargs['policy_type'] = policy_type if cooldown != policy.cooldown: kwargs['cooldown'] = cooldown if hasattr(policy, 'change') and change != policy.change: kwargs['change'] = change if hasattr(policy, 'changePercent') and is_percent is False: kwargs['change'] = change kwargs['is_percent'] = False elif hasattr(policy, 'change') and is_percent is True: kwargs['change'] = change kwargs['is_percent'] = True if hasattr(policy, 'desiredCapacity') and change: kwargs['change'] = change elif ((hasattr(policy, 'change') or hasattr(policy, 'changePercent')) and desired_capacity): kwargs['desired_capacity'] = desired_capacity if hasattr(policy, 'args') and args != policy.args: kwargs['args'] = args if kwargs: policy.update(**kwargs) changed = True policy.get() module.exit_json(changed=changed, autoscale_policy=rax_to_dict(policy)) else: try: policies = filter(lambda p: name == p.name, sg.list_policies()) if len(policies) > 1: module.fail_json(msg='No unique policy match found by name') elif not policies: policy = {} else: policy.delete() changed = True except Exception as e: module.fail_json(msg='%s' % e.message) module.exit_json(changed=changed, autoscale_policy=rax_to_dict(policy)) def main(): argument_spec = rax_argument_spec() argument_spec.update( dict( at=dict(), change=dict(type='int'), cron=dict(), cooldown=dict(type='int', default=300), desired_capacity=dict(type='int'), is_percent=dict(type='bool', default=False), name=dict(required=True), policy_type=dict(required=True, choices=['webhook', 'schedule']), scaling_group=dict(required=True), state=dict(default='present', choices=['present', 'absent']), ) ) module = AnsibleModule( argument_spec=argument_spec, required_together=rax_required_together(), mutually_exclusive=[ ['cron', 'at'], ['change', 'desired_capacity'], ] ) if not HAS_PYRAX: module.fail_json(msg='pyrax is required for this module') at = module.params.get('at') change = module.params.get('change') cron = module.params.get('cron') cooldown = module.params.get('cooldown') desired_capacity = module.params.get('desired_capacity') is_percent = module.params.get('is_percent') name = module.params.get('name') policy_type = module.params.get('policy_type') scaling_group = module.params.get('scaling_group') state = module.params.get('state') if (at or cron) and policy_type == 'webhook': module.fail_json(msg='policy_type=schedule is required for a time ' 'based policy') setup_rax_module(module, pyrax) rax_asp(module, at=at, change=change, cron=cron, cooldown=cooldown, desired_capacity=desired_capacity, is_percent=is_percent, name=name, policy_type=policy_type, scaling_group=scaling_group, state=state) if __name__ == '__main__': main()