[cloud] New module aws_scaling_policy (#31241)
* Add scaling_policy module * Change exception format * Rename scaling_policy module to aws_application_scaling_policy
This commit is contained in:
parent
18ea816a0e
commit
8fba6e6684
1 changed files with 294 additions and 0 deletions
|
@ -0,0 +1,294 @@
|
||||||
|
#!/usr/bin/python
|
||||||
|
# Copyright: Ansible Project
|
||||||
|
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||||
|
|
||||||
|
from __future__ import absolute_import, division, print_function
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
|
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||||
|
'status': ['preview'],
|
||||||
|
'supported_by': 'community'}
|
||||||
|
|
||||||
|
|
||||||
|
DOCUMENTATION = '''
|
||||||
|
---
|
||||||
|
module: aws_application_scaling_policy
|
||||||
|
short_description: Manage Application Auto Scaling Scaling Policies
|
||||||
|
notes:
|
||||||
|
- for details of the parameters and returns see
|
||||||
|
U(http://boto3.readthedocs.io/en/latest/reference/services/application-autoscaling.html#ApplicationAutoScaling.Client.put_scaling_policy)
|
||||||
|
description:
|
||||||
|
- Creates, updates or removes a Scaling Policy
|
||||||
|
version_added: "2.5"
|
||||||
|
author:
|
||||||
|
- Gustavo Maia(@gurumaia)
|
||||||
|
requirements: [ json, botocore, boto3 ]
|
||||||
|
options:
|
||||||
|
policy_name:
|
||||||
|
description: The name of the scaling policy.
|
||||||
|
required: yes
|
||||||
|
service_namespace:
|
||||||
|
description: The namespace of the AWS service.
|
||||||
|
required: yes
|
||||||
|
choices: ['ecs', 'elasticmapreduce', 'ec2', 'appstream', 'dynamodb']
|
||||||
|
resource_id:
|
||||||
|
description: The identifier of the resource associated with the scalable target.
|
||||||
|
required: yes
|
||||||
|
scalable_dimension:
|
||||||
|
description: The scalable dimension associated with the scalable target.
|
||||||
|
required: yes
|
||||||
|
choices: [ 'ecs:service:DesiredCount',
|
||||||
|
'ec2:spot-fleet-request:TargetCapacity',
|
||||||
|
'elasticmapreduce:instancegroup:InstanceCount',
|
||||||
|
'appstream:fleet:DesiredCapacity',
|
||||||
|
'dynamodb:table:ReadCapacityUnits',
|
||||||
|
'dynamodb:table:WriteCapacityUnits',
|
||||||
|
'dynamodb:index:ReadCapacityUnits',
|
||||||
|
'dynamodb:index:WriteCapacityUnits']
|
||||||
|
policy_type:
|
||||||
|
description: The policy type.
|
||||||
|
required: yes
|
||||||
|
choices: ['StepScaling', 'TargetTrackingScaling']
|
||||||
|
step_scaling_policy_configuration:
|
||||||
|
description: A step scaling policy. This parameter is required if you are creating a policy and the policy type is StepScaling.
|
||||||
|
required: no
|
||||||
|
target_tracking_scaling_policy_configuration:
|
||||||
|
description: A target tracking policy. This parameter is required if you are creating a new policy and the policy type is TargetTrackingScaling.
|
||||||
|
required: no
|
||||||
|
extends_documentation_fragment:
|
||||||
|
- aws
|
||||||
|
- ec2
|
||||||
|
'''
|
||||||
|
|
||||||
|
EXAMPLES = '''
|
||||||
|
# Note: These examples do not set authentication details, see the AWS Guide for details.
|
||||||
|
|
||||||
|
# Create scaling policy for ECS Service
|
||||||
|
- name: scaling_policy
|
||||||
|
aws_application_scaling_policy:
|
||||||
|
state: present
|
||||||
|
policy_name: test_policy
|
||||||
|
service_namespace: ecs
|
||||||
|
resource_id: service/poc-pricing/test-as
|
||||||
|
scalable_dimension: ecs:service:DesiredCount
|
||||||
|
policy_type: StepScaling
|
||||||
|
step_scaling_policy_configuration:
|
||||||
|
AdjustmentType: ChangeInCapacity
|
||||||
|
StepAdjustments:
|
||||||
|
- MetricIntervalUpperBound: 123
|
||||||
|
ScalingAdjustment: 2
|
||||||
|
- MetricIntervalLowerBound: 123
|
||||||
|
ScalingAdjustment: -2
|
||||||
|
Cooldown: 123
|
||||||
|
MetricAggregationType: Average
|
||||||
|
|
||||||
|
# Remove scalable target for ECS Service
|
||||||
|
- name: scaling_policy
|
||||||
|
aws_application_scaling_policy:
|
||||||
|
state: absent
|
||||||
|
policy_name: test_policy
|
||||||
|
policy_type: StepScaling
|
||||||
|
service_namespace: ecs
|
||||||
|
resource_id: service/cluster-name/service-name
|
||||||
|
scalable_dimension: ecs:service:DesiredCount
|
||||||
|
'''
|
||||||
|
|
||||||
|
RETURN = '''
|
||||||
|
service_namespace:
|
||||||
|
description: The namespace of the AWS service.
|
||||||
|
returned: when state present
|
||||||
|
type: string
|
||||||
|
sample: ecs
|
||||||
|
resource_id:
|
||||||
|
description: The identifier of the resource associated with the scalable target.
|
||||||
|
returned: when state present
|
||||||
|
type: string
|
||||||
|
sample: service/cluster-name/service-name
|
||||||
|
scalable_dimension:
|
||||||
|
description: The scalable dimension associated with the scalable target.
|
||||||
|
returned: when state present
|
||||||
|
type: string
|
||||||
|
sample: ecs:service:DesiredCount
|
||||||
|
min_capacity:
|
||||||
|
description: The minimum value to scale to in response to a scale in event. Required if I(state) is C(present).
|
||||||
|
returned: when state present
|
||||||
|
type: int
|
||||||
|
sample: 1
|
||||||
|
max_capacity:
|
||||||
|
description: The maximum value to scale to in response to a scale out event. Required if I(state) is C(present).
|
||||||
|
returned: when state present
|
||||||
|
type: int
|
||||||
|
sample: 2
|
||||||
|
role_arn:
|
||||||
|
description: The ARN of an IAM role that allows Application Auto Scaling to modify the scalable target on your behalf. Required if I(state) is C(present).
|
||||||
|
returned: when state present
|
||||||
|
type: string
|
||||||
|
sample: arn:aws:iam::123456789123:role/roleName
|
||||||
|
creation_time:
|
||||||
|
description: The Unix timestamp for when the scalable target was created.
|
||||||
|
returned: when state present
|
||||||
|
type: string
|
||||||
|
sample: '2017-09-28T08:22:51.881000-03:00'
|
||||||
|
''' # NOQA
|
||||||
|
|
||||||
|
import traceback
|
||||||
|
|
||||||
|
try:
|
||||||
|
import boto3
|
||||||
|
HAS_BOTO3 = True
|
||||||
|
except ImportError:
|
||||||
|
HAS_BOTO3 = False
|
||||||
|
|
||||||
|
from ansible.module_utils.basic import AnsibleModule
|
||||||
|
from ansible.module_utils.ec2 import _camel_to_snake, camel_dict_to_snake_dict, boto3_conn, ec2_argument_spec, get_aws_connection_info
|
||||||
|
|
||||||
|
try:
|
||||||
|
import botocore
|
||||||
|
except ImportError:
|
||||||
|
pass # will be detected by imported HAS_BOTO3
|
||||||
|
|
||||||
|
|
||||||
|
def delete_scaling_policy(connection, module):
|
||||||
|
changed = False
|
||||||
|
scaling_policy = connection.describe_scaling_policies(
|
||||||
|
ServiceNamespace=module.params.get('service_namespace'),
|
||||||
|
ResourceId=module.params.get('resource_id'),
|
||||||
|
ScalableDimension=module.params.get('scalable_dimension'),
|
||||||
|
PolicyNames=[module.params.get('policy_name')],
|
||||||
|
MaxResults=1
|
||||||
|
)
|
||||||
|
|
||||||
|
if scaling_policy['ScalingPolicies']:
|
||||||
|
try:
|
||||||
|
connection.delete_scaling_policy(
|
||||||
|
ServiceNamespace=module.params.get('service_namespace'),
|
||||||
|
ResourceId=module.params.get('resource_id'),
|
||||||
|
ScalableDimension=module.params.get('scalable_dimension'),
|
||||||
|
PolicyName=module.params.get('policy_name'),
|
||||||
|
)
|
||||||
|
changed = True
|
||||||
|
except Exception as e:
|
||||||
|
module.fail_json(msg=str(e), exception=traceback.format_exc())
|
||||||
|
|
||||||
|
module.exit_json(changed=changed)
|
||||||
|
|
||||||
|
|
||||||
|
def create_scaling_policy(connection, module):
|
||||||
|
scaling_policy = connection.describe_scaling_policies(
|
||||||
|
ServiceNamespace=module.params.get('service_namespace'),
|
||||||
|
ResourceId=module.params.get('resource_id'),
|
||||||
|
ScalableDimension=module.params.get('scalable_dimension'),
|
||||||
|
PolicyNames=[module.params.get('policy_name')],
|
||||||
|
MaxResults=1
|
||||||
|
)
|
||||||
|
|
||||||
|
changed = False
|
||||||
|
|
||||||
|
if scaling_policy['ScalingPolicies']:
|
||||||
|
scaling_policy = scaling_policy['ScalingPolicies'][0]
|
||||||
|
# check if the input parameters are equal to what's already configured
|
||||||
|
for attr in ('PolicyName',
|
||||||
|
'ServiceNamespace',
|
||||||
|
'ResourceId',
|
||||||
|
'ScalableDimension',
|
||||||
|
'PolicyType',
|
||||||
|
'StepScalingPolicyConfiguration',
|
||||||
|
'TargetTrackingScalingPolicyConfiguration'):
|
||||||
|
if attr in scaling_policy and scaling_policy[attr] != module.params.get(_camel_to_snake(attr)):
|
||||||
|
changed = True
|
||||||
|
scaling_policy[attr] = module.params.get(_camel_to_snake(attr))
|
||||||
|
else:
|
||||||
|
changed = True
|
||||||
|
scaling_policy = {
|
||||||
|
'PolicyName': module.params.get('policy_name'),
|
||||||
|
'ServiceNamespace': module.params.get('service_namespace'),
|
||||||
|
'ResourceId': module.params.get('resource_id'),
|
||||||
|
'ScalableDimension': module.params.get('scalable_dimension'),
|
||||||
|
'PolicyType': module.params.get('policy_type'),
|
||||||
|
'StepScalingPolicyConfiguration': module.params.get('step_scaling_policy_configuration'),
|
||||||
|
'TargetTrackingScalingPolicyConfiguration': module.params.get('target_tracking_scaling_policy_configuration')
|
||||||
|
}
|
||||||
|
|
||||||
|
if changed:
|
||||||
|
try:
|
||||||
|
if (module.params.get('step_scaling_policy_configuration')):
|
||||||
|
connection.put_scaling_policy(
|
||||||
|
PolicyName=scaling_policy['PolicyName'],
|
||||||
|
ServiceNamespace=scaling_policy['ServiceNamespace'],
|
||||||
|
ResourceId=scaling_policy['ResourceId'],
|
||||||
|
ScalableDimension=scaling_policy['ScalableDimension'],
|
||||||
|
PolicyType=scaling_policy['PolicyType'],
|
||||||
|
StepScalingPolicyConfiguration=scaling_policy['StepScalingPolicyConfiguration']
|
||||||
|
)
|
||||||
|
elif (module.params.get('target_tracking_scaling_policy_configuration')):
|
||||||
|
connection.put_scaling_policy(
|
||||||
|
PolicyName=scaling_policy['PolicyName'],
|
||||||
|
ServiceNamespace=scaling_policy['ServiceNamespace'],
|
||||||
|
ResourceId=scaling_policy['ResourceId'],
|
||||||
|
ScalableDimension=scaling_policy['ScalableDimension'],
|
||||||
|
PolicyType=scaling_policy['PolicyType'],
|
||||||
|
TargetTrackingScalingPolicyConfiguration=scaling_policy['TargetTrackingScalingPolicyConfiguration']
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
module.fail_json(msg=str(e), exception=traceback.format_exc())
|
||||||
|
|
||||||
|
try:
|
||||||
|
response = connection.describe_scaling_policies(
|
||||||
|
ServiceNamespace=module.params.get('service_namespace'),
|
||||||
|
ResourceId=module.params.get('resource_id'),
|
||||||
|
ScalableDimension=module.params.get('scalable_dimension'),
|
||||||
|
PolicyNames=[module.params.get('policy_name')],
|
||||||
|
MaxResults=1
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
module.fail_json(msg=str(e), exception=traceback.format_exc())
|
||||||
|
|
||||||
|
if (response['ScalingPolicies']):
|
||||||
|
snaked_response = camel_dict_to_snake_dict(response['ScalingPolicies'][0])
|
||||||
|
else:
|
||||||
|
snaked_response = {}
|
||||||
|
module.exit_json(changed=changed, response=snaked_response)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
argument_spec = ec2_argument_spec()
|
||||||
|
argument_spec.update(dict(
|
||||||
|
state=dict(required=True, choices=['present', 'absent'], type='str'),
|
||||||
|
policy_name=dict(required=True, type='str'),
|
||||||
|
service_namespace=dict(required=True, choices=['ecs', 'elasticmapreduce', 'ec2', 'appstream', 'dynamodb'], type='str'),
|
||||||
|
resource_id=dict(required=True, type='str'),
|
||||||
|
scalable_dimension=dict(required=True, choices=['ecs:service:DesiredCount',
|
||||||
|
'ec2:spot-fleet-request:TargetCapacity',
|
||||||
|
'elasticmapreduce:instancegroup:InstanceCount',
|
||||||
|
'appstream:fleet:DesiredCapacity',
|
||||||
|
'dynamodb:table:ReadCapacityUnits',
|
||||||
|
'dynamodb:table:WriteCapacityUnits',
|
||||||
|
'dynamodb:index:ReadCapacityUnits',
|
||||||
|
'dynamodb:index:WriteCapacityUnits'
|
||||||
|
], type='str'),
|
||||||
|
policy_type=dict(required=True, choices=['StepScaling', 'TargetTrackingScaling'], type='str'),
|
||||||
|
step_scaling_policy_configuration=dict(required=False, type='dict'),
|
||||||
|
target_tracking_scaling_policy_configuration=dict(required=False, type='dict')
|
||||||
|
))
|
||||||
|
|
||||||
|
module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True)
|
||||||
|
|
||||||
|
if not HAS_BOTO3:
|
||||||
|
module.fail_json(msg='boto3 is required.')
|
||||||
|
|
||||||
|
try:
|
||||||
|
region, ec2_url, aws_connect_kwargs = get_aws_connection_info(module, boto3=True)
|
||||||
|
if not region:
|
||||||
|
module.fail_json(msg="Region must be specified as a parameter, in EC2_REGION or AWS_REGION environment variables or in boto configuration file")
|
||||||
|
connection = boto3_conn(module, conn_type='client', resource='application-autoscaling', region=region, endpoint=ec2_url, **aws_connect_kwargs)
|
||||||
|
except botocore.exceptions.ProfileNotFound as e:
|
||||||
|
module.fail_json(msg=str(e))
|
||||||
|
|
||||||
|
if module.params.get("state") == 'present':
|
||||||
|
create_scaling_policy(connection, module)
|
||||||
|
else:
|
||||||
|
delete_scaling_policy(connection, module)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
Loading…
Reference in a new issue