Merge pull request #41053 from bodhi-space/infra4795

INFRA-4795 - fix logic for volume tagging in EC2
This commit is contained in:
Mike Place 2017-05-04 09:25:54 -06:00 committed by GitHub
commit 71627f62a2
2 changed files with 55 additions and 44 deletions

View File

@ -1758,20 +1758,18 @@ def set_volumes_tags(tag_maps, authoritative=False, dry_run=False,
''' '''
ret = {'success': True, 'comment': '', 'changes': {}} ret = {'success': True, 'comment': '', 'changes': {}}
running_states = ('pending', 'rebooting', 'running', 'stopping', 'stopped') running_states = ('pending', 'rebooting', 'running', 'stopping', 'stopped')
### First creeate a dictionary mapping all changes for a given volume to it's volume ID...
tag_sets = {}
for tm in tag_maps: for tm in tag_maps:
filters = tm.get('filters') filters = dict(tm.get('filters', {}))
tags = tm.get('tags') tags = dict(tm.get('tags', {}))
if not isinstance(filters, dict):
raise SaltInvocationError('Tag filters must be a dictionary: got {0}'.format(filters))
if not isinstance(tags, dict):
raise SaltInvocationError('Tags must be a dictionary: got {0}'.format(tags))
args = {'return_objs': True, 'region': region, 'key': key, 'keyid': keyid, 'profile': profile} args = {'return_objs': True, 'region': region, 'key': key, 'keyid': keyid, 'profile': profile}
new_filters = {} new_filters = {}
log.debug('got filters: {0}'.format(filters)) log.debug('got filters: {0}'.format(filters))
instance_id = None instance_id = None
in_states = tm.get('in_states', running_states) in_states = tm.get('in_states', running_states)
try: try:
for k, v in six.iteritems(filters): for k, v in filters.items():
if k == 'volume_ids': if k == 'volume_ids':
args['volume_ids'] = v args['volume_ids'] = v
elif k == 'instance_name': elif k == 'instance_name':
@ -1789,39 +1787,45 @@ def set_volumes_tags(tag_maps, authoritative=False, dry_run=False,
args['filters'] = new_filters args['filters'] = new_filters
volumes = get_all_volumes(**args) volumes = get_all_volumes(**args)
log.debug('got volume list: {0}'.format(volumes)) log.debug('got volume list: {0}'.format(volumes))
changes = {'old': {}, 'new': {}}
for vol in volumes: for vol in volumes:
log.debug('current tags on vol.id {0}: {1}'.format(vol.id, dict(getattr(vol, 'tags', {})))) tag_sets.setdefault(vol.id.replace('-', '_'), {'vol': vol, 'tags': tags.copy()})['tags'].update(tags.copy())
curr = set(dict(getattr(vol, 'tags', {})).keys()) log.debug('tag_sets after munging: {0}'.format(tag_sets))
log.debug('requested tags on vol.id {0}: {1}'.format(vol.id, tags))
req = set(tags.keys()) ### ...then loop through all those volume->tag pairs and apply them.
add = list(req - curr) changes = {'old': {}, 'new': {}}
update = [r for r in (req & curr) if vol.tags[r] != tags[r]] for volume in tag_sets.values():
remove = list(curr - req) vol, tags = volume['vol'], volume['tags']
if add or update or (authoritative and remove): log.debug('current tags on vol.id {0}: {1}'.format(vol.id, dict(getattr(vol, 'tags', {}))))
changes['old'][vol.id] = dict(getattr(vol, 'tags', {})) curr = set(dict(getattr(vol, 'tags', {})).keys())
changes['new'][vol.id] = tags log.debug('requested tags on vol.id {0}: {1}'.format(vol.id, tags))
else: req = set(tags.keys())
log.debug('No changes needed for vol.id {0}'.format(vol.id)) add = list(req - curr)
if len(add): update = [r for r in (req & curr) if vol.tags[r] != tags[r]]
d = dict((k, tags[k]) for k in add) remove = list(curr - req)
log.debug('New tags for vol.id {0}: {1}'.format(vol.id, d)) if add or update or (authoritative and remove):
if len(update): changes['old'][vol.id] = dict(getattr(vol, 'tags', {}))
d = dict((k, tags[k]) for k in update) changes['new'][vol.id] = tags
log.debug('Updated tags for vol.id {0}: {1}'.format(vol.id, d)) else:
if not dry_run: log.debug('No changes needed for vol.id {0}'.format(vol.id))
if not create_tags(vol.id, tags, region=region, key=key, keyid=keyid, profile=profile): if len(add):
ret['success'] = False d = dict((k, tags[k]) for k in add)
ret['comment'] = "Failed to set tags on vol.id {0}: {1}".format(vol.id, tags) log.debug('New tags for vol.id {0}: {1}'.format(vol.id, d))
return ret if len(update):
if authoritative: d = dict((k, tags[k]) for k in update)
if len(remove): log.debug('Updated tags for vol.id {0}: {1}'.format(vol.id, d))
log.debug('Removed tags for vol.id {0}: {1}'.format(vol.id, remove)) if not dry_run:
if not delete_tags(vol.id, remove, region=region, key=key, keyid=keyid, profile=profile): if not create_tags(vol.id, tags, region=region, key=key, keyid=keyid, profile=profile):
ret['success'] = False ret['success'] = False
ret['comment'] = "Failed to remove tags on vol.id {0}: {1}".format(vol.id, remove) ret['comment'] = "Failed to set tags on vol.id {0}: {1}".format(vol.id, tags)
return ret return ret
ret['changes'].update(changes) if changes['old'] or changes['new'] else None # pylint: disable=W0106 if authoritative:
if len(remove):
log.debug('Removed tags for vol.id {0}: {1}'.format(vol.id, remove))
if not delete_tags(vol.id, remove, region=region, key=key, keyid=keyid, profile=profile):
ret['success'] = False
ret['comment'] = "Failed to remove tags on vol.id {0}: {1}".format(vol.id, remove)
return ret
ret['changes'].update(changes) if changes['old'] or changes['new'] else None # pylint: disable=W0106
return ret return ret

View File

@ -1229,13 +1229,20 @@ def volumes_tagged(name, tag_maps, authoritative=False, region=None, key=None,
if __opts__['test']: if __opts__['test']:
args['dry_run'] = True args['dry_run'] = True
r = __salt__['boto_ec2.set_volumes_tags'](**args) r = __salt__['boto_ec2.set_volumes_tags'](**args)
if r.get('changes'): if r['success']:
ret['comment'] = 'The following changes would be applied: {0}'.format(r) if r.get('changes'):
ret['comment'] = 'Tags would be updated.'
ret['changes'] = r['changes']
ret['result'] = None
else:
ret['comment'] = 'Error validating requested volume tags.'
ret['result'] = False
return ret return ret
r = __salt__['boto_ec2.set_volumes_tags'](**args) r = __salt__['boto_ec2.set_volumes_tags'](**args)
if r['success'] is True: if r['success']:
ret['comment'] = 'Tags applied.' if r.get('changes'):
ret['changes'] = r['changes'] ret['comment'] = 'Tags applied.'
ret['changes'] = r['changes']
else: else:
ret['comment'] = 'Error updating requested volume tags.' ret['comment'] = 'Error updating requested volume tags.'
ret['result'] = False ret['result'] = False