summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason Gerard DeRose <jderose@redhat.com>2008-10-24 20:02:14 -0600
committerJason Gerard DeRose <jderose@redhat.com>2008-10-24 20:02:14 -0600
commitac4efac3944d180cffd0ad9d63f631dc928e1d28 (patch)
tree169357c91ee70371ee42894bf89641008fcff9e6
parent8ca44bcbfa2aec0c7c84205dc08c81f711a22c5d (diff)
downloadfreeipa-ac4efac3944d180cffd0ad9d63f631dc928e1d28.tar.gz
freeipa-ac4efac3944d180cffd0ad9d63f631dc928e1d28.tar.xz
freeipa-ac4efac3944d180cffd0ad9d63f631dc928e1d28.zip
Finished Env._finalize_core() and corresponding unit tests
-rw-r--r--ipalib/config.py62
-rw-r--r--ipalib/constants.py38
-rw-r--r--tests/test_ipalib/test_config.py124
-rw-r--r--tests/util.py8
4 files changed, 208 insertions, 24 deletions
diff --git a/ipalib/config.py b/ipalib/config.py
index dd00d713f..bced62fda 100644
--- a/ipalib/config.py
+++ b/ipalib/config.py
@@ -145,13 +145,20 @@ class Env(object):
self.home = path.abspath(os.environ['HOME'])
self.dot_ipa = path.join(self.home, '.ipa')
- def __do(self, name):
+ def __doing(self, name):
if name in self.__done:
raise StandardError(
'%s.%s() already called' % (self.__class__.__name__, name)
)
self.__done.add(name)
+ def __do_if_not_done(self, name):
+ if name not in self.__done:
+ getattr(self, name)()
+
+ def _isdone(self, name):
+ return name in self.__done
+
def _bootstrap(self, **overrides):
"""
Initialize basic environment.
@@ -159,10 +166,8 @@ class Env(object):
This method will initialize only enough environment information to
determine whether ipa is running in-tree, what the context is,
and the location of the configuration file.
-
- This method should be called before any plugins are loaded.
"""
- self.__do('_bootstrap')
+ self.__doing('_bootstrap')
for (key, value) in overrides.items():
self[key] = value
if 'in_tree' not in self:
@@ -180,7 +185,46 @@ class Env(object):
else:
self.conf = path.join('/', 'etc', 'ipa', name)
- def _load_config(self, conf_file):
+ def _finalize_core(self, **defaults):
+ """
+ Complete initialization of standard IPA environment.
+
+ After this method is called, the all environment variables
+ used by all the built-in plugins will be available.
+
+ This method should be called before loading any plugins. It will
+ automatically call `Env._bootstrap()` if it has not yet been called.
+
+ After this method has finished, the `Env` instance is still writable
+ so that third
+ """
+ self.__doing('_finalize_core')
+ self.__do_if_not_done('_bootstrap')
+ self._merge_config(self.conf)
+ if 'in_server' not in self:
+ self.in_server = (self.context == 'server')
+ if 'log' not in self:
+ name = '%s.log' % self.context
+ if self.in_tree or self.context == 'cli':
+ self.log = path.join(self.dot_ipa, 'log', name)
+ else:
+ self.log = path.join('/', 'var', 'log', 'ipa', name)
+ for (key, value) in defaults.items():
+ if key not in self:
+ self[key] = value
+
+ def _finalize(self):
+ """
+ Finalize and lock environment.
+
+ This method should be called after all plugins have bean loaded and
+ after `plugable.API.finalize()` has been called.
+ """
+ self.__doing('_finalize')
+ self.__do_if_not_done('_finalize_core')
+ self.__lock__()
+
+ def _merge_config(self, conf_file):
"""
Merge in values from ``conf_file`` into this `Env`.
"""
@@ -204,14 +248,6 @@ class Env(object):
i += 1
return (i, len(items))
- def _finalize(self, **defaults):
- """
- Finalize and lock environment.
-
- This method should be called after all plugins have bean loaded and
- after `plugable.API.finalize()` has been called.
- """
-
def __lock__(self):
"""
Prevent further changes to environment.
diff --git a/ipalib/constants.py b/ipalib/constants.py
index d817fda45..a1cc5b4c6 100644
--- a/ipalib/constants.py
+++ b/ipalib/constants.py
@@ -21,5 +21,41 @@
Constants centralized in one file.
"""
-# The section read in config files, i.e. [global]
+# The section to read in the config files, i.e. [global]
CONFIG_SECTION = 'global'
+
+
+# The default configuration for api.env
+DEFAULT_CONFIG = (
+ ('lite_xmlrpc_port', 8888),
+ ('lite_webui_port', 9999),
+ ('xmlrpc_uri', 'http://localhost:8888'),
+ ('ldap_uri', ''),
+
+ ('verbose', False),
+ ('debug', False),
+
+ # Env.__init__() or Env._bootstrap() or Env._finalize_core()
+ # will have filled in all the keys below by the time DEFAULT_CONFIG
+ # is merged in, so the values below are never actually used. They are
+ # listed both to provide a big picture and so DEFAULT_CONFIG contains
+ # the keys that should be present after Env._load_standard is called.
+
+ # Set in Env.__init__():
+ ('ipalib', None), # The directory containing ipalib/__init__.py
+ ('site_packages', None), # The directory contaning ipalib
+ ('script', None), # sys.argv[0]
+ ('bin', None), # The directory containing script
+ ('home', None), # The home directory of user underwhich process is running
+ ('dot_ipa', None), # ~/.ipa directory
+
+ # Set in Env._bootstrap():
+ ('in_tree', None), # Whether or not running in-tree (bool)
+ ('context', None), # Name of context, default is 'default'
+ ('conf', None), # Path to configuration file
+
+ # Set in Env._finalize_core():
+ ('in_server', None), # Whether or not running in-server (bool)
+ ('log', None), # Path to log file
+
+)
diff --git a/tests/test_ipalib/test_config.py b/tests/test_ipalib/test_config.py
index 01ff2f01a..b4c86319f 100644
--- a/tests/test_ipalib/test_config.py
+++ b/tests/test_ipalib/test_config.py
@@ -28,7 +28,7 @@ import sys
from tests.util import raises, setitem, delitem, ClassChecker
from tests.util import getitem, setitem, delitem
from tests.util import TempDir, TempHome
-from ipalib import config
+from ipalib import config, constants
def test_Environment():
@@ -157,6 +157,7 @@ WfUu+/mDOAGOjsRo0UkIo+pPl6Rckl7ehuR1INGAj9u0kW2nXvK45YlQp1odukaICSAjgSQWf//Z
# A config file that tries to override some standard vars:
config_override = """
[global]
+
key0 = var0
home = /home/sweet/home
key1 = var1
@@ -165,9 +166,10 @@ key2 = var2
key3 = var3
"""
-# A config file that test the automatic type conversion
+# A config file that tests the automatic type conversion
config_good = """
[global]
+
yes = TRUE
no = False
number = 42
@@ -205,7 +207,9 @@ class test_Env(ClassChecker):
def bootstrap(self, **overrides):
(o, home) = self.new()
+ assert o._isdone('_bootstrap') is False
o._bootstrap(**overrides)
+ assert o._isdone('_bootstrap') is True
e = raises(StandardError, o._bootstrap)
assert str(e) == 'Env._bootstrap() already called'
return (o, home)
@@ -214,7 +218,6 @@ class test_Env(ClassChecker):
"""
Test the `ipalib.config.Env._bootstrap` method.
"""
-
# Test defaults created by _bootstrap():
(o, home) = self.new()
assert 'in_tree' not in o
@@ -253,9 +256,110 @@ class test_Env(ClassChecker):
assert getattr(o, key) == value
assert o[key] == value
- def test_load_config(self):
+ def finalize_core(self, **defaults):
+ (o, home) = self.new()
+ assert o._isdone('_finalize_core') is False
+ o._finalize_core(**defaults)
+ assert o._isdone('_finalize_core') is True
+ e = raises(StandardError, o._finalize_core)
+ assert str(e) == 'Env._finalize_core() already called'
+ return (o, home)
+
+ def test_finalize_core(self):
+ """
+ Test the `ipalib.config.Env._finalize_core` method.
+ """
+ # Check that calls cascade up the chain:
+ (o, home) = self.new()
+ assert o._isdone('_bootstrap') is False
+ assert o._isdone('_finalize_core') is False
+ assert o._isdone('_finalize') is False
+ o._finalize_core()
+ assert o._isdone('_bootstrap') is True
+ assert o._isdone('_finalize_core') is True
+ assert o._isdone('_finalize') is False
+
+ # Check that it can't be called twice:
+ e = raises(StandardError, o._finalize_core)
+ assert str(e) == 'Env._finalize_core() already called'
+
+ # Check that _bootstrap() did its job:
+ (o, home) = self.bootstrap()
+ assert 'in_tree' in o
+ assert 'conf' in o
+ assert 'context' in o
+
+ # Check that keys _finalize_core() will set are not set yet:
+ assert 'log' not in o
+ assert 'in_server' not in o
+
+ # Check that _finalize_core() did its job:
+ o._finalize_core()
+ assert 'in_server' in o
+ assert 'log' in o
+ assert o.in_tree is False
+ assert o.context == 'default'
+ assert o.in_server is False
+ assert o.log == '/var/log/ipa/default.log'
+
+ # Check log is in ~/.ipa/log when context='cli'
+ (o, home) = self.bootstrap(context='cli')
+ o._finalize_core()
+ assert o.in_tree is False
+ assert o.log == home.join('.ipa', 'log', 'cli.log')
+
+ # Check **defaults can't set in_server nor log:
+ (o, home) = self.bootstrap(in_server='tRUE')
+ o._finalize_core(in_server=False)
+ assert o.in_server is True
+ (o, home) = self.bootstrap(log='/some/silly/log')
+ o._finalize_core(log='/a/different/log')
+ assert o.log == '/some/silly/log'
+
+ # Test loading config file, plus test some in-tree stuff
+ (o, home) = self.bootstrap(in_tree=True, context='server')
+ for key in ('yes', 'no', 'number'):
+ assert key not in o
+ home.write(config_good, '.ipa', 'server.conf')
+ o._finalize_core()
+ assert o.in_tree is True
+ assert o.context == 'server'
+ assert o.in_server is True
+ assert o.log == home.join('.ipa', 'log', 'server.log')
+ assert o.yes is True
+ assert o.no is False
+ assert o.number == 42
+
+ # Test using DEFAULT_CONFIG:
+ defaults = dict(constants.DEFAULT_CONFIG)
+ (o, home) = self.finalize_core(**defaults)
+ assert list(o) == sorted(defaults)
+ for (key, value) in defaults.items():
+ if value is None:
+ continue
+ assert o[key] is value
+
+ def test_finalize(self):
+ """
+ Test the `ipalib.config.Env._finalize` method.
+ """
+ # Check that calls cascade up the chain:
+ (o, home) = self.new()
+ assert o._isdone('_bootstrap') is False
+ assert o._isdone('_finalize_core') is False
+ assert o._isdone('_finalize') is False
+ o._finalize()
+ assert o._isdone('_bootstrap') is True
+ assert o._isdone('_finalize_core') is True
+ assert o._isdone('_finalize') is True
+
+ # Check that it can't be called twice:
+ e = raises(StandardError, o._finalize)
+ assert str(e) == 'Env._finalize() already called'
+
+ def test_merge_config(self):
"""
- Test the `ipalib.config.Env._load_config` method.
+ Test the `ipalib.config.Env._merge_config` method.
"""
tmp = TempDir()
assert callable(tmp.join)
@@ -266,27 +370,27 @@ class test_Env(ClassChecker):
o = self.cls()
keys = tuple(o)
orig = dict((k, o[k]) for k in o)
- assert o._load_config(no_exist) is None
+ assert o._merge_config(no_exist) is None
assert tuple(o) == keys
# Test an empty config file
empty = tmp.touch('empty.conf')
assert path.isfile(empty)
- assert o._load_config(empty) is None
+ assert o._merge_config(empty) is None
assert tuple(o) == keys
# Test a mal-formed config file:
bad = tmp.join('bad.conf')
open(bad, 'w').write(config_bad)
assert path.isfile(bad)
- assert o._load_config(bad) is None
+ assert o._merge_config(bad) is None
assert tuple(o) == keys
# Test a valid config file that tries to override
override = tmp.join('override.conf')
open(override, 'w').write(config_override)
assert path.isfile(override)
- assert o._load_config(override) == (4, 6)
+ assert o._merge_config(override) == (4, 6)
for (k, v) in orig.items():
assert o[k] is v
assert list(o) == sorted(keys + ('key0', 'key1', 'key2', 'key3'))
@@ -298,7 +402,7 @@ class test_Env(ClassChecker):
good = tmp.join('good.conf')
open(good, 'w').write(config_good)
assert path.isfile(good)
- assert o._load_config(good) == (3, 3)
+ assert o._merge_config(good) == (3, 3)
assert list(o) == sorted(keys + ('yes', 'no', 'number'))
assert o.yes is True
assert o.no is False
diff --git a/tests/util.py b/tests/util.py
index 1cbc4e312..cc761ce72 100644
--- a/tests/util.py
+++ b/tests/util.py
@@ -61,6 +61,14 @@ class TempDir(object):
assert path.isfile(f) and not path.islink(f)
return f
+ def write(self, content, *parts):
+ d = self.makedirs(*parts[:-1])
+ f = path.join(d, parts[-1])
+ assert not path.exists(f)
+ open(f, 'w').write(content)
+ assert path.isfile(f) and not path.islink(f)
+ return f
+
def join(self, *parts):
return path.join(self.path, *parts)