Skip to content

Commit

Permalink
Improve error messages
Browse files Browse the repository at this point in the history
  • Loading branch information
pawelbeza committed Dec 8, 2023
1 parent d0272dc commit b3945de
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 36 deletions.
98 changes: 63 additions & 35 deletions pkg/koyeb/cp.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
"path"

"github.com/koyeb/koyeb-api-client-go/api/v1/koyeb"
"github.com/pkg/errors"
"github.com/koyeb/koyeb-cli/pkg/koyeb/errors"
)

type CopyManager struct {
Expand Down Expand Up @@ -47,14 +47,10 @@ func (manager *CopyManager) Copy(ctx *CLIContext) error {
func (manager *CopyManager) copyToInstance(ctx *CLIContext) error {
reader, writer := io.Pipe()

var tarErr error
go func(srcPath string, writer io.WriteCloser) {
defer writer.Close()

err := Tar(srcPath, writer)
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to tar file: %s\n", err)
os.Exit(1)
}
tarErr = Tar(srcPath, writer)
}(manager.Src.FilePath, writer)

retCode, err := ctx.ExecClient.ExecWithStreams(
Expand All @@ -70,12 +66,14 @@ func (manager *CopyManager) copyToInstance(ctx *CLIContext) error {
},
[]string{"tar", "-C", manager.Dst.FilePath, "-xf", "-"},
)
if err != nil {
return fmt.Errorf("failed to copy file: %w", err)
}

if retCode != 0 {
os.Exit(retCode)
if err != nil || retCode != 0 {
return &errors.CLIError{
What: "Error while copying",
Why: fmt.Sprintf("Failed copying path %v", manager.Src.FilePath),
Additional: []string{"This might indicate issues with connectivity to the instance"},
Orig: fmt.Errorf("err: %v, return code: %v, tar err: %v", err, retCode, tarErr),
Solution: "Make sure that your network connection is stable. If the problem persists, try to update the CLI to the latest version.",
}
}

return nil
Expand All @@ -84,14 +82,11 @@ func (manager *CopyManager) copyToInstance(ctx *CLIContext) error {
func (manager *CopyManager) copyFromInstance(ctx *CLIContext) error {
reader, writer := io.Pipe()

var untarErr error
go func(dstPath string, reader io.ReadCloser) {
defer reader.Close()

err := Untar(dstPath, reader)
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to tar file: %s\n", err)
os.Exit(1)
}
untarErr = Untar(dstPath, reader)
}(manager.Dst.FilePath, reader)

pathDir := path.Dir(manager.Src.FilePath)
Expand All @@ -109,45 +104,67 @@ func (manager *CopyManager) copyFromInstance(ctx *CLIContext) error {
},
[]string{"tar", "-C", pathDir, "-czf", "-", pathBase},
)
if err != nil {
return fmt.Errorf("failed to copy path %s: %w", manager.Src.FilePath, err)
}

if retCode != 0 {
os.Exit(retCode)
if err != nil || retCode != 0 {
return &errors.CLIError{
What: "Error while copying",
Why: fmt.Sprintf("Failed copying path %v", manager.Src.FilePath),
Additional: []string{"This might indicate issues with connectivity to the instance"},
Orig: fmt.Errorf("err: %v, return code: %v, untar err: %v", err, retCode, untarErr),
Solution: "Make sure that your network connection is stable. If the problem persists, try to update the CLI to the latest version.",
}
}

return nil
}

func ValidateTargets(srcSpec, dstSpec *FileSpec) error {
if srcSpec.InstanceID != "" && dstSpec.InstanceID != "" {
return fmt.Errorf("one of src or dest must be a local file specification")
return &errors.CLIError{
What: "Error while copying",
Why: "One of source or destination path must be a local path",
Additional: []string{"This might indicate that you passed two remote paths"},
Orig: nil,
Solution: "If the problem persists, try to update the CLI to the latest version.",
}
}

if srcSpec.InstanceID == "" && dstSpec.InstanceID == "" {
return fmt.Errorf("one of src or dest must be an instance name")
return &errors.CLIError{
What: "Error while copying",
Why: "One of source or destination must be a remote path",
Additional: []string{"This might indicate that you passed two local paths"},
Orig: nil,
Solution: "If the problem persists, try to update the CLI to the latest version.",
}
}

if len(srcSpec.FilePath) == 0 || len(dstSpec.FilePath) == 0 {
return errors.New("filepath cannot be empty")
return &errors.CLIError{
What: "Error while copying",
Why: "Paths cannot be empty",
Additional: []string{"This might indicate that you passed empty path"},
Orig: nil,
Solution: "If the problem persists, try to update the CLI to the latest version.",
}
}

return nil
}

var (
errFileSpecDoesntMatchFormat = errors.New("filespec must match the canonical format: [instance:]file/path")
)

type FileSpec struct {
InstanceID string
FilePath string
}

func (spec *FileSpec) validateLocalPath() error {
if _, err := os.Stat(spec.FilePath); err != nil {
return fmt.Errorf("filepath %s doesn't exist", spec.FilePath)
return &errors.CLIError{
What: "Error while copying",
Why: fmt.Sprintf("The local path %s doesn't exist", spec.FilePath),
Additional: nil,
Orig: err,
Solution: "Make sure that the local path exists",
}
}
return nil
}
Expand All @@ -174,12 +191,23 @@ func (spec *FileSpec) validateRemotePath(ctx *CLIContext, isDir bool) error {
[]string{"test", testFlag, spec.FilePath},
)
if err != nil {
return fmt.Errorf("failed to check if path %s exist %v", spec.FilePath, err)
return &errors.CLIError{
What: "Error while copying",
Why: fmt.Sprintf("Failed to verify if remote path %v exists", spec.FilePath),
Additional: []string{"This might indicate issues with connectivity to the instance"},
Orig: err,
Solution: "Make sure that your network connection is stable. If the problem persists, try to update the CLI to the latest version.",
}
}

if retCode != 0 {
fmt.Fprintf(os.Stdout, "Remote path %s doesn't exist", spec.FilePath)
os.Exit(retCode)
return &errors.CLIError{
What: "Error while copying",
Why: fmt.Sprintf("The remote path %s doesn't exist", spec.FilePath),
Additional: []string{"You might also double check if you have permissions to read this path"},
Orig: err,
Solution: "Make sure that the remote path exists",
}
}

return err
Expand Down
9 changes: 8 additions & 1 deletion pkg/koyeb/instances_cp.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,21 @@ package koyeb
import (
"strings"

"github.com/koyeb/koyeb-cli/pkg/koyeb/errors"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)

func (h *InstanceHandler) ExtractFileSpec(ctx *CLIContext, target string) (*FileSpec, error) {
switch i := strings.Index(target, ":"); i {
case 0:
return nil, errFileSpecDoesntMatchFormat
return nil, &errors.CLIError{
What: "Error while copying",
Why: "Filespec must match the canonical format: [instance:]file/path",
Additional: nil,
Orig: nil,
Solution: "If the problem persists, try to update the CLI to the latest version.",
}
case -1:
return &FileSpec{
FilePath: target,
Expand Down

0 comments on commit b3945de

Please sign in to comment.