Skip to content
This repository was archived by the owner on Sep 12, 2018. It is now read-only.

Commit 4b40c3f

Browse files
author
Mangled Deutz
committed
New config class
Docker-DCO-1.1-Signed-off-by: Mangled Deutz <[email protected]> (github: dmp42)
1 parent 39b4c32 commit 4b40c3f

File tree

1 file changed

+71
-53
lines changed

1 file changed

+71
-53
lines changed

docker_registry/lib/config.py

Lines changed: 71 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -4,52 +4,72 @@
44
import rsa
55
import yaml
66

7+
from docker_registry.core import compat
78
from docker_registry.core import exceptions
89

910

1011
class Config(object):
12+
"""A simple config class that:
13+
* gives properties access through either items or attributes
14+
* enforce types (thanks to yaml)
15+
* interpolate from ENV
16+
"""
1117

12-
def __init__(self, config):
13-
self._config = config
18+
def __init__(self, config=''):
19+
try:
20+
# Config is kept as-is...
21+
self._config = config
22+
# ... save Strings, that are yaml loaded
23+
if isinstance(config, compat.basestring):
24+
self._config = yaml.load(config)
25+
except Exception as e:
26+
# Failed yaml loading? Stop here!
27+
raise exceptions.ConfigError(
28+
'Config is not valid yaml (%s): \n%s' % (e, config))
1429

1530
def __repr__(self):
1631
return repr(self._config)
1732

33+
def __dir__(self):
34+
return self._config.keys()
35+
36+
# Python 2.6 and below need this
37+
@property
38+
def __members__(self):
39+
return self._config.keys()
40+
41+
@property
42+
def __methods__(self):
43+
return []
44+
1845
def __getattr__(self, key):
19-
if key in self._config:
20-
return self._config[key]
21-
22-
def get(self, *args, **kwargs):
23-
return self._config.get(*args, **kwargs)
24-
25-
26-
def _walk_object(obj, callback):
27-
if not hasattr(obj, '__iter__'):
28-
return callback(obj)
29-
obj_new = {}
30-
if isinstance(obj, dict):
31-
for i, value in obj.iteritems():
32-
value = _walk_object(value, callback)
33-
if value or value == '':
34-
obj_new[i] = value
35-
return obj_new
36-
for i, value in enumerate(obj):
37-
value = _walk_object(value, callback)
38-
if value or value == '':
39-
obj_new[i] = value
40-
return obj_new
41-
42-
43-
def convert_env_vars(config):
44-
def _replace_env(s):
45-
if isinstance(s, basestring) and s.startswith('_env:'):
46-
parts = s.split(':', 2)
47-
varname = parts[1]
48-
vardefault = None if len(parts) < 3 else parts[2]
49-
return os.environ.get(varname, vardefault)
50-
return s
51-
52-
return _walk_object(config, _replace_env)
46+
# Unset keys return None
47+
if key not in self._config:
48+
return None
49+
# raise exceptions.ConfigError("No such attribute: %s" % key)
50+
result = self._config[key]
51+
# Dicts are rewrapped inside a Config object
52+
if isinstance(result, dict):
53+
return Config(result)
54+
# Strings starting with `_env:' get evaluated
55+
if isinstance(
56+
result, compat.basestring) and result.startswith('_env:'):
57+
result = result.split(':', 2)
58+
varname = result[1]
59+
vardefault = '' if len(result) < 3 else result[2]
60+
try:
61+
result = yaml.load(os.environ.get(varname, vardefault))
62+
except Exception as e:
63+
raise exceptions.ConfigError(
64+
'Config `%s` (value: `%s`) is not valid: %s' % (
65+
varname, e, result))
66+
return result
67+
68+
def __getitem__(self, key):
69+
return getattr(self, key)
70+
71+
def __contains__(self, key):
72+
return key in self._config
5373

5474

5575
_config = None
@@ -59,8 +79,10 @@ def load():
5979
global _config
6080
if _config is not None:
6181
return _config
62-
data = None
82+
83+
flavor = os.environ.get('SETTINGS_FLAVOR', 'dev')
6384
config_path = os.environ.get('DOCKER_REGISTRY_CONFIG', 'config.yml')
85+
6486
if not os.path.isabs(config_path):
6587
config_path = os.path.join(os.path.dirname(__file__), '../../',
6688
'config', config_path)
@@ -70,29 +92,25 @@ def load():
7092
raise exceptions.FileNotFoundError(
7193
'Heads-up! File is missing: %s' % config_path)
7294

73-
try:
74-
data = yaml.load(f)
75-
except Exception:
76-
raise exceptions.ConfigError(
77-
'Config file (%s) is not valid yaml' % config_path)
95+
_config = Config(f.read())
96+
if flavor:
97+
_config = _config[flavor]
98+
_config.flavor = flavor
7899

79-
config = data.get('common', {})
80-
flavor = os.environ.get('SETTINGS_FLAVOR', 'dev')
81-
config.update(data.get(flavor, {}))
82-
config['flavor'] = flavor
83-
config = convert_env_vars(config)
84-
if 'privileged_key' in config:
100+
if _config.privileged_key:
85101
try:
86-
f = open(config['privileged_key'])
102+
f = open(_config.privileged_key)
87103
except Exception:
88104
raise exceptions.FileNotFoundError(
89-
'Heads-up! File is missing: %s' % config['privileged_key'])
105+
'Heads-up! File is missing: %s' % _config.privileged_key)
90106

91107
try:
92-
config['privileged_key'] = rsa.PublicKey.load_pkcs1(f.read())
108+
_config.privileged_key = rsa.PublicKey.load_pkcs1(f.read())
93109
except Exception:
94110
raise exceptions.ConfigError(
95-
'Key at %s is not a valid RSA key' % config['privileged_key'])
111+
'Key at %s is not a valid RSA key' % _config.privileged_key)
112+
113+
if _config.index_endpoint:
114+
_config.index_endpoint = _config.index_endpoint.strip('/')
96115

97-
_config = Config(config)
98116
return _config

0 commit comments

Comments
 (0)