Skip to content

Commit

Permalink
fix: Avoid crashing on invalid function name (#7392)
Browse files Browse the repository at this point in the history
* fix: Avoid crashing on invalid function name

* Remove unused exception
  • Loading branch information
mildaniel authored Aug 21, 2024
1 parent 210ea0e commit 8aa0022
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 4 deletions.
9 changes: 9 additions & 0 deletions samcli/lib/providers/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,3 +83,12 @@ def resource_identifier(self) -> "ResourceIdentifier":
@property
def property_name(self) -> str:
return self._property_name


class MissingFunctionNameException(Exception):
"""
Exception when a resource does not have function name specified
"""

def __init__(self) -> None:
super().__init__("Unable to get Lambda function because the function identifier is not defined.")
5 changes: 3 additions & 2 deletions samcli/lib/providers/sam_function_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from samcli.commands._utils.template import TemplateFailedParsingException
from samcli.commands.local.cli_common.user_exceptions import InvalidLayerVersionArn
from samcli.lib.build.exceptions import MissingFunctionHandlerException
from samcli.lib.providers.exceptions import InvalidLayerReference
from samcli.lib.providers.exceptions import InvalidLayerReference, MissingFunctionNameException
from samcli.lib.utils.colors import Colored, Colors
from samcli.lib.utils.file_observer import FileObserver
from samcli.lib.utils.packagetype import IMAGE, ZIP
Expand Down Expand Up @@ -119,7 +119,8 @@ def get(self, name: str) -> Optional[Function]:
"""

if not name:
raise ValueError("Function name is required")
LOG.debug("Function name is not defined, unable to fetch Lambda function.")
raise MissingFunctionNameException()

resolved_function = None

Expand Down
5 changes: 5 additions & 0 deletions samcli/local/apigw/local_apigw_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

from samcli.commands.local.lib.exceptions import UnsupportedInlineCodeError
from samcli.commands.local.lib.local_lambda import LocalLambdaRunner
from samcli.lib.providers.exceptions import MissingFunctionNameException
from samcli.lib.providers.provider import Api, Cors
from samcli.lib.telemetry.event import EventName, EventTracker, UsedFeature
from samcli.lib.utils.stream_writer import StreamWriter
Expand Down Expand Up @@ -733,6 +734,10 @@ def _request_handler(self, **kwargs):
endpoint_service_error = ServiceErrorResponses.lambda_body_failure_response()
except DockerContainerCreationFailedException as ex:
endpoint_service_error = ServiceErrorResponses.container_creation_failed(ex.message)
except MissingFunctionNameException as ex:
endpoint_service_error = ServiceErrorResponses.lambda_failure_response(
f"Failed to execute endpoint. Got an invalid function name ({str(ex)})",
)

if endpoint_service_error:
return endpoint_service_error
Expand Down
4 changes: 2 additions & 2 deletions tests/unit/commands/local/lib/test_sam_function_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from samcli.commands.local.cli_common.user_exceptions import InvalidLayerVersionArn
from samcli.lib.providers.provider import Function, LayerVersion, Stack, FunctionBuildInfo
from samcli.lib.providers.sam_function_provider import SamFunctionProvider, RefreshableSamFunctionProvider
from samcli.lib.providers.exceptions import InvalidLayerReference
from samcli.lib.providers.exceptions import InvalidLayerReference, MissingFunctionNameException
from samcli.lib.utils.packagetype import IMAGE, ZIP


Expand Down Expand Up @@ -1908,7 +1908,7 @@ class TestSamFunctionProvider_get(TestCase):
def test_raise_on_invalid_name(self):
provider = SamFunctionProvider([])

with self.assertRaises(ValueError):
with self.assertRaises(MissingFunctionNameException):
provider.get(None)

def test_must_return_function_value(self):
Expand Down
43 changes: 43 additions & 0 deletions tests/unit/local/apigw/test_local_apigw_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from parameterized import parameterized, param
from werkzeug.datastructures import Headers

from samcli.lib.providers.exceptions import MissingFunctionNameException
from samcli.lib.providers.provider import Api
from samcli.lib.providers.provider import Cors
from samcli.lib.telemetry.event import EventName, EventTracker, UsedFeature
Expand All @@ -23,6 +24,7 @@
LambdaResponseParseException,
PayloadFormatVersionValidateException,
)
from samcli.local.apigw.service_error_responses import ServiceErrorResponses
from samcli.local.docker.exceptions import DockerContainerCreationFailedException
from samcli.local.lambdafn.exceptions import FunctionNotFound
from samcli.commands.local.lib.exceptions import UnsupportedInlineCodeError
Expand Down Expand Up @@ -1040,6 +1042,47 @@ def test_authorizer_function_not_found_invokes_endpoint(
self.api_gateway_route.function_name, ANY, stdout=ANY, stderr=self.stderr
)

@patch.object(LocalApigwService, "get_request_methods_endpoints")
@patch.object(LocalApigwService, "_generate_lambda_authorizer_event")
@patch.object(LocalApigwService, "_valid_identity_sources")
@patch.object(LocalApigwService, "_invoke_lambda_function")
@patch.object(LocalApigwService, "_invoke_parse_lambda_authorizer")
@patch.object(EventTracker, "track_event")
@patch("samcli.local.apigw.local_apigw_service.construct_v1_event")
@patch("samcli.local.apigw.local_apigw_service.construct_v2_event_http")
@patch("samcli.local.apigw.local_apigw_service.ServiceErrorResponses")
def test_lambda_invoke_fails_no_function_name_exception(
self,
service_mock,
v2_event_mock,
v1_event_mock,
track_mock,
lambda_invoke_mock,
invoke_mock,
validate_id_mock,
gen_auth_event_mock,
request_mock,
):
self.api_service._get_current_route = MagicMock()

self.api_gateway_route.authorizer_object = Mock()

self.api_service._get_current_route.return_value = self.api_gateway_route
self.api_service._get_current_route.methods = []
self.api_service._get_current_route.return_value.payload_format_version = "2.0"

invoke_mock.side_effect = MissingFunctionNameException()
service_mock.lambda_failure_response = Mock()
request_mock.return_value = ("test", "test")
v1_event_mock.return_value = {}

self.api_service._request_handler()

service_mock.lambda_failure_response.assert_called_once_with(
"Failed to execute endpoint. Got an invalid function name "
"(Unable to get Lambda function because the function identifier is not defined.)"
)


class TestApiGatewayModel(TestCase):
def setUp(self):
Expand Down

0 comments on commit 8aa0022

Please sign in to comment.