Skip to content
Merged
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
project: charts/redpanda
kind: Deprecated
body: '- `statefulset.sideCars.controllers.createRBAC` is deprecated and no longer respected. In most cases, setting this field to `false` would result in a broken deployment. RBAC may be controlled via `rbac.enabled` or per controller via `statefulset.sideCars.controllers.{pvcUnbinder,brokerDecommissioner}.enabled`.'
time: 2025-10-21T14:38:34.206376-04:00
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
project: charts/redpanda
kind: Deprecated
body: '`statefulset.sideCars.controllers.run` has been unused for many releases and is now deprecated. Individual controllers may be enabled/disabled by setting their enabled field: `statefulset.sideCars.pvcUnbinder.enabled`, `statefulset.sideCars.brokerDecommissioner.enabled`.'
time: 2025-10-21T14:44:13.331483-04:00
4 changes: 3 additions & 1 deletion Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ tasks:
- task: build:image
vars:
CLI_ARGS: '' # Don't forward CLI args to build:image
- task: build:charts
vars:
RUN: '{{ default `"^TestIntegration"` .RUN }}'
cmds:
Expand All @@ -204,6 +205,7 @@ tasks:
- task: build:charts
vars:
CLI_ARGS: '' # Don't forward CLI args to build:image
- task: build:charts
vars:
RUN: '{{ default `"^TestAcceptance"` .RUN }}'
GO_TEST_RUNNER: '{{default "go test" .GO_TEST_RUNNER}}'
Expand All @@ -215,7 +217,7 @@ tasks:
# Minor speed up only building the acceptance package, which (surprise
# surprise) is the only package with acceptance tests.
PKG: ./acceptance/
CLI_ARGS: '{{.CLI_ARGS}} -run {{.RUN}} -timeout 35m -tags acceptance'
CLI_ARGS: '{{.CLI_ARGS}} -run {{.RUN}} -timeout 55m -tags acceptance'

test:pull-images:
vars:
Expand Down
2 changes: 1 addition & 1 deletion acceptance/features/decommissioning.feature
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ Feature: Decommissioning brokers
When I physically shutdown a kubernetes node for cluster "decommissioning"
And cluster "decommissioning" is unhealthy
And cluster "decommissioning" has only 2 remaining nodes
And I prune any kubernetes node that is now in a NotReady status
And I prune kubernetes node that was removed in previous step
Then cluster "decommissioning" should recover
And cluster "decommissioning" should be stable with 3 nodes
39 changes: 39 additions & 0 deletions acceptance/features/helm-chart.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
@operator:none
Feature: Redpanda Helm Chart

Scenario: Tolerating Node Failure
Given I helm install "redpanda" "../charts/redpanda" with values:
```yaml
nameOverride: foobar
fullnameOverride: bazquux

statefulset:
sideCars:
image:
tag: dev
repository: localhost/redpanda-operator
pvcUnbinder:
enabled: true
unbindAfter: 15s
brokerDecommissioner:
enabled: true
decommissionAfter: 15s
```
When I stop the Node running Pod "bazquux-2"
And Pod "bazquux-2" is eventually Pending
Then Pod "bazquux-2" will eventually be Running
And kubectl exec -it "bazquux-0" "rpk redpanda admin brokers list | sed -E 's/\s+/ /gm' | cut -d ' ' -f 1,6" will eventually output:
```
ID MEMBERSHIP
0 active
1 active
3 active
```
And kubectl exec -it "bazquux-0" "rpk redpanda admin brokers list --include-decommissioned | sed -E 's/\s+/ /gm' | cut -d ' ' -f 1,6" will eventually output:
```
ID MEMBERSHIP
0 active
1 active
3 active
2 -
```
2 changes: 1 addition & 1 deletion acceptance/features/migration.feature
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Feature: Helm chart to Redpanda Operator migration

@skip:gke @skip:aks @skip:eks
Scenario: Migrate from a Helm chart release to a Redpanda custom resource
Given a Helm release named "redpanda-migration-example" of the "redpanda/redpanda" helm chart with the values:
Given I helm install "redpanda-migration-example" "../charts/redpanda" with values:
"""
# tag::helm-values[]
fullnameOverride: name-override
Expand Down
58 changes: 52 additions & 6 deletions acceptance/features/operator-upgrades.feature
Original file line number Diff line number Diff line change
@@ -1,31 +1,77 @@
@operator:none
Feature: Upgrading the operator

@skip:gke @skip:aks @skip:eks
Scenario: Operator upgrade from 2.3.x
Given I install redpanda helm chart version "v2.3.9-24.3.11" with the values:
Given I kubectl kustomize "https://github.com/redpanda-data/redpanda-operator//operator/config/crd?ref=v2.3.9-24.3.11" | kubectl apply -f - --server-side
And I helm install "redpanda-operator" "redpanda/operator" --version v2.3.9-24.3.11 with values:
"""

"""
And I apply Kubernetes manifest:
"""
---
apiVersion: cluster.redpanda.com/v1alpha2
kind: Redpanda
metadata:
name: operator-upgrade
name: operator-upgrade-2-3
spec:
clusterSpec:
statefulset:
replicas: 1
"""
# use just a Ready status check here since that's all the
# old operator supports
And cluster "operator-upgrade" is available
Then I can upgrade to the latest operator with the values:
And cluster "operator-upgrade-2-3" is available
Then I can helm upgrade "redpanda-operator" "../operator/chart" with values:
"""
image:
tag: dev
repository: localhost/redpanda-operator
crds:
enabled: true
experimental: true
"""
# use the new status as this will eventually get set
And cluster "operator-upgrade" should be stable with 1 nodes
And cluster "operator-upgrade-2-3" should be stable with 1 nodes

@skip:gke @skip:aks @skip:eks
Scenario: Operator upgrade from 2.4.x
Given I kubectl kustomize "https://github.com/redpanda-data/redpanda-operator//operator/config/crd?ref=operator/v2.4.5" | kubectl apply -f - --server-side
And I can helm install "redpanda-operator" "redpanda/operator" --version v2.4.5 with values:
"""
console:
enabled: false
"""
And I apply Kubernetes manifest:
"""
---
apiVersion: cluster.redpanda.com/v1alpha2
kind: Redpanda
metadata:
name: operator-upgrade-2-4
spec:
clusterSpec:
console:
enabled: false
statefulset:
replicas: 1
sideCars:
image:
tag: dev
repository: localhost/redpanda-operator
"""
# use just a Ready status check here since that's all the
# old operator supports
And cluster "operator-upgrade-2-4" is available
Then I can helm upgrade "redpanda-operator" "../operator/chart" with values:
"""
image:
tag: dev
repository: localhost/redpanda-operator
crds:
enabled: true
experimental: true
"""
# use the new status as this will eventually get set
And cluster "operator-upgrade-2-4" should be stable with 1 nodes
2 changes: 1 addition & 1 deletion acceptance/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module github.com/redpanda-data/redpanda-operator/acceptance
go 1.24.3

require (
github.com/cockroachdb/errors v1.11.3
github.com/cucumber/godog v0.14.1
github.com/prometheus/common v0.64.0
github.com/redpanda-data/common-go/rpadmin v0.1.14
Expand Down Expand Up @@ -75,7 +76,6 @@ require (
github.com/chai2010/gettext-go v1.0.2 // indirect
github.com/cisco-open/k8s-objectmatcher v1.9.0 // indirect
github.com/cloudhut/common v0.10.0 // indirect
github.com/cockroachdb/errors v1.11.3 // indirect
github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect
github.com/cockroachdb/redact v1.1.5 // indirect
github.com/containerd/containerd v1.7.27 // indirect
Expand Down
22 changes: 14 additions & 8 deletions acceptance/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,14 @@ import (
"testing"

"github.com/stretchr/testify/require"
"k8s.io/utils/ptr"

_ "github.com/redpanda-data/redpanda-operator/acceptance/steps"
framework "github.com/redpanda-data/redpanda-operator/harpoon"
"github.com/redpanda-data/redpanda-operator/harpoon/providers"
redpandav1alpha1 "github.com/redpanda-data/redpanda-operator/operator/api/redpanda/v1alpha1"
redpandav1alpha2 "github.com/redpanda-data/redpanda-operator/operator/api/redpanda/v1alpha2"
operatorchart "github.com/redpanda-data/redpanda-operator/operator/chart"
"github.com/redpanda-data/redpanda-operator/pkg/helm"
"github.com/redpanda-data/redpanda-operator/pkg/otelutil"
"github.com/redpanda-data/redpanda-operator/pkg/testutil"
Expand Down Expand Up @@ -76,16 +78,20 @@ var setupSuite = sync.OnceValues(func() (*framework.Suite, error) {
return
}
t.Log("Installing default Redpanda operator chart")
t.InstallLocalHelmChart(ctx, "../operator/chart", helm.InstallOptions{
t.InstallHelmChart(ctx, "../operator/chart", helm.InstallOptions{
Name: "redpanda-operator",
Namespace: namespace,
Values: map[string]any{
"logLevel": "trace",
"image": map[string]any{
"tag": imageTag,
"repository": imageRepo,
Values: operatorchart.PartialValues{
LogLevel: ptr.To("trace"),
Image: &operatorchart.PartialImage{
Tag: ptr.To(imageTag),
Repository: ptr.To(imageRepo),
},
"additionalCmdFlags": []string{
CRDs: &operatorchart.PartialCRDs{
Enabled: ptr.To(true),
Experimental: ptr.To(true),
},
AdditionalCmdFlags: []string{
// These are needed for running decommissioning tests.
"--additional-controllers=all",
"--unbind-pvcs-after=5s",
Expand Down Expand Up @@ -140,7 +146,7 @@ func OperatorTag(ctx context.Context, t framework.TestingT, args ...string) cont
}

t.Logf("Installing Redpanda operator chart: %q", name)
t.InstallLocalHelmChart(ctx, "../operator/chart", helm.InstallOptions{
t.InstallHelmChart(ctx, "../operator/chart", helm.InstallOptions{
Name: "redpanda-operator",
Namespace: t.Namespace(),
ValuesFile: filepath.Join("operator", fmt.Sprintf("%s.yaml", name)),
Expand Down
29 changes: 28 additions & 1 deletion acceptance/steps/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ func checkClusterHealthCondition(ctx context.Context, t framework.TestingT, clus
t.Logf("Cluster %q contains Healthy reason %q!", clusterName, reason)
}

func shutdownRandomClusterNode(ctx context.Context, t framework.TestingT, clusterName string) {
func shutdownRandomClusterNode(ctx context.Context, t framework.TestingT, clusterName string) context.Context {
var clusterSet appsv1.StatefulSet

key := t.ResourceKey(clusterName)
Expand All @@ -123,6 +123,27 @@ func shutdownRandomClusterNode(ctx context.Context, t framework.TestingT, cluste
pod := pods.Items[index]

t.ShutdownNode(ctx, pod.Spec.NodeName)
return context.WithValue(ctx, recordedVariable("ShutdownNodeName"), pod.Spec.NodeName)
}

func shutdownNodeOfPod(ctx context.Context, t framework.TestingT, podName string) context.Context {
t.ResourceKey(podName)

var pod corev1.Pod
require.NoError(t, t.Get(ctx, t.ResourceKey(podName), &pod))

var node corev1.Node
require.NoError(t, t.Get(ctx, t.ResourceKey(pod.Spec.NodeName), &node))

node.Spec.Taints = append(node.Spec.Taints, corev1.Taint{
Key: "node.kubernetes.io/out-of-service",
Effect: corev1.TaintEffectNoExecute,
})

require.NoError(t, t.Update(ctx, &node))

t.ShutdownNode(ctx, pod.Spec.NodeName)
return context.WithValue(ctx, recordedVariable("ShutdownNodeName"), pod.Spec.NodeName)
}

func deleteNotReadyKubernetesNodes(ctx context.Context, t framework.TestingT) {
Expand All @@ -138,6 +159,12 @@ func deleteNotReadyKubernetesNodes(ctx context.Context, t framework.TestingT) {
}
}

func deleteKubernetesNodesFromContext(ctx context.Context, t framework.TestingT) {
shutdownNodeName := ctx.Value(recordedVariable("ShutdownNodeName"))
t.Logf("Deleting Kubernetes node: %q", shutdownNodeName)
t.DeleteNode(ctx, shutdownNodeName.(string))
}

func checkClusterNodeCount(ctx context.Context, t framework.TestingT, clusterName string, nodeCount int32) {
var cluster redpandav1alpha2.Redpanda
var actualNodeCount int32
Expand Down
35 changes: 20 additions & 15 deletions acceptance/steps/helm.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,40 +3,45 @@ package steps
import (
"context"
"fmt"
"strings"

"github.com/cucumber/godog"
"github.com/stretchr/testify/require"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/rest"
"sigs.k8s.io/yaml"

framework "github.com/redpanda-data/redpanda-operator/harpoon"
"github.com/redpanda-data/redpanda-operator/pkg/helm"
)

// The unused parameter is meant to specify a Helm chart place (remote or local in the file system).
func iInstallHelmRelease(ctx context.Context, t framework.TestingT, helmReleaseName, _ string, values *godog.DocString) {
func iHelmInstall(ctx context.Context, t framework.TestingT, name, chart, version string, values *godog.DocString) {
// We don't really reference anything other than the redpanda repo, so just
// handle repos as a naive check here.
if strings.HasPrefix(chart, "redpanda/") {
t.AddHelmRepo(ctx, "redpanda", "https://charts.redpanda.com")
}

var valuesMap map[string]any
require.NoError(t, yaml.Unmarshal([]byte(values.Content), &valuesMap))

helmClient, err := helm.New(helm.Options{
KubeConfig: rest.CopyConfig(t.RestConfig()),
t.InstallHelmChart(ctx, chart, helm.InstallOptions{
Name: name,
Version: version,
Values: valuesMap,
Namespace: t.Namespace(),
})
require.NoError(t, err)

require.NoError(t, helmClient.RepoAdd(ctx, "console", "https://charts.redpanda.com"))
}

path := "../charts/redpanda"
require.NoError(t, helmClient.DependencyBuild(ctx, path))
func iHelmUpgrade(ctx context.Context, t framework.TestingT, name, chart, version string, values *godog.DocString) {
var valuesMap map[string]any
require.NoError(t, yaml.Unmarshal([]byte(values.Content), &valuesMap))

t.Logf("installing chart %q", path)
_, err = helmClient.Install(ctx, path, helm.InstallOptions{
Name: helmReleaseName,
Namespace: t.Namespace(),
t.UpgradeHelmChart(ctx, name, chart, helm.UpgradeOptions{
Version: version,
Values: valuesMap,
Namespace: t.Namespace(),
})
require.NoError(t, err)
}

func iDeleteHelmReleaseSecret(ctx context.Context, t framework.TestingT, helmReleaseName string) {
Expand Down
14 changes: 0 additions & 14 deletions acceptance/steps/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,7 @@ import (
authenticationv1 "k8s.io/api/authentication/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/client-go/kubernetes"
"k8s.io/utils/ptr"
runtimeclient "sigs.k8s.io/controller-runtime/pkg/client"
Expand Down Expand Up @@ -476,15 +474,3 @@ func clientsForOperator(ctx context.Context, includeTLS bool, serviceAccountName
}},
}
}

func removeAllFinalizers(ctx context.Context, t framework.TestingT, gvk schema.GroupVersionKind) {
Copy link
Contributor

@chrisseto chrisseto Nov 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is unused as the upgrade tests are performed within a vCluster. (I'm pretty sure at least but I just noticed the isolated tag is missing in this branch)

list := &unstructured.UnstructuredList{}
list.SetGroupVersionKind(gvk)

require.NoError(t, t.List(ctx, list))
for i := range list.Items {
item := list.Items[i]
item.SetFinalizers(nil)
require.NoError(t, t.Update(ctx, &item))
}
}
Loading