Skip to content

Commit 61b4f46

Browse files
author
vittoria salim
committed
fix (patch): patching data based on valuesize for realistic load testing (configmaps and secrets)
1 parent d8bf3a0 commit 61b4f46

File tree

3 files changed

+56
-46
lines changed

3 files changed

+56
-46
lines changed

api/types/load_traffic.go

Lines changed: 8 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,7 @@
44
package types
55

66
import (
7-
"encoding/json"
87
"fmt"
9-
"strings"
10-
118
apitypes "k8s.io/apimachinery/pkg/types"
129
)
1310

@@ -165,10 +162,9 @@ type RequestPatch struct {
165162
Name string `json:"name" yaml:"name"`
166163
// KeySpaceSize is used to generate random number as name's suffix.
167164
KeySpaceSize int `json:"keySpaceSize" yaml:"keySpaceSize"`
168-
// PatchType is the type of patch, e.g. "json", "merge", "strategic-merge".
169-
PatchType string `json:"patchType" yaml:"patchType"`
170-
// Body is the request body, for fields to be changed.
171-
Body string `json:"body" yaml:"body"`
165+
// ValueSize is the object's size in bytes. how many bytes to patch data
166+
ValueSize int `json:"valueSize" yaml:"valueSize"`
167+
172168
}
173169

174170
// RequestGetPodLog defines GetLog request for target pod.
@@ -362,24 +358,13 @@ func (r *RequestPatch) Validate() error {
362358
if r.Name == "" {
363359
return fmt.Errorf("name is required")
364360
}
365-
if r.Body == "" {
366-
return fmt.Errorf("body is required")
367-
}
368-
369-
// Validate patch type
370-
_, ok := GetPatchType(r.PatchType)
371-
if !ok {
372-
return fmt.Errorf("unknown patch type: %s (valid types: json, merge, strategic-merge)", r.PatchType)
361+
if r.Resource == "" {
362+
return fmt.Errorf("resource is required")
373363
}
374-
375-
// Validate JSON body and trim it
376-
trimmed := strings.TrimSpace(r.Body)
377-
if !json.Valid([]byte(trimmed)) {
378-
return fmt.Errorf("invalid JSON in patch body: %q", r.Body)
364+
if (r.Resource == "configmaps" || r.Resource == "secrets" ) && r.ValueSize <= 0{
365+
return fmt.Errorf("valueSize must > 0 for configmaps and secrets, to generate data to be patched")
379366
}
380-
381-
r.Body = trimmed // Store the trimmed body
382-
367+
383368
return nil
384369
}
385370

contrib/utils/utils.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@ package utils
66
import (
77
"bytes"
88
"context"
9+
"crypto/rand"
910
"encoding/json"
1011
"errors"
1112
"fmt"
13+
"math/big"
1214
"net"
1315
"os"
1416
"sort"
@@ -39,8 +41,25 @@ var (
3941
// provider ID for all the virtual nodes so that EKS cloud provider
4042
// won't delete our virtual nodes.
4143
EKSIdleNodepoolInstanceType = "m4.large"
44+
// letterRunes contains the alphabet for random string generation
45+
letterRunes = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
4246
)
47+
// randString generates a random string of specified length
48+
func RandString(n int) (string, error) {
49+
if n <= 0 {
50+
return "", fmt.Errorf("length must be positive")
51+
}
4352

53+
b := make([]rune, n)
54+
for i := range b {
55+
random, err := rand.Int(rand.Reader, big.NewInt(int64(len(letterRunes))))
56+
if err != nil {
57+
return "", fmt.Errorf("error generating random number: %w", err)
58+
}
59+
b[i] = letterRunes[int(random.Int64())]
60+
}
61+
return string(b), nil
62+
}
4463
// RepeatJobWithPod repeats to deploy 3k pods.
4564
func RepeatJobWithPod(ctx context.Context, kubeCfgPath string, namespace string,
4665
target string, timeoutOpts ...JobTimeoutOpt) {

request/random.go

Lines changed: 29 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ func NewWeightedRandomRequests(spec *types.LoadProfileSpec) (*WeightedRandomRequ
6161
case r.GetPodLog != nil:
6262
builder = newRequestGetPodLogBuilder(r.GetPodLog, spec.MaxRetries)
6363
case r.Patch != nil:
64-
builder = newRequestPatchBuilder(r.Patch, "", spec.MaxRetries)
64+
builder = newRequestPatchBuilder(r.Patch, spec.MaxRetries)
6565
case r.PostDel != nil:
6666
builder = newRequestPostDelBuilder(r.PostDel, "", spec.MaxRetries)
6767
default:
@@ -363,33 +363,27 @@ func (b *requestGetPodLogBuilder) Build(cli rest.Interface) Requester {
363363
}
364364

365365
type requestPatchBuilder struct {
366-
version schema.GroupVersion
367-
resource string
368-
resourceVersion string
369-
namespace string
370-
name string
371-
keySpaceSize int
372-
patchType apitypes.PatchType
373-
body interface{}
374-
maxRetries int
366+
version schema.GroupVersion
367+
resource string
368+
namespace string
369+
name string
370+
keySpaceSize int
371+
valueSize int
372+
maxRetries int
375373
}
376374

377-
func newRequestPatchBuilder(src *types.RequestPatch, resourceVersion string, maxRetries int) *requestPatchBuilder {
378-
patchType, _ := types.GetPatchType(src.PatchType)
379-
375+
func newRequestPatchBuilder(src *types.RequestPatch, maxRetries int) *requestPatchBuilder {
380376
return &requestPatchBuilder{
381377
version: schema.GroupVersion{
382378
Group: src.Group,
383379
Version: src.Version,
384380
},
385-
resource: src.Resource,
386-
resourceVersion: resourceVersion,
387-
namespace: src.Namespace,
388-
name: src.Name,
389-
keySpaceSize: src.KeySpaceSize,
390-
patchType: patchType,
391-
body: []byte(src.Body),
392-
maxRetries: maxRetries,
381+
resource: src.Resource,
382+
namespace: src.Namespace,
383+
name: src.Name,
384+
keySpaceSize: src.KeySpaceSize,
385+
valueSize: src.ValueSize,
386+
maxRetries: maxRetries,
393387
}
394388
}
395389

@@ -413,11 +407,23 @@ func (b *requestPatchBuilder) Build(cli rest.Interface) Requester {
413407
finalName := fmt.Sprintf("%s-%d", b.name, suffix)
414408
comps = append(comps, b.resource, finalName)
415409

410+
var body []byte
411+
412+
// For configmapas and secrets: generate data based on valueSize
413+
if b.resource == "configmaps" || b.resource == "secrets" && b.valueSize > 0 {
414+
randomData, _ := utils.RandString(b.valueSize)
415+
416+
body = []byte(fmt.Sprintf(`{"data":{"data-key":"%s"}}`, randomData))
417+
} else {
418+
// For other resources: patch based on simple data annotations
419+
body = []byte(fmt.Sprintf(`{"metadata":{"annotations":{"force-update":"%d-%d"}}}`, suffix, time.Now().UnixNano()))
420+
}
421+
416422
return &DiscardRequester{
417423
BaseRequester: BaseRequester{
418424
method: "PATCH",
419-
req: cli.Patch(b.patchType).AbsPath(comps...).
420-
Body(b.body).
425+
req: cli.Patch(apitypes.MergePatchType).AbsPath(comps...).
426+
Body(body).
421427
MaxRetries(b.maxRetries),
422428
},
423429
}

0 commit comments

Comments
 (0)