1# Copyright (c) 2006,2007 Mitch Garnaat http://garnaat.org/ 2# Copyright (c) 2011 Chris Moyer http://coredumped.org/ 3# 4# Permission is hereby granted, free of charge, to any person obtaining a 5# copy of this software and associated documentation files (the 6# "Software"), to deal in the Software without restriction, including 7# without limitation the rights to use, copy, modify, merge, publish, dis- 8# tribute, sublicense, and/or sell copies of the Software, and to permit 9# persons to whom the Software is furnished to do so, subject to the fol- 10# lowing conditions: 11# 12# The above copyright notice and this permission notice shall be included 13# in all copies or substantial portions of the Software. 14# 15# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 16# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- 17# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 18# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 19# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21# IN THE SOFTWARE. 22# 23import os 24import re 25import warnings 26 27import boto 28 29from boto.compat import expanduser, ConfigParser, StringIO 30 31 32# By default we use two locations for the boto configurations, 33# /etc/boto.cfg and ~/.boto (which works on Windows and Unix). 34BotoConfigPath = '/etc/boto.cfg' 35BotoConfigLocations = [BotoConfigPath] 36UserConfigPath = os.path.join(expanduser('~'), '.boto') 37BotoConfigLocations.append(UserConfigPath) 38 39# If there's a BOTO_CONFIG variable set, we load ONLY 40# that variable 41if 'BOTO_CONFIG' in os.environ: 42 BotoConfigLocations = [expanduser(os.environ['BOTO_CONFIG'])] 43 44# If there's a BOTO_PATH variable set, we use anything there 45# as the current configuration locations, split with os.pathsep. 46elif 'BOTO_PATH' in os.environ: 47 BotoConfigLocations = [] 48 for path in os.environ['BOTO_PATH'].split(os.pathsep): 49 BotoConfigLocations.append(expanduser(path)) 50 51 52class Config(ConfigParser): 53 54 def __init__(self, path=None, fp=None, do_load=True): 55 # We don't use ``super`` here, because ``ConfigParser`` still uses 56 # old-style classes. 57 ConfigParser.__init__(self, {'working_dir': '/mnt/pyami', 58 'debug': '0'}) 59 if do_load: 60 if path: 61 self.load_from_path(path) 62 elif fp: 63 self.readfp(fp) 64 else: 65 self.read(BotoConfigLocations) 66 if "AWS_CREDENTIAL_FILE" in os.environ: 67 full_path = expanduser(os.environ['AWS_CREDENTIAL_FILE']) 68 try: 69 self.load_credential_file(full_path) 70 except IOError: 71 warnings.warn('Unable to load AWS_CREDENTIAL_FILE (%s)' % full_path) 72 73 def load_credential_file(self, path): 74 """Load a credential file as is setup like the Java utilities""" 75 c_data = StringIO() 76 c_data.write("[Credentials]\n") 77 for line in open(path, "r").readlines(): 78 c_data.write(line.replace("AWSAccessKeyId", "aws_access_key_id").replace("AWSSecretKey", "aws_secret_access_key")) 79 c_data.seek(0) 80 self.readfp(c_data) 81 82 def load_from_path(self, path): 83 file = open(path) 84 for line in file.readlines(): 85 match = re.match("^#import[\s\t]*([^\s^\t]*)[\s\t]*$", line) 86 if match: 87 extended_file = match.group(1) 88 (dir, file) = os.path.split(path) 89 self.load_from_path(os.path.join(dir, extended_file)) 90 self.read(path) 91 92 def save_option(self, path, section, option, value): 93 """ 94 Write the specified Section.Option to the config file specified by path. 95 Replace any previous value. If the path doesn't exist, create it. 96 Also add the option the the in-memory config. 97 """ 98 config = ConfigParser() 99 config.read(path) 100 if not config.has_section(section): 101 config.add_section(section) 102 config.set(section, option, value) 103 fp = open(path, 'w') 104 config.write(fp) 105 fp.close() 106 if not self.has_section(section): 107 self.add_section(section) 108 self.set(section, option, value) 109 110 def save_user_option(self, section, option, value): 111 self.save_option(UserConfigPath, section, option, value) 112 113 def save_system_option(self, section, option, value): 114 self.save_option(BotoConfigPath, section, option, value) 115 116 def get_instance(self, name, default=None): 117 try: 118 val = self.get('Instance', name) 119 except: 120 val = default 121 return val 122 123 def get_user(self, name, default=None): 124 try: 125 val = self.get('User', name) 126 except: 127 val = default 128 return val 129 130 def getint_user(self, name, default=0): 131 try: 132 val = self.getint('User', name) 133 except: 134 val = default 135 return val 136 137 def get_value(self, section, name, default=None): 138 return self.get(section, name, default) 139 140 def get(self, section, name, default=None): 141 try: 142 val = ConfigParser.get(self, section, name) 143 except: 144 val = default 145 return val 146 147 def getint(self, section, name, default=0): 148 try: 149 val = ConfigParser.getint(self, section, name) 150 except: 151 val = int(default) 152 return val 153 154 def getfloat(self, section, name, default=0.0): 155 try: 156 val = ConfigParser.getfloat(self, section, name) 157 except: 158 val = float(default) 159 return val 160 161 def getbool(self, section, name, default=False): 162 if self.has_option(section, name): 163 val = self.get(section, name) 164 if val.lower() == 'true': 165 val = True 166 else: 167 val = False 168 else: 169 val = default 170 return val 171 172 def setbool(self, section, name, value): 173 if value: 174 self.set(section, name, 'true') 175 else: 176 self.set(section, name, 'false') 177 178 def dump(self): 179 s = StringIO() 180 self.write(s) 181 print(s.getvalue()) 182 183 def dump_safe(self, fp=None): 184 if not fp: 185 fp = StringIO() 186 for section in self.sections(): 187 fp.write('[%s]\n' % section) 188 for option in self.options(section): 189 if option == 'aws_secret_access_key': 190 fp.write('%s = xxxxxxxxxxxxxxxxxx\n' % option) 191 else: 192 fp.write('%s = %s\n' % (option, self.get(section, option))) 193 194 def dump_to_sdb(self, domain_name, item_name): 195 from boto.compat import json 196 sdb = boto.connect_sdb() 197 domain = sdb.lookup(domain_name) 198 if not domain: 199 domain = sdb.create_domain(domain_name) 200 item = domain.new_item(item_name) 201 item.active = False 202 for section in self.sections(): 203 d = {} 204 for option in self.options(section): 205 d[option] = self.get(section, option) 206 item[section] = json.dumps(d) 207 item.save() 208 209 def load_from_sdb(self, domain_name, item_name): 210 from boto.compat import json 211 sdb = boto.connect_sdb() 212 domain = sdb.lookup(domain_name) 213 item = domain.get_item(item_name) 214 for section in item.keys(): 215 if not self.has_section(section): 216 self.add_section(section) 217 d = json.loads(item[section]) 218 for attr_name in d.keys(): 219 attr_value = d[attr_name] 220 if attr_value is None: 221 attr_value = 'None' 222 if isinstance(attr_value, bool): 223 self.setbool(section, attr_name, attr_value) 224 else: 225 self.set(section, attr_name, attr_value) 226