From 4ba60d00c8d7e62912a37ec24f90f6e5d0770c4d Mon Sep 17 00:00:00 2001 From: jctanner Date: Tue, 28 Jun 2016 13:24:57 -0400 Subject: [PATCH] Refactor the parameter splitting in ini lookup to handle more path formats (#16477) Refactor the parameter splitting in ini lookup to handle more path formats. Fixes #16468 --- lib/ansible/plugins/lookup/ini.py | 37 ++++++++++++++-- test/units/plugins/lookup/test_ini.py | 63 +++++++++++++++++++++++++++ 2 files changed, 96 insertions(+), 4 deletions(-) create mode 100644 test/units/plugins/lookup/test_ini.py diff --git a/lib/ansible/plugins/lookup/ini.py b/lib/ansible/plugins/lookup/ini.py index 0e68816dc32..5881930e9f7 100644 --- a/lib/ansible/plugins/lookup/ini.py +++ b/lib/ansible/plugins/lookup/ini.py @@ -19,12 +19,41 @@ __metaclass__ = type from io import StringIO import os -import ConfigParser import re +try: + # python2 + import ConfigParser as configparser +except ImportError: + # python3 + import configparser + from ansible.errors import AnsibleError from ansible.plugins.lookup import LookupBase + +def _parse_params(term): + '''Safely split parameter term to preserve spaces''' + + keys = ['key', 'section', 'file', 're'] + params = {} + for k in keys: + params[k] = '' + + thiskey = 'key' + for idp,phrase in enumerate(term.split()): + for k in keys: + if ('%s=' % k) in phrase: + thiskey = k + if idp == 0 or not params[thiskey]: + params[thiskey] = phrase + else: + params[thiskey] += ' ' + phrase + + rparams = [params[x] for x in keys if params[x]] + return rparams + + class LookupModule(LookupBase): def read_properties(self, filename, key, dflt, is_regexp): @@ -46,7 +75,7 @@ class LookupModule(LookupBase): # Retrieve a single value try: value = self.cp.get(section, key) - except ConfigParser.NoOptionError: + except configparser.NoOptionError: return dflt return value @@ -54,11 +83,11 @@ class LookupModule(LookupBase): basedir = self.get_basedir(variables) self.basedir = basedir - self.cp = ConfigParser.ConfigParser() + self.cp = configparser.ConfigParser() ret = [] for term in terms: - params = term.split() + params = _parse_params(term) key = params[0] paramvals = { diff --git a/test/units/plugins/lookup/test_ini.py b/test/units/plugins/lookup/test_ini.py new file mode 100644 index 00000000000..aeb6c2e067f --- /dev/null +++ b/test/units/plugins/lookup/test_ini.py @@ -0,0 +1,63 @@ +# -*- coding: utf-8 -*- +# (c) 2015, Toshio Kuratomi +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see . + +# Make coding more python3-ish +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +from ansible.compat.tests import unittest +from ansible.plugins.lookup.ini import _parse_params + + +class TestINILookup(unittest.TestCase): + + # Currently there isn't a new-style + old_style_params_data = ( + # Simple case + dict(term=u'keyA section=sectionA file=/path/to/file', + expected=[u'keyA', u'section=sectionA', u'file=/path/to/file'], + ), + dict(term=u'keyB section=sectionB with space file=/path/with/embedded spaces and/file', + expected=[u'keyB', u'section=sectionB with space', u'file=/path/with/embedded spaces and/file'], + ), + dict(term=u'keyC section=sectionC file=/path/with/equals/cn=com.ansible', + expected=[u'keyC', u'section=sectionC', u'file=/path/with/equals/cn=com.ansible'], + ), + dict(term=u'keyD section=sectionD file=/path/with space and/equals/cn=com.ansible', + expected=[u'keyD', u'section=sectionD', u'file=/path/with space and/equals/cn=com.ansible'], + ), + dict(term=u'keyE section=sectionE file=/path/with/unicode/くらとみ/file', + expected=[u'keyE', u'section=sectionE', u'file=/path/with/unicode/くらとみ/file'], + ), + dict(term=u'keyF section=sectionF file=/path/with/utf 8 and spaces/くらとみ/file', + expected=[u'keyF', u'section=sectionF', u'file=/path/with/utf 8 and spaces/くらとみ/file'], + ), + ) + + + def setUp(self): + pass + + def tearDown(self): + pass + + def test_parse_parameters(self): + for testcase in self.old_style_params_data: + #print(testcase) + params = _parse_params(testcase['term']) + self.assertEqual(params, testcase['expected'])