Skip to content
Merged
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
8 changes: 4 additions & 4 deletions apis/v1alpha1/ack-generate-metadata.yaml
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
ack_generate_info:
build_date: "2022-04-27T16:40:07Z"
build_hash: 141cb9db73f881228ea20e572de3ba9df19d5b6f
build_date: "2022-05-13T16:30:20Z"
build_hash: 302c31fcf0cb7eacf535af8a65569882b3ee0d7c
go_version: go1.18.1
version: v0.18.4-4-g141cb9d-dirty
version: v0.18.4-3-g302c31f
api_directory_checksum: 7c4e0f8971a8ab06389e98b21c00eddad87366f3
api_version: v1alpha1
aws_sdk_go_version: v1.42.0
generator_config_info:
file_checksum: c48a2acfc8da0b28ee9b81745b9af773d10c7f71
file_checksum: 2559b6bfec9b6a5155e6119d9c649a8a4586b188
original_file_name: generator.yaml
last_modification:
reason: API generation
3 changes: 3 additions & 0 deletions apis/v1alpha1/generator.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ resources:
GetFunction:
input_fields:
FunctionName: Name
exceptions:
terminal_codes:
- InvalidParameterValueException
hooks:
delta_pre_compare:
code: customPreCompare(delta, a, b)
Expand Down
3 changes: 3 additions & 0 deletions generator.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ resources:
GetFunction:
input_fields:
FunctionName: Name
exceptions:
terminal_codes:
- InvalidParameterValueException
hooks:
delta_pre_compare:
code: customPreCompare(delta, a, b)
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module github.com/aws-controllers-k8s/lambda-controller
go 1.17

require (
github.com/aws-controllers-k8s/runtime v0.18.4
github.com/aws-controllers-k8s/runtime v0.18.5
github.com/aws/aws-sdk-go v1.42.0
github.com/go-logr/logr v1.2.0
github.com/spf13/pflag v1.0.5
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@ github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hC
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
github.com/aws-controllers-k8s/runtime v0.18.4 h1:iwLYNwhbuiWZrHPoulGj75oT+alE91wCNkF1FUELiAw=
github.com/aws-controllers-k8s/runtime v0.18.4/go.mod h1:oA8ML1/LL3chPn26P6SzBNu1CUI2nekB+PTqykNs0qU=
github.com/aws-controllers-k8s/runtime v0.18.5 h1:P8oMQagd45JQaloVQ+duuJzMw4ii8/IXYIgPN2EjU+8=
github.com/aws-controllers-k8s/runtime v0.18.5/go.mod h1:oA8ML1/LL3chPn26P6SzBNu1CUI2nekB+PTqykNs0qU=
github.com/aws/aws-sdk-go v1.42.0 h1:BMZws0t8NAhHFsfnT3B40IwD13jVDG5KerlRksctVIw=
github.com/aws/aws-sdk-go v1.42.0/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q=
github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM=
Expand Down
47 changes: 31 additions & 16 deletions pkg/resource/function/hooks.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,19 @@ import (
"errors"
"time"

svcapitypes "github.com/aws-controllers-k8s/lambda-controller/apis/v1alpha1"
ackcompare "github.com/aws-controllers-k8s/runtime/pkg/compare"
ackerr "github.com/aws-controllers-k8s/runtime/pkg/errors"
ackrequeue "github.com/aws-controllers-k8s/runtime/pkg/requeue"
ackrtlog "github.com/aws-controllers-k8s/runtime/pkg/runtime/log"
"github.com/aws/aws-sdk-go/aws"
svcsdk "github.com/aws/aws-sdk-go/service/lambda"

svcapitypes "github.com/aws-controllers-k8s/lambda-controller/apis/v1alpha1"
)

var (
ErrFunctionPending = errors.New("Function in 'Pending' state, cannot be modified or deleted")
ErrFunctionPending = errors.New("Function in 'Pending' state, cannot be modified or deleted")
ErrCannotSetFunctionCSC = errors.New("cannot set function code signing config when package type is Image")
)

var (
Expand Down Expand Up @@ -98,10 +101,16 @@ func (rm *resourceManager) customUpdateFunction(
return nil, err
}
}

if delta.DifferentAt("Spec.CodeSigningConfigARN") {
err = rm.updateFunctionCodeSigningConfig(ctx, desired)
if err != nil {
return nil, err
if desired.ko.Spec.PackageType != nil && *desired.ko.Spec.PackageType == "Image" &&
desired.ko.Spec.CodeSigningConfigARN != nil && *desired.ko.Spec.CodeSigningConfigARN != "" {
return nil, ackerr.NewTerminalError(ErrCannotSetFunctionCSC)
} else {
err = rm.updateFunctionCodeSigningConfig(ctx, desired)
if err != nil {
return nil, err
}
}
}

Expand Down Expand Up @@ -500,17 +509,23 @@ func (rm *resourceManager) setResourceAdditionalFields(
}
ko.Spec.ReservedConcurrentExecutions = getFunctionConcurrencyOutput.ReservedConcurrentExecutions

var getFunctionCodeSigningConfigOutput *svcsdk.GetFunctionCodeSigningConfigOutput
getFunctionCodeSigningConfigOutput, err = rm.sdkapi.GetFunctionCodeSigningConfigWithContext(
ctx,
&svcsdk.GetFunctionCodeSigningConfigInput{
FunctionName: ko.Spec.Name,
},
)
rm.metrics.RecordAPICall("GET", "GetFunctionCodeSigningConfig", err)
if err != nil {
return err
if ko.Spec.PackageType != nil && *ko.Spec.PackageType == "Zip" {
var getFunctionCodeSigningConfigOutput *svcsdk.GetFunctionCodeSigningConfigOutput
getFunctionCodeSigningConfigOutput, err = rm.sdkapi.GetFunctionCodeSigningConfigWithContext(
ctx,
&svcsdk.GetFunctionCodeSigningConfigInput{
FunctionName: ko.Spec.Name,
},
)
rm.metrics.RecordAPICall("GET", "GetFunctionCodeSigningConfig", err)
if err != nil {
return err
}
ko.Spec.CodeSigningConfigARN = getFunctionCodeSigningConfigOutput.CodeSigningConfigArn
}
if ko.Spec.PackageType != nil && *ko.Spec.PackageType == "Image" &&
ko.Spec.CodeSigningConfigARN != nil && *ko.Spec.CodeSigningConfigARN != "" {
return ackerr.NewTerminalError(ErrCannotSetFunctionCSC)
}
ko.Spec.CodeSigningConfigARN = getFunctionCodeSigningConfigOutput.CodeSigningConfigArn
return nil
}
13 changes: 13 additions & 0 deletions test/e2e/resources/function_package_type_image.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
apiVersion: lambda.services.k8s.aws/v1alpha1
kind: Function
metadata:
name: $FUNCTION_NAME
annotations:
services.k8s.aws/region: $AWS_REGION
spec:
name: $FUNCTION_NAME
code:
imageURI: $IMAGE_URL
role: $LAMBDA_ROLE
description: function created by ACK lambda-controller e2e tests
packageType: Image
5 changes: 5 additions & 0 deletions test/e2e/resources/lambda_function/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
FROM public.ecr.aws/lambda/python:3.8

COPY main.py main.py

CMD [ "main.handler" ]
17 changes: 17 additions & 0 deletions test/e2e/resources/lambda_function/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
AWS_REGION ?= "us-west-2"
ECR_REPOSITORY ?= ack-e2e-testing-lambda-controller
IMAGE_TAG ?= v1

AWS_ACCOUNT_ID ?= $(shell aws sts get-caller-identity --query "Account" --output text)
IMAGE_URL ?= $(AWS_ACCOUNT_ID).dkr.ecr.us-west-2.amazonaws.com/$(ECR_REPOSITORY):$(IMAGE_TAG)

build-image:
docker build -t $(IMAGE_URL) .

publish-image:
docker push $(IMAGE_URL)

create-ecr-repository:
aws ecr create-repository --region $(AWS_REGION) --repository-name $(ECR_REPOSITORY) >/dev/null

all: build-image publish-image
125 changes: 124 additions & 1 deletion test/e2e/tests/test_function.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
from typing import Dict, Tuple

from acktest.resources import random_suffix_name
from acktest.aws.identity import get_region
from acktest.aws.identity import get_region, get_account_id
from acktest.k8s import resource as k8s
from e2e import service_marker, CRD_GROUP, CRD_VERSION, load_lambda_resource
from e2e.replacement_values import REPLACEMENT_VALUES
Expand All @@ -33,6 +33,12 @@
UPDATE_WAIT_AFTER_SECONDS = 25
DELETE_WAIT_AFTER_SECONDS = 25


def get_testing_image_url():
aws_region = get_region()
account_id = get_account_id()
return f"{account_id}.dkr.ecr.{aws_region}.amazonaws.com/ack-e2e-testing-lambda-controller:v1"

@pytest.fixture(scope="module")
def lambda_client():
return boto3.client("lambda")
Expand Down Expand Up @@ -313,3 +319,120 @@ def test_function_code_signing_config(self, lambda_client, code_signing_config):
# Check Lambda function doesn't exist
exists = self.function_exists(lambda_client, resource_name)
assert not exists

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

resources = get_bootstrap_resources()

replacements = REPLACEMENT_VALUES.copy()
replacements["FUNCTION_NAME"] = resource_name
replacements["LAMBDA_ROLE"] = resources.LambdaBasicRoleARN
replacements["AWS_REGION"] = get_region()
replacements["IMAGE_URL"] = get_testing_image_url()

# Load Lambda CR
resource_data = load_lambda_resource(
"function_package_type_image",
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)

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)

# Check Lambda function exists
exists = self.function_exists(lambda_client, resource_name)
assert exists

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

time.sleep(DELETE_WAIT_AFTER_SECONDS)

# Check Lambda function doesn't exist
exists = self.function_exists(lambda_client, resource_name)
assert not exists

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

resources = get_bootstrap_resources()

replacements = REPLACEMENT_VALUES.copy()
replacements["FUNCTION_NAME"] = resource_name
replacements["LAMBDA_ROLE"] = resources.LambdaBasicRoleARN
replacements["AWS_REGION"] = get_region()
replacements["IMAGE_URL"] = get_testing_image_url()

# Load Lambda CR
resource_data = load_lambda_resource(
"function_package_type_image",
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)

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)

# Check Lambda function exists
exists = self.function_exists(lambda_client, resource_name)
assert exists

# Add signing configuration
cr["spec"]["codeSigningConfigARN"] = "random-csc"
k8s.patch_custom_resource(ref, cr)

time.sleep(UPDATE_WAIT_AFTER_SECONDS)

cr = k8s.wait_resource_consumed_by_controller(ref)
# assert condition
assert k8s.assert_condition_state_message(
ref,
"ACK.Terminal",
"True",
"cannot set function code signing config when package type is Image",
)

cr = k8s.wait_resource_consumed_by_controller(ref)

# Remove signing configuration
cr["spec"]["codeSigningConfigARN"] = ""
k8s.patch_custom_resource(ref, cr)

time.sleep(UPDATE_WAIT_AFTER_SECONDS)

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

time.sleep(DELETE_WAIT_AFTER_SECONDS)

# Check Lambda function doesn't exist
exists = self.function_exists(lambda_client, resource_name)
assert not exists