mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-01-11 16:51:55 -06:00
Removed depreciated code from config.py; removed corresponding unit tests
This commit is contained in:
parent
885efbe085
commit
5b637f6a18
@ -37,7 +37,6 @@ import backend
|
|||||||
import errors
|
import errors
|
||||||
import plugable
|
import plugable
|
||||||
import ipa_types
|
import ipa_types
|
||||||
from config import set_default_env, read_config
|
|
||||||
import util
|
import util
|
||||||
from constants import CLI_TAB
|
from constants import CLI_TAB
|
||||||
|
|
||||||
|
281
ipalib/config.py
281
ipalib/config.py
@ -25,107 +25,13 @@ It will also take care of settings that can be discovered by different
|
|||||||
methods, such as DNS.
|
methods, such as DNS.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from ConfigParser import SafeConfigParser, ParsingError, RawConfigParser
|
from ConfigParser import RawConfigParser, ParsingError
|
||||||
import types
|
import types
|
||||||
import os
|
import os
|
||||||
from os import path
|
from os import path
|
||||||
import sys
|
import sys
|
||||||
from errors import check_isinstance, raise_TypeError
|
|
||||||
import constants
|
import constants
|
||||||
|
|
||||||
DEFAULT_CONF='/etc/ipa/ipa.conf'
|
|
||||||
|
|
||||||
|
|
||||||
class Environment(object):
|
|
||||||
"""
|
|
||||||
A mapping object used to store the environment variables.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
object.__setattr__(self, '_Environment__map', {})
|
|
||||||
|
|
||||||
def __getattr__(self, name):
|
|
||||||
"""
|
|
||||||
Return the attribute named ``name``.
|
|
||||||
"""
|
|
||||||
return self[name]
|
|
||||||
|
|
||||||
def __setattr__(self, name, value):
|
|
||||||
"""
|
|
||||||
Set the attribute named ``name`` to ``value``.
|
|
||||||
"""
|
|
||||||
self[name] = value
|
|
||||||
|
|
||||||
def __delattr__(self, name):
|
|
||||||
"""
|
|
||||||
Raise AttributeError (deletion is not allowed).
|
|
||||||
"""
|
|
||||||
raise AttributeError('cannot del %s.%s' %
|
|
||||||
(self.__class__.__name__, name)
|
|
||||||
)
|
|
||||||
|
|
||||||
def __getitem__(self, key):
|
|
||||||
"""
|
|
||||||
Return the value corresponding to ``key``.
|
|
||||||
"""
|
|
||||||
val = self.__map[key]
|
|
||||||
if hasattr(val, 'get_value'):
|
|
||||||
return val.get_value()
|
|
||||||
else:
|
|
||||||
return val
|
|
||||||
|
|
||||||
def __setitem__(self, key, value):
|
|
||||||
"""
|
|
||||||
Set the item at ``key`` to ``value``.
|
|
||||||
"""
|
|
||||||
if key in self or hasattr(self, key):
|
|
||||||
if hasattr(self.__map[key], 'set_value'):
|
|
||||||
self.__map[key].set_value(value)
|
|
||||||
else:
|
|
||||||
raise AttributeError('cannot overwrite %s.%s' %
|
|
||||||
(self.__class__.__name__, key)
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
self.__map[key] = value
|
|
||||||
|
|
||||||
def __contains__(self, key):
|
|
||||||
"""
|
|
||||||
Return True if instance contains ``key``; otherwise return False.
|
|
||||||
"""
|
|
||||||
return key in self.__map
|
|
||||||
|
|
||||||
def __iter__(self):
|
|
||||||
"""
|
|
||||||
Iterate through keys in ascending order.
|
|
||||||
"""
|
|
||||||
for key in sorted(self.__map):
|
|
||||||
yield key
|
|
||||||
|
|
||||||
def update(self, new_vals, ignore_errors = False):
|
|
||||||
"""
|
|
||||||
Update variables using keys and values from ``new_vals``.
|
|
||||||
|
|
||||||
Error will occur if there is an attempt to override variable that was
|
|
||||||
already set, unless``ignore_errors`` is True.
|
|
||||||
"""
|
|
||||||
assert type(new_vals) == dict
|
|
||||||
for key, value in new_vals.iteritems():
|
|
||||||
if ignore_errors:
|
|
||||||
try:
|
|
||||||
self[key] = value
|
|
||||||
except (AttributeError, KeyError):
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
self[key] = value
|
|
||||||
|
|
||||||
def get(self, name, default=None):
|
|
||||||
"""
|
|
||||||
Return the value corresponding to ``key``. Defaults to ``default``.
|
|
||||||
"""
|
|
||||||
if name in self:
|
|
||||||
return self[name]
|
|
||||||
else:
|
|
||||||
return default
|
|
||||||
|
|
||||||
|
|
||||||
class Env(object):
|
class Env(object):
|
||||||
@ -349,188 +255,3 @@ class Env(object):
|
|||||||
"""
|
"""
|
||||||
for key in sorted(self.__d):
|
for key in sorted(self.__d):
|
||||||
yield key
|
yield key
|
||||||
|
|
||||||
|
|
||||||
def set_default_env(env):
|
|
||||||
"""
|
|
||||||
Set default values for ``env``.
|
|
||||||
"""
|
|
||||||
assert isinstance(env, Environment)
|
|
||||||
|
|
||||||
default = dict(
|
|
||||||
basedn = EnvProp(basestring, 'dc=example,dc=com'),
|
|
||||||
container_accounts = EnvProp(basestring, 'cn=accounts'),
|
|
||||||
container_user = EnvProp(basestring, 'cn=users,cn=accounts'),
|
|
||||||
container_group = EnvProp(basestring, 'cn=groups,cn=accounts'),
|
|
||||||
container_service = EnvProp(basestring, 'cn=services,cn=accounts'),
|
|
||||||
container_host = EnvProp(basestring, 'cn=computers,cn=accounts'),
|
|
||||||
container_hostgroup = EnvProp(basestring, 'cn=hostgroups,cn=accounts'),
|
|
||||||
domain = LazyProp(basestring, get_domain),
|
|
||||||
interactive = EnvProp(bool, True),
|
|
||||||
query_dns = EnvProp(bool, True),
|
|
||||||
realm = LazyProp(basestring, get_realm),
|
|
||||||
server_context = EnvProp(bool, True),
|
|
||||||
server = LazyIter(basestring, get_servers),
|
|
||||||
verbose = EnvProp(bool, False),
|
|
||||||
ldaphost = EnvProp(basestring, 'localhost'),
|
|
||||||
ldapport = EnvProp(int, 389),
|
|
||||||
)
|
|
||||||
|
|
||||||
env.update(default)
|
|
||||||
|
|
||||||
|
|
||||||
class EnvProp(object):
|
|
||||||
"""
|
|
||||||
Environment set-once property with optional default value.
|
|
||||||
"""
|
|
||||||
def __init__(self, type_, default, multi_value=False):
|
|
||||||
"""
|
|
||||||
:param type_: Type of the property.
|
|
||||||
:param default: Default value.
|
|
||||||
:param multi_value: Allow multiple values.
|
|
||||||
"""
|
|
||||||
if multi_value:
|
|
||||||
if isinstance(default, tuple) and len(default):
|
|
||||||
check_isinstance(default[0], type_, allow_none=True)
|
|
||||||
self._type = type_
|
|
||||||
self._default = default
|
|
||||||
self._value = None
|
|
||||||
self._multi_value = multi_value
|
|
||||||
|
|
||||||
def get_value(self):
|
|
||||||
"""
|
|
||||||
Return the value if it was set.
|
|
||||||
|
|
||||||
If the value is not set return the default. Otherwise raise an
|
|
||||||
exception.
|
|
||||||
"""
|
|
||||||
if self._get() != None:
|
|
||||||
return self._get()
|
|
||||||
else:
|
|
||||||
raise KeyError, 'Value not set'
|
|
||||||
|
|
||||||
def set_value(self, value):
|
|
||||||
"""
|
|
||||||
Set the value.
|
|
||||||
"""
|
|
||||||
if self._value != None:
|
|
||||||
raise KeyError, 'Value already set'
|
|
||||||
self._value = self._validate(value)
|
|
||||||
|
|
||||||
def _get(self):
|
|
||||||
"""
|
|
||||||
Return value, default, or None.
|
|
||||||
"""
|
|
||||||
if self._value != None:
|
|
||||||
return self._value
|
|
||||||
elif self._default != None:
|
|
||||||
return self._default
|
|
||||||
else:
|
|
||||||
return None
|
|
||||||
|
|
||||||
def _validate(self, value):
|
|
||||||
"""
|
|
||||||
Make sure ``value`` is of the right type. Do conversions if necessary.
|
|
||||||
|
|
||||||
This will also handle multi value.
|
|
||||||
"""
|
|
||||||
if self._multi_value and isinstance(value, tuple):
|
|
||||||
converted = []
|
|
||||||
for val in value:
|
|
||||||
converted.append(self._validate_value(val))
|
|
||||||
return tuple(converted)
|
|
||||||
else:
|
|
||||||
return self._validate_value(value)
|
|
||||||
|
|
||||||
def _validate_value(self, value):
|
|
||||||
"""
|
|
||||||
Validate and convert a single value.
|
|
||||||
"""
|
|
||||||
bool_true = ('true', 'yes', 'on')
|
|
||||||
bool_false = ('false', 'no', 'off')
|
|
||||||
|
|
||||||
if self._type == bool and isinstance(value, basestring):
|
|
||||||
if value.lower() in bool_true:
|
|
||||||
return True
|
|
||||||
elif value.lower() in bool_false:
|
|
||||||
return False
|
|
||||||
else:
|
|
||||||
raise raise_TypeError(value, bool, 'value')
|
|
||||||
check_isinstance(value, self._type, 'value')
|
|
||||||
return value
|
|
||||||
|
|
||||||
|
|
||||||
class LazyProp(EnvProp):
|
|
||||||
def __init__(self, type_, func, default=None, multi_value=False):
|
|
||||||
check_isinstance(func, types.FunctionType, 'func')
|
|
||||||
self._func = func
|
|
||||||
EnvProp.__init__(self, type_, default, multi_value)
|
|
||||||
|
|
||||||
def get_value(self):
|
|
||||||
if self._get() != None:
|
|
||||||
return self._get()
|
|
||||||
else:
|
|
||||||
return self._func()
|
|
||||||
|
|
||||||
|
|
||||||
class LazyIter(LazyProp):
|
|
||||||
def __init__(self, type_, func, default=None):
|
|
||||||
LazyProp.__init__(self, type_, func, default, multi_value=True)
|
|
||||||
|
|
||||||
def get_value(self):
|
|
||||||
val = self._get()
|
|
||||||
if val != None:
|
|
||||||
if type(val) == tuple:
|
|
||||||
for item in val:
|
|
||||||
yield item
|
|
||||||
else:
|
|
||||||
yield val
|
|
||||||
for item in self._func():
|
|
||||||
if not val or item not in val:
|
|
||||||
yield item
|
|
||||||
|
|
||||||
|
|
||||||
# TODO: Make it possible to use var = 'foo, bar' without
|
|
||||||
# turning it into ("'foo", "bar'")
|
|
||||||
def read_config(config_file=None):
|
|
||||||
assert config_file == None or isinstance(config_file, (basestring, file))
|
|
||||||
|
|
||||||
parser = SafeConfigParser()
|
|
||||||
if config_file == None:
|
|
||||||
files = [DEFAULT_CONF, os.path.expanduser('~/.ipa.conf')]
|
|
||||||
else:
|
|
||||||
files = [config_file]
|
|
||||||
|
|
||||||
for f in files:
|
|
||||||
try:
|
|
||||||
if isinstance(f, file):
|
|
||||||
parser.readfp(f)
|
|
||||||
else:
|
|
||||||
parser.read(f)
|
|
||||||
except ParsingError:
|
|
||||||
print "Can't read %s" % f
|
|
||||||
|
|
||||||
ret = {}
|
|
||||||
if parser.has_section('defaults'):
|
|
||||||
for name, value in parser.items('defaults'):
|
|
||||||
value = tuple(elem.strip() for elem in value.split(','))
|
|
||||||
if len(value) == 1:
|
|
||||||
value = value[0]
|
|
||||||
ret[name] = value
|
|
||||||
|
|
||||||
return ret
|
|
||||||
|
|
||||||
|
|
||||||
# these functions are here just to "emulate" dns resolving for now
|
|
||||||
def get_domain():
|
|
||||||
return "ipatest.com"
|
|
||||||
|
|
||||||
|
|
||||||
def get_realm():
|
|
||||||
return "IPATEST.COM"
|
|
||||||
|
|
||||||
|
|
||||||
def get_servers():
|
|
||||||
yield "server.ipatest.com"
|
|
||||||
yield "backup.ipatest.com"
|
|
||||||
yield "fake.ipatest.com"
|
|
||||||
|
@ -35,7 +35,7 @@ from os import path
|
|||||||
import subprocess
|
import subprocess
|
||||||
import errors
|
import errors
|
||||||
from errors import check_type, check_isinstance
|
from errors import check_type, check_isinstance
|
||||||
from config import Environment, Env
|
from config import Env
|
||||||
from constants import DEFAULT_CONFIG
|
from constants import DEFAULT_CONFIG
|
||||||
import util
|
import util
|
||||||
|
|
||||||
|
@ -31,88 +31,7 @@ from tests.util import TempDir, TempHome
|
|||||||
from ipalib import config, constants
|
from ipalib import config, constants
|
||||||
|
|
||||||
|
|
||||||
def test_Environment():
|
|
||||||
"""
|
|
||||||
Test the `ipalib.config.Environment` class.
|
|
||||||
"""
|
|
||||||
# This has to be the same as iter_cnt
|
|
||||||
control_cnt = 0
|
|
||||||
class prop_class:
|
|
||||||
def __init__(self, val):
|
|
||||||
self._val = val
|
|
||||||
def get_value(self):
|
|
||||||
return self._val
|
|
||||||
|
|
||||||
class iter_class(prop_class):
|
|
||||||
# Increment this for each time iter_class yields
|
|
||||||
iter_cnt = 0
|
|
||||||
def get_value(self):
|
|
||||||
for item in self._val:
|
|
||||||
self.__class__.iter_cnt += 1
|
|
||||||
yield item
|
|
||||||
|
|
||||||
# Tests for basic functionality
|
|
||||||
basic_tests = (
|
|
||||||
('a', 1),
|
|
||||||
('b', 'basic_foo'),
|
|
||||||
('c', ('basic_bar', 'basic_baz')),
|
|
||||||
)
|
|
||||||
# Tests with prop classes
|
|
||||||
prop_tests = (
|
|
||||||
('d', prop_class(2), 2),
|
|
||||||
('e', prop_class('prop_foo'), 'prop_foo'),
|
|
||||||
('f', prop_class(('prop_bar', 'prop_baz')), ('prop_bar', 'prop_baz')),
|
|
||||||
)
|
|
||||||
# Tests with iter classes
|
|
||||||
iter_tests = (
|
|
||||||
('g', iter_class((3, 4, 5)), (3, 4, 5)),
|
|
||||||
('h', iter_class(('iter_foo', 'iter_bar', 'iter_baz')),
|
|
||||||
('iter_foo', 'iter_bar', 'iter_baz')
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
# Set all the values
|
|
||||||
env = config.Environment()
|
|
||||||
for name, val in basic_tests:
|
|
||||||
env[name] = val
|
|
||||||
for name, val, dummy in prop_tests:
|
|
||||||
env[name] = val
|
|
||||||
for name, val, dummy in iter_tests:
|
|
||||||
env[name] = val
|
|
||||||
|
|
||||||
# Test if the values are correct
|
|
||||||
for name, val in basic_tests:
|
|
||||||
assert env[name] == val
|
|
||||||
for name, dummy, val in prop_tests:
|
|
||||||
assert env[name] == val
|
|
||||||
# Test if the get_value() function is called only when needed
|
|
||||||
for name, dummy, correct_values in iter_tests:
|
|
||||||
values_in_env = []
|
|
||||||
for val in env[name]:
|
|
||||||
control_cnt += 1
|
|
||||||
assert iter_class.iter_cnt == control_cnt
|
|
||||||
values_in_env.append(val)
|
|
||||||
assert tuple(values_in_env) == correct_values
|
|
||||||
|
|
||||||
# Test __setattr__()
|
|
||||||
env.spam = 'ham'
|
|
||||||
|
|
||||||
assert env.spam == 'ham'
|
|
||||||
assert env['spam'] == 'ham'
|
|
||||||
assert env.get('spam') == 'ham'
|
|
||||||
assert env.get('nonexistent') == None
|
|
||||||
assert env.get('nonexistent', 42) == 42
|
|
||||||
|
|
||||||
# Test if we throw AttributeError exception when trying to overwrite
|
|
||||||
# existing value, or delete it
|
|
||||||
raises(AttributeError, setitem, env, 'a', 1)
|
|
||||||
raises(AttributeError, setattr, env, 'a', 1)
|
|
||||||
raises(AttributeError, delitem, env, 'a')
|
|
||||||
raises(AttributeError, delattr, env, 'a')
|
|
||||||
raises(AttributeError, config.Environment.update, env, dict(a=1000))
|
|
||||||
# This should be silently ignored
|
|
||||||
env.update(dict(a=1000), True)
|
|
||||||
assert env.a != 1000
|
|
||||||
|
|
||||||
|
|
||||||
# Random base64-encoded data to simulate a misbehaving config file.
|
# Random base64-encoded data to simulate a misbehaving config file.
|
||||||
@ -557,82 +476,3 @@ class test_Env(ClassChecker):
|
|||||||
for key in keys:
|
for key in keys:
|
||||||
o[key] = 'the value'
|
o[key] = 'the value'
|
||||||
assert list(o) == sorted(keys + default_keys)
|
assert list(o) == sorted(keys + default_keys)
|
||||||
|
|
||||||
|
|
||||||
def test_set_default_env():
|
|
||||||
"""
|
|
||||||
Test the `ipalib.config.set_default_env` function.
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Make sure we don't overwrite any properties
|
|
||||||
d = dict(
|
|
||||||
query_dns = False,
|
|
||||||
server = ('first', 'second'),
|
|
||||||
realm = 'myrealm',
|
|
||||||
# test right conversions
|
|
||||||
server_context = 'off',
|
|
||||||
)
|
|
||||||
env = config.Environment()
|
|
||||||
config.set_default_env(env)
|
|
||||||
env.update(d)
|
|
||||||
assert env['server_context'] == False
|
|
||||||
assert env['query_dns'] == False
|
|
||||||
|
|
||||||
# Make sure the servers is overwrote properly (that it is still LazyProp)
|
|
||||||
iter = env['server']
|
|
||||||
assert iter.next() == 'first'
|
|
||||||
assert iter.next() == 'second'
|
|
||||||
|
|
||||||
|
|
||||||
def test_LazyProp():
|
|
||||||
"""
|
|
||||||
Test the `ipalib.config.LazyProp` class.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def dummy():
|
|
||||||
return 1
|
|
||||||
|
|
||||||
# Basic sanity testing with no initial value
|
|
||||||
prop = config.LazyProp(int, dummy)
|
|
||||||
assert prop.get_value() == 1
|
|
||||||
prop.set_value(2)
|
|
||||||
assert prop.get_value() == 2
|
|
||||||
|
|
||||||
# Basic sanity testing with initial value
|
|
||||||
prop = config.LazyProp(int, dummy, 3)
|
|
||||||
assert prop.get_value() == 3
|
|
||||||
prop.set_value(4)
|
|
||||||
assert prop.get_value() == 4
|
|
||||||
|
|
||||||
|
|
||||||
def test_LazyIter():
|
|
||||||
"""
|
|
||||||
Test the `ipalib.config.LazyIter` class.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def dummy():
|
|
||||||
yield 1
|
|
||||||
yield 2
|
|
||||||
|
|
||||||
# Basic sanity testing with no initial value
|
|
||||||
prop = config.LazyIter(int, dummy)
|
|
||||||
iter = prop.get_value()
|
|
||||||
assert iter.next() == 1
|
|
||||||
assert iter.next() == 2
|
|
||||||
raises(StopIteration, iter.next)
|
|
||||||
|
|
||||||
# Basic sanity testing with initial value
|
|
||||||
prop = config.LazyIter(int, dummy, 0)
|
|
||||||
iter = prop.get_value()
|
|
||||||
assert iter.next() == 0
|
|
||||||
assert iter.next() == 1
|
|
||||||
assert iter.next() == 2
|
|
||||||
raises(StopIteration, iter.next)
|
|
||||||
|
|
||||||
|
|
||||||
def test_read_config():
|
|
||||||
"""
|
|
||||||
Test the `ipalib.config.read_config` class.
|
|
||||||
"""
|
|
||||||
|
|
||||||
raises(AssertionError, config.read_config, 1)
|
|
||||||
|
Loading…
Reference in New Issue
Block a user