Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ Return a typed error in case DecodePluginConfig was unable to find the provided key #1985

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 16 additions & 6 deletions pkg/config/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
20 changes: 16 additions & 4 deletions pkg/config/errors_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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",
}
Expand All @@ -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",
Expand All @@ -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")
Expand Down
14 changes: 7 additions & 7 deletions pkg/config/v2/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -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",
}
Expand All @@ -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",
}
Expand Down Expand Up @@ -131,15 +131,15 @@ 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",
}
}

// ClearComponentConfig implements config.Config
func (c *cfg) ClearComponentConfig() error {
return config.UnsupportedField{
return config.UnsupportedFieldError{
Version: Version,
Field: "component config",
}
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -234,15 +234,15 @@ 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",
}
}

// EncodePluginConfig implements config.Config
func (c cfg) EncodePluginConfig(string, interface{}) error {
return config.UnsupportedField{
return config.UnsupportedFieldError{
Version: Version,
Field: "plugins",
}
Expand Down
7 changes: 4 additions & 3 deletions pkg/config/v3/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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.
Expand All @@ -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.
Expand Down
10 changes: 9 additions & 1 deletion pkg/config/v3/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)

Expand Down Expand Up @@ -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
Expand Down