Skip to content

Commit 097eae3

Browse files
committed
test(e2e): backup and restore
Run basic backup and restore tests for the plugin. Use MinIO for S3, Azurite for ACS and fake-gcs-server for GCS. Signed-off-by: Francesco Canovai <[email protected]>
1 parent afd4603 commit 097eae3

File tree

26 files changed

+1997
-99
lines changed

26 files changed

+1997
-99
lines changed

go.mod

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ toolchain go1.23.3
66

77
require (
88
github.com/cert-manager/cert-manager v1.16.2
9+
github.com/cloudnative-pg/api v0.0.0-20241116094849-219d7a1d257f
910
github.com/cloudnative-pg/barman-cloud v0.0.0-20241105055149-ae6c2408bd14
1011
github.com/cloudnative-pg/cloudnative-pg v1.24.1-0.20241113134512-8608232c2813
1112
github.com/cloudnative-pg/cnpg-i v0.0.0-20241109002750-8abd359df734
@@ -40,7 +41,6 @@ require (
4041
github.com/blang/semver/v4 v4.0.0 // indirect
4142
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
4243
github.com/cespare/xxhash/v2 v2.3.0 // indirect
43-
github.com/cloudnative-pg/api v0.0.0-20241004125129-98baa9f4957b // indirect
4444
github.com/containerd/log v0.1.0 // indirect
4545
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
4646
github.com/distribution/reference v0.6.0 // indirect
@@ -78,7 +78,7 @@ require (
7878
github.com/inconshreveable/mousetrap v1.1.0 // indirect
7979
github.com/josharian/intern v1.0.0 // indirect
8080
github.com/json-iterator/go v1.1.12 // indirect
81-
github.com/klauspost/compress v1.17.9 // indirect
81+
github.com/klauspost/compress v1.17.11 // indirect
8282
github.com/kubernetes-csi/external-snapshotter/client/v8 v8.0.0 // indirect
8383
github.com/lib/pq v1.10.9 // indirect
8484
github.com/magiconair/properties v1.8.7 // indirect

go.sum

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ github.com/cert-manager/cert-manager v1.16.2 h1:c9UU2E+8XWGruyvC/mdpc1wuLddtgmNr
2424
github.com/cert-manager/cert-manager v1.16.2/go.mod h1:MfLVTL45hFZsqmaT1O0+b2ugaNNQQZttSFV9hASHUb0=
2525
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
2626
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
27-
github.com/cloudnative-pg/api v0.0.0-20241004125129-98baa9f4957b h1:LZ9tIgKmWb8ZvyLg/J8ExXtmBtEWP2dr3Y4TU4nCq/w=
28-
github.com/cloudnative-pg/api v0.0.0-20241004125129-98baa9f4957b/go.mod h1:mzd1EvoLYy16jJdne6/4nwhoj7t4IZ0MqJMEH4mla8Q=
27+
github.com/cloudnative-pg/api v0.0.0-20241116094849-219d7a1d257f h1:KAXst7XLaipdFk9Qv796+tThfEJwFMG4wPLAizZ7wx4=
28+
github.com/cloudnative-pg/api v0.0.0-20241116094849-219d7a1d257f/go.mod h1:aYVZDHteiejVYbntDxJVx1K45xeV8y0KtR/wK4zvt7U=
2929
github.com/cloudnative-pg/barman-cloud v0.0.0-20241105055149-ae6c2408bd14 h1:HX5pXyzVAqfjcDgCa1l8b4sumf7XYnGqiP+6XMgbB2E=
3030
github.com/cloudnative-pg/barman-cloud v0.0.0-20241105055149-ae6c2408bd14/go.mod h1:HPGwXHlatQEnb2HdsbGTZLEo8qlxKLdxTHiTeF9TTqw=
3131
github.com/cloudnative-pg/cloudnative-pg v1.24.1-0.20241113134512-8608232c2813 h1:XWpr5y28JRwcA4BzxBkHFx7C8JDqOSdDIN7RbRdI6Dg=
@@ -126,8 +126,8 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr
126126
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
127127
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
128128
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
129-
github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
130-
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
129+
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
130+
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
131131
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
132132
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
133133
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=

kubernetes/deployment.yaml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ spec:
1818
serviceAccountName: plugin-barman-cloud
1919
containers:
2020
- image: plugin-barman-cloud:latest
21-
imagePullPolicy: IfNotPresent
2221
name: barman-cloud
2322
ports:
2423
- containerPort: 9090

test/e2e/e2e_suite_test.go

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,21 +23,25 @@ import (
2323
"time"
2424

2525
certmanagerv1 "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1"
26+
cloudnativepgv1 "github.com/cloudnative-pg/api/pkg/api/v1"
2627
admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
2728
appsv1 "k8s.io/api/apps/v1"
2829
corev1 "k8s.io/api/core/v1"
2930
rbacv1 "k8s.io/api/rbac/v1"
3031
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
31-
"k8s.io/apimachinery/pkg/runtime"
3232
apimachineryTypes "k8s.io/apimachinery/pkg/types"
3333
"k8s.io/apimachinery/pkg/util/wait"
3434
"sigs.k8s.io/controller-runtime/pkg/client"
3535
kustomizeTypes "sigs.k8s.io/kustomize/api/types"
36+
"sigs.k8s.io/kustomize/kyaml/resid"
3637

38+
pluginBarmanCloudV1 "github.com/cloudnative-pg/plugin-barman-cloud/api/v1"
3739
"github.com/cloudnative-pg/plugin-barman-cloud/test/e2e/internal/deployment"
3840
"github.com/cloudnative-pg/plugin-barman-cloud/test/e2e/internal/e2etestenv"
3941
"github.com/cloudnative-pg/plugin-barman-cloud/test/e2e/internal/kustomize"
4042

43+
_ "github.com/cloudnative-pg/plugin-barman-cloud/test/e2e/internal/tests/backup"
44+
4145
. "github.com/onsi/ginkgo/v2"
4246
. "github.com/onsi/gomega"
4347
)
@@ -72,9 +76,26 @@ var _ = SynchronizedBeforeSuite(func(ctx SpecContext) []byte {
7276
},
7377
},
7478
},
79+
Patches: []kustomizeTypes.Patch{
80+
{
81+
Patch: `[{"op": "replace", "path": "/spec/template/spec/containers/0/imagePullPolicy", "value": "Always"}]`,
82+
Target: &kustomizeTypes.Selector{
83+
ResId: resid.ResId{
84+
Gvk: resid.Gvk{
85+
Group: "apps",
86+
Version: "v1",
87+
Kind: "Deployment",
88+
},
89+
Name: "barman-cloud",
90+
Namespace: "cnpg-system",
91+
},
92+
},
93+
Options: nil,
94+
},
95+
},
7596
}
7697

77-
scheme := runtime.NewScheme()
98+
scheme := cl.Scheme()
7899
if err := corev1.AddToScheme(scheme); err != nil {
79100
Fail(fmt.Sprintf("failed to add core/v1 to scheme: %v", err))
80101
}
@@ -93,6 +114,12 @@ var _ = SynchronizedBeforeSuite(func(ctx SpecContext) []byte {
93114
if err := certmanagerv1.AddToScheme(scheme); err != nil {
94115
Fail(fmt.Sprintf("failed to add cert-manager.io/v1 to scheme: %v", err))
95116
}
117+
if err := pluginBarmanCloudV1.AddToScheme(scheme); err != nil {
118+
Fail(fmt.Sprintf("failed to add plugin-barman-cloud/v1 to scheme: %v", err))
119+
}
120+
if err := cloudnativepgv1.AddToScheme(scheme); err != nil {
121+
Fail(fmt.Sprintf("failed to add postgresql.cnpg.io/v1 to scheme: %v", err))
122+
}
96123

97124
if err := kustomize.ApplyKustomization(ctx, cl, barmanCloudKustomization); err != nil {
98125
Fail(fmt.Sprintf("failed to apply kustomization: %v", err))

test/e2e/internal/certmanager/certmanager.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,23 +29,23 @@ import (
2929
"github.com/cloudnative-pg/plugin-barman-cloud/test/e2e/internal/kustomize"
3030
)
3131

32-
// InstallOptions contains the options for installing cert-manager
32+
// InstallOptions contains the options for installing cert-manager.
3333
type InstallOptions struct {
3434
Version string
3535
IgnoreExistResources bool
3636
}
3737

38-
// InstallOption is a function that sets up an option for installing cert-manager
38+
// InstallOption is a function that sets up an option for installing cert-manager.
3939
type InstallOption func(*InstallOptions)
4040

41-
// WithVersion sets the version of cert-manager to install
41+
// WithVersion sets the version of cert-manager to install.
4242
func WithVersion(version string) InstallOption {
4343
return func(opts *InstallOptions) {
4444
opts.Version = version
4545
}
4646
}
4747

48-
// WithIgnoreExistingResources sets whether to ignore existing resources
48+
// WithIgnoreExistingResources sets whether to ignore existing resources.
4949
func WithIgnoreExistingResources(ignore bool) InstallOption {
5050
return func(opts *InstallOptions) {
5151
opts.IgnoreExistResources = ignore
@@ -54,10 +54,10 @@ func WithIgnoreExistingResources(ignore bool) InstallOption {
5454

5555
// TODO: renovate
5656

57-
// DefaultVersion is the default version of cert-manager to install
57+
// DefaultVersion is the default version of cert-manager to install.
5858
const DefaultVersion = "v1.15.1"
5959

60-
// Install installs cert-manager using kubectl
60+
// Install installs cert-manager using kubectl.
6161
func Install(ctx context.Context, cl client.Client, opts ...InstallOption) error {
6262
options := &InstallOptions{
6363
Version: DefaultVersion,
@@ -98,7 +98,7 @@ func Install(ctx context.Context, cl client.Client, opts ...InstallOption) error
9898
Namespace: "cert-manager",
9999
Name: deploymentName,
100100
}, interval); err != nil {
101-
return err
101+
return fmt.Errorf("failed to wait for deployment %s to be ready: %w", deploymentName, err)
102102
}
103103
}
104104

test/e2e/internal/client/client.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
Copyright 2024.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package client
18+
19+
import (
20+
"fmt"
21+
22+
"k8s.io/client-go/kubernetes"
23+
"k8s.io/client-go/rest"
24+
"sigs.k8s.io/controller-runtime/pkg/client"
25+
"sigs.k8s.io/controller-runtime/pkg/client/config"
26+
)
27+
28+
// NewClient creates a new controller-runtime Kubernetes client.
29+
//
30+
//nolint:ireturn
31+
func NewClient() (client.Client, *rest.Config, error) {
32+
cfg, err := config.GetConfig()
33+
if err != nil {
34+
return nil, nil, fmt.Errorf("failed to get Kubernetes config: %w", err)
35+
}
36+
cl, err := client.New(cfg, client.Options{})
37+
if err != nil {
38+
return nil, nil, fmt.Errorf("failed to create Kubernetes client: %w", err)
39+
}
40+
41+
return cl, cfg, nil
42+
}
43+
44+
// NewClientSet creates a new k8s client-go clientset.
45+
func NewClientSet() (*kubernetes.Clientset, *rest.Config, error) {
46+
cfg, err := config.GetConfig()
47+
if err != nil {
48+
return nil, nil, fmt.Errorf("failed to get Kubernetes config: %w", err)
49+
}
50+
clientSet, err := kubernetes.NewForConfig(cfg)
51+
if err != nil {
52+
return nil, nil, fmt.Errorf("failed to create Kubernetes client: %w", err)
53+
}
54+
55+
return clientSet, cfg, nil
56+
}
Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,5 @@ See the License for the specific language governing permissions and
1414
limitations under the License.
1515
*/
1616

17-
package e2e
18-
19-
import (
20-
. "github.com/onsi/ginkgo/v2"
21-
. "github.com/onsi/gomega"
22-
)
23-
24-
// const namespace = "plugin-barman-cloud-system"
25-
26-
var _ = Describe("controller", Ordered, func() {
27-
It("passes", func() {
28-
Expect(true).To(BeTrue())
29-
})
30-
})
17+
// Package client provides function to create Kubernetes clients.
18+
package client

test/e2e/internal/cloudnativepg/cloudnativepg.go

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"fmt"
2222
"time"
2323

24+
appsv1 "k8s.io/api/apps/v1"
2425
types2 "k8s.io/apimachinery/pkg/types"
2526
"sigs.k8s.io/controller-runtime/pkg/client"
2627
"sigs.k8s.io/kustomize/api/types"
@@ -30,7 +31,7 @@ import (
3031
"github.com/cloudnative-pg/plugin-barman-cloud/test/e2e/internal/kustomize"
3132
)
3233

33-
// InstallCloudNativePGOptions contains the options for installing CloudNativePG
34+
// InstallCloudNativePGOptions contains the options for installing CloudNativePG.
3435
type InstallCloudNativePGOptions struct {
3536
ImageName string
3637
ImageTag string
@@ -40,52 +41,52 @@ type InstallCloudNativePGOptions struct {
4041
IgnoreExistResources bool
4142
}
4243

43-
// InstallOption is a function that sets up an option for installing CloudNativePG
44+
// InstallOption is a function that sets up an option for installing CloudNativePG.
4445
type InstallOption func(*InstallCloudNativePGOptions)
4546

46-
// WithImageName sets the name for the CloudNativePG image
47+
// WithImageName sets the name for the CloudNativePG image.
4748
func WithImageName(ref string) InstallOption {
4849
return func(opts *InstallCloudNativePGOptions) {
4950
opts.ImageName = ref
5051
}
5152
}
5253

53-
// WithImageTag sets the tag for the CloudNativePG image
54+
// WithImageTag sets the tag for the CloudNativePG image.
5455
func WithImageTag(tag string) InstallOption {
5556
return func(opts *InstallCloudNativePGOptions) {
5657
opts.ImageTag = tag
5758
}
5859
}
5960

60-
// WithKustomizationResourceURL sets the URL for the CloudNativePG kustomization
61+
// WithKustomizationResourceURL sets the URL for the CloudNativePG kustomization.
6162
func WithKustomizationResourceURL(url string) InstallOption {
6263
return func(opts *InstallCloudNativePGOptions) {
6364
opts.KustomizationResourceURL = url
6465
}
6566
}
6667

67-
// WithKustomizationRef sets the ref for the CloudNativePG kustomization
68+
// WithKustomizationRef sets the ref for the CloudNativePG kustomization.
6869
func WithKustomizationRef(ref string) InstallOption {
6970
return func(opts *InstallCloudNativePGOptions) {
7071
opts.KustomizationRef = ref
7172
}
7273
}
7374

74-
// WithKustomizationTimeout sets the timeout for the kustomization resources
75+
// WithKustomizationTimeout sets the timeout for the kustomization resources.
7576
func WithKustomizationTimeout(timeout string) InstallOption {
7677
return func(opts *InstallCloudNativePGOptions) {
7778
opts.KustomizationTimeout = timeout
7879
}
7980
}
8081

81-
// WithIgnoreExistingResources sets whether to ignore existing resources
82+
// WithIgnoreExistingResources sets whether to ignore existing resources.
8283
func WithIgnoreExistingResources(ignore bool) InstallOption {
8384
return func(opts *InstallCloudNativePGOptions) {
8485
opts.IgnoreExistResources = ignore
8586
}
8687
}
8788

88-
// Install installs CloudNativePG using kubectl
89+
// Install installs CloudNativePG using kubectl.
8990
func Install(ctx context.Context, cl client.Client, opts ...InstallOption) error {
9091
// Defining the default options
9192
options := &InstallCloudNativePGOptions{
@@ -129,6 +130,16 @@ func Install(ctx context.Context, cl client.Client, opts ...InstallOption) error
129130
},
130131
}
131132

133+
// If the deployment exist, exit doing nothing
134+
// If we redeploy, we'll zero out the webhook ca configuration and the tests will fail
135+
if options.IgnoreExistResources {
136+
deploy := &appsv1.Deployment{}
137+
err := cl.Get(ctx, types2.NamespacedName{Namespace: "cnpg-system", Name: "cnpg-controller-manager"}, deploy)
138+
if err == nil {
139+
return nil
140+
}
141+
}
142+
132143
if err := kustomize.ApplyKustomization(ctx, cl, kustomization); err != nil {
133144
return fmt.Errorf("failed to apply kustomization: %w", err)
134145
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
Copyright 2024.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package cluster
18+
19+
import (
20+
v1 "github.com/cloudnative-pg/api/pkg/api/v1"
21+
)
22+
23+
// TODO: improve this with what we already have in CloudNativePG e2e.
24+
func IsReady(cluster v1.Cluster) bool {
25+
if cluster.Status.ReadyInstances != cluster.Spec.Instances {
26+
return false
27+
}
28+
for _, condition := range cluster.Status.Conditions {
29+
if condition.Type == string(v1.ConditionClusterReady) {
30+
return string(condition.Status) == string(v1.ConditionTrue)
31+
}
32+
}
33+
34+
return false
35+
}

test/e2e/internal/cluster/doc.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/*
2+
Copyright 2024.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
// Package cluster contains functions to interact with the CloudNativePG clusters
18+
package cluster

0 commit comments

Comments
 (0)