From 4d50e020b5c9e170d6b36756a3ae325206bfcc34 Mon Sep 17 00:00:00 2001 From: Stefan Prodan Date: Sun, 2 Apr 2023 11:34:48 +0300 Subject: [PATCH] Add bundle linting tests Signed-off-by: Stefan Prodan --- cmd/timoni/bundle_apply.go | 7 +- cmd/timoni/bundle_apply_test.go | 7 +- cmd/timoni/bundle_lint.go | 4 + cmd/timoni/bundle_lint_test.go | 156 ++++++++++++++++++++++++++++++++ cmd/timoni/main_test.go | 2 + 5 files changed, 171 insertions(+), 5 deletions(-) create mode 100644 cmd/timoni/bundle_lint_test.go diff --git a/cmd/timoni/bundle_apply.go b/cmd/timoni/bundle_apply.go index 7ecc4c25..07e2efb3 100644 --- a/cmd/timoni/bundle_apply.go +++ b/cmd/timoni/bundle_apply.go @@ -27,9 +27,8 @@ import ( "time" "cuelang.org/go/cue" - "cuelang.org/go/cue/load" - "cuelang.org/go/cue/cuecontext" + "cuelang.org/go/cue/load" "github.com/fluxcd/pkg/ssa" "github.com/spf13/cobra" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" @@ -122,6 +121,10 @@ func runBundleApplyCmd(cmd *cobra.Command, args []string) error { return v.Err() } + if err := v.Validate(cue.Concrete(true)); err != nil { + return err + } + apiVersion := v.LookupPath(cue.ParsePath(apiv1.BundleAPIVersionSelector.String())) if apiVersion.Err() != nil { return fmt.Errorf("lookup %s failed, error: %w", apiv1.BundleAPIVersionSelector.String(), apiVersion.Err()) diff --git a/cmd/timoni/bundle_apply_test.go b/cmd/timoni/bundle_apply_test.go index c03f0af0..b28b0970 100644 --- a/cmd/timoni/bundle_apply_test.go +++ b/cmd/timoni/bundle_apply_test.go @@ -19,13 +19,14 @@ package main import ( "context" "fmt" - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "os" "path/filepath" - "sigs.k8s.io/controller-runtime/pkg/client" "testing" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "sigs.k8s.io/controller-runtime/pkg/client" + . "github.com/onsi/gomega" ) diff --git a/cmd/timoni/bundle_lint.go b/cmd/timoni/bundle_lint.go index 1d091348..4b7ab60e 100644 --- a/cmd/timoni/bundle_lint.go +++ b/cmd/timoni/bundle_lint.go @@ -92,6 +92,10 @@ func runBundleLintCmd(cmd *cobra.Command, args []string) error { return v.Err() } + if err := v.Validate(cue.Concrete(true)); err != nil { + return err + } + apiVersion := v.LookupPath(cue.ParsePath(apiv1.BundleAPIVersionSelector.String())) if apiVersion.Err() != nil { return fmt.Errorf("lookup %s failed, error: %w", apiv1.BundleAPIVersionSelector.String(), apiVersion.Err()) diff --git a/cmd/timoni/bundle_lint_test.go b/cmd/timoni/bundle_lint_test.go new file mode 100644 index 00000000..bb8c27d8 --- /dev/null +++ b/cmd/timoni/bundle_lint_test.go @@ -0,0 +1,156 @@ +/* +Copyright 2023 Stefan Prodan + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package main + +import ( + "fmt" + "os" + "path/filepath" + "testing" + + . "github.com/onsi/gomega" +) + +func Test_BundleLint(t *testing.T) { + + tests := []struct { + name string + bundle string + matchErr string + }{ + { + name: "fails for invalid API Version", + matchErr: "bundle.apiVersion", + bundle: ` +bundle: { + apiVersion: "v1alpha2" + instances: { + test: { + module: { + url: "oci://docker.io/test" + version: "latest" + } + namespace: "default" + values: {} + } + } +} +`, + }, + { + name: "fails for invalid module URL", + matchErr: "bundle.instances.test.module.url", + bundle: ` +bundle: { + apiVersion: "v1alpha1" + instances: { + test: { + module: { + url: "docker.io/test" + version: "latest" + } + namespace: "default" + values: {} + } + } +} +`, + }, + { + name: "fails for missing module version", + matchErr: "bundle.instances.test.module.version", + bundle: ` +bundle: { + apiVersion: "v1alpha1" + instances: { + test: { + module: { + url: "oci://docker.io/test" + } + namespace: "default" + values: {} + } + } +} +`, + }, + { + name: "fails for invalid module prop", + matchErr: "url2", + bundle: ` +bundle: { + apiVersion: "v1alpha1" + instances: { + test: { + module: { + url2: "oci://docker.io/test" + version: "latest" + } + namespace: "default" + values: {} + } + } +} +`, + }, + { + name: "fails for missing namespace", + matchErr: "bundle.instances.test.namespace", + bundle: ` +bundle: { + apiVersion: "v1alpha1" + instances: { + test: { + module: { + url: "oci://docker.io/test" + version: "latest" + } + } + } +} +`, + }, + { + name: "fails for missing instances", + matchErr: "no instances", + bundle: ` +bundle: { + apiVersion: "v1alpha1" + instances: {} +} +`, + }, + } + + tmpDir := t.TempDir() + for i, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + g := NewWithT(t) + bundlePath := filepath.Join(tmpDir, fmt.Sprintf("bundle-%v.cue", i)) + err := os.WriteFile(bundlePath, []byte(tt.bundle), 0644) + g.Expect(err).ToNot(HaveOccurred()) + + _, err = executeCommand(fmt.Sprintf( + "bundle lint -f %s", + bundlePath, + )) + + g.Expect(err).To(HaveOccurred()) + g.Expect(err.Error()).To(MatchRegexp(tt.matchErr)) + }) + } +} diff --git a/cmd/timoni/main_test.go b/cmd/timoni/main_test.go index e2928004..14244956 100644 --- a/cmd/timoni/main_test.go +++ b/cmd/timoni/main_test.go @@ -114,6 +114,8 @@ func resetCmdArgs() { listArgs = listFlags{} pullModArgs = pullModFlags{} pushModArgs = pushModFlags{} + bundleApplyArgs = bundleApplyFlags{} + bundleLintArgs = bundleLintFlags{} } func rnd(prefix string, n int) string {