@@ -3,9 +3,13 @@ package hsdp
33import (
44 "context"
55 "fmt"
6+ "github.com/cenkalti/backoff/v4"
67 "github.com/hashicorp/terraform-plugin-sdk/v2/diag"
78 "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
9+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
810 "github.com/philips-software/go-hsdp-api/console"
11+ "net/http"
12+ "strings"
913 "time"
1014)
1115
@@ -34,21 +38,23 @@ func resourceMetricsAutoscaler() *schema.Resource {
3438 ForceNew : true ,
3539 },
3640 "max_instances" : {
37- Type : schema .TypeInt ,
38- Optional : true ,
39- Default : 10 ,
41+ Type : schema .TypeInt ,
42+ Optional : true ,
43+ Default : 10 ,
44+ ValidateFunc : validation .IntBetween (0 , 1000000000 ),
4045 },
4146 "min_instances" : {
42- Type : schema .TypeInt ,
43- Optional : true ,
44- Default : 1 ,
47+ Type : schema .TypeInt ,
48+ Optional : true ,
49+ Default : 1 ,
50+ ValidateFunc : validation .IntBetween (0 , 1000000000 ),
4551 },
4652 "enabled" : {
4753 Type : schema .TypeBool ,
4854 Optional : true ,
4955 Default : false ,
5056 },
51- "threshold_http_latency" : & schema. Schema {
57+ "threshold_http_latency" : {
5258 Type : schema .TypeSet ,
5359 Required : true ,
5460 MaxItems : 1 ,
@@ -59,19 +65,21 @@ func resourceMetricsAutoscaler() *schema.Resource {
5965 Required : true ,
6066 },
6167 "max" : {
62- Type : schema .TypeFloat ,
63- Optional : true ,
64- Default : 10000 ,
68+ Type : schema .TypeFloat ,
69+ Optional : true ,
70+ Default : 10000 ,
71+ ValidateFunc : validation .FloatBetween (1 , 1000000 ),
6572 },
6673 "min" : {
67- Type : schema .TypeFloat ,
68- Optional : true ,
69- Default : 10 ,
74+ Type : schema .TypeFloat ,
75+ Optional : true ,
76+ Default : 10 ,
77+ ValidateFunc : validation .FloatBetween (1 , 1000000 ),
7078 },
7179 },
7280 },
7381 },
74- "threshold_http_rate" : & schema. Schema {
82+ "threshold_http_rate" : {
7583 Type : schema .TypeSet ,
7684 Required : true ,
7785 MaxItems : 1 ,
@@ -82,19 +90,21 @@ func resourceMetricsAutoscaler() *schema.Resource {
8290 Required : true ,
8391 },
8492 "max" : {
85- Type : schema .TypeFloat ,
86- Optional : true ,
87- Default : 6000000 ,
93+ Type : schema .TypeFloat ,
94+ Optional : true ,
95+ Default : 6000000 ,
96+ ValidateFunc : validation .FloatBetween (1 , 6000000 ),
8897 },
8998 "min" : {
90- Type : schema .TypeFloat ,
91- Optional : true ,
92- Default : 300 ,
99+ Type : schema .TypeFloat ,
100+ Optional : true ,
101+ Default : 300 ,
102+ ValidateFunc : validation .FloatBetween (1 , 6000000 ),
93103 },
94104 },
95105 },
96106 },
97- "threshold_memory" : & schema. Schema {
107+ "threshold_memory" : {
98108 Type : schema .TypeSet ,
99109 Required : true ,
100110 MaxItems : 1 ,
@@ -105,19 +115,21 @@ func resourceMetricsAutoscaler() *schema.Resource {
105115 Required : true ,
106116 },
107117 "max" : {
108- Type : schema .TypeFloat ,
109- Optional : true ,
110- Default : 100 ,
118+ Type : schema .TypeFloat ,
119+ Optional : true ,
120+ Default : 100 ,
121+ ValidateFunc : validation .FloatBetween (0 , 100 ),
111122 },
112123 "min" : {
113- Type : schema .TypeFloat ,
114- Optional : true ,
115- Default : 20 ,
124+ Type : schema .TypeFloat ,
125+ Optional : true ,
126+ Default : 20 ,
127+ ValidateFunc : validation .FloatBetween (0 , 100 ),
116128 },
117129 },
118130 },
119131 },
120- "threshold_cpu" : & schema. Schema {
132+ "threshold_cpu" : {
121133 Type : schema .TypeSet ,
122134 Required : true ,
123135 MaxItems : 1 ,
@@ -129,14 +141,16 @@ func resourceMetricsAutoscaler() *schema.Resource {
129141 Default : false ,
130142 },
131143 "max" : {
132- Type : schema .TypeFloat ,
133- Optional : true ,
134- Default : 100 ,
144+ Type : schema .TypeFloat ,
145+ Optional : true ,
146+ Default : 100 ,
147+ ValidateFunc : validation .FloatBetween (0 , 100 ),
135148 },
136149 "min" : {
137- Type : schema .TypeFloat ,
138- Optional : true ,
139- Default : 5 ,
150+ Type : schema .TypeFloat ,
151+ Optional : true ,
152+ Default : 5 ,
153+ ValidateFunc : validation .FloatBetween (0 , 100 ),
140154 },
141155 },
142156 },
@@ -158,7 +172,7 @@ func resourceMetricsAutoscalerDelete(ctx context.Context, d *schema.ResourceData
158172 instanceID := d .Get ("metrics_instance_id" ).(string )
159173 app .Name = d .Get ("app_name" ).(string )
160174 app .Enabled = false
161- result , _ , err := client . Metrics . UpdateApplicationAutoscaler ( instanceID , app )
175+ result , err := updateWithRetry ( client , instanceID , app )
162176 if err != nil {
163177 return diag .FromErr (err )
164178 }
@@ -185,7 +199,7 @@ func resourceMetricsAutoscalerRead(ctx context.Context, d *schema.ResourceData,
185199 instanceID := d .Get ("metrics_instance_id" ).(string )
186200 name := d .Get ("app_name" ).(string )
187201
188- app , _ , err := client . Metrics . GetApplicationAutoscaler ( instanceID , name )
202+ app , err := getWitRetry ( client , instanceID , name )
189203 if err != nil {
190204 return diag .FromErr (err )
191205 }
@@ -244,7 +258,7 @@ func resourceMetricsAutoscalerCreate(ctx context.Context, d *schema.ResourceData
244258 }
245259 }
246260 }
247- created , _ , err := client . Metrics . UpdateApplicationAutoscaler ( instanceID , app )
261+ created , err := updateWithRetry ( client , instanceID , app )
248262 if err != nil {
249263 return diag .FromErr (err )
250264 }
@@ -254,3 +268,41 @@ func resourceMetricsAutoscalerCreate(ctx context.Context, d *schema.ResourceData
254268 d .SetId (instanceID + created .Name )
255269 return diags
256270}
271+
272+ func updateWithRetry (client * console.Client , instanceID string , app console.Application ) (* console.Application , error ) {
273+ var created * console.Application
274+ operation := func () error {
275+ var err error
276+ var resp * console.Response
277+ created , resp , err = client .Metrics .UpdateApplicationAutoscaler (instanceID , app )
278+ return checkForIntermittentErrors (resp , err )
279+ }
280+ err := backoff .Retry (operation , backoff .NewExponentialBackOff ())
281+ return created , err
282+ }
283+
284+ func getWitRetry (client * console.Client , instanceID string , name string ) (* console.Application , error ) {
285+ var app * console.Application
286+ operation := func () error {
287+ var err error
288+ var resp * console.Response
289+ app , resp , err = client .Metrics .GetApplicationAutoscaler (instanceID , name )
290+ return checkForIntermittentErrors (resp , err )
291+ }
292+ err := backoff .Retry (operation , backoff .NewExponentialBackOff ())
293+ return app , err
294+ }
295+
296+ func checkForIntermittentErrors (resp * console.Response , err error ) error {
297+ if resp == nil || resp .StatusCode > 500 {
298+ return err
299+ }
300+ if resp .StatusCode == http .StatusInternalServerError {
301+ return backoff .Permanent (fmt .Errorf ("console: %s %w" , resp .Error .Message , err ))
302+ }
303+ if resp .StatusCode == http .StatusBadRequest &&
304+ strings .Contains (resp .Error .Message , "invalid character" ) {
305+ return ErrIntermittent
306+ }
307+ return backoff .Permanent (err )
308+ }
0 commit comments