Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
1 change: 1 addition & 0 deletions .goreleaser.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ before:
builds:
- id: controller
binary: manager
main: ./cmd
goos:
- linux
goarch:
Expand Down
2 changes: 1 addition & 1 deletion .local.mockery.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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: {}
Expand Down
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
10 changes: 5 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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) \
Expand Down Expand Up @@ -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))
Expand Down Expand Up @@ -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:
Expand Down
2 changes: 1 addition & 1 deletion PROJECT
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 1 addition & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -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

Expand Down
35 changes: 17 additions & 18 deletions api/v1beta1/disruption_cron_webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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(
Expand All @@ -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(
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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(
Expand Down
2 changes: 1 addition & 1 deletion api/v1beta1/disruption_cron_webhook_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
45 changes: 21 additions & 24 deletions api/v1beta1/disruption_webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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)
}
Expand Down
2 changes: 1 addition & 1 deletion api/v1beta1/disruption_webhook_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
3 changes: 1 addition & 2 deletions api/v1beta1/userinfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down Expand Up @@ -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
}
Expand Down
2 changes: 1 addition & 1 deletion bin/manager/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion cloudservice/manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
Loading