1
- //go:build scale
2
- // +build scale
3
-
4
- package scale
1
+ package framework
5
2
6
3
import (
7
4
"bytes"
5
+ "errors"
8
6
"fmt"
9
- "os"
10
- "path/filepath"
7
+ "io"
11
8
"text/template"
9
+
10
+ "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
11
+ "k8s.io/apimachinery/pkg/util/yaml"
12
+ "sigs.k8s.io/controller-runtime/pkg/client"
12
13
)
13
14
14
- var gwTmplTxt = `apiVersion: gateway.networking.k8s.io/v1
15
+ const gwTmplTxt = `apiVersion: gateway.networking.k8s.io/v1
15
16
kind: Gateway
16
17
metadata:
17
18
name: gateway
33
34
{{- end -}}
34
35
{{- end -}}`
35
36
36
- var hrTmplTxt = `apiVersion: gateway.networking.k8s.io/v1
37
+ const hrTmplTxt = `apiVersion: gateway.networking.k8s.io/v1
37
38
kind: HTTPRoute
38
39
metadata:
39
40
name: {{ .Name }}
53
54
port: 80`
54
55
55
56
// nolint:all
56
- var secretTmplTxt = `apiVersion: v1
57
+ const secretTmplTxt = `apiVersion: v1
57
58
kind: Secret
58
59
metadata:
59
60
name: {{ . }}
63
64
tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRQzZtTnJSdUZ2WXZoSE4KbXI3c1FvNUtKSUVDN3N6TFVrNExFeklSNS9yMEVaUjQ2RnRTaGJQd0ZuaXAwMFBxekhpVkhKYy92TjdkQTVLeApQS1VmdFJuQ1J6YldVaTZBZzJpRU93bXF6WUhGbVNpZkFlVjk0RlAxOGtSbjl1ckV3OEpiRXJIUncrVW51L25tCmFMRHF1eGpFTVBweGhuRklCSnYwK1R3djNEVGx6TjNwUlV6dnpidGZvZCtEVTZBSmR6N3Rid1dTNmR6MHc1Z2kKbW9RelZnbFpnVDBJek9FZkV3NVpWMnRMZllHZWRlRVJ1VjhtR041c09va3R2aGxsMU1udHRaMkZNVHgySmVjUQo3K0xBRm9YVnBTS2NjbUFVZ1JBM0xOOHdVZXBVTHZZdFhiUm1QTFc4SjFINmhFeHJHTHBiTERZNmpzbGxBNlZpCk0xMjVjU0hsQWdNQkFBRUNnZ0VBQnpaRE50bmVTdWxGdk9HZlFYaHRFWGFKdWZoSzJBenRVVVpEcUNlRUxvekQKWlV6dHdxbkNRNlJLczUyandWNTN4cU9kUU94bTNMbjNvSHdNa2NZcEliWW82MjJ2dUczYnkwaVEzaFlsVHVMVgpqQmZCcS9UUXFlL2NMdngvSkczQWhFNmJxdFRjZFlXeGFmTmY2eUtpR1dzZk11WVVXTWs4MGVJVUxuRmZaZ1pOCklYNTlSOHlqdE9CVm9Sa3hjYTVoMW1ZTDFsSlJNM3ZqVHNHTHFybmpOTjNBdWZ3ZGRpK1VDbGZVL2l0K1EvZkUKV216aFFoTlRpNVFkRWJLVStOTnYvNnYvb2JvandNb25HVVBCdEFTUE05cmxFemIralQ1WHdWQjgvLzRGY3VoSwoyVzNpcjhtNHVlQ1JHSVlrbGxlLzhuQmZ0eVhiVkNocVRyZFBlaGlPM1FLQmdRRGlrR3JTOTc3cjg3Y1JPOCtQClpoeXltNXo4NVIzTHVVbFNTazJiOTI1QlhvakpZL2RRZDVTdFVsSWE4OUZKZnNWc1JRcEhHaTFCYzBMaTY1YjIKazR0cE5xcVFoUmZ1UVh0UG9GYXRuQzlPRnJVTXJXbDVJN0ZFejZnNkNQMVBXMEg5d2hPemFKZUdpZVpNYjlYTQoybDdSSFZOcC9jTDlYbmhNMnN0Q1lua2Iwd0tCZ1FEUzF4K0crakEyUVNtRVFWNXA1RnRONGcyamsyZEFjMEhNClRIQ2tTazFDRjhkR0Z2UWtsWm5ZbUt0dXFYeXNtekJGcnZKdmt2eUhqbUNYYTducXlpajBEdDZtODViN3BGcVAKQWxtajdtbXI3Z1pUeG1ZMXBhRWFLMXY4SDNINGtRNVl3MWdrTWRybVJHcVAvaTBGaDVpaGtSZS9DOUtGTFVkSQpDcnJjTzhkUVp3S0JnSHA1MzRXVWNCMVZibzFlYStIMUxXWlFRUmxsTWlwRFM2TzBqeWZWSmtFb1BZSEJESnp2ClIrdzZLREJ4eFoyWmJsZ05LblV0YlhHSVFZd3lGelhNcFB5SGxNVHpiZkJhYmJLcDFyR2JVT2RCMXpXM09PRkgKcmppb21TUm1YNmxhaDk0SjRHU0lFZ0drNGw1SHhxZ3JGRDZ2UDd4NGRjUktJWFpLZ0w2dVJSSUpBb0dCQU1CVApaL2p5WStRNTBLdEtEZHUrYU9ORW4zaGxUN3hrNXRKN3NBek5rbWdGMU10RXlQUk9Xd1pQVGFJbWpRbk9qbHdpCldCZ2JGcXg0M2ZlQ1Z4ZXJ6V3ZEM0txaWJVbWpCTkNMTGtYeGh3ZEVteFQwVit2NzZGYzgwaTNNYVdSNnZZR08KditwVVovL0F6UXdJcWZ6dlVmV2ZxdStrMHlhVXhQOGNlcFBIRyt0bEFvR0FmQUtVVWhqeFU0Ym5vVzVwVUhKegpwWWZXZXZ5TW54NWZyT2VsSmRmNzlvNGMvMHhVSjh1eFBFWDFkRmNrZW96dHNpaVFTNkN6MENRY09XVWxtSkRwCnVrdERvVzM3VmNSQU1BVjY3NlgxQVZlM0UwNm5aL2g2Tkd4Z28rT042Q3pwL0lkMkJPUm9IMFAxa2RjY1NLT3kKMUtFZlNnb1B0c1N1eEpBZXdUZmxDMXc9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K
64
65
`
65
66
66
- var appTmplTxt = `apiVersion: v1
67
- apiVersion: apps/v1
67
+ const appTmplTxt = `apiVersion: apps/v1
68
68
kind: Deployment
69
69
metadata:
70
70
name: {{ . }}
@@ -105,25 +105,55 @@ var (
105
105
appTmpl = template .Must (template .New ("app" ).Parse (appTmplTxt ))
106
106
)
107
107
108
- type Listener struct {
108
+ type listener struct {
109
109
Name string
110
110
HostnamePrefix string
111
111
SecretName string
112
112
}
113
113
114
- type Route struct {
114
+ type route struct {
115
115
Name string
116
116
ListenerName string
117
117
HostnamePrefix string
118
118
BackendName string
119
119
}
120
120
121
- func getPrereqDirName (manifestDir string ) string {
122
- return filepath .Join (manifestDir , "prereqs" )
121
+ // ScaleObjects contains objects for scale testing.
122
+ type ScaleObjects struct {
123
+ // BaseObjects contains objects that are common to all scale iterations.
124
+ BaseObjects []client.Object
125
+ // ScaleIterationGroups contains objects for each scale iteration.
126
+ ScaleIterationGroups [][]client.Object
123
127
}
124
128
125
- func generateScaleListenerManifests (numListeners int , manifestDir string , tls bool ) error {
126
- listeners := make ([]Listener , 0 )
129
+ func decodeObjects (reader io.Reader ) ([]client.Object , error ) {
130
+ var objects []client.Object
131
+
132
+ decoder := yaml .NewYAMLOrJSONDecoder (reader , 4096 )
133
+ for {
134
+ obj := unstructured.Unstructured {}
135
+ if err := decoder .Decode (& obj ); err != nil {
136
+ if errors .Is (err , io .EOF ) {
137
+ break
138
+ }
139
+ return nil , fmt .Errorf ("error decoding resource: %w" , err )
140
+ }
141
+
142
+ if len (obj .Object ) == 0 {
143
+ continue
144
+ }
145
+
146
+ objects = append (objects , & obj )
147
+ }
148
+
149
+ return objects , nil
150
+ }
151
+
152
+ // GenerateScaleListenerObjects generates objects for a given number of listeners for the scale test.
153
+ func GenerateScaleListenerObjects (numListeners int , tls bool ) (ScaleObjects , error ) {
154
+ var result ScaleObjects
155
+
156
+ listeners := make ([]listener , 0 )
127
157
backends := make ([]string , 0 )
128
158
secrets := make ([]string , 0 )
129
159
@@ -138,13 +168,13 @@ func generateScaleListenerManifests(numListeners int, manifestDir string, tls bo
138
168
secrets = append (secrets , secretName )
139
169
}
140
170
141
- listeners = append (listeners , Listener {
171
+ listeners = append (listeners , listener {
142
172
Name : listenerName ,
143
173
HostnamePrefix : hostnamePrefix ,
144
174
SecretName : secretName ,
145
175
})
146
176
147
- route := Route {
177
+ r := route {
148
178
Name : fmt .Sprintf ("route-%d" , i ),
149
179
ListenerName : listenerName ,
150
180
HostnamePrefix : hostnamePrefix ,
@@ -153,80 +183,101 @@ func generateScaleListenerManifests(numListeners int, manifestDir string, tls bo
153
183
154
184
backends = append (backends , backendName )
155
185
156
- if err := generateManifests (manifestDir , i , listeners , []Route {route }); err != nil {
157
- return err
186
+ objects , err := generateManifests (listeners , []route {r })
187
+ if err != nil {
188
+ return ScaleObjects {}, err
158
189
}
190
+
191
+ result .ScaleIterationGroups = append (result .ScaleIterationGroups , objects )
159
192
}
160
193
161
- if err := generateSecrets (getPrereqDirName (manifestDir ), secrets ); err != nil {
162
- return err
194
+ secretObjects , err := generateSecrets (secrets )
195
+ if err != nil {
196
+ return ScaleObjects {}, err
163
197
}
164
198
165
- return generateBackendAppManifests (getPrereqDirName (manifestDir ), backends )
166
- }
199
+ result .BaseObjects = append (result .BaseObjects , secretObjects ... )
167
200
168
- func generateSecrets (secretsDir string , secrets []string ) error {
169
- err := os .Mkdir (secretsDir , 0o750 )
170
- if err != nil && ! os .IsExist (err ) {
171
- return err
201
+ backendObjects , err := generateBackendAppObjects (backends )
202
+ if err != nil {
203
+ return ScaleObjects {}, err
172
204
}
173
205
206
+ result .BaseObjects = append (result .BaseObjects , backendObjects ... )
207
+
208
+ return result , nil
209
+ }
210
+
211
+ func generateSecrets (secrets []string ) ([]client.Object , error ) {
212
+ objects := make ([]client.Object , 0 , len (secrets ))
213
+
174
214
for _ , secret := range secrets {
175
215
var buf bytes.Buffer
176
216
177
- if err = secretTmpl .Execute (& buf , secret ); err != nil {
178
- return err
217
+ if err : = secretTmpl .Execute (& buf , secret ); err != nil {
218
+ return nil , err
179
219
}
180
220
181
- path := filepath .Join (secretsDir , fmt .Sprintf ("%s.yaml" , secret ))
182
-
183
- fmt .Println ("Writing" , path )
184
- if err := os .WriteFile (path , buf .Bytes (), 0o600 ); err != nil {
185
- return err
221
+ objs , err := decodeObjects (& buf )
222
+ if err != nil {
223
+ return nil , err
186
224
}
225
+
226
+ objects = append (objects , objs ... )
187
227
}
188
228
189
- return nil
229
+ return objects , nil
190
230
}
191
231
192
- func generateScaleHTTPRouteManifests (numRoutes int , manifestDir string ) error {
193
- l := Listener {
232
+ // GenerateScaleHTTPRouteObjects generates objects for a given number of routes for the scale test.
233
+ func GenerateScaleHTTPRouteObjects (numRoutes int ) (ScaleObjects , error ) {
234
+ var result ScaleObjects
235
+
236
+ l := listener {
194
237
Name : "listener" ,
195
238
HostnamePrefix : "*" ,
196
239
}
197
240
198
241
backendName := "backend"
199
242
200
243
for i := 0 ; i < numRoutes ; i ++ {
201
-
202
- route := Route {
244
+ r := route {
203
245
Name : fmt .Sprintf ("route-%d" , i ),
204
246
HostnamePrefix : fmt .Sprintf ("%d" , i ),
205
247
ListenerName : "listener" ,
206
248
BackendName : backendName ,
207
249
}
208
250
209
- var listeners []Listener
251
+ var listeners []listener
210
252
if i == 0 {
211
253
// only generate a Gateway on the first iteration
212
- listeners = []Listener {l }
254
+ listeners = []listener {l }
213
255
}
214
256
215
- if err := generateManifests (manifestDir , i , listeners , []Route {route }); err != nil {
216
- return err
257
+ objects , err := generateManifests (listeners , []route {r })
258
+ if err != nil {
259
+ return ScaleObjects {}, err
217
260
}
218
261
262
+ result .ScaleIterationGroups = append (result .ScaleIterationGroups , objects )
263
+ }
264
+
265
+ backendObjects , err := generateBackendAppObjects ([]string {backendName })
266
+ if err != nil {
267
+ return ScaleObjects {}, err
219
268
}
220
269
221
- return generateBackendAppManifests (getPrereqDirName (manifestDir ), []string {backendName })
270
+ result .BaseObjects = backendObjects
271
+
272
+ return result , nil
222
273
}
223
274
224
- func generateManifests (outDir string , version int , listeners []Listener , routes []Route ) error {
275
+ func generateManifests (listeners []listener , routes []route ) ([]client. Object , error ) {
225
276
var buf bytes.Buffer
226
277
227
278
if len (listeners ) > 0 {
228
279
if err := gwTmpl .Execute (& buf , listeners ); err != nil {
229
- return err
280
+ return nil , err
230
281
}
231
282
}
232
283
@@ -236,42 +287,30 @@ func generateManifests(outDir string, version int, listeners []Listener, routes
236
287
}
237
288
238
289
if err := hrTmpl .Execute (& buf , r ); err != nil {
239
- return err
290
+ return nil , err
240
291
}
241
292
}
242
293
243
- err := os .Mkdir (outDir , 0o750 )
244
- if err != nil && ! os .IsExist (err ) {
245
- return err
246
- }
247
-
248
- filename := fmt .Sprintf ("manifest-%d.yaml" , version )
249
- path := filepath .Join (outDir , filename )
250
-
251
- fmt .Println ("Writing" , path )
252
- return os .WriteFile (path , buf .Bytes (), 0o600 )
294
+ return decodeObjects (& buf )
253
295
}
254
296
255
- func generateBackendAppManifests (outDir string , backends []string ) error {
256
- err := os .Mkdir (outDir , 0o750 )
257
- if err != nil && ! os .IsExist (err ) {
258
- return err
259
- }
297
+ func generateBackendAppObjects (backends []string ) ([]client.Object , error ) {
298
+ objects := make ([]client.Object , 0 , 2 * len (backends ))
260
299
261
300
for _ , backend := range backends {
262
301
var buf bytes.Buffer
263
302
264
- if err = appTmpl .Execute (& buf , backend ); err != nil {
265
- return err
303
+ if err : = appTmpl .Execute (& buf , backend ); err != nil {
304
+ return nil , err
266
305
}
267
306
268
- path := filepath .Join (outDir , fmt .Sprintf ("%s.yaml" , backend ))
269
-
270
- fmt .Println ("Writing" , path )
271
- if err := os .WriteFile (path , buf .Bytes (), 0o600 ); err != nil {
272
- return err
307
+ objs , err := decodeObjects (& buf )
308
+ if err != nil {
309
+ return nil , err
273
310
}
311
+
312
+ objects = append (objects , objs ... )
274
313
}
275
314
276
- return nil
315
+ return objects , nil
277
316
}
0 commit comments