Merge pull request #11078 from Yannig/devel

New lookup plugin : ini
This commit is contained in:
Brian Coca 2015-08-07 09:46:54 -04:00
commit 8f106c9a58
6 changed files with 272 additions and 0 deletions

View file

@ -139,6 +139,65 @@ default empty string return value if the key is not in the csv file
.. note:: The default delimiter is TAB, *not* comma.
.. _ini_lookup:
The INI File Lookup
```````````````````
.. versionadded:: 2.0
The ``ini`` lookup reads the contents of a file in INI format (key1=value1).
This plugin retrieve the value on the right side after the equal sign ('=') of
a given section ([section]). You can also read a property file which - in this
case - does not contain section.
Here's a simple example of an INI file with user/password configuration::
[production]
# My production information
user=robert
pass=somerandompassword
[integration]
# My integration information
user=gertrude
pass=anotherpassword
We can use the ``ini`` plugin to lookup user configuration::
- 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') }}"
Another example for this plugin is for looking for a value on java properties.
Here's a simple properties we'll take as an example::
user.name=robert
user.pass=somerandompassword
You can retrieve the ``user.name`` field with the following lookup::
- debug: msg="user.name is {{ lookup('ini', 'user.name type=property file=user.properties') }}"
The ``ini`` lookup supports several arguments like the csv plugin. The format for passing
arguments is::
lookup('ini', 'key [type=<properties|ini>] [section=section] [file=file.ini] [re=true] [default=<defaultvalue>]')
The first value in the argument is the ``key``, which must be an entry that
appears exactly once on keys. All other arguments are optional.
========== ============ =========================================================================================
Field Default Description
---------- ------------ -----------------------------------------------------------------------------------------
type ini Type of the file. Can be ini or properties (for java properties).
file ansible.ini Name of the file to load
section global Default section where to lookup for key.
re False The key is a regexp.
default empty string return value if the key is not in the ini file
========== ============ =========================================================================================
.. note:: In java properties files, there's no need to specify a section.
.. _credstash_lookup:

View file

@ -347,6 +347,54 @@ It's uncommonly used::
debug: msg="at array position {{ item.0 }} there is a value {{ item.1 }}"
with_indexed_items: "{{some_list}}"
.. _using_ini_with_a_loop:
Using ini file with a loop
``````````````````````````
.. versionadded: 2.0
The ini plugin can use regexp to retrieve a set of keys. As a consequence, we can loop over this set. Here is the ini file we'll use::
[section1]
value1=section1/value1
value2=section1/value2
[section2]
value1=section2/value1
value2=section2/value2
Here is an example of using ``with_ini``::
- debug: msg="{{item}}"
with_ini: value[1-2] section=section1 file=lookup.ini re=true
And here is the returned value::
{
"changed": false,
"msg": "All items completed",
"results": [
{
"invocation": {
"module_args": "msg=\"section1/value1\"",
"module_name": "debug"
},
"item": "section1/value1",
"msg": "section1/value1",
"verbose_always": true
},
{
"invocation": {
"module_args": "msg=\"section1/value2\"",
"module_name": "debug"
},
"item": "section1/value2",
"msg": "section1/value2",
"verbose_always": true
}
]
}
.. _flattening_a_list:
Flattening A List

View file

@ -0,0 +1,96 @@
# (c) 2015, Yannig Perre <yannig.perre(at)gmail.com>
#
# 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 <http://www.gnu.org/licenses/>.
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
import StringIO
import os
import codecs
import ConfigParser
import re
from ansible.errors import *
from ansible.plugins.lookup import LookupBase
class LookupModule(LookupBase):
def read_properties(self, filename, key, dflt, is_regexp):
config = StringIO.StringIO()
config.write('[java_properties]\n' + open(filename).read())
config.seek(0, os.SEEK_SET)
self.cp.readfp(config)
return self.get_value(key, 'java_properties', dflt, is_regexp)
def read_ini(self, filename, key, section, dflt, is_regexp):
self.cp.readfp(open(filename))
return self.get_value(key, section, dflt, is_regexp)
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, e:
return dflt
return value
def run(self, terms, variables=None, **kwargs):
if isinstance(terms, basestring):
terms = [ terms ]
basedir = self.get_basedir(variables)
self.basedir = basedir
self.cp = ConfigParser.ConfigParser()
ret = []
for term in terms:
params = term.split()
key = params[0]
paramvals = {
'file' : 'ansible.ini',
're' : False,
'default' : None,
'section' : "global",
'type' : "ini",
}
# parameters specified?
try:
for param in params[1:]:
name, value = param.split('=')
assert(name in paramvals)
paramvals[name] = value
except (ValueError, AssertionError), e:
raise errors.AnsibleError(e)
path = self._loader.path_dwim_relative(basedir, 'files', paramvals['file'])
if paramvals['type'] == "properties":
var = self.read_properties(path, key, paramvals['default'], paramvals['re'])
else:
var = self.read_ini(path, key, paramvals['section'], paramvals['default'], paramvals['re'])
if var is not None:
if type(var) is list:
for v in var:
ret.append(v)
else:
ret.append(var)
return ret

View file

@ -0,0 +1,24 @@
[global]
# A comment
value1=Text associated with value1 and global section
value2=Same for value2 and global section
value.dot=Properties with dot
field.with.space = another space
[section1]
value1=section1/value1
value2=section1/value2
[value_section]
value1=1
value2=2
value3=3
other1=4
other2=5
[other_section]
value1=1
value2=2
value3=3
other1=4
other2=5

View file

@ -0,0 +1,5 @@
# A comment
value1=Text associated with value1
value2=Same for value2
value.dot=Properties with dot
field.with.space = another space

View file

@ -0,0 +1,40 @@
---
- name: "Lookup test"
hosts: "localhost"
# connection: local
tasks:
- name: "read properties value"
set_fact:
test1: "{{lookup('ini', 'value1 type=properties file=lookup.properties')}}"
test2: "{{lookup('ini', 'value2 type=properties file=lookup.properties')}}"
test_dot: "{{lookup('ini', 'value.dot type=properties file=lookup.properties')}}"
field_with_space: "{{lookup('ini', 'field.with.space type=properties file=lookup.properties')}}"
- debug: var={{item}}
with_items: [ 'test1', 'test2', 'test_dot', 'field_with_space' ]
- name: "read ini value"
set_fact:
value1_global: "{{lookup('ini', 'value1 section=global file=lookup.ini')}}"
value2_global: "{{lookup('ini', 'value2 section=global file=lookup.ini')}}"
value1_section1: "{{lookup('ini', 'value1 section=section1 file=lookup.ini')}}"
- debug: var={{item}}
with_items: [ 'value1_global', 'value2_global', 'value1_section1' ]
- name: "read ini value with section and regexp"
set_fact:
value_section: "{{lookup('ini', 'value[1-2] section=value_section file=lookup.ini re=true')}}"
other_section: "{{lookup('ini', 'other[1-2] section=other_section file=lookup.ini re=true')}}"
- debug: var={{item}}
with_items: [ 'value_section', 'other_section' ]
- name: "Reading unknown value"
set_fact:
unknown: "{{lookup('ini', 'value2 default=unknown section=section1 file=lookup.ini')}}"
- debug: var=unknown
- name: "Looping over section section1"
debug: msg="{{item}}"
with_ini: value[1-2] section=section1 file=lookup.ini re=true
- name: "Looping over section value_section"
debug: msg="{{item}}"
with_ini: value[1-2] section=value_section file=lookup.ini re=true
- debug: msg="{{item}}"
with_ini: value[1-2] section=section1 file=lookup.ini re=true
register: _
- debug: var=_