-
Notifications
You must be signed in to change notification settings - Fork 484
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
[Part 1]Add unit tests for reconcile methods #250
[Part 1]Add unit tests for reconcile methods #250
Conversation
Signed-off-by: santosh <[email protected]>
@jpkrohling - I am unable to test Patch call (updating existing configmap) with envtest. err = expectedConfigMaps(context.Background(), params(), []v1.ConfigMap{configMap()}, true)
assert.NoError(t, err) While running expectedConfigMaps with existing configmap, I am seeing below error returned.
While running on debug - i could see the control reaching the Patch statement - if err := params.Client.Patch(ctx, updated, patch); err != nil {
return fmt.Errorf("failed to apply changes: %w", err)
} And Patch is returning above error. Any clues what might be causing this. Current PR has this particular test commented. |
Signed-off-by: santosh <[email protected]>
Signed-off-by: santosh <[email protected]>
@humivo @IrisTuntun can you take a look at this PR too for the Operator enhancements we're working on? |
I would need help with above blocker. If this is resolved, I can add tests for all the other reconcilers similarly. |
Signed-off-by: santosh <[email protected]>
Signed-off-by: santosh <[email protected]>
Signed-off-by: santosh <[email protected]>
@jpkrohling - I guess there is a bug in Patch logic -
We are generating patch from Instance, (not sure why). If I generate the patch from existing configmap [ which should be the case, as we are pacthing configmap - not openTelemetryCollector CR ] , like below - patch := client.MergeFrom(existing) Patch Tests are passing. Below is the documentation of mergeFrom function - MergeFrom creates a Patch that patches using the merge-patch strategy with the given object as base. // MergeFrom creates a Patch that patches using the merge-patch strategy with the given object as base.
// The difference between MergeFrom and StrategicMergeFrom lays in the handling of modified list fields.
// When using MergeFrom, existing lists will be completely replaced by new lists.
// When using StrategicMergeFrom, the list field's `patchStrategy` is respected if specified in the API type,
// e.g. the existing list is not replaced completely but rather merged with the new one using the list's `patchMergeKey`.
// See https://kubernetes.io/docs/tasks/manage-kubernetes-objects/update-api-object-kubectl-patch/ for more details on
// the difference between merge-patch and strategic-merge-patch.
func MergeFrom(obj runtime.Object) Patch {
return &mergeFromPatch{patchType: types.MergePatchType, createPatch: createMergePatch, from: obj}
} Same is the case for all the patch calls ( configmap, daemonset, deployment , etc). Kindly confirm. I ll update this thread after testing the operator using above fix |
Works well. I could see deployment being patched if I manually edit the deployment. I am pushing the above change with this PR if its ok. @jpkrohling - Thoughts? |
We were generating patches from params.Instance as base for configmap,deployments & daemonsets. Get the patch from existing resource instead. Signed-off-by: santosh <[email protected]>
Signed-off-by: santosh <[email protected]>
Sorry for taking so long to look into this, I'll review this today or, at the latest, tomorrow. |
Hi, I'm working on adding StatefulSet to reconcile and have a test added in this PR. The test works without changing the |
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.
It's looking great! Would you like to get this one merged first, before working on the next tests? This way, we don't get huge PRs in the queue.
|
||
func TestDesiredConfigMap(t *testing.T) { | ||
t.Run("should return expected config map", func(t *testing.T) { | ||
expected := configMap("test-collector") |
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.
I would skip the local configMap, and make explicit assertions about certain aspects of the returned config map, like checking the returned labels and the name, and possibly the config.
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.
Done
|
||
func TestExpectedConfigMap(t *testing.T) { | ||
|
||
cm := configMap("test-collector") |
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.
You can call the desiredConfigMap here, as you are testing its correctness in another test.
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.
Done
}) | ||
} | ||
|
||
func daemonset(name string) v1.DaemonSet { |
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.
Same as the configmap: if you have a test for the desiredDaemonSet, this one here could probably be removed in favor of the official one.
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.
Yep makes sense.
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.
Same as below
}) | ||
} | ||
|
||
func deployment(name string) v1.Deployment { |
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.
Ditto :-)
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.
Will do
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.
For delete test cases - I cant use desiredDaemonSet/desiredDeployment - As I would need to a resource with same labels as the one in Params but with different name.
i.e.
Lables should be
Labels: map[string]string{
"app.kubernetes.io/managed-by": "opentelemetry-operator",
"app.kubernetes.io/instance": fmt.Sprintf("%s.%s", params.Instance.Namespace, params().Instance.Name),
},
but name should be different than params.Instance.Name. Its not possible using desiredDaemonSet/desiredDeployment functions. So I would have to retain the daemonset and deployment helper functions.
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.
I think all you need for those cases is a deployment/daemonset with one or two labels (managed-by, I believe). This is what we have in the jaeger-operator:
The good thing about doing it like this is that we see exactly what has influence on the decision to remove the CR.
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.
In our case - we are actually creating the object. So would need the entire spec, only namespacedName and labels wont suffice. Basically have to move everything in daemonset function to actual test. Will do the same then
Makes sense. I am half way through with service tests - I ll raise another PR for it. |
Signed-off-by: santosh <[email protected]>
Let me know once this is ready for another review. |
Signed-off-by: santosh <[email protected]>
Done. Also added one more test case each for daemonset and deployment to make sure we dont delete resources which are not owned by operator. Kindly review @jpkrohling |
Raised second PR for this. Could you also take a look at - #261 @jpkrohling |
CodeQL seems stuck. Would you be able to do a "git commit --amend" and push it again? |
Signed-off-by: santosh <[email protected]>
Signed-off-by: santosh <[email protected]>
Signed-off-by: santosh [email protected]
Resolves #35
Raised #261 for service and service account reconcilers