@@ -19,7 +19,6 @@ package filters
1919import  (
2020	"net/http" 
2121	"net/http/httptest" 
22- 	"strings" 
2322	"testing" 
2423	"time" 
2524
@@ -32,137 +31,90 @@ import (
3231	clocktesting "k8s.io/utils/clock/testing" 
3332)
3433
35- func  TestWithShutdownLateAnnotation (t  * testing.T ) {
34+ func  TestWithShutdownResponseHeader (t  * testing.T ) {
3635	var  (
37- 		shutdownDelayDuration      =  100  *  time .Second 
38- 		signaledAt                 =  time .Now ()
39- 		elapsedAtWithingThreshold  =  signaledAt .Add (shutdownDelayDuration  -  21 * time .Second )
40- 		elapsedAtBeyondThreshold   =  signaledAt .Add (shutdownDelayDuration  -  19 * time .Second )
36+ 		signaledAt  =  time .Now ()
37+ 		elapsedAt   =  signaledAt .Add (20  *  time .Second )
4138	)
4239
4340	tests  :=  []struct  {
44- 		name                     string 
45- 		shutdownInitiated        func () lifecycleEvent 
46- 		delayDuration            time.Duration 
47- 		user                     authenticationuser.Info 
48- 		clock                    func () utilsclock.PassiveClock 
49- 		url                      string 
50- 		remoteAddr               string 
51- 		handlerInvoked           int 
52- 		statusCodeExpected       int 
53- 		annotationShouldContain  string 
41+ 		name                string 
42+ 		optIn               bool 
43+ 		shutdownInitiated   func () lifecycleEvent 
44+ 		delayDuration       time.Duration 
45+ 		clock               func () utilsclock.PassiveClock 
46+ 		handlerInvoked      int 
47+ 		statusCodeExpected  int 
48+ 		responseHeader      string 
5449	}{
5550		{
56- 			name : "shutdown is  not initiated " ,
51+ 			name : "client did  not opt in " ,
5752			shutdownInitiated : func () lifecycleEvent  {
58- 				return  fakeLifecycleSignal { ch :  make ( chan   struct {})} 
53+ 				return  nil 
5954			},
6055			handlerInvoked :     1 ,
6156			statusCodeExpected : http .StatusOK ,
6257		},
6358		{
64- 			name : "shutdown initiated, health probes are not annotated" ,
59+ 			name :  "client opted in, shutdown not initiated" ,
60+ 			optIn : true ,
6561			shutdownInitiated : func () lifecycleEvent  {
66- 				return  fakeLifecycleSignal {ch : newClosedChannel ( )}
62+ 				return  fakeLifecycleSignal {ch : make ( chan   struct {} )}
6763			},
68- 			url :                "/readyz?verbos=1" ,
69- 			user :               & authenticationuser.DefaultInfo {Name : authenticationuser .Anonymous },
64+ 			delayDuration :      10  *  time .Second ,
7065			handlerInvoked :     1 ,
7166			statusCodeExpected : http .StatusOK ,
72- 		},
73- 		// use cases where the request will be annotated 
74- 		{
75- 			name : "shutdown initiated, no user in request context" ,
76- 			shutdownInitiated : func () lifecycleEvent  {
77- 				return  fakeLifecycleSignal {ch : newClosedChannel (), at : & signaledAt }
78- 			},
79- 			handlerInvoked :          1 ,
80- 			statusCodeExpected :      http .StatusOK ,
81- 			annotationShouldContain : "self= loopback=" ,
82- 		},
83- 		{
84- 			name : "shutdown initiated, self=true" ,
85- 			shutdownInitiated : func () lifecycleEvent  {
86- 				return  fakeLifecycleSignal {ch : newClosedChannel (), at : & signaledAt }
87- 			},
88- 			user :                    & authenticationuser.DefaultInfo {Name : authenticationuser .APIServerUser },
89- 			handlerInvoked :          1 ,
90- 			statusCodeExpected :      http .StatusOK ,
91- 			annotationShouldContain : "self=true" ,
92- 		},
93- 		{
94- 			name : "shutdown initiated, self=false" ,
95- 			shutdownInitiated : func () lifecycleEvent  {
96- 				return  fakeLifecycleSignal {ch : newClosedChannel (), at : & signaledAt }
97- 			},
98- 			user :                    & authenticationuser.DefaultInfo {Name : authenticationuser .Anonymous },
99- 			handlerInvoked :          1 ,
100- 			statusCodeExpected :      http .StatusOK ,
101- 			annotationShouldContain : "self=false" ,
67+ 			responseHeader :     "shutdown=false shutdown-delay-duration=10s elapsed=0s host=foo" ,
10268		},
10369		{
104- 			name : "shutdown initiated, loopback=true" ,
70+ 			name :          "client opted in, shutdown initiated, signaled at is nil" ,
71+ 			optIn :         true ,
72+ 			delayDuration : 10  *  time .Second ,
10573			shutdownInitiated : func () lifecycleEvent  {
106- 				return  fakeLifecycleSignal {ch : newClosedChannel (), at : & signaledAt }
74+ 				return  fakeLifecycleSignal {ch : newClosedChannel (), at : nil }
10775			},
108- 			user :                    & authenticationuser.DefaultInfo {Name : authenticationuser .Anonymous },
109- 			remoteAddr :              "127.0.0.1:80" ,
110- 			handlerInvoked :          1 ,
111- 			statusCodeExpected :      http .StatusOK ,
112- 			annotationShouldContain : "loopback=true" ,
113- 		},
114- 		{
115- 			name : "shutdown initiated, loopback=false" ,
116- 			shutdownInitiated : func () lifecycleEvent  {
117- 				return  fakeLifecycleSignal {ch : newClosedChannel (), at : & signaledAt }
118- 			},
119- 			user :                    & authenticationuser.DefaultInfo {Name : authenticationuser .Anonymous },
120- 			remoteAddr :              "www.foo.bar:80" ,
121- 			handlerInvoked :          1 ,
122- 			statusCodeExpected :      http .StatusOK ,
123- 			annotationShouldContain : "loopback=false" ,
76+ 			handlerInvoked :     1 ,
77+ 			statusCodeExpected : http .StatusOK ,
78+ 			responseHeader :     "shutdown=true shutdown-delay-duration=10s elapsed=0s host=foo" ,
12479		},
12580		{
126- 			name : "shutdown initiated, shutdown delay duration is zero" ,
81+ 			name :          "client opted in, shutdown initiated, signaled at is nil" ,
82+ 			optIn :         true ,
83+ 			delayDuration : 10  *  time .Second ,
12784			shutdownInitiated : func () lifecycleEvent  {
128- 				return  fakeLifecycleSignal {ch : newClosedChannel (), at : & signaledAt }
129- 			},
130- 			delayDuration : time .Duration (0 ),
131- 			clock : func () utilsclock.PassiveClock  {
132- 				return  clocktesting .NewFakeClock (elapsedAtWithingThreshold )
85+ 				return  fakeLifecycleSignal {ch : newClosedChannel (), at : nil }
13386			},
134- 			user :                    & authenticationuser.DefaultInfo {Name : authenticationuser .Anonymous },
135- 			handlerInvoked :          1 ,
136- 			statusCodeExpected :      http .StatusOK ,
137- 			annotationShouldContain : "elapsed=1m19s threshold= late=true" ,
87+ 			handlerInvoked :     1 ,
88+ 			statusCodeExpected : http .StatusOK ,
89+ 			responseHeader :     "shutdown=true shutdown-delay-duration=10s elapsed=0s host=foo" ,
13890		},
13991		{
140- 			name : "shutdown initiated, within 80%" ,
92+ 			name :          "client opted in, shutdown delay duration is zero" ,
93+ 			optIn :         true ,
94+ 			delayDuration : 0 ,
14195			shutdownInitiated : func () lifecycleEvent  {
14296				return  fakeLifecycleSignal {ch : newClosedChannel (), at : & signaledAt }
14397			},
144- 			delayDuration : shutdownDelayDuration ,
14598			clock : func () utilsclock.PassiveClock  {
146- 				return  clocktesting .NewFakeClock (elapsedAtWithingThreshold )
99+ 				return  clocktesting .NewFakeClock (elapsedAt )
147100			},
148- 			user :                    & authenticationuser.DefaultInfo {Name : authenticationuser .Anonymous },
149- 			handlerInvoked :          1 ,
150- 			statusCodeExpected :      http .StatusOK ,
151- 			annotationShouldContain : "elapsed=1m19s threshold=79.00% late=false self=false loopback=false" ,
101+ 			handlerInvoked :     1 ,
102+ 			statusCodeExpected : http .StatusOK ,
103+ 			responseHeader :     "shutdown=true shutdown-delay-duration=0s elapsed=20s host=foo" ,
152104		},
153105		{
154- 			name : "shutdown initiated, outside 80%" ,
106+ 			name :          "client opted in, shutdown initiated, signaled at is valied" ,
107+ 			optIn :         true ,
108+ 			delayDuration : 10  *  time .Second ,
155109			shutdownInitiated : func () lifecycleEvent  {
156110				return  fakeLifecycleSignal {ch : newClosedChannel (), at : & signaledAt }
157111			},
158- 			delayDuration : shutdownDelayDuration ,
159112			clock : func () utilsclock.PassiveClock  {
160- 				return  clocktesting .NewFakeClock (elapsedAtBeyondThreshold )
113+ 				return  clocktesting .NewFakeClock (elapsedAt )
161114			},
162- 			user :                    & authenticationuser.DefaultInfo {Name : authenticationuser .Anonymous },
163- 			handlerInvoked :          1 ,
164- 			statusCodeExpected :      http .StatusOK ,
165- 			annotationShouldContain : "elapsed=1m21s threshold=81.00% late=true self=false loopback=false" ,
115+ 			handlerInvoked :     1 ,
116+ 			statusCodeExpected : http .StatusOK ,
117+ 			responseHeader :     "shutdown=true shutdown-delay-duration=10s elapsed=20s host=foo" ,
166118		},
167119	}
168120
@@ -179,33 +131,14 @@ func TestWithShutdownLateAnnotation(t *testing.T) {
179131			if  test .clock  !=  nil  {
180132				clock  =  test .clock ()
181133			}
182- 			target  :=  withShutdownLateAnnotation (handler , event , test .delayDuration , exemptIfHealthProbe , clock )
134+ 			target  :=  withShutdownResponseHeader (handler , event , test .delayDuration , "foo" , clock )
183135
184- 			url  :=  "/api/v1/namespaces" 
185- 			if  test .url  !=  ""  {
186- 				url  =  test .url 
187- 			}
188- 			req , err  :=  http .NewRequest (http .MethodGet , url , nil )
136+ 			req , err  :=  http .NewRequest (http .MethodGet , "/api/v1/namespaces" , nil )
189137			if  err  !=  nil  {
190138				t .Fatalf ("failed to create new http request - %v" , err )
191139			}
192- 			if  test .remoteAddr  !=  ""  {
193- 				req .RemoteAddr  =  test .remoteAddr 
194- 			}
195- 
196- 			ctx  :=  req .Context ()
197- 			if  test .user  !=  nil  {
198- 				ctx  =  apirequest .WithUser (ctx , test .user )
199- 			}
200- 			ctx  =  audit .WithAuditContext (ctx )
201- 			req  =  req .WithContext (ctx )
202- 
203- 			ac  :=  audit .AuditContextFrom (req .Context ())
204- 			if  ac  ==  nil  {
205- 				t .Fatalf ("expected audit context inside the request context" )
206- 			}
207- 			ac .Event  =  & auditinternal.Event {
208- 				Level : auditinternal .LevelMetadata ,
140+ 			if  test .optIn  {
141+ 				req .Header .Set ("X-Openshift-If-Disruption" , "true" )
209142			}
210143
211144			w  :=  httptest .NewRecorder ()
@@ -219,19 +152,16 @@ func TestWithShutdownLateAnnotation(t *testing.T) {
219152				t .Errorf ("expected status code: %d, but got: %d" , test .statusCodeExpected , w .Result ().StatusCode )
220153			}
221154
222- 			key  :=  "apiserver.k8s.io/shutdown " 
155+ 			key  :=  "X-OpenShift-Disruption " 
223156			switch  {
224- 			case  len (test .annotationShouldContain ) ==  0 :
225- 				if  valueGot ,  ok   :=  ac . Event . Annotations [ key ];  ok  {
226- 					t .Errorf ("did not expect annotation  to be added, but got: %s" , valueGot )
157+ 			case  len (test .responseHeader ) ==  0 :
158+ 				if  valueGot   :=  w . Header (). Get ( key );  len ( valueGot )  >   0  {
159+ 					t .Errorf ("did not expect header  to be added to the response , but got: %s" , valueGot )
227160				}
228161			default :
229- 				if  valueGot ,  ok   :=  ac . Event . Annotations [ key ];  ! ok   ||  ! strings . Contains ( valueGot ,  test .annotationShouldContain )  {
162+ 				if  valueGot   :=  w . Header (). Get ( key );  len ( valueGot )  ==   0   ||  test .responseHeader   !=   valueGot  {
230163					t .Logf ("got: %s" , valueGot )
231- 					t .Errorf ("expected annotation to match, diff: %s" , cmp .Diff (test .annotationShouldContain , valueGot ))
232- 				}
233- 				if  header  :=  w .Header ().Get ("X-OpenShift-Shutdown" ); ! strings .Contains (header , test .annotationShouldContain ) {
234- 					t .Errorf ("expected response header to match, diff: %s" , cmp .Diff (test .annotationShouldContain , header ))
164+ 					t .Errorf ("expected response header to match, diff: %s" , cmp .Diff (test .responseHeader , valueGot ))
235165				}
236166			}
237167		})
0 commit comments