diff -Nru awscli-1.11.13/awscli/alias.py awscli-1.11.44/awscli/alias.py --- awscli-1.11.13/awscli/alias.py 1970-01-01 00:00:00.000000000 +0000 +++ awscli-1.11.44/awscli/alias.py 2017-01-27 00:22:38.000000000 +0000 @@ -0,0 +1,282 @@ +# 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 logging +import os +import shlex +import subprocess + +from botocore.configloader import raw_config_parse + +from awscli.commands import CLICommand +from awscli.utils import emit_top_level_args_parsed_event + + +LOG = logging.getLogger(__name__) + + +class InvalidAliasException(Exception): + pass + + +class AliasLoader(object): + def __init__(self, + alias_filename=os.path.expanduser( + os.path.join('~', '.aws', 'cli', 'alias'))): + """Interface for loading and interacting with alias file + + :param alias_filename: The name of the file to load aliases from. + This file must be an INI file. + """ + self._filename = alias_filename + self._aliases = None + + def _build_aliases(self): + self._aliases = self._load_aliases() + self._cleanup_alias_values(self._aliases.get('toplevel', {})) + + def _load_aliases(self): + if os.path.exists(self._filename): + return raw_config_parse( + self._filename, parse_subsections=False) + return {'toplevel': {}} + + def _cleanup_alias_values(self, aliases): + for alias in aliases: + # Beginning and end line separators should not be included + # in the internal representation of the alias value. + aliases[alias] = aliases[alias].strip() + + def get_aliases(self): + if self._aliases is None: + self._build_aliases() + return self._aliases.get('toplevel', {}) + + +class AliasCommandInjector(object): + def __init__(self, session, alias_loader): + """Injects alias commands for a command table + + :type session: botocore.session.Session + :param session: The botocore session + + :type alias_loader: awscli.alias.AliasLoader + :param alias_loader: The alias loader to use + """ + self._session = session + self._alias_loader = alias_loader + + def inject_aliases(self, command_table, parser): + for alias_name, alias_value in \ + self._alias_loader.get_aliases().items(): + if alias_value.startswith('!'): + alias_cmd = ExternalAliasCommand(alias_name, alias_value) + else: + service_alias_cmd_args = [ + alias_name, alias_value, self._session, command_table, + parser + ] + # If the alias name matches something already in the + # command table provide the command it is about + # to clobber as a possible reference that it will + # need to proxy to. + if alias_name in command_table: + service_alias_cmd_args.append( + command_table[alias_name]) + alias_cmd = ServiceAliasCommand(*service_alias_cmd_args) + command_table[alias_name] = alias_cmd + + +class BaseAliasCommand(CLICommand): + _UNDOCUMENTED = True + + def __init__(self, alias_name, alias_value): + """Base class for alias command + + :type alias_name: string + :param alias_name: The name of the alias + + :type alias_value: string + :param alias_value: The parsed value of the alias. This can be + retrieved from `AliasLoader.get_aliases()[alias_name]` + """ + self._alias_name = alias_name + self._alias_value = alias_value + + def __call__(self, args, parsed_args): + raise NotImplementedError('__call__') + + @property + def name(self): + return self._alias_name + + @name.setter + def name(self, value): + self._alias_name = value + + +class ServiceAliasCommand(BaseAliasCommand): + UNSUPPORTED_GLOBAL_PARAMETERS = [ + 'debug', + 'profile' + ] + + def __init__(self, alias_name, alias_value, session, command_table, + parser, shadow_proxy_command=None): + """Command for a `toplevel` subcommand alias + + :type alias_name: string + :param alias_name: The name of the alias + + :type alias_value: string + :param alias_value: The parsed value of the alias. This can be + retrieved from `AliasLoader.get_aliases()[alias_name]` + + :type session: botocore.session.Session + :param session: The botocore session + + :type command_table: dict + :param command_table: The command table containing all of the + possible service command objects that a particular alias could + redirect to. + + :type parser: awscli.argparser.MainArgParser + :param parser: The parser to parse commands provided at the top level + of a CLI command which includes service commands and global + parameters. This is used to parse the service commmand and any + global parameters from the alias's value. + + :type shadow_proxy_command: CLICommand + :param shadow_proxy_command: A built-in command that + potentially shadows the alias in name. If the alias + references this command in its value, the alias should proxy + to this command as oppposed to proxy to itself in the command + table + """ + super(ServiceAliasCommand, self).__init__(alias_name, alias_value) + self._session = session + self._command_table = command_table + self._parser = parser + self._shadow_proxy_command = shadow_proxy_command + + def __call__(self, args, parsed_globals): + alias_args = self._get_alias_args() + parsed_alias_args, remaining = self._parser.parse_known_args( + alias_args) + self._update_parsed_globals(parsed_alias_args, parsed_globals) + # Take any of the remaining arguments that were not parsed out and + # prepend them to the remaining args provided to the alias. + remaining.extend(args) + LOG.debug( + 'Alias %r passing on arguments: %r to %r command', + self._alias_name, remaining, parsed_alias_args.command) + # Pass the update remaing args and global args to the service command + # the alias proxied to. + command = self._command_table[parsed_alias_args.command] + if self._shadow_proxy_command: + shadow_name = self._shadow_proxy_command.name + # Use the shadow command only if the aliases value + # uses that command indicating it needs to proxy over to + # a built-in command. + if shadow_name == parsed_alias_args.command: + LOG.debug( + 'Using shadowed command object: %s ' + 'for alias: %s', self._shadow_proxy_command, + self._alias_name + ) + command = self._shadow_proxy_command + return command(remaining, parsed_globals) + + def _get_alias_args(self): + try: + alias_args = shlex.split(self._alias_value) + except ValueError as e: + raise InvalidAliasException( + 'Value of alias "%s" could not be parsed. ' + 'Received error: %s when parsing:\n%s' % ( + self._alias_name, e, self._alias_value) + ) + + alias_args = [arg.strip(os.linesep) for arg in alias_args] + LOG.debug( + 'Expanded subcommand alias %r with value: %r to: %r', + self._alias_name, self._alias_value, alias_args + ) + return alias_args + + def _update_parsed_globals(self, parsed_alias_args, parsed_globals): + global_params_to_update = self._get_global_parameters_to_update( + parsed_alias_args) + # Emit the top level args parsed event to ensure all possible + # customizations that typically get applied are applied to the + # global parameters provided in the alias before updating + # the original provided global parameter values + # and passing those onto subsequent commands. + emit_top_level_args_parsed_event(self._session, parsed_alias_args) + for param_name in global_params_to_update: + updated_param_value = getattr(parsed_alias_args, param_name) + setattr(parsed_globals, param_name, updated_param_value) + + def _get_global_parameters_to_update(self, parsed_alias_args): + # Retrieve a list of global parameters that the newly parsed args + # from the alias will have to clobber from the originally provided + # parsed globals. + global_params_to_update = [] + for parsed_param, value in vars(parsed_alias_args).items(): + # To determine which parameters in the alias were global values + # compare the parsed alias parameters to the default as + # specified by the parser. If the parsed values from the alias + # differs from the default value in the parser, + # that global parameter must have been provided in the alias. + if self._parser.get_default(parsed_param) != value: + if parsed_param in self.UNSUPPORTED_GLOBAL_PARAMETERS: + raise InvalidAliasException( + 'Global parameter "--%s" detected in alias "%s" ' + 'which is not support in subcommand aliases.' % ( + parsed_param, self._alias_name)) + else: + global_params_to_update.append(parsed_param) + return global_params_to_update + + +class ExternalAliasCommand(BaseAliasCommand): + def __init__(self, alias_name, alias_value, invoker=subprocess.call): + """Command for external aliases + + Executes command external of CLI as opposed to being a proxy + to another command. + + :type alias_name: string + :param alias_name: The name of the alias + + :type alias_value: string + :param alias_value: The parsed value of the alias. This can be + retrieved from `AliasLoader.get_aliases()[alias_name]` + + :type invoker: callable + :param invoker: Callable to run arguments of external alias. The + signature should match that of ``subprocess.call`` + """ + self._alias_name = alias_name + self._alias_value = alias_value + self._invoker = invoker + + def __call__(self, args, parsed_globals): + command_components = [ + self._alias_value[1:] + ] + command_components.extend(args) + command = ' '.join(command_components) + LOG.debug( + 'Using external alias %r with value: %r to run: %r', + self._alias_name, self._alias_value, command) + return self._invoker(command, shell=True) diff -Nru awscli-1.11.13/awscli/argparser.py awscli-1.11.44/awscli/argparser.py --- awscli-1.11.13/awscli/argparser.py 2016-11-03 20:32:27.000000000 +0000 +++ awscli-1.11.44/awscli/argparser.py 2017-01-27 00:22:38.000000000 +0000 @@ -29,6 +29,35 @@ ) +class CommandAction(argparse.Action): + """Custom action for CLI command arguments + + Allows the choices for the argument to be mutable. The choices + are dynamically retrieved from the keys of the referenced command + table + """ + def __init__(self, option_strings, dest, command_table, **kwargs): + self.command_table = command_table + super(CommandAction, self).__init__( + option_strings, dest, choices=self.choices, **kwargs + ) + + def __call__(self, parser, namespace, values, option_string=None): + setattr(namespace, self.dest, values) + + @property + def choices(self): + return list(self.command_table.keys()) + + @choices.setter + def choices(self, val): + # argparse.Action will always try to set this value upon + # instantiation, but this value should be dynamically + # generated from the command table keys. So make this a + # NOOP if argparse.Action tries to set this value. + pass + + class CLIArgParser(argparse.ArgumentParser): Formatter = argparse.RawTextHelpFormatter @@ -106,7 +135,8 @@ self.add_argument('--version', action="version", version=version_string, help='Display the version of this tool') - self.add_argument('command', choices=list(command_table.keys())) + self.add_argument('command', action=CommandAction, + command_table=command_table) class ServiceArgParser(CLIArgParser): @@ -121,7 +151,8 @@ self._service_name = service_name def _build(self, operations_table): - self.add_argument('operation', choices=list(operations_table.keys())) + self.add_argument('operation', action=CommandAction, + command_table=operations_table) class ArgTableArgParser(CLIArgParser): @@ -145,8 +176,8 @@ argument = argument_table[arg_name] argument.add_to_parser(self) if command_table: - self.add_argument('subcommand', choices=list(command_table.keys()), - nargs='?') + self.add_argument('subcommand', action=CommandAction, + command_table=command_table, nargs='?') def parse_known_args(self, args, namespace=None): if len(args) == 1 and args[0] == 'help': diff -Nru awscli-1.11.13/awscli/clidocs.py awscli-1.11.44/awscli/clidocs.py --- awscli-1.11.13/awscli/clidocs.py 2016-11-03 20:32:27.000000000 +0000 +++ awscli-1.11.44/awscli/clidocs.py 2017-01-27 00:22:38.000000000 +0000 @@ -300,6 +300,8 @@ class OperationDocumentEventHandler(CLIDocumentEventHandler): + AWS_DOC_BASE = 'https://docs.aws.amazon.com/goto/WebAPI' + def build_translation_map(self): operation_model = self.help_command.obj d = {} @@ -330,6 +332,24 @@ operation_model = help_command.obj doc.style.h2('Description') doc.include_doc_string(operation_model.documentation) + self._add_webapi_crosslink(help_command) + + def _add_webapi_crosslink(self, help_command): + doc = help_command.doc + operation_model = help_command.obj + service_model = operation_model.service_model + service_uid = service_model.metadata.get('uid') + if service_uid is None: + # If there's no service_uid in the model, we can't + # be certain if the generated cross link will work + # so we don't generate any crosslink info. + return + doc.style.new_paragraph() + doc.write("See also: ") + link = '%s/%s/%s' % (self.AWS_DOC_BASE, service_uid, + operation_model.name) + doc.style.external_link(title="AWS API Documentation", link=link) + doc.writeln('') def _json_example_value_name(self, argument_model, include_enum_values=True): # If include_enum_values is True, then the valid enum values diff -Nru awscli-1.11.13/awscli/clidriver.py awscli-1.11.44/awscli/clidriver.py --- awscli-1.11.13/awscli/clidriver.py 2016-11-03 20:32:27.000000000 +0000 +++ awscli-1.11.44/awscli/clidriver.py 2017-01-27 00:22:38.000000000 +0000 @@ -25,6 +25,7 @@ from awscli import EnvironmentVariables, __version__ from awscli.formatter import get_formatter from awscli.plugin import load_plugins +from awscli.commands import CLICommand from awscli.argparser import MainArgParser from awscli.argparser import ServiceArgParser from awscli.argparser import ArgTableArgParser @@ -38,6 +39,9 @@ from awscli.arguments import CLIArgument from awscli.arguments import UnknownArgumentError from awscli.argprocess import unpack_argument +from awscli.alias import AliasLoader +from awscli.alias import AliasCommandInjector +from awscli.utils import emit_top_level_args_parsed_event LOG = logging.getLogger('awscli.clidriver') @@ -77,6 +81,7 @@ self._cli_data = None self._command_table = None self._argument_table = None + self.alias_loader = AliasLoader() def _get_cli_data(self): # Not crazy about this but the data in here is needed in @@ -120,6 +125,12 @@ service_name=service_name) return commands + def _add_aliases(self, command_table, parser): + parser = self._create_parser(command_table) + injector = AliasCommandInjector( + self.session, self.alias_loader) + injector.inject_aliases(command_table, parser) + def _build_argument_table(self): argument_table = OrderedDict() cli_data = self._get_cli_data() @@ -152,9 +163,8 @@ cli_data.get('synopsis', None), cli_data.get('help_usage', None)) - def _create_parser(self): + def _create_parser(self, command_table): # Also add a 'help' command. - command_table = self._get_command_table() command_table['help'] = self.create_help_command() cli_data = self._get_cli_data() parser = MainArgParser( @@ -173,8 +183,9 @@ """ if args is None: args = sys.argv[1:] - parser = self._create_parser() command_table = self._get_command_table() + parser = self._create_parser(command_table) + self._add_aliases(command_table, parser) parsed_args, remaining = parser.parse_known_args(args) try: # Because _handle_top_level_args emits events, it's possible @@ -226,8 +237,7 @@ sys.stderr.write('\n') def _handle_top_level_args(self, args): - self.session.emit( - 'top-level-args-parsed', parsed_args=args, session=self.session) + emit_top_level_args_parsed_event(self.session, args) if args.profile: self.session.set_config_variable('profile', args.profile) if args.debug: @@ -249,64 +259,6 @@ log_level=logging.ERROR) -class CLICommand(object): - - """Interface for a CLI command. - - This class represents a top level CLI command - (``aws ec2``, ``aws s3``, ``aws config``). - - """ - - @property - def name(self): - # Subclasses must implement a name. - raise NotImplementedError("name") - - @name.setter - def name(self, value): - # Subclasses must implement setting/changing the cmd name. - raise NotImplementedError("name") - - @property - def lineage(self): - # Represents how to get to a specific command using the CLI. - # It includes all commands that came before it and itself in - # a list. - return [self] - - @property - def lineage_names(self): - # Represents the lineage of a command in terms of command ``name`` - return [cmd.name for cmd in self.lineage] - - def __call__(self, args, parsed_globals): - """Invoke CLI operation. - - :type args: str - :param args: The remaining command line args. - - :type parsed_globals: ``argparse.Namespace`` - :param parsed_globals: The parsed arguments so far. - - :rtype: int - :return: The return code of the operation. This will be used - as the RC code for the ``aws`` process. - - """ - # Subclasses are expected to implement this method. - pass - - def create_help_command(self): - # Subclasses are expected to implement this method if they want - # help docs. - return None - - @property - def arg_table(self): - return {} - - class ServiceCommand(CLICommand): """A service command for the CLI. @@ -666,6 +618,13 @@ service_name, region_name=parsed_globals.region, endpoint_url=parsed_globals.endpoint_url, verify=parsed_globals.verify_ssl) + response = self._make_client_call( + client, operation_name, parameters, parsed_globals) + self._display_response(operation_name, response, parsed_globals) + return 0 + + def _make_client_call(self, client, operation_name, parameters, + parsed_globals): py_operation_name = xform_name(operation_name) if client.can_paginate(py_operation_name) and parsed_globals.paginate: paginator = client.get_paginator(py_operation_name) @@ -673,8 +632,7 @@ else: response = getattr(client, xform_name(operation_name))( **parameters) - self._display_response(operation_name, response, parsed_globals) - return 0 + return response def _display_response(self, command_name, response, parsed_globals): diff -Nru awscli-1.11.13/awscli/commands.py awscli-1.11.44/awscli/commands.py --- awscli-1.11.13/awscli/commands.py 1970-01-01 00:00:00.000000000 +0000 +++ awscli-1.11.44/awscli/commands.py 2017-01-27 00:22:38.000000000 +0000 @@ -0,0 +1,70 @@ +# 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. + + +class CLICommand(object): + + """Interface for a CLI command. + + This class represents a top level CLI command + (``aws ec2``, ``aws s3``, ``aws config``). + + """ + + @property + def name(self): + # Subclasses must implement a name. + raise NotImplementedError("name") + + @name.setter + def name(self, value): + # Subclasses must implement setting/changing the cmd name. + raise NotImplementedError("name") + + @property + def lineage(self): + # Represents how to get to a specific command using the CLI. + # It includes all commands that came before it and itself in + # a list. + return [self] + + @property + def lineage_names(self): + # Represents the lineage of a command in terms of command ``name`` + return [cmd.name for cmd in self.lineage] + + def __call__(self, args, parsed_globals): + """Invoke CLI operation. + + :type args: str + :param args: The remaining command line args. + + :type parsed_globals: ``argparse.Namespace`` + :param parsed_globals: The parsed arguments so far. + + :rtype: int + :return: The return code of the operation. This will be used + as the RC code for the ``aws`` process. + + """ + # Subclasses are expected to implement this method. + pass + + def create_help_command(self): + # Subclasses are expected to implement this method if they want + # help docs. + return None + + @property + def arg_table(self): + return {} diff -Nru awscli-1.11.13/awscli/compat.py awscli-1.11.44/awscli/compat.py --- awscli-1.11.13/awscli/compat.py 2016-11-03 20:32:27.000000000 +0000 +++ awscli-1.11.44/awscli/compat.py 2017-01-27 00:22:38.000000000 +0000 @@ -57,6 +57,12 @@ import msvcrt msvcrt.setmode(sys.stdout.fileno(), self.previous_mode) +def ensure_text_type(s): + if isinstance(s, six.text_type): + return s + if isinstance(s, six.binary_type): + return s.decode('utf-8') + raise ValueError("Expected str, unicode or bytes, received %s." % type(s)) if six.PY3: import locale diff -Nru awscli-1.11.13/awscli/customizations/argrename.py awscli-1.11.44/awscli/customizations/argrename.py --- awscli-1.11.13/awscli/customizations/argrename.py 2016-11-03 20:32:27.000000000 +0000 +++ awscli-1.11.44/awscli/customizations/argrename.py 2017-01-27 00:22:39.000000000 +0000 @@ -50,6 +50,11 @@ 'gamelift.update-build.version': 'build-version', 'route53domains.view-billing.start': 'start-time', 'route53domains.view-billing.end': 'end-time', + 'apigateway.create-rest-api.version': 'api-version', + 'pinpoint.get-campaign-version.version': 'campaign-version', + 'pinpoint.get-segment-version.version': 'segment-version', + 'stepfunctions.send-task-success.output': 'task-output', + 'clouddirectory.publish-schema.version': 'schema-version', } # Same format as ARGUMENT_RENAMES, but instead of renaming the arguments, diff -Nru awscli-1.11.13/awscli/customizations/cloudformation/artifact_exporter.py awscli-1.11.44/awscli/customizations/cloudformation/artifact_exporter.py --- awscli-1.11.13/awscli/customizations/cloudformation/artifact_exporter.py 1970-01-01 00:00:00.000000000 +0000 +++ awscli-1.11.44/awscli/customizations/cloudformation/artifact_exporter.py 2017-01-27 00:22:38.000000000 +0000 @@ -0,0 +1,418 @@ +# Copyright 2012-2015 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 logging +import os +import tempfile +import zipfile +import contextlib +import uuid +from awscli.compat import six + +from six.moves.urllib.parse import urlparse, parse_qs +from contextlib import contextmanager +from awscli.customizations.cloudformation import exceptions +from awscli.customizations.cloudformation.yamlhelper import yaml_dump, \ + yaml_parse + +LOG = logging.getLogger(__name__) + + +def is_path_value_valid(path): + return isinstance(path, six.string_types) + + +def make_abs_path(directory, path): + if is_path_value_valid(path) and not os.path.isabs(path): + return os.path.normpath(os.path.join(directory, path)) + else: + return path + + +def is_s3_url(url): + try: + parse_s3_url(url) + return True + except ValueError: + return False + + +def is_local_folder(path): + return is_path_value_valid(path) and os.path.isdir(path) + + +def is_local_file(path): + return is_path_value_valid(path) and os.path.isfile(path) + + +def parse_s3_url(url, + bucket_name_property="Bucket", + object_key_property="Key", + version_property=None): + + if isinstance(url, six.string_types) \ + and url.startswith("s3://"): + + # Python < 2.7.10 don't parse query parameters from URI with custom + # scheme such as s3://blah/blah. As a workaround, remove scheme + # altogether to trigger the parser "s3://foo/bar?v=1" =>"//foo/bar?v=1" + parsed = urlparse(url[3:]) + query = parse_qs(parsed.query) + + if parsed.netloc and parsed.path: + result = dict() + result[bucket_name_property] = parsed.netloc + result[object_key_property] = parsed.path.lstrip('/') + + # If there is a query string that has a single versionId field, + # set the object version and return + if version_property is not None \ + and 'versionId' in query \ + and len(query['versionId']) == 1: + result[version_property] = query['versionId'][0] + + return result + + raise ValueError("URL given to the parse method is not a valid S3 url " + "{0}".format(url)) + + +def upload_local_artifacts(resource_id, resource_dict, property_name, + parent_dir, uploader): + """ + Upload local artifacts referenced by the property at given resource and + return S3 URL of the uploaded object. It is the responsibility of callers + to ensure property value is a valid string + + If path refers to a file, this method will upload the file. If path refers + to a folder, this method will zip the folder and upload the zip to S3. + If path is omitted, this method will zip the current working folder and + upload. + + If path is already a path to S3 object, this method does nothing. + + :param resource_id: Id of the CloudFormation resource + :param resource_dict: Dictionary containing resource definition + :param property_name: Property name of CloudFormation resource where this + local path is present + :param parent_dir: Resolve all relative paths with respect to this + directory + :param uploader: Method to upload files to S3 + + :return: S3 URL of the uploaded object + :raise: ValueError if path is not a S3 URL or a local path + """ + + local_path = resource_dict.get(property_name, None) + + if local_path is None: + # Build the root directory and upload to S3 + local_path = parent_dir + + if is_s3_url(local_path): + # A valid CloudFormation template will specify artifacts as S3 URLs. + # This check is supporting the case where your resource does not + # refer to local artifacts + # Nothing to do if property value is an S3 URL + LOG.debug("Property {0} of {1} is already a S3 URL" + .format(property_name, resource_id)) + return local_path + + local_path = make_abs_path(parent_dir, local_path) + + # Or, pointing to a folder. Zip the folder and upload + if is_local_folder(local_path): + return zip_and_upload(local_path, uploader) + + # Path could be pointing to a file. Upload the file + elif is_local_file(local_path): + return uploader.upload_with_dedup(local_path) + + raise exceptions.InvalidLocalPathError( + resource_id=resource_id, + property_name=property_name, + local_path=local_path) + + +def zip_and_upload(local_path, uploader): + with zip_folder(local_path) as zipfile: + return uploader.upload_with_dedup(zipfile) + + +@contextmanager +def zip_folder(folder_path): + """ + Zip the entire folder and return a file to the zip. Use this inside + a "with" statement to cleanup the zipfile after it is used. + + :param folder_path: + :return: Name of the zipfile + """ + + filename = os.path.join( + tempfile.gettempdir(), "data-" + uuid.uuid4().hex) + + zipfile_name = make_zip(filename, folder_path) + try: + yield zipfile_name + finally: + if os.path.exists(zipfile_name): + os.remove(zipfile_name) + + +def make_zip(filename, source_root): + zipfile_name = "{0}.zip".format(filename) + source_root = os.path.abspath(source_root) + with open(zipfile_name, 'wb') as f: + zip_file = zipfile.ZipFile(f, 'w', zipfile.ZIP_DEFLATED) + with contextlib.closing(zip_file) as zf: + for root, dirs, files in os.walk(source_root): + for filename in files: + full_path = os.path.join(root, filename) + relative_path = os.path.relpath( + full_path, source_root) + zf.write(full_path, relative_path) + + return zipfile_name + + +@contextmanager +def mktempfile(): + directory = tempfile.gettempdir() + filename = os.path.join(directory, uuid.uuid4().hex) + + try: + with open(filename, "w+") as handle: + yield handle + finally: + if os.path.exists(filename): + os.remove(filename) + + +class Resource(object): + """ + Base class representing a CloudFormation resource that can be exported + """ + + PROPERTY_NAME = None + PACKAGE_NULL_PROPERTY = True + + def __init__(self, uploader): + self.uploader = uploader + + def export(self, resource_id, resource_dict, parent_dir): + if resource_dict is None: + return + + property_value = resource_dict.get(self.PROPERTY_NAME, None) + + if not property_value and not self.PACKAGE_NULL_PROPERTY: + return + + if isinstance(property_value, dict): + LOG.debug("Property {0} of {1} resource is not a URL" + .format(self.PROPERTY_NAME, resource_id)) + return + + try: + self.do_export(resource_id, resource_dict, parent_dir) + + except Exception as ex: + LOG.debug("Unable to export", exc_info=ex) + raise exceptions.ExportFailedError( + resource_id=resource_id, + property_name=self.PROPERTY_NAME, + property_value=property_value, + ex=ex) + + def do_export(self, resource_id, resource_dict, parent_dir): + """ + Default export action is to upload artifacts and set the property to + S3 URL of the uploaded object + """ + resource_dict[self.PROPERTY_NAME] = \ + upload_local_artifacts(resource_id, resource_dict, + self.PROPERTY_NAME, + parent_dir, self.uploader) + + +class ResourceWithS3UrlDict(Resource): + """ + Represents CloudFormation resources that need the S3 URL to be specified as + an dict like {Bucket: "", Key: "", Version: ""} + """ + + BUCKET_NAME_PROPERTY = None + OBJECT_KEY_PROPERTY = None + VERSION_PROPERTY = None + + def __init__(self, uploader): + super(ResourceWithS3UrlDict, self).__init__(uploader) + + def do_export(self, resource_id, resource_dict, parent_dir): + """ + Upload to S3 and set property to an dict representing the S3 url + of the uploaded object + """ + + artifact_s3_url = \ + upload_local_artifacts(resource_id, resource_dict, + self.PROPERTY_NAME, + parent_dir, self.uploader) + + resource_dict[self.PROPERTY_NAME] = parse_s3_url( + artifact_s3_url, + bucket_name_property=self.BUCKET_NAME_PROPERTY, + object_key_property=self.OBJECT_KEY_PROPERTY, + version_property=self.VERSION_PROPERTY) + + +class ServerlessFunctionResource(Resource): + PROPERTY_NAME = "CodeUri" + + +class ServerlessApiResource(Resource): + PROPERTY_NAME = "DefinitionUri" + + +class LambdaFunctionResource(ResourceWithS3UrlDict): + PROPERTY_NAME = "Code" + BUCKET_NAME_PROPERTY = "S3Bucket" + OBJECT_KEY_PROPERTY = "S3Key" + VERSION_PROPERTY = "S3ObjectVersion" + + +class ApiGatewayRestApiResource(ResourceWithS3UrlDict): + PROPERTY_NAME = "BodyS3Location" + PACKAGE_NULL_PROPERTY = False + BUCKET_NAME_PROPERTY = "Bucket" + OBJECT_KEY_PROPERTY = "Key" + VERSION_PROPERTY = "Version" + + +class ElasticBeanstalkApplicationVersion(ResourceWithS3UrlDict): + PROPERTY_NAME = "SourceBundle" + BUCKET_NAME_PROPERTY = "S3Bucket" + OBJECT_KEY_PROPERTY = "S3Key" + VERSION_PROPERTY = None + + +class CloudFormationStackResource(Resource): + """ + Represents CloudFormation::Stack resource that can refer to a nested + stack template via TemplateURL property. + """ + PROPERTY_NAME = "TemplateURL" + + def __init__(self, uploader): + super(CloudFormationStackResource, self).__init__(uploader) + + def do_export(self, resource_id, resource_dict, parent_dir): + """ + If the nested stack template is valid, this method will + export on the nested template, upload the exported template to S3 + and set property to URL of the uploaded S3 template + """ + + template_path = resource_dict.get(self.PROPERTY_NAME, None) + + if template_path is None or is_s3_url(template_path): + # Nothing to do + return + + abs_template_path = make_abs_path(parent_dir, template_path) + if not is_local_file(abs_template_path): + raise exceptions.InvalidTemplateUrlParameterError( + property_name=self.PROPERTY_NAME, + resource_id=resource_id, + template_path=abs_template_path) + + exported_template_dict = \ + Template(template_path, parent_dir, self.uploader).export() + + exported_template_str = yaml_dump(exported_template_dict) + + with mktempfile() as temporary_file: + temporary_file.write(exported_template_str) + temporary_file.flush() + + url = self.uploader.upload_with_dedup( + temporary_file.name, "template") + + # TemplateUrl property requires S3 URL to be in path-style format + parts = parse_s3_url(url, version_property="Version") + resource_dict[self.PROPERTY_NAME] = self.uploader.to_path_style_s3_url( + parts["Key"], parts.get("Version", None)) + + +EXPORT_DICT = { + "AWS::Serverless::Function": ServerlessFunctionResource, + "AWS::Serverless::Api": ServerlessApiResource, + "AWS::ApiGateway::RestApi": ApiGatewayRestApiResource, + "AWS::Lambda::Function": LambdaFunctionResource, + "AWS::ElasticBeanstalk::ApplicationVersion": + ElasticBeanstalkApplicationVersion, + "AWS::CloudFormation::Stack": CloudFormationStackResource +} + + +class Template(object): + """ + Class to export a CloudFormation template + """ + + def __init__(self, template_path, parent_dir, uploader, + resources_to_export=EXPORT_DICT): + """ + Reads the template and makes it ready for export + """ + + if not (is_local_folder(parent_dir) and os.path.isabs(parent_dir)): + raise ValueError("parent_dir parameter must be " + "an absolute path to a folder {0}" + .format(parent_dir)) + + abs_template_path = make_abs_path(parent_dir, template_path) + template_dir = os.path.dirname(abs_template_path) + + with open(abs_template_path, "r") as handle: + template_str = handle.read() + + self.template_dict = yaml_parse(template_str) + self.template_dir = template_dir + self.resources_to_export = resources_to_export + self.uploader = uploader + + def export(self): + """ + Exports the local artifacts referenced by the given template to an + s3 bucket. + + :return: The template with references to artifacts that have been + exported to s3. + """ + if "Resources" not in self.template_dict: + return self.template_dict + + for resource_id, resource in self.template_dict["Resources"].items(): + + resource_type = resource.get("Type", None) + resource_dict = resource.get("Properties", None) + + if resource_type in self.resources_to_export: + # Export code resources + exporter = self.resources_to_export[resource_type]( + self.uploader) + exporter.export(resource_id, resource_dict, self.template_dir) + + return self.template_dict diff -Nru awscli-1.11.13/awscli/customizations/cloudformation/deployer.py awscli-1.11.44/awscli/customizations/cloudformation/deployer.py --- awscli-1.11.13/awscli/customizations/cloudformation/deployer.py 1970-01-01 00:00:00.000000000 +0000 +++ awscli-1.11.44/awscli/customizations/cloudformation/deployer.py 2017-01-27 00:22:38.000000000 +0000 @@ -0,0 +1,182 @@ +# Copyright 2012-2015 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 +import time +import logging +import botocore +import collections + +from awscli.customizations.cloudformation import exceptions +from datetime import datetime + +LOG = logging.getLogger(__name__) + +ChangeSetResult = collections.namedtuple( + "ChangeSetResult", ["changeset_id", "changeset_type"]) + + +class Deployer(object): + + def __init__(self, cloudformation_client, + changeset_prefix="awscli-cloudformation-package-deploy-"): + self._client = cloudformation_client + self.changeset_prefix = changeset_prefix + + def has_stack(self, stack_name): + """ + Checks if a CloudFormation stack with given name exists + + :param stack_name: Name or ID of the stack + :return: True if stack exists. False otherwise + """ + try: + resp = self._client.describe_stacks(StackName=stack_name) + if len(resp["Stacks"]) != 1: + return False + + # When you run CreateChangeSet on a a stack that does not exist, + # CloudFormation will create a stack and set it's status + # REVIEW_IN_PROGRESS. However this stack is cannot be manipulated + # by "update" commands. Under this circumstances, we treat like + # this stack does not exist and call CreateChangeSet will + # ChangeSetType set to CREATE and not UPDATE. + stack = resp["Stacks"][0] + return stack["StackStatus"] != "REVIEW_IN_PROGRESS" + + except botocore.exceptions.ClientError as e: + # If a stack does not exist, describe_stacks will throw an + # exception. Unfortunately we don't have a better way than parsing + # the exception msg to understand the nature of this exception. + msg = str(e) + + if "Stack with id {0} does not exist".format(stack_name) in msg: + LOG.debug("Stack with id {0} does not exist".format( + stack_name)) + return False + else: + # We don't know anything about this exception. Don't handle + LOG.debug("Unable to get stack details.", exc_info=e) + raise e + + def create_changeset(self, stack_name, cfn_template, + parameter_values, capabilities): + """ + Call Cloudformation to create a changeset and wait for it to complete + + :param stack_name: Name or ID of stack + :param cfn_template: CloudFormation template string + :param parameter_values: Template parameters object + :param capabilities: Array of capabilities passed to CloudFormation + :return: + """ + + now = datetime.utcnow().isoformat() + description = "Created by AWS CLI at {0} UTC".format(now) + + # Each changeset will get a unique name based on time + changeset_name = self.changeset_prefix + str(int(time.time())) + + changeset_type = "UPDATE" + if not self.has_stack(stack_name): + changeset_type = "CREATE" + + try: + resp = self._client.create_change_set( + ChangeSetName=changeset_name, + StackName=stack_name, + TemplateBody=cfn_template, + ChangeSetType=changeset_type, + Parameters=parameter_values, + Capabilities=capabilities, + Description=description + ) + return ChangeSetResult(resp["Id"], changeset_type) + except Exception as ex: + LOG.debug("Unable to create changeset", exc_info=ex) + raise ex + + def wait_for_changeset(self, changeset_id, stack_name): + """ + Waits until the changeset creation completes + + :param changeset_id: ID or name of the changeset + :param stack_name: Stack name + :return: Latest status of the create-change-set operation + """ + sys.stdout.write("Waiting for changeset to be created..\n") + sys.stdout.flush() + + # Wait for changeset to be created + waiter = self._client.get_waiter("change_set_create_complete") + # Poll every 10 seconds. Changeset creation should be fast + waiter.config.delay = 10 + try: + waiter.wait(ChangeSetName=changeset_id, StackName=stack_name) + except botocore.exceptions.WaiterError as ex: + LOG.debug("Create changeset waiter exception", exc_info=ex) + + resp = ex.last_response + status = resp["Status"] + reason = resp["StatusReason"] + + if status == "FAILED" and \ + "No updates are to be performed" in reason: + raise exceptions.ChangeEmptyError(stack_name=stack_name) + + raise RuntimeError("Failed to create the changeset: {0} " + "Status: {1}. Reason: {2}" + .format(ex, status, reason)) + + def execute_changeset(self, changeset_id, stack_name): + """ + Calls CloudFormation to execute changeset + + :param changeset_id: ID of the changeset + :param stack_name: Name or ID of the stack + :return: Response from execute-change-set call + """ + return self._client.execute_change_set( + ChangeSetName=changeset_id, + StackName=stack_name) + + def wait_for_execute(self, stack_name, changeset_type): + + sys.stdout.write("Waiting for stack create/update to complete\n") + sys.stdout.flush() + + # Pick the right waiter + if changeset_type == "CREATE": + waiter = self._client.get_waiter("stack_create_complete") + elif changeset_type == "UPDATE": + waiter = self._client.get_waiter("stack_update_complete") + else: + raise RuntimeError("Invalid changeset type {0}" + .format(changeset_type)) + + try: + waiter.wait(StackName=stack_name) + except botocore.exceptions.WaiterError as ex: + LOG.debug("Execute changeset waiter exception", exc_info=ex) + + raise exceptions.DeployFailedError(stack_name=stack_name) + + def create_and_wait_for_changeset(self, stack_name, cfn_template, + parameter_values, capabilities): + + result = self.create_changeset( + stack_name, cfn_template, parameter_values, capabilities) + + self.wait_for_changeset(result.changeset_id, stack_name) + + return result diff -Nru awscli-1.11.13/awscli/customizations/cloudformation/deploy.py awscli-1.11.44/awscli/customizations/cloudformation/deploy.py --- awscli-1.11.13/awscli/customizations/cloudformation/deploy.py 1970-01-01 00:00:00.000000000 +0000 +++ awscli-1.11.44/awscli/customizations/cloudformation/deploy.py 2017-01-27 00:22:38.000000000 +0000 @@ -0,0 +1,232 @@ +# Copyright 2015 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 sys +import logging + +from awscli.customizations.cloudformation import exceptions +from awscli.customizations.cloudformation.deployer import Deployer +from awscli.customizations.cloudformation.yamlhelper import yaml_parse + +from awscli.customizations.commands import BasicCommand + +LOG = logging.getLogger(__name__) + + +class DeployCommand(BasicCommand): + + MSG_NO_EXECUTE_CHANGESET = \ + ("Changeset created successfully. Run the following command to " + "review changes:" + "\n" + "aws cloudformation describe-change-set --change-set-name " + "{changeset_id}" + "\n") + + MSG_EXECUTE_SUCCESS = "Successfully created/updated stack - {stack_name}\n" + + PARAMETER_OVERRIDE_CMD = "parameter-overrides" + + NAME = 'deploy' + DESCRIPTION = BasicCommand.FROM_FILE("cloudformation", + "_deploy_description.rst") + + ARG_TABLE = [ + { + 'name': 'template-file', + 'required': True, + 'help_text': ( + 'The path where your AWS CloudFormation' + ' template is located.' + ) + }, + { + 'name': 'stack-name', + 'action': 'store', + 'required': True, + 'help_text': ( + 'The name of the AWS CloudFormation stack you\'re deploying to.' + ' If you specify an existing stack, the command updates the' + ' stack. If you specify a new stack, the command creates it.' + ) + }, + { + 'name': PARAMETER_OVERRIDE_CMD, + 'action': 'store', + 'required': False, + 'schema': { + 'type': 'array', + 'items': { + 'type': 'string' + } + }, + 'default': [], + 'help_text': ( + 'A list of parameter structures that specify input parameters' + ' for your stack template. If you\'re updating a stack and you' + ' don\'t specify a parameter, the command uses the stack\'s' + ' exisiting value. For new stacks, you must specify' + ' parameters that don\'t have a default value.' + ' Syntax: ParameterKey1=ParameterValue1' + ' ParameterKey2=ParameterValue2 ...' + ) + }, + { + 'name': 'capabilities', + 'action': 'store', + 'required': False, + 'schema': { + 'type': 'array', + 'items': { + 'type': 'string', + 'enum': [ + 'CAPABILITY_IAM', + 'CAPABILITY_NAMED_IAM' + ] + } + }, + 'default': [], + 'help_text': ( + 'A list of capabilities that you must specify before AWS' + ' Cloudformation can create certain stacks. Some stack' + ' templates might include resources that can affect' + ' permissions in your AWS account, for example, by creating' + ' new AWS Identity and Access Management (IAM) users. For' + ' those stacks, you must explicitly acknowledge their' + ' capabilities by specifying this parameter. ' + ' The only valid values are CAPABILITY_IAM and' + ' CAPABILITY_NAMED_IAM. If you have IAM resources, you can' + ' specify either capability. If you have IAM resources with' + ' custom names, you must specify CAPABILITY_NAMED_IAM. If you' + ' don\'t specify this parameter, this action returns an' + ' InsufficientCapabilities error.' + ) + + }, + { + 'name': 'no-execute-changeset', + 'action': 'store_false', + 'dest': 'execute_changeset', + 'required': False, + 'help_text': ( + 'Indicates whether to execute the change set. Specify this' + ' flag if you want to view your stack changes before' + ' executing the change set. The command creates an' + ' AWS CloudFormation change set and then exits without' + ' executing the change set. After you view the change set,' + ' execute it to implement your changes.' + ) + } + ] + + def _run_main(self, parsed_args, parsed_globals): + cloudformation_client = \ + self._session.create_client( + 'cloudformation', region_name=parsed_globals.region, + endpoint_url=parsed_globals.endpoint_url, + verify=parsed_globals.verify_ssl) + + template_path = parsed_args.template_file + if not os.path.isfile(template_path): + raise exceptions.InvalidTemplatePathError( + template_path=template_path) + + # Parse parameters + with open(template_path, "r") as handle: + template_str = handle.read() + + stack_name = parsed_args.stack_name + parameter_overrides = self.parse_parameter_arg( + parsed_args.parameter_overrides) + + template_dict = yaml_parse(template_str) + + parameters = self.merge_parameters(template_dict, parameter_overrides) + + deployer = Deployer(cloudformation_client) + return self.deploy(deployer, stack_name, template_str, + parameters, parsed_args.capabilities, + parsed_args.execute_changeset) + + def deploy(self, deployer, stack_name, template_str, + parameters, capabilities, execute_changeset): + result = deployer.create_and_wait_for_changeset( + stack_name=stack_name, + cfn_template=template_str, + parameter_values=parameters, + capabilities=capabilities) + + if execute_changeset: + deployer.execute_changeset(result.changeset_id, stack_name) + deployer.wait_for_execute(stack_name, result.changeset_type) + sys.stdout.write(self.MSG_EXECUTE_SUCCESS.format( + stack_name=stack_name)) + else: + sys.stdout.write(self.MSG_NO_EXECUTE_CHANGESET.format( + changeset_id=result.changeset_id)) + + sys.stdout.flush() + return 0 + + def merge_parameters(self, template_dict, parameter_overrides): + """ + CloudFormation CreateChangeset requires a value for every parameter + from the template, either specifying a new value or use previous value. + For convenience, this method will accept new parameter values and + generates a dict of all parameters in a format that ChangeSet API + will accept + + :param parameter_overrides: + :return: + """ + parameter_values = [] + + if not isinstance(template_dict.get("Parameters", None), dict): + return parameter_values + + for key, value in template_dict["Parameters"].items(): + + if key not in parameter_overrides and "Default" in value: + # Parameters that have default value and not overridden, should not be + # passed to CloudFormation + continue + + obj = { + "ParameterKey": key + } + + if key in parameter_overrides: + obj["ParameterValue"] = parameter_overrides[key] + else: + obj["UsePreviousValue"] = True + + parameter_values.append(obj) + + return parameter_values + + def parse_parameter_arg(self, parameter_arg): + result = {} + for data in parameter_arg: + + # Split at first '=' from left + key_value_pair = data.split("=", 1) + + if len(key_value_pair) != 2: + raise exceptions.InvalidParameterOverrideArgumentError( + argname=self.PARAMETER_OVERRIDE_CMD, + value=key_value_pair) + + result[key_value_pair[0]] = key_value_pair[1] + + return result diff -Nru awscli-1.11.13/awscli/customizations/cloudformation/exceptions.py awscli-1.11.44/awscli/customizations/cloudformation/exceptions.py --- awscli-1.11.13/awscli/customizations/cloudformation/exceptions.py 1970-01-01 00:00:00.000000000 +0000 +++ awscli-1.11.44/awscli/customizations/cloudformation/exceptions.py 2017-01-27 00:22:38.000000000 +0000 @@ -0,0 +1,55 @@ + +class CloudFormationCommandError(Exception): + fmt = 'An unspecified error occurred' + + def __init__(self, **kwargs): + msg = self.fmt.format(**kwargs) + Exception.__init__(self, msg) + self.kwargs = kwargs + + +class InvalidTemplatePathError(CloudFormationCommandError): + fmt = "Invalid template path {template_path}" + + +class NoSuchBucketError(CloudFormationCommandError): + fmt = ("S3 Bucket does not exist. " + "Execute the command to create a new bucket" + "\n" + "aws s3 mb s3://{bucket_name}") + + +class ChangeEmptyError(CloudFormationCommandError): + fmt = "No changes to deploy. Stack {stack_name} is up to date" + + +class InvalidLocalPathError(CloudFormationCommandError): + fmt = ("Parameter {property_name} of resource {resource_id} refers " + "to a file or folder that does not exist {local_path}") + + +class InvalidTemplateUrlParameterError(CloudFormationCommandError): + fmt = ("{property_name} parameter of {resource_id} resource is invalid. " + "It must be a S3 URL or path to CloudFormation " + "template file. Actual: {template_path}") + + +class ExportFailedError(CloudFormationCommandError): + fmt = ("Unable to upload artifact {property_value} referenced " + "by {property_name} parameter of {resource_id} resource." + "\n" + "{ex}") + + +class InvalidParameterOverrideArgumentError(CloudFormationCommandError): + fmt = ("{value} value passed to --{argname} must be of format " + "ParameterKey=ParameterValue") + + +class DeployFailedError(CloudFormationCommandError): + fmt = \ + ("Failed to create/update the stack. Run the following command" + "\n" + "to fetch the list of events leading up to the failure" + "\n" + "aws cloudformation describe-stack-events --stack-name {stack_name}") diff -Nru awscli-1.11.13/awscli/customizations/cloudformation/__init__.py awscli-1.11.44/awscli/customizations/cloudformation/__init__.py --- awscli-1.11.13/awscli/customizations/cloudformation/__init__.py 1970-01-01 00:00:00.000000000 +0000 +++ awscli-1.11.44/awscli/customizations/cloudformation/__init__.py 2017-01-27 00:22:38.000000000 +0000 @@ -0,0 +1,31 @@ +# Copyright 2012-2015 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. +from awscli.customizations.cloudformation.package import PackageCommand +from awscli.customizations.cloudformation.deploy import DeployCommand + + +def initialize(cli): + """ + The entry point for CloudFormation high level commands. + """ + cli.register('building-command-table.cloudformation', inject_commands) + + +def inject_commands(command_table, session, **kwargs): + """ + Called when the CloudFormation command table is being built. Used to + inject new high level commands into the command list. These high level + commands must not collide with existing low-level API call names. + """ + command_table['package'] = PackageCommand(session) + command_table['deploy'] = DeployCommand(session) diff -Nru awscli-1.11.13/awscli/customizations/cloudformation/package.py awscli-1.11.44/awscli/customizations/cloudformation/package.py --- awscli-1.11.13/awscli/customizations/cloudformation/package.py 1970-01-01 00:00:00.000000000 +0000 +++ awscli-1.11.44/awscli/customizations/cloudformation/package.py 2017-01-27 00:22:38.000000000 +0000 @@ -0,0 +1,152 @@ +# Copyright 2012-2015 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 +import sys + +from botocore.client import Config + +from awscli.customizations.cloudformation.s3uploader import S3Uploader +from awscli.customizations.cloudformation.artifact_exporter import Template +from awscli.customizations.cloudformation.yamlhelper import yaml_dump +from awscli.customizations.cloudformation import exceptions +from awscli.customizations.commands import BasicCommand + +LOG = logging.getLogger(__name__) + + +class PackageCommand(BasicCommand): + + MSG_PACKAGED_TEMPLATE_WRITTEN = ( + "Successfully packaged artifacts and wrote output template " + "to file {output_file_name}." + "\n" + "Execute the following command to deploy the packaged template" + "\n" + "aws cloudformation deploy --template-file {output_file_path} " + "--stack-name " + "\n") + + NAME = "package" + + DESCRIPTION = BasicCommand.FROM_FILE("cloudformation", + "_package_description.rst") + + ARG_TABLE = [ + { + 'name': 'template-file', + 'required': True, + 'help_text': ( + 'The path where your AWS CloudFormation' + ' template is located.' + ) + }, + + { + 'name': 's3-bucket', + 'required': True, + 'help_text': ( + 'The name of the S3 bucket where this command uploads' + ' the artifacts that are referenced in your template.' + ) + }, + + { + 'name': 's3-prefix', + 'help_text': ( + 'A prefix name that the command adds to the' + ' artifacts\' name when it uploads them to the S3 bucket.' + ' The prefix name is a path name (folder name) for' + ' the S3 bucket.' + ) + }, + + { + 'name': 'kms-key-id', + 'help_text': ( + 'The ID of an AWS KMS key that the command uses' + ' to encrypt artifacts that are at rest in the S3 bucket.' + ) + }, + + { + "name": "output-template-file", + "help_text": ( + "The path to the file where the command writes the" + " output AWS CloudFormation template. If you don't specify" + " a path, the command writes the template to the standard" + " output." + ) + }, + + { + "name": "force-upload", + "action": "store_true", + "help_text": ( + 'Indicates whether to override existing files in the S3 bucket.' + ' Specify this flag to upload artifacts even if they ' + ' match existing artifacts in the S3 bucket.' + ) + } + ] + + def _run_main(self, parsed_args, parsed_globals): + s3_client = self._session.create_client( + "s3", + config=Config(signature_version='s3v4'), + region_name=parsed_globals.region, + verify=parsed_globals.verify_ssl) + + template_path = parsed_args.template_file + if not os.path.isfile(template_path): + raise exceptions.InvalidTemplatePathError( + template_path=template_path) + + bucket = parsed_args.s3_bucket + + self.s3_uploader = S3Uploader(s3_client, + bucket, + parsed_globals.region, + parsed_args.s3_prefix, + parsed_args.kms_key_id, + parsed_args.force_upload) + + output_file = parsed_args.output_template_file + exported_str = self._export(template_path) + + sys.stdout.write("\n") + self.write_output(output_file, exported_str) + + if output_file: + msg = self.MSG_PACKAGED_TEMPLATE_WRITTEN.format( + output_file_name=output_file, + output_file_path=os.path.abspath(output_file)) + sys.stdout.write(msg) + + sys.stdout.flush() + return 0 + + def _export(self, template_path): + template = Template(template_path, os.getcwd(), self.s3_uploader) + exported_template = template.export() + exported_str = yaml_dump(exported_template) + return exported_str + + def write_output(self, output_file_name, data): + if output_file_name is None: + sys.stdout.write(data) + return + + with open(output_file_name, "w") as fp: + fp.write(data) diff -Nru awscli-1.11.13/awscli/customizations/cloudformation/s3uploader.py awscli-1.11.44/awscli/customizations/cloudformation/s3uploader.py --- awscli-1.11.13/awscli/customizations/cloudformation/s3uploader.py 1970-01-01 00:00:00.000000000 +0000 +++ awscli-1.11.44/awscli/customizations/cloudformation/s3uploader.py 2017-01-27 00:22:38.000000000 +0000 @@ -0,0 +1,202 @@ +# Copyright 2012-2015 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 hashlib +import logging +import threading +import os +import sys + +import botocore +import botocore.exceptions +from s3transfer.manager import TransferManager +from s3transfer.subscribers import BaseSubscriber + +from awscli.customizations.cloudformation import exceptions + +LOG = logging.getLogger(__name__) + + +class S3Uploader(object): + """ + Class to upload objects to S3 bucket that use versioning. If bucket + does not already use versioning, this class will turn on versioning. + """ + + def __init__(self, s3_client, + bucket_name, + region, + prefix=None, + kms_key_id=None, + force_upload=False, + transfer_manager=None): + self.bucket_name = bucket_name + self.prefix = prefix + self.kms_key_id = kms_key_id or None + self.force_upload = force_upload + self.s3 = s3_client + self.region = region + + self.transfer_manager = transfer_manager + if not transfer_manager: + self.transfer_manager = TransferManager(self.s3) + + def upload(self, file_name, remote_path): + """ + Uploads given file to S3 + :param file_name: Path to the file that will be uploaded + :param remote_path: be uploaded + :return: VersionId of the latest upload + """ + + if self.prefix and len(self.prefix) > 0: + remote_path = "{0}/{1}".format(self.prefix, remote_path) + + # Check if a file with same data exists + if not self.force_upload and self.file_exists(remote_path): + LOG.debug("File with same data is already exists at {0}. " + "Skipping upload".format(remote_path)) + return self.make_url(remote_path) + + try: + + # Default to regular server-side encryption unless customer has + # specified their own KMS keys + additional_args = { + "ServerSideEncryption": "AES256" + } + + if self.kms_key_id: + additional_args["ServerSideEncryption"] = "aws:kms" + additional_args["SSEKMSKeyId"] = self.kms_key_id + + print_progress_callback = \ + ProgressPercentage(file_name, remote_path) + future = self.transfer_manager.upload(file_name, + self.bucket_name, + remote_path, + additional_args, + [print_progress_callback]) + future.result() + + return self.make_url(remote_path) + + except botocore.exceptions.ClientError as ex: + error_code = ex.response["Error"]["Code"] + if error_code == "NoSuchBucket": + raise exceptions.NoSuchBucketError( + bucket_name=self.bucket_name) + raise ex + + def upload_with_dedup(self, file_name, extension=None): + """ + Makes and returns name of the S3 object based on the file's MD5 sum + + :param file_name: file to upload + :param extension: String of file extension to append to the object + :return: S3 URL of the uploaded object + """ + + # This construction of remote_path is critical to preventing duplicate + # uploads of same object. Uploader will check if the file exists in S3 + # and re-upload only if necessary. So the template points to same file + # in multiple places, this will upload only once + + filemd5 = self.file_checksum(file_name) + remote_path = filemd5 + if extension: + remote_path = remote_path + "." + extension + + return self.upload(file_name, remote_path) + + def file_exists(self, remote_path): + """ + Check if the file we are trying to upload already exists in S3 + + :param remote_path: + :return: True, if file exists. False, otherwise + """ + + try: + # Find the object that matches this ETag + self.s3.head_object( + Bucket=self.bucket_name, Key=remote_path) + return True + except botocore.exceptions.ClientError: + # Either File does not exist or we are unable to get + # this information. + return False + + def make_url(self, obj_path): + return "s3://{0}/{1}".format( + self.bucket_name, obj_path) + + def file_checksum(self, file_name): + + with open(file_name, "rb") as file_handle: + md5 = hashlib.md5() + # Read file in chunks of 4096 bytes + block_size = 4096 + + # Save current cursor position and reset cursor to start of file + curpos = file_handle.tell() + file_handle.seek(0) + + buf = file_handle.read(block_size) + while len(buf) > 0: + md5.update(buf) + buf = file_handle.read(block_size) + + # Restore file cursor's position + file_handle.seek(curpos) + + return md5.hexdigest() + + def to_path_style_s3_url(self, key, version=None): + """ + This link describes the format of Path Style URLs + http://docs.aws.amazon.com/AmazonS3/latest/dev/UsingBucket.html#access-bucket-intro + """ + base = "https://s3.amazonaws.com" + if self.region and self.region != "us-east-1": + base = "https://s3-{0}.amazonaws.com".format(self.region) + + result = "{0}/{1}/{2}".format(base, self.bucket_name, key) + if version: + result = "{0}?versionId={1}".format(result, version) + + return result + + +class ProgressPercentage(BaseSubscriber): + # This class was copied directly from S3Transfer docs + + def __init__(self, filename, remote_path): + self._filename = filename + self._remote_path = remote_path + self._size = float(os.path.getsize(filename)) + self._seen_so_far = 0 + self._lock = threading.Lock() + + def on_progress(self, future, bytes_transferred, **kwargs): + + # To simplify we'll assume this is hooked up + # to a single filename. + with self._lock: + self._seen_so_far += bytes_transferred + percentage = (self._seen_so_far / self._size) * 100 + sys.stdout.write( + "\rUploading to %s %s / %s (%.2f%%)" % + (self._remote_path, self._seen_so_far, + self._size, percentage)) + sys.stdout.flush() diff -Nru awscli-1.11.13/awscli/customizations/cloudformation/yamlhelper.py awscli-1.11.44/awscli/customizations/cloudformation/yamlhelper.py --- awscli-1.11.13/awscli/customizations/cloudformation/yamlhelper.py 1970-01-01 00:00:00.000000000 +0000 +++ awscli-1.11.44/awscli/customizations/cloudformation/yamlhelper.py 2017-01-27 00:22:38.000000000 +0000 @@ -0,0 +1,68 @@ +# Copyright 2012-2015 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 yaml +from yaml.resolver import ScalarNode, SequenceNode + + +def intrinsics_multi_constructor(loader, tag_prefix, node): + """ + YAML constructor to parse CloudFormation intrinsics. + This will return a dictionary with key being the instrinsic name + """ + + # Get the actual tag name excluding the first exclamation + tag = node.tag[1:] + + # All CloudFormation intrinsics have prefix Fn:: except Ref + prefix = "Fn::" + if tag == "Ref": + prefix = "" + + cfntag = prefix + tag + + if tag == "GetAtt": + # ShortHand notation for !GetAtt accepts Resource.Attribute format + # while the standard notation is to use an array + # [Resource, Attribute]. Convert shorthand to standard format + value = node.value.split(".", 1) + + elif isinstance(node, ScalarNode): + # Value of this node is scalar + value = loader.construct_scalar(node) + + elif isinstance(node, SequenceNode): + # Value of this node is an array (Ex: [1,2]) + value = loader.construct_sequence(node) + + else: + # Value of this node is an mapping (ex: {foo: bar}) + value = loader.construct_mapping(node) + + return {cfntag: value} + + +def yaml_dump(dict_to_dump): + """ + Dumps the dictionary as a YAML document + :param dict_to_dump: + :return: + """ + return yaml.safe_dump(dict_to_dump, default_flow_style=False) + + +def yaml_parse(yamlstr): + + yaml.SafeLoader.add_multi_constructor("!", intrinsics_multi_constructor) + + return yaml.safe_load(yamlstr) diff -Nru awscli-1.11.13/awscli/customizations/cloudfront.py awscli-1.11.44/awscli/customizations/cloudfront.py --- awscli-1.11.13/awscli/customizations/cloudfront.py 2016-11-03 20:32:27.000000000 +0000 +++ awscli-1.11.44/awscli/customizations/cloudfront.py 2017-01-27 00:22:38.000000000 +0000 @@ -48,7 +48,8 @@ 'default-root-object', CreateDefaultRootObject(argument_table))) context = {} - event_handler.register('top-level-args-parsed', context.update) + event_handler.register( + 'top-level-args-parsed', context.update, unique_id='cloudfront') event_handler.register( 'operation-args-parsed.cloudfront.update-distribution', validate_mutually_exclusive_handler( diff -Nru awscli-1.11.13/awscli/customizations/ec2/runinstances.py awscli-1.11.44/awscli/customizations/ec2/runinstances.py --- awscli-1.11.13/awscli/customizations/ec2/runinstances.py 2016-11-03 20:32:27.000000000 +0000 +++ awscli-1.11.44/awscli/customizations/ec2/runinstances.py 2017-01-27 00:22:38.000000000 +0000 @@ -42,6 +42,7 @@ '[EC2-VPC] If specified a public IP address will be assigned ' 'to the new instance in a VPC.') + def _add_params(argument_table, **kwargs): arg = SecondaryPrivateIpAddressesArgument( name='secondary-private-ip-addresses', @@ -97,28 +98,32 @@ 'AssociatePublicIpAddress' ] if 'NetworkInterfaces' in params: - ni = params['NetworkInterfaces'] - for network_interface_param in network_interface_params: - if network_interface_param in ni[0]: - if 'SubnetId' in params: - ni[0]['SubnetId'] = params['SubnetId'] - del params['SubnetId'] - if 'SecurityGroupIds' in params: - ni[0]['Groups'] = params['SecurityGroupIds'] - del params['SecurityGroupIds'] - if 'PrivateIpAddress' in params: - ip_addr = {'PrivateIpAddress': params['PrivateIpAddress'], - 'Primary': True} - ni[0]['PrivateIpAddresses'] = [ip_addr] - del params['PrivateIpAddress'] - return + interface = params['NetworkInterfaces'][0] + if any(param in interface for param in network_interface_params): + if 'SubnetId' in params: + interface['SubnetId'] = params['SubnetId'] + del params['SubnetId'] + if 'SecurityGroupIds' in params: + interface['Groups'] = params['SecurityGroupIds'] + del params['SecurityGroupIds'] + if 'PrivateIpAddress' in params: + ip_addr = {'PrivateIpAddress': params['PrivateIpAddress'], + 'Primary': True} + interface['PrivateIpAddresses'] = [ip_addr] + del params['PrivateIpAddress'] + if 'Ipv6AddressCount' in params: + interface['Ipv6AddressCount'] = params['Ipv6AddressCount'] + del params['Ipv6AddressCount'] + if 'Ipv6Addresses' in params: + interface['Ipv6Addresses'] = params['Ipv6Addresses'] + del params['Ipv6Addresses'] EVENTS = [ ('building-argument-table.ec2.run-instances', _add_params), ('operation-args-parsed.ec2.run-instances', _check_args), ('before-parameter-build.ec2.RunInstances', _fix_args), - ] +] def register_runinstances(event_handler): @@ -147,11 +152,9 @@ def add_to_params(self, parameters, value): if value: - value = [{'PrivateIpAddress': v, 'Primary': False} for - v in value] - _build_network_interfaces(parameters, - 'PrivateIpAddresses', - value) + value = [{'PrivateIpAddress': v, 'Primary': False} for v in value] + _build_network_interfaces( + parameters, 'PrivateIpAddresses', value) class SecondaryPrivateIpAddressCountArgument(CustomArgument): @@ -162,24 +165,21 @@ def add_to_params(self, parameters, value): if value: - _build_network_interfaces(parameters, - 'SecondaryPrivateIpAddressCount', - value) + _build_network_interfaces( + parameters, 'SecondaryPrivateIpAddressCount', value) class AssociatePublicIpAddressArgument(CustomArgument): def add_to_params(self, parameters, value): if value is True: - _build_network_interfaces(parameters, - 'AssociatePublicIpAddress', - value) + _build_network_interfaces( + parameters, 'AssociatePublicIpAddress', value) class NoAssociatePublicIpAddressArgument(CustomArgument): def add_to_params(self, parameters, value): if value is False: - _build_network_interfaces(parameters, - 'AssociatePublicIpAddress', - value) + _build_network_interfaces( + parameters, 'AssociatePublicIpAddress', value) diff -Nru awscli-1.11.13/awscli/customizations/emr/argumentschema.py awscli-1.11.44/awscli/customizations/emr/argumentschema.py --- awscli-1.11.13/awscli/customizations/emr/argumentschema.py 2016-11-03 20:32:27.000000000 +0000 +++ awscli-1.11.44/awscli/customizations/emr/argumentschema.py 2017-01-27 00:22:38.000000000 +0000 @@ -93,6 +93,149 @@ } } } + }, + "AutoScalingPolicy": { + "type": "object", + "description": "Auto Scaling policy that will be associated with the instance group.", + "properties": { + "Constraints": { + "type": "object", + "description": "The Constraints that will be associated to an Auto Scaling policy.", + "properties": { + "MinCapacity": { + "type": "integer", + "description": "The minimum value for the instances to scale in" + " to in response to scaling activities." + }, + "MaxCapacity": { + "type": "integer", + "description": "The maximum value for the instances to scale out to in response" + " to scaling activities" + } + } + }, + "Rules": { + "type": "array", + "description": "The Rules associated to an Auto Scaling policy.", + "items": { + "type": "object", + "properties": { + "Name": { + "type": "string", + "description": "Name of the Auto Scaling rule." + }, + "Description": { + "type": "string", + "description": "Description of the Auto Scaling rule." + }, + "Action": { + "type": "object", + "description": "The Action associated to an Auto Scaling rule.", + "properties": { + "Market": { # Required for Instance Fleets + "type": "string", + "description": "Market type of the Amazon EC2 instances used to create a " + "cluster node by Auto Scaling action.", + "enum": ["ON_DEMAND", "SPOT"] + }, + "SimpleScalingPolicyConfiguration": { + "type": "object", + "description": "The Simple scaling configuration that will be associated" + "to Auto Scaling action.", + "properties": { + "AdjustmentType": { + "type": "string", + "description": "Specifies how the ScalingAdjustment parameter is " + "interpreted.", + "enum": ["CHANGE_IN_CAPACITY", "PERCENT_CHANGE_IN_CAPACITY", + "EXACT_CAPACITY"] + }, + "ScalingAdjustment": { + "type": "integer", + "description": "The amount by which to scale, based on the " + "specified adjustment type." + }, + "CoolDown": { + "type": "integer", + "description": "The amount of time, in seconds, after a scaling " + "activity completes and before the next scaling " + "activity can start." + } + } + } + } + }, + "Trigger": { + "type": "object", + "description": "The Trigger associated to an Auto Scaling rule.", + "properties": { + "CloudWatchAlarmDefinition": { + "type": "object", + "description": "The Alarm to be registered with CloudWatch, to trigger" + " scaling activities.", + "properties": { + "ComparisonOperator": { + "type": "string", + "description": "The arithmetic operation to use when comparing the" + " specified Statistic and Threshold." + }, + "EvaluationPeriods": { + "type": "integer", + "description": "The number of periods over which data is compared" + " to the specified threshold." + }, + "MetricName": { + "type": "string", + "description": "The name for the alarm's associated metric." + }, + "Namespace": { + "type": "string", + "description": "The namespace for the alarm's associated metric." + }, + "Period": { + "type": "integer", + "description": "The period in seconds over which the specified " + "statistic is applied." + }, + "Statistic": { + "type": "string", + "description": "The statistic to apply to the alarm's associated " + "metric." + }, + "Threshold": { + "type": "double", + "description": "The value against which the specified statistic is " + "compared." + }, + "Unit": { + "type": "string", + "description": "The statistic's unit of measure." + }, + "Dimensions": { + "type": "array", + "description": "The dimensions for the alarm's associated metric.", + "items": { + "type": "object", + "properties": { + "Key": { + "type": "string", + "description": "Dimension Key." + }, + "Value": { + "type": "string", + "description": "Dimension Value." + } + } + } + } + } + } + } + } + } + } + } + } } } } diff -Nru awscli-1.11.13/awscli/customizations/emr/constants.py awscli-1.11.44/awscli/customizations/emr/constants.py --- awscli-1.11.13/awscli/customizations/emr/constants.py 2016-11-03 20:32:27.000000000 +0000 +++ awscli-1.11.44/awscli/customizations/emr/constants.py 2017-01-27 00:22:38.000000000 +0000 @@ -15,10 +15,11 @@ EC2_ROLE_NAME = "EMR_EC2_DefaultRole" EMR_ROLE_NAME = "EMR_DefaultRole" -EC2_ROLE_ARN_PATTERN = ("arn:{{region_suffix}}:iam::aws:policy/service-role/" - "AmazonElasticMapReduceforEC2Role") -EMR_ROLE_ARN_PATTERN = ("arn:{{region_suffix}}:iam::aws:policy/service-role/" - "AmazonElasticMapReduceRole") +EMR_AUTOSCALING_ROLE_NAME = "EMR_AutoScaling_DefaultRole" +ROLE_ARN_PATTERN = "arn:{{region_suffix}}:iam::aws:policy/service-role/{{policy_name}}" +EC2_ROLE_POLICY_NAME = "AmazonElasticMapReduceforEC2Role" +EMR_ROLE_POLICY_NAME = "AmazonElasticMapReduceRole" +EMR_AUTOSCALING_ROLE_POLICY_NAME = "AmazonElasticMapReduceforAutoScalingRole" # Action on failure CONTINUE = 'CONTINUE' @@ -174,7 +175,7 @@ EC2 = 'ec2' EMR = 'elasticmapreduce' - +APPLICATION_AUTOSCALING = 'application-autoscaling' LATEST = 'latest' APPLICATIONS = ["HIVE", "PIG", "HBASE", "GANGLIA", "IMPALA", "SPARK", "MAPR", diff -Nru awscli-1.11.13/awscli/customizations/emr/createcluster.py awscli-1.11.44/awscli/customizations/emr/createcluster.py --- awscli-1.11.13/awscli/customizations/emr/createcluster.py 2016-11-03 20:32:27.000000000 +0000 +++ awscli-1.11.44/awscli/customizations/emr/createcluster.py 2017-01-27 00:22:38.000000000 +0000 @@ -57,6 +57,8 @@ 'help_text': helptext.LOG_URI}, {'name': 'service-role', 'help_text': helptext.SERVICE_ROLE}, + {'name': 'auto-scaling-role', + 'help_text': helptext.AUTOSCALING_ROLE}, {'name': 'use-default-roles', 'action': 'store_true', 'help_text': helptext.USE_DEFAULT_ROLES}, {'name': 'configurations', @@ -69,6 +71,8 @@ 'help_text': helptext.TERMINATION_PROTECTED}, {'name': 'no-termination-protected', 'action': 'store_true', 'group_name': 'termination_protected'}, + {'name': 'scale-down-behavior', + 'help_text': helptext.SCALE_DOWN_BEHAVIOR}, {'name': 'visible-to-all-users', 'action': 'store_true', 'group_name': 'visibility', 'help_text': helptext.VISIBILITY}, @@ -166,6 +170,16 @@ emrutils.apply_dict(params, 'ServiceRole', parsed_args.service_role) + for instance_group in instances_config['InstanceGroups']: + if 'AutoScalingPolicy' in instance_group.keys(): + if parsed_args.auto_scaling_role is None: + raise exceptions.MissingAutoScalingRoleError() + + emrutils.apply_dict(params, 'AutoScalingRole', parsed_args.auto_scaling_role) + + if parsed_args.scale_down_behavior is not None: + emrutils.apply_dict(params, 'ScaleDownBehavior', parsed_args.scale_down_behavior) + if ( parsed_args.no_auto_terminate is False and parsed_args.auto_terminate is False): diff -Nru awscli-1.11.13/awscli/customizations/emr/createdefaultroles.py awscli-1.11.44/awscli/customizations/emr/createdefaultroles.py --- awscli-1.11.13/awscli/customizations/emr/createdefaultroles.py 2016-11-03 20:32:27.000000000 +0000 +++ awscli-1.11.44/awscli/customizations/emr/createdefaultroles.py 2017-01-27 00:22:38.000000000 +0000 @@ -13,8 +13,6 @@ import logging import re - - import botocore.exceptions from botocore import xform_name @@ -24,10 +22,14 @@ from awscli.customizations.emr.command import Command from awscli.customizations.emr.constants import EC2 from awscli.customizations.emr.constants import EC2_ROLE_NAME -from awscli.customizations.emr.constants import EC2_ROLE_ARN_PATTERN +from awscli.customizations.emr.constants import ROLE_ARN_PATTERN from awscli.customizations.emr.constants import EMR from awscli.customizations.emr.constants import EMR_ROLE_NAME -from awscli.customizations.emr.constants import EMR_ROLE_ARN_PATTERN +from awscli.customizations.emr.constants import EMR_AUTOSCALING_ROLE_NAME +from awscli.customizations.emr.constants import APPLICATION_AUTOSCALING +from awscli.customizations.emr.constants import EC2_ROLE_POLICY_NAME +from awscli.customizations.emr.constants import EMR_ROLE_POLICY_NAME +from awscli.customizations.emr.constants import EMR_AUTOSCALING_ROLE_POLICY_NAME from awscli.customizations.emr.exceptions import ResolveServicePrincipalError @@ -48,15 +50,11 @@ } -def get_service_role_policy_arn(region): +def get_role_policy_arn(region, policy_name): region_suffix = _get_policy_arn_suffix(region) - return EMR_ROLE_ARN_PATTERN.replace("{{region_suffix}}", region_suffix) - - -def get_ec2_role_policy_arn(region): - region_suffix = _get_policy_arn_suffix(region) - return EC2_ROLE_ARN_PATTERN.replace("{{region_suffix}}", region_suffix) - + role_arn = ROLE_ARN_PATTERN.replace("{{region_suffix}}", region_suffix) + role_arn = role_arn.replace("{{policy_name}}", policy_name) + return role_arn def _get_policy_arn_suffix(region): region_string = region.lower() @@ -128,10 +126,6 @@ ] def _run_main_command(self, parsed_args, parsed_globals): - ec2_result = None - ec2_policy = None - emr_result = None - emr_policy = None self.iam_endpoint_url = parsed_args.iam_endpoint @@ -146,19 +140,11 @@ LOG.debug('elasticmapreduce endpoint used for resolving' ' service principal: ' + self.emr_endpoint_url) - # Check if the default EC2 Role for EMR exists. - role_name = EC2_ROLE_NAME - if self.check_if_role_exists(role_name, parsed_globals): - LOG.debug('Role ' + role_name + ' exists.') - else: - LOG.debug('Role ' + role_name + ' does not exist.' - ' Creating default role for EC2: ' + role_name) - role_arn = get_ec2_role_policy_arn(self.region) - ec2_result = self._create_role_with_role_policy( - role_name, EC2, role_arn, parsed_globals) - ec2_policy = self._get_role_policy(role_arn, parsed_globals) + # Create default EC2 Role for EMR if it does not exist. + ec2_result, ec2_policy = self._create_role_if_not_exists(parsed_globals, EC2_ROLE_NAME, + EC2_ROLE_POLICY_NAME, [EC2]) - # Check if the default EC2 Instance Profile for EMR exists. + # Create default EC2 Instance Profile for EMR if it does not exist. instance_profile_name = EC2_ROLE_NAME if self.check_if_instance_profile_exists(instance_profile_name, parsed_globals): @@ -171,28 +157,41 @@ instance_profile_name, parsed_globals) - # Check if the default EMR Role exists. - role_name = EMR_ROLE_NAME - if self.check_if_role_exists(role_name, parsed_globals): - LOG.debug('Role ' + role_name + ' exists.') - else: - LOG.debug('Role ' + role_name + ' does not exist.' - ' Creating default role for EMR: ' + role_name) - role_arn = get_service_role_policy_arn(self.region) - emr_result = self._create_role_with_role_policy( - role_name, EMR, role_arn, parsed_globals) - emr_policy = self._get_role_policy(role_arn, parsed_globals) + # Create default EMR Role if it does not exist. + emr_result, emr_policy = self._create_role_if_not_exists(parsed_globals, EMR_ROLE_NAME, + EMR_ROLE_POLICY_NAME, [EMR]) + + # Create default EMR AutoScaling Role if it does not exist. + emr_autoscaling_result, emr_autoscaling_policy = \ + self._create_role_if_not_exists(parsed_globals, EMR_AUTOSCALING_ROLE_NAME, + EMR_AUTOSCALING_ROLE_POLICY_NAME, [EMR, APPLICATION_AUTOSCALING]) configutils.update_roles(self._session) emrutils.display_response( self._session, 'create_role', self._construct_result(ec2_result, ec2_policy, - emr_result, emr_policy), + emr_result, emr_policy, + emr_autoscaling_result, emr_autoscaling_policy), parsed_globals) return 0 + def _create_role_if_not_exists(self, parsed_globals, role_name, policy_name, service_names): + result = None + policy = None + + if self.check_if_role_exists(role_name, parsed_globals): + LOG.debug('Role ' + role_name + ' exists.') + else: + LOG.debug('Role ' + role_name + ' does not exist.' + ' Creating default role: ' + role_name) + role_arn = get_role_policy_arn(self.region, policy_name) + result = self._create_role_with_role_policy( + role_name, service_names, role_arn, parsed_globals) + policy = self._get_role_policy(role_arn, parsed_globals) + return result, policy + def _check_for_iam_endpoint(self, region, iam_endpoint): try: self._session.create_client('emr', region) @@ -201,12 +200,15 @@ raise exceptions.UnknownIamEndpointError(region=region) def _construct_result(self, ec2_response, ec2_policy, - emr_response, emr_policy): + emr_response, emr_policy, + emr_autoscaling_response, emr_autoscaling_policy): result = [] self._construct_role_and_role_policy_structure( result, ec2_response, ec2_policy) self._construct_role_and_role_policy_structure( result, emr_response, emr_policy) + self._construct_role_and_role_policy_structure( + result, emr_autoscaling_response, emr_autoscaling_policy) return result def _construct_role_and_role_policy_structure( @@ -217,13 +219,13 @@ def check_if_role_exists(self, role_name, parsed_globals): parameters = {'RoleName': role_name} + try: self._call_iam_operation('GetRole', parameters, parsed_globals) except botocore.exceptions.ClientError as e: - role_not_found_msg = \ - 'The role with name %s cannot be found.' % role_name - error_message = e.response.get('Error', {}).get('Message', '') - if role_not_found_msg in error_message: + role_not_found_code = "NoSuchEntity" + error_code = e.response.get('Error', {}).get('Code', '') + if role_not_found_code == error_code: # No role error. return False else: @@ -239,10 +241,9 @@ self._call_iam_operation('GetInstanceProfile', parameters, parsed_globals) except botocore.exceptions.ClientError as e: - profile_not_found_msg = \ - 'Instance Profile %s cannot be found.' % instance_profile_name - error_message = e.response.get('Error', {}).get('Message') - if profile_not_found_msg in error_message: + profile_not_found_code = 'NoSuchEntity' + error_code = e.response.get('Error', {}).get('Code') + if profile_not_found_code == error_code: # No instance profile error. return False else: @@ -263,9 +264,15 @@ return policy_version_details["PolicyVersion"]["Document"] def _create_role_with_role_policy( - self, role_name, service_name, role_arn, parsed_globals): - service_principal = get_service_principal(service_name, - self.emr_endpoint_url) + self, role_name, service_names, role_arn, parsed_globals): + + if len(service_names) == 1: + service_principal = get_service_principal(service_names[0], self.emr_endpoint_url) + else: + service_principal = [] + for service in service_names: + service_principal.append(get_service_principal(service, self.emr_endpoint_url)) + LOG.debug(service_principal) parameters = {'RoleName': role_name} diff -Nru awscli-1.11.13/awscli/customizations/emr/exceptions.py awscli-1.11.44/awscli/customizations/emr/exceptions.py --- awscli-1.11.13/awscli/customizations/emr/exceptions.py 2016-11-03 20:32:27.000000000 +0000 +++ awscli-1.11.44/awscli/customizations/emr/exceptions.py 2017-01-27 00:22:38.000000000 +0000 @@ -334,3 +334,8 @@ fmt = ("aws: error: {command} is not supported with " "'{release_label}' release.") + +class MissingAutoScalingRoleError(EmrError): + + fmt = ("aws: error: Must specify --auto-scaling-role when configuring an " + "AutoScaling policy for an instance group.") diff -Nru awscli-1.11.13/awscli/customizations/emr/helptext.py awscli-1.11.44/awscli/customizations/emr/helptext.py --- awscli-1.11.13/awscli/customizations/emr/helptext.py 2016-11-03 20:32:27.000000000 +0000 +++ awscli-1.11.44/awscli/customizations/emr/helptext.py 2017-01-27 00:22:38.000000000 +0000 @@ -57,6 +57,10 @@ 'This command will also create the default EC2 instance profile ' '' + EC2_ROLE_NAME + '.') +AUTOSCALING_ROLE = ( + '

Allows EMR to call other service such as AnyScale and CloudWatch on your behalf.

' +) + USE_DEFAULT_ROLES = ( '

Uses --service-role=' + EMR_ROLE_NAME + ', and ' '--ec2-attributes InstanceProfile=' + EC2_ROLE_NAME + '' @@ -112,12 +116,19 @@ ' of Amazon EC2 instances to create instance groups in a cluster.

' '

Each instance group takes the following parameters: ' '[Name], InstanceGroupType, InstanceType, InstanceCount,' - ' [BidPrice], [EbsConfiguration]. [EbsConfiguration] is optional.' - ' EbsConfiguration takes the following parameters: EbsOptimized' + ' [BidPrice], [EbsConfiguration], [AutoScalingPolicy]. [EbsConfiguration] and [AutoScalingPolicy]' + ' are optional. EbsConfiguration takes the following parameters: EbsOptimized' ' and EbsBlockDeviceConfigs. EbsBlockDeviceConfigs is an array of EBS volume' ' specifications, which takes the following parameters : ([VolumeType], ' ' [SizeInGB], Iops) and VolumesPerInstance which is the count of EBS volumes' - ' per instance with this specification.

') + ' per instance with this specification.

' + '

AutoScalingPolicy takes the following parameters: Constraints and Rules.' + ' Constraints takes the following parameters: MinCapacity, MaxCapacity. Rules is a list of AutoScaling' + ' rules associated to the policy. Each rule has the following parameters: Name, [Description], Action, ' + ' Trigger. Action takes the following parameters: Market, SimpleScalingPolicyConfiguration' + ' (AdjustmentType, ScalingAdjustment). Trigger takes CloudWatchAlarmDefinition(AlarmNamePrefix,' + ' ComparisonOperator, EvaluationPeriods, MetricName, Namespace, Period, Statistic, Threshold, Unit,' + ' [Dimensions]).

') INSTANCE_TYPE = ( '

Shortcut option for --instance-groups. A specification of the ' @@ -179,6 +190,12 @@ 'user intervention, or in the event of an error. Termination protection ' 'is off by default.

') +SCALE_DOWN_BEHAVIOR = ( + '

Specifies the Scale down behavior for the cluster.

' + '

The valid values are:' + '

  • TERMINATE_AT_TASK_COMPLETION
  • ' + '
  • TERMINATE_AT_INSTANCE_HOUR
  • ' +) VISIBILITY = ( '

    Specifies whether the cluster is visible to all IAM users of' ' the AWS account associated with the cluster. If set to ' diff -Nru awscli-1.11.13/awscli/customizations/emr/instancegroupsutils.py awscli-1.11.44/awscli/customizations/emr/instancegroupsutils.py --- awscli-1.11.13/awscli/customizations/emr/instancegroupsutils.py 2016-11-03 20:32:27.000000000 +0000 +++ awscli-1.11.44/awscli/customizations/emr/instancegroupsutils.py 2017-01-27 00:22:38.000000000 +0000 @@ -41,6 +41,10 @@ ig_config['Market'] = constants.ON_DEMAND if 'EbsConfiguration' in keys: ig_config['EbsConfiguration'] = instance_group['EbsConfiguration'] + + if 'AutoScalingPolicy' in keys: + ig_config['AutoScalingPolicy'] = instance_group['AutoScalingPolicy'] + instance_groups.append(ig_config) return instance_groups diff -Nru awscli-1.11.13/awscli/customizations/generatecliskeleton.py awscli-1.11.44/awscli/customizations/generatecliskeleton.py --- awscli-1.11.13/awscli/customizations/generatecliskeleton.py 2016-11-03 20:32:27.000000000 +0000 +++ awscli-1.11.44/awscli/customizations/generatecliskeleton.py 2017-01-27 00:22:38.000000000 +0000 @@ -13,9 +13,13 @@ import json import sys +from botocore import xform_name +from botocore.stub import Stubber from botocore.utils import ArgumentGenerator +from awscli.clidriver import CLIOperationCaller from awscli.customizations.arguments import OverrideRequiredArgsArgument +from awscli.utils import json_encoder def register_generate_cli_skeleton(cli): @@ -36,18 +40,21 @@ The argument, if present in the command line, will prevent the intended command from taking place. Instead, it will generate a JSON skeleton and - print it to standard output. This JSON skeleton then can be filled out - and can be used as input to ``--input-cli-json`` in order to run the - command with the filled out JSON skeleton. + print it to standard output. """ ARG_DATA = { 'name': 'generate-cli-skeleton', - 'help_text': 'Prints a sample input JSON to standard output. Note the ' - 'specified operation is not run if this argument is ' - 'specified. The sample input can be used as an argument ' - 'for ``--cli-input-json``.', - 'action': 'store_true', - 'group_name': 'generate_cli_skeleton' + 'help_text': ( + 'Prints a JSON skeleton to standard output without sending ' + 'an API request. If provided with no value or the value ' + '``input``, prints a sample input JSON that can be used as an ' + 'argument for ``--cli-input-json``. If provided with the value ' + '``output``, it validates the command inputs and returns a ' + 'sample output JSON for that command.' + ), + 'nargs': '?', + 'const': 'input', + 'choices': ['input', 'output'], } def __init__(self, session, operation_model): @@ -59,29 +66,70 @@ 'calling-command.*', self.generate_json_skeleton) super(GenerateCliSkeletonArgument, self)._register_argument_action() + def override_required_args(self, argument_table, args, **kwargs): + arg_name = '--' + self.name + if arg_name in args: + arg_location = args.index(arg_name) + try: + # If the value of --generate-cli-skeleton is ``output``, + # do not force required arguments to be optional as + # ``--generate-cli-skeleton output`` validates commands + # as well as print out the sample output. + if args[arg_location + 1] == 'output': + return + except IndexError: + pass + super(GenerateCliSkeletonArgument, self).override_required_args( + argument_table, args, **kwargs) + def generate_json_skeleton(self, call_parameters, parsed_args, parsed_globals, **kwargs): - - # Only perform the method if the ``--generate-cli-skeleton`` was - # included in the command line. - if getattr(parsed_args, 'generate_cli_skeleton', False): - - # Obtain the model of the operation + if getattr(parsed_args, 'generate_cli_skeleton', None): + for_output = parsed_args.generate_cli_skeleton == 'output' operation_model = self._operation_model - # Generate the skeleton based on the ``input_shape``. - argument_generator = ArgumentGenerator() - operation_input_shape = operation_model.input_shape - # If the ``input_shape`` is ``None``, generate an empty - # dictionary. - if operation_input_shape is None: - skeleton = {} + if for_output: + service_name = operation_model.service_model.service_name + operation_name = operation_model.name + # TODO: It would be better to abstract this logic into + # classes for both the input and output option such that + # a similar set of inputs are taken in and output + # similar functionality. + return StubbedCLIOperationCaller(self._session).invoke( + service_name, operation_name, call_parameters, + parsed_globals) else: - skeleton = argument_generator.generate_skeleton( - operation_input_shape) + argument_generator = ArgumentGenerator() + operation_input_shape = operation_model.input_shape + if operation_input_shape is None: + skeleton = {} + else: + skeleton = argument_generator.generate_skeleton( + operation_input_shape) + + sys.stdout.write( + json.dumps(skeleton, indent=4, default=json_encoder) + ) + sys.stdout.write('\n') + return 0 - # Write the generated skeleton to standard output. - sys.stdout.write(json.dumps(skeleton, indent=4)) - sys.stdout.write('\n') - # This is the return code - return 0 + +class StubbedCLIOperationCaller(CLIOperationCaller): + """A stubbed CLIOperationCaller + + It generates a fake response and uses the response and provided parameters + to make a stubbed client call for an operation command. + """ + def _make_client_call(self, client, operation_name, parameters, + parsed_globals): + method_name = xform_name(operation_name) + operation_model = client.meta.service_model.operation_model( + operation_name) + fake_response = {} + if operation_model.output_shape: + argument_generator = ArgumentGenerator(use_member_names=True) + fake_response = argument_generator.generate_skeleton( + operation_model.output_shape) + with Stubber(client) as stubber: + stubber.add_response(method_name, fake_response) + return getattr(client, method_name)(**parameters) diff -Nru awscli-1.11.13/awscli/customizations/globalargs.py awscli-1.11.44/awscli/customizations/globalargs.py --- awscli-1.11.13/awscli/customizations/globalargs.py 2016-11-03 20:32:27.000000000 +0000 +++ awscli-1.11.44/awscli/customizations/globalargs.py 2017-01-27 00:22:38.000000000 +0000 @@ -22,11 +22,16 @@ def register_parse_global_args(cli): - cli.register('top-level-args-parsed', resolve_types) - cli.register('top-level-args-parsed', no_sign_request) - cli.register('top-level-args-parsed', resolve_verify_ssl) - cli.register('top-level-args-parsed', resolve_cli_read_timeout) - cli.register('top-level-args-parsed', resolve_cli_connect_timeout) + cli.register('top-level-args-parsed', resolve_types, + unique_id='resolve-types') + cli.register('top-level-args-parsed', no_sign_request, + unique_id='no-sign') + cli.register('top-level-args-parsed', resolve_verify_ssl, + unique_id='resolve-verify-ssl') + cli.register('top-level-args-parsed', resolve_cli_read_timeout, + unique_id='resolve-cli-read-timeout') + cli.register('top-level-args-parsed', resolve_cli_connect_timeout, + unique_id='resolve-cli-connect-timeout') def resolve_types(parsed_args, **kwargs): @@ -80,7 +85,8 @@ if not parsed_args.sign_request: # In order to make signing disabled for all requests # we need to use botocore's ``disable_signing()`` handler. - session.register('choose-signer', disable_signing) + session.register( + 'choose-signer', disable_signing, unique_id='disable-signing') def resolve_cli_connect_timeout(parsed_args, session, **kwargs): diff -Nru awscli-1.11.13/awscli/customizations/opsworkscm.py awscli-1.11.44/awscli/customizations/opsworkscm.py --- awscli-1.11.13/awscli/customizations/opsworkscm.py 1970-01-01 00:00:00.000000000 +0000 +++ awscli-1.11.44/awscli/customizations/opsworkscm.py 2017-01-27 00:22:38.000000000 +0000 @@ -0,0 +1,21 @@ +# 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. +from awscli.customizations.utils import alias_command + + +def register_alias_opsworks_cm(event_emitter): + event_emitter.register('building-command-table.main', alias_opsworks_cm) + + +def alias_opsworks_cm(command_table, **kwargs): + alias_command(command_table, 'opsworkscm', 'opsworks-cm') diff -Nru awscli-1.11.13/awscli/customizations/opsworks.py awscli-1.11.44/awscli/customizations/opsworks.py --- awscli-1.11.13/awscli/customizations/opsworks.py 2016-11-03 20:32:27.000000000 +0000 +++ awscli-1.11.44/awscli/customizations/opsworks.py 2017-01-27 00:22:38.000000000 +0000 @@ -24,7 +24,7 @@ from botocore.exceptions import ClientError -from awscli.compat import shlex_quote, urlopen +from awscli.compat import shlex_quote, urlopen, ensure_text_type from awscli.customizations.commands import BasicCommand from awscli.customizations.utils import create_client_from_parsed_globals @@ -278,7 +278,8 @@ if args.infrastructure_class == 'ec2' and args.local: # make sure the regions match - region = json.loads(urlopen(IDENTITY_URL).read())['region'] + region = json.loads( + ensure_text_type(urlopen(IDENTITY_URL).read()))['region'] if region != self._stack['Region']: raise ValueError( "The stack's and the instance's region must match.") diff -Nru awscli-1.11.13/awscli/customizations/s3/results.py awscli-1.11.44/awscli/customizations/s3/results.py --- awscli-1.11.13/awscli/customizations/s3/results.py 2016-11-03 20:32:27.000000000 +0000 +++ awscli-1.11.44/awscli/customizations/s3/results.py 2017-01-27 00:22:38.000000000 +0000 @@ -10,9 +10,11 @@ # 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. +from __future__ import division import logging import sys import threading +import time from collections import namedtuple from collections import defaultdict @@ -50,7 +52,8 @@ QueuedResult = _create_new_result_cls('QueuedResult', ['total_transfer_size']) ProgressResult = _create_new_result_cls( - 'ProgressResult', ['bytes_transferred', 'total_transfer_size']) + 'ProgressResult', ['bytes_transferred', 'total_transfer_size', + 'timestamp']) SuccessResult = _create_new_result_cls('SuccessResult') @@ -97,7 +100,8 @@ def on_progress(self, future, bytes_transferred, **kwargs): result_kwargs = self._result_kwargs_cache[future.meta.transfer_id] progress_result = ProgressResult( - bytes_transferred=bytes_transferred, **result_kwargs) + bytes_transferred=bytes_transferred, timestamp=time.time(), + **result_kwargs) self._result_queue.put(progress_result) def _on_success(self, future): @@ -208,6 +212,9 @@ self.expected_files_transferred = 0 self.final_expected_files_transferred = None + self.start_time = None + self.bytes_transfer_speed = 0 + self._ongoing_progress = defaultdict(int) self._ongoing_total_sizes = {} @@ -253,6 +260,8 @@ pass def _record_queued_result(self, result, **kwargs): + if self.start_time is None: + self.start_time = time.time() total_transfer_size = result.total_transfer_size self._ongoing_total_sizes[ self._get_ongoing_dict_key(result)] = total_transfer_size @@ -268,6 +277,16 @@ self._ongoing_progress[ self._get_ongoing_dict_key(result)] += bytes_transferred self.bytes_transferred += bytes_transferred + # Since the start time is captured in the result recorder and + # capture timestamps in the subscriber, there is a chance that if + # a progress result gets created right after the queued result + # gets created that the timestamp on the progress result is less + # than the timestamp of when the result processor actually + # processes that initial queued result. So this will avoid + # negative progress being displayed or zero divison occuring. + if result.timestamp > self.start_time: + self.bytes_transfer_speed = self.bytes_transferred / ( + result.timestamp - self.start_time) def _update_ongoing_transfer_size_if_unknown(self, result): # This is a special case when the transfer size was previous not @@ -327,8 +346,8 @@ _ESTIMATED_EXPECTED_TOTAL = "~{expected_total}" _STILL_CALCULATING_TOTALS = " (calculating...)" BYTE_PROGRESS_FORMAT = ( - 'Completed {bytes_completed}/{expected_bytes_completed} with ' - + _FILES_REMAINING + 'Completed {bytes_completed}/{expected_bytes_completed} ' + '({transfer_speed}) with ' + _FILES_REMAINING ) FILE_PROGRESS_FORMAT = ( 'Completed {files_completed} file(s) with ' + _FILES_REMAINING @@ -474,9 +493,12 @@ human_readable_size( self._result_recorder.expected_bytes_transferred)) + transfer_speed = human_readable_size( + self._result_recorder.bytes_transfer_speed) + '/s' progress_statement = self.BYTE_PROGRESS_FORMAT.format( bytes_completed=bytes_completed, expected_bytes_completed=expected_bytes_completed, + transfer_speed=transfer_speed, remaining_files=remaining_files ) else: diff -Nru awscli-1.11.13/awscli/customizations/s3/utils.py awscli-1.11.44/awscli/customizations/s3/utils.py --- awscli-1.11.13/awscli/customizations/s3/utils.py 2016-11-03 20:32:27.000000000 +0000 +++ awscli-1.11.44/awscli/customizations/s3/utils.py 2017-01-27 00:22:38.000000000 +0000 @@ -216,13 +216,13 @@ try: update_time = datetime.fromtimestamp(stats.st_mtime, tzlocal()) - except (ValueError, OSError): + except (ValueError, OSError, OverflowError): # Python's fromtimestamp raises value errors when the timestamp is out # of range of the platform's C localtime() function. This can cause - # issues when syncing from systems with a wide range of valid timestamps - # to systems with a lower range. Some systems support 64-bit timestamps, - # for instance, while others only support 32-bit. We don't want to fail - # in these cases, so instead we pass along none. + # issues when syncing from systems with a wide range of valid + # timestamps to systems with a lower range. Some systems support + # 64-bit timestamps, for instance, while others only support 32-bit. + # We don't want to fail in these cases, so instead we pass along none. update_time = None return stats.st_size, update_time diff -Nru awscli-1.11.13/awscli/customizations/s3endpoint.py awscli-1.11.44/awscli/customizations/s3endpoint.py --- awscli-1.11.13/awscli/customizations/s3endpoint.py 2016-11-03 20:32:27.000000000 +0000 +++ awscli-1.11.44/awscli/customizations/s3endpoint.py 2017-01-27 00:22:38.000000000 +0000 @@ -31,7 +31,8 @@ def register_s3_endpoint(cli): handler = partial(on_top_level_args_parsed, event_handler=cli) - cli.register('top-level-args-parsed', handler) + cli.register( + 'top-level-args-parsed', handler, unique_id='s3-endpoint') def on_top_level_args_parsed(parsed_args, event_handler, **kwargs): diff -Nru awscli-1.11.13/awscli/customizations/scalarparse.py awscli-1.11.44/awscli/customizations/scalarparse.py --- awscli-1.11.13/awscli/customizations/scalarparse.py 2016-11-03 20:32:27.000000000 +0000 +++ awscli-1.11.44/awscli/customizations/scalarparse.py 2017-01-27 00:22:39.000000000 +0000 @@ -27,6 +27,10 @@ in the future. """ +from botocore.utils import parse_timestamp +from botocore.exceptions import ProfileNotFound + + def register_scalar_parser(event_handlers): event_handlers.register_first( 'session-initialized', add_scalar_parsers) @@ -36,13 +40,40 @@ return x +def iso_format(value): + return parse_timestamp(value).isoformat() + + +def add_timestamp_parser(session): + factory = session.get_component('response_parser_factory') + try: + timestamp_format = session.get_scoped_config().get( + 'cli_timestamp_format', + 'none') + except ProfileNotFound: + # If a --profile is provided that does not exist, loading + # a value from get_scoped_config will crash the CLI. + # This function can be called as the first handler for + # the session-initialized event, which happens before a + # profile can be created, even if the command would have + # successfully created a profile. Instead of crashing here + # on a ProfileNotFound the CLI should just use 'none'. + timestamp_format = 'none' + if timestamp_format == 'none': + # For backwards compatibility reasons, we replace botocore's timestamp + # parser (which parses to a datetime.datetime object) with the + # identity function which prints the date exactly the same as it comes + # across the wire. + timestamp_parser = identity + elif timestamp_format == 'iso8601': + timestamp_parser = iso_format + else: + raise ValueError('Unknown cli_timestamp_format value: %s, valid values' + ' are "none" or "iso8601"' % timestamp_format) + factory.set_parser_defaults(timestamp_parser=timestamp_parser) + + def add_scalar_parsers(session, **kwargs): factory = session.get_component('response_parser_factory') - # For backwards compatibility reasons, we replace botocore's timestamp - # parser (which parsers to a datetime.datetime object) with the identity - # function which prints the date exactly the same as it comes across the - # wire. We will eventually add a config option that allows for a user to - # have normalized datetime representation, but we can't change the default. - factory.set_parser_defaults( - blob_parser=identity, - timestamp_parser=identity) + factory.set_parser_defaults(blob_parser=identity) + add_timestamp_parser(session) diff -Nru awscli-1.11.13/awscli/customizations/utils.py awscli-1.11.44/awscli/customizations/utils.py --- awscli-1.11.13/awscli/customizations/utils.py 2016-11-03 20:32:27.000000000 +0000 +++ awscli-1.11.44/awscli/customizations/utils.py 2017-01-27 00:22:38.000000000 +0000 @@ -26,6 +26,14 @@ del argument_table[existing_name] +def _copy_argument(argument_table, current_name, copy_name): + current = argument_table[current_name] + copy_arg = copy.copy(current) + copy_arg.name = copy_name + argument_table[copy_name] = copy_arg + return copy_arg + + def make_hidden_alias(argument_table, existing_name, alias_name): """Create a hidden alias for an existing argument. @@ -39,9 +47,8 @@ """ current = argument_table[existing_name] - copy_arg = copy.copy(current) + copy_arg = _copy_argument(argument_table, existing_name, alias_name) copy_arg._UNDOCUMENTED = True - copy_arg.name = alias_name if current.required: # If the current argument is required, then # we'll mark both as not required, but @@ -50,7 +57,6 @@ copy_arg.required = False current.required = False current._DOCUMENT_AS_REQUIRED = True - argument_table[alias_name] = copy_arg def rename_command(command_table, existing_name, new_name): @@ -60,6 +66,13 @@ del command_table[existing_name] +def alias_command(command_table, existing_name, new_name): + """Moves an argument to a new name, keeping the old as a hidden alias.""" + current = command_table[existing_name] + _copy_argument(command_table, existing_name, new_name) + current._UNDOCUMENTED = True + + def validate_mutually_exclusive_handler(*groups): def _handler(parsed_args, **kwargs): return validate_mutually_exclusive(parsed_args, *groups) diff -Nru awscli-1.11.13/awscli/examples/batch/cancel-job.rst awscli-1.11.44/awscli/examples/batch/cancel-job.rst --- awscli-1.11.13/awscli/examples/batch/cancel-job.rst 1970-01-01 00:00:00.000000000 +0000 +++ awscli-1.11.44/awscli/examples/batch/cancel-job.rst 2017-01-27 00:22:38.000000000 +0000 @@ -0,0 +1,7 @@ +**To cancel a job** + +This example cancels a job with the specified job ID. + +Command:: + + aws batch cancel-job --job-id bcf0b186-a532-4122-842e-2ccab8d54efb --reason "Cancelling job." diff -Nru awscli-1.11.13/awscli/examples/batch/create-compute-environment.rst awscli-1.11.44/awscli/examples/batch/create-compute-environment.rst --- awscli-1.11.13/awscli/examples/batch/create-compute-environment.rst 1970-01-01 00:00:00.000000000 +0000 +++ awscli-1.11.44/awscli/examples/batch/create-compute-environment.rst 2017-01-27 00:22:38.000000000 +0000 @@ -0,0 +1,97 @@ +**To create a managed compute environment with On-Demand instances** + +This example creates a managed compute environment with specific C4 instance types that are launched on demand. The compute environment is called `C4OnDemand`. + +Command:: + + aws batch create-compute-environment --cli-input-json file:///C4OnDemand.json + +JSON file format:: + + { + "computeEnvironmentName": "C4OnDemand", + "type": "MANAGED", + "state": "ENABLED", + "computeResources": { + "type": "EC2", + "minvCpus": 0, + "maxvCpus": 128, + "desiredvCpus": 48, + "instanceTypes": [ + "c4.large", + "c4.xlarge", + "c4.2xlarge", + "c4.4xlarge", + "c4.8xlarge" + ], + "subnets": [ + "subnet-220c0e0a", + "subnet-1a95556d", + "subnet-978f6dce" + ], + "securityGroupIds": [ + "sg-cf5093b2" + ], + "ec2KeyPair": "id_rsa", + "instanceRole": "ecsInstanceRole", + "tags": { + "Name": "Batch Instance - C4OnDemand" + } + }, + "serviceRole": "arn:aws:iam::012345678910:role/AWSBatchServiceRole" + } + +Output:: + + { + "computeEnvironmentName": "C4OnDemand", + "computeEnvironmentArn": "arn:aws:batch:us-east-1:012345678910:compute-environment/C4OnDemand" + } + +**To create a managed compute environment with Spot Instances** + +This example creates a managed compute environment with the M4 instance type that is launched when the Spot bid price is at or below 20% of the On-Demand price for the instance type. The compute environment is called `M4Spot`. + +Command:: + + aws batch create-compute-environment --cli-input-json file:///M4Spot.json + +JSON file format:: + + { + "computeEnvironmentName": "M4Spot", + "type": "MANAGED", + "state": "ENABLED", + "computeResources": { + "type": "SPOT", + "spotIamFleetRole": "arn:aws:iam::012345678910:role/aws-ec2-spot-fleet-role", + "minvCpus": 0, + "maxvCpus": 128, + "desiredvCpus": 4, + "instanceTypes": [ + "m4" + ], + "bidPercentage": 20, + "subnets": [ + "subnet-220c0e0a", + "subnet-1a95556d", + "subnet-978f6dce" + ], + "securityGroupIds": [ + "sg-cf5093b2" + ], + "ec2KeyPair": "id_rsa", + "instanceRole": "ecsInstanceRole", + "tags": { + "Name": "Batch Instance - M4Spot" + } + }, + "serviceRole": "arn:aws:iam::012345678910:role/AWSBatchServiceRole" + } + +Output:: + + { + "computeEnvironmentName": "M4Spot", + "computeEnvironmentArn": "arn:aws:batch:us-east-1:012345678910:compute-environment/M4Spot" + } diff -Nru awscli-1.11.13/awscli/examples/batch/create-job-queue.rst awscli-1.11.44/awscli/examples/batch/create-job-queue.rst --- awscli-1.11.13/awscli/examples/batch/create-job-queue.rst 1970-01-01 00:00:00.000000000 +0000 +++ awscli-1.11.44/awscli/examples/batch/create-job-queue.rst 2017-01-27 00:22:38.000000000 +0000 @@ -0,0 +1,61 @@ +**To create a low priority job queue with a single compute environment** + +This example creates a job queue called `LowPriority` that uses the `M4Spot` compute environment. + +Command:: + + aws batch create-job-queue --cli-input-json file:///LowPriority.json + +JSON file format:: + + { + "jobQueueName": "LowPriority", + "state": "ENABLED", + "priority": 10, + "computeEnvironmentOrder": [ + { + "order": 1, + "computeEnvironment": "M4Spot" + } + ] + } + +Output:: + + { + "jobQueueArn": "arn:aws:batch:us-east-1:012345678910:job-queue/LowPriority", + "jobQueueName": "LowPriority" + } + +**To create a high priority job queue with two compute environments** + +This example creates a job queue called `HighPriority` that uses the `C4OnDemand` compute environment with an order of 1 and the `M4Spot` compute environment with an order of 2. The scheduler will attempt to place jobs on the `C4OnDemand` compute environment first. + +Command:: + + aws batch create-job-queue --cli-input-json file:///HighPriority.json + +JSON file format:: + + { + "jobQueueName": "HighPriority", + "state": "ENABLED", + "priority": 1, + "computeEnvironmentOrder": [ + { + "order": 1, + "computeEnvironment": "C4OnDemand" + }, + { + "order": 2, + "computeEnvironment": "M4Spot" + } + ] + } + +Output:: + + { + "jobQueueArn": "arn:aws:batch:us-east-1:012345678910:job-queue/HighPriority", + "jobQueueName": "HighPriority" + } diff -Nru awscli-1.11.13/awscli/examples/batch/delete-compute-environment.rst awscli-1.11.44/awscli/examples/batch/delete-compute-environment.rst --- awscli-1.11.13/awscli/examples/batch/delete-compute-environment.rst 1970-01-01 00:00:00.000000000 +0000 +++ awscli-1.11.44/awscli/examples/batch/delete-compute-environment.rst 2017-01-27 00:22:38.000000000 +0000 @@ -0,0 +1,7 @@ +**To delete a compute environment** + +This example deletes the `P2OnDemand` compute environment. + +Command:: + + aws batch delete-compute-environment --compute-environment P2OnDemand diff -Nru awscli-1.11.13/awscli/examples/batch/delete-job-queue.rst awscli-1.11.44/awscli/examples/batch/delete-job-queue.rst --- awscli-1.11.13/awscli/examples/batch/delete-job-queue.rst 1970-01-01 00:00:00.000000000 +0000 +++ awscli-1.11.44/awscli/examples/batch/delete-job-queue.rst 2017-01-27 00:22:38.000000000 +0000 @@ -0,0 +1,7 @@ +**To delete a job queue** + +This example deletes the GPGPU job queue. + +Command:: + + aws batch delete-job-queue --job-queue GPGPU diff -Nru awscli-1.11.13/awscli/examples/batch/deregister-job-definition.rst awscli-1.11.44/awscli/examples/batch/deregister-job-definition.rst --- awscli-1.11.13/awscli/examples/batch/deregister-job-definition.rst 1970-01-01 00:00:00.000000000 +0000 +++ awscli-1.11.44/awscli/examples/batch/deregister-job-definition.rst 2017-01-27 00:22:38.000000000 +0000 @@ -0,0 +1,8 @@ +**To deregister a job definition** + +This example deregisters a job definition called sleep10. + +Command:: + + aws batch deregister-job-definition --job-definition sleep10 + diff -Nru awscli-1.11.13/awscli/examples/batch/describe-compute-environments.rst awscli-1.11.44/awscli/examples/batch/describe-compute-environments.rst --- awscli-1.11.13/awscli/examples/batch/describe-compute-environments.rst 1970-01-01 00:00:00.000000000 +0000 +++ awscli-1.11.44/awscli/examples/batch/describe-compute-environments.rst 2017-01-27 00:22:38.000000000 +0000 @@ -0,0 +1,46 @@ +**To describe a compute environment** + +This example describes the `P2OnDemand` compute environment. + +Command:: + + aws batch describe-compute-environments --compute-environments P2OnDemand + +Output:: + + { + "computeEnvironments": [ + { + "status": "VALID", + "serviceRole": "arn:aws:iam::012345678910:role/AWSBatchServiceRole", + "computeEnvironmentArn": "arn:aws:batch:us-east-1:012345678910:compute-environment/P2OnDemand", + "computeResources": { + "subnets": [ + "subnet-220c0e0a", + "subnet-1a95556d", + "subnet-978f6dce" + ], + "tags": { + "Name": "Batch Instance - P2OnDemand" + }, + "desiredvCpus": 48, + "minvCpus": 0, + "instanceTypes": [ + "p2" + ], + "securityGroupIds": [ + "sg-cf5093b2" + ], + "instanceRole": "ecsInstanceRole", + "maxvCpus": 128, + "type": "EC2", + "ec2KeyPair": "id_rsa" + }, + "statusReason": "ComputeEnvironment Healthy", + "ecsClusterArn": "arn:aws:ecs:us-east-1:012345678910:cluster/P2OnDemand_Batch_2c06f29d-d1fe-3a49-879d-42394c86effc", + "state": "ENABLED", + "computeEnvironmentName": "P2OnDemand", + "type": "MANAGED" + } + ] + } diff -Nru awscli-1.11.13/awscli/examples/batch/describe-job-definitions.rst awscli-1.11.44/awscli/examples/batch/describe-job-definitions.rst --- awscli-1.11.13/awscli/examples/batch/describe-job-definitions.rst 1970-01-01 00:00:00.000000000 +0000 +++ awscli-1.11.44/awscli/examples/batch/describe-job-definitions.rst 2017-01-27 00:22:38.000000000 +0000 @@ -0,0 +1,35 @@ +**To describe active job definitions** + +This example describes all of your active job definitions. + +Command:: + + aws batch describe-job-definitions --status ACTIVE + +Output:: + + { + "jobDefinitions": [ + { + "status": "ACTIVE", + "jobDefinitionArn": "arn:aws:batch:us-east-1:012345678910:job-definition/sleep60:1", + "containerProperties": { + "mountPoints": [], + "parameters": {}, + "image": "busybox", + "environment": {}, + "vcpus": 1, + "command": [ + "sleep", + "60" + ], + "volumes": [], + "memory": 128, + "ulimits": [] + }, + "type": "container", + "jobDefinitionName": "sleep60", + "revision": 1 + } + ] + } diff -Nru awscli-1.11.13/awscli/examples/batch/describe-job-queues.rst awscli-1.11.44/awscli/examples/batch/describe-job-queues.rst --- awscli-1.11.13/awscli/examples/batch/describe-job-queues.rst 1970-01-01 00:00:00.000000000 +0000 +++ awscli-1.11.44/awscli/examples/batch/describe-job-queues.rst 2017-01-27 00:22:38.000000000 +0000 @@ -0,0 +1,28 @@ +**To describe a job queue** + +This example describes the `HighPriority` job queue. + +Command:: + + aws batch describe-job-queues --job-queues HighPriority + +Output:: + + { + "jobQueues": [ + { + "status": "VALID", + "jobQueueArn": "arn:aws:batch:us-east-1:012345678910:job-queue/HighPriority", + "computeEnvironmentOrder": [ + { + "computeEnvironment": "arn:aws:batch:us-east-1:012345678910:compute-environment/C4OnDemand", + "order": 1 + } + ], + "statusReason": "JobQueue Healthy", + "priority": 1, + "state": "ENABLED", + "jobQueueName": "HighPriority" + } + ] + } diff -Nru awscli-1.11.13/awscli/examples/batch/describe-jobs.rst awscli-1.11.44/awscli/examples/batch/describe-jobs.rst --- awscli-1.11.13/awscli/examples/batch/describe-jobs.rst 1970-01-01 00:00:00.000000000 +0000 +++ awscli-1.11.44/awscli/examples/batch/describe-jobs.rst 2017-01-27 00:22:38.000000000 +0000 @@ -0,0 +1,37 @@ +**To describe a job** + +This example describes a job with the specified job ID. + +Command:: + + aws batch describe-jobs --jobs bcf0b186-a532-4122-842e-2ccab8d54efb + +Output:: + + { + "jobs": [ + { + "status": "SUBMITTED", + "container": { + "mountPoints": [], + "image": "busybox", + "environment": [], + "vcpus": 1, + "command": [ + "sleep", + "60" + ], + "volumes": [], + "memory": 128, + "ulimits": [] + }, + "parameters": {}, + "jobDefinition": "sleep60", + "jobQueue": "arn:aws:batch:us-east-1:012345678910:job-queue/HighPriority", + "jobId": "bcf0b186-a532-4122-842e-2ccab8d54efb", + "dependsOn": [], + "jobName": "example", + "createdAt": 1480483387803 + } + ] + } diff -Nru awscli-1.11.13/awscli/examples/batch/list-jobs.rst awscli-1.11.44/awscli/examples/batch/list-jobs.rst --- awscli-1.11.13/awscli/examples/batch/list-jobs.rst 1970-01-01 00:00:00.000000000 +0000 +++ awscli-1.11.44/awscli/examples/batch/list-jobs.rst 2017-01-27 00:22:38.000000000 +0000 @@ -0,0 +1,39 @@ +**To list running jobs** + +This example lists the running jobs in the `HighPriority` job queue. + +Command:: + + aws batch list-jobs --job-queue HighPriority + +Output:: + + { + "jobSummaryList": [ + { + "jobName": "example", + "jobId": "e66ff5fd-a1ff-4640-b1a2-0b0a142f49bb" + } + ] + } + + +**To list submitted jobs** + +This example lists jobs in the `HighPriority` job queue that are in the `SUBMITTED` job status. + +Command:: + + aws batch list-jobs --job-queue HighPriority --job-status SUBMITTED + +Output:: + + { + "jobSummaryList": [ + { + "jobName": "example", + "jobId": "68f0c163-fbd4-44e6-9fd1-25b14a434786" + } + ] + } + \ No newline at end of file diff -Nru awscli-1.11.13/awscli/examples/batch/register-job-definition.rst awscli-1.11.44/awscli/examples/batch/register-job-definition.rst --- awscli-1.11.13/awscli/examples/batch/register-job-definition.rst 1970-01-01 00:00:00.000000000 +0000 +++ awscli-1.11.44/awscli/examples/batch/register-job-definition.rst 2017-01-27 00:22:38.000000000 +0000 @@ -0,0 +1,15 @@ +**To register a job definition** + +This example registers a job definition for a simple container job. + +Command:: + + aws batch register-job-definition --job-definition-name sleep30 --type container --container-properties '{ "image": "busybox", "vcpus": 1, "memory": 128, "command": [ "sleep", "30"]}' + +Output:: + + { + "jobDefinitionArn": "arn:aws:batch:us-east-1:012345678910:job-definition/sleep30:1", + "jobDefinitionName": "sleep30", + "revision": 1 + } diff -Nru awscli-1.11.13/awscli/examples/batch/submit-job.rst awscli-1.11.44/awscli/examples/batch/submit-job.rst --- awscli-1.11.13/awscli/examples/batch/submit-job.rst 1970-01-01 00:00:00.000000000 +0000 +++ awscli-1.11.44/awscli/examples/batch/submit-job.rst 2017-01-27 00:22:38.000000000 +0000 @@ -0,0 +1,14 @@ +**To submit a job** + +This example submits a simple container job called `example` to the `HighPriority` job queue. + +Command:: + + aws batch submit-job --job-name example --job-queue HighPriority --job-definition sleep60 + +Output:: + + { + "jobName": "example", + "jobId": "876da822-4198-45f2-a252-6cea32512ea8" + } diff -Nru awscli-1.11.13/awscli/examples/batch/terminate-job.rst awscli-1.11.44/awscli/examples/batch/terminate-job.rst --- awscli-1.11.13/awscli/examples/batch/terminate-job.rst 1970-01-01 00:00:00.000000000 +0000 +++ awscli-1.11.44/awscli/examples/batch/terminate-job.rst 2017-01-27 00:22:38.000000000 +0000 @@ -0,0 +1,7 @@ +**To terminate a job** + +This example terminates a job with the specified job ID. + +Command:: + + aws batch terminate-job --job-id 61e743ed-35e4-48da-b2de-5c8333821c84 --reason "Terminating job." diff -Nru awscli-1.11.13/awscli/examples/batch/update-compute-environment.rst awscli-1.11.44/awscli/examples/batch/update-compute-environment.rst --- awscli-1.11.13/awscli/examples/batch/update-compute-environment.rst 1970-01-01 00:00:00.000000000 +0000 +++ awscli-1.11.44/awscli/examples/batch/update-compute-environment.rst 2017-01-27 00:22:38.000000000 +0000 @@ -0,0 +1,14 @@ +**To update a compute environment** + +This example disables the `P2OnDemand` compute environment so it can be deleted. + +Command:: + + aws batch update-compute-environment --compute-environment P2OnDemand --state DISABLED + +Output:: + + { + "computeEnvironmentName": "P2OnDemand", + "computeEnvironmentArn": "arn:aws:batch:us-east-1:012345678910:compute-environment/P2OnDemand" + } diff -Nru awscli-1.11.13/awscli/examples/batch/update-job-queue.rst awscli-1.11.44/awscli/examples/batch/update-job-queue.rst --- awscli-1.11.13/awscli/examples/batch/update-job-queue.rst 1970-01-01 00:00:00.000000000 +0000 +++ awscli-1.11.44/awscli/examples/batch/update-job-queue.rst 2017-01-27 00:22:38.000000000 +0000 @@ -0,0 +1,14 @@ +**To update a job queue** + +This example disables a job queue so that it can be deleted. + +Command:: + + aws batch update-job-queue --job-queue GPGPU --state DISABLE + +Output:: + + { + "jobQueueArn": "arn:aws:batch:us-east-1:012345678910:job-queue/GPGPU", + "jobQueueName": "GPGPU" + } diff -Nru awscli-1.11.13/awscli/examples/cloudformation/create-stack.rst awscli-1.11.44/awscli/examples/cloudformation/create-stack.rst --- awscli-1.11.13/awscli/examples/cloudformation/create-stack.rst 2016-11-03 20:32:27.000000000 +0000 +++ awscli-1.11.44/awscli/examples/cloudformation/create-stack.rst 2017-01-27 00:22:38.000000000 +0000 @@ -2,7 +2,7 @@ The following ``create-stacks`` command creates a stack with the name ``myteststack`` using the ``sampletemplate.json`` template:: - aws cloudformation create-stack --stack-name myteststack --template-body file:////home//local//test//sampletemplate.json + aws cloudformation create-stack --stack-name myteststack --template-body file:////home//local//test//sampletemplate.json --parameters ParameterKey=KeyPairName,ParameterValue=TestKey ParameterKey=SubnetIDs,ParameterValue=SubnetID1\\,SubnetID2 Output:: diff -Nru awscli-1.11.13/awscli/examples/cloudformation/_deploy_description.rst awscli-1.11.44/awscli/examples/cloudformation/_deploy_description.rst --- awscli-1.11.13/awscli/examples/cloudformation/_deploy_description.rst 1970-01-01 00:00:00.000000000 +0000 +++ awscli-1.11.44/awscli/examples/cloudformation/_deploy_description.rst 2017-01-27 00:22:38.000000000 +0000 @@ -0,0 +1,8 @@ +Deploys the specified AWS CloudFormation template by creating and then executing +a change set. The command terminates after AWS CloudFormation executes the +change set. If you want to view the change set before AWS CloudFormation +executes it, use the ``--no-execute-changeset`` flag. + +To update a stack, specify the name of an existing stack. To create a new stack, +specify a new stack name. + diff -Nru awscli-1.11.13/awscli/examples/cloudformation/deploy.rst awscli-1.11.44/awscli/examples/cloudformation/deploy.rst --- awscli-1.11.13/awscli/examples/cloudformation/deploy.rst 1970-01-01 00:00:00.000000000 +0000 +++ awscli-1.11.44/awscli/examples/cloudformation/deploy.rst 2017-01-27 00:22:38.000000000 +0000 @@ -0,0 +1,6 @@ +Following command deploys template named ``template.json`` to a stack named +``my-new-stack``:: + + + aws cloudformation deploy --template-file /path_to_template/template.json --stack-name my-new-stack --parameter-overrides Key1=Value1 Key2=Value2 + diff -Nru awscli-1.11.13/awscli/examples/cloudformation/_package_description.rst awscli-1.11.44/awscli/examples/cloudformation/_package_description.rst --- awscli-1.11.13/awscli/examples/cloudformation/_package_description.rst 1970-01-01 00:00:00.000000000 +0000 +++ awscli-1.11.44/awscli/examples/cloudformation/_package_description.rst 2017-01-27 00:22:38.000000000 +0000 @@ -0,0 +1,43 @@ +Packages the local artifacts (local paths) that your AWS CloudFormation template +references. The command uploads local artifacts, such as source code for an AWS +Lambda function or a Swagger file for an AWS API Gateway REST API, to an S3 +bucket. The command returns a copy of your template, replacing references to +local artifacts with the S3 location where the command uploaded the artifacts. + +Use this command to quickly upload local artifacts that might be required by +your template. After you package your template's artifacts, run the deploy +command to ``deploy`` the returned template. + +This command can upload local artifacts specified by following properties of a resource: + + + - ``BodyS3Location`` property for the ``AWS::ApiGateway::RestApi`` resource + - ``Code`` property for the ``AWS::Lambda::Function`` resource + - ``CodeUri`` property for the ``AWS::Serverless::Function`` resource + - ``DefinitionUri`` property for the ``AWS::Serverless::Api`` resource + - ``SourceBundle`` property for the ``AWS::ElasticBeanstalk::ApplicationVersion`` resource + - ``TemplateURL`` property for the ``AWS::CloudFormation::Stack`` resource + + +To specify a local artifact in your template, specify a path to a local file or folder, +as either an absolute or relative path. The relative path is a location +that is relative to your template's location. + +For example, if your AWS Lambda function source code is in the +``/home/user/code/lambdafunction/`` folder, specify +`` CodeUri: /home/user/code/lambdafunction`` for the +``AWS::Serverless::Function`` resource. The command returns a template and replaces +the local path with the S3 location: ``CodeUri: s3://mybucket/lambdafunction.zip``. + +If you specify a file, the command directly uploads it to the S3 bucket. If you +specify a folder, the command zips the folder and then uploads the .zip file. +For most resources, if you don't specify a path, the command zips and uploads the +current working directory. The exception is ``AWS::ApiGateway::RestApi``; +if you don't specify a ``BodyS3Location``, this command will not upload an artifact to S3. + +Before the command uploads artifacts, it checks if the artifacts are already +present in the S3 bucket to prevent unnecessary uploads. The command uses MD5 +checksums to compare files. If the values match, the command doesn't upload the +artifacts. Use the ``--force flag`` to skip this check and always upload the +artifacts. + diff -Nru awscli-1.11.13/awscli/examples/cloudformation/package.rst awscli-1.11.44/awscli/examples/cloudformation/package.rst --- awscli-1.11.13/awscli/examples/cloudformation/package.rst 1970-01-01 00:00:00.000000000 +0000 +++ awscli-1.11.44/awscli/examples/cloudformation/package.rst 2017-01-27 00:22:38.000000000 +0000 @@ -0,0 +1,6 @@ +Following command exports a template named ``template.json`` by uploading local +artifacts to S3 bucket ``bucket-name`` and writes the exported template to +``packaged-template.json``:: + + aws cloudformation package --template-file /path_to_template/template.json --s3-bucket bucket-name --output-template-file packaged-template.json + diff -Nru awscli-1.11.13/awscli/examples/cloudtrail/get-event-selectors.rst awscli-1.11.44/awscli/examples/cloudtrail/get-event-selectors.rst --- awscli-1.11.13/awscli/examples/cloudtrail/get-event-selectors.rst 1970-01-01 00:00:00.000000000 +0000 +++ awscli-1.11.44/awscli/examples/cloudtrail/get-event-selectors.rst 2017-01-27 00:22:38.000000000 +0000 @@ -0,0 +1,18 @@ +**To view the event selector settings for a trail** + +The following ``get-event-selectors`` command returns the settings for ``Trail1``:: + + aws cloudtrail get-event-selectors --trail-name Trail1 + +Output:: + + { + "EventSelectors": [ + { + "IncludeManagementEvents": true, + "DataResources": [], + "ReadWriteType": "All" + } + ], + "TrailARN": "arn:aws:cloudtrail:us-east-1:123456789012:trail/Trail1" + } diff -Nru awscli-1.11.13/awscli/examples/cloudtrail/put-event-selectors.rst awscli-1.11.44/awscli/examples/cloudtrail/put-event-selectors.rst --- awscli-1.11.13/awscli/examples/cloudtrail/put-event-selectors.rst 1970-01-01 00:00:00.000000000 +0000 +++ awscli-1.11.44/awscli/examples/cloudtrail/put-event-selectors.rst 2017-01-27 00:22:38.000000000 +0000 @@ -0,0 +1,25 @@ +**To configure event selectors for a trail** + +The following ``put-event-selectors`` command configures an event selector for ``Trail1``:: + + aws cloudtrail put-event-selectors --trail-name Trail1 --event-selectors '[{ "ReadWriteType": "All", "IncludeManagementEvents":true, "DataResources": [{ "Type": "AWS::S3::Object", "Values": ["arn:aws:s3:::mybucket/prefix"] }] }]' + +Output:: + + { + "EventSelectors": [ + { + "IncludeManagementEvents": true, + "DataResources": [ + { + "Values": [ + "arn:aws:s3:::mybucket/prefix" + ], + "Type": "AWS::S3::Object" + } + ], + "ReadWriteType": "All" + } + ], + "TrailARN": "arn:aws:cloudtrail:us-east-1:123456789012:trail/Trail1" + } diff -Nru awscli-1.11.13/awscli/examples/codecommit/get-repository.rst awscli-1.11.44/awscli/examples/codecommit/get-repository.rst --- awscli-1.11.13/awscli/examples/codecommit/get-repository.rst 2016-11-03 20:32:27.000000000 +0000 +++ awscli-1.11.44/awscli/examples/codecommit/get-repository.rst 2017-01-27 00:22:38.000000000 +0000 @@ -13,7 +13,7 @@ "creationDate": 1429203623.625, "defaultBranch": "master", "repositoryName": "MyDemoRepo", - "cloneUrlSsh": "ssh://ssh://git-codecommit.us-east-1.amazonaws.com/v1/repos//v1/repos/MyDemoRepo", + "cloneUrlSsh": "ssh://git-codecommit.us-east-1.amazonaws.com/v1/repos/v1/repos/MyDemoRepo", "lastModifiedDate": 1430783812.0869999, "repositoryDescription": "My demonstration repository", "cloneUrlHttp": "https://codecommit.us-east-1.amazonaws.com/v1/repos/MyDemoRepo", @@ -21,4 +21,4 @@ "Arn": "arn:aws:codecommit:us-east-1:80398EXAMPLE:MyDemoRepo "accountId": "111111111111" } - } \ No newline at end of file + } diff -Nru awscli-1.11.13/awscli/examples/configservice/delete-evaluation-results.rst awscli-1.11.44/awscli/examples/configservice/delete-evaluation-results.rst --- awscli-1.11.13/awscli/examples/configservice/delete-evaluation-results.rst 1970-01-01 00:00:00.000000000 +0000 +++ awscli-1.11.44/awscli/examples/configservice/delete-evaluation-results.rst 2017-01-27 00:22:38.000000000 +0000 @@ -0,0 +1,5 @@ +**To manually delete evaluation results** + +The following command deletes the current evaluation results for the AWS managed rule s3-bucket-versioning-enabled:: + + aws configservice delete-evaluation-results --config-rule-name s3-bucket-versioning-enabled \ No newline at end of file diff -Nru awscli-1.11.13/awscli/examples/configservice/start-config-rules-evaluation.rst awscli-1.11.44/awscli/examples/configservice/start-config-rules-evaluation.rst --- awscli-1.11.13/awscli/examples/configservice/start-config-rules-evaluation.rst 1970-01-01 00:00:00.000000000 +0000 +++ awscli-1.11.44/awscli/examples/configservice/start-config-rules-evaluation.rst 2017-01-27 00:22:38.000000000 +0000 @@ -0,0 +1,5 @@ +**To run an on-demand evaluation for AWS Config rules** + +The following command starts an evaluation for two AWS managed rules:: + + aws configservice start-config-rules-evaluation --config-rule-names s3-bucket-versioning-enabled cloudtrail-enabled \ No newline at end of file diff -Nru awscli-1.11.13/awscli/examples/directconnect/describe-tags.rst awscli-1.11.44/awscli/examples/directconnect/describe-tags.rst --- awscli-1.11.13/awscli/examples/directconnect/describe-tags.rst 1970-01-01 00:00:00.000000000 +0000 +++ awscli-1.11.44/awscli/examples/directconnect/describe-tags.rst 2017-01-27 00:22:38.000000000 +0000 @@ -0,0 +1,23 @@ +**To describe tags for your AWS Direct Connect resources** + +The following command describes the tags for the connection ``dxcon-abcabc12``. + +Command:: + + aws directconnect describe-tags --resource-arns arn:aws:directconnect:us-east-1:123456789012:dxcon/dxcon-abcabc12 + +Output:: + + { + "resourceTags": [ + { + "resourceArn": "arn:aws:directconnect:us-east-1:123456789012:dxcon/dxcon-abcabc12", + "tags": [ + { + "value": "VAConnection", + "key": "Name" + } + ] + } + ] + } \ No newline at end of file diff -Nru awscli-1.11.13/awscli/examples/directconnect/tag-resource.rst awscli-1.11.44/awscli/examples/directconnect/tag-resource.rst --- awscli-1.11.13/awscli/examples/directconnect/tag-resource.rst 1970-01-01 00:00:00.000000000 +0000 +++ awscli-1.11.44/awscli/examples/directconnect/tag-resource.rst 2017-01-27 00:22:38.000000000 +0000 @@ -0,0 +1,8 @@ +**To add a tag to an AWS Direct Connect resource** + +The following command adds a tag with a key of ``Name`` and a value of ``VAConnection`` to the connection ``dxcon-abcabc12``. If the command succeeds, no output is returned. + +Command:: + + aws directconnect tag-resource --resource-arn arn:aws:directconnect:us-east-1:123456789012:dxcon/dxcon-abcabc12 --tags "key=Name,value=VAConnection" + diff -Nru awscli-1.11.13/awscli/examples/directconnect/untag-resource.rst awscli-1.11.44/awscli/examples/directconnect/untag-resource.rst --- awscli-1.11.13/awscli/examples/directconnect/untag-resource.rst 1970-01-01 00:00:00.000000000 +0000 +++ awscli-1.11.44/awscli/examples/directconnect/untag-resource.rst 2017-01-27 00:22:38.000000000 +0000 @@ -0,0 +1,8 @@ +**To remove a tag from an AWS Direct Connect resource** + +The following command removes the tag with the key ``Name`` from connection ``dxcon-abcabc12``. If the command succeeds, no output is returned. + +Command:: + + aws directconnect untag-resource --resource-arn arn:aws:directconnect:us-east-1:123456789012:dxcon/dxcon-abcabc12 --tag-keys Name + diff -Nru awscli-1.11.13/awscli/examples/discovery/describe-agents.rst awscli-1.11.44/awscli/examples/discovery/describe-agents.rst --- awscli-1.11.13/awscli/examples/discovery/describe-agents.rst 1970-01-01 00:00:00.000000000 +0000 +++ awscli-1.11.44/awscli/examples/discovery/describe-agents.rst 2017-01-27 00:22:38.000000000 +0000 @@ -0,0 +1,46 @@ +**Describe agents with specified collectionStatus states** + +This example command describes collection agents with collection status of "STARTED" or "STOPPED". + +Command:: + + aws discovery describe-agents --filters name="collectionStatus",values="STARTED","STOPPED",condition="EQUALS" --max-results 3 + +Output:: + + { + "Snapshots": [ + { + "version": "1.0.40.0", + "agentType": "EC2", + "hostName": "ip-172-31-40-234", + "collectionStatus": "STOPPED", + "agentNetworkInfoList": [ + { + "macAddress": "06:b5:97:14:fc:0d", + "ipAddress": "172.31.40.234" + } + ], + "health": "UNKNOWN", + "agentId": "i-003305c02a776e883", + "registeredTime": "2016-12-09T19:05:06Z", + "lastHealthPingTime": "2016-12-09T19:05:10Z" + }, + { + "version": "1.0.40.0", + "agentType": "EC2", + "hostName": "ip-172-31-39-64", + "collectionStatus": "STARTED", + "agentNetworkInfoList": [ + { + "macAddress": "06:a1:0e:c7:b2:73", + "ipAddress": "172.31.39.64" + } + ], + "health": "SHUTDOWN", + "agentId": "i-003a5e5e2b36cf8bd", + "registeredTime": "2016-11-16T16:36:25Z", + "lastHealthPingTime": "2016-11-16T16:47:37Z" + } + ] + } diff -Nru awscli-1.11.13/awscli/examples/discovery/describe-configurations.rst awscli-1.11.44/awscli/examples/discovery/describe-configurations.rst --- awscli-1.11.13/awscli/examples/discovery/describe-configurations.rst 1970-01-01 00:00:00.000000000 +0000 +++ awscli-1.11.44/awscli/examples/discovery/describe-configurations.rst 2017-01-27 00:22:38.000000000 +0000 @@ -0,0 +1,122 @@ +**Describe selected asset configurations** + +This example command describes the configurations of two specified servers. The action detects the type of asset from the configuration ID. Only one type of asset is allowed per command. + +Command:: + + aws discovery describe-configurations --configuration-ids "d-server-099385097ef9fbcfb" "d-server-0c4f2dd1fee22c6c1" + +Output:: + + { + "configurations": [ + { + "server.performance.maxCpuUsagePct": "0.0", + "server.performance.maxDiskReadIOPS": "0.0", + "server.performance.avgCpuUsagePct": "0.0", + "server.type": "EC2", + "server.performance.maxNetworkReadsPerSecondInKB": "0.19140625", + "server.hostName": "ip-172-31-35-152", + "server.configurationId": "d-server-0c4f2dd1fee22c6c1", + "server.tags.hasMoreValues": "false", + "server.performance.minFreeRAMInKB": "1543496.0", + "server.osVersion": "3.14.48-33.39.amzn1.x86_64", + "server.performance.maxDiskReadsPerSecondInKB": "0.0", + "server.applications": "[]", + "server.performance.numDisks": "1", + "server.performance.numCpus": "1", + "server.performance.numCores": "1", + "server.performance.maxDiskWriteIOPS": "0.0", + "server.performance.maxNetworkWritesPerSecondInKB": "0.82421875", + "server.performance.avgDiskWritesPerSecondInKB": "0.0", + "server.networkInterfaceInfo": "[{\"name\":\"eth0\",\"macAddress\":\"06:A7:7D:3F:54:57\",\"ipAddress\":\"172.31.35.152\",\"netMask\":\"255.255.240.0\"},{\"name\":\"lo\",\"macAddress\":\"00:00:00:00:00:00\",\"ipAddress\":\"127.0.0.1\",\"netMask\":\"255.0.0.0\"},{\"name\":\"eth0\",\"macAddress\":\"06:A7:7D:3F:54:57\",\"ipAddress\":\"fe80::4a7:7dff:fe3f:5457\"},{\"name\":\"lo\",\"macAddress\":\"00:00:00:00:00:00\",\"ipAddress\":\"::1\"}]", + "server.performance.avgNetworkReadsPerSecondInKB": "0.04915364583333333", + "server.tags": "[]", + "server.applications.hasMoreValues": "false", + "server.timeOfCreation": "2016-10-28 23:44:00.0", + "server.agentId": "i-4447bc1b", + "server.performance.maxDiskWritesPerSecondInKB": "0.0", + "server.performance.avgDiskReadIOPS": "0.0", + "server.performance.avgFreeRAMInKB": "1547210.1333333333", + "server.performance.avgDiskReadsPerSecondInKB": "0.0", + "server.performance.avgDiskWriteIOPS": "0.0", + "server.performance.numNetworkCards": "2", + "server.hypervisor": "xen", + "server.networkInterfaceInfo.hasMoreValues": "false", + "server.performance.avgNetworkWritesPerSecondInKB": "0.1380859375", + "server.osName": "Linux - Amazon Linux AMI release 2015.03", + "server.performance.totalRAMInKB": "1694732.0", + "server.cpuType": "x64" + }, + { + "server.performance.maxCpuUsagePct": "100.0", + "server.performance.maxDiskReadIOPS": "0.0", + "server.performance.avgCpuUsagePct": "14.733333333333338", + "server.type": "EC2", + "server.performance.maxNetworkReadsPerSecondInKB": "13.400390625", + "server.hostName": "ip-172-31-42-208", + "server.configurationId": "d-server-099385097ef9fbcfb", + "server.tags.hasMoreValues": "false", + "server.performance.minFreeRAMInKB": "1531104.0", + "server.osVersion": "3.14.48-33.39.amzn1.x86_64", + "server.performance.maxDiskReadsPerSecondInKB": "0.0", + "server.applications": "[]", + "server.performance.numDisks": "1", + "server.performance.numCpus": "1", + "server.performance.numCores": "1", + "server.performance.maxDiskWriteIOPS": "1.0", + "server.performance.maxNetworkWritesPerSecondInKB": "12.271484375", + "server.performance.avgDiskWritesPerSecondInKB": "0.5333333333333334", + "server.networkInterfaceInfo": "[{\"name\":\"eth0\",\"macAddress\":\"06:4A:79:60:75:61\",\"ipAddress\":\"172.31.42.208\",\"netMask\":\"255.255.240.0\"},{\"name\":\"eth0\",\"macAddress\":\"06:4A:79:60:75:61\",\"ipAddress\":\"fe80::44a:79ff:fe60:7561\"},{\"name\":\"lo\",\"macAddress\":\"00:00:00:00:00:00\",\"ipAddress\":\"::1\"},{\"name\":\"lo\",\"macAddress\":\"00:00:00:00:00:00\",\"ipAddress\":\"127.0.0.1\",\"netMask\":\"255.0.0.0\"}]", + "server.performance.avgNetworkReadsPerSecondInKB": "2.8720052083333334", + "server.tags": "[]", + "server.applications.hasMoreValues": "false", + "server.timeOfCreation": "2016-10-28 23:44:30.0", + "server.agentId": "i-c142b99e", + "server.performance.maxDiskWritesPerSecondInKB": "4.0", + "server.performance.avgDiskReadIOPS": "0.0", + "server.performance.avgFreeRAMInKB": "1534946.4", + "server.performance.avgDiskReadsPerSecondInKB": "0.0", + "server.performance.avgDiskWriteIOPS": "0.13333333333333336", + "server.performance.numNetworkCards": "2", + "server.hypervisor": "xen", + "server.networkInterfaceInfo.hasMoreValues": "false", + "server.performance.avgNetworkWritesPerSecondInKB": "1.7977864583333332", + "server.osName": "Linux - Amazon Linux AMI release 2015.03", + "server.performance.totalRAMInKB": "1694732.0", + "server.cpuType": "x64" + } + ] + } + + +**Describe selected asset configurations** + +This example command describes the configurations of two specified applications. The action detects the type of asset from the configuration ID. Only one type of asset is allowed per command. + +Command:: + + aws discovery describe-configurations --configuration-ids "d-application-0ac39bc0e4fad0e42" "d-application-02444a45288013764q" + +Output:: + + { + "configurations": [ + { + "application.serverCount": "0", + "application.name": "Application-12345", + "application.lastModifiedTime": "2016-12-13 23:53:27.0", + "application.description": "", + "application.timeOfCreation": "2016-12-13 23:53:27.0", + "application.configurationId": "d-application-0ac39bc0e4fad0e42" + }, + { + "application.serverCount": "0", + "application.name": "Application-67890", + "application.lastModifiedTime": "2016-12-13 23:53:33.0", + "application.description": "", + "application.timeOfCreation": "2016-12-13 23:53:33.0", + "application.configurationId": "d-application-02444a45288013764" + } + ] + } diff -Nru awscli-1.11.13/awscli/examples/discovery/list-configurations.rst awscli-1.11.44/awscli/examples/discovery/list-configurations.rst --- awscli-1.11.13/awscli/examples/discovery/list-configurations.rst 1970-01-01 00:00:00.000000000 +0000 +++ awscli-1.11.44/awscli/examples/discovery/list-configurations.rst 2017-01-27 00:22:38.000000000 +0000 @@ -0,0 +1,32 @@ +**To list all of the discovered servers meeting a set of filter conditions** + +This example command lists discovered servers matching either of two hostname patterns and not running Ubuntu. + +Command:: + + aws discovery list-configurations --configuration-type SERVER --filters name="server.hostName",values="172-31-35","172-31-42",condition="CONTAINS" name="server.osName",values="Ubuntu",condition="NOT_CONTAINS" + +Output:: + + { + "configurations": [ + { + "server.osVersion": "3.14.48-33.39.amzn1.x86_64", + "server.type": "EC2", + "server.hostName": "ip-172-31-42-208", + "server.timeOfCreation": "2016-10-28 23:44:30.0", + "server.configurationId": "d-server-099385097ef9fbcfb", + "server.osName": "Linux - Amazon Linux AMI release 2015.03", + "server.agentId": "i-c142b99e" + }, + { + "server.osVersion": "3.14.48-33.39.amzn1.x86_64", + "server.type": "EC2", + "server.hostName": "ip-172-31-35-152", + "server.timeOfCreation": "2016-10-28 23:44:00.0", + "server.configurationId": "d-server-0c4f2dd1fee22c6c1", + "server.osName": "Linux - Amazon Linux AMI release 2015.03", + "server.agentId": "i-4447bc1b" + } + ] + } diff -Nru awscli-1.11.13/awscli/examples/ec2/assign-ipv6-addresses.rst awscli-1.11.44/awscli/examples/ec2/assign-ipv6-addresses.rst --- awscli-1.11.13/awscli/examples/ec2/assign-ipv6-addresses.rst 1970-01-01 00:00:00.000000000 +0000 +++ awscli-1.11.44/awscli/examples/ec2/assign-ipv6-addresses.rst 2017-01-27 00:22:38.000000000 +0000 @@ -0,0 +1,35 @@ +**To assign specific IPv6 addresses to a network interface** + +This example assigns the specified IPv6 addresses to the specified network interface. + +Command:: + + aws ec2 assign-ipv6-addresses --network-interface-id eni-38664473 --ipv6-addresses 2001:db8:1234:1a00:3304:8879:34cf:4071 2001:db8:1234:1a00:9691:9503:25ad:1761 + +Output:: + + { + "AssignedIpv6Addresses": [ + "2001:db8:1234:1a00:3304:8879:34cf:4071", + "2001:db8:1234:1a00:9691:9503:25ad:1761" + ], + "NetworkInterfaceId": "eni-38664473" + } + +**To assign IPv6 addresses that Amazon selects to a network interface** + +This example assigns two IPv6 addresses to the specified network interface. Amazon automatically assigns these IPv6 addresses from the available IPv6 addresses in the IPv6 CIDR block range of the subnet. + +Command:: + + aws ec2 assign-ipv6-addresses --network-interface-id eni-38664473 --ipv6-address-count 2 + +Output:: + + { + "AssignedIpv6Addresses": [ + "2001:db8:1234:1a00:3304:8879:34cf:4071", + "2001:db8:1234:1a00:9691:9503:25ad:1761" + ], + "NetworkInterfaceId": "eni-38664473" + } diff -Nru awscli-1.11.13/awscli/examples/ec2/associate-subnet-cidr-block.rst awscli-1.11.44/awscli/examples/ec2/associate-subnet-cidr-block.rst --- awscli-1.11.13/awscli/examples/ec2/associate-subnet-cidr-block.rst 1970-01-01 00:00:00.000000000 +0000 +++ awscli-1.11.44/awscli/examples/ec2/associate-subnet-cidr-block.rst 2017-01-27 00:22:38.000000000 +0000 @@ -0,0 +1,20 @@ +**To associate an IPv6 CIDR block with a subnet** + +This example associates an IPv6 CIDR block with the specified subnet. + +Command:: + + aws ec2 associate-subnet-cidr-block --subnet-id subnet-5f46ec3b --ipv6-cidr-block 2001:db8:1234:1a00::/64 + +Output:: + + { + "SubnetId": "subnet-5f46ec3b", + "Ipv6CidrBlockAssociation": { + "Ipv6CidrBlock": "2001:db8:1234:1a00::/64", + "AssociationId": "subnet-cidr-assoc-3aa54053", + "Ipv6CidrBlockState": { + "State": "associating" + } + } + } \ No newline at end of file diff -Nru awscli-1.11.13/awscli/examples/ec2/associate-vpc-cidr-block.rst awscli-1.11.44/awscli/examples/ec2/associate-vpc-cidr-block.rst --- awscli-1.11.13/awscli/examples/ec2/associate-vpc-cidr-block.rst 1970-01-01 00:00:00.000000000 +0000 +++ awscli-1.11.44/awscli/examples/ec2/associate-vpc-cidr-block.rst 2017-01-27 00:22:38.000000000 +0000 @@ -0,0 +1,19 @@ +**To associate an IPv6 CIDR block with a VPC** + +This example associates an IPv6 CIDR block with a VPC. + +Command:: + + aws ec2 associate-vpc-cidr-block --amazon-provided-ipv6-cidr-block --vpc-id vpc-a034d6c4 + +Output:: + + { + "Ipv6CidrBlockAssociation": { + "Ipv6CidrBlockState": { + "State": "associating" + }, + "AssociationId": "vpc-cidr-assoc-eca54085" + }, + "VpcId": "vpc-a034d6c4" + } \ No newline at end of file diff -Nru awscli-1.11.13/awscli/examples/ec2/authorize-security-group-ingress.rst awscli-1.11.44/awscli/examples/ec2/authorize-security-group-ingress.rst --- awscli-1.11.13/awscli/examples/ec2/authorize-security-group-ingress.rst 2016-11-03 20:32:27.000000000 +0000 +++ awscli-1.11.44/awscli/examples/ec2/authorize-security-group-ingress.rst 2017-01-27 00:22:38.000000000 +0000 @@ -46,6 +46,14 @@ aws ec2 authorize-security-group-ingress --group-id sg-123abc12 --ip-permissions '[{"IpProtocol": "icmp", "FromPort": 3, "ToPort": 4, "IpRanges": [{"CidrIp": "0.0.0.0/0"}]}]' +**[EC2-VPC] To add a rule for IPv6 traffic** + +This example grants SSH access (port 22) from the IPv6 range ``2001:db8:1234:1a00::/64``. + +Command:: + + aws ec2 authorize-security-group-ingress --group-id sg-9bf6ceff --ip-permissions '[{"IpProtocol": "tcp", "FromPort": 22, "ToPort": 22, "Ipv6Ranges": [{"CidrIpv6": "2001:db8:1234:1a00::/64"}]}]' + For more information, see `Using Security Groups`_ in the *AWS Command Line Interface User Guide*. .. _`Using Security Groups`: http://docs.aws.amazon.com/cli/latest/userguide/cli-ec2-sg.html diff -Nru awscli-1.11.13/awscli/examples/ec2/create-egress-only-internet-gateway.rst awscli-1.11.44/awscli/examples/ec2/create-egress-only-internet-gateway.rst --- awscli-1.11.13/awscli/examples/ec2/create-egress-only-internet-gateway.rst 1970-01-01 00:00:00.000000000 +0000 +++ awscli-1.11.44/awscli/examples/ec2/create-egress-only-internet-gateway.rst 2017-01-27 00:22:38.000000000 +0000 @@ -0,0 +1,21 @@ +**To create an egress-only Internet gateway** + +This example creates an egress-only Internet gateway for the specified VPC. + +Command:: + + aws ec2 create-egress-only-internet-gateway --vpc-id vpc-0c62a468 + +Output:: + + { + "EgressOnlyInternetGateway": { + "EgressOnlyInternetGatewayId": "eigw-015e0e244e24dfe8a", + "Attachments": [ + { + "State": "attached", + "VpcId": "vpc-0c62a468" + } + ] + } + } \ No newline at end of file diff -Nru awscli-1.11.13/awscli/examples/ec2/create-network-acl-entry.rst awscli-1.11.44/awscli/examples/ec2/create-network-acl-entry.rst --- awscli-1.11.13/awscli/examples/ec2/create-network-acl-entry.rst 2016-11-03 20:32:27.000000000 +0000 +++ awscli-1.11.44/awscli/examples/ec2/create-network-acl-entry.rst 2017-01-27 00:22:38.000000000 +0000 @@ -1,7 +1,14 @@ **To create a network ACL entry** -This example creates an entry for the specified network ACL. The rule allows ingress traffic from anywhere (0.0.0.0/0) on UDP port 53 (DNS) into any associated subnet. If the command succeeds, no output is returned. +This example creates an entry for the specified network ACL. The rule allows ingress traffic from any IPv4 address (0.0.0.0/0) on UDP port 53 (DNS) into any associated subnet. If the command succeeds, no output is returned. Command:: aws ec2 create-network-acl-entry --network-acl-id acl-5fb85d36 --ingress --rule-number 100 --protocol udp --port-range From=53,To=53 --cidr-block 0.0.0.0/0 --rule-action allow + + +This example creates a rule for the specified network ACL that allows ingress traffic from any IPv6 address (::/0) on TCP port 80 (HTTP). + +Command:: + + aws ec2 create-network-acl-entry --network-acl-id acl-5fb85d36 --ingress --rule-number 120 --protocol tcp --port-range From=80,To=80 --ipv6-cidr-block ::/0 --rule-action allow \ No newline at end of file diff -Nru awscli-1.11.13/awscli/examples/ec2/create-network-interface.rst awscli-1.11.44/awscli/examples/ec2/create-network-interface.rst --- awscli-1.11.13/awscli/examples/ec2/create-network-interface.rst 2016-11-03 20:32:27.000000000 +0000 +++ awscli-1.11.44/awscli/examples/ec2/create-network-interface.rst 2017-01-27 00:22:38.000000000 +0000 @@ -24,6 +24,7 @@ ], "RequesterManaged": false, "AvailabilityZone": "us-east-1d", + "Ipv6Addresses": [], "Groups": [ { "GroupName": "default", diff -Nru awscli-1.11.13/awscli/examples/ec2/create-route.rst awscli-1.11.44/awscli/examples/ec2/create-route.rst --- awscli-1.11.13/awscli/examples/ec2/create-route.rst 2016-11-03 20:32:27.000000000 +0000 +++ awscli-1.11.44/awscli/examples/ec2/create-route.rst 2017-01-27 00:22:38.000000000 +0000 @@ -1,15 +1,21 @@ **To create a route** -This example creates a route for the specified route table. The route matches all traffic (``0.0.0.0/0``) and routes it to the specified Internet gateway. If the command succeeds, no output is returned. +This example creates a route for the specified route table. The route matches all IPv4 traffic (``0.0.0.0/0``) and routes it to the specified Internet gateway. If the command succeeds, no output is returned. Command:: aws ec2 create-route --route-table-id rtb-22574640 --destination-cidr-block 0.0.0.0/0 --gateway-id igw-c0a643a9 -This example command creates a route in route table rtb-g8ff4ea2. The route matches traffic for the CIDR block +This example command creates a route in route table rtb-g8ff4ea2. The route matches traffic for the IPv4 CIDR block 10.0.0.0/16 and routes it to VPC peering connection, pcx-111aaa22. This route enables traffic to be directed to the peer VPC in the VPC peering connection. If the command succeeds, no output is returned. Command:: aws ec2 create-route --route-table-id rtb-g8ff4ea2 --destination-cidr-block 10.0.0.0/16 --vpc-peering-connection-id pcx-1a2b3c4d + +This example creates a route in the specified route table that matches all IPv6 traffic (``::/0``) and routes it to the specified egress-only Internet gateway. + +Command:: + + aws ec2 create-route --route-table-id rtb-dce620b8 --destination-ipv6-cidr-block ::/0 --egress-only-internet-gateway-id eigw-01eadbd45ecd7943f diff -Nru awscli-1.11.13/awscli/examples/ec2/create-subnet.rst awscli-1.11.44/awscli/examples/ec2/create-subnet.rst --- awscli-1.11.13/awscli/examples/ec2/create-subnet.rst 2016-11-03 20:32:27.000000000 +0000 +++ awscli-1.11.44/awscli/examples/ec2/create-subnet.rst 2017-01-27 00:22:38.000000000 +0000 @@ -1,6 +1,6 @@ **To create a subnet** -This example creates a subnet in the specified VPC with the specified CIDR block. We recommend that you let us select an Availability Zone for you. Alternatively, you can use the ``--availability-zone`` option to specify the Availability Zone. +This example creates a subnet in the specified VPC with the specified IPv4 CIDR block. We recommend that you let us select an Availability Zone for you. Alternatively, you can use the ``--availability-zone`` option to specify the Availability Zone. Command:: @@ -10,11 +10,48 @@ { "Subnet": { - "VpcId": "vpc-a01106c2", - "CidrBlock": "10.0.1.0/24", - "State": "pending", - "AvailabilityZone": "us-east-1c", - "SubnetId": "subnet-9d4a7b6c", - "AvailableIpAddressCount": 251 + "VpcId": "vpc-a01106c2", + "AvailableIpAddressCount": 251, + "MapPublicIpOnLaunch": false, + "DefaultForAz": false, + "Ipv6CidrBlockAssociationSet": [], + "State": "pending", + "AvailabilityZone": "us-east-1a", + "SubnetId": "subnet-2c2de375", + "CidrBlock": "10.0.1.0/24", + "AssignIpv6AddressOnCreation": false } + } + +**To create a subnet with an IPv6 CIDR block** + +This example creates a subnet in the specified VPC with the specified IPv4 and IPv6 CIDR blocks (from the ranges of the VPC). + +Command:: + + aws ec2 create-subnet --vpc-id vpc-31896b55 --cidr-block 10.0.0.0/24 --ipv6-cidr-block 2001:db8:1234:a100::/64 + +Output:: + + { + "Subnet": { + "VpcId": "vpc-31896b55", + "AvailableIpAddressCount": 251, + "MapPublicIpOnLaunch": false, + "DefaultForAz": false, + "Ipv6CidrBlockAssociationSet": [ + { + "Ipv6CidrBlock": "2001:db8:1234:a100::/64", + "AssociationId": "subnet-cidr-assoc-3fe7e347", + "Ipv6CidrBlockState": { + "State": "ASSOCIATING" + } + } + ], + "State": "pending", + "AvailabilityZone": "ap-southeast-2a", + "SubnetId": "subnet-5504d223", + "CidrBlock": "10.0.0.0/24", + "AssignIpv6AddressOnCreation": false + } } \ No newline at end of file diff -Nru awscli-1.11.13/awscli/examples/ec2/create-vpc.rst awscli-1.11.44/awscli/examples/ec2/create-vpc.rst --- awscli-1.11.13/awscli/examples/ec2/create-vpc.rst 2016-11-03 20:32:27.000000000 +0000 +++ awscli-1.11.44/awscli/examples/ec2/create-vpc.rst 2017-01-27 00:22:38.000000000 +0000 @@ -1,6 +1,6 @@ **To create a VPC** -This example creates a VPC with the specified CIDR block. +This example creates a VPC with the specified IPv4 CIDR block. Command:: @@ -10,17 +10,20 @@ { "Vpc": { - "InstanceTenancy": "default", - "State": "pending", - "VpcId": "vpc-a01106c2", - "CidrBlock": "10.0.0.0/16", - "DhcpOptionsId": "dopt-7a8b9c2d" + "VpcId": "vpc-145db170", + "InstanceTenancy": "default", + "CidrBlockAssociationSet": [], + "Ipv6CidrBlockAssociationSet": [], + "State": "pending", + "DhcpOptionsId": "dopt-dbedadb2", + "CidrBlock": "10.0.0.0/16", + "IsDefault": false } } **To create a VPC with dedicated tenancy** -This example creates a VPC with the specified CIDR block and ``dedicated`` tenancy. +This example creates a VPC with the specified IPv4 CIDR block and ``dedicated`` tenancy. Command:: @@ -30,10 +33,44 @@ { "Vpc": { - "InstanceTenancy": "dedicated", - "State": "pending", - "VpcId": "vpc-a01106c2", - "CidrBlock": "10.0.0.0/16", - "DhcpOptionsId": "dopt-7a8b9c2d" + "VpcId": "vpc-145db170", + "InstanceTenancy": "dedicated", + "CidrBlockAssociationSet": [], + "Ipv6CidrBlockAssociationSet": [], + "State": "pending", + "DhcpOptionsId": "dopt-dbedadb2", + "CidrBlock": "10.0.0.0/16", + "IsDefault": false } - } \ No newline at end of file + } + +**To create a VPC with an IPv6 CIDR block** + +This example creates a VPC with an Amazon-provided IPv6 CIDR block. + +Command:: + + aws ec2 create-vpc --cidr-block 10.0.0.0/16 --amazon-provided-ipv6-cidr-block + +Output:: + + { + "Vpc": { + "VpcId": "vpc-31896b55", + "InstanceTenancy": "default", + "CidrBlockAssociationSet": [], + "Ipv6CidrBlockAssociationSet": [ + { + "Ipv6CidrBlock": "", + "AssociationId": "vpc-cidr-assoc-17a5407e", + "Ipv6CidrBlockState": { + "State": "associating" + } + } + ], + "State": "pending", + "DhcpOptionsId": "dopt-dbedadb2", + "CidrBlock": "10.0.0.0/16", + "IsDefault": false + } + } diff -Nru awscli-1.11.13/awscli/examples/ec2/delete-egress-only-internet-gateway.rst awscli-1.11.44/awscli/examples/ec2/delete-egress-only-internet-gateway.rst --- awscli-1.11.13/awscli/examples/ec2/delete-egress-only-internet-gateway.rst 1970-01-01 00:00:00.000000000 +0000 +++ awscli-1.11.44/awscli/examples/ec2/delete-egress-only-internet-gateway.rst 2017-01-27 00:22:38.000000000 +0000 @@ -0,0 +1,13 @@ +**To delete an egress-only Internet gateway** + +This example deletes the specified egress-only Internet gateway. + +Command:: + + aws ec2 delete-egress-only-internet-gateway --egress-only-internet-gateway-id eigw-01eadbd45ecd7943f + +Output:: + + { + "ReturnCode": true + } \ No newline at end of file diff -Nru awscli-1.11.13/awscli/examples/ec2/describe-egress-only-internet-gateways.rst awscli-1.11.44/awscli/examples/ec2/describe-egress-only-internet-gateways.rst --- awscli-1.11.13/awscli/examples/ec2/describe-egress-only-internet-gateways.rst 1970-01-01 00:00:00.000000000 +0000 +++ awscli-1.11.44/awscli/examples/ec2/describe-egress-only-internet-gateways.rst 2017-01-27 00:22:38.000000000 +0000 @@ -0,0 +1,23 @@ +**To describe your egress-only Internet gateways** + +This example describes your egress-only Internet gateways. + +Command:: + + aws ec2 describe-egress-only-internet-gateways + +Output:: + + { + "EgressOnlyInternetGateways": [ + { + "EgressOnlyInternetGatewayId": "eigw-015e0e244e24dfe8a", + "Attachments": [ + { + "State": "attached", + "VpcId": "vpc-0c62a468" + } + ] + } + ] + } \ No newline at end of file diff -Nru awscli-1.11.13/awscli/examples/ec2/describe-network-acls.rst awscli-1.11.44/awscli/examples/ec2/describe-network-acls.rst --- awscli-1.11.13/awscli/examples/ec2/describe-network-acls.rst 2016-11-03 20:32:27.000000000 +0000 +++ awscli-1.11.44/awscli/examples/ec2/describe-network-acls.rst 2017-01-27 00:22:38.000000000 +0000 @@ -117,6 +117,57 @@ } ], "IsDefault": true - } + }, + { + "Associations": [], + "NetworkAclId": "acl-6da75208", + "VpcId": "vpc-4e20d42b", + "Tags": [], + "Entries": [ + { + "CidrBlock": "0.0.0.0/0", + "RuleNumber": 32767, + "Protocol": "-1", + "Egress": true, + "RuleAction": "deny" + }, + { + "Ipv6CidrBlock": "::/0", + "RuleNumber": 32768, + "Protocol": "-1", + "Egress": true, + "RuleAction": "deny" + }, + { + "CidrBlock": "0.0.0.0/0", + "RuleNumber": 100, + "Protocol": "-1", + "Egress": false, + "RuleAction": "allow" + }, + { + "Ipv6CidrBlock": "::/0", + "RuleNumber": 101, + "Protocol": "-1", + "Egress": false, + "RuleAction": "allow" + }, + { + "CidrBlock": "0.0.0.0/0", + "RuleNumber": 32767, + "Protocol": "-1", + "Egress": false, + "RuleAction": "deny" + }, + { + "Ipv6CidrBlock": "::/0", + "RuleNumber": 32768, + "Protocol": "-1", + "Egress": false, + "RuleAction": "deny" + } + ], + "IsDefault": true + } ] } \ No newline at end of file diff -Nru awscli-1.11.13/awscli/examples/ec2/describe-network-interfaces.rst awscli-1.11.44/awscli/examples/ec2/describe-network-interfaces.rst --- awscli-1.11.13/awscli/examples/ec2/describe-network-interfaces.rst 2016-11-03 20:32:27.000000000 +0000 +++ awscli-1.11.44/awscli/examples/ec2/describe-network-interfaces.rst 2017-01-27 00:22:38.000000000 +0000 @@ -37,6 +37,7 @@ } ], "RequesterManaged": false, + "Ipv6Addresses": [], "PrivateDnsName": "ip-10-0-1-17.ec2.internal", "AvailabilityZone": "us-east-1d", "Attachment": { @@ -81,6 +82,7 @@ } ], "RequesterManaged": false, + "Ipv6Addresses": [], "AvailabilityZone": "us-east-1d", "Attachment": { "Status": "attached", @@ -104,3 +106,56 @@ } ] } + + +This example describes network interfaces that have a tag with the key ``Purpose`` and the value ``Prod``. + +Command:: + + aws ec2 describe-network-interfaces --filters Name=tag:Purpose,Values=Prod + +Output:: + + { + "NetworkInterfaces": [ + { + "Status": "available", + "MacAddress": "12:2c:bd:f9:bf:17", + "SourceDestCheck": true, + "VpcId": "vpc-8941ebec", + "Description": "ProdENI", + "NetworkInterfaceId": "eni-b9a5ac93", + "PrivateIpAddresses": [ + { + "PrivateDnsName": "ip-10-0-1-55.ec2.internal", + "Primary": true, + "PrivateIpAddress": "10.0.1.55" + }, + { + "PrivateDnsName": "ip-10-0-1-117.ec2.internal", + "Primary": false, + "PrivateIpAddress": "10.0.1.117" + } + ], + "RequesterManaged": false, + "PrivateDnsName": "ip-10-0-1-55.ec2.internal", + "AvailabilityZone": "us-east-1d", + "Ipv6Addresses": [], + "Groups": [ + { + "GroupName": "MySG", + "GroupId": "sg-905002f5" + } + ], + "SubnetId": "subnet-31d6c219", + "OwnerId": "123456789012", + "TagSet": [ + { + "Value": "Prod", + "Key": "Purpose" + } + ], + "PrivateIpAddress": "10.0.1.55" + } + ] + } \ No newline at end of file diff -Nru awscli-1.11.13/awscli/examples/ec2/describe-route-tables.rst awscli-1.11.44/awscli/examples/ec2/describe-route-tables.rst --- awscli-1.11.13/awscli/examples/ec2/describe-route-tables.rst 2016-11-03 20:32:27.000000000 +0000 +++ awscli-1.11.44/awscli/examples/ec2/describe-route-tables.rst 2017-01-27 00:22:38.000000000 +0000 @@ -26,7 +26,8 @@ { "GatewayId": "local", "DestinationCidrBlock": "10.0.0.0/16", - "State": "active" + "State": "active", + "Origin": "CreateRouteTable" } ] }, @@ -35,6 +36,7 @@ { "SubnetId": "subnet-b61f49f0", "RouteTableAssociationId": "rtbassoc-781d0d1a", + "Main": false, "RouteTableId": "rtb-22574640" } ], @@ -50,14 +52,55 @@ { "GatewayId": "local", "DestinationCidrBlock": "10.0.0.0/16", - "State": "active" + "State": "active", + "Origin": "CreateRouteTable" }, { "GatewayId": "igw-046d7966", "DestinationCidrBlock": "0.0.0.0/0", - "State": "active" + "State": "active", + "Origin": "CreateRoute" } ] - } - ] - } \ No newline at end of file + }, + { + "Associations": [ + { + "RouteTableAssociationId": "rtbassoc-91fbacf5", + "Main": true, + "RouteTableId": "rtb-1a459c7e" + } + ], + "RouteTableId": "rtb-1a459c7e", + "VpcId": "vpc-31896b55", + "PropagatingVgws": [], + "Tags": [], + "Routes": [ + { + "GatewayId": "local", + "DestinationCidrBlock": "10.0.0.0/16", + "State": "active", + "Origin": "CreateRouteTable" + }, + { + "GatewayId": "igw-2fa4e34a", + "DestinationCidrBlock": "0.0.0.0/0", + "State": "active", + "Origin": "CreateRoute" + }, + { + "GatewayId": "local", + "Origin": "CreateRouteTable", + "State": "active", + "DestinationIpv6CidrBlock": "2001:db8:1234:a100::/56" + }, + { + "GatewayId": "igw-2fa4e34a", + "Origin": "CreateRoute", + "State": "active", + "DestinationIpv6CidrBlock": "::/0" + } + ] + } + ] + } \ No newline at end of file diff -Nru awscli-1.11.13/awscli/examples/ec2/describe-subnets.rst awscli-1.11.44/awscli/examples/ec2/describe-subnets.rst --- awscli-1.11.13/awscli/examples/ec2/describe-subnets.rst 2016-11-03 20:32:27.000000000 +0000 +++ awscli-1.11.44/awscli/examples/ec2/describe-subnets.rst 2017-01-27 00:22:38.000000000 +0000 @@ -12,24 +12,36 @@ "Subnets": [ { "VpcId": "vpc-a01106c2", - "CidrBlock": "10.0.1.0/24", + "AvailableIpAddressCount": 251, "MapPublicIpOnLaunch": false, "DefaultForAz": false, + "Ipv6CidrBlockAssociationSet": [], "State": "available", "AvailabilityZone": "us-east-1c", "SubnetId": "subnet-9d4a7b6c", - "AvailableIpAddressCount": 251 + "CidrBlock": "10.0.1.0/24", + "AssignIpv6AddressOnCreation": false }, { - "VpcId": "vpc-b61106d4", - "CidrBlock": "10.0.0.0/24", - "MapPublicIpOnLaunch": false, - "DefaultForAz": false, - "State": "available", - "AvailabilityZone": "us-east-1d", - "SubnetId": "subnet-65ea5f08", - "AvailableIpAddressCount": 251 - } + "VpcId": "vpc-31896b55", + "AvailableIpAddressCount": 251, + "MapPublicIpOnLaunch": false, + "DefaultForAz": false, + "Ipv6CidrBlockAssociationSet": [ + { + "Ipv6CidrBlock": "2001:db8:1234:a101::/64", + "AssociationId": "subnet-cidr-assoc-30e7e348", + "Ipv6CidrBlockState": { + "State": "ASSOCIATED" + } + } + ], + "State": "available", + "AvailabilityZone": "us-east-1a", + "SubnetId": "subnet-4204d234", + "CidrBlock": "10.0.1.0/24", + "AssignIpv6AddressOnCreation": false + } ] } @@ -41,23 +53,6 @@ aws ec2 describe-subnets --filters "Name=vpc-id,Values=vpc-a01106c2" -Output:: - - { - "Subnets": [ - { - "VpcId": "vpc-a01106c2", - "CidrBlock": "10.0.1.0/24", - "MapPublicIpOnLaunch": false, - "DefaultForAz": false, - "State": "available", - "AvailabilityZone": "us-east-1c", - "SubnetId": "subnet-9d4a7b6c", - "AvailableIpAddressCount": 251 - } - ] - } - **To describe subnets with a specific tag** This example lists subnets with the tag ``Name=MySubnet`` and returns the output in text format. @@ -68,5 +63,5 @@ Output:: - SUBNETS us-east-1a 251 10.0.1.0/24 False False available subnet-1a2b3c4d vpc-11223344 + SUBNETS False us-east-1a 251 10.0.1.0/24 False False available subnet-5f46ec3b vpc-a034d6c4 TAGS Name MySubnet \ No newline at end of file diff -Nru awscli-1.11.13/awscli/examples/ec2/describe-vpcs.rst awscli-1.11.44/awscli/examples/ec2/describe-vpcs.rst --- awscli-1.11.13/awscli/examples/ec2/describe-vpcs.rst 2016-11-03 20:32:27.000000000 +0000 +++ awscli-1.11.44/awscli/examples/ec2/describe-vpcs.rst 2017-01-27 00:22:38.000000000 +0000 @@ -31,7 +31,24 @@ "DhcpOptionsId": "dopt-97eb5efa", "CidrBlock": "10.50.0.0/16", "IsDefault": false - } + }, + { + "VpcId": "vpc-a45db1c0", + "InstanceTenancy": "default", + "Ipv6CidrBlockAssociationSet": [ + { + "Ipv6CidrBlock": "2001:db8:1234:8800::/56", + "AssociationId": "vpc-cidr-assoc-e5a5408c", + "Ipv6CidrBlockState": { + "State": "ASSOCIATED" + } + } + ], + "State": "available", + "DhcpOptionsId": "dopt-dbedadb2", + "CidrBlock": "198.168.0.0/24", + "IsDefault": false + } ] } diff -Nru awscli-1.11.13/awscli/examples/ec2/disassociate-subnet-cidr-block.rst awscli-1.11.44/awscli/examples/ec2/disassociate-subnet-cidr-block.rst --- awscli-1.11.13/awscli/examples/ec2/disassociate-subnet-cidr-block.rst 1970-01-01 00:00:00.000000000 +0000 +++ awscli-1.11.44/awscli/examples/ec2/disassociate-subnet-cidr-block.rst 2017-01-27 00:22:38.000000000 +0000 @@ -0,0 +1,20 @@ +**To disassociate an IPv6 CIDR block from a subnet** + +This example disassociates an IPv6 CIDR block from a subnet using the association ID for the CIDR block. + +Command:: + + aws ec2 disassociate-subnet-cidr-block --association-id subnet-cidr-assoc-3aa54053 + +Output:: + + { + "SubnetId": "subnet-5f46ec3b", + "Ipv6CidrBlockAssociation": { + "Ipv6CidrBlock": "2001:db8:1234:1a00::/64", + "AssociationId": "subnet-cidr-assoc-3aa54053", + "Ipv6CidrBlockState": { + "State": "disassociating" + } + } + } \ No newline at end of file diff -Nru awscli-1.11.13/awscli/examples/ec2/disassociate-vpc-cidr-block.rst awscli-1.11.44/awscli/examples/ec2/disassociate-vpc-cidr-block.rst --- awscli-1.11.13/awscli/examples/ec2/disassociate-vpc-cidr-block.rst 1970-01-01 00:00:00.000000000 +0000 +++ awscli-1.11.44/awscli/examples/ec2/disassociate-vpc-cidr-block.rst 2017-01-27 00:22:38.000000000 +0000 @@ -0,0 +1,20 @@ +**To disassociate an IPv6 CIDR block from a VPC** + +This example disassociates an IPv6 CIDR block from a VPC using the association ID for the CIDR block. + +Command:: + + aws ec2 disassociate-vpc-cidr-block --association-id vpc-cidr-assoc-eca54085 + +Output:: + + { + "Ipv6CidrBlockAssociation": { + "Ipv6CidrBlock": "2001:db8:1234:1a00::/56", + "AssociationId": "vpc-cidr-assoc-eca54085", + "Ipv6CidrBlockState": { + "State": "disassociating" + } + }, + "VpcId": "vpc-a034d6c4" + } \ No newline at end of file diff -Nru awscli-1.11.13/awscli/examples/ec2/modify-subnet-attribute.rst awscli-1.11.44/awscli/examples/ec2/modify-subnet-attribute.rst --- awscli-1.11.13/awscli/examples/ec2/modify-subnet-attribute.rst 2016-11-03 20:32:27.000000000 +0000 +++ awscli-1.11.44/awscli/examples/ec2/modify-subnet-attribute.rst 2017-01-27 00:22:38.000000000 +0000 @@ -1,11 +1,19 @@ -**To change a subnet's public IP addressing behavior** +**To change a subnet's public IPv4 addressing behavior** -This example modifies subnet-1a2b3c4d to specify that all instances launched into this subnet are assigned a public IP address. If the command succeeds, no output is returned. +This example modifies subnet-1a2b3c4d to specify that all instances launched into this subnet are assigned a public IPv4 address. If the command succeeds, no output is returned. Command:: aws ec2 modify-subnet-attribute --subnet-id subnet-1a2b3c4d --map-public-ip-on-launch +**To change a subnet's IPv6 addressing behavior** + +This example modifies subnet-1a2b3c4d to specify that all instances launched into this subnet are assigned an IPv6 address from the range of the subnet. + +Command:: + + aws ec2 modify-subnet-attribute --subnet-id subnet-1a2b3c4d --assign-ipv6-address-on-creation + For more information, see `IP Addressing in Your VPC`_ in the *AWS Virtual Private Cloud User Guide*. .. _`IP Addressing in Your VPC`: http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/vpc-ip-addressing.html \ No newline at end of file diff -Nru awscli-1.11.13/awscli/examples/ec2/run-instances.rst awscli-1.11.44/awscli/examples/ec2/run-instances.rst --- awscli-1.11.13/awscli/examples/ec2/run-instances.rst 2016-11-03 20:32:27.000000000 +0000 +++ awscli-1.11.44/awscli/examples/ec2/run-instances.rst 2017-01-27 00:22:38.000000000 +0000 @@ -1,12 +1,12 @@ **To launch an instance in EC2-Classic** -This example launches a single instance of type ``t1.micro``. +This example launches a single instance of type ``c3.large``. The key pair and security group, named ``MyKeyPair`` and ``MySecurityGroup``, must exist. Command:: - aws ec2 run-instances --image-id ami-1a2b3c4d --count 1 --instance-type t1.micro --key-name MyKeyPair --security-groups MySecurityGroup + aws ec2 run-instances --image-id ami-1a2b3c4d --count 1 --instance-type c3.large --key-name MyKeyPair --security-groups MySecurityGroup Output:: @@ -45,7 +45,7 @@ } ], "ClientToken": null, - "InstanceType": "t1.micro", + "InstanceType": "c3.large", "NetworkInterfaces": [], "Placement": { "Tenancy": "default", @@ -126,6 +126,7 @@ "PrivateIpAddress": "10.0.1.114" } ], + "Ipv6Addresses": [], "PrivateDnsName": "ip-10-0-1-114.ec2.internal", "Attachment": { "Status": "attached", @@ -169,7 +170,7 @@ Command:: - aws ec2 run-instances --image-id ami-c3b8d6aa --count 1 --instance-type t1.micro --key-name MyKeyPair --security-group-ids sg-903004f8 --subnet-id subnet-6e7f829e --associate-public-ip-address + aws ec2 run-instances --image-id ami-c3b8d6aa --count 1 --instance-type t2.medium --key-name MyKeyPair --security-group-ids sg-903004f8 --subnet-id subnet-6e7f829e --associate-public-ip-address **To launch an instance using a block device mapping** diff -Nru awscli-1.11.13/awscli/examples/ec2/unassign-ipv6-addresses.rst awscli-1.11.44/awscli/examples/ec2/unassign-ipv6-addresses.rst --- awscli-1.11.13/awscli/examples/ec2/unassign-ipv6-addresses.rst 1970-01-01 00:00:00.000000000 +0000 +++ awscli-1.11.44/awscli/examples/ec2/unassign-ipv6-addresses.rst 2017-01-27 00:22:38.000000000 +0000 @@ -0,0 +1,16 @@ +**To unassign an IPv6 address from a network interface** + +This example unassigns the specified IPv6 address from the specified network interface. + +Command:: + + aws ec2 unassign-ipv6-addresses --ipv6-addresses 2001:db8:1234:1a00:3304:8879:34cf:4071 --network-interface-id eni-23c49b68 + +Output:: + + { + "NetworkInterfaceId": "eni-23c49b68", + "UnassignedIpv6Addresses": [ + "2001:db8:1234:1a00:3304:8879:34cf:4071" + ] + } diff -Nru awscli-1.11.13/awscli/examples/elbv2/deregister-targets.rst awscli-1.11.44/awscli/examples/elbv2/deregister-targets.rst --- awscli-1.11.13/awscli/examples/elbv2/deregister-targets.rst 2016-11-03 20:32:27.000000000 +0000 +++ awscli-1.11.44/awscli/examples/elbv2/deregister-targets.rst 2017-01-27 00:22:38.000000000 +0000 @@ -5,3 +5,11 @@ Command:: aws elbv2 deregister-targets --target-group-arn arn:aws:elasticloadbalancing:us-west-2:123456789012:targetgroup/my-targets/73e2d6bc24d8a067 --targets Id=i-0f76fade + +**To deregister a target registered using port overrides** + +This example deregisters an instance that was registered using port overrides. + +Command:: + + aws elbv2 deregister-targets --target-group-arn arn:aws:elasticloadbalancing:us-west-2:123456789012:targetgroup/my-internal-targets/3bb63f11dfb0faf9 --targets Id=i-80c8dd94,Port=80 Id=i-80c8dd94,Port=766 diff -Nru awscli-1.11.13/awscli/examples/emr/create-cluster-examples.rst awscli-1.11.44/awscli/examples/emr/create-cluster-examples.rst --- awscli-1.11.13/awscli/examples/emr/create-cluster-examples.rst 2016-11-03 20:32:27.000000000 +0000 +++ awscli-1.11.44/awscli/examples/emr/create-cluster-examples.rst 2017-01-27 00:22:38.000000000 +0000 @@ -169,6 +169,12 @@ VolumeType, SizeInGB if EbsBlockDeviceConfigs specified +- Create a cluster with an Auto Scaling policy attached to the CORE instance group. The Auto Scaling policy can be attached to CORE and TASK instance groups. For instance groups with an Auto Scaling policy attached, you should enclose the entire instance group argument with single quotes. For instance groups with no Auto Scaling policy, using single quotes is optional. + +- Command:: + + aws emr create-cluster --release-label emr-5.0.0 --use-default-roles --auto-scaling-role EMR_AutoScaling_DefaultRole --instance-groups InstanceGroupType=MASTER,InstanceType=d2.xlarge,InstanceCount=1 'InstanceGroupType=CORE,InstanceType=d2.xlarge,InstanceCount=2,AutoScalingPolicy={Constraints={MinCapacity=1,MaxCapacity=5},Rules=[{Name=TestRule,Description=TestDescription,Action={Market=ON_DEMAND,SimpleScalingPolicyConfiguration={AdjustmentType=EXACT_CAPACITY,ScalingAdjustment=2}},Trigger={CloudWatchAlarmDefinition={ComparisonOperator=GREATER_THAN,EvaluationPeriods=5,MetricName=TestMetric,Namespace=EMR,Period=3,Statistic=MAXIMUM,Threshold=4.5,Unit=NONE,Dimensions=[{Key=TestKey,Value=TestValue}]}}}]}' + **13. To add custom JAR steps to a cluster when creating an Amazon EMR cluster** - Command:: diff -Nru awscli-1.11.13/awscli/examples/opsworks-cm/associate-node.rst awscli-1.11.44/awscli/examples/opsworks-cm/associate-node.rst --- awscli-1.11.13/awscli/examples/opsworks-cm/associate-node.rst 1970-01-01 00:00:00.000000000 +0000 +++ awscli-1.11.44/awscli/examples/opsworks-cm/associate-node.rst 2017-01-27 00:22:38.000000000 +0000 @@ -0,0 +1,22 @@ +**To associate nodes** + +The following ``associate-node`` command associates a node named ``i-44de882p`` with +a Chef Automate server named ``automate-06``, meaning that the ``automate-06`` server +manages the node, and communicates recipe commands to the node through ``chef-client`` agent software +that is installed on the node by the associate-node command. Valid node names are EC2 instance IDs.:: + + aws opsworks-cm disassociate-node --server-name "automate-06" --node-name "i-43de882p" --engine-attributes "Name=CHEF_ORGANIZATION,Value='default'" + +The output returned by the command resembles the following. +*Output*:: + + { + "NodeAssociationStatusToken": "AHUY8wFe4pdXtZC5DiJa5SOLp5o14DH//rHRqHDWXxwVoNBxcEy4V7R0NOFymh7E/1HumOBPsemPQFE6dcGaiFk" + } + +**More Information** + +For more information, see `Adding Nodes Automatically in AWS OpsWorks for Chef Automate`_ in the *AWS OpsWorks User Guide*. + +.. _`Adding Nodes Automatically in AWS OpsWorks for Chef Automate`: http://docs.aws.amazon.com/opsworks/latest/userguide/opscm-unattend-assoc.html + diff -Nru awscli-1.11.13/awscli/examples/opsworks-cm/create-backup.rst awscli-1.11.44/awscli/examples/opsworks-cm/create-backup.rst --- awscli-1.11.13/awscli/examples/opsworks-cm/create-backup.rst 1970-01-01 00:00:00.000000000 +0000 +++ awscli-1.11.44/awscli/examples/opsworks-cm/create-backup.rst 2017-01-27 00:22:38.000000000 +0000 @@ -0,0 +1,46 @@ +**To create backups** + +The following ``create-backup`` command starts a manual backup of a Chef Automate server +named ``automate-06`` in the ``us-east-1`` region. The command adds a descriptive message to +the backup in the ``--description`` parameter.:: + + aws opsworks-cm create-backup --server-name 'automate-06' --description "state of my infrastructure at launch" + +The output shows you information similar to the following about the new backup. +*Output*:: + + { + "Backups": [ + { + "BackupArn": "string", + "BackupId": "automate-06-20160729133847520", + "BackupType": "MANUAL", + "CreatedAt": 2016-07-29T13:38:47.520Z, + "Description": "state of my infrastructure at launch", + "Engine": "Chef", + "EngineModel": "Single", + "EngineVersion": "12", + "InstanceProfileArn": "arn:aws:iam::1019881987024:instance-profile/automate-06-1010V4UU2WRM2", + "InstanceType": "m4.large", + "KeyPair": "", + "PreferredBackupWindow": "", + "PreferredMaintenanceWindow": "", + "S3LogUrl": "https://s3.amazonaws.com/automate-06/automate-06-20160729133847520", + "SecurityGroupIds": [ "sg-1a24c270" ], + "ServerName": "automate-06", + "ServiceRoleArn": "arn:aws:iam::1019881987024:role/aws-opsworks-cm-service-role.1114810729735", + "Status": "OK", + "StatusDescription": "", + "SubnetIds": [ "subnet-49436a18" ], + "ToolsVersion": "string", + "UserArn": "arn:aws:iam::1019881987024:user/opsworks-user" + } + ], + } + +**More Information** + +For more information, see `Back Up and Restore an AWS OpsWorks for Chef Automate Server`_ in the *AWS OpsWorks User Guide*. + +.. _`Back Up and Restore an AWS OpsWorks for Chef Automate Server`: http://docs.aws.amazon.com/opsworks/latest/userguide/opscm-backup-restore.html + diff -Nru awscli-1.11.13/awscli/examples/opsworks-cm/create-server.rst awscli-1.11.44/awscli/examples/opsworks-cm/create-server.rst --- awscli-1.11.13/awscli/examples/opsworks-cm/create-server.rst 1970-01-01 00:00:00.000000000 +0000 +++ awscli-1.11.44/awscli/examples/opsworks-cm/create-server.rst 2017-01-27 00:22:38.000000000 +0000 @@ -0,0 +1,51 @@ +**To create a server** + +The following ``create-server`` command creates a new Chef Automate server +named ``automate-06`` in your default region. Note that defaults are used for +most other settings, such as number of backups to retain, and maintenance and backup +start times. Before you run a ``create-server`` command, complete prerequisites in +.. _`Getting Started with AWS OpsWorks for Chef Automate`: http://docs.aws.amazon.com/opsworks/latest/userguide/gettingstarted-opscm.html +.:: + + aws opsworks-cm create-server --engine "Chef" --engine-model "Single" --engine-version "12" --server-name "automate-06" --instance-profile-arn "arn:aws:iam::1019881987024:instance-profile/aws-opsworks-cm-ec2-role" --instance-type "t2.medium" --key-pair "amazon-test" --service-role-arn "arn:aws:iam::044726508045:role/aws-opsworks-cm-service-role" + +The output shows you information similar to the following about the new server. +*Output*:: + + { + "Server": { + "BackupRetentionCount": 10, + "CreatedAt": 2016-07-29T13:38:47.520Z, + "DisableAutomatedBackup": FALSE, + "Endpoint": "https://opsworks-cm.us-east-1.amazonaws.com", + "Engine": "Chef", + "EngineAttributes": [ + { + "Name": "CHEF_DELIVERY_ADMIN_PASSWORD", + "Value": "1Password1" + } + ], + "EngineModel": "Single", + "EngineVersion": "12", + "InstanceProfileArn": "arn:aws:iam::1019881987024:instance-profile/aws-opsworks-cm-ec2-role", + "InstanceType": "t2.medium", + "KeyPair": "amazon-test", + "MaintenanceStatus": "", + "PreferredBackupWindow": "Sun:02:00", + "PreferredMaintenanceWindow": "00:00", + "SecurityGroupIds": [ "sg-1a24c270" ], + "ServerArn": "arn:aws:iam::1019881987024:instance/automate-06-1010V4UU2WRM2", + "ServerName": "automate-06", + "ServiceRoleArn": "arn:aws:iam::1019881987024:role/aws-opsworks-cm-service-role", + "Status": "CREATING", + "StatusReason": "", + "SubnetIds": [ "subnet-49436a18" ] + } +} + +**More Information** + +For more information, see `UpdateServer`_ in the *AWS OpsWorks for Chef Automate API Reference*. + +.. _`UpdateServer`: http://docs.aws.amazon.com/opsworks-cm/latest/APIReference/API_UpdateServer.html + diff -Nru awscli-1.11.13/awscli/examples/opsworks-cm/delete-backup.rst awscli-1.11.44/awscli/examples/opsworks-cm/delete-backup.rst --- awscli-1.11.13/awscli/examples/opsworks-cm/delete-backup.rst 1970-01-01 00:00:00.000000000 +0000 +++ awscli-1.11.44/awscli/examples/opsworks-cm/delete-backup.rst 2017-01-27 00:22:38.000000000 +0000 @@ -0,0 +1,17 @@ +**To delete backups** + +The following ``delete-backup`` command deletes a manual or automated backup of +a Chef Automate server, identified by the backup ID. This command is useful when +you are approaching the maximum number of backups that you can save, or you want +to minimize your Amazon S3 storage costs.:: + + aws opsworks-cm delete-backup --backup-id "automate-06-2016-11-19T23:42:40.240Z" + +The output shows whether the backup deletion succeeded. + +**More Information** + +For more information, see `Back Up and Restore an AWS OpsWorks for Chef Automate Server`_ in the *AWS OpsWorks User Guide*. + +.. _`Back Up and Restore an AWS OpsWorks for Chef Automate Server`: http://docs.aws.amazon.com/opsworks/latest/userguide/opscm-backup-restore.html + diff -Nru awscli-1.11.13/awscli/examples/opsworks-cm/delete-server.rst awscli-1.11.44/awscli/examples/opsworks-cm/delete-server.rst --- awscli-1.11.13/awscli/examples/opsworks-cm/delete-server.rst 1970-01-01 00:00:00.000000000 +0000 +++ awscli-1.11.44/awscli/examples/opsworks-cm/delete-server.rst 2017-01-27 00:22:38.000000000 +0000 @@ -0,0 +1,16 @@ +**To delete servers** + +The following ``delete-server`` command deletes a Chef Automate server, identified +by the server's name. After the server is deleted, it is no longer returned by +``DescribeServer`` requests.:: + + aws opsworks-cm delete-server --server-name "automate-06" + +The output shows whether the server deletion succeeded. + +**More Information** + +For more information, see `Delete an AWS OpsWorks for Chef Automate Server`_ in the *AWS OpsWorks User Guide*. + +.. _`Delete an AWS OpsWorks for Chef Automate Server`: http://docs.aws.amazon.com/opsworks/latest/userguide/opscm-delete-server.html + diff -Nru awscli-1.11.13/awscli/examples/opsworks-cm/describe-account-attributes.rst awscli-1.11.44/awscli/examples/opsworks-cm/describe-account-attributes.rst --- awscli-1.11.13/awscli/examples/opsworks-cm/describe-account-attributes.rst 1970-01-01 00:00:00.000000000 +0000 +++ awscli-1.11.44/awscli/examples/opsworks-cm/describe-account-attributes.rst 2017-01-27 00:22:38.000000000 +0000 @@ -0,0 +1,26 @@ +**To describe account attributes** + +The following ``describe-account-attributes`` command returns information about your +account's usage of AWS OpsWorks for Chef Automate resources.:: + + aws opsworks-cm describe-account-attributes + +The output for each account attribute entry returned by the command resembles the following. +*Output*:: + + { + "Attributes": [ + { + "Maximum": 5, + "Name": "ServerLimit", + "Used": 2 + } + ] + } + +**More Information** + +For more information, see `DescribeAccountAttributes`_ in the *AWS OpsWorks for Chef Automate API Reference*. + +.. _`DescribeAccountAttributes`: http://docs.aws.amazon.com/opsworks-cm/latest/APIReference/API_DescribeAccountAttributes.html + diff -Nru awscli-1.11.13/awscli/examples/opsworks-cm/describe-backups.rst awscli-1.11.44/awscli/examples/opsworks-cm/describe-backups.rst --- awscli-1.11.13/awscli/examples/opsworks-cm/describe-backups.rst 1970-01-01 00:00:00.000000000 +0000 +++ awscli-1.11.44/awscli/examples/opsworks-cm/describe-backups.rst 2017-01-27 00:22:38.000000000 +0000 @@ -0,0 +1,45 @@ +**To describe backups** + +The following ``describe-backups`` command returns information about all backups +associated with your account in your default region.:: + + aws opsworks-cm describe-backups + +The output for each backup entry returned by the command resembles the following. +*Output*:: + + { + "Backups": [ + { + "BackupArn": "string", + "BackupId": "automate-06-20160729133847520", + "BackupType": "MANUAL", + "CreatedAt": 2016-07-29T13:38:47.520Z, + "Description": "state of my infrastructure at launch", + "Engine": "Chef", + "EngineModel": "Single", + "EngineVersion": "12", + "InstanceProfileArn": "arn:aws:iam::1019881987024:instance-profile/automate-06-1010V4UU2WRM2", + "InstanceType": "m4.large", + "KeyPair": "", + "PreferredBackupWindow": "", + "PreferredMaintenanceWindow": "", + "S3LogUrl": "https://s3.amazonaws.com/automate-06/automate-06-20160729133847520", + "SecurityGroupIds": [ "sg-1a24c270" ], + "ServerName": "automate-06", + "ServiceRoleArn": "arn:aws:iam::1019881987024:role/aws-opsworks-cm-service-role.1114810729735", + "Status": "Successful", + "StatusDescription": "", + "SubnetIds": [ "subnet-49436a18" ], + "ToolsVersion": "string", + "UserArn": "arn:aws:iam::1019881987024:user/opsworks-user" + } + ], + } + +**More Information** + +For more information, see `Back Up and Restore an AWS OpsWorks for Chef Automate Server`_ in the *AWS OpsWorks User Guide*. + +.. _`Back Up and Restore an AWS OpsWorks for Chef Automate Server`: http://docs.aws.amazon.com/opsworks/latest/userguide/opscm-backup-restore.html + diff -Nru awscli-1.11.13/awscli/examples/opsworks-cm/describe-events.rst awscli-1.11.44/awscli/examples/opsworks-cm/describe-events.rst --- awscli-1.11.13/awscli/examples/opsworks-cm/describe-events.rst 1970-01-01 00:00:00.000000000 +0000 +++ awscli-1.11.44/awscli/examples/opsworks-cm/describe-events.rst 2017-01-27 00:22:38.000000000 +0000 @@ -0,0 +1,27 @@ +**To describe events** + +The following ``describe-events`` command returns information about all events +that are associated with a Chef Automate server named ``automate-06``.:: + + aws opsworks-cm describe-events --server-name 'automate-06' + +The output for each event entry returned by the command resembles the following. +*Output*:: + + { + "ServerEvents": [ + { + "CreatedAt": 2016-07-29T13:38:47.520Z, + "LogUrl": "https://s3.amazonaws.com/automate-06/automate-06-20160729133847520", + "Message": "Updates successfully installed.", + "ServerName": "automate-06" + } + ] +} + +**More Information** + +For more information, see `General Troubleshooting Tips`_ in the *AWS OpsWorks User Guide*. + +.. _`General Troubleshooting Tips`: http://docs.aws.amazon.com/opsworks/latest/userguide/troubleshoot-opscm.html#d0e4561 + diff -Nru awscli-1.11.13/awscli/examples/opsworks-cm/describe-node-association-status.rst awscli-1.11.44/awscli/examples/opsworks-cm/describe-node-association-status.rst --- awscli-1.11.13/awscli/examples/opsworks-cm/describe-node-association-status.rst 1970-01-01 00:00:00.000000000 +0000 +++ awscli-1.11.44/awscli/examples/opsworks-cm/describe-node-association-status.rst 2017-01-27 00:22:38.000000000 +0000 @@ -0,0 +1,20 @@ +**To describe node association status** + +The following ``describe-node-association-status`` command returns the status of a +request to associate a node with a Chef Automate server named ``automate-06``.:: + + aws opsworks-cm describe-node-association-status --server-name "automate-06" --node-association-status-token "AflJKl+/GoKLZJBdDQEx0O65CDi57blQe9nKM8joSok0pQ9xr8DqApBN9/1O6sLdSvlfDEKkEx+eoCHvjoWHaOs=" + +The output for each account attribute entry returned by the command resembles the following. +*Output*:: + + { + "NodeAssociationStatus": "IN_PROGRESS" + } + +**More Information** + +For more information, see `DescribeNodeAssociationStatus`_ in the *AWS OpsWorks for Chef Automate API Reference*. + +.. _`DescribeNodeAssociationStatus`: http://docs.aws.amazon.com/opsworks-cm/latest/APIReference/API_DescribeNodeAssociationStatus.html + diff -Nru awscli-1.11.13/awscli/examples/opsworks-cm/describe-servers.rst awscli-1.11.44/awscli/examples/opsworks-cm/describe-servers.rst --- awscli-1.11.13/awscli/examples/opsworks-cm/describe-servers.rst 1970-01-01 00:00:00.000000000 +0000 +++ awscli-1.11.44/awscli/examples/opsworks-cm/describe-servers.rst 2017-01-27 00:22:38.000000000 +0000 @@ -0,0 +1,48 @@ +**To describe servers** + +The following ``describe-servers`` command returns information about all servers +that are associated with your account, and in your default region.:: + + aws opsworks-cm describe-servers + +The output for each server entry returned by the command resembles the following. +*Output*:: + + { + "Servers": [ + { + "BackupRetentionCount": 8, + "CreatedAt": 2016-07-29T13:38:47.520Z, + "DisableAutomatedBackup": FALSE, + "Endpoint": "https://opsworks-cm.us-east-1.amazonaws.com", + "Engine": "Chef", + "EngineAttributes": [ + { + "Name": "CHEF_DELIVERY_ADMIN_PASSWORD", + "Value": "1Password1" + } + ], + "EngineModel": "Single", + "EngineVersion": "12", + "InstanceProfileArn": "arn:aws:iam::1019881987024:instance-profile/automate-06-1010V4UU2WRM2", + "InstanceType": "m4.large", + "KeyPair": "", + "MaintenanceStatus": "SUCCESS", + "PreferredBackupWindow": "03:00", + "PreferredMaintenanceWindow": "Mon:09:00", + "SecurityGroupIds": [ "sg-1a24c270" ], + "ServerArn": "arn:aws:iam::1019881987024:instance/automate-06-1010V4UU2WRM2", + "ServerName": "automate-06", + "ServiceRoleArn": "arn:aws:iam::1019881987024:role/aws-opsworks-cm-service-role.1114810729735", + "Status": "HEALTHY", + "StatusReason": "", + "SubnetIds": [ "subnet-49436a18" ] + } + ] + } + +**More Information** + +For more information, see `DescribeServers`_ in the *AWS OpsWorks for Chef Automate API Guide*. + +.. _`DescribeServers`: http://docs.aws.amazon.com/opsworks-cm/latest/APIReference/API_DescribeServers.html diff -Nru awscli-1.11.13/awscli/examples/opsworks-cm/disassociate-node.rst awscli-1.11.44/awscli/examples/opsworks-cm/disassociate-node.rst --- awscli-1.11.13/awscli/examples/opsworks-cm/disassociate-node.rst 1970-01-01 00:00:00.000000000 +0000 +++ awscli-1.11.44/awscli/examples/opsworks-cm/disassociate-node.rst 2017-01-27 00:22:38.000000000 +0000 @@ -0,0 +1,19 @@ +**To disassociate nodes** + +The following ``disassociate-node`` command disassociates a node named ``i-44de882p``, removing the node from +management by a Chef Automate server named ``automate-06``. Valid node names are EC2 instance IDs.:: + + aws opsworks-cm disassociate-node --server-name "automate-06" --node-name "i-43de882p" --engine-attributes "Name=CHEF_ORGANIZATION,Value='default'" + +The output returned by the command resembles the following. +*Output*:: + + { + "NodeAssociationStatusToken": "AHUY8wFe4pdXtZC5DiJa5SOLp5o14DH//rHRqHDWXxwVoNBxcEy4V7R0NOFymh7E/1HumOBPsemPQFE6dcGaiFk" + } + +**More Information** + +For more information, see `Delete an AWS OpsWorks for Chef Automate Server`_ in the *AWS OpsWorks User Guide*. + +.. _`Delete an AWS OpsWorks for Chef Automate Server`: http://docs.aws.amazon.com/opsworks/latest/userguide/opscm-delete-server.html diff -Nru awscli-1.11.13/awscli/examples/opsworks-cm/restore-server.rst awscli-1.11.44/awscli/examples/opsworks-cm/restore-server.rst --- awscli-1.11.13/awscli/examples/opsworks-cm/restore-server.rst 1970-01-01 00:00:00.000000000 +0000 +++ awscli-1.11.44/awscli/examples/opsworks-cm/restore-server.rst 2017-01-27 00:22:38.000000000 +0000 @@ -0,0 +1,20 @@ +**To restore a server** + +The following ``restore-server`` command performs an in-place restoration of a +Chef Automate server named ``automate-06`` in your default region from a backup +with an ID of ``automate-06-2016-11-22T16:13:27.998Z``. Restoring a server restores +connections to the nodes that the Chef Automate server was managing at the time +that the specified backup was performed. + + aws opsworks-cm restore-server --backup-id "automate-06-2016-11-22T16:13:27.998Z" --server-name "automate-06" + +The output is the command ID only. +*Output*:: + + (None) + +**More Information** + +For more information, see `Restore a Failed AWS OpsWorks for Chef Automate Server`_ in the *AWS OpsWorks User Guide*. + +.. _`Restore a Failed AWS OpsWorks for Chef Automate Server`: http://docs.aws.amazon.com/opsworks/latest/userguide/opscm-chef-restore.html diff -Nru awscli-1.11.13/awscli/examples/opsworks-cm/start-maintenance.rst awscli-1.11.44/awscli/examples/opsworks-cm/start-maintenance.rst --- awscli-1.11.13/awscli/examples/opsworks-cm/start-maintenance.rst 1970-01-01 00:00:00.000000000 +0000 +++ awscli-1.11.44/awscli/examples/opsworks-cm/start-maintenance.rst 2017-01-27 00:22:38.000000000 +0000 @@ -0,0 +1,48 @@ +**To start maintenance** + +The following ``start-maintenance`` command manually starts maintenance on a Chef Automate server +named ``automate-06`` in your default region. This command can be useful if an earlier, automated +maintenance attempt failed, and the underlying cause of maintenance failure has been resolved.:: + + aws opsworks-cm start-maintenance --server-name 'automate-06' + +The output shows you information similar to the following about the maintenance request. +*Output*:: + + { + "Server": { + "BackupRetentionCount": 8, + "CreatedAt": 2016-07-29T13:38:47.520Z, + "DisableAutomatedBackup": TRUE, + "Endpoint": "https://opsworks-cm.us-east-1.amazonaws.com", + "Engine": "Chef", + "EngineAttributes": [ + { + "Name": "CHEF_DELIVERY_ADMIN_PASSWORD", + "Value": "1Password1" + } + ], + "EngineModel": "Single", + "EngineVersion": "12", + "InstanceProfileArn": "arn:aws:iam::1019881987024:instance-profile/automate-06-1010V4UU2WRM2", + "InstanceType": "m4.large", + "KeyPair": "", + "MaintenanceStatus": "SUCCESS", + "PreferredBackupWindow": "", + "PreferredMaintenanceWindow": "", + "SecurityGroupIds": [ "sg-1a24c270" ], + "ServerArn": "arn:aws:iam::1019881987024:instance/automate-06-1010V4UU2WRM2", + "ServerName": "automate-06", + "ServiceRoleArn": "arn:aws:iam::1019881987024:role/aws-opsworks-cm-service-role.1114810729735", + "Status": "HEALTHY", + "StatusReason": "", + "SubnetIds": [ "subnet-49436a18" ] + } +} + +**More Information** + +For more information, see `StartMaintenance`_ in the *AWS OpsWorks for Chef Automate API Reference*. + +.. _`StartMaintenance`: http://docs.aws.amazon.com/opsworks-cm/latest/APIReference/API_StartMaintenance.html + diff -Nru awscli-1.11.13/awscli/examples/opsworks-cm/update-server-engine-attributes.rst awscli-1.11.44/awscli/examples/opsworks-cm/update-server-engine-attributes.rst --- awscli-1.11.13/awscli/examples/opsworks-cm/update-server-engine-attributes.rst 1970-01-01 00:00:00.000000000 +0000 +++ awscli-1.11.44/awscli/examples/opsworks-cm/update-server-engine-attributes.rst 2017-01-27 00:22:38.000000000 +0000 @@ -0,0 +1,48 @@ +**To update server engine attributes** + +The following ``update-server-engine-attributes`` command updates the value of the +``CHEF_PIVOTAL_KEY`` engine attribute for a Chef Automate server named ``automate-06``. +It is currently not possible to change the value of other engine attributes.:: + + aws opsworks-cm update-server-engine-attributes --attribute-name CHEF_PIVOTAL_KEY --attribute-value "new key value" --server-name "automate-06" + +The output shows you information similar to the following about the updated server. +*Output*:: + + { + "Server": { + "BackupRetentionCount": 2, + "CreatedAt": 2016-07-29T13:38:47.520Z, + "DisableAutomatedBackup": FALSE, + "Endpoint": "https://opsworks-cm.us-east-1.amazonaws.com", + "Engine": "Chef", + "EngineAttributes": [ + { + "Name": "CHEF_PIVOTAL_KEY", + "Value": "new key value" + } + ], + "EngineModel": "Single", + "EngineVersion": "12", + "InstanceProfileArn": "arn:aws:iam::1019881987024:instance-profile/automate-06-1010V4UU2WRM2", + "InstanceType": "m4.large", + "KeyPair": "", + "MaintenanceStatus": "SUCCESS", + "PreferredBackupWindow": "Mon:09:15", + "PreferredMaintenanceWindow": "03:00", + "SecurityGroupIds": [ "sg-1a24c270" ], + "ServerArn": "arn:aws:iam::1019881987024:instance/automate-06-1010V4UU2WRM2", + "ServerName": "automate-06", + "ServiceRoleArn": "arn:aws:iam::1019881987024:role/aws-opsworks-cm-service-role.1114810729735", + "Status": "HEALTHY", + "StatusReason": "", + "SubnetIds": [ "subnet-49436a18" ] + } +} + +**More Information** + +For more information, see `UpdateServerEngineAttributes`_ in the *AWS OpsWorks for Chef Automate API Reference*. + +.. _`UpdateServerEngineAttributes`: http://docs.aws.amazon.com/opsworks-cm/latest/APIReference/API_UpdateServerEngineAttributes.html + diff -Nru awscli-1.11.13/awscli/examples/opsworks-cm/update-server.rst awscli-1.11.44/awscli/examples/opsworks-cm/update-server.rst --- awscli-1.11.13/awscli/examples/opsworks-cm/update-server.rst 1970-01-01 00:00:00.000000000 +0000 +++ awscli-1.11.44/awscli/examples/opsworks-cm/update-server.rst 2017-01-27 00:22:38.000000000 +0000 @@ -0,0 +1,48 @@ +**To update a server** + +The following ``update-server`` command updates the maintenance start time of a Chef Automate server +named ``automate-06`` in your default region. The ``--preferred-maintenance-window`` parameter is +added to change the start day and time of server maintenance to Mondays at 9:15 a.m. UTC.:: + + aws opsworks-cm update-server --server-name "automate-06" --preferred-maintenance-window "Mon:09:15" + +The output shows you information similar to the following about the updated server. +*Output*:: + + { + "Server": { + "BackupRetentionCount": 8, + "CreatedAt": 2016-07-29T13:38:47.520Z, + "DisableAutomatedBackup": TRUE, + "Endpoint": "https://opsworks-cm.us-east-1.amazonaws.com", + "Engine": "Chef", + "EngineAttributes": [ + { + "Name": "CHEF_DELIVERY_ADMIN_PASSWORD", + "Value": "1Password1" + } + ], + "EngineModel": "Single", + "EngineVersion": "12", + "InstanceProfileArn": "arn:aws:iam::1019881987024:instance-profile/automate-06-1010V4UU2WRM2", + "InstanceType": "m4.large", + "KeyPair": "", + "MaintenanceStatus": "OK", + "PreferredBackupWindow": "Mon:09:15", + "PreferredMaintenanceWindow": "03:00", + "SecurityGroupIds": [ "sg-1a24c270" ], + "ServerArn": "arn:aws:iam::1019881987024:instance/automate-06-1010V4UU2WRM2", + "ServerName": "automate-06", + "ServiceRoleArn": "arn:aws:iam::1019881987024:role/aws-opsworks-cm-service-role.1114810729735", + "Status": "HEALTHY", + "StatusReason": "", + "SubnetIds": [ "subnet-49436a18" ] + } +} + +**More Information** + +For more information, see `UpdateServer`_ in the *AWS OpsWorks for Chef Automate API Reference*. + +.. _`UpdateServer`: http://docs.aws.amazon.com/opsworks-cm/latest/APIReference/API_UpdateServer.html + diff -Nru awscli-1.11.13/awscli/examples/swf/register-domain.rst awscli-1.11.44/awscli/examples/swf/register-domain.rst --- awscli-1.11.13/awscli/examples/swf/register-domain.rst 2016-11-03 20:32:27.000000000 +0000 +++ awscli-1.11.44/awscli/examples/swf/register-domain.rst 2017-01-27 00:22:38.000000000 +0000 @@ -4,8 +4,7 @@ You can use the AWS CLI to register new domains. Use the ``swf register-domain`` command. There are two required parameters, ``--name``, which takes the domain name, and ``--workflow-execution-retention-period-in-days``, which takes an integer to specify the number of days to retain workflow execution data on this domain, up to a maxium period of 90 -days (for more information, see the `SWF FAQ `). If you specify zero (0) -for this value, the retention period is automatically set at the maximum duration. Otherwise, workflow execution data +days (for more information, see the `SWF FAQ `). Workflow execution data will not be retained after the specified number of days have passed. Here's an example of registering a new domain: diff -Nru awscli-1.11.13/awscli/handlers.py awscli-1.11.44/awscli/handlers.py --- awscli-1.11.13/awscli/handlers.py 2016-11-03 20:32:27.000000000 +0000 +++ awscli-1.11.44/awscli/handlers.py 2017-01-27 00:22:38.000000000 +0000 @@ -24,6 +24,7 @@ from awscli.customizations.assumerole import register_assume_role_provider from awscli.customizations.awslambda import register_lambda_create_function from awscli.customizations.cliinputjson import register_cli_input_json +from awscli.customizations.cloudformation import initialize as cloudformation_init from awscli.customizations.cloudfront import register as register_cloudfront from awscli.customizations.cloudsearch import initialize as cloudsearch_init from awscli.customizations.cloudsearchdomain import register_cloudsearchdomain @@ -71,6 +72,7 @@ from awscli.customizations.streamingoutputarg import add_streaming_output_arg from awscli.customizations.toplevelbool import register_bool_params from awscli.customizations.waiters import register_add_waiters +from awscli.customizations.opsworkscm import register_alias_opsworks_cm def awscli_initialize(event_handlers): @@ -144,3 +146,5 @@ register_cloudfront(event_handlers) register_gamelift_commands(event_handlers) register_ec2_page_size_injector(event_handlers) + cloudformation_init(event_handlers) + register_alias_opsworks_cm(event_handlers) diff -Nru awscli-1.11.13/awscli/__init__.py awscli-1.11.44/awscli/__init__.py --- awscli-1.11.13/awscli/__init__.py 2016-11-03 20:32:28.000000000 +0000 +++ awscli-1.11.44/awscli/__init__.py 2017-01-27 00:22:39.000000000 +0000 @@ -17,7 +17,7 @@ """ import os -__version__ = '1.11.13' +__version__ = '1.11.44' # # Get our data path to be added to botocore's search path diff -Nru awscli-1.11.13/awscli/paramfile.py awscli-1.11.44/awscli/paramfile.py --- awscli-1.11.13/awscli/paramfile.py 2016-11-03 20:32:27.000000000 +0000 +++ awscli-1.11.44/awscli/paramfile.py 2017-01-27 00:22:38.000000000 +0000 @@ -36,6 +36,10 @@ 'cloudformation.create-stack.stack-policy-url', 'cloudformation.update-stack.stack-policy-url', 'cloudformation.set-stack-policy.stack-policy-url', + # aws cloudformation package --template-file + 'custom.package.template-file', + # aws cloudformation deploy --template-file + 'custom.deploy.template-file', 'cloudformation.update-stack.stack-policy-during-update-url', # We will want to change the event name to ``s3`` as opposed to diff -Nru awscli-1.11.13/awscli/testutils.py awscli-1.11.44/awscli/testutils.py --- awscli-1.11.13/awscli/testutils.py 2016-11-03 20:32:27.000000000 +0000 +++ awscli-1.11.44/awscli/testutils.py 2017-01-27 00:22:39.000000000 +0000 @@ -463,6 +463,58 @@ super(BaseAWSPreviewCommandParamsTest, self).tearDown() +class BaseCLIWireResponseTest(unittest.TestCase): + def setUp(self): + self.environ = { + 'AWS_DATA_PATH': os.environ['AWS_DATA_PATH'], + 'AWS_DEFAULT_REGION': 'us-east-1', + 'AWS_ACCESS_KEY_ID': 'access_key', + 'AWS_SECRET_ACCESS_KEY': 'secret_key', + 'AWS_CONFIG_FILE': '' + } + self.environ_patch = mock.patch('os.environ', self.environ) + self.environ_patch.start() + self.send_patch = mock.patch('botocore.endpoint.Session.send') + self.send_is_patched = False + self.driver = create_clidriver() + + def tearDown(self): + self.environ_patch.stop() + if self.send_is_patched: + self.send_patch.stop() + self.send_is_patched = False + + def patch_send(self, status_code=200, headers={}, content=b''): + if self.send_is_patched: + self.patch_send.stop() + self.send_is_patched = False + send_patch = self.send_patch.start() + send_patch.return_value = mock.Mock(status_code=status_code, + headers=headers, + content=content) + self.send_is_patched = True + + def run_cmd(self, cmd, expected_rc=0): + if not isinstance(cmd, list): + cmdlist = cmd.split() + else: + cmdlist = cmd + with capture_output() as captured: + try: + rc = self.driver.main(cmdlist) + except SystemExit as e: + rc = e.code + stderr = captured.stderr.getvalue() + stdout = captured.stdout.getvalue() + self.assertEqual( + rc, expected_rc, + "Unexpected rc (expected: %s, actual: %s) for command: %s\n" + "stdout:\n%sstderr:\n%s" % ( + expected_rc, rc, cmd, stdout, stderr)) + return stdout, stderr, rc + + + class FileCreator(object): def __init__(self): self.rootdir = tempfile.mkdtemp() @@ -694,6 +746,10 @@ # Subclasses can use this to define extra teardown steps. pass + def override_parser(self, **kwargs): + factory = self.session.get_component('response_parser_factory') + factory.set_parser_defaults(**kwargs) + def create_client_for_bucket(self, bucket_name): region = self.regions.get(bucket_name, self.region) client = self.session.create_client('s3', region_name=region) @@ -775,6 +831,16 @@ response = client.head_object(Bucket=bucket_name, Key=key_name) return response + def wait_until_key_exists(self, bucket_name, key_name, extra_params=None, + min_successes=3): + client = self.create_client_for_bucket(bucket_name) + waiter = client.get_waiter('object_exists') + params = {'Bucket': bucket_name, 'Key': key_name} + if extra_params is not None: + params.update(extra_params) + for _ in range(min_successes): + waiter.wait(**params) + def assert_no_errors(self, p): self.assertEqual( p.rc, 0, diff -Nru awscli-1.11.13/awscli/topics/config-vars.rst awscli-1.11.44/awscli/topics/config-vars.rst --- awscli-1.11.13/awscli/topics/config-vars.rst 2016-11-03 20:32:27.000000000 +0000 +++ awscli-1.11.44/awscli/topics/config-vars.rst 2017-01-27 00:22:39.000000000 +0000 @@ -60,15 +60,17 @@ The AWS CLI has a few general options: -=========== ========= ===================== ===================== ============================ -Variable Option Config Entry Environment Variable Description -=========== ========= ===================== ===================== ============================ -profile --profile N/A AWS_DEFAULT_PROFILE Default profile name ------------ --------- --------------------- --------------------- ---------------------------- -region --region region AWS_DEFAULT_REGION Default AWS Region ------------ --------- --------------------- --------------------- ---------------------------- -output --output output AWS_DEFAULT_OUTPUT Default output style -=========== ========= ===================== ===================== ============================ +==================== ========= ===================== ===================== ============================ +Variable Option Config Entry Environment Variable Description +==================== ========= ===================== ===================== ============================ +profile --profile N/A AWS_DEFAULT_PROFILE Default profile name +-------------------- --------- --------------------- --------------------- ---------------------------- +region --region region AWS_DEFAULT_REGION Default AWS Region +-------------------- --------- --------------------- --------------------- ---------------------------- +output --output output AWS_DEFAULT_OUTPUT Default output style +-------------------- --------- --------------------- --------------------- ---------------------------- +cli_timestamp_format N/A cli_timestamp_format N/A Output format of timestamps +==================== ========= ===================== ===================== ============================ The third column, Config Entry, is the value you would specify in the AWS CLI config file. By default, this location is ``~/.aws/config``. If you need to @@ -81,6 +83,12 @@ * table * text +``cli_timestamp_format`` controls the format of timestamps displayed by the AWS CLI. +The valid values of the ``cli_timestamp_format`` configuration varaible are: + +* none - Display the timestamp exactly as received from the HTTP response. +* iso8601 - Reformat timestamp using iso8601 and your local timezone. + When you specify a profile, either using ``--profile profile-name`` or by setting a value for the ``AWS_DEFAULT_PROFILE`` environment variable, profile name you provide is used to find the corresponding section in the AWS CLI diff -Nru awscli-1.11.13/awscli/utils.py awscli-1.11.44/awscli/utils.py --- awscli-1.11.13/awscli/utils.py 2016-11-03 20:32:27.000000000 +0000 +++ awscli-1.11.44/awscli/utils.py 2017-01-27 00:22:38.000000000 +0000 @@ -141,3 +141,8 @@ yield finally: signal.signal(signal.SIGINT, original) + + +def emit_top_level_args_parsed_event(session, args): + session.emit( + 'top-level-args-parsed', parsed_args=args, session=session) diff -Nru awscli-1.11.13/awscli.egg-info/PKG-INFO awscli-1.11.44/awscli.egg-info/PKG-INFO --- awscli-1.11.13/awscli.egg-info/PKG-INFO 2016-11-03 20:32:28.000000000 +0000 +++ awscli-1.11.44/awscli.egg-info/PKG-INFO 2017-01-27 00:22:39.000000000 +0000 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: awscli -Version: 1.11.13 +Version: 1.11.44 Summary: Universal Command Line Environment for AWS. Home-page: http://aws.amazon.com/cli/ Author: Amazon Web Services @@ -13,7 +13,7 @@ .. image:: https://travis-ci.org/aws/aws-cli.svg?branch=develop :target: https://travis-ci.org/aws/aws-cli :alt: Build Status - + .. image:: https://badges.gitter.im/aws/aws-cli.svg :target: https://gitter.im/aws/aws-cli :alt: Gitter @@ -28,6 +28,7 @@ * 3.3.x and greater * 3.4.x and greater * 3.5.x and greater + * 3.6.x and greater .. attention:: We recommend that all customers regularly monitor the @@ -193,25 +194,27 @@ configured either with environment variables, configuration file entries or both. The following table documents these. - =========== =========== ===================== ===================== ============================ - Variable Option Config Entry Environment Variable Description - =========== =========== ===================== ===================== ============================ - profile --profile profile AWS_DEFAULT_PROFILE Default profile name - ----------- ----------- --------------------- --------------------- ---------------------------- - region --region region AWS_DEFAULT_REGION Default AWS Region - ----------- ----------- --------------------- --------------------- ---------------------------- - config_file AWS_CONFIG_FILE Alternate location of config - ----------- ----------- --------------------- --------------------- ---------------------------- - output --output output AWS_DEFAULT_OUTPUT Default output style - ----------- ----------- --------------------- --------------------- ---------------------------- - ca_bundle --ca-bundle ca_bundle AWS_CA_BUNDLE CA Certificate Bundle - ----------- ----------- --------------------- --------------------- ---------------------------- - access_key aws_access_key_id AWS_ACCESS_KEY_ID AWS Access Key - ----------- ----------- --------------------- --------------------- ---------------------------- - secret_key aws_secret_access_key AWS_SECRET_ACCESS_KEY AWS Secret Key - ----------- ----------- --------------------- --------------------- ---------------------------- - token aws_session_token AWS_SESSION_TOKEN AWS Token (temp credentials) - =========== =========== ===================== ===================== ============================ + ==================== =========== ===================== ===================== ============================ + Variable Option Config Entry Environment Variable Description + ==================== =========== ===================== ===================== ============================ + profile --profile profile AWS_DEFAULT_PROFILE Default profile name + -------------------- ----------- --------------------- --------------------- ---------------------------- + region --region region AWS_DEFAULT_REGION Default AWS Region + -------------------- ----------- --------------------- --------------------- ---------------------------- + config_file AWS_CONFIG_FILE Alternate location of config + -------------------- ----------- --------------------- --------------------- ---------------------------- + output --output output AWS_DEFAULT_OUTPUT Default output style + -------------------- ----------- --------------------- --------------------- ---------------------------- + ca_bundle --ca-bundle ca_bundle AWS_CA_BUNDLE CA Certificate Bundle + -------------------- ----------- --------------------- --------------------- ---------------------------- + access_key aws_access_key_id AWS_ACCESS_KEY_ID AWS Access Key + -------------------- ----------- --------------------- --------------------- ---------------------------- + secret_key aws_secret_access_key AWS_SECRET_ACCESS_KEY AWS Secret Key + -------------------- ----------- --------------------- --------------------- ---------------------------- + token aws_session_token AWS_SESSION_TOKEN AWS Token (temp credentials) + -------------------- ----------- --------------------- --------------------- ---------------------------- + cli_timestamp_format cli_timestamp_format Ouput format of timestamps + ==================== =========== ===================== ===================== ============================ ^^^^^^^^ Examples @@ -429,3 +432,4 @@ Classifier: Programming Language :: Python :: 3.3 Classifier: Programming Language :: Python :: 3.4 Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 diff -Nru awscli-1.11.13/awscli.egg-info/requires.txt awscli-1.11.44/awscli.egg-info/requires.txt --- awscli-1.11.13/awscli.egg-info/requires.txt 2016-11-03 20:32:28.000000000 +0000 +++ awscli-1.11.44/awscli.egg-info/requires.txt 2017-01-27 00:22:39.000000000 +0000 @@ -1,8 +1,9 @@ -botocore==1.4.70 +botocore==1.5.7 colorama>=0.2.5,<=0.3.7 docutils>=0.10 rsa>=3.1.2,<=3.5.0 s3transfer>=0.1.9,<0.2.0 +PyYAML>=3.10,<=3.12 [:python_version=="2.6"] -argparse>=1.1 \ No newline at end of file +argparse>=1.1 diff -Nru awscli-1.11.13/awscli.egg-info/SOURCES.txt awscli-1.11.44/awscli.egg-info/SOURCES.txt --- awscli-1.11.13/awscli.egg-info/SOURCES.txt 2016-11-03 20:32:28.000000000 +0000 +++ awscli-1.11.44/awscli.egg-info/SOURCES.txt 2017-01-27 00:22:39.000000000 +0000 @@ -5,11 +5,13 @@ setup.cfg setup.py awscli/__init__.py +awscli/alias.py awscli/argparser.py awscli/argprocess.py awscli/arguments.py awscli/clidocs.py awscli/clidriver.py +awscli/commands.py awscli/compat.py awscli/completer.py awscli/errorhandler.py @@ -51,6 +53,7 @@ awscli/customizations/iot_data.py awscli/customizations/kms.py awscli/customizations/opsworks.py +awscli/customizations/opsworkscm.py awscli/customizations/paginate.py awscli/customizations/preview.py awscli/customizations/putmetricdata.py @@ -65,6 +68,14 @@ awscli/customizations/toplevelbool.py awscli/customizations/utils.py awscli/customizations/waiters.py +awscli/customizations/cloudformation/__init__.py +awscli/customizations/cloudformation/artifact_exporter.py +awscli/customizations/cloudformation/deploy.py +awscli/customizations/cloudformation/deployer.py +awscli/customizations/cloudformation/exceptions.py +awscli/customizations/cloudformation/package.py +awscli/customizations/cloudformation/s3uploader.py +awscli/customizations/cloudformation/yamlhelper.py awscli/customizations/cloudtrail/__init__.py awscli/customizations/cloudtrail/subscribe.py awscli/customizations/cloudtrail/utils.py @@ -311,11 +322,31 @@ awscli/examples/autoscaling/suspend-processes.rst awscli/examples/autoscaling/terminate-instance-in-auto-scaling-group.rst awscli/examples/autoscaling/update-auto-scaling-group.rst +awscli/examples/batch/cancel-job.rst +awscli/examples/batch/create-compute-environment.rst +awscli/examples/batch/create-job-queue.rst +awscli/examples/batch/delete-compute-environment.rst +awscli/examples/batch/delete-job-queue.rst +awscli/examples/batch/deregister-job-definition.rst +awscli/examples/batch/describe-compute-environments.rst +awscli/examples/batch/describe-job-definitions.rst +awscli/examples/batch/describe-job-queues.rst +awscli/examples/batch/describe-jobs.rst +awscli/examples/batch/list-jobs.rst +awscli/examples/batch/register-job-definition.rst +awscli/examples/batch/submit-job.rst +awscli/examples/batch/terminate-job.rst +awscli/examples/batch/update-compute-environment.rst +awscli/examples/batch/update-job-queue.rst +awscli/examples/cloudformation/_deploy_description.rst +awscli/examples/cloudformation/_package_description.rst awscli/examples/cloudformation/cancel-update-stack.rst awscli/examples/cloudformation/create-stack.rst +awscli/examples/cloudformation/deploy.rst awscli/examples/cloudformation/describe-stacks.rst awscli/examples/cloudformation/get-template.rst awscli/examples/cloudformation/list-stacks.rst +awscli/examples/cloudformation/package.rst awscli/examples/cloudformation/update-stack.rst awscli/examples/cloudformation/validate-template.rst awscli/examples/cloudfront/create-distribution.rst @@ -332,10 +363,12 @@ awscli/examples/cloudtrail/create-trail.rst awscli/examples/cloudtrail/delete-trail.rst awscli/examples/cloudtrail/describe-trails.rst +awscli/examples/cloudtrail/get-event-selectors.rst awscli/examples/cloudtrail/get-trail-status.rst awscli/examples/cloudtrail/list-public-keys.rst awscli/examples/cloudtrail/list-tags.rst awscli/examples/cloudtrail/lookup-events.rst +awscli/examples/cloudtrail/put-event-selectors.rst awscli/examples/cloudtrail/remove-tags.rst awscli/examples/cloudtrail/start-logging.rst awscli/examples/cloudtrail/stop-logging.rst @@ -382,6 +415,7 @@ awscli/examples/codepipeline/update-pipeline.rst awscli/examples/configservice/delete-config-rule.rst awscli/examples/configservice/delete-delivery-channel.rst +awscli/examples/configservice/delete-evaluation-results.rst awscli/examples/configservice/deliver-config-snapshot.rst awscli/examples/configservice/describe-compliance-by-config-rule.rst awscli/examples/configservice/describe-compliance-by-resource.rst @@ -401,6 +435,7 @@ awscli/examples/configservice/put-config-rule.rst awscli/examples/configservice/put-configuration-recorder.rst awscli/examples/configservice/put-delivery-channel.rst +awscli/examples/configservice/start-config-rules-evaluation.rst awscli/examples/configservice/start-configuration-recorder.rst awscli/examples/configservice/stop-configuration-recorder.rst awscli/examples/configservice/subscribe.rst @@ -476,8 +511,14 @@ awscli/examples/directconnect/describe-interconnect-loa.rst awscli/examples/directconnect/describe-interconnects.rst awscli/examples/directconnect/describe-locations.rst +awscli/examples/directconnect/describe-tags.rst awscli/examples/directconnect/describe-virtual-gateways.rst awscli/examples/directconnect/describe-virtual-interfaces.rst +awscli/examples/directconnect/tag-resource.rst +awscli/examples/directconnect/untag-resource.rst +awscli/examples/discovery/describe-agents.rst +awscli/examples/discovery/describe-configurations.rst +awscli/examples/discovery/list-configurations.rst awscli/examples/dms/create-endpoint.rst awscli/examples/dms/create-replication-instance.rst awscli/examples/dms/create-replication-task.rst @@ -499,10 +540,13 @@ awscli/examples/ec2/accept-vpc-peering-connection.rst awscli/examples/ec2/allocate-address.rst awscli/examples/ec2/allocate-hosts.rst +awscli/examples/ec2/assign-ipv6-addresses.rst awscli/examples/ec2/assign-private-ip-addresses.rst awscli/examples/ec2/associate-address.rst awscli/examples/ec2/associate-dhcp-options.rst awscli/examples/ec2/associate-route-table.rst +awscli/examples/ec2/associate-subnet-cidr-block.rst +awscli/examples/ec2/associate-vpc-cidr-block.rst awscli/examples/ec2/attach-classic-link-vpc.rst awscli/examples/ec2/attach-internet-gateway.rst awscli/examples/ec2/attach-network-interface.rst @@ -521,6 +565,7 @@ awscli/examples/ec2/copy-snapshot.rst awscli/examples/ec2/create-customer-gateway.rst awscli/examples/ec2/create-dhcp-options.rst +awscli/examples/ec2/create-egress-only-internet-gateway.rst awscli/examples/ec2/create-flow-logs.rst awscli/examples/ec2/create-image.rst awscli/examples/ec2/create-instance-export-task.rst @@ -547,6 +592,7 @@ awscli/examples/ec2/create-vpn-gateway.rst awscli/examples/ec2/delete-customer-gateway.rst awscli/examples/ec2/delete-dhcp-options.rst +awscli/examples/ec2/delete-egress-only-internet-gateway.rst awscli/examples/ec2/delete-flow-logs.rst awscli/examples/ec2/delete-internet-gateway.rst awscli/examples/ec2/delete-key-pair.rst @@ -578,6 +624,7 @@ awscli/examples/ec2/describe-conversion-tasks.rst awscli/examples/ec2/describe-customer-gateways.rst awscli/examples/ec2/describe-dhcp-options.rst +awscli/examples/ec2/describe-egress-only-internet-gateways.rst awscli/examples/ec2/describe-export-tasks.rst awscli/examples/ec2/describe-flow-logs.rst awscli/examples/ec2/describe-hosts.rst @@ -639,6 +686,8 @@ awscli/examples/ec2/disable-vpc-classic-link.rst awscli/examples/ec2/disassociate-address.rst awscli/examples/ec2/disassociate-route-table.rst +awscli/examples/ec2/disassociate-subnet-cidr-block.rst +awscli/examples/ec2/disassociate-vpc-cidr-block.rst awscli/examples/ec2/enable-vgw-route-propagation.rst awscli/examples/ec2/enable-volume-io.rst awscli/examples/ec2/enable-vpc-classic-link-dns-support.rst @@ -688,6 +737,7 @@ awscli/examples/ec2/start-instances.rst awscli/examples/ec2/stop-instances.rst awscli/examples/ec2/terminate-instances.rst +awscli/examples/ec2/unassign-ipv6-addresses.rst awscli/examples/ec2/unassign-private-ip-addresses.rst awscli/examples/ec2/unmonitor-instances.rst awscli/examples/ecr/batch-delete-image.rst @@ -1066,6 +1116,21 @@ awscli/examples/opsworks/update-my-user-profile.rst awscli/examples/opsworks/update-rds-db-instance.rst awscli/examples/opsworks/update-volume.rst +awscli/examples/opsworks-cm/associate-node.rst +awscli/examples/opsworks-cm/create-backup.rst +awscli/examples/opsworks-cm/create-server.rst +awscli/examples/opsworks-cm/delete-backup.rst +awscli/examples/opsworks-cm/delete-server.rst +awscli/examples/opsworks-cm/describe-account-attributes.rst +awscli/examples/opsworks-cm/describe-backups.rst +awscli/examples/opsworks-cm/describe-events.rst +awscli/examples/opsworks-cm/describe-node-association-status.rst +awscli/examples/opsworks-cm/describe-servers.rst +awscli/examples/opsworks-cm/disassociate-node.rst +awscli/examples/opsworks-cm/restore-server.rst +awscli/examples/opsworks-cm/start-maintenance.rst +awscli/examples/opsworks-cm/update-server-engine-attributes.rst +awscli/examples/opsworks-cm/update-server.rst awscli/examples/rds/add-tag-to-resource.rst awscli/examples/rds/create-db-instance.rst awscli/examples/rds/create-db-security-group.rst diff -Nru awscli-1.11.13/bin/aws.cmd awscli-1.11.44/bin/aws.cmd --- awscli-1.11.13/bin/aws.cmd 2016-11-03 20:32:27.000000000 +0000 +++ awscli-1.11.44/bin/aws.cmd 2017-01-27 00:22:38.000000000 +0000 @@ -17,6 +17,7 @@ ) ) %PythonExe% -x %PythonExeFlags% "%~f0" %* +exit /B %ERRORLEVEL% goto :EOF :SetPythonExe diff -Nru awscli-1.11.13/debian/changelog awscli-1.11.44/debian/changelog --- awscli-1.11.13/debian/changelog 2017-01-10 19:32:40.000000000 +0000 +++ awscli-1.11.44/debian/changelog 2017-02-02 09:12:34.000000000 +0000 @@ -1,9 +1,11 @@ -awscli (1.11.13-1ubuntu1) zesty; urgency=high +awscli (1.11.44-1) unstable; urgency=medium - * debian/control: awscli 1.11.? requires python3-botocore(>=1.4.?) - - Depend on python3-botocore(>=1.4.70) (LP: #1654315) + * New upstream version 1.11.44 + * debian/rules: Rename a bash completion file. (Closes: #823398) + * debian/control: add version info to depending packages. + (Closes: #850867, #851685) - -- Kamal Mostafa Tue, 10 Jan 2017 11:25:28 -0800 + -- TANIGUCHI Takaki Thu, 02 Feb 2017 18:12:34 +0900 awscli (1.11.13-1) unstable; urgency=medium diff -Nru awscli-1.11.13/debian/control awscli-1.11.44/debian/control --- awscli-1.11.13/debian/control 2017-01-12 17:10:33.000000000 +0000 +++ awscli-1.11.44/debian/control 2017-02-02 09:12:34.000000000 +0000 @@ -1,20 +1,20 @@ Source: awscli Section: admin Priority: optional -Maintainer: Ubuntu Developers -XSBC-Original-Maintainer: Debian Python Modules Team +Maintainer: Debian Python Modules Team Uploaders: TANIGUCHI Takaki Build-Depends: debhelper (>= 9) , python3 , python3-setuptools Build-Depends-Indep: python3-six - , python3-botocore - , python3-colorama - , python3-docutils + , python3-botocore(>=1.5.7) + , python3-colorama(>=0.2.5) + , python3-docutils(>=0.10) , python3-bcdoc , python3-pyasn1 - , python3-rsa - , python3-s3transfer + , python3-rsa(>=3.1.2) + , python3-s3transfer(>=0.1.9) + , python3-yaml(>=3.10) Standards-Version: 3.9.8 Homepage: http://aws.amazon.com/cli/ Vcs-Git: https://anonscm.debian.org/git/python-modules/packages/awscli.git @@ -23,7 +23,7 @@ Package: awscli Architecture: all -Depends: python3, python3-botocore(>=1.4.70), ${python3:Depends}, ${misc:Depends} +Depends: python3, python3-botocore(>=1.3.9), ${python3:Depends}, ${misc:Depends} Description: Universal Command Line Environment for AWS This package provides a unified command line interface to many Amazon Web Services. diff -Nru awscli-1.11.13/debian/rules awscli-1.11.44/debian/rules --- awscli-1.11.13/debian/rules 2016-11-10 10:50:29.000000000 +0000 +++ awscli-1.11.44/debian/rules 2017-02-02 09:12:34.000000000 +0000 @@ -10,7 +10,7 @@ override_dh_auto_install: python3 setup.py install --root=debian/awscli --install-layout=deb mv $(CURDIR)/debian/awscli/usr/bin/aws_bash_completer \ - $(CURDIR)/debian/awscli/usr/share/bash-completion/completions + $(CURDIR)/debian/awscli/usr/share/bash-completion/completions/aws mv $(CURDIR)/debian/awscli/usr/bin/aws_zsh_completer.sh \ $(CURDIR)/debian/awscli/usr/share/zsh/vendor-completions/_awscli rm $(CURDIR)/debian/awscli/usr/bin/aws.cmd @@ -18,7 +18,7 @@ override_dh_fixperms: dh_fixperms chmod -x $(CURDIR)/debian/awscli/usr/lib/python3/dist-packages/awscli/examples/*/*.rst - chmod -x $(CURDIR)/debian/awscli/usr/share/bash-completion/completions/aws_bash_completer + chmod -x $(CURDIR)/debian/awscli/usr/share/bash-completion/completions/aws chmod -x $(CURDIR)/debian/awscli/usr/share/zsh/vendor-completions/_awscli # override_dh_auto_build: diff -Nru awscli-1.11.13/LICENSE.txt awscli-1.11.44/LICENSE.txt --- awscli-1.11.13/LICENSE.txt 2016-11-03 20:32:27.000000000 +0000 +++ awscli-1.11.44/LICENSE.txt 2017-01-27 00:22:38.000000000 +0000 @@ -1,4 +1,4 @@ -Copyright 2012-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. +Copyright 2012-2017 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 diff -Nru awscli-1.11.13/PKG-INFO awscli-1.11.44/PKG-INFO --- awscli-1.11.13/PKG-INFO 2016-11-03 20:32:29.000000000 +0000 +++ awscli-1.11.44/PKG-INFO 2017-01-27 00:22:40.000000000 +0000 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: awscli -Version: 1.11.13 +Version: 1.11.44 Summary: Universal Command Line Environment for AWS. Home-page: http://aws.amazon.com/cli/ Author: Amazon Web Services @@ -13,7 +13,7 @@ .. image:: https://travis-ci.org/aws/aws-cli.svg?branch=develop :target: https://travis-ci.org/aws/aws-cli :alt: Build Status - + .. image:: https://badges.gitter.im/aws/aws-cli.svg :target: https://gitter.im/aws/aws-cli :alt: Gitter @@ -28,6 +28,7 @@ * 3.3.x and greater * 3.4.x and greater * 3.5.x and greater + * 3.6.x and greater .. attention:: We recommend that all customers regularly monitor the @@ -193,25 +194,27 @@ configured either with environment variables, configuration file entries or both. The following table documents these. - =========== =========== ===================== ===================== ============================ - Variable Option Config Entry Environment Variable Description - =========== =========== ===================== ===================== ============================ - profile --profile profile AWS_DEFAULT_PROFILE Default profile name - ----------- ----------- --------------------- --------------------- ---------------------------- - region --region region AWS_DEFAULT_REGION Default AWS Region - ----------- ----------- --------------------- --------------------- ---------------------------- - config_file AWS_CONFIG_FILE Alternate location of config - ----------- ----------- --------------------- --------------------- ---------------------------- - output --output output AWS_DEFAULT_OUTPUT Default output style - ----------- ----------- --------------------- --------------------- ---------------------------- - ca_bundle --ca-bundle ca_bundle AWS_CA_BUNDLE CA Certificate Bundle - ----------- ----------- --------------------- --------------------- ---------------------------- - access_key aws_access_key_id AWS_ACCESS_KEY_ID AWS Access Key - ----------- ----------- --------------------- --------------------- ---------------------------- - secret_key aws_secret_access_key AWS_SECRET_ACCESS_KEY AWS Secret Key - ----------- ----------- --------------------- --------------------- ---------------------------- - token aws_session_token AWS_SESSION_TOKEN AWS Token (temp credentials) - =========== =========== ===================== ===================== ============================ + ==================== =========== ===================== ===================== ============================ + Variable Option Config Entry Environment Variable Description + ==================== =========== ===================== ===================== ============================ + profile --profile profile AWS_DEFAULT_PROFILE Default profile name + -------------------- ----------- --------------------- --------------------- ---------------------------- + region --region region AWS_DEFAULT_REGION Default AWS Region + -------------------- ----------- --------------------- --------------------- ---------------------------- + config_file AWS_CONFIG_FILE Alternate location of config + -------------------- ----------- --------------------- --------------------- ---------------------------- + output --output output AWS_DEFAULT_OUTPUT Default output style + -------------------- ----------- --------------------- --------------------- ---------------------------- + ca_bundle --ca-bundle ca_bundle AWS_CA_BUNDLE CA Certificate Bundle + -------------------- ----------- --------------------- --------------------- ---------------------------- + access_key aws_access_key_id AWS_ACCESS_KEY_ID AWS Access Key + -------------------- ----------- --------------------- --------------------- ---------------------------- + secret_key aws_secret_access_key AWS_SECRET_ACCESS_KEY AWS Secret Key + -------------------- ----------- --------------------- --------------------- ---------------------------- + token aws_session_token AWS_SESSION_TOKEN AWS Token (temp credentials) + -------------------- ----------- --------------------- --------------------- ---------------------------- + cli_timestamp_format cli_timestamp_format Ouput format of timestamps + ==================== =========== ===================== ===================== ============================ ^^^^^^^^ Examples @@ -429,3 +432,4 @@ Classifier: Programming Language :: Python :: 3.3 Classifier: Programming Language :: Python :: 3.4 Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 diff -Nru awscli-1.11.13/README.rst awscli-1.11.44/README.rst --- awscli-1.11.13/README.rst 2016-11-03 20:32:27.000000000 +0000 +++ awscli-1.11.44/README.rst 2017-01-27 00:22:39.000000000 +0000 @@ -5,7 +5,7 @@ .. image:: https://travis-ci.org/aws/aws-cli.svg?branch=develop :target: https://travis-ci.org/aws/aws-cli :alt: Build Status - + .. image:: https://badges.gitter.im/aws/aws-cli.svg :target: https://gitter.im/aws/aws-cli :alt: Gitter @@ -20,6 +20,7 @@ * 3.3.x and greater * 3.4.x and greater * 3.5.x and greater +* 3.6.x and greater .. attention:: We recommend that all customers regularly monitor the @@ -185,25 +186,27 @@ configured either with environment variables, configuration file entries or both. The following table documents these. -=========== =========== ===================== ===================== ============================ -Variable Option Config Entry Environment Variable Description -=========== =========== ===================== ===================== ============================ -profile --profile profile AWS_DEFAULT_PROFILE Default profile name ------------ ----------- --------------------- --------------------- ---------------------------- -region --region region AWS_DEFAULT_REGION Default AWS Region ------------ ----------- --------------------- --------------------- ---------------------------- -config_file AWS_CONFIG_FILE Alternate location of config ------------ ----------- --------------------- --------------------- ---------------------------- -output --output output AWS_DEFAULT_OUTPUT Default output style ------------ ----------- --------------------- --------------------- ---------------------------- -ca_bundle --ca-bundle ca_bundle AWS_CA_BUNDLE CA Certificate Bundle ------------ ----------- --------------------- --------------------- ---------------------------- -access_key aws_access_key_id AWS_ACCESS_KEY_ID AWS Access Key ------------ ----------- --------------------- --------------------- ---------------------------- -secret_key aws_secret_access_key AWS_SECRET_ACCESS_KEY AWS Secret Key ------------ ----------- --------------------- --------------------- ---------------------------- -token aws_session_token AWS_SESSION_TOKEN AWS Token (temp credentials) -=========== =========== ===================== ===================== ============================ +==================== =========== ===================== ===================== ============================ +Variable Option Config Entry Environment Variable Description +==================== =========== ===================== ===================== ============================ +profile --profile profile AWS_DEFAULT_PROFILE Default profile name +-------------------- ----------- --------------------- --------------------- ---------------------------- +region --region region AWS_DEFAULT_REGION Default AWS Region +-------------------- ----------- --------------------- --------------------- ---------------------------- +config_file AWS_CONFIG_FILE Alternate location of config +-------------------- ----------- --------------------- --------------------- ---------------------------- +output --output output AWS_DEFAULT_OUTPUT Default output style +-------------------- ----------- --------------------- --------------------- ---------------------------- +ca_bundle --ca-bundle ca_bundle AWS_CA_BUNDLE CA Certificate Bundle +-------------------- ----------- --------------------- --------------------- ---------------------------- +access_key aws_access_key_id AWS_ACCESS_KEY_ID AWS Access Key +-------------------- ----------- --------------------- --------------------- ---------------------------- +secret_key aws_secret_access_key AWS_SECRET_ACCESS_KEY AWS Secret Key +-------------------- ----------- --------------------- --------------------- ---------------------------- +token aws_session_token AWS_SESSION_TOKEN AWS Token (temp credentials) +-------------------- ----------- --------------------- --------------------- ---------------------------- +cli_timestamp_format cli_timestamp_format Ouput format of timestamps +==================== =========== ===================== ===================== ============================ ^^^^^^^^ Examples diff -Nru awscli-1.11.13/requirements.txt awscli-1.11.44/requirements.txt --- awscli-1.11.13/requirements.txt 2016-11-03 20:32:27.000000000 +0000 +++ awscli-1.11.44/requirements.txt 2017-01-27 00:22:38.000000000 +0000 @@ -11,3 +11,4 @@ mock==1.3.0 rsa>=3.1.2,<=3.5.0 wheel==0.24.0 +PyYAML>=3.10,<=3.12 diff -Nru awscli-1.11.13/setup.cfg awscli-1.11.44/setup.cfg --- awscli-1.11.13/setup.cfg 2016-11-03 20:32:29.000000000 +0000 +++ awscli-1.11.44/setup.cfg 2017-01-27 00:22:40.000000000 +0000 @@ -3,15 +3,15 @@ [metadata] requires-dist = - botocore==1.4.70 + botocore==1.5.7 colorama>=0.2.5,<=0.3.7 docutils>=0.10 rsa>=3.1.2,<=3.5.0 + PyYAML>=3.10,<=3.12 s3transfer>=0.1.9,<0.2.0 argparse>=1.1; python_version=="2.6" [egg_info] tag_build = tag_date = 0 -tag_svn_revision = 0 diff -Nru awscli-1.11.13/setup.py awscli-1.11.44/setup.py --- awscli-1.11.13/setup.py 2016-11-03 20:32:28.000000000 +0000 +++ awscli-1.11.44/setup.py 2017-01-27 00:22:39.000000000 +0000 @@ -6,11 +6,12 @@ import awscli -requires = ['botocore==1.4.70', +requires = ['botocore==1.5.7', 'colorama>=0.2.5,<=0.3.7', 'docutils>=0.10', 'rsa>=3.1.2,<=3.5.0', - 's3transfer>=0.1.9,<0.2.0'] + 's3transfer>=0.1.9,<0.2.0', + 'PyYAML>=3.10,<=3.12'] if sys.version_info[:2] == (2, 6): @@ -53,6 +54,7 @@ 'Programming Language :: Python :: 3.3', 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', + 'Programming Language :: Python :: 3.6', ), )