Skip to content

Commit 6afc17e

Browse files
committed
Configure fuzzer as a standalone Go module and fix dependency issues
- Implement local CreatePodWithRetries to remove k8s.io/kubernetes dependency. - Initialize go.mod with k8s.io v0.32.1 dependencies. - Update README and CLI flags to reflect standalone directory structure. Examples: 1. High-concurrency 50k pod injection: go run cmd/main.go --base-pod templates/complex-daemonset.yaml --namespace fuzz-test --name-prefix representative-pod --count 50000 --concurrency 100 2. Single fuzzed output pod for inspection: go run cmd/main.go --base-pod templates/complex-daemonset.yaml --count 1 --out-dir ./output-pod
1 parent fab4c54 commit 6afc17e

File tree

6 files changed

+276
-8
lines changed

6 files changed

+276
-8
lines changed

fuzzer/README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,8 @@ kubectl create serviceaccount cilium -n fuzz-test
4848
Inject the pods using high concurrency.
4949

5050
```bash
51-
go run test/utils/fuzzer/cmd/main.go \
52-
--base-pod test/utils/fuzzer/templates/complex-daemonset.yaml \
51+
go run cmd/main.go \
52+
--base-pod templates/complex-daemonset.yaml \
5353
--namespace fuzz-test \
5454
--name-prefix representative-pod \
5555
--count 50000 \
@@ -61,7 +61,7 @@ go run test/utils/fuzzer/cmd/main.go \
6161
### Generate Pod Manifests to Disk
6262
To generate fuzzed manifests for manual inspection:
6363
```bash
64-
go run test/utils/fuzzer/cmd/main.go \
64+
go run cmd/main.go \
6565
--base-pod path/to/real-pod.yaml \
6666
--name-prefix representative-pod \
6767
--namespace my-test-ns \

fuzzer/cmd/main.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,14 @@ import (
2727
v1 "k8s.io/api/core/v1"
2828
"k8s.io/client-go/kubernetes"
2929
"k8s.io/client-go/tools/clientcmd"
30-
"k8s.io/kubernetes/test/utils/fuzzer"
30+
"k8s.io/perf-tests/fuzzer"
3131
"sigs.k8s.io/yaml"
3232
)
3333

3434
func main() {
3535
count := flag.Int("count", 1000, "Number of pods to generate")
3636
offset := flag.Int("offset", 0, "Starting index for pod naming")
37-
basePodPath := flag.String("base-pod", "test/utils/fuzzer/templates/complex-daemonset.yaml", "Path to the real pod YAML to sanitize and clone")
37+
basePodPath := flag.String("base-pod", "templates/complex-daemonset.yaml", "Path to the real pod YAML to sanitize and clone")
3838
namespace := flag.String("namespace", "fuzz-test", "Target namespace for fuzzed pods")
3939
namePrefix := flag.String("name-prefix", "fuzzed-pod", "Prefix for generated pod names")
4040
outDir := flag.String("out-dir", "", "Directory to write YAMLs (if specified, no cluster injection)")

fuzzer/fuzzer.go

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,16 +26,39 @@ import (
2626
"strings"
2727
"sync"
2828
"sync/atomic"
29+
"time"
2930

3031
"golang.org/x/sync/errgroup"
3132
v1 "k8s.io/api/core/v1"
33+
apierrors "k8s.io/apimachinery/pkg/api/errors"
3234
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3335
"k8s.io/apimachinery/pkg/types"
36+
"k8s.io/apimachinery/pkg/util/wait"
3437
clientset "k8s.io/client-go/kubernetes"
35-
"k8s.io/kubernetes/test/utils"
3638
"sigs.k8s.io/yaml"
3739
)
3840

41+
// CreatePodWithRetries creates a pod with exponential backoff retries on transient errors.
42+
func CreatePodWithRetries(c clientset.Interface, namespace string, obj *v1.Pod) error {
43+
if obj == nil {
44+
return fmt.Errorf("object provided to create is empty")
45+
}
46+
backoff := wait.Backoff{
47+
Duration: 100 * time.Millisecond,
48+
Factor: 3,
49+
Steps: 6,
50+
}
51+
return wait.ExponentialBackoff(backoff, func() (bool, error) {
52+
_, err := c.CoreV1().Pods(namespace).Create(context.TODO(), obj, metav1.CreateOptions{})
53+
if err == nil || apierrors.IsAlreadyExists(err) {
54+
return true, nil
55+
}
56+
// GenerateName conflict or other temporary issues can be retried if needed,
57+
// but for the fuzzer we assume concrete names.
58+
return false, fmt.Errorf("failed to create pod %s: %v", obj.Name, err)
59+
})
60+
}
61+
3962
// ExemplaryPodFuzzer generates fuzzed Pod objects derived from a base pod.
4063
type ExemplaryPodFuzzer struct {
4164
rng *rand.Rand
@@ -221,7 +244,7 @@ func NewExemplaryPodCreator(client clientset.Interface, seed int64, namePrefix,
221244
// CreateExemplaryPods creates a batch of pods concurrently based on a base pod.
222245
func (c *ExemplaryPodCreator) CreateExemplaryPods(ctx context.Context, base *v1.Pod, count int, offset int, concurrency int, progress ProgressCallback) error {
223246
return c.processExemplaryPods(ctx, base, count, offset, concurrency, progress, func(pod *v1.Pod) error {
224-
return utils.CreatePodWithRetries(c.client, pod.Namespace, pod)
247+
return CreatePodWithRetries(c.client, pod.Namespace, pod)
225248
})
226249
}
227250

fuzzer/fuzzer_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ func TestDeeplyNestedManagedFields(t *testing.T) {
108108
assert.Len(t, pod.ManagedFields, 1)
109109
assert.Equal(t, "kubelet", pod.ManagedFields[0].Manager)
110110

111-
raw := string(pod.ManagedFields[0].FieldsV1.GetRawBytes())
111+
raw := string(pod.ManagedFields[0].FieldsV1.Raw)
112112
// Verify it contains fuzzed field paths
113113
assert.Contains(t, raw, "f:fuzzed_field_")
114114
assert.Contains(t, raw, "k:{\\\"id\\\":")

fuzzer/go.mod

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
module k8s.io/perf-tests/fuzzer
2+
3+
go 1.25.0
4+
5+
require (
6+
github.com/stretchr/testify v1.10.0
7+
golang.org/x/sync v0.10.0
8+
k8s.io/api v0.32.1
9+
k8s.io/apimachinery v0.32.1
10+
k8s.io/client-go v0.32.1
11+
sigs.k8s.io/yaml v1.4.0
12+
)
13+
14+
require (
15+
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
16+
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
17+
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
18+
github.com/go-logr/logr v1.4.2 // indirect
19+
github.com/go-openapi/jsonpointer v0.21.0 // indirect
20+
github.com/go-openapi/jsonreference v0.20.2 // indirect
21+
github.com/go-openapi/swag v0.23.0 // indirect
22+
github.com/gogo/protobuf v1.3.2 // indirect
23+
github.com/golang/protobuf v1.5.4 // indirect
24+
github.com/google/gnostic-models v0.6.8 // indirect
25+
github.com/google/go-cmp v0.6.0 // indirect
26+
github.com/google/gofuzz v1.2.0 // indirect
27+
github.com/google/uuid v1.6.0 // indirect
28+
github.com/josharian/intern v1.0.0 // indirect
29+
github.com/json-iterator/go v1.1.12 // indirect
30+
github.com/mailru/easyjson v0.7.7 // indirect
31+
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
32+
github.com/modern-go/reflect2 v1.0.2 // indirect
33+
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
34+
github.com/pkg/errors v0.9.1 // indirect
35+
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
36+
github.com/spf13/pflag v1.0.5 // indirect
37+
github.com/x448/float16 v0.8.4 // indirect
38+
golang.org/x/net v0.30.0 // indirect
39+
golang.org/x/oauth2 v0.23.0 // indirect
40+
golang.org/x/sys v0.26.0 // indirect
41+
golang.org/x/term v0.25.0 // indirect
42+
golang.org/x/text v0.19.0 // indirect
43+
golang.org/x/time v0.7.0 // indirect
44+
google.golang.org/protobuf v1.35.1 // indirect
45+
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
46+
gopkg.in/inf.v0 v0.9.1 // indirect
47+
gopkg.in/yaml.v3 v3.0.1 // indirect
48+
k8s.io/klog/v2 v2.130.1 // indirect
49+
k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f // indirect
50+
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect
51+
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect
52+
sigs.k8s.io/structured-merge-diff/v4 v4.4.2 // indirect
53+
)
54+
55+
replace (
56+
k8s.io/api => k8s.io/api v0.32.1
57+
k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.32.1
58+
k8s.io/apimachinery => k8s.io/apimachinery v0.32.1
59+
k8s.io/apiserver => k8s.io/apiserver v0.32.1
60+
k8s.io/cli-runtime => k8s.io/cli-runtime v0.32.1
61+
k8s.io/client-go => k8s.io/client-go v0.32.1
62+
k8s.io/cloud-provider => k8s.io/cloud-provider v0.32.1
63+
k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.32.1
64+
k8s.io/code-generator => k8s.io/code-generator v0.32.1
65+
k8s.io/component-base => k8s.io/component-base v0.32.1
66+
k8s.io/component-helpers => k8s.io/component-helpers v0.32.1
67+
k8s.io/controller-manager => k8s.io/controller-manager v0.32.1
68+
k8s.io/cri-api => k8s.io/cri-api v0.32.1
69+
k8s.io/cri-control-plane => k8s.io/cri-control-plane v0.32.1
70+
k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.32.1
71+
k8s.io/dynamic-resource-allocation => k8s.io/dynamic-resource-allocation v0.32.1
72+
k8s.io/endpointslice => k8s.io/endpointslice v0.32.1
73+
k8s.io/external-connector => k8s.io/external-connector v0.32.1
74+
k8s.io/kms => k8s.io/kms v0.32.1
75+
k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.32.1
76+
k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.32.1
77+
k8s.io/kube-proxy => k8s.io/kube-proxy v0.32.1
78+
k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.32.1
79+
k8s.io/kubectl => k8s.io/kubectl v0.32.1
80+
k8s.io/kubelet => k8s.io/kubelet v0.32.1
81+
k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.32.1
82+
k8s.io/metrics => k8s.io/metrics v0.32.1
83+
k8s.io/mount-utils => k8s.io/mount-utils v0.32.1
84+
k8s.io/node-api => k8s.io/node-api v0.32.1
85+
k8s.io/pod-security-admission => k8s.io/pod-security-admission v0.32.1
86+
k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.32.1
87+
k8s.io/sample-cli-plugin => k8s.io/sample-cli-plugin v0.32.1
88+
k8s.io/sample-controller => k8s.io/sample-controller v0.32.1
89+
)

0 commit comments

Comments
 (0)