Skip to content

Commit 5f50dd1

Browse files
committed
add unit-tests
1 parent fd91c63 commit 5f50dd1

9 files changed

Lines changed: 399 additions & 8 deletions

File tree

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ require (
1818
github.com/kubernetes-csi/external-snapshotter/client/v8 v8.2.0
1919
github.com/onsi/ginkgo/v2 v2.23.4
2020
github.com/onsi/gomega v1.37.0
21-
github.com/pganalyze/pg_query_go/v5 v5.1.0
21+
github.com/pganalyze/pg_query_go/v6 v6.1.0
2222
github.com/pkg/errors v0.9.1
2323
github.com/sirupsen/logrus v1.9.3
2424
github.com/xdg-go/stringprep v1.0.4

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,8 +169,8 @@ github.com/onsi/gomega v1.37.0/go.mod h1:8D9+Txp43QWKhM24yyOBEdpkzN8FvJyAwecBgsU
169169
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
170170
github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs=
171171
github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
172-
github.com/pganalyze/pg_query_go/v5 v5.1.0 h1:MlxQqHZnvA3cbRQYyIrjxEjzo560P6MyTgtlaf3pmXg=
173-
github.com/pganalyze/pg_query_go/v5 v5.1.0/go.mod h1:FsglvxidZsVN+Ltw3Ai6nTgPVcK2BPukH3jCDEqc1Ug=
172+
github.com/pganalyze/pg_query_go/v6 v6.1.0 h1:jG5ZLhcVgL1FAw4C/0VNQaVmX1SUJx71wBGdtTtBvls=
173+
github.com/pganalyze/pg_query_go/v6 v6.1.0/go.mod h1:nvTHIuoud6e1SfrUaFwHqT0i4b5Nr+1rPWVds3B5+50=
174174
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
175175
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
176176
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=

internal/postgres/users.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import (
1010
"encoding/json"
1111
"strings"
1212

13-
pg_query "github.com/pganalyze/pg_query_go/v5"
13+
pg_query "github.com/pganalyze/pg_query_go/v6"
1414

1515
"github.com/percona/percona-postgresql-operator/internal/feature"
1616
"github.com/percona/percona-postgresql-operator/internal/logging"

percona/controller/pgbackup/controller.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -692,10 +692,11 @@ func failIfClusterIsNotReady(ctx context.Context, cl client.Client, pgCluster *v
692692
}
693693

694694
crunchyCluster := new(v1beta1.PostgresCluster)
695-
if err := cl.Get(ctx, types.NamespacedName{Name: pgBackup.Spec.PGCluster, Namespace: pgBackup.Namespace}, crunchyCluster); err != nil {
695+
if err := cl.Get(ctx, client.ObjectKeyFromObject(pgCluster), crunchyCluster); err != nil {
696696
return errors.Wrap(err, "get PostgresCluster")
697697
}
698698

699+
// Waiting for the crunchy cluster to receive the annotations added by the startBackup function.
699700
_, ok := crunchyCluster.Annotations[pNaming.ToCrunchyAnnotation(naming.PGBackRestBackup)]
700701
if !ok {
701702
return nil
@@ -705,7 +706,7 @@ func failIfClusterIsNotReady(ctx context.Context, cl client.Client, pgCluster *v
705706
return nil
706707
}
707708

708-
log.Info("Cluster is not ready for backup for too long. Throwing error")
709+
log.Info("Cluster is not ready for backup for too long. Setting it's state to Failed")
709710

710711
if err := updateStatus(ctx, cl, pgBackup, func(bcp *v2.PerconaPGBackup) {
711712
bcp.Status.State = v2.BackupFailed
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
package pgbackup
2+
3+
import (
4+
"context"
5+
"testing"
6+
"time"
7+
8+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
9+
"sigs.k8s.io/controller-runtime/pkg/client"
10+
11+
"github.com/percona/percona-postgresql-operator/internal/naming"
12+
pNaming "github.com/percona/percona-postgresql-operator/percona/naming"
13+
v2 "github.com/percona/percona-postgresql-operator/pkg/apis/pgv2.percona.com/v2"
14+
"github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1"
15+
)
16+
17+
func TestFailIfClusterIsNotReady(t *testing.T) {
18+
ctx := context.Background()
19+
20+
cr, err := readDefaultCR("ready-for-backup", "ready-for-backup")
21+
if err != nil {
22+
t.Fatal(err)
23+
}
24+
cr.Annotations[pNaming.AnnotationBackupInProgress] = "some-backup"
25+
cr.Annotations[naming.PGBackRestBackup] = "some-backup"
26+
27+
tests := []struct {
28+
name string
29+
cr *v2.PerconaPGCluster
30+
pgBackup *v2.PerconaPGBackup
31+
expectedState v2.PGBackupState
32+
}{
33+
{
34+
name: "no condition",
35+
cr: cr.DeepCopy(),
36+
pgBackup: &v2.PerconaPGBackup{
37+
ObjectMeta: metav1.ObjectMeta{
38+
Name: "some-backup",
39+
Namespace: cr.Namespace,
40+
},
41+
Status: v2.PerconaPGBackupStatus{
42+
State: v2.BackupStarting,
43+
},
44+
},
45+
expectedState: v2.BackupStarting,
46+
},
47+
{
48+
name: "true condition",
49+
cr: func() *v2.PerconaPGCluster {
50+
cr := cr.DeepCopy()
51+
cr.Status.Conditions = append(cr.Status.Conditions, metav1.Condition{
52+
Type: pNaming.ConditionClusterIsReadyForBackup,
53+
Status: metav1.ConditionTrue,
54+
LastTransitionTime: metav1.Now(),
55+
})
56+
return cr
57+
}(),
58+
pgBackup: &v2.PerconaPGBackup{
59+
ObjectMeta: metav1.ObjectMeta{
60+
Name: "some-backup",
61+
Namespace: cr.Namespace,
62+
},
63+
Status: v2.PerconaPGBackupStatus{
64+
State: v2.BackupStarting,
65+
},
66+
},
67+
expectedState: v2.BackupStarting,
68+
},
69+
{
70+
name: "false condition with current time",
71+
cr: func() *v2.PerconaPGCluster {
72+
cr := cr.DeepCopy()
73+
cr.Status.Conditions = append(cr.Status.Conditions, metav1.Condition{
74+
Type: pNaming.ConditionClusterIsReadyForBackup,
75+
Status: metav1.ConditionFalse,
76+
LastTransitionTime: metav1.Now(),
77+
})
78+
return cr
79+
}(),
80+
pgBackup: &v2.PerconaPGBackup{
81+
ObjectMeta: metav1.ObjectMeta{
82+
Name: "some-backup",
83+
Namespace: cr.Namespace,
84+
},
85+
Status: v2.PerconaPGBackupStatus{
86+
State: v2.BackupStarting,
87+
},
88+
},
89+
expectedState: v2.BackupStarting,
90+
},
91+
{
92+
name: "false condition with old time",
93+
cr: func() *v2.PerconaPGCluster {
94+
cr := cr.DeepCopy()
95+
cr.Status.Conditions = append(cr.Status.Conditions, metav1.Condition{
96+
Type: pNaming.ConditionClusterIsReadyForBackup,
97+
Status: metav1.ConditionFalse,
98+
LastTransitionTime: metav1.Time{Time: time.Now().Add(-time.Hour)},
99+
})
100+
return cr
101+
}(),
102+
pgBackup: &v2.PerconaPGBackup{
103+
ObjectMeta: metav1.ObjectMeta{
104+
Name: "some-backup",
105+
Namespace: cr.Namespace,
106+
},
107+
Status: v2.PerconaPGBackupStatus{
108+
State: v2.BackupStarting,
109+
},
110+
},
111+
expectedState: v2.BackupFailed,
112+
},
113+
{
114+
name: "false condition with old time without annotations",
115+
cr: func() *v2.PerconaPGCluster {
116+
cr := cr.DeepCopy()
117+
cr.Annotations = make(map[string]string)
118+
cr.Status.Conditions = append(cr.Status.Conditions, metav1.Condition{
119+
Type: pNaming.ConditionClusterIsReadyForBackup,
120+
Status: metav1.ConditionFalse,
121+
LastTransitionTime: metav1.Time{Time: time.Now().Add(-time.Hour)},
122+
})
123+
return cr
124+
}(),
125+
pgBackup: &v2.PerconaPGBackup{
126+
ObjectMeta: metav1.ObjectMeta{
127+
Name: "some-backup",
128+
Namespace: cr.Namespace,
129+
},
130+
Status: v2.PerconaPGBackupStatus{
131+
State: v2.BackupStarting,
132+
},
133+
},
134+
expectedState: v2.BackupStarting,
135+
},
136+
}
137+
138+
for _, tt := range tests {
139+
t.Run(tt.name, func(t *testing.T) {
140+
cl, err := buildFakeClient(ctx, tt.cr, tt.pgBackup)
141+
if err != nil {
142+
t.Fatal(err)
143+
}
144+
145+
crunchyCluster := new(v1beta1.PostgresCluster)
146+
if err := cl.Get(ctx, client.ObjectKeyFromObject(tt.cr), crunchyCluster); err != nil {
147+
t.Fatal(err)
148+
}
149+
if err := failIfClusterIsNotReady(ctx, cl, tt.cr, tt.pgBackup); err != nil {
150+
t.Fatal(err)
151+
}
152+
bcp := new(v2.PerconaPGBackup)
153+
if err := cl.Get(ctx, client.ObjectKeyFromObject(tt.pgBackup), bcp); err != nil {
154+
t.Fatal(err)
155+
}
156+
if bcp.Status.State != tt.expectedState {
157+
t.Fatalf("expected state: %s; got: %s", tt.expectedState, bcp.Status.State)
158+
}
159+
})
160+
}
161+
}
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
package pgbackup
2+
3+
import (
4+
"context"
5+
"os"
6+
"path/filepath"
7+
8+
appsv1 "k8s.io/api/apps/v1"
9+
corev1 "k8s.io/api/core/v1"
10+
k8serrors "k8s.io/apimachinery/pkg/api/errors"
11+
"k8s.io/apimachinery/pkg/util/yaml"
12+
"k8s.io/client-go/kubernetes/scheme"
13+
"sigs.k8s.io/controller-runtime/pkg/client"
14+
"sigs.k8s.io/controller-runtime/pkg/client/fake"
15+
16+
"github.com/percona/percona-postgresql-operator/internal/naming"
17+
pNaming "github.com/percona/percona-postgresql-operator/percona/naming"
18+
v2 "github.com/percona/percona-postgresql-operator/pkg/apis/pgv2.percona.com/v2"
19+
"github.com/percona/percona-postgresql-operator/pkg/apis/postgres-operator.crunchydata.com/v1beta1"
20+
)
21+
22+
type fakeClient struct {
23+
client.Client
24+
}
25+
26+
var _ = client.Client(new(fakeClient))
27+
28+
func (f *fakeClient) Patch(ctx context.Context, obj client.Object, patch client.Patch, options ...client.PatchOption) error {
29+
err := f.Client.Patch(ctx, obj, patch, options...)
30+
if !k8serrors.IsNotFound(err) {
31+
return err
32+
}
33+
if err := f.Client.Create(ctx, obj); err != nil {
34+
return err
35+
}
36+
return f.Client.Patch(ctx, obj, patch, options...)
37+
}
38+
39+
func buildFakeClient(ctx context.Context, cr *v2.PerconaPGCluster, objs ...client.Object) (client.Client, error) {
40+
s := scheme.Scheme
41+
42+
if err := v1beta1.AddToScheme(s); err != nil {
43+
return nil, err
44+
}
45+
if err := v2.AddToScheme(s); err != nil {
46+
return nil, err
47+
}
48+
49+
objs = append(objs, cr)
50+
cr.Default()
51+
postgresCluster, err := cr.ToCrunchy(ctx, nil, s)
52+
if err != nil {
53+
return nil, err
54+
}
55+
objs = append(objs, postgresCluster)
56+
57+
dcs := &corev1.Endpoints{ObjectMeta: naming.PatroniDistributedConfiguration(postgresCluster)}
58+
dcs.Annotations = map[string]string{
59+
"initialize": "system-identifier",
60+
}
61+
objs = append(objs, dcs)
62+
63+
cl := new(fakeClient)
64+
cl.Client = fake.NewClientBuilder().WithScheme(s).WithObjects(objs...).WithStatusSubresource(objs...).Build()
65+
66+
return cl, nil
67+
}
68+
69+
func readDefaultCR(name, namespace string) (*v2.PerconaPGCluster, error) {
70+
data, err := os.ReadFile(filepath.Join("..", "..", "..", "deploy", "cr.yaml"))
71+
if err != nil {
72+
return nil, err
73+
}
74+
75+
cr := &v2.PerconaPGCluster{}
76+
77+
if err := yaml.Unmarshal(data, cr); err != nil {
78+
return nil, err
79+
}
80+
81+
cr.Name = name
82+
if cr.Annotations == nil {
83+
cr.Annotations = make(map[string]string)
84+
}
85+
cr.Spec.InitContainer = &v1beta1.InitContainerSpec{
86+
Image: "some-image",
87+
}
88+
cr.Annotations[pNaming.AnnotationCustomPatroniVersion] = "4.0.0"
89+
cr.Namespace = namespace
90+
cr.Status.Postgres.Version = cr.Spec.PostgresVersion
91+
return cr, nil
92+
}
93+
94+
func readDefaultOperator(name, namespace string) (*appsv1.Deployment, error) {
95+
data, err := os.ReadFile(filepath.Join("..", "..", "..", "deploy", "operator.yaml"))
96+
if err != nil {
97+
return nil, err
98+
}
99+
100+
cr := &appsv1.Deployment{}
101+
102+
if err := yaml.Unmarshal(data, cr); err != nil {
103+
return nil, err
104+
}
105+
106+
cr.Name = name
107+
cr.Namespace = namespace
108+
return cr, nil
109+
}

percona/controller/pgcluster/schedule.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ func (r *PGClusterReconciler) createScheduledBackup(log logr.Logger, backupName,
109109
}
110110
condition := meta.FindStatusCondition(cr.Status.Conditions, pNaming.ConditionClusterIsReadyForBackup)
111111
if condition != nil && condition.Status == metav1.ConditionFalse {
112-
log.Info("ReadyForBackup condition is set to true. Can't start scheduled backup")
112+
log.Info("ReadyForBackup condition is set to false. Can't start scheduled backup")
113113
return nil
114114
}
115115

percona/controller/pgcluster/status.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,6 @@ func updateConditions(cr *v2.PerconaPGCluster, status *v1beta1.PostgresClusterSt
157157
return
158158
}
159159

160-
setClusterNotReadyCondition(metav1.ConditionTrue, postgrescluster.ConditionReplicaCreate)
160+
setClusterNotReadyCondition(metav1.ConditionTrue, "AllConditionsAreTrue")
161161
return
162162
}

0 commit comments

Comments
 (0)