Path: blob/develop/tests/unit/customizations/test_globalargs.py
2624 views
# Copyright 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved.1#2# Licensed under the Apache License, Version 2.0 (the "License"). You3# may not use this file except in compliance with the License. A copy of4# the License is located at5#6# http://aws.amazon.com/apache2.0/7#8# or in the "license" file accompanying this file. This file is9# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF10# ANY KIND, either express or implied. See the License for the specific11# language governing permissions and limitations under the License.12from unittest.mock import patch, Mock1314from botocore.session import get_session15from botocore import UNSIGNED16import os1718from awscli.testutils import mock, unittest, capture_output19from awscli.customizations import globalargs202122class FakeParsedArgs(object):23def __init__(self, **kwargs):24self.__dict__.update(kwargs)2526def __getattr__(self, arg):27return None282930class FakeSession(object):3132def __init__(self, session_vars=None, config_file_vars=None):33if session_vars is None:34session_vars = {}35self.session_var_map = session_vars36if config_file_vars is None:37config_file_vars = {}38self.config_file_vars = config_file_vars3940def get_config_variable(self, name, methods=('env', 'config'),41default=None):42value = None43config_name, envvar_name = self.session_var_map[name]44if methods is not None:45if 'env' in methods and value is None:46value = os.environ.get(envvar_name)47if 'config' in methods and value is None:48value = self.config_file_vars.get(config_name)49else:50value = default51return value525354class TestGlobalArgsCustomization(unittest.TestCase):5556def test_parse_query(self):57parsed_args = FakeParsedArgs(query='foo.bar')58globalargs.resolve_types(parsed_args)59# Assert that it looks like a jmespath parsed expression.60self.assertFalse(isinstance(parsed_args.query, str))61self.assertTrue(hasattr(parsed_args.query, 'search'))6263def test_parse_query_error_message(self):64# Invalid jmespath expression.65parsed_args = FakeParsedArgs(query='foo.bar.')66with self.assertRaises(ValueError):67globalargs.resolve_types(parsed_args)68globalargs.resolve_types('query')6970def test_parse_verify_ssl_default_value(self):71with mock.patch('os.environ', {}):72parsed_args = FakeParsedArgs(verify_ssl=True, ca_bundle=None)73session_var_map = {'ca_bundle': ('ca_bundle', 'AWS_CA_BUNDLE')}74session = FakeSession(session_vars=session_var_map)75globalargs.resolve_verify_ssl(parsed_args, session)76# None, so that botocore can apply it's default logic.77self.assertIsNone(parsed_args.verify_ssl)7879def test_parse_verify_ssl_verify_turned_off(self):80with mock.patch('os.environ', {}):81parsed_args = FakeParsedArgs(verify_ssl=False, ca_bundle=None)82session_var_map = {'ca_bundle': ('ca_bundle', 'AWS_CA_BUNDLE')}83session = FakeSession(session_vars=session_var_map)84globalargs.resolve_verify_ssl(parsed_args, session)85self.assertFalse(parsed_args.verify_ssl)8687def test_cli_overrides_cert_bundle(self):88environ = {}89with mock.patch('os.environ', environ):90parsed_args = FakeParsedArgs(91verify_ssl=True,92ca_bundle='/path/to/cli_bundle.pem')93config_file_vars = {}94session_var_map = {'ca_bundle': ('ca_bundle', 'AWS_CA_BUNDLE')}95session = FakeSession(96session_vars=session_var_map,97config_file_vars=config_file_vars)98globalargs.resolve_verify_ssl(parsed_args, session)99self.assertEqual(parsed_args.verify_ssl, '/path/to/cli_bundle.pem')100101def test_cli_overrides_env_cert_bundle(self):102environ = {103'AWS_CA_BUNDLE': '/path/to/env_bundle.pem',104}105with mock.patch('os.environ', environ):106parsed_args = FakeParsedArgs(107verify_ssl=True,108ca_bundle='/path/to/cli_bundle.pem')109config_file_vars = {}110session_var_map = {'ca_bundle': ('ca_bundle', 'AWS_CA_BUNDLE')}111session = FakeSession(112session_vars=session_var_map,113config_file_vars=config_file_vars)114globalargs.resolve_verify_ssl(parsed_args, session)115self.assertEqual(parsed_args.verify_ssl, '/path/to/cli_bundle.pem')116117def test_no_verify_ssl_overrides_cli_cert_bundle(self):118environ = {119'AWS_CA_BUNDLE': '/path/to/env_bundle.pem',120}121with mock.patch('os.environ', environ):122parsed_args = FakeParsedArgs(123verify_ssl=False,124ca_bundle='/path/to/cli_bundle.pem')125config_file_vars = {}126session_var_map = {'ca_bundle': ('ca_bundle', 'AWS_CA_BUNDLE')}127session = FakeSession(128session_vars=session_var_map,129config_file_vars=config_file_vars)130globalargs.resolve_verify_ssl(parsed_args, session)131self.assertFalse(parsed_args.verify_ssl)132133def test_no_sign_request_if_option_specified(self):134args = FakeParsedArgs(sign_request=False)135session = mock.Mock()136with mock.patch('awscli.customizations.globalargs._update_default_client_config') as mock_update:137globalargs.no_sign_request(args, session)138mock_update.assert_called_once_with(session, 'signature_version', UNSIGNED)139140def test_request_signed_by_default(self):141args = FakeParsedArgs(sign_request=True)142session = mock.Mock()143globalargs.no_sign_request(args, session)144self.assertFalse(session.register.called)145146def test_invalid_endpoint_url(self):147# Invalid jmespath expression.148parsed_args = FakeParsedArgs(endpoint_url='missing-scheme.com')149with self.assertRaises(ValueError):150globalargs.resolve_types(parsed_args)151152def test_valid_endpoint_url(self):153parsed_args = FakeParsedArgs(endpoint_url='http://custom-endpoint.com')154globalargs.resolve_types(parsed_args)155self.assertEqual(parsed_args.endpoint_url,156'http://custom-endpoint.com')157158def test_cli_read_timeout(self):159parsed_args = FakeParsedArgs(read_timeout='60')160session = get_session()161globalargs.resolve_cli_read_timeout(parsed_args, session)162self.assertEqual(parsed_args.read_timeout, 60)163self.assertEqual(164session.get_default_client_config().read_timeout, 60)165166def test_cli_connect_timeout(self):167parsed_args = FakeParsedArgs(connect_timeout='60')168session = get_session()169globalargs.resolve_cli_connect_timeout(parsed_args, session)170self.assertEqual(parsed_args.connect_timeout, 60)171self.assertEqual(172session.get_default_client_config().connect_timeout, 60)173174def test_cli_read_timeout_for_blocking(self):175parsed_args = FakeParsedArgs(read_timeout='0')176session = get_session()177globalargs.resolve_cli_read_timeout(parsed_args, session)178self.assertEqual(parsed_args.read_timeout, None)179self.assertEqual(180session.get_default_client_config().read_timeout, None)181182def test_cli_connect_timeout_for_blocking(self):183parsed_args = FakeParsedArgs(connect_timeout='0')184session = get_session()185globalargs.resolve_cli_connect_timeout(parsed_args, session)186self.assertEqual(parsed_args.connect_timeout, None)187self.assertEqual(188session.get_default_client_config().connect_timeout, None)189190def test_register_feature_id(self):191parsed_args = FakeParsedArgs(v2_debug=True)192session = get_session()193globalargs.detect_migration_breakage(194parsed_args,195session,196[],197)198# Verify the correct feature ID is registered during the199# provide-client-params event.200with (mock.patch('awscli.customizations.globalargs.register_feature_id')201as mock_register_feature_id):202session.emit(203'provide-client-params.s3.ListBuckets',204params={},205model={},206)207mock_register_feature_id.assert_any_call(208'CLI_V1_TO_V2_MIGRATION_DEBUG_MODE'209)210211def test_ecr_login_v2_debug(self):212parsed_args = FakeParsedArgs(command='ecr', v2_debug=True)213remaining_args = ['get-login']214session = get_session()215with capture_output() as output:216globalargs.detect_migration_breakage(217parsed_args,218session,219remaining_args,220)221# Verify the expected warning is printed222self.assertIn(223'AWS CLI v2 UPGRADE WARNING: The `ecr get-login` command has '224'been removed in AWS CLI v2.',225output.stderr.getvalue()226)227228def test_ecr_login_v2_debug_env_var(self):229parsed_args = FakeParsedArgs(command='ecr')230remaining_args = ['get-login']231session = get_session()232env = {'AWS_CLI_UPGRADE_DEBUG_MODE': 'true'}233with capture_output() as output:234with mock.patch('os.environ', env):235globalargs.detect_migration_breakage(236parsed_args,237session,238remaining_args,239)240# Verify the expected warning is printed241self.assertIn(242'AWS CLI v2 UPGRADE WARNING: The `ecr get-login` command has '243'been removed in AWS CLI v2.',244output.stderr.getvalue()245)246247def test_v2_debug_python_utf8_env_var(self):248parsed_args = FakeParsedArgs(v2_debug=True)249session = get_session()250environ = {'PYTHONUTF8': '1'}251with mock.patch('os.environ', environ):252with capture_output() as output:253globalargs.detect_migration_breakage(parsed_args, session, [])254self.assertIn(255'The AWS CLI v2 does not support The `PYTHONUTF8` and '256'`PYTHONIOENCODING` environment variables, and instead '257'uses the `AWS_CLI_FILE_ENCODING` variable',258output.stderr.getvalue()259)260261def test_v2_debug_python_utf8_resolved_env_var(self):262parsed_args = FakeParsedArgs(v2_debug=True)263session = get_session()264environ = {'PYTHONUTF8': '1', 'AWS_CLI_FILE_ENCODING': 'UTF-8'}265with mock.patch('os.environ', environ):266with capture_output() as output:267globalargs.detect_migration_breakage(parsed_args, session, [])268self.assertNotIn(269'AWS CLI v2 UPGRADE WARNING: The PYTHONUTF8 and '270'PYTHONIOENCODING environment variables are unsupported '271'in AWS CLI v2.',272output.stderr.getvalue()273)274275def test_v2_debug_python_io_encoding_env_var(self):276parsed_args = FakeParsedArgs(v2_debug=True)277session = get_session()278environ = {'PYTHONIOENCODING': 'UTF8'}279with mock.patch('os.environ', environ):280with capture_output() as output:281globalargs.detect_migration_breakage(parsed_args, session, [])282self.assertIn(283'The AWS CLI v2 does not support The `PYTHONUTF8` and '284'`PYTHONIOENCODING` environment variables, and instead '285'uses the `AWS_CLI_FILE_ENCODING` variable',286output.stderr.getvalue()287)288289def test_v2_debug_s3_sigv2(self):290parsed_args = FakeParsedArgs(v2_debug=True)291session = get_session()292globalargs.detect_migration_breakage(parsed_args, session, [])293with capture_output() as output:294session.emit(295'choose-signer.s3.*',296signing_name='s3',297region_name='us-west-2',298signature_version='v2',299context={'auth_type': 'v2'},300)301self.assertIn(302'AWS CLI v2 UPGRADE WARNING: The AWS CLI v2 only uses Signature '303'v4 to authenticate Amazon S3 requests.',304output.stderr.getvalue()305)306307def test_v2_debug_s3_us_east_1(self):308parsed_args = FakeParsedArgs(v2_debug=True, region='us-east-1')309session = get_session()310globalargs.detect_migration_breakage(parsed_args, session, [])311def mock_get(key: str):312if key == 'retries':313return {'invocation-id': '012345'}314return None315316with capture_output() as output:317mock_request = Mock()318mock_request.url = 'https://s3.amazonaws.com'319mock_request.context.get.side_effect = mock_get320mock_request.headers = {}321322session.emit(323'request-created.s3.ListBuckets',324request=mock_request,325operation_name='ListBuckets',326)327self.assertIn(328'AWS CLI v2 UPGRADE WARNING: When you configure AWS CLI v2 '329'to use the `us-east-1` region, it uses the true regional '330'endpoint rather than the global endpoint.',331output.stderr.getvalue()332)333334def test_v2_debug_s3api_us_east_1(self):335parsed_args = FakeParsedArgs(v2_debug=True, region='us-east-1')336session = get_session()337globalargs.detect_migration_breakage(parsed_args, session, [])338339def mock_get(key: str):340if key == 'retries':341return {'invocation-id': '012345'}342return None343344with capture_output() as output:345mock_request = Mock()346mock_request.url = 'https://s3.amazonaws.com'347mock_request.context.get.side_effect = mock_get348mock_request.headers = {}349350session.emit(351'request-created.s3api.ListBuckets',352request=mock_request,353operation_name='ListBuckets',354)355self.assertIn(356'AWS CLI v2 UPGRADE WARNING: When you configure AWS CLI v2 '357'to use the `us-east-1` region, it uses the true regional '358'endpoint rather than the global endpoint.',359output.stderr.getvalue()360)361362