summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ipalib/cli.py25
-rw-r--r--ipalib/config.py211
-rw-r--r--ipalib/plugable.py72
-rwxr-xr-xtest_server3
-rw-r--r--tests/test_ipalib/test_config.py106
-rw-r--r--tests/test_ipalib/test_crud.py2
-rw-r--r--tests/test_ipalib/test_frontend.py4
-rw-r--r--tests/test_ipalib/test_plugable.py79
8 files changed, 278 insertions, 224 deletions
diff --git a/ipalib/cli.py b/ipalib/cli.py
index 5dd2c44f2..07956e0a7 100644
--- a/ipalib/cli.py
+++ b/ipalib/cli.py
@@ -25,11 +25,12 @@ import re
import sys
import code
import optparse
+
import frontend
import errors
import plugable
import ipa_types
-import config
+from config import set_default_env, read_config
def exit_error(error):
sys.exit('ipa: ERROR: %s' % error)
@@ -207,7 +208,6 @@ class CLI(object):
self.__api = api
self.__all_interactive = False
self.__not_interactive = False
- self.__config = None
def __get_api(self):
return self.__api
@@ -256,9 +256,8 @@ class CLI(object):
def run(self):
self.finalize()
- (args, env_dict) = self.parse_globals()
- env_dict.update(config.read_config(self.__config))
- self.api.env.update(config.generate_env(env_dict))
+ set_default_env(self.api.env)
+ args = self.parse_globals()
if len(args) < 1:
self.print_commands()
print 'Usage: ipa [global-options] COMMAND'
@@ -329,7 +328,6 @@ class CLI(object):
return parser
def parse_globals(self, argv=sys.argv[1:]):
- env_dict = {}
parser = optparse.OptionParser()
parser.disable_interspersed_args()
parser.add_option('-a', dest='interactive', action='store_true',
@@ -348,20 +346,23 @@ class CLI(object):
self.__all_interactive = True
elif options.interactive == False:
self.__not_interactive = True
- if options.config_file:
- self.__config = options.config_file
+ if options.verbose != None:
+ self.api.env.verbose = True
if options.environment:
+ env_dict = {}
for a in options.environment.split(','):
a = a.split('=', 1)
if len(a) < 2:
parser.error('badly specified environment string,'\
'use var1=val1[,var2=val2]..')
env_dict[a[0].strip()] = a[1].strip()
- if options.verbose != None:
- env_dict.update(verbose=True)
-
- return (args, env_dict)
+ self.api.env.update(env_dict, True)
+ if options.config_file:
+ self.api.env.update(read_config(options.config_file), True)
+ else:
+ self.api.env.update(read_config(), True)
+ return args
def get_usage(self, cmd):
return ' '.join(self.get_usage_iter(cmd))
diff --git a/ipalib/config.py b/ipalib/config.py
index 42bf7787b..7899d077f 100644
--- a/ipalib/config.py
+++ b/ipalib/config.py
@@ -21,74 +21,193 @@ from ConfigParser import SafeConfigParser, ParsingError
import types
import os
+from errors import check_isinstance, raise_TypeError
+
DEFAULT_CONF='/etc/ipa/ipa.conf'
-def generate_env(d={}):
- default = dict(
- container_accounts = 'cn=accounts',
- basedn = 'dc=example,dc=com',
- container_user = 'cn=users,cn=accounts',
- container_group = 'cn=groups,cn=accounts',
- container_service = 'cn=services,cn=accounts',
- domain = LazyProp(get_domain),
- interactive = True,
- query_dns = True,
- realm = LazyProp(get_realm),
- server_context = True,
- server = LazyIter(get_servers),
- verbose = False,
- )
- for key, value in d.iteritems():
- if key in default:
- if isinstance(default[key], (LazyIter, LazyProp)):
- default[key].set_value(value)
+
+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:
- default[key] = convert_val(type(default[key]), value)
+ raise AttributeError('cannot overwrite %s.%s' %
+ (self.__class__.__name__, key)
+ )
else:
- default[key] = value
+ self.__map[key] = value
- return default
+ 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
-# TODO: Add a validation function
-def convert_val(target_type, value):
- bool_true = ('true', 'yes', 'on')
- bool_false = ('false', 'no', 'off')
+ def update(self, new_vals, ignore_errors = False):
+ 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
- if target_type == bool and isinstance(value, basestring):
- if value.lower() in bool_true:
- return True
- elif value.lower() in bool_false:
- return False
- return target_type(value)
+ def get(self, name, default=None):
+ return self.__map.get(name, default)
-class LazyProp(object):
- def __init__(self, func, value=None):
- assert isinstance(func, types.FunctionType)
- self._func = func
- self._value = value
- def set_value(self, value):
- self._value = value
+def set_default_env(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'),
+ 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),
+ )
+
+ env.update(default)
+
+
+class EnvProp(object):
+ def __init__(self, type_, default, multi_value=False):
+ 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):
- if self._value == None:
- return self._func()
+ if self._get() != None:
+ return self._get()
else:
+ raise KeyError, 'Value not set'
+
+ def set_value(self, value):
+ if self._value != None:
+ raise KeyError, 'Value already set'
+ self._value = self._validate(value)
+
+ def _get(self):
+ if self._value != None:
return self._value
+ elif self._default != None:
+ return self._default
+ else:
+ return None
+
+ def _validate(self, 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):
+ 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):
- if self._value != None:
- if type(self._value) == tuple:
- for item in self._value:
+ val = self._get()
+ if val != None:
+ if type(val) == tuple:
+ for item in val:
yield item
else:
- yield self._value
+ yield val
for item in self._func():
- if not self._value or item not in self._value:
+ if not val or item not in val:
yield item
diff --git a/ipalib/plugable.py b/ipalib/plugable.py
index 4a2658a74..98aa41720 100644
--- a/ipalib/plugable.py
+++ b/ipalib/plugable.py
@@ -29,6 +29,7 @@ import re
import inspect
import errors
from errors import check_type, check_isinstance
+from config import Environment
class ReadOnly(object):
@@ -692,77 +693,6 @@ class Registrar(DictProxy):
self.__registered.add(klass)
-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):
- raise AttributeError('cannot overwrite %s.%s' %
- (self.__class__.__name__, key)
- )
- 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):
- assert type(new_vals) == dict
- for key, value in new_vals.iteritems():
- if key in self and ignore_errors:
- continue
- self[key] = value
-
- def get(self, name, default=None):
- return self.__map.get(name, default)
-
class API(DictProxy):
"""
Dynamic API object through which `Plugin` instances are accessed.
diff --git a/test_server b/test_server
index d58d00af7..86df68156 100755
--- a/test_server
+++ b/test_server
@@ -146,9 +146,10 @@ XMLRPCServer.register_introspection_functions()
api.finalize()
# Initialize our environment
+config.set_default_env(api.env)
env_dict = config.read_config()
env_dict['server_context'] = True
-api.env.update(config.generate_env(env_dict))
+api.env.update(env_dict)
# Get and register all the methods
for cmd in api.Command:
diff --git a/tests/test_ipalib/test_config.py b/tests/test_ipalib/test_config.py
index 3fe44136a..df8302326 100644
--- a/tests/test_ipalib/test_config.py
+++ b/tests/test_ipalib/test_config.py
@@ -23,29 +23,111 @@ Test the `ipalib.config` module.
import types
-from tests.util import raises
+from tests.util import raises, setitem, delitem
+#from tests.util import getitem, setitem, delitem
from ipalib import config
-def test_generate_env():
+def test_Environment():
"""
- Test the `ipalib.config.generate_env` function.
+ 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'
+
+ # 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
+
+
+def test_set_default_env():
+ """
+ Test the `ipalib.config.set_default_env` function.
"""
# Make sure we don't overwrite any properties
- env = dict(
+ d = dict(
query_dns = False,
server = ('first', 'second'),
realm = 'myrealm',
# test right conversions
server_context = 'off',
)
- d = config.generate_env(env)
- assert d['server_context'] == False
- assert d['query_dns'] == False
+ 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 = d['server'].get_value()
+ iter = env['server']
assert iter.next() == 'first'
assert iter.next() == 'second'
@@ -59,13 +141,13 @@ def test_LazyProp():
return 1
# Basic sanity testing with no initial value
- prop = config.LazyProp(dummy)
+ 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(dummy, 3)
+ prop = config.LazyProp(int, dummy, 3)
assert prop.get_value() == 3
prop.set_value(4)
assert prop.get_value() == 4
@@ -81,14 +163,14 @@ def test_LazyIter():
yield 2
# Basic sanity testing with no initial value
- prop = config.LazyIter(dummy)
+ 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(dummy, 0)
+ prop = config.LazyIter(int, dummy, 0)
iter = prop.get_value()
assert iter.next() == 0
assert iter.next() == 1
diff --git a/tests/test_ipalib/test_crud.py b/tests/test_ipalib/test_crud.py
index d7e6b51f3..9a207cce9 100644
--- a/tests/test_ipalib/test_crud.py
+++ b/tests/test_ipalib/test_crud.py
@@ -40,7 +40,7 @@ class CrudChecker(ClassChecker):
frontend.Method,
frontend.Property,
)
- api.env.update(config.generate_env())
+ config.set_default_env(api.env)
class user(frontend.Object):
takes_params = (
'givenname',
diff --git a/tests/test_ipalib/test_frontend.py b/tests/test_ipalib/test_frontend.py
index 9ab0504b2..c57428867 100644
--- a/tests/test_ipalib/test_frontend.py
+++ b/tests/test_ipalib/test_frontend.py
@@ -894,7 +894,7 @@ class test_Object(ClassChecker):
frontend.Method,
frontend.Property,
)
- api.env.update(config.generate_env())
+ config.set_default_env(api.env)
api.finalize()
# Test with no primary keys:
@@ -951,7 +951,7 @@ class test_Object(ClassChecker):
frontend.Property,
backend.Backend,
)
- api.env.update(config.generate_env())
+ config.set_default_env(api.env)
class ldap(backend.Backend):
whatever = 'It worked!'
api.register(ldap)
diff --git a/tests/test_ipalib/test_plugable.py b/tests/test_ipalib/test_plugable.py
index dec893a9c..610117971 100644
--- a/tests/test_ipalib/test_plugable.py
+++ b/tests/test_ipalib/test_plugable.py
@@ -659,85 +659,6 @@ class test_NameSpace(ClassChecker):
'NameSpace(<%d members>, sort=%r)' % (cnt, sort)
-def test_Environment():
- """
- Test the `ipalib.plugable.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 = plugable.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'
-
- # 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, plugable.Environment.update, env, dict(a=1000))
- # This should be silently ignored
- env.update(dict(a=1000), True)
- assert env.a != 1000
-
-
def test_Registrar():
"""
Test the `ipalib.plugable.Registrar` class