-
Notifications
You must be signed in to change notification settings - Fork 123
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1514 from ravilr/rds_prevent_drift_due_to_automan…
…aged_upgrades ignore drift in rds.Cluster and rds.Instance due to engine_version diff arising out of automanaged upgrades
- Loading branch information
Showing
3 changed files
with
306 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
// SPDX-FileCopyrightText: 2024 The Crossplane Authors <https://crossplane.io> | ||
// | ||
// SPDX-License-Identifier: CC0-1.0 | ||
|
||
package utils | ||
|
||
import ( | ||
"strconv" | ||
"strings" | ||
) | ||
|
||
// EngineVersion represents an AWS RDS engine version. | ||
type EngineVersion []any | ||
|
||
// ParseEngineVersion from a raw string. | ||
func ParseEngineVersion(raw string) EngineVersion { | ||
split := strings.Split(raw, ".") | ||
|
||
v := make(EngineVersion, len(split)) | ||
for i, s := range split { | ||
d, err := strconv.Atoi(s) | ||
if err != nil { | ||
v[i] = s | ||
} else { | ||
v[i] = d | ||
} | ||
} | ||
return v | ||
} | ||
|
||
const ( | ||
compareIsHigher = 1 | ||
compareIsEqual = 0 | ||
compareIsLower = -1 | ||
) | ||
|
||
// Compare returns a positive value if v is represents a higher version number | ||
// than other. A negative value is returned if other is higher than v. | ||
// It returns 0 if both are considered equal. | ||
func (v EngineVersion) Compare(other EngineVersion) int { | ||
if other == nil { | ||
return compareIsHigher | ||
} | ||
|
||
for i := 0; i < len(v); i++ { | ||
a := v.get(i) | ||
b := other.get(i) | ||
c := compareVersionComponents(a, b) | ||
if c != 0 { | ||
return c | ||
} | ||
} | ||
return compareIsEqual | ||
} | ||
|
||
func compareVersionComponents(a, b any) int { | ||
if a == b { | ||
return compareIsEqual | ||
} | ||
if b == nil { | ||
return compareIsHigher | ||
} | ||
aI, aIsInt := a.(int) | ||
bI, bIsInt := b.(int) | ||
if aIsInt { | ||
if bIsInt { | ||
return aI - bI | ||
} | ||
return compareIsHigher | ||
} | ||
if bIsInt { | ||
return compareIsLower | ||
} | ||
return compareIsEqual // We cannot decide if both are strings. | ||
} | ||
|
||
func (v EngineVersion) get(i int) any { | ||
if i >= 0 && i < len(v) { | ||
return v[i] | ||
} | ||
return nil | ||
} | ||
|
||
// CompareEngineVersions is a shortcut to compare two engine versions. | ||
func CompareEngineVersions(a, b string) int { | ||
av := ParseEngineVersion(a) | ||
bv := ParseEngineVersion(b) | ||
return av.Compare(bv) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,186 @@ | ||
// SPDX-FileCopyrightText: 2024 The Crossplane Authors <https://crossplane.io> | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package utils | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/google/go-cmp/cmp" | ||
) | ||
|
||
func TestEngineVersionIsHigherOrEqual(t *testing.T) { | ||
type args struct { | ||
spec string | ||
current string | ||
} | ||
|
||
type want struct { | ||
result int | ||
} | ||
|
||
cases := map[string]struct { | ||
args | ||
want | ||
}{ | ||
"AuroraMySQLIsEqual": { | ||
args: args{ | ||
spec: "5", | ||
current: "5.7.mysql_aurora.2.07.0", | ||
}, | ||
want: want{ | ||
result: 0, | ||
}, | ||
}, | ||
"AuroraMySQLIsEqual2": { | ||
args: args{ | ||
spec: "5.7", | ||
current: "5.7.mysql_aurora.2.07.0", | ||
}, | ||
want: want{ | ||
result: 0, | ||
}, | ||
}, | ||
"AuroraMySQLIsHigher": { | ||
args: args{ | ||
spec: "8", | ||
current: "5.7.mysql_aurora.2.07.0", | ||
}, | ||
want: want{ | ||
result: 1, | ||
}, | ||
}, | ||
"AuroraPostgresIsEqual": { | ||
args: args{ | ||
spec: "14", | ||
current: "14.4", | ||
}, | ||
want: want{ | ||
result: 0, | ||
}, | ||
}, | ||
"AuroraPostgresIsLower": { | ||
args: args{ | ||
spec: "14", | ||
current: "15.2", | ||
}, | ||
want: want{ | ||
result: -1, | ||
}, | ||
}, | ||
"MariaDBIsEqual": { | ||
args: args{ | ||
spec: "10", | ||
current: "10.3.35", | ||
}, | ||
want: want{ | ||
result: 0, | ||
}, | ||
}, | ||
"MariaDBNotIsLower": { | ||
args: args{ | ||
spec: "10", | ||
current: "11.0", | ||
}, | ||
want: want{ | ||
result: -1, | ||
}, | ||
}, | ||
"MySQLIsEqual": { | ||
args: args{ | ||
spec: "5.7", | ||
current: "5.7.38", | ||
}, | ||
want: want{ | ||
result: 0, | ||
}, | ||
}, | ||
"MySQLIsHigher": { | ||
args: args{ | ||
spec: "8", | ||
current: "5.7.38", | ||
}, | ||
want: want{ | ||
result: 1, | ||
}, | ||
}, | ||
"OracleIsEqual": { | ||
args: args{ | ||
spec: "19", | ||
current: "19.0.0.0.ru-2023-01.rur-2023-01.r1", | ||
}, | ||
want: want{ | ||
result: 0, | ||
}, | ||
}, | ||
"OracleIsHigher": { | ||
args: args{ | ||
spec: "20", | ||
current: "19.0.0.0.ru-2023-01.rur-2023-01.r1", | ||
}, | ||
want: want{ | ||
result: 1, | ||
}, | ||
}, | ||
"PostgresIsEqual": { | ||
args: args{ | ||
spec: "10", | ||
current: "10.17", | ||
}, | ||
want: want{ | ||
result: 0, | ||
}, | ||
}, | ||
"PostgresIsHigher": { | ||
args: args{ | ||
spec: "14", | ||
current: "10.17", | ||
}, | ||
want: want{ | ||
result: 1, | ||
}, | ||
}, | ||
"SQLServerIsEqual": { | ||
args: args{ | ||
spec: "12", | ||
current: "12.00.6293.0.v1", | ||
}, | ||
want: want{ | ||
result: 0, | ||
}, | ||
}, | ||
"SQLServerIsHigher": { | ||
args: args{ | ||
spec: "14", | ||
current: "12.00.6293.0.v1", | ||
}, | ||
want: want{ | ||
result: 1, | ||
}, | ||
}, | ||
} | ||
|
||
for name, tc := range cases { | ||
t.Run(name, func(t *testing.T) { | ||
specV := ParseEngineVersion(tc.args.spec) | ||
curV := ParseEngineVersion(tc.args.current) | ||
|
||
res := specV.Compare(curV) | ||
resSign := sign(res) | ||
if diff := cmp.Diff(tc.want.result, resSign); diff != "" { | ||
t.Errorf("r: -want, +got:\n%q\n%q\n%s", tc.args.spec, tc.args.current, diff) | ||
} | ||
}) | ||
} | ||
} | ||
|
||
func sign(x int) int { | ||
if x < 0 { | ||
return -1 | ||
} | ||
if x > 0 { | ||
return 1 | ||
} | ||
return 0 | ||
} |