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

External changes messages enhancement #657

Merged
merged 1 commit into from
Jan 3, 2024

Conversation

worryg0d
Copy link
Collaborator

@worryg0d worryg0d commented Dec 22, 2023

Problem

The current implementation of indicating if there are any external changes to the resource spec writes to events the whole k8s and Instaclustr resource specs. It causes problems in identifying which exact field of the k8s resource differs from the value from the Instaclustr spec.

Solution

This PR adds dcomprasion pkg that provides a deep comparing function. It returns a slice of ObjectDiff. Each ObjectDiff stores the field, the value of the field from the first object, and the value from the second.

@worryg0d worryg0d added the enhancement New feature or request label Dec 22, 2023
@worryg0d worryg0d self-assigned this Dec 22, 2023
@worryg0d worryg0d force-pushed the external-changes-messages-enhancement branch from ad56415 to ee316e4 Compare December 22, 2023 14:00
Comment on lines 220 to 233

diffs := dcomparison.MapsDiff("spec", k8sSpecMap, iSpecMap)
if len(diffs) == 1 {
return fmt.Sprintf(
"%s Diff: {path: %s, k8sValue: %s, instaclustrValue: %s}",
externalChangesBaseMsg,
diffs[0].Path,
diffs[0].Value1,
diffs[0].Value2,
), nil
}

var diffMessages []string
for _, diff := range diffs {
diffMessages = append(diffMessages, fmt.Sprintf(
"{field: %s, k8sValue: %v, instaclustrValue: %v}",
diff.Path,
diff.Value1,
diff.Value2,
))
}
Copy link
Contributor

Choose a reason for hiding this comment

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

There are a lot of cases when our specification differs from instaclustr API specification. Does that mean that in all such cases even if the values are equal, but the structure is different, we will receive such messages about external changes?

Copy link
Collaborator Author

@worryg0d worryg0d Dec 22, 2023

Choose a reason for hiding this comment

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

We received the spec from the Instaclustr API and unmarshaled it to the specific struct (e.g we got cassandra cluster details and unmarshal its spec to the Cassandra) before. Also, before calling MapsDiff we deleted redundant fields from the spec as userReferences. We already don't have any differences between Instaclustr and k8s representation of resources specs.

Comment on lines 222 to 230
if len(diffs) == 1 {
return fmt.Sprintf(
"%s Diff: {path: %s, k8sValue: %s, instaclustrValue: %s}",
externalChangesBaseMsg,
diffs[0].Path,
diffs[0].Value1,
diffs[0].Value2,
), nil
}
Copy link
Contributor

Choose a reason for hiding this comment

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

remove it please

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Done


// ObjectDiff stores the path to a value and the differing values from two maps.
type ObjectDiff struct {
Path string
Copy link
Contributor

Choose a reason for hiding this comment

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

Field

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Done.

Comment on lines 232 to 242
var diffMessages []string
for _, diff := range diffs {
diffMessages = append(diffMessages, fmt.Sprintf(
"{field: %s, k8sValue: %v, instaclustrValue: %v}",
diff.Path,
diff.Value1,
diff.Value2,
))
}

return msg + specDifference, nil
return fmt.Sprintf("%s Diffs: %s", externalChangesBaseMsg, strings.Join(diffMessages, ", ")), nil
Copy link
Contributor

Choose a reason for hiding this comment

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

please make into methods

Copy link
Collaborator Author

@worryg0d worryg0d Dec 22, 2023

Choose a reason for hiding this comment

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

It will look a bit strange if use instaclustrValue and k8sValue inside methods of ObjectDiff. I decided to create a func that prepares the diff message.

@worryg0d worryg0d force-pushed the external-changes-messages-enhancement branch from ee316e4 to 8aafba7 Compare December 22, 2023 16:04
@worryg0d worryg0d force-pushed the external-changes-messages-enhancement branch from 8aafba7 to f0e7583 Compare January 3, 2024 11:22
return "", err
}

const externalChangesBaseMsg = "There are external changes on the Instaclustr console. Please reconcile the specification manually."
Copy link
Collaborator

Choose a reason for hiding this comment

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

Let's move to the models

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Done


const externalChangesBaseMsg = "There are external changes on the Instaclustr console. Please reconcile the specification manually."

diffs := dcomparison.MapsDiff("spec", k8sSpecMap, iSpecMap)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Let's move the "spec" parameter to the constants also

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Done

slice2 := reflect.ValueOf(value2)
maxLength := max(slice1.Len(), slice2.Len())

for i := 0; i < maxLength; i++ {
Copy link
Collaborator

Choose a reason for hiding this comment

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

What if two slices have different lengths?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It uses the length of the biggest one to iterate over two slices. If they have different lengths it adds the corresponding element path to the result. One of the elements will equal the corresponding value, but the second will be nil.
I added some test cases for this.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Also, I added the same test cases for nested maps with different lengths.

@worryg0d worryg0d force-pushed the external-changes-messages-enhancement branch from f0e7583 to 2047e24 Compare January 3, 2024 13:12
@ribaraka ribaraka merged commit 7dc4d3d into main Jan 3, 2024
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants