Skip to content

Commit 411a397

Browse files
authoredMar 6, 2025
K8SPG-648 Fix patroni-version-check (#1071)
1 parent 759653a commit 411a397

File tree

11 files changed

+68
-6
lines changed

11 files changed

+68
-6
lines changed
 

‎build/crd/percona/generated/pgv2.percona.com_perconapgclusters.yaml

+2
Original file line numberDiff line numberDiff line change
@@ -17531,6 +17531,8 @@ spec:
1753117531
type: object
1753217532
postgres:
1753317533
properties:
17534+
imageID:
17535+
type: string
1753417536
instances:
1753517537
items:
1753617538
properties:

‎config/crd/bases/pgv2.percona.com_perconapgclusters.yaml

+2
Original file line numberDiff line numberDiff line change
@@ -17937,6 +17937,8 @@ spec:
1793717937
type: object
1793817938
postgres:
1793917939
properties:
17940+
imageID:
17941+
type: string
1794017942
instances:
1794117943
items:
1794217944
properties:

‎deploy/bundle.yaml

+2
Original file line numberDiff line numberDiff line change
@@ -18230,6 +18230,8 @@ spec:
1823018230
type: object
1823118231
postgres:
1823218232
properties:
18233+
imageID:
18234+
type: string
1823318235
instances:
1823418236
items:
1823518237
properties:

‎deploy/crd.yaml

+2
Original file line numberDiff line numberDiff line change
@@ -18230,6 +18230,8 @@ spec:
1823018230
type: object
1823118231
postgres:
1823218232
properties:
18233+
imageID:
18234+
type: string
1823318235
instances:
1823418236
items:
1823518237
properties:

‎deploy/cw-bundle.yaml

+2
Original file line numberDiff line numberDiff line change
@@ -18230,6 +18230,8 @@ spec:
1823018230
type: object
1823118231
postgres:
1823218232
properties:
18233+
imageID:
18234+
type: string
1823318235
instances:
1823418236
items:
1823518237
properties:

‎percona/controller/pgcluster/controller.go

+41-3
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,7 @@ func (r *PGClusterReconciler) Reconcile(ctx context.Context, request reconcile.R
294294
}
295295

296296
var opRes controllerutil.OperationResult
297-
if err := retry.RetryOnConflict(retry.DefaultRetry, func() error {
297+
if err := retry.OnError(retry.DefaultRetry, func(err error) bool { return err != nil }, func() error {
298298
var err error
299299
opRes, err = controllerutil.CreateOrUpdate(ctx, r.Client, postgresCluster, func() error {
300300
var err error
@@ -334,7 +334,44 @@ func (r *PGClusterReconciler) reconcilePatroniVersionCheck(ctx context.Context,
334334
cr.Annotations = make(map[string]string)
335335
}
336336

337-
if cr.Status.Postgres.Version == cr.Spec.PostgresVersion && cr.Status.PatroniVersion != "" {
337+
// This annotation is used for unit-tests only. Allows to skip the patroni version check
338+
if _, ok := cr.Annotations[pNaming.InternalAnnotationDisablePatroniVersionCheck]; ok {
339+
cr.Annotations[pNaming.AnnotationPatroniVersion] = cr.Status.PatroniVersion
340+
return nil
341+
}
342+
343+
getImageIDFromPod := func(pod *corev1.Pod, containerName string) string {
344+
idx := slices.IndexFunc(pod.Status.ContainerStatuses, func(s corev1.ContainerStatus) bool {
345+
return s.Name == containerName
346+
})
347+
if idx == -1 {
348+
return ""
349+
}
350+
return pod.Status.ContainerStatuses[idx].ImageID
351+
}
352+
353+
pods := new(corev1.PodList)
354+
instances, err := naming.AsSelector(naming.ClusterInstances(cr.Name))
355+
if err != nil {
356+
return err
357+
}
358+
if err = r.Client.List(ctx, pods, client.InNamespace(cr.Namespace), client.MatchingLabelsSelector{Selector: instances}); err != nil {
359+
return err
360+
}
361+
362+
// Collecting all image IDs from instance pods. Under normal conditions, this slice will contain a single image ID, as all pods typically use the same image.
363+
// During an image update, it may contain multiple different image IDs as the update progresses.
364+
imageIDs := []string{}
365+
for _, pod := range pods.Items {
366+
imageID := getImageIDFromPod(&pod, naming.ContainerDatabase)
367+
if imageID != "" && !slices.Contains(imageIDs, imageID) {
368+
imageIDs = append(imageIDs, imageID)
369+
}
370+
}
371+
372+
// If the imageIDs slice contains the imageID from the status, we skip checking the Patroni version.
373+
// This ensures that the Patroni version is only checked after all pods have been updated.
374+
if slices.Contains(imageIDs, cr.Status.Postgres.ImageID) && cr.Status.PatroniVersion != "" {
338375
cr.Annotations[pNaming.AnnotationPatroniVersion] = cr.Status.PatroniVersion
339376
return nil
340377
}
@@ -348,7 +385,7 @@ func (r *PGClusterReconciler) reconcilePatroniVersionCheck(ctx context.Context,
348385
ObjectMeta: meta,
349386
}
350387

351-
err := r.Client.Get(ctx, client.ObjectKeyFromObject(p), p)
388+
err = r.Client.Get(ctx, client.ObjectKeyFromObject(p), p)
352389
if client.IgnoreNotFound(err) != nil {
353390
return errors.Wrap(err, "failed to get patroni version check pod")
354391
}
@@ -418,6 +455,7 @@ func (r *PGClusterReconciler) reconcilePatroniVersionCheck(ctx context.Context,
418455

419456
cr.Status.PatroniVersion = patroniVersion
420457
cr.Status.Postgres.Version = cr.Spec.PostgresVersion
458+
cr.Status.Postgres.ImageID = getImageIDFromPod(p, pNaming.ContainerPatroniVersionCheck)
421459

422460
if err := r.Client.Status().Patch(ctx, cr.DeepCopy(), client.MergeFrom(orig)); err != nil {
423461
return errors.Wrap(err, "failed to patch patroni version")

‎percona/controller/pgcluster/controller_test.go

-1
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,6 @@ var _ = Describe("Annotations", Ordered, func() {
113113
})
114114

115115
It("should create PerconaPGCluster with annotations", func() {
116-
cr.Annotations = make(map[string]string)
117116
cr.Annotations["pgv2.percona.com/trigger-switchover"] = "true"
118117
cr.Annotations["egedemo.com/test"] = "true"
119118

‎percona/controller/pgcluster/testutils_test.go

+9
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"github.com/percona/percona-postgresql-operator/internal/controller/postgrescluster"
2222
"github.com/percona/percona-postgresql-operator/internal/naming"
2323
"github.com/percona/percona-postgresql-operator/percona/controller/pgbackup"
24+
pNaming "github.com/percona/percona-postgresql-operator/percona/naming"
2425
"github.com/percona/percona-postgresql-operator/percona/utils/registry"
2526
"github.com/percona/percona-postgresql-operator/percona/watcher"
2627
v2 "github.com/percona/percona-postgresql-operator/pkg/apis/pgv2.percona.com/v2"
@@ -94,6 +95,10 @@ func readTestCR(name, namespace, testFile string) (*v2.PerconaPGCluster, error)
9495
if cr.Spec.PostgresVersion == 0 {
9596
return nil, errors.New("postgresVersion should be specified")
9697
}
98+
if cr.Annotations == nil {
99+
cr.Annotations = make(map[string]string)
100+
}
101+
cr.Annotations[pNaming.InternalAnnotationDisablePatroniVersionCheck] = "true"
97102
cr.Status.Postgres.Version = cr.Spec.PostgresVersion
98103
cr.Status.PatroniVersion = "4.0.0"
99104
return cr, nil
@@ -112,6 +117,10 @@ func readDefaultCR(name, namespace string) (*v2.PerconaPGCluster, error) {
112117
}
113118

114119
cr.Name = name
120+
if cr.Annotations == nil {
121+
cr.Annotations = make(map[string]string)
122+
}
123+
cr.Annotations[pNaming.InternalAnnotationDisablePatroniVersionCheck] = "true"
115124
cr.Namespace = namespace
116125
cr.Status.Postgres.Version = cr.Spec.PostgresVersion
117126
cr.Status.PatroniVersion = "4.0.0"

‎percona/naming/annotations.go

+3
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,7 @@ const (
3939
AnnotationClusterBootstrapRestore = PrefixPerconaPGV2 + "cluster-bootstrap-restore"
4040

4141
AnnotationPatroniVersion = PrefixPerconaPGV2 + "patroni-version"
42+
43+
// Should be used only for unit-testing
44+
InternalAnnotationDisablePatroniVersionCheck = PrefixPerconaInternal + "patroni-version-check-disable"
4245
)

‎percona/watcher/wal.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ func WatchCommitTimestamps(ctx context.Context, cli client.Client, eventChan cha
6161
return
6262
}
6363

64-
latestBackup, err := getLatestBackup(ctx, cli, cr)
64+
latestBackup, err := getLatestBackup(ctx, cli, localCr)
6565
if err != nil {
6666
if !errors.Is(err, errRunningBackup) && !errors.Is(err, errNoBackups) {
6767
log.Error(err, "get latest backup")
@@ -70,7 +70,7 @@ func WatchCommitTimestamps(ctx context.Context, cli client.Client, eventChan cha
7070
continue
7171
}
7272

73-
ts, err := GetLatestCommitTimestamp(ctx, cli, execCli, cr, latestBackup)
73+
ts, err := GetLatestCommitTimestamp(ctx, cli, execCli, localCr, latestBackup)
7474
if err != nil {
7575
switch {
7676
case errors.Is(err, PrimaryPodNotFound) && localCr.Status.State != pgv2.AppStateReady:

‎pkg/apis/pgv2.percona.com/v2/perconapgcluster_types.go

+3
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,9 @@ type PostgresStatus struct {
401401

402402
// +optional
403403
Version int `json:"version"`
404+
405+
// +optional
406+
ImageID string `json:"imageID"`
404407
}
405408

406409
type PGBouncerStatus struct {

0 commit comments

Comments
 (0)
Please sign in to comment.