From fa4084636326754c3f7671fadd60d336b3f8b732 Mon Sep 17 00:00:00 2001 From: Adrian Orive Oneca Date: Mon, 1 Feb 2021 22:02:31 +0100 Subject: [PATCH] Return a typed error in case DecodePluginConfig was unable to find the provided key Signed-off-by: Adrian Orive Oneca --- pkg/config/errors.go | 22 ++++++++++++++++------ pkg/config/errors_test.go | 20 ++++++++++++++++---- pkg/config/v2/config.go | 14 +++++++------- pkg/config/v3/config.go | 7 ++++--- pkg/config/v3/config_test.go | 10 +++++++++- 5 files changed, 52 insertions(+), 21 deletions(-) diff --git a/pkg/config/errors.go b/pkg/config/errors.go index fed0b421882..d2884147478 100644 --- a/pkg/config/errors.go +++ b/pkg/config/errors.go @@ -32,28 +32,38 @@ func (e UnsupportedVersionError) Error() string { return fmt.Sprintf("version %s is not supported", e.Version) } -// UnsupportedField is returned when a project configuration version does not support +// UnsupportedFieldError is returned when a project configuration version does not support // one of the fields as interface must be common for all the versions -type UnsupportedField struct { +type UnsupportedFieldError struct { Version Version Field string } // Error implements error interface -func (e UnsupportedField) Error() string { +func (e UnsupportedFieldError) Error() string { return fmt.Sprintf("version %s does not support the %s field", e.Version, e.Field) } -// UnknownResource is returned by Config.GetResource when the provided GVK cannot be found -type UnknownResource struct { +// ResourceNotFoundError is returned by Config.GetResource when the provided GVK cannot be found +type ResourceNotFoundError struct { GVK resource.GVK } // Error implements error interface -func (e UnknownResource) Error() string { +func (e ResourceNotFoundError) Error() string { return fmt.Sprintf("resource %v could not be found", e.GVK) } +// PluginKeyNotFoundError is returned by Config.DecodePluginConfig when the provided key cannot be found +type PluginKeyNotFoundError struct { + Key string +} + +// Error implements error interface +func (e PluginKeyNotFoundError) Error() string { + return fmt.Sprintf("plugin key %q could not be found", e.Key) +} + // MarshalError is returned by Config.Marshal when something went wrong while marshalling to YAML type MarshalError struct { Err error diff --git a/pkg/config/errors_test.go b/pkg/config/errors_test.go index b998ea949e4..2c4fcbd727c 100644 --- a/pkg/config/errors_test.go +++ b/pkg/config/errors_test.go @@ -37,8 +37,8 @@ var _ = Describe("UnsupportedVersionError", func() { }) }) -var _ = Describe("UnsupportedField", func() { - var err = UnsupportedField{ +var _ = Describe("UnsupportedFieldError", func() { + var err = UnsupportedFieldError{ Version: Version{Number: 1}, Field: "name", } @@ -50,8 +50,8 @@ var _ = Describe("UnsupportedField", func() { }) }) -var _ = Describe("UnknownResource", func() { - var err = UnknownResource{ +var _ = Describe("ResourceNotFoundError", func() { + var err = ResourceNotFoundError{ GVK: resource.GVK{ Group: "group", Domain: "my.domain", @@ -67,6 +67,18 @@ var _ = Describe("UnknownResource", func() { }) }) +var _ = Describe("PluginKeyNotFoundError", func() { + var err = PluginKeyNotFoundError{ + Key: "go.kubebuilder.io/v1", + } + + Context("Error", func() { + It("should return the correct error message", func() { + Expect(err.Error()).To(Equal("plugin key \"go.kubebuilder.io/v1\" could not be found")) + }) + }) +}) + var _ = Describe("MarshalError", func() { var ( wrapped = fmt.Errorf("error message") diff --git a/pkg/config/v2/config.go b/pkg/config/v2/config.go index 9b3812fe8cb..b9ee4b57f5d 100644 --- a/pkg/config/v2/config.go +++ b/pkg/config/v2/config.go @@ -88,7 +88,7 @@ func (c cfg) GetProjectName() string { // SetProjectName implements config.Config func (c *cfg) SetProjectName(string) error { - return config.UnsupportedField{ + return config.UnsupportedFieldError{ Version: Version, Field: "project name", } @@ -101,7 +101,7 @@ func (c cfg) GetLayout() string { // SetLayout implements config.Config func (c *cfg) SetLayout(string) error { - return config.UnsupportedField{ + return config.UnsupportedFieldError{ Version: Version, Field: "layout", } @@ -131,7 +131,7 @@ func (c cfg) IsComponentConfig() bool { // SetComponentConfig implements config.Config func (c *cfg) SetComponentConfig() error { - return config.UnsupportedField{ + return config.UnsupportedFieldError{ Version: Version, Field: "component config", } @@ -139,7 +139,7 @@ func (c *cfg) SetComponentConfig() error { // ClearComponentConfig implements config.Config func (c *cfg) ClearComponentConfig() error { - return config.UnsupportedField{ + return config.UnsupportedFieldError{ Version: Version, Field: "component config", } @@ -175,7 +175,7 @@ func (c cfg) GetResource(gvk resource.GVK) (resource.Resource, error) { } } - return resource.Resource{}, config.UnknownResource{GVK: gvk} + return resource.Resource{}, config.ResourceNotFoundError{GVK: gvk} } // GetResources implements config.Config @@ -234,7 +234,7 @@ func (c cfg) IsWebhookVersionCompatible(webhookVersion string) bool { // DecodePluginConfig implements config.Config func (c cfg) DecodePluginConfig(string, interface{}) error { - return config.UnsupportedField{ + return config.UnsupportedFieldError{ Version: Version, Field: "plugins", } @@ -242,7 +242,7 @@ func (c cfg) DecodePluginConfig(string, interface{}) error { // EncodePluginConfig implements config.Config func (c cfg) EncodePluginConfig(string, interface{}) error { - return config.UnsupportedField{ + return config.UnsupportedFieldError{ Version: Version, Field: "plugins", } diff --git a/pkg/config/v3/config.go b/pkg/config/v3/config.go index 78e48e354ec..144e9580d96 100644 --- a/pkg/config/v3/config.go +++ b/pkg/config/v3/config.go @@ -180,7 +180,7 @@ func (c cfg) GetResource(gvk resource.GVK) (resource.Resource, error) { } } - return resource.Resource{}, config.UnknownResource{GVK: gvk} + return resource.Resource{}, config.ResourceNotFoundError{GVK: gvk} } // GetResources implements config.Config @@ -283,7 +283,7 @@ func (c cfg) resourceAPIVersionCompatible(verType, version string) bool { // DecodePluginConfig implements config.Config func (c cfg) DecodePluginConfig(key string, configObj interface{}) error { if len(c.Plugins) == 0 { - return nil + return config.PluginKeyNotFoundError{Key: key} } // Get the object blob by key and unmarshal into the object. @@ -295,9 +295,10 @@ func (c cfg) DecodePluginConfig(key string, configObj interface{}) error { if err := yaml.Unmarshal(b, configObj); err != nil { return fmt.Errorf("failed to unmarshal extra fields object: %w", err) } + return nil } - return nil + return config.PluginKeyNotFoundError{Key: key} } // EncodePluginConfig will return an error if used on any project version < v3. diff --git a/pkg/config/v3/config_test.go b/pkg/config/v3/config_test.go index 853a41b56ad..37ed9d864af 100644 --- a/pkg/config/v3/config_test.go +++ b/pkg/config/v3/config_test.go @@ -17,12 +17,14 @@ limitations under the License. package v3 import ( + "errors" "testing" . "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo/extensions/table" . "github.com/onsi/gomega" + "sigs.k8s.io/kubebuilder/v3/pkg/config" "sigs.k8s.io/kubebuilder/v3/pkg/model/resource" ) @@ -390,13 +392,19 @@ var _ = Describe("cfg", func() { } ) + It("DecodePluginConfig should fail for no plugin config object", func() { + var pluginConfig PluginConfig + err := c0.DecodePluginConfig(key, &pluginConfig) + Expect(err).To(HaveOccurred()) + Expect(errors.As(err, &config.PluginKeyNotFoundError{})).To(BeTrue()) + }) + DescribeTable("DecodePluginConfig should retrieve the plugin data correctly", func(inputConfig cfg, expectedPluginConfig PluginConfig) { var pluginConfig PluginConfig Expect(inputConfig.DecodePluginConfig(key, &pluginConfig)).To(Succeed()) Expect(pluginConfig).To(Equal(expectedPluginConfig)) }, - Entry("for no plugin config object", c0, nil), Entry("for an empty plugin config object", c1, PluginConfig{}), Entry("for a full plugin config object", c2, pluginConfig), // TODO (coverage): add cases where yaml.Marshal returns an error