diff --git a/awscli2.spec b/awscli2.spec index dca890e..f5911e2 100644 --- a/awscli2.spec +++ b/awscli2.spec @@ -19,8 +19,6 @@ Patch0: ruamel-yaml-0.17.32.patch Patch1: python312.patch # fix incorrect assertions in TestKubeconfigLoader Patch2: assertions.patch -# skip flaky test which compares yaml output as plain text -Patch3: test-yaml.patch BuildArch: noarch diff --git a/python312.patch b/python312.patch index a3485d7..5ee4eee 100644 --- a/python312.patch +++ b/python312.patch @@ -48,7 +48,7 @@ index edae233..2483b32 100644 if self.credentials is None: raise NoCredentialsError() - datetime_now = datetime.datetime.utcnow() -+ datetime_now = datetime.datetime.now(datetime.UTC) ++ datetime_now = datetime.datetime.now(datetime.timezone.utc) request.context['timestamp'] = datetime_now.strftime(SIGV4_TIMESTAMP) # This could be a retry. Make sure the previous # authorization header is removed first. @@ -57,7 +57,7 @@ index edae233..2483b32 100644 """ def add_auth(self, request): - datetime_now = datetime.datetime.utcnow() -+ datetime_now = datetime.datetime.now(datetime.UTC) ++ datetime_now = datetime.datetime.now(datetime.timezone.utc) request.context['timestamp'] = datetime_now.strftime(SIGV4_TIMESTAMP) fields = {} @@ -109,7 +109,7 @@ index 534a7f8..474e675 100644 # timezone because CRT assumes naive datetime is local time. - datetime_now = datetime.datetime.utcnow().replace( - tzinfo=datetime.timezone.utc) -+ datetime_now = datetime.datetime.now(datetime.UTC) ++ datetime_now = datetime.datetime.now(datetime.timezone.utc) # Use existing 'X-Amz-Content-SHA256' header if able existing_sha256 = self._get_existing_sha256(request) @@ -119,7 +119,7 @@ index 534a7f8..474e675 100644 # timezone because CRT assumes naive datetime is local time. - datetime_now = datetime.datetime.utcnow().replace( - tzinfo=datetime.timezone.utc) -+ datetime_now = datetime.datetime.now(datetime.UTC) ++ datetime_now = datetime.datetime.now(datetime.timezone.utc) # Use existing 'X-Amz-Content-SHA256' header if able existing_sha256 = self._get_existing_sha256(request) @@ -218,7 +218,7 @@ index 77a9346..93b8af0 100644 # Create an expiration date for the policy - datetime_now = datetime.datetime.utcnow() -+ datetime_now = datetime.datetime.now(datetime.UTC) ++ datetime_now = datetime.datetime.now(datetime.timezone.utc) expire_date = datetime_now + datetime.timedelta(seconds=expires_in) policy['expiration'] = expire_date.strftime(botocore.auth.ISO8601) @@ -240,7 +240,7 @@ index 81b41dc..0740339 100644 ) refresh_interval_with_jitter = refresh_interval + random.randint(120, 600) - current_time = datetime.datetime.utcnow() -+ current_time = datetime.datetime.now(datetime.UTC) ++ current_time = datetime.datetime.now(datetime.timezone.utc) refresh_offset = datetime.timedelta(seconds=refresh_interval_with_jitter) extension_time = expiration - refresh_offset if current_time >= extension_time: @@ -280,7 +280,7 @@ index 3733c55..48e69a6 100644 from awscli.customizations.cloudformation.artifact_exporter import mktempfile, parse_s3_url -from datetime import datetime -+from datetime import datetime, UTC ++from datetime import datetime, timezone LOG = logging.getLogger(__name__) @@ -289,7 +289,7 @@ index 3733c55..48e69a6 100644 """ - now = datetime.utcnow().isoformat() -+ now = datetime.now(UTC).isoformat() ++ now = datetime.now(timezone.utc).isoformat() description = "Created by AWS CLI at {0} UTC".format(now) # Each changeset will get a unique name based on time @@ -302,7 +302,7 @@ index 78e2540..9a515e0 100644 import zlib from zlib import error as ZLibError -from datetime import datetime, timedelta -+from datetime import datetime, timedelta, UTC ++from datetime import datetime, timedelta, timezone from dateutil import tz, parser import cryptography @@ -311,7 +311,7 @@ index 78e2540..9a515e0 100644 """ if end_date is None: - end_date = datetime.utcnow() -+ end_date = datetime.now(UTC) ++ end_date = datetime.now(timezone.utc) end_date = normalize_date(end_date) start_date = normalize_date(start_date) bucket = self.starting_bucket @@ -320,7 +320,7 @@ index 78e2540..9a515e0 100644 self.end_time = normalize_date(parse_date(args.end_time)) else: - self.end_time = normalize_date(datetime.utcnow()) -+ self.end_time = datetime.now(UTC) ++ self.end_time = datetime.now(timezone.utc) if self.start_time > self.end_time: raise ParamValidationError( 'Invalid time range specified: start-time must ' @@ -333,7 +333,7 @@ index 6b30e83..935f27b 100644 request.url = url_to_sign request.method = 'GIT' - now = datetime.datetime.utcnow() -+ now = datetime.datetime.now(datetime.UTC) ++ now = datetime.datetime.now(datetime.timezone.utc) request.context['timestamp'] = now.strftime('%Y%m%dT%H%M%S') split = urlsplit(request.url) # we don't want to include the port number in the signature @@ -346,7 +346,7 @@ index 4c08664..8531c03 100644 import tempfile import contextlib -from datetime import datetime -+from datetime import datetime, UTC ++from datetime import datetime, timezone from botocore.exceptions import ClientError @@ -355,7 +355,7 @@ index 4c08664..8531c03 100644 parsed_args.description = ( 'Uploaded by AWS CLI {0} UTC'.format( - datetime.utcnow().isoformat() -+ datetime.now(UTC).isoformat() ++ datetime.now(timezone.utc).isoformat() ) ) @@ -381,7 +381,7 @@ index c47ca94..309406c 100644 import json -from datetime import datetime, timedelta -+from datetime import datetime, timedelta, UTC ++from datetime import datetime, timedelta, timezone from awscli.formatter import get_formatter from awscli.arguments import CustomArgument @@ -390,7 +390,7 @@ index c47ca94..309406c 100644 def __init__(self, current_time=None): if current_time is None: - current_time = datetime.utcnow() -+ current_time = datetime.now(UTC) ++ current_time = datetime.now(timezone.utc) self.current_time = current_time def build_query(self, parsed_args): @@ -403,7 +403,7 @@ index 96d9ece..31a4962 100644 # Creates a policy that provides access for 24 hours. delta = datetime.timedelta(hours=24) - expires = datetime.datetime.utcnow() + delta -+ expires = datetime.datetime.now(datetime.UTC) + delta ++ expires = datetime.datetime.now(datetime.timezone.utc) + delta expires_iso = expires.strftime("%Y-%m-%dT%H:%M:%S.%fZ") policy = POLICY.format(expires=expires_iso, bucket=params['Bucket'], @@ -416,7 +416,7 @@ index c85b86d..4d12661 100644 import sys -from datetime import datetime, timedelta -+from datetime import datetime, timedelta, UTC ++from datetime import datetime, timedelta, timezone from botocore.signers import RequestSigner from botocore.model import ServiceId @@ -425,7 +425,7 @@ index c85b86d..4d12661 100644 def get_expiration_time(self): - token_expiration = datetime.utcnow() + timedelta( -+ token_expiration = datetime.now(UTC) + timedelta( ++ token_expiration = datetime.now(timezone.utc) + timedelta( minutes=TOKEN_EXPIRATION_MINS ) return token_expiration.strftime('%Y-%m-%dT%H:%M:%SZ') @@ -438,7 +438,7 @@ index cb31510..b2f8563 100644 # language governing permissions and limitations under the License. from collections import defaultdict -from datetime import datetime, timedelta -+from datetime import datetime, timedelta, UTC ++from datetime import datetime, timedelta, timezone +import functools import json import re @@ -448,7 +448,7 @@ index cb31510..b2f8563 100644 self._now = now if now is None: - self._now = datetime.utcnow -+ self._now = functools.partial(datetime.now, UTC) ++ self._now = functools.partial(datetime.now, timezone.utc) def to_epoch_millis(self, timestamp): re_match = self._RELATIVE_TIMESTAMP_REGEX.match(timestamp) @@ -461,7 +461,7 @@ index a2a0c1e..217bfca 100644 } if timeout is not None: - valid_until = datetime.datetime.utcnow() + timeout -+ valid_until = datetime.datetime.now(datetime.UTC) + timeout ++ valid_until = datetime.datetime.now(datetime.timezone.utc) + timeout statement["Condition"] = { "DateLessThan": { "aws:CurrentTime": @@ -474,7 +474,7 @@ index 843be90..1bd9201 100644 import tempfile import shutil -from datetime import datetime, timedelta -+from datetime import datetime, timedelta, UTC ++from datetime import datetime, timedelta, timezone import sys import pytest @@ -484,8 +484,8 @@ index 843be90..1bd9201 100644 -TIME_IN_ONE_HOUR = datetime.utcnow() + timedelta(hours=1) -TIME_IN_SIX_MONTHS = datetime.utcnow() + timedelta(hours=4320) -+TIME_IN_ONE_HOUR = datetime.now(UTC) + timedelta(hours=1) -+TIME_IN_SIX_MONTHS = datetime.now(UTC) + timedelta(hours=4320) ++TIME_IN_ONE_HOUR = datetime.now(timezone.utc) + timedelta(hours=1) ++TIME_IN_SIX_MONTHS = datetime.now(timezone.utc) + timedelta(hours=4320) class TestCredentialRefreshRaces(unittest.TestCase): @@ -498,7 +498,7 @@ index 795094e..fed43d2 100644 '\n' ) - self.now = datetime.datetime(2011, 9, 9, 23, 36) -+ self.now = datetime.datetime(2011, 9, 9, 23, 36, tzinfo=datetime.UTC) ++ self.now = datetime.datetime(2011, 9, 9, 23, 36, tzinfo=datetime.timezone.utc) self.datetime_patch = mock.patch.object( botocore.auth.datetime, 'datetime', mock.Mock(wraps=datetime.datetime) @@ -518,7 +518,7 @@ index 7e7f619..eb623ec 100644 # language governing permissions and limitations under the License. import mock -from datetime import datetime -+from datetime import datetime, UTC ++from datetime import datetime, timezone from tests import BaseSessionTest, ClientHTTPStubber @@ -527,7 +527,7 @@ index 7e7f619..eb623ec 100644 } - timestamp = datetime(2017, 3, 22, 0, 0) -+ timestamp = datetime(2017, 3, 22, 0, 0, tzinfo=UTC) ++ timestamp = datetime(2017, 3, 22, 0, 0, tzinfo=timezone.utc) with mock.patch('botocore.auth.datetime') as _datetime: - _datetime.datetime.utcnow.return_value = timestamp @@ -544,7 +544,7 @@ index cdc212a..75b367c 100644 # ANY KIND, either express or implied. See the License for the specific # language governing permissions and limitations under the License. -from datetime import datetime -+from datetime import datetime, UTC ++from datetime import datetime, timezone import re import mock @@ -553,7 +553,7 @@ index cdc212a..75b367c 100644 def test_presigned_url_contains_no_content_type(self): - timestamp = datetime(2017, 3, 22, 0, 0) -+ timestamp = datetime(2017, 3, 22, 0, 0, tzinfo=UTC) ++ timestamp = datetime(2017, 3, 22, 0, 0, tzinfo=timezone.utc) with mock.patch('botocore.auth.datetime') as _datetime: - _datetime.datetime.utcnow.return_value = timestamp + _datetime.datetime.now.return_value = timestamp @@ -578,7 +578,7 @@ index 5bc3204..7dcc416 100644 ) mocked_datetime = self.datetime_patcher.start() - mocked_datetime.utcnow.return_value = datetime.datetime(2013, 8, 9) -+ mocked_datetime.now.return_value = datetime.datetime(2013, 8, 9, tzinfo=datetime.UTC) ++ mocked_datetime.now.return_value = datetime.datetime(2013, 8, 9, tzinfo=datetime.timezone.utc) def tearDown(self): super(TestBundleInstance, self).tearDown() @@ -617,7 +617,7 @@ index 89801f9..ea48865 100644 # language governing permissions and limitations under the License. import base64 -from datetime import datetime -+from datetime import datetime, UTC ++from datetime import datetime, timezone import json import os @@ -626,7 +626,7 @@ index 89801f9..ea48865 100644 @mock.patch('awscli.customizations.eks.get_token.datetime') def test_get_token(self, mock_datetime): - mock_datetime.utcnow.return_value = datetime(2019, 10, 23, 23, 0, 0, 0) -+ mock_datetime.now.return_value = datetime(2019, 10, 23, 23, 0, 0, 0, tzinfo=UTC) ++ mock_datetime.now.return_value = datetime(2019, 10, 23, 23, 0, 0, 0, tzinfo=timezone.utc) cmd = 'eks get-token --cluster-name %s' % self.cluster_name response = self.run_get_token(cmd) self.assertEqual( @@ -635,7 +635,7 @@ index 89801f9..ea48865 100644 @mock.patch('awscli.customizations.eks.get_token.datetime') def test_query_nested_object(self, mock_datetime): - mock_datetime.utcnow.return_value = datetime(2019, 10, 23, 23, 0, 0, 0) -+ mock_datetime.now.return_value = datetime(2019, 10, 23, 23, 0, 0, 0, tzinfo=UTC) ++ mock_datetime.now.return_value = datetime(2019, 10, 23, 23, 0, 0, 0, tzinfo=timezone.utc) cmd = 'eks get-token --cluster-name %s' % self.cluster_name cmd += ' --query status' response = self.run_get_token(cmd) @@ -644,7 +644,7 @@ index 89801f9..ea48865 100644 @mock.patch('awscli.customizations.eks.get_token.datetime') def test_output_text(self, mock_datetime): - mock_datetime.utcnow.return_value = datetime(2019, 10, 23, 23, 0, 0, 0) -+ mock_datetime.now.return_value = datetime(2019, 10, 23, 23, 0, 0, 0, tzinfo=UTC) ++ mock_datetime.now.return_value = datetime(2019, 10, 23, 23, 0, 0, 0, tzinfo=timezone.utc) cmd = 'eks get-token --cluster-name %s' % self.cluster_name cmd += ' --output text' stdout, _, _ = self.run_cmd(cmd) @@ -653,7 +653,7 @@ index 89801f9..ea48865 100644 @mock.patch('awscli.customizations.eks.get_token.datetime') def test_output_table(self, mock_datetime): - mock_datetime.utcnow.return_value = datetime(2019, 10, 23, 23, 0, 0, 0) -+ mock_datetime.now.return_value = datetime(2019, 10, 23, 23, 0, 0, 0, tzinfo=UTC) ++ mock_datetime.now.return_value = datetime(2019, 10, 23, 23, 0, 0, 0, tzinfo=timezone.utc) cmd = 'eks get-token --cluster-name %s' % self.cluster_name cmd += ' --output table' stdout, _, _ = self.run_cmd(cmd) @@ -708,7 +708,7 @@ index 2db338a..8b3120a 100644 FROZEN_TIME = mock.Mock(return_value=FROZEN_TIMESTAMP) FROZEN_DATETIME = mock.Mock( - return_value=datetime.datetime(2016, 8, 18, 14, 33, 3, 0)) -+ return_value=datetime.datetime(2016, 8, 18, 14, 33, 3, 0, tzinfo=datetime.UTC)) ++ return_value=datetime.datetime(2016, 8, 18, 14, 33, 3, 0, tzinfo=datetime.timezone.utc)) class TestPresignCommand(BaseAWSCommandParamsTest): @@ -744,7 +744,7 @@ index 73d3b12..3b3922d 100644 self.datetime_patch = mock.patch('botocore.auth.datetime.datetime') self.datetime_mock = self.datetime_patch.start() - self.datetime_mock.utcnow.return_value = self.fixed_date -+ self.datetime_mock.now.return_value = self.fixed_date.replace(tzinfo=datetime.UTC) ++ self.datetime_mock.now.return_value = self.fixed_date.replace(tzinfo=datetime.timezone.utc) self.datetime_mock.strptime.return_value = self.fixed_date def tearDown(self): @@ -753,7 +753,7 @@ index 73d3b12..3b3922d 100644 botocore.auth.datetime, 'datetime', mock.Mock(wraps=datetime.datetime)) as mock_datetime: - original_utcnow = datetime.datetime(2014, 1, 1, 0, 0) -+ original_now = datetime.datetime(2014, 1, 1, 0, 0, tzinfo=datetime.UTC) ++ original_now = datetime.datetime(2014, 1, 1, 0, 0, tzinfo=datetime.timezone.utc) - mock_datetime.utcnow.return_value = original_utcnow + mock_datetime.now.return_value = original_now @@ -767,7 +767,7 @@ index 73d3b12..3b3922d 100644 - mock_datetime.utcnow.return_value = datetime.datetime( - 2014, 1, 2, 0, 0) + mock_datetime.now.return_value = datetime.datetime( -+ 2014, 1, 2, 0, 0, tzinfo=datetime.UTC) ++ 2014, 1, 2, 0, 0, tzinfo=datetime.timezone.utc) # Smaller methods like the canonical request and string_to_sign # should have the timestamp attached to the request in their # body and not what the time is now mocked as. This is to ensure @@ -778,7 +778,7 @@ index 73d3b12..3b3922d 100644 - mocked_datetime.utcnow.return_value = datetime.datetime( - 2014, 1, 1, 0, 0) + mocked_datetime.now.return_value = datetime.datetime( -+ 2014, 1, 1, 0, 0, tzinfo=datetime.UTC) ++ 2014, 1, 1, 0, 0, tzinfo=datetime.timezone.utc) def tearDown(self): self.datetime_patcher.stop() @@ -789,7 +789,7 @@ index 73d3b12..3b3922d 100644 - mocked_datetime.utcnow.return_value = datetime.datetime( - 2014, 1, 1, 0, 0) + mocked_datetime.now.return_value = datetime.datetime( -+ 2014, 1, 1, 0, 0, tzinfo=datetime.UTC) ++ 2014, 1, 1, 0, 0, tzinfo=datetime.timezone.utc) def tearDown(self): self.datetime_patcher.stop() @@ -837,7 +837,7 @@ index cc49596..0a5e4d7 100644 # ANY KIND, either express or implied. See the License for the specific # language governing permissions and limitations under the License. -from datetime import datetime, timedelta -+from datetime import datetime, timedelta, UTC ++from datetime import datetime, timedelta, timezone import subprocess import mock import os @@ -847,7 +847,7 @@ index cc49596..0a5e4d7 100644 def test_retrieves_from_cache(self): - date_in_future = datetime.utcnow() + timedelta(seconds=1000) - utc_timestamp = date_in_future.isoformat() + 'Z' -+ date_in_future = datetime.now(UTC) + timedelta(seconds=1000) ++ date_in_future = datetime.now(timezone.utc) + timedelta(seconds=1000) + utc_timestamp = date_in_future.isoformat() cache_key = ( '793d6e2f27667ab2da104824407e486bfec24a47' @@ -858,7 +858,7 @@ index cc49596..0a5e4d7 100644 def test_retrieves_from_cache(self): - date_in_future = datetime.utcnow() + timedelta(seconds=1000) - utc_timestamp = date_in_future.isoformat() + 'Z' -+ date_in_future = datetime.now(UTC) + timedelta(seconds=1000) ++ date_in_future = datetime.now(timezone.utc) + timedelta(seconds=1000) + utc_timestamp = date_in_future.isoformat() cache_key = ( '793d6e2f27667ab2da104824407e486bfec24a47' @@ -869,7 +869,7 @@ index cc49596..0a5e4d7 100644 def test_assume_role_retrieves_from_cache(self): - date_in_future = datetime.utcnow() + timedelta(seconds=1000) - utc_timestamp = date_in_future.isoformat() + 'Z' -+ date_in_future = datetime.now(UTC) + timedelta(seconds=1000) ++ date_in_future = datetime.now(timezone.utc) + timedelta(seconds=1000) + utc_timestamp = date_in_future.isoformat() cache_key = ( @@ -880,7 +880,7 @@ index cc49596..0a5e4d7 100644 def test_assume_role_retrieves_from_cache(self): - date_in_future = datetime.utcnow() + timedelta(seconds=1000) - utc_timestamp = date_in_future.isoformat() + 'Z' -+ date_in_future = datetime.now(UTC) + timedelta(seconds=1000) ++ date_in_future = datetime.now(timezone.utc) + timedelta(seconds=1000) + utc_timestamp = date_in_future.isoformat() self.fake_config['profiles']['development']['role_arn'] = 'myrole' @@ -891,7 +891,7 @@ index cc49596..0a5e4d7 100644 def test_chain_prefers_cache(self): - date_in_future = datetime.utcnow() + timedelta(seconds=1000) - utc_timestamp = date_in_future.isoformat() + 'Z' -+ date_in_future = datetime.now(UTC) + timedelta(seconds=1000) ++ date_in_future = datetime.now(timezone.utc) + timedelta(seconds=1000) + utc_timestamp = date_in_future.isoformat() # The profile we will be using has a cache entry, but the profile it @@ -905,7 +905,7 @@ index e06e0c1..fc56d71 100644 self.datetime_patch = mock.patch('botocore.signers.datetime') self.datetime_mock = self.datetime_patch.start() - self.fixed_date = datetime.datetime(2014, 3, 10, 17, 2, 55, 0) -+ self.fixed_date = datetime.datetime(2014, 3, 10, 17, 2, 55, 0, tzinfo=datetime.UTC) ++ self.fixed_date = datetime.datetime(2014, 3, 10, 17, 2, 55, 0, tzinfo=datetime.timezone.utc) self.fixed_delta = datetime.timedelta(seconds=3600) - self.datetime_mock.datetime.utcnow.return_value = self.fixed_date + self.datetime_mock.datetime.now.return_value = self.fixed_date @@ -939,7 +939,7 @@ index a4d7f13..97df14b 100644 ): if dt is None: - dt = datetime.datetime.utcnow() -+ dt = datetime.datetime.now(datetime.UTC) ++ dt = datetime.datetime.now(datetime.timezone.utc) if offset is not None: dt = offset_func(dt, offset) @@ -967,7 +967,7 @@ index 1471ba9..3e30717 100644 - mocked_datetime.utcnow.return_value = datetime.datetime( - 2013, 8, 9, 23, 42) + mocked_datetime.now.return_value = datetime.datetime( -+ 2013, 8, 9, 23, 42, tzinfo=datetime.UTC) ++ 2013, 8, 9, 23, 42, tzinfo=datetime.timezone.utc) def tearDown(self): self.datetime_patcher.stop() @@ -980,7 +980,7 @@ index 964ec88..2213f96 100644 def __init__(self, module, date=None): if date is None: - date = datetime.datetime.utcnow() -+ date = datetime.datetime.now(datetime.UTC) ++ date = datetime.datetime.now(datetime.timezone.utc) self.date = date self.datetime_patcher = mock.patch.object( module, 'datetime', diff --git a/ruamel-yaml-0.17.32.patch b/ruamel-yaml-0.17.32.patch index eee82b9..471dd9f 100644 --- a/ruamel-yaml-0.17.32.patch +++ b/ruamel-yaml-0.17.32.patch @@ -1,15 +1,23 @@ diff --git a/awscli/customizations/cloudformation/yamlhelper.py b/awscli/customizations/cloudformation/yamlhelper.py -index abdc749..ef32415 100644 +index abdc749..9cf9496 100644 --- a/awscli/customizations/cloudformation/yamlhelper.py +++ b/awscli/customizations/cloudformation/yamlhelper.py -@@ -92,6 +92,7 @@ def yaml_dump(dict_to_dump): +@@ -92,8 +92,14 @@ def yaml_dump(dict_to_dump): yaml.Representer = FlattenAliasRepresenter _add_yaml_1_1_boolean_resolvers(yaml.Resolver) yaml.Representer.add_representer(OrderedDict, _dict_representer) + yaml.Representer.add_representer(dict, _dict_representer) - return dump_yaml_to_str(yaml, dict_to_dump) +- return dump_yaml_to_str(yaml, dict_to_dump) ++ result = dump_yaml_to_str(yaml, dict_to_dump) ++ ++ # let other YAML instances use the default dict representer ++ yaml.Representer.add_representer(dict, ruamel.yaml.representer.SafeRepresenter.represent_dict) ++ ++ return result + + def _dict_constructor(loader, node): diff --git a/awscli/customizations/eks/kubeconfig.py b/awscli/customizations/eks/kubeconfig.py index 5130f7f..64526a7 100644 --- a/awscli/customizations/eks/kubeconfig.py @@ -33,10 +41,10 @@ index 5130f7f..64526a7 100644 f"Entry in {key} not a {dict}. ") diff --git a/awscli/customizations/eks/ordered_yaml.py b/awscli/customizations/eks/ordered_yaml.py -index 23834e0..1ea6341 100644 +index 23834e0..5c0f92a 100644 --- a/awscli/customizations/eks/ordered_yaml.py +++ b/awscli/customizations/eks/ordered_yaml.py -@@ -46,8 +46,10 @@ def ordered_yaml_dump(to_dump, stream=None): +@@ -46,10 +46,18 @@ def ordered_yaml_dump(to_dump, stream=None): :type stream: file """ yaml = ruamel.yaml.YAML(typ="safe", pure=True) @@ -46,9 +54,19 @@ index 23834e0..1ea6341 100644 + yaml.Representer.add_representer(dict, _ordered_representer) if stream is None: - return dump_yaml_to_str(yaml, to_dump) +- return dump_yaml_to_str(yaml, to_dump) ++ result = dump_yaml_to_str(yaml, to_dump) ++ else: ++ result = None ++ yaml.dump(to_dump, stream) + +- yaml.dump(to_dump, stream) ++ # let other YAML instances use the default dict representer ++ yaml.Representer.add_representer(dict, ruamel.yaml.representer.SafeRepresenter.represent_dict) ++ ++ return result diff --git a/tests/unit/customizations/cloudformation/test_yamlhelper.py b/tests/unit/customizations/cloudformation/test_yamlhelper.py -index 9f511b0..29a93a5 100644 +index 466ae2e..1adad4e 100644 --- a/tests/unit/customizations/cloudformation/test_yamlhelper.py +++ b/tests/unit/customizations/cloudformation/test_yamlhelper.py @@ -139,10 +139,10 @@ class TestYaml(BaseYAMLTest):