mirror of
https://github.com/saltstack/salt.git
synced 2025-04-17 10:10:20 +00:00
Merging tag and cname modifications
This commit is contained in:
parent
2f715803b2
commit
3316959866
3 changed files with 362 additions and 21 deletions
|
@ -77,6 +77,7 @@ except ImportError:
|
|||
|
||||
# Import Salt libs
|
||||
from salt.ext.six import string_types
|
||||
from salt.utils.boto_elb_tag import TagDescriptions as TagDescriptions
|
||||
import salt.utils.odict as odict
|
||||
|
||||
|
||||
|
@ -144,6 +145,7 @@ def get_elb_config(name, region=None, key=None, keyid=None, profile=None):
|
|||
ret['security_groups'] = lb.security_groups
|
||||
ret['scheme'] = lb.scheme
|
||||
ret['dns_name'] = lb.dns_name
|
||||
ret['tags'] = _get_all_tags(conn, name)
|
||||
lb_policy_lists = [
|
||||
lb.policies.app_cookie_stickiness_policies,
|
||||
lb.policies.lb_cookie_stickiness_policies,
|
||||
|
@ -743,3 +745,130 @@ def set_listener_policy(name, port, policies=None, region=None, key=None,
|
|||
log.info('Failed to set policy {0} on ELB {1} listener {2}: {3}'.format(policies, name, port, e.message))
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def set_tags(name, tags, region=None, key=None, keyid=None, profile=None):
|
||||
'''
|
||||
Add the tags on an ELB
|
||||
|
||||
.. versionadded:: Boron
|
||||
|
||||
name
|
||||
name of the ELB
|
||||
|
||||
tags
|
||||
dict of name/value pair tags
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt myminion boto_elb.set_tags my-elb-name "{'Tag1': 'Value', 'Tag2': 'Another Value'}"
|
||||
'''
|
||||
|
||||
if exists(name, region, key, keyid, profile):
|
||||
conn = _get_conn(region=region, key=key, keyid=keyid, profile=profile)
|
||||
ret = _add_tags(conn, name, tags)
|
||||
return ret
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
def delete_tags(name, tags, region=None, key=None, keyid=None, profile=None):
|
||||
'''
|
||||
Add the tags on an ELB
|
||||
|
||||
name
|
||||
name of the ELB
|
||||
|
||||
tags
|
||||
list of tags to remove
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt myminion boto_elb.delete_tags my-elb-name ['TagToRemove1', 'TagToRemove2']
|
||||
'''
|
||||
if exists(name, region, key, keyid, profile):
|
||||
conn = _get_conn(region=region, key=key, keyid=keyid, profile=profile)
|
||||
ret = _remove_tags(conn, name, tags)
|
||||
return ret
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
def _build_tag_param_list(params, tags):
|
||||
'''
|
||||
helper function to build a tag parameter list to send
|
||||
'''
|
||||
keys = sorted(tags.keys())
|
||||
i = 1
|
||||
for key in keys:
|
||||
value = tags[key]
|
||||
params['Tags.member.{0}.Key'.format(i)] = key
|
||||
if value is not None:
|
||||
params['Tags.member.{0}.Value'.format(i)] = value
|
||||
i += 1
|
||||
|
||||
|
||||
def _get_all_tags(conn, load_balancer_names=None):
|
||||
'''
|
||||
Retrieve all the metadata tags associated with your ELB(s).
|
||||
|
||||
:type load_balancer_names: list
|
||||
:param load_balancer_names: An optional list of load balancer names.
|
||||
|
||||
:rtype: list
|
||||
:return: A list of :class:`boto.ec2.elb.tag.Tag` objects
|
||||
'''
|
||||
params = {}
|
||||
if load_balancer_names:
|
||||
conn.build_list_params(params, load_balancer_names,
|
||||
'LoadBalancerNames.member.%d')
|
||||
|
||||
tags = conn.get_object('DescribeTags', params, TagDescriptions,
|
||||
verb='POST')
|
||||
if tags[load_balancer_names]:
|
||||
return tags[load_balancer_names]
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def _add_tags(conn, load_balancer_names, tags):
|
||||
'''
|
||||
Create new metadata tags for the specified resource ids.
|
||||
|
||||
:type load_balancer_names: list
|
||||
:param load_balancer_names: A list of load balancer names.
|
||||
|
||||
:type tags: dict
|
||||
:param tags: A dictionary containing the name/value pairs.
|
||||
If you want to create only a tag name, the
|
||||
value for that tag should be the empty string
|
||||
(e.g. '').
|
||||
'''
|
||||
params = {}
|
||||
conn.build_list_params(params, load_balancer_names,
|
||||
'LoadBalancerNames.member.%d')
|
||||
_build_tag_param_list(params, tags)
|
||||
return conn.get_status('AddTags', params, verb='POST')
|
||||
|
||||
|
||||
def _remove_tags(conn, load_balancer_names, tags):
|
||||
'''
|
||||
Delete metadata tags for the specified resource ids.
|
||||
|
||||
:type load_balancer_names: list
|
||||
:param load_balancer_names: A list of load balancer names.
|
||||
|
||||
:type tags: list
|
||||
:param tags: A list containing just tag names for the tags to be
|
||||
deleted.
|
||||
'''
|
||||
params = {}
|
||||
conn.build_list_params(params, load_balancer_names,
|
||||
'LoadBalancerNames.member.%d')
|
||||
conn.build_list_params(params, tags,
|
||||
'Tags.member.%d.Key')
|
||||
return conn.get_status('RemoveTags', params, verb='POST')
|
||||
|
|
|
@ -206,6 +206,21 @@ Overriding the alarm values on the resource:
|
|||
UnHealthyHostCount:
|
||||
attributes:
|
||||
threshold: 2.0
|
||||
|
||||
Tags can also be set:
|
||||
|
||||
.. versionadded:: Boron
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
Ensure myelb ELB exists:
|
||||
boto_elb.present:
|
||||
- name: myelb
|
||||
- region: us-east-1
|
||||
- profile: myelbprofile
|
||||
- tags:
|
||||
MyTag: 'My Tag Value'
|
||||
OtherTag: 'My Other Value'
|
||||
'''
|
||||
|
||||
# Import Python Libs
|
||||
|
@ -218,6 +233,7 @@ import salt.utils.dictupdate as dictupdate
|
|||
from salt.exceptions import SaltInvocationError
|
||||
import salt.ext.six as six
|
||||
|
||||
|
||||
def __virtual__():
|
||||
'''
|
||||
Only load if boto is available.
|
||||
|
@ -244,7 +260,8 @@ def present(
|
|||
key=None,
|
||||
keyid=None,
|
||||
profile=None,
|
||||
wait_for_sync=True):
|
||||
wait_for_sync=True,
|
||||
tags=None):
|
||||
'''
|
||||
Ensure the ELB exists.
|
||||
|
||||
|
@ -282,8 +299,11 @@ def present(
|
|||
state will override those from pillar.
|
||||
|
||||
cnames
|
||||
A list of cname dicts with attributes: name, zone, ttl, and identifier.
|
||||
A list of cname dicts with attributes needed for the DNS add_record state.
|
||||
By default the boto_route53.add_record state will be used, which requires: name, zone, ttl, and identifier.
|
||||
See the boto_route53 state for information about these attributes.
|
||||
Other DNS modules can be called by specifying the provider keyword.
|
||||
the cnames dict will be passed to the state as kwargs.
|
||||
|
||||
alarms:
|
||||
a dictionary of name->boto_cloudwatch_alarm sections to be associated with this ELB.
|
||||
|
@ -310,6 +330,9 @@ def present(
|
|||
|
||||
wait_for_sync
|
||||
Wait for an INSYNC change status from Route53.
|
||||
|
||||
tags
|
||||
dict of tags
|
||||
'''
|
||||
|
||||
# load data from attributes_from_pillar and merge with attributes
|
||||
|
@ -352,18 +375,22 @@ def present(
|
|||
name, region, key, keyid, profile
|
||||
)
|
||||
for cname in cnames:
|
||||
_ret = __states__['boto_route53.present'](
|
||||
name=cname.get('name'),
|
||||
value=lb['dns_name'],
|
||||
zone=cname.get('zone'),
|
||||
record_type='CNAME',
|
||||
identifier=cname.get('identifier', None),
|
||||
ttl=cname.get('ttl', None),
|
||||
region=region,
|
||||
key=key,
|
||||
keyid=keyid,
|
||||
profile=profile
|
||||
)
|
||||
_ret = None
|
||||
dns_provider = 'boto_route53'
|
||||
cname['record_type'] = 'CNAME'
|
||||
cname['value'] = lb['dns_name']
|
||||
if 'provider' in cname:
|
||||
dns_provider = cname.pop('provider')
|
||||
if dns_provider == 'boto_route53':
|
||||
if 'profile' not in cname:
|
||||
cname['profile'] = profile
|
||||
if 'key' not in cname:
|
||||
cname['key'] = key
|
||||
if 'keyid' not in cname:
|
||||
cname['keyid'] = keyid
|
||||
if 'region' not in cname:
|
||||
cname['region'] = region
|
||||
_ret = __states__['.'.join([dns_provider, 'present'])](**cname)
|
||||
ret['changes'] = dictupdate.update(ret['changes'], _ret['changes'])
|
||||
ret['comment'] = ' '.join([ret['comment'], _ret['comment']])
|
||||
if not _ret['result']:
|
||||
|
@ -378,7 +405,14 @@ def present(
|
|||
if ret['result'] is False:
|
||||
return ret
|
||||
_ret = _policies_present(name, policies, policies_from_pillar, listeners, region, key,
|
||||
keyid, profile)
|
||||
keyid, profile)
|
||||
ret['changes'] = dictupdate.update(ret['changes'], _ret['changes'])
|
||||
ret['comment'] = ' '.join([ret['comment'], _ret['comment']])
|
||||
if not _ret['result']:
|
||||
ret['result'] = _ret['result']
|
||||
if ret['result'] is False:
|
||||
return ret
|
||||
_ret = _tags_present(name, tags, region, key, keyid, profile)
|
||||
ret['changes'] = dictupdate.update(ret['changes'], _ret['changes'])
|
||||
ret['comment'] = ' '.join([ret['comment'], _ret['comment']])
|
||||
if not _ret['result']:
|
||||
|
@ -452,6 +486,7 @@ def register_instances(name, instances, region=None, key=None, keyid=None,
|
|||
|
||||
DEFAULT_PILLAR_LISTENER_POLICY_KEY = 'boto_elb_listener_policies'
|
||||
|
||||
|
||||
def _elb_present(
|
||||
name,
|
||||
availability_zones,
|
||||
|
@ -506,6 +541,7 @@ def _elb_present(
|
|||
vpc_id = __salt__['boto_vpc.get_subnet_association'](
|
||||
subnets, region, key, keyid, profile
|
||||
)
|
||||
vpc_id = vpc_id.get('vpc_id')
|
||||
if not vpc_id:
|
||||
msg = 'Subnets {0} do not map to a valid vpc id.'.format(subnets)
|
||||
raise SaltInvocationError(msg)
|
||||
|
@ -999,17 +1035,17 @@ def _policies_present(
|
|||
for p in policies:
|
||||
if 'policy_name' not in p:
|
||||
raise SaltInvocationError('policy_name is a required value for '
|
||||
'policies.')
|
||||
'policies.')
|
||||
if 'policy_type' not in p:
|
||||
raise SaltInvocationError('policy_type is a required value for '
|
||||
'policies.')
|
||||
'policies.')
|
||||
if 'policy' not in p:
|
||||
raise SaltInvocationError('policy is a required value for '
|
||||
'listeners.')
|
||||
'listeners.')
|
||||
# check for unique policy names
|
||||
if p['policy_name'] in policy_names:
|
||||
raise SaltInvocationError('Policy names must be unique: policy {}'
|
||||
' is declared twice.'.format(p['policy_name']))
|
||||
' is declared twice.'.format(p['policy_name']))
|
||||
policy_names.add(p['policy_name'])
|
||||
|
||||
# check that listeners refer to valid policy names
|
||||
|
@ -1017,7 +1053,7 @@ def _policies_present(
|
|||
for p in l.get('policies', []):
|
||||
if p not in policy_names:
|
||||
raise SaltInvocationError('Listener {} on ELB {} refers to '
|
||||
'undefined policy {}.'.format(l['elb_port'], name, p))
|
||||
'undefined policy {}.'.format(l['elb_port'], name, p))
|
||||
|
||||
ret = {'result': True, 'comment': '', 'changes': {}}
|
||||
|
||||
|
@ -1145,7 +1181,7 @@ def _policies_present(
|
|||
|
||||
if to_delete:
|
||||
for policy_name in to_delete:
|
||||
deleted = __salt__['boto_elb.delete_policy'](
|
||||
deleted = __salt__['boto_elb.delete_policy'](
|
||||
name=name,
|
||||
policy_name=policy_name,
|
||||
region=region,
|
||||
|
@ -1181,6 +1217,12 @@ def absent(
|
|||
key=None,
|
||||
keyid=None,
|
||||
profile=None):
|
||||
'''
|
||||
Ensure an ELB does not exist
|
||||
|
||||
name
|
||||
name of the ELB
|
||||
'''
|
||||
ret = {'name': name, 'result': True, 'comment': '', 'changes': {}}
|
||||
|
||||
exists = __salt__['boto_elb.exists'](name, region, key, keyid, profile)
|
||||
|
@ -1201,3 +1243,95 @@ def absent(
|
|||
else:
|
||||
ret['comment'] = '{0} ELB does not exist.'.format(name)
|
||||
return ret
|
||||
|
||||
|
||||
def _tags_present(name,
|
||||
tags,
|
||||
region,
|
||||
key,
|
||||
keyid,
|
||||
profile):
|
||||
'''
|
||||
helper function to validate tags on elb
|
||||
'''
|
||||
ret = {'result': True, 'comment': '', 'changes': {}}
|
||||
if tags:
|
||||
lb = __salt__['boto_elb.get_elb_config'](name, region, key, keyid, profile)
|
||||
|
||||
tags_to_add = tags
|
||||
tags_to_update = {}
|
||||
tags_to_remove = []
|
||||
if lb['tags']:
|
||||
for _tag in lb['tags'].keys():
|
||||
if _tag not in tags.keys():
|
||||
if _tag not in tags_to_remove:
|
||||
tags_to_remove.append(_tag)
|
||||
else:
|
||||
if tags[_tag] != lb['tags'][_tag]:
|
||||
tags_to_update[_tag] = tags[_tag]
|
||||
tags_to_add.pop(_tag)
|
||||
if tags_to_remove:
|
||||
if __opts__['test']:
|
||||
msg = 'The following tag{0} set to be removed: {1}.'.format(
|
||||
('s are' if len(tags_to_remove) > 1 else ' is'), ', '.join(tags_to_remove))
|
||||
ret['comment'] = ' '.join([ret['comment'], msg])
|
||||
ret['result'] = None
|
||||
else:
|
||||
_ret = __salt__['boto_elb.delete_tags'](
|
||||
name,
|
||||
tags_to_remove,
|
||||
region,
|
||||
key,
|
||||
keyid,
|
||||
profile)
|
||||
if not _ret:
|
||||
ret['result'] = False
|
||||
msg = 'Error attempting to delete tag {0}.'.format(tags_to_remove)
|
||||
ret['comment'] = ' '.join([ret['comment'], msg])
|
||||
return ret
|
||||
if 'old' not in ret['changes']:
|
||||
ret['changes'] = dictupdate.update(ret['changes'], {'old': {'tags': {}}})
|
||||
for _tag in tags_to_remove:
|
||||
ret['changes']['old']['tags'][_tag] = lb['tags'][_tag]
|
||||
if tags_to_add or tags_to_update:
|
||||
if __opts__['test']:
|
||||
if tags_to_add:
|
||||
msg = 'The following tag{0} set to be added: {1}.'.format(
|
||||
('s are' if len(tags_to_add.keys()) > 1 else ' is'),
|
||||
', '.join(tags_to_add.keys()))
|
||||
ret['comment'] = ' '. join([ret['comment'], msg])
|
||||
ret['result'] = None
|
||||
if tags_to_update:
|
||||
msg = 'The following tag {0} set to be updated: {1}.'.format(
|
||||
('values are' if len(tags_to_update.keys()) > 1 else 'value is'),
|
||||
', '.join(tags_to_update.keys()))
|
||||
ret['comment'] = ' '.join([ret['comment'], msg])
|
||||
ret['result'] = None
|
||||
else:
|
||||
all_tag_changes = dictupdate.update(tags_to_add, tags_to_update)
|
||||
_ret = __salt__['boto_elb.set_tags'](
|
||||
name,
|
||||
all_tag_changes,
|
||||
region,
|
||||
key,
|
||||
keyid,
|
||||
profile)
|
||||
if not _ret:
|
||||
ret['result'] = False
|
||||
msg = 'Error attempting to set tags.'
|
||||
ret['comment'] = ' '.join([ret['comment'], msg])
|
||||
return ret
|
||||
if 'old' not in ret['changes']:
|
||||
ret['changes'] = dictupdate.update(ret['changes'], {'old': {'tags': {}}})
|
||||
if 'new' not in ret['changes']:
|
||||
ret['changes'] = dictupdate.update(ret['changes'], {'new': {'tags': {}}})
|
||||
for tag in all_tag_changes:
|
||||
ret['changes']['new']['tags'][tag] = tags[tag]
|
||||
if 'tags' in lb:
|
||||
if lb['tags']:
|
||||
if tag in lb['tags']:
|
||||
ret['changes']['old']['tags'][tag] = lb['tags'][tag]
|
||||
if not tags_to_update and not tags_to_remove and not tags_to_add:
|
||||
msg = 'Tags are already set.'
|
||||
ret['comment'] = ' '.join([ret['comment'], msg])
|
||||
return ret
|
||||
|
|
78
salt/utils/boto_elb_tag.py
Normal file
78
salt/utils/boto_elb_tag.py
Normal file
|
@ -0,0 +1,78 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2010 Mitch Garnaat http://garnaat.org/
|
||||
# Copyright (c) 2010, Eucalyptus Systems, Inc.
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a
|
||||
# copy of this software and associated documentation files (the
|
||||
# "Software"), to deal in the Software without restriction, including
|
||||
# without limitation the rights to use, copy, modify, merge, publish, dis-
|
||||
# tribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
# persons to whom the Software is furnished to do so, subject to the fol-
|
||||
# lowing conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included
|
||||
# in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
|
||||
# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
# IN THE SOFTWARE.
|
||||
|
||||
|
||||
class TagDescriptions(dict):
|
||||
'''
|
||||
A TagDescriptions is used to collect the tags associated with ELB resources.
|
||||
See :class:`boto.ec2.elb.LoadBalancer` for more details.
|
||||
'''
|
||||
|
||||
def __init__(self, connection=None):
|
||||
dict.__init__(self)
|
||||
self.connection = connection
|
||||
self._load_balancer_name = None
|
||||
self._tags = None
|
||||
|
||||
def startElement(self, name, attrs, connection):
|
||||
if name == 'member':
|
||||
self.load_balancer_name = None
|
||||
self.tags = None
|
||||
if name == 'Tags':
|
||||
self._tags = TagSet()
|
||||
return self._tags
|
||||
return None
|
||||
|
||||
def endElement(self, name, value, connection):
|
||||
if name == 'LoadBalancerName':
|
||||
self._load_balancer_name = value
|
||||
elif name == 'member':
|
||||
self[self._load_balancer_name] = self._tags
|
||||
|
||||
|
||||
class TagSet(dict):
|
||||
'''
|
||||
A TagSet is used to collect the tags associated with a particular
|
||||
ELB resource. See :class:`boto.ec2.elb.LoadBalancer` for more
|
||||
details.
|
||||
'''
|
||||
|
||||
def __init__(self, connection=None):
|
||||
dict.__init__(self)
|
||||
self.connection = connection
|
||||
self._current_key = None
|
||||
self._current_value = None
|
||||
|
||||
def startElement(self, name, attrs, connection):
|
||||
if name == 'member':
|
||||
self._current_key = None
|
||||
self._current_value = None
|
||||
return None
|
||||
|
||||
def endElement(self, name, value, connection):
|
||||
if name == 'Key':
|
||||
self._current_key = value
|
||||
elif name == 'Value':
|
||||
self._current_value = value
|
||||
elif name == 'member':
|
||||
self[self._current_key] = self._current_value
|
Loading…
Add table
Reference in a new issue