chore: review

Signed-off-by: Leonardo Cecchi <leonardo.cecchi@enterprisedb.com>
This commit is contained in:
Leonardo Cecchi 2024-10-30 11:33:43 +01:00
parent 4bd0f2ab63
commit aa70ae33ea
15 changed files with 439 additions and 344 deletions

View File

@ -8,14 +8,15 @@ spec:
bootstrap:
recovery:
backup:
name: backup-example
usePlugin: true
source: source
plugins:
- name: barman-cloud.cloudnative-pg.io
# parameters:
# barmanObjectName: minio-store
externalClusters:
- name: source
plugin:
name: barman-cloud.cloudnative-pg.io
parameters:
barmanObjectName: minio-store
serverName: cluster-example
storage:
size: 1Gi

34
go.mod
View File

@ -6,20 +6,20 @@ toolchain go1.23.1
require (
github.com/cloudnative-pg/barman-cloud v0.0.0-20240924124724-92831d48562a
github.com/cloudnative-pg/cloudnative-pg v1.24.1-0.20241017151552-20297270038b
github.com/cloudnative-pg/cnpg-i v0.0.0-20241021130537-c4a74d755f0a
github.com/cloudnative-pg/cloudnative-pg v1.24.1-0.20241031170209-ad2b0d78a230
github.com/cloudnative-pg/cnpg-i v0.0.0-20241030162745-80b6d07403c1
github.com/cloudnative-pg/cnpg-i-machinery v0.0.0-20241014090747-e9c2b3738d19
github.com/cloudnative-pg/machinery v0.0.0-20241010122207-5ac7af31ef72
github.com/cloudnative-pg/machinery v0.0.0-20241014090714-c27747f9974b
github.com/onsi/ginkgo/v2 v2.20.2
github.com/onsi/gomega v1.34.2
github.com/spf13/cobra v1.8.1
github.com/spf13/viper v1.19.0
google.golang.org/grpc v1.67.1
k8s.io/api v0.31.1
k8s.io/apimachinery v0.31.1
k8s.io/client-go v0.31.1
k8s.io/api v0.31.2
k8s.io/apimachinery v0.31.2
k8s.io/client-go v0.31.2
k8s.io/utils v0.0.0-20240921022957-49e7df575cb6
sigs.k8s.io/controller-runtime v0.19.0
sigs.k8s.io/controller-runtime v0.19.1
)
require (
@ -74,8 +74,8 @@ require (
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.77.1 // indirect
github.com/prometheus/client_golang v1.20.4 // indirect
github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.77.2 // indirect
github.com/prometheus/client_golang v1.20.5 // indirect
github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/common v0.59.1 // indirect
github.com/prometheus/procfs v0.15.1 // indirect
@ -102,13 +102,13 @@ require (
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.27.0 // indirect
golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 // indirect
golang.org/x/net v0.29.0 // indirect
golang.org/x/net v0.30.0 // indirect
golang.org/x/oauth2 v0.23.0 // indirect
golang.org/x/sync v0.8.0 // indirect
golang.org/x/sys v0.25.0 // indirect
golang.org/x/term v0.24.0 // indirect
golang.org/x/text v0.18.0 // indirect
golang.org/x/time v0.6.0 // indirect
golang.org/x/sys v0.26.0 // indirect
golang.org/x/term v0.25.0 // indirect
golang.org/x/text v0.19.0 // indirect
golang.org/x/time v0.7.0 // indirect
golang.org/x/tools v0.25.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 // indirect
@ -118,9 +118,9 @@ require (
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/apiextensions-apiserver v0.31.1 // indirect
k8s.io/apiserver v0.31.1 // indirect
k8s.io/component-base v0.31.1 // indirect
k8s.io/apiextensions-apiserver v0.31.2 // indirect
k8s.io/apiserver v0.31.2 // indirect
k8s.io/component-base v0.31.2 // indirect
k8s.io/klog/v2 v2.130.1 // indirect
k8s.io/kube-openapi v0.0.0-20240903163716-9e1beecbcb38 // indirect
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.30.3 // indirect

68
go.sum
View File

@ -18,14 +18,14 @@ github.com/cloudnative-pg/api v0.0.0-20241004125129-98baa9f4957b h1:LZ9tIgKmWb8Z
github.com/cloudnative-pg/api v0.0.0-20241004125129-98baa9f4957b/go.mod h1:mzd1EvoLYy16jJdne6/4nwhoj7t4IZ0MqJMEH4mla8Q=
github.com/cloudnative-pg/barman-cloud v0.0.0-20240924124724-92831d48562a h1:0v1ML9Eibfq3helbT9GtU0EstqFtG91k/MPO9azY5ME=
github.com/cloudnative-pg/barman-cloud v0.0.0-20240924124724-92831d48562a/go.mod h1:Jm0tOp5oB7utpt8wz6RfSv31h1mThOtffjfyxVupriE=
github.com/cloudnative-pg/cloudnative-pg v1.24.1-0.20241017151552-20297270038b h1:47OKNQRgSs9XWvIt2bm8B1Yo7TA5oxBGjQPqF0j+Llw=
github.com/cloudnative-pg/cloudnative-pg v1.24.1-0.20241017151552-20297270038b/go.mod h1:0grklCuA9WSA5lazBeTgDqLHjxP13fqAhqlveDx7hPg=
github.com/cloudnative-pg/cnpg-i v0.0.0-20241021130537-c4a74d755f0a h1:K4c+gX96NAt9C3AeffB8T4tvI3Qn9Fpi5x7Kzd+Iiyg=
github.com/cloudnative-pg/cnpg-i v0.0.0-20241021130537-c4a74d755f0a/go.mod h1:fAU7ySVzjpt/RZntxWZiWJCjaBJayzIxEnd0NuO7oQc=
github.com/cloudnative-pg/cloudnative-pg v1.24.1-0.20241031170209-ad2b0d78a230 h1:zRqm1WUMOqkPWGyvtvCAdWlQ+WTtb0iQA/rvCar27/E=
github.com/cloudnative-pg/cloudnative-pg v1.24.1-0.20241031170209-ad2b0d78a230/go.mod h1:La89zdElTqqZ5LXHFm/UjOwvS9iHSE8GuOW4fYUgHw8=
github.com/cloudnative-pg/cnpg-i v0.0.0-20241030162745-80b6d07403c1 h1:v3Vr+FH5BXmS7Eqx17u51oijZ4T7y62vUMCUAr7CffE=
github.com/cloudnative-pg/cnpg-i v0.0.0-20241030162745-80b6d07403c1/go.mod h1:fAU7ySVzjpt/RZntxWZiWJCjaBJayzIxEnd0NuO7oQc=
github.com/cloudnative-pg/cnpg-i-machinery v0.0.0-20241014090747-e9c2b3738d19 h1:qy+LrScvQpIwt4qeg9FfCJuoC9CbX/kpFGLF8vSobXg=
github.com/cloudnative-pg/cnpg-i-machinery v0.0.0-20241014090747-e9c2b3738d19/go.mod h1:X6r1fRuUEIAv4+5SSBY2RmQ201K6GcptOXgnmaX/8tY=
github.com/cloudnative-pg/machinery v0.0.0-20241010122207-5ac7af31ef72 h1:3pgtSYhv3RDd+51bnlqICNrcVpWQQvriCOvkxtbZpaE=
github.com/cloudnative-pg/machinery v0.0.0-20241010122207-5ac7af31ef72/go.mod h1:bWp1Es5zlxElg4Z/c5f0RKOkDcyNvDHdYIvNcPQU4WM=
github.com/cloudnative-pg/machinery v0.0.0-20241014090714-c27747f9974b h1:4Q2VQsPlLHliJdi87zodQ0FHLd1cJINMm4N70eu8rRg=
github.com/cloudnative-pg/machinery v0.0.0-20241014090714-c27747f9974b/go.mod h1:+mUFdys1IX+qwQUrV+/i56Tey/mYh8ZzWZYttwivRns=
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@ -140,10 +140,10 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.77.1 h1:XGoEXT6WTTihO+MD8MAao+YaQIH905HbK0WK2lyo28k=
github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.77.1/go.mod h1:D0KY8md81DQKdaR/cXwnhoWB3MYYyc/UjvqE8GFkIvA=
github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI=
github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.77.2 h1:F/MALZ518KfI1zEg+Kg8/uTzoXKDyqw+LNC/5irJlJE=
github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.77.2/go.mod h1:D0KY8md81DQKdaR/cXwnhoWB3MYYyc/UjvqE8GFkIvA=
github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y=
github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
github.com/prometheus/common v0.59.1 h1:LXb1quJHWm1P6wq/U824uxYi4Sg0oGvNeUm1z5dJoX0=
@ -228,8 +228,8 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo=
golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0=
golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4=
golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU=
golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs=
golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -240,16 +240,16 @@ golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM=
golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8=
golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24=
golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224=
golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U=
golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM=
golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ=
golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
@ -286,18 +286,18 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
k8s.io/api v0.31.1 h1:Xe1hX/fPW3PXYYv8BlozYqw63ytA92snr96zMW9gWTU=
k8s.io/api v0.31.1/go.mod h1:sbN1g6eY6XVLeqNsZGLnI5FwVseTrZX7Fv3O26rhAaI=
k8s.io/apiextensions-apiserver v0.31.1 h1:L+hwULvXx+nvTYX/MKM3kKMZyei+UiSXQWciX/N6E40=
k8s.io/apiextensions-apiserver v0.31.1/go.mod h1:tWMPR3sgW+jsl2xm9v7lAyRF1rYEK71i9G5dRtkknoQ=
k8s.io/apimachinery v0.31.1 h1:mhcUBbj7KUjaVhyXILglcVjuS4nYXiwC+KKFBgIVy7U=
k8s.io/apimachinery v0.31.1/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo=
k8s.io/apiserver v0.31.1 h1:Sars5ejQDCRBY5f7R3QFHdqN3s61nhkpaX8/k1iEw1c=
k8s.io/apiserver v0.31.1/go.mod h1:lzDhpeToamVZJmmFlaLwdYZwd7zB+WYRYIboqA1kGxM=
k8s.io/client-go v0.31.1 h1:f0ugtWSbWpxHR7sjVpQwuvw9a3ZKLXX0u0itkFXufb0=
k8s.io/client-go v0.31.1/go.mod h1:sKI8871MJN2OyeqRlmA4W4KM9KBdBUpDLu/43eGemCg=
k8s.io/component-base v0.31.1 h1:UpOepcrX3rQ3ab5NB6g5iP0tvsgJWzxTyAo20sgYSy8=
k8s.io/component-base v0.31.1/go.mod h1:WGeaw7t/kTsqpVTaCoVEtillbqAhF2/JgvO0LDOMa0w=
k8s.io/api v0.31.2 h1:3wLBbL5Uom/8Zy98GRPXpJ254nEFpl+hwndmk9RwmL0=
k8s.io/api v0.31.2/go.mod h1:bWmGvrGPssSK1ljmLzd3pwCQ9MgoTsRCuK35u6SygUk=
k8s.io/apiextensions-apiserver v0.31.2 h1:W8EwUb8+WXBLu56ser5IudT2cOho0gAKeTOnywBLxd0=
k8s.io/apiextensions-apiserver v0.31.2/go.mod h1:i+Geh+nGCJEGiCGR3MlBDkS7koHIIKWVfWeRFiOsUcM=
k8s.io/apimachinery v0.31.2 h1:i4vUt2hPK56W6mlT7Ry+AO8eEsyxMD1U44NR22CLTYw=
k8s.io/apimachinery v0.31.2/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo=
k8s.io/apiserver v0.31.2 h1:VUzOEUGRCDi6kX1OyQ801m4A7AUPglpsmGvdsekmcI4=
k8s.io/apiserver v0.31.2/go.mod h1:o3nKZR7lPlJqkU5I3Ove+Zx3JuoFjQobGX1Gctw6XuE=
k8s.io/client-go v0.31.2 h1:Y2F4dxU5d3AQj+ybwSMqQnpZH9F30//1ObxOKlTI9yc=
k8s.io/client-go v0.31.2/go.mod h1:NPa74jSVR/+eez2dFsEIHNa+3o09vtNaWwWwb1qSxSs=
k8s.io/component-base v0.31.2 h1:Z1J1LIaC0AV+nzcPRFqfK09af6bZ4D1nAOpWsy9owlA=
k8s.io/component-base v0.31.2/go.mod h1:9PeyyFN/drHjtJZMCTkSpQJS3U9OXORnHQqMLDz0sUQ=
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/kube-openapi v0.0.0-20240903163716-9e1beecbcb38 h1:1dWzkmJrrprYvjGwh9kEUxmcUV/CtNU8QM7h1FLWQOo=
@ -306,8 +306,8 @@ k8s.io/utils v0.0.0-20240921022957-49e7df575cb6 h1:MDF6h2H/h4tbzmtIKTuctcwZmY0tY
k8s.io/utils v0.0.0-20240921022957-49e7df575cb6/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.30.3 h1:2770sDpzrjjsAtVhSeUFseziht227YAWYHLGNM8QPwY=
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.30.3/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw=
sigs.k8s.io/controller-runtime v0.19.0 h1:nWVM7aq+Il2ABxwiCizrVDSlmDcshi9llbaFbC0ji/Q=
sigs.k8s.io/controller-runtime v0.19.0/go.mod h1:iRmWllt8IlaLjvTTDLhRBXIEtkCK6hwVBJJsYS9Ajf4=
sigs.k8s.io/controller-runtime v0.19.1 h1:Son+Q40+Be3QWb+niBXAg2vFiYWolDjjRfO8hn/cxOk=
sigs.k8s.io/controller-runtime v0.19.1/go.mod h1:iRmWllt8IlaLjvTTDLhRBXIEtkCK6hwVBJJsYS9Ajf4=
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo=
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4=

View File

@ -36,8 +36,6 @@ func NewCmd() *cobra.Command {
}
_ = viper.BindEnv("namespace", "NAMESPACE")
_ = viper.BindEnv("backup-to-restore", "BACKUP_TO_RESTORE")
_ = viper.BindEnv("barman-archive-configuration", "BARMAN_OBJECT_NAME")
_ = viper.BindEnv("cluster-name", "CLUSTER_NAME")
_ = viper.BindEnv("pod-name", "POD_NAME")
_ = viper.BindEnv("pgdata", "PGDATA")

View File

@ -1,21 +0,0 @@
package common
import (
"encoding/json"
"fmt"
barmanapi "github.com/cloudnative-pg/barman-cloud/pkg/api"
cnpgv1 "github.com/cloudnative-pg/cloudnative-pg/api/v1"
)
// GetCredentialsFromBackup extracts the Barman credentials from the backup
func GetCredentialsFromBackup(backup *cnpgv1.Backup) (barmanapi.BarmanCredentials, error) {
rawCred := backup.Status.PluginMetadata["credentials"]
var creds barmanapi.BarmanCredentials
if err := json.Unmarshal([]byte(rawCred), &creds); err != nil {
return barmanapi.BarmanCredentials{}, fmt.Errorf("while unmarshaling credentials: %w", err)
}
return creds, nil
}

View File

@ -0,0 +1,72 @@
package common
import (
"fmt"
"strings"
barmanapi "github.com/cloudnative-pg/barman-cloud/pkg/api"
)
// TODO: refactor.
const (
// ScratchDataDirectory is the directory to be used for scratch data.
ScratchDataDirectory = "/controller"
// CertificatesDir location to store the certificates.
CertificatesDir = ScratchDataDirectory + "/certificates/"
// BarmanBackupEndpointCACertificateLocation is the location where the barman endpoint
// CA certificate is stored.
BarmanBackupEndpointCACertificateLocation = CertificatesDir + BarmanBackupEndpointCACertificateFileName
// BarmanBackupEndpointCACertificateFileName is the name of the file in which the barman endpoint
// CA certificate for backups is stored.
BarmanBackupEndpointCACertificateFileName = "backup-" + BarmanEndpointCACertificateFileName
// BarmanRestoreEndpointCACertificateFileName is the name of the file in which the barman endpoint
// CA certificate for restores is stored.
BarmanRestoreEndpointCACertificateFileName = "restore-" + BarmanEndpointCACertificateFileName
// BarmanEndpointCACertificateFileName is the name of the file in which the barman endpoint
// CA certificate is stored.
BarmanEndpointCACertificateFileName = "barman-ca.crt"
)
// GetRestoreCABundleEnv gets the enveronment variables to be used when custom
// Object Store CA is present
func GetRestoreCABundleEnv(configuration *barmanapi.BarmanObjectStoreConfiguration) []string {
var env []string
if configuration.EndpointCA != nil && configuration.BarmanCredentials.AWS != nil {
env = append(env, fmt.Sprintf("AWS_CA_BUNDLE=%s", BarmanBackupEndpointCACertificateLocation))
} else if configuration.EndpointCA != nil && configuration.BarmanCredentials.Azure != nil {
env = append(env, fmt.Sprintf("REQUESTS_CA_BUNDLE=%s", BarmanBackupEndpointCACertificateLocation))
}
return env
}
// MergeEnv merges all the values inside incomingEnv into env.
func MergeEnv(env []string, incomingEnv []string) []string {
result := make([]string, len(env), len(env)+len(incomingEnv))
copy(result, env)
for _, incomingItem := range incomingEnv {
incomingKV := strings.SplitAfterN(incomingItem, "=", 2)
if len(incomingKV) != 2 {
continue
}
found := false
for idx, item := range result {
if strings.HasPrefix(item, incomingKV[0]) {
result[idx] = incomingItem
found = true
}
}
if !found {
result = append(result, incomingItem)
}
}
return result
}

View File

@ -2,7 +2,6 @@ package instance
import (
"context"
"encoding/json"
"fmt"
"os"
"strconv"
@ -11,6 +10,7 @@ import (
barmanBackup "github.com/cloudnative-pg/barman-cloud/pkg/backup"
barmanCapabilities "github.com/cloudnative-pg/barman-cloud/pkg/capabilities"
barmanCredentials "github.com/cloudnative-pg/barman-cloud/pkg/credentials"
cnpgv1 "github.com/cloudnative-pg/cloudnative-pg/api/v1"
"github.com/cloudnative-pg/cloudnative-pg/pkg/postgres"
"github.com/cloudnative-pg/cnpg-i/pkg/backup"
"github.com/cloudnative-pg/machinery/pkg/fileutils"
@ -20,6 +20,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
barmancloudv1 "github.com/cloudnative-pg/plugin-barman-cloud/api/v1"
"github.com/cloudnative-pg/plugin-barman-cloud/internal/cnpgi/common"
"github.com/cloudnative-pg/plugin-barman-cloud/internal/cnpgi/metadata"
)
@ -69,6 +70,11 @@ func (b BackupServiceImplementation) Backup(
contextLogger.Info("Starting backup")
var cluster cnpgv1.Cluster
if err := b.Client.Get(ctx, b.ClusterObjectKey, &cluster); err != nil {
return nil, err
}
var objectStore barmancloudv1.ObjectStore
if err := b.Client.Get(ctx, b.BarmanObjectKey, &objectStore); err != nil {
contextLogger.Error(err, "while getting object store", "key", b.BarmanObjectKey)
@ -93,24 +99,33 @@ func (b BackupServiceImplementation) Backup(
// We need to connect to PostgreSQL and to do that we need
// PGHOST (and the like) to be available
osEnvironment := os.Environ()
caBundleEnvironment := getRestoreCABundleEnv(&objectStore.Spec.Configuration)
caBundleEnvironment := common.GetRestoreCABundleEnv(&objectStore.Spec.Configuration)
env, err := barmanCredentials.EnvSetBackupCloudCredentials(
ctx,
b.Client,
objectStore.Namespace,
&objectStore.Spec.Configuration,
mergeEnv(osEnvironment, caBundleEnvironment))
common.MergeEnv(osEnvironment, caBundleEnvironment))
if err != nil {
contextLogger.Error(err, "while setting backup cloud credentials")
return nil, err
}
serverName := cluster.Name
for _, plugin := range cluster.Spec.Plugins {
if plugin.IsEnabled() && plugin.Name == metadata.PluginName {
if pluginServerName, ok := plugin.Parameters["serverName"]; ok {
serverName = pluginServerName
}
}
}
backupName := fmt.Sprintf("backup-%v", pgTime.ToCompactISO8601(time.Now()))
if err = backupCmd.Take(
ctx,
backupName,
objectStore.Name,
serverName,
env,
barmanCloudExecutor{},
postgres.BackupTemporaryDirectory,
@ -122,7 +137,7 @@ func (b BackupServiceImplementation) Backup(
executedBackupInfo, err := backupCmd.GetExecutedBackupInfo(
ctx,
backupName,
objectStore.Name,
serverName,
barmanCloudExecutor{},
env)
if err != nil {
@ -130,25 +145,6 @@ func (b BackupServiceImplementation) Backup(
return nil, err
}
cred, err := json.Marshal(objectStore.Spec.Configuration.BarmanCredentials)
if err != nil {
contextLogger.Error(err, "while marshalling credentials")
return nil, err
}
var endpointCA *backup.KeyName
if objectStore.Spec.Configuration.EndpointCA != nil {
endpointCA = &backup.KeyName{
Name: objectStore.Spec.Configuration.EndpointCA.Name,
Key: objectStore.Spec.Configuration.EndpointCA.Key,
}
}
var encryption string
if objectStore.Spec.Configuration.Data != nil {
encryption = string(objectStore.Spec.Configuration.Data.Encryption)
}
contextLogger.Info("Backup completed", "backup", executedBackupInfo.ID)
return &backup.BackupResult{
BackupId: executedBackupInfo.ID,
@ -166,13 +162,6 @@ func (b BackupServiceImplementation) Backup(
"version": metadata.Data.Version,
"name": metadata.Data.Name,
"displayName": metadata.Data.DisplayName,
// TODO: is it safe?
"credentials": string(cred),
},
ServerName: objectStore.Name,
EndpointUrl: objectStore.Spec.Configuration.EndpointURL,
DestinationPath: objectStore.Spec.Configuration.DestinationPath,
EndpointCa: endpointCA,
Encryption: encryption,
}, nil
}

View File

@ -6,10 +6,8 @@ import (
"fmt"
"os"
"path"
"strings"
"time"
barmanapi "github.com/cloudnative-pg/barman-cloud/pkg/api"
"github.com/cloudnative-pg/barman-cloud/pkg/archiver"
barmanCommand "github.com/cloudnative-pg/barman-cloud/pkg/command"
barmanCredentials "github.com/cloudnative-pg/barman-cloud/pkg/credentials"
@ -21,6 +19,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
barmancloudv1 "github.com/cloudnative-pg/plugin-barman-cloud/api/v1"
"github.com/cloudnative-pg/plugin-barman-cloud/internal/cnpgi/common"
"github.com/cloudnative-pg/plugin-barman-cloud/internal/cnpgi/metadata"
)
@ -66,6 +65,21 @@ func (w WALServiceImplementation) Archive(
ctx context.Context,
request *wal.WALArchiveRequest,
) (*wal.WALArchiveResult, error) {
var cluster cnpgv1.Cluster
if err := w.Client.Get(ctx, w.ClusterObjectKey, &cluster); err != nil {
return nil, err
}
// TODO: refactor this code elsewhere
serverName := cluster.Name
for _, plugin := range cluster.Spec.Plugins {
if plugin.IsEnabled() && plugin.Name == metadata.PluginName {
if pluginServerName, ok := plugin.Parameters["serverName"]; ok {
serverName = pluginServerName
}
}
}
var objectStore barmancloudv1.ObjectStore
if err := w.Client.Get(ctx, w.BarmanObjectKey, &objectStore); err != nil {
return nil, err
@ -95,7 +109,7 @@ func (w WALServiceImplementation) Archive(
return nil, err
}
options, err := arch.BarmanCloudWalArchiveOptions(ctx, &objectStore.Spec.Configuration, objectStore.Name)
options, err := arch.BarmanCloudWalArchiveOptions(ctx, &objectStore.Spec.Configuration, serverName)
if err != nil {
return nil, err
}
@ -111,6 +125,7 @@ func (w WALServiceImplementation) Archive(
}
// Restore implements the WALService interface
// nolint: gocognit
func (w WALServiceImplementation) Restore(
ctx context.Context,
request *wal.WALRestoreRequest,
@ -134,7 +149,7 @@ func (w WALServiceImplementation) Restore(
barmanConfiguration := &objectStore.Spec.Configuration
env := getRestoreCABundleEnv(barmanConfiguration)
env := common.GetRestoreCABundleEnv(barmanConfiguration)
credentialsEnv, err := barmanCredentials.EnvSetBackupCloudCredentials(
ctx,
w.Client,
@ -145,9 +160,19 @@ func (w WALServiceImplementation) Restore(
if err != nil {
return nil, fmt.Errorf("while getting recover credentials: %w", err)
}
env = mergeEnv(env, credentialsEnv)
env = common.MergeEnv(env, credentialsEnv)
options, err := barmanCommand.CloudWalRestoreOptions(ctx, barmanConfiguration, objectStore.Name)
// TODO: refactor this code elsewhere
serverName := cluster.Name
for _, plugin := range cluster.Spec.Plugins {
if plugin.IsEnabled() && plugin.Name == metadata.PluginName {
if pluginServerName, ok := plugin.Parameters["serverName"]; ok {
serverName = pluginServerName
}
}
}
options, err := barmanCommand.CloudWalRestoreOptions(ctx, barmanConfiguration, serverName)
if err != nil {
return nil, fmt.Errorf("while getting barman-cloud-wal-restore options: %w", err)
}
@ -254,68 +279,6 @@ func (w WALServiceImplementation) SetFirstRequired(
panic("implement me")
}
// mergeEnv merges all the values inside incomingEnv into env.
func mergeEnv(env []string, incomingEnv []string) []string {
result := make([]string, len(env), len(env)+len(incomingEnv))
copy(result, env)
for _, incomingItem := range incomingEnv {
incomingKV := strings.SplitAfterN(incomingItem, "=", 2)
if len(incomingKV) != 2 {
continue
}
found := false
for idx, item := range result {
if strings.HasPrefix(item, incomingKV[0]) {
result[idx] = incomingItem
found = true
}
}
if !found {
result = append(result, incomingItem)
}
}
return result
}
// TODO: refactor.
const (
// ScratchDataDirectory is the directory to be used for scratch data.
ScratchDataDirectory = "/controller"
// CertificatesDir location to store the certificates.
CertificatesDir = ScratchDataDirectory + "/certificates/"
// BarmanBackupEndpointCACertificateLocation is the location where the barman endpoint
// CA certificate is stored.
BarmanBackupEndpointCACertificateLocation = CertificatesDir + BarmanBackupEndpointCACertificateFileName
// BarmanBackupEndpointCACertificateFileName is the name of the file in which the barman endpoint
// CA certificate for backups is stored.
BarmanBackupEndpointCACertificateFileName = "backup-" + BarmanEndpointCACertificateFileName
// BarmanRestoreEndpointCACertificateFileName is the name of the file in which the barman endpoint
// CA certificate for restores is stored.
BarmanRestoreEndpointCACertificateFileName = "restore-" + BarmanEndpointCACertificateFileName
// BarmanEndpointCACertificateFileName is the name of the file in which the barman endpoint
// CA certificate is stored.
BarmanEndpointCACertificateFileName = "barman-ca.crt"
)
func getRestoreCABundleEnv(configuration *barmanapi.BarmanObjectStoreConfiguration) []string {
var env []string
if configuration.EndpointCA != nil && configuration.BarmanCredentials.AWS != nil {
env = append(env, fmt.Sprintf("AWS_CA_BUNDLE=%s", BarmanBackupEndpointCACertificateLocation))
} else if configuration.EndpointCA != nil && configuration.BarmanCredentials.Azure != nil {
env = append(env, fmt.Sprintf("REQUESTS_CA_BUNDLE=%s", BarmanBackupEndpointCACertificateLocation))
}
return env
}
// isStreamingAvailable checks if this pod can replicate via streaming connection.
func isStreamingAvailable(cluster *cnpgv1.Cluster, podName string) bool {
if cluster == nil {

View File

@ -16,6 +16,7 @@ import (
corev1 "k8s.io/api/core/v1"
"k8s.io/utils/ptr"
"github.com/cloudnative-pg/plugin-barman-cloud/internal/cnpgi/metadata"
"github.com/cloudnative-pg/plugin-barman-cloud/internal/cnpgi/operator/config"
)
@ -103,13 +104,11 @@ func reconcileJob(
pluginConfiguration *config.PluginConfiguration,
) (*lifecycle.OperatorLifecycleResponse, error) {
contextLogger := log.FromContext(ctx).WithName("lifecycle")
if !cluster.UsePluginForBootstrapRecoveryBackup() {
contextLogger.Debug("cluster does not use the plugin for recovery, skipping")
if pluginConfig := cluster.GetRecoverySourcePlugin(); pluginConfig == nil || pluginConfig.Name != metadata.PluginName {
contextLogger.Debug("cluster does not use the this plugin for recovery, skipping")
return nil, nil
}
backupSource := cluster.Spec.Bootstrap.Recovery.Backup
var job batchv1.Job
if err := decoder.DecodeObject(
request.GetObjectDefinition(),
@ -138,12 +137,6 @@ func reconcileJob(
"full-recovery",
corev1.Container{
Args: []string{"restore"},
Env: []corev1.EnvVar{
{
Name: "BACKUP_TO_RESTORE",
Value: backupSource.Name,
},
},
},
); err != nil {
return nil, fmt.Errorf("while reconciling pod spec for job: %w", err)
@ -231,9 +224,6 @@ func reconcilePodSpec(
sidecarConfig.Name = "plugin-barman-cloud"
sidecarConfig.Image = viper.GetString("sidecar-image")
sidecarConfig.ImagePullPolicy = cluster.Spec.ImagePullPolicy
sidecarConfig.Command = []string{
"/manager",
}
// merge the main container envs if they aren't already set
for _, container := range spec.Containers {

View File

@ -9,7 +9,6 @@ import (
batchv1 "k8s.io/api/batch/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/utils/ptr"
"github.com/cloudnative-pg/plugin-barman-cloud/internal/cnpgi/operator/config"
@ -34,17 +33,31 @@ var _ = Describe("LifecycleImplementation", func() {
BeforeEach(func() {
pluginConfiguration = &config.PluginConfiguration{
BarmanObjectName: "barman-object",
BarmanObjectName: "minio-store-dest",
}
cluster = &cnpgv1.Cluster{
Spec: cnpgv1.ClusterSpec{
Bootstrap: &cnpgv1.BootstrapConfiguration{
Recovery: &cnpgv1.BootstrapRecovery{
Backup: &cnpgv1.BackupSource{
LocalObjectReference: cnpgv1.LocalObjectReference{
Name: "backup-object",
Source: "origin-server",
},
UsePlugin: ptr.To(true),
},
ExternalClusters: []cnpgv1.ExternalCluster{
{
Name: "origin-server",
PluginConfiguration: &cnpgv1.PluginConfiguration{
Name: "barman-cloud.cloudnative-pg.io",
Parameters: map[string]string{
"barmanObjectName": "minio-store-source",
},
},
},
},
Plugins: cnpgv1.PluginConfigurationList{
{
Name: "barman-cloud.cloudnative-pg.io",
Parameters: map[string]string{
"barmanObjectName": "minio-store-dest",
},
},
},
@ -180,8 +193,9 @@ var _ = Describe("LifecycleImplementation", func() {
err = json.Unmarshal(response.JsonPatch, &patch)
Expect(err).NotTo(HaveOccurred())
Expect(patch).To(ContainElement(HaveKeyWithValue("op", "add")))
Expect(patch).To(ContainElement(HaveKeyWithValue("path", "/spec/containers/1")))
Expect(patch).To(ContainElement(HaveKeyWithValue("value", HaveKeyWithValue("name", "plugin-barman-cloud"))))
Expect(patch).To(ContainElement(HaveKeyWithValue("path", "/spec/initContainers")))
Expect(patch).To(ContainElement(
HaveKey("value")))
})
It("returns an error for invalid pod definition", func(ctx SpecContext) {

View File

@ -15,7 +15,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
barmancloudv1 "github.com/cloudnative-pg/plugin-barman-cloud/api/v1"
"github.com/cloudnative-pg/plugin-barman-cloud/internal/cnpgi/common"
"github.com/cloudnative-pg/plugin-barman-cloud/internal/cnpgi/metadata"
"github.com/cloudnative-pg/plugin-barman-cloud/internal/cnpgi/operator/config"
"github.com/cloudnative-pg/plugin-barman-cloud/internal/cnpgi/operator/specs"
)
@ -75,14 +75,16 @@ func (r ReconcilerImplementation) Pre(
pluginConfiguration := config.NewFromCluster(&cluster)
contextLogger.Debug("parsing barman object configuration")
var barmanObject *barmancloudv1.ObjectStore
var barmanObjects []barmancloudv1.ObjectStore
// this could be empty during recoveries
if pluginConfiguration.BarmanObjectName != "" {
barmanObject = &barmancloudv1.ObjectStore{}
var barmanObject barmancloudv1.ObjectStore
if err := r.Client.Get(ctx, client.ObjectKey{
Namespace: cluster.Namespace,
Name: pluginConfiguration.BarmanObjectName,
}, barmanObject); err != nil {
}, &barmanObject); err != nil {
if apierrs.IsNotFound(err) {
contextLogger.Info("barman object configuration not found, requeuing")
return &reconciler.ReconcilerHooksResult{
@ -92,28 +94,23 @@ func (r ReconcilerImplementation) Pre(
return nil, err
}
barmanObjects = append(barmanObjects, barmanObject)
}
if barmanObject, err := r.getRecoveryBarmanObject(ctx, &cluster); err != nil {
if apierrs.IsNotFound(err) {
contextLogger.Info("barman recovery object configuration not found, requeuing")
return &reconciler.ReconcilerHooksResult{
Behavior: reconciler.ReconcilerHooksResult_BEHAVIOR_REQUEUE,
}, nil
}
} else if barmanObject != nil {
barmanObjects = append(barmanObjects, *barmanObject)
}
var additionalSecretNames []string
if cluster.UsePluginForBootstrapRecoveryBackup() {
var backup cnpgv1.Backup
if err := r.Client.Get(ctx, client.ObjectKey{
Namespace: cluster.Namespace,
Name: cluster.Spec.Bootstrap.Recovery.Backup.Name,
}, &backup); err != nil {
return nil, err
}
credentials, err := common.GetCredentialsFromBackup(&backup)
if err != nil {
return nil, err
}
additionalSecretNames = append(additionalSecretNames, specs.CollectSecretNamesFromCredentials(&credentials)...)
if backup.Status.EndpointCA != nil {
additionalSecretNames = append(additionalSecretNames, backup.Status.EndpointCA.Name)
}
}
if err := r.ensureRole(ctx, &cluster, barmanObject, additionalSecretNames); err != nil {
if err := r.ensureRole(ctx, &cluster, barmanObjects, additionalSecretNames); err != nil {
return nil, err
}
@ -127,6 +124,30 @@ func (r ReconcilerImplementation) Pre(
}, nil
}
func (r ReconcilerImplementation) getRecoveryBarmanObject(
ctx context.Context,
cluster *cnpgv1.Cluster,
) (*barmancloudv1.ObjectStore, error) {
recoveryConfig := cluster.GetRecoverySourcePlugin()
if recoveryConfig != nil && recoveryConfig.Name == metadata.PluginName {
// TODO: refactor -> cnpg-i-machinery should be able to help us on getting
// the configuration for a recovery plugin
if recoveryObjectStore, ok := recoveryConfig.Parameters["barmanObjectName"]; ok {
var barmanObject barmancloudv1.ObjectStore
if err := r.Client.Get(ctx, client.ObjectKey{
Namespace: cluster.Namespace,
Name: recoveryObjectStore,
}, &barmanObject); err != nil {
return nil, err
}
return &barmanObject, nil
}
}
return nil, nil
}
// Post implements the reconciler interface
func (r ReconcilerImplementation) Post(
_ context.Context,
@ -140,11 +161,11 @@ func (r ReconcilerImplementation) Post(
func (r ReconcilerImplementation) ensureRole(
ctx context.Context,
cluster *cnpgv1.Cluster,
barmanObject *barmancloudv1.ObjectStore,
barmanObjects []barmancloudv1.ObjectStore,
additionalSecretNames []string,
) error {
contextLogger := log.FromContext(ctx)
newRole := specs.BuildRole(cluster, barmanObject, additionalSecretNames)
newRole := specs.BuildRole(cluster, barmanObjects, additionalSecretNames)
var role rbacv1.Role
if err := r.Client.Get(ctx, client.ObjectKey{

View File

@ -14,7 +14,7 @@ import (
// BuildRole builds the Role object for this cluster
func BuildRole(
cluster *cnpgv1.Cluster,
barmanObject *barmancloudv1.ObjectStore,
barmanObjects []barmancloudv1.ObjectStore,
additionalSecretNames []string,
) *rbacv1.Role {
role := &rbacv1.Role{
@ -27,8 +27,7 @@ func BuildRole(
}
secretsSet := stringset.New()
// TODO: we should handle removals too?
if barmanObject != nil {
for _, barmanObject := range barmanObjects {
role.Rules = append(role.Rules, rbacv1.PolicyRule{
APIGroups: []string{
"barmancloud.cnpg.io",

View File

@ -32,9 +32,7 @@ func Start(ctx context.Context) error {
setupLog := log.FromContext(ctx)
setupLog.Info("Starting barman cloud instance plugin")
namespace := viper.GetString("namespace")
archiveConfiguration := viper.GetString("barman-archive-configuration")
clusterName := viper.GetString("cluster-name")
backupToRestoreName := viper.GetString("backup-to-restore")
objs := map[client.Object]cache.ByObject{
&cnpgv1.Cluster{}: {
@ -43,20 +41,6 @@ func Start(ctx context.Context) error {
namespace: {},
},
},
&cnpgv1.Backup{}: {
Field: fields.OneTermEqualSelector("metadata.name", backupToRestoreName),
Namespaces: map[string]cache.Config{
namespace: {},
},
},
}
if archiveConfiguration != "" {
objs[&barmancloudv1.ObjectStore{}] = cache.ByObject{
Field: fields.OneTermEqualSelector("metadata.name", archiveConfiguration),
Namespaces: map[string]cache.Config{
namespace: {},
},
}
}
mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
@ -68,6 +52,7 @@ func Start(ctx context.Context) error {
Cache: &client.CacheOptions{
DisableFor: []client.Object{
&corev1.Secret{},
&barmancloudv1.ObjectStore{},
},
},
},
@ -80,18 +65,10 @@ func Start(ctx context.Context) error {
if err := mgr.Add(&CNPGI{
PluginPath: viper.GetString("plugin-path"),
SpoolDirectory: viper.GetString("spool-directory"),
ArchiveConfiguration: client.ObjectKey{
Namespace: namespace,
Name: archiveConfiguration,
},
ClusterObjectKey: client.ObjectKey{
Namespace: namespace,
Name: clusterName,
},
BackupToRestoreObjectKey: client.ObjectKey{
Namespace: namespace,
Name: backupToRestoreName,
},
Client: mgr.GetClient(),
PGDataPath: viper.GetString("pgdata"),
}); err != nil {

View File

@ -12,6 +12,7 @@ import (
"github.com/cloudnative-pg/barman-cloud/pkg/api"
barmanArchiver "github.com/cloudnative-pg/barman-cloud/pkg/archiver"
barmanCapabilities "github.com/cloudnative-pg/barman-cloud/pkg/capabilities"
barmanCatalog "github.com/cloudnative-pg/barman-cloud/pkg/catalog"
barmanCommand "github.com/cloudnative-pg/barman-cloud/pkg/command"
barmanCredentials "github.com/cloudnative-pg/barman-cloud/pkg/credentials"
barmanRestorer "github.com/cloudnative-pg/barman-cloud/pkg/restorer"
@ -22,10 +23,11 @@ import (
"github.com/cloudnative-pg/machinery/pkg/execlog"
"github.com/cloudnative-pg/machinery/pkg/fileutils"
"github.com/cloudnative-pg/machinery/pkg/log"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"
barmancloudv1 "github.com/cloudnative-pg/plugin-barman-cloud/api/v1"
"github.com/cloudnative-pg/plugin-barman-cloud/internal/cnpgi/common"
"github.com/cloudnative-pg/plugin-barman-cloud/internal/cnpgi/metadata"
)
@ -44,7 +46,6 @@ type JobHookImpl struct {
Client client.Client
ClusterObjectKey client.ObjectKey
BackupToRestore client.ObjectKey
ArchiveConfiguration client.ObjectKey
SpoolDirectory string
PgDataPath string
PgWalFolderToSymlink string
@ -78,32 +79,70 @@ func (impl JobHookImpl) Restore(
); err != nil {
return nil, err
}
// Before starting the restore we check if the archive destination is safe to use
// otherwise, we stop creating the cluster
if err := impl.checkBackupDestination(ctx, &cluster); err != nil {
recoveryPluginConfiguration := cluster.GetRecoverySourcePlugin()
var recoveryObjectStore barmancloudv1.ObjectStore
if err := impl.Client.Get(ctx, types.NamespacedName{
Namespace: cluster.Namespace,
// TODO: refactor -> cnpg-i-machinery should be able to help us on getting
// the configuration for a recovery plugin
Name: recoveryPluginConfiguration.Parameters["barmanObjectName"],
}, &recoveryObjectStore); err != nil {
return nil, err
}
var backup cnpgv1.Backup
if err := decoder.DecodeObject(
req.GetBackupDefinition(),
&backup,
cnpgv1.GroupVersion.WithKind("Backup"),
); err != nil {
return nil, err
var targetObjectStoreName types.NamespacedName
for _, plugin := range cluster.Spec.Plugins {
if plugin.IsEnabled() && plugin.Name == metadata.PluginName {
targetObjectStoreName = types.NamespacedName{
Namespace: cluster.Namespace,
Name: plugin.Parameters["barmanObjectName"],
}
}
}
env, err := impl.getBarmanEnvFromBackup(ctx, &backup)
var targetObjectStore barmancloudv1.ObjectStore
if targetObjectStoreName.Name != "" {
if err := impl.Client.Get(ctx, targetObjectStoreName, &targetObjectStore); err != nil {
return nil, err
}
}
// Before starting the restore we check if the archive destination is safe to use,
// otherwise we stop creating the cluster
if targetObjectStoreName.Name != "" {
if err := impl.checkBackupDestination(ctx, &cluster, &targetObjectStore.Spec.Configuration); err != nil {
return nil, err
}
}
// Detect the backup to recover
backup, env, err := loadBackupObjectFromExternalCluster(
ctx,
impl.Client,
&cluster,
&recoveryObjectStore.Spec.Configuration,
)
if err != nil {
return nil, err
}
if err := impl.ensureArchiveContainsLastCheckpointRedoWAL(ctx, &cluster, env, &backup); err != nil {
if err := impl.ensureArchiveContainsLastCheckpointRedoWAL(
ctx,
env,
backup,
&recoveryObjectStore.Spec.Configuration,
); err != nil {
return nil, err
}
if err := impl.restoreDataDir(ctx, &backup, env); err != nil {
if err := impl.restoreDataDir(
ctx,
backup,
env,
&recoveryObjectStore.Spec.Configuration,
); err != nil {
return nil, err
}
@ -113,7 +152,7 @@ func (impl JobHookImpl) Restore(
}
}
config, err := getRestoreWalConfig(ctx, &backup)
config, err := getRestoreWalConfig(ctx, backup, &recoveryObjectStore.Spec.Configuration)
if err != nil {
return nil, err
}
@ -126,7 +165,12 @@ func (impl JobHookImpl) Restore(
}
// restoreDataDir restores PGDATA from an existing backup
func (impl JobHookImpl) restoreDataDir(ctx context.Context, backup *cnpgv1.Backup, env []string) error {
func (impl JobHookImpl) restoreDataDir(
ctx context.Context,
backup *cnpgv1.Backup,
env []string,
barmanConfiguration *cnpgv1.BarmanObjectStoreConfiguration,
) error {
var options []string
if backup.Status.EndpointURL != "" {
@ -136,11 +180,7 @@ func (impl JobHookImpl) restoreDataDir(ctx context.Context, backup *cnpgv1.Backu
options = append(options, backup.Status.ServerName)
options = append(options, backup.Status.BackupID)
creds, err := common.GetCredentialsFromBackup(backup)
if err != nil {
return err
}
options, err = barmanCommand.AppendCloudProviderOptionsFromBackup(ctx, options, creds)
options, err := barmanCommand.AppendCloudProviderOptionsFromConfiguration(ctx, options, barmanConfiguration)
if err != nil {
return err
}
@ -168,9 +208,9 @@ func (impl JobHookImpl) restoreDataDir(ctx context.Context, backup *cnpgv1.Backu
func (impl JobHookImpl) ensureArchiveContainsLastCheckpointRedoWAL(
ctx context.Context,
cluster *cnpgv1.Cluster,
env []string,
backup *cnpgv1.Backup,
barmanConfiguration *cnpgv1.BarmanObjectStoreConfiguration,
) error {
// it's the full path of the file that will temporarily contain the LastCheckpointRedoWAL
const testWALPath = RecoveryTemporaryDirectory + "/test.wal"
@ -191,17 +231,7 @@ func (impl JobHookImpl) ensureArchiveContainsLastCheckpointRedoWAL(
return err
}
creds, err := common.GetCredentialsFromBackup(backup)
if err != nil {
return err
}
opts, err := barmanCommand.CloudWalRestoreOptions(ctx, &api.BarmanObjectStoreConfiguration{
BarmanCredentials: creds,
EndpointCA: backup.Status.EndpointCA,
EndpointURL: backup.Status.EndpointURL,
DestinationPath: backup.Status.DestinationPath,
ServerName: backup.Status.ServerName,
}, cluster.Name)
opts, err := barmanCommand.CloudWalRestoreOptions(ctx, barmanConfiguration, backup.Status.ServerName)
if err != nil {
return err
}
@ -216,21 +246,13 @@ func (impl JobHookImpl) ensureArchiveContainsLastCheckpointRedoWAL(
func (impl *JobHookImpl) checkBackupDestination(
ctx context.Context,
cluster *cnpgv1.Cluster,
barmanConfiguration *cnpgv1.BarmanObjectStoreConfiguration,
) error {
if impl.ArchiveConfiguration.Name == "" {
return nil
}
var barmanObj barmancloudv1.ObjectStore
if err := impl.Client.Get(ctx, impl.ArchiveConfiguration, &barmanObj); err != nil {
return err
}
// Get environment from cache
env, err := barmanCredentials.EnvSetRestoreCloudCredentials(ctx,
impl.Client,
barmanObj.Namespace,
&barmanObj.Spec.Configuration,
cluster.Namespace,
barmanConfiguration,
os.Environ())
if err != nil {
return fmt.Errorf("can't get credentials for cluster %v: %w", cluster.Name, err)
@ -251,9 +273,19 @@ func (impl *JobHookImpl) checkBackupDestination(
return fmt.Errorf("while creating the archiver: %w", err)
}
// TODO: refactor this code elsewhere
serverName := cluster.Name
for _, plugin := range cluster.Spec.Plugins {
if plugin.IsEnabled() && plugin.Name == metadata.PluginName {
if pluginServerName, ok := plugin.Parameters["serverName"]; ok {
serverName = pluginServerName
}
}
}
// Get WAL archive options
checkWalOptions, err := walArchiver.BarmanCloudCheckWalArchiveOptions(
ctx, &barmanObj.Spec.Configuration, barmanObj.Name)
ctx, barmanConfiguration, serverName)
if err != nil {
log.Error(err, "while getting barman-cloud-wal-archive options")
return err
@ -267,34 +299,6 @@ func (impl *JobHookImpl) checkBackupDestination(
return nil
}
func (impl JobHookImpl) getBarmanEnvFromBackup(
ctx context.Context,
backup *cnpgv1.Backup,
) ([]string, error) {
creds, err := common.GetCredentialsFromBackup(backup)
if err != nil {
return nil, err
}
env, err := barmanCredentials.EnvSetRestoreCloudCredentials(
ctx,
impl.Client,
impl.BackupToRestore.Namespace,
&api.BarmanObjectStoreConfiguration{
BarmanCredentials: creds,
EndpointURL: backup.Status.EndpointURL,
EndpointCA: backup.Status.EndpointCA,
DestinationPath: backup.Status.DestinationPath,
ServerName: backup.Status.ServerName,
},
os.Environ())
if err != nil {
return nil, err
}
log.Info("Recovering existing backup", "backup", backup)
return env, nil
}
// restoreCustomWalDir moves the current pg_wal data to the specified custom wal dir and applies the symlink
// returns indicating if any changes were made and any error encountered in the process
func (impl JobHookImpl) restoreCustomWalDir(ctx context.Context) (bool, error) {
@ -332,7 +336,11 @@ func (impl JobHookImpl) restoreCustomWalDir(ctx context.Context) (bool, error) {
// getRestoreWalConfig obtains the content to append to `custom.conf` allowing PostgreSQL
// to complete the WAL recovery from the object storage and then start
// as a new primary
func getRestoreWalConfig(ctx context.Context, backup *cnpgv1.Backup) (string, error) {
func getRestoreWalConfig(
ctx context.Context,
backup *cnpgv1.Backup,
barmanConfiguration *cnpgv1.BarmanObjectStoreConfiguration,
) (string, error) {
var err error
cmd := []string{barmanCapabilities.BarmanCloudWalRestore}
@ -342,12 +350,7 @@ func getRestoreWalConfig(ctx context.Context, backup *cnpgv1.Backup) (string, er
cmd = append(cmd, backup.Status.DestinationPath)
cmd = append(cmd, backup.Status.ServerName)
creds, err := common.GetCredentialsFromBackup(backup)
if err != nil {
return "", err
}
cmd, err = barmanCommand.AppendCloudProviderOptionsFromBackup(ctx, cmd, creds)
cmd, err = barmanCommand.AppendCloudProviderOptionsFromConfiguration(ctx, cmd, barmanConfiguration)
if err != nil {
return "", err
}
@ -361,3 +364,96 @@ func getRestoreWalConfig(ctx context.Context, backup *cnpgv1.Backup) (string, er
return recoveryFileContents, nil
}
// loadBackupObjectFromExternalCluster generates an in-memory Backup structure given a reference to
// an external cluster, loading the required information from the object store
func loadBackupObjectFromExternalCluster(
ctx context.Context,
typedClient client.Client,
cluster *cnpgv1.Cluster,
recoveryObjectStore *api.BarmanObjectStoreConfiguration,
) (*cnpgv1.Backup, []string, error) {
contextLogger := log.FromContext(ctx)
sourceName := cluster.Spec.Bootstrap.Recovery.Source
if sourceName == "" {
return nil, nil, fmt.Errorf("recovery source not specified")
}
server, found := cluster.ExternalCluster(sourceName)
if !found {
return nil, nil, fmt.Errorf("missing external cluster: %v", sourceName)
}
// TODO: document this, should this be in the helper?
var serverName string
if pluginServerName, ok := server.PluginConfiguration.Parameters["serverName"]; ok {
serverName = pluginServerName
} else {
serverName = server.Name
}
contextLogger.Info("Recovering from external cluster",
"sourceName", sourceName,
"serverName", serverName)
env, err := barmanCredentials.EnvSetRestoreCloudCredentials(
ctx,
typedClient,
cluster.Namespace,
recoveryObjectStore,
os.Environ())
if err != nil {
return nil, nil, err
}
backupCatalog, err := barmanCommand.GetBackupList(ctx, recoveryObjectStore, serverName, env)
if err != nil {
return nil, nil, err
}
// We are now choosing the right backup to restore
var targetBackup *barmanCatalog.BarmanBackup
if cluster.Spec.Bootstrap.Recovery != nil &&
cluster.Spec.Bootstrap.Recovery.RecoveryTarget != nil {
targetBackup, err = backupCatalog.FindBackupInfo(
cluster.Spec.Bootstrap.Recovery.RecoveryTarget,
)
if err != nil {
return nil, nil, err
}
} else {
targetBackup = backupCatalog.LatestBackupInfo()
}
if targetBackup == nil {
return nil, nil, fmt.Errorf("no target backup found")
}
contextLogger.Info("Target backup found", "backup", targetBackup)
return &cnpgv1.Backup{
Spec: cnpgv1.BackupSpec{
Cluster: cnpgv1.LocalObjectReference{
Name: serverName,
},
},
Status: cnpgv1.BackupStatus{
BarmanCredentials: recoveryObjectStore.BarmanCredentials,
EndpointCA: recoveryObjectStore.EndpointCA,
EndpointURL: recoveryObjectStore.EndpointURL,
DestinationPath: recoveryObjectStore.DestinationPath,
ServerName: serverName,
BackupID: targetBackup.ID,
Phase: cnpgv1.BackupPhaseCompleted,
StartedAt: &metav1.Time{Time: targetBackup.BeginTime},
StoppedAt: &metav1.Time{Time: targetBackup.EndTime},
BeginWal: targetBackup.BeginWal,
EndWal: targetBackup.EndWal,
BeginLSN: targetBackup.BeginLSN,
EndLSN: targetBackup.EndLSN,
Error: targetBackup.Error,
CommandOutput: "",
CommandError: "",
},
}, env, nil
}

View File

@ -13,9 +13,7 @@ import (
type CNPGI struct {
PluginPath string
SpoolDirectory string
ArchiveConfiguration client.ObjectKey
ClusterObjectKey client.ObjectKey
BackupToRestoreObjectKey client.ObjectKey
Client client.Client
PGDataPath string
}
@ -29,11 +27,9 @@ func (c *CNPGI) Start(ctx context.Context) error {
restore.RegisterRestoreJobHooksServer(server, &JobHookImpl{
Client: c.Client,
ClusterObjectKey: c.ClusterObjectKey,
BackupToRestore: c.BackupToRestoreObjectKey,
SpoolDirectory: c.SpoolDirectory,
PgDataPath: c.PGDataPath,
PgWalFolderToSymlink: PgWalVolumePgWalPath,
ArchiveConfiguration: c.ArchiveConfiguration,
})
return nil
}