From f6ee7e1ca943eab65113281ffad1fda3ef44e2e1 Mon Sep 17 00:00:00 2001 From: Krzysztof Kwiatosz Date: Thu, 19 Dec 2024 12:43:38 +0100 Subject: [PATCH] Validate spec.runtime (#1327) --- .../api/v1alpha2/function_types.go | 1 + .../controller/state/validate_function.go | 27 ++++++++++++++++++- .../controllers/serverless/validation.go | 15 ++++++++++- .../controllers/serverless/validation_test.go | 9 +++++++ .../serverless/v1alpha2/runtime_validation.go | 14 +++++++++- 5 files changed, 63 insertions(+), 3 deletions(-) diff --git a/components/buildless-serverless/api/v1alpha2/function_types.go b/components/buildless-serverless/api/v1alpha2/function_types.go index ca802bf38..75e5ff7d1 100644 --- a/components/buildless-serverless/api/v1alpha2/function_types.go +++ b/components/buildless-serverless/api/v1alpha2/function_types.go @@ -28,6 +28,7 @@ type Runtime string const ( Python312 Runtime = "python312" NodeJs20 Runtime = "nodejs20" + NodeJs22 Runtime = "nodejs22" ) // FunctionSpec defines the desired state of Function. diff --git a/components/buildless-serverless/internal/controller/state/validate_function.go b/components/buildless-serverless/internal/controller/state/validate_function.go index 96d4d7aff..480436c48 100644 --- a/components/buildless-serverless/internal/controller/state/validate_function.go +++ b/components/buildless-serverless/internal/controller/state/validate_function.go @@ -4,11 +4,13 @@ import ( "context" "errors" "fmt" + "slices" + "strings" + serverlessv1alpha2 "github.com/kyma-project/serverless/api/v1alpha2" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" utilvalidation "k8s.io/apimachinery/pkg/util/validation" ctrl "sigs.k8s.io/controller-runtime" - "strings" ) func sFnValidateFunction(_ context.Context, m *stateMachine) (stateFn, *ctrl.Result, error) { @@ -16,6 +18,7 @@ func sFnValidateFunction(_ context.Context, m *stateMachine) (stateFn, *ctrl.Res validationFns := []func() []string{ v.validateEnvs, v.validateInlineDeps, + v.validateRuntime, //TODO: add more validation functions } @@ -72,6 +75,17 @@ func (v *functionValidator) validateInlineDeps() []string { return []string{} } +func (v *functionValidator) validateRuntime() []string { + runtime := v.instance.Spec.Runtime + + if err := validateRuntime(runtime); err != nil { + return []string{ + fmt.Sprintf("invalid runtime value: %s", err.Error()), + } + } + return []string{} +} + func validateDependencies(runtime serverlessv1alpha2.Runtime, dependencies string) error { switch runtime { case serverlessv1alpha2.NodeJs20: @@ -89,6 +103,17 @@ func validateNodeJSDependencies(dependencies string) error { return nil } +func validateRuntime(runtime serverlessv1alpha2.Runtime) error { + if len(runtime) == 0 { + return nil + } + supportedruntimes := []serverlessv1alpha2.Runtime{serverlessv1alpha2.NodeJs20, serverlessv1alpha2.NodeJs22, serverlessv1alpha2.Python312} + if slices.Contains(supportedruntimes, runtime) { + return nil + } + return fmt.Errorf("cannot find runtime: %s", runtime) +} + func enrichErrors(errs []string, path string, value string) []string { enrichedErrs := []string{} for _, err := range errs { diff --git a/components/serverless/internal/controllers/serverless/validation.go b/components/serverless/internal/controllers/serverless/validation.go index 5a470f632..b22f5b17e 100644 --- a/components/serverless/internal/controllers/serverless/validation.go +++ b/components/serverless/internal/controllers/serverless/validation.go @@ -3,6 +3,8 @@ package serverless import ( "context" "fmt" + "strings" + serverlessv1alpha2 "github.com/kyma-project/serverless/components/serverless/pkg/apis/serverless/v1alpha2" corev1 "k8s.io/api/core/v1" resource "k8s.io/apimachinery/pkg/api/resource" @@ -12,7 +14,6 @@ import ( utilvalidation "k8s.io/apimachinery/pkg/util/validation" "k8s.io/apimachinery/pkg/util/validation/field" ctrl "sigs.k8s.io/controller-runtime" - "strings" ) var _ stateFn = stateFnValidateFunction @@ -28,6 +29,7 @@ func stateFnValidateFunction(_ context.Context, r *reconciler, s *systemState) ( spec := s.instance.Spec validationFns := []validationFn{ + validateRuntime(spec.Runtime), validateFunctionResources, validateBuildResources, validateEnvs(spec.Env, "spec.env"), @@ -142,6 +144,17 @@ func validateInlineDeps(runtime serverlessv1alpha2.Runtime, inlineSource *server } } +func validateRuntime(runtime serverlessv1alpha2.Runtime) validationFn { + return func() []string { + if err := serverlessv1alpha2.ValidateRuntime(runtime); err != nil { + return []string{ + fmt.Sprintf("invalid runtime value: %s", err.Error()), + } + } + return []string{} + } +} + func validateFunctionLabels(labels map[string]string, path string) validationFn { return func() []string { errs := field.ErrorList{} diff --git a/components/serverless/internal/controllers/serverless/validation_test.go b/components/serverless/internal/controllers/serverless/validation_test.go index 58f492ec8..a27e822be 100644 --- a/components/serverless/internal/controllers/serverless/validation_test.go +++ b/components/serverless/internal/controllers/serverless/validation_test.go @@ -432,6 +432,15 @@ func TestValidation_Invalid(t *testing.T) { }, expectedCondMsg: "source.gitRepository.URL: parse \"g0t@github.com:kyma-project/kyma.git\": invalid URI for request", }, + "Invalid runtime": { + fn: serverlessv1alpha2.Function{ + ObjectMeta: metav1.ObjectMeta{GenerateName: "test-fn"}, + Spec: serverlessv1alpha2.FunctionSpec{ + Runtime: "foo", + }, + }, + expectedCondMsg: "invalid runtime value: cannot find runtime: foo", + }, } //WHEN diff --git a/components/serverless/pkg/apis/serverless/v1alpha2/runtime_validation.go b/components/serverless/pkg/apis/serverless/v1alpha2/runtime_validation.go index 0d37d8f98..8872837d3 100644 --- a/components/serverless/pkg/apis/serverless/v1alpha2/runtime_validation.go +++ b/components/serverless/pkg/apis/serverless/v1alpha2/runtime_validation.go @@ -3,6 +3,7 @@ package v1alpha2 import ( "errors" "fmt" + "slices" "strings" ) @@ -13,7 +14,7 @@ func ValidateDependencies(runtime Runtime, dependencies string) error { case Python312: return nil } - return fmt.Errorf("cannot find runtime: %s", runtime) + return nil } func validateNodeJSDependencies(dependencies string) error { @@ -22,3 +23,14 @@ func validateNodeJSDependencies(dependencies string) error { } return nil } + +func ValidateRuntime(runtime Runtime) error { + if len(runtime) == 0 { + return nil + } + supportedruntimes := []Runtime{NodeJs20, NodeJs22, Python312} + if slices.Contains(supportedruntimes, runtime) { + return nil + } + return fmt.Errorf("cannot find runtime: %s", runtime) +}