@ -23,7 +23,7 @@ DOCUMENTATION = """
choices : [ ' ini ' , ' properties ' ]
choices : [ ' ini ' , ' properties ' ]
file :
file :
description : Name of the file to load .
description : Name of the file to load .
default : ansible . ini
default : ' ansible.ini '
section :
section :
default : global
default : global
description : Section where to lookup the key .
description : Section where to lookup the key .
@ -40,16 +40,15 @@ DOCUMENTATION = """
"""
"""
EXAMPLES = """
EXAMPLES = """
- debug : msg = " User in integration is {{ lookup( ' ini ' , ' user section=integration file=users.ini' ) }} "
- 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 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 = " user.name is {{ lookup( ' ini ' , ' user.name ' , type=' properties' , file=' user.properties' ) }} "
- debug :
- debug :
msg : " {{ item }} "
msg : " {{ item }} "
with_ini :
loop : " {{ q( ' ini ' , ' .* ' , section= ' section1 ' , file= ' test.ini ' , re=True)}} "
- ' .* section=section1 file=test.ini re=True '
"""
"""
RETURN = """
RETURN = """
@ -59,37 +58,48 @@ _raw:
type : list
type : list
elements : str
elements : str
"""
"""
import os
import os
import re
import re
from io import StringIO
from io import StringIO
from collections import defaultdict
from ansible . errors import Ansible Error, AnsibleAssertion Error
from ansible . errors import Ansible Lookup Error
from ansible . module_utils . six . moves import configparser
from ansible . module_utils . six . moves import configparser
from ansible . module_utils . _text import to_bytes , to_text
from ansible . module_utils . _text import to_bytes , to_text , to_native
from ansible . module_utils . common . _collections_compat import MutableSequence
from ansible . module_utils . common . _collections_compat import MutableSequence
from ansible . plugins . lookup import LookupBase
from ansible . plugins . lookup import LookupBase
def _parse_params ( term ):
def _parse_params ( term , paramvals ):
''' Safely split parameter term to preserve spaces '''
''' Safely split parameter term to preserve spaces '''
keys = [ ' key ' , ' type ' , ' section ' , ' file ' , ' re ' , ' default ' , ' encoding ' ]
# TODO: deprecate this method
params = { }
valid_keys = paramvals . keys ( )
for k in keys :
params = defaultdict ( lambda : ' ' )
params [ k ] = ' '
thiskey = ' key '
# TODO: check kv_parser to see if it can handle spaces this same way
keys = [ ]
thiskey = ' key ' # initialize for 'lookup item'
for idp , phrase in enumerate ( term . split ( ) ) :
for idp , phrase in enumerate ( term . split ( ) ) :
for k in keys :
if ( ' %s = ' % k ) in phrase :
# update current key if used
thiskey = k
if ' = ' in phrase :
for k in valid_keys :
if ( ' %s = ' % k ) in phrase :
thiskey = k
# if first term or key does not exist
if idp == 0 or not params [ thiskey ] :
if idp == 0 or not params [ thiskey ] :
params [ thiskey ] = phrase
params [ thiskey ] = phrase
keys . append ( thiskey )
else :
else :
# append to existing key
params [ thiskey ] + = ' ' + phrase
params [ thiskey ] + = ' ' + phrase
rparams = [ params [ x ] for x in keys if params [ x ] ]
# return list of values
return r params
return [ params[ x ] for x in keys ]
class LookupModule ( LookupBase ) :
class LookupModule ( LookupBase ) :
@ -108,36 +118,36 @@ class LookupModule(LookupBase):
def run ( self , terms , variables = None , * * kwargs ) :
def run ( self , terms , variables = None , * * kwargs ) :
self . set_options ( var_options = variables , direct = kwargs )
paramvals = self . get_options ( )
self . cp = configparser . ConfigParser ( )
self . cp = configparser . ConfigParser ( )
ret = [ ]
ret = [ ]
for term in terms :
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 ' ,
}
key = term
# parameters specified?
# parameters specified?
try :
if ' = ' in term or ' ' in term . strip ( ) :
for param in params [ 1 : ] :
self . _deprecate_inline_kv ( )
name , value = param . split ( ' = ' )
params = _parse_params ( term , paramvals )
if name not in paramvals :
try :
raise AnsibleAssertionError ( ' %s not in paramvals ' %
for param in params :
name )
if ' = ' in param :
paramvals [ name ] = value
name , value = param . split ( ' = ' )
except ( ValueError , AssertionError ) as e :
if name not in paramvals :
raise AnsibleError ( e )
raise AnsibleLookupError ( ' %s is not a valid option. ' % name )
paramvals [ name ] = value
elif key == term :
# only take first, this format never supported multiple keys inline
key = param
except ValueError as e :
# bad params passed
raise AnsibleLookupError ( " Could not use ' %s ' from ' %s ' : %s " % ( param , params , to_native ( e ) ) , orig_exc = e )
# TODO: look to use cache to avoid redoing this for every term if they use same file
# Retrieve file path
# Retrieve file path
path = self . find_file_in_search_path ( variables , ' files ' ,
path = self . find_file_in_search_path ( variables , ' files ' , paramvals [ ' file ' ] )
paramvals [ ' file ' ] )
# Create StringIO later used to parse ini
# Create StringIO later used to parse ini
config = StringIO ( )
config = StringIO ( )
@ -148,14 +158,12 @@ class LookupModule(LookupBase):
# Open file using encoding
# Open file using encoding
contents , show_data = self . _loader . _get_file_contents ( path )
contents , show_data = self . _loader . _get_file_contents ( path )
contents = to_text ( contents , errors = ' surrogate_or_strict ' ,
contents = to_text ( contents , errors = ' surrogate_or_strict ' , encoding = paramvals [ ' encoding ' ] )
encoding = paramvals [ ' encoding ' ] )
config . write ( contents )
config . write ( contents )
config . seek ( 0 , os . SEEK_SET )
config . seek ( 0 , os . SEEK_SET )
self . cp . readfp ( config )
self . cp . readfp ( config )
var = self . get_value ( key , paramvals [ ' section ' ] ,
var = self . get_value ( key , paramvals [ ' section ' ] , paramvals [ ' default ' ] , paramvals [ ' re ' ] )
paramvals [ ' default ' ] , paramvals [ ' re ' ] )
if var is not None :
if var is not None :
if isinstance ( var , MutableSequence ) :
if isinstance ( var , MutableSequence ) :
for v in var :
for v in var :