Repository: mariadb-operator/mariadb-operator

Issue:
[Bug] Unsafe dereferencing of optional MariaDB.Spec.Replication.Primary.AutomaticFailoverDelay causes panic in GetAutomaticFailoverDelay().
- [x] I acknowledge that I have read the relevant [documentation](https://github.com/mariadb-operator/mariadb-operator/tree/main/docs).

https://github.com/mariadb-operator/mariadb-operator/blob/8eb21ac8d3e7dbeb9e5b3d942cbd87ae1839a680/api/v1alpha1/mariadb_replication_types.go#L269

Unsafe dereferencing of optional `MariaDB.Spec.Replication.Primary.AutomaticFailoverDelay` causes panic in `GetAutomaticFailoverDelay()`: the function doesn't check if `MariaDB.Spec.Replication.Primary.AutomaticFailoverDelay` is `nil` before accessing `Duration`.

**Expected behaviour**
Automatic failover delay duration is returned if specified, otherwise default value (`0`?) is returned.

**Steps to reproduce the bug**
Panic happens every time `GetAutomaticFailoverDelay()` is called during master pod failover and it's not present in the CR.

- `mariadb-operator` logs.
```
{"level":"error","ts":1757438996.689212,"msg":"Observed a panic","controller":"pod-replication","controllerGroup":"","controllerKind":"Pod","Pod":{"name":"mariadb-repl-0","namespace":"default"},"namespace":"default","name":"mariadb-repl-0","reconcileID":"3369f320-40c5-4982-86ee-84896e3453e2","panic":"runtime error: invalid memory address or nil pointer dereference","panicGoValue":"\"invalid memory address or nil pointer dereference\"","stacktrace":"goroutine 953 [running]:\nk8s.io/apimachinery/pkg/util/runtime.logPanic({0x299a178, 0xc000b52f30}, {0x21feac0, 0x3dd7840})\n\t/go/pkg/mod/k8s.io/apimachinery@v0.33.3/pkg/util/runtime/runtime.go:132 +0xbc\nsigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller[...]).Reconcile.func1()\n\t/go/pkg/mod/sigs.k8s.io/controller-runtime@v0.21.0/pkg/internal/controller/controller.go:108 +0x112\npanic({0x21feac0?, 0x3dd7840?})\n\t/usr/local/go/src/runtime/panic.go:792 +0x132\ngithub.com/mariadb-operator/mariadb-operator/v25/api/v1alpha1.(*MariaDB).GetAutomatic...
```


Discussion:
@hedgieinsocks: Hm, when I added this feature, I also added the part where it sets the default value for it. Not sure yet where is the loophole.  @hedgieinsocks: If your CR does not have the default value for delay, perhaps the webhook.enabled is false in your helm chart? @bzakhar: I just upgraded the operator with existing MariaDB CR from pre-v25 and ran into this issue. It doesn't seem to be actually affecting the failover, but a panic is never a good thing to see in the logs...@hedgieinsocks: Could you pls try to suspend your mariadb  `spec.suspend: true` back and forth to simulate mariadb spec change and force operator to set missing defaults?

If this does not help, another guess is to check that CRD chart is properly upgraded as well.

And in general, maybe it makes sense to use kubebuilder default tag whenever possible to set defaults.@laurentiusoica: > Hm, when I added this feature, I also added the part where it sets the default value for it. Not sure yet where is the loophole.

Maybe on the very first Reconcile after startup, if the pod isn’t ready, ReconcilePodNotReady gets triggered before FillWithDefaults has run? If that's the case, maybe using m.Replication() instead of m.Spec.Replication it's a safer approach.@mmontes11: As @laurentiusoica said, accessing through `Replication()` is the desired way. I've opened a PR for this which will be released shortly in `25.8.4`:
- https://github.com/mariadb-operator/mariadb-operator/pull/1424

Regarding the overall replication feature to be GA, we are actively working on it:
- https://github.com/mariadb-operator/mariadb-operator/issues/1423

Solution patch:
diff --git a/.gitignore b/.gitignore
index c3323dd9..72e573b4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -47,3 +47,5 @@ pprof.out
 
 # Nvim config
 .nvim.lua
+
+.envrc
diff --git a/api/v1alpha1/mariadb_replication_types.go b/api/v1alpha1/mariadb_replication_types.go
index e34bf07c..08513fb2 100644
--- a/api/v1alpha1/mariadb_replication_types.go
+++ b/api/v1alpha1/mariadb_replication_types.go
@@ -96,20 +96,17 @@ type PrimaryReplication struct {
 	AutomaticFailoverDelay *metav1.Duration `json:"automaticFailoverDelay,omitempty"`
 }
 
-// FillWithDefaults fills the current PrimaryReplication object with DefaultReplicationSpec.
+// SetDefaults fills the current PrimaryReplication object with DefaultReplicationSpec.
 // This enables having minimal PrimaryReplication objects and provides sensible defaults.
-func (r *PrimaryReplication) FillWithDefaults() {
+func (r *PrimaryReplication) SetDefaults() {
 	if r.PodIndex == nil {
-		index := *DefaultReplicationSpec.Primary.PodIndex
-		r.PodIndex = &index
+		r.PodIndex = ptr.To(0)
 	}
 	if r.AutomaticFailover == nil {
-		failover := *DefaultReplicationSpec.Primary.AutomaticFailover
-		r.AutomaticFailover = &failover
+		r.AutomaticFailover = ptr.To(true)
 	}
 	if r.AutomaticFailoverDelay == nil {
-		failoverDelay := *DefaultReplicationSpec.Primary.AutomaticFailoverDelay
-		r.AutomaticFailoverDelay = &failoverDelay
+		r.AutomaticFailoverDelay = ptr.To(metav1.Duration{})
 	}
 }
 
@@ -155,28 +152,23 @@ type ReplicaReplication struct {
 	MaxLagSeconds *int `json:"maxLagSeconds,omitempty"`
 }
 
-// FillWithDefaults fills the current ReplicaReplication object with DefaultReplicationSpec.
+// SetDefaults fills the current ReplicaReplication object with DefaultReplicationSpec.
 // This enables having minimal ReplicaReplication objects and provides sensible defaults.
-func (r *ReplicaReplication) FillWithDefaults() {
+func (r *ReplicaReplication) SetDefaults() {
 	if r.WaitPoint == nil {
-		waitPoint := *DefaultReplicationSpec.Replica.WaitPoint
-		r.WaitPoint = &waitPoint
+		r.WaitPoint = ptr.To(WaitPointAfterCommit)
 	}
 	if r.Gtid == nil {
-		gtid := *DefaultReplicationSpec.Replica.Gtid
-		r.Gtid = &gtid
+		r.Gtid = ptr.To(GtidCurrentPos)
 	}
 	if r.ConnectionTimeout == nil {
-		timeout := *DefaultReplicationSpec.Replica.ConnectionTimeout
-		r.ConnectionTimeout = &timeout
+		r.ConnectionTimeout = ptr.To(metav1.Duration{Duration: 10 * time.Second})
 	}
 	if r.ConnectionRetries == nil {
-		retries := *DefaultReplicationSpec.Replica.ConnectionRetries
-		r.ConnectionRetries = &retries
+		r.ConnectionRetries = ptr.To(10)
 	}
 	if r.SyncTimeout == nil {
-		timeout := *DefaultReplicationSpec.Replica.SyncTimeout
-		r.SyncTimeout = &timeout
+		r.SyncTimeout = ptr.To(metav1.Duration{Duration: 10 * time.Second})
 	}
 }
 
@@ -206,48 +198,16 @@ type Replication struct {
 	Enabled bool `json:"enabled,omitempty"`
 }
 
-// SetDefaults sets reasonable defaults.
-func (r *Replication) SetDefaults(mdb *MariaDB, env *environment.OperatorEnv) error {
-	if r.GtidStrictMode == nil {
-		r.GtidStrictMode = ptr.To(true)
-	}
-	if reflect.ValueOf(r.InitContainer).IsZero() {
-		r.InitContainer = InitContainer{
-			Image: env.MariadbOperatorImage,
-		}
-	}
-	if err := r.Agent.SetDefaults(mdb, env); err != nil {
-		return fmt.Errorf("error setting agent defaults: %v", err)
-	}
-
-	autoUpdateDataPlane := ptr.Deref(mdb.Spec.UpdateStrategy.AutoUpdateDataPlane, false)
-	if autoUpdateDataPlane {
-		initBumped, err := docker.SetTagOrDigest(env.MariadbOperatorImage, r.InitContainer.Image)
-		if err != nil {
-			return fmt.Errorf("error bumping replication init image: %v", err)
-		}
-		r.InitContainer.Image = initBumped
-
-		agentBumped, err := docker.SetTagOrDigest(env.MariadbOperatorImage, r.Agent.Image)
-		if err != nil {
-			return fmt.Errorf("error bumping replication agent image: %v", err)
-		}
-		r.Agent.Image = agentBumped
-	}
-
-	return nil
-}
-
 // ReplicationSpec is the Replication desired state specification.
 type ReplicationSpec struct {
 	// Primary is the replication configuration for the primary node.
 	// +optional
 	// +operator-sdk:csv:customresourcedefinitions:type=spec,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:advanced"}
-	Primary *PrimaryReplication `json:"primary,omitempty"`
+	Primary PrimaryReplication `json:"primary,omitempty"`
 	// ReplicaReplication is the replication configuration for the replica nodes.
 	// +optional
 	// +operator-sdk:csv:customresourcedefinitions:type=spec,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:advanced"}
-	Replica *ReplicaReplication `json:"replica,omitempty"`
+	Replica ReplicaReplication `json:"replica,omitempty"`
 	// GtidStrictMode determines whether the GTID strict mode is enabled. See: https://mariadb.com/docs/server/ha-and-performance/standard-replication/gtid#gtid_strict_mode.
 	// It is enabled by default.
 	// +optional
@@ -268,52 +228,50 @@ type ReplicationSpec struct {
 	Agent Agent `json:"agent,omitempty"`
 }
 
-// FillWithDefaults fills the current ReplicationSpec object with DefaultReplicationSpec.
-// This enables having minimal ReplicationSpec objects and provides sensible defaults.
-func (r *ReplicationSpec) FillWithDefaults() {
-	if r.Primary == nil {
-		primary := *DefaultReplicationSpec.Primary
-		r.Primary = &primary
-	} else {
-		r.Primary.FillWithDefaults()
-	}
-	if r.Replica == nil {
-		replica := *DefaultReplicationSpec.Replica
-		r.Replica = &replica
-	} else {
-		r.Replica.FillWithDefaults()
+// SetDefaults fills the current Replication object with DefaultReplicationSpec.
+// This enables having minimal Replication objects and provides sensible defaults.
+func (r *Replication) SetDefaults(mdb *MariaDB, env *environment.OperatorEnv) error {
+	if r.GtidStrictMode == nil {
+		r.GtidStrictMode = ptr.To(true)
 	}
 	if r.SyncBinlog == nil {
-		syncBinlog := *DefaultReplicationSpec.SyncBinlog
-		r.SyncBinlog = &syncBinlog
+		r.SyncBinlog = ptr.To(1)
 	}
-}
 
-var (
-	tenSeconds = metav1.Duration{Duration: 10 * time.Second}
-
-	// DefaultReplicationSpec provides sensible defaults for the ReplicationSpec.
-	DefaultReplicationSpec = ReplicationSpec{
-		Primary: &PrimaryReplication{
-			PodIndex:               ptr.To(0),
-			AutomaticFailover:      ptr.To(true),
-			AutomaticFailoverDelay: ptr.To(metav1.Duration{}),
-		},
-		Replica: &ReplicaReplication{
-			WaitPoint:         ptr.To(WaitPointAfterCommit),
-			Gtid:              ptr.To(GtidCurrentPos),
-			ConnectionTimeout: ptr.To(tenSeconds),
-			ConnectionRetries: ptr.To(10),
-			SyncTimeout:       ptr.To(tenSeconds),
-		},
-		SyncBinlog: ptr.To(1),
+	if reflect.ValueOf(r.InitContainer).IsZero() {
+		r.InitContainer = InitContainer{
+			Image: env.MariadbOperatorImage,
+		}
 	}
-)
+	if err := r.Agent.SetDefaults(mdb, env); err != nil {
+		return fmt.Errorf("error setting agent defaults: %v", err)
+	}
+
+	autoUpdateDataPlane := ptr.Deref(mdb.Spec.UpdateStrategy.AutoUpdateDataPlane, false)
+	if autoUpdateDataPlane {
+		initBumped, err := docker.SetTagOrDigest(env.MariadbOperatorImage, r.InitContainer.Image)
+		if err != nil {
+			return fmt.Errorf("error bumping replication init image: %v", err)
+		}
+		r.InitContainer.Image = initBumped
+
+		agentBumped, err := docker.SetTagOrDigest(env.MariadbOperatorImage, r.Agent.Image)
+		if err != nil {
+			return fmt.Errorf("error bumping replication agent image: %v", err)
+		}
+		r.Agent.Image = agentBumped
+	}
+
+	r.Primary.SetDefaults()
+	r.Replica.SetDefaults()
+
+	return nil
+}
 
 // GetAutomaticFailoverDelay returns the duration of the automatic failover delay.
 func (m *MariaDB) GetAutomaticFailoverDelay() time.Duration {
-	primary := ptr.Deref(m.Replication().Primary, PrimaryReplication{})
-	automaticFailoverDelay := ptr.Deref(primary.AutomaticFailoverDelay, *DefaultReplicationSpec.Primary.AutomaticFailoverDelay)
+	primary := ptr.Deref(m.Spec.Replication, Replication{}).Primary
+	automaticFailoverDelay := ptr.Deref(primary.AutomaticFailoverDelay, metav1.Duration{})
 
 	return automaticFailoverDelay.Duration
 }
@@ -339,7 +297,7 @@ func (m *MariaDB) IsSwitchoverRequired() bool {
 		return false
 	}
 	currentPodIndex := ptr.Deref(m.Status.CurrentPrimaryPodIndex, 0)
-	desiredPodIndex := ptr.Deref(m.Replication().Primary.PodIndex, 0)
+	desiredPodIndex := ptr.Deref(ptr.Deref(m.Spec.Replication, Replication{}).Primary.PodIndex, 0)
 	return currentPodIndex != desiredPodIndex
 }
 
diff --git a/api/v1alpha1/mariadb_types.go b/api/v1alpha1/mariadb_types.go
index 557b1791..a68f7a7f 100644
--- a/api/v1alpha1/mariadb_types.go
+++ b/api/v1alpha1/mariadb_types.go
@@ -841,7 +841,7 @@ func (m *MariaDB) SetDefaults(env *environment.OperatorEnv) error {
 			return fmt.Errorf("error setting Galera defaults: %v", err)
 		}
 	}
-	if m.Spec.Replication != nil && m.Spec.Replication.Enabled {
+	if m.IsReplicationEnabled() {
 		if err := m.Spec.Replication.SetDefaults(m, env); err != nil {
 			return fmt.Errorf("error setting replication defaults: %v", err)
 		}
@@ -860,23 +860,19 @@ func (m *MariaDB) SetDefaults(env *environment.OperatorEnv) error {
 	return nil
 }
 
-// Replication with defaulting accessor
-func (m *MariaDB) Replication() Replication {
-	if m.Spec.Replication == nil {
-		m.Spec.Replication = &Replication{}
-	}
-	m.Spec.Replication.FillWithDefaults()
-	return *m.Spec.Replication
-}
-
-// IsHAEnabled indicates whether the MariaDB instance has Galera enabled
+// IsGaleraEnabled indicates whether the MariaDB instance has Galera enabled
 func (m *MariaDB) IsGaleraEnabled() bool {
 	return ptr.Deref(m.Spec.Galera, Galera{}).Enabled
 }
 
+// IsReplicationEnabled indicates whether the MariaDB instance has replication enabled
+func (m *MariaDB) IsReplicationEnabled() bool {
+	return ptr.Deref(m.Spec.Replication, Replication{}).Enabled
+}
+
 // IsHAEnabled indicates whether the MariaDB instance has HA enabled
 func (m *MariaDB) IsHAEnabled() bool {
-	return m.Replication().Enabled || m.IsGaleraEnabled()
+	return m.IsReplicationEnabled() || m.IsGaleraEnabled()
 }
 
 // IsMaxScaleEnabled indicates that a MaxScale instance is forwarding traffic to this MariaDB instance
@@ -953,7 +949,7 @@ func (m *MariaDB) IsResizingStorage() bool {
 	return meta.IsStatusConditionFalse(m.Status.Conditions, ConditionTypeStorageResized)
 }
 
-// IsResizingStorage indicates whether the MariaDB instance is waiting for storage resize
+// IsWaitingForStorageResize indicates whether the MariaDB instance is waiting for storage resize
 func (m *MariaDB) IsWaitingForStorageResize() bool {
 	condition := meta.FindStatusCondition(m.Status.Conditions, ConditionTypeStorageResized)
 	if condition == nil {
diff --git a/api/v1alpha1/maxscale_types.go b/api/v1alpha1/maxscale_types.go
index deaa91c6..9df81df4 100644
--- a/api/v1alpha1/maxscale_types.go
+++ b/api/v1alpha1/maxscale_types.go
@@ -537,7 +537,7 @@ func (m *MaxScaleTLS) SetDefaults(mdb *MariaDB) {
 		return
 	}
 
-	if mdb.Replication().Enabled && m.ReplicationSSLEnabled == nil {
+	if mdb.IsReplicationEnabled() && m.ReplicationSSLEnabled == nil {
 		m.ReplicationSSLEnabled = ptr.To(true)
 	}
 	if m.ServerCASecretRef == nil {
diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go
index 66dfcba6..9214e5b1 100644
--- a/api/v1alpha1/zz_generated.deepcopy.go
+++ b/api/v1alpha1/zz_generated.deepcopy.go
@@ -3878,16 +3878,8 @@ func (in *Replication) DeepCopy() *Replication {
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *ReplicationSpec) DeepCopyInto(out *ReplicationSpec) {
 	*out = *in
-	if in.Primary != nil {
-		in, out := &in.Primary, &out.Primary
-		*out = new(PrimaryReplication)
-		(*in).DeepCopyInto(*out)
-	}
-	if in.Replica != nil {
-		in, out := &in.Replica, &out.Replica
-		*out = new(ReplicaReplication)
-		(*in).DeepCopyInto(*out)
-	}
+	in.Primary.DeepCopyInto(&out.Primary)
+	in.Replica.DeepCopyInto(&out.Replica)
 	if in.GtidStrictMode != nil {
 		in, out := &in.GtidStrictMode, &out.GtidStrictMode
 		*out = new(bool)
diff --git a/config/webhook/kustomizeconfig.yaml b/config/webhook/kustomizeconfig.yaml
index 25e21e3c..91902721 100644
--- a/config/webhook/kustomizeconfig.yaml
+++ b/config/webhook/kustomizeconfig.yaml
@@ -1,25 +1,18 @@
 # the following config is for teaching kustomize where to look at when substituting vars.
 # It requires kustomize v2.1.0 or newer to work properly.
 nameReference:
-- kind: Service
-  version: v1
-  fieldSpecs:
-  - kind: MutatingWebhookConfiguration
-    group: admissionregistration.k8s.io
-    path: webhooks/clientConfig/service/name
-  - kind: ValidatingWebhookConfiguration
-    group: admissionregistration.k8s.io
-    path: webhooks/clientConfig/service/name
+  - kind: Service
+    version: v1
+    fieldSpecs:
+      - kind: ValidatingWebhookConfiguration
+        group: admissionregistration.k8s.io
+        path: webhooks/clientConfig/service/name
 
 namespace:
-- kind: MutatingWebhookConfiguration
-  group: admissionregistration.k8s.io
-  path: webhooks/clientConfig/service/namespace
-  create: true
-- kind: ValidatingWebhookConfiguration
-  group: admissionregistration.k8s.io
-  path: webhooks/clientConfig/service/namespace
-  create: true
+  - kind: ValidatingWebhookConfiguration
+    group: admissionregistration.k8s.io
+    path: webhooks/clientConfig/service/namespace
+    create: true
 
 varReference:
-- path: metadata/annotations
+  - path: metadata/annotations
diff --git a/config/webhook/manifests.yaml b/config/webhook/manifests.yaml
index 440190b3..edb3159a 100644
--- a/config/webhook/manifests.yaml
+++ b/config/webhook/manifests.yaml
@@ -1,31 +1,5 @@
 ---
 apiVersion: admissionregistration.k8s.io/v1
-kind: MutatingWebhookConfiguration
-metadata:
-  name: mutating-webhook-configuration
-webhooks:
-- admissionReviewVersions:
-  - v1
-  clientConfig:
-    service:
-      name: webhook-service
-      namespace: system
-      path: /mutate-k8s-mariadb-com-v1alpha1-mariadb
-  failurePolicy: Fail
-  name: mmariadb-v1alpha1.kb.io
-  rules:
-  - apiGroups:
-    - k8s.mariadb.com
-    apiVersions:
-    - v1alpha1
-    operations:
-    - CREATE
-    - UPDATE
-    resources:
-    - mariadbs
-  sideEffects: None
----
-apiVersion: admissionregistration.k8s.io/v1
 kind: ValidatingWebhookConfiguration
 metadata:
   name: validating-webhook-configuration
diff --git a/deploy/charts/mariadb-operator/templates/webhook/config.yaml b/deploy/charts/mariadb-operator/templates/webhook/config.yaml
index d7206f31..4df29743 100644
--- a/deploy/charts/mariadb-operator/templates/webhook/config.yaml
+++ b/deploy/charts/mariadb-operator/templates/webhook/config.yaml
@@ -1,41 +1,5 @@
 {{ if and (not .Values.currentNamespaceOnly) .Values.webhook.enabled }}
 {{ $fullName := include "mariadb-operator.fullname" . }}
-apiVersion: admissionregistration.k8s.io/v1
-kind: MutatingWebhookConfiguration
-metadata:
-  name: {{ $fullName }}-webhook
-  labels:
-    {{- include "mariadb-operator-webhook.labels" . | nindent 4 }}
-  annotations:
-    {{- if .Values.webhook.cert.certManager.enabled }}
-    cert-manager.io/inject-ca-from: {{ .Release.Namespace }}/{{ include "mariadb-operator.fullname" . }}-webhook-cert
-    {{- else }}
-    k8s.mariadb.com/webhook: ""
-    {{- end }}
-    {{- with .Values.webhook.annotations }}
-    {{ toYaml . | indent 4 }}
-    {{- end }}
-webhooks:
-- admissionReviewVersions:
-  - v1
-  clientConfig:
-    service:
-      name: {{ $fullName }}-webhook
-      namespace: {{ .Release.Namespace }}
-      path: /mutate-k8s-mariadb-com-v1alpha1-mariadb
-  failurePolicy: Fail
-  name: mmariadb-v1alpha1.kb.io
-  rules:
-  - apiGroups:
-    - k8s.mariadb.com
-    apiVersions:
-    - v1alpha1
-    operations:
-    - CREATE
-    - UPDATE
-    resources:
-    - mariadbs
-  sideEffects: None
 ---
 apiVersion: admissionregistration.k8s.io/v1
 kind: ValidatingWebhookConfiguration
@@ -253,4 +217,4 @@ webhooks:
         resources:
           - users
     sideEffects: None
-{{- end }}
\ No newline at end of file
+{{- end }}
diff --git a/examples/manifests/webhook/mutatingwebhookconfig.yaml b/examples/manifests/webhook/mutatingwebhookconfig.yaml
deleted file mode 100644
index 8fc66240..00000000
--- a/examples/manifests/webhook/mutatingwebhookconfig.yaml
+++ /dev/null
@@ -1,27 +0,0 @@
-apiVersion: admissionregistration.k8s.io/v1
-kind: MutatingWebhookConfiguration
-metadata:
-  name: mariadb-operator-webhook
-  annotations:
-    k8s.mariadb.com/webhook: ""
-webhooks:
-- admissionReviewVersions:
-  - v1
-  clientConfig:
-    service:
-      name: mariadb-operator-webhook
-      namespace: default
-      path: /mutate-k8s-mariadb-com-v1alpha1-mariadb
-  failurePolicy: Fail
-  name: mmariadb.kb.io
-  rules:
-  - apiGroups:
-    - k8s.mariadb.com
-    apiVersions:
-    - v1alpha1
-    operations:
-    - CREATE
-    - UPDATE
-    resources:
-    - mariadbs
-  sideEffects: None
\ No newline at end of file
diff --git a/internal/controller/mariadb_controller_status.go b/internal/controller/mariadb_controller_status.go
index dea25886..a91701e4 100644
--- a/internal/controller/mariadb_controller_status.go
+++ b/internal/controller/mariadb_controller_status.go
@@ -83,7 +83,7 @@ func (r *MariaDBReconciler) reconcileStatus(ctx context.Context, mdb *mariadbv1a
 
 func (r *MariaDBReconciler) getReplicationStatus(ctx context.Context,
 	mdb *mariadbv1alpha1.MariaDB) (mariadbv1alpha1.ReplicationStatus, error) {
-	if !mdb.Replication().Enabled {
+	if !mdb.IsReplicationEnabled() {
 		return nil, nil
 	}
 
@@ -228,9 +228,9 @@ func defaultPrimary(mdb *mariadbv1alpha1.MariaDB) {
 		galera := ptr.Deref(mdb.Spec.Galera, mariadbv1alpha1.Galera{})
 		podIndex = ptr.Deref(galera.Primary.PodIndex, 0)
 	}
-	if mdb.Replication().Enabled {
-		primaryReplication := ptr.Deref(mdb.Replication().Primary, mariadbv1alpha1.PrimaryReplication{})
-		podIndex = ptr.Deref(primaryReplication.PodIndex, 0)
+	if mdb.IsReplicationEnabled() {
+		replication := ptr.Deref(mdb.Spec.Replication, mariadbv1alpha1.Replication{})
+		podIndex = ptr.Deref(replication.Primary.PodIndex, 0)
 	}
 	mdb.Status.CurrentPrimaryPodIndex = &podIndex
 	mdb.Status.CurrentPrimary = ptr.To(stspkg.PodName(mdb.ObjectMeta, podIndex))
diff --git a/internal/controller/mariadb_controller_update.go b/internal/controller/mariadb_controller_update.go
index a50a4275..4ab2aff6 100644
--- a/internal/controller/mariadb_controller_update.go
+++ b/internal/controller/mariadb_controller_update.go
@@ -196,7 +196,7 @@ func (r *MariaDBReconciler) waitForReadyStatus(ctx context.Context, mdb *mariadb
 }
 
 func (r *MariaDBReconciler) waitForConfiguredReplica(mdb *mariadbv1alpha1.MariaDB, logger logr.Logger) error {
-	if !mdb.Replication().Enabled {
+	if !mdb.IsReplicationEnabled() {
 		return nil
 	}
 
@@ -343,7 +343,7 @@ func (r *MariaDBReconciler) triggerSwitchover(ctx context.Context, mariadb *mari
 		switchoverLogger.Info("Triggering MariaDB switchover")
 
 		if err := r.patch(ctx, mariadb, func(mdb *mariadbv1alpha1.MariaDB) error {
-			mdb.Replication().Primary.PodIndex = newPrimary
+			mdb.Spec.Replication.Primary.PodIndex = newPrimary
 			return nil
 		}); err != nil {
 			return fmt.Errorf("error triggering MariaDB switchover: %v", err)
@@ -389,5 +389,5 @@ func shouldTriggerSwitchover(mariadb *mariadbv1alpha1.MariaDB) bool {
 	if mariadb.IsRestoringBackup() {
 		return false
 	}
-	return mariadb.Replication().Enabled && mariadb.HasConfiguredReplica()
+	return mariadb.IsReplicationEnabled() && mariadb.HasConfiguredReplica()
 }
diff --git a/internal/controller/maxscale_controller_api.go b/internal/controller/maxscale_controller_api.go
index 9e235d70..a4645c93 100644
--- a/internal/controller/maxscale_controller_api.go
+++ b/internal/controller/maxscale_controller_api.go
@@ -131,11 +131,13 @@ func (m *maxScaleAPI) maxScaleReplicationCustomOptions(mdb *mariadbv1alpha1.Mari
 		kvOpts["MASTER_SSL_CA"] = builderpki.CACertPath
 	}
 
-	if mdb != nil && mdb.Replication().Enabled {
+	if mdb != nil && mdb.IsReplicationEnabled() {
 		if kvOpts == nil {
 			kvOpts = make(map[string]string)
 		}
-		kvOpts["MASTER_CONNECT_RETRY"] = strconv.Itoa(ptr.Deref(mdb.Replication().Replica.ConnectionRetries, 10))
+
+		replSpec := ptr.Deref(mdb.Spec.Replication, mariadbv1alpha1.Replication{})
+		kvOpts["MASTER_CONNECT_RETRY"] = strconv.Itoa(ptr.Deref(replSpec.Replica.ConnectionRetries, 10))
 	}
 
 	pairs := make([]string, len(kvOpts))
diff --git a/internal/controller/pod_replication_controller.go b/internal/controller/pod_replication_controller.go
index bd277288..ec7b1eda 100644
--- a/internal/controller/pod_replication_controller.go
+++ b/internal/controller/pod_replication_controller.go
@@ -119,7 +119,7 @@ func (r *PodReplicationController) ReconcilePodNotReady(ctx context.Context, pod
 
 	var errBundle *multierror.Error
 	err = r.patch(ctx, mariadb, func(mdb *mariadbv1alpha1.MariaDB) {
-		mdb.Replication().Primary.PodIndex = newPrimary
+		mdb.Spec.Replication.Primary.PodIndex = newPrimary
 	})
 	errBundle = multierror.Append(errBundle, err)
 
@@ -143,8 +143,8 @@ func shouldReconcile(mariadb *mariadbv1alpha1.MariaDB) bool {
 	if mariadb.IsMaxScaleEnabled() || mariadb.IsRestoringBackup() || mariadb.IsSuspended() {
 		return false
 	}
-	primaryRepl := ptr.Deref(mariadb.Replication().Primary, mariadbv1alpha1.PrimaryReplication{})
-	return mariadb.Replication().Enabled && *primaryRepl.AutomaticFailover && mariadb.HasConfiguredReplica()
+	primaryRepl := ptr.Deref(mariadb.Spec.Replication, mariadbv1alpha1.Replication{}).Primary
+	return mariadb.IsReplicationEnabled() && *primaryRepl.AutomaticFailover && mariadb.HasConfiguredReplica()
 }
 
 func (r *PodReplicationController) patch(ctx context.Context, mariadb *mariadbv1alpha1.MariaDB,
diff --git a/internal/webhook/v1alpha1/mariadb_webhook.go b/internal/webhook/v1alpha1/mariadb_webhook.go
index 03c34dae..24333272 100644
--- a/internal/webhook/v1alpha1/mariadb_webhook.go
+++ b/internal/webhook/v1alpha1/mariadb_webhook.go
@@ -24,34 +24,9 @@ var mariadblog = logf.Log.WithName("mariadb-resource")
 func SetupMariaDBWebhookWithManager(mgr ctrl.Manager) error {
 	return ctrl.NewWebhookManagedBy(mgr).For(&v1alpha1.MariaDB{}).
 		WithValidator(&MariaDBCustomValidator{}).
-		WithDefaulter(&MariaDBCustomDefaulter{}).
 		Complete()
 }
 
-// +kubebuilder:webhook:path=/mutate-k8s-mariadb-com-v1alpha1-mariadb,mutating=true,failurePolicy=fail,sideEffects=None,groups=k8s.mariadb.com,resources=mariadbs,verbs=create;update,versions=v1alpha1,name=mmariadb-v1alpha1.kb.io,admissionReviewVersions=v1
-
-// MariaDBCustomDefaulter struct is responsible for setting default values on the custom resource of the
-// Kind MariaDB when those are created or updated.
-type MariaDBCustomDefaulter struct{}
-
-var _ webhook.CustomDefaulter = &MariaDBCustomDefaulter{}
-
-// Default implements webhook.CustomDefaulter so a webhook will be registered for the Kind MariaDB.
-func (d *MariaDBCustomDefaulter) Default(ctx context.Context, obj runtime.Object) error {
-	mariadb, ok := obj.(*v1alpha1.MariaDB)
-	if !ok {
-		return fmt.Errorf("expected an MariaDB object but got %T", obj)
-	}
-	mariadblog.V(1).Info("Defaulting for MariaDB", "name", mariadb.GetName())
-
-	if mariadb.Spec.Replication != nil && mariadb.Spec.Replication.Enabled {
-		mariadblog.V(1).Info("Defaulting spec.replication", "mariadb", mariadb.Name)
-		mariadb.Spec.Replication.FillWithDefaults()
-		return nil
-	}
-	return nil
-}
-
 // +kubebuilder:webhook:path=/validate-k8s-mariadb-com-v1alpha1-mariadb,mutating=false,failurePolicy=fail,sideEffects=None,groups=k8s.mariadb.com,resources=mariadbs,verbs=create;update,versions=v1alpha1,name=vmariadb-v1alpha1.kb.io,admissionReviewVersions=v1
 
 // MariaDBCustomValidator struct is responsible for validating the MariaDB resource
@@ -131,7 +106,7 @@ func (v *MariaDBCustomValidator) ValidateDelete(ctx context.Context, obj runtime
 }
 
 func validateHA(mariadb *v1alpha1.MariaDB) error {
-	if mariadb.Replication().Enabled && mariadb.IsGaleraEnabled() {
+	if mariadb.IsReplicationEnabled() && mariadb.IsGaleraEnabled() {
 		return errors.New("you may only enable one HA method at a time, either 'spec.replication' or 'spec.galera'")
 	}
 	if !mariadb.IsHAEnabled() && mariadb.Spec.Replicas > 1 {
@@ -172,7 +147,7 @@ func validateGalera(mariadb *v1alpha1.MariaDB) error {
 		if *galera.Primary.PodIndex < 0 || *galera.Primary.PodIndex >= int(mariadb.Spec.Replicas) {
 			return field.Invalid(
 				field.NewPath("spec").Child("galera").Child("primary").Child("podIndex"),
-				mariadb.Replication().Primary.PodIndex,
+				ptr.Deref(mariadb.Spec.Galera, v1alpha1.Galera{}).Primary.PodIndex,
 				"'spec.galera.primary.podIndex' out of 'spec.replicas' bounds",
 			)
 		}
@@ -227,20 +202,21 @@ func validateGalera(mariadb *v1alpha1.MariaDB) error {
 }
 
 func validateReplication(mariadb *v1alpha1.MariaDB) error {
-	if !mariadb.Replication().Enabled {
+	replication := ptr.Deref(mariadb.Spec.Replication, v1alpha1.Replication{})
+	if !replication.Enabled {
 		return nil
 	}
-	if *mariadb.Replication().Primary.PodIndex < 0 || *mariadb.Replication().Primary.PodIndex >= int(mariadb.Spec.Replicas) {
+	if *replication.Primary.PodIndex < 0 || *replication.Primary.PodIndex >= int(mariadb.Spec.Replicas) {
 		return field.Invalid(
 			field.NewPath("spec").Child("replication").Child("primary").Child("podIndex"),
-			mariadb.Replication().Primary.PodIndex,
+			replication.Primary.PodIndex,
 			"'spec.replication.primary.podIndex' out of 'spec.replicas' bounds",
 		)
 	}
-	if err := mariadb.Replication().Replica.Validate(); err != nil {
+	if err := replication.Replica.Validate(); err != nil {
 		return field.Invalid(
 			field.NewPath("spec").Child("replication").Child("replica"),
-			mariadb.Replication(),
+			replication,
 			err.Error(),
 		)
 	}
@@ -248,19 +224,21 @@ func validateReplication(mariadb *v1alpha1.MariaDB) error {
 }
 
 func validatePrimarySwitchover(mariadb, old *v1alpha1.MariaDB) error {
-	if old.Replication().Enabled && old.IsSwitchingPrimary() {
-		if *old.Replication().Primary.PodIndex != *mariadb.Replication().Primary.PodIndex {
+	if old.IsReplicationEnabled() && old.IsSwitchingPrimary() {
+		oldReplication := ptr.Deref(old.Spec.Replication, v1alpha1.Replication{})
+		mariadbReplication := ptr.Deref(mariadb.Spec.Replication, v1alpha1.Replication{})
+		if *oldReplication.Primary.PodIndex != *mariadbReplication.Primary.PodIndex {
 			return field.Invalid(
 				field.NewPath("spec").Child("replication").Child("primary").Child("podIndex"),
-				mariadb.Replication().Primary.PodIndex,
+				mariadbReplication.Primary.PodIndex,
 				"'spec.replication.primary.podIndex' cannot be updated during a primary switchover",
 			)
 		}
-		if *old.Replication().Primary.AutomaticFailover != *mariadb.Replication().Primary.AutomaticFailover &&
-			*mariadb.Replication().Primary.AutomaticFailover {
+		if *oldReplication.Primary.AutomaticFailover != *mariadbReplication.Primary.AutomaticFailover &&
+			*mariadbReplication.Primary.AutomaticFailover {
 			return field.Invalid(
 				field.NewPath("spec").Child("replication").Child("primary").Child("automaticFailover"),
-				mariadb.Replication().Primary.PodIndex,
+				mariadbReplication.Primary.PodIndex,
 				"'spec.replication.primary.automaticFailover' cannot be enabled during a primary switchover",
 			)
 		}
diff --git a/make/pki.mk b/make/pki.mk
index 2b2bab2c..2bca0f02 100644
--- a/make/pki.mk
+++ b/make/pki.mk
@@ -102,7 +102,7 @@ CERT_ALT_NAMES ?=
 cert-leaf: ## Generates leaf certificate keypair.
 	@mkdir -p $(PKI_DIR)
 	@openssl ecparam -genkey -name $(EC_PARAM) -noout -out $(KEY)
-	@openssl req -new -key $(KEY) $(EC_HASH) -sha256 -days 365 \
+	@openssl req -new -key $(KEY) $(EC_HASH) -days 365 \
 		-CA $(CA_CERT) -CAkey $(CA_KEY) \
 		-out $(CERT) -subj $(CERT_SUBJECT) -addext $(CERT_ALT_NAMES)
 
@@ -293,4 +293,4 @@ cert-secret-tls: kubectl ## Creates a TLS Secret.
 # Entrypoint ==============================================================================================================================
 
 .PHONY: cert
-cert: cert-mariadb cert-mariadb-galera cert-mariadb-repl cert-mxs-galera cert-mxs-repl cert-webhook cert-minio ## Generate certificates.
\ No newline at end of file
+cert: cert-mariadb cert-mariadb-galera cert-mariadb-repl cert-mxs-galera cert-mxs-repl cert-webhook cert-minio ## Generate certificates.
diff --git a/pkg/agent/handler/replication/probe.go b/pkg/agent/handler/replication/probe.go
index b0995dd3..eac5facd 100644
--- a/pkg/agent/handler/replication/probe.go
+++ b/pkg/agent/handler/replication/probe.go
@@ -159,6 +159,6 @@ func (p *ReplicationProbe) getMaxLagSeconds(ctx context.Context) int {
 	}
 
 	replication := ptr.Deref(mdb.Spec.Replication, mariadbv1alpha1.Replication{})
-	replica := ptr.Deref(replication.Replica, mariadbv1alpha1.ReplicaReplication{})
+	replica := replication.Replica
 	return ptr.Deref(replica.MaxLagSeconds, 0)
 }
diff --git a/pkg/builder/container_builder.go b/pkg/builder/container_builder.go
index 99d0f746..b7ef04fe 100644
--- a/pkg/builder/container_builder.go
+++ b/pkg/builder/container_builder.go
@@ -479,7 +479,7 @@ func mariadbEnv(mariadb *mariadbv1alpha1.MariaDB) ([]corev1.EnvVar, error) {
 		}
 	}
 
-	if mariadb.Replication().Enabled {
+	if mariadb.IsReplicationEnabled() {
 		env = append(env, []corev1.EnvVar{
 			{
 				Name:  "MARIADB_REPL_ENABLED",
@@ -487,8 +487,8 @@ func mariadbEnv(mariadb *mariadbv1alpha1.MariaDB) ([]corev1.EnvVar, error) {
 			},
 		}...)
 
-		replication := mariadb.Replication()
-		replica := ptr.Deref(replication.Replica, mariadbv1alpha1.ReplicaReplication{})
+		replication := ptr.Deref(mariadb.Spec.Replication, mariadbv1alpha1.Replication{})
+		replica := replication.Replica
 
 		if ptr.Deref(replication.GtidStrictMode, true) {
 			env = append(env, corev1.EnvVar{
@@ -588,7 +588,7 @@ func mariadbVolumeMounts(mariadb *mariadbv1alpha1.MariaDB, opts ...mariadbPodOpt
 
 	volumeMounts = append(volumeMounts, mariadbStorageVolumeMount(mariadb))
 
-	if mariadb.Replication().Enabled {
+	if mariadb.IsReplicationEnabled() {
 		volumeMounts = append(volumeMounts, corev1.VolumeMount{
 			Name:      MariadbConfigVolume,
 			MountPath: MariadbConfigMountPath,
diff --git a/pkg/builder/pod_builder.go b/pkg/builder/pod_builder.go
index 5611909d..7d06b8cc 100644
--- a/pkg/builder/pod_builder.go
+++ b/pkg/builder/pod_builder.go
@@ -314,7 +314,7 @@ func mariadbVolumes(mariadb *mariadbv1alpha1.MariaDB, opts ...mariadbPodOpt) ([]
 		tlsVolumes, _ := mariadbTLSVolumes(mariadb)
 		volumes = append(volumes, tlsVolumes...)
 	}
-	if mariadb.Replication().Enabled {
+	if mariadb.IsReplicationEnabled() {
 		volumes = append(volumes, corev1.Volume{
 			Name: MariadbConfigVolume,
 			VolumeSource: corev1.VolumeSource{
diff --git a/pkg/builder/statefulset_builder.go b/pkg/builder/statefulset_builder.go
index 65b99583..7b5d2e66 100644
--- a/pkg/builder/statefulset_builder.go
+++ b/pkg/builder/statefulset_builder.go
@@ -239,7 +239,7 @@ func mariadbHAAnnotations(mariadb *mariadbv1alpha1.MariaDB) map[string]string {
 		annotations = map[string]string{
 			annotation.MariadbAnnotation: mariadb.Name,
 		}
-		if mariadb.Replication().Enabled {
+		if mariadb.IsReplicationEnabled() {
 			annotations[annotation.ReplicationAnnotation] = ""
 		}
 		if mariadb.IsGaleraEnabled() {
diff --git a/pkg/controller/replication/clientset.go b/pkg/controller/replication/clientset.go
index a63d6115..7e467dc2 100644
--- a/pkg/controller/replication/clientset.go
+++ b/pkg/controller/replication/clientset.go
@@ -9,6 +9,7 @@ import (
 	"github.com/mariadb-operator/mariadb-operator/v25/pkg/refresolver"
 	sqlClient "github.com/mariadb-operator/mariadb-operator/v25/pkg/sql"
 	sqlClientSet "github.com/mariadb-operator/mariadb-operator/v25/pkg/sqlset"
+	"k8s.io/utils/ptr"
 )
 
 type ReplicationClientSet struct {
@@ -16,7 +17,7 @@ type ReplicationClientSet struct {
 }
 
 func NewReplicationClientSet(mariadb *mariadbv1alpha1.MariaDB, refResolver *refresolver.RefResolver) (*ReplicationClientSet, error) {
-	if !mariadb.Replication().Enabled {
+	if !mariadb.IsReplicationEnabled() {
 		return nil, errors.New("'mariadb.spec.replication' is required to create a replicationClientSet")
 	}
 	return &ReplicationClientSet{
@@ -44,7 +45,8 @@ func (c *ReplicationClientSet) currentPrimaryClient(ctx context.Context, clientO
 }
 
 func (c *ReplicationClientSet) newPrimaryClient(ctx context.Context, clientOpts ...sqlClient.Opt) (*sqlClient.Client, error) {
-	client, err := c.ClientForIndex(ctx, *c.Mariadb.Replication().Primary.PodIndex, clientOpts...)
+	replication := ptr.Deref(c.Mariadb.Spec.Replication, mariadbv1alpha1.Replication{})
+	client, err := c.ClientForIndex(ctx, *replication.Primary.PodIndex, clientOpts...)
 	if err != nil {
 		return nil, fmt.Errorf("error getting new primary client: %v", err)
 	}
diff --git a/pkg/controller/replication/config.go b/pkg/controller/replication/config.go
index 7050e8fb..97e321f2 100644
--- a/pkg/controller/replication/config.go
+++ b/pkg/controller/replication/config.go
@@ -128,7 +128,9 @@ func (r *ReplicationConfigClient) changeMaster(ctx context.Context, mariadb *mar
 		return fmt.Errorf("error getting replication password: %v", err)
 	}
 
-	gtid := ptr.Deref(mariadb.Replication().Replica.Gtid, mariadbv1alpha1.GtidCurrentPos)
+	replication := ptr.Deref(mariadb.Spec.Replication, mariadbv1alpha1.Replication{})
+
+	gtid := ptr.Deref(replication.Replica.Gtid, mariadbv1alpha1.GtidCurrentPos)
 	gtidString, err := gtid.MariaDBFormat()
 	if err != nil {
 		return fmt.Errorf("error getting GTID: %v", err)
@@ -144,7 +146,7 @@ func (r *ReplicationConfigClient) changeMaster(ctx context.Context, mariadb *mar
 		sql.WithChangeMasterPort(mariadb.Spec.Port),
 		sql.WithChangeMasterCredentials(replUser, password),
 		sql.WithChangeMasterGtid(gtidString),
-		sql.WithChangeMasterRetries(*mariadb.Replication().Replica.ConnectionRetries),
+		sql.WithChangeMasterRetries(*replication.Replica.ConnectionRetries),
 	}
 	if mariadb.IsTLSEnabled() {
 		changeMasterOpts = append(changeMasterOpts, sql.WithChangeMasterSSL(
@@ -333,8 +335,9 @@ sync_binlog={{ . }}
 }
 
 func newReplPasswordRef(mariadb *mariadbv1alpha1.MariaDB) mariadbv1alpha1.GeneratedSecretKeyRef {
-	if mariadb.Replication().Enabled && mariadb.Replication().Replica.ReplPasswordSecretKeyRef != nil {
-		return *mariadb.Replication().Replica.ReplPasswordSecretKeyRef
+	replication := ptr.Deref(mariadb.Spec.Replication, mariadbv1alpha1.Replication{})
+	if replication.Enabled && replication.Replica.ReplPasswordSecretKeyRef != nil {
+		return *replication.Replica.ReplPasswordSecretKeyRef
 	}
 	return mariadbv1alpha1.GeneratedSecretKeyRef{
 		SecretKeySelector: mariadbv1alpha1.SecretKeySelector{
diff --git a/pkg/controller/replication/controller.go b/pkg/controller/replication/controller.go
index ed53cbe0..013f0558 100644
--- a/pkg/controller/replication/controller.go
+++ b/pkg/controller/replication/controller.go
@@ -90,7 +90,7 @@ type reconcileRequest struct {
 }
 
 func (r *ReplicationReconciler) Reconcile(ctx context.Context, mdb *mariadbv1alpha1.MariaDB) (ctrl.Result, error) {
-	if !mdb.Replication().Enabled {
+	if !mdb.IsReplicationEnabled() {
 		return ctrl.Result{}, nil
 	}
 	logger := log.FromContext(ctx).WithName("replication")
diff --git a/pkg/controller/replication/switchover.go b/pkg/controller/replication/switchover.go
index 5bd198cd..bf4f8168 100644
--- a/pkg/controller/replication/switchover.go
+++ b/pkg/controller/replication/switchover.go
@@ -16,6 +16,7 @@ import (
 	corev1 "k8s.io/api/core/v1"
 	apierrors "k8s.io/apimachinery/pkg/api/errors"
 	"k8s.io/apimachinery/pkg/types"
+	"k8s.io/utils/ptr"
 )
 
 type switchoverPhase struct {
@@ -47,9 +48,10 @@ func (r *ReplicationReconciler) reconcileSwitchover(ctx context.Context, req *re
 		return nil
 	}
 
+	replication := ptr.Deref(req.mariadb.Spec.Replication, mariadbv1alpha1.Replication{})
 	primary := req.mariadb.Status.CurrentPrimaryPodIndex
-	newPrimary := *req.mariadb.Replication().Primary.PodIndex
-	newPrimaryPodName := statefulset.PodName(req.mariadb.ObjectMeta, *req.mariadb.Replication().Primary.PodIndex)
+	newPrimary := *replication.Primary.PodIndex
+	newPrimaryPodName := statefulset.PodName(req.mariadb.ObjectMeta, *replication.Primary.PodIndex)
 	logger = logger.WithValues("primary", primary, "new-primary", newPrimary)
 
 	if err := r.patchStatus(ctx, req.mariadb, func(status *mariadbv1alpha1.MariaDBStatus) {
@@ -219,6 +221,7 @@ func (r *ReplicationReconciler) waitForReplicaSync(ctx context.Context, req *rec
 	logger.Info("Waiting for replicas to be synced with primary", "gtid", primaryGtid)
 	r.recorder.Event(req.mariadb, corev1.EventTypeNormal, mariadbv1alpha1.ReasonReplicationReplicaSync,
 		"Waiting for replicas to be synced with primary")
+	replication := ptr.Deref(req.mariadb.Spec.Replication, mariadbv1alpha1.Replication{})
 	for i := 0; i < int(req.mariadb.Spec.Replicas); i++ {
 		if i == *req.mariadb.Status.CurrentPrimaryPodIndex {
 			continue
@@ -233,7 +236,7 @@ func (r *ReplicationReconciler) waitForReplicaSync(ctx context.Context, req *rec
 			}
 
 			logger.V(1).Info("Syncing replica with primary GTID", "replica", i, "gtid", primaryGtid)
-			timeout := req.mariadb.Replication().Replica.SyncTimeout.Duration
+			timeout := replication.Replica.SyncTimeout.Duration
 			if err := replClient.WaitForReplicaGtid(ctx, primaryGtid, timeout); err != nil {
 				logger.Error(err, "Error waiting for GTID in replica", "gtid", primaryGtid, "replica", i)
 				r.recorder.Eventf(req.mariadb, corev1.EventTypeWarning, mariadbv1alpha1.ReasonReplicationReplicaSyncErr,
@@ -263,7 +266,7 @@ func (r *ReplicationReconciler) waitForReplicaSync(ctx context.Context, req *rec
 }
 
 func (r *ReplicationReconciler) configureNewPrimary(ctx context.Context, req *reconcileRequest, logger logr.Logger) error {
-	newPrimary := *req.mariadb.Replication().Primary.PodIndex
+	newPrimary := *ptr.Deref(req.mariadb.Spec.Replication, mariadbv1alpha1.Replication{}).Primary.PodIndex
 	newPrimaryClient, err := req.clientSet.newPrimaryClient(ctx)
 	if err != nil {
 		return fmt.Errorf("error getting new primary client: %v", err)
@@ -287,7 +290,7 @@ func (r *ReplicationReconciler) connectReplicasToNewPrimary(ctx context.Context,
 	doneChan := make(chan struct{})
 	errChan := make(chan error)
 
-	newPrimary := *req.mariadb.Replication().Primary.PodIndex
+	newPrimary := *ptr.Deref(req.mariadb.Spec.Replication, mariadbv1alpha1.Replication{}).Primary.PodIndex
 	newPrimaryClient, err := req.clientSet.newPrimaryClient(ctx)
 	if err != nil {
 		return fmt.Errorf("error getting new primary client: %v", err)
@@ -302,8 +305,10 @@ func (r *ReplicationReconciler) connectReplicasToNewPrimary(ctx context.Context,
 		return fmt.Errorf("error getting replica options: %v", err)
 	}
 
+	replicationPrimaryPodIndex := ptr.Deref(req.mariadb.Spec.Replication, mariadbv1alpha1.Replication{}).Primary.PodIndex
+
 	for i := 0; i < int(req.mariadb.Spec.Replicas); i++ {
-		if i == *req.mariadb.Status.CurrentPrimaryPodIndex || i == *req.mariadb.Replication().Primary.PodIndex {
+		if i == *req.mariadb.Status.CurrentPrimaryPodIndex || i == *replicationPrimaryPodIndex {
 			continue
 		}
 		wg.Add(1)
@@ -373,7 +378,7 @@ func (r *ReplicationReconciler) changePrimaryToReplica(ctx context.Context, req
 	if err != nil {
 		return fmt.Errorf("error getting current primary client: %v", err)
 	}
-	newPrimary := *req.mariadb.Replication().Primary.PodIndex
+	newPrimary := *ptr.Deref(req.mariadb.Spec.Replication, mariadbv1alpha1.Replication{}).Primary.PodIndex
 	newPrimaryClient, err := req.clientSet.newPrimaryClient(ctx)
 	if err != nil {
 		return fmt.Errorf("error getting new primary client: %v", err)



Test patch:
diff --git a/api/v1alpha1/mariadb_types_test.go b/api/v1alpha1/mariadb_types_test.go
index 7a795bdf..85782bcc 100644
--- a/api/v1alpha1/mariadb_types_test.go
+++ b/api/v1alpha1/mariadb_types_test.go
@@ -1,6 +1,8 @@
 package v1alpha1
 
 import (
+	"time"
+
 	"github.com/mariadb-operator/mariadb-operator/v25/pkg/environment"
 	. "github.com/onsi/ginkgo/v2"
 	. "github.com/onsi/gomega"
@@ -20,6 +22,12 @@ var _ = Describe("MariaDB types", func() {
 	env := &environment.OperatorEnv{
 		RelatedMariadbImage: "mariadb:11.0.3",
 	}
+
+	envWithSpecificNs := &environment.OperatorEnv{
+		RelatedMariadbImage:      "mariadb:11.0.3",
+		WatchNamespace:           "mariadb-obj",
+		MariadbOperatorNamespace: "mariadb-obj",
+	}
 	Context("When creating a MariaDB object", func() {
 		DescribeTable(
 			"Should default",
@@ -1282,6 +1290,221 @@ var _ = Describe("MariaDB types", func() {
 				},
 				env,
 			),
+
+			Entry(
+				"replication disabled has zeroed replication",
+				&MariaDB{
+					ObjectMeta: objMeta,
+					Spec: MariaDBSpec{
+						Replication: &Replication{
+							Enabled: false,
+						},
+					},
+				},
+				&MariaDB{
+					ObjectMeta: objMeta,
+					Spec: MariaDBSpec{
+						Replication:       &Replication{},
+						Image:             env.RelatedMariadbImage,
+						RootEmptyPassword: ptr.To(false),
+						RootPasswordSecretKeyRef: GeneratedSecretKeyRef{
+							SecretKeySelector: SecretKeySelector{
+								LocalObjectReference: LocalObjectReference{
+									Name: "mariadb-obj-root",
+								},
+								Key: "password",
+							},
+							Generate: true,
+						},
+						Port: 3306,
+						Storage: Storage{
+							Ephemeral:           ptr.To(false),
+							ResizeInUseVolumes:  ptr.To(true),
+							WaitForVolumeResize: ptr.To(true),
+						},
+						TLS: &TLS{
+							Enabled: true,
+						},
+						UpdateStrategy: UpdateStrategy{
+							Type:                ReplicasFirstPrimaryLastUpdateType,
+							AutoUpdateDataPlane: ptr.To(false),
+						},
+						PodTemplate: PodTemplate{
+							ServiceAccountName: &objMeta.Name,
+						},
+					},
+				},
+				env,
+			),
+
+			Entry(
+				"replication enabled sets defaults",
+				&MariaDB{
+					ObjectMeta: objMeta,
+					Spec: MariaDBSpec{
+						Replication: &Replication{
+							Enabled: true,
+						},
+					},
+				},
+				&MariaDB{
+					ObjectMeta: objMeta,
+					Spec: MariaDBSpec{
+						Replication: &Replication{
+							Enabled: true,
+							ReplicationSpec: ReplicationSpec{
+								GtidStrictMode: ptr.To(true),
+								SyncBinlog:     ptr.To(1),
+								InitContainer: InitContainer{
+									Image:             env.MariadbOperatorImage,
+									ContainerTemplate: ContainerTemplate{},
+									ImagePullPolicy:   "",
+								},
+								Agent: Agent{
+
+									Image:     env.MariadbOperatorImage,
+									Port:      5555,
+									ProbePort: 5566,
+									KubernetesAuth: &KubernetesAuth{
+										Enabled: true,
+									},
+									GracefulShutdownTimeout: ptr.To(metav1.Duration{Duration: 1 * time.Second}),
+								},
+								Replica: ReplicaReplication{
+									WaitPoint:         ptr.To(WaitPointAfterCommit),
+									Gtid:              ptr.To(GtidCurrentPos),
+									ConnectionTimeout: ptr.To(metav1.Duration{Duration: 10 * time.Second}),
+									ConnectionRetries: ptr.To(10),
+									SyncTimeout:       ptr.To(metav1.Duration{Duration: 10 * time.Second}),
+								},
+								Primary: PrimaryReplication{
+									PodIndex:               ptr.To(0),
+									AutomaticFailover:      ptr.To(true),
+									AutomaticFailoverDelay: ptr.To(metav1.Duration{}),
+								},
+							},
+						},
+						Image:             env.RelatedMariadbImage,
+						RootEmptyPassword: ptr.To(false),
+						RootPasswordSecretKeyRef: GeneratedSecretKeyRef{
+							SecretKeySelector: SecretKeySelector{
+								LocalObjectReference: LocalObjectReference{
+									Name: "mariadb-obj-root",
+								},
+								Key: "password",
+							},
+							Generate: true,
+						},
+						Port: 3306,
+						Storage: Storage{
+							Ephemeral:           ptr.To(false),
+							ResizeInUseVolumes:  ptr.To(true),
+							WaitForVolumeResize: ptr.To(true),
+						},
+						TLS: &TLS{
+							Enabled: true,
+						},
+						UpdateStrategy: UpdateStrategy{
+							Type:                ReplicasFirstPrimaryLastUpdateType,
+							AutoUpdateDataPlane: ptr.To(false),
+						},
+						PodTemplate: PodTemplate{
+							ServiceAccountName: &objMeta.Name,
+						},
+					},
+				},
+				env,
+			),
+
+			Entry(
+				"replication with watchnamespace sets Basic Auth",
+				&MariaDB{
+					ObjectMeta: objMeta,
+					Spec: MariaDBSpec{
+						Replication: &Replication{
+							Enabled: true,
+						},
+					},
+				},
+				&MariaDB{
+					ObjectMeta: objMeta,
+					Spec: MariaDBSpec{
+						Replication: &Replication{
+							Enabled: true,
+							ReplicationSpec: ReplicationSpec{
+								GtidStrictMode: ptr.To(true),
+								SyncBinlog:     ptr.To(1),
+								InitContainer: InitContainer{
+									Image:             env.MariadbOperatorImage,
+									ContainerTemplate: ContainerTemplate{},
+									ImagePullPolicy:   "",
+								},
+								Agent: Agent{
+
+									Image:     env.MariadbOperatorImage,
+									Port:      5555,
+									ProbePort: 5566,
+									BasicAuth: &BasicAuth{
+										Enabled:  true,
+										Username: "mariadb-operator",
+										PasswordSecretKeyRef: GeneratedSecretKeyRef{
+
+											SecretKeySelector: SecretKeySelector{
+												LocalObjectReference: LocalObjectReference{
+													Name: "mariadb-obj-agent-auth",
+												},
+												Key: "password",
+											},
+											Generate: true,
+										},
+									},
+									GracefulShutdownTimeout: ptr.To(metav1.Duration{Duration: 1 * time.Second}),
+								},
+								Replica: ReplicaReplication{
+									WaitPoint:         ptr.To(WaitPointAfterCommit),
+									Gtid:              ptr.To(GtidCurrentPos),
+									ConnectionTimeout: ptr.To(metav1.Duration{Duration: 10 * time.Second}),
+									ConnectionRetries: ptr.To(10),
+									SyncTimeout:       ptr.To(metav1.Duration{Duration: 10 * time.Second}),
+								},
+								Primary: PrimaryReplication{
+									PodIndex:               ptr.To(0),
+									AutomaticFailover:      ptr.To(true),
+									AutomaticFailoverDelay: ptr.To(metav1.Duration{}),
+								},
+							},
+						},
+						Image:             env.RelatedMariadbImage,
+						RootEmptyPassword: ptr.To(false),
+						RootPasswordSecretKeyRef: GeneratedSecretKeyRef{
+							SecretKeySelector: SecretKeySelector{
+								LocalObjectReference: LocalObjectReference{
+									Name: "mariadb-obj-root",
+								},
+								Key: "password",
+							},
+							Generate: true,
+						},
+						Port: 3306,
+						Storage: Storage{
+							Ephemeral:           ptr.To(false),
+							ResizeInUseVolumes:  ptr.To(true),
+							WaitForVolumeResize: ptr.To(true),
+						},
+						TLS: &TLS{
+							Enabled: true,
+						},
+						UpdateStrategy: UpdateStrategy{
+							Type:                ReplicasFirstPrimaryLastUpdateType,
+							AutoUpdateDataPlane: ptr.To(false),
+						},
+						PodTemplate: PodTemplate{
+							ServiceAccountName: &objMeta.Name,
+						},
+					},
+				},
+				envWithSpecificNs,
+			),
 		)
 
 		DescribeTable(
diff --git a/internal/controller/mariadb_controller_replication_test.go b/internal/controller/mariadb_controller_replication_test.go
index b8d5a507..b4bc0d2c 100644
--- a/internal/controller/mariadb_controller_replication_test.go
+++ b/internal/controller/mariadb_controller_replication_test.go
@@ -52,11 +52,11 @@ var _ = Describe("MariaDB replication", Ordered, func() {
 				),
 				Replication: &mariadbv1alpha1.Replication{
 					ReplicationSpec: mariadbv1alpha1.ReplicationSpec{
-						Primary: &mariadbv1alpha1.PrimaryReplication{
+						Primary: mariadbv1alpha1.PrimaryReplication{
 							PodIndex:          ptr.To(0),
 							AutomaticFailover: ptr.To(true),
 						},
-						Replica: &mariadbv1alpha1.ReplicaReplication{
+						Replica: mariadbv1alpha1.ReplicaReplication{
 							WaitPoint: ptr.To(mariadbv1alpha1.WaitPointAfterCommit),
 							Gtid:      ptr.To(mariadbv1alpha1.GtidCurrentPos),
 						},
@@ -282,7 +282,7 @@ var _ = Describe("MariaDB replication", Ordered, func() {
 		}
 		Eventually(func(g Gomega) bool {
 			g.Expect(k8sClient.Get(testCtx, key, mdb)).To(Succeed())
-			mdb.Replication().Primary.PodIndex = &podIndex
+			mdb.Spec.Replication.Primary.PodIndex = &podIndex
 			g.Expect(k8sClient.Update(testCtx, mdb)).To(Succeed())
 			return true
 		}, testTimeout, testInterval).Should(BeTrue())
diff --git a/internal/controller/maxscale_controller_api_test.go b/internal/controller/maxscale_controller_api_test.go
index 2aa8370c..75a55665 100644
--- a/internal/controller/maxscale_controller_api_test.go
+++ b/internal/controller/maxscale_controller_api_test.go
@@ -79,7 +79,7 @@ var _ = Describe("MaxScale Replication options", Label("basic"), func() {
 					Replication: &mariadbv1alpha1.Replication{
 						Enabled: true,
 						ReplicationSpec: mariadbv1alpha1.ReplicationSpec{
-							Replica: &mariadbv1alpha1.ReplicaReplication{
+							Replica: mariadbv1alpha1.ReplicaReplication{
 								ConnectionRetries: ptr.To(5),
 							},
 						},
@@ -102,7 +102,7 @@ var _ = Describe("MaxScale Replication options", Label("basic"), func() {
 					Replication: &mariadbv1alpha1.Replication{
 						Enabled: true,
 						ReplicationSpec: mariadbv1alpha1.ReplicationSpec{
-							Replica: &mariadbv1alpha1.ReplicaReplication{
+							Replica: mariadbv1alpha1.ReplicaReplication{
 								ConnectionRetries: ptr.To(5),
 							},
 						},
diff --git a/internal/helmtest/mariadb_cluster_test.go b/internal/helmtest/mariadb_cluster_test.go
index 8735f1fb..254188b5 100644
--- a/internal/helmtest/mariadb_cluster_test.go
+++ b/internal/helmtest/mariadb_cluster_test.go
@@ -7,6 +7,7 @@ import (
 	"time"
 
 	"github.com/gruntwork-io/terratest/modules/helm"
+	"github.com/gruntwork-io/terratest/modules/k8s"
 	"github.com/mariadb-operator/mariadb-operator/v25/api/v1alpha1"
 	. "github.com/onsi/gomega"
 	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -18,6 +19,10 @@ var (
 	clusterHelmNamespace   = "default"
 )
 
+var kubectlopts = &k8s.KubectlOptions{
+	Namespace: "default",
+}
+
 func TestClusterHelmMariaDB(t *testing.T) {
 	RegisterTestingT(t)
 
@@ -35,6 +40,7 @@ func TestClusterHelmMariaDB(t *testing.T) {
 			"mariadb.rootPasswordSecretKeyRef.key":  rootPasswordSecretKeyRefKey,
 			"mariadb.rootPasswordSecretKeyRef.name": rootPasswordSecretKeyRefName,
 		},
+		KubectlOptions: kubectlopts,
 	}
 
 	renderedData := helm.RenderTemplate(t, opts, clusterHelmChartPath, clusterHelmReleaseName, []string{"templates/mariadb.yaml"})
@@ -77,6 +83,7 @@ func TestClusterHelmDatabase(t *testing.T) {
 			"databases[0].mariaDBRef.name":      "cluster",
 			"databases[0].mariaDBRef.namespace": "namespace",
 		},
+		KubectlOptions: kubectlopts,
 	}
 
 	renderedData := helm.RenderTemplate(t, opts, clusterHelmChartPath, clusterHelmReleaseName, []string{"templates/database.yaml"})
@@ -131,6 +138,7 @@ func TestClusterHelmUser(t *testing.T) {
 			"users[0].mariaDBRef.name":           "cluster",
 			"users[0].mariaDBRef.namespace":      "namespace",
 		},
+		KubectlOptions: kubectlopts,
 	}
 
 	renderedData := helm.RenderTemplate(t, opts, clusterHelmChartPath, clusterHelmReleaseName, []string{"templates/user.yaml"})
@@ -192,6 +200,7 @@ func TestClusterHelmGrant(t *testing.T) {
 			"grants[0].mariaDBRef.name":      "cluster",
 			"grants[0].mariaDBRef.namespace": "namespace",
 		},
+		KubectlOptions: kubectlopts,
 	}
 
 	renderedData := helm.RenderTemplate(t, opts, clusterHelmChartPath, clusterHelmReleaseName, []string{"templates/grant.yaml"})
@@ -256,6 +265,7 @@ func TestClusterHelmBackup(t *testing.T) {
 			"backups[0].mariaDBRef.name":                             "cluster",
 			"backups[0].mariaDBRef.namespace":                        "namespace",
 		},
+		KubectlOptions: kubectlopts,
 	}
 
 	renderedData := helm.RenderTemplate(t, opts, clusterHelmChartPath, clusterHelmReleaseName, []string{"templates/backup.yaml"})
@@ -330,6 +340,7 @@ func TestClusterHelmPhysicalBackup(t *testing.T) {
 			"physicalBackups[0].mariaDBRef.name":                             "cluster",
 			"physicalBackups[0].mariaDBRef.namespace":                        "namespace",
 		},
+		KubectlOptions: kubectlopts,
 	}
 
 	renderedData := helm.RenderTemplate(t, opts, clusterHelmChartPath, clusterHelmReleaseName, []string{"templates/physicalbackup.yaml"})
diff --git a/internal/helmtest/mariadb_operator_test.go b/internal/helmtest/mariadb_operator_test.go
index c80bbc00..59756083 100644
--- a/internal/helmtest/mariadb_operator_test.go
+++ b/internal/helmtest/mariadb_operator_test.go
@@ -26,6 +26,9 @@ func TestOperatorHelmExtraEnvFrom(t *testing.T) {
 			"extraEnvFrom[0].configMapRef.name": `env-extra-configmap`,
 			"extraEnvFrom[1].secretRef.name":    `env-extra-secret`,
 		},
+		KubectlOptions: &k8s.KubectlOptions{
+			Namespace: operatorTestNamespace,
+		},
 	}
 
 	deploymentData := helm.RenderTemplate(t, opts,
diff --git a/internal/webhook/v1alpha1/mariadb_webhook_test.go b/internal/webhook/v1alpha1/mariadb_webhook_test.go
index c9c89b79..4abb902d 100644
--- a/internal/webhook/v1alpha1/mariadb_webhook_test.go
+++ b/internal/webhook/v1alpha1/mariadb_webhook_test.go
@@ -104,7 +104,7 @@ var _ = Describe("v1alpha1.MariaDB webhook", func() {
 					Spec: v1alpha1.MariaDBSpec{
 						Replication: &v1alpha1.Replication{
 							ReplicationSpec: v1alpha1.ReplicationSpec{
-								Primary: &v1alpha1.PrimaryReplication{
+								Primary: v1alpha1.PrimaryReplication{
 									PodIndex: func() *int { i := 0; return &i }(),
 								},
 								SyncBinlog: ptr.To(1),
@@ -126,7 +126,7 @@ var _ = Describe("v1alpha1.MariaDB webhook", func() {
 					Spec: v1alpha1.MariaDBSpec{
 						Replication: &v1alpha1.Replication{
 							ReplicationSpec: v1alpha1.ReplicationSpec{
-								Primary: &v1alpha1.PrimaryReplication{
+								Primary: v1alpha1.PrimaryReplication{
 									PodIndex: func() *int { i := 0; return &i }(),
 								},
 								SyncBinlog: ptr.To(1),
@@ -321,10 +321,10 @@ var _ = Describe("v1alpha1.MariaDB webhook", func() {
 					Spec: v1alpha1.MariaDBSpec{
 						Replication: &v1alpha1.Replication{
 							ReplicationSpec: v1alpha1.ReplicationSpec{
-								Primary: &v1alpha1.PrimaryReplication{
+								Primary: v1alpha1.PrimaryReplication{
 									PodIndex: func() *int { i := 4; return &i }(),
 								},
-								Replica: &v1alpha1.ReplicaReplication{
+								Replica: v1alpha1.ReplicaReplication{
 									WaitPoint:         ptr.To(v1alpha1.WaitPointAfterCommit),
 									ConnectionTimeout: &metav1.Duration{Duration: time.Duration(1 * time.Second)},
 									ConnectionRetries: func() *int { r := 3; return &r }(),
@@ -368,7 +368,7 @@ var _ = Describe("v1alpha1.MariaDB webhook", func() {
 					Spec: v1alpha1.MariaDBSpec{
 						Replication: &v1alpha1.Replication{
 							ReplicationSpec: v1alpha1.ReplicationSpec{
-								Replica: &v1alpha1.ReplicaReplication{
+								Replica: v1alpha1.ReplicaReplication{
 									WaitPoint: ptr.To(v1alpha1.WaitPoint("foo")),
 								},
 							},
@@ -389,7 +389,7 @@ var _ = Describe("v1alpha1.MariaDB webhook", func() {
 					Spec: v1alpha1.MariaDBSpec{
 						Replication: &v1alpha1.Replication{
 							ReplicationSpec: v1alpha1.ReplicationSpec{
-								Replica: &v1alpha1.ReplicaReplication{
+								Replica: v1alpha1.ReplicaReplication{
 									Gtid: ptr.To(v1alpha1.Gtid("foo")),
 								},
 							},
@@ -571,72 +571,6 @@ var _ = Describe("v1alpha1.MariaDB webhook", func() {
 				false,
 			),
 		)
-
-		It("Should default replication", func() {
-			mariadb := v1alpha1.MariaDB{
-				ObjectMeta: metav1.ObjectMeta{
-					Name:      "mariadb-repl-default-webhook",
-					Namespace: testNamespace,
-				},
-				Spec: v1alpha1.MariaDBSpec{
-					Replicas: 3,
-					Replication: &v1alpha1.Replication{
-						Enabled: true,
-					},
-					Storage: v1alpha1.Storage{
-						Size: ptr.To(resource.MustParse("100Mi")),
-					},
-				},
-			}
-			Expect(k8sClient.Create(testCtx, &mariadb)).To(Succeed())
-			Expect(k8sClient.Get(testCtx, client.ObjectKeyFromObject(&mariadb), &mariadb)).To(Succeed())
-
-			By("Expect v1alpha1.MariaDB replication spec to be defaulted")
-			Expect(mariadb.Spec.Replication.ReplicationSpec).To(Equal(v1alpha1.DefaultReplicationSpec))
-		})
-
-		It("Should partially default replication", func() {
-			mariadb := v1alpha1.MariaDB{
-				ObjectMeta: metav1.ObjectMeta{
-					Name:      "mariadb-repl-partial-default-webhook",
-					Namespace: testNamespace,
-				},
-				Spec: v1alpha1.MariaDBSpec{
-					Replicas: 3,
-					Replication: &v1alpha1.Replication{
-						Enabled: true,
-						ReplicationSpec: v1alpha1.ReplicationSpec{
-							Primary: &v1alpha1.PrimaryReplication{
-								PodIndex: ptr.To(0),
-							},
-							Replica: &v1alpha1.ReplicaReplication{
-								WaitPoint: ptr.To(v1alpha1.WaitPointAfterCommit),
-							},
-						},
-					},
-					Storage: v1alpha1.Storage{
-						Size: ptr.To(resource.MustParse("100Mi")),
-						VolumeClaimTemplate: &v1alpha1.VolumeClaimTemplate{
-							PersistentVolumeClaimSpec: v1alpha1.PersistentVolumeClaimSpec{
-								Resources: corev1.VolumeResourceRequirements{
-									Requests: corev1.ResourceList{
-										corev1.ResourceStorage: resource.MustParse("100Mi"),
-									},
-								},
-								AccessModes: []corev1.PersistentVolumeAccessMode{
-									corev1.ReadWriteOnce,
-								},
-							},
-						},
-					},
-				},
-			}
-			Expect(k8sClient.Create(testCtx, &mariadb)).To(Succeed())
-			Expect(k8sClient.Get(testCtx, client.ObjectKeyFromObject(&mariadb), &mariadb)).To(Succeed())
-
-			By("Expect v1alpha1.MariaDB replication spec to be defaulted")
-			Expect(mariadb.Spec.Replication.ReplicationSpec).To(Equal(v1alpha1.DefaultReplicationSpec))
-		})
 	})
 
 	Context("When updating a v1alpha1.MariaDB", Ordered, func() {
@@ -923,7 +857,7 @@ var _ = Describe("v1alpha1.MariaDB webhook", func() {
 					},
 					Replication: &v1alpha1.Replication{
 						ReplicationSpec: v1alpha1.ReplicationSpec{
-							Primary: &v1alpha1.PrimaryReplication{
+							Primary: v1alpha1.PrimaryReplication{
 								PodIndex:          func() *int { i := 0; return &i }(),
 								AutomaticFailover: func() *bool { f := false; return &f }(),
 							},
@@ -954,7 +888,7 @@ var _ = Describe("v1alpha1.MariaDB webhook", func() {
 					},
 					Replication: &v1alpha1.Replication{
 						ReplicationSpec: v1alpha1.ReplicationSpec{
-							Primary: &v1alpha1.PrimaryReplication{
+							Primary: v1alpha1.PrimaryReplication{
 								PodIndex:          func() *int { i := 0; return &i }(),
 								AutomaticFailover: func() *bool { f := false; return &f }(),
 							},