Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions pkg/resource/function/sdk.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions templates/hooks/function/sdk_read_one_post_set_output.go.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@
ko.Spec.Layers = layer
ko.Status.LayerStatuses = f16
} else {
// ko is a deep copy of the desired resource, so Spec.Layers has to be
// explicitly cleared when the function has no layers in AWS. Leaving the
// desired value in place makes desired and latest identical, no delta is
// computed for Spec.Layers and the layers are never attached.
ko.Spec.Layers = nil
ko.Status.LayerStatuses = nil
}
if resp.Tags != nil {
Expand Down
15 changes: 15 additions & 0 deletions test/e2e/resources/function_no_layers.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
apiVersion: lambda.services.k8s.aws/v1alpha1
kind: Function
metadata:
name: $FUNCTION_NAME
annotations:
services.k8s.aws/region: $AWS_REGION
spec:
name: $FUNCTION_NAME
code:
s3Bucket: $BUCKET_NAME
s3Key: $LAMBDA_FILE_NAME
role: $LAMBDA_ROLE
runtime: python3.9
handler: main
description: function created by ACK lambda-controller e2e tests
72 changes: 72 additions & 0 deletions test/e2e/tests/test_function.py
Original file line number Diff line number Diff line change
Expand Up @@ -800,6 +800,78 @@ def test_function_layers(self, lambda_client):
# Check Lambda function doesn't exist
assert not lambda_validator.function_exists(resource_name)

def test_function_add_layers_to_function_without_layers(self, lambda_client):
resource_name = random_suffix_name("functionnolayers", 24)

resources = get_bootstrap_resources()
logging.debug(resources)

replacements = REPLACEMENT_VALUES.copy()
replacements["FUNCTION_NAME"] = resource_name
replacements["BUCKET_NAME"] = resources.FunctionsBucket.name
replacements["LAMBDA_ROLE"] = resources.EICRole.arn
replacements["LAMBDA_FILE_NAME"] = LAMBDA_FUNCTION_FILE_ZIP
replacements["AWS_REGION"] = get_region()

# Load Lambda CR that does not declare any layer
resource_data = load_lambda_resource(
"function_no_layers",
additional_replacements=replacements,
)
logging.debug(resource_data)

# Create k8s resource
ref = k8s.CustomResourceReference(
CRD_GROUP, CRD_VERSION, RESOURCE_PLURAL,
resource_name, namespace="default",
)
k8s.create_custom_resource(ref, resource_data)
cr = k8s.wait_resource_consumed_by_controller(ref, wait_periods=CONTROLLER_WAIT_PERIODS, period_length=CONTROLLER_PERIOD_LENGTH)

assert cr is not None
assert k8s.get_resource_exists(ref)

time.sleep(CREATE_WAIT_AFTER_SECONDS)

cr = k8s.wait_resource_consumed_by_controller(ref, wait_periods=CONTROLLER_WAIT_PERIODS, period_length=CONTROLLER_PERIOD_LENGTH)

lambda_validator = LambdaValidator(lambda_client)

# Check Lambda function exists and has no layer attached
assert lambda_validator.function_exists(resource_name)
function = lambda_validator.get_function(resource_name)
assert "Layers" not in function["Configuration"]

# Add layers to a function that currently has none. GetFunction returns
# no layer for it, so the controller has to clear Spec.Layers on the
# latest resource for the delta against the desired spec to be computed.
layers_list = ["arn:aws:lambda:us-west-2:017000801446:layer:AWSLambdaPowertoolsPythonV2:68", "arn:aws:lambda:us-west-2:580247275435:layer:LambdaInsightsExtension:52"]
cr["spec"]["layers"] = layers_list

# Patch k8s resource
k8s.patch_custom_resource(ref, cr)
time.sleep(UPDATE_WAIT_AFTER_SECONDS)

# Check the layers were attached to the function in AWS
function = lambda_validator.get_function(resource_name)
assert len(function["Configuration"]["Layers"]) == len(layers_list)
for i in range(len(layers_list)):
assert function["Configuration"]["Layers"][i]["Arn"] == layers_list[i]

# Check the layers are also reported back in the CR status
cr = k8s.get_resource(ref)
assert cr["status"]["layerStatuses"] is not None
assert len(cr["status"]["layerStatuses"]) == len(layers_list)

# Delete k8s resource
_, deleted = k8s.delete_custom_resource(ref, wait_periods=DELETE_WAIT_PERIODS, period_length=DELETE_PERIOD_LENGTH)
assert deleted is True

time.sleep(DELETE_WAIT_AFTER_SECONDS)

# Check Lambda function doesn't exist
assert not lambda_validator.function_exists(resource_name)

def test_function_event_invoke_config(self, lambda_client):
resource_name = random_suffix_name("lambda-function", 24)

Expand Down