Skip to content
This repository has been archived by the owner on Jun 28, 2023. It is now read-only.

Commit

Permalink
GIT-4850: create new errors package and update extensions/docker-desktop
Browse files Browse the repository at this point in the history
  • Loading branch information
harshanarayana committed Jun 27, 2022
1 parent 762ed99 commit ae77e61
Show file tree
Hide file tree
Showing 12 changed files with 194 additions and 34 deletions.
95 changes: 95 additions & 0 deletions errors/errors.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package errors

import (
"fmt"
)

type Reason string

const (
ReasonUnknown Reason = "Unknown"
ReasonLockFailed Reason = "LockFailed"
ReasonMergeFailed Reason = "MergeFailed"
ReasonReadFailed Reason = "ReadFailed"
ReasonIOFailed Reason = "IOFailed"
ReasonMarshallingFailed Reason = "MarshallingFailed"
ReasonEncodeFailed Reason = "EncodeFailed"
ReasonNormalizationFailed Reason = "NormalizationFailed"
ReasonValidationFailed Reason = "ValidationFailed"
ReasonTimeout Reason = "Timeout"
ReasonGeneric Reason = "GenericFailure"
)

// TODO: implement the errors.Unwrap interface to support errors.Unwrap cleanly
type TanzuError struct {
ErrorDetails ErrorDetails `json:"errorDetails"`
}

type ErrorDetails struct {
Message string `json:"message,omitempty"`
Reason Reason `json:"reason,omitempty"`
Err error `json:"err"`
}

func (t TanzuError) Error() string {
return fmt.Sprintf("%s: %s (%s)", t.ErrorDetails.Reason, t.ErrorDetails.Message, t.ErrorDetails.Err)
}

func generateError(reason Reason, err error, args ...interface{}) TanzuError {
var message string
switch len(args) {
case 0:
message = ""
case 1:
message = args[0].(string)
default:
message = fmt.Sprintf(args[0].(string), args[1:]...)
}
return TanzuError{
ErrorDetails: ErrorDetails{
Reason: reason,
Message: message,
Err: err,
},
}
}

func NewLockFailed(err error, args ...interface{}) TanzuError {
return generateError(ReasonLockFailed, err, args...)
}

func NewMergeFailed(err error, args ...interface{}) TanzuError {
return generateError(ReasonMergeFailed, err, args...)
}

func NewReadFailed(err error, args ...interface{}) TanzuError {
return generateError(ReasonReadFailed, err, args...)
}

func NewIOFailed(err error, args ...interface{}) TanzuError {
return generateError(ReasonIOFailed, err, args...)
}

func NewMarshallingFailed(err error, args ...interface{}) TanzuError {
return generateError(ReasonMarshallingFailed, err, args...)
}

func NewNormalizationFailed(err error, args ...interface{}) TanzuError {
return generateError(ReasonNormalizationFailed, err, args...)
}

func NewValidationFailed(err error, args ...interface{}) TanzuError {
return generateError(ReasonValidationFailed, err, args...)
}

func NewTimeout(err error, args ...interface{}) TanzuError {
return generateError(ReasonTimeout, err, args...)
}

func NewGenericFail(err error, args ...interface{}) TanzuError {
return generateError(ReasonGeneric, err, args...)
}

func NewEncodeFail(err error, args ...interface{}) TanzuError {
return generateError(ReasonEncodeFailed, err, args...)
}
59 changes: 59 additions & 0 deletions errors/errors_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package errors

import (
"errors"
"fmt"
"reflect"
"runtime"
"testing"
)

func TestErrors(t *testing.T) {
tests := []struct {
errorFunc func(err error, args ...interface{}) TanzuError
Reason Reason
}{
{
NewLockFailed, ReasonLockFailed,
},
{
NewMergeFailed, ReasonMergeFailed,
},
{
NewReadFailed, ReasonReadFailed,
},
{
NewIOFailed, ReasonIOFailed,
},
{
NewMarshallingFailed, ReasonMarshallingFailed,
},
{
NewNormalizationFailed, ReasonNormalizationFailed,
},
{
NewValidationFailed, ReasonValidationFailed,
},
{
NewTimeout, ReasonTimeout,
},
{
NewGenericFail, ReasonGeneric,
},
}

for _, tc := range tests {
tc := tc
name := runtime.FuncForPC(reflect.ValueOf(tc.errorFunc).Pointer()).Name()
t.Run(name, func(t *testing.T) {
err := tc.errorFunc(errors.New("fail"), "some failure. Arg %s", "test")
if err.ErrorDetails.Reason != tc.Reason {
t.Errorf("%s, Expected: %v, got: %v", name, tc.Reason, err.ErrorDetails.Reason)
}
expected := fmt.Sprintf("%s: %s (%s)", tc.Reason, "some failure. Arg test", "fail")
if err.Error() != expected {
t.Errorf("%s, Expected: %s, got: %s", name, expected, err.Error())
}
})
}
}
3 changes: 3 additions & 0 deletions errors/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module github.com/vmware-tanzu/community-edition/errors

go 1.17
14 changes: 7 additions & 7 deletions extensions/docker-desktop/apps/clustermgr/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ go 1.17
require (
github.com/docker/docker v20.10.16+incompatible
github.com/juju/fslock v0.0.0-20160525022230-4d5c94c67b4b
github.com/pkg/errors v0.9.1
github.com/sirupsen/logrus v1.8.1
github.com/stretchr/testify v1.7.1
github.com/vmware-tanzu/community-edition/cli/cmd/plugin/unmanaged-cluster v0.0.0-20220607164142-9853e16163cb
gopkg.in/yaml.v3 v3.0.1
sigs.k8s.io/kind v0.14.0
github.com/vmware-tanzu/community-edition/errors v0.0.0
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
sigs.k8s.io/yaml v1.3.0
)

Expand Down Expand Up @@ -62,6 +62,7 @@ require (
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.0.3-0.20220114050600-8b9d41f48198 // indirect
github.com/pelletier/go-toml v1.9.4 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/spf13/cobra v1.4.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
Expand All @@ -72,6 +73,7 @@ require (
github.com/vmware-tanzu/carvel-kapp-controller v0.37.0 // indirect
github.com/vmware-tanzu/carvel-kbld v0.32.1-0.20220207174123-dd5e71b95085 // indirect
github.com/vmware-tanzu/carvel-vendir v0.27.0 // indirect
github.com/vmware-tanzu/community-edition v0.12.1 // indirect
golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 // indirect
golang.org/x/net v0.0.0-20220516155154-20f960328961 // indirect
golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5 // indirect
Expand All @@ -93,10 +95,8 @@ require (
k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42 // indirect
k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9 // indirect
sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2 // indirect
sigs.k8s.io/kind v0.14.0 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.2.1 // indirect
)

require (
github.com/stretchr/testify v1.7.2
github.com/vmware-tanzu/community-edition v0.12.1 // indirect
)
replace github.com/vmware-tanzu/community-edition/errors => ../../../../errors
6 changes: 2 additions & 4 deletions extensions/docker-desktop/apps/clustermgr/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1179,9 +1179,8 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.2 h1:4jaiDzPyXQvSd7D0EjG45355tLlV3VOECpq10pLC+8s=
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/sylvia7788/contextcheck v1.0.4/go.mod h1:vuPKJMQ7MQ91ZTqfdyreNKwZjyUg6KO+IebVyQDedZQ=
github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
Expand Down Expand Up @@ -2021,9 +2020,8 @@ gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ import (
"bytes"

yaml "gopkg.in/yaml.v3"
"sigs.k8s.io/kind/pkg/errors"
kubeyaml "sigs.k8s.io/yaml"

"github.com/vmware-tanzu/community-edition/errors"
)

// Encode encodes the cfg to yaml
Expand All @@ -17,15 +18,15 @@ func Encode(cfg *Config) ([]byte, error) {
// so we're not using that to marshal
encoded, err := yaml.Marshal(cfg)
if err != nil {
return nil, errors.Wrap(err, "failed to encode KUBECONFIG")
return nil, errors.NewEncodeFail(err, "failed to encode KUBECONFIG file")
}

// normalize with kubernetes's yaml library
// this is not strictly necessary, but it ensures minimal diffs when
// modifying kubeconfig files, which is nice to have
encoded, err = normYaml(encoded)
if err != nil {
return nil, errors.Wrap(err, "failed to normalize KUBECONFIG encoding")
return nil, errors.NewNormalizationFailed(err, "failed to normalize KUBECONFIG encoding")
}

return encoded, nil
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
package kubeconfig

import (
"sigs.k8s.io/kind/pkg/errors"
"fmt"

"github.com/vmware-tanzu/community-edition/errors"
)

// KINDClusterKey identifies kind clusters in kubeconfig files
Expand All @@ -16,13 +18,13 @@ func KINDClusterKey(clusterName string) string {
// our expectations, namely on the number of entries
func checkKubeadmExpectations(cfg *Config) error {
if len(cfg.Clusters) != 1 {
return errors.Errorf("kubeadm KUBECONFIG should have one cluster, but read %d", len(cfg.Clusters))
return errors.NewValidationFailed(fmt.Errorf("kubeadm KUBECONFIG should have one cluster, but read %d", len(cfg.Clusters)))
}
if len(cfg.Users) != 1 {
return errors.Errorf("kubeadm KUBECONFIG should have one user, but read %d", len(cfg.Users))
return errors.NewValidationFailed(fmt.Errorf("kubeadm KUBECONFIG should have one user, but read %d", len(cfg.Users)))
}
if len(cfg.Contexts) != 1 {
return errors.Errorf("kubeadm KUBECONFIG should have one context, but read %d", len(cfg.Contexts))
return errors.NewValidationFailed(fmt.Errorf("kubeadm KUBECONFIG should have one context, but read %d", len(cfg.Contexts)))
}
return nil
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ package kubeconfig
import (
"os"

"sigs.k8s.io/kind/pkg/errors"
"github.com/vmware-tanzu/community-edition/errors"
)

// WriteMerged writes a kind kubeconfig (see KINDFromRawKubeadm) into configPath
Expand All @@ -18,7 +18,7 @@ func WriteMerged(kindConfig *Config, explicitConfigPath string) error {

// lock config file the same as client-go
if err := lockFile(configPath); err != nil {
return errors.Wrap(err, "failed to lock config file")
return errors.NewLockFailed(err, "failed to lock config file %s", configPath)
}
defer func() {
_ = unlockFile(configPath)
Expand All @@ -27,12 +27,12 @@ func WriteMerged(kindConfig *Config, explicitConfigPath string) error {
// read in existing
existing, err := read(configPath)
if err != nil {
return errors.Wrap(err, "failed to get kubeconfig to merge")
return errors.NewReadFailed(err, "failed to read kubeconfig file %s", configPath)
}

// merge with kind kubeconfig
if err := merge(existing, kindConfig); err != nil {
return err
return errors.NewMergeFailed(err, "failed to merge kubeconfig file %s", configPath)
}

// write back out
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import (
"os"

yaml "gopkg.in/yaml.v3"
"sigs.k8s.io/kind/pkg/errors"

"github.com/vmware-tanzu/community-edition/errors"
)

// KINDFromRawKubeadm returns a kind kubeconfig derived from the raw kubeadm kubeconfig,
Expand Down Expand Up @@ -56,17 +57,17 @@ func read(configPath string) (*Config, error) {
if os.IsNotExist(err) {
return &Config{}, nil
} else if err != nil {
return nil, errors.WithStack(err)
return nil, errors.NewReadFailed(err, "failed to read config file %s", configPath)
}

// otherwise read in and deserialize
cfg := &Config{}
rawExisting, err := io.ReadAll(f)
if err != nil {
return nil, errors.WithStack(err)
return nil, errors.NewIOFailed(err, "failed to read config file data")
}
if err := yaml.Unmarshal(rawExisting, cfg); err != nil {
return nil, errors.WithStack(err)
return nil, errors.NewMarshallingFailed(err, "faled to marshall kubeconfig file %s", configPath)
}

return cfg, nil
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ package kubeconfig
import (
"os"

"sigs.k8s.io/kind/pkg/errors"
"github.com/vmware-tanzu/community-edition/errors"
)

// RemoveKIND removes the kind cluster kindClusterName from the KUBECONFIG
Expand All @@ -17,7 +17,7 @@ func RemoveKIND(kindClusterName, explicitPath string) error {
if err := func(configPath string) error {
// lock before modifying
if err := lockFile(configPath); err != nil {
return errors.Wrap(err, "failed to lock config file")
return errors.NewLockFailed(err, "failed to lock config file %s", configPath)
}
defer func(configPath string) {
_ = unlockFile(configPath)
Expand All @@ -26,7 +26,7 @@ func RemoveKIND(kindClusterName, explicitPath string) error {
// read in existing
existing, err := read(configPath)
if err != nil {
return errors.Wrap(err, "failed to read kubeconfig to remove KIND entry")
return errors.NewReadFailed(err, "failed to read kubeconfig to remove KIND entry")
}

// remove the kind cluster from the config
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
"os"
"path/filepath"

"sigs.k8s.io/kind/pkg/errors"
"github.com/vmware-tanzu/community-edition/errors"
)

// write writes cfg to configPath
Expand All @@ -21,11 +21,11 @@ func write(cfg *Config, configPath string) error {
dir := filepath.Dir(configPath)
if _, err := os.Stat(dir); os.IsNotExist(err) {
if err = os.MkdirAll(dir, 0755); err != nil {
return errors.Wrap(err, "failed to create directory for KUBECONFIG")
return errors.NewIOFailed(err, "failed to create directory for KUBECONFIG")
}
}
if err := os.WriteFile(configPath, encoded, 0600); err != nil {
return errors.Wrap(err, "failed to write KUBECONFIG")
return errors.NewIOFailed(err, "failed to write KUBECONFIG")
}
return nil
}
Loading

0 comments on commit ae77e61

Please sign in to comment.