diff --git a/api/v1/cluster_funcs.go b/api/v1/cluster_funcs.go index 211ec3bc7f..3fc919188c 100644 --- a/api/v1/cluster_funcs.go +++ b/api/v1/cluster_funcs.go @@ -25,14 +25,15 @@ import ( "strings" "time" + "github.com/cloudnative-pg/machinery/pkg/image/reference" "github.com/cloudnative-pg/machinery/pkg/log" + "github.com/cloudnative-pg/machinery/pkg/postgres/version" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "github.com/cloudnative-pg/cloudnative-pg/internal/configuration" - "github.com/cloudnative-pg/cloudnative-pg/pkg/postgres" "github.com/cloudnative-pg/cloudnative-pg/pkg/stringset" "github.com/cloudnative-pg/cloudnative-pg/pkg/system" "github.com/cloudnative-pg/cloudnative-pg/pkg/utils" @@ -399,26 +400,16 @@ func (cluster *Cluster) GetImageName() string { // image name or from the ImageCatalogRef. // Example: // -// ghcr.io/cloudnative-pg/postgresql:14.0 corresponds to version 140000 -// ghcr.io/cloudnative-pg/postgresql:13.2 corresponds to version 130002 -// ghcr.io/cloudnative-pg/postgresql:9.6.3 corresponds to version 90603 -func (cluster *Cluster) GetPostgresqlVersion() (int, error) { +// ghcr.io/cloudnative-pg/postgresql:14.0 corresponds to version (14,0) +// ghcr.io/cloudnative-pg/postgresql:13.2 corresponds to version (13,2) +func (cluster *Cluster) GetPostgresqlVersion() (version.Data, error) { if cluster.Spec.ImageCatalogRef != nil { - return postgres.GetPostgresVersionFromTag(strconv.Itoa(cluster.Spec.ImageCatalogRef.Major)) + return version.FromTag(strconv.Itoa(cluster.Spec.ImageCatalogRef.Major)) } image := cluster.GetImageName() - tag := utils.GetImageTag(image) - return postgres.GetPostgresVersionFromTag(tag) -} - -// GetPostgresqlMajorVersion gets the PostgreSQL image major version used in the Cluster -func (cluster *Cluster) GetPostgresqlMajorVersion() (int, error) { - version, err := cluster.GetPostgresqlVersion() - if err != nil { - return 0, err - } - return postgres.GetPostgresMajorVersion(version), nil + tag := reference.New(image).Tag + return version.FromTag(tag) } // GetImagePullSecret get the name of the pull secret to use diff --git a/api/v1/cluster_funcs_test.go b/api/v1/cluster_funcs_test.go index 03a92ae90a..7d459faca0 100644 --- a/api/v1/cluster_funcs_test.go +++ b/api/v1/cluster_funcs_test.go @@ -21,6 +21,7 @@ import ( "time" barmanCatalog "github.com/cloudnative-pg/barman-cloud/pkg/catalog" + "github.com/cloudnative-pg/machinery/pkg/postgres/version" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -770,19 +771,15 @@ var _ = Describe("A config map resource version", func() { var _ = Describe("PostgreSQL version detection", func() { tests := []struct { imageName string - postgresVersion int + postgresVersion version.Data }{ { "ghcr.io/cloudnative-pg/postgresql:14.0", - 140000, + version.New(14, 0), }, { "ghcr.io/cloudnative-pg/postgresql:13.2", - 130002, - }, - { - "ghcr.io/cloudnative-pg/postgresql:9.6.3", - 90603, + version.New(13, 2), }, } @@ -802,7 +799,7 @@ var _ = Describe("PostgreSQL version detection", func() { }, Major: 16, } - Expect(cluster.GetPostgresqlVersion()).To(Equal(160000)) + Expect(cluster.GetPostgresqlVersion()).To(Equal(version.New(16, 0))) }) }) diff --git a/api/v1/cluster_webhook.go b/api/v1/cluster_webhook.go index 8b82c6b9e5..16b8c73c52 100644 --- a/api/v1/cluster_webhook.go +++ b/api/v1/cluster_webhook.go @@ -24,7 +24,9 @@ import ( "strings" barmanWebhooks "github.com/cloudnative-pg/barman-cloud/pkg/api/webhooks" + "github.com/cloudnative-pg/machinery/pkg/image/reference" "github.com/cloudnative-pg/machinery/pkg/log" + "github.com/cloudnative-pg/machinery/pkg/postgres/version" "github.com/cloudnative-pg/machinery/pkg/types" storagesnapshotv1 "github.com/kubernetes-csi/external-snapshotter/client/v8/apis/volumesnapshot/v1" v1 "k8s.io/api/core/v1" @@ -126,7 +128,7 @@ func (r *Cluster) setDefaults(preserveUserSettings bool) { // validateImageName function info := postgres.ConfigurationInfo{ Settings: postgres.CnpgConfigurationSettings, - MajorVersion: psqlVersion, + Version: psqlVersion, UserSettings: r.Spec.PostgresConfiguration.Parameters, IsReplicaCluster: r.IsReplica(), PreserveFixedSettingsFromUser: preserveUserSettings, @@ -965,7 +967,7 @@ func (r *Cluster) validateImageName() field.ErrorList { } // We have to check if the image has a valid tag - tag := utils.GetImageTag(r.Spec.ImageName) + tag := reference.New(r.Spec.ImageName).Tag switch tag { case "latest": result = append( @@ -982,7 +984,7 @@ func (r *Cluster) validateImageName() field.ErrorList { r.Spec.ImageName, "Can't use just the image sha as we can't detect upgrades")) default: - _, err := postgres.GetPostgresVersionFromTag(tag) + _, err := version.FromTag(tag) if err != nil { result = append( result, @@ -1094,7 +1096,7 @@ func (r *Cluster) validateConfiguration() field.ErrorList { // validateImageName function return result } - if pgVersion < 110000 { + if pgVersion.Major() < 11 { result = append(result, field.Invalid( field.NewPath("spec", "imageName"), @@ -1103,7 +1105,7 @@ func (r *Cluster) validateConfiguration() field.ErrorList { } info := postgres.ConfigurationInfo{ Settings: postgres.CnpgConfigurationSettings, - MajorVersion: pgVersion, + Version: pgVersion, UserSettings: r.Spec.PostgresConfiguration.Parameters, IsReplicaCluster: r.IsReplica(), IsWalArchivingDisabled: utils.IsWalArchivingDisabled(&r.ObjectMeta), @@ -1369,7 +1371,7 @@ func validateSyncReplicaElectionConstraint(constraints SyncReplicaElectionConstr // to a new one. func (r *Cluster) validateImageChange(old *Cluster) field.ErrorList { var result field.ErrorList - var newMajor, oldMajor int + var newVersion, oldVersion version.Data var err error var newImagePath *field.Path if r.Spec.ImageCatalogRef != nil { @@ -1379,7 +1381,7 @@ func (r *Cluster) validateImageChange(old *Cluster) field.ErrorList { } r.Status.Image = "" - newMajor, err = r.GetPostgresqlVersion() + newVersion, err = r.GetPostgresqlVersion() if err != nil { // The validation error will be already raised by the // validateImageName function @@ -1387,23 +1389,23 @@ func (r *Cluster) validateImageChange(old *Cluster) field.ErrorList { } old.Status.Image = "" - oldMajor, err = old.GetPostgresqlVersion() + oldVersion, err = old.GetPostgresqlVersion() if err != nil { // The validation error will be already raised by the // validateImageName function return result } - status := postgres.IsUpgradePossible(oldMajor, newMajor) + status := version.IsUpgradePossible(oldVersion, newVersion) if !status { result = append( result, field.Invalid( newImagePath, - newMajor, + newVersion, fmt.Sprintf("can't upgrade between majors %v and %v", - oldMajor, newMajor))) + oldVersion, newVersion))) } return result @@ -2194,7 +2196,7 @@ func (r *Cluster) validateReplicationSlots() field.ErrorList { return nil } - if psqlVersion < 110000 { + if psqlVersion.Major() < 11 { if replicationSlots.HighAvailability.GetEnabled() { return field.ErrorList{ field.Invalid( diff --git a/api/v1/cluster_webhook_test.go b/api/v1/cluster_webhook_test.go index cb9b456696..85a28e9044 100644 --- a/api/v1/cluster_webhook_test.go +++ b/api/v1/cluster_webhook_test.go @@ -23,6 +23,8 @@ import ( "strings" "time" + "github.com/cloudnative-pg/machinery/pkg/image/reference" + pgversion "github.com/cloudnative-pg/machinery/pkg/postgres/version" storagesnapshotv1 "github.com/kubernetes-csi/external-snapshotter/client/v8/apis/volumesnapshot/v1" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" @@ -1440,6 +1442,9 @@ var _ = Describe("validate image name change", func() { Expect(clusterNew.validateImageChange(&clusterOld)).To(HaveLen(1)) }) It("doesn't complain going from default imageName to same major imageCatalogRef", func() { + defaultImageRef := reference.New(versions.DefaultImageName) + version, err := pgversion.FromTag(defaultImageRef.Tag) + Expect(err).ToNot(HaveOccurred()) clusterOld := Cluster{ Spec: ClusterSpec{}, } @@ -1450,7 +1455,7 @@ var _ = Describe("validate image name change", func() { Name: "test", Kind: "ImageCatalog", }, - Major: 16, + Major: int(version.Major()), }, }, } @@ -1497,7 +1502,7 @@ var _ = Describe("validate image name change", func() { } Expect(clusterNew.validateImageChange(&clusterOld)).To(HaveLen(1)) }) - It("complains going from default imageName to different major imageCatalogRef", func() { + It("complains going from imageCatalogRef to different major default imageName", func() { clusterOld := Cluster{ Spec: ClusterSpec{ ImageCatalogRef: &ImageCatalogRef{ @@ -1514,7 +1519,11 @@ var _ = Describe("validate image name change", func() { } Expect(clusterNew.validateImageChange(&clusterOld)).To(HaveLen(1)) }) - It("doesn't complain going from default imageName to same major imageCatalogRef", func() { + It("doesn't complain going from imageCatalogRef to same major default imageName", func() { + imageNameRef := reference.New(versions.DefaultImageName) + version, err := pgversion.FromTag(imageNameRef.Tag) + Expect(err).ToNot(HaveOccurred()) + clusterOld := Cluster{ Spec: ClusterSpec{ ImageCatalogRef: &ImageCatalogRef{ @@ -1522,7 +1531,7 @@ var _ = Describe("validate image name change", func() { Name: "test", Kind: "ImageCatalog", }, - Major: 16, + Major: int(version.Major()), }, }, } diff --git a/docs/src/supported_releases.md b/docs/src/supported_releases.md index 5aee05fb84..c3d367e268 100644 --- a/docs/src/supported_releases.md +++ b/docs/src/supported_releases.md @@ -81,7 +81,7 @@ Git tags for versions are prefixed with `v`. | Version | Currently supported | Release date | End of life | Supported Kubernetes versions | Tested, but not supported | Supported Postgres versions | |-----------------|----------------------|-------------------|---------------------|-------------------------------|---------------------------|-----------------------------| -| 1.24.x | Yes | August 22, 2024 | ~ February, 2025 | 1.28, 1.29, 1.30, 1.31 | 1.27 | 12 - 16 | +| 1.24.x | Yes | August 22, 2024 | ~ February, 2025 | 1.28, 1.29, 1.30, 1.31 | 1.27 | 12 - 17 | | 1.23.x | Yes | April 24, 2024 | ~ November, 2024 | 1.27, 1.28, 1.29 | 1.30, 1.31 | 12 - 16 | | main | No, development only | | | | | 12 - 16 | diff --git a/go.mod b/go.mod index 8e5341a1db..8a88225e10 100644 --- a/go.mod +++ b/go.mod @@ -6,13 +6,13 @@ toolchain go1.23.1 require ( github.com/DATA-DOG/go-sqlmock v1.5.2 - github.com/Masterminds/semver/v3 v3.2.1 + github.com/Masterminds/semver/v3 v3.3.0 github.com/avast/retry-go/v4 v4.6.0 github.com/blang/semver v3.5.1+incompatible github.com/cheynewallace/tabby v1.1.1 github.com/cloudnative-pg/barman-cloud v0.0.0-20240924124724-92831d48562a github.com/cloudnative-pg/cnpg-i v0.0.0-20240820123829-5844b833f4eb - github.com/cloudnative-pg/machinery v0.0.0-20240919131343-9dd62b9257c7 + github.com/cloudnative-pg/machinery v0.0.0-20241001075747-34c8797af80f github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc github.com/evanphx/json-patch/v5 v5.9.0 github.com/go-logr/logr v1.4.2 diff --git a/go.sum b/go.sum index c0d62b12f0..c6ecb0ceac 100644 --- a/go.sum +++ b/go.sum @@ -2,8 +2,8 @@ github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25 github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU= github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU= -github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0rYXWg0= -github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= +github.com/Masterminds/semver/v3 v3.3.0 h1:B8LGeaivUe71a5qox1ICM/JLl0NqZSW5CHyL+hmvYS0= +github.com/Masterminds/semver/v3 v3.3.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/avast/retry-go/v4 v4.6.0 h1:K9xNA+KeB8HHc2aWFuLb25Offp+0iVRXEvFx8IinRJA= @@ -22,8 +22,8 @@ github.com/cloudnative-pg/barman-cloud v0.0.0-20240924124724-92831d48562a h1:0v1 github.com/cloudnative-pg/barman-cloud v0.0.0-20240924124724-92831d48562a/go.mod h1:Jm0tOp5oB7utpt8wz6RfSv31h1mThOtffjfyxVupriE= github.com/cloudnative-pg/cnpg-i v0.0.0-20240820123829-5844b833f4eb h1:kZQk+KUCTHQMEgcH8j2/ypcG2HY58zKocmVUvX6c1IA= github.com/cloudnative-pg/cnpg-i v0.0.0-20240820123829-5844b833f4eb/go.mod h1:UILpBDaWvXcYC5kY5DMaVEEQY5483CBApMuHIn0GJdg= -github.com/cloudnative-pg/machinery v0.0.0-20240919131343-9dd62b9257c7 h1:glRSFwMeX1tb1wlN6ZxihPH3nMXL9ZlwU1/xvNFB0iE= -github.com/cloudnative-pg/machinery v0.0.0-20240919131343-9dd62b9257c7/go.mod h1:bWp1Es5zlxElg4Z/c5f0RKOkDcyNvDHdYIvNcPQU4WM= +github.com/cloudnative-pg/machinery v0.0.0-20241001075747-34c8797af80f h1:RgPmQJkuSu3eTdfd4T2K95RYQi57LHB2+Jfsu/faKOM= +github.com/cloudnative-pg/machinery v0.0.0-20241001075747-34c8797af80f/go.mod h1:bWp1Es5zlxElg4Z/c5f0RKOkDcyNvDHdYIvNcPQU4WM= github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= diff --git a/internal/cmd/manager/instance/pgbasebackup/cmd.go b/internal/cmd/manager/instance/pgbasebackup/cmd.go index 433770cec6..d8ccead7cf 100644 --- a/internal/cmd/manager/instance/pgbasebackup/cmd.go +++ b/internal/cmd/manager/instance/pgbasebackup/cmd.go @@ -134,7 +134,7 @@ func (env *CloneInfo) bootstrapUsingPgbasebackup(ctx context.Context) error { "Error while parsing PostgreSQL server version to define connection options, defaulting to PostgreSQL 11", "imageName", cluster.GetImageName(), "err", err) - } else if pgVersion >= 120000 { + } else if pgVersion.Major() >= 12 { // We explicitly disable wal_sender_timeout for join-related pg_basebackup executions. // A short timeout could not be enough in case the instance is slow to send data, // like when the I/O is overloaded. diff --git a/internal/management/controller/instance_startup.go b/internal/management/controller/instance_startup.go index 1bc852613d..ea796fcb88 100644 --- a/internal/management/controller/instance_startup.go +++ b/internal/management/controller/instance_startup.go @@ -236,7 +236,7 @@ func (r *InstanceReconciler) verifyPgDataCoherenceForPrimary(ctx context.Context return err } - pgMajorVersion, err := cluster.GetPostgresqlMajorVersion() + pgVersion, err := cluster.GetPostgresqlVersion() if err != nil { return err } @@ -262,7 +262,7 @@ func (r *InstanceReconciler) verifyPgDataCoherenceForPrimary(ctx context.Context // The only way to check if we really need to start it up before // invoking pg_rewind is to try using pg_rewind and, on failures, // retrying after having started up the instance. - err = r.instance.Rewind(ctx, pgMajorVersion) + err = r.instance.Rewind(ctx, pgVersion) if err != nil { contextLogger.Info( "pg_rewind failed, starting the server to complete the crash recovery", @@ -277,7 +277,7 @@ func (r *InstanceReconciler) verifyPgDataCoherenceForPrimary(ctx context.Context } // Then let's go back to the point of the new primary - err = r.instance.Rewind(ctx, pgMajorVersion) + err = r.instance.Rewind(ctx, pgVersion) if err != nil { return err } diff --git a/pkg/management/postgres/configuration.go b/pkg/management/postgres/configuration.go index 209777fc5d..08bb4e1aad 100644 --- a/pkg/management/postgres/configuration.go +++ b/pkg/management/postgres/configuration.go @@ -100,7 +100,7 @@ func (instance *Instance) GeneratePostgresqlHBA(cluster *apiv1.Cluster, ldapBind // See: // https://www.postgresql.org/docs/14/release-14.html defaultAuthenticationMethod := "scram-sha-256" - if version < 140000 { + if version.Major() < 14 { defaultAuthenticationMethod = "md5" } @@ -429,7 +429,7 @@ func createPostgresqlConfiguration(cluster *apiv1.Cluster, preserveUserSettings info := postgres.ConfigurationInfo{ Settings: postgres.CnpgConfigurationSettings, - MajorVersion: fromVersion, + Version: fromVersion, UserSettings: cluster.Spec.PostgresConfiguration.Parameters, IncludingSharedPreloadLibraries: true, AdditionalSharedPreloadLibraries: cluster.Spec.PostgresConfiguration.AdditionalLibraries, diff --git a/pkg/management/postgres/instance.go b/pkg/management/postgres/instance.go index 035d2ad736..0496445681 100644 --- a/pkg/management/postgres/instance.go +++ b/pkg/management/postgres/instance.go @@ -36,6 +36,7 @@ import ( "github.com/cloudnative-pg/machinery/pkg/fileutils" "github.com/cloudnative-pg/machinery/pkg/fileutils/compatibility" "github.com/cloudnative-pg/machinery/pkg/log" + "github.com/cloudnative-pg/machinery/pkg/postgres/version" "go.uber.org/atomic" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/client-go/util/retry" @@ -982,7 +983,7 @@ func (instance *Instance) removePgControlFileBackup() error { // Rewind uses pg_rewind to align this data directory with the contents of the primary node. // If postgres major version is >= 13, add "--restore-target-wal" option -func (instance *Instance) Rewind(ctx context.Context, postgresMajorVersion int) error { +func (instance *Instance) Rewind(ctx context.Context, postgresVersion version.Data) error { contextLogger := log.FromContext(ctx) // Signal the liveness probe that we are running pg_rewind before starting postgres @@ -1002,7 +1003,7 @@ func (instance *Instance) Rewind(ctx context.Context, postgresMajorVersion int) // As PostgreSQL 13 introduces support of restore from the WAL archive in pg_rewind, // let’s automatically use it, if possible - if postgresMajorVersion >= 130000 { + if postgresVersion.Major() >= 13 { options = append(options, "--restore-target-wal") } diff --git a/pkg/management/postgres/join.go b/pkg/management/postgres/join.go index 419d4ccfd1..fb3cfc7914 100644 --- a/pkg/management/postgres/join.go +++ b/pkg/management/postgres/join.go @@ -79,7 +79,7 @@ func (info InitInfo) Join(cluster *apiv1.Cluster) error { "Error while parsing PostgreSQL server version to define connection options, defaulting to PostgreSQL 11", "imageName", cluster.GetImageName(), "err", err) - } else if pgVersion >= 120000 { + } else if pgVersion.Major() >= 12 { // We explicitly disable wal_sender_timeout for join-related pg_basebackup executions. // A short timeout could not be enough in case the instance is slow to send data, // like when the I/O is overloaded. diff --git a/pkg/postgres/configuration.go b/pkg/postgres/configuration.go index 4095888839..9bd377c26e 100644 --- a/pkg/postgres/configuration.go +++ b/pkg/postgres/configuration.go @@ -25,6 +25,8 @@ import ( "strings" "text/template" "time" + + "github.com/cloudnative-pg/machinery/pkg/postgres/version" ) // WalLevelValue a value that is assigned to the 'wal_level' configuration field @@ -241,15 +243,15 @@ var hbaTemplate = template.Must(template.New("pg_hba.conf").Parse(hbaTemplateStr var identTemplate = template.Must(template.New("pg_ident.conf").Parse(identTemplateString)) // MajorVersionRangeUnlimited is used to represent an unbound limit in a MajorVersionRange -const MajorVersionRangeUnlimited = 0 +var MajorVersionRangeUnlimited = version.Data{} -// MajorVersionRange is used to represent a range of PostgreSQL versions -type MajorVersionRange = struct { +// VersionRange is used to represent a range of PostgreSQL versions +type VersionRange struct { // The minimum limit of PostgreSQL major version, extreme included - Min int + Min version.Data // The maximum limit of PostgreSQL version, extreme excluded, or MajorVersionRangeUnlimited - Max int + Max version.Data } // SettingsCollection is a collection of PostgreSQL settings @@ -265,7 +267,7 @@ type ConfigurationSettings struct { // The following settings are like GlobalPostgresSettings // but are relative only to certain PostgreSQL versions - DefaultSettings map[MajorVersionRange]SettingsCollection + DefaultSettings map[VersionRange]SettingsCollection // The following settings are applied to the final PostgreSQL configuration, // even if the user specified something different @@ -284,8 +286,8 @@ type ConfigurationInfo struct { // The database settings to be used Settings ConfigurationSettings - // The major version - MajorVersion int + // The PostgreSQL version + Version version.Data // The list of user-level settings UserSettings map[string]string @@ -487,19 +489,19 @@ var ( // the parameter cannot be changed without a restart. SharedPreloadLibraries: "", }, - DefaultSettings: map[MajorVersionRange]SettingsCollection{ - {MajorVersionRangeUnlimited, 120000}: { + DefaultSettings: map[VersionRange]SettingsCollection{ + {MajorVersionRangeUnlimited, version.New(12, 0)}: { "wal_keep_segments": "32", }, - {120000, 130000}: { + {version.New(12, 0), version.New(13, 0)}: { "wal_keep_segments": "32", "shared_memory_type": "mmap", }, - {130000, MajorVersionRangeUnlimited}: { + {version.New(13, 0), MajorVersionRangeUnlimited}: { "wal_keep_size": "512MB", "shared_memory_type": "mmap", }, - {120000, MajorVersionRangeUnlimited}: { + {version.New(12, 0), MajorVersionRangeUnlimited}: { "ssl_max_protocol_version": "TLSv1.3", "ssl_min_protocol_version": "TLSv1.3", }, @@ -645,9 +647,7 @@ func CreatePostgresqlConfiguration(info ConfigurationInfo) *PgConfiguration { configuration.OverwriteConfig(key, value) } - // IMPORTANT: yes, this field is called MajorVersion but actually - // it's just the PostgreSQL version number - if info.MajorVersion >= 170000 { + if info.Version.Major() >= 17 { configuration.OverwriteConfig("allow_alter_system", info.getAlterSystemEnabledValue()) } } @@ -716,8 +716,11 @@ func setDefaultConfigurations(info ConfigurationInfo, configuration *PgConfigura // apply settings relative to a certain PostgreSQL version for constraints, settings := range info.Settings.DefaultSettings { - if constraints.Min == MajorVersionRangeUnlimited || (constraints.Min <= info.MajorVersion) { - if constraints.Max == MajorVersionRangeUnlimited || (info.MajorVersion < constraints.Max) { + if constraints.Min == MajorVersionRangeUnlimited || + constraints.Min == info.Version || + constraints.Min.Less(info.Version) { + if constraints.Max == MajorVersionRangeUnlimited || + info.Version.Less(constraints.Max) { for key, value := range settings { configuration.OverwriteConfig(key, value) } diff --git a/pkg/postgres/configuration_test.go b/pkg/postgres/configuration_test.go index 986d3ccf2b..adc3891582 100644 --- a/pkg/postgres/configuration_test.go +++ b/pkg/postgres/configuration_test.go @@ -20,6 +20,8 @@ import ( "strings" "time" + "github.com/cloudnative-pg/machinery/pkg/postgres/version" + . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" ) @@ -32,7 +34,7 @@ var _ = Describe("PostgreSQL configuration creation", func() { It("apply the default settings", func() { info := ConfigurationInfo{ Settings: CnpgConfigurationSettings, - MajorVersion: 100000, + Version: version.New(10, 0), UserSettings: settings, IncludingMandatory: true, } @@ -43,8 +45,8 @@ var _ = Describe("PostgreSQL configuration creation", func() { It("enforce the mandatory values", func() { info := ConfigurationInfo{ - Settings: CnpgConfigurationSettings, - MajorVersion: 100000, + Settings: CnpgConfigurationSettings, + Version: version.New(10, 0), UserSettings: map[string]string{ "hot_standby": "off", }, @@ -57,7 +59,7 @@ var _ = Describe("PostgreSQL configuration creation", func() { It("generate a config file", func() { info := ConfigurationInfo{ Settings: CnpgConfigurationSettings, - MajorVersion: 100000, + Version: version.New(10, 0), UserSettings: settings, IncludingMandatory: true, } @@ -82,7 +84,7 @@ var _ = Describe("PostgreSQL configuration creation", func() { It("will use appropriate settings", func() { info := ConfigurationInfo{ Settings: CnpgConfigurationSettings, - MajorVersion: 100000, + Version: version.New(10, 0), UserSettings: settings, IncludingMandatory: true, } @@ -95,7 +97,7 @@ var _ = Describe("PostgreSQL configuration creation", func() { It("will use appropriate settings", func() { info := ConfigurationInfo{ Settings: CnpgConfigurationSettings, - MajorVersion: 130000, + Version: version.New(13, 0), UserSettings: settings, IncludingMandatory: true, } @@ -110,7 +112,7 @@ var _ = Describe("PostgreSQL configuration creation", func() { It("will set archive_mode to always", func() { info := ConfigurationInfo{ Settings: CnpgConfigurationSettings, - MajorVersion: 130000, + Version: version.New(13, 0), UserSettings: settings, IncludingMandatory: true, IsReplicaCluster: true, @@ -124,7 +126,7 @@ var _ = Describe("PostgreSQL configuration creation", func() { It("will set archive_mode to on", func() { info := ConfigurationInfo{ Settings: CnpgConfigurationSettings, - MajorVersion: 130000, + Version: version.New(13, 0), UserSettings: settings, IncludingMandatory: true, IsReplicaCluster: false, @@ -137,7 +139,7 @@ var _ = Describe("PostgreSQL configuration creation", func() { It("adds shared_preload_library correctly", func() { info := ConfigurationInfo{ Settings: CnpgConfigurationSettings, - MajorVersion: 130000, + Version: version.New(13, 0), IncludingMandatory: true, IncludingSharedPreloadLibraries: true, AdditionalSharedPreloadLibraries: []string{"some_library", "another_library", ""}, @@ -151,8 +153,8 @@ var _ = Describe("PostgreSQL configuration creation", func() { It("checks if PreserveFixedSettingsFromUser works properly", func() { info := ConfigurationInfo{ - Settings: CnpgConfigurationSettings, - MajorVersion: 100000, + Settings: CnpgConfigurationSettings, + Version: version.New(10, 0), UserSettings: map[string]string{ "ssl": "off", "recovery_target_name": "test", @@ -195,7 +197,7 @@ var _ = Describe("PostgreSQL configuration creation", func() { It("can properly set allow_alter_system to on", func() { info := ConfigurationInfo{ IsAlterSystemEnabled: true, - MajorVersion: 170000, + Version: version.New(17, 0), IncludingMandatory: true, } config := CreatePostgresqlConfiguration(info) @@ -205,7 +207,7 @@ var _ = Describe("PostgreSQL configuration creation", func() { It("can properly set allow_alter_system to off", func() { info := ConfigurationInfo{ IsAlterSystemEnabled: false, - MajorVersion: 180000, + Version: version.New(18, 0), IncludingMandatory: true, } config := CreatePostgresqlConfiguration(info) @@ -217,7 +219,7 @@ var _ = Describe("PostgreSQL configuration creation", func() { It("should not set allow_alter_system", func() { info := ConfigurationInfo{ IsAlterSystemEnabled: false, - MajorVersion: 140000, + Version: version.New(14, 0), IncludingMandatory: true, } config := CreatePostgresqlConfiguration(info) @@ -228,7 +230,7 @@ var _ = Describe("PostgreSQL configuration creation", func() { It("should not set allow_alter_system", func() { info := ConfigurationInfo{ IsAlterSystemEnabled: true, - MajorVersion: 140000, + Version: version.New(14, 0), IncludingMandatory: true, } config := CreatePostgresqlConfiguration(info) @@ -307,7 +309,7 @@ var _ = Describe("pgaudit", func() { It("adds pgaudit to shared_preload_library", func() { info := ConfigurationInfo{ Settings: CnpgConfigurationSettings, - MajorVersion: 130000, + Version: version.New(13, 0), UserSettings: map[string]string{"pgaudit.something": "something"}, IncludingSharedPreloadLibraries: true, IncludingMandatory: true, @@ -324,7 +326,7 @@ var _ = Describe("pgaudit", func() { It("adds pg_stat_statements to shared_preload_library", func() { info := ConfigurationInfo{ Settings: CnpgConfigurationSettings, - MajorVersion: 130000, + Version: version.New(13, 0), UserSettings: map[string]string{"pg_stat_statements.something": "something"}, IncludingMandatory: true, IncludingSharedPreloadLibraries: true, @@ -340,8 +342,8 @@ var _ = Describe("pgaudit", func() { It("adds pg_stat_statements and pgaudit to shared_preload_library", func() { info := ConfigurationInfo{ - Settings: CnpgConfigurationSettings, - MajorVersion: 130000, + Settings: CnpgConfigurationSettings, + Version: version.New(13, 0), UserSettings: map[string]string{ "pg_stat_statements.something": "something", "pgaudit.somethingelse": "somethingelse", @@ -361,7 +363,7 @@ var _ = Describe("pg_failover_slots", func() { It("adds pg_failover_slots to shared_preload_library", func() { info := ConfigurationInfo{ Settings: CnpgConfigurationSettings, - MajorVersion: 130000, + Version: version.New(13, 0), UserSettings: map[string]string{"pg_failover_slots.something": "something"}, IncludingMandatory: true, IncludingSharedPreloadLibraries: true, @@ -378,7 +380,7 @@ var _ = Describe("recovery_min_apply_delay", func() { It("is not added when zero", func() { info := ConfigurationInfo{ Settings: CnpgConfigurationSettings, - MajorVersion: 130000, + Version: version.New(13, 0), UserSettings: map[string]string{"pg_failover_slots.something": "something"}, IncludingMandatory: true, IncludingSharedPreloadLibraries: true, @@ -391,7 +393,7 @@ var _ = Describe("recovery_min_apply_delay", func() { It("is added to the configuration when specified", func() { info := ConfigurationInfo{ Settings: CnpgConfigurationSettings, - MajorVersion: 130000, + Version: version.New(13, 0), UserSettings: map[string]string{"pg_failover_slots.something": "something"}, IncludingMandatory: true, IncludingSharedPreloadLibraries: true, diff --git a/pkg/postgres/version.go b/pkg/postgres/version.go deleted file mode 100644 index 2384b1003a..0000000000 --- a/pkg/postgres/version.go +++ /dev/null @@ -1,92 +0,0 @@ -/* -Copyright The CloudNativePG Contributors - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package postgres - -import ( - "fmt" - "regexp" - "strconv" - "strings" -) - -const firstMajorWithoutMinor = 10 - -var semanticVersionRegex = regexp.MustCompile(`^(\d\.?)+`) - -// GetPostgresVersionFromTag parse a PostgreSQL version string returning -// a major version ID. Example: -// -// GetPostgresVersionFromTag("9.5.3") == 90503 -// GetPostgresVersionFromTag("10.2") == 100002 -// GetPostgresVersionFromTag("15beta1") == 150000 -func GetPostgresVersionFromTag(version string) (int, error) { - if !semanticVersionRegex.MatchString(version) { - return 0, - fmt.Errorf("version not starting with a semantic version regex (%v): %s", semanticVersionRegex, version) - } - - if versionOnly := semanticVersionRegex.FindString(version); versionOnly != "" { - version = versionOnly - } - - splitVersion := strings.Split(version, ".") - - idx := 0 - majorVersion, err := strconv.Atoi(splitVersion[idx]) - if err != nil { - return 0, fmt.Errorf("wrong PostgreSQL major in version %v", version) - } - parsedVersion := majorVersion * 10000 - idx++ - - if majorVersion < firstMajorWithoutMinor { - if len(splitVersion) <= idx { - return 0, fmt.Errorf("missing PostgreSQL minor in version %v", version) - } - minorVersion, err := strconv.Atoi(splitVersion[idx]) - if err != nil || minorVersion >= 100 { - return 0, fmt.Errorf("wrong PostgreSQL minor in version %v", version) - } - parsedVersion += minorVersion * 100 - idx++ - } - - if len(splitVersion) > idx { - patchLevel, err := strconv.Atoi(splitVersion[idx]) - if err != nil || patchLevel >= 100 { - return 0, fmt.Errorf("wrong PostgreSQL patch level in version %v", version) - } - parsedVersion += patchLevel - } - - return parsedVersion, nil -} - -// GetPostgresMajorVersion gets only the Major version from a PostgreSQL version string. -// Example: -// -// GetPostgresMajorVersion("90503") == 90500 -// GetPostgresMajorVersion("100002") == 100000 -func GetPostgresMajorVersion(parsedVersion int) int { - return parsedVersion - parsedVersion%100 -} - -// IsUpgradePossible detect if it's possible to upgrade from fromVersion to -// toVersion -func IsUpgradePossible(fromVersion, toVersion int) bool { - return GetPostgresMajorVersion(fromVersion) == GetPostgresMajorVersion(toVersion) -} diff --git a/pkg/postgres/version_test.go b/pkg/postgres/version_test.go deleted file mode 100644 index 3ef75e84db..0000000000 --- a/pkg/postgres/version_test.go +++ /dev/null @@ -1,82 +0,0 @@ -/* -Copyright The CloudNativePG Contributors - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package postgres - -import ( - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" -) - -var _ = Describe("PostgreSQL version handling", func() { - Describe("parsing", func() { - It("should parse versions < 10", func() { - Expect(GetPostgresVersionFromTag("9.5.3")).To(Equal(90503)) - Expect(GetPostgresVersionFromTag("9.4")).To(Equal(90400)) - }) - - It("should parse versions >= 10", func() { - Expect(GetPostgresVersionFromTag("10.3")).To(Equal(100003)) - Expect(GetPostgresVersionFromTag("12.3")).To(Equal(120003)) - }) - - It("should ignore extra components", func() { - Expect(GetPostgresVersionFromTag("3.4.3.2.5")).To(Equal(30403)) - Expect(GetPostgresVersionFromTag("10.11.12")).To(Equal(100011)) - Expect(GetPostgresVersionFromTag("9.4_beautiful")).To(Equal(90400)) - Expect(GetPostgresVersionFromTag("11-1")).To(Equal(110000)) - Expect(GetPostgresVersionFromTag("15beta1")).To(Equal(150000)) - }) - - It("should gracefully handle errors", func() { - _, err := GetPostgresVersionFromTag("") - Expect(err).To(HaveOccurred()) - - _, err = GetPostgresVersionFromTag("8") - Expect(err).To(HaveOccurred()) - - _, err = GetPostgresVersionFromTag("9.five") - Expect(err).To(HaveOccurred()) - - _, err = GetPostgresVersionFromTag("10.old") - Expect(err).To(HaveOccurred()) - }) - }) - - Describe("major version extraction", func() { - It("should extract the major version for PostgreSQL >= 10", func() { - Expect(GetPostgresMajorVersion(100003)).To(Equal(100000)) - }) - - It("should extract the major version for PostgreSQL < 10", func() { - Expect(GetPostgresMajorVersion(90504)).To(Equal(90500)) - Expect(GetPostgresMajorVersion(90400)).To(Equal(90400)) - }) - }) - - Describe("detect whenever a version upgrade is possible using the numeric version", func() { - It("succeed when the major version is the same", func() { - Expect(IsUpgradePossible(100000, 100003)).To(BeTrue()) - Expect(IsUpgradePossible(90302, 90303)).To(BeTrue()) - }) - - It("prevent upgrading to a different major version", func() { - Expect(IsUpgradePossible(100003, 110003)).To(BeFalse()) - Expect(IsUpgradePossible(90604, 100000)).To(BeFalse()) - Expect(IsUpgradePossible(90503, 900604)).To(BeFalse()) - }) - }) -}) diff --git a/pkg/utils/imagename.go b/pkg/utils/imagename.go deleted file mode 100644 index 0a9e04c4d2..0000000000 --- a/pkg/utils/imagename.go +++ /dev/null @@ -1,88 +0,0 @@ -/* -Copyright The CloudNativePG Contributors - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package utils - -import ( - "fmt" - "regexp" - "strings" -) - -var ( - digestRegex = regexp.MustCompile(`@sha256:(?P[a-fA-F0-9]+)$`) - tagRegex = regexp.MustCompile(`:(?P[^/]+)$`) - hostRegex = regexp.MustCompile(`^[^./:]+((\.[^./:]+)+(:[0-9]+)?|:[0-9]+)/`) -) - -// Reference . -type Reference struct { - Name string - Tag string - Digest string -} - -// GetNormalizedName returns the normalized name of a reference -func (r *Reference) GetNormalizedName() (name string) { - name = r.Name - if r.Tag != "" { - name = fmt.Sprintf("%s:%s", name, r.Tag) - } - if r.Digest != "" { - name = fmt.Sprintf("%s@sha256:%s", name, r.Digest) - } - return name -} - -// NewReference parses the image name and returns an error if the name is invalid. -func NewReference(name string) *Reference { - reference := &Reference{} - - if !strings.Contains(name, "/") { - name = "docker.io/library/" + name - } else if !hostRegex.MatchString(name) { - name = "docker.io/" + name - } - - if digestRegex.MatchString(name) { - res := digestRegex.FindStringSubmatch(name) - reference.Digest = res[1] // digest capture group index - name = strings.TrimSuffix(name, res[0]) - } - - if tagRegex.MatchString(name) { - res := tagRegex.FindStringSubmatch(name) - reference.Tag = res[1] // tag capture group index - name = strings.TrimSuffix(name, res[0]) - } else if reference.Digest == "" { - reference.Tag = "latest" - } - - // everything else is the name - reference.Name = name - - return reference -} - -// GetImageTag gets the image tag from a full image string. -// Example: -// -// GetImageTag("postgres") == "latest" -// GetImageTag("ghcr.io/cloudnative-pg/postgresql:12.3") == "12.3" -func GetImageTag(imageName string) string { - ref := NewReference(imageName) - return ref.Tag -} diff --git a/pkg/utils/imagename_test.go b/pkg/utils/imagename_test.go deleted file mode 100644 index 15bf1bec38..0000000000 --- a/pkg/utils/imagename_test.go +++ /dev/null @@ -1,49 +0,0 @@ -/* -Copyright The CloudNativePG Contributors - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package utils - -import ( - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" -) - -var _ = Describe("image name management", func() { - It("should normalize image names", func() { - Expect(NewReference("postgres").GetNormalizedName()).To( - Equal("docker.io/library/postgres:latest")) - Expect(NewReference("myimage/postgres").GetNormalizedName()).To( - Equal("docker.io/myimage/postgres:latest")) - Expect(NewReference("localhost:5000/postgres").GetNormalizedName()).To( - Equal("localhost:5000/postgres:latest")) - Expect(NewReference("registry.localhost:5000/postgres:14.4").GetNormalizedName()).To( - Equal("registry.localhost:5000/postgres:14.4")) - Expect(NewReference("ghcr.io/cloudnative-pg/postgresql:34").GetNormalizedName()).To( - Equal("ghcr.io/cloudnative-pg/postgresql:34")) - }) - - It("should extract tag names", func() { - Expect(GetImageTag("postgres")).To(Equal("latest")) - Expect(GetImageTag("postgres:34.3")).To(Equal("34.3")) - Expect(GetImageTag("postgres:13@sha256:cff94de382ca538861622bbe84cfe03f44f307a9846a5c5eda672cf4dc692866")). - To(Equal("13")) - }) - - It("should not extract a tag name", func() { - Expect(GetImageTag("postgres@sha256:cff94dd382ca538861622bbe84cfe03f44f307a9846a5c5eda672cf4dc692866")). - To(BeEmpty()) - }) -}) diff --git a/tests/e2e/cluster_microservice_test.go b/tests/e2e/cluster_microservice_test.go index 571db88a81..7252bf13b3 100644 --- a/tests/e2e/cluster_microservice_test.go +++ b/tests/e2e/cluster_microservice_test.go @@ -22,13 +22,13 @@ import ( "strings" "time" + "github.com/cloudnative-pg/machinery/pkg/image/reference" + "github.com/cloudnative-pg/machinery/pkg/postgres/version" batchv1 "k8s.io/api/batch/v1" "k8s.io/apimachinery/pkg/types" apiv1 "github.com/cloudnative-pg/cloudnative-pg/api/v1" - "github.com/cloudnative-pg/cloudnative-pg/pkg/postgres" "github.com/cloudnative-pg/cloudnative-pg/pkg/specs" - "github.com/cloudnative-pg/cloudnative-pg/pkg/utils" "github.com/cloudnative-pg/cloudnative-pg/pkg/versions" "github.com/cloudnative-pg/cloudnative-pg/tests" testsUtils "github.com/cloudnative-pg/cloudnative-pg/tests/utils" @@ -172,15 +172,15 @@ var _ = Describe("Imports with Microservice Approach", Label(tests.LabelImportin // shouldSkip skip this test if the current POSTGRES_IMG is already the latest major func shouldSkip(postgresImage string) bool { // Get the current tag - currentImageReference := utils.NewReference(postgresImage) - currentImageVersion, err := postgres.GetPostgresVersionFromTag(currentImageReference.Tag) + currentImageReference := reference.New(postgresImage) + currentImageVersion, err := version.FromTag(currentImageReference.Tag) Expect(err).ToNot(HaveOccurred()) // Get the default tag - defaultImageReference := utils.NewReference(versions.DefaultImageName) - defaultImageVersion, err := postgres.GetPostgresVersionFromTag(defaultImageReference.Tag) + defaultImageReference := reference.New(versions.DefaultImageName) + defaultImageVersion, err := version.FromTag(defaultImageReference.Tag) Expect(err).ToNot(HaveOccurred()) - return currentImageVersion >= defaultImageVersion + return currentImageVersion.Major() >= defaultImageVersion.Major() } // assertCreateTableWithDataOnSourceCluster will create on the source Cluster, as postgres superUser: diff --git a/tests/e2e/rolling_update_test.go b/tests/e2e/rolling_update_test.go index 9c61427c56..ec50ba5119 100644 --- a/tests/e2e/rolling_update_test.go +++ b/tests/e2e/rolling_update_test.go @@ -19,6 +19,8 @@ package e2e import ( "os" + "github.com/cloudnative-pg/machinery/pkg/image/reference" + "github.com/cloudnative-pg/machinery/pkg/postgres/version" corev1 "k8s.io/api/core/v1" apierrs "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -27,7 +29,6 @@ import ( apiv1 "github.com/cloudnative-pg/cloudnative-pg/api/v1" "github.com/cloudnative-pg/cloudnative-pg/internal/configuration" - "github.com/cloudnative-pg/cloudnative-pg/pkg/postgres" "github.com/cloudnative-pg/cloudnative-pg/pkg/specs" "github.com/cloudnative-pg/cloudnative-pg/pkg/utils" "github.com/cloudnative-pg/cloudnative-pg/tests" @@ -308,7 +309,7 @@ var _ = Describe("Rolling updates", Label(tests.LabelPostgresConfiguration), fun }) } - newImageCatalog := func(namespace string, name string, major int, image string) *apiv1.ImageCatalog { + newImageCatalog := func(namespace string, name string, major uint64, image string) *apiv1.ImageCatalog { imgCat := &apiv1.ImageCatalog{ ObjectMeta: metav1.ObjectMeta{ Namespace: namespace, @@ -318,7 +319,7 @@ var _ = Describe("Rolling updates", Label(tests.LabelPostgresConfiguration), fun Images: []apiv1.CatalogImage{ { Image: image, - Major: major, + Major: int(major), }, }, }, @@ -328,7 +329,7 @@ var _ = Describe("Rolling updates", Label(tests.LabelPostgresConfiguration), fun } newImageCatalogCluster := func( - namespace string, name string, major int, instances int, storageClass string, + namespace string, name string, major uint64, instances int, storageClass string, ) *apiv1.Cluster { cluster := &apiv1.Cluster{ ObjectMeta: metav1.ObjectMeta{ @@ -343,7 +344,7 @@ var _ = Describe("Rolling updates", Label(tests.LabelPostgresConfiguration), fun Name: name, Kind: "ImageCatalog", }, - Major: major, + Major: int(major), }, PostgresConfiguration: apiv1.PostgresConfiguration{ Parameters: map[string]string{ @@ -376,7 +377,7 @@ var _ = Describe("Rolling updates", Label(tests.LabelPostgresConfiguration), fun return cluster } - newClusterImageCatalog := func(name string, major int, image string) *apiv1.ClusterImageCatalog { + newClusterImageCatalog := func(name string, major uint64, image string) *apiv1.ClusterImageCatalog { imgCat := &apiv1.ClusterImageCatalog{ ObjectMeta: metav1.ObjectMeta{ Name: name, @@ -385,7 +386,7 @@ var _ = Describe("Rolling updates", Label(tests.LabelPostgresConfiguration), fun Images: []apiv1.CatalogImage{ { Image: image, - Major: major, + Major: int(major), }, }, }, @@ -522,7 +523,7 @@ var _ = Describe("Rolling updates", Label(tests.LabelPostgresConfiguration), fun var storageClass string var preRollingImg string var updatedImageName string - var major int + var pgVersion version.Data BeforeEach(func() { storageClass = os.Getenv("E2E_DEFAULT_STORAGE_CLASS") preRollingImg = os.Getenv("E2E_PRE_ROLLING_UPDATE_IMG") @@ -533,11 +534,11 @@ var _ = Describe("Rolling updates", Label(tests.LabelPostgresConfiguration), fun // We automate the extraction of the major version from the image, because we don't want to keep maintaining // the major version in the test - version, err := postgres.GetPostgresVersionFromTag(utils.GetImageTag(preRollingImg)) + var err error + pgVersion, err = version.FromTag(reference.New(preRollingImg).Tag) if err != nil { Expect(err).ToNot(HaveOccurred()) } - major = postgres.GetPostgresMajorVersion(version) / 10000 }) Context("ImageCatalog", func() { @@ -558,8 +559,8 @@ var _ = Describe("Rolling updates", Label(tests.LabelPostgresConfiguration), fun Expect(err).ToNot(HaveOccurred()) // Create a new image catalog and a new cluster - catalog := newImageCatalog(namespace, clusterName, major, preRollingImg) - cluster := newImageCatalogCluster(namespace, clusterName, major, 3, storageClass) + catalog := newImageCatalog(namespace, clusterName, pgVersion.Major(), preRollingImg) + cluster := newImageCatalogCluster(namespace, clusterName, pgVersion.Major(), 3, storageClass) AssertRollingUpdateWithImageCatalog(cluster, catalog, updatedImageName, true) }) @@ -577,8 +578,8 @@ var _ = Describe("Rolling updates", Label(tests.LabelPostgresConfiguration), fun namespace, err := env.CreateUniqueTestNamespace(namespacePrefix) Expect(err).ToNot(HaveOccurred()) - catalog := newImageCatalog(namespace, clusterName, major, preRollingImg) - cluster := newImageCatalogCluster(namespace, clusterName, major, 1, storageClass) + catalog := newImageCatalog(namespace, clusterName, pgVersion.Major(), preRollingImg) + cluster := newImageCatalogCluster(namespace, clusterName, pgVersion.Major(), 1, storageClass) AssertRollingUpdateWithImageCatalog(cluster, catalog, updatedImageName, false) }) }) @@ -589,7 +590,7 @@ var _ = Describe("Rolling updates", Label(tests.LabelPostgresConfiguration), fun ) var catalog *apiv1.ClusterImageCatalog BeforeEach(func() { - catalog = newClusterImageCatalog(clusterName, major, preRollingImg) + catalog = newClusterImageCatalog(clusterName, pgVersion.Major(), preRollingImg) }) AfterEach(func() { err := env.Client.Delete(env.Ctx, catalog) @@ -613,7 +614,7 @@ var _ = Describe("Rolling updates", Label(tests.LabelPostgresConfiguration), fun namespace, err := env.CreateUniqueTestNamespace(namespacePrefix) Expect(err).ToNot(HaveOccurred()) - cluster := newImageCatalogCluster(namespace, clusterName, major, 3, storageClass) + cluster := newImageCatalogCluster(namespace, clusterName, pgVersion.Major(), 3, storageClass) cluster.Spec.ImageCatalogRef.Kind = "ClusterImageCatalog" AssertRollingUpdateWithImageCatalog(cluster, catalog, updatedImageName, true) }) @@ -631,7 +632,7 @@ var _ = Describe("Rolling updates", Label(tests.LabelPostgresConfiguration), fun namespace, err := env.CreateUniqueTestNamespace(namespacePrefix) Expect(err).ToNot(HaveOccurred()) - cluster := newImageCatalogCluster(namespace, clusterName, major, 1, storageClass) + cluster := newImageCatalogCluster(namespace, clusterName, pgVersion.Major(), 1, storageClass) cluster.Spec.ImageCatalogRef.Kind = "ClusterImageCatalog" AssertRollingUpdateWithImageCatalog(cluster, catalog, updatedImageName, false) }) diff --git a/tests/utils/environment.go b/tests/utils/environment.go index ea9cefe4bb..90e019327e 100644 --- a/tests/utils/environment.go +++ b/tests/utils/environment.go @@ -25,7 +25,9 @@ import ( "sync" "time" + "github.com/cloudnative-pg/machinery/pkg/image/reference" "github.com/cloudnative-pg/machinery/pkg/log" + "github.com/cloudnative-pg/machinery/pkg/postgres/version" "github.com/go-logr/logr" storagesnapshotv1 "github.com/kubernetes-csi/external-snapshotter/client/v8/apis/volumesnapshot/v1" monitoringv1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1" @@ -46,7 +48,6 @@ import ( "sigs.k8s.io/controller-runtime/pkg/log/zap" apiv1 "github.com/cloudnative-pg/cloudnative-pg/api/v1" - "github.com/cloudnative-pg/cloudnative-pg/pkg/postgres" "github.com/cloudnative-pg/cloudnative-pg/pkg/specs" "github.com/cloudnative-pg/cloudnative-pg/pkg/utils" "github.com/cloudnative-pg/cloudnative-pg/pkg/versions" @@ -78,7 +79,7 @@ type TestingEnvironment struct { Scheme *runtime.Scheme PreserveNamespaces []string Log logr.Logger - PostgresVersion int + PostgresVersion uint64 createdNamespaces *uniqueStringSlice AzureConfiguration AzureConfiguration SternLogDir string @@ -137,12 +138,12 @@ func NewTestingEnvironment() (*TestingEnvironment, error) { if postgresImageFromUser, exist := os.LookupEnv("POSTGRES_IMG"); exist { postgresImage = postgresImageFromUser } - imageReference := utils.NewReference(postgresImage) - postgresImageVersion, err := postgres.GetPostgresVersionFromTag(imageReference.Tag) + imageReference := reference.New(postgresImage) + postgresImageVersion, err := version.FromTag(imageReference.Tag) if err != nil { return nil, err } - env.PostgresVersion = postgresImageVersion / 10000 + env.PostgresVersion = postgresImageVersion.Major() env.Client, err = client.New(env.RestClientConfig, client.Options{Scheme: env.Scheme}) if err != nil { diff --git a/tests/utils/version.go b/tests/utils/version.go index 1c814faf8c..2416df4b08 100644 --- a/tests/utils/version.go +++ b/tests/utils/version.go @@ -19,32 +19,33 @@ package utils import ( "fmt" - "github.com/cloudnative-pg/cloudnative-pg/pkg/postgres" - "github.com/cloudnative-pg/cloudnative-pg/pkg/utils" + "github.com/cloudnative-pg/machinery/pkg/image/reference" + "github.com/cloudnative-pg/machinery/pkg/postgres/version" + "github.com/cloudnative-pg/cloudnative-pg/pkg/versions" ) // BumpPostgresImageMajorVersion returns a postgresImage incrementing the major version of the argument (if available) func BumpPostgresImageMajorVersion(postgresImage string) (string, error) { - imageReference := utils.NewReference(postgresImage) + imageReference := reference.New(postgresImage) - postgresImageVersion, err := postgres.GetPostgresVersionFromTag(imageReference.Tag) + postgresImageVersion, err := version.FromTag(imageReference.Tag) if err != nil { return "", err } - targetPostgresImageVersionInt := postgresImageVersion + 1_00_00 + targetPostgresImageMajorVersionInt := postgresImageVersion.Major() + 1 - defaultImageVersion, err := postgres.GetPostgresVersionFromTag(utils.GetImageTag(versions.DefaultImageName)) + defaultImageVersion, err := version.FromTag(reference.New(versions.DefaultImageName).Tag) if err != nil { return "", err } - if targetPostgresImageVersionInt >= defaultImageVersion { + if targetPostgresImageMajorVersionInt >= defaultImageVersion.Major() { return postgresImage, nil } - imageReference.Tag = fmt.Sprintf("%d", postgresImageVersion/10000+1) + imageReference.Tag = fmt.Sprintf("%d", postgresImageVersion.Major()+1) return imageReference.GetNormalizedName(), nil }