Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changes/next-release/enhancement-Migration-48043.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"type": "enhancement",
"category": "Migration",
"description": "Implement a ``--migrate-v2`` flag that detects breaking changes for AWS CLI v2 for entered commands."
}
6 changes: 3 additions & 3 deletions awscli/alias.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ def __call__(self, args, parsed_globals):
parsed_alias_args, remaining = self._parser.parse_known_args(
alias_args
)
self._update_parsed_globals(parsed_alias_args, parsed_globals)
self._update_parsed_globals(parsed_alias_args, parsed_globals, remaining)
# 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)
Expand Down Expand Up @@ -228,7 +228,7 @@ def _get_alias_args(self):
)
return alias_args

def _update_parsed_globals(self, parsed_alias_args, parsed_globals):
def _update_parsed_globals(self, parsed_alias_args, parsed_globals, remaining):
global_params_to_update = self._get_global_parameters_to_update(
parsed_alias_args
)
Expand All @@ -237,7 +237,7 @@ def _update_parsed_globals(self, parsed_alias_args, parsed_globals):
# 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)
emit_top_level_args_parsed_event(self._session, parsed_alias_args, remaining)
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)
Expand Down
8 changes: 5 additions & 3 deletions awscli/clidriver.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ def main():
def create_clidriver():
session = botocore.session.Session(EnvironmentVariables)
_set_user_agent_for_session(session)
# TODO check if full config plugins is empty or not. if it's not, we signal the warning for plugin support being provisional
# similarly, we check for api_versions config value here.
load_plugins(
session.full_config.get('plugins', {}),
event_hooks=session.get_component('event_emitter'),
Expand Down Expand Up @@ -225,7 +227,7 @@ def main(self, args=None):
# that exceptions can be raised, which should have the same
# general exception handling logic as calling into the
# command table. This is why it's in the try/except clause.
self._handle_top_level_args(parsed_args)
self._handle_top_level_args(parsed_args, remaining)
self._emit_session_event(parsed_args)
HISTORY_RECORDER.record(
'CLI_VERSION', self.session.user_agent(), 'CLI'
Expand Down Expand Up @@ -279,8 +281,8 @@ def _show_error(self, msg):
sys.stderr.write(msg)
sys.stderr.write('\n')

def _handle_top_level_args(self, args):
emit_top_level_args_parsed_event(self.session, args)
def _handle_top_level_args(self, args, remaining):
emit_top_level_args_parsed_event(self.session, args, remaining)
if args.profile:
self.session.set_config_variable('profile', args.profile)
if args.region:
Expand Down
3 changes: 3 additions & 0 deletions awscli/customizations/cloudformation/deploy.py
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,9 @@ def deploy(self, deployer, stack_name, template_str,
tags=tags
)
except exceptions.ChangeEmptyError as ex:
# TODO print the runtime check for cli v2 breakage. technically won't be breaking if --fail-on-empty-changeset is
# explicitly provided. but we cannot differentiate between whether fail-on-empty-changeset is true because it's default
# or because it's explicitly specified.
if fail_on_empty_changeset:
raise
write_exception(ex, outfile=get_stdout_text_writer())
Expand Down
19 changes: 19 additions & 0 deletions awscli/customizations/globalargs.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
# language governing permissions and limitations under the License.
import sys
import os

from awscli.customizations.argrename import HIDDEN_ALIASES
from awscli.customizations.utils import uni_print
from botocore.client import Config
from botocore import UNSIGNED
from botocore.endpoint import DEFAULT_TIMEOUT
Expand All @@ -30,6 +33,8 @@ def register_parse_global_args(cli):
unique_id='resolve-cli-read-timeout')
cli.register('top-level-args-parsed', resolve_cli_connect_timeout,
unique_id='resolve-cli-connect-timeout')
cli.register('top-level-args-parsed', detect_migration_breakage,
unique_id='detect-migration-breakage')


def resolve_types(parsed_args, **kwargs):
Expand Down Expand Up @@ -90,6 +95,20 @@ def resolve_cli_connect_timeout(parsed_args, session, **kwargs):
arg_name = 'connect_timeout'
_resolve_timeout(session, parsed_args, arg_name)

def detect_migration_breakage(parsed_args, remaining_args, session, **kwargs):
if parsed_args.v2_debug:
url_params = [param for param in remaining_args if param.startswith('http://') or param.startswith('https://')]
if parsed_args.command == 'ecr' and remaining_args[0] == 'get-login':
uni_print('AWS CLI v2 MIGRATION WARNING: The ecr get-login command has been removed in AWS CLI v2. See https://docs.aws.amazon.com/cli/latest/userguide/cliv2-migration-changes.html#cliv2-migration-ecr-get-login.\n')
if url_params and session.full_config.get('cli_follow_urlparam', True):
uni_print('AWS CLI v2 MIGRATION WARNING: For input parameters that have a prefix of http:// or https://, AWS CLI v2 will no longer automatically request the content of the URL for the parameter, and the cli_follow_urlparam option has been removed. See https://docs.aws.amazon.com/cli/latest/userguide/cliv2-migration-changes.html#cliv2-migration-paramfile.\n')
for working, obsolete in HIDDEN_ALIASES.items():
working_split = working.split('.')
working_service = working_split[0]
working_cmd = working_split[1]
working_param = working_split[2]
if parsed_args.command == working_service and remaining_args[0] == working_cmd and f"--{working_param}" in remaining_args:
uni_print('AWS CLI v2 MIGRATION WARNING: You have entered command arguments that uses at least 1 of 21 hidden aliases that were removed in AWS CLI v2. See https://docs.aws.amazon.com/cli/latest/userguide/cliv2-migration-changes.html#cliv2-migration-aliases.\n')

def resolve_cli_read_timeout(parsed_args, session, **kwargs):
arg_name = 'read_timeout'
Expand Down
1 change: 1 addition & 0 deletions awscli/customizations/scalarparse.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ def add_timestamp_parser(session):
# 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.
# TODO create an inner function that wraps identity here. it'll signal to print the runtime check.
timestamp_parser = identity
elif timestamp_format == 'iso8601':
timestamp_parser = iso_format
Expand Down
5 changes: 5 additions & 0 deletions awscli/data/cli.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,11 @@
"dest": "connect_timeout",
"type": "int",
"help": "<p>The maximum socket connect time in seconds. If the value is set to 0, the socket connect will be blocking and not timeout. The default value is 60 seconds.</p>"
},
"v2-debug": {
"action": "store_true",
"dest": "v2_debug",
"help": "<p>Enable AWS CLI v2 migration assistance. Prints warnings if the command would face a breaking change after swapping AWS CLI v1 for AWS CLI v2 in the current environment. Prints one warning for each breaking change detected.</p>"
}
}
}
4 changes: 4 additions & 0 deletions awscli/examples/global_options.rst
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,7 @@

The maximum socket connect time in seconds. If the value is set to 0, the socket connect will be blocking and not timeout. The default value is 60 seconds.

``--v2-debug`` (boolean)

Enable AWS CLI v2 migration assistance. Prints warnings if the command would face a breaking change after swapping AWS CLI v1 for AWS CLI v2 in the current environment. Prints one warning for each breaking change detected.

1 change: 1 addition & 0 deletions awscli/examples/global_synopsis.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@
[--ca-bundle <value>]
[--cli-read-timeout <value>]
[--cli-connect-timeout <value>]
[--v2-debug]
9 changes: 7 additions & 2 deletions awscli/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,8 +205,13 @@ def ignore_ctrl_c():
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)
def emit_top_level_args_parsed_event(session, args, remaining):
session.emit(
'top-level-args-parsed',
parsed_args=args,
remaining_args=remaining,
session=session
)


def is_a_tty():
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/test_alias.py
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,7 @@ def replace_global_param_value_with_foo(event_name, **kwargs):
alias_cmd([], FakeParsedArgs(command=self.alias_name))
self.session.emit.assert_called_with(
'top-level-args-parsed', parsed_args=mock.ANY,
session=self.session)
session=self.session, remaining_args=mock.ANY)

command_table['myservice'].assert_called_with(
['myoperation'],
Expand Down
5 changes: 5 additions & 0 deletions tests/unit/test_clidriver.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,11 @@
"connect-timeout": {
"type": "int",
"help": ""
},
"migrate-v2": {
"action": "store_true",
"dest": "migrate_v2",
"help": "",
}
}
},
Expand Down
Loading