From be5b1c592fbeb6432d8a7d19d8f2925140cd76f9 Mon Sep 17 00:00:00 2001 From: Bert Blommers Date: Thu, 7 May 2020 10:40:24 +0100 Subject: [PATCH 1/3] Lambda - Add actual logs to LogResult, instead of replicating the response --- moto/awslambda/models.py | 21 +++++++++++++-------- tests/test_awslambda/test_lambda.py | 14 +++++--------- 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/moto/awslambda/models.py b/moto/awslambda/models.py index 589a790ae..28cbe61af 100644 --- a/moto/awslambda/models.py +++ b/moto/awslambda/models.py @@ -379,6 +379,7 @@ class LambdaFunction(BaseModel): event = dict() if context is None: context = {} + output = None try: # TODO: I believe we can keep the container running and feed events as needed @@ -394,7 +395,7 @@ class LambdaFunction(BaseModel): env_vars.update(self.environment_vars) - container = output = exit_code = None + container = exit_code = None log_config = docker.types.LogConfig(type=docker.types.LogConfig.types.JSON) with _DockerDataVolumeContext(self) as data_vol: try: @@ -455,24 +456,28 @@ class LambdaFunction(BaseModel): # We only care about the response from the lambda # Which is the last line of the output, according to https://github.com/lambci/docker-lambda/issues/25 - output = output.splitlines()[-1] - return output, False + resp = output.splitlines()[-1] + logs = os.linesep.join( + [line for line in self.convert(output).splitlines()[:-1]] + ) + return resp, False, logs except BaseException as e: traceback.print_exc() - return "error running lambda: {}".format(e), True + logs = os.linesep.join( + [line for line in self.convert(output).splitlines()[:-1]] + ) + return "error running lambda: {}".format(e), True, logs def invoke(self, body, request_headers, response_headers): - payload = dict() if body: body = json.loads(body) # Get the invocation type: - res, errored = self._invoke_lambda(code=self.code, event=body) + res, errored, logs = self._invoke_lambda(code=self.code, event=body) if request_headers.get("x-amz-invocation-type") == "RequestResponse": - encoded = base64.b64encode(res.encode("utf-8")) + encoded = base64.b64encode(logs.encode("utf-8")) response_headers["x-amz-log-result"] = encoded.decode("utf-8") - payload["result"] = response_headers["x-amz-log-result"] result = res.encode("utf-8") else: result = res diff --git a/tests/test_awslambda/test_lambda.py b/tests/test_awslambda/test_lambda.py index e67576518..62e2bcef6 100644 --- a/tests/test_awslambda/test_lambda.py +++ b/tests/test_awslambda/test_lambda.py @@ -43,6 +43,7 @@ def _process_lambda(func_str): def get_test_zip_file1(): pfunc = """ def lambda_handler(event, context): + print("custom log event") return event """ return _process_lambda(pfunc) @@ -115,11 +116,11 @@ def test_invoke_requestresponse_function(): ) success_result["StatusCode"].should.equal(200) - result_obj = json.loads( - base64.b64decode(success_result["LogResult"]).decode("utf-8") - ) + logs = base64.b64decode(success_result["LogResult"]).decode("utf-8") - result_obj.should.equal(in_data) + logs.should.contain("START RequestId:") + logs.should.contain("custom log event") + logs.should.contain("END RequestId:") payload = success_result["Payload"].read().decode("utf-8") json.loads(payload).should.equal(in_data) @@ -152,11 +153,6 @@ def test_invoke_requestresponse_function_with_arn(): ) success_result["StatusCode"].should.equal(200) - result_obj = json.loads( - base64.b64decode(success_result["LogResult"]).decode("utf-8") - ) - - result_obj.should.equal(in_data) payload = success_result["Payload"].read().decode("utf-8") json.loads(payload).should.equal(in_data) From f82e834225809af1d3a56769baec8960a4b90481 Mon Sep 17 00:00:00 2001 From: Bert Blommers Date: Thu, 7 May 2020 10:55:15 +0100 Subject: [PATCH 2/3] Lambda - Only return Logs if LogType=Tail --- moto/awslambda/models.py | 4 ++-- moto/awslambda/responses.py | 4 +++- tests/test_awslambda/test_lambda.py | 11 +++++++++++ 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/moto/awslambda/models.py b/moto/awslambda/models.py index 28cbe61af..829aa76d2 100644 --- a/moto/awslambda/models.py +++ b/moto/awslambda/models.py @@ -1049,9 +1049,9 @@ class LambdaBackend(BaseBackend): if fn: payload = fn.invoke(body, headers, response_headers) response_headers["Content-Length"] = str(len(payload)) - return response_headers, payload + return payload else: - return response_headers, None + return None def do_validate_s3(): diff --git a/moto/awslambda/responses.py b/moto/awslambda/responses.py index d81bd55d9..a4f559fc2 100644 --- a/moto/awslambda/responses.py +++ b/moto/awslambda/responses.py @@ -178,7 +178,7 @@ class LambdaResponse(BaseResponse): function_name = unquote(self.path.rsplit("/", 2)[-2]) qualifier = self._get_param("qualifier") - response_header, payload = self.lambda_backend.invoke( + payload = self.lambda_backend.invoke( function_name, qualifier, self.body, self.headers, response_headers ) if payload: @@ -187,6 +187,8 @@ class LambdaResponse(BaseResponse): elif request.headers.get("X-Amz-Invocation-Type") == "DryRun": status_code = 204 else: + if request.headers.get("X-Amz-Log-Type") != "Tail": + del response_headers["x-amz-log-result"] status_code = 200 return status_code, response_headers, payload else: diff --git a/tests/test_awslambda/test_lambda.py b/tests/test_awslambda/test_lambda.py index 62e2bcef6..be5835b5f 100644 --- a/tests/test_awslambda/test_lambda.py +++ b/tests/test_awslambda/test_lambda.py @@ -113,6 +113,7 @@ def test_invoke_requestresponse_function(): FunctionName="testFunction", InvocationType="RequestResponse", Payload=json.dumps(in_data), + LogType="Tail" ) success_result["StatusCode"].should.equal(200) @@ -125,6 +126,16 @@ def test_invoke_requestresponse_function(): payload = success_result["Payload"].read().decode("utf-8") json.loads(payload).should.equal(in_data) + # Logs should not be returned by default, only when the LogType-param is supplied + success_result = conn.invoke( + FunctionName="testFunction", + InvocationType="RequestResponse", + Payload=json.dumps(in_data), + ) + + success_result["StatusCode"].should.equal(200) + assert "LogResult" not in success_result + @mock_lambda def test_invoke_requestresponse_function_with_arn(): From 0718525a2a732ba2db060a8c55c3fc6b9b1b9763 Mon Sep 17 00:00:00 2001 From: Bert Blommers Date: Thu, 7 May 2020 12:29:18 +0100 Subject: [PATCH 3/3] Linting --- tests/test_awslambda/test_lambda.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_awslambda/test_lambda.py b/tests/test_awslambda/test_lambda.py index be5835b5f..8879ad7e3 100644 --- a/tests/test_awslambda/test_lambda.py +++ b/tests/test_awslambda/test_lambda.py @@ -113,7 +113,7 @@ def test_invoke_requestresponse_function(): FunctionName="testFunction", InvocationType="RequestResponse", Payload=json.dumps(in_data), - LogType="Tail" + LogType="Tail", ) success_result["StatusCode"].should.equal(200)