1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
|
from os.path import abspath, isabs, join, dirname
import logging
import tempfile
import shutil
import urllib
import urlparse
from .deployment import Deployment
from .utils import ErrorExit, yaml_load, path_exists, dict_merge
class ConfigStack(object):
log = logging.getLogger("deployer.config")
def __init__(self, config_files):
self.config_files = config_files
self.data = {}
self.yaml = {}
self.include_dirs = []
self.urlopen = urllib.urlopen
self.load()
def _yaml_load(self, config_file):
if config_file in self.yaml:
return self.yaml[config_file]
if urlparse.urlparse(config_file).scheme:
response = self.urlopen(config_file)
if response.getcode() == 200:
temp = tempfile.NamedTemporaryFile(delete=True)
shutil.copyfileobj(response, temp)
temp.flush()
config_file = temp.name
else:
self.log.warning("Could not retrieve %s", config_file)
raise ErrorExit()
with open(config_file) as fh:
try:
self.yaml[config_file] = yaml_load(fh.read())
except Exception, e:
self.log.warning(
"Couldn't load config file @ %r, error: %s:%s",
config_file, type(e), e)
raise
return self.yaml[config_file]
def keys(self):
return sorted(self.data)
def get(self, key):
if not key in self.data:
self.log.warning("Deployment %r not found. Available %s",
key, ", ".join(self.keys()))
raise ErrorExit()
deploy_data = self.data[key]
deploy_data = self._resolve_inherited(deploy_data)
return Deployment(key, deploy_data, self.include_dirs)
def load(self):
data = {}
include_dirs = []
for fp in self._resolve_included():
if path_exists(fp):
include_dirs.append(dirname(abspath(fp)))
d = self._yaml_load(fp)
data = dict_merge(data, d)
self.data = data
if 'include-config' in self.data:
self.data.pop('include-config')
self.include_dirs = include_dirs
def _inherits(self, d):
parents = d.get('inherits', ())
if isinstance(parents, basestring):
parents = [parents]
return parents
def _resolve_inherited(self, deploy_data):
if not 'inherits' in deploy_data:
return deploy_data
inherits = parents = self._inherits(deploy_data)
for parent_name in parents:
parent = self.get(parent_name)
inherits.extend(self._inherits(parent.data))
deploy_data = dict_merge(parent.data, deploy_data)
deploy_data['inherits'] = inherits
return deploy_data
def _includes(self, config_file):
files = [config_file]
d = self._yaml_load(config_file)
if 'include-config' in d:
inc_f = d['include-config']
if not isabs(inc_f):
inc_f = join(dirname(config_file), inc_f)
files.extend(self._includes(inc_f))
return files
def _resolve_included(self):
files = []
[files.extend(self._includes(cf)) for cf in self.config_files]
return files
|