diff --git a/.changes/1.18.61.json b/.changes/1.18.61.json new file mode 100644 index 000000000000..823a3f091a8d --- /dev/null +++ b/.changes/1.18.61.json @@ -0,0 +1,22 @@ +[ + { + "category": "``ecr``", + "description": "Update ecr command to latest version", + "type": "api-change" + }, + { + "category": "``glue``", + "description": "Update glue command to latest version", + "type": "api-change" + }, + { + "category": "``cloudformation``", + "description": "Update cloudformation command to latest version", + "type": "api-change" + }, + { + "category": "``sts``", + "description": "Update sts command to latest version", + "type": "api-change" + } +] \ No newline at end of file diff --git a/.changes/1.18.62.json b/.changes/1.18.62.json new file mode 100644 index 000000000000..d721be2313e3 --- /dev/null +++ b/.changes/1.18.62.json @@ -0,0 +1,32 @@ +[ + { + "category": "``qldb``", + "description": "Update qldb command to latest version", + "type": "api-change" + }, + { + "category": "``ecs``", + "description": "Update ecs command to latest version", + "type": "api-change" + }, + { + "category": "``dynamodb``", + "description": "Update dynamodb command to latest version", + "type": "api-change" + }, + { + "category": "``macie2``", + "description": "Update macie2 command to latest version", + "type": "api-change" + }, + { + "category": "``chime``", + "description": "Update chime command to latest version", + "type": "api-change" + }, + { + "category": "``ec2``", + "description": "Update ec2 command to latest version", + "type": "api-change" + } +] \ No newline at end of file diff --git a/.changes/1.18.63.json b/.changes/1.18.63.json new file mode 100644 index 000000000000..b6ecca4b7537 --- /dev/null +++ b/.changes/1.18.63.json @@ -0,0 +1,27 @@ +[ + { + "category": "``health``", + "description": "Update health command to latest version", + "type": "api-change" + }, + { + "category": "s3", + "description": "Mute warnings for not restored glacier deep archive objects if --ignore-glacier-warnings option enabled. Fixes `#4039 `__", + "type": "bugfix" + }, + { + "category": "``transcribe``", + "description": "Update transcribe command to latest version", + "type": "api-change" + }, + { + "category": "``ec2``", + "description": "Update ec2 command to latest version", + "type": "api-change" + }, + { + "category": "``chime``", + "description": "Update chime command to latest version", + "type": "api-change" + } +] \ No newline at end of file diff --git a/.changes/2.0.15.json b/.changes/2.0.15.json new file mode 100644 index 000000000000..4130bcb6ab97 --- /dev/null +++ b/.changes/2.0.15.json @@ -0,0 +1,72 @@ +[ + { + "category": "IMDS", + "description": "Use IMDSv2 for autodiscovering EC2 region. Fixes `#4976 `__", + "type": "enhancement" + }, + { + "category": "``glue``", + "description": "Update glue command to latest version", + "type": "api-change" + }, + { + "category": "``cloudformation``", + "description": "Update cloudformation command to latest version", + "type": "api-change" + }, + { + "category": "``sts``", + "description": "Update sts command to latest version", + "type": "api-change" + }, + { + "category": "``dynamodb``", + "description": "Update dynamodb command to latest version", + "type": "api-change" + }, + { + "category": "``chime``", + "description": "Update chime command to latest version", + "type": "api-change" + }, + { + "category": "``transcribe``", + "description": "Update transcribe command to latest version", + "type": "api-change" + }, + { + "category": "``qldb``", + "description": "Update qldb command to latest version", + "type": "api-change" + }, + { + "category": "``health``", + "description": "Update health command to latest version", + "type": "api-change" + }, + { + "category": "``ec2``", + "description": "Update ec2 command to latest version", + "type": "api-change" + }, + { + "category": "``ecr``", + "description": "Update ecr command to latest version", + "type": "api-change" + }, + { + "category": "s3", + "description": "Mute warnings for not restored glacier deep archive objects if --ignore-glacier-warnings option enabled. Fixes `#4039 `__", + "type": "bugfix" + }, + { + "category": "``macie2``", + "description": "Update macie2 command to latest version", + "type": "api-change" + }, + { + "category": "``ecs``", + "description": "Update ecs command to latest version", + "type": "api-change" + } +] diff --git a/.changes/next-release/enhancement,-IMDS-59801.json b/.changes/next-release/enhancement,-IMDS-59801.json deleted file mode 100644 index 676c14133a47..000000000000 --- a/.changes/next-release/enhancement,-IMDS-59801.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "type": "enhancement,", - "category": "IMDS", - "description": "Use IMDSv2 for autodiscovering EC2 region. Fixes `#4976 `__" -} diff --git a/CHANGELOG.rst b/CHANGELOG.rst index eb0af03e5db4..eb403c893b34 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -2,6 +2,25 @@ CHANGELOG ========= +2.0.15 +====== + +* enhancement:IMDS: Use IMDSv2 for autodiscovering EC2 region. Fixes `#4976 `__ +* api-change:``glue``: Update glue command to latest version +* api-change:``cloudformation``: Update cloudformation command to latest version +* api-change:``sts``: Update sts command to latest version +* api-change:``dynamodb``: Update dynamodb command to latest version +* api-change:``chime``: Update chime command to latest version +* api-change:``transcribe``: Update transcribe command to latest version +* api-change:``qldb``: Update qldb command to latest version +* api-change:``health``: Update health command to latest version +* api-change:``ec2``: Update ec2 command to latest version +* api-change:``ecr``: Update ecr command to latest version +* bugfix:s3: Mute warnings for not restored glacier deep archive objects if --ignore-glacier-warnings option enabled. Fixes `#4039 `__ +* api-change:``macie2``: Update macie2 command to latest version +* api-change:``ecs``: Update ecs command to latest version + + 2.0.14 ====== @@ -313,6 +332,36 @@ CHANGELOG * feature:wizard: Added support for AWS CLI Wizards. See `#3752 `__. +1.18.63 +======= + +* api-change:``health``: Update health command to latest version +* bugfix:s3: Mute warnings for not restored glacier deep archive objects if --ignore-glacier-warnings option enabled. Fixes `#4039 `__ +* api-change:``transcribe``: Update transcribe command to latest version +* api-change:``ec2``: Update ec2 command to latest version +* api-change:``chime``: Update chime command to latest version + + +1.18.62 +======= + +* api-change:``qldb``: Update qldb command to latest version +* api-change:``ecs``: Update ecs command to latest version +* api-change:``dynamodb``: Update dynamodb command to latest version +* api-change:``macie2``: Update macie2 command to latest version +* api-change:``chime``: Update chime command to latest version +* api-change:``ec2``: Update ec2 command to latest version + + +1.18.61 +======= + +* api-change:``ecr``: Update ecr command to latest version +* api-change:``glue``: Update glue command to latest version +* api-change:``cloudformation``: Update cloudformation command to latest version +* api-change:``sts``: Update sts command to latest version + + 1.18.60 ======= diff --git a/awscli/__init__.py b/awscli/__init__.py index fce6b8540245..d8f1df407624 100644 --- a/awscli/__init__.py +++ b/awscli/__init__.py @@ -17,7 +17,7 @@ """ import os -__version__ = '2.0.14' +__version__ = '2.0.15' # # Get our data path to be added to botocore's search path diff --git a/awscli/customizations/ecs/deploy.py b/awscli/customizations/ecs/deploy.py index a498d9a35c14..6e35d807111f 100644 --- a/awscli/customizations/ecs/deploy.py +++ b/awscli/customizations/ecs/deploy.py @@ -16,7 +16,7 @@ import os import sys -from botocore import compat +from botocore import compat, config from botocore.exceptions import ClientError from awscli.compat import compat_open from awscli.customizations.ecs import exceptions, filehelpers @@ -109,6 +109,8 @@ class ECSDeploy(BasicCommand): MSG_SUCCESS = ("Successfully deployed {task_def} to " "service '{service}'\n") + USER_AGENT_EXTRA = 'customization/ecs-deploy' + def _run_main(self, parsed_args, parsed_globals): register_task_def_kwargs, appspec_obj = \ @@ -116,7 +118,7 @@ def _run_main(self, parsed_args, parsed_globals): parsed_args.codedeploy_appspec) ecs_client_wrapper = ECSClient( - self._session, parsed_args, parsed_globals) + self._session, parsed_args, parsed_globals, self.USER_AGENT_EXTRA) self.resources = self._get_resource_names( parsed_args, ecs_client_wrapper) @@ -124,7 +126,8 @@ def _run_main(self, parsed_args, parsed_globals): codedeploy_client = self._session.create_client( 'codedeploy', region_name=parsed_globals.region, - verify=parsed_globals.verify_ssl) + verify=parsed_globals.verify_ssl, + config=config.Config(user_agent_extra=self.USER_AGENT_EXTRA)) self._validate_code_deploy_resources(codedeploy_client) @@ -400,13 +403,16 @@ def validate_deployment_group(self): class ECSClient(): - def __init__(self, session, parsed_args, parsed_globals): + + def __init__(self, session, parsed_args, parsed_globals, user_agent_extra): self._args = parsed_args + self._custom_config = config.Config(user_agent_extra=user_agent_extra) self._client = session.create_client( 'ecs', region_name=parsed_globals.region, endpoint_url=parsed_globals.endpoint_url, - verify=parsed_globals.verify_ssl) + verify=parsed_globals.verify_ssl, + config=self._custom_config) def get_service_details(self): cluster = self._args.cluster diff --git a/awscli/customizations/s3/fileinfo.py b/awscli/customizations/s3/fileinfo.py index 66b8c852ceac..80ed625802fc 100644 --- a/awscli/customizations/s3/fileinfo.py +++ b/awscli/customizations/s3/fileinfo.py @@ -80,9 +80,10 @@ def is_glacier_compatible(self): return True def _is_glacier_object(self, response_data): + glacier_storage_classes = ['GLACIER', 'DEEP_ARCHIVE'] if response_data: - if response_data.get('StorageClass') == 'GLACIER' and \ - not self._is_restored(response_data): + if response_data.get('StorageClass') in glacier_storage_classes \ + and not self._is_restored(response_data): return True return False diff --git a/awscli/data/ac.index b/awscli/data/ac.index index f58966b92daa..b43fe97dd57a 100644 Binary files a/awscli/data/ac.index and b/awscli/data/ac.index differ diff --git a/doc/source/conf.py b/doc/source/conf.py index 8d7fbeadf574..4c91e7b7868e 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -71,7 +71,7 @@ # The short X.Y version. version = '2.0' # The full version, including alpha/beta/rc tags. -release = '2.0.14' +release = '2.0.15' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/setup.cfg b/setup.cfg index 14197931e372..c429c0b9d86b 100644 --- a/setup.cfg +++ b/setup.cfg @@ -4,7 +4,7 @@ universal = 1 [metadata] requires-dist = - botocore==2.0.0dev18 + botocore==2.0.0dev19 colorama>=0.2.5,<0.4.4 docutils>=0.10,<0.16 cryptography>=2.8.0,<=2.9.0 diff --git a/setup.py b/setup.py index bd0b1ddecf3c..3d417eb87086 100644 --- a/setup.py +++ b/setup.py @@ -24,7 +24,7 @@ def find_version(*file_paths): requires = [ - 'botocore==2.0.0dev18', + 'botocore==2.0.0dev19', 'colorama>=0.2.5,<0.4.4', 'docutils>=0.10,<0.16', 'cryptography>=2.8.0,<=2.9.0', diff --git a/tests/functional/s3/test_cp_command.py b/tests/functional/s3/test_cp_command.py index 7b033dc4a691..87f8eaa9edc9 100644 --- a/tests/functional/s3/test_cp_command.py +++ b/tests/functional/s3/test_cp_command.py @@ -367,6 +367,20 @@ def test_warns_on_glacier_incompatible_operation(self): self.assertEqual(self.operations_called[0][0].name, 'HeadObject') self.assertIn('GLACIER', stderr) + def test_warns_on_deep_arhive_incompatible_operation(self): + self.parsed_responses = [ + {'ContentLength': '100', 'LastModified': '00:00:00Z', + 'StorageClass': 'DEEP_ARCHIVE'}, + ] + cmdline = ('%s s3://bucket/key.txt .' % self.prefix) + _, stderr, _ = self.run_cmd(cmdline, expected_rc=2) + # There should not have been a download attempted because the + # operation was skipped because it is glacier + # deep archive incompatible. + self.assertEqual(len(self.operations_called), 1) + self.assertEqual(self.operations_called[0][0].name, 'HeadObject') + self.assertIn('GLACIER', stderr) + def test_warns_on_glacier_incompatible_operation_for_multipart_file(self): self.parsed_responses = [ {'ContentLength': str(20 * (1024 ** 2)), @@ -381,6 +395,21 @@ def test_warns_on_glacier_incompatible_operation_for_multipart_file(self): self.assertEqual(self.operations_called[0][0].name, 'HeadObject') self.assertIn('GLACIER', stderr) + def test_warns_on_deep_archive_incompatible_op_for_multipart_file(self): + self.parsed_responses = [ + {'ContentLength': str(20 * (1024 ** 2)), + 'LastModified': '00:00:00Z', + 'StorageClass': 'DEEP_ARCHIVE'}, + ] + cmdline = ('%s s3://bucket/key.txt .' % self.prefix) + _, stderr, _ = self.run_cmd(cmdline, expected_rc=2) + # There should not have been a download attempted because the + # operation was skipped because it is glacier + # deep archive incompatible. + self.assertEqual(len(self.operations_called), 1) + self.assertEqual(self.operations_called[0][0].name, 'HeadObject') + self.assertIn('GLACIER', stderr) + def test_turn_off_glacier_warnings(self): self.parsed_responses = [ {'ContentLength': str(20 * (1024 ** 2)), @@ -396,6 +425,21 @@ def test_turn_off_glacier_warnings(self): self.assertEqual(self.operations_called[0][0].name, 'HeadObject') self.assertEqual('', stderr) + def test_turn_off_glacier_warnings_for_deep_archive(self): + self.parsed_responses = [ + {'ContentLength': str(20 * (1024 ** 2)), + 'LastModified': '00:00:00Z', + 'StorageClass': 'DEEP_ARCHIVE'}, + ] + cmdline = ( + '%s s3://bucket/key.txt . --ignore-glacier-warnings' % self.prefix) + _, stderr, _ = self.run_cmd(cmdline, expected_rc=0) + # There should not have been a download attempted because the + # operation was skipped because it is glacier incompatible. + self.assertEqual(len(self.operations_called), 1) + self.assertEqual(self.operations_called[0][0].name, 'HeadObject') + self.assertEqual('', stderr) + def test_cp_with_sse_flag(self): full_path = self.files.create_file('foo.txt', 'contents') cmdline = ( diff --git a/tests/functional/s3/test_sync_command.py b/tests/functional/s3/test_sync_command.py index 3a9ccb63aae3..41953404ce8b 100644 --- a/tests/functional/s3/test_sync_command.py +++ b/tests/functional/s3/test_sync_command.py @@ -96,22 +96,31 @@ def test_handles_glacier_incompatible_operations(self): self.parsed_responses = [ {'Contents': [ {'Key': 'foo', 'Size': 100, - 'LastModified': '00:00:00Z', 'StorageClass': 'GLACIER'}]} + 'LastModified': '00:00:00Z', 'StorageClass': 'GLACIER'}, + {'Key': 'bar', 'Size': 100, + 'LastModified': '00:00:00Z', 'StorageClass': 'DEEP_ARCHIVE'} + ]} ] cmdline = '%s s3://bucket/ %s' % ( self.prefix, self.files.rootdir) _, stderr, _ = self.run_cmd(cmdline, expected_rc=2) # There should not have been a download attempted because the - # operation was skipped because it is glacier incompatible. + # operation was skipped because it is glacier and glacier + # deep archive incompatible. self.assertEqual(len(self.operations_called), 1) self.assertEqual(self.operations_called[0][0].name, 'ListObjectsV2') self.assertIn('GLACIER', stderr) + self.assertIn('s3://bucket/foo', stderr) + self.assertIn('s3://bucket/bar', stderr) def test_turn_off_glacier_warnings(self): self.parsed_responses = [ {'Contents': [ {'Key': 'foo', 'Size': 100, - 'LastModified': '00:00:00Z', 'StorageClass': 'GLACIER'}]} + 'LastModified': '00:00:00Z', 'StorageClass': 'GLACIER'}, + {'Key': 'bar', 'Size': 100, + 'LastModified': '00:00:00Z', 'StorageClass': 'DEEP_ARCHIVE'} + ]} ] cmdline = '%s s3://bucket/ %s --ignore-glacier-warnings' % ( self.prefix, self.files.rootdir) diff --git a/tests/unit/customizations/ecs/test_ecsclient.py b/tests/unit/customizations/ecs/test_ecsclient.py new file mode 100644 index 000000000000..ceaa41891e2c --- /dev/null +++ b/tests/unit/customizations/ecs/test_ecsclient.py @@ -0,0 +1,46 @@ +# Copyright 2020 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 mock + +from argparse import Namespace +from botocore import config +from awscli.testutils import capture_output, unittest +from awscli.customizations.ecs.deploy import ECSClient, ECSDeploy + + +class TestECSClient(unittest.TestCase): + + def setUp(self): + ecs_client = mock.Mock() + self.session = mock.Mock() + self.session.create_client.side_effect = ecs_client + + # set global args + self.global_args = Namespace() + self.global_args.region = 'us-east-1' + self.global_args.endpoint_url = None + self.global_args.verify_ssl = None + + def test_client_config(self): + self.test_client = ECSClient( + self.session, None, self.global_args, ECSDeploy.USER_AGENT_EXTRA) + + expected_user_agent_extra = 'customization/ecs-deploy' + + create_args = self.session.create_client.call_args + self.assertEquals(create_args[0][0], 'ecs') + self.assertEquals( + create_args[1]['region_name'], self.global_args.region) + self.assertEquals(create_args[1]['config'].user_agent_extra, + expected_user_agent_extra)