diff --git a/S3/Config.py b/S3/Config.py index 8b4b2759..6755ef31 100644 --- a/S3/Config.py +++ b/S3/Config.py @@ -261,18 +261,19 @@ class Config(object): max_retries = 5 ## Creating a singleton - def __new__(self, configfile = None, access_key=None, secret_key=None, access_token=None): + def __new__(self, configfile = None, access_key=None, secret_key=None, access_token=None, profile=None): if self._instance is None: self._instance = object.__new__(self) return self._instance - def __init__(self, configfile = None, access_key=None, secret_key=None, access_token=None): + def __init__(self, configfile = None, access_key=None, secret_key=None, access_token=None, profile=None): if configfile: + debug("Config: Initializing with config file '%s', profile '%s'" % (configfile, profile)) try: - self.read_config_file(configfile) + self.read_config_file(configfile, profile) except IOError: if 'AWS_SHARED_CREDENTIALS_FILE' in os.environ or 'AWS_CREDENTIAL_FILE' in os.environ or 'AWS_PROFILE' in os.environ: - self.aws_credential_file() + self.aws_credential_file(profile) # override these if passed on the command-line # Allow blank secret_key @@ -335,7 +336,7 @@ def role_config(self): '%s=%s' % (k, s3_quote(v, unicode_output=True)) for k, v in params.items() ]) - sts_endpoint = os.environ.get("AWS_STS_ENDPOINT", sts_endpoint) + sts_endpoint = os.environ.get("AWS_STS_ENDPOINT", sts_endpoint) if os.environ.get("AWS_STS_REGIONAL_ENDPOINTS") == "regional": # Check if the AWS_REGION variable is available to use as a region. region = os.environ.get("AWS_REGION") @@ -441,7 +442,7 @@ def role_refresh(self): except Exception: warning("Could not refresh role") - def aws_credential_file(self): + def aws_credential_file(self, profile=None): try: aws_credential_file = os.path.expanduser('~/.aws/credentials') credential_file_from_env = os.environ.get('AWS_SHARED_CREDENTIALS_FILE') \ @@ -482,7 +483,8 @@ def aws_credential_file(self): "Error reading aws_credential_file " "(%s): %s" % (aws_credential_file, str(exc))) - profile = base_unicodise(os.environ.get('AWS_PROFILE', "default")) + if profile is None: + profile = base_unicodise(os.environ.get('AWS_PROFILE', "default")) debug("Using AWS profile '%s'" % (profile)) # get_key - helper function to read the aws profile credentials @@ -559,8 +561,14 @@ def option_list(self): retval.append(option) return retval - def read_config_file(self, configfile): - cp = ConfigParser(configfile) + def read_config_file(self, configfile, profile=None): + if profile is None: + profile = os.environ.get('AWS_PROFILE', 'default') + + cp = ConfigParser(configfile, ["default"]) + if profile and profile != "default": + cp.parse_file(configfile, [profile]) + for option in self.option_list(): _option = cp.get(option) if _option is not None: @@ -655,7 +663,8 @@ def parse_file(self, file, sections = []): debug("ConfigParser: Reading file '%s'" % file) if type(sections) != type([]): sections = [sections] - in_our_section = True + in_our_section = not sections # If no sections specified, read all + current_section = "default" r_comment = re.compile(r'^\s*#.*') r_empty = re.compile(r'^\s*$') r_section = re.compile(r'^\[([^\]]+)\]') @@ -667,8 +676,8 @@ def parse_file(self, file, sections = []): continue is_section = r_section.match(line) if is_section: - section = is_section.groups()[0] - in_our_section = (section in sections) or (len(sections) == 0) + current_section = is_section.groups()[0] + in_our_section = (current_section in sections) or (not sections) continue is_data = r_data.match(line) if is_data and in_our_section: @@ -682,6 +691,9 @@ def parse_file(self, file, sections = []): print_value = data["value"] debug("ConfigParser: %s->%s" % (data["key"], print_value)) continue + if is_data and not in_our_section: + # Skip data in sections we're not interested in + continue warning("Ignoring invalid line in '%s': %s" % (file, line)) def __getitem__(self, name): diff --git a/s3cmd b/s3cmd index e3b526fa..417e3ec0 100755 --- a/s3cmd +++ b/s3cmd @@ -3158,6 +3158,7 @@ def main(): optparser.add_option( "--access_key", dest="access_key", help="AWS Access Key") optparser.add_option( "--secret_key", dest="secret_key", help="AWS Secret Key") optparser.add_option( "--access_token", dest="access_token", help="AWS Access Token") + optparser.add_option( "--profile", dest="profile", metavar="PROFILE", help="Profile to use from .s3cfg file") optparser.add_option("-n", "--dry-run", dest="dry_run", action="store_true", help="Only show what should be uploaded or downloaded but don't actually do it. May still perform S3 requests to get bucket listings and other information though (only for file transfer commands)") @@ -3316,7 +3317,7 @@ def main(): sys.exit(EX_CONFIG) try: - cfg = Config(options.config, options.access_key, options.secret_key, options.access_token) + cfg = Config(options.config, options.access_key, options.secret_key, options.access_token, options.profile) except ValueError as exc: raise ParameterError(unicode(exc)) except IOError as e: