Skip to content

Commit f2b0391

Browse files
committed
fix patching spec during an update
1 parent 786ab7c commit f2b0391

File tree

1 file changed

+100
-7
lines changed

1 file changed

+100
-7
lines changed

pkg/resource/db_cluster/custom_update.go

+100-7
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"math"
2020
"regexp"
2121
"slices"
22+
"strconv"
2223

2324
ackv1alpha1 "github.com/aws-controllers-k8s/runtime/apis/core/v1alpha1"
2425
ackcompare "github.com/aws-controllers-k8s/runtime/pkg/compare"
@@ -33,7 +34,8 @@ import (
3334
svcapitypes "github.com/aws-controllers-k8s/rds-controller/apis/v1alpha1"
3435
)
3536

36-
var r = regexp.MustCompile(`[0-9]*$`)
37+
// regex: 14.15 -> [14.15, 14, 15]
38+
var versionRegex = regexp.MustCompile(`^(\d+)\.(\d+)`)
3739

3840
// customUpdate is required to fix
3941
// https://github.com/aws-controllers-k8s/community/issues/917. The Input shape
@@ -97,6 +99,7 @@ func (rm *resourceManager) customUpdate(
9799
// Merge in the information we read from the API call above to the copy of
98100
// the original Kubernetes object we passed to the function
99101
ko := desired.ko.DeepCopy()
102+
desiredEngineVersion := desired.ko.Spec.EngineVersion
100103

101104
if resp.DBCluster.ActivityStreamKinesisStreamName != nil {
102105
ko.Status.ActivityStreamKinesisStreamName = resp.DBCluster.ActivityStreamKinesisStreamName
@@ -324,8 +327,18 @@ func (rm *resourceManager) customUpdate(
324327
} else {
325328
ko.Spec.EngineMode = nil
326329
}
330+
fmt.Printf("\n\n\nVariable: %s\n\n\n", *desiredEngineVersion)
327331
if resp.DBCluster.EngineVersion != nil {
328-
ko.Spec.EngineVersion = resp.DBCluster.EngineVersion
332+
// special case during update do not patch
333+
canUpdate, err := requireEngineVersionUpdate(desiredEngineVersion, resp.DBCluster.EngineVersion, *resp.DBCluster.AutoMinorVersionUpgrade)
334+
if err != nil {
335+
return nil, err
336+
}
337+
if desiredEngineVersion != nil && canUpdate {
338+
ko.Spec.EngineVersion = desiredEngineVersion
339+
} else {
340+
ko.Spec.EngineVersion = resp.DBCluster.EngineVersion
341+
}
329342
} else {
330343
ko.Spec.EngineVersion = nil
331344
}
@@ -551,12 +564,29 @@ func (rm *resourceManager) newCustomUpdateRequestPayload(
551564
res.EnableIAMDatabaseAuthentication = desired.ko.Spec.EnableIAMDatabaseAuthentication
552565
}
553566
if desired.ko.Spec.EngineVersion != nil && delta.DifferentAt("Spec.EngineVersion") {
567+
rlog := ackrtlog.FromContext(ctx)
554568
autoMinorVersionUpgrade := true
555569
if desired.ko.Spec.AutoMinorVersionUpgrade != nil {
556570
autoMinorVersionUpgrade = *desired.ko.Spec.AutoMinorVersionUpgrade
557571
}
558-
if requireEngineVersionUpdate(desired.ko.Spec.EngineVersion, latest.ko.Spec.EngineVersion, autoMinorVersionUpgrade) {
572+
573+
shouldUpdate, err := requireEngineVersionUpdate(desired.ko.Spec.EngineVersion, latest.ko.Spec.EngineVersion, autoMinorVersionUpgrade)
574+
if err != nil {
575+
rlog.Debug("error checking engine version update", "error", err.Error())
576+
// Don't return error, just don't include engine version in update
577+
}
578+
579+
if shouldUpdate {
580+
rlog.Debug("including engine version in update",
581+
"desired", *desired.ko.Spec.EngineVersion,
582+
"latest", *latest.ko.Spec.EngineVersion)
559583
res.EngineVersion = desired.ko.Spec.EngineVersion
584+
}
585+
586+
if !shouldUpdate {
587+
rlog.Debug("skipping engine version update",
588+
"desired", *desired.ko.Spec.EngineVersion,
589+
"latest", *latest.ko.Spec.EngineVersion)
560590
}
561591
}
562592
if desired.ko.Spec.MasterUserPassword != nil && delta.DifferentAt("Spec.MasterUserPassword") {
@@ -650,8 +680,71 @@ func getCloudwatchLogExportsConfigDifferences(cloudwatchLogExportsConfigDesired
650680
return logsTypesToEnable, logsTypesToDisable
651681
}
652682

653-
func requireEngineVersionUpdate(desiredEngineVersion *string, latestEngineVersion *string, autoMinorVersionUpgrade bool) bool {
654-
desiredMajorEngineVersion := r.ReplaceAllString(*desiredEngineVersion, "${1}")
655-
latestMajorEngineVersion := r.ReplaceAllString(*latestEngineVersion, "${1}")
656-
return !autoMinorVersionUpgrade || desiredMajorEngineVersion != latestMajorEngineVersion
683+
// requireEngineVersionUpdate determines whether an engine version update should be included
684+
func requireEngineVersionUpdate(desiredEngineVersion *string, latestEngineVersion *string, autoMinorVersionUpgrade bool) (bool, error) {
685+
686+
// what should we do if
687+
if latestEngineVersion == nil {
688+
return false, fmt.Errorf("engine versions cannot be nil")
689+
}
690+
691+
// Check if versions are already identical
692+
if *desiredEngineVersion == *latestEngineVersion {
693+
return false, nil
694+
}
695+
696+
// Parse the desired version
697+
// desiredMatches[0] is the entire string
698+
desiredMatches := versionRegex.FindStringSubmatch(*desiredEngineVersion)
699+
latestMatches := versionRegex.FindStringSubmatch(*latestEngineVersion)
700+
701+
// possible patterms with 2 or more dots....
702+
if len(desiredMatches) < 3 {
703+
return false, fmt.Errorf("invalid desired engine version format: %s", *desiredEngineVersion)
704+
}
705+
if len(latestMatches) < 3 {
706+
return false, fmt.Errorf("invalid latest engine version format: %s", *latestEngineVersion)
707+
}
708+
709+
desiredMajor, err := strconv.Atoi(desiredMatches[1])
710+
if err != nil {
711+
return false, fmt.Errorf("invalid desired major version: %s", desiredMatches[1])
712+
}
713+
714+
desiredMinor, err := strconv.Atoi(desiredMatches[2])
715+
if err != nil {
716+
return false, fmt.Errorf("invalid desired minor version: %s", desiredMatches[2])
717+
}
718+
719+
latestMajor, err := strconv.Atoi(latestMatches[1])
720+
if err != nil {
721+
return false, fmt.Errorf("invalid latest major version: %s", latestMatches[1])
722+
}
723+
724+
latestMinor, err := strconv.Atoi(latestMatches[2])
725+
if err != nil {
726+
return false, fmt.Errorf("invalid latest minor version: %s", latestMatches[2])
727+
}
728+
729+
// Check for downgrade attempts - this should raise an error to prevent
730+
// confusing error messages
731+
if desiredMajor < latestMajor || (desiredMajor == latestMajor && desiredMinor < latestMinor) {
732+
return false, fmt.Errorf("downgrading engine version from %s to %s is not supported",
733+
*latestEngineVersion, *desiredEngineVersion)
734+
}
735+
736+
// Handle major version upgrades - always require explicit update
737+
if desiredMajor > latestMajor {
738+
return true, nil
739+
}
740+
741+
// Handle minor version upgrades
742+
if desiredMajor == latestMajor && desiredMinor > latestMinor {
743+
// If autoMinorVersionUpgrade is false, we should explicitly handle minor version upgrades
744+
// If true, AWS will handle it automatically
745+
return !autoMinorVersionUpgrade, nil
746+
}
747+
748+
// Versions are identical (should have been caught above, but keeping as a safeguard)
749+
return false, nil
657750
}

0 commit comments

Comments
 (0)