@@ -19,6 +19,7 @@ import (
19
19
"math"
20
20
"regexp"
21
21
"slices"
22
+ "strconv"
22
23
23
24
ackv1alpha1 "github.com/aws-controllers-k8s/runtime/apis/core/v1alpha1"
24
25
ackcompare "github.com/aws-controllers-k8s/runtime/pkg/compare"
@@ -33,7 +34,8 @@ import (
33
34
svcapitypes "github.com/aws-controllers-k8s/rds-controller/apis/v1alpha1"
34
35
)
35
36
36
- var r = regexp .MustCompile (`[0-9]*$` )
37
+ // regex: 14.15 -> [14.15, 14, 15]
38
+ var versionRegex = regexp .MustCompile (`^(\d+)\.(\d+)` )
37
39
38
40
// customUpdate is required to fix
39
41
// https://github.com/aws-controllers-k8s/community/issues/917. The Input shape
@@ -97,6 +99,7 @@ func (rm *resourceManager) customUpdate(
97
99
// Merge in the information we read from the API call above to the copy of
98
100
// the original Kubernetes object we passed to the function
99
101
ko := desired .ko .DeepCopy ()
102
+ desiredEngineVersion := desired .ko .Spec .EngineVersion
100
103
101
104
if resp .DBCluster .ActivityStreamKinesisStreamName != nil {
102
105
ko .Status .ActivityStreamKinesisStreamName = resp .DBCluster .ActivityStreamKinesisStreamName
@@ -324,8 +327,18 @@ func (rm *resourceManager) customUpdate(
324
327
} else {
325
328
ko .Spec .EngineMode = nil
326
329
}
330
+ fmt .Printf ("\n \n \n Variable: %s\n \n \n " , * desiredEngineVersion )
327
331
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
+ }
329
342
} else {
330
343
ko .Spec .EngineVersion = nil
331
344
}
@@ -551,12 +564,29 @@ func (rm *resourceManager) newCustomUpdateRequestPayload(
551
564
res .EnableIAMDatabaseAuthentication = desired .ko .Spec .EnableIAMDatabaseAuthentication
552
565
}
553
566
if desired .ko .Spec .EngineVersion != nil && delta .DifferentAt ("Spec.EngineVersion" ) {
567
+ rlog := ackrtlog .FromContext (ctx )
554
568
autoMinorVersionUpgrade := true
555
569
if desired .ko .Spec .AutoMinorVersionUpgrade != nil {
556
570
autoMinorVersionUpgrade = * desired .ko .Spec .AutoMinorVersionUpgrade
557
571
}
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 )
559
583
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 )
560
590
}
561
591
}
562
592
if desired .ko .Spec .MasterUserPassword != nil && delta .DifferentAt ("Spec.MasterUserPassword" ) {
@@ -650,8 +680,71 @@ func getCloudwatchLogExportsConfigDifferences(cloudwatchLogExportsConfigDesired
650
680
return logsTypesToEnable , logsTypesToDisable
651
681
}
652
682
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
657
750
}
0 commit comments