Skip to content

Commit

Permalink
Make more use of api-server validation
Browse files Browse the repository at this point in the history
Signed-off-by: Erik Godding Boye <[email protected]>
  • Loading branch information
erikgb committed Nov 16, 2024
1 parent 41dc93d commit 3749249
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ spec:
defaultCAPackageVersion field of the Bundle's status field.
type: boolean
type: object
minItems: 1
type: array
target:
description: Target is the target location in all namespaces to sync source data to.
Expand All @@ -230,6 +231,7 @@ spec:
properties:
key:
description: Key is the key of the entry in the object's `data` field to be used.
minLength: 1
type: string
password:
default: changeit
Expand All @@ -247,6 +249,7 @@ spec:
properties:
key:
description: Key is the key of the entry in the object's `data` field to be used.
minLength: 1
type: string
password:
default: ""
Expand All @@ -264,6 +267,7 @@ spec:
properties:
key:
description: Key is the key of the entry in the object's `data` field to be used.
minLength: 1
type: string
required:
- key
Expand All @@ -289,11 +293,15 @@ spec:
properties:
key:
description: Key is the key of the entry in the object's `data` field to be used.
minLength: 1
type: string
required:
- key
type: object
type: object
x-kubernetes-validations:
- message: must define at least one target configMap/secret
rule: '[has(self.configMap), has(self.secret)].exists(x,x)'
required:
- sources
- target
Expand Down
3 changes: 3 additions & 0 deletions pkg/apis/trust/v1alpha1/types_bundle.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ type BundleList struct {
// BundleSpec defines the desired state of a Bundle.
type BundleSpec struct {
// Sources is a set of references to data whose data will sync to the target.
// +kubebuilder:validation:MinItems=1
Sources []BundleSource `json:"sources"`

// Target is the target location in all namespaces to sync source data to.
Expand Down Expand Up @@ -96,6 +97,7 @@ type BundleSource struct {

// BundleTarget is the target resource that the Bundle will sync all source
// data to.
// +kubebuilder:validation:XValidation:rule="[has(self.configMap), has(self.secret)].exists(x,x)", message="must define at least one target configMap/secret"
type BundleTarget struct {
// ConfigMap is the target ConfigMap in Namespaces that all Bundle source
// data will be synced to.
Expand Down Expand Up @@ -182,6 +184,7 @@ type SourceObjectKeySelector struct {
// KeySelector is a reference to a key for some map data object.
type KeySelector struct {
// Key is the key of the entry in the object's `data` field to be used.
// +kubebuilder:validation:MinLength=1
Key string `json:"key"`
}

Expand Down
8 changes: 6 additions & 2 deletions test/integration/bundle/integration.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package test

import (
"os"
"path/filepath"

"k8s.io/utils/ptr"
"sigs.k8s.io/controller-runtime/pkg/envtest"
Expand All @@ -38,14 +39,17 @@ var _ = BeforeSuite(func() {
logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true)))

crdsYamlFile := os.Getenv("TRUST_MANAGER_CRDS")
Expect(crdsYamlFile).NotTo(BeEmpty(), "TRUST_MANAGER_CRDS must be set to the path of the CRDs to install")
if len(crdsYamlFile) == 0 {
crdsYamlFile = filepath.Join("..", "..", "..", "_bin", "scratch", "crds")
}

env = &envtest.Environment{
UseExistingCluster: ptr.To(false),
CRDDirectoryPaths: []string{
crdsYamlFile,
},
Scheme: trustapi.GlobalScheme,
ErrorIfCRDPathMissing: true,
Scheme: trustapi.GlobalScheme,
}

_, err := env.Start()
Expand Down
80 changes: 80 additions & 0 deletions test/integration/bundle/validation_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
Copyright 2021 The cert-manager Authors.
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 test

import (
"context"
"k8s.io/utils/ptr"

"k8s.io/klog/v2/ktesting"
"sigs.k8s.io/controller-runtime/pkg/client"

trustapi "github.com/cert-manager/trust-manager/pkg/apis/trust/v1alpha1"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)

var _ = Describe("Bundle Validation", func() {
var (
ctx context.Context
cl client.Client
bundle *trustapi.Bundle
)
BeforeEach(func() {
_, ctx = ktesting.NewTestContext(GinkgoT())

var err error
cl, err = client.New(env.Config, client.Options{
Scheme: trustapi.GlobalScheme,
})
Expect(err).NotTo(HaveOccurred())

bundle = &trustapi.Bundle{}
bundle.GenerateName = "validation-"
bundle.Spec.Sources = []trustapi.BundleSource{{
UseDefaultCAs: ptr.To(true),
}}
})

Context("Sources", func() {
It("should require at least one source", func() {
bundle.Spec.Sources = make([]trustapi.BundleSource, 0)

expectedErr := "spec.sources: Invalid value: 0: spec.sources in body should have at least 1 items"
Expect(cl.Create(ctx, bundle)).Should(MatchError(ContainSubstring(expectedErr)))
})
})

Context("Target", func() {
DescribeTable("should require at least one target configMap/secret",
func(target trustapi.BundleTarget, wantErr bool) {
bundle.Spec.Target = target
if wantErr {
expectedErr := "spec.target: Invalid value: \"object\": must define at least one target configMap/secret"
Expect(cl.Create(ctx, bundle)).Should(MatchError(ContainSubstring(expectedErr)))
} else {
Expect(cl.Create(ctx, bundle)).To(Succeed())
}
},
Entry("when none set", trustapi.BundleTarget{NamespaceSelector: &trustapi.NamespaceSelector{}}, true),
Entry("when configMap set", trustapi.BundleTarget{ConfigMap: &trustapi.KeySelector{Key: "ca-bundle.crt"}}, false),
Entry("when secret set", trustapi.BundleTarget{Secret: &trustapi.KeySelector{Key: "ca-bundle.crt"}}, false),
Entry("when both set", trustapi.BundleTarget{Secret: &trustapi.KeySelector{Key: "ca-bundle.crt"}}, false),
)
})
})

0 comments on commit 3749249

Please sign in to comment.