Skip to content

Commit d7b7561

Browse files
wrap errors with grpc
1 parent ea70ac2 commit d7b7561

File tree

16 files changed

+181
-64
lines changed

16 files changed

+181
-64
lines changed

go.sum

Lines changed: 72 additions & 0 deletions
Large diffs are not rendered by default.

pkg/connector/client/client.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77

88
"github.com/conductorone/baton-sdk/pkg/uhttp"
99
"github.com/grpc-ecosystem/go-grpc-middleware/logging/zap/ctxzap"
10+
"google.golang.org/grpc/codes"
1011
)
1112

1213
var (
@@ -33,21 +34,21 @@ type WorkatoClient struct {
3334
func NewWorkatoClient(ctx context.Context, apiKey, baseUrl string) (*WorkatoClient, error) {
3435
parseBaseUrl, err := url.Parse(baseUrl)
3536
if err != nil {
36-
return nil, err
37+
return nil, uhttp.WrapErrors(codes.InvalidArgument, "baton-workato: failed to parse base URL", err)
3738
}
3839

3940
if apiKey == "" {
40-
return nil, ErrApiKeyIsEmpty
41+
return nil, uhttp.WrapErrors(codes.InvalidArgument, "baton-workato: api key is empty", ErrApiKeyIsEmpty)
4142
}
4243

4344
httpClient, err := uhttp.NewClient(ctx, uhttp.WithLogger(true, ctxzap.Extract(ctx)))
4445
if err != nil {
45-
return nil, err
46+
return nil, uhttp.WrapErrors(codes.Internal, "baton-workato: failed to create HTTP client", err)
4647
}
4748

4849
uhttpClient, err := uhttp.NewBaseHttpClientWithContext(ctx, httpClient)
4950
if err != nil {
50-
return nil, err
51+
return nil, uhttp.WrapErrors(codes.Internal, "baton-workato: failed to create base HTTP client", err)
5152
}
5253

5354
return &WorkatoClient{

pkg/connector/client/colaborator.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ func (c *WorkatoClient) GetCollaboratorPrivileges(ctx context.Context, id int) (
3030
}
3131

3232
if len(response.Data) == 0 {
33-
return nil, status.Errorf(codes.NotFound, "baton-workato: no collaborator privileges found")
33+
return nil, status.Errorf(codes.NotFound, "baton-workato: no collaborator privileges found for id %d", id)
3434
}
3535

3636
return response.Data, nil

pkg/connector/client/folder.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ import (
55
"fmt"
66
"net/http"
77
"strconv"
8+
9+
"github.com/conductorone/baton-sdk/pkg/uhttp"
10+
"google.golang.org/grpc/codes"
811
)
912

1013
func (c *WorkatoClient) GetFolders(ctx context.Context, parentId *int, pToken string) ([]Folder, string, error) {
@@ -15,7 +18,7 @@ func (c *WorkatoClient) GetFolders(ctx context.Context, parentId *int, pToken st
1518
if pToken != "" {
1619
page, err = strconv.Atoi(pToken)
1720
if err != nil {
18-
return nil, "", ErrInvalidPaginationToken
21+
return nil, "", uhttp.WrapErrors(codes.InvalidArgument, "baton-workato: invalid pagination token for folders", ErrInvalidPaginationToken)
1922
}
2023
}
2124

pkg/connector/client/helpers.go

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"github.com/conductorone/baton-sdk/pkg/uhttp"
1313
"github.com/grpc-ecosystem/go-grpc-middleware/logging/zap/ctxzap"
1414
"go.uber.org/zap"
15+
"google.golang.org/grpc/codes"
1516
)
1617

1718
var (
@@ -32,22 +33,42 @@ func (c *WorkatoClient) getPath(path string) *url.URL {
3233
return c.baseUrl.JoinPath(path)
3334
}
3435

36+
// httpToGRPCCode maps HTTP status codes to gRPC codes.
37+
func httpToGRPCCode(statusCode int) codes.Code {
38+
switch statusCode {
39+
case http.StatusBadRequest:
40+
return codes.InvalidArgument
41+
case http.StatusUnauthorized:
42+
return codes.Unauthenticated
43+
case http.StatusForbidden:
44+
return codes.PermissionDenied
45+
case http.StatusNotFound:
46+
return codes.NotFound
47+
case http.StatusInternalServerError:
48+
return codes.Internal
49+
default:
50+
return codes.Unknown
51+
}
52+
}
53+
3554
func getError(ctx context.Context, originalErr error, resp *http.Response) error {
55+
grpcCode := httpToGRPCCode(resp.StatusCode)
56+
3657
bytes, err := io.ReadAll(resp.Body)
3758
if err != nil {
3859
// We expect the response body to be JSON, according to the Workato API docs, but this is not guaranteed.
3960
l := ctxzap.Extract(ctx)
4061
l.Debug("failed to read response body", zap.String("body", string(bytes)))
41-
return errors.Join(originalErr, err)
62+
return uhttp.WrapErrors(grpcCode, "baton-workato: failed to read error response", errors.Join(originalErr, err))
4263
}
4364

4465
var cErr ApiError
4566
err = json.Unmarshal(bytes, &cErr)
4667
if err != nil {
47-
return errors.Join(originalErr, err)
68+
return uhttp.WrapErrors(grpcCode, "baton-workato: failed to parse error response", errors.Join(originalErr, err))
4869
}
4970

50-
return errors.Join(originalErr, errors.New(cErr.Message))
71+
return uhttp.WrapErrors(grpcCode, fmt.Sprintf("baton-workato: API error (status %d)", resp.StatusCode), errors.Join(originalErr, errors.New(cErr.Message)))
5172
}
5273

5374
func (c *WorkatoClient) doRequest(ctx context.Context, method string, urlAddress *url.URL, res interface{}, body interface{}) error {
@@ -64,7 +85,7 @@ func (c *WorkatoClient) doRequest(ctx context.Context, method string, urlAddress
6485
uhttp.WithJSONBody(body),
6586
)
6687
if err != nil {
67-
return err
88+
return uhttp.WrapErrors(codes.Internal, "baton-workato: failed to create HTTP request", err)
6889
}
6990

7091
var options []uhttp.DoOption
@@ -77,10 +98,10 @@ func (c *WorkatoClient) doRequest(ctx context.Context, method string, urlAddress
7798

7899
if resp == nil {
79100
if err != nil {
80-
return err
101+
return uhttp.WrapErrors(codes.Internal, "baton-workato: response is nil and error is nil, this should never happen", err)
81102
}
82103

83-
return errors.New("baton-workato: response is nil and error is nil, this should never happen, might be a bug in the http client")
104+
return uhttp.WrapErrors(codes.Internal, "baton-workato: response is nil and error is nil, this should never happen", err)
84105
}
85106

86107
defer resp.Body.Close()

pkg/connector/client/project.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ import (
55
"fmt"
66
"net/http"
77
"strconv"
8+
9+
"github.com/conductorone/baton-sdk/pkg/uhttp"
10+
"google.golang.org/grpc/codes"
811
)
912

1013
func (c *WorkatoClient) GetProjects(ctx context.Context, pToken string) ([]Project, string, error) {
@@ -15,7 +18,7 @@ func (c *WorkatoClient) GetProjects(ctx context.Context, pToken string) ([]Proje
1518
if pToken != "" {
1619
page, err = strconv.Atoi(pToken)
1720
if err != nil {
18-
return nil, "", ErrInvalidPaginationToken
21+
return nil, "", uhttp.WrapErrors(codes.InvalidArgument, "baton-workato: invalid pagination token for projects", ErrInvalidPaginationToken)
1922
}
2023
}
2124

pkg/connector/client/roles.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ import (
55
"fmt"
66
"net/http"
77
"strconv"
8+
9+
"github.com/conductorone/baton-sdk/pkg/uhttp"
10+
"google.golang.org/grpc/codes"
811
)
912

1013
func (c *WorkatoClient) GetRoles(ctx context.Context, pToken string) ([]Role, string, error) {
@@ -15,7 +18,7 @@ func (c *WorkatoClient) GetRoles(ctx context.Context, pToken string) ([]Role, st
1518
if pToken != "" {
1619
page, err = strconv.Atoi(pToken)
1720
if err != nil {
18-
return nil, "", ErrInvalidPaginationToken
21+
return nil, "", uhttp.WrapErrors(codes.InvalidArgument, "baton-workato: invalid pagination token for roles", ErrInvalidPaginationToken)
1922
}
2023
}
2124

pkg/connector/collaborator.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@ import (
44
"context"
55

66
"github.com/conductorone/baton-sdk/pkg/types/resource"
7+
"github.com/conductorone/baton-sdk/pkg/uhttp"
78
"github.com/conductorone/baton-workato/pkg/connector/client"
89

910
v2 "github.com/conductorone/baton-sdk/pb/c1/connector/v2"
1011
"github.com/conductorone/baton-sdk/pkg/annotations"
1112
"github.com/conductorone/baton-sdk/pkg/pagination"
1213

1314
"github.com/grpc-ecosystem/go-grpc-middleware/logging/zap/ctxzap"
15+
"google.golang.org/grpc/codes"
1416
)
1517

1618
type collaboratorBuilder struct {
@@ -37,7 +39,7 @@ func (o *collaboratorBuilder) List(ctx context.Context, parentResourceID *v2.Res
3739
for i, collaborator := range collaborators {
3840
us, err := collaboratorResource(&collaborator)
3941
if err != nil {
40-
return nil, "", nil, err
42+
return nil, "", nil, uhttp.WrapErrors(codes.Internal, "baton-workato: failed to create collaborator resource", err)
4143
}
4244
rv[i] = us
4345
}
@@ -91,7 +93,7 @@ func collaboratorResource(collaborator *client.Collaborator) (*v2.Resource, erro
9193
traits,
9294
)
9395
if err != nil {
94-
return nil, err
96+
return nil, uhttp.WrapErrors(codes.Internal, "baton-workato: failed to create collaborator resource", err)
9597
}
9698

9799
return ret, nil

pkg/connector/collaborator_cache.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package connector
22

33
import (
44
"context"
5+
"fmt"
56
"strconv"
67
"sync"
78

@@ -53,7 +54,7 @@ func (p *collaboratorCache) init(ctx context.Context) error {
5354
}
5455

5556
if err := p.buildCache(ctx); err != nil {
56-
return err
57+
return fmt.Errorf("baton-workato: failed to build collaborator cache: %w", err)
5758
}
5859

5960
p.initialized = true
@@ -70,7 +71,7 @@ func (p *collaboratorCache) buildCache(ctx context.Context) error {
7071

7172
collaborators, err := p.client.GetCollaborators(ctx)
7273
if err != nil {
73-
return err
74+
return fmt.Errorf("baton-workato: failed to get collaborators for cache: %w", err)
7475
}
7576

7677
l.Debug("Building cache for collaborators", zap.Int("count", len(collaborators)))
@@ -82,7 +83,7 @@ func (p *collaboratorCache) buildCache(ctx context.Context) error {
8283
l.Warn("Collaborator not found, skipping", zap.Int("collaborator_id", collaborator.Id))
8384
continue
8485
}
85-
return err
86+
return fmt.Errorf("baton-workato: failed to get collaborator privileges for cache building (id %d): %w", collaborator.Id, err)
8687
}
8788

8889
compoundUser := &CompoundUser{

pkg/connector/cpagination/generic_bag.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@ package cpagination
22

33
import (
44
"encoding/json"
5-
"fmt"
65

76
"github.com/conductorone/baton-sdk/pkg/pagination"
7+
"github.com/conductorone/baton-sdk/pkg/uhttp"
8+
"google.golang.org/grpc/codes"
89
)
910

1011
type genericSerializedPaginationBag[T any] struct {
@@ -24,7 +25,7 @@ func GenBagFromToken[T any](pToken pagination.Token) (*GenBag[T], error) {
2425
bag := &GenBag[T]{}
2526
err := bag.Unmarshal(pToken.Token)
2627
if err != nil {
27-
return nil, err
28+
return nil, uhttp.WrapErrors(codes.Internal, "baton-workato: failed to unmarshal pagination token for generic bag", err)
2829
}
2930
return bag, nil
3031
}
@@ -83,7 +84,7 @@ func (pb *GenBag[T]) Unmarshal(input string) error {
8384
if input != "" {
8485
err := json.Unmarshal([]byte(input), &target)
8586
if err != nil {
86-
return fmt.Errorf("page token corrupt: %w", err)
87+
return uhttp.WrapErrors(codes.Internal, "baton-workato: failed to unmarshal pagination token for generic bag", err)
8788
}
8889

8990
pb.states = target.States

0 commit comments

Comments
 (0)