Skip to content

feat(controller): customize PDB value#456

Open
Sudmota wants to merge 1 commit intodragonflydb:mainfrom
Sudmota:main
Open

feat(controller): customize PDB value#456
Sudmota wants to merge 1 commit intodragonflydb:mainfrom
Sudmota:main

Conversation

@Sudmota
Copy link

@Sudmota Sudmota commented Feb 12, 2026

Summary

This PR allows for customizing the values for the PDB when replicas > 1, by accepting values other than "1", which is currently hardcoded. In the absence of a custom PDB, the operator falls back to the previous behaviour.

Changes

  • Add Pdb field to DragonflySpec in api/v1alpha1/dragonfly_types.go
  • Regenerate CRD manifests and deepcopy functions
  • Alter the handling of the PDB in internal/resources/resources.go, so that, in case replicas > 1:
    • if maxUnavailable is set in the CR, that one is used
    • else if minAvailable is set in the CR, that one is used
    • else, maxUnavailable = 1 is used (old behaviour)

Example Usage

apiVersion: dragonflydb.io/v1alpha1
kind: Dragonfly
metadata:
  name: dragonfly-sample
spec:
  replicas: 3
  pdb:
    maxUnavailable: 25%

Testing

Tested in Kubernetes v1.31.0:

  • pdb not specified in CR
  • pdb.maxUnavailable specified with an integer in CR
  • pdb.maxUnavailable specified with a percentage in CR
  • pdb.minAvailable specified with an integer in CR
  • pdb.minAvailable specified with a percentage in CR

Signed-off-by: Eduardo Mota <eduardo.mota@farfetch.com>
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds customization support for PodDisruptionBudget (PDB) configuration in Dragonfly deployments with replicas > 1. Previously, the PDB was hardcoded with maxUnavailable: 1. Now users can specify custom minAvailable or maxUnavailable values (as integers or percentages) through the Dragonfly CR spec.

Changes:

  • Added PdbSpec struct to the API with MinAvailable and MaxUnavailable string fields
  • Updated PDB generation logic to use custom values when specified, falling back to default behavior
  • Regenerated CRD manifests and deepcopy functions to reflect the new API

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.

File Description
api/v1alpha1/dragonfly_types.go Adds PdbSpec struct with MinAvailable and MaxUnavailable fields to DragonflySpec
api/v1alpha1/zz_generated.deepcopy.go Auto-generated deepcopy methods for the new PdbSpec type
config/crd/bases/dragonflydb.io_dragonflies.yaml CRD manifest updated with pdb configuration schema
internal/resources/resources.go Modified PDB generation to conditionally apply custom or default values

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +185 to +190
// (Optional) Dragonfly Pod Disruption Budget minAvailable configuration
// +optional
// +kubebuilder:validation:Optional
MinAvailable string `json:"minAvailable,omitempty"`

// (Optional) Dragonfly Pod Disruption Budget maxUnavailable configuration
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

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

The documentation comments for MinAvailable and MaxUnavailable are generic and don't provide guidance on expected values or format. Consider enhancing these comments to clarify:

  1. That these fields accept either an integer (e.g., "1") or a percentage (e.g., "25%")
  2. That only one of these fields should be specified, not both
  3. A brief explanation of what each field controls

For example: "An integer (e.g., 1) or percentage (e.g., 25%) representing the minimum number of pods that must be available during disruptions. Cannot be used together with maxUnavailable."

This would improve the developer experience by making the API more self-documenting and reduce the likelihood of misconfiguration.

Suggested change
// (Optional) Dragonfly Pod Disruption Budget minAvailable configuration
// +optional
// +kubebuilder:validation:Optional
MinAvailable string `json:"minAvailable,omitempty"`
// (Optional) Dragonfly Pod Disruption Budget maxUnavailable configuration
// (Optional) Minimum number of Dragonfly pods that must be available during voluntary disruptions.
// Accepts an absolute number (e.g. "1") or a percentage of total pods (e.g. "25%").
// Cannot be used together with MaxUnavailable; only one of minAvailable or maxUnavailable should be set.
// +optional
// +kubebuilder:validation:Optional
MinAvailable string `json:"minAvailable,omitempty"`
// (Optional) Maximum number of Dragonfly pods that can be unavailable during voluntary disruptions.
// Accepts an absolute number (e.g. "1") or a percentage of total pods (e.g. "25%").
// Cannot be used together with MinAvailable; only one of maxUnavailable or minAvailable should be set.

Copilot uses AI. Check for mistakes.
Comment on lines +485 to +496
if df.Spec.Pdb.MaxUnavailable != "" {
maxUnavailable := intstr.Parse(df.Spec.Pdb.MaxUnavailable)
pdb.Spec.MaxUnavailable = &maxUnavailable
} else if df.Spec.Pdb.MinAvailable != "" {
minAvailable := intstr.Parse(df.Spec.Pdb.MinAvailable)
pdb.Spec.MinAvailable = &minAvailable
} else {
pdb.Spec.MaxUnavailable = &intstr.IntOrString{
Type: intstr.Int,
IntVal: 1,
}
}
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

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

Potential nil pointer dereference: The code accesses df.Spec.Pdb.MaxUnavailable and df.Spec.Pdb.MinAvailable without first checking if df.Spec.Pdb is nil. Since Pdb is an optional pointer field (defined as *PdbSpec), it can be nil when not specified in the CR.

The code should follow the established pattern seen elsewhere in this file (e.g., lines 159, 164, 169, 442) where optional pointer fields are checked for nil before accessing their members. The check should wrap the entire conditional block.

Copilot uses AI. Check for mistakes.
Comment on lines +184 to 194
type PdbSpec struct {
// (Optional) Dragonfly Pod Disruption Budget minAvailable configuration
// +optional
// +kubebuilder:validation:Optional
MinAvailable string `json:"minAvailable,omitempty"`

// (Optional) Dragonfly Pod Disruption Budget maxUnavailable configuration
// +optional
// +kubebuilder:validation:Optional
MaxUnavailable string `json:"maxUnavailable,omitempty"`
}
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

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

The PdbSpec struct allows setting both MinAvailable and MaxAvailable fields simultaneously, which could lead to confusion for users. According to Kubernetes PodDisruptionBudget API semantics, only one of these fields should be specified.

While the implementation in resources.go safely handles this by prioritizing MaxUnavailable, it would be better to add kubebuilder validation markers to enforce mutual exclusivity at the API level, preventing users from creating invalid configurations. Consider adding a webhook validator or CEL validation rule to ensure only one field is set.

Copilot uses AI. Check for mistakes.
Comment on lines +485 to +495
if df.Spec.Pdb.MaxUnavailable != "" {
maxUnavailable := intstr.Parse(df.Spec.Pdb.MaxUnavailable)
pdb.Spec.MaxUnavailable = &maxUnavailable
} else if df.Spec.Pdb.MinAvailable != "" {
minAvailable := intstr.Parse(df.Spec.Pdb.MinAvailable)
pdb.Spec.MinAvailable = &minAvailable
} else {
pdb.Spec.MaxUnavailable = &intstr.IntOrString{
Type: intstr.Int,
IntVal: 1,
}
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

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

The new PDB configuration logic lacks unit test coverage. The existing test file internal/resources/resources_test.go contains tests for other functions like mergeNamedSlices, establishing a pattern of testing utility functions in this package.

The PDB configuration logic should have tests covering:

  1. When Pdb is nil (default behavior with maxUnavailable=1)
  2. When Pdb.MaxUnavailable is set with an integer
  3. When Pdb.MaxUnavailable is set with a percentage
  4. When Pdb.MinAvailable is set with an integer
  5. When Pdb.MinAvailable is set with a percentage
  6. When both fields are set (verifying maxUnavailable takes precedence)

These test cases align with the testing performed manually according to the PR description.

Suggested change
if df.Spec.Pdb.MaxUnavailable != "" {
maxUnavailable := intstr.Parse(df.Spec.Pdb.MaxUnavailable)
pdb.Spec.MaxUnavailable = &maxUnavailable
} else if df.Spec.Pdb.MinAvailable != "" {
minAvailable := intstr.Parse(df.Spec.Pdb.MinAvailable)
pdb.Spec.MinAvailable = &minAvailable
} else {
pdb.Spec.MaxUnavailable = &intstr.IntOrString{
Type: intstr.Int,
IntVal: 1,
}
if df.Spec.Pdb == nil || (df.Spec.Pdb.MaxUnavailable == "" && df.Spec.Pdb.MinAvailable == "") {
// Default behavior: maxUnavailable = 1 when Pdb is nil or both fields are unset
pdb.Spec.MaxUnavailable = &intstr.IntOrString{
Type: intstr.Int,
IntVal: 1,
}
} else if df.Spec.Pdb.MaxUnavailable != "" {
maxUnavailable := intstr.Parse(df.Spec.Pdb.MaxUnavailable)
pdb.Spec.MaxUnavailable = &maxUnavailable
} else if df.Spec.Pdb.MinAvailable != "" {
minAvailable := intstr.Parse(df.Spec.Pdb.MinAvailable)
pdb.Spec.MinAvailable = &minAvailable

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant