Merge pull request #718 from darko-poljak/bugfix/716-conflicting-object-parameters

Fix DirectoryDict getitem.
This commit is contained in:
Darko Poljak 2018-10-14 10:32:15 +02:00 committed by GitHub
commit 72a0da5537
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 110 additions and 5 deletions

View file

@ -182,6 +182,29 @@ class Emulator(object):
lockfname = lockfname.replace(os.sep, '_') lockfname = lockfname.replace(os.sep, '_')
self.flock_path = os.path.join(self.object_base_path, lockfname) self.flock_path = os.path.join(self.object_base_path, lockfname)
def _object_params_in_context(self):
''' Get cdist_object parameters dict adopted by context.
Context consists of cdist_type boolean, optional, required,
optional_multiple and required_multiple parameters. If parameter
is multiple parameter then its value is a list.
This adaptation works on cdist_object.parameters which are read from
directory based dict where it is unknown what kind of data is in
file. If there is only one line in the file it is unknown if this
is a value of required/optional parameter or if it is one value of
multiple values parameter.
'''
params = {}
if self.cdist_object.exists:
for param in self.cdist_object.parameters:
value = ('' if param in self.cdist_type.boolean_parameters
else self.cdist_object.parameters[param])
if ((param in self.cdist_type.required_multiple_parameters or
param in self.cdist_type.optional_multiple_parameters) and
not isinstance(value, list)):
value = [value]
params[param] = value
return params
def setup_object(self): def setup_object(self):
# Create object with given parameters # Create object with given parameters
self.parameters = {} self.parameters = {}
@ -193,12 +216,13 @@ class Emulator(object):
# Make existing requirements a set so that we can compare it # Make existing requirements a set so that we can compare it
# later with new requirements. # later with new requirements.
self._existing_reqs = set(self.cdist_object.requirements) self._existing_reqs = set(self.cdist_object.requirements)
if self.cdist_object.parameters != self.parameters: obj_params = self._object_params_in_context()
if obj_params != self.parameters:
errmsg = ("Object %s already exists with conflicting " errmsg = ("Object %s already exists with conflicting "
"parameters:\n%s: %s\n%s: %s" % ( "parameters:\n%s: %s\n%s: %s" % (
self.cdist_object.name, self.cdist_object.name,
" ".join(self.cdist_object.source), " ".join(self.cdist_object.source),
self.cdist_object.parameters, obj_params,
self.object_source, self.object_source,
self.parameters)) self.parameters))
raise cdist.Error(errmsg) raise cdist.Error(errmsg)
@ -252,7 +276,7 @@ class Emulator(object):
self.cdist_object.name, self.cdist_object.name,
requirement, e.name, self.object_source))) requirement, e.name, self.object_source)))
raise raise
except core.cdist_object.MissingObjectIdError as e: except core.cdist_object.MissingObjectIdError:
self.log.error(("%s requires object %s without object id." self.log.error(("%s requires object %s without object id."
" Defined at %s" % (self.cdist_object.name, " Defined at %s" % (self.cdist_object.name,
requirement, requirement,

View file

@ -420,6 +420,27 @@ class ArgumentsTestCase(test.CdistTestCase):
self.assertEqual(cdist_object.parameters['required1'], value) self.assertEqual(cdist_object.parameters['required1'], value)
self.assertEqual(cdist_object.parameters['required2'], value) self.assertEqual(cdist_object.parameters['required2'], value)
def test_required_multiple_arguments(self):
"""check whether assigning required multiple parameter works"""
type_name = '__arguments_required_multiple'
object_id = 'some-id'
value1 = 'value1'
value2 = 'value2'
argv = [type_name, object_id, '--required1', value1,
'--required1', value2]
os.environ.update(self.env)
emu = emulator.Emulator(argv)
emu.run()
cdist_type = core.CdistType(self.local.type_path, type_name)
cdist_object = core.CdistObject(cdist_type, self.local.object_path,
self.local.object_marker_name,
object_id)
self.assertTrue('required1' in cdist_object.parameters)
self.assertTrue(value1 in cdist_object.parameters['required1'])
self.assertTrue(value2 in cdist_object.parameters['required1'])
# def test_required_missing(self): # def test_required_missing(self):
# type_name = '__arguments_required' # type_name = '__arguments_required'
# object_id = 'some-id' # object_id = 'some-id'
@ -447,6 +468,25 @@ class ArgumentsTestCase(test.CdistTestCase):
self.assertFalse('optional2' in cdist_object.parameters) self.assertFalse('optional2' in cdist_object.parameters)
self.assertEqual(cdist_object.parameters['optional1'], value) self.assertEqual(cdist_object.parameters['optional1'], value)
def test_optional_multiple(self):
type_name = '__arguments_optional_multiple'
object_id = 'some-id'
value1 = 'value1'
value2 = 'value2'
argv = [type_name, object_id, '--optional1', value1, '--optional1',
value2]
os.environ.update(self.env)
emu = emulator.Emulator(argv)
emu.run()
cdist_type = core.CdistType(self.local.type_path, type_name)
cdist_object = core.CdistObject(cdist_type, self.local.object_path,
self.local.object_marker_name,
object_id)
self.assertTrue('optional1' in cdist_object.parameters)
self.assertTrue(value1 in cdist_object.parameters['optional1'])
self.assertTrue(value2 in cdist_object.parameters['optional1'])
def test_argument_defaults(self): def test_argument_defaults(self):
type_name = '__argument_defaults' type_name = '__argument_defaults'
object_id = 'some-id' object_id = 'some-id'
@ -464,6 +504,29 @@ class ArgumentsTestCase(test.CdistTestCase):
self.assertFalse('optional2' in cdist_object.parameters) self.assertFalse('optional2' in cdist_object.parameters)
self.assertEqual(cdist_object.parameters['optional1'], value) self.assertEqual(cdist_object.parameters['optional1'], value)
def test_object_params_in_context(self):
type_name = '__arguments_all'
object_id = 'some-id'
argv = [type_name, object_id, '--opt', 'opt', '--req', 'req',
'--bool', '--optmul', 'val1', '--optmul', 'val2',
'--reqmul', 'val3', '--reqmul', 'val4',
'--optmul1', 'val5', '--reqmul1', 'val6']
os.environ.update(self.env)
emu = emulator.Emulator(argv)
emu.run()
obj_params = emu._object_params_in_context()
obj_params_expected = {
'bool': '',
'opt': 'opt',
'optmul1': ['val5', ],
'optmul': ['val1', 'val2', ],
'req': 'req',
'reqmul1': ['val6', ],
'reqmul': ['val3', 'val4', ],
}
self.assertEqual(obj_params, obj_params_expected)
class StdinTestCase(test.CdistTestCase): class StdinTestCase(test.CdistTestCase):

View file

@ -0,0 +1,2 @@
optmul
optmul1

View file

@ -0,0 +1,2 @@
reqmul
reqmul1

View file

@ -58,7 +58,7 @@ class FileList(collections.MutableSequence):
with open(self.path) as fd: with open(self.path) as fd:
for line in fd: for line in fd:
lines.append(line.rstrip('\n')) lines.append(line.rstrip('\n'))
except EnvironmentError as e: except EnvironmentError:
# error ignored # error ignored
pass pass
return lines return lines
@ -127,7 +127,16 @@ class DirectoryDict(collections.MutableMapping):
def __getitem__(self, key): def __getitem__(self, key):
try: try:
with open(os.path.join(self.path, key), "r") as fd: with open(os.path.join(self.path, key), "r") as fd:
return fd.read().rstrip('\n') value = fd.read().splitlines()
# if there is no value/empty line then return ''
# if there is only one value then return that value
# if there are multiple lines in file then return list
if not value:
return ''
elif len(value) == 1:
return value[0]
else:
return value
except EnvironmentError: except EnvironmentError:
raise KeyError(key) raise KeyError(key)