@@ -24,6 +24,37 @@ func (f *flushTransferer) TransferOut(ctx context.Context) error {
24
24
return f .lifecycler .ChangeState (ctx , ACTIVE )
25
25
}
26
26
27
+ func testLifecyclerConfig (ringConfig Config , id string ) LifecyclerConfig {
28
+ var lifecyclerConfig LifecyclerConfig
29
+ flagext .DefaultValues (& lifecyclerConfig )
30
+ lifecyclerConfig .Addr = "0.0.0.0"
31
+ lifecyclerConfig .Port = 1
32
+ lifecyclerConfig .RingConfig = ringConfig
33
+ lifecyclerConfig .NumTokens = 1
34
+ lifecyclerConfig .ClaimOnRollout = true
35
+ lifecyclerConfig .ID = id
36
+ lifecyclerConfig .FinalSleep = 0
37
+ return lifecyclerConfig
38
+ }
39
+
40
+ func checkDenormalised (d interface {}, id string ) bool {
41
+ desc , ok := d .(* Desc )
42
+ return ok &&
43
+ len (desc .Ingesters ) == 1 &&
44
+ desc .Ingesters [id ].State == ACTIVE &&
45
+ len (desc .Ingesters [id ].Tokens ) == 0 &&
46
+ len (desc .Tokens ) == 1
47
+ }
48
+
49
+ func checkNormalised (d interface {}, id string ) bool {
50
+ desc , ok := d .(* Desc )
51
+ return ok &&
52
+ len (desc .Ingesters ) == 1 &&
53
+ desc .Ingesters [id ].State == ACTIVE &&
54
+ len (desc .Ingesters [id ].Tokens ) == 1 &&
55
+ len (desc .Tokens ) == 0
56
+ }
57
+
27
58
func TestRingNormaliseMigration (t * testing.T ) {
28
59
var ringConfig Config
29
60
flagext .DefaultValues (& ringConfig )
@@ -35,15 +66,7 @@ func TestRingNormaliseMigration(t *testing.T) {
35
66
defer r .Stop ()
36
67
37
68
// Add an 'ingester' with denormalised tokens.
38
- var lifecyclerConfig1 LifecyclerConfig
39
- flagext .DefaultValues (& lifecyclerConfig1 )
40
- lifecyclerConfig1 .Addr = "0.0.0.0"
41
- lifecyclerConfig1 .Port = 1
42
- lifecyclerConfig1 .RingConfig = ringConfig
43
- lifecyclerConfig1 .NumTokens = 1
44
- lifecyclerConfig1 .ClaimOnRollout = true
45
- lifecyclerConfig1 .ID = "ing1"
46
- lifecyclerConfig1 .FinalSleep = 0
69
+ lifecyclerConfig1 := testLifecyclerConfig (ringConfig , "ing1" )
47
70
48
71
ft := & flushTransferer {}
49
72
l1 , err := NewLifecycler (lifecyclerConfig1 , ft , "ingester" )
@@ -53,23 +76,15 @@ func TestRingNormaliseMigration(t *testing.T) {
53
76
test .Poll (t , 1000 * time .Millisecond , true , func () interface {} {
54
77
d , err := r .KVClient .Get (context .Background (), ConsulKey )
55
78
require .NoError (t , err )
56
-
57
- desc , ok := d .(* Desc )
58
- return ok &&
59
- len (desc .Ingesters ) == 1 &&
60
- desc .Ingesters ["ing1" ].State == ACTIVE &&
61
- len (desc .Ingesters ["ing1" ].Tokens ) == 0 &&
62
- len (desc .Tokens ) == 1
79
+ return checkDenormalised (d , "ing1" )
63
80
})
64
81
65
82
token := l1 .tokens [0 ]
66
83
67
84
// Add a second ingester with normalised tokens.
68
- var lifecyclerConfig2 = lifecyclerConfig1
85
+ var lifecyclerConfig2 = testLifecyclerConfig ( ringConfig , "ing2" )
69
86
lifecyclerConfig2 .JoinAfter = 100 * time .Second
70
87
lifecyclerConfig2 .NormaliseTokens = true
71
- lifecyclerConfig2 .ID = "ing2"
72
- lifecyclerConfig1 .FinalSleep = 0
73
88
74
89
l2 , err := NewLifecycler (lifecyclerConfig2 , & flushTransferer {}, "ingester" )
75
90
require .NoError (t , err )
@@ -82,13 +97,55 @@ func TestRingNormaliseMigration(t *testing.T) {
82
97
test .Poll (t , 1000 * time .Millisecond , true , func () interface {} {
83
98
d , err := r .KVClient .Get (context .Background (), ConsulKey )
84
99
require .NoError (t , err )
100
+ return checkNormalised (d , "ing2" ) &&
101
+ d .(* Desc ).Ingesters ["ing2" ].Tokens [0 ] == token
102
+ })
103
+ }
104
+
105
+ type nopFlushTransferer struct {}
106
+
107
+ func (f * nopFlushTransferer ) StopIncomingRequests () {}
108
+ func (f * nopFlushTransferer ) Flush () {}
109
+ func (f * nopFlushTransferer ) TransferOut (ctx context.Context ) error {
110
+ panic ("should not be called" )
111
+ }
112
+
113
+ func TestRingRestart (t * testing.T ) {
114
+ var ringConfig Config
115
+ flagext .DefaultValues (& ringConfig )
116
+ codec := ProtoCodec {Factory : ProtoDescFactory }
117
+ ringConfig .KVStore .Mock = NewInMemoryKVClient (codec )
118
+
119
+ r , err := New (ringConfig , "ingester" )
120
+ require .NoError (t , err )
121
+ defer r .Stop ()
122
+
123
+ // Add an 'ingester' with normalised tokens.
124
+ lifecyclerConfig1 := testLifecyclerConfig (ringConfig , "ing1" )
125
+ lifecyclerConfig1 .NormaliseTokens = true
126
+ l1 , err := NewLifecycler (lifecyclerConfig1 , & nopFlushTransferer {}, "ingester" )
127
+ require .NoError (t , err )
128
+
129
+ // Check this ingester joined, is active, and has one token.
130
+ test .Poll (t , 1000 * time .Millisecond , true , func () interface {} {
131
+ d , err := r .KVClient .Get (context .Background (), ConsulKey )
132
+ require .NoError (t , err )
133
+ return checkNormalised (d , "ing1" )
134
+ })
85
135
86
- desc , ok := d .(* Desc )
87
- return ok &&
88
- len (desc .Ingesters ) == 1 &&
89
- desc .Ingesters ["ing2" ].State == ACTIVE &&
90
- len (desc .Ingesters ["ing2" ].Tokens ) == 1 &&
91
- desc .Ingesters ["ing2" ].Tokens [0 ] == token &&
92
- len (desc .Tokens ) == 0
136
+ token := l1 .tokens [0 ]
137
+
138
+ // Add a second ingester with the same settings, so it will think it has restarted
139
+ l2 , err := NewLifecycler (lifecyclerConfig1 , & nopFlushTransferer {}, "ingester" )
140
+ require .NoError (t , err )
141
+
142
+ // Check the new ingester picked up the same token
143
+ test .Poll (t , 1000 * time .Millisecond , true , func () interface {} {
144
+ d , err := r .KVClient .Get (context .Background (), ConsulKey )
145
+ require .NoError (t , err )
146
+ l2Tokens := l2 .getTokens ()
147
+ return checkNormalised (d , "ing1" ) &&
148
+ len (l2Tokens ) == 1 &&
149
+ l2Tokens [0 ] == token
93
150
})
94
151
}
0 commit comments