Skip to content

Commit 8385a5a

Browse files
Anthony Landrethtony-landreth
Anthony Landreth
authored andcommitted
Defines registration and encumbrance PGO-217
1 parent 38c460c commit 8385a5a

File tree

10 files changed

+212
-3
lines changed

10 files changed

+212
-3
lines changed

config/crd/bases/postgres-operator.crunchydata.com_postgresclusters.yaml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15424,13 +15424,24 @@ spec:
1542415424
type: integer
1542515425
type: object
1542615426
type: object
15427+
registrationRequired:
15428+
description: Version information for installations with a registration
15429+
requirement.
15430+
properties:
15431+
pgoVersion:
15432+
type: string
15433+
type: object
1542715434
startupInstance:
1542815435
description: The instance that should be started first when bootstrapping
1542915436
and/or starting a PostgresCluster.
1543015437
type: string
1543115438
startupInstanceSet:
1543215439
description: The instance set associated with the startupInstance
1543315440
type: string
15441+
tokenRequired:
15442+
description: Signals the need for a token to be applied when registration
15443+
is required.
15444+
type: string
1543415445
userInterface:
1543515446
description: Current state of the PostgreSQL user interface.
1543615447
properties:

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ require (
2020
go.opentelemetry.io/otel/sdk v1.2.0
2121
go.opentelemetry.io/otel/trace v1.2.0
2222
golang.org/x/crypto v0.11.0
23+
golang.org/x/mod v0.8.0
2324
gotest.tools/v3 v3.1.0
2425
k8s.io/api v0.24.2
2526
k8s.io/apimachinery v0.24.2

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -597,6 +597,8 @@ golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
597597
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
598598
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
599599
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
600+
golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8=
601+
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
600602
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
601603
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
602604
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=

internal/config/config.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,15 @@ func defaultFromEnv(value, key string) string {
3030
return value
3131
}
3232

33+
func RegistrationRequired() bool {
34+
return os.Getenv("REGISTRATION_REQUIRED") == "true"
35+
}
36+
37+
// Get the version of CPK that applied the first RegistrationRequired status to this cluster.
38+
func RegistrationRequiredBy(cluster *v1beta1.PostgresCluster) string {
39+
return cluster.Status.RegistrationRequired.PGOVersion
40+
}
41+
3342
// Red Hat Marketplace requires operators to use environment variables be used
3443
// for any image other than the operator itself. Those variables must start with
3544
// "RELATED_IMAGE_" so that OSBS can transform their tag values into digests

internal/controller/postgrescluster/controller.go

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ func (r *Reconciler) Reconcile(
192192
err error
193193
)
194194

195-
// Define the function for the updating the PostgresCluster status. Returns any error that
195+
// Define a function for updating PostgresCluster status. Returns any error that
196196
// occurs while attempting to patch the status, while otherwise simply returning the
197197
// Result and error variables that are populated while reconciling the PostgresCluster.
198198
patchClusterStatus := func() (reconcile.Result, error) {
@@ -209,6 +209,21 @@ func (r *Reconciler) Reconcile(
209209
return result, err
210210
}
211211

212+
if config.RegistrationRequired() {
213+
if !registrationRequiredStatusFound(cluster) {
214+
addRegistrationRequiredStatus(cluster)
215+
return patchClusterStatus()
216+
}
217+
218+
if shouldEncumberReconciliation(cluster) {
219+
emitEncumbranceWarning(cluster, r)
220+
// Encumbrance is just an early return from the reconciliation loop.
221+
return patchClusterStatus()
222+
} else {
223+
emitAdvanceWarning(cluster, r)
224+
}
225+
}
226+
212227
// if the cluster is paused, set a condition and return
213228
if cluster.Spec.Paused != nil && *cluster.Spec.Paused {
214229
meta.SetStatusCondition(&cluster.Status.Conditions, metav1.Condition{

internal/controller/postgrescluster/controller_test.go

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ package postgrescluster
2121
import (
2222
"context"
2323
"fmt"
24+
"os"
2425
"strings"
2526
"testing"
2627

@@ -41,6 +42,7 @@ import (
4142
"sigs.k8s.io/controller-runtime/pkg/reconcile"
4243
"sigs.k8s.io/yaml"
4344

45+
"github.com/crunchydata/postgres-operator/internal/config"
4446
"github.com/crunchydata/postgres-operator/internal/naming"
4547
"github.com/crunchydata/postgres-operator/internal/testing/require"
4648
"github.com/crunchydata/postgres-operator/internal/util"
@@ -164,6 +166,80 @@ var _ = Describe("PostgresCluster Reconciler", func() {
164166
return result
165167
}
166168

169+
Context("New Cluster with Registration Requirement, no need to Encumber", func() {
170+
var cluster *v1beta1.PostgresCluster
171+
172+
BeforeEach(func() {
173+
// PGO_VERSION and REGISTRATION_REQUIRED will be set by OLM installers.
174+
os.Setenv("PGO_VERSION", "v5.4.2")
175+
os.Setenv("REGISTRATION_REQUIRED", "true")
176+
cluster = create(`
177+
metadata:
178+
name: olm
179+
spec:
180+
postgresVersion: 13
181+
image: postgres
182+
instances:
183+
- name: register-now
184+
dataVolumeClaimSpec:
185+
accessModes:
186+
- "ReadWriteMany"
187+
resources:
188+
requests:
189+
storage: 1Gi
190+
backups:
191+
pgbackrest:
192+
image: pgbackrest
193+
repos:
194+
- name: repo1
195+
volume:
196+
volumeClaimSpec:
197+
accessModes:
198+
- "ReadWriteOnce"
199+
resources:
200+
requests:
201+
storage: 1Gi
202+
`)
203+
Expect(reconcile(cluster)).To(BeZero())
204+
})
205+
206+
AfterEach(func() {
207+
ctx := context.Background()
208+
209+
if cluster != nil {
210+
Expect(client.IgnoreNotFound(
211+
suite.Client.Delete(ctx, cluster),
212+
)).To(Succeed())
213+
214+
// Remove finalizers, if any, so the namespace can terminate.
215+
Expect(client.IgnoreNotFound(
216+
suite.Client.Patch(ctx, cluster, client.RawPatch(
217+
client.Merge.Type(), []byte(`{"metadata":{"finalizers":[]}}`))),
218+
)).To(Succeed())
219+
}
220+
os.Unsetenv("PGO_VERSION")
221+
os.Unsetenv("REGISTRATION_REQUIRED")
222+
})
223+
224+
Specify("Cluster RegistrationRequired Status", func() {
225+
existing := &v1beta1.PostgresCluster{}
226+
Expect(suite.Client.Get(
227+
context.Background(), client.ObjectKeyFromObject(cluster), existing,
228+
)).To(Succeed())
229+
230+
registrationRequired := config.RegistrationRequired()
231+
Expect(registrationRequired).To(BeTrue())
232+
233+
pgoVersion := existing.Status.RegistrationRequired.PGOVersion
234+
Expect(pgoVersion).To(Equal("v5.4.2"))
235+
236+
shouldEncumber := shouldEncumberReconciliation(existing)
237+
// Only encumber when the RegistrationRequired PGOVersion <
238+
// the running CPK version.
239+
Expect(shouldEncumber).To(BeFalse())
240+
})
241+
})
242+
167243
Context("Cluster", func() {
168244
var cluster *v1beta1.PostgresCluster
169245

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package postgrescluster
2+
3+
import (
4+
"os"
5+
6+
"golang.org/x/mod/semver"
7+
corev1 "k8s.io/api/core/v1"
8+
"k8s.io/apimachinery/pkg/api/meta"
9+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
10+
11+
"github.com/crunchydata/postgres-operator/internal/config"
12+
"github.com/crunchydata/postgres-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1"
13+
)
14+
15+
func emitAdvanceWarning(cluster *v1beta1.PostgresCluster, r *Reconciler) {
16+
advanceWarning := "Crunchy Postgres for Kubernetes now requires registration for " +
17+
"operator upgrades. Register now to be ready for your next upgrade. See " +
18+
"http://crunchydata.com/register-cpk for further details."
19+
r.Recorder.Event(cluster, corev1.EventTypeWarning, "Register Soon", advanceWarning)
20+
}
21+
22+
func emitEncumbranceWarning(cluster *v1beta1.PostgresCluster, r *Reconciler) {
23+
encumbranceWarning := "Registration required for Crunchy Postgres for Kubernetes to modify " +
24+
cluster.Name + ". See http://crunchydata.com/register-cpk for further details."
25+
r.Recorder.Event(cluster, corev1.EventTypeWarning, "Registration Required", encumbranceWarning)
26+
addTokenRequiredCondition(cluster)
27+
}
28+
29+
func registrationRequiredStatusFound(cluster *v1beta1.PostgresCluster) bool {
30+
return cluster.Status.RegistrationRequired.PGOVersion != ""
31+
}
32+
33+
func addTokenRequiredCondition(cluster *v1beta1.PostgresCluster) {
34+
meta.SetStatusCondition(&cluster.Status.Conditions, metav1.Condition{
35+
Type: v1beta1.TokenRequired,
36+
Status: metav1.ConditionTrue,
37+
Reason: "TokenRequired",
38+
Message: "Reconciliation suspended",
39+
ObservedGeneration: cluster.GetGeneration(),
40+
})
41+
}
42+
43+
func addRegistrationRequiredStatus(cluster *v1beta1.PostgresCluster) {
44+
cluster.Status.RegistrationRequired = v1beta1.RegistrationRequirementStatus{
45+
PGOVersion: os.Getenv("PGO_VERSION"),
46+
}
47+
}
48+
49+
func shouldEncumberReconciliation(cluster *v1beta1.PostgresCluster) bool {
50+
validToken := false
51+
52+
// TODO(tlandreth): Implement token validation.
53+
if validToken {
54+
return false
55+
}
56+
57+
// Get the CPK version that first imposed RegistrationRequired status on this cluster.
58+
trialStartedWith := config.RegistrationRequiredBy(cluster)
59+
currentPGOVersion := os.Getenv("PGO_VERSION")
60+
startedLessThanCurrent := semver.Compare(trialStartedWith, currentPGOVersion) == -1
61+
62+
return startedLessThanCurrent
63+
}

pkg/apis/postgres-operator.crunchydata.com/v1beta1/postgrescluster_test.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,8 @@ status:
6767
postgresVersion: 0
6868
proxy:
6969
pgBouncer: {}
70-
`)+"\n")
70+
registrationRequired: {}
71+
`)+"\n")
7172
})
7273

7374
t.Run("one instance set", func(t *testing.T) {
@@ -105,7 +106,8 @@ status:
105106
postgresVersion: 0
106107
proxy:
107108
pgBouncer: {}
108-
`)+"\n")
109+
registrationRequired: {}
110+
`)+"\n")
109111
})
110112

111113
t.Run("empty proxy", func(t *testing.T) {

pkg/apis/postgres-operator.crunchydata.com/v1beta1/postgrescluster_types.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,14 @@ type PostgresClusterStatus struct {
340340
// +optional
341341
PGBackRest *PGBackRestStatus `json:"pgbackrest,omitempty"`
342342

343+
// Version information for installations with a registration requirement.
344+
// +optional
345+
RegistrationRequired RegistrationRequirementStatus `json:"registrationRequired,omitempty"`
346+
347+
// Signals the need for a token to be applied when registration is required.
348+
// +optional
349+
TokenRequired string `json:"tokenRequired,omitempty"`
350+
343351
// Stores the current PostgreSQL major version following a successful
344352
// major PostgreSQL upgrade.
345353
// +optional
@@ -393,6 +401,8 @@ const (
393401
PersistentVolumeResizing = "PersistentVolumeResizing"
394402
PostgresClusterProgressing = "Progressing"
395403
ProxyAvailable = "ProxyAvailable"
404+
RegistrationRequired = "RegistrationRequired"
405+
TokenRequired = "TokenRequired"
396406
)
397407

398408
type PostgresInstanceSetSpec struct {
@@ -558,6 +568,10 @@ func (s *PostgresProxySpec) Default() {
558568
}
559569
}
560570

571+
type RegistrationRequirementStatus struct {
572+
PGOVersion string `json:"pgoVersion,omitempty"`
573+
}
574+
561575
type PostgresProxyStatus struct {
562576
PGBouncer PGBouncerPodStatus `json:"pgBouncer,omitempty"`
563577
}

pkg/apis/postgres-operator.crunchydata.com/v1beta1/zz_generated.deepcopy.go

Lines changed: 16 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)