Skip to content

Commit 0186e25

Browse files
d0weinbergertomazpu
authored andcommitted
feat(clients): Improved error handling
Instead of 4 different error struct (`ErrorPermissionGet`, `ErrorPermissionCreate`, `ErrorPermissionUpdate`, and `ErrorPermissionDelete`), there is only one struct (`ErrorPermissions`) which holds an instance of `ClientOperation`, which can be either `GET`, `POST`, `PUT`, or `DELETE`. `Unwrap()` is implemented and `Error()` is improved, s.t. it also prints the reader-friendly version of the client operation.
1 parent 59709cc commit 0186e25

File tree

4 files changed

+208
-163
lines changed

4 files changed

+208
-163
lines changed

clients/settings/permissions/errors.go

Lines changed: 14 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -25,34 +25,24 @@ var (
2525
ErrorMissingAccessorType = errors.New("accessorType cannot be empty")
2626
)
2727

28-
type ErrorPermissionGet struct {
29-
Err error
30-
}
31-
32-
func (e ErrorPermissionGet) Error() string {
33-
return fmt.Sprintf("failed to get permission(s): %v", e.Err)
34-
}
35-
36-
type ErrorPermissionCreate struct {
37-
Err error
38-
}
28+
type ClientOperation string
3929

40-
func (e ErrorPermissionCreate) Error() string {
41-
return fmt.Sprintf("failed to create permission: %v", e.Err)
42-
}
43-
44-
type ErrorPermissionUpdate struct {
45-
Err error
46-
}
30+
const (
31+
GET ClientOperation = "get"
32+
POST ClientOperation = "create"
33+
PUT ClientOperation = "update"
34+
DELETE ClientOperation = "delete"
35+
)
4736

48-
func (e ErrorPermissionUpdate) Error() string {
49-
return fmt.Sprintf("failed to update permission: %v", e.Err)
37+
type ErrorPermissions struct {
38+
Wrapped error
39+
Operation ClientOperation
5040
}
5141

52-
type ErrorPermissionDelete struct {
53-
Err error
42+
func (e ErrorPermissions) Error() string {
43+
return fmt.Sprintf("failed to %v permission(s): %v", e.Operation, e.Wrapped)
5444
}
5545

56-
func (e ErrorPermissionDelete) Error() string {
57-
return fmt.Sprintf("failed to delete permission object: %v", e.Err)
46+
func (e ErrorPermissions) Unwrap() error {
47+
return e.Wrapped
5848
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// @license
2+
// Copyright 2025 Dynatrace LLC
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package permissions_test
16+
17+
import (
18+
"testing"
19+
20+
"github.com/stretchr/testify/assert"
21+
22+
"github.com/dynatrace/dynatrace-configuration-as-code-core/clients/settings/permissions"
23+
)
24+
25+
func TestErrorPermissions_Error_GET(t *testing.T) {
26+
err := permissions.ErrorPermissions{Wrapped: nil, Operation: permissions.GET}
27+
28+
assert.Equal(t, "failed to get permission(s): <nil>", err.Error())
29+
}
30+
31+
func TestErrorPermissions_Error_POST(t *testing.T) {
32+
err := permissions.ErrorPermissions{Wrapped: nil, Operation: permissions.POST}
33+
34+
assert.Equal(t, "failed to create permission(s): <nil>", err.Error())
35+
}
36+
37+
func TestErrorPermissions_Error_PUT(t *testing.T) {
38+
err := permissions.ErrorPermissions{Wrapped: nil, Operation: permissions.PUT}
39+
40+
assert.Equal(t, "failed to update permission(s): <nil>", err.Error())
41+
}
42+
43+
func TestErrorPermissions_Error_DELETE(t *testing.T) {
44+
err := permissions.ErrorPermissions{Wrapped: nil, Operation: permissions.DELETE}
45+
46+
assert.Equal(t, "failed to delete permission(s): <nil>", err.Error())
47+
}

clients/settings/permissions/permissions.go

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -45,48 +45,48 @@ func (c *Client) GetAllUsersAccessor(ctx context.Context, objectID string) (api.
4545

4646
func (c *Client) GetAccessor(ctx context.Context, objectID string, accessorType string, accessorID string) (api.Response, error) {
4747
if accessorType == "" {
48-
return api.Response{}, ErrorPermissionGet{ErrorMissingAccessorType}
48+
return api.Response{}, ErrorPermissions{Wrapped: ErrorMissingAccessorType, Operation: GET}
4949
}
5050

5151
if accessorID == "" {
52-
return api.Response{}, ErrorPermissionGet{ErrorMissingAccessorID}
52+
return api.Response{}, ErrorPermissions{Wrapped: ErrorMissingAccessorID, Operation: GET}
5353
}
5454

5555
return c.get(ctx, objectID, accessorType, accessorID)
5656
}
5757

5858
func (c *Client) get(ctx context.Context, objectID string, accessorType string, accessorID string) (api.Response, error) {
5959
if objectID == "" {
60-
return api.Response{}, ErrorPermissionGet{ErrorMissingObjectID}
60+
return api.Response{}, ErrorPermissions{Wrapped: ErrorMissingObjectID, Operation: GET}
6161
}
6262

6363
path, err := url.JoinPath(endpointConfigPath, objectID, permissionResourcePath, accessorType, accessorID)
6464
if err != nil {
65-
return api.Response{}, ErrorPermissionGet{err}
65+
return api.Response{}, ErrorPermissions{Wrapped: err, Operation: GET}
6666
}
6767

6868
resp, err := c.client.GET(ctx, path, rest.RequestOptions{CustomShouldRetryFunc: rest.RetryIfTooManyRequests})
6969

7070
if err != nil {
71-
return api.Response{}, ErrorPermissionGet{err}
71+
return api.Response{}, ErrorPermissions{Wrapped: err, Operation: GET}
7272
}
7373

7474
return api.NewResponseFromHTTPResponse(resp)
7575
}
7676

7777
func (c *Client) Create(ctx context.Context, objectID string, body []byte) (api.Response, error) {
7878
if objectID == "" {
79-
return api.Response{}, ErrorPermissionCreate{ErrorMissingObjectID}
79+
return api.Response{}, ErrorPermissions{Wrapped: ErrorMissingObjectID, Operation: POST}
8080
}
8181

8282
path, err := url.JoinPath(endpointConfigPath, objectID, permissionResourcePath)
8383
if err != nil {
84-
return api.Response{}, ErrorPermissionCreate{err}
84+
return api.Response{}, ErrorPermissions{Wrapped: err, Operation: POST}
8585
}
8686

8787
resp, err := c.client.POST(ctx, path, bytes.NewReader(body), rest.RequestOptions{CustomShouldRetryFunc: rest.RetryIfTooManyRequests})
8888
if err != nil {
89-
return api.Response{}, ErrorPermissionCreate{err}
89+
return api.Response{}, ErrorPermissions{Wrapped: err, Operation: POST}
9090
}
9191

9292
return api.NewResponseFromHTTPResponse(resp)
@@ -98,30 +98,30 @@ func (c *Client) UpdateAllUsersAccessor(ctx context.Context, objectID string, bo
9898

9999
func (c *Client) UpdateAccessor(ctx context.Context, objectID string, accessorType string, accessorID string, body []byte) (api.Response, error) {
100100
if accessorType == "" {
101-
return api.Response{}, ErrorPermissionUpdate{ErrorMissingAccessorType}
101+
return api.Response{}, ErrorPermissions{Wrapped: ErrorMissingAccessorType, Operation: PUT}
102102
}
103103

104104
if accessorID == "" {
105-
return api.Response{}, ErrorPermissionUpdate{ErrorMissingAccessorID}
105+
return api.Response{}, ErrorPermissions{Wrapped: ErrorMissingAccessorID, Operation: PUT}
106106
}
107107

108108
return c.update(ctx, objectID, accessorType, accessorID, body)
109109
}
110110

111111
func (c *Client) update(ctx context.Context, objectID string, accessorType string, accessorID string, body []byte) (api.Response, error) {
112112
if objectID == "" {
113-
return api.Response{}, ErrorPermissionUpdate{ErrorMissingObjectID}
113+
return api.Response{}, ErrorPermissions{Wrapped: ErrorMissingObjectID, Operation: PUT}
114114
}
115115

116116
path, err := url.JoinPath(endpointConfigPath, objectID, permissionResourcePath, accessorType, accessorID)
117117
if err != nil {
118-
return api.Response{}, ErrorPermissionUpdate{err}
118+
return api.Response{}, ErrorPermissions{Wrapped: err, Operation: PUT}
119119
}
120120

121121
httpResp, err := c.client.PUT(ctx, path, bytes.NewReader(body), rest.RequestOptions{CustomShouldRetryFunc: rest.RetryIfTooManyRequests})
122122

123123
if err != nil {
124-
return api.Response{}, ErrorPermissionUpdate{err}
124+
return api.Response{}, ErrorPermissions{Wrapped: err, Operation: PUT}
125125
}
126126

127127
return api.NewResponseFromHTTPResponse(httpResp)
@@ -133,30 +133,30 @@ func (c *Client) DeleteAllUsersAccessor(ctx context.Context, objectID string) (a
133133

134134
func (c *Client) DeleteAccessor(ctx context.Context, objectID string, accessorType string, accessorID string) (api.Response, error) {
135135
if accessorType == "" {
136-
return api.Response{}, ErrorPermissionDelete{ErrorMissingAccessorType}
136+
return api.Response{}, ErrorPermissions{Wrapped: ErrorMissingAccessorType, Operation: DELETE}
137137
}
138138

139139
if accessorID == "" {
140-
return api.Response{}, ErrorPermissionDelete{ErrorMissingAccessorID}
140+
return api.Response{}, ErrorPermissions{Wrapped: ErrorMissingAccessorID, Operation: DELETE}
141141
}
142142

143143
return c.delete(ctx, objectID, accessorType, accessorID)
144144
}
145145

146146
func (c *Client) delete(ctx context.Context, objectID string, accessorType string, accessorID string) (api.Response, error) {
147147
if objectID == "" {
148-
return api.Response{}, ErrorPermissionDelete{ErrorMissingObjectID}
148+
return api.Response{}, ErrorPermissions{Wrapped: ErrorMissingObjectID, Operation: DELETE}
149149
}
150150

151151
path, err := url.JoinPath(endpointConfigPath, objectID, permissionResourcePath, accessorType, accessorID)
152152
if err != nil {
153-
return api.Response{}, ErrorPermissionDelete{err}
153+
return api.Response{}, ErrorPermissions{Wrapped: err, Operation: DELETE}
154154
}
155155

156156
httpResp, err := c.client.DELETE(ctx, path, rest.RequestOptions{CustomShouldRetryFunc: rest.RetryIfTooManyRequests})
157157

158158
if err != nil {
159-
return api.Response{}, ErrorPermissionDelete{err}
159+
return api.Response{}, ErrorPermissions{Wrapped: err, Operation: DELETE}
160160
}
161161

162162
return api.NewResponseFromHTTPResponse(httpResp)

0 commit comments

Comments
 (0)