-
Notifications
You must be signed in to change notification settings - Fork 43
Fix delta comparison for auto failover, multi AZ, primary cluster ID #69
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -25,8 +25,8 @@ import ( | |
| "github.com/aws-controllers-k8s/elasticache-controller/pkg/common" | ||
| ) | ||
|
|
||
| // filterDelta removes non-meaningful differences from the delta and adds additional differences if necessary | ||
| func filterDelta( | ||
| // modifyDelta removes non-meaningful differences from the delta and adds additional differences if necessary | ||
| func modifyDelta( | ||
| delta *ackcompare.Delta, | ||
| desired *resource, | ||
| latest *resource, | ||
|
|
@@ -54,6 +54,19 @@ func filterDelta( | |
| delta.Add("Spec.LogDeliveryConfigurations", desired.ko.Spec.LogDeliveryConfigurations, | ||
| unmarshalLastRequestedLDCs(desired)) | ||
| } | ||
|
|
||
| if multiAZRequiresUpdate(desired, latest) { | ||
| delta.Add("Spec.MultiAZEnabled", desired.ko.Spec.MultiAZEnabled, latest.ko.Status.MultiAZ) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why isn't the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. They are different types; see response below for more detail |
||
| } | ||
|
|
||
| if autoFailoverRequiresUpdate(desired, latest) { | ||
| delta.Add("Spec.AutomaticFailoverEnabled", desired.ko.Spec.AutomaticFailoverEnabled, | ||
| latest.ko.Status.AutomaticFailover) | ||
| } | ||
|
|
||
| if updateRequired, current := primaryClusterIDRequiresUpdate(desired, latest); updateRequired { | ||
| delta.Add("Spec.PrimaryClusterID", desired.ko.Spec.PrimaryClusterID, *current) | ||
| } | ||
|
Comment on lines
+58
to
+69
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since |
||
| } | ||
|
|
||
| // returns true if desired and latest engine versions match and false otherwise | ||
|
|
@@ -100,3 +113,76 @@ func unmarshalLastRequestedLDCs(desired *resource) []*svcapitypes.LogDeliveryCon | |
|
|
||
| return lastRequestedConfigs | ||
| } | ||
|
|
||
| // multiAZRequiresUpdate returns true if the latest multi AZ status does not yet match the | ||
| // desired state, and false otherwise | ||
| func multiAZRequiresUpdate(desired *resource, latest *resource) bool { | ||
| // no preference for multi AZ specified; no update required | ||
| if desired.ko.Spec.MultiAZEnabled == nil { | ||
| return false | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If it is One thing to note is that If |
||
| } | ||
|
|
||
| // API should return a non-nil value, but if it doesn't then attempt to update | ||
| if latest.ko.Status.MultiAZ == nil { | ||
| return true | ||
| } | ||
|
|
||
| // true maps to "enabled"; false maps to "disabled" | ||
| // this accounts for values such as "enabling" and "disabling" | ||
| if *desired.ko.Spec.MultiAZEnabled { | ||
| return *latest.ko.Status.MultiAZ != string(svcapitypes.MultiAZStatus_enabled) | ||
| } else { | ||
| return *latest.ko.Status.MultiAZ != string(svcapitypes.MultiAZStatus_disabled) | ||
| } | ||
|
Comment on lines
+130
to
+136
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Two things:
// MultiAZEnabled is a boolean in the Spec field but a string enum in the
// output shape field. Here, we reconcile that difference...
if (respRG.MultiAZ == nil) {
// Or set this to a default value if nil isn't default?
resource.ko.Spec.MultiAZEnabled = nil
} else {
resource.ko.Spec.MultiAZEnabled = (*respRG.MultiAZ == string(svcapitypes.MultiAZStatus_enabled))
}If you do the above, you don't have to worry about delta comparisons at all. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Agreed in principle, but the existence of a separate
I'm glad you brought this up because it's helping me externalize why we're moving away from Initially, I wanted to use However, Granted, the As far as the role of So to sum up, the function currently named |
||
| } | ||
|
|
||
| // autoFailoverRequiresUpdate returns true if the latest auto failover status does not yet match the | ||
| // desired state, and false otherwise | ||
| func autoFailoverRequiresUpdate(desired *resource, latest *resource) bool { | ||
| // the logic is exactly analogous to multiAZRequiresUpdate above | ||
| if desired.ko.Spec.AutomaticFailoverEnabled == nil { | ||
| return false | ||
| } | ||
|
|
||
| if latest.ko.Status.AutomaticFailover == nil { | ||
| return true | ||
| } | ||
|
|
||
| if *desired.ko.Spec.AutomaticFailoverEnabled { | ||
| return *latest.ko.Status.AutomaticFailover != string(svcapitypes.AutomaticFailoverStatus_enabled) | ||
| } else { | ||
| return *latest.ko.Status.AutomaticFailover != string(svcapitypes.AutomaticFailoverStatus_disabled) | ||
| } | ||
| } | ||
|
|
||
| // primaryClusterIDRequiresUpdate retrieves the current primary cluster ID and determines whether | ||
| // an update is required. If no desired state is specified or there is an issue retrieving the | ||
| // latest state, return false, nil. Otherwise, return false or true depending on equality of | ||
| // the latest and desired states, and a non-nil pointer to the latest value | ||
| func primaryClusterIDRequiresUpdate(desired *resource, latest *resource) (bool, *string) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Tiny QQ: Any reason why are you using a |
||
| if desired.ko.Spec.PrimaryClusterID == nil { | ||
| return false, nil | ||
| } | ||
|
|
||
| // primary cluster ID applies to cluster mode disabled only; if API returns multiple | ||
| // or no node groups, or the provided node group is nil, there is nothing that can be done | ||
| if len(latest.ko.Status.NodeGroups) != 1 || latest.ko.Status.NodeGroups[0] == nil { | ||
| return false, nil | ||
| } | ||
|
|
||
| // attempt to find primary cluster in node group. If for some reason it is not present, we | ||
| // don't have a reliable latest state, so do nothing | ||
| ng := *latest.ko.Status.NodeGroups[0] | ||
| for _, member := range ng.NodeGroupMembers { | ||
| if member == nil { | ||
| continue | ||
| } | ||
|
|
||
| if member.CurrentRole != nil && *member.CurrentRole == "primary" && member.CacheClusterID != nil { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. QQ: you can only have one "primary" cluster in a node group? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Correct, and primary "cluster" (it's just a node) ID can only be specified when there is one node group in the replication group. |
||
| val := *member.CacheClusterID | ||
| return val != *desired.ko.Spec.PrimaryClusterID, &val | ||
| } | ||
| } | ||
|
|
||
| return false, nil | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -555,7 +555,6 @@ def test_rg_update_misc(self, rg_update_misc_input, rg_update_misc): | |
| assert_misc_fields(reference, rg_update_misc_input['RG_ID'], pmw, description, srl, sw) | ||
|
|
||
| # test modifying properties related to tolerance: replica promotion, multi AZ, automatic failover | ||
| @pytest.mark.blocked # TODO: remove when passing | ||
| def test_rg_fault_tolerance(self, rg_fault_tolerance): | ||
| (reference, _) = rg_fault_tolerance | ||
| assert k8s.wait_on_condition(reference, "ACK.ResourceSynced", "True", wait_periods=30) | ||
|
|
@@ -607,8 +606,8 @@ def test_rg_fault_tolerance(self, rg_fault_tolerance): | |
| raise AssertionError(f"Unknown node {node['cacheClusterID']}") | ||
|
|
||
| # assert AF and multi AZ | ||
| assert resource['status']['automaticFailover'] == "disabled" | ||
| assert resource['status']['multiAZ'] == "disabled" | ||
| assert resource['status']['automaticFailover'] == "enabled" | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. these were just wrong assertions; if you check the file the last patch enables both of these fields |
||
| assert resource['status']['multiAZ'] == "enabled" | ||
|
|
||
| # test association and disassociation of other resources (VPC security groups, SNS topic, user groups) | ||
| @pytest.mark.blocked # TODO: remove when passing | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting, maybe we should open an Issue for this?