Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] new module - autoscaling_instance #2296

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions meta/runtime.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
requires_ansible: ">=2.15.0"
action_groups:
aws:
- autoscaling_instance
- autoscaling_instance_info
- autoscaling_group
- autoscaling_group_info
- aws_az_info
Expand Down
Empty file.
25 changes: 25 additions & 0 deletions plugins/module_utils/_autoscaling/common.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# -*- coding: utf-8 -*-

# Copyright: Contributors to the Ansible project
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)

# try:
# import botocore
# except ImportError:
# pass # Modules are responsible for handling this.

from ..botocore import is_boto3_error_code
from ..errors import AWSErrorHandler
from ..exceptions import AnsibleAWSError


class AnsibleAutoScalingError(AnsibleAWSError):
pass


class AutoScalingErrorHandler(AWSErrorHandler):
_CUSTOM_EXCEPTION = AnsibleAutoScalingError

@classmethod
def _is_missing(cls):
return is_boto3_error_code("NoSuchEntity")
22 changes: 22 additions & 0 deletions plugins/module_utils/_autoscaling/groups.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# -*- coding: utf-8 -*-

# Copyright: Contributors to the Ansible project
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)

from ..retries import AWSRetry

# from .common import AnsibleAutoScalingError
from .common import AutoScalingErrorHandler


@AutoScalingErrorHandler.list_error_handler("list auto scaling groups", default_value=[])
@AWSRetry.jittered_backoff()
def describe_auto_scaling_groups(client, group_names=None, filters=None):
args = {}
if group_names:
args["AutoScalingGroupNames"] = group_names
if filters:
args["Filters"] = filters

paginator = client.get_paginator("describe_auto_scaling_groups")
return paginator.paginate(**args).build_full_result()["AutoScalingGroups"]
20 changes: 20 additions & 0 deletions plugins/module_utils/_autoscaling/instances.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-

# Copyright: Contributors to the Ansible project
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)

from ..retries import AWSRetry

# from .common import AnsibleAutoScalingError
from .common import AutoScalingErrorHandler


@AutoScalingErrorHandler.list_error_handler("list auto scaling instances", default_value=[])
@AWSRetry.jittered_backoff()
def describe_auto_scaling_instances(client, instance_ids=None):
args = {}
if instance_ids:
args["InstanceIds"] = instance_ids

paginator = client.get_paginator("describe_auto_scaling_instances")
return paginator.paginate(**args).build_full_result()["AutoScalingInstances"]
60 changes: 60 additions & 0 deletions plugins/module_utils/_autoscaling/transformations.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# -*- coding: utf-8 -*-

# Copyright: Contributors to the Ansible project
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)

from typing import Optional

# from ..transformation import AnsibleAWSResource
from ..transformation import AnsibleAWSResourceList
from ..transformation import BotoResource
from ..transformation import BotoResourceList
from ..transformation import boto3_resource_to_ansible_dict

# from ..transformation import boto3_resource_list_to_ansible_dict


def _inject_asg_name(
instance: BotoResource,
group_name: Optional[str] = None,
) -> BotoResource:
if not group_name:
return instance
if "AutoScalingGroupName" in instance:
return instance
instance["AutoScalingGroupName"] = group_name
return instance


def normalize_autoscaling_instance(
instance: BotoResource,
group_name: Optional[str] = None,
):
"""Converts an AutoScaling Instance from the CamelCase boto3 format to the snake_case Ansible format.

Also handles inconsistencies in the output between describe_autoscaling_group() and describe_autoscaling_instances().
"""
if not instance:
return instance

# describe_autoscaling_group doesn't add AutoScalingGroupName
instance = _inject_asg_name(instance, group_name)

try:
# describe_autoscaling_group and describe_autoscaling_instances aren't consistent
instance["HealthStatus"] = instance["HealthStatus"].upper()
except KeyError:
pass

return boto3_resource_to_ansible_dict(instance, force_tags=False)


def normalize_autoscaling_instances(
autoscaling_instances: BotoResourceList,
group_name: Optional[str] = None,
) -> AnsibleAWSResourceList:
"""Converts a list of AutoScaling Instances from the CamelCase boto3 format to the snake_case Ansible format"""
if not autoscaling_instances:
return autoscaling_instances
autoscaling_instances = [normalize_autoscaling_instance(i, group_name) for i in autoscaling_instances]
return sorted(autoscaling_instances, key=lambda d: d.get("instance_id", None))
32 changes: 32 additions & 0 deletions plugins/module_utils/autoscaling.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# -*- coding: utf-8 -*-

# Copyright: Contributors to the Ansible project
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)

# It would be nice to be able to use autoscaling.XYZ, but we're bound by Ansible's "empty-init"
# policy: https://docs.ansible.com/ansible-core/devel/dev_guide/testing/sanity/empty-init.html

from ._autoscaling import groups as _groups
from ._autoscaling import instances as _instances
from ._autoscaling import transformations as _transformations
from ._autoscaling.common import AnsibleAutoScalingError # pylint: disable=unused-import
from ._autoscaling.common import AutoScalingErrorHandler # pylint: disable=unused-import


def get_autoscaling_groups(client, group_names=None):
return _groups.describe_auto_scaling_groups(client, group_names)


def _get_autoscaling_instances(client, instance_ids=None, group_name=None):
if group_name:
try:
groups = _groups.describe_auto_scaling_groups(client, [group_name])
return groups[0]["Instances"]
except (KeyError, IndexError):
return None
return _instances.describe_auto_scaling_instances(client, instance_ids)


def get_autoscaling_instances(client, instance_ids=None, group_name=None):
instances = _get_autoscaling_instances(client, instance_ids=instance_ids, group_name=group_name)
return _transformations.normalize_autoscaling_instances(instances, group_name=group_name)
Loading
Loading