Finished Env._finalize_core() and corresponding unit tests

This commit is contained in:
Jason Gerard DeRose 2008-10-24 20:02:14 -06:00
parent 8ca44bcbfa
commit ac4efac394
4 changed files with 208 additions and 24 deletions

View File

@ -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.

View File

@ -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
)

View File

@ -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._load_config` method.
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._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

View File

@ -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)