diff --git a/api/v1alpha1/validation/envoyproxy_validate.go b/api/v1alpha1/validation/envoyproxy_validate.go index f404ac4a09f..41d4840d9d8 100644 --- a/api/v1alpha1/validation/envoyproxy_validate.go +++ b/api/v1alpha1/validation/envoyproxy_validate.go @@ -24,7 +24,7 @@ import ( _ "github.com/envoyproxy/gateway/internal/xds/extensions" // register the generated types to support protojson unmarshalling ) -// Validate validates the provided EnvoyProxy. +// ValidateEnvoyProxy validates the provided EnvoyProxy. func ValidateEnvoyProxy(proxy *egv1a1.EnvoyProxy) error { var errs []error if proxy == nil { diff --git a/test/cel-validation/envoyproxy_test.go b/test/cel-validation/envoyproxy_test.go new file mode 100644 index 00000000000..919a1ec9241 --- /dev/null +++ b/test/cel-validation/envoyproxy_test.go @@ -0,0 +1,89 @@ +// Copyright Envoy Gateway Authors +// SPDX-License-Identifier: Apache-2.0 +// The full text of the Apache license is available in the LICENSE file at +// the root of the repo. + +//go:build validation +// +build validation + +package cel_validation + +import ( + "context" + "fmt" + "strings" + "testing" + "time" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" +) + +func TestEnvoyProxyProvider(t *testing.T) { + ctx := context.Background() + baseEnvoyProxy := egv1a1.EnvoyProxy{ + ObjectMeta: metav1.ObjectMeta{ + Name: "proxy", + Namespace: metav1.NamespaceDefault, + }, + Spec: egv1a1.EnvoyProxySpec{}, + } + + cases := []struct { + desc string + mutate func(envoy *egv1a1.EnvoyProxy) + mutateStatus func(envoy *egv1a1.EnvoyProxy) + wantErrors []string + }{ + { + desc: "nil provider", + mutate: func(envoy *egv1a1.EnvoyProxy) { + + }, + wantErrors: []string{}, + }, + { + desc: "unsupported provider", + mutate: func(envoy *egv1a1.EnvoyProxy) { + envoy.Spec = egv1a1.EnvoyProxySpec{ + Provider: &egv1a1.EnvoyProxyProvider{ + Type: "foo", + }, + } + }, + wantErrors: []string{"Unsupported value: \"foo\": supported values: \"Kubernetes\""}, + }, + } + + for _, tc := range cases { + t.Run(tc.desc, func(t *testing.T) { + proxy := baseEnvoyProxy.DeepCopy() + proxy.Name = fmt.Sprintf("proxy-%v", time.Now().UnixNano()) + + if tc.mutate != nil { + tc.mutate(proxy) + } + err := c.Create(ctx, proxy) + + if tc.mutateStatus != nil { + tc.mutateStatus(proxy) + err = c.Status().Update(ctx, proxy) + } + + if (len(tc.wantErrors) != 0) != (err != nil) { + t.Fatalf("Unexpected response while creating EnvoyProxy; got err=\n%v\n;want error=%v", err, tc.wantErrors != nil) + } + + var missingErrorStrings []string + for _, wantError := range tc.wantErrors { + if !strings.Contains(strings.ToLower(err.Error()), strings.ToLower(wantError)) { + missingErrorStrings = append(missingErrorStrings, wantError) + } + } + if len(missingErrorStrings) != 0 { + t.Errorf("Unexpected response while creating EnvoyProxy; got err=\n%v\n;missing strings within error=%q", err, missingErrorStrings) + } + }) + } +} diff --git a/test/cel-validation/main_test.go b/test/cel-validation/main_test.go new file mode 100644 index 00000000000..64915388439 --- /dev/null +++ b/test/cel-validation/main_test.go @@ -0,0 +1,66 @@ +// Copyright Envoy Gateway Authors +// SPDX-License-Identifier: Apache-2.0 +// The full text of the Apache license is available in the LICENSE file at +// the root of the repo. + +//go:build celvalidation +// +build celvalidation + +package celvalidation + +import ( + "context" + "fmt" + "os" + "path/filepath" + "testing" + + "k8s.io/client-go/rest" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/envtest" + "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/log/zap" + + egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" +) + +var c client.Client + +func TestMain(m *testing.M) { + // Setup the test environment. + testEnv, restCfg, err := startEnv() + if err != nil { + panic(fmt.Sprintf("Failed to start testenv: %v", err)) + } + + _, cancel := context.WithCancel(ctrl.SetupSignalHandler()) + defer func() { + cancel() + if err := testEnv.Stop(); err != nil { + panic(fmt.Sprintf("Failed to stop testenv: %v", err)) + } + }() + + c, err = client.New(restCfg, client.Options{}) + if err != nil { + panic(fmt.Sprintf("Error initializing client: %v", err)) + } + _ = egv1a1.AddToScheme(c.Scheme()) + + os.Exit(m.Run()) +} + +func startEnv() (*envtest.Environment, *rest.Config, error) { + log.SetLogger(zap.New(zap.WriteTo(os.Stderr), zap.UseDevMode(true))) + egAPIs := filepath.Join("..", "..", "charts", "gateway-helm", "crds", "generated") + + env := &envtest.Environment{ + CRDDirectoryPaths: []string{egAPIs}, + } + cfg, err := env.Start() + if err != nil { + return env, nil, err + } + return env, cfg, nil +} diff --git a/tools/make/golang.mk b/tools/make/golang.mk index 4cf7d4e3bbb..b0142e7e180 100644 --- a/tools/make/golang.mk +++ b/tools/make/golang.mk @@ -52,7 +52,7 @@ go.testdata.complete: ## Override test ouputdata go test -timeout 30s github.com/envoyproxy/gateway/internal/gatewayapi --override-testdata=true .PHONY: go.test.coverage -go.test.coverage: $(tools/setup-envtest) ## Run go unit and integration tests in GitHub Actions +go.test.coverage: kube-test $(tools/setup-envtest) ## Run go unit and integration tests in GitHub Actions @$(LOG_TARGET) KUBEBUILDER_ASSETS="$(shell $(tools/setup-envtest) use $(ENVTEST_K8S_VERSION) -p path)" go test ./... --tags=integration -race -coverprofile=coverage.xml -covermode=atomic diff --git a/tools/make/kube.mk b/tools/make/kube.mk index 0489b60bc53..a12aa103270 100644 --- a/tools/make/kube.mk +++ b/tools/make/kube.mk @@ -49,6 +49,7 @@ kube-generate: $(tools/controller-gen) ## Generate code containing DeepCopy, Dee kube-test: manifests generate $(tools/setup-envtest) ## Run Kubernetes provider tests. @$(LOG_TARGET) KUBEBUILDER_ASSETS="$(shell $(tools/setup-envtest) use $(ENVTEST_K8S_VERSION) -p path)" go test --tags=integration ./... -coverprofile cover.out + KUBEBUILDER_ASSETS="$(shell $(tools/setup-envtest) use $(ENVTEST_K8S_VERSION) -p path)" go test --tags=celvalidation ./... -coverprofile cover.out ##@ Kubernetes Deployment