Skip to content

Commit 239fc9d

Browse files
dipanjankknikure
andauthored
feature: Add Extra Parameters to Lambda Function Wrapper (#3594)
Co-authored-by: Kalyani Nikure <[email protected]>
1 parent 2f9bf05 commit 239fc9d

File tree

2 files changed

+126
-8
lines changed

2 files changed

+126
-8
lines changed

src/sagemaker/lambda_helper.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ def __init__(
3636
timeout: int = 120,
3737
memory_size: int = 128,
3838
runtime: str = "python3.8",
39+
vpc_config: dict = None,
40+
architectures: list = None,
41+
environment: dict = None,
42+
layers: list = None,
3943
):
4044
"""Constructs a Lambda instance.
4145
@@ -66,6 +70,11 @@ def __init__(
6670
timeout (int): Timeout of the Lambda function in seconds. Default is 120 seconds.
6771
memory_size (int): Memory of the Lambda function in megabytes. Default is 128 MB.
6872
runtime (str): Runtime of the Lambda function. Default is set to python3.8.
73+
vpc_config (dict): VPC to deploy the Lambda function to. Default is None.
74+
architectures (list): Which architecture to deploy to. Valid Values are
75+
'x86_64' and 'arm64', default is None.
76+
environment (dict): Environment Variables for the Lambda function. Default is None.
77+
layers (list): List of Lambda layers for the Lambda function. Default is None.
6978
"""
7079
self.function_arn = function_arn
7180
self.function_name = function_name
@@ -78,6 +87,10 @@ def __init__(
7887
self.timeout = timeout
7988
self.memory_size = memory_size
8089
self.runtime = runtime
90+
self.vpc_config = vpc_config
91+
self.environment = environment
92+
self.architectures = architectures
93+
self.layers = layers
8194

8295
if function_arn is None and function_name is None:
8396
raise ValueError("Either function_arn or function_name must be provided.")
@@ -127,6 +140,10 @@ def create(self):
127140
Code=code,
128141
Timeout=self.timeout,
129142
MemorySize=self.memory_size,
143+
VpcConfig=self.vpc_config,
144+
Environment=self.environment,
145+
Architectures=self.architectures,
146+
Layers=self.layers,
130147
)
131148
return response
132149
except ClientError as e:
@@ -146,6 +163,7 @@ def update(self):
146163
response = lambda_client.update_function_code(
147164
FunctionName=self.function_name or self.function_arn,
148165
ZipFile=_zip_lambda_code(self.script),
166+
Architectures=self.architectures,
149167
)
150168
else:
151169
bucket = self.s3_bucket or self.session.default_bucket()
@@ -168,6 +186,7 @@ def update(self):
168186
zipped_code_dir=self.zipped_code_dir,
169187
s3_bucket=bucket,
170188
),
189+
Architectures=self.architectures,
171190
)
172191
return response
173192
except ClientError as e:

tests/unit/test_lambda_helper.py

Lines changed: 107 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,10 @@ def test_create_lambda_happycase1(sagemaker_session):
187187
Code=code,
188188
Timeout=120,
189189
MemorySize=128,
190+
Architectures=None,
191+
VpcConfig=None,
192+
Environment=None,
193+
Layers=None,
190194
)
191195

192196

@@ -212,6 +216,45 @@ def test_create_lambda_happycase2(sagemaker_session):
212216
Code=code,
213217
Timeout=120,
214218
MemorySize=128,
219+
Architectures=None,
220+
VpcConfig=None,
221+
Environment=None,
222+
Layers=None,
223+
)
224+
225+
226+
@patch("sagemaker.lambda_helper._zip_lambda_code", return_value=ZIPPED_CODE)
227+
def test_create_lambda_happycase3(sagemaker_session):
228+
lambda_obj = lambda_helper.Lambda(
229+
function_name=FUNCTION_NAME,
230+
execution_role_arn=EXECUTION_ROLE,
231+
script=SCRIPT,
232+
handler=HANDLER,
233+
session=sagemaker_session,
234+
architectures=["x86_64"],
235+
environment={"Name": "my-test-lambda"},
236+
vpc_config={
237+
"SubnetIds": ["test-subnet-1"],
238+
"SecurityGroupIds": ["sec-group-1"],
239+
},
240+
layers=["my-test-layer-1", "my-test-layer-2"],
241+
)
242+
243+
lambda_obj.create()
244+
code = {"ZipFile": ZIPPED_CODE}
245+
246+
sagemaker_session.lambda_client.create_function.assert_called_with(
247+
FunctionName=FUNCTION_NAME,
248+
Runtime="python3.8",
249+
Handler=HANDLER,
250+
Role=EXECUTION_ROLE,
251+
Code=code,
252+
Timeout=120,
253+
MemorySize=128,
254+
Architectures=["x86_64"],
255+
VpcConfig={"SubnetIds": ["test-subnet-1"], "SecurityGroupIds": ["sec-group-1"]},
256+
Environment={"Name": "my-test-lambda"},
257+
Layers=["my-test-layer-1", "my-test-layer-2"],
215258
)
216259

217260

@@ -241,7 +284,12 @@ def test_create_lambda_client_error(sagemaker_session):
241284
session=sagemaker_session,
242285
)
243286
sagemaker_session.lambda_client.create_function.side_effect = ClientError(
244-
{"Error": {"Code": "ResourceConflictException", "Message": "Function already exists"}},
287+
{
288+
"Error": {
289+
"Code": "ResourceConflictException",
290+
"Message": "Function already exists",
291+
}
292+
},
245293
"CreateFunction",
246294
)
247295

@@ -264,7 +312,9 @@ def test_update_lambda_happycase1(sagemaker_session):
264312
lambda_obj.update()
265313

266314
sagemaker_session.lambda_client.update_function_code.assert_called_with(
267-
FunctionName=FUNCTION_NAME, ZipFile=ZIPPED_CODE
315+
FunctionName=FUNCTION_NAME,
316+
ZipFile=ZIPPED_CODE,
317+
Architectures=None,
268318
)
269319

270320

@@ -282,7 +332,35 @@ def test_update_lambda_happycase2(sagemaker_session):
282332
lambda_obj.update()
283333

284334
sagemaker_session.lambda_client.update_function_code.assert_called_with(
285-
FunctionName=LAMBDA_ARN, S3Bucket=S3_BUCKET, S3Key=S3_KEY
335+
FunctionName=LAMBDA_ARN,
336+
S3Bucket=S3_BUCKET,
337+
S3Key=S3_KEY,
338+
Architectures=None,
339+
)
340+
341+
342+
@patch("sagemaker.lambda_helper._zip_lambda_code", return_value=ZIPPED_CODE)
343+
def test_update_lambda_happycase3(sagemaker_session):
344+
lambda_obj = lambda_helper.Lambda(
345+
function_name=FUNCTION_NAME,
346+
execution_role_arn=EXECUTION_ROLE,
347+
script=SCRIPT,
348+
handler=HANDLER,
349+
session=sagemaker_session,
350+
architectures=["x86_64"],
351+
environment={"Name": "my-test-lambda"},
352+
vpc_config={
353+
"SubnetIds": ["test-subnet-1"],
354+
"SecurityGroupIds": ["sec-group-1"],
355+
},
356+
)
357+
358+
lambda_obj.update()
359+
360+
sagemaker_session.lambda_client.update_function_code.assert_called_with(
361+
FunctionName=FUNCTION_NAME,
362+
ZipFile=ZIPPED_CODE,
363+
Architectures=["x86_64"],
286364
)
287365

288366

@@ -302,6 +380,7 @@ def test_update_lambda_s3bucket_not_provided(s3_upload, sagemaker_session):
302380
FunctionName=LAMBDA_ARN,
303381
S3Bucket=sagemaker_session.default_bucket(),
304382
S3Key=s3_upload.return_value,
383+
Architectures=None,
305384
)
306385

307386

@@ -346,6 +425,10 @@ def test_upsert_lambda_happycase1(sagemaker_session):
346425
Code=code,
347426
Timeout=120,
348427
MemorySize=128,
428+
Architectures=None,
429+
VpcConfig=None,
430+
Environment=None,
431+
Layers=None,
349432
)
350433

351434

@@ -360,14 +443,19 @@ def test_upsert_lambda_happycase2(sagemaker_session):
360443
)
361444

362445
sagemaker_session.lambda_client.create_function.side_effect = ClientError(
363-
{"Error": {"Code": "ResourceConflictException", "Message": "Lambda already exists"}},
446+
{
447+
"Error": {
448+
"Code": "ResourceConflictException",
449+
"Message": "Lambda already exists",
450+
}
451+
},
364452
"CreateFunction",
365453
)
366454

367455
lambda_obj.upsert()
368456

369457
sagemaker_session.lambda_client.update_function_code.assert_called_once_with(
370-
FunctionName=FUNCTION_NAME, ZipFile=ZIPPED_CODE
458+
FunctionName=FUNCTION_NAME, ZipFile=ZIPPED_CODE, Architectures=None
371459
)
372460

373461

@@ -382,12 +470,22 @@ def test_upsert_lambda_client_error(sagemaker_session):
382470
)
383471

384472
sagemaker_session.lambda_client.create_function.side_effect = ClientError(
385-
{"Error": {"Code": "ResourceConflictException", "Message": "Lambda already exists"}},
473+
{
474+
"Error": {
475+
"Code": "ResourceConflictException",
476+
"Message": "Lambda already exists",
477+
}
478+
},
386479
"CreateFunction",
387480
)
388481

389482
sagemaker_session.lambda_client.update_function_code.side_effect = ClientError(
390-
{"Error": {"Code": "ResourceConflictException", "Message": "Cannot update code"}},
483+
{
484+
"Error": {
485+
"Code": "ResourceConflictException",
486+
"Message": "Cannot update code",
487+
}
488+
},
391489
"UpdateFunctionCode",
392490
)
393491

@@ -410,7 +508,8 @@ def test_invoke_lambda_client_error(sagemaker_session):
410508
lambda_obj = lambda_helper.Lambda(function_arn=LAMBDA_ARN, session=sagemaker_session)
411509

412510
sagemaker_session.lambda_client.invoke.side_effect = ClientError(
413-
{"Error": {"Code": "InvalidCodeException", "Message": "invoke failed"}}, "Invoke"
511+
{"Error": {"Code": "InvalidCodeException", "Message": "invoke failed"}},
512+
"Invoke",
414513
)
415514
with pytest.raises(ValueError) as error:
416515
lambda_obj.invoke()

0 commit comments

Comments
 (0)