def test_compare_aws_tags_equal(self): new_dict = dict(self.tag_example_dict) keys_to_set, keys_to_unset = compare_aws_tags(self.tag_example_dict, new_dict) self.assertEqual({}, keys_to_set) self.assertEqual([], keys_to_unset) keys_to_set, keys_to_unset = compare_aws_tags(self.tag_example_dict, new_dict, purge_tags=False) self.assertEqual({}, keys_to_set) self.assertEqual([], keys_to_unset) keys_to_set, keys_to_unset = compare_aws_tags(self.tag_example_dict, new_dict, purge_tags=True) self.assertEqual({}, keys_to_set) self.assertEqual([], keys_to_unset)
def test_compare_aws_tags_removed(self): new_dict = dict(self.tag_example_dict) del new_dict['lowerCamel'] del new_dict['Normal case'] keys_to_set, keys_to_unset = compare_aws_tags(self.tag_example_dict, new_dict) self.assertEqual({}, keys_to_set) self.assertEqual(set(['lowerCamel', 'Normal case']), set(keys_to_unset)) keys_to_set, keys_to_unset = compare_aws_tags(self.tag_example_dict, new_dict, purge_tags=False) self.assertEqual({}, keys_to_set) self.assertEqual([], keys_to_unset) keys_to_set, keys_to_unset = compare_aws_tags(self.tag_example_dict, new_dict, purge_tags=True) self.assertEqual({}, keys_to_set) self.assertEqual(set(['lowerCamel', 'Normal case']), set(keys_to_unset))
def test_compare_aws_tags_changed(self): new_dict = dict(self.tag_example_dict) new_keys = {'UpperCamel': 'anotherCamelValue', 'Normal case': 'normal value'} new_dict.update(new_keys) keys_to_set, keys_to_unset = compare_aws_tags(self.tag_example_dict, new_dict) self.assertEqual(new_keys, keys_to_set) self.assertEqual([], keys_to_unset) keys_to_set, keys_to_unset = compare_aws_tags(self.tag_example_dict, new_dict, purge_tags=False) self.assertEqual(new_keys, keys_to_set) self.assertEqual([], keys_to_unset) keys_to_set, keys_to_unset = compare_aws_tags(self.tag_example_dict, new_dict, purge_tags=True) self.assertEqual(new_keys, keys_to_set) self.assertEqual([], keys_to_unset)
def test_compare_aws_tags_added(self): new_dict = dict(self.tag_example_dict) new_keys = {'add_me': 'lower case', 'Me too!': 'Contributing'} new_dict.update(new_keys) keys_to_set, keys_to_unset = compare_aws_tags(self.tag_example_dict, new_dict) self.assertEqual(new_keys, keys_to_set) self.assertEqual([], keys_to_unset) keys_to_set, keys_to_unset = compare_aws_tags(self.tag_example_dict, new_dict, purge_tags=False) self.assertEqual(new_keys, keys_to_set) self.assertEqual([], keys_to_unset) keys_to_set, keys_to_unset = compare_aws_tags(self.tag_example_dict, new_dict, purge_tags=True) self.assertEqual(new_keys, keys_to_set) self.assertEqual([], keys_to_unset)
def test_compare_aws_tags_complex_update(self): # Adds 'Me too!', Changes 'UpperCamel' and removes 'Normal case' new_dict = dict(self.tag_example_dict) new_keys = {'UpperCamel': 'anotherCamelValue', 'Me too!': 'Contributing'} new_dict.update(new_keys) del new_dict['Normal case'] keys_to_set, keys_to_unset = compare_aws_tags(self.tag_example_dict, new_dict) self.assertEqual(new_keys, keys_to_set) self.assertEqual(['Normal case'], keys_to_unset) keys_to_set, keys_to_unset = compare_aws_tags(self.tag_example_dict, new_dict, purge_tags=False) self.assertEqual(new_keys, keys_to_set) self.assertEqual([], keys_to_unset) keys_to_set, keys_to_unset = compare_aws_tags(self.tag_example_dict, new_dict, purge_tags=True) self.assertEqual(new_keys, keys_to_set) self.assertEqual(['Normal case'], keys_to_unset)
def ensure_tags(connection=None, module=None, resource_id=None, tags=None, purge_tags=None, check_mode=None): try: cur_tags = describe_tags_with_backoff(connection, resource_id) except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws(e, msg='Unable to list tags for VPC') to_add, to_delete = compare_aws_tags(cur_tags, tags, purge_tags) if not to_add and not to_delete: return {'changed': False, 'tags': cur_tags} if check_mode: if not purge_tags: tags = cur_tags.update(tags) return {'changed': True, 'tags': tags} if to_delete: try: connection.delete_tags(Resources=[resource_id], Tags=[{'Key': k} for k in to_delete]) except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws(e, msg="Couldn't delete tags") if to_add: try: connection.create_tags(Resources=[resource_id], Tags=ansible_dict_to_boto3_tag_list(to_add)) except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws(e, msg="Couldn't create tags") try: latest_tags = describe_tags_with_backoff(connection, resource_id) except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws(e, msg='Unable to list tags for VPC') return {'changed': True, 'tags': latest_tags}
def update_role_tags(connection, module, params, role): new_tags = params.get('Tags') if new_tags is None: return False new_tags = boto3_tag_list_to_ansible_dict(new_tags) role_name = module.params.get('name') purge_tags = module.params.get('purge_tags') try: existing_tags = boto3_tag_list_to_ansible_dict(connection.list_role_tags(RoleName=role_name, aws_retry=True)['Tags']) except (ClientError, KeyError): existing_tags = {} tags_to_add, tags_to_remove = compare_aws_tags(existing_tags, new_tags, purge_tags=purge_tags) if not module.check_mode: try: if tags_to_remove: connection.untag_role(RoleName=role_name, TagKeys=tags_to_remove, aws_retry=True) if tags_to_add: connection.tag_role(RoleName=role_name, Tags=ansible_dict_to_boto3_tag_list(tags_to_add), aws_retry=True) except (ClientError, BotoCoreError) as e: module.fail_json_aws(e, msg='Unable to set tags for role %s' % role_name) changed = bool(tags_to_add) or bool(tags_to_remove) return changed
def ensure_tags(client, module, resource_arn, existing_tags, tags, purge_tags): if tags is None: return False tags_to_add, tags_to_remove = compare_aws_tags(existing_tags, tags, purge_tags) changed = bool(tags_to_add or tags_to_remove) if tags_to_add: try: client.add_tags_to_resource( ResourceName=resource_arn, Tags=ansible_dict_to_boto3_tag_list(tags_to_add)) except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws( e, "Couldn't add tags to snapshot {0}".format(resource_arn)) if tags_to_remove: try: client.remove_tags_from_resource(ResourceName=resource_arn, TagKeys=tags_to_remove) except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws( e, "Couldn't remove tags from snapshot {0}".format(resource_arn)) return changed
def update_tags(module, connection, group, tags): changed = False existing_tags = connection.list_tags_for_resource( ResourceName=group['DBParameterGroupArn'])['TagList'] to_update, to_delete = compare_aws_tags( boto3_tag_list_to_ansible_dict(existing_tags), tags, module.params['purge_tags']) if to_update: try: connection.add_tags_to_resource( ResourceName=group['DBParameterGroupArn'], Tags=ansible_dict_to_boto3_tag_list(to_update)) changed = True except botocore.exceptions.ClientError as e: module.fail_json(msg="Couldn't add tags to parameter group: %s" % str(e), exception=traceback.format_exc(), **camel_dict_to_snake_dict(e.response)) except botocore.exceptions.ParamValidationError as e: # Usually a tag value has been passed as an int or bool, needs to be a string # The AWS exception message is reasonably ok for this purpose module.fail_json(msg="Couldn't add tags to parameter group: %s." % str(e), exception=traceback.format_exc()) if to_delete: try: connection.remove_tags_from_resource( ResourceName=group['DBParameterGroupArn'], TagKeys=to_delete) changed = True except botocore.exceptions.ClientError as e: module.fail_json( msg="Couldn't remove tags from parameter group: %s" % str(e), exception=traceback.format_exc(), **camel_dict_to_snake_dict(e.response)) return changed
def _update_tags(current_table): _tags = module.params.get('tags') if _tags is None: return False tags_to_add, tags_to_remove = compare_aws_tags(current_table['tags'], module.params.get('tags'), purge_tags=module.params.get('purge_tags')) # If neither need updating we can return already if not (tags_to_add or tags_to_remove): return False if module.check_mode: return True if tags_to_add: try: client.tag_resource( aws_retry=True, ResourceArn=current_table['arn'], Tags=ansible_dict_to_boto3_tag_list(tags_to_add), ) except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws(e, msg="Failed to tag table") if tags_to_remove: try: client.untag_resource( aws_retry=True, ResourceArn=current_table['arn'], TagKeys=tags_to_remove, ) except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws(e, msg="Failed to untag table") return True
def update_tags(client, queue_url, module): new_tags = module.params.get('tags') purge_tags = module.params.get('purge_tags') if new_tags is None: return False, {} try: existing_tags = client.list_queue_tags(QueueUrl=queue_url, aws_retry=True)['Tags'] except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError, KeyError) as e: existing_tags = {} tags_to_add, tags_to_remove = compare_aws_tags(existing_tags, new_tags, purge_tags=purge_tags) if not module.check_mode: if tags_to_remove: client.untag_queue(QueueUrl=queue_url, TagKeys=tags_to_remove, aws_retry=True) if tags_to_add: client.tag_queue(QueueUrl=queue_url, Tags=tags_to_add) existing_tags = client.list_queue_tags(QueueUrl=queue_url, aws_retry=True).get('Tags', {}) else: existing_tags = new_tags changed = bool(tags_to_remove) or bool(tags_to_add) return changed, existing_tags
def set_tag(client, module, tags, function): changed = False arn = function['Configuration']['FunctionArn'] try: current_tags = client.list_tags(Resource=arn, aws_retry=True).get('Tags', {}) except (BotoCoreError, ClientError) as e: module.fail_json_aws(e, msg="Unable to list tags") tags_to_add, tags_to_remove = compare_aws_tags(current_tags, tags, purge_tags=True) try: if tags_to_remove: client.untag_resource(Resource=arn, TagKeys=tags_to_remove, aws_retry=True) changed = True if tags_to_add: client.tag_resource(Resource=arn, Tags=tags_to_add, aws_retry=True) changed = True except (BotoCoreError, ClientError) as e: module.fail_json_aws(e, msg="Unable to tag resource {0}".format(arn)) return changed
def update_cluster_tags(client, module, arn): new_tags = module.params.get('tags') if new_tags is None: return False purge_tags = module.params.get('purge_tags') try: existing_tags = client.list_tags_for_resource(ResourceArn=arn, aws_retry=True)['Tags'] except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws( e, msg="Unable to retrieve tags for cluster '{0}'".format(arn)) tags_to_add, tags_to_remove = compare_aws_tags(existing_tags, new_tags, purge_tags=purge_tags) if not module.check_mode: try: if tags_to_remove: client.untag_resource(ResourceArn=arn, TagKeys=tags_to_remove, aws_retry=True) if tags_to_add: client.tag_resource(ResourceArn=arn, Tags=tags_to_add, aws_retry=True) except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws( e, msg="Unable to set tags for cluster '{0}'".format(arn)) changed = bool(tags_to_add) or bool(tags_to_remove) return changed
def update_user_tags(connection, module, params, user): user_name = params['UserName'] existing_tags = user['user']['tags'] new_tags = params.get('Tags') if new_tags is None: return False new_tags = boto3_tag_list_to_ansible_dict(new_tags) purge_tags = module.params.get('purge_tags') tags_to_add, tags_to_remove = compare_aws_tags(existing_tags, new_tags, purge_tags=purge_tags) if not module.check_mode: try: if tags_to_remove: connection.untag_user(UserName=user_name, TagKeys=tags_to_remove) if tags_to_add: connection.tag_user( UserName=user_name, Tags=ansible_dict_to_boto3_tag_list(tags_to_add)) except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws(e, msg='Unable to set tags for user %s' % user_name) changed = bool(tags_to_add) or bool(tags_to_remove) return changed
def _ensure_tags(redshift, identifier, existing_tags, module): """Compares and update resource tags""" account_id = get_aws_account_id(module) region = module.params.get('region') resource_arn = "arn:aws:redshift:{0}:{1}:cluster:{2}" .format(region, account_id, identifier) tags = module.params.get('tags') purge_tags = module.params.get('purge_tags') tags_to_add, tags_to_remove = compare_aws_tags(boto3_tag_list_to_ansible_dict(existing_tags), tags, purge_tags) if tags_to_add: try: redshift.create_tags(ResourceName=resource_arn, Tags=ansible_dict_to_boto3_tag_list(tags_to_add)) except (botocore.exceptions.BotoCoreError, botocore.exceptions.ClientError) as e: module.fail_json_aws(e, msg="Failed to add tags to cluster") if tags_to_remove: try: redshift.delete_tags(ResourceName=resource_arn, TagKeys=tags_to_remove) except (botocore.exceptions.BotoCoreError, botocore.exceptions.ClientError) as e: module.fail_json_aws(e, msg="Failed to delete tags on cluster") changed = bool(tags_to_add or tags_to_remove) return changed
def update_tags(connection, module, key, desired_tags, purge_tags): # purge_tags needs to be explicitly set, so an empty tags list means remove # all tags to_add, to_remove = compare_aws_tags(key['tags'], desired_tags, purge_tags) if not (bool(to_add) or bool(to_remove)): return False key_id = key['key_arn'] if not module.check_mode: if to_remove: try: connection.untag_resource(KeyId=key_id, TagKeys=to_remove) except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws(e, msg="Unable to remove tag") if to_add: try: tags = ansible_dict_to_boto3_tag_list( module.params['tags'], tag_name_key_name='TagKey', tag_value_key_name='TagValue') connection.tag_resource(KeyId=key_id, Tags=tags) except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws(e, msg="Unable to add tag to key") return True
def update_tags(module, connection, group, tags): changed = False existing_tags = connection.list_tags_for_resource( ResourceName=group['DBParameterGroupArn'])['TagList'] to_update, to_delete = compare_aws_tags( boto3_tag_list_to_ansible_dict(existing_tags), tags, module.params['purge_tags']) if to_update: try: connection.add_tags_to_resource( ResourceName=group['DBParameterGroupArn'], Tags=ansible_dict_to_boto3_tag_list(to_update)) changed = True except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws(e, msg="Couldn't add tags to parameter group") if to_delete: try: connection.remove_tags_from_resource( ResourceName=group['DBParameterGroupArn'], TagKeys=to_delete) changed = True except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws( e, msg="Couldn't remove tags from parameter group") return changed
def compare_tags(state_machine_arn, sfn_client, module): new_tags = module.params.get('tags') current_tags = sfn_client.list_tags_for_resource( resourceArn=state_machine_arn).get('tags') return compare_aws_tags(boto3_tag_list_to_ansible_dict(current_tags), new_tags if new_tags else {}, module.params.get('purge_tags'))
def ensure_tags(conn, module, subnet, tags, purge_tags, start_time): changed = False filters = ansible_dict_to_boto3_filter_list({ 'resource-id': subnet['id'], 'resource-type': 'subnet' }) try: cur_tags = conn.describe_tags(Filters=filters) except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws(e, msg="Couldn't describe tags") to_update, to_delete = compare_aws_tags( boto3_tag_list_to_ansible_dict(cur_tags.get('Tags')), tags, purge_tags) if to_update: try: if not module.check_mode: AWSRetry.exponential_backoff( catch_extra_error_codes=['InvalidSubnetID.NotFound'])( conn.create_tags)( Resources=[subnet['id']], Tags=ansible_dict_to_boto3_tag_list(to_update)) changed = True except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws(e, msg="Couldn't create tags") if to_delete: try: if not module.check_mode: tags_list = [] for key in to_delete: tags_list.append({'Key': key}) AWSRetry.exponential_backoff( catch_extra_error_codes=['InvalidSubnetID.NotFound'])( conn.delete_tags)(Resources=[subnet['id']], Tags=tags_list) changed = True except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws(e, msg="Couldn't delete tags") if module.params['wait'] and not module.check_mode: # Wait for tags to be updated filters = [{ 'Name': 'tag:{0}'.format(k), 'Values': [v] } for k, v in tags.items()] handle_waiter(conn, module, 'subnet_exists', { 'SubnetIds': [subnet['id']], 'Filters': filters }, start_time) return changed
def ensure_tags(self, tgw_vpc_attachment_id, tags, purge_tags): """ Ensures tags are applied to the transit gateway. Optionally will remove any existing tags not in the tags argument if purge_tags is set to true :param tgw_vpc_attachment_id: The AWS id of the transit gateway VPC attachment :param tags: list of tags to apply to the transit gateway. :param purge_tags: when true existing tags not in tags parms are removed :return: true if tags were updated """ tags_changed = False filters = ansible_dict_to_boto3_filter_list( {'resource-id': tgw_vpc_attachment_id}) try: cur_tags = self._connection.describe_tags(Filters=filters) except (ClientError, BotoCoreError) as e: self._module.fail_json_aws(e, msg="Couldn't describe tags") to_update, to_delete = compare_aws_tags( boto3_tag_list_to_ansible_dict(cur_tags.get('Tags')), tags, purge_tags) if to_update: try: if not self._check_mode: AWSRetry.exponential_backoff()( self._connection.create_tags)( Resources=[tgw_vpc_attachment_id], Tags=ansible_dict_to_boto3_tag_list(to_update)) self._results['changed'] = True tags_changed = True except (ClientError, BotoCoreError) as e: self._module.fail_json_aws( e, msg="Couldn't create tags {0} for resource {1}".format( ansible_dict_to_boto3_tag_list(to_update), tgw_vpc_attachment_id)) if to_delete: try: if not self._check_mode: tags_list = [] for key in to_delete: tags_list.append({'Key': key}) AWSRetry.exponential_backoff()( self._connection.delete_tags)( Resources=[tgw_vpc_attachment_id], Tags=tags_list) self._results['changed'] = True tags_changed = True except (ClientError, BotoCoreError) as e: self._module.fail_json_aws( e, msg="Couldn't delete tags {0} for resource {1}".format( ansible_dict_to_boto3_tag_list(to_delete), tgw_vpc_attachment_id)) return tags_changed
def main(): ''' MAIN ''' argument_spec = dict( resource=dict(required=True), tags=dict(type='dict', required=True), purge_tags=dict(type='bool', default=False), state=dict(default='present', choices=['present', 'absent']) ) module = AnsibleAWSModule(argument_spec=argument_spec, supports_check_mode=True) resource = module.params['resource'] tags = module.params['tags'] state = module.params['state'] purge_tags = module.params['purge_tags'] result = {'changed': False} efs = module.client('efs', retry_decorator=AWSRetry.jittered_backoff()) current_tags = get_tags(efs, module, resource) add_tags, remove = compare_aws_tags(current_tags, tags, purge_tags=purge_tags) remove_tags = {} if state == 'absent': for key in tags: if key in current_tags and (tags[key] is None or current_tags[key] == tags[key]): remove_tags[key] = current_tags[key] for key in remove: remove_tags[key] = current_tags[key] if remove_tags: result['changed'] = True result['removed_tags'] = remove_tags if not module.check_mode: try: efs.untag_resource(aws_retry=True, ResourceId=resource, TagKeys=list(remove_tags.keys())) except (BotoCoreError, ClientError) as remove_tag_error: module.fail_json_aws(remove_tag_error, msg='Failed to remove tags {0} from resource {1}'.format(remove_tags, resource)) if state == 'present' and add_tags: result['changed'] = True result['added_tags'] = add_tags current_tags.update(add_tags) if not module.check_mode: try: tags = ansible_dict_to_boto3_tag_list(add_tags) efs.tag_resource(aws_retry=True, ResourceId=resource, Tags=tags) except (BotoCoreError, ClientError) as set_tag_error: module.fail_json_aws(set_tag_error, msg='Failed to set tags {0} on resource {1}'.format(add_tags, resource)) result['tags'] = get_tags(efs, module, resource) module.exit_json(**result)
def ensure_tags(self, igw_id, tags, purge_tags): final_tags = [] filters = ansible_dict_to_boto3_filter_list({'resource-id': igw_id, 'resource-type': 'internet-gateway'}) cur_tags = None try: cur_tags = self._connection.describe_tags(aws_retry=True, Filters=filters) except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: self._module.fail_json_aws(e, msg="Couldn't describe tags") if tags is None: return boto3_tag_list_to_ansible_dict(cur_tags.get('Tags')) to_update, to_delete = compare_aws_tags(boto3_tag_list_to_ansible_dict(cur_tags.get('Tags')), tags, purge_tags) final_tags = boto3_tag_list_to_ansible_dict(cur_tags.get('Tags')) if to_update: try: if self._check_mode: final_tags.update(to_update) else: self._connection.create_tags( aws_retry=True, Resources=[igw_id], Tags=ansible_dict_to_boto3_tag_list(to_update) ) self._results['changed'] = True except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: self._module.fail_json_aws(e, msg="Couldn't create tags") if to_delete: try: if self._check_mode: for key in to_delete: del final_tags[key] else: tags_list = [] for key in to_delete: tags_list.append({'Key': key}) self._connection.delete_tags(aws_retry=True, Resources=[igw_id], Tags=tags_list) self._results['changed'] = True except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: self._module.fail_json_aws(e, msg="Couldn't delete tags") if not self._check_mode and (to_update or to_delete): try: response = self._connection.describe_tags(aws_retry=True, Filters=filters) final_tags = boto3_tag_list_to_ansible_dict(response.get('Tags')) except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: self._module.fail_json_aws(e, msg="Couldn't describe tags") return final_tags
def ensure_tags(connection, module, glue_job): changed = False if module.params.get('tags') is None: return False account_id, partition = get_aws_account_info(module) arn = 'arn:{0}:glue:{1}:{2}:job/{3}'.format(partition, module.region, account_id, module.params.get('name')) try: existing_tags = connection.get_tags(aws_retry=True, ResourceArn=arn).get('Tags', {}) except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: if module.check_mode: existing_tags = {} else: module.fail_json_aws(e, msg='Unable to get tags for Glue job %s' % module.params.get('name')) tags_to_add, tags_to_remove = compare_aws_tags( existing_tags, module.params.get('tags'), module.params.get('purge_tags')) if tags_to_remove: changed = True if not module.check_mode: try: connection.untag_resource(aws_retry=True, ResourceArn=arn, TagsToRemove=tags_to_remove) except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws(e, msg='Unable to set tags for Glue job %s' % module.params.get('name')) if tags_to_add: changed = True if not module.check_mode: try: connection.tag_resource(aws_retry=True, ResourceArn=arn, TagsToAdd=tags_to_add) except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws(e, msg='Unable to set tags for Glue job %s' % module.params.get('name')) return changed
def update_tags(client, stream_name, tags, check_mode=False): """Update tags for an amazon resource. Args: resource_id (str): The Amazon resource id. tags (dict): Dictionary of tags you want applied to the Kinesis stream. Kwargs: check_mode (bool): This will pass DryRun as one of the parameters to the aws api. default=False Basic Usage: >>> client = boto3.client('ec2') >>> stream_name = 'test-stream' >>> tags = {'env': 'development'} >>> update_tags(client, stream_name, tags) [True, ''] Return: Tuple (bool, str) """ success = False changed = False err_msg = '' tag_success, tag_msg, current_tags = (get_tags(client, stream_name)) tags_to_set, tags_to_delete = compare_aws_tags( current_tags, tags, purge_tags=True, ) if tags_to_delete: delete_success, delete_msg = (tags_action(client, stream_name, tags_to_delete, action='delete', check_mode=check_mode)) if not delete_success: return delete_success, changed, delete_msg tag_msg = 'Tags removed' if tags_to_set: create_success, create_msg = (tags_action(client, stream_name, tags_to_set, action='create', check_mode=check_mode)) if create_success: changed = True return create_success, changed, create_msg return success, changed, err_msg
def ensure_tags(client, module, vpc_endpoint_id): changed = False tags = module.params['tags'] purge_tags = module.params['purge_tags'] filters = ansible_dict_to_boto3_filter_list( {'resource-id': vpc_endpoint_id}) try: current_tags = client.describe_tags(aws_retry=True, Filters=filters) except (botocore.exceptions.BotoCoreError, botocore.exceptions.ClientError) as e: module.fail_json_aws( e, msg="Failed to describe tags for VPC Endpoint: {0}".format( vpc_endpoint_id)) tags_to_set, tags_to_unset = compare_aws_tags( boto3_tag_list_to_ansible_dict(current_tags.get('Tags')), tags, purge_tags=purge_tags) if purge_tags and not tags: tags_to_unset = current_tags if tags_to_unset: changed = True if not module.check_mode: try: client.delete_tags( aws_retry=True, Resources=[vpc_endpoint_id], Tags=[dict(Key=tagkey) for tagkey in tags_to_unset]) except (botocore.exceptions.BotoCoreError, botocore.exceptions.ClientError) as e: module.fail_json_aws( e, msg="Unable to delete tags {0}".format(tags_to_unset)) if tags_to_set: changed = True if not module.check_mode: try: client.create_tags( aws_retry=True, Resources=[vpc_endpoint_id], Tags=ansible_dict_to_boto3_tag_list(tags_to_set)) except (botocore.exceptions.BotoCoreError, botocore.exceptions.ClientError) as e: module.fail_json_aws( e, msg="Unable to add tags {0}".format(tags_to_set)) return changed
def check_for_update(connection, module_params, vpn_connection_id): """ Determines if there are any tags or routes that need to be updated. Ensures non-modifiable attributes aren't expected to change. """ tags = module_params.get('tags') routes = module_params.get('routes') purge_tags = module_params.get('purge_tags') purge_routes = module_params.get('purge_routes') vpn_connection = find_connection(connection, module_params, vpn_connection_id=vpn_connection_id) current_attrs = camel_dict_to_snake_dict(vpn_connection) # Initialize changes dict changes = {'tags_to_add': [], 'tags_to_remove': [], 'routes_to_add': [], 'routes_to_remove': []} # Get changes to tags current_tags = boto3_tag_list_to_ansible_dict(current_attrs.get('tags', []), u'key', u'value') tags_to_add, changes['tags_to_remove'] = compare_aws_tags(current_tags, tags, purge_tags) changes['tags_to_add'] = ansible_dict_to_boto3_tag_list(tags_to_add) # Get changes to routes if 'Routes' in vpn_connection: current_routes = [route['DestinationCidrBlock'] for route in vpn_connection['Routes']] if purge_routes: changes['routes_to_remove'] = [old_route for old_route in current_routes if old_route not in routes] changes['routes_to_add'] = [new_route for new_route in routes if new_route not in current_routes] # Check if nonmodifiable attributes are attempted to be modified for attribute in current_attrs: if attribute in ("tags", "routes", "state"): continue elif attribute == 'options': will_be = module_params.get('static_only', None) is_now = bool(current_attrs[attribute]['static_routes_only']) attribute = 'static_only' elif attribute == 'type': will_be = module_params.get("connection_type", None) is_now = current_attrs[attribute] else: is_now = current_attrs[attribute] will_be = module_params.get(attribute, None) if will_be is not None and to_text(will_be) != to_text(is_now): raise VPNConnectionException(msg="You cannot modify {0}, the current value of which is {1}. Modifiable VPN " "connection attributes are tags and routes. The value you tried to change it to " "is {2}.".format(attribute, is_now, will_be)) return changes
def ensure_tags(client, module, resource_arn, existing_tags, tags, purge_tags): if tags is None: return (False, existing_tags) tags_to_add, tags_to_remove = compare_aws_tags(existing_tags, tags, purge_tags) changed = bool(tags_to_add or tags_to_remove) if tags_to_add and not module.check_mode: try: client.add_tags_to_certificate( CertificateArn=resource_arn, Tags=ansible_dict_to_boto3_tag_list(tags_to_add), ) except ( botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError, ) as e: module.fail_json_aws( e, "Couldn't add tags to certificate {0}".format(resource_arn)) if tags_to_remove and not module.check_mode: # remove_tags_from_certificate wants a list of key, value pairs, not a list of keys. tags_list = [{ 'Key': key, 'Value': existing_tags.get(key) } for key in tags_to_remove] try: client.remove_tags_from_certificate( CertificateArn=resource_arn, Tags=tags_list, ) except ( botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError, ) as e: module.fail_json_aws( e, "Couldn't remove tags from certificate {0}".format( resource_arn)) new_tags = deepcopy(existing_tags) for key, value in tags_to_add.items(): new_tags[key] = value for key in tags_to_remove: new_tags.pop(key, None) return (changed, new_tags)
def update_tags(client, module, option_group): if module.params.get('tags') is None: return False try: existing_tags = client.list_tags_for_resource( aws_retry=True, ResourceName=option_group['option_group_arn'])['TagList'] except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws(e, msg="Couldn't obtain option group tags.") to_update, to_delete = compare_aws_tags( boto3_tag_list_to_ansible_dict(existing_tags), module.params['tags'], module.params['purge_tags']) changed = bool(to_update or to_delete) if to_update: try: if module.check_mode: return changed client.add_tags_to_resource( aws_retry=True, ResourceName=option_group['option_group_arn'], Tags=ansible_dict_to_boto3_tag_list(to_update)) except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws(e, msg="Couldn't add tags to option group.") if to_delete: try: if module.check_mode: return changed client.remove_tags_from_resource( aws_retry=True, ResourceName=option_group['option_group_arn'], TagKeys=to_delete) except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws(e, msg="Couldn't remove tags from option group.") return changed
def set_tag(client, module, tags, function): if not hasattr(client, "list_tags"): module.fail_json(msg="Using tags requires botocore 1.5.40 or above") changed = False arn = function['Configuration']['FunctionArn'] try: current_tags = client.list_tags(Resource=arn).get('Tags', {}) except ClientError as e: module.fail_json(msg="Unable to list tags: {0}".format(to_native(e)), exception=traceback.format_exc()) tags_to_add, tags_to_remove = compare_aws_tags(current_tags, tags, purge_tags=True) try: if tags_to_remove: client.untag_resource( Resource=arn, TagKeys=tags_to_remove ) changed = True if tags_to_add: client.tag_resource( Resource=arn, Tags=tags_to_add ) changed = True except ClientError as e: module.fail_json(msg="Unable to tag resource {0}: {1}".format(arn, to_native(e)), exception=traceback.format_exc(), **camel_dict_to_snake_dict(e.response)) except BotoCoreError as e: module.fail_json(msg="Unable to tag resource {0}: {1}".format(arn, to_native(e)), exception=traceback.format_exc()) return changed
def ensure_tags(client, module, resource_arn, existing_tags, tags, purge_tags): if tags is None: return False tags_to_add, tags_to_remove = compare_aws_tags(existing_tags, tags, purge_tags) changed = bool(tags_to_add or tags_to_remove) if tags_to_add: call_method(client, module, method_name='add_tags_to_resource', parameters={ 'ResourceName': resource_arn, 'Tags': ansible_dict_to_boto3_tag_list(tags_to_add) }) if tags_to_remove: call_method(client, module, method_name='remove_tags_from_resource', parameters={ 'ResourceName': resource_arn, 'TagKeys': tags_to_remove }) return changed