diff --git a/pkg/binding/binding.go b/pkg/binding/binding.go index 7a91453f6ee..f721a9ef019 100644 --- a/pkg/binding/binding.go +++ b/pkg/binding/binding.go @@ -154,7 +154,7 @@ func (o *BindingClient) GetBindingsFromDevfile(devfileObj parser.DevfileObj, con } sb.Status, err = o.getStatusFromBinding(sb.Name) if err != nil { - warning = clierrors.NewWarning("unable to access the cluster", err) + warning = clierrors.NewWarning(kclient.NewNoConnectionError().Error(), err) } result = append(result, sb) @@ -170,7 +170,7 @@ func (o *BindingClient) GetBindingsFromDevfile(devfileObj parser.DevfileObj, con sb := kclient.APIServiceBindingFromSpec(sbc) sb.Status, err = o.getStatusFromSpec(sb.Name) if err != nil { - warning = clierrors.NewWarning("unable to access the cluster", err) + warning = clierrors.NewWarning(kclient.NewNoConnectionError().Error(), err) } result = append(result, sb) diff --git a/pkg/kclient/errors.go b/pkg/kclient/errors.go index 2f6e42d9584..d8d2417f7c5 100644 --- a/pkg/kclient/errors.go +++ b/pkg/kclient/errors.go @@ -19,3 +19,14 @@ type ServiceNotFoundError struct { func (e *ServiceNotFoundError) Error() string { return fmt.Sprintf("service not found for the selector %q", e.Selector) } + +type NoConnectionError struct{} + +func NewNoConnectionError() NoConnectionError { + return NoConnectionError{} +} + +func (e NoConnectionError) Error() string { + // could also be "cluster is non accessible" + return "unable to access the cluster" +} diff --git a/pkg/odo/cli/describe/component.go b/pkg/odo/cli/describe/component.go index 223fee17be2..86be92ef7af 100644 --- a/pkg/odo/cli/describe/component.go +++ b/pkg/odo/cli/describe/component.go @@ -93,7 +93,7 @@ func (o *ComponentOptions) Validate(ctx context.Context) (err error) { switch fcontext.GetPlatform(ctx, commonflags.PlatformCluster) { case commonflags.PlatformCluster: if o.clientset.KubernetesClient == nil { - log.Warning("No connection to cluster defined") + log.Warning(kclient.NewNoConnectionError()) } case commonflags.PlatformPodman: if o.namespaceFlag != "" { @@ -147,25 +147,25 @@ func (o *ComponentOptions) describeNamedComponent(ctx context.Context, name stri if isPlatformFeatureEnabled { //Get info from all platforms if kubeClient == nil { - log.Warning("cluster is non accessible") + log.Warning(kclient.NewNoConnectionError()) } if podmanClient == nil { - log.Warning("unable to access podman. Do you have podman client installed?") + log.Warning(podman.NewPodmanNotFoundError(nil)) } } else { if kubeClient == nil { - return api.Component{}, nil, errors.New("cluster is non accessible") + return api.Component{}, nil, kclient.NewNoConnectionError() } podmanClient = nil } case commonflags.PlatformCluster: if kubeClient == nil { - return api.Component{}, nil, errors.New("cluster is non accessible") + return api.Component{}, nil, kclient.NewNoConnectionError() } podmanClient = nil case commonflags.PlatformPodman: if podmanClient == nil { - return api.Component{}, nil, errors.New("unable to access podman. Do you have podman client installed?") + return api.Component{}, nil, podman.NewPodmanNotFoundError(nil) } kubeClient = nil } @@ -224,19 +224,19 @@ func (o *ComponentOptions) describeDevfileComponent(ctx context.Context) (result switch platform { case "": if kubeClient == nil { - log.Warning("cluster is non accessible") + log.Warning(kclient.NewNoConnectionError()) } if isPlatformFeatureEnabled && podmanClient == nil { - log.Warning("unable to access podman. Do you have podman client installed?") + log.Warning(podman.NewPodmanNotFoundError(nil)) } case commonflags.PlatformCluster: if kubeClient == nil { - return api.Component{}, nil, errors.New("cluster is non accessible") + return api.Component{}, nil, kclient.NewNoConnectionError() } podmanClient = nil case commonflags.PlatformPodman: if podmanClient == nil { - return api.Component{}, nil, errors.New("unable to access podman. Do you have podman client installed?") + return api.Component{}, nil, podman.NewPodmanNotFoundError(nil) } kubeClient = nil } diff --git a/pkg/odo/cli/dev/dev.go b/pkg/odo/cli/dev/dev.go index 884b45c9e6c..99dd63a8509 100644 --- a/pkg/odo/cli/dev/dev.go +++ b/pkg/odo/cli/dev/dev.go @@ -2,7 +2,6 @@ package dev import ( "context" - "errors" "fmt" "io" "path/filepath" @@ -12,6 +11,7 @@ import ( "github.com/redhat-developer/odo/pkg/component" "github.com/redhat-developer/odo/pkg/dev" + "github.com/redhat-developer/odo/pkg/kclient" "github.com/redhat-developer/odo/pkg/libdevfile" "github.com/redhat-developer/odo/pkg/log" clierrors "github.com/redhat-developer/odo/pkg/odo/cli/errors" @@ -23,6 +23,7 @@ import ( "github.com/redhat-developer/odo/pkg/odo/genericclioptions" "github.com/redhat-developer/odo/pkg/odo/genericclioptions/clientset" odoutil "github.com/redhat-developer/odo/pkg/odo/util" + "github.com/redhat-developer/odo/pkg/podman" scontext "github.com/redhat-developer/odo/pkg/segment/context" "github.com/redhat-developer/odo/pkg/util" "github.com/redhat-developer/odo/pkg/version" @@ -105,12 +106,12 @@ func (o *DevOptions) Validate(ctx context.Context) error { switch platform { case commonflags.PlatformCluster: if o.clientset.KubernetesClient == nil { - return errors.New("no connection to cluster defined") + return kclient.NewNoConnectionError() } scontext.SetPlatform(ctx, o.clientset.KubernetesClient) case commonflags.PlatformPodman: if o.clientset.PodmanClient == nil { - return errors.New("unable to access podman. Do you have podman client installed?") + return podman.NewPodmanNotFoundError(nil) } scontext.SetPlatform(ctx, o.clientset.PodmanClient) } diff --git a/pkg/odo/cli/list/component/list.go b/pkg/odo/cli/list/component/list.go index 161c7452f40..f123621d769 100644 --- a/pkg/odo/cli/list/component/list.go +++ b/pkg/odo/cli/list/component/list.go @@ -2,7 +2,6 @@ package component import ( "context" - "errors" "fmt" "github.com/jedib0t/go-pretty/v6/table" @@ -10,6 +9,7 @@ import ( "github.com/spf13/cobra" "github.com/redhat-developer/odo/pkg/api" + "github.com/redhat-developer/odo/pkg/kclient" "github.com/redhat-developer/odo/pkg/odo/cli/feature" "github.com/redhat-developer/odo/pkg/odo/cli/ui" "github.com/redhat-developer/odo/pkg/odo/commonflags" @@ -64,7 +64,7 @@ func (lo *ListOptions) Complete(ctx context.Context, cmdline cmdline.Cmdline, ar // if it hasn't, we will search from the default project / namespace. if lo.namespaceFlag != "" { if lo.clientset.KubernetesClient == nil { - return errors.New("cluster is non accessible") + return kclient.NewNoConnectionError() } lo.namespaceFilter = lo.namespaceFlag } else if lo.clientset.KubernetesClient != nil { @@ -77,7 +77,7 @@ func (lo *ListOptions) Complete(ctx context.Context, cmdline cmdline.Cmdline, ar // Validate ... func (lo *ListOptions) Validate(ctx context.Context) (err error) { if lo.clientset.KubernetesClient == nil { - log.Warning("No connection to cluster defined") + log.Warning(kclient.NewNoConnectionError()) } return nil } diff --git a/pkg/odo/genericclioptions/clientset/clientset.go b/pkg/odo/genericclioptions/clientset/clientset.go index 1e0e1242d6b..f1d44e0cc95 100644 --- a/pkg/odo/genericclioptions/clientset/clientset.go +++ b/pkg/odo/genericclioptions/clientset/clientset.go @@ -169,8 +169,9 @@ func Fetch(command *cobra.Command, platform string) (*Clientset, error) { if isDefined(command, PODMAN) || isDefined(command, PODMAN_NULLABLE) { dep.PodmanClient, err = podman.NewPodmanCli(ctx) if err != nil { - if isDefined(command, PODMAN) { - return nil, err + // send error in case the command is to run on podman platform or if PODMAN clientset is required. + if isDefined(command, PODMAN) || platform == commonflags.PlatformPodman { + return nil, podman.NewPodmanNotFoundError(err) } dep.PodmanClient = nil } diff --git a/pkg/podman/errors.go b/pkg/podman/errors.go new file mode 100644 index 00000000000..ea37f7ed5d9 --- /dev/null +++ b/pkg/podman/errors.go @@ -0,0 +1,21 @@ +package podman + +import ( + "fmt" +) + +type PodmanNotFoundError struct { + err error +} + +func NewPodmanNotFoundError(err error) PodmanNotFoundError { + return PodmanNotFoundError{err: err} +} + +func (o PodmanNotFoundError) Error() string { + msg := "unable to access podman. Do you have podman client installed and configured correctly?" + if o.err == nil { + return msg + } + return fmt.Errorf("%s cause: %w", msg, o.err).Error() +} diff --git a/pkg/podman/podman.go b/pkg/podman/podman.go index 754a22c8a6c..75d48e6930c 100644 --- a/pkg/podman/podman.go +++ b/pkg/podman/podman.go @@ -27,7 +27,7 @@ func NewPodmanCli(ctx context.Context) (*PodmanCli, error) { } version, err := cli.Version() if err != nil { - return nil, fmt.Errorf("executable %q not found", cli.podmanCmd) + return nil, err } if version.Client == nil { return nil, fmt.Errorf("executable %q not recognized as podman client", cli.podmanCmd) diff --git a/tests/integration/cmd_describe_component_test.go b/tests/integration/cmd_describe_component_test.go index ce97a1f7f1f..16b56d8c099 100644 --- a/tests/integration/cmd_describe_component_test.go +++ b/tests/integration/cmd_describe_component_test.go @@ -350,7 +350,7 @@ var _ = Describe("odo describe component command tests", func() { // Podman mode assumes the test does not require a cluster. // But running "odo describe component --name" in non-experimental mode attempts to get information from a cluster first. // TODO We need to think about how to test both Cluster and Podman modes. - Expect(stderr).To(ContainSubstring("cluster is non accessible")) + Expect(stderr).To(ContainSubstring("unable to access the cluster")) Expect(stdout).NotTo(ContainSubstring("Forwarded ports")) Expect(stdout).NotTo(ContainSubstring("Running on")) Expect(stdout).NotTo(ContainSubstring("podman:")) @@ -522,7 +522,7 @@ var _ = Describe("odo describe component command tests", func() { Expect(stdout).To(BeEmpty()) helper.JsonPathDoesNotExist(stderr, "runningOn") // Deprecated helper.JsonPathDoesNotExist(stderr, "platform") - helper.JsonPathContentIs(stderr, "message", "cluster is non accessible") + helper.JsonPathContentIs(stderr, "message", "unable to access the cluster") helper.JsonPathDoesNotExist(stderr, "devfilePath") helper.JsonPathDoesNotExist(stderr, "devForwardedPorts") helper.JsonPathDoesNotExist(stderr, "devfileData") diff --git a/tests/integration/cmd_dev_test.go b/tests/integration/cmd_dev_test.go index 6705c1a2a95..d80ed67a7d5 100644 --- a/tests/integration/cmd_dev_test.go +++ b/tests/integration/cmd_dev_test.go @@ -3290,6 +3290,17 @@ CMD ["npm", "start"] } + Context("odo dev on podman when podman in unavailable", Label(helper.LabelPodman), func() { + BeforeEach(func() { + helper.CopyExampleDevFile(filepath.Join("source", "devfiles", "nodejs", "devfile.yaml"), + filepath.Join(commonVar.Context, "devfile.yaml"), + helper.DevfileMetadataNameSetter(cmpName)) + }) + It("should fail to run odo dev", func() { + errOut := helper.Cmd("odo", "dev", "--platform", "podman").WithEnv("PODMAN_CMD=echo", "ODO_EXPERIMENTAL_MODE=true").ShouldFail().Err() + Expect(errOut).To(ContainSubstring("unable to access podman. Do you have podman client installed and configured correctly? cause: exec: \"echo\": executable file not found in $PATH")) + }) + }) Context("odo dev on podman with a devfile bound to fail", Label(helper.LabelPodman), func() { BeforeEach(func() { helper.CopyExample(filepath.Join("source", "devfiles", "nodejs", "project"), commonVar.Context)