@@ -19,6 +19,7 @@ import (
1919 "github.com/stretchr/testify/require"
2020 "github.com/weaveworks/common/httpgrpc"
2121 "github.com/weaveworks/common/user"
22+ "go.uber.org/atomic"
2223 "google.golang.org/grpc"
2324 "google.golang.org/grpc/health/grpc_health_v1"
2425
@@ -37,6 +38,7 @@ func TestDistributor_DistributeRequest(t *testing.T) {
3738 name string
3839 numAM , numHappyAM int
3940 replicationFactor int
41+ failedReqCount int
4042 isRead bool
4143 isDelete bool
4244 expStatusCode int
@@ -196,6 +198,25 @@ func TestDistributor_DistributeRequest(t *testing.T) {
196198 expStatusCode : http .StatusOK ,
197199 expectedTotalCalls : 1 ,
198200 route : "/status" ,
201+ }, {
202+ name : "Read /status should try all alert managers on error" ,
203+ numAM : 3 ,
204+ numHappyAM : 0 ,
205+ replicationFactor : 3 ,
206+ isRead : true ,
207+ expStatusCode : http .StatusInternalServerError ,
208+ expectedTotalCalls : 3 ,
209+ route : "/status" ,
210+ }, {
211+ name : "Read /status is sent to 3 AM when 2 are not happy" ,
212+ numAM : 3 ,
213+ numHappyAM : 3 ,
214+ failedReqCount : 2 ,
215+ replicationFactor : 3 ,
216+ isRead : true ,
217+ expStatusCode : http .StatusOK ,
218+ expectedTotalCalls : 3 ,
219+ route : "/status" ,
199220 }, {
200221 name : "Write /status not supported" ,
201222 numAM : 5 ,
@@ -229,7 +250,7 @@ func TestDistributor_DistributeRequest(t *testing.T) {
229250 for _ , c := range cases {
230251 t .Run (c .name , func (t * testing.T ) {
231252 route := "/alertmanager/api/v1" + c .route
232- d , ams , cleanup := prepare (t , c .numAM , c .numHappyAM , c .replicationFactor , c .responseBody )
253+ d , ams , cleanup := prepare (t , c .numAM , c .numHappyAM , c .failedReqCount , c . replicationFactor , c .responseBody )
233254 t .Cleanup (cleanup )
234255
235256 ctx := user .InjectOrgID (context .Background (), "1" )
@@ -306,20 +327,21 @@ func TestDistributor_IsPathSupported(t *testing.T) {
306327
307328 for path , isSupported := range supported {
308329 t .Run (path , func (t * testing.T ) {
309- d , _ , cleanup := prepare (t , 1 , 1 , 1 , []byte {})
330+ d , _ , cleanup := prepare (t , 1 , 1 , 0 , 1 , []byte {})
310331 t .Cleanup (cleanup )
311332 require .Equal (t , isSupported , d .IsPathSupported (path ))
312333 })
313334 }
314335}
315336
316- func prepare (t * testing.T , numAM , numHappyAM , replicationFactor int , responseBody []byte ) (* Distributor , []* mockAlertmanager , func ()) {
337+ func prepare (t * testing.T , numAM , numHappyAM , totalFailedReq , replicationFactor int , responseBody []byte ) (* Distributor , []* mockAlertmanager , func ()) {
317338 ams := []* mockAlertmanager {}
339+ failedReqCount := atomic .NewInt32 (int32 (totalFailedReq ))
318340 for i := 0 ; i < numHappyAM ; i ++ {
319- ams = append (ams , newMockAlertmanager (i , true , responseBody ))
341+ ams = append (ams , newMockAlertmanager (i , true , failedReqCount , responseBody ))
320342 }
321343 for i := numHappyAM ; i < numAM ; i ++ {
322- ams = append (ams , newMockAlertmanager (i , false , responseBody ))
344+ ams = append (ams , newMockAlertmanager (i , false , failedReqCount , responseBody ))
323345 }
324346
325347 // Use a real ring with a mock KV store to test ring RF logic.
@@ -383,14 +405,16 @@ type mockAlertmanager struct {
383405 myAddr string
384406 happy bool
385407 responseBody []byte
408+ failedReqCount * atomic.Int32
386409}
387410
388- func newMockAlertmanager (idx int , happy bool , responseBody []byte ) * mockAlertmanager {
411+ func newMockAlertmanager (idx int , happy bool , failedReqCount * atomic. Int32 , responseBody []byte ) * mockAlertmanager {
389412 return & mockAlertmanager {
390413 receivedRequests : make (map [string ]map [int ]int ),
391414 myAddr : fmt .Sprintf ("127.0.0.1:%05d" , 10000 + idx ),
392415 happy : happy ,
393416 responseBody : responseBody ,
417+ failedReqCount : failedReqCount ,
394418 }
395419}
396420
@@ -409,7 +433,8 @@ func (am *mockAlertmanager) HandleRequest(_ context.Context, in *httpgrpc.HTTPRe
409433 am .receivedRequests [path ] = m
410434 }
411435
412- if am .happy {
436+ failedCountLocal := am .failedReqCount .Dec ()
437+ if am .happy && failedCountLocal < 0 {
413438 m [http .StatusOK ]++
414439 return & httpgrpc.HTTPResponse {
415440 Code : http .StatusOK ,
0 commit comments