From 61a5c5fc968df73fab7c06f0f977fdf2e0398f82 Mon Sep 17 00:00:00 2001 From: kevin-james-sp Date: Thu, 2 May 2024 15:14:15 +0100 Subject: [PATCH 01/18] Allow AWS sam local invoke to retrieve account id from current logged in session --- samcli/commands/local/cli_common/invoke_context.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/samcli/commands/local/cli_common/invoke_context.py b/samcli/commands/local/cli_common/invoke_context.py index 10e9fdb307..35438037d9 100644 --- a/samcli/commands/local/cli_common/invoke_context.py +++ b/samcli/commands/local/cli_common/invoke_context.py @@ -2,6 +2,8 @@ Reads CLI arguments and performs necessary preparation to be able to run the function """ +import boto3 +from botocore.exceptions import TokenRetrievalError import errno import json import logging @@ -172,6 +174,17 @@ def __init__( self._global_parameter_overrides: Optional[Dict] = None if aws_region: self._global_parameter_overrides = {"AWS::Region": aws_region} + + # Attempt to get the Account ID from the current session (if any) + sts = boto3.client("sts") + try: + account_id = sts.get_caller_identity()["Account"] + if account_id: + if self._global_parameter_overrides is None: + self._global_parameter_overrides = {} + self._global_parameter_overrides["AWS::AccountId"] = account_id + except TokenRetrievalError: + LOG.warning( "No current session found, using default AWS::AccountId" ) self._layer_cache_basedir = layer_cache_basedir self._force_image_build = force_image_build From 9605545aa0b866265f8c1e0814e46c38cb0ec6bb Mon Sep 17 00:00:00 2001 From: kevin-james-sp Date: Fri, 3 May 2024 10:09:15 +0100 Subject: [PATCH 02/18] Moved account id code to separate function --- .../local/cli_common/invoke_context.py | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/samcli/commands/local/cli_common/invoke_context.py b/samcli/commands/local/cli_common/invoke_context.py index 35438037d9..efc3b78750 100644 --- a/samcli/commands/local/cli_common/invoke_context.py +++ b/samcli/commands/local/cli_common/invoke_context.py @@ -175,17 +175,7 @@ def __init__( if aws_region: self._global_parameter_overrides = {"AWS::Region": aws_region} - # Attempt to get the Account ID from the current session (if any) - sts = boto3.client("sts") - try: - account_id = sts.get_caller_identity()["Account"] - if account_id: - if self._global_parameter_overrides is None: - self._global_parameter_overrides = {} - self._global_parameter_overrides["AWS::AccountId"] = account_id - except TokenRetrievalError: - LOG.warning( "No current session found, using default AWS::AccountId" ) - + self._global_parameter_overrides = self._add_account_id_to_global(self._global_parameter_overrides) self._layer_cache_basedir = layer_cache_basedir self._force_image_build = force_image_build self._aws_region = aws_region @@ -358,6 +348,19 @@ def _clean_running_containers_and_related_resources(self) -> None: cast(WarmLambdaRuntime, self.lambda_runtime).clean_running_containers_and_related_resources() cast(RefreshableSamFunctionProvider, self._function_provider).stop_observer() + def _add_account_id_to_global(self, parameters) -> Dict|None: + # Attempt to get the Account ID from the current session (if any) + sts = boto3.client("sts") + try: + account_id = sts.get_caller_identity()["Account"] + if account_id: + if parameters is None: + parameters = {} + parameters["AWS::AccountId"] = account_id + except TokenRetrievalError: + LOG.warning( "No current session found, using default AWS::AccountId" ) + return parameters + @property def function_identifier(self) -> str: """ From 8ef323f2fe72385e8ea08609de40a4174dde969d Mon Sep 17 00:00:00 2001 From: defenderkev <135826328+defenderkev@users.noreply.github.com> Date: Tue, 7 May 2024 10:57:16 +0100 Subject: [PATCH 03/18] Update samcli/commands/local/cli_common/invoke_context.py Co-authored-by: Daniel Mil <84205762+mildaniel@users.noreply.github.com> --- samcli/commands/local/cli_common/invoke_context.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samcli/commands/local/cli_common/invoke_context.py b/samcli/commands/local/cli_common/invoke_context.py index efc3b78750..2b745d41cc 100644 --- a/samcli/commands/local/cli_common/invoke_context.py +++ b/samcli/commands/local/cli_common/invoke_context.py @@ -352,7 +352,7 @@ def _add_account_id_to_global(self, parameters) -> Dict|None: # Attempt to get the Account ID from the current session (if any) sts = boto3.client("sts") try: - account_id = sts.get_caller_identity()["Account"] + account_id = sts.get_caller_identity().get("Account") if account_id: if parameters is None: parameters = {} From 6a39e1db0aae23efe694c64070e31430b88e178e Mon Sep 17 00:00:00 2001 From: defenderkev <135826328+defenderkev@users.noreply.github.com> Date: Tue, 7 May 2024 10:57:23 +0100 Subject: [PATCH 04/18] Update samcli/commands/local/cli_common/invoke_context.py Co-authored-by: Daniel Mil <84205762+mildaniel@users.noreply.github.com> --- samcli/commands/local/cli_common/invoke_context.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samcli/commands/local/cli_common/invoke_context.py b/samcli/commands/local/cli_common/invoke_context.py index 2b745d41cc..c2d7a455ba 100644 --- a/samcli/commands/local/cli_common/invoke_context.py +++ b/samcli/commands/local/cli_common/invoke_context.py @@ -348,7 +348,7 @@ def _clean_running_containers_and_related_resources(self) -> None: cast(WarmLambdaRuntime, self.lambda_runtime).clean_running_containers_and_related_resources() cast(RefreshableSamFunctionProvider, self._function_provider).stop_observer() - def _add_account_id_to_global(self, parameters) -> Dict|None: + def _add_account_id_to_global(self, parameters) -> Optional[Dict]: # Attempt to get the Account ID from the current session (if any) sts = boto3.client("sts") try: From fb33fbe5efb1724e54934522893b62e4233d6fc8 Mon Sep 17 00:00:00 2001 From: kevin-james-sp Date: Tue, 7 May 2024 12:53:15 +0100 Subject: [PATCH 05/18] Requested changes --- .../local/cli_common/invoke_context.py | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/samcli/commands/local/cli_common/invoke_context.py b/samcli/commands/local/cli_common/invoke_context.py index c2d7a455ba..16336da914 100644 --- a/samcli/commands/local/cli_common/invoke_context.py +++ b/samcli/commands/local/cli_common/invoke_context.py @@ -2,8 +2,6 @@ Reads CLI arguments and performs necessary preparation to be able to run the function """ -import boto3 -from botocore.exceptions import TokenRetrievalError import errno import json import logging @@ -12,6 +10,9 @@ from pathlib import Path from typing import Any, Dict, List, Optional, TextIO, Tuple, Type, cast +import boto3 +from botocore.exceptions import TokenRetrievalError + from samcli.commands._utils.template import TemplateFailedParsingException, TemplateNotFoundException from samcli.commands.exceptions import ContainersInitializationException from samcli.commands.local.cli_common.user_exceptions import DebugContextException, InvokeContextException @@ -174,8 +175,8 @@ def __init__( self._global_parameter_overrides: Optional[Dict] = None if aws_region: self._global_parameter_overrides = {"AWS::Region": aws_region} - - self._global_parameter_overrides = self._add_account_id_to_global(self._global_parameter_overrides) + + self._add_account_id_to_global() self._layer_cache_basedir = layer_cache_basedir self._force_image_build = force_image_build self._aws_region = aws_region @@ -348,18 +349,17 @@ def _clean_running_containers_and_related_resources(self) -> None: cast(WarmLambdaRuntime, self.lambda_runtime).clean_running_containers_and_related_resources() cast(RefreshableSamFunctionProvider, self._function_provider).stop_observer() - def _add_account_id_to_global(self, parameters) -> Optional[Dict]: + def _add_account_id_to_global(self): # Attempt to get the Account ID from the current session (if any) sts = boto3.client("sts") try: - account_id = sts.get_caller_identity().get("Account") + account_id = sts.get_caller_identity().get("Account") if account_id: - if parameters is None: - parameters = {} - parameters["AWS::AccountId"] = account_id + if self._global_parameter_overrides is None: + self._global_parameter_overrides = {} + self._global_parameter_overrides["AWS::AccountId"] = account_id except TokenRetrievalError: - LOG.warning( "No current session found, using default AWS::AccountId" ) - return parameters + LOG.warning("No current session found, using default AWS::AccountId") @property def function_identifier(self) -> str: From 77543bf694a47bbedbe491d8304f0ef421b9a2b3 Mon Sep 17 00:00:00 2001 From: kevin-james-sp Date: Tue, 7 May 2024 12:53:26 +0100 Subject: [PATCH 06/18] unit tests --- .../local/cli_common/test_invoke_context.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tests/unit/commands/local/cli_common/test_invoke_context.py b/tests/unit/commands/local/cli_common/test_invoke_context.py index ccdfebaae7..36698c961f 100644 --- a/tests/unit/commands/local/cli_common/test_invoke_context.py +++ b/tests/unit/commands/local/cli_common/test_invoke_context.py @@ -1360,3 +1360,20 @@ def test_must_pass_custom_region(self, get_stacks_mock): get_stacks_mock.assert_called_with( "template_file", parameter_overrides=None, global_parameter_overrides={"AWS::Region": "my-custom-region"} ) + + +class TestInvokeContext_add_account_id_to_global(TestCase): + def test_must_work_with_no_token(self): + invoke_context = InvokeContext("template_file") + invoke_context._add_account_id_to_global() + assert invoke_context._global_parameter_overrides is None + + @patch("boto3.client") + def test_must_work_with_token(self, get_caller_identity_mock): + get_caller_identity_mock.return_value.get_caller_identity.return_value.get.return_value = "210987654321" + invoke_context = InvokeContext("template_file") + invoke_context._add_account_id_to_global() + print("\n") + print(invoke_context._global_parameter_overrides) + print("\n") + assert invoke_context._global_parameter_overrides.get("AWS::AccountId") is "210987654321" From fe8ace6e13d3ba5c44b954a58b831afab0c84e7b Mon Sep 17 00:00:00 2001 From: defenderkev <135826328+defenderkev@users.noreply.github.com> Date: Tue, 7 May 2024 20:17:44 +0100 Subject: [PATCH 07/18] Update tests/unit/commands/local/cli_common/test_invoke_context.py Co-authored-by: Daniel Mil <84205762+mildaniel@users.noreply.github.com> --- tests/unit/commands/local/cli_common/test_invoke_context.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/commands/local/cli_common/test_invoke_context.py b/tests/unit/commands/local/cli_common/test_invoke_context.py index 36698c961f..1b7470c574 100644 --- a/tests/unit/commands/local/cli_common/test_invoke_context.py +++ b/tests/unit/commands/local/cli_common/test_invoke_context.py @@ -1366,7 +1366,7 @@ class TestInvokeContext_add_account_id_to_global(TestCase): def test_must_work_with_no_token(self): invoke_context = InvokeContext("template_file") invoke_context._add_account_id_to_global() - assert invoke_context._global_parameter_overrides is None + self.assertIsNone(invoke_context._global_parameter_overrides) @patch("boto3.client") def test_must_work_with_token(self, get_caller_identity_mock): From f2ee4a2ba1b5a96c8359cb1ec69000a4c3858613 Mon Sep 17 00:00:00 2001 From: kevin-james-sp Date: Tue, 7 May 2024 20:25:53 +0100 Subject: [PATCH 08/18] put docstring in --- samcli/commands/local/cli_common/invoke_context.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/samcli/commands/local/cli_common/invoke_context.py b/samcli/commands/local/cli_common/invoke_context.py index 16336da914..11ad10f1f3 100644 --- a/samcli/commands/local/cli_common/invoke_context.py +++ b/samcli/commands/local/cli_common/invoke_context.py @@ -350,7 +350,11 @@ def _clean_running_containers_and_related_resources(self) -> None: cast(RefreshableSamFunctionProvider, self._function_provider).stop_observer() def _add_account_id_to_global(self): - # Attempt to get the Account ID from the current session (if any) + """ + Attempts to get the Account ID from the current session + If there is no current session, the standard parameter override for + AWS::AccountId is used + """ sts = boto3.client("sts") try: account_id = sts.get_caller_identity().get("Account") From 8da5919c6d2fa1ef5efeb5a2d1574c9675df1e41 Mon Sep 17 00:00:00 2001 From: kevin-james-sp Date: Tue, 7 May 2024 20:26:16 +0100 Subject: [PATCH 09/18] requested assertion changes --- tests/unit/commands/local/cli_common/test_invoke_context.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tests/unit/commands/local/cli_common/test_invoke_context.py b/tests/unit/commands/local/cli_common/test_invoke_context.py index 1b7470c574..0a56406a34 100644 --- a/tests/unit/commands/local/cli_common/test_invoke_context.py +++ b/tests/unit/commands/local/cli_common/test_invoke_context.py @@ -1373,7 +1373,4 @@ def test_must_work_with_token(self, get_caller_identity_mock): get_caller_identity_mock.return_value.get_caller_identity.return_value.get.return_value = "210987654321" invoke_context = InvokeContext("template_file") invoke_context._add_account_id_to_global() - print("\n") - print(invoke_context._global_parameter_overrides) - print("\n") - assert invoke_context._global_parameter_overrides.get("AWS::AccountId") is "210987654321" + self.assertEqual(invoke_context._global_parameter_overrides.get("AWS::AccountId"), "210987654321") From 0c6d02571a217617f6a5a55a423c8cf3ccde781d Mon Sep 17 00:00:00 2001 From: defenderkev Date: Mon, 20 May 2024 11:58:47 +0100 Subject: [PATCH 10/18] Fix changes requested by @hawflau --- samcli/commands/local/cli_common/invoke_context.py | 8 ++++++-- .../unit/commands/local/cli_common/test_invoke_context.py | 8 +++++--- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/samcli/commands/local/cli_common/invoke_context.py b/samcli/commands/local/cli_common/invoke_context.py index 11ad10f1f3..8b534fe2ee 100644 --- a/samcli/commands/local/cli_common/invoke_context.py +++ b/samcli/commands/local/cli_common/invoke_context.py @@ -10,9 +10,9 @@ from pathlib import Path from typing import Any, Dict, List, Optional, TextIO, Tuple, Type, cast -import boto3 from botocore.exceptions import TokenRetrievalError +import samcli.lib.utils.boto_utils from samcli.commands._utils.template import TemplateFailedParsingException, TemplateNotFoundException from samcli.commands.exceptions import ContainersInitializationException from samcli.commands.local.cli_common.user_exceptions import DebugContextException, InvokeContextException @@ -355,7 +355,10 @@ def _add_account_id_to_global(self): If there is no current session, the standard parameter override for AWS::AccountId is used """ - sts = boto3.client("sts") + client_provider = samcli.lib.utils.boto_utils.get_boto_client_provider_with_config() + + sts = client_provider("sts") + try: account_id = sts.get_caller_identity().get("Account") if account_id: @@ -492,6 +495,7 @@ def _is_debugging(self) -> bool: def _get_stacks(self) -> List[Stack]: try: + print(SamLocalStackProvider.get_stacks) stacks, _ = SamLocalStackProvider.get_stacks( self._template_file, parameter_overrides=self._parameter_overrides, diff --git a/tests/unit/commands/local/cli_common/test_invoke_context.py b/tests/unit/commands/local/cli_common/test_invoke_context.py index 0a56406a34..4da15c2e1b 100644 --- a/tests/unit/commands/local/cli_common/test_invoke_context.py +++ b/tests/unit/commands/local/cli_common/test_invoke_context.py @@ -1368,9 +1368,11 @@ def test_must_work_with_no_token(self): invoke_context._add_account_id_to_global() self.assertIsNone(invoke_context._global_parameter_overrides) - @patch("boto3.client") - def test_must_work_with_token(self, get_caller_identity_mock): - get_caller_identity_mock.return_value.get_caller_identity.return_value.get.return_value = "210987654321" + @patch("samcli.lib.utils.boto_utils.get_boto_client_provider_with_config") + def test_must_work_with_token(self, get_boto_client_provider_with_config_mock): + get_boto_client_provider_with_config_mock.return_value.return_value.get_caller_identity.return_value.get.return_value = ( + "210987654321" + ) invoke_context = InvokeContext("template_file") invoke_context._add_account_id_to_global() self.assertEqual(invoke_context._global_parameter_overrides.get("AWS::AccountId"), "210987654321") From 290c55690f5a07d71a7969532fcebaec18406687 Mon Sep 17 00:00:00 2001 From: defenderkev Date: Fri, 24 May 2024 10:39:43 +0100 Subject: [PATCH 11/18] missed removing a debugging statement --- samcli/commands/local/cli_common/invoke_context.py | 1 - 1 file changed, 1 deletion(-) diff --git a/samcli/commands/local/cli_common/invoke_context.py b/samcli/commands/local/cli_common/invoke_context.py index 8b534fe2ee..82fc397262 100644 --- a/samcli/commands/local/cli_common/invoke_context.py +++ b/samcli/commands/local/cli_common/invoke_context.py @@ -495,7 +495,6 @@ def _is_debugging(self) -> bool: def _get_stacks(self) -> List[Stack]: try: - print(SamLocalStackProvider.get_stacks) stacks, _ = SamLocalStackProvider.get_stacks( self._template_file, parameter_overrides=self._parameter_overrides, From b3c5831c219f0f827276efbb56b00bdb6f102635 Mon Sep 17 00:00:00 2001 From: defenderkev Date: Fri, 24 May 2024 11:14:08 +0100 Subject: [PATCH 12/18] add cmd line params to client_provider init --- samcli/commands/local/cli_common/invoke_context.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/samcli/commands/local/cli_common/invoke_context.py b/samcli/commands/local/cli_common/invoke_context.py index 82fc397262..bf9e192e0b 100644 --- a/samcli/commands/local/cli_common/invoke_context.py +++ b/samcli/commands/local/cli_common/invoke_context.py @@ -176,12 +176,12 @@ def __init__( if aws_region: self._global_parameter_overrides = {"AWS::Region": aws_region} - self._add_account_id_to_global() self._layer_cache_basedir = layer_cache_basedir self._force_image_build = force_image_build self._aws_region = aws_region self._aws_profile = aws_profile self._shutdown = shutdown + self._add_account_id_to_global() self._container_host = container_host self._container_host_interface = container_host_interface @@ -355,7 +355,9 @@ def _add_account_id_to_global(self): If there is no current session, the standard parameter override for AWS::AccountId is used """ - client_provider = samcli.lib.utils.boto_utils.get_boto_client_provider_with_config() + client_provider = samcli.lib.utils.boto_utils.get_boto_client_provider_with_config( + region=self._aws_region, profile=self._aws_profile + ) sts = client_provider("sts") From c2543ce3e32900c2a9769d3b0ce3f2873dc310a9 Mon Sep 17 00:00:00 2001 From: defenderkev Date: Tue, 28 May 2024 11:16:13 +0100 Subject: [PATCH 13/18] import get boto client method directly --- samcli/commands/local/cli_common/invoke_context.py | 6 ++---- tests/unit/commands/local/cli_common/test_invoke_context.py | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/samcli/commands/local/cli_common/invoke_context.py b/samcli/commands/local/cli_common/invoke_context.py index bf9e192e0b..23c469cfc9 100644 --- a/samcli/commands/local/cli_common/invoke_context.py +++ b/samcli/commands/local/cli_common/invoke_context.py @@ -12,7 +12,6 @@ from botocore.exceptions import TokenRetrievalError -import samcli.lib.utils.boto_utils from samcli.commands._utils.template import TemplateFailedParsingException, TemplateNotFoundException from samcli.commands.exceptions import ContainersInitializationException from samcli.commands.local.cli_common.user_exceptions import DebugContextException, InvokeContextException @@ -23,6 +22,7 @@ from samcli.lib.providers.sam_stack_provider import SamLocalStackProvider from samcli.lib.utils import osutils from samcli.lib.utils.async_utils import AsyncContext +from samcli.lib.utils.boto_utils import get_boto_client_provider_with_config from samcli.lib.utils.packagetype import ZIP from samcli.lib.utils.stream_writer import StreamWriter from samcli.local.docker.exceptions import PortAlreadyInUse @@ -355,9 +355,7 @@ def _add_account_id_to_global(self): If there is no current session, the standard parameter override for AWS::AccountId is used """ - client_provider = samcli.lib.utils.boto_utils.get_boto_client_provider_with_config( - region=self._aws_region, profile=self._aws_profile - ) + client_provider = get_boto_client_provider_with_config(region=self._aws_region, profile=self._aws_profile) sts = client_provider("sts") diff --git a/tests/unit/commands/local/cli_common/test_invoke_context.py b/tests/unit/commands/local/cli_common/test_invoke_context.py index 4da15c2e1b..404fc5c51a 100644 --- a/tests/unit/commands/local/cli_common/test_invoke_context.py +++ b/tests/unit/commands/local/cli_common/test_invoke_context.py @@ -1368,7 +1368,7 @@ def test_must_work_with_no_token(self): invoke_context._add_account_id_to_global() self.assertIsNone(invoke_context._global_parameter_overrides) - @patch("samcli.lib.utils.boto_utils.get_boto_client_provider_with_config") + @patch("samcli.commands.local.cli_common.invoke_context.get_boto_client_provider_with_config") def test_must_work_with_token(self, get_boto_client_provider_with_config_mock): get_boto_client_provider_with_config_mock.return_value.return_value.get_caller_identity.return_value.get.return_value = ( "210987654321" From 3ec98477de7f2b70766b6a28cd1a805814b4336f Mon Sep 17 00:00:00 2001 From: defenderkev Date: Tue, 28 May 2024 11:35:29 +0100 Subject: [PATCH 14/18] Changed some existing tests, as the new code now means any profile specified has to be a real profile, and always returns an aws_profile value (even if it is `None`) --- .../local/cli_common/test_invoke_context.py | 21 ++++++------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/tests/unit/commands/local/cli_common/test_invoke_context.py b/tests/unit/commands/local/cli_common/test_invoke_context.py index 404fc5c51a..e0b76a9059 100644 --- a/tests/unit/commands/local/cli_common/test_invoke_context.py +++ b/tests/unit/commands/local/cli_common/test_invoke_context.py @@ -61,7 +61,6 @@ def test_must_read_from_necessary_files(self, SamFunctionProviderMock, Container debug_args="args", parameter_overrides={}, aws_region="region", - aws_profile="profile", shutdown=False, invoke_images={None: "image"}, ) @@ -144,7 +143,6 @@ def test_must_initialize_all_containers_if_warm_containers_is_enabled( debug_args="args", parameter_overrides=parameter_overrides, aws_region="region", - aws_profile="profile", warm_container_initialization_mode=ContainersInitializationMode.EAGER.value, shutdown=True, invoke_images={None: "image"}, @@ -237,7 +235,6 @@ def test_must_set_debug_function_if_warm_containers_enabled_no_debug_function_pr debug_args="args", parameter_overrides=parameter_overrides, aws_region="region", - aws_profile="profile", warm_container_initialization_mode=ContainersInitializationMode.EAGER.value, debug_function="", shutdown=True, @@ -329,7 +326,6 @@ def test_no_container_will_be_initialized_if_lazy_containers_is_enabled( debug_args="args", parameter_overrides=parameter_overrides, aws_region="region", - aws_profile="profile", warm_container_initialization_mode=ContainersInitializationMode.LAZY.value, debug_function="debug_function", shutdown=True, @@ -519,7 +515,6 @@ def test_must_work_in_with_statement(self, ExitMock, EnterMock): debug_ports=[1111], debugger_path="path-to-debugger", debug_args="args", - aws_profile="profile", invoke_images={None: "image"}, ) as context: self.assertEqual(context_obj, context) @@ -599,7 +594,6 @@ def test_must_create_runner( debug_ports=[1111], debugger_path="path-to-debugger", debug_args="args", - aws_profile="profile", aws_region="region", ) self.context.get_cwd = Mock() @@ -628,7 +622,7 @@ def test_must_create_runner( real_path=ANY, debug_context=None, env_vars_values=ANY, - aws_profile="profile", + aws_profile=None, aws_region="region", container_host=None, container_host_interface=None, @@ -678,7 +672,6 @@ def test_must_create_runner_using_warm_containers( debug_ports=[1111], debugger_path="path-to-debugger", debug_args="args", - aws_profile="profile", aws_region="region", warm_container_initialization_mode=ContainersInitializationMode.EAGER, ) @@ -708,7 +701,7 @@ def test_must_create_runner_using_warm_containers( real_path=ANY, debug_context=None, env_vars_values=ANY, - aws_profile="profile", + aws_profile=None, aws_region="region", container_host=None, container_host_interface=None, @@ -763,7 +756,6 @@ def test_must_create_runner_with_container_host_option( debug_ports=[1111], debugger_path="path-to-debugger", debug_args="args", - aws_profile="profile", aws_region="region", container_host="abcdef", container_host_interface="192.168.100.101", @@ -794,7 +786,7 @@ def test_must_create_runner_with_container_host_option( real_path=ANY, debug_context=None, env_vars_values=ANY, - aws_profile="profile", + aws_profile=None, aws_region="region", container_host="abcdef", container_host_interface="192.168.100.101", @@ -849,7 +841,6 @@ def test_must_create_runner_with_extra_hosts_option( debug_ports=[1111], debugger_path="path-to-debugger", debug_args="args", - aws_profile="profile", aws_region="region", container_host="abcdef", add_host={"prod-na.host": "10.11.12.13", "gamma-na.host": "10.22.23.24"}, @@ -880,7 +871,7 @@ def test_must_create_runner_with_extra_hosts_option( real_path=ANY, debug_context=None, env_vars_values=ANY, - aws_profile="profile", + aws_profile=None, aws_region="region", container_host="abcdef", container_host_interface=None, @@ -938,7 +929,7 @@ def test_must_create_runner_with_invoke_image_option( debug_ports=[1111], debugger_path="path-to-debugger", debug_args="args", - aws_profile="profile", + # aws_profile="aws_profile", aws_region="region", invoke_images={None: "image"}, ) @@ -968,7 +959,7 @@ def test_must_create_runner_with_invoke_image_option( real_path=ANY, debug_context=None, env_vars_values=ANY, - aws_profile="profile", + aws_profile=None, aws_region="region", container_host=None, container_host_interface=None, From 40ee4e2298dfd99d308f80631448723d0aab9874 Mon Sep 17 00:00:00 2001 From: defenderkev Date: Tue, 28 May 2024 21:29:19 +0100 Subject: [PATCH 15/18] Added return type annotation --- samcli/commands/local/cli_common/invoke_context.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samcli/commands/local/cli_common/invoke_context.py b/samcli/commands/local/cli_common/invoke_context.py index 23c469cfc9..c8a4f92d7c 100644 --- a/samcli/commands/local/cli_common/invoke_context.py +++ b/samcli/commands/local/cli_common/invoke_context.py @@ -349,7 +349,7 @@ def _clean_running_containers_and_related_resources(self) -> None: cast(WarmLambdaRuntime, self.lambda_runtime).clean_running_containers_and_related_resources() cast(RefreshableSamFunctionProvider, self._function_provider).stop_observer() - def _add_account_id_to_global(self): + def _add_account_id_to_global(self) -> None: """ Attempts to get the Account ID from the current session If there is no current session, the standard parameter override for From e7061b392e345dfefedd461c24846757ac4746b8 Mon Sep 17 00:00:00 2001 From: defenderkev Date: Tue, 28 May 2024 23:12:18 +0100 Subject: [PATCH 16/18] catch another Exception type, as `make pr` was failing when no credentials files exist (e.g. github actions environment) --- samcli/commands/local/cli_common/invoke_context.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/samcli/commands/local/cli_common/invoke_context.py b/samcli/commands/local/cli_common/invoke_context.py index c8a4f92d7c..4da721f49d 100644 --- a/samcli/commands/local/cli_common/invoke_context.py +++ b/samcli/commands/local/cli_common/invoke_context.py @@ -10,7 +10,7 @@ from pathlib import Path from typing import Any, Dict, List, Optional, TextIO, Tuple, Type, cast -from botocore.exceptions import TokenRetrievalError +from botocore.exceptions import NoCredentialsError, TokenRetrievalError from samcli.commands._utils.template import TemplateFailedParsingException, TemplateNotFoundException from samcli.commands.exceptions import ContainersInitializationException @@ -365,7 +365,7 @@ def _add_account_id_to_global(self) -> None: if self._global_parameter_overrides is None: self._global_parameter_overrides = {} self._global_parameter_overrides["AWS::AccountId"] = account_id - except TokenRetrievalError: + except (NoCredentialsError, TokenRetrievalError): LOG.warning("No current session found, using default AWS::AccountId") @property From 90bca1a6d11d54070f209d67de42ca4b134fd7a4 Mon Sep 17 00:00:00 2001 From: Kev Date: Mon, 3 Jun 2024 05:07:53 +0100 Subject: [PATCH 17/18] Add ClientError catch and update some of the tests --- .../local/cli_common/invoke_context.py | 4 +- .../local/cli_common/test_invoke_context.py | 37 +++++++++++++------ 2 files changed, 28 insertions(+), 13 deletions(-) diff --git a/samcli/commands/local/cli_common/invoke_context.py b/samcli/commands/local/cli_common/invoke_context.py index 4da721f49d..0e56e27846 100644 --- a/samcli/commands/local/cli_common/invoke_context.py +++ b/samcli/commands/local/cli_common/invoke_context.py @@ -10,7 +10,7 @@ from pathlib import Path from typing import Any, Dict, List, Optional, TextIO, Tuple, Type, cast -from botocore.exceptions import NoCredentialsError, TokenRetrievalError +from botocore.exceptions import ClientError, NoCredentialsError, TokenRetrievalError from samcli.commands._utils.template import TemplateFailedParsingException, TemplateNotFoundException from samcli.commands.exceptions import ContainersInitializationException @@ -365,7 +365,7 @@ def _add_account_id_to_global(self) -> None: if self._global_parameter_overrides is None: self._global_parameter_overrides = {} self._global_parameter_overrides["AWS::AccountId"] = account_id - except (NoCredentialsError, TokenRetrievalError): + except (NoCredentialsError, TokenRetrievalError, ClientError): LOG.warning("No current session found, using default AWS::AccountId") @property diff --git a/tests/unit/commands/local/cli_common/test_invoke_context.py b/tests/unit/commands/local/cli_common/test_invoke_context.py index e0b76a9059..3d6a32c34e 100644 --- a/tests/unit/commands/local/cli_common/test_invoke_context.py +++ b/tests/unit/commands/local/cli_common/test_invoke_context.py @@ -28,7 +28,8 @@ class TestInvokeContext__enter__(TestCase): @patch("samcli.commands.local.cli_common.invoke_context.ContainerManager") @patch("samcli.commands.local.cli_common.invoke_context.SamFunctionProvider") - def test_must_read_from_necessary_files(self, SamFunctionProviderMock, ContainerManagerMock): + @patch("samcli.commands.local.cli_common.invoke_context.InvokeContext._add_account_id_to_global") + def test_must_read_from_necessary_files(self, _add_account_id_to_global_mock, SamFunctionProviderMock, ContainerManagerMock): function_provider = Mock() function_provider.get_all.return_value = [ Mock( @@ -61,6 +62,7 @@ def test_must_read_from_necessary_files(self, SamFunctionProviderMock, Container debug_args="args", parameter_overrides={}, aws_region="region", + aws_profile="profile", shutdown=False, invoke_images={None: "image"}, ) @@ -115,8 +117,9 @@ def test_must_read_from_necessary_files(self, SamFunctionProviderMock, Container @patch("samcli.commands.local.cli_common.invoke_context.ContainerManager") @patch("samcli.commands.local.cli_common.invoke_context.RefreshableSamFunctionProvider") + @patch("samcli.commands.local.cli_common.invoke_context.InvokeContext._add_account_id_to_global") def test_must_initialize_all_containers_if_warm_containers_is_enabled( - self, RefreshableSamFunctionProviderMock, ContainerManagerMock + self, _add_account_id_to_global_mock, RefreshableSamFunctionProviderMock, ContainerManagerMock ): function_provider = Mock() function = Mock() @@ -143,6 +146,7 @@ def test_must_initialize_all_containers_if_warm_containers_is_enabled( debug_args="args", parameter_overrides=parameter_overrides, aws_region="region", + aws_profile="profile", warm_container_initialization_mode=ContainersInitializationMode.EAGER.value, shutdown=True, invoke_images={None: "image"}, @@ -203,8 +207,9 @@ def test_must_initialize_all_containers_if_warm_containers_is_enabled( @patch("samcli.commands.local.cli_common.invoke_context.ContainerManager") @patch("samcli.commands.local.cli_common.invoke_context.RefreshableSamFunctionProvider") + @patch("samcli.commands.local.cli_common.invoke_context.InvokeContext._add_account_id_to_global") def test_must_set_debug_function_if_warm_containers_enabled_no_debug_function_provided_and_template_contains_one_function( - self, RefreshableSamFunctionProviderMock, ContainerManagerMock + self, _add_account_id_to_global_mock, RefreshableSamFunctionProviderMock, ContainerManagerMock ): function_provider = Mock() function = Mock( @@ -235,6 +240,7 @@ def test_must_set_debug_function_if_warm_containers_enabled_no_debug_function_pr debug_args="args", parameter_overrides=parameter_overrides, aws_region="region", + aws_profile="profile", warm_container_initialization_mode=ContainersInitializationMode.EAGER.value, debug_function="", shutdown=True, @@ -297,8 +303,10 @@ def test_must_set_debug_function_if_warm_containers_enabled_no_debug_function_pr @patch("samcli.commands.local.cli_common.invoke_context.ContainerManager") @patch("samcli.commands.local.cli_common.invoke_context.RefreshableSamFunctionProvider") + @patch("samcli.commands.local.cli_common.invoke_context.InvokeContext._add_account_id_to_global") + def test_no_container_will_be_initialized_if_lazy_containers_is_enabled( - self, RefreshableSamFunctionProviderMock, ContainerManagerMock + self, _add_account_id_to_global_mock, RefreshableSamFunctionProviderMock, ContainerManagerMock ): function_provider = Mock() function_provider.get_all.return_value = [ @@ -326,6 +334,7 @@ def test_no_container_will_be_initialized_if_lazy_containers_is_enabled( debug_args="args", parameter_overrides=parameter_overrides, aws_region="region", + aws_profile="profile", warm_container_initialization_mode=ContainersInitializationMode.LAZY.value, debug_function="debug_function", shutdown=True, @@ -515,6 +524,7 @@ def test_must_work_in_with_statement(self, ExitMock, EnterMock): debug_ports=[1111], debugger_path="path-to-debugger", debug_args="args", + aws_profile="profile", invoke_images={None: "image"}, ) as context: self.assertEqual(context_obj, context) @@ -594,6 +604,7 @@ def test_must_create_runner( debug_ports=[1111], debugger_path="path-to-debugger", debug_args="args", + aws_profile="profile", aws_region="region", ) self.context.get_cwd = Mock() @@ -622,7 +633,7 @@ def test_must_create_runner( real_path=ANY, debug_context=None, env_vars_values=ANY, - aws_profile=None, + aws_profile="profile", aws_region="region", container_host=None, container_host_interface=None, @@ -672,6 +683,7 @@ def test_must_create_runner_using_warm_containers( debug_ports=[1111], debugger_path="path-to-debugger", debug_args="args", + aws_profile="profile", aws_region="region", warm_container_initialization_mode=ContainersInitializationMode.EAGER, ) @@ -701,7 +713,7 @@ def test_must_create_runner_using_warm_containers( real_path=ANY, debug_context=None, env_vars_values=ANY, - aws_profile=None, + aws_profile="profile", aws_region="region", container_host=None, container_host_interface=None, @@ -756,6 +768,7 @@ def test_must_create_runner_with_container_host_option( debug_ports=[1111], debugger_path="path-to-debugger", debug_args="args", + aws_profile="profile", aws_region="region", container_host="abcdef", container_host_interface="192.168.100.101", @@ -786,7 +799,7 @@ def test_must_create_runner_with_container_host_option( real_path=ANY, debug_context=None, env_vars_values=ANY, - aws_profile=None, + aws_profile="profile", aws_region="region", container_host="abcdef", container_host_interface="192.168.100.101", @@ -841,6 +854,7 @@ def test_must_create_runner_with_extra_hosts_option( debug_ports=[1111], debugger_path="path-to-debugger", debug_args="args", + aws_profile="profile", aws_region="region", container_host="abcdef", add_host={"prod-na.host": "10.11.12.13", "gamma-na.host": "10.22.23.24"}, @@ -871,7 +885,7 @@ def test_must_create_runner_with_extra_hosts_option( real_path=ANY, debug_context=None, env_vars_values=ANY, - aws_profile=None, + aws_profile="profile", aws_region="region", container_host="abcdef", container_host_interface=None, @@ -929,7 +943,7 @@ def test_must_create_runner_with_invoke_image_option( debug_ports=[1111], debugger_path="path-to-debugger", debug_args="args", - # aws_profile="aws_profile", + aws_profile="profile", aws_region="region", invoke_images={None: "image"}, ) @@ -959,7 +973,7 @@ def test_must_create_runner_with_invoke_image_option( real_path=ANY, debug_context=None, env_vars_values=ANY, - aws_profile=None, + aws_profile="profile", aws_region="region", container_host=None, container_host_interface=None, @@ -1344,7 +1358,8 @@ def test_debugger_path_resolves(self, pathlib_mock, debug_context_mock): class TestInvokeContext_get_stacks(TestCase): @patch("samcli.commands.local.cli_common.invoke_context.SamLocalStackProvider.get_stacks") - def test_must_pass_custom_region(self, get_stacks_mock): + @patch("samcli.commands.local.cli_common.invoke_context.InvokeContext._add_account_id_to_global") + def test_must_pass_custom_region(self, add_account_id_to_global_mock, get_stacks_mock): get_stacks_mock.return_value = [Mock(), []] invoke_context = InvokeContext("template_file", aws_region="my-custom-region") invoke_context._get_stacks() From 1740627b28a707472d27b625c4ba56476e6dc873 Mon Sep 17 00:00:00 2001 From: defenderkev Date: Wed, 5 Jun 2024 11:16:30 +0100 Subject: [PATCH 18/18] Fixed the last tests - mocked out the new account_id code as it's not relevant for the tests --- .../local/cli_common/test_invoke_context.py | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/tests/unit/commands/local/cli_common/test_invoke_context.py b/tests/unit/commands/local/cli_common/test_invoke_context.py index 3d6a32c34e..d406df5060 100644 --- a/tests/unit/commands/local/cli_common/test_invoke_context.py +++ b/tests/unit/commands/local/cli_common/test_invoke_context.py @@ -29,7 +29,9 @@ class TestInvokeContext__enter__(TestCase): @patch("samcli.commands.local.cli_common.invoke_context.ContainerManager") @patch("samcli.commands.local.cli_common.invoke_context.SamFunctionProvider") @patch("samcli.commands.local.cli_common.invoke_context.InvokeContext._add_account_id_to_global") - def test_must_read_from_necessary_files(self, _add_account_id_to_global_mock, SamFunctionProviderMock, ContainerManagerMock): + def test_must_read_from_necessary_files( + self, _add_account_id_to_global_mock, SamFunctionProviderMock, ContainerManagerMock + ): function_provider = Mock() function_provider.get_all.return_value = [ Mock( @@ -304,7 +306,6 @@ def test_must_set_debug_function_if_warm_containers_enabled_no_debug_function_pr @patch("samcli.commands.local.cli_common.invoke_context.ContainerManager") @patch("samcli.commands.local.cli_common.invoke_context.RefreshableSamFunctionProvider") @patch("samcli.commands.local.cli_common.invoke_context.InvokeContext._add_account_id_to_global") - def test_no_container_will_be_initialized_if_lazy_containers_is_enabled( self, _add_account_id_to_global_mock, RefreshableSamFunctionProviderMock, ContainerManagerMock ): @@ -509,7 +510,8 @@ class TestInvokeContextAsContextManager(TestCase): @patch.object(InvokeContext, "__enter__") @patch.object(InvokeContext, "__exit__") - def test_must_work_in_with_statement(self, ExitMock, EnterMock): + @patch("samcli.commands.local.cli_common.invoke_context.InvokeContext._add_account_id_to_global") + def test_must_work_in_with_statement(self, _add_account_id_to_global_mock, ExitMock, EnterMock): context_obj = Mock() EnterMock.return_value = context_obj @@ -567,8 +569,10 @@ class TestInvokeContext_local_lambda_runner(TestCase): @patch("samcli.commands.local.cli_common.invoke_context.LambdaRuntime") @patch("samcli.commands.local.cli_common.invoke_context.LocalLambdaRunner") @patch("samcli.commands.local.cli_common.invoke_context.SamFunctionProvider") + @patch("samcli.commands.local.cli_common.invoke_context.InvokeContext._add_account_id_to_global") def test_must_create_runner( self, + _add_account_id_to_global_mock, SamFunctionProviderMock, LocalLambdaMock, LambdaRuntimeMock, @@ -650,8 +654,10 @@ def test_must_create_runner( @patch("samcli.commands.local.cli_common.invoke_context.WarmLambdaRuntime") @patch("samcli.commands.local.cli_common.invoke_context.LocalLambdaRunner") @patch("samcli.commands.local.cli_common.invoke_context.RefreshableSamFunctionProvider") + @patch("samcli.commands.local.cli_common.invoke_context.InvokeContext._add_account_id_to_global") def test_must_create_runner_using_warm_containers( self, + _add_account_id_to_global_mock, RefreshableSamFunctionProviderMock, LocalLambdaMock, WarmLambdaRuntimeMock, @@ -731,8 +737,10 @@ def test_must_create_runner_using_warm_containers( @patch("samcli.commands.local.cli_common.invoke_context.LambdaRuntime") @patch("samcli.commands.local.cli_common.invoke_context.LocalLambdaRunner") @patch("samcli.commands.local.cli_common.invoke_context.SamFunctionProvider") + @patch("samcli.commands.local.cli_common.invoke_context.InvokeContext._add_account_id_to_global") def test_must_create_runner_with_container_host_option( self, + _add_account_id_to_global_mock, SamFunctionProviderMock, LocalLambdaMock, LambdaRuntimeMock, @@ -817,8 +825,10 @@ def test_must_create_runner_with_container_host_option( @patch("samcli.commands.local.cli_common.invoke_context.LambdaRuntime") @patch("samcli.commands.local.cli_common.invoke_context.LocalLambdaRunner") @patch("samcli.commands.local.cli_common.invoke_context.SamFunctionProvider") + @patch("samcli.commands.local.cli_common.invoke_context.InvokeContext._add_account_id_to_global") def test_must_create_runner_with_extra_hosts_option( self, + _add_account_id_to_global_mock, SamFunctionProviderMock, LocalLambdaMock, LambdaRuntimeMock, @@ -906,8 +916,10 @@ def test_must_create_runner_with_extra_hosts_option( @patch("samcli.commands.local.cli_common.invoke_context.LambdaRuntime") @patch("samcli.commands.local.cli_common.invoke_context.LocalLambdaRunner") @patch("samcli.commands.local.cli_common.invoke_context.SamFunctionProvider") + @patch("samcli.commands.local.cli_common.invoke_context.InvokeContext._add_account_id_to_global") def test_must_create_runner_with_invoke_image_option( self, + _add_account_id_to_global_mock, SamFunctionProviderMock, LocalLambdaMock, LambdaRuntimeMock,