root / kamaki / config.py @ d2cea1e2
History | View | Annotate | Download (4.1 kB)
1 |
# Copyright 2011 GRNET S.A. All rights reserved.
|
---|---|
2 |
#
|
3 |
# Redistribution and use in source and binary forms, with or
|
4 |
# without modification, are permitted provided that the following
|
5 |
# conditions are met:
|
6 |
#
|
7 |
# 1. Redistributions of source code must retain the above
|
8 |
# copyright notice, this list of conditions and the following
|
9 |
# disclaimer.
|
10 |
#
|
11 |
# 2. Redistributions in binary form must reproduce the above
|
12 |
# copyright notice, this list of conditions and the following
|
13 |
# disclaimer in the documentation and/or other materials
|
14 |
# provided with the distribution.
|
15 |
#
|
16 |
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
|
17 |
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
18 |
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
19 |
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
|
20 |
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
21 |
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
22 |
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
23 |
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
24 |
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
25 |
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
26 |
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
27 |
# POSSIBILITY OF SUCH DAMAGE.
|
28 |
#
|
29 |
# The views and conclusions contained in the software and
|
30 |
# documentation are those of the authors and should not be
|
31 |
# interpreted as representing official policies, either expressed
|
32 |
# or implied, of GRNET S.A.
|
33 |
|
34 |
import json |
35 |
import logging |
36 |
import os |
37 |
|
38 |
from os.path import exists, expanduser |
39 |
|
40 |
|
41 |
# Path to the file that stores the configuration
|
42 |
CONFIG_PATH = expanduser('~/.kamakirc')
|
43 |
|
44 |
# Name of a shell variable to bypass the CONFIG_PATH value
|
45 |
CONFIG_ENV = 'KAMAKI_CONFIG'
|
46 |
|
47 |
# The defaults also determine the allowed keys
|
48 |
CONFIG_DEFAULTS = { |
49 |
'apis': 'compute image storage cyclades pithos', |
50 |
'token': '', |
51 |
'url': '', |
52 |
'compute_token': '', |
53 |
'compute_url': 'https://okeanos.grnet.gr/api/v1', |
54 |
'image_token': '', |
55 |
'image_url': 'https://okeanos.grnet.gr/plankton', |
56 |
'storage_account': '', |
57 |
'storage_container': '', |
58 |
'storage_token': '', |
59 |
'storage_url': 'https://plus.pithos.grnet.gr/v1' |
60 |
} |
61 |
|
62 |
|
63 |
log = logging.getLogger('kamaki.config')
|
64 |
|
65 |
|
66 |
class ConfigError(Exception): |
67 |
pass
|
68 |
|
69 |
|
70 |
class Config(object): |
71 |
def __init__(self): |
72 |
self.path = os.environ.get(CONFIG_ENV, CONFIG_PATH)
|
73 |
self.defaults = CONFIG_DEFAULTS
|
74 |
|
75 |
d = self.read()
|
76 |
for key, val in d.items(): |
77 |
if key not in self.defaults: |
78 |
log.warning('Ignoring unknown config key "%s".', key)
|
79 |
|
80 |
self.d = d
|
81 |
self.overrides = {}
|
82 |
|
83 |
def read(self): |
84 |
if not exists(self.path): |
85 |
return {}
|
86 |
|
87 |
with open(self.path) as f: |
88 |
data = f.read() |
89 |
|
90 |
try:
|
91 |
d = json.loads(data) |
92 |
assert isinstance(d, dict) |
93 |
return d
|
94 |
except (ValueError, AssertionError): |
95 |
msg = '"%s" does not look like a kamaki config file.' % self.path |
96 |
raise ConfigError(msg)
|
97 |
|
98 |
def write(self): |
99 |
self.read() # Make sure we don't overwrite anything wrong |
100 |
with open(self.path, 'w') as f: |
101 |
data = json.dumps(self.d, indent=True) |
102 |
f.write(data) |
103 |
|
104 |
def items(self): |
105 |
for key, val in self.defaults.items(): |
106 |
yield key, self.get(key) |
107 |
|
108 |
def get(self, key): |
109 |
if key in self.overrides: |
110 |
return self.overrides[key] |
111 |
if key in self.d: |
112 |
return self.d[key] |
113 |
return self.defaults.get(key, '') |
114 |
|
115 |
def set(self, key, val): |
116 |
if key not in self.defaults: |
117 |
log.warning('Ignoring unknown config key "%s".', key)
|
118 |
return
|
119 |
self.d[key] = val
|
120 |
self.write()
|
121 |
|
122 |
def delete(self, key): |
123 |
if key not in self.defaults: |
124 |
log.warning('Ignoring unknown config key "%s".', key)
|
125 |
return
|
126 |
self.d.pop(key, None) |
127 |
self.write()
|
128 |
|
129 |
def override(self, key, val): |
130 |
assert key in self.defaults |
131 |
if val is not None: |
132 |
self.overrides[key] = val
|