Improve config, tests and docs

Add better support to env variables.
This commit is contained in:
vrde 2016-03-31 11:37:09 +02:00
parent e4d3915533
commit 804365db24
5 changed files with 58 additions and 28 deletions

View File

@ -26,7 +26,7 @@ def run_show_config(args):
# TODO Proposal: remove the "hidden" configuration. Only show config. If # TODO Proposal: remove the "hidden" configuration. Only show config. If
# the system needs to be configured, then display information on how to # the system needs to be configured, then display information on how to
# configure the system. # configure the system.
bigchaindb.config_utils.file_config(args.config) bigchaindb.config_utils.autoconfigure(filename=args.config, force=True)
pprint(bigchaindb.config) pprint(bigchaindb.config)

View File

@ -155,20 +155,38 @@ def update_types(config):
reference = bigchaindb.config reference = bigchaindb.config
def _coerce(current, value):
# Coerce a value to the `current` type.
try:
# First we try to apply current to the value, since it
# might be a function
return current(value)
except TypeError:
# Then we check if current is a list AND if the value
# is a string.
if isinstance(current, list) and isinstance(value, str):
# If so, we use the colon as the separator
return value.split(':')
try:
# If we are here, we should try to apply the type
# of `current` to the value
return type(current)(value)
except TypeError:
# Worst case scenario we return the value itself.
return value
def _update_type(value, path): def _update_type(value, path):
ref = reference current = reference
for elem in path: for elem in path:
ref = ref[elem]
try: try:
return ref(value) current = current[elem]
except TypeError: except KeyError:
try:
return type(ref)(value)
except TypeError:
return value return value
return _coerce(current, value)
return map_leafs(_update_type, config) return map_leafs(_update_type, config)
@ -207,6 +225,7 @@ def autoconfigure(filename=None, config=None, force=False):
been initialized.""" been initialized."""
if not force and bigchaindb.config.get('CONFIGURED'): if not force and bigchaindb.config.get('CONFIGURED'):
logger.info('System already configured, skipping autoconfiguration')
return return
newconfig = env_config(bigchaindb.config) newconfig = env_config(bigchaindb.config)
@ -215,9 +234,10 @@ def autoconfigure(filename=None, config=None, force=False):
newconfig = update(newconfig, config) newconfig = update(newconfig, config)
try: try:
newconfig = update(newconfig, file_config()) # import pdb; pdb.set_trace()
except FileNotFoundError: newconfig = update(newconfig, file_config(filename=filename))
logger.warning('Cannot find your config file.') except FileNotFoundError as e:
logger.warning('Cannot find config file `%s`.' % e.filename)
dict_config(newconfig) dict_config(newconfig)
return newconfig return newconfig

View File

@ -29,7 +29,6 @@ For more information check the help with `bigchaindb -h`.
# Precedence in reading configuration values # Precedence in reading configuration values
Note that there is a precedence in reading configuration values: Note that there is a precedence in reading configuration values:
- (**not yet**) command line;
- local config file; - local config file;
- environment vars; - environment vars;
- default config file (contained in ``bigchaindb.__init__``). - default config file (contained in ``bigchaindb.__init__``).
@ -46,29 +45,37 @@ This means that if the default configuration contains an entry that is:
while your local file `local.json` contains: while your local file `local.json` contains:
``` ```
{... {...
"database": {"host": "whatever"} "database": {"host": "ec2-xx-xx-xxx-xxx.eu-central-1.compute.amazonaws.com"}
...} ...}
``` ```
and you run this command: and you run this command:
``` ```
$ BIGCHAINDB_DATABASE_HOST=foobar BIGCHAINDB_DATABASE_PORT=42000 bigchaindb -c local.json show-config $ BIGCHAINDB_DATABASE_HOST=anotherhost.com \
BIGCHAINDB_DATABASE_PORT=4242 \
BIGCHAINDB_KEYRING=pubkey0:pubkey1 \
bigchaindb -c local.json show-config
``` ```
you will get: you will get:
``` ```
Cannot find config file `/home/vrde/.bigchaindb`.
INFO:bigchaindb.config_utils:Configuration loaded from `local.json` INFO:bigchaindb.config_utils:Configuration loaded from `local.json`
{'CONFIGURED': True, {'CONFIGURED': True,
'api_endpoint': 'http://localhost:8008/api/v1', 'api_endpoint': 'http://localhost:8008/api/v1',
'consensus_plugin': 'default', 'consensus_plugin': 'default',
'database': {'host': 'localhost', 'name': 'bigchain', 'port': 28015}, 'database': {'host': 'ec2-xx-xx-xxx-xxx.eu-central-1.compute.amazonaws.com',
'keypair': {'private': 'Hbqvh...', 'name': 'bigchain',
'public': '2Bi5NU...'}, 'port': 4242},
'keyring': [], 'keypair': {'private': None, 'public': None},
'keyring': ['pubkey0', 'pubkey1'],
'statsd': {'host': 'localhost', 'port': 8125, 'rate': 0.01}} 'statsd': {'host': 'localhost', 'port': 8125, 'rate': 0.01}}
``` ```
Note that the type of `keyring` is a list. If you want to pass a list as an
environ variable you need to use colon (`:`) as separator.
# List of env variables # List of env variables
``` ```
@ -77,6 +84,7 @@ INFO:bigchaindb.config_utils:Configuration loaded from `local.json`
- BIGCHAINDB_DATABASE_NAME - BIGCHAINDB_DATABASE_NAME
- BIGCHAINDB_KEYPAIR_PUBLIC - BIGCHAINDB_KEYPAIR_PUBLIC
- BIGCHAINDB_KEYPAIR_PRIVATE - BIGCHAINDB_KEYPAIR_PRIVATE
- BIGCHAINDB_KEYRING
- BIGCHAINDB_STATSD_HOST - BIGCHAINDB_STATSD_HOST
- BIGCHAINDB_STATSD_PORT - BIGCHAINDB_STATSD_PORT
- BIGCHAINDB_STATSD_RATE - BIGCHAINDB_STATSD_RATE

View File

@ -14,7 +14,7 @@ def mock_run_configure(monkeypatch):
@pytest.fixture @pytest.fixture
def mock_file_config(monkeypatch): def mock_file_config(monkeypatch):
from bigchaindb import config_utils from bigchaindb import config_utils
monkeypatch.setattr(config_utils, 'file_config', lambda *args: None) monkeypatch.setattr(config_utils, 'file_config', lambda *args, **kwargs: {})
@pytest.fixture @pytest.fixture

View File

@ -106,28 +106,30 @@ def test_env_config(monkeypatch):
def test_autoconfigure_read_both_from_file_and_env(monkeypatch): def test_autoconfigure_read_both_from_file_and_env(monkeypatch):
monkeypatch.setattr('bigchaindb.config_utils.file_config', lambda: {}) file_config = {
monkeypatch.setattr('os.environ', {'BIGCHAINDB_DATABASE_HOST': 'test-host', 'database': {'host': 'test-host'}
'BIGCHAINDB_DATABASE_PORT': '4242'}) }
monkeypatch.setattr('bigchaindb.config_utils.file_config', lambda *args, **kwargs: file_config)
monkeypatch.setattr('os.environ', {'BIGCHAINDB_DATABASE_NAME': 'test-dbname',
'BIGCHAINDB_DATABASE_PORT': '4242',
'BIGCHAINDB_KEYRING': 'pubkey_0:pubkey_1:pubkey_2'})
import bigchaindb import bigchaindb
from bigchaindb import config_utils from bigchaindb import config_utils
config_utils.autoconfigure() config_utils.autoconfigure()
assert bigchaindb.config['database']['host'] == 'test-host'
assert bigchaindb.config['database']['port'] == 4242
assert bigchaindb.config == { assert bigchaindb.config == {
'CONFIGURED': True, 'CONFIGURED': True,
'database': { 'database': {
'host': 'test-host', 'host': 'test-host',
'port': 4242, 'port': 4242,
'name': 'bigchain', 'name': 'test-dbname',
}, },
'keypair': { 'keypair': {
'public': None, 'public': None,
'private': None, 'private': None,
}, },
'keyring': [], 'keyring': ['pubkey_0', 'pubkey_1', 'pubkey_2'],
'statsd': { 'statsd': {
'host': 'localhost', 'host': 'localhost',
'port': 8125, 'port': 8125,