Skip to content

Commit d47154f

Browse files
committed
add suggestion for timeout error
1 parent 7ded72d commit d47154f

File tree

3 files changed

+118
-40
lines changed

3 files changed

+118
-40
lines changed

oci/crud_helpers.go

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ func LoadBalancerWaitForWorkRequest(client *oci_load_balancer.LoadBalancerClient
210210

211211
func CreateDBSystemResource(d *schema.ResourceData, sync ResourceCreator) error {
212212
if e := sync.Create(); e != nil {
213-
return handleServiceError(sync, e)
213+
return handleError(sync, e)
214214
}
215215

216216
// ID is required for state refresh
@@ -257,7 +257,7 @@ func CreateResource(d *schema.ResourceData, sync ResourceCreator) error {
257257
}
258258

259259
if e := sync.Create(); e != nil {
260-
return handleServiceError(sync, e)
260+
return handleError(sync, e)
261261
}
262262

263263
// ID is required for state refresh
@@ -295,7 +295,7 @@ func ReadResource(sync ResourceReader) error {
295295
if e := sync.Get(); e != nil {
296296
log.Printf("ERROR IN GET: %v\n", e.Error())
297297
handleMissingResourceError(sync, &e)
298-
return handleServiceError(sync, e)
298+
return handleError(sync, e)
299299
}
300300

301301
if e := sync.SetData(); e != nil {
@@ -326,7 +326,7 @@ func UpdateResource(d *schema.ResourceData, sync ResourceUpdater) error {
326326
d.Partial(true)
327327
if e := sync.Update(); e != nil {
328328

329-
return handleServiceError(sync, e)
329+
return handleError(sync, e)
330330
}
331331
d.Partial(false)
332332

@@ -358,7 +358,7 @@ func DeleteResource(d *schema.ResourceData, sync ResourceDeleter) error {
358358

359359
if e := sync.Delete(); e != nil {
360360
handleMissingResourceError(sync, &e)
361-
return handleServiceError(sync, e)
361+
return handleError(sync, e)
362362
}
363363

364364
if stateful, ok := sync.(StatefullyDeletedResource); ok {
@@ -440,11 +440,9 @@ func waitForStateRefresh(sync StatefulResource, timeout time.Duration, operation
440440

441441
if _, e := stateConf.WaitForState(); e != nil {
442442
handleMissingResourceError(sync, &e)
443-
if e != nil && strings.Contains(e.Error(), "unexpected state") {
444-
resourceId := sync.ID()
445-
if resourceId != "" {
446-
e = fmt.Errorf("Resource reached unexpected lifecycle state %s during %s, whereas expected lifecycle state is %s. \n Affected resource OCID: %s", sync.State(), operationName, target[0], resourceId)
447-
}
443+
if _, ok := e.(*resource.UnexpectedStateError); ok {
444+
e = fmt.Errorf("During %s, Terraform expected the resource to reach state: %s, but the service reported unexpected state: %s.", operationName, target[0], sync.State())
445+
return handleError(sync, e)
448446
}
449447

450448
if _, ok := e.(*resource.TimeoutError); ok {

oci/errors.go

Lines changed: 82 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -12,45 +12,93 @@ import (
1212
oci_common "github.com/oracle/oci-go-sdk/v35/common"
1313
)
1414

15+
type errorTypeEnum string
16+
17+
const (
18+
ServiceError errorTypeEnum = "ServiceError"
19+
TimeoutError errorTypeEnum = "TimeoutError"
20+
UnexpectedStateError errorTypeEnum = "UnexpectedStateError"
21+
WorkRequestError errorTypeEnum = "WorkRequestError"
22+
)
23+
1524
type customError struct {
16-
isServiceError bool
17-
ErrorCode int
18-
ErrorCodeName string
19-
Service string
20-
Message string
21-
OpcRequestID string
22-
Suggestion string
25+
TypeOfError errorTypeEnum
26+
ErrorCode int
27+
ErrorCodeName string
28+
Service string
29+
Message string
30+
OpcRequestID string
31+
ResourceOCID string
32+
Suggestion string
2333
}
2434

2535
// Create new error format for Terraform output
2636
func newCustomError(sync interface{}, err error) error {
2737
var tfError customError
38+
2839
// Service error
2940
if failure, isServiceError := oci_common.IsServiceError(err); isServiceError {
3041
tfError = customError{
31-
isServiceError: true,
32-
ErrorCode: failure.GetHTTPStatusCode(),
33-
ErrorCodeName: failure.GetCode(),
34-
Message: failure.GetMessage(),
35-
OpcRequestID: failure.GetOpcRequestID(),
36-
Service: getServiceName(sync),
42+
TypeOfError: ServiceError,
43+
ErrorCode: failure.GetHTTPStatusCode(),
44+
ErrorCodeName: failure.GetCode(),
45+
Message: failure.GetMessage(),
46+
OpcRequestID: failure.GetOpcRequestID(),
47+
Service: getServiceName(sync),
48+
}
49+
}
50+
51+
// Timeout error
52+
if strings.Contains(err.Error(), "timeout while waiting for state") {
53+
tfError = customError{
54+
TypeOfError: TimeoutError,
55+
ErrorCodeName: "Operation Timeout",
56+
Message: err.Error(),
57+
Service: getServiceName(sync),
58+
}
59+
// Unexpected state error
60+
} else if strings.Contains(err.Error(), "unexpected state") {
61+
tfError = customError{
62+
TypeOfError: UnexpectedStateError,
63+
ErrorCodeName: "Unexpected LifeCycle state",
64+
Message: err.Error(),
65+
Service: getServiceName(sync),
66+
ResourceOCID: getResourceOCID(sync),
3767
}
3868
} else {
3969
// Terraform error return as is
40-
tfError.isServiceError = false
4170
return err
4271
}
72+
4373
tfError.Suggestion = getSuggestionFromError(tfError)
4474
return tfError.Error()
4575
}
4676

4777
func (tfE customError) Error() error {
48-
return fmt.Errorf("%d-%s \n"+
49-
"Service: %s \n"+
50-
"Error Message: %s \n"+
51-
"OPC request ID: %s \n"+
52-
"Suggestion: %s\n",
53-
tfE.ErrorCode, tfE.ErrorCodeName, tfE.Service, tfE.Message, tfE.OpcRequestID, tfE.Suggestion)
78+
switch tfE.TypeOfError {
79+
case ServiceError:
80+
return fmt.Errorf("%d-%s \n"+
81+
"Service: %s \n"+
82+
"Error Message: %s \n"+
83+
"OPC request ID: %s \n"+
84+
"Suggestion: %s\n",
85+
tfE.ErrorCode, tfE.ErrorCodeName, tfE.Service, tfE.Message, tfE.OpcRequestID, tfE.Suggestion)
86+
case TimeoutError:
87+
return fmt.Errorf("%s \n"+
88+
"Service: %s \n"+
89+
"Error Message: %s \n"+
90+
"Suggestion: %s\n",
91+
tfE.ErrorCodeName, tfE.Service, tfE.Message, tfE.Suggestion)
92+
case UnexpectedStateError:
93+
return fmt.Errorf("%s \n"+
94+
"Service: %s \n"+
95+
"Error Message: %s \n"+
96+
"Resource OCID: %s \n"+
97+
"Suggestion: %s\n",
98+
tfE.ErrorCodeName, tfE.Service, tfE.Message, tfE.ResourceOCID, tfE.Suggestion)
99+
default:
100+
return fmt.Errorf(tfE.Message)
101+
}
54102
}
55103

56104
func handleMissingResourceError(sync ResourceVoider, err *error) {
@@ -75,9 +123,12 @@ func handleMissingResourceError(sync ResourceVoider, err *error) {
75123
}
76124
}
77125

78-
func handleServiceError(sync interface{}, err error) error {
79-
tfError := newCustomError(sync, err)
80-
return tfError
126+
func handleError(sync interface{}, err error) error {
127+
if err != nil {
128+
tfError := newCustomError(sync, err)
129+
return tfError
130+
}
131+
return err
81132
}
82133

83134
func getServiceName(sync interface{}) string {
@@ -87,3 +138,11 @@ func getServiceName(sync interface{}) string {
87138
}
88139
return ""
89140
}
141+
142+
// Use to get OCID from refresh state only
143+
func getResourceOCID(sync interface{}) string {
144+
if syn, ok := sync.(StatefulResource); ok {
145+
return syn.ID()
146+
}
147+
return ""
148+
}

oci/suggestions.go

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,19 @@ package oci
66
import "fmt"
77

88
func getSuggestionFromError(tfError customError) string {
9+
switch tfError.TypeOfError {
10+
case ServiceError:
11+
return getSuggestionForServiceError(tfError)
12+
case TimeoutError:
13+
return getSuggestionForTimeoutError()
14+
case UnexpectedStateError:
15+
return getSuggestionForUnexpectedState(tfError)
16+
default:
17+
return getSuggestionForDefault(tfError)
18+
}
19+
}
20+
21+
func getSuggestionForServiceError(tfError customError) string {
922
switch tfError.ErrorCode {
1023
case 400:
1124
return getSuggestionFor400(tfError)
@@ -25,33 +38,41 @@ func getSuggestionFromError(tfError customError) string {
2538
func getSuggestionFor400(tfError customError) string {
2639
switch tfError.ErrorCodeName {
2740
case "InvalidParameter":
28-
return fmt.Sprintf("Please update the parameter(s) in the Terraform config as per error message: %s", tfError.Message)
41+
return fmt.Sprintf("Please update the parameter(s) in the Terraform config as per error message %s", tfError.Message)
2942
case "LimitExceeded":
30-
return fmt.Sprintf("Request a service limit increase for this resource: %s", tfError.Service)
43+
return fmt.Sprintf("Request a service limit increase for this resource %s", tfError.Service)
3144
case "QuotaExceeded":
3245
return fmt.Sprintf("Contact your administrator to increase limit for your account or compartment for this service: %s", tfError.Service)
3346
default:
34-
return fmt.Sprintf(tfError.Message)
47+
return getSuggestionForDefault(tfError)
3548
}
3649
}
3750

3851
func getSuggestionFor404(tfError customError) string {
39-
return fmt.Sprintf("Either the resource has been deleted or service %s need policy to access this resource.", tfError.Service)
52+
return fmt.Sprintf("Either the resource has been deleted or service %s need policy to access this resource. Policy reference: https://docs.oracle.com/en-us/iaas/Content/Identity/Reference/policyreference.htm", tfError.Service)
4053
}
4154

4255
func getSuggestionFor409(tfError customError) string {
43-
return fmt.Sprintf("The resource is in a conflicted state. Please retry again or contact support for help with service %s", tfError.Service)
56+
return fmt.Sprintf("The resource is in a conflicted state. Please retry again or contact support for help with service: %s", tfError.Service)
4457
}
4558

4659
func getSuggestionFor429(tfError customError) string {
4760
return fmt.Sprintf("Please re-apply your Terraform config and/or increase the retry timeout using this document: https://docs.oracle.com/en-us/iaas/Content/API/SDKDocs/terraformtroubleshooting.htm#common_issues__automaticretries")
4861
}
4962

5063
func getSuggestionFor500(tfError customError) string {
51-
return fmt.Sprintf("The service for this resource encountered an error. Please contact support for help with service %s", tfError.Service)
64+
return fmt.Sprintf("The service for this resource encountered an error. Please contact support for help with service: %s", tfError.Service)
5265
}
5366

5467
func getSuggestionForDefault(tfError customError) string {
5568
// return error message for default
56-
return tfError.Message
69+
return fmt.Sprintf("Please retry or contact support for help with service: %s", tfError.Service)
70+
}
71+
72+
func getSuggestionForTimeoutError() string {
73+
return fmt.Sprintf("Try increasing the timeout by referring to this document: https://docs.oracle.com/en-us/iaas/Content/API/SDKDocs/terraformtroubleshooting.htm#common_issues__timeoutwhilewaiting")
74+
}
75+
76+
func getSuggestionForUnexpectedState(tfError customError) string {
77+
return fmt.Sprintf("Please retry or contact support for help with service: %s", tfError.Service)
5778
}

0 commit comments

Comments
 (0)