1
from os.path import abspath, isabs, join, dirname
9
from .deployment import Deployment
10
from .utils import ErrorExit, yaml_load, path_exists, dict_merge
13
class ConfigStack(object):
15
log = logging.getLogger("deployer.config")
17
def __init__(self, config_files):
18
self.config_files = config_files
21
self.include_dirs = []
22
self.urlopen = urllib.urlopen
25
def _yaml_load(self, config_file):
26
if config_file in self.yaml:
27
return self.yaml[config_file]
29
if urlparse.urlparse(config_file).scheme:
30
response = self.urlopen(config_file)
31
if response.getcode() == 200:
32
temp = tempfile.NamedTemporaryFile(delete=True)
33
shutil.copyfileobj(response, temp)
35
config_file = temp.name
37
self.log.warning("Could not retrieve %s", config_file)
40
with open(config_file) as fh:
42
self.yaml[config_file] = yaml_load(fh.read())
45
"Couldn't load config file @ %r, error: %s:%s",
46
config_file, type(e), e)
49
return self.yaml[config_file]
52
return sorted(self.data)
55
if not key in self.data:
56
self.log.warning("Deployment %r not found. Available %s",
57
key, ", ".join(self.keys()))
59
deploy_data = self.data[key]
60
deploy_data = self._resolve_inherited(deploy_data)
61
return Deployment(key, deploy_data, self.include_dirs)
66
for fp in self._resolve_included():
68
include_dirs.append(dirname(abspath(fp)))
69
d = self._yaml_load(fp)
70
data = dict_merge(data, d)
72
if 'include-config' in self.data:
73
self.data.pop('include-config')
74
self.include_dirs = include_dirs
76
def _inherits(self, d):
77
parents = d.get('inherits', ())
78
if isinstance(parents, basestring):
82
def _resolve_inherited(self, deploy_data):
83
if not 'inherits' in deploy_data:
85
inherits = parents = self._inherits(deploy_data)
86
for parent_name in parents:
87
parent = self.get(parent_name)
88
inherits.extend(self._inherits(parent.data))
89
deploy_data = dict_merge(parent.data, deploy_data)
91
deploy_data['inherits'] = inherits
94
def _includes(self, config_file):
96
d = self._yaml_load(config_file)
97
if 'include-config' in d:
98
inc_f = d['include-config']
100
inc_f = join(dirname(config_file), inc_f)
101
files.extend(self._includes(inc_f))
104
def _resolve_included(self):
106
[files.extend(self._includes(cf)) for cf in self.config_files]