Skip to content

Commit 25c7723

Browse files
author
Michal Ploski
committed
Refactor code to use common libs
1 parent 5dde53e commit 25c7723

File tree

9 files changed

+329
-277
lines changed

9 files changed

+329
-277
lines changed

poetry.lock

Lines changed: 19 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ python = "^3.6.2"
3131
# 2022-04-21: jmespath was removed, to be re-added once we drop python 3.6.
3232
# issue #1148
3333
aws-cdk-lib = "^2.23.0"
34+
"aws-cdk.aws-lambda-python-alpha" = "2.23.0-alpha.0"
3435
bandit = "^1.7.1"
3536
black = "^21.12b0"
3637
coverage = {extras = ["toml"], version = "^6.2"}

tests/e2e/conftest.py

Lines changed: 20 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -1,95 +1,31 @@
1+
import datetime
12
import uuid
23

3-
import boto3
44
import pytest
5-
import yaml
6-
from aws_cdk import App, CfnOutput, RemovalPolicy, Stack, aws_lambda_python_alpha, aws_logs
7-
from aws_cdk.aws_lambda import Code, Function, Runtime, Tracing
85

9-
from . import utils
6+
from tests.e2e.utils import helpers, infrastructure
107

118

12-
def transform_output(outputs):
13-
return {output["OutputKey"]: output["OutputValue"] for output in outputs if output["OutputKey"]}
14-
15-
16-
# Create CDK cloud assembly code
17-
def prepare_infrastructure(handlers_name, handlers_dir, stack_name, environment_variables, **config):
18-
integration_test_app = App()
19-
stack = Stack(integration_test_app, stack_name)
20-
powertools_layer = aws_lambda_python_alpha.PythonLayerVersion(
21-
stack,
22-
"aws-lambda-powertools",
23-
layer_version_name="aws-lambda-powertools",
24-
entry=".",
25-
compatible_runtimes=[Runtime.PYTHON_3_9],
26-
)
27-
code = Code.from_asset(handlers_dir)
28-
29-
for filename in handlers_name:
30-
31-
function_python = Function(
32-
stack,
33-
f"{filename}-lambda",
34-
runtime=Runtime.PYTHON_3_9,
35-
code=code,
36-
handler=f"{filename}.lambda_handler",
37-
layers=[powertools_layer],
38-
environment=environment_variables,
39-
tracing=Tracing.ACTIVE if config.get("tracing") == "ACTIVE" else Tracing.DISABLED,
40-
)
41-
42-
aws_logs.LogGroup(
43-
stack,
44-
f"{filename}-lg",
45-
log_group_name=f"/aws/lambda/{function_python.function_name}",
46-
retention=aws_logs.RetentionDays.ONE_DAY,
47-
removal_policy=RemovalPolicy.DESTROY,
48-
)
49-
CfnOutput(stack, f"{filename}_arn", value=function_python.function_arn)
50-
return (
51-
integration_test_app.synth().get_stack_by_name(stack_name).template,
52-
integration_test_app.synth().directory,
53-
integration_test_app.synth().artifacts,
54-
)
55-
56-
57-
def deploy_infrastructure(template, asset_root_dir, stack_name, client):
58-
59-
utils.upload_assets(template, asset_root_dir)
60-
61-
response = client.create_stack(
62-
StackName=stack_name,
63-
TemplateBody=yaml.dump(template),
64-
TimeoutInMinutes=10,
65-
OnFailure="DO_NOTHING",
66-
Capabilities=["CAPABILITY_IAM"],
67-
)
68-
waiter = client.get_waiter("stack_create_complete")
69-
waiter.wait(StackName=stack_name, WaiterConfig={"Delay": 2, "MaxAttempts": 50})
70-
response = client.describe_stacks(StackName=stack_name)
71-
return response["Stacks"][0]["Outputs"]
72-
73-
74-
@pytest.fixture(scope="session")
75-
def deploy():
76-
cf_client = boto3.Session().client("cloudformation")
9+
@pytest.fixture(scope="module")
10+
def execute_lambda(config, request):
7711
stack_name = f"test-lambda-{uuid.uuid4()}"
12+
test_dir = request.fspath.dirname
13+
handlers_dir = f"{test_dir}/handlers/"
14+
15+
infra = infrastructure.Infrastructure(
16+
stack_name=stack_name,
17+
handlers_dir=handlers_dir,
18+
config=config["parameters"],
19+
environment_variables=config["environment_variables"],
20+
)
7821

79-
def deploy(handlers_name, handlers_dir, environment_variables, **config):
22+
lambda_arns = infra.deploy()
23+
execution_time = datetime.datetime.utcnow()
8024

81-
template, asset_root_dir, artifact = prepare_infrastructure(
82-
handlers_name=handlers_name,
83-
handlers_dir=handlers_dir,
84-
stack_name=stack_name,
85-
environment_variables=environment_variables,
86-
**config,
87-
)
88-
outputs = deploy_infrastructure(
89-
template=template, asset_root_dir=asset_root_dir, stack_name=stack_name, client=cf_client
90-
)
91-
return transform_output(outputs)
25+
for name, arn in lambda_arns.items():
26+
helpers.trigger_lambda(lambda_arn=arn, client=infra.lambda_client)
27+
print(f"lambda {name} triggered")
9228

93-
yield deploy
29+
yield {"arns": lambda_arns, "execution_time": execution_time}
9430
# Ensure stack deletion is triggered at the end of the test session
95-
cf_client.delete_stack(StackName=stack_name)
31+
infra.delete()

tests/e2e/logger/test_logger.py

Lines changed: 100 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,74 +1,72 @@
1-
import datetime
2-
import os
3-
from functools import lru_cache
4-
51
import boto3
62
import pytest
73

8-
from .. import utils
9-
10-
dirname = os.path.dirname(__file__)
4+
from ..utils import helpers
115

126

137
@pytest.fixture(scope="module")
148
def config():
15-
return {"MESSAGE": "logger message test", "LOG_LEVEL": "INFO", "ADDITIONAL_KEY": "extra_info"}
9+
return {
10+
"parameters": {},
11+
"environment_variables": {
12+
"MESSAGE": "logger message test",
13+
"LOG_LEVEL": "INFO",
14+
"ADDITIONAL_KEY": "extra_info",
15+
},
16+
}
1617

1718

18-
@pytest.fixture(scope="module")
19-
def deploy_lambdas(deploy, config):
20-
handlers_dir = f"{dirname}/handlers/"
21-
22-
lambda_arns = deploy(
23-
handlers_name=utils.find_handlers(handlers_dir),
24-
handlers_dir=handlers_dir,
25-
environment_variables=config,
19+
@pytest.mark.e2e
20+
def test_basic_lambda_logs_visible(execute_lambda, config):
21+
# GIVEN
22+
lambda_arn = execute_lambda["arns"]["basichandlerarn"]
23+
timestamp = int(execute_lambda["execution_time"].timestamp() * 1000)
24+
cw_client = boto3.client("logs")
25+
26+
# WHEN
27+
filtered_logs = helpers.get_logs(
28+
lambda_function_name=lambda_arn.split(":")[-1], start_time=timestamp, log_client=cw_client
2629
)
2730

28-
for name, arn in lambda_arns.items():
29-
utils.trigger_lambda(lambda_arn=arn)
30-
print(f"lambda {name} triggered")
31-
return lambda_arns
32-
33-
34-
@pytest.fixture(scope="module")
35-
def trigger_lambdas(deploy_lambdas):
36-
for name, arn in deploy_lambdas.items():
37-
utils.trigger_lambda(lambda_arn=arn)
38-
print(f"lambda {name} triggered")
39-
40-
41-
@lru_cache(maxsize=10, typed=False)
42-
def fetch_logs(lambda_arn):
43-
start_time = int(datetime.datetime.now().timestamp() * 1000)
44-
result = utils.trigger_lambda(lambda_arn=lambda_arn)
45-
46-
filtered_logs = utils.get_logs(
47-
start_time=start_time,
48-
lambda_function_name=lambda_arn.split(":")[-1],
49-
log_client=boto3.client("logs"),
31+
# THEN
32+
assert any(
33+
log.message == config["environment_variables"]["MESSAGE"]
34+
and log.level == config["environment_variables"]["LOG_LEVEL"]
35+
for log in filtered_logs
5036
)
51-
return filtered_logs
5237

5338

5439
@pytest.mark.e2e
55-
def test_basic_lambda_logs_visible(deploy_lambdas, config):
56-
57-
filtered_logs = fetch_logs(lambda_arn=deploy_lambdas["basichandlerarn"])
40+
def test_basic_lambda_no_debug_logs_visible(execute_lambda, config):
41+
# GIVEN
42+
lambda_arn = execute_lambda["arns"]["basichandlerarn"]
43+
timestamp = int(execute_lambda["execution_time"].timestamp() * 1000)
44+
cw_client = boto3.client("logs")
45+
46+
# WHEN
47+
filtered_logs = helpers.get_logs(
48+
lambda_function_name=lambda_arn.split(":")[-1], start_time=timestamp, log_client=cw_client
49+
)
5850

59-
assert any(log.message == config["MESSAGE"] and log.level == config["LOG_LEVEL"] for log in filtered_logs)
51+
# THEN
52+
assert not any(
53+
log.message == config["environment_variables"]["MESSAGE"] and log.level == "DEBUG" for log in filtered_logs
54+
)
6055

6156

6257
@pytest.mark.e2e
63-
def test_basic_lambda_no_debug_logs_visible(deploy_lambdas, config):
64-
filtered_logs = fetch_logs(lambda_arn=deploy_lambdas["basichandlerarn"])
65-
66-
assert not any(log.message == config["MESSAGE"] and log.level == "DEBUG" for log in filtered_logs)
67-
58+
def test_basic_lambda_contextual_data_logged(execute_lambda):
59+
# GIVEN
60+
lambda_arn = execute_lambda["arns"]["basichandlerarn"]
61+
timestamp = int(execute_lambda["execution_time"].timestamp() * 1000)
62+
cw_client = boto3.client("logs")
63+
64+
# WHEN
65+
filtered_logs = helpers.get_logs(
66+
lambda_function_name=lambda_arn.split(":")[-1], start_time=timestamp, log_client=cw_client
67+
)
6868

69-
@pytest.mark.e2e
70-
def test_basic_lambda_contextual_data_logged(deploy_lambdas):
71-
filtered_logs = fetch_logs(lambda_arn=deploy_lambdas["basichandlerarn"])
69+
# THEN
7270
for log in filtered_logs:
7371
assert (
7472
log.xray_trace_id
@@ -81,26 +79,58 @@ def test_basic_lambda_contextual_data_logged(deploy_lambdas):
8179

8280

8381
@pytest.mark.e2e
84-
def test_basic_lambda_additional_key_persistence_basic_lambda(deploy_lambdas, config):
85-
filtered_logs = fetch_logs(lambda_arn=deploy_lambdas["basichandlerarn"])
82+
def test_basic_lambda_additional_key_persistence_basic_lambda(execute_lambda, config):
83+
# GIVEN
8684

85+
lambda_arn = execute_lambda["arns"]["basichandlerarn"]
86+
timestamp = int(execute_lambda["execution_time"].timestamp() * 1000)
87+
cw_client = boto3.client("logs")
88+
89+
# WHEN
90+
filtered_logs = helpers.get_logs(
91+
lambda_function_name=lambda_arn.split(":")[-1], start_time=timestamp, log_client=cw_client
92+
)
93+
94+
# THEN
8795
assert any(
88-
log.extra_info and log.message == config["MESSAGE"] and log.level == config["LOG_LEVEL"]
96+
log.extra_info
97+
and log.message == config["environment_variables"]["MESSAGE"]
98+
and log.level == config["environment_variables"]["LOG_LEVEL"]
8999
for log in filtered_logs
90100
)
91101

92102

93103
@pytest.mark.e2e
94-
def test_basic_lambda_empty_event_logged(deploy_lambdas):
95-
filtered_logs = fetch_logs(lambda_arn=deploy_lambdas["basichandlerarn"])
104+
def test_basic_lambda_empty_event_logged(execute_lambda):
105+
106+
# GIVEN
107+
lambda_arn = execute_lambda["arns"]["basichandlerarn"]
108+
timestamp = int(execute_lambda["execution_time"].timestamp() * 1000)
109+
cw_client = boto3.client("logs")
96110

111+
# WHEN
112+
filtered_logs = helpers.get_logs(
113+
lambda_function_name=lambda_arn.split(":")[-1], start_time=timestamp, log_client=cw_client
114+
)
115+
116+
# THEN
97117
assert any(log.message == {} for log in filtered_logs)
98118

99119

100120
@pytest.mark.e2e
101-
def test_no_context_lambda_contextual_data_not_logged(deploy_lambdas):
102-
filtered_logs = fetch_logs(lambda_arn=deploy_lambdas["nocontexthandlerarn"])
121+
def test_no_context_lambda_contextual_data_not_logged(execute_lambda):
122+
123+
# GIVEN
124+
lambda_arn = execute_lambda["arns"]["nocontexthandlerarn"]
125+
timestamp = int(execute_lambda["execution_time"].timestamp() * 1000)
126+
cw_client = boto3.client("logs")
127+
128+
# WHEN
129+
filtered_logs = helpers.get_logs(
130+
lambda_function_name=lambda_arn.split(":")[-1], start_time=timestamp, log_client=cw_client
131+
)
103132

133+
# THEN
104134
assert not any(
105135
(
106136
log.xray_trace_id
@@ -115,9 +145,19 @@ def test_no_context_lambda_contextual_data_not_logged(deploy_lambdas):
115145

116146

117147
@pytest.mark.e2e
118-
def test_no_context_lambda_event_not_logged(deploy_lambdas):
119-
filtered_logs = fetch_logs(lambda_arn=deploy_lambdas["nocontexthandlerarn"])
148+
def test_no_context_lambda_event_not_logged(execute_lambda):
149+
150+
# GIVEN
151+
lambda_arn = execute_lambda["arns"]["nocontexthandlerarn"]
152+
timestamp = int(execute_lambda["execution_time"].timestamp() * 1000)
153+
cw_client = boto3.client("logs")
154+
155+
# WHEN
156+
filtered_logs = helpers.get_logs(
157+
lambda_function_name=lambda_arn.split(":")[-1], start_time=timestamp, log_client=cw_client
158+
)
120159

160+
# THEN
121161
assert not any(log.message == {} for log in filtered_logs)
122162

123163

0 commit comments

Comments
 (0)