follower in symlink

This commit is contained in:
egarette@silique.fr 2023-01-24 22:31:32 +01:00
parent d2e790a2e2
commit 302be618ce
3 changed files with 49 additions and 3 deletions

View file

@ -283,10 +283,17 @@ async def test_symlink_with_follower(config_type):
await cfg.option('ip_admin_eth0.ip_admin_eth0').value.set(['val1', 'val2']) await cfg.option('ip_admin_eth0.ip_admin_eth0').value.set(['val1', 'val2'])
assert await cfg.value.dict() == {'ip_admin_eth0.ip_admin_eth0': ['val1', 'val2'], 'ip_admin_eth0.netmask_admin_eth0': [None, None], 'follower': [None, None]} assert await cfg.value.dict() == {'ip_admin_eth0.ip_admin_eth0': ['val1', 'val2'], 'ip_admin_eth0.netmask_admin_eth0': [None, None], 'follower': [None, None]}
# #
assert await cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).owner.get() == 'default'
assert await cfg.option('ip_admin_eth0.netmask_admin_eth0', 1).owner.get() == 'default'
assert await cfg.option('follower', 0).owner.get() == 'default'
assert await cfg.option('follower', 1).owner.get() == 'default'
assert await cfg.option('follower').owner.get() == ['default', 'default']
#
assert await cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get() == None assert await cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get() == None
assert await cfg.option('ip_admin_eth0.netmask_admin_eth0', 1).value.get() == None assert await cfg.option('ip_admin_eth0.netmask_admin_eth0', 1).value.get() == None
assert await cfg.option('follower', 0).value.get() == None assert await cfg.option('follower', 0).value.get() == None
assert await cfg.option('follower', 1).value.get() == None assert await cfg.option('follower', 1).value.get() == None
assert await cfg.option('follower').value.get() == [None, None]
# #
await cfg.option('ip_admin_eth0.netmask_admin_eth0', 1).value.set('val3') await cfg.option('ip_admin_eth0.netmask_admin_eth0', 1).value.set('val3')
assert await cfg.value.dict() == {'ip_admin_eth0.ip_admin_eth0': ['val1', 'val2'], 'ip_admin_eth0.netmask_admin_eth0': [None, 'val3'], 'follower': [None, 'val3']} assert await cfg.value.dict() == {'ip_admin_eth0.ip_admin_eth0': ['val1', 'val2'], 'ip_admin_eth0.netmask_admin_eth0': [None, 'val3'], 'follower': [None, 'val3']}
@ -295,6 +302,13 @@ async def test_symlink_with_follower(config_type):
assert await cfg.option('ip_admin_eth0.netmask_admin_eth0', 1).value.get() == 'val3' assert await cfg.option('ip_admin_eth0.netmask_admin_eth0', 1).value.get() == 'val3'
assert await cfg.option('follower', 0).value.get() == None assert await cfg.option('follower', 0).value.get() == None
assert await cfg.option('follower', 1).value.get() == 'val3' assert await cfg.option('follower', 1).value.get() == 'val3'
assert await cfg.option('follower').value.get() == [None, 'val3']
#
assert await cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).owner.get() == 'default'
assert await cfg.option('ip_admin_eth0.netmask_admin_eth0', 1).owner.get() == 'user'
assert await cfg.option('follower', 0).owner.get() == 'default'
assert await cfg.option('follower', 1).owner.get() == 'user'
assert await cfg.option('follower').owner.get() == ['default', 'user']
assert not await list_sessions() assert not await list_sessions()

View file

@ -145,6 +145,8 @@ class CommonTiramisuOption(CommonTiramisu):
self._subconfig = None self._subconfig = None
def __getattr__(self, name): def __getattr__(self, name):
if name == '__name__':
return self.__class__.__name__
raise APIError(_('unknown method "{}" in "{}"').format(name, self.__class__.__name__)) raise APIError(_('unknown method "{}" in "{}"').format(name, self.__class__.__name__))
@ -451,6 +453,19 @@ class TiramisuOptionOwner(CommonTiramisuOption):
@option_and_connection @option_and_connection
async def get(self): async def get(self):
"""Get owner for a specified option""" """Get owner for a specified option"""
if self._option_bag.option.impl_is_follower() and self._option_bag.index is None:
if self._option_bag.option.impl_is_symlinkoption():
length = await self._subconfig.cfgimpl_get_length_leadership(self._option_bag)
value = []
for index in range(length):
soption_bag = self._option_bag.copy()
soption_bag.index = index
value.append(await self._values.getowner(soption_bag,
self._name,
)
)
return value
raise APIError('index must be set with a follower option')
return await self._values.getowner(self._option_bag) return await self._values.getowner(self._option_bag)
@option_and_connection @option_and_connection
@ -663,7 +678,10 @@ def option_type(typ):
del config_bag.connection del config_bag.connection
raise APIError(_('please specify a valid sub function ({})').format(func.__name__)) raise APIError(_('please specify a valid sub function ({})').format(func.__name__))
ret = await func(*args, **kwargs) ret = await func(*args, **kwargs)
try:
del config_bag.connection del config_bag.connection
except AttributeError:
pass
return ret return ret
wrapped.func = func wrapped.func = func
return wrapped return wrapped
@ -698,6 +716,17 @@ class TiramisuOptionValue(CommonTiramisuOption):
async def get(self): async def get(self):
"""Get option's value""" """Get option's value"""
if self._option_bag.option.impl_is_follower() and self._option_bag.index is None: if self._option_bag.option.impl_is_follower() and self._option_bag.index is None:
# if it's a follower included in a symlinkoption, this should consider as a list
if self._option_bag.option.impl_is_symlinkoption():
value = []
for index in range(await self._len()):
soption_bag = self._option_bag.copy()
soption_bag.index = index
value.append(await self._subconfig.getattr(self._name,
soption_bag,
)
)
return value
raise APIError('index must be set with a follower option') raise APIError('index must be set with a follower option')
return await self._subconfig.getattr(self._name, return await self._subconfig.getattr(self._name,
self._option_bag, self._option_bag,
@ -784,6 +813,9 @@ class TiramisuOptionValue(CommonTiramisuOption):
@option_type('follower') @option_type('follower')
async def len(self): async def len(self):
return await self._len()
async def _len(self):
"""Length of follower option""" """Length of follower option"""
# for example if index is None # for example if index is None
if '_length' not in vars(self): if '_length' not in vars(self):

View file

@ -307,8 +307,8 @@ class Values:
"convenience method to know if an option is empty" "convenience method to know if an option is empty"
empty = opt._empty empty = opt._empty
if index in [None, undefined] and opt.impl_is_multi(): if index in [None, undefined] and opt.impl_is_multi():
isempty = value is None or (not force_allow_empty_list and value == []) or \ isempty = value is None or (isinstance(value, list) and not force_allow_empty_list and value == []) or \
None in value or empty in value (isinstance(value, list) and None in value) or empty in value
else: else:
isempty = value is None or value == empty or (opt.impl_is_submulti() and value == []) isempty = value is None or value == empty or (opt.impl_is_submulti() and value == [])
return isempty return isempty