diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5634934c59..9cc807c14a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -188,11 +188,11 @@ jobs: git diff --exit-code - name: Validate disruptionlistener protobuf run: | - make generate-disruptionlistener-protobuf + make generate-disruptionlistener-protobuf PROTOC_OS=linux git diff --exit-code ':!go.*' - name: Validate chaosdogfood protobuf run: | - make generate-chaosdogfood-protobuf + make generate-chaosdogfood-protobuf PROTOC_OS=linux git diff --exit-code ':!go.*' python-checks: diff --git a/.goreleaser.yml b/.goreleaser.yml index d4a8177482..388322d392 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -5,6 +5,7 @@ before: builds: - id: controller binary: manager + main: ./cmd goos: - linux goarch: diff --git a/.local.mockery.yaml b/.local.mockery.yaml index cd527870bc..e03d5b3861 100644 --- a/.local.mockery.yaml +++ b/.local.mockery.yaml @@ -25,7 +25,7 @@ packages: github.com/DataDog/chaos-controller/cloudservice/types: {} github.com/DataDog/chaos-controller/command: {} github.com/DataDog/chaos-controller/container: {} - github.com/DataDog/chaos-controller/controllers: {} + github.com/DataDog/chaos-controller/internal/controller: {} github.com/DataDog/chaos-controller/cpuset: {} github.com/DataDog/chaos-controller/disk: {} github.com/DataDog/chaos-controller/dogfood/chaosdogfood: {} diff --git a/CLAUDE.md b/CLAUDE.md index 73453629fe..5317d3416a 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -137,6 +137,6 @@ CRDs are defined in `api/v1beta1/` with kubebuilder markers. After modifying typ ## Requirements -- Kubernetes >= 1.16 (not 1.20.0-1.20.4) +- Kubernetes >= 1.22 - Go 1.25.6 - Docker with buildx (multi-arch: amd64, arm64) diff --git a/Makefile b/Makefile index cfd266ac8a..efb4c88392 100644 --- a/Makefile +++ b/Makefile @@ -68,7 +68,7 @@ E2E_TEST_CLUSTER_NAME ?= lima-$(LIMA_INSTANCE) E2E_TEST_KUBECTL_CONTEXT ?= lima KUBECTL ?= limactl shell $(LIMA_INSTANCE) sudo kubectl -PROTOC_VERSION = 3.17.3 +PROTOC_VERSION = 35.0 PROTOC_OS ?= osx PROTOC_ZIP = protoc-${PROTOC_VERSION}-${PROTOC_OS}-x86_64.zip # you might also want to change ~/lima.yaml k3s version @@ -111,7 +111,7 @@ endif WATCHEXEC_ARCHIVE = watchexec-$(WATCHEXEC_VERSION)-$(WATCHEXEC_ARCH_WE)-$(WATCHEXEC_OS) WATCHEXEC_INSTALLED_VERSION = $(shell $(LOCALBIN)/watchexec --version 2>/dev/null | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1) -PROTOC_INSTALLED_VERSION = $(shell $(LOCALBIN)/protoc --version 2>/dev/null | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1) +PROTOC_INSTALLED_VERSION = $(shell $(LOCALBIN)/protoc --version 2>/dev/null | grep -oE '[0-9]+\.[0-9]+' | head -1) PROTOC_GEN_GO_VERSION = v1.27.1 PROTOC_GEN_GO_INSTALLED_VERSION = $(shell $(LOCALBIN)/protoc-gen-go --version 2>&1 | grep -oE 'v[0-9]+\.[0-9]+\.[0-9]+' | head -1) @@ -256,7 +256,7 @@ GINKGO_PROCS ?= 4 _ginkgo_test: # Run the test and write a file if succeed # Do not stop on any error - -go run github.com/onsi/ginkgo/v2/ginkgo --fail-on-pending --keep-going --vv \ + -go run github.com/onsi/ginkgo/v2/ginkgo --fail-on-pending --keep-going --no-color \ --cover --coverprofile=cover.profile --randomize-all \ --race --trace --json-report=report-$(GO_TEST_REPORT_NAME).json --junit-report=report-$(GO_TEST_REPORT_NAME).xml \ --compilers=$(GINKGO_PROCS) --procs=$(GINKGO_PROCS) \ @@ -285,7 +285,7 @@ endif test: generate-controller manifests $(if $(GOPATH),,$(error GOPATH is not set. Please set GOPATH before running make test)) $(MAKE) _ginkgo_test GO_TEST_REPORT_NAME=$@ \ - GINKGO_TEST_ARGS="-r --skip-package=controllers --randomize-suites --timeout=10m $(TEST_ARGS)" + GINKGO_TEST_ARGS="-r --skip-package=internal/controller --randomize-suites --timeout=10m $(TEST_ARGS)" spellcheck-deps: ifeq (, $(shell which npm)) @@ -335,7 +335,7 @@ ifneq (true,$(SKIP_DEPLOY)) # we can only wait for a controller if it exists, lo $(MAKE) lima-install HELM_VALUES=ci.yaml endif E2E_TEST_CLUSTER_NAME=$(E2E_TEST_CLUSTER_NAME) E2E_TEST_KUBECTL_CONTEXT=$(E2E_TEST_KUBECTL_CONTEXT) $(MAKE) _ginkgo_test GO_TEST_REPORT_NAME=$@ \ - GINKGO_TEST_ARGS="--flake-attempts=3 --timeout=25m controllers" + GINKGO_TEST_ARGS="--flake-attempts=3 --timeout=25m internal/controller" # Test chaosli API portability chaosli-test: diff --git a/PROJECT b/PROJECT index 5e43133bcc..a0d56f2ddc 100644 --- a/PROJECT +++ b/PROJECT @@ -2,7 +2,7 @@ domain: datadoghq.com repo: github.com/DataDog/chaos-controller projectName: chaos-controller layout: -- go.kubebuilder.io/v3 +- go.kubebuilder.io/v4 resources: - api: crdVersion: v1beta1 diff --git a/README.md b/README.md index d85323362a..1e3158e064 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,4 @@ -**Oldest Kubernetes version supported: 1.16** - -> :warning: **Kubernetes version 1.20.x is not supported!** _This [Kubernetes issue](https://github.com/kubernetes/kubernetes/issues/97288) prevents the controller from running properly on Kubernetes 1.20.0-1.20.4. Earlier versions of Kubernetes as well as 1.20.5 and later are still supported._ +**Oldest Kubernetes version supported: 1.22** # Datadog Chaos Controller diff --git a/api/v1beta1/disruption_cron_webhook.go b/api/v1beta1/disruption_cron_webhook.go index 89ec10495f..ece8b87472 100644 --- a/api/v1beta1/disruption_cron_webhook.go +++ b/api/v1beta1/disruption_cron_webhook.go @@ -17,11 +17,10 @@ import ( "go.uber.org/zap" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" - "k8s.io/apimachinery/pkg/runtime" + k8sruntime "k8s.io/apimachinery/pkg/runtime" validationutils "k8s.io/apimachinery/pkg/util/validation" "k8s.io/client-go/tools/record" ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/webhook" "sigs.k8s.io/controller-runtime/pkg/webhook/admission" "github.com/DataDog/chaos-controller/o11y/metrics" @@ -66,21 +65,21 @@ func (d *DisruptionCron) SetupWebhookWithManager(setupWebhookConfig utils.SetupW defaultDuration = setupWebhookConfig.DefaultDurationFlag return ctrl.NewWebhookManagedBy(setupWebhookConfig.Manager). + For(d). WithDefaulter(&DisruptionCron{}). WithValidator(&DisruptionCron{}). - For(d). Complete() } //+kubebuilder:webhook:webhookVersions={v1},path=/mutate-chaos-datadoghq-com-v1beta1-disruptioncron,mutating=true,failurePolicy=fail,sideEffects=None,groups=chaos.datadoghq.com,resources=disruptioncrons,verbs=create;update,versions=v1beta1,name=mdisruptioncron.kb.io,admissionReviewVersions={v1,v1beta1} -var _ webhook.CustomDefaulter = &DisruptionCron{} +var _ admission.CustomDefaulter = &DisruptionCron{} -// Default implements webhook.CustomDefaulter so a webhook will be registered for the type -func (d *DisruptionCron) Default(_ context.Context, obj runtime.Object) error { +// Default implements admission.CustomDefaulter so a webhook will be registered for the type. +func (d *DisruptionCron) Default(_ context.Context, obj k8sruntime.Object) error { disruptionCronObj, ok := obj.(*DisruptionCron) if !ok { - return fmt.Errorf("expected *DisruptionCron, got %T", obj) + return fmt.Errorf("expected a *DisruptionCron object but got %T", obj) } log := disruptionCronWebhookLogger.With( @@ -104,13 +103,13 @@ func (d *DisruptionCron) Default(_ context.Context, obj runtime.Object) error { //+kubebuilder:webhook:webhookVersions={v1},path=/validate-chaos-datadoghq-com-v1beta1-disruptioncron,mutating=false,failurePolicy=fail,sideEffects=None,groups=chaos.datadoghq.com,resources=disruptioncrons,verbs=create;update;delete,versions=v1beta1,name=vdisruptioncron.kb.io,admissionReviewVersions={v1,v1beta1} -var _ webhook.CustomValidator = &DisruptionCron{} +var _ admission.CustomValidator = &DisruptionCron{} -// ValidateCreate implements webhook.CustomValidator so a webhook will be registered for the type -func (d *DisruptionCron) ValidateCreate(_ context.Context, obj runtime.Object) (warnings admission.Warnings, err error) { +// ValidateCreate implements admission.CustomValidator so a webhook will be registered for the type. +func (d *DisruptionCron) ValidateCreate(_ context.Context, obj k8sruntime.Object) (warnings admission.Warnings, err error) { disruptionCronObj, ok := obj.(*DisruptionCron) if !ok { - return nil, fmt.Errorf("expected *DisruptionCron, got %T", obj) + return nil, fmt.Errorf("expected a *DisruptionCron object but got %T", obj) } log := disruptionCronWebhookLogger.With( @@ -161,15 +160,15 @@ func (d *DisruptionCron) ValidateCreate(_ context.Context, obj runtime.Object) ( return nil, nil } -func (d *DisruptionCron) ValidateUpdate(_ context.Context, oldObj, newObj runtime.Object) (warnings admission.Warnings, err error) { - newDisruptionCronObj, ok := newObj.(*DisruptionCron) +func (d *DisruptionCron) ValidateUpdate(_ context.Context, oldObj, newObj k8sruntime.Object) (warnings admission.Warnings, err error) { + oldDisruptionCronObj, ok := oldObj.(*DisruptionCron) if !ok { - return nil, fmt.Errorf("expected *DisruptionCron, got %T", newObj) + return nil, fmt.Errorf("expected a *DisruptionCron object but got %T", oldObj) } - oldDisruptionCronObj, ok := oldObj.(*DisruptionCron) + newDisruptionCronObj, ok := newObj.(*DisruptionCron) if !ok { - return nil, fmt.Errorf("expected *DisruptionCron, got %T", oldObj) + return nil, fmt.Errorf("expected a *DisruptionCron object but got %T", newObj) } log := disruptionCronWebhookLogger.With( @@ -220,10 +219,10 @@ func (d *DisruptionCron) ValidateUpdate(_ context.Context, oldObj, newObj runtim return nil, nil } -func (d *DisruptionCron) ValidateDelete(_ context.Context, obj runtime.Object) (warnings admission.Warnings, err error) { +func (d *DisruptionCron) ValidateDelete(_ context.Context, obj k8sruntime.Object) (warnings admission.Warnings, err error) { disruptionCronObj, ok := obj.(*DisruptionCron) if !ok { - return nil, fmt.Errorf("expected *DisruptionCron, got %T", obj) + return nil, fmt.Errorf("expected a *DisruptionCron object but got %T", obj) } log := disruptionCronWebhookLogger.With( diff --git a/api/v1beta1/disruption_cron_webhook_test.go b/api/v1beta1/disruption_cron_webhook_test.go index 206fd5f6eb..34541ed324 100644 --- a/api/v1beta1/disruption_cron_webhook_test.go +++ b/api/v1beta1/disruption_cron_webhook_test.go @@ -9,7 +9,7 @@ import ( "encoding/json" "time" - "github.com/DataDog/chaos-controller/mocks" + "github.com/DataDog/chaos-controller/cmd/mocks" metricsnoop "github.com/DataDog/chaos-controller/o11y/metrics/noop" "github.com/stretchr/testify/mock" "go.uber.org/zap/zaptest" diff --git a/api/v1beta1/disruption_webhook.go b/api/v1beta1/disruption_webhook.go index bc1b16e2b9..0a9cf30545 100644 --- a/api/v1beta1/disruption_webhook.go +++ b/api/v1beta1/disruption_webhook.go @@ -21,12 +21,11 @@ import ( corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" - "k8s.io/apimachinery/pkg/runtime" + k8sruntime "k8s.io/apimachinery/pkg/runtime" "k8s.io/client-go/tools/record" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" - "sigs.k8s.io/controller-runtime/pkg/webhook" "sigs.k8s.io/controller-runtime/pkg/webhook/admission" "github.com/DataDog/chaos-controller/cloudservice" @@ -98,40 +97,39 @@ func (d *Disruption) SetupWebhookWithManager(setupWebhookConfig utils.SetupWebho permittedUserGroupWarningString = strings.Join(setupWebhookConfig.PermittedUserGroups, ",") return ctrl.NewWebhookManagedBy(setupWebhookConfig.Manager). + For(d). WithDefaulter(&Disruption{}). WithValidator(&Disruption{}). - For(d). Complete() } //+kubebuilder:webhook:webhookVersions={v1},path=/mutate-chaos-datadoghq-com-v1beta1-disruption,mutating=true,failurePolicy=fail,sideEffects=None,groups=chaos.datadoghq.com,resources=disruptions,verbs=create;update,versions=v1beta1,name=mdisruption.kb.io,admissionReviewVersions={v1,v1beta1} -var _ webhook.CustomDefaulter = &Disruption{} +var _ admission.CustomDefaulter = &Disruption{} -// Default implements webhook.CustomDefaulter so a webhook will be registered for the type -func (d *Disruption) Default(_ context.Context, obj runtime.Object) error { - disruptionObj, ok := obj.(*Disruption) +// Default implements admission.CustomDefaulter so a webhook will be registered for the type. +func (d *Disruption) Default(_ context.Context, obj k8sruntime.Object) error { + disruption, ok := obj.(*Disruption) if !ok { - return fmt.Errorf("expected *Disruption, got %T", obj) + return fmt.Errorf("expected a *Disruption object but got %T", obj) } - disruptionObj.Spec.SetDefaults() + disruption.Spec.SetDefaults() return nil } //+kubebuilder:webhook:webhookVersions={v1},path=/validate-chaos-datadoghq-com-v1beta1-disruption,mutating=false,failurePolicy=fail,sideEffects=None,groups=chaos.datadoghq.com,resources=disruptions,verbs=create;update;delete,versions=v1beta1,name=vdisruption.kb.io,admissionReviewVersions={v1,v1beta1} -var _ webhook.CustomValidator = &Disruption{} +var _ admission.CustomValidator = &Disruption{} -// ValidateCreate implements webhook.CustomValidator so a webhook will be registered for the type -func (d *Disruption) ValidateCreate(ctx context.Context, obj runtime.Object) (_ admission.Warnings, err error) { +// ValidateCreate implements admission.CustomValidator so a webhook will be registered for the type. +func (d *Disruption) ValidateCreate(ctx context.Context, obj k8sruntime.Object) (_ admission.Warnings, err error) { disruptionObj, ok := obj.(*Disruption) if !ok { - return nil, fmt.Errorf("expected *Disruption, got %T", obj) + return nil, fmt.Errorf("expected a *Disruption object but got %T", obj) } - // Use the object from parameter instead of r log := logger.With( tagutil.DisruptionNameKey, disruptionObj.Name, tagutil.DisruptionNamespaceKey, disruptionObj.Namespace, @@ -303,16 +301,16 @@ func (d *Disruption) ValidateCreate(ctx context.Context, obj runtime.Object) (_ return nil, nil } -// ValidateUpdate implements webhook.CustomValidator so a webhook will be registered for the type -func (d *Disruption) ValidateUpdate(_ context.Context, oldObj, newObj runtime.Object) (_ admission.Warnings, err error) { - newDisruptionObj, ok := newObj.(*Disruption) +// ValidateUpdate implements admission.CustomValidator so a webhook will be registered for the type. +func (d *Disruption) ValidateUpdate(_ context.Context, oldObj, newObj k8sruntime.Object) (_ admission.Warnings, err error) { + oldDisruption, ok := oldObj.(*Disruption) if !ok { - return nil, fmt.Errorf("expected *Disruption, got %T", newObj) + return nil, fmt.Errorf("expected a *Disruption object but got %T", oldObj) } - oldDisruption, ok := oldObj.(*Disruption) + newDisruptionObj, ok := newObj.(*Disruption) if !ok { - return nil, fmt.Errorf("expected *Disruption, got %T", oldObj) + return nil, fmt.Errorf("expected a *Disruption object but got %T", newObj) } log := logger.With( @@ -415,14 +413,13 @@ You first need to remove those chaos pods (and potentially their finalizers) to return nil, nil } -// ValidateDelete implements webhook.CustomValidator so a webhook will be registered for the type -func (d *Disruption) ValidateDelete(_ context.Context, obj runtime.Object) (admission.Warnings, error) { +// ValidateDelete implements admission.CustomValidator so a webhook will be registered for the type. +func (d *Disruption) ValidateDelete(_ context.Context, obj k8sruntime.Object) (admission.Warnings, error) { disruptionObj, ok := obj.(*Disruption) if !ok { - return nil, fmt.Errorf("expected *Disruption, got %T", obj) + return nil, fmt.Errorf("expected a *Disruption object but got %T", obj) } - // Use the object from parameter if mErr := metricsSink.MetricValidationDeleted(disruptionObj.getMetricsTags()); mErr != nil { logger.Errorw("error sending a metric", tagutil.ErrorKey, mErr) } diff --git a/api/v1beta1/disruption_webhook_test.go b/api/v1beta1/disruption_webhook_test.go index b1ff50c97e..cea6959e8d 100644 --- a/api/v1beta1/disruption_webhook_test.go +++ b/api/v1beta1/disruption_webhook_test.go @@ -21,7 +21,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client/fake" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" - "github.com/DataDog/chaos-controller/mocks" + "github.com/DataDog/chaos-controller/cmd/mocks" metricsnoop "github.com/DataDog/chaos-controller/o11y/metrics/noop" tracernoop "github.com/DataDog/chaos-controller/o11y/tracer/noop" chaostypes "github.com/DataDog/chaos-controller/types" diff --git a/api/v1beta1/userinfo.go b/api/v1beta1/userinfo.go index f9a750c4f6..23cfb83d60 100644 --- a/api/v1beta1/userinfo.go +++ b/api/v1beta1/userinfo.go @@ -11,7 +11,6 @@ import ( "strings" authV1 "k8s.io/api/authentication/v1" - "k8s.io/api/authentication/v1beta1" metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/controller-runtime/pkg/client" @@ -109,7 +108,7 @@ func validateUserInfoImmutable(oldObject, newObject client.Object) error { return nil } - emptyUserInfo := fmt.Sprintf("%v", v1beta1.UserInfo{}) + emptyUserInfo := fmt.Sprintf("%v", authV1.UserInfo{}) if fmt.Sprintf("%v", oldUserInfo) == emptyUserInfo { return nil } diff --git a/bin/manager/Dockerfile b/bin/manager/Dockerfile index 941c67aef5..e21594572b 100644 --- a/bin/manager/Dockerfile +++ b/bin/manager/Dockerfile @@ -16,7 +16,7 @@ COPY . . # Build the manager binary RUN CGO_ENABLED=0 GOOS=${TARGETOS} GOARCH=${TARGETARCH} \ - go build -o manager . + go build -o manager ./cmd # Final stage FROM gcr.io/distroless/base-debian13:nonroot diff --git a/cloudservice/manager_test.go b/cloudservice/manager_test.go index c2c40c9156..5b3b65b85d 100644 --- a/cloudservice/manager_test.go +++ b/cloudservice/manager_test.go @@ -16,8 +16,8 @@ import ( "github.com/DataDog/chaos-controller/cloudservice/gcp" "github.com/DataDog/chaos-controller/cloudservice/types" + "github.com/DataDog/chaos-controller/cmd/mocks" "github.com/DataDog/chaos-controller/log" - "github.com/DataDog/chaos-controller/mocks" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" "github.com/stretchr/testify/mock" diff --git a/main.go b/cmd/main.go similarity index 98% rename from main.go rename to cmd/main.go index e4f12ed574..765f9d46d2 100644 --- a/main.go +++ b/cmd/main.go @@ -24,9 +24,9 @@ import ( chaosv1beta1 "github.com/DataDog/chaos-controller/api/v1beta1" "github.com/DataDog/chaos-controller/cloudservice" "github.com/DataDog/chaos-controller/config" - "github.com/DataDog/chaos-controller/controllers" "github.com/DataDog/chaos-controller/eventbroadcaster" "github.com/DataDog/chaos-controller/eventnotifier" + "github.com/DataDog/chaos-controller/internal/controller" "github.com/DataDog/chaos-controller/log" "github.com/DataDog/chaos-controller/o11y/metrics" metricstypes "github.com/DataDog/chaos-controller/o11y/metrics/types" @@ -60,8 +60,8 @@ import ( "go.opentelemetry.io/otel/propagation" ) -//go:generate mockery --config .local.mockery.yaml -//go:generate mockery --config .vendor.mockery.yaml +//go:generate mockery --config ../.local.mockery.yaml +//go:generate mockery --config ../.vendor.mockery.yaml var scheme = runtime.NewScheme() @@ -241,7 +241,7 @@ func main() { } // create disruption reconciler - disruptionReconciler := &controllers.DisruptionReconciler{ + disruptionReconciler := &controller.DisruptionReconciler{ Client: mgr.GetClient(), APIReader: mgr.GetAPIReader(), BaseLog: logger, @@ -347,7 +347,7 @@ func main() { globalInformerFactory.Start(stopCh) // create disruption rollout reconciler - disruptionRolloutReconciler := &controllers.DisruptionRolloutReconciler{ + disruptionRolloutReconciler := &controller.DisruptionRolloutReconciler{ Client: mgr.GetClient(), BaseLog: logger, Scheme: mgr.GetScheme(), @@ -416,7 +416,7 @@ func main() { defer closeMetricsSink(logger, disruptionCronMetricsSink) // create disruption cron reconciler - disruptionCronReconciler := &controllers.DisruptionCronReconciler{ + disruptionCronReconciler := &controller.DisruptionCronReconciler{ Client: mgr.GetClient(), BaseLog: logger, Scheme: mgr.GetScheme(), diff --git a/mocks/cache.go b/cmd/mocks/cache.go similarity index 100% rename from mocks/cache.go rename to cmd/mocks/cache.go diff --git a/mocks/client.go b/cmd/mocks/client.go similarity index 100% rename from mocks/client.go rename to cmd/mocks/client.go diff --git a/mocks/client_interface.go b/cmd/mocks/client_interface.go similarity index 100% rename from mocks/client_interface.go rename to cmd/mocks/client_interface.go diff --git a/mocks/controller.go b/cmd/mocks/controller.go similarity index 100% rename from mocks/controller.go rename to cmd/mocks/controller.go diff --git a/mocks/event_broadcaster.go b/cmd/mocks/event_broadcaster.go similarity index 100% rename from mocks/event_broadcaster.go rename to cmd/mocks/event_broadcaster.go diff --git a/mocks/event_recorder.go b/cmd/mocks/event_recorder.go similarity index 100% rename from mocks/event_recorder.go rename to cmd/mocks/event_recorder.go diff --git a/mocks/informer.go b/cmd/mocks/informer.go similarity index 100% rename from mocks/informer.go rename to cmd/mocks/informer.go diff --git a/mocks/manager.go b/cmd/mocks/manager.go similarity index 100% rename from mocks/manager.go rename to cmd/mocks/manager.go diff --git a/mocks/reader.go b/cmd/mocks/reader.go similarity index 100% rename from mocks/reader.go rename to cmd/mocks/reader.go diff --git a/mocks/resource_event_handler.go b/cmd/mocks/resource_event_handler.go similarity index 100% rename from mocks/resource_event_handler.go rename to cmd/mocks/resource_event_handler.go diff --git a/mocks/round_tripper.go b/cmd/mocks/round_tripper.go similarity index 100% rename from mocks/round_tripper.go rename to cmd/mocks/round_tripper.go diff --git a/mocks/stat_fs.go b/cmd/mocks/stat_fs.go similarity index 100% rename from mocks/stat_fs.go rename to cmd/mocks/stat_fs.go diff --git a/mocks/syncing_source.go b/cmd/mocks/syncing_source.go similarity index 100% rename from mocks/syncing_source.go rename to cmd/mocks/syncing_source.go diff --git a/mocks/watcher.go b/cmd/mocks/watcher.go similarity index 100% rename from mocks/watcher.go rename to cmd/mocks/watcher.go diff --git a/command/command.go b/command/command.go index a5759d3d51..8a8953d54c 100644 --- a/command/command.go +++ b/command/command.go @@ -89,6 +89,7 @@ type backgroundCmd struct { ticker *time.Ticker // Used to send regular SIGCONT signal to process err chan error // Used to monitor the exit of the command keepAliveQuit chan int // Used to kill the keepAlive goroutine + keepAliveDone chan struct{} // Closed when the keepAlive goroutine exits pid int // PID of the process done chan struct{} // Closed when the process exits } @@ -204,10 +205,13 @@ func (w *backgroundCmd) KeepAlive() { w.ticker = time.NewTicker(cmdKeepAliveTickDuration) w.keepAliveQuit = make(chan int, 1) // we need a buffered channel so the sender doesn't block + w.keepAliveDone = make(chan struct{}) w.log.Debug("monitoring sending SIGCONT signal to process every 1s") go func() { + defer close(w.keepAliveDone) + for { exit, err := w.sendSIGCONTSignal() if err != nil { diff --git a/command/command_test.go b/command/command_test.go index dd353d1774..b4e319dcdb 100644 --- a/command/command_test.go +++ b/command/command_test.go @@ -244,13 +244,19 @@ var _ = Describe("BackgroundCmd", func() { sut.KeepAlive() sut.KeepAlive() // we call it twice voluntarily to test the invariant that only a single goroutine is created - // Wait enough interval to have at least expected calls (times + 20%) - <-time.After(cmdKeepAliveTickDuration*time.Duration(times) + cmdBootstrapAllowedDuration/5) - underSut, ok := sut.(*backgroundCmd) Expect(ok).To(BeTrue()) Expect(underSut).ToNot(BeNil()) + // Ensure the keepAlive goroutine has fully exited before mock cleanup runs, + // preventing panics when mocks are called after the test finishes. + DeferCleanup(func() { + <-underSut.keepAliveDone + }) + + // Wait enough interval to have at least expected calls (times + 20%) + <-time.After(cmdKeepAliveTickDuration*time.Duration(times) + cmdBootstrapAllowedDuration/5) + // Stop timer ASAP to have realistic amount of calls underSut.keepAliveQuit <- 0 }, @@ -268,12 +274,17 @@ var _ = Describe("BackgroundCmd", func() { sut.KeepAlive() sut.KeepAlive() // we call it twice voluntarily to test the invariant that only a single goroutine is created - // Wait enough interval to have at least expected calls (times + 20%) - <-time.After(cmdKeepAliveTickDuration*time.Duration(times) + cmdBootstrapAllowedDuration/5) - underSut, ok := sut.(*backgroundCmd) Expect(ok).To(BeTrue()) Expect(underSut).ToNot(BeNil()) + + // Ensure the keepAlive goroutine has fully exited before mock cleanup runs. + DeferCleanup(func() { + <-underSut.keepAliveDone + }) + + // Wait enough interval to have at least expected calls (times + 20%) + <-time.After(cmdKeepAliveTickDuration*time.Duration(times) + cmdBootstrapAllowedDuration/5) }, Entry("Find fails once", nil, errors.New("find fails"), nil, 1), Entry("Signal fails once", &os.Process{}, nil, errors.New("signal fails"), 1), diff --git a/docs/features.md b/docs/features.md index b3c3df21db..952ea9a529 100644 --- a/docs/features.md +++ b/docs/features.md @@ -90,7 +90,7 @@ See [targeting](./targeting.md) > :memo: This mode has some restrictions: > -> - it requires a 1.15+ Kubernetes cluster +> - it requires a 1.22+ Kubernetes cluster > - it requires the `--handler-enabled` flag on the controller container > - it only works for network disruptions > - it only works with the pod level diff --git a/dogfood/chaosdogfood/chaosdogfood.pb.go b/dogfood/chaosdogfood/chaosdogfood.pb.go index 9d71d7b1b8..54d19d2f37 100644 --- a/dogfood/chaosdogfood/chaosdogfood.pb.go +++ b/dogfood/chaosdogfood/chaosdogfood.pb.go @@ -6,7 +6,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.27.1 -// protoc v3.17.3 +// protoc v7.35.0 // source: chaosdogfood.proto package chaosdogfood diff --git a/ebpf/validator_test.go b/ebpf/validator_test.go index c1960839ca..ec08c7ef59 100644 --- a/ebpf/validator_test.go +++ b/ebpf/validator_test.go @@ -8,8 +8,8 @@ package ebpf_test import ( "fmt" + "github.com/DataDog/chaos-controller/cmd/mocks" "github.com/DataDog/chaos-controller/ebpf" - "github.com/DataDog/chaos-controller/mocks" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" "github.com/stretchr/testify/mock" diff --git a/eventbroadcaster/notifiersink_test.go b/eventbroadcaster/notifiersink_test.go index 368f8519ed..9c0e63889d 100644 --- a/eventbroadcaster/notifiersink_test.go +++ b/eventbroadcaster/notifiersink_test.go @@ -21,9 +21,9 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "github.com/DataDog/chaos-controller/api/v1beta1" + "github.com/DataDog/chaos-controller/cmd/mocks" "github.com/DataDog/chaos-controller/eventnotifier" notifTypes "github.com/DataDog/chaos-controller/eventnotifier/types" - "github.com/DataDog/chaos-controller/mocks" chaostypes "github.com/DataDog/chaos-controller/types" . "github.com/onsi/ginkgo/v2" diff --git a/eventnotifier/datadog/datadog_test.go b/eventnotifier/datadog/datadog_test.go index 90f33a4920..e2169ee49d 100644 --- a/eventnotifier/datadog/datadog_test.go +++ b/eventnotifier/datadog/datadog_test.go @@ -15,10 +15,10 @@ import ( k8sclient "sigs.k8s.io/controller-runtime/pkg/client" "github.com/DataDog/chaos-controller/api/v1beta1" + "github.com/DataDog/chaos-controller/cmd/mocks" "github.com/DataDog/chaos-controller/eventnotifier/datadog" "github.com/DataDog/chaos-controller/eventnotifier/types" "github.com/DataDog/chaos-controller/eventnotifier/utils" - "github.com/DataDog/chaos-controller/mocks" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" diff --git a/grpc/disruptionlistener/disruptionlistener.pb.go b/grpc/disruptionlistener/disruptionlistener.pb.go index 0f2bcac9b8..ece0519caa 100644 --- a/grpc/disruptionlistener/disruptionlistener.pb.go +++ b/grpc/disruptionlistener/disruptionlistener.pb.go @@ -6,7 +6,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.27.1 -// protoc v3.17.3 +// protoc v7.35.0 // source: disruptionlistener.proto package disruptionlistener diff --git a/controllers/clientset_test.go b/internal/controller/clientset_test.go similarity index 99% rename from controllers/clientset_test.go rename to internal/controller/clientset_test.go index cceb64e0d6..6628aae9b5 100644 --- a/controllers/clientset_test.go +++ b/internal/controller/clientset_test.go @@ -3,7 +3,7 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2026 Datadog, Inc. -package controllers +package controller import ( "fmt" diff --git a/controllers/cpu_pressure_test.go b/internal/controller/cpu_pressure_test.go similarity index 99% rename from controllers/cpu_pressure_test.go rename to internal/controller/cpu_pressure_test.go index e4fe2208ad..4e9f265316 100644 --- a/controllers/cpu_pressure_test.go +++ b/internal/controller/cpu_pressure_test.go @@ -3,7 +3,7 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2026 Datadog, Inc. -package controllers +package controller import ( "strings" diff --git a/controllers/cron_rollout_helpers.go b/internal/controller/cron_rollout_helpers.go similarity index 99% rename from controllers/cron_rollout_helpers.go rename to internal/controller/cron_rollout_helpers.go index e7ac3e5283..6356406f52 100644 --- a/controllers/cron_rollout_helpers.go +++ b/internal/controller/cron_rollout_helpers.go @@ -3,7 +3,7 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2026 Datadog, Inc. -package controllers +package controller import ( "context" diff --git a/controllers/disruption_controller.go b/internal/controller/disruption_controller.go similarity index 99% rename from controllers/disruption_controller.go rename to internal/controller/disruption_controller.go index 8c65280e17..d779850852 100644 --- a/controllers/disruption_controller.go +++ b/internal/controller/disruption_controller.go @@ -3,7 +3,7 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2026 Datadog, Inc. -package controllers +package controller // +kubebuilder:rbac:groups=chaos.datadoghq.com,resources=disruptions;disruptioncrons;disruptionrollouts,verbs=get;list;watch;create;update;patch;delete // +kubebuilder:rbac:groups=chaos.datadoghq.com,resources=disruptions/status;disruptioncrons/status;disruptionrollouts/status,verbs=get;update;patch diff --git a/controllers/disruption_controller_test.go b/internal/controller/disruption_controller_test.go similarity index 99% rename from controllers/disruption_controller_test.go rename to internal/controller/disruption_controller_test.go index ef2556937a..67a8e15afc 100644 --- a/controllers/disruption_controller_test.go +++ b/internal/controller/disruption_controller_test.go @@ -3,7 +3,7 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2026 Datadog, Inc. -package controllers +package controller import ( "fmt" diff --git a/controllers/disruption_cron_controller.go b/internal/controller/disruption_cron_controller.go similarity index 99% rename from controllers/disruption_cron_controller.go rename to internal/controller/disruption_cron_controller.go index d01fe2d318..d5e233ff65 100644 --- a/controllers/disruption_cron_controller.go +++ b/internal/controller/disruption_cron_controller.go @@ -3,7 +3,7 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2026 Datadog, Inc. -package controllers +package controller import ( "context" diff --git a/controllers/disruption_rollout_controller.go b/internal/controller/disruption_rollout_controller.go similarity index 99% rename from controllers/disruption_rollout_controller.go rename to internal/controller/disruption_rollout_controller.go index 8705474ddf..1e66e2193b 100644 --- a/controllers/disruption_rollout_controller.go +++ b/internal/controller/disruption_rollout_controller.go @@ -3,7 +3,7 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2026 Datadog, Inc. -package controllers +package controller import ( "context" diff --git a/controllers/memory_pressure_test.go b/internal/controller/memory_pressure_test.go similarity index 99% rename from controllers/memory_pressure_test.go rename to internal/controller/memory_pressure_test.go index 6be8f2edf2..b8126f3bd8 100644 --- a/controllers/memory_pressure_test.go +++ b/internal/controller/memory_pressure_test.go @@ -3,7 +3,7 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2026 Datadog, Inc. -package controllers +package controller import ( "fmt" diff --git a/controllers/suite_test.go b/internal/controller/suite_test.go similarity index 98% rename from controllers/suite_test.go rename to internal/controller/suite_test.go index a449d0c67e..c822f279e5 100644 --- a/controllers/suite_test.go +++ b/internal/controller/suite_test.go @@ -3,7 +3,7 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2026 Datadog, Inc. -package controllers +package controller import ( "context" @@ -69,7 +69,7 @@ var _ = BeforeSuite(func(ctx SpecContext) { log = zaptest.NewLogger(GinkgoT()).Sugar() - ciValues, err := os.ReadFile("../chart/values/ci.yaml") + ciValues, err := os.ReadFile("../../chart/values/ci.yaml") Expect(err).ToNot(HaveOccurred()) Expect(yaml.Unmarshal(ciValues, &lightCfg)).To(Succeed()) Expect(lightCfg).ToNot(BeZero()) diff --git a/controllers/suite_toolsfor_test.go b/internal/controller/suite_toolsfor_test.go similarity index 99% rename from controllers/suite_toolsfor_test.go rename to internal/controller/suite_toolsfor_test.go index 6518fd8c8c..fe46ce72a2 100644 --- a/controllers/suite_toolsfor_test.go +++ b/internal/controller/suite_toolsfor_test.go @@ -3,7 +3,7 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2026 Datadog, Inc. -package controllers +package controller import ( "fmt" diff --git a/controllers/watcher_handler_test.go b/internal/controller/watcher_handler_test.go similarity index 99% rename from controllers/watcher_handler_test.go rename to internal/controller/watcher_handler_test.go index 6d0bdb1cc8..3004340a1b 100644 --- a/controllers/watcher_handler_test.go +++ b/internal/controller/watcher_handler_test.go @@ -3,7 +3,7 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2026 Datadog, Inc. -package controllers +package controller import ( corev1 "k8s.io/api/core/v1" diff --git a/lima.yaml b/lima.yaml index aae813f147..82615e1a4e 100644 --- a/lima.yaml +++ b/lima.yaml @@ -35,7 +35,7 @@ provision: - mode: system script: | #!/usr/bin/env bash - curl -sfL https://get.k3s.io | INSTALL_K3S_VERSION=v1.26.3+k3s1 sh -s - --kubelet-arg="--cpu-manager-policy=static" --kubelet-arg='--reserved-cpus=0' + curl -sfL https://get.k3s.io | INSTALL_K3S_VERSION=v1.35.1+k3s1 sh -s - --kubelet-arg="--cpu-manager-policy=static" --kubelet-arg='--reserved-cpus=0' if ! timeout 90s bash -c "until test -e /run/k3s/containerd/containerd.sock; do sleep 3; done"; then echo >&2 "containerd is not running" exit 1 diff --git a/services/chaospod_test.go b/services/chaospod_test.go index 390dc59d64..9810826633 100644 --- a/services/chaospod_test.go +++ b/services/chaospod_test.go @@ -26,7 +26,7 @@ import ( chaosapi "github.com/DataDog/chaos-controller/api" chaosv1beta1 "github.com/DataDog/chaos-controller/api/v1beta1" builderstest "github.com/DataDog/chaos-controller/builderstest" - "github.com/DataDog/chaos-controller/mocks" + "github.com/DataDog/chaos-controller/cmd/mocks" "github.com/DataDog/chaos-controller/o11y/metrics" "github.com/DataDog/chaos-controller/services" "github.com/DataDog/chaos-controller/targetselector" diff --git a/targetselector/running_target_selector_test.go b/targetselector/running_target_selector_test.go index f7087d188c..0a193932b4 100644 --- a/targetselector/running_target_selector_test.go +++ b/targetselector/running_target_selector_test.go @@ -10,7 +10,7 @@ import ( "os" chaosv1beta1 "github.com/DataDog/chaos-controller/api/v1beta1" - "github.com/DataDog/chaos-controller/mocks" + "github.com/DataDog/chaos-controller/cmd/mocks" "github.com/DataDog/chaos-controller/targetselector" "github.com/DataDog/chaos-controller/types" "github.com/stretchr/testify/mock" diff --git a/targetselector/targetselector_extra_test.go b/targetselector/targetselector_extra_test.go index 714d18449f..0d22b052f9 100644 --- a/targetselector/targetselector_extra_test.go +++ b/targetselector/targetselector_extra_test.go @@ -9,7 +9,7 @@ import ( "context" "errors" - "github.com/DataDog/chaos-controller/mocks" + "github.com/DataDog/chaos-controller/cmd/mocks" "github.com/DataDog/chaos-controller/targetselector" "github.com/stretchr/testify/mock" corev1 "k8s.io/api/core/v1" diff --git a/watchers/deployment_handler_test.go b/watchers/deployment_handler_test.go index 1c786b8a12..48d9e8e3e1 100644 --- a/watchers/deployment_handler_test.go +++ b/watchers/deployment_handler_test.go @@ -15,7 +15,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "github.com/DataDog/chaos-controller/api/v1beta1" - "github.com/DataDog/chaos-controller/mocks" + "github.com/DataDog/chaos-controller/cmd/mocks" "github.com/DataDog/chaos-controller/watchers" "github.com/stretchr/testify/mock" "go.uber.org/zap/zaptest" diff --git a/watchers/disruptions_watchers_manager_test.go b/watchers/disruptions_watchers_manager_test.go index d0c7305416..76eda34bd3 100644 --- a/watchers/disruptions_watchers_manager_test.go +++ b/watchers/disruptions_watchers_manager_test.go @@ -11,7 +11,7 @@ import ( "net/http" chaosv1beta1 "github.com/DataDog/chaos-controller/api/v1beta1" - "github.com/DataDog/chaos-controller/mocks" + "github.com/DataDog/chaos-controller/cmd/mocks" "github.com/DataDog/chaos-controller/watchers" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" diff --git a/watchers/factory_test.go b/watchers/factory_test.go index 9e9045aaba..0f5a164268 100644 --- a/watchers/factory_test.go +++ b/watchers/factory_test.go @@ -7,7 +7,7 @@ package watchers_test import ( chaosv1beta1 "github.com/DataDog/chaos-controller/api/v1beta1" - "github.com/DataDog/chaos-controller/mocks" + "github.com/DataDog/chaos-controller/cmd/mocks" "github.com/DataDog/chaos-controller/o11y/metrics/noop" "github.com/DataDog/chaos-controller/types" chaostypes "github.com/DataDog/chaos-controller/types" diff --git a/watchers/manager_test.go b/watchers/manager_test.go index 05f00815db..8b1a391f1e 100644 --- a/watchers/manager_test.go +++ b/watchers/manager_test.go @@ -10,7 +10,7 @@ import ( "net/http" "github.com/DataDog/chaos-controller/api/v1beta1" - "github.com/DataDog/chaos-controller/mocks" + "github.com/DataDog/chaos-controller/cmd/mocks" . "github.com/DataDog/chaos-controller/watchers" "github.com/stretchr/testify/mock" "k8s.io/apimachinery/pkg/api/errors" diff --git a/watchers/shared_handler_test.go b/watchers/shared_handler_test.go index e08f982737..a66b179198 100644 --- a/watchers/shared_handler_test.go +++ b/watchers/shared_handler_test.go @@ -10,7 +10,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/tools/record" - "github.com/DataDog/chaos-controller/mocks" + "github.com/DataDog/chaos-controller/cmd/mocks" chaostypes "github.com/DataDog/chaos-controller/types" "github.com/DataDog/chaos-controller/watchers" "github.com/stretchr/testify/mock" diff --git a/watchers/watcher_test.go b/watchers/watcher_test.go index dd392b4916..abb6f1a1fa 100644 --- a/watchers/watcher_test.go +++ b/watchers/watcher_test.go @@ -15,7 +15,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/source" - "github.com/DataDog/chaos-controller/mocks" + "github.com/DataDog/chaos-controller/cmd/mocks" "github.com/DataDog/chaos-controller/watchers" "github.com/stretchr/testify/mock" diff --git a/webhook/userinfo_mutator_test.go b/webhook/userinfo_mutator_test.go index 1cab0b83a3..fc24d7235f 100644 --- a/webhook/userinfo_mutator_test.go +++ b/webhook/userinfo_mutator_test.go @@ -11,7 +11,7 @@ import ( "net/http" "github.com/DataDog/chaos-controller/api/v1beta1" - "github.com/DataDog/chaos-controller/mocks" + "github.com/DataDog/chaos-controller/cmd/mocks" "github.com/DataDog/chaos-controller/webhook" "go.uber.org/zap" "go.uber.org/zap/zaptest"