Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EVEREST-1841 MongoDB Major Version Upgrades #1080

Open
wants to merge 34 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
171a3e7
EVEREST-1841 unlock major version upgrades for MongoDB
recharte Feb 4, 2025
3da7a4b
EVEREST-1841 add downgrade tests for PSMDB and PG
recharte Feb 13, 2025
0c43d33
EVEREST-1841 don't allow skipping a major version
recharte Feb 14, 2025
bfc3a38
EVEREST-1841 block major version upgrades for PXC
recharte Feb 14, 2025
be92273
chore: lint/format
recharte Feb 14, 2025
dad0cfa
Merge branch 'main' into EVEREST-1841-mongodb-major-upgrades
percona-robot Feb 14, 2025
f066fbb
Merge branch 'main' into EVEREST-1841-mongodb-major-upgrades
percona-robot Feb 14, 2025
2185272
EVEREST-1841 don't allow skipping major versions
recharte Feb 14, 2025
503cd19
Merge branch 'main' into EVEREST-1841-mongodb-major-upgrades
percona-robot Feb 14, 2025
4f4e56b
Merge branch 'main' into EVEREST-1841-mongodb-major-upgrades
percona-robot Feb 14, 2025
86c02ad
Merge branch 'main' into EVEREST-1841-mongodb-major-upgrades
percona-robot Feb 14, 2025
9f65760
Merge branch 'main' into EVEREST-1841-mongodb-major-upgrades
percona-robot Feb 14, 2025
44715ff
Merge branch 'main' into EVEREST-1841-mongodb-major-upgrades
percona-robot Feb 17, 2025
4326efc
Merge branch 'main' into EVEREST-1841-mongodb-major-upgrades
percona-robot Feb 18, 2025
620a7dd
Merge branch 'main' into EVEREST-1841-mongodb-major-upgrades
percona-robot Feb 18, 2025
22f3ea8
Merge branch 'main' into EVEREST-1841-mongodb-major-upgrades
percona-robot Feb 19, 2025
7139518
Merge branch 'main' into EVEREST-1841-mongodb-major-upgrades
percona-robot Feb 19, 2025
a80225d
Merge branch 'main' into EVEREST-1841-mongodb-major-upgrades
percona-robot Feb 19, 2025
4bdd81f
Merge branch 'main' into EVEREST-1841-mongodb-major-upgrades
percona-robot Feb 20, 2025
f0c9ddd
Merge branch 'main' into EVEREST-1841-mongodb-major-upgrades
percona-robot Feb 20, 2025
65d5561
Merge branch 'main' into EVEREST-1841-mongodb-major-upgrades
percona-robot Feb 20, 2025
9c9867d
Merge branch 'main' into EVEREST-1841-mongodb-major-upgrades
percona-robot Feb 20, 2025
81a9a20
Merge branch 'main' into EVEREST-1841-mongodb-major-upgrades
percona-robot Feb 20, 2025
b39bab3
Merge branch 'main' into EVEREST-1841-mongodb-major-upgrades
percona-robot Feb 20, 2025
fa4cd70
Merge branch 'main' into EVEREST-1841-mongodb-major-upgrades
percona-robot Feb 20, 2025
b3644f8
Merge branch 'main' into EVEREST-1841-mongodb-major-upgrades
percona-robot Feb 21, 2025
f55802f
Merge branch 'main' into EVEREST-1841-mongodb-major-upgrades
percona-robot Feb 21, 2025
c7a4da4
Merge branch 'main' into EVEREST-1841-mongodb-major-upgrades
percona-robot Feb 21, 2025
92c6e9e
Merge branch 'main' into EVEREST-1841-mongodb-major-upgrades
percona-robot Feb 25, 2025
a701387
Merge branch 'main' into EVEREST-1841-mongodb-major-upgrades
percona-robot Feb 25, 2025
e8dbe79
Merge branch 'main' into EVEREST-1841-mongodb-major-upgrades
percona-robot Feb 26, 2025
f683354
Merge branch 'main' into EVEREST-1841-mongodb-major-upgrades
percona-robot Feb 27, 2025
4314a21
Merge branch 'main' into EVEREST-1841-mongodb-major-upgrades
percona-robot Mar 1, 2025
cd8712c
Merge branch 'main' into EVEREST-1841-mongodb-major-upgrades
percona-robot Mar 3, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 16 additions & 9 deletions internal/server/handlers/validation/database_cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"errors"
"fmt"
"strconv"
"strings"

goversion "github.com/hashicorp/go-version"
Expand Down Expand Up @@ -536,7 +537,7 @@ func (h *validateHandler) validateDatabaseClusterOnUpdate(
newVersion := dbc.Spec.Engine.Version
oldVersion := oldDB.Spec.Engine.Version
if newVersion != "" && newVersion != oldVersion {
if err := validateDBEngineVersionUpgrade(newVersion, oldVersion); err != nil {
if err := validateDBEngineVersionUpgrade(oldDB.Spec.Engine.Type, newVersion, oldVersion); err != nil {
return err
}
}
Expand All @@ -557,7 +558,7 @@ func (h *validateHandler) validateDatabaseClusterOnUpdate(
}

// validateDBEngineVersionUpgrade validates if upgrade of DBEngine from `oldVersion` to `newVersion` is allowed.
func validateDBEngineVersionUpgrade(newVersion, oldVersion string) error {
func validateDBEngineVersionUpgrade(engineType everestv1alpha1.EngineType, newVersion, oldVersion string) error {
// Ensure a "v" prefix so that it is a valid semver.
if !strings.HasPrefix(newVersion, "v") {
newVersion = "v" + newVersion
Expand All @@ -575,15 +576,21 @@ func validateDBEngineVersionUpgrade(newVersion, oldVersion string) error {
if semver.Compare(newVersion, oldVersion) < 0 {
return errDBEngineDowngrade
}
// We will not allow major upgrades.
// Major upgrades are handled differently for different operators, so for now we simply won't allow it.
// For example:
// - PXC operator allows major upgrades.
// - PSMDB operator allows major upgrades, but we need to handle FCV.
// - PG operator does not allow major upgrades.
if semver.Major(oldVersion) != semver.Major(newVersion) {
// We will not allow major upgrades for PXC and PG.
// - PXC: Major upgrades are not supported.
// - PG: Major upgrades are in technical preview. https://docs.percona.com/percona-operator-for-postgresql/2.0/update.html#major-version-upgrade
if engineType != everestv1alpha1.DatabaseEnginePSMDB && semver.Major(oldVersion) != semver.Major(newVersion) {
return errDBEngineMajorVersionUpgrade
}

// It's fine to ignore the errors here because we have already validated the version.
newMajorInt, _ := strconv.Atoi(semver.Major(newVersion)[1:])
oldMajorInt, _ := strconv.Atoi(semver.Major(oldVersion)[1:])
// We will not allow major upgrades if the versions are not sequential.
if newMajorInt-oldMajorInt > 1 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what if newMajor version < oldMajor version?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks like this case is validated earlier in the function, the errDBEngineDowngrade will be returned

fmt.Println("errDBEngineMajorUpgradeNotSeq")
return errDBEngineMajorUpgradeNotSeq
}
return nil
}

Expand Down
25 changes: 23 additions & 2 deletions internal/server/handlers/validation/database_engine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,42 +92,63 @@ func TestValidateDBEngineUpgrade(t *testing.T) {
t.Parallel()
testCases := []struct {
name string
engineType everestv1alpha1.EngineType
oldVersion string
newVersion string
err error
}{
{
name: "invalid version",
engineType: everestv1alpha1.DatabaseEnginePXC,
oldVersion: "1.0.0",
newVersion: "1!00;",
err: errInvalidVersion,
},
{
name: "major upgrade",
name: "major upgrade PXC",
engineType: everestv1alpha1.DatabaseEnginePXC,
oldVersion: "8.0.22",
newVersion: "9.0.0",
err: errDBEngineMajorVersionUpgrade,
},
{
name: "major upgrade PSMDB",
engineType: everestv1alpha1.DatabaseEnginePSMDB,
oldVersion: "8.0.22",
newVersion: "9.0.0",
err: nil,
},
{
name: "skipping major upgrade PSMDB",
engineType: everestv1alpha1.DatabaseEnginePSMDB,
oldVersion: "8.0.22",
newVersion: "10.0.0",
err: errDBEngineMajorUpgradeNotSeq,
},
{
name: "downgrade",
engineType: everestv1alpha1.DatabaseEnginePXC,
oldVersion: "8.0.22",
newVersion: "8.0.21",
err: errDBEngineDowngrade,
},
{
name: "valid upgrade",
engineType: everestv1alpha1.DatabaseEnginePXC,
oldVersion: "8.0.22",
newVersion: "8.0.23",
err: nil,
},
{
name: "valid upgrade (with 'v' prefix)",
engineType: everestv1alpha1.DatabaseEnginePXC,
oldVersion: "v8.0.22",
newVersion: "v8.0.23",
err: nil,
},
{
name: "major version downgrade",
engineType: everestv1alpha1.DatabaseEnginePXC,
oldVersion: "16.1",
newVersion: "15.5",
err: errDBEngineDowngrade,
Expand All @@ -136,7 +157,7 @@ func TestValidateDBEngineUpgrade(t *testing.T) {
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
err := validateDBEngineVersionUpgrade(tc.newVersion, tc.oldVersion)
err := validateDBEngineVersionUpgrade(tc.engineType, tc.newVersion, tc.oldVersion)
assert.ErrorIs(t, err, tc.err)
})
}
Expand Down
1 change: 1 addition & 0 deletions internal/server/handlers/validation/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ var (
errInvalidBucketName = fmt.Errorf("invalid bucketName")
errInvalidVersion = errors.New("invalid database engine version provided")
errDBEngineMajorVersionUpgrade = errors.New("database engine cannot be upgraded to a major version")
errDBEngineMajorUpgradeNotSeq = errors.New("database engine major version upgrade is not supported for non-sequential versions")
errDBEngineDowngrade = errors.New("database engine version cannot be downgraded")
errDuplicatedSchedules = errors.New("duplicated backup schedules are not allowed")
errDuplicatedStoragePG = errors.New("postgres clusters can't use the same storage for the different schedules")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,57 +33,63 @@ describe('DBVersion Available filter test', () => {
expect(
filterAvailableDbVersionsForDbEngineEdition(
generateDbEngineWithVersions(
['5.0.0', '4.0.0', '4.3.9', '4.4.1'],
['8.0.39-30.1', '8.0.36-28.1', '8.0.35-27.1', '5.7.44-31.65'],
DbEngineType.PXC
),
'4.4.0'
'8.0.39-30.1'
).map(({ version }) => version)
).toEqual(['5.0.0', '4.4.1']);
});

it('should coerce PG versions to semver', () => {
).toEqual(['8.0.39-30.1']);
expect(
filterAvailableDbVersionsForDbEngineEdition(
generateDbEngineWithVersions(
['13.0', '14.0', '14.1', '15.0'],
['7.0.15-9', '7.0.14-8', '7.0.12-7', '6.0.19-16'],
DbEngineType.PSMDB
),
'7.0.15-9'
).map(({ version }) => version)
).toEqual(['7.0.15-9']);
expect(
filterAvailableDbVersionsForDbEngineEdition(
generateDbEngineWithVersions(
['16.4', '16.3', '15.8'],
DbEngineType.POSTGRESQL
),
'14.1'
'16.4'
).map(({ version }) => version)
).toEqual(['14.1']);
).toEqual(['16.4']);
});

it('should allow major upgrades for PXC', () => {
it('should allow major upgrade to the next version for PSMDB', () => {
expect(
filterAvailableDbVersionsForDbEngineEdition(
generateDbEngineWithVersions(
['5.0.0', '4.0.0', '4.3.9', '4.4.1'],
DbEngineType.PXC
['8.0.4-1', '7.0.15-9', '7.0.14-8', '6.0.19-16', '6.0.18-15'],
DbEngineType.PSMDB
),
'4.4.0'
'6.0.18-15'
).map(({ version }) => version)
).toEqual(['5.0.0', '4.4.1']);
).toEqual(['7.0.15-9', '7.0.14-8', '6.0.19-16', '6.0.18-15']);
});

it('should rule out major upgrades/downgrades for PSMDB/PG', () => {
it('should rule out major upgrades for PXC/PG', () => {
expect(
filterAvailableDbVersionsForDbEngineEdition(
generateDbEngineWithVersions(
[
'1.0.0',
'1.2.0',
'2.3.3',
'2.5.0',
'2.9.0',
'3.1.0',
'4.3.0',
'5.4.1',
],
DbEngineType.PSMDB
['9.0.0', '8.4.2-2.1', '8.0.39-30.1', '8.0.36-28.1', '8.0.35-27.1'],
DbEngineType.PXC
),
'8.0.36-28.1'
).map(({ version }) => version)
).toEqual(['8.4.2-2.1', '8.0.39-30.1', '8.0.36-28.1']);
expect(
filterAvailableDbVersionsForDbEngineEdition(
generateDbEngineWithVersions(
['16.4', '16.3', '15.8', '15.7'],
DbEngineType.POSTGRESQL
),
'2.3.0'
'15.7'
).map(({ version }) => version)
).toEqual(['2.3.3', '2.5.0', '2.9.0']);
).toEqual(['15.8', '15.7']);
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,19 @@ export const filterAvailableDbVersionsForDbEngineEdition = (
return semverVersion ? gte(semverVersion, currentSemverVersion) : true;
});

// If the engine is PSMDB or PG, major version upgrades are also ruled out
if ([DbEngineType.PSMDB, DbEngineType.POSTGRESQL].includes(dbType)) {
// If the engine is PXC or PG, major version upgrades are also ruled out
if ([DbEngineType.PXC, DbEngineType.POSTGRESQL].includes(dbType)) {
versions = versions.filter(({ version }) => {
const semverVersion = coerce(version);
return semverVersion ? semverVersion.major === currentMajor : true;
});
}

// Rule out skipping major versions
versions = versions.filter(({ version }) => {
const semverVersion = coerce(version);
return semverVersion ? semverVersion.major - currentMajor <= 1 : true;
});

return versions;
};
Loading