@@ -25,18 +25,69 @@ import (
25
25
"io/ioutil"
26
26
"net/http"
27
27
"testing"
28
+ "time"
28
29
29
30
"github.com/Azure/azure-sdk-for-go/services/network/mgmt/2019-06-01/network"
30
31
"github.com/Azure/go-autorest/autorest"
31
32
"github.com/Azure/go-autorest/autorest/to"
32
33
"github.com/golang/mock/gomock"
33
34
"github.com/stretchr/testify/assert"
34
35
36
+ "k8s.io/client-go/util/flowcontrol"
35
37
azclients "k8s.io/legacy-cloud-providers/azure/clients"
36
38
"k8s.io/legacy-cloud-providers/azure/clients/armclient"
37
39
"k8s.io/legacy-cloud-providers/azure/clients/armclient/mockarmclient"
40
+ "k8s.io/legacy-cloud-providers/azure/retry"
38
41
)
39
42
43
+ // 2065-01-24 05:20:00 +0000 UTC
44
+ func getFutureTime () time.Time {
45
+ return time .Unix (3000000000 , 0 )
46
+ }
47
+
48
+ func TestNew (t * testing.T ) {
49
+ config := & azclients.ClientConfig {
50
+ SubscriptionID : "sub" ,
51
+ ResourceManagerEndpoint : "endpoint" ,
52
+ Location : "eastus" ,
53
+ RateLimitConfig : & azclients.RateLimitConfig {
54
+ CloudProviderRateLimit : true ,
55
+ CloudProviderRateLimitQPS : 0.5 ,
56
+ CloudProviderRateLimitBucket : 1 ,
57
+ CloudProviderRateLimitQPSWrite : 0.5 ,
58
+ CloudProviderRateLimitBucketWrite : 1 ,
59
+ },
60
+ Backoff : & retry.Backoff {Steps : 1 },
61
+ }
62
+
63
+ routetableClient := New (config )
64
+ assert .Equal (t , "sub" , routetableClient .subscriptionID )
65
+ assert .NotEmpty (t , routetableClient .rateLimiterReader )
66
+ assert .NotEmpty (t , routetableClient .rateLimiterWriter )
67
+ }
68
+
69
+ func TestGet (t * testing.T ) {
70
+ ctrl := gomock .NewController (t )
71
+ defer ctrl .Finish ()
72
+
73
+ resourceID := "/subscriptions/subscriptionID/resourceGroups/rg/providers/Microsoft.Network/routeTables/rt1"
74
+ response := & http.Response {
75
+ StatusCode : http .StatusOK ,
76
+ Body : ioutil .NopCloser (bytes .NewReader ([]byte ("{}" ))),
77
+ }
78
+
79
+ armClient := mockarmclient .NewMockInterface (ctrl )
80
+ armClient .EXPECT ().GetResource (gomock .Any (), resourceID , "" ).Return (response , nil ).Times (1 )
81
+ armClient .EXPECT ().CloseResponse (gomock .Any (), gomock .Any ()).Times (1 )
82
+
83
+ routetableClient := getTestRouteTableClient (armClient )
84
+ expected := network.RouteTable {}
85
+ expected .Response = autorest.Response {Response : response }
86
+ result , rerr := routetableClient .Get (context .TODO (), "rg" , "rt1" , "" )
87
+ assert .Equal (t , expected , result )
88
+ assert .Nil (t , rerr )
89
+ }
90
+
40
91
func TestGetNotFound (t * testing.T ) {
41
92
ctrl := gomock .NewController (t )
42
93
defer ctrl .Finish ()
@@ -79,24 +130,166 @@ func TestGetInternalError(t *testing.T) {
79
130
assert .Equal (t , http .StatusInternalServerError , rerr .HTTPStatusCode )
80
131
}
81
132
133
+ func TestGetNeverRateLimiter (t * testing.T ) {
134
+ ctrl := gomock .NewController (t )
135
+ defer ctrl .Finish ()
136
+
137
+ rtGetErr := & retry.Error {
138
+ RawError : fmt .Errorf ("azure cloud provider rate limited(%s) for operation %q" , "read" , "RouteTableGet" ),
139
+ Retriable : true ,
140
+ }
141
+
142
+ armClient := mockarmclient .NewMockInterface (ctrl )
143
+
144
+ routetableClient := getTestRouteTableClientWithNeverRateLimiter (armClient )
145
+ expected := network.RouteTable {}
146
+ result , rerr := routetableClient .Get (context .TODO (), "rg" , "rt1" , "" )
147
+ assert .Equal (t , expected , result )
148
+ assert .Equal (t , rtGetErr , rerr )
149
+ }
150
+
151
+ func TestGetRetryAfterReader (t * testing.T ) {
152
+ ctrl := gomock .NewController (t )
153
+ defer ctrl .Finish ()
154
+
155
+ rtGetErr := & retry.Error {
156
+ RawError : fmt .Errorf ("azure cloud provider throttled for operation %s with reason %q" , "RouteTableGet" , "client throttled" ),
157
+ Retriable : true ,
158
+ RetryAfter : getFutureTime (),
159
+ }
160
+
161
+ armClient := mockarmclient .NewMockInterface (ctrl )
162
+
163
+ routetableClient := getTestRouteTableClientWithRetryAfterReader (armClient )
164
+ expected := network.RouteTable {}
165
+ result , rerr := routetableClient .Get (context .TODO (), "rg" , "rt1" , "" )
166
+ assert .Equal (t , expected , result )
167
+ assert .Equal (t , rtGetErr , rerr )
168
+ }
169
+
170
+ func TestGetThrottle (t * testing.T ) {
171
+ ctrl := gomock .NewController (t )
172
+ defer ctrl .Finish ()
173
+
174
+ resourceID := "/subscriptions/subscriptionID/resourceGroups/rg/providers/Microsoft.Network/routeTables/rt1"
175
+ response := & http.Response {
176
+ StatusCode : http .StatusTooManyRequests ,
177
+ Body : ioutil .NopCloser (bytes .NewReader ([]byte ("{}" ))),
178
+ }
179
+ throttleErr := & retry.Error {
180
+ HTTPStatusCode : http .StatusTooManyRequests ,
181
+ RawError : fmt .Errorf ("error" ),
182
+ Retriable : true ,
183
+ RetryAfter : time .Unix (100 , 0 ),
184
+ }
185
+ armClient := mockarmclient .NewMockInterface (ctrl )
186
+ armClient .EXPECT ().GetResource (gomock .Any (), resourceID , "" ).Return (response , throttleErr ).Times (1 )
187
+ armClient .EXPECT ().CloseResponse (gomock .Any (), gomock .Any ()).Times (1 )
188
+
189
+ routetableClient := getTestRouteTableClient (armClient )
190
+ result , rerr := routetableClient .Get (context .TODO (), "rg" , "rt1" , "" )
191
+ assert .Empty (t , result )
192
+ assert .Equal (t , throttleErr , rerr )
193
+ }
194
+
82
195
func TestCreateOrUpdate (t * testing.T ) {
83
196
ctrl := gomock .NewController (t )
84
197
defer ctrl .Finish ()
85
198
86
- lb := getTestRouteTable ("rt1" )
199
+ rt1 := getTestRouteTable ("rt1" )
87
200
armClient := mockarmclient .NewMockInterface (ctrl )
88
201
response := & http.Response {
89
202
StatusCode : http .StatusOK ,
90
203
Body : ioutil .NopCloser (bytes .NewReader ([]byte ("" ))),
91
204
}
92
- armClient .EXPECT ().PutResourceWithDecorators (gomock .Any (), to .String (lb .ID ), lb , gomock .Any ()).Return (response , nil ).Times (1 )
205
+ armClient .EXPECT ().PutResourceWithDecorators (gomock .Any (), to .String (rt1 .ID ), rt1 , gomock .Any ()).Return (response , nil ).Times (1 )
93
206
armClient .EXPECT ().CloseResponse (gomock .Any (), gomock .Any ()).Times (1 )
94
207
95
208
rtClient := getTestRouteTableClient (armClient )
96
- rerr := rtClient .CreateOrUpdate (context .TODO (), "rg" , "rt1" , lb , "" )
209
+ rerr := rtClient .CreateOrUpdate (context .TODO (), "rg" , "rt1" , rt1 , "* " )
97
210
assert .Nil (t , rerr )
98
211
}
99
212
213
+ func TestCreateOrUpdateWithNeverRateLimiter (t * testing.T ) {
214
+ ctrl := gomock .NewController (t )
215
+ defer ctrl .Finish ()
216
+
217
+ rcCreateOrUpdatetErr := & retry.Error {
218
+ RawError : fmt .Errorf ("azure cloud provider rate limited(%s) for operation %q" , "write" , "RouteTableCreateOrUpdate" ),
219
+ Retriable : true ,
220
+ }
221
+
222
+ rt1 := getTestRouteTable ("rt1" )
223
+ armClient := mockarmclient .NewMockInterface (ctrl )
224
+
225
+ routetableClient := getTestRouteTableClientWithNeverRateLimiter (armClient )
226
+ rerr := routetableClient .CreateOrUpdate (context .TODO (), "rg" , "rt1" , rt1 , "" )
227
+ assert .Equal (t , rcCreateOrUpdatetErr , rerr )
228
+ }
229
+
230
+ func TestCreateOrUpdateRetryAfterReader (t * testing.T ) {
231
+ ctrl := gomock .NewController (t )
232
+ defer ctrl .Finish ()
233
+
234
+ rcCreateOrUpdateErr := & retry.Error {
235
+ RawError : fmt .Errorf ("azure cloud provider throttled for operation %s with reason %q" , "RouteTableCreateOrUpdate" , "client throttled" ),
236
+ Retriable : true ,
237
+ RetryAfter : getFutureTime (),
238
+ }
239
+
240
+ rt1 := getTestRouteTable ("rt1" )
241
+ armClient := mockarmclient .NewMockInterface (ctrl )
242
+
243
+ routetableClient := getTestRouteTableClientWithRetryAfterReader (armClient )
244
+ rerr := routetableClient .CreateOrUpdate (context .TODO (), "rg" , "rt1" , rt1 , "" )
245
+ assert .NotNil (t , rerr )
246
+ assert .Equal (t , rcCreateOrUpdateErr , rerr )
247
+ }
248
+
249
+ func TestCreateOrUpdateThrottle (t * testing.T ) {
250
+ ctrl := gomock .NewController (t )
251
+ defer ctrl .Finish ()
252
+
253
+ response := & http.Response {
254
+ StatusCode : http .StatusTooManyRequests ,
255
+ Body : ioutil .NopCloser (bytes .NewReader ([]byte ("{}" ))),
256
+ }
257
+ throttleErr := & retry.Error {
258
+ HTTPStatusCode : http .StatusTooManyRequests ,
259
+ RawError : fmt .Errorf ("error" ),
260
+ Retriable : true ,
261
+ RetryAfter : time .Unix (100 , 0 ),
262
+ }
263
+
264
+ rt1 := getTestRouteTable ("rt1" )
265
+ armClient := mockarmclient .NewMockInterface (ctrl )
266
+ armClient .EXPECT ().PutResourceWithDecorators (gomock .Any (), to .String (rt1 .ID ), rt1 , gomock .Any ()).Return (response , throttleErr ).Times (1 )
267
+ armClient .EXPECT ().CloseResponse (gomock .Any (), gomock .Any ()).Times (1 )
268
+
269
+ routetableClient := getTestRouteTableClient (armClient )
270
+ rerr := routetableClient .CreateOrUpdate (context .TODO (), "rg" , "rt1" , rt1 , "" )
271
+ assert .Equal (t , throttleErr , rerr )
272
+ }
273
+
274
+ func TestCreateOrUpdateWithCreateOrUpdateResponderError (t * testing.T ) {
275
+ ctrl := gomock .NewController (t )
276
+ defer ctrl .Finish ()
277
+
278
+ rt1 := getTestRouteTable ("rt1" )
279
+ armClient := mockarmclient .NewMockInterface (ctrl )
280
+ response := & http.Response {
281
+ StatusCode : http .StatusNotFound ,
282
+ Body : ioutil .NopCloser (bytes .NewReader ([]byte ("" ))),
283
+ }
284
+
285
+ armClient .EXPECT ().PutResourceWithDecorators (gomock .Any (), to .String (rt1 .ID ), rt1 , gomock .Any ()).Return (response , nil ).Times (1 )
286
+ armClient .EXPECT ().CloseResponse (gomock .Any (), gomock .Any ()).Times (1 )
287
+
288
+ routetableClient := getTestRouteTableClient (armClient )
289
+ rerr := routetableClient .CreateOrUpdate (context .TODO (), "rg" , "rt1" , rt1 , "" )
290
+ assert .NotNil (t , rerr )
291
+ }
292
+
100
293
func getTestRouteTable (name string ) network.RouteTable {
101
294
return network.RouteTable {
102
295
ID : to .StringPtr (fmt .Sprintf ("/subscriptions/subscriptionID/resourceGroups/rg/providers/Microsoft.Network/routeTables/%s" , name )),
@@ -114,3 +307,27 @@ func getTestRouteTableClient(armClient armclient.Interface) *Client {
114
307
rateLimiterWriter : rateLimiterWriter ,
115
308
}
116
309
}
310
+
311
+ func getTestRouteTableClientWithNeverRateLimiter (armClient armclient.Interface ) * Client {
312
+ rateLimiterReader := flowcontrol .NewFakeNeverRateLimiter ()
313
+ rateLimiterWriter := flowcontrol .NewFakeNeverRateLimiter ()
314
+ return & Client {
315
+ armClient : armClient ,
316
+ subscriptionID : "subscriptionID" ,
317
+ rateLimiterReader : rateLimiterReader ,
318
+ rateLimiterWriter : rateLimiterWriter ,
319
+ }
320
+ }
321
+
322
+ func getTestRouteTableClientWithRetryAfterReader (armClient armclient.Interface ) * Client {
323
+ rateLimiterReader := flowcontrol .NewFakeAlwaysRateLimiter ()
324
+ rateLimiterWriter := flowcontrol .NewFakeAlwaysRateLimiter ()
325
+ return & Client {
326
+ armClient : armClient ,
327
+ subscriptionID : "subscriptionID" ,
328
+ rateLimiterReader : rateLimiterReader ,
329
+ rateLimiterWriter : rateLimiterWriter ,
330
+ RetryAfterReader : getFutureTime (),
331
+ RetryAfterWriter : getFutureTime (),
332
+ }
333
+ }
0 commit comments