forked from aws/aws-cli
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* release-1.10.7: Bumping version to 1.10.7 Add route53 to changelog Update changelog with latest changes Handle empty sections when using configure set command Break the configure model into several distinct files. add .python-version to gitignore
- Loading branch information
Showing
22 changed files
with
1,481 additions
and
1,283 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
# Copyright 2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"). You | ||
# may not use this file except in compliance with the License. A copy of | ||
# the License is located at | ||
# | ||
# http://aws.amazon.com/apache2.0/ | ||
# | ||
# or in the "license" file accompanying this file. This file is | ||
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF | ||
# ANY KIND, either express or implied. See the License for the specific | ||
# language governing permissions and limitations under the License. | ||
import os | ||
import logging | ||
|
||
from botocore.exceptions import ProfileNotFound | ||
|
||
from awscli.compat import raw_input | ||
from awscli.customizations.commands import BasicCommand | ||
from awscli.customizations.configure.addmodel import AddModelCommand | ||
from awscli.customizations.configure.set import ConfigureSetCommand | ||
from awscli.customizations.configure.get import ConfigureGetCommand | ||
from awscli.customizations.configure.list import ConfigureListCommand | ||
from awscli.customizations.configure.writer import ConfigFileWriter | ||
|
||
from . import mask_value | ||
|
||
|
||
logger = logging.getLogger(__name__) | ||
|
||
|
||
def register_configure_cmd(cli): | ||
cli.register('building-command-table.main', | ||
ConfigureCommand.add_command) | ||
|
||
|
||
class InteractivePrompter(object): | ||
|
||
def get_value(self, current_value, config_name, prompt_text=''): | ||
if config_name in ('aws_access_key_id', 'aws_secret_access_key'): | ||
current_value = mask_value(current_value) | ||
response = raw_input("%s [%s]: " % (prompt_text, current_value)) | ||
if not response: | ||
# If the user hits enter, we return a value of None | ||
# instead of an empty string. That way we can determine | ||
# whether or not a value has changed. | ||
response = None | ||
return response | ||
|
||
|
||
class ConfigureCommand(BasicCommand): | ||
NAME = 'configure' | ||
DESCRIPTION = BasicCommand.FROM_FILE() | ||
SYNOPSIS = ('aws configure [--profile profile-name]') | ||
EXAMPLES = ( | ||
'To create a new configuration::\n' | ||
'\n' | ||
' $ aws configure\n' | ||
' AWS Access Key ID [None]: accesskey\n' | ||
' AWS Secret Access Key [None]: secretkey\n' | ||
' Default region name [None]: us-west-2\n' | ||
' Default output format [None]:\n' | ||
'\n' | ||
'To update just the region name::\n' | ||
'\n' | ||
' $ aws configure\n' | ||
' AWS Access Key ID [****]:\n' | ||
' AWS Secret Access Key [****]:\n' | ||
' Default region name [us-west-1]: us-west-2\n' | ||
' Default output format [None]:\n' | ||
) | ||
SUBCOMMANDS = [ | ||
{'name': 'list', 'command_class': ConfigureListCommand}, | ||
{'name': 'get', 'command_class': ConfigureGetCommand}, | ||
{'name': 'set', 'command_class': ConfigureSetCommand}, | ||
{'name': 'add-model', 'command_class': AddModelCommand} | ||
] | ||
|
||
# If you want to add new values to prompt, update this list here. | ||
VALUES_TO_PROMPT = [ | ||
# (logical_name, config_name, prompt_text) | ||
('aws_access_key_id', "AWS Access Key ID"), | ||
('aws_secret_access_key', "AWS Secret Access Key"), | ||
('region', "Default region name"), | ||
('output', "Default output format"), | ||
] | ||
|
||
def __init__(self, session, prompter=None, config_writer=None): | ||
super(ConfigureCommand, self).__init__(session) | ||
if prompter is None: | ||
prompter = InteractivePrompter() | ||
self._prompter = prompter | ||
if config_writer is None: | ||
config_writer = ConfigFileWriter() | ||
self._config_writer = config_writer | ||
|
||
def _run_main(self, parsed_args, parsed_globals): | ||
# Called when invoked with no args "aws configure" | ||
new_values = {} | ||
# This is the config from the config file scoped to a specific | ||
# profile. | ||
try: | ||
config = self._session.get_scoped_config() | ||
except ProfileNotFound: | ||
config = {} | ||
for config_name, prompt_text in self.VALUES_TO_PROMPT: | ||
current_value = config.get(config_name) | ||
new_value = self._prompter.get_value(current_value, config_name, | ||
prompt_text) | ||
if new_value is not None and new_value != current_value: | ||
new_values[config_name] = new_value | ||
config_filename = os.path.expanduser( | ||
self._session.get_config_variable('config_file')) | ||
if new_values: | ||
self._write_out_creds_file_values(new_values, | ||
parsed_globals.profile) | ||
if parsed_globals.profile is not None: | ||
new_values['__section__'] = ( | ||
'profile %s' % parsed_globals.profile) | ||
self._config_writer.update_config(new_values, config_filename) | ||
|
||
def _write_out_creds_file_values(self, new_values, profile_name): | ||
# The access_key/secret_key are now *always* written to the shared | ||
# credentials file (~/.aws/credentials), see aws/aws-cli#847. | ||
# post-conditions: ~/.aws/credentials will have the updated credential | ||
# file values and new_values will have the cred vars removed. | ||
credential_file_values = {} | ||
if 'aws_access_key_id' in new_values: | ||
credential_file_values['aws_access_key_id'] = new_values.pop( | ||
'aws_access_key_id') | ||
if 'aws_secret_access_key' in new_values: | ||
credential_file_values['aws_secret_access_key'] = new_values.pop( | ||
'aws_secret_access_key') | ||
if credential_file_values: | ||
if profile_name is not None: | ||
credential_file_values['__section__'] = profile_name | ||
shared_credentials_filename = os.path.expanduser( | ||
self._session.get_config_variable('credentials_file')) | ||
self._config_writer.update_config( | ||
credential_file_values, | ||
shared_credentials_filename) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
# Copyright 2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"). You | ||
# may not use this file except in compliance with the License. A copy of | ||
# the License is located at | ||
# | ||
# http://aws.amazon.com/apache2.0/ | ||
# | ||
# or in the "license" file accompanying this file. This file is | ||
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF | ||
# ANY KIND, either express or implied. See the License for the specific | ||
# language governing permissions and limitations under the License. | ||
import sys | ||
|
||
from awscli.customizations.commands import BasicCommand | ||
|
||
from . import PREDEFINED_SECTION_NAMES | ||
|
||
|
||
class ConfigureGetCommand(BasicCommand): | ||
NAME = 'get' | ||
DESCRIPTION = BasicCommand.FROM_FILE('configure', 'get', | ||
'_description.rst') | ||
SYNOPSIS = ('aws configure get varname [--profile profile-name]') | ||
EXAMPLES = BasicCommand.FROM_FILE('configure', 'get', '_examples.rst') | ||
ARG_TABLE = [ | ||
{'name': 'varname', | ||
'help_text': 'The name of the config value to retrieve.', | ||
'action': 'store', | ||
'cli_type_name': 'string', 'positional_arg': True}, | ||
] | ||
|
||
def __init__(self, session, stream=sys.stdout): | ||
super(ConfigureGetCommand, self).__init__(session) | ||
self._stream = stream | ||
|
||
def _run_main(self, args, parsed_globals): | ||
varname = args.varname | ||
value = None | ||
if '.' not in varname: | ||
# get_scoped_config() returns the config variables in the config | ||
# file (not the logical_var names), which is what we want. | ||
config = self._session.get_scoped_config() | ||
value = config.get(varname) | ||
else: | ||
value = self._get_dotted_config_value(varname) | ||
if value is not None: | ||
self._stream.write(value) | ||
self._stream.write('\n') | ||
return 0 | ||
else: | ||
return 1 | ||
|
||
def _get_dotted_config_value(self, varname): | ||
parts = varname.split('.') | ||
num_dots = varname.count('.') | ||
# Logic to deal with predefined sections like [preview], [plugin] and etc. | ||
if num_dots == 1 and parts[0] in PREDEFINED_SECTION_NAMES: | ||
full_config = self._session.full_config | ||
section, config_name = varname.split('.') | ||
value = full_config.get(section, {}).get(config_name) | ||
if value is None: | ||
# Try to retrieve it from the profile config. | ||
value = full_config['profiles'].get( | ||
section, {}).get(config_name) | ||
return value | ||
if parts[0] == 'profile': | ||
profile_name = parts[1] | ||
config_name = parts[2] | ||
remaining = parts[3:] | ||
# Check if varname starts with 'default' profile (e.g. default.emr-dev.emr.instance_profile) | ||
# If not, go further to check if varname starts with a known profile name | ||
elif parts[0] == 'default' or (parts[0] in self._session.full_config['profiles']): | ||
profile_name = parts[0] | ||
config_name = parts[1] | ||
remaining = parts[2:] | ||
else: | ||
profile_name = self._session.get_config_variable('profile') | ||
config_name = parts[0] | ||
remaining = parts[1:] | ||
|
||
value = self._session.full_config['profiles'].get( | ||
profile_name, {}).get(config_name) | ||
if len(remaining) == 1: | ||
try: | ||
value = value.get(remaining[-1]) | ||
except AttributeError: | ||
value = None | ||
return value |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
# Copyright 2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"). You | ||
# may not use this file except in compliance with the License. A copy of | ||
# the License is located at | ||
# | ||
# http://aws.amazon.com/apache2.0/ | ||
# | ||
# or in the "license" file accompanying this file. This file is | ||
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF | ||
# ANY KIND, either express or implied. See the License for the specific | ||
# language governing permissions and limitations under the License. | ||
import sys | ||
|
||
from awscli.customizations.commands import BasicCommand | ||
|
||
from . import ConfigValue, NOT_SET | ||
|
||
|
||
class ConfigureListCommand(BasicCommand): | ||
NAME = 'list' | ||
DESCRIPTION = ( | ||
'List the AWS CLI configuration data. This command will ' | ||
'show you the current configuration data. For each configuration ' | ||
'item, it will show you the value, where the configuration value ' | ||
'was retrieved, and the configuration variable name. For example, ' | ||
'if you provide the AWS region in an environment variable, this ' | ||
'command will show you the name of the region you\'ve configured, ' | ||
'it will tell you that this value came from an environment ' | ||
'variable, and it will tell you the name of the environment ' | ||
'variable.\n' | ||
) | ||
SYNOPSIS = 'aws configure list [--profile profile-name]' | ||
EXAMPLES = ( | ||
'To show your current configuration values::\n' | ||
'\n' | ||
' $ aws configure list\n' | ||
' Name Value Type Location\n' | ||
' ---- ----- ---- --------\n' | ||
' profile <not set> None None\n' | ||
' access_key ****************ABCD config_file ~/.aws/config\n' | ||
' secret_key ****************ABCD config_file ~/.aws/config\n' | ||
' region us-west-2 env AWS_DEFAULT_REGION\n' | ||
'\n' | ||
) | ||
|
||
def __init__(self, session, stream=sys.stdout): | ||
super(ConfigureListCommand, self).__init__(session) | ||
self._stream = stream | ||
|
||
def _run_main(self, args, parsed_globals): | ||
self._display_config_value(ConfigValue('Value', 'Type', 'Location'), | ||
'Name') | ||
self._display_config_value(ConfigValue('-----', '----', '--------'), | ||
'----') | ||
|
||
if self._session.profile is not None: | ||
profile = ConfigValue(self._session.profile, 'manual', | ||
'--profile') | ||
else: | ||
profile = self._lookup_config('profile') | ||
self._display_config_value(profile, 'profile') | ||
|
||
access_key, secret_key = self._lookup_credentials() | ||
self._display_config_value(access_key, 'access_key') | ||
self._display_config_value(secret_key, 'secret_key') | ||
|
||
region = self._lookup_config('region') | ||
self._display_config_value(region, 'region') | ||
|
||
def _display_config_value(self, config_value, config_name): | ||
self._stream.write('%10s %24s %16s %s\n' % ( | ||
config_name, config_value.value, config_value.config_type, | ||
config_value.config_variable)) | ||
|
||
def _lookup_credentials(self): | ||
# First try it with _lookup_config. It's possible | ||
# that we don't find credentials this way (for example, | ||
# if we're using an IAM role). | ||
access_key = self._lookup_config('access_key') | ||
if access_key.value is not NOT_SET: | ||
secret_key = self._lookup_config('secret_key') | ||
access_key.mask_value() | ||
secret_key.mask_value() | ||
return access_key, secret_key | ||
else: | ||
# Otherwise we can try to use get_credentials(). | ||
# This includes a few more lookup locations | ||
# (IAM roles, some of the legacy configs, etc.) | ||
credentials = self._session.get_credentials() | ||
if credentials is None: | ||
no_config = ConfigValue(NOT_SET, None, None) | ||
return no_config, no_config | ||
else: | ||
# For the ConfigValue, we don't track down the | ||
# config_variable because that info is not | ||
# visible from botocore.credentials. I think | ||
# the credentials.method is sufficient to show | ||
# where the credentials are coming from. | ||
access_key = ConfigValue(credentials.access_key, | ||
credentials.method, '') | ||
secret_key = ConfigValue(credentials.secret_key, | ||
credentials.method, '') | ||
access_key.mask_value() | ||
secret_key.mask_value() | ||
return access_key, secret_key | ||
|
||
def _lookup_config(self, name): | ||
# First try to look up the variable in the env. | ||
value = self._session.get_config_variable(name, methods=('env',)) | ||
if value is not None: | ||
return ConfigValue(value, 'env', self._session.session_var_map[name][1]) | ||
# Then try to look up the variable in the config file. | ||
value = self._session.get_config_variable(name, methods=('config',)) | ||
if value is not None: | ||
return ConfigValue(value, 'config-file', | ||
self._session.get_config_variable('config_file')) | ||
else: | ||
return ConfigValue(NOT_SET, None, None) |
Oops, something went wrong.