diff --git a/pkg/crd/decoder.go b/pkg/crd/decoder.go index 1b24fb0..52a66a4 100644 --- a/pkg/crd/decoder.go +++ b/pkg/crd/decoder.go @@ -23,6 +23,7 @@ import ( hubv1alpha1 "github.com/traefik/hub-crds/pkg/apis/hub/v1alpha1" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions" apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/serializer" ) @@ -75,24 +76,31 @@ func NewHubDecoder() (*HubDecoder, error) { return nil, fmt.Errorf("adding hub.traefik.io/v1alpha1 resources: %w", err) } - decoder := serializer.NewCodecFactory(scheme).UniversalDeserializer() + decoder := serializer.NewCodecFactory(scheme, serializer.EnableStrict).UniversalDeserializer() return &HubDecoder{decoder: decoder}, nil } -// Decode decodes the given YAML/JSON manifest into a runtime object. -// If `into` is nil, a new runtime.Object will be created. -// A nil runtime.Object will be returned if it doesn't match a known resource type of is not a Kubernetes manifest. -func (d *HubDecoder) Decode(document []byte, into runtime.Object) (runtime.Object, error) { - object, _, err := d.decoder.Decode(document, nil, into) - if err != nil { +// Decode decodes the given YAML/JSON. +func (d *HubDecoder) Decode(document []byte, into *unstructured.Unstructured) error { + // Decoding in an Unstructured object doesn't check for unknown fields. Therefore, we must + // decode twice, the first time only for checking this type of error. + if _, _, err := d.decoder.Decode(document, nil, nil); err != nil { + switch { + case runtime.IsMissingKind(err), runtime.IsNotRegisteredError(err): + default: + return fmt.Errorf("decoding: %w", err) + } + } + + if _, _, err := d.decoder.Decode(document, nil, into); err != nil { switch { case runtime.IsMissingKind(err), runtime.IsNotRegisteredError(err): - return nil, nil + return nil default: - return nil, fmt.Errorf("decoding: %w", err) + return fmt.Errorf("decoding: %w", err) } } - return object, nil + return nil } diff --git a/pkg/crd/loader.go b/pkg/crd/loader.go index 1c29c43..f49063d 100644 --- a/pkg/crd/loader.go +++ b/pkg/crd/loader.go @@ -81,6 +81,7 @@ func loadManifests(filesystem fs.FS) ([]manifest, error) { if err != nil { return fmt.Errorf("opening file: %w", err) } + defer func() { _ = reader.Close() }() r := yaml.NewYAMLReader(bufio.NewReader(reader)) diff --git a/pkg/validation/v1alpha1/access_test.go b/pkg/validation/v1alpha1/access_test.go index 0ec5b8f..3c42bfb 100644 --- a/pkg/validation/v1alpha1/access_test.go +++ b/pkg/validation/v1alpha1/access_test.go @@ -60,7 +60,7 @@ spec: - name: my-api namespace: my-ns apiSelector: - labelSelector: + matchLabels: key: value operationFilter: include: diff --git a/pkg/validation/v1alpha1/validation_test.go b/pkg/validation/v1alpha1/validation_test.go index 4029abf..a3b8b96 100644 --- a/pkg/validation/v1alpha1/validation_test.go +++ b/pkg/validation/v1alpha1/validation_test.go @@ -52,7 +52,7 @@ func checkValidation(t *testing.T, test validationTestCase) { require.NoError(t, err) var object unstructured.Unstructured - _, decoderErr := decoder.Decode(test.manifest, &object) + decoderErr := decoder.Decode(test.manifest, &object) require.NoError(t, decoderErr) gotErrs := validator.Validate(&object)