1
16
17 package apiserver
18
19 import (
20 "strings"
21 "testing"
22
23 v1 "k8s.io/api/core/v1"
24 apierrors "k8s.io/apimachinery/pkg/api/errors"
25 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
26 "k8s.io/apimachinery/pkg/types"
27 "k8s.io/kubernetes/test/integration/framework"
28 "k8s.io/kubernetes/test/utils/ktesting"
29 )
30
31
32 func TestMaxResourceSize(t *testing.T) {
33 tCtx := ktesting.Init(t)
34 clientSet, _, tearDownFn := framework.StartTestServer(tCtx, t, framework.TestServerSetup{})
35 defer tearDownFn()
36
37 hugeData := []byte(strings.Repeat("x", 3*1024*1024+1))
38
39 rest := clientSet.Discovery().RESTClient()
40
41 c := clientSet.CoreV1().RESTClient()
42 t.Run("Create should limit the request body size", func(t *testing.T) {
43 err := c.Post().AbsPath("/api/v1/namespaces/default/pods").
44 Body(hugeData).Do(tCtx).Error()
45 if err == nil {
46 t.Fatalf("unexpected no error")
47 }
48 if !apierrors.IsRequestEntityTooLargeError(err) {
49 t.Errorf("expected requested entity too large err, got %v", err)
50
51 }
52 })
53
54
55 secret := &v1.Secret{
56 ObjectMeta: metav1.ObjectMeta{
57 Name: "test",
58 },
59 }
60 _, err := clientSet.CoreV1().Secrets("default").Create(tCtx, secret, metav1.CreateOptions{})
61 if err != nil {
62 t.Fatal(err)
63 }
64
65 t.Run("Update should limit the request body size", func(t *testing.T) {
66 err = c.Put().AbsPath("/api/v1/namespaces/default/secrets/test").
67 Body(hugeData).Do(tCtx).Error()
68 if err == nil {
69 t.Fatalf("unexpected no error")
70 }
71 if !apierrors.IsRequestEntityTooLargeError(err) {
72 t.Errorf("expected requested entity too large err, got %v", err)
73
74 }
75 })
76 t.Run("Patch should limit the request body size", func(t *testing.T) {
77 err = c.Patch(types.JSONPatchType).AbsPath("/api/v1/namespaces/default/secrets/test").
78 Body(hugeData).Do(tCtx).Error()
79 if err == nil {
80 t.Fatalf("unexpected no error")
81 }
82 if !apierrors.IsRequestEntityTooLargeError(err) {
83 t.Errorf("expected requested entity too large err, got %v", err)
84
85 }
86 })
87 t.Run("JSONPatchType should handle a patch just under the max limit", func(t *testing.T) {
88 if testing.Short() {
89 t.Skip("skipping expensive test")
90 }
91 patchBody := []byte(`[{"op":"add","path":"/foo","value":` + strings.Repeat("[", 3*1024*1024/2-100) + strings.Repeat("]", 3*1024*1024/2-100) + `}]`)
92 err = rest.Patch(types.JSONPatchType).AbsPath("/api/v1/namespaces/default/secrets/test").
93 Body(patchBody).Do(tCtx).Error()
94 if err != nil && !apierrors.IsBadRequest(err) {
95 t.Errorf("expected success or bad request err, got %v", err)
96 }
97 })
98 t.Run("JSONPatchType should handle a valid patch just under the max limit", func(t *testing.T) {
99 if testing.Short() {
100 t.Skip("skipping expensive test")
101 }
102 patchBody := []byte(`[{"op":"add","path":"/foo","value":0` + strings.Repeat(" ", 3*1024*1024-100) + `}]`)
103 err = rest.Patch(types.JSONPatchType).AbsPath("/api/v1/namespaces/default/secrets/test").
104 Body(patchBody).Do(tCtx).Error()
105 if err != nil {
106 t.Errorf("unexpected error: %v", err)
107 }
108 })
109 t.Run("MergePatchType should handle a patch just under the max limit", func(t *testing.T) {
110 if testing.Short() {
111 t.Skip("skipping expensive test")
112 }
113 patchBody := []byte(`{"value":` + strings.Repeat("[", 3*1024*1024/2-100) + strings.Repeat("]", 3*1024*1024/2-100) + `}`)
114 err = rest.Patch(types.MergePatchType).AbsPath("/api/v1/namespaces/default/secrets/test").
115 Body(patchBody).Do(tCtx).Error()
116 if err != nil && !apierrors.IsBadRequest(err) {
117 t.Errorf("expected success or bad request err, got %v", err)
118 }
119 })
120 t.Run("MergePatchType should handle a valid patch just under the max limit", func(t *testing.T) {
121 if testing.Short() {
122 t.Skip("skipping expensive test")
123 }
124 patchBody := []byte(`{"value":0` + strings.Repeat(" ", 3*1024*1024-100) + `}`)
125 err = rest.Patch(types.MergePatchType).AbsPath("/api/v1/namespaces/default/secrets/test").
126 Body(patchBody).Do(tCtx).Error()
127 if err != nil {
128 t.Errorf("unexpected error: %v", err)
129 }
130 })
131 t.Run("StrategicMergePatchType should handle a patch just under the max limit", func(t *testing.T) {
132 if testing.Short() {
133 t.Skip("skipping expensive test")
134 }
135 patchBody := []byte(`{"value":` + strings.Repeat("[", 3*1024*1024/2-100) + strings.Repeat("]", 3*1024*1024/2-100) + `}`)
136 err = rest.Patch(types.StrategicMergePatchType).AbsPath("/api/v1/namespaces/default/secrets/test").
137 Body(patchBody).Do(tCtx).Error()
138 if err != nil && !apierrors.IsBadRequest(err) {
139 t.Errorf("expected success or bad request err, got %v", err)
140 }
141 })
142 t.Run("StrategicMergePatchType should handle a valid patch just under the max limit", func(t *testing.T) {
143 if testing.Short() {
144 t.Skip("skipping expensive test")
145 }
146 patchBody := []byte(`{"value":0` + strings.Repeat(" ", 3*1024*1024-100) + `}`)
147 err = rest.Patch(types.StrategicMergePatchType).AbsPath("/api/v1/namespaces/default/secrets/test").
148 Body(patchBody).Do(tCtx).Error()
149 if err != nil {
150 t.Errorf("unexpected error: %v", err)
151 }
152 })
153 t.Run("ApplyPatchType should handle a patch just under the max limit", func(t *testing.T) {
154 if testing.Short() {
155 t.Skip("skipping expensive test")
156 }
157 patchBody := []byte(`{"value":` + strings.Repeat("[", 3*1024*1024/2-100) + strings.Repeat("]", 3*1024*1024/2-100) + `}`)
158 err = rest.Patch(types.ApplyPatchType).Param("fieldManager", "test").AbsPath("/api/v1/namespaces/default/secrets/test").
159 Body(patchBody).Do(tCtx).Error()
160 if err != nil && !apierrors.IsBadRequest(err) {
161 t.Errorf("expected success or bad request err, got %#v", err)
162 }
163 })
164 t.Run("ApplyPatchType should handle a valid patch just under the max limit", func(t *testing.T) {
165 if testing.Short() {
166 t.Skip("skipping expensive test")
167 }
168 patchBody := []byte(`{"apiVersion":"v1","kind":"Secret"` + strings.Repeat(" ", 3*1024*1024-100) + `}`)
169 err = rest.Patch(types.ApplyPatchType).Param("fieldManager", "test").AbsPath("/api/v1/namespaces/default/secrets/test").
170 Body(patchBody).Do(tCtx).Error()
171 if err != nil {
172 t.Errorf("unexpected error: %v", err)
173 }
174 })
175 t.Run("Delete should limit the request body size", func(t *testing.T) {
176 err = c.Delete().AbsPath("/api/v1/namespaces/default/secrets/test").
177 Body(hugeData).Do(tCtx).Error()
178 if err == nil {
179 t.Fatalf("unexpected no error")
180 }
181 if !apierrors.IsRequestEntityTooLargeError(err) {
182 t.Errorf("expected requested entity too large err, got %v", err)
183
184 }
185 })
186
187
188 t.Run("create should limit yaml parsing", func(t *testing.T) {
189 yamlBody := []byte(`
190 apiVersion: v1
191 kind: ConfigMap
192 metadata:
193 name: mytest
194 values: ` + strings.Repeat("[", 3*1024*1024))
195
196 _, err := rest.Post().
197 SetHeader("Accept", "application/yaml").
198 SetHeader("Content-Type", "application/yaml").
199 AbsPath("/api/v1/namespaces/default/configmaps").
200 Body(yamlBody).
201 DoRaw(tCtx)
202 if !apierrors.IsRequestEntityTooLargeError(err) {
203 t.Errorf("expected too large error, got %v", err)
204 }
205 })
206
207
208 t.Run("create should handle a yaml document just under the maximum size with correct nesting", func(t *testing.T) {
209 if testing.Short() {
210 t.Skip("skipping expensive test")
211 }
212 yamlBody := []byte(`
213 apiVersion: v1
214 kind: ConfigMap
215 metadata:
216 name: mytest
217 values: ` + strings.Repeat("[", 3*1024*1024/2-500) + strings.Repeat("]", 3*1024*1024/2-500))
218
219 _, err := rest.Post().
220 SetHeader("Accept", "application/yaml").
221 SetHeader("Content-Type", "application/yaml").
222 AbsPath("/api/v1/namespaces/default/configmaps").
223 Body(yamlBody).
224 DoRaw(tCtx)
225 if !apierrors.IsBadRequest(err) {
226 t.Errorf("expected bad request, got %v", err)
227 }
228 })
229
230
231 t.Run("create should handle a yaml document just under the maximum size with unbalanced nesting", func(t *testing.T) {
232 if testing.Short() {
233 t.Skip("skipping expensive test")
234 }
235 yamlBody := []byte(`
236 apiVersion: v1
237 kind: ConfigMap
238 metadata:
239 name: mytest
240 values: ` + strings.Repeat("[", 3*1024*1024-1000))
241
242 _, err := rest.Post().
243 SetHeader("Accept", "application/yaml").
244 SetHeader("Content-Type", "application/yaml").
245 AbsPath("/api/v1/namespaces/default/configmaps").
246 Body(yamlBody).
247 DoRaw(tCtx)
248 if !apierrors.IsBadRequest(err) {
249 t.Errorf("expected bad request, got %v", err)
250 }
251 })
252
253
254 t.Run("create should limit json parsing", func(t *testing.T) {
255 jsonBody := []byte(`{
256 "apiVersion": "v1",
257 "kind": "ConfigMap",
258 "metadata": {
259 "name": "mytest"
260 },
261 "values": ` + strings.Repeat("[", 3*1024*1024/2) + strings.Repeat("]", 3*1024*1024/2) + "}")
262
263 _, err := rest.Post().
264 SetHeader("Accept", "application/json").
265 SetHeader("Content-Type", "application/json").
266 AbsPath("/api/v1/namespaces/default/configmaps").
267 Body(jsonBody).
268 DoRaw(tCtx)
269 if !apierrors.IsRequestEntityTooLargeError(err) {
270 t.Errorf("expected too large error, got %v", err)
271 }
272 })
273
274
275 t.Run("create should handle a json document just under the maximum size with correct nesting", func(t *testing.T) {
276 if testing.Short() {
277 t.Skip("skipping expensive test")
278 }
279 jsonBody := []byte(`{
280 "apiVersion": "v1",
281 "kind": "ConfigMap",
282 "metadata": {
283 "name": "mytest"
284 },
285 "values": ` + strings.Repeat("[", 3*1024*1024/2-100) + strings.Repeat("]", 3*1024*1024/2-100) + "}")
286
287 _, err := rest.Post().
288 SetHeader("Accept", "application/json").
289 SetHeader("Content-Type", "application/json").
290 AbsPath("/api/v1/namespaces/default/configmaps").
291 Body(jsonBody).
292 DoRaw(tCtx)
293
294 if err != nil && !apierrors.IsBadRequest(err) {
295 t.Errorf("expected bad request, got %v", err)
296 }
297 })
298
299
300 t.Run("create should handle a json document just under the maximum size with unbalanced nesting", func(t *testing.T) {
301 if testing.Short() {
302 t.Skip("skipping expensive test")
303 }
304 jsonBody := []byte(`{
305 "apiVersion": "v1",
306 "kind": "ConfigMap",
307 "metadata": {
308 "name": "mytest"
309 },
310 "values": ` + strings.Repeat("[", 3*1024*1024-1000) + "}")
311
312 _, err := rest.Post().
313 SetHeader("Accept", "application/json").
314 SetHeader("Content-Type", "application/json").
315 AbsPath("/api/v1/namespaces/default/configmaps").
316 Body(jsonBody).
317 DoRaw(tCtx)
318 if !apierrors.IsBadRequest(err) {
319 t.Errorf("expected bad request, got %v", err)
320 }
321 })
322 }
323
View as plain text