@@ -27,7 +27,6 @@ import (
27
27
28
28
"github.com/prometheus/common/expfmt"
29
29
"github.com/prometheus/common/model"
30
- "github.com/stretchr/testify/require"
31
30
32
31
flowcontrolv1alpha1 "k8s.io/api/flowcontrol/v1alpha1"
33
32
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -43,9 +42,10 @@ import (
43
42
)
44
43
45
44
const (
46
- dispatchedRequestCountMetricsName = "apiserver_flowcontrol_dispatched_requests_total"
47
- dispatchedRequestCountMetricsLabelPriorityLevel = "priorityLevel"
48
- timeout = time .Second * 10
45
+ sharedConcurrencyMetricsName = "apiserver_flowcontrol_request_concurrency_limit"
46
+ dispatchedRequestCountMetricsName = "apiserver_flowcontrol_dispatched_requests_total"
47
+ labelPriorityLevel = "priorityLevel"
48
+ timeout = time .Second * 10
49
49
)
50
50
51
51
func setup (t testing.TB ) (* httptest.Server , * rest.Config , framework.CloseFunc ) {
@@ -57,8 +57,8 @@ func setup(t testing.TB) (*httptest.Server, *rest.Config, framework.CloseFunc) {
57
57
Group : "flowcontrol.apiserver.k8s.io" ,
58
58
Version : "v1alpha1" ,
59
59
})
60
- masterConfig .GenericConfig .MaxRequestsInFlight = 5
61
- masterConfig .GenericConfig .MaxMutatingRequestsInFlight = 5
60
+ masterConfig .GenericConfig .MaxRequestsInFlight = 1
61
+ masterConfig .GenericConfig .MaxMutatingRequestsInFlight = 1
62
62
masterConfig .GenericConfig .OpenAPIConfig = framework .DefaultOpenAPIConfig ()
63
63
masterConfig .ExtraConfig .APIResourceConfigSource = resourceConfig
64
64
_ , s , closeFn := framework .RunAMaster (masterConfig )
@@ -81,33 +81,59 @@ func TestPriorityLevelIsolation(t *testing.T) {
81
81
82
82
priorityLevelNoxu1 , _ , err := createPriorityLevelAndBindingFlowSchemaForUser (
83
83
loopbackClient , "noxu1" , concurrencyShares , queueLength )
84
- require .NoError (t , err )
84
+ if err != nil {
85
+ t .Error (err )
86
+ }
85
87
priorityLevelNoxu2 , _ , err := createPriorityLevelAndBindingFlowSchemaForUser (
86
88
loopbackClient , "noxu2" , concurrencyShares , queueLength )
87
- require .NoError (t , err )
89
+ if err != nil {
90
+ t .Error (err )
91
+ }
92
+
93
+ sharedConcurrency , err := getSharedConcurrencyOfPriorityLevel (loopbackClient )
94
+ if err != nil {
95
+ t .Error (err )
96
+ }
97
+
98
+ if 1 != sharedConcurrency [priorityLevelNoxu1 .Name ] {
99
+ t .Errorf ("unexpected shared concurrency %v instead of %v" , sharedConcurrency [priorityLevelNoxu1 .Name ], 1 )
100
+ }
101
+ if 1 != sharedConcurrency [priorityLevelNoxu2 .Name ] {
102
+ t .Errorf ("unexpected shared concurrency %v instead of %v" , sharedConcurrency [priorityLevelNoxu2 .Name ], 1 )
103
+ }
88
104
89
105
stopCh := make (chan struct {})
90
106
defer close (stopCh )
107
+
91
108
// "elephant"
92
109
streamRequests (concurrencyShares + queueLength , func () {
93
110
_ , err := noxu1Client .CoreV1 ().Namespaces ().List (context .Background (), metav1.ListOptions {})
94
- require .NoError (t , err )
111
+ if err != nil {
112
+ t .Error (err )
113
+ }
95
114
}, stopCh )
96
115
// "mouse"
97
- streamRequests (1 , func () {
116
+ streamRequests (3 , func () {
98
117
_ , err := noxu2Client .CoreV1 ().Namespaces ().List (context .Background (), metav1.ListOptions {})
99
- require .NoError (t , err )
118
+ if err != nil {
119
+ t .Error (err )
120
+ }
100
121
}, stopCh )
101
122
102
123
time .Sleep (time .Second * 10 ) // running in background for a while
103
124
104
125
reqCounts , err := getRequestCountOfPriorityLevel (loopbackClient )
126
+ if err != nil {
127
+ t .Error (err )
128
+ }
105
129
106
130
noxu1RequestCount := reqCounts [priorityLevelNoxu1 .Name ]
107
131
noxu2RequestCount := reqCounts [priorityLevelNoxu2 .Name ]
108
132
109
- if (noxu1RequestCount / 2 ) > noxu2RequestCount {
110
- t .Errorf ("total requests made by noxu2 should at least half of noxu1: (%d:%d)" , noxu1RequestCount , noxu2RequestCount )
133
+ // Theoretically, the actual expected value of request counts upon the two priority-level should be
134
+ // the equal. We're deliberately lax to make flakes super rare.
135
+ if (noxu1RequestCount / 2 ) > noxu2RequestCount || (noxu2RequestCount / 2 ) > noxu1RequestCount {
136
+ t .Errorf ("imbalanced requests made by noxu1/2: (%d:%d)" , noxu1RequestCount , noxu2RequestCount )
111
137
}
112
138
}
113
139
@@ -123,12 +149,51 @@ func getClientFor(loopbackConfig *rest.Config, username string) clientset.Interf
123
149
return clientset .NewForConfigOrDie (config )
124
150
}
125
151
126
- func getRequestCountOfPriorityLevel (c clientset.Interface ) (map [ string ] int , error ) {
152
+ func getMetrics (c clientset.Interface ) (string , error ) {
127
153
resp , err := c .CoreV1 ().
128
154
RESTClient ().
129
155
Get ().
130
156
RequestURI ("/metrics" ).
131
157
DoRaw (context .Background ())
158
+ if err != nil {
159
+ return "" , err
160
+ }
161
+ return string (resp ), err
162
+ }
163
+
164
+ func getSharedConcurrencyOfPriorityLevel (c clientset.Interface ) (map [string ]int , error ) {
165
+ resp , err := getMetrics (c )
166
+ if err != nil {
167
+ return nil , err
168
+ }
169
+
170
+ dec := expfmt .NewDecoder (strings .NewReader (string (resp )), expfmt .FmtText )
171
+ decoder := expfmt.SampleDecoder {
172
+ Dec : dec ,
173
+ Opts : & expfmt.DecodeOptions {},
174
+ }
175
+
176
+ concurrency := make (map [string ]int )
177
+ for {
178
+ var v model.Vector
179
+ if err := decoder .Decode (& v ); err != nil {
180
+ if err == io .EOF {
181
+ // Expected loop termination condition.
182
+ return concurrency , nil
183
+ }
184
+ return nil , fmt .Errorf ("failed decoding metrics: %v" , err )
185
+ }
186
+ for _ , metric := range v {
187
+ switch name := string (metric .Metric [model .MetricNameLabel ]); name {
188
+ case sharedConcurrencyMetricsName :
189
+ concurrency [string (metric .Metric [labelPriorityLevel ])] = int (metric .Value )
190
+ }
191
+ }
192
+ }
193
+ }
194
+
195
+ func getRequestCountOfPriorityLevel (c clientset.Interface ) (map [string ]int , error ) {
196
+ resp , err := getMetrics (c )
132
197
if err != nil {
133
198
return nil , err
134
199
}
@@ -152,7 +217,7 @@ func getRequestCountOfPriorityLevel(c clientset.Interface) (map[string]int, erro
152
217
for _ , metric := range v {
153
218
switch name := string (metric .Metric [model .MetricNameLabel ]); name {
154
219
case dispatchedRequestCountMetricsName :
155
- reqCounts [string (metric .Metric [dispatchedRequestCountMetricsLabelPriorityLevel ])] = int (metric .Value )
220
+ reqCounts [string (metric .Metric [labelPriorityLevel ])] = int (metric .Value )
156
221
}
157
222
}
158
223
}
0 commit comments