AWSlambda: Support creation of functions with PackageType=Image (#5213)

This commit is contained in:
Bert Blommers 2022-06-10 14:09:13 +00:00 committed by GitHub
parent 8a8eaff547
commit 6bb409e29d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 61 additions and 12 deletions

View File

@ -60,6 +60,10 @@ lambda
- [X] get_policy - [X] get_policy
- [ ] get_provisioned_concurrency_config - [ ] get_provisioned_concurrency_config
- [X] invoke - [X] invoke
Invoking a Function with PackageType=Image is not yet supported.
- [ ] invoke_async - [ ] invoke_async
- [ ] list_aliases - [ ] list_aliases
- [ ] list_code_signing_configs - [ ] list_code_signing_configs

View File

@ -380,9 +380,9 @@ class LambdaFunction(CloudFormationModel, DockerModel):
self.region = region self.region = region
self.code = spec["Code"] self.code = spec["Code"]
self.function_name = spec["FunctionName"] self.function_name = spec["FunctionName"]
self.handler = spec["Handler"] self.handler = spec.get("Handler")
self.role = spec["Role"] self.role = spec["Role"]
self.run_time = spec["Runtime"] self.run_time = spec.get("Runtime")
self.logs_backend = logs_backends[self.region] self.logs_backend = logs_backends[self.region]
self.environment_vars = spec.get("Environment", {}).get("Variables", {}) self.environment_vars = spec.get("Environment", {}).get("Variables", {})
self.policy = None self.policy = None
@ -423,7 +423,7 @@ class LambdaFunction(CloudFormationModel, DockerModel):
# TODO: we should be putting this in a lambda bucket # TODO: we should be putting this in a lambda bucket
self.code["UUID"] = str(uuid.uuid4()) self.code["UUID"] = str(uuid.uuid4())
self.code["S3Key"] = "{}-{}".format(self.function_name, self.code["UUID"]) self.code["S3Key"] = "{}-{}".format(self.function_name, self.code["UUID"])
else: elif "S3Bucket" in self.code:
key = _validate_s3_bucket_and_key(self.code) key = _validate_s3_bucket_and_key(self.code)
if key: if key:
( (
@ -436,6 +436,11 @@ class LambdaFunction(CloudFormationModel, DockerModel):
self.code_bytes = "" self.code_bytes = ""
self.code_size = 0 self.code_size = 0
self.code_sha_256 = "" self.code_sha_256 = ""
elif "ImageUri" in self.code:
self.code_sha_256 = hashlib.sha256(
self.code["ImageUri"].encode("utf-8")
).hexdigest()
self.code_size = 0
self.function_arn = make_function_arn( self.function_arn = make_function_arn(
self.region, get_account_id(), self.function_name self.region, get_account_id(), self.function_name
@ -521,26 +526,33 @@ class LambdaFunction(CloudFormationModel, DockerModel):
return config return config
def get_code(self): def get_code(self):
code = { resp = {"Configuration": self.get_configuration()}
"Code": { if "S3Key" in self.code:
resp["Code"] = {
"Location": "s3://awslambda-{0}-tasks.s3-{0}.amazonaws.com/{1}".format( "Location": "s3://awslambda-{0}-tasks.s3-{0}.amazonaws.com/{1}".format(
self.region, self.code["S3Key"] self.region, self.code["S3Key"]
), ),
"RepositoryType": "S3", "RepositoryType": "S3",
}, }
"Configuration": self.get_configuration(), elif "ImageUri" in self.code:
resp["Code"] = {
"RepositoryType": "ECR",
"ImageUri": self.code.get("ImageUri"),
"ResolvedImageUri": self.code.get("ImageUri").split(":")[0]
+ "@sha256:"
+ self.code_sha_256,
} }
if self.tags: if self.tags:
code["Tags"] = self.tags resp["Tags"] = self.tags
if self.reserved_concurrency: if self.reserved_concurrency:
code.update( resp.update(
{ {
"Concurrency": { "Concurrency": {
"ReservedConcurrentExecutions": self.reserved_concurrency "ReservedConcurrentExecutions": self.reserved_concurrency
} }
} }
) )
return code return resp
def update_configuration(self, config_updates): def update_configuration(self, config_updates):
for key, value in config_updates.items(): for key, value in config_updates.items():
@ -745,7 +757,6 @@ class LambdaFunction(CloudFormationModel, DockerModel):
) )
def invoke(self, body, request_headers, response_headers): def invoke(self, body, request_headers, response_headers):
if body: if body:
body = json.loads(body) body = json.loads(body)
else: else:
@ -1640,6 +1651,9 @@ class LambdaBackend(BaseBackend):
return fn.update_configuration(body) if fn else None return fn.update_configuration(body) if fn else None
def invoke(self, function_name, qualifier, body, headers, response_headers): def invoke(self, function_name, qualifier, body, headers, response_headers):
"""
Invoking a Function with PackageType=Image is not yet supported.
"""
fn = self.get_function(function_name, qualifier) fn = self.get_function(function_name, qualifier)
if fn: if fn:
payload = fn.invoke(body, headers, response_headers) payload = fn.invoke(body, headers, response_headers)

View File

@ -213,6 +213,37 @@ def test_create_function__with_tracingmode(tracing_mode):
result.should.have.key("TracingConfig").should.equal({"Mode": output}) result.should.have.key("TracingConfig").should.equal({"Mode": output})
@mock_lambda
def test_create_function_from_image():
lambda_client = boto3.client("lambda", "us-east-1")
fn_name = str(uuid4())[0:6]
image_uri = "111122223333.dkr.ecr.us-east-1.amazonaws.com/testlambda:latest"
dic = {
"FunctionName": fn_name,
"Role": get_role_name(),
"Code": {"ImageUri": image_uri},
"PackageType": "Image",
"Timeout": 100,
}
resp = lambda_client.create_function(**dic)
resp.should.have.key("FunctionName").equals(fn_name)
resp.should.have.key("CodeSize").equals(0)
resp.should.have.key("CodeSha256")
resp.should.have.key("PackageType").equals("Image")
result = lambda_client.get_function(FunctionName=fn_name)
result.should.have.key("Configuration")
config = result["Configuration"]
result.should.have.key("Code")
code = result["Code"]
code.should.have.key("RepositoryType").equals("ECR")
code.should.have.key("ImageUri").equals(image_uri)
image_uri_without_tag = image_uri.split(":")[0]
resolved_image_uri = f"{image_uri_without_tag}@sha256:{config['CodeSha256']}"
code.should.have.key("ResolvedImageUri").equals(resolved_image_uri)
@mock_lambda @mock_lambda
@mock_s3 @mock_s3
@freeze_time("2015-01-01 00:00:00") @freeze_time("2015-01-01 00:00:00")