Skip to content

Commit

Permalink
Report missing kubeconfig or error connecting to cluster
Browse files Browse the repository at this point in the history
 Fixes #315
 - Improve error reporting if
    - kubeconfig file is missing or
    - there is no route to host
    - i/o timeout
  • Loading branch information
navidshaikh committed Mar 10, 2020
1 parent ba7e14c commit 1239c95
Show file tree
Hide file tree
Showing 7 changed files with 95 additions and 30 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@
|===
| | Description | PR

| 🐛
| Improve reporting for missing kubeconfig and error connecting to the cluster
| https://github.com/knative/client/pull/725[#725]

| 🎁
| Add `kn source list`
| https://github.com/knative/client/pull/666[#666]
Expand Down
16 changes: 14 additions & 2 deletions pkg/errors/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,19 @@ import (
func newInvalidCRD(apiGroup string) *KNError {
parts := strings.Split(apiGroup, ".")
name := parts[0]
msg := fmt.Sprintf("no Knative %s API found on the backend. Please verify the installation.", name)

msg := fmt.Sprintf("no Knative %s API found on the backend, please verify the installation", name)
return NewKNError(msg)
}

func newNoRouteToHost(errString string) error {
parts := strings.SplitAfter(errString, "dial tcp")
if len(parts) == 2 {
return NewKNError(fmt.Sprintf("error connecting to the cluster, please verify connection at: %s", strings.Trim(parts[1], " ")))
} else {
return NewKNError(fmt.Sprintf("error connecting to the cluster: %s", errString))
}
}

func newNoKubeConfig(errString string) error {
return NewKNError("no kubeconfig has been provided, please use a valid configuration to connect to the cluster")
}
8 changes: 4 additions & 4 deletions pkg/errors/errors_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,12 @@ import (

func TestNewInvalidCRD(t *testing.T) {
err := newInvalidCRD("serving.knative.dev")
assert.Error(t, err, "no Knative serving API found on the backend. Please verify the installation.")
assert.Error(t, err, "no Knative serving API found on the backend, please verify the installation")

err = newInvalidCRD("serving")
assert.Error(t, err, "no Knative serving API found on the backend. Please verify the installation.")
err = newInvalidCRD("eventing")
assert.Error(t, err, "no Knative eventing API found on the backend, please verify the installation")

err = newInvalidCRD("")
assert.Error(t, err, "no Knative API found on the backend. Please verify the installation.")
assert.Error(t, err, "no Knative API found on the backend, please verify the installation")

}
44 changes: 27 additions & 17 deletions pkg/errors/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,29 +27,39 @@ func isCRDError(status api_errors.APIStatus) bool {
return true
}
}

return false
}

func isNoRouteToHostError(err error) bool {
return strings.Contains(err.Error(), "no route to host") || strings.Contains(err.Error(), "i/o timeout")
}

func isEmptyConfigError(err error) bool {
return strings.Contains(err.Error(), "no configuration has been provided")
}

//Retrieves a custom error struct based on the original error APIStatus struct
//Returns the original error struct in case it can't identify the kind of APIStatus error
func GetError(err error) error {
apiStatus, ok := err.(api_errors.APIStatus)
if !ok {
return err
}

if apiStatus.Status().Details == nil {
switch {
case isEmptyConfigError(err):
return newNoKubeConfig(err.Error())
case isNoRouteToHostError(err):
return newNoRouteToHost(err.Error())
default:
apiStatus, ok := err.(api_errors.APIStatus)
if !ok {
return err
}
if apiStatus.Status().Details == nil {
return err
}
var knerr *KNError
if isCRDError(apiStatus) {
knerr = newInvalidCRD(apiStatus.Status().Details.Group)
knerr.Status = apiStatus
return knerr
}
return err
}

var knerr *KNError

if isCRDError(apiStatus) {
knerr = newInvalidCRD(apiStatus.Status().Details.Group)
knerr.Status = apiStatus
return knerr
}

return err
}
42 changes: 40 additions & 2 deletions pkg/errors/factory_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package errors

import (
"errors"
"testing"

"gotest.tools/assert"
Expand All @@ -23,7 +24,7 @@ import (
"k8s.io/apimachinery/pkg/runtime/schema"
)

func TestBuild(t *testing.T) {
func TestKnErrorsStatusErrors(t *testing.T) {
cases := []struct {
Name string
Schema schema.GroupResource
Expand All @@ -47,7 +48,7 @@ func TestBuild(t *testing.T) {
}
return statusError
},
ExpectedMsg: "no Knative serving API found on the backend. Please verify the installation.",
ExpectedMsg: "no Knative serving API found on the backend, please verify the installation",
Validate: func(t *testing.T, err error, msg string) {
assert.Error(t, err, msg)
},
Expand Down Expand Up @@ -92,3 +93,40 @@ func TestBuild(t *testing.T) {
})
}
}

func TestKnErrors(t *testing.T) {
cases := []struct {
Name string
Error error
ExpectedMsg string
}{
{
Name: "no kubeconfig provided",
Error: errors.New("invalid configuration: no configuration has been provided"),
ExpectedMsg: "no kubeconfig has been provided, please use a valid configuration to connect to the cluster",
},
{
Name: "i/o timeout",
Error: errors.New("Get https://api.example.com:27435/apis/foo/bar: dial tcp 192.168.1.1:27435: i/o timeout"),
ExpectedMsg: "error connecting to the cluster, please verify connection at: 192.168.1.1:27435: i/o timeout",
},
{
Name: "no route to host",
Error: errors.New("Get https://192.168.39.141:8443/apis/foo/bar: dial tcp 192.168.39.141:8443: connect: no route to host"),
ExpectedMsg: "error connecting to the cluster, please verify connection at: 192.168.39.141:8443: connect: no route to host",
},
{
Name: "no route to host without dial tcp string",
Error: errors.New("no route to host 192.168.1.1"),
ExpectedMsg: "error connecting to the cluster: no route to host 192.168.1.1",
},
}
for _, tc := range cases {
tc := tc
t.Run(tc.Name, func(t *testing.T) {
t.Parallel()
err := GetError(tc.Error)
assert.Error(t, err, tc.ExpectedMsg)
})
}
}
5 changes: 3 additions & 2 deletions pkg/kn/commands/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import (
"knative.dev/client/pkg/util"

clientdynamic "knative.dev/client/pkg/dynamic"
knerrors "knative.dev/client/pkg/errors"
clienteventingv1alpha1 "knative.dev/client/pkg/eventing/v1alpha1"
clientservingv1 "knative.dev/client/pkg/serving/v1"
)
Expand Down Expand Up @@ -145,13 +146,13 @@ func (params *KnParams) RestConfig() (*rest.Config, error) {
if params.ClientConfig == nil {
params.ClientConfig, err = params.GetClientConfig()
if err != nil {
return nil, err
return nil, knerrors.GetError(err)
}
}

config, err := params.ClientConfig.ClientConfig()
if err != nil {
return nil, err
return nil, knerrors.GetError(err)
}
if params.LogHTTP {
// TODO: When we update to the newer version of client-go, replace with
Expand Down
6 changes: 3 additions & 3 deletions pkg/kn/commands/types_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ func TestPrepareConfig(t *testing.T) {
for i, tc := range []configTestCase{
{
clientcmd.NewDefaultClientConfig(clientcmdapi.Config{}, &clientcmd.ConfigOverrides{}),
"no configuration has been provided",
"no kubeconfig has been provided, please use a valid configuration to connect to the cluster",
false,
},
{
Expand Down Expand Up @@ -151,7 +151,7 @@ func TestNewSourcesClient(t *testing.T) {
for i, tc := range []configTestCase{
{
clientcmd.NewDefaultClientConfig(clientcmdapi.Config{}, &clientcmd.ConfigOverrides{}),
"no configuration has been provided",
"no kubeconfig has been provided, please use a valid configuration to connect to the cluster",
false,
},
{
Expand Down Expand Up @@ -202,7 +202,7 @@ func TestNewDynamicClient(t *testing.T) {
for i, tc := range []configTestCase{
{
clientcmd.NewDefaultClientConfig(clientcmdapi.Config{}, &clientcmd.ConfigOverrides{}),
"no configuration has been provided",
"no kubeconfig has been provided, please use a valid configuration to connect to the cluster",
false,
},
{
Expand Down

0 comments on commit 1239c95

Please sign in to comment.