19

I'm automatically securing SSL keys like this:

- name: Find ssl keys
  find: paths="/etc/ssl/" patterns="*.key" recurse=yes
  register: secure_ssl_keys_result

- name: Secure ssl keys
  file: path={{ item.path }} user=root group=root mode=600
  with_items: secure_ssl_keys_result.files

Now, for every item, there is a huge log message with the whole content of the item:

ok: [127.0.0.1] => (item={u'uid': 0, u'woth': False, u'mtime': 1454939377.264, u'inode': 400377, u'isgid': False, u'size': 3243, u'roth': False, u'isuid': False, u'isreg': True, u'gid': 0, u'ischr': False, u'wusr': True, u'xoth': False, u'rusr': True, u'nlink': 1, u'issock': False, u'rgrp': False, u'path': u'/etc/ssl/foo.key', u'xusr': False, u'atime': 1454939377.264, u'isdir': False, u'ctime': 1454939657.116, u'isblk': False, u'xgrp': False, u'dev': 65025, u'wgrp': False, u'isfifo': False, u'mode': u'0600', u'islnk': False})

This is incredibly unreadable, as I only want to know the path of the item that is being processed (and maybe changed). With a big number of keys, this get's out of hand really quick.

How can I change this play in a way that only the item.path is being printed out for each item?

I have already tried no_log: True, but this completely omits the output of course.

slm
  • 7,615
  • 16
  • 56
  • 76
Zulakis
  • 4,153
  • 14
  • 48
  • 76
  • Maybe you could write a [Jinja Filter](docs.ansible.com/ansible/playbooks_filters.html) set `no_log: true` and return the value of `item.path` with [debug module](http://docs.ansible.com/ansible/debug_module.html) – Henrik Pingel Feb 16 '16 at 10:08

3 Answers3

28

Ansible 2.2 has loop_control.label for this.

- name: Secure ssl keys
  file: path={{ item.path }} user=root group=root mode=600
  with_items: secure_ssl_keys_result.files
  loop_control:
    label: "{{ item.path }}"
sourcejedi
  • 1,100
  • 10
  • 20
6

Method 1

Use

secure_ssl_keys_result.files|map(attribute='path')|list

It will return a list of paths:

['/etc/ssl../', '/etc/ssl/.../']

Your whole task would become:

- name: Secure ssl keys
  file: path={{ item }} user=root group=root mode=600
  with_items: secure_ssl_keys_result.files|map(attribute='path')|list

Beware that you can only select a single attribute, it is not possible to use attribute=['path', 'mode'] or similar.

Method 2

I thought of using extract to be able to fetch multiple keys (because it is sometimes necessary to have a second key for a when condition), but didn't manage to do it, as I would need to map the list of dicts, then map the list of keys over the specific dict, which doesn't seem possible, as map only accepts a function name but not a function definition/chained functions. I would be grateful for an suggestion here!

A great idea from the comments (Thanks, Uditha Desilva!):

- name: Secure ssl keys file: path={{ item.0 }} mode=600 owner={{ item.1 }}
  with_together: 
  - secure_ssl_keys_result.files|map(attribute='path')|list 
  - secure_ssl_keys_result.files|map(attribute='uid')|list 

Method 3

Alternatively, a custom filter like this could be used (that's what I did before I found out about map):

from ansible import errors
import re

def cleandict(items, keepkeys):
    try:
        newitems = []
        if not isinstance(items, list):
          items = [items]
        if not isinstance(keepkeys, list):
          keepkeys = [keepkeys]
        for dictionary in items:
          newdictionary = {}
          for keepkey in keepkeys:
            newdictionary[keepkey] = dictionary.get(keepkey)
          newitems.append(newdictionary)  
        return newitems
    except Exception, e:
        raise errors.AnsibleFilterError('split plugin error: %s' % str(e) )
        #raise errors.AnsibleFilterError('split plugin error: %s, string=%s' % str(e),str(items) )

class FilterModule(object):
    ''' A filter to split a string into a list. '''
    def filters(self):
        return {
            'cleandict' : cleandict
        }

ansible.cfg:

filter_plugins = ~/.ansible/plugins/filter_plugins/:/usr/share/ansible_plugins/filter_plugins
Zulakis
  • 4,153
  • 14
  • 48
  • 76
  • 1
    Regarding your method 2, it would seem viable to use "with_together", even if it isn't super-efficient (unfortunately comments can't use code tags so this will look odd): - name: Secure ssl keys file: path={{ item[0] }} mode=600 owner={{ item[1] }} with_together: - secure_ssl_keys_result.files|map(attribute='path')|list - secure_ssl_keys_result.files|map(attribute='uid')|list – Uditha Desilva Mar 02 '16 at 11:04
1

You can't. It's either all or nothing (via no_log: True)

udondan
  • 2,061
  • 15
  • 18