Skip to content

Commit cfb8657

Browse files
authored
Handle not found errors on resource Read and Delete (#247)
* Handle not found errors on resource Read and Delete * Fix status code logic * Guard against a nil status object inside a service error
1 parent 992c978 commit cfb8657

File tree

8 files changed

+188
-7
lines changed

8 files changed

+188
-7
lines changed

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ go 1.22.7
55
toolchain go1.23.2
66

77
require (
8+
github.com/google/uuid v1.6.0
89
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.2.0
910
github.com/hashicorp/terraform-plugin-docs v0.20.1
1011
github.com/hashicorp/terraform-plugin-framework v1.13.0
@@ -40,7 +41,6 @@ require (
4041
github.com/golang/mock v1.6.0 // indirect
4142
github.com/golang/protobuf v1.5.4 // indirect
4243
github.com/google/go-cmp v0.6.0 // indirect
43-
github.com/google/uuid v1.6.0 // indirect
4444
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect
4545
github.com/grpc-ecosystem/grpc-gateway/v2 v2.23.0 // indirect
4646
github.com/hashicorp/cli v1.1.6 // indirect

internal/client/errors.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package client
2+
3+
import (
4+
"go.temporal.io/api/serviceerror"
5+
"google.golang.org/grpc/codes"
6+
"google.golang.org/grpc/status"
7+
)
8+
9+
func StatusCode(err error) codes.Code {
10+
if err == nil {
11+
return codes.OK
12+
}
13+
14+
if serviceErr, ok := err.(serviceerror.ServiceError); ok {
15+
st := serviceErr.Status()
16+
if st != nil {
17+
return st.Code()
18+
}
19+
}
20+
21+
return status.Code(err)
22+
}

internal/provider/apikey_resource.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import (
55
"fmt"
66
"github.com/google/uuid"
77
"github.com/hashicorp/terraform-plugin-framework/resource/schema/booldefault"
8+
"github.com/hashicorp/terraform-plugin-log/tflog"
9+
"google.golang.org/grpc/codes"
810
"time"
911

1012
"github.com/hashicorp/terraform-plugin-framework-timeouts/resource/timeouts"
@@ -233,6 +235,16 @@ func (r *apiKeyResource) Read(ctx context.Context, req resource.ReadRequest, res
233235
KeyId: state.ID.ValueString(),
234236
})
235237
if err != nil {
238+
switch client.StatusCode(err) {
239+
case codes.NotFound:
240+
tflog.Warn(ctx, "API Key Resource not found, removing from state", map[string]interface{}{
241+
"id": state.ID.ValueString(),
242+
})
243+
244+
resp.State.RemoveResource(ctx)
245+
return
246+
}
247+
236248
resp.Diagnostics.AddError("Failed to get API key", err.Error())
237249
return
238250
}
@@ -340,6 +352,15 @@ func (r *apiKeyResource) Delete(ctx context.Context, req resource.DeleteRequest,
340352
KeyId: state.ID.ValueString(),
341353
})
342354
if err != nil {
355+
switch client.StatusCode(err) {
356+
case codes.NotFound:
357+
tflog.Warn(ctx, "API Key Resource not found, removing from state", map[string]interface{}{
358+
"id": state.ID.ValueString(),
359+
})
360+
361+
return
362+
}
363+
343364
resp.Diagnostics.AddError("Failed to get current API key status", err.Error())
344365
return
345366
}
@@ -353,6 +374,15 @@ func (r *apiKeyResource) Delete(ctx context.Context, req resource.DeleteRequest,
353374
AsyncOperationId: uuid.New().String(),
354375
})
355376
if err != nil {
377+
switch client.StatusCode(err) {
378+
case codes.NotFound:
379+
tflog.Warn(ctx, "API Key Resource not found, removing from state", map[string]interface{}{
380+
"id": state.ID.ValueString(),
381+
})
382+
383+
return
384+
}
385+
356386
resp.Diagnostics.AddError("Failed to delete API key", err.Error())
357387
return
358388
}

internal/provider/namespace_resource.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ import (
2727
"encoding/base64"
2828
"fmt"
2929
"github.com/google/uuid"
30+
"github.com/hashicorp/terraform-plugin-log/tflog"
31+
"google.golang.org/grpc/codes"
3032
"time"
3133

3234
"github.com/hashicorp/terraform-plugin-framework-validators/listvalidator"
@@ -384,6 +386,16 @@ func (r *namespaceResource) Read(ctx context.Context, req resource.ReadRequest,
384386
Namespace: state.ID.ValueString(),
385387
})
386388
if err != nil {
389+
switch client.StatusCode(err) {
390+
case codes.NotFound:
391+
tflog.Warn(ctx, "Namespace Resource not found, removing from state", map[string]interface{}{
392+
"id": state.ID.ValueString(),
393+
})
394+
395+
resp.State.RemoveResource(ctx)
396+
return
397+
}
398+
387399
resp.Diagnostics.AddError("Failed to get namespace", err.Error())
388400
return
389401
}
@@ -519,6 +531,15 @@ func (r *namespaceResource) Delete(ctx context.Context, req resource.DeleteReque
519531
Namespace: state.ID.ValueString(),
520532
})
521533
if err != nil {
534+
switch client.StatusCode(err) {
535+
case codes.NotFound:
536+
tflog.Warn(ctx, "Namespace Resource not found, removing from state", map[string]interface{}{
537+
"id": state.ID.ValueString(),
538+
})
539+
540+
return
541+
}
542+
522543
resp.Diagnostics.AddError("Failed to get current namespace status", err.Error())
523544
return
524545
}
@@ -530,6 +551,15 @@ func (r *namespaceResource) Delete(ctx context.Context, req resource.DeleteReque
530551
AsyncOperationId: uuid.New().String(),
531552
})
532553
if err != nil {
554+
switch client.StatusCode(err) {
555+
case codes.NotFound:
556+
tflog.Warn(ctx, "Namespace Resource not found, removing from state", map[string]interface{}{
557+
"id": state.ID.ValueString(),
558+
})
559+
560+
return
561+
}
562+
533563
resp.Diagnostics.AddError("Failed to delete namespace", err.Error())
534564
return
535565
}

internal/provider/namespace_search_attribute_resource.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import (
44
"context"
55
"fmt"
66
"github.com/google/uuid"
7+
"github.com/hashicorp/terraform-plugin-log/tflog"
8+
"google.golang.org/grpc/codes"
79
"strings"
810

911
"github.com/hashicorp/terraform-plugin-framework/diag"
@@ -186,6 +188,16 @@ func (r *namespaceSearchAttributeResource) Read(ctx context.Context, req resourc
186188
Namespace: state.NamespaceID.ValueString(),
187189
})
188190
if err != nil {
191+
switch client.StatusCode(err) {
192+
case codes.NotFound:
193+
tflog.Warn(ctx, "Namespace Search Attribute Resource not found, removing from state", map[string]interface{}{
194+
"id": state.ID.ValueString(),
195+
})
196+
197+
resp.State.RemoveResource(ctx)
198+
return
199+
}
200+
189201
resp.Diagnostics.AddError("Failed to get namespace", err.Error())
190202
return
191203
}

internal/provider/nexus_endpoint_resource.go

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@ import (
44
"context"
55
"fmt"
66
"github.com/google/uuid"
7-
87
"github.com/hashicorp/terraform-plugin-framework/attr"
98
"github.com/hashicorp/terraform-plugin-framework/diag"
109
"github.com/hashicorp/terraform-plugin-framework/path"
1110
"github.com/hashicorp/terraform-plugin-framework/types/basetypes"
11+
"github.com/hashicorp/terraform-plugin-log/tflog"
12+
"google.golang.org/grpc/codes"
1213

1314
"github.com/hashicorp/terraform-plugin-framework-timeouts/resource/timeouts"
1415
"github.com/hashicorp/terraform-plugin-framework/resource"
@@ -213,6 +214,16 @@ func (r *nexusEndpointResource) Read(ctx context.Context, req resource.ReadReque
213214
EndpointId: state.ID.ValueString(),
214215
})
215216
if err != nil {
217+
switch client.StatusCode(err) {
218+
case codes.NotFound:
219+
tflog.Warn(ctx, "Nexus Endpoint Resource not found, removing from state", map[string]interface{}{
220+
"id": state.ID.ValueString(),
221+
})
222+
223+
resp.State.RemoveResource(ctx)
224+
return
225+
}
226+
216227
resp.Diagnostics.AddError("Failed to get Nexus endpoint", err.Error())
217228
return
218229
}
@@ -314,6 +325,15 @@ func (r *nexusEndpointResource) Delete(ctx context.Context, req resource.DeleteR
314325
EndpointId: state.ID.ValueString(),
315326
})
316327
if err != nil {
328+
switch client.StatusCode(err) {
329+
case codes.NotFound:
330+
tflog.Warn(ctx, "Nexus Endpoint Resource not found, removing from state", map[string]interface{}{
331+
"id": state.ID.ValueString(),
332+
})
333+
334+
return
335+
}
336+
317337
resp.Diagnostics.AddError("Failed to get current Nexus endpoint status", err.Error())
318338
return
319339
}
@@ -327,6 +347,15 @@ func (r *nexusEndpointResource) Delete(ctx context.Context, req resource.DeleteR
327347
AsyncOperationId: uuid.New().String(),
328348
})
329349
if err != nil {
350+
switch client.StatusCode(err) {
351+
case codes.NotFound:
352+
tflog.Warn(ctx, "Nexus Endpoint Resource not found, removing from state", map[string]interface{}{
353+
"id": state.ID.ValueString(),
354+
})
355+
356+
return
357+
}
358+
330359
resp.Diagnostics.AddError("Failed to delete Nexus endpoint", err.Error())
331360
return
332361
}

internal/provider/service_account_resource.go

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,8 @@ import (
44
"context"
55
"fmt"
66
"github.com/google/uuid"
7-
"github.com/hashicorp/terraform-plugin-framework-validators/setvalidator"
8-
97
"github.com/hashicorp/terraform-plugin-framework-timeouts/resource/timeouts"
8+
"github.com/hashicorp/terraform-plugin-framework-validators/setvalidator"
109
"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
1110
"github.com/hashicorp/terraform-plugin-framework/attr"
1211
"github.com/hashicorp/terraform-plugin-framework/diag"
@@ -18,6 +17,8 @@ import (
1817
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
1918
"github.com/hashicorp/terraform-plugin-framework/types"
2019
"github.com/hashicorp/terraform-plugin-framework/types/basetypes"
20+
"github.com/hashicorp/terraform-plugin-log/tflog"
21+
"google.golang.org/grpc/codes"
2122

2223
"github.com/temporalio/terraform-provider-temporalcloud/internal/client"
2324
"github.com/temporalio/terraform-provider-temporalcloud/internal/provider/enums"
@@ -226,6 +227,16 @@ func (r *serviceAccountResource) Read(ctx context.Context, req resource.ReadRequ
226227
ServiceAccountId: state.ID.ValueString(),
227228
})
228229
if err != nil {
230+
switch client.StatusCode(err) {
231+
case codes.NotFound:
232+
tflog.Warn(ctx, "Service Account Resource not found, removing from state", map[string]interface{}{
233+
"id": state.ID.ValueString(),
234+
})
235+
236+
resp.State.RemoveResource(ctx)
237+
return
238+
}
239+
229240
resp.Diagnostics.AddError("Failed to get Service Account", err.Error())
230241
return
231242
}
@@ -319,6 +330,15 @@ func (r *serviceAccountResource) Delete(ctx context.Context, req resource.Delete
319330
ServiceAccountId: state.ID.ValueString(),
320331
})
321332
if err != nil {
333+
switch client.StatusCode(err) {
334+
case codes.NotFound:
335+
tflog.Warn(ctx, "Service Account Resource not found, removing from state", map[string]interface{}{
336+
"id": state.ID.ValueString(),
337+
})
338+
339+
return
340+
}
341+
322342
resp.Diagnostics.AddError("Failed to get current Service Account status", err.Error())
323343
return
324344
}
@@ -332,6 +352,15 @@ func (r *serviceAccountResource) Delete(ctx context.Context, req resource.Delete
332352
AsyncOperationId: uuid.New().String(),
333353
})
334354
if err != nil {
355+
switch client.StatusCode(err) {
356+
case codes.NotFound:
357+
tflog.Warn(ctx, "Service Account Resource not found, removing from state", map[string]interface{}{
358+
"id": state.ID.ValueString(),
359+
})
360+
361+
return
362+
}
363+
335364
resp.Diagnostics.AddError("Failed to delete Service Account", err.Error())
336365
return
337366
}

internal/provider/user_resource.go

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,8 @@ import (
44
"context"
55
"fmt"
66
"github.com/google/uuid"
7-
"github.com/hashicorp/terraform-plugin-framework-validators/setvalidator"
8-
"github.com/temporalio/terraform-provider-temporalcloud/internal/validation"
9-
107
"github.com/hashicorp/terraform-plugin-framework-timeouts/resource/timeouts"
8+
"github.com/hashicorp/terraform-plugin-framework-validators/setvalidator"
119
"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
1210
"github.com/hashicorp/terraform-plugin-framework/attr"
1311
"github.com/hashicorp/terraform-plugin-framework/diag"
@@ -19,11 +17,14 @@ import (
1917
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
2018
"github.com/hashicorp/terraform-plugin-framework/types"
2119
"github.com/hashicorp/terraform-plugin-framework/types/basetypes"
20+
"github.com/hashicorp/terraform-plugin-log/tflog"
2221
"github.com/temporalio/terraform-provider-temporalcloud/internal/client"
2322
"github.com/temporalio/terraform-provider-temporalcloud/internal/provider/enums"
2423
internaltypes "github.com/temporalio/terraform-provider-temporalcloud/internal/types"
24+
"github.com/temporalio/terraform-provider-temporalcloud/internal/validation"
2525
cloudservicev1 "go.temporal.io/api/cloud/cloudservice/v1"
2626
identityv1 "go.temporal.io/api/cloud/identity/v1"
27+
"google.golang.org/grpc/codes"
2728
)
2829

2930
type (
@@ -228,6 +229,16 @@ func (r *userResource) Read(ctx context.Context, req resource.ReadRequest, resp
228229
UserId: state.ID.ValueString(),
229230
})
230231
if err != nil {
232+
switch client.StatusCode(err) {
233+
case codes.NotFound:
234+
tflog.Warn(ctx, "User Resource not found, removing from state", map[string]interface{}{
235+
"id": state.ID.ValueString(),
236+
})
237+
238+
resp.State.RemoveResource(ctx)
239+
return
240+
}
241+
231242
resp.Diagnostics.AddError("Failed to get user", err.Error())
232243
return
233244
}
@@ -323,6 +334,15 @@ func (r *userResource) Delete(ctx context.Context, req resource.DeleteRequest, r
323334
UserId: state.ID.ValueString(),
324335
})
325336
if err != nil {
337+
switch client.StatusCode(err) {
338+
case codes.NotFound:
339+
tflog.Warn(ctx, "User Resource not found, removing from state", map[string]interface{}{
340+
"id": state.ID.ValueString(),
341+
})
342+
343+
return
344+
}
345+
326346
resp.Diagnostics.AddError("Failed to get current user status", err.Error())
327347
return
328348
}
@@ -336,6 +356,15 @@ func (r *userResource) Delete(ctx context.Context, req resource.DeleteRequest, r
336356
AsyncOperationId: uuid.New().String(),
337357
})
338358
if err != nil {
359+
switch client.StatusCode(err) {
360+
case codes.NotFound:
361+
tflog.Warn(ctx, "User Resource not found, removing from state", map[string]interface{}{
362+
"id": state.ID.ValueString(),
363+
})
364+
365+
return
366+
}
367+
339368
resp.Diagnostics.AddError("Failed to delete user", err.Error())
340369
return
341370
}

0 commit comments

Comments
 (0)