Statistics
| Branch: | Tag: | Revision:

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