diff --git a/lib/ansible/modules/files/xattr.py b/lib/ansible/modules/files/xattr.py index 000ddd0a296..676436fec05 100644 --- a/lib/ansible/modules/files/xattr.py +++ b/lib/ansible/modules/files/xattr.py @@ -25,6 +25,11 @@ options: - Before 2.3 this option was only usable as I(name). aliases: [ name ] required: true + namespace: + description: + - Namespace of the named name/key. + default: user + version_added: "2.7" key: description: - The name of a specific Extended attribute key to set/retrieve. @@ -58,22 +63,34 @@ EXAMPLES = ''' xattr: path: /etc/foo.conf -- name: Sets the key 'foo' to value 'bar' +- name: Set the key 'user.foo' to value 'bar' xattr: path: /etc/foo.conf - key: user.foo + key: foo value: bar -- name: Removes the key 'foo' +- name: Set the key 'trusted.glusterfs.volume-id' to value '0x817b94343f164f199e5b573b4ea1f914' + xattr: + path: /mnt/bricks/brick1 + namespace: trusted + key: glusterfs.volume-id + value: "0x817b94343f164f199e5b573b4ea1f914" + +- name: Remove the key 'user.foo' xattr: path: /etc/foo.conf - key: user.foo + key: foo + state: absent + +- name: Remove the key 'trusted.glusterfs.volume-id' + xattr: + path: /mnt/bricks/brick1 + namespace: trusted + key: glusterfs.volume-id state: absent ''' -import operator import os -import re # import module snippets from ansible.module_utils.basic import AnsibleModule @@ -140,10 +157,10 @@ def _run_xattr(module, cmd, check_rc=True): # result = {'raw': out} result = {} for line in out.splitlines(): - if re.match("^#", line) or line == "": + if line.startswith('#') or line == '': pass - elif re.search('=', line): - (key, val) = line.split("=") + elif '=' in line: + (key, val) = line.split('=') result[key] = val.strip('"') else: result[line] = '' @@ -154,6 +171,7 @@ def main(): module = AnsibleModule( argument_spec=dict( path=dict(type='path', required=True, aliases=['name']), + namespace=dict(type='str', default='user'), key=dict(type='str'), value=dict(type='str'), state=dict(type='str', default='read', choices=['absent', 'all', 'keys', 'present', 'read']), @@ -162,6 +180,7 @@ def main(): supports_check_mode=True, ) path = module.params.get('path') + namespace = module.params.get('namespace') key = module.params.get('key') value = module.params.get('value') state = module.params.get('state') @@ -177,9 +196,13 @@ def main(): if key is None and state in ['absent', 'present']: module.fail_json(msg="%s needs a key parameter" % state) - # All xattr must begin in user namespace - if key is not None and not re.match(r'^user\.', key): - key = 'user.%s' % key + # Prepend the key with the namespace if defined + if ( + key is not None and + namespace is not None and + len(namespace) > 0 and + not (namespace == 'user' and key.startswith('user.'))): + key = '%s.%s' % (namespace, key) if (state == 'present' or value is not None): current = get_xattr(module, path, key, follow) diff --git a/test/integration/targets/xattr/tasks/test.yml b/test/integration/targets/xattr/tasks/test.yml index 4f4f35672c1..616432681f9 100644 --- a/test/integration/targets/xattr/tasks/test.yml +++ b/test/integration/targets/xattr/tasks/test.yml @@ -13,7 +13,7 @@ - name: Get specific attribute xattr: path: "{{ test_file }}" - key: user.foo + key: foo register: xattr_get_specific_result - assert: @@ -27,7 +27,8 @@ - name: Set attribute again xattr: path: "{{ test_file }}" - key: user.foo + namespace: user + key: foo value: bar register: xattr_set_again_result @@ -38,11 +39,11 @@ - name: Unset attribute xattr: path: "{{ test_file }}" - key: user.foo + key: foo state: absent register: xattr_unset_result -- name: get attributes +- name: Get attributes xattr: path: "{{ test_file }}" register: xattr_get_after_unset_result @@ -56,7 +57,8 @@ - name: Unset attribute again xattr: path: "{{ test_file }}" - key: user.foo + namespace: user + key: foo state: absent register: xattr_unset_result