Skip to content
Open
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
19 changes: 11 additions & 8 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,11 @@ jobs:
fail_ci_if_error: false

integration-test:
name: Integration test
name: Integration tests
runs-on: ubuntu-24.04
needs: [check, unit-test]
strategy:
matrix:
matrix: &kubernetes-matrix
kubernetes: [1.32.0, 1.33.1, 1.34.0, 1.35.1]
steps:
- uses: actions/checkout@v6
Expand All @@ -64,18 +64,21 @@ jobs:
go-version-file: go.mod
- name: Install conntrack
run: sudo apt-get install -y conntrack
- uses: medyagh/setup-minikube@v0.0.21
- &setup-minikube
name: Start minikube
uses: medyagh/setup-minikube@v0.0.21
with:
kubernetes-version: ${{ matrix.kubernetes }}
minikube-version: 1.38.1
driver: none
- name: Add redisfailover CRD
- name: Install redisfailover CRD
run: kubectl create -f manifests/databases.spotahome.com_redisfailovers.yaml
- run: make ci-integration-test
- name: Run integration tests
run: make ci-integration-test

chart-test:
name: Chart testing
runs-on: ubuntu-latest
name: Chart tests
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
with:
Expand All @@ -84,7 +87,7 @@ jobs:
uses: azure/setup-helm@v4
with:
version: v3.7.2
- name: Helm test
- name: Run chart tests
run: make helm-test

docker:
Expand Down
41 changes: 41 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ helm repo update
helm install redis-operator redis-operator/redis-operator
```

The Helm chart includes values schema validation. Invalid combinations such as enabling RBAC while reusing an existing Service Account without setting `serviceAccount.name`, or enabling `imageCredentials.create` without either existing secrets or registry credentials, will fail during `helm lint`, `helm template` or `helm install`.

#### Update helm chart

Helm chart only manages the creation of CRD in the first installation. To update the CRD, you will need to apply it directly.
Expand All @@ -41,6 +43,45 @@ kubectl replace -f https://raw.githubusercontent.com/Saremox/redis-operator/${RE
```
helm upgrade redis-operator redis-operator/redis-operator
```

#### Helm chart configuration

The chart exposes a small set of options to customize operator deployment:

- `imagePullSecrets` to reuse existing image pull secrets in the release namespace.
- `imageCredentials` to create a pull secret from registry credentials, or reference existing secrets with `imageCredentials.existsSecrets`.
- `serviceAccount.create`, `serviceAccount.name` and `serviceAccount.annotations` to create or reuse the Service Account used by the operator.
- `rbac.create` to control creation of RBAC resources.
- `podSecurityContext` and `containerSecurityContext` to configure pod and container security settings.
- `operator.*` and `operator.extraArgs` to configure operator CLI flags.
- `extraEnv` to add extra environment variables to the operator container.

The following chart values are deprecated:

- `image.cli_args`: prefer `operator.*` values or `operator.extraArgs`.
- `securityContext`: prefer `podSecurityContext` and `containerSecurityContext`.

Example:

```yaml
imagePullSecrets:
- registrysecret

serviceAccount:
create: false
name: redis-operator

operator:
logLevel: debug
supportedNamespacesRegex: "prod-.*"
extraArgs:
- --concurrency=5

extraEnv:
- name: HTTP_PROXY
value: http://proxy.example:8080
```

### Using kubectl

To create the operator, you can directly create it with kubectl:
Expand Down
2 changes: 1 addition & 1 deletion charts/redisoperator/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@ keywords:
- "cluster"
sources:
- https://github.com/saremox/redis-operator
kubeVersion: ">=1.32.0-0"
kubeVersion: ">=1.22.0-0"
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

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

kubeVersion is relaxed to ">=1.22.0-0", but the CI Kubernetes matrix shown in this PR only runs integration tests on 1.32+. If the chart is intended to support 1.22, consider adding at least one older version to the test matrix (or keep kubeVersion aligned with what is exercised in CI) to avoid advertising untested compatibility.

Suggested change
kubeVersion: ">=1.22.0-0"
kubeVersion: ">=1.32.0-0"

Copilot uses AI. Check for mistakes.
115 changes: 103 additions & 12 deletions charts/redisoperator/templates/deployment.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,87 @@
{{- $fullName := include "chart.fullname" . -}}
{{ $name := "registry" }}
{{- $name := "registry" -}}
{{- $data := dict "Chart" .Chart "Release" .Release "Values" .Values -}}
{{- $legacySecurityContext := .Values.securityContext | default dict -}}
{{- $podSecurityContext := dict -}}
{{- $containerSecurityContext := dict -}}
{{- if $legacySecurityContext }}
{{- /* Start from legacy securityContext, then let new values override. */ -}}
{{- $podSecurityContext = merge (pick $legacySecurityContext "fsGroup" "fsGroupChangePolicy" "supplementalGroups" "supplementalGroupsPolicy" "sysctls") (.Values.podSecurityContext | default dict) -}}
{{- $containerSecurityContext = merge (omit $legacySecurityContext "fsGroup" "fsGroupChangePolicy" "supplementalGroups" "supplementalGroupsPolicy" "sysctls") (.Values.containerSecurityContext | default dict) -}}
Comment on lines +9 to +10
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

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

The comment says new podSecurityContext / containerSecurityContext values should override the legacy securityContext, but Sprig/Helm merge keeps existing keys from the first map (it does not overwrite). As written, legacy keys can win over the new values. Consider swapping merge order (new values first) or using an overwrite merge function so the override behavior matches the intent.

Suggested change
{{- $podSecurityContext = merge (pick $legacySecurityContext "fsGroup" "fsGroupChangePolicy" "supplementalGroups" "supplementalGroupsPolicy" "sysctls") (.Values.podSecurityContext | default dict) -}}
{{- $containerSecurityContext = merge (omit $legacySecurityContext "fsGroup" "fsGroupChangePolicy" "supplementalGroups" "supplementalGroupsPolicy" "sysctls") (.Values.containerSecurityContext | default dict) -}}
{{- $podSecurityContext = merge (.Values.podSecurityContext | default dict) (pick $legacySecurityContext "fsGroup" "fsGroupChangePolicy" "supplementalGroups" "supplementalGroupsPolicy" "sysctls") -}}
{{- $containerSecurityContext = merge (.Values.containerSecurityContext | default dict) (omit $legacySecurityContext "fsGroup" "fsGroupChangePolicy" "supplementalGroups" "supplementalGroupsPolicy" "sysctls") -}}

Copilot uses AI. Check for mistakes.
{{- else }}
{{- /* No legacy securityContext: just use the new values (or {} if unset). */ -}}
{{- $podSecurityContext = .Values.podSecurityContext | default dict -}}
{{- $containerSecurityContext = .Values.containerSecurityContext | default dict -}}
{{- end }}
{{- $imagePullSecrets := list -}}
{{- with .Values.imagePullSecrets }}
{{- range . }}
{{- $secretName := trim . -}}
{{- if $secretName }}
{{- $imagePullSecrets = append $imagePullSecrets (dict "name" $secretName) -}}
{{- end }}
{{- end }}
{{- end }}
{{- with .Values.imageCredentials.existsSecrets }}
{{- range . }}
{{- $secretName := trim . -}}
{{- if $secretName }}
{{- $imagePullSecrets = append $imagePullSecrets (dict "name" $secretName) -}}
{{- end }}
{{- end }}
{{- end }}
{{- if .Values.imageCredentials.create }}
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

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

imageCredentials.create=true always appends the auto-generated secret name to imagePullSecrets, but templates/private-registry.yaml only creates that secret when imageCredentials.existsSecrets is empty. If users set both imageCredentials.create=true and imageCredentials.existsSecrets (which the schema allows), the Deployment will reference a non-existent secret and Pods will fail to pull images. Only append the generated secret when it will actually be created (or change the secret template to always create it when create=true).

Suggested change
{{- if .Values.imageCredentials.create }}
{{- if and .Values.imageCredentials.create (not .Values.imageCredentials.existsSecrets) }}

Copilot uses AI. Check for mistakes.
{{- $imagePullSecrets = append $imagePullSecrets (dict "name" (printf "%s-%s" $fullName $name)) -}}
{{- end }}
{{- $args := list -}}
{{- with .Values.operator.logLevel }}
{{- if ne . "" }}
{{- $args = append $args (printf "--log-level=%s" .) -}}
{{- end }}
{{- end }}
{{- with .Values.operator.supportedNamespacesRegex }}
{{- if ne . "" }}
{{- $args = append $args (printf "--supported-namespaces-regex=%s" .) -}}
{{- end }}
{{- end }}
{{- with .Values.operator.listenAddress }}
{{- if ne . "" }}
{{- $args = append $args (printf "--listen-address=%s" .) -}}
{{- end }}
{{- end }}
{{- with .Values.operator.metricsPath }}
{{- if ne . "" }}
{{- $args = append $args (printf "--metrics-path=%s" .) -}}
{{- end }}
{{- end }}
{{- with .Values.operator.k8sCliQpsLimit }}
{{- $args = append $args (printf "--k8s-cli-qps-limit=%v" .) -}}
{{- end }}
{{- with .Values.operator.k8sCliBurstableLimit }}
{{- $args = append $args (printf "--k8s-cli-burstable-limit=%v" .) -}}
{{- end }}
{{- with .Values.operator.concurrency }}
{{- $args = append $args (printf "--concurrency=%v" .) -}}
{{- end }}
{{- with .Values.operator.syncInterval }}
{{- $args = append $args (printf "--sync-interval=%v" .) -}}
{{- end }}
{{- with .Values.operator.extraArgs }}
{{- range . }}
{{- $arg := trim . -}}
{{- if $arg }}
{{- $args = append $args $arg -}}
{{- end }}
{{- end }}
{{- end }}
{{- with .Values.image.cli_args }}
{{- range (splitList " " (trim .)) }}
{{- $arg := trim . -}}
{{- if $arg }}
{{- $args = append $args $arg -}}
{{- end }}
Comment on lines +78 to +82
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

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

Splitting the deprecated image.cli_args string on spaces changes the previous behavior (it used to be passed as a single argument) and breaks cases where values include quoting/embedded spaces (e.g. --foo="a b"). For backward compatibility, keep image.cli_args as a single arg (or support a proper list-based legacy field) and avoid naive whitespace splitting.

Suggested change
{{- range (splitList " " (trim .)) }}
{{- $arg := trim . -}}
{{- if $arg }}
{{- $args = append $args $arg -}}
{{- end }}
{{- $arg := trim . -}}
{{- if $arg }}
{{- $args = append $args $arg -}}

Copilot uses AI. Check for mistakes.
{{- end }}
{{- end }}
apiVersion: {{ template "common.capabilities.deployment.apiVersion" . }}
kind: Deployment
metadata:
Expand Down Expand Up @@ -30,23 +111,31 @@ spec:
spec:
serviceAccountName: {{ template "chart.serviceAccountName" . }}
enableServiceLinks: false
{{- if (and .Values.imageCredentials.create (not .Values.imageCredentials.existsSecrets)) }}
imagePullSecrets:
- name: {{ $fullName }}-{{ $name }}
{{- else if (and .Values.imageCredentials.create .Values.imageCredentials.existsSecrets) }}
{{- range .Values.imageCredentials.existsSecrets }}
imagePullSecrets:
{{ printf "- name: %s" . }}
{{- if gt (len $podSecurityContext) 0 }}
securityContext:
{{- toYaml $podSecurityContext | nindent 8 }}
{{- end }}
{{- if gt (len $imagePullSecrets) 0 }}
imagePullSecrets:
{{- toYaml $imagePullSecrets | nindent 8 }}
{{- end }}
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion}}"
{{- if .Values.image.cli_args }}
args:
- {{ quote .Values.image.cli_args }}
{{- if gt (len $args) 0 }}
args:
{{- toYaml $args | nindent 10 }}
{{- end }}
imagePullPolicy: {{ .Values.image.pullPolicy }}
env:
- name: POD_NAMESPACE
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.namespace
{{- with .Values.extraEnv }}
{{- toYaml . | nindent 10 }}
{{- end }}
ports:
- name: metrics
containerPort: {{ .Values.container.port }}
Expand All @@ -65,8 +154,10 @@ spec:
timeoutSeconds: 5
failureThreshold: 6
successThreshold: 1
{{- if gt (len $containerSecurityContext) 0 }}
securityContext:
{{- toYaml .Values.securityContext | nindent 12 }}
{{- toYaml $containerSecurityContext | nindent 12 }}
{{- end }}
resources:
{{- toYaml .Values.resources | nindent 12 }}
{{- with .Values.affinity }}
Expand Down
13 changes: 11 additions & 2 deletions charts/redisoperator/templates/private-registry.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
{{- if (and .Values.imageCredentials.create (not .Values.imageCredentials.existsSecrets)) -}}
{{- $fullName := include "chart.fullname" . -}}
{{- $name := "registry" -}}
{{- $data := dict "name" $name "Chart" .Chart "Release" .Release "Values" .Values -}}
{{- $imageCredentialsSecrets := list -}}
{{- with .Values.imageCredentials.existsSecrets }}
{{- range . }}
{{- $secretName := trim . -}}
{{- if $secretName }}
{{- $imageCredentialsSecrets = append $imageCredentialsSecrets $secretName -}}
{{- end }}
{{- end }}
{{- end }}
{{- if and .Values.imageCredentials.create (eq (len $imageCredentialsSecrets) 0) -}}
apiVersion: v1
kind: Secret
metadata:
Expand All @@ -16,4 +25,4 @@ metadata:
type: kubernetes.io/dockerconfigjson
data:
.dockerconfigjson: {{ template "imagePullSecret" . }}
{{- end }}
{{- end }}
25 changes: 10 additions & 15 deletions charts/redisoperator/templates/service-account.yaml
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
{{ if .Values.serviceAccount.create }}
{{- $fullName := include "chart.fullname" . -}}
{{- $data := dict "Chart" .Chart "Release" .Release "Values" .Values -}}
{{- $serviceAccountName := include "chart.serviceAccountName" . -}}
{{- if .Values.serviceAccount.create }}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ $fullName }}
name: {{ $serviceAccountName }}
namespace: {{ include "chart.namespaceName" . }}
labels:
{{- include "chart.labels" $data | nindent 4 }}
{{- with .Values.serviceAccount.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}
{{- if .Values.rbac.create }}
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
Expand All @@ -29,18 +36,6 @@ rules:
- patch
- update
- watch
- apiGroups:
- apiextensions.k8s.io
resources:
- customresourcedefinitions
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- coordination.k8s.io
resources:
Expand Down Expand Up @@ -106,7 +101,7 @@ metadata:
name: {{ $fullName }}
subjects:
- kind: ServiceAccount
name: {{ $fullName }}
name: {{ $serviceAccountName }}
namespace: {{ include "chart.namespaceName" . }}
roleRef:
apiGroup: rbac.authorization.k8s.io
Expand Down
Loading
Loading