1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
| ## (c) 2015, Yannig Perre <yannig.perre(at)gmail.com>
## (c) 2017 Ansible Project
## GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
DOCUMENTATION = """
lookup: ini
author: Yannig Perre <yannig.perre(at)gmail.com>
version_added: "2.0"
short_description: read data from a ini file
description:
- "The ini lookup reads the contents of a file in INI format C(key1=value1).
This plugin retrieves the value on the right side after the equal sign C('=') of a given section C([section])."
- "You can also read a property file which - in this case - does not contain section."
options:
_terms:
description: The key(s) to look up
required: True
type:
description: Type of the file. 'properties' refers to the Java properties files.
default: 'ini'
choices: ['ini', 'properties']
file:
description: Name of the file to load.
default: ansible.ini
section:
default: global
description: Section where to lookup the key.
re:
default: False
type: boolean
description: Flag to indicate if the key supplied is a regexp.
encoding:
default: utf-8
description: Text encoding to use.
default:
description: Return value if the key is not in the ini file.
default: ''
"""
EXAMPLES = """
- debug: msg="User in integration is {{ lookup('ini', 'user section=integration file=users.ini') }}"
- debug: msg="User in production is {{ lookup('ini', 'user section=production file=users.ini') }}"
- debug: msg="user.name is {{ lookup('ini', 'user.name type=properties file=user.properties') }}"
- debug:
msg: "{{ item }}"
with_ini:
- '.* section=section1 file=test.ini re=True'
"""
RETURN = """
_raw:
description:
- value(s) of the key(s) in the ini file
"""
import os
import re
from io import StringIO
from ansible.errors import AnsibleError, AnsibleAssertionError
from ansible.module_utils.six.moves import configparser
from ansible.module_utils._text import to_bytes, to_text
from ansible.module_utils.common._collections_compat import MutableSequence
from ansible.plugins.lookup import LookupBase
def _parse_params(term):
'''Safely split parameter term to preserve spaces'''
keys = ['key', 'type', 'section', 'file', 're', 'default', 'encoding']
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 get_value(self, key, section, dflt, is_regexp):
# Retrieve all values from a section using a regexp
if is_regexp:
return [v for k, v in self.cp.items(section) if re.match(key, k)]
value = None
# Retrieve a single value
try:
value = self.cp.get(section, key)
except configparser.NoOptionError:
return dflt
return value
def run(self, terms, variables=None, **kwargs):
self.cp = configparser.ConfigParser()
ret = []
for term in terms:
params = _parse_params(term)
key = params[0]
paramvals = {
'file': 'ansible.ini',
're': False,
'default': None,
'section': "global",
'type': "ini",
'encoding': 'utf-8',
}
# parameters specified?
try:
for param in params[1:]:
name, value = param.split('=')
if name not in paramvals:
raise AnsibleAssertionError('%s not in paramvals' %
name)
paramvals[name] = value
except (ValueError, AssertionError) as e:
raise AnsibleError(e)
# Retrieve file path
path = self.find_file_in_search_path(variables, 'files',
paramvals['file'])
# Create StringIO later used to parse ini
config = StringIO()
# Special case for java properties
if paramvals['type'] == "properties":
config.write(u'[java_properties]\n')
paramvals['section'] = 'java_properties'
# Open file using encoding
contents, show_data = self._loader._get_file_contents(path)
contents = to_text(contents, errors='surrogate_or_strict',
encoding=paramvals['encoding'])
config.write(contents)
config.seek(0, os.SEEK_SET)
self.cp.readfp(config)
var = self.get_value(key, paramvals['section'],
paramvals['default'], paramvals['re'])
if var is not None:
if isinstance(var, MutableSequence):
for v in var:
ret.append(v)
else:
ret.append(var)
return ret
|