mirror of
https://github.com/valitydev/salt.git
synced 2024-11-07 17:09:03 +00:00
Merge pull request #40263 from deuscapturus/boto_elbv2
Add boto_elbv2 states and modules for de/registering targets and chec…
This commit is contained in:
commit
9d11993f38
200
salt/modules/boto_elbv2.py
Normal file
200
salt/modules/boto_elbv2.py
Normal file
@ -0,0 +1,200 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
'''
|
||||
Connection module for Amazon ALB
|
||||
|
||||
.. versionadded:: TBD
|
||||
|
||||
:configuration: This module accepts explicit elb credentials but can also utilize
|
||||
IAM roles assigned to the instance through Instance Profiles. Dynamic
|
||||
credentials are then automatically obtained from AWS API and no further
|
||||
configuration is necessary. More Information available at:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html
|
||||
|
||||
If IAM roles are not used you need to specify them either in a pillar or
|
||||
in the minion's config file:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
elbv2.keyid: GKTADJGHEIQSXMKKRBJ08H
|
||||
elbv2.key: askdjghsdfjkghWupUjasdflkdfklgjsdfjajkghs
|
||||
elbv2.region: us-west-2
|
||||
|
||||
If a region is not specified, the default is us-east-1.
|
||||
|
||||
It's also possible to specify key, keyid and region via a profile, either
|
||||
as a passed in dict, or as a string to pull from pillars or minion config:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
myprofile:
|
||||
keyid: GKTADJGHEIQSXMKKRBJ08H
|
||||
key: askdjghsdfjkghWupUjasdflkdfklgjsdfjajkghs
|
||||
region: us-east-1
|
||||
'''
|
||||
# keep lint from choking on _get_conn and _cache_id
|
||||
# pylint: disable=E0602
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
# Import Python libs
|
||||
import logging
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
# Import Salt libs
|
||||
|
||||
# Import third party libs
|
||||
import salt.ext.six as six
|
||||
|
||||
try:
|
||||
# pylint: disable=unused-import
|
||||
import salt.utils.boto3
|
||||
# pylint: enable=unused-import
|
||||
|
||||
# TODO Version check using salt.utils.versions
|
||||
from botocore.exceptions import ClientError
|
||||
logging.getLogger('boto3').setLevel(logging.CRITICAL)
|
||||
HAS_BOTO = True
|
||||
except ImportError:
|
||||
HAS_BOTO = False
|
||||
|
||||
|
||||
def __virtual__():
|
||||
'''
|
||||
Only load if boto3 libraries exist.
|
||||
'''
|
||||
if not HAS_BOTO:
|
||||
return (False, "The boto_elbv2 module cannot be loaded: boto3 library not found")
|
||||
__utils__['boto3.assign_funcs'](__name__, 'elbv2')
|
||||
return True
|
||||
|
||||
|
||||
def target_group_exists(name, region=None, key=None, keyid=None, profile=None):
|
||||
'''
|
||||
Check to see if an target group exists.
|
||||
|
||||
CLI example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt myminion boto_elbv2.exists arn:aws:elasticloadbalancing:us-west-2:644138682826:targetgroup/learn1give1-api/414788a16b5cf163
|
||||
'''
|
||||
conn = _get_conn(region=region, key=key, keyid=keyid, profile=profile)
|
||||
|
||||
try:
|
||||
alb = conn.describe_target_groups(TargetGroupArns=[name])
|
||||
if alb:
|
||||
return True
|
||||
else:
|
||||
log.warning('The target group does not exist in region {0}'.format(region))
|
||||
return False
|
||||
except ClientError as error:
|
||||
log.warning(error)
|
||||
return False
|
||||
|
||||
|
||||
def describe_target_health(name, targets=None, region=None, key=None, keyid=None, profile=None):
|
||||
'''
|
||||
Get the curret health check status for targets in a target group.
|
||||
|
||||
CLI example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt myminion boto_elbv2.describe_target_health arn:aws:elasticloadbalancing:us-west-2:644138682826:targetgroup/learn1give1-api/414788a16b5cf163 targets=["i-isdf23ifjf"]
|
||||
'''
|
||||
conn = _get_conn(region=region, key=key, keyid=keyid, profile=profile)
|
||||
|
||||
try:
|
||||
if targets:
|
||||
targetsdict = []
|
||||
for target in targets:
|
||||
targetsdict.append({"Id": target})
|
||||
instances = conn.describe_target_health(TargetGroupArn=name, Targets=targetsdict)
|
||||
else:
|
||||
instances = conn.describe_target_health(TargetGroupArn=name)
|
||||
ret = {}
|
||||
for instance in instances['TargetHealthDescriptions']:
|
||||
ret.update({instance['Target']['Id']: instance['TargetHealth']['State']})
|
||||
|
||||
return ret
|
||||
except ClientError as error:
|
||||
log.warning(error)
|
||||
return {}
|
||||
|
||||
|
||||
def register_targets(name, targets, region=None, key=None, keyid=None,
|
||||
profile=None):
|
||||
'''
|
||||
Register targets to a target froup of an ALB. ``targets`` is either a
|
||||
instance id string or a list of instance id's.
|
||||
|
||||
Returns:
|
||||
|
||||
- ``True``: instance(s) registered successfully
|
||||
- ``False``: instance(s) failed to be registered
|
||||
|
||||
CLI example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt myminion boto_elbv2.register_targets myelb instance_id
|
||||
salt myminion boto_elbv2.register_targets myelb "[instance_id,instance_id]"
|
||||
'''
|
||||
targetsdict = []
|
||||
if isinstance(targets, str) or isinstance(targets, six.text_type):
|
||||
targetsdict.append({"Id": targets})
|
||||
else:
|
||||
for target in targets:
|
||||
targetsdict.append({"Id": target})
|
||||
conn = _get_conn(region=region, key=key, keyid=keyid, profile=profile)
|
||||
|
||||
try:
|
||||
registered_targets = conn.register_targets(TargetGroupArn=name, Targets=targetsdict)
|
||||
if registered_targets:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
except ClientError as error:
|
||||
log.warning(error)
|
||||
return False
|
||||
|
||||
|
||||
def deregister_targets(name, targets, region=None, key=None, keyid=None,
|
||||
profile=None):
|
||||
'''
|
||||
Deregister targets to a target froup of an ALB. ``targets`` is either a
|
||||
instance id string or a list of instance id's.
|
||||
|
||||
Returns:
|
||||
|
||||
- ``True``: instance(s) deregistered successfully
|
||||
- ``False``: instance(s) failed to be deregistered
|
||||
|
||||
CLI example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt myminion boto_elbv2.deregister_targets myelb instance_id
|
||||
salt myminion boto_elbv2.deregister_targets myelb "[instance_id,instance_id]"
|
||||
'''
|
||||
targetsdict = []
|
||||
if isinstance(targets, str) or isinstance(targets, six.text_type):
|
||||
targetsdict.append({"Id": targets})
|
||||
else:
|
||||
for target in targets:
|
||||
targetsdict.append({"Id": target})
|
||||
conn = _get_conn(region=region, key=key, keyid=keyid, profile=profile)
|
||||
|
||||
try:
|
||||
registered_targets = conn.deregister_targets(TargetGroupArn=name, Targets=targetsdict)
|
||||
if registered_targets:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
except ClientError as error:
|
||||
log.warning(error)
|
||||
return False
|
195
salt/states/boto_elbv2.py
Normal file
195
salt/states/boto_elbv2.py
Normal file
@ -0,0 +1,195 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
'''
|
||||
Manage AWS Application Load Balancer
|
||||
|
||||
.. versionadded:: TBD
|
||||
|
||||
Add and remove targets from an ALB target group.
|
||||
|
||||
This module uses ``boto3``, which can be installed via package, or pip.
|
||||
|
||||
This module accepts explicit alb credentials but can also utilize
|
||||
IAM roles assigned to the instance through Instance Profiles. Dynamic
|
||||
credentials are then automatically obtained from AWS API and no further
|
||||
configuration is necessary. More information available `here
|
||||
<http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html>`_.
|
||||
|
||||
If IAM roles are not used you need to specify them either in a pillar file or
|
||||
in the minion's config file:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
elbv2.keyid: GKTADJGHEIQSXMKKRBJ08H
|
||||
elbv2.key: askdjghsdfjkghWupUjasdflkdfklgjsdfjajkghs
|
||||
elbv2.region: us-west-2
|
||||
|
||||
It's also possible to specify ``key``, ``keyid`` and ``region`` via a profile, either
|
||||
passed in as a dict, or as a string to pull from pillars or minion config:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
myprofile:
|
||||
keyid: GKTADJGHEIQSXMKKRBJ08H
|
||||
key: askdjghsdfjkghWupUjasdflkdfklgjsdfjajkghs
|
||||
region: us-east-1
|
||||
'''
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
# Import Python Libs
|
||||
import logging
|
||||
import copy
|
||||
|
||||
# Import Salt Libs
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def __virtual__():
|
||||
'''
|
||||
Only load if boto is available.
|
||||
'''
|
||||
return 'boto_elbv2' if 'boto_elbv2.target_group_exists' in __salt__ else False
|
||||
|
||||
|
||||
def targets_registered(name, targets, region=None, key=None, keyid=None,
|
||||
profile=None):
|
||||
'''
|
||||
Add targets to an Application Load Balancer target group. This state will not remove targets.
|
||||
|
||||
name
|
||||
The ARN of the Application Load Balancer Target Group to add targets to.
|
||||
|
||||
targets
|
||||
A list of target IDs or a string of a single target that this target group should
|
||||
distribute traffic to.
|
||||
|
||||
.. versionadded:: TBD
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
add-targets:
|
||||
boto_elb.targets_registered:
|
||||
- name: arn:myloadbalancer
|
||||
- targets:
|
||||
- instance-id1
|
||||
- instance-id2
|
||||
'''
|
||||
ret = {'name': name, 'result': None, 'comment': '', 'changes': {}}
|
||||
tg = __salt__['boto_elbv2.target_group_exists'](name, region, key, keyid, profile)
|
||||
|
||||
if tg:
|
||||
health = __salt__['boto_elbv2.describe_target_health'](name, region=region, key=key, keyid=keyid, profile=profile)
|
||||
failure = False
|
||||
changes = False
|
||||
newhealth_mock = copy.copy(health)
|
||||
|
||||
if isinstance(targets, str):
|
||||
targets = [targets]
|
||||
|
||||
for target in targets:
|
||||
if target in health and health.get(target) != "draining":
|
||||
ret['comment'] = ret['comment'] + 'Target/s {0} already registered and is {1}.\n'.format(target, health[target])
|
||||
ret['result'] = True
|
||||
else:
|
||||
if __opts__['test']:
|
||||
changes = True
|
||||
newhealth_mock.update({target: "initial"})
|
||||
else:
|
||||
state = __salt__['boto_elbv2.register_targets'](name,
|
||||
targets,
|
||||
region,
|
||||
key,
|
||||
keyid,
|
||||
profile)
|
||||
if state:
|
||||
changes = True
|
||||
ret['result'] = True
|
||||
else:
|
||||
ret['comment'] = 'Target Group {0} failed to add targets'.format(name)
|
||||
failure = True
|
||||
if failure:
|
||||
ret['result'] = False
|
||||
if changes:
|
||||
ret['changes']['old'] = health
|
||||
if __opts__['test']:
|
||||
ret['comment'] = 'Target Group {0} would be changed'.format(name)
|
||||
ret['result'] = None
|
||||
ret['changes']['new'] = newhealth_mock
|
||||
else:
|
||||
ret['comment'] = 'Target Group {0} has been changed'.format(name)
|
||||
newhealth = __salt__['boto_elbv2.describe_target_health'](name, region=region, key=key, keyid=keyid, profile=profile)
|
||||
ret['changes']['new'] = newhealth
|
||||
return ret
|
||||
else:
|
||||
ret['comment'] = 'Could not find target group {0}'.format(name)
|
||||
return ret
|
||||
|
||||
|
||||
def targets_deregistered(name, targets, region=None, key=None, keyid=None,
|
||||
profile=None):
|
||||
'''
|
||||
Remove targets to an Application Load Balancer target group.
|
||||
|
||||
name
|
||||
The ARN of the Application Load Balancer Target Group to remove targets from.
|
||||
|
||||
targets
|
||||
A list of target IDs or a string of a single target registered to the target group to be removed
|
||||
|
||||
.. versionadded:: Unknown
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
remove-targets:
|
||||
boto_elb.targets_deregistered:
|
||||
- name: arn:myloadbalancer
|
||||
- targets:
|
||||
- instance-id1
|
||||
- instance-id2
|
||||
'''
|
||||
ret = {'name': name, 'result': None, 'comment': '', 'changes': {}}
|
||||
tg = __salt__['boto_elbv2.target_group_exists'](name, region, key, keyid, profile)
|
||||
if tg:
|
||||
health = __salt__['boto_elbv2.describe_target_health'](name, region, key, keyid, profile)
|
||||
failure = False
|
||||
changes = False
|
||||
newhealth_mock = copy.copy(health)
|
||||
if isinstance(targets, str):
|
||||
targets = [targets]
|
||||
for target in targets:
|
||||
if target not in health or health.get(target) == "draining":
|
||||
ret['comment'] = ret['comment'] + 'Target/s {0} already deregistered\n'.format(target)
|
||||
ret['result'] = True
|
||||
else:
|
||||
if __opts__['test']:
|
||||
changes = True
|
||||
newhealth_mock.update({target: "draining"})
|
||||
else:
|
||||
state = __salt__['boto_elbv2.deregister_targets'](name,
|
||||
targets,
|
||||
region,
|
||||
key,
|
||||
keyid,
|
||||
profile)
|
||||
if state:
|
||||
changes = True
|
||||
ret['result'] = True
|
||||
else:
|
||||
ret['comment'] = 'Target Group {0} failed to remove targets'.format(name)
|
||||
failure = True
|
||||
if failure:
|
||||
ret['result'] = False
|
||||
if changes:
|
||||
ret['changes']['old'] = health
|
||||
if __opts__['test']:
|
||||
ret['comment'] = 'Target Group {0} would be changed'.format(name)
|
||||
ret['result'] = None
|
||||
ret['changes']['new'] = newhealth_mock
|
||||
else:
|
||||
ret['comment'] = 'Target Group {0} has been changed'.format(name)
|
||||
newhealth = __salt__['boto_elbv2.describe_target_health'](name, region, key, keyid, profile)
|
||||
ret['changes']['new'] = newhealth
|
||||
return ret
|
||||
else:
|
||||
ret['comment'] = 'Could not find target group {0}'.format(name)
|
||||
return ret
|
Loading…
Reference in New Issue
Block a user