Skip to content

Commit

Permalink
fix(cli): add proper error handling for network related errors (#597)
Browse files Browse the repository at this point in the history
Signed-off-by: Aryakoste <aryakhochare@gmail.com>
  • Loading branch information
Aryakoste authored May 7, 2024
1 parent a27d19a commit c381ae0
Show file tree
Hide file tree
Showing 5 changed files with 30 additions and 19 deletions.
12 changes: 4 additions & 8 deletions internal/clientutils/resources.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,8 @@ import (
)

func FetchResources(url string) ([]unstructured.Unstructured, error) {
response, err := http.Get(url)
response, err := httperror.CheckResponse(http.Get(url))
if err != nil {
return nil, fmt.Errorf("could not download manifest %v: %w", url, err)
}
defer func(Body io.ReadCloser) {
_ = Body.Close()
}(response.Body)

if err := httperror.CheckResponse(response); err != nil {
switch {
case httperror.IsNotFound(err):
return nil, fmt.Errorf("manifest not found at %v: %v", url, err)
Expand All @@ -31,6 +24,9 @@ func FetchResources(url string) ([]unstructured.Unstructured, error) {
return nil, fmt.Errorf("failed to download manifest from %v: %v", url, err)
}
}
defer func(Body io.ReadCloser) {
_ = Body.Close()
}(response.Body)

decoder := yaml.NewYAMLOrJSONDecoder(response.Body, 4096)
resources := make([]unstructured.Unstructured, 0)
Expand Down
16 changes: 12 additions & 4 deletions internal/httperror/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package httperror
import (
"errors"
"fmt"
"net"
"net/http"
)

Expand All @@ -27,11 +28,13 @@ func IsErrorResponse(respose *http.Response) bool {
return respose.StatusCode >= 400
}

func CheckResponse(response *http.Response) error {
if IsErrorResponse(response) {
return &statusError{response.Status, response.StatusCode}
func CheckResponse(response *http.Response, err error) (*http.Response, error) {
if err != nil {
return response, err
} else if IsErrorResponse(response) {
return response, &statusError{response.Status, response.StatusCode}
} else {
return nil
return response, nil
}
}

Expand All @@ -47,3 +50,8 @@ func Is(err error, code int) bool {
func IsNotFound(err error) bool {
return Is(err, http.StatusNotFound)
}

func IsTimeoutError(err error) bool {
var netErr net.Error
return errors.As(err, &netErr) && netErr.Timeout()
}
8 changes: 6 additions & 2 deletions internal/releaseinfo/releaseinfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package releaseinfo
import (
"encoding/json"
"net/http"

"github.com/glasskube/glasskube/internal/httperror"
)

type ReleaseInfo struct {
Expand All @@ -12,8 +14,10 @@ type ReleaseInfo struct {
func FetchLatestRelease() (*ReleaseInfo, error) {
url := "https://glasskube.dev/release.json"

resp, _ := http.Get(url)

resp, err := httperror.CheckResponse(http.Get(url))
if err != nil {
return nil, err
}
defer func() {
_ = resp.Body.Close()
}()
Expand Down
7 changes: 2 additions & 5 deletions internal/repo/client/defaultclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,14 +124,11 @@ func (c *defaultClient) fetchYAMLOrJSON(url string, target any) error {
fmt.Fprintln(os.Stderr, "cache miss", url)
}

resp, err := http.Get(url)
resp, err := httperror.CheckResponse(http.Get(url))
if err != nil {
return err
}
defer func() { _ = resp.Body.Close() }()
if err = httperror.CheckResponse(resp); err != nil {
return fmt.Errorf("failed to fetch %v: %w", url, err)
}
defer func() { _ = resp.Body.Close() }()
if bytes, err := io.ReadAll(resp.Body); err != nil {
return err
} else if err := yaml.Unmarshal(bytes, target); err != nil {
Expand Down
6 changes: 6 additions & 0 deletions pkg/bootstrap/bootstrap.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ package bootstrap
import (
"context"
"fmt"
"net/http"
"time"

"github.com/fatih/color"
"github.com/glasskube/glasskube/internal/clientutils"
"github.com/glasskube/glasskube/internal/config"
"github.com/glasskube/glasskube/internal/constants"
"github.com/glasskube/glasskube/internal/httperror"
"github.com/glasskube/glasskube/internal/releaseinfo"
"github.com/glasskube/glasskube/internal/telemetry"
"github.com/glasskube/glasskube/internal/telemetry/annotations"
Expand Down Expand Up @@ -77,6 +79,10 @@ func (c *BootstrapClient) Bootstrap(ctx context.Context, options BootstrapOption
version := config.Version
if options.Latest {
if releaseInfo, err := releaseinfo.FetchLatestRelease(); err != nil {
if httperror.Is(err, http.StatusServiceUnavailable) || httperror.IsTimeoutError(err) {
telemetry.BootstrapFailure(time.Since(start))
return fmt.Errorf("Network connectivity error, check your network, cannot bootstrap")
}
telemetry.BootstrapFailure(time.Since(start))
return fmt.Errorf("could not determine latest version: %w", err)
} else {
Expand Down

0 comments on commit c381ae0

Please sign in to comment.