-
Notifications
You must be signed in to change notification settings - Fork 73
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
SANDBOX-838: loop update calls #1074
SANDBOX-838: loop update calls #1074
Conversation
/retest hitting known flaky test SANDBOX-837 |
/retest hitting known flaky test SANDBOX-836 |
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.
Thanks a lot for taking care of this.
I believe that we could lower the amount of copy-pasting by expanding the Waiter
generic type
toolchain-e2e/testsupport/wait/awaitility.go
Lines 669 to 675 in f22abed
// Waiter is a helper struct for `wait.For()` that provides functions to query the cluster waiting | |
// for the results. | |
type Waiter[T client.Object] struct { | |
await *Awaitility | |
t *testing.T | |
gvk schema.GroupVersionKind | |
} |
cc @metlos
Something like this could work:
func (w *Waiter[T]) Update(status bool, objectName string, modify func(T)) (T, error) {
var objectToReturn T
err := wait.PollUntilContextTimeout(context.TODO(), w.await.RetryInterval, w.await.Timeout, true, func(ctx context.Context) (done bool, err error) {
obj := &unstructured.Unstructured{}
obj.SetGroupVersionKind(w.gvk)
if err := w.await.Client.Get(context.TODO(), types.NamespacedName{Namespace: w.await.Namespace, Name: objectName}, obj); err != nil {
return true, err
}
object, err := w.cast(obj)
if err != nil {
return false, fmt.Errorf("failed to cast the object to GVK %v: %w", w.gvk, err)
}
modify(object)
if status {
// Update the Status
if err := w.await.Client.Status().Update(context.TODO(), object); err != nil {
w.t.Logf("error updating '%v' Status '%s': %s. Will retry again...", w.gvk, objectName, err.Error())
return false, err
}
} else {
// Update the Spec
if err := w.await.Client.Update(context.TODO(), object); err != nil {
w.t.Logf("Error updating '%v' Spec '%s': %s. Will retry again...", w.gvk, objectName, err.Error())
return false, err
}
}
objectToReturn = object
return true, nil
})
return objectToReturn, err
}
so you could then call it:
_, err = For(t, hostAwait.Awaitility, &toolchainv1alpha1.NSTemplateTier{}).
Update(false, tier.NSTemplateTier.Name, func(nstt *toolchainv1alpha1.NSTemplateTier) {
nstt.Spec = tier.NSTemplateTier.Spec
})
or:
event, err = For(t, hostAwait.Awaitility, &toolchainv1alpha1.SocialEvent{}).
Update(false, event.Name, func(ev *toolchainv1alpha1.SocialEvent) {
ev.Spec.SpaceTier = "base"
})
You could also add other methods with some syntactic sugar:
func (w *Waiter[T]) Update(objectName string, modify func(T)) (T, error) {
return w.doUpdate(false, objectName, modify)
}
func (w *Waiter[T]) UpdateStatus(objectName string, modify func(T)) (T, error) {
return w.doUpdate(true, objectName, modify)
}
func (w *Waiter[T]) doUpdate(status bool, objectName string, modify func(T)) (T, error) {
var objectToReturn T
...
test/e2e/parallel/proxy_test.go
Outdated
t.Run("use proxy to update a HAS Application CR in the user appstudio namespace via proxy API", func(t *testing.T) { | ||
// Update application | ||
// Get application name | ||
applicationName := user.getApplicationName(0) | ||
// Get application | ||
proxyApp := user.getApplication(t, proxyCl, applicationName) | ||
// Update DisplayName | ||
changedDisplayName := fmt.Sprintf("Proxy test for user %s - updated application", tenantNsName(user.compliantUsername)) | ||
proxyApp.Spec.DisplayName = changedDisplayName | ||
err := proxyCl.Update(context.TODO(), proxyApp) | ||
// Update application | ||
proxyApp, err := awaitilities.Host().UpdateApplication(t, proxyCl, applicationName, tenantNsName(user.compliantUsername), func(app *appstudiov1.Application) { | ||
app.Spec.DisplayName = changedDisplayName | ||
}) | ||
require.NoError(t, err) |
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.
Not related to this PR, but I think that we can drop the "AppStudio API"-specific test cases. It's completely fine to test modification on standard k8s resources (eg. ConfigMap), no need to maintain the other API
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.
Apart from that, there is actually no Application controller running that would watch/modify these resources. This means that we don't expect any conflicts for this resource and the update through the proxy should work fine without having the loop.
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.
Thank you so much! I will remove the loop here. And take care of the "AppStudio API"-specific test cases in a different PR
@MatousJobanek excellent idea!! 🚀 Should we move the |
as discussed in the KubeSaw sync call, it should stay here 👍 |
Perfect, thank you so much! I addressed for now only some cases to the pr to not be too heavy to review. I will clean up the other Update's functions in a separate PR once this one is merged |
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.
Nice, thanks for taking care of this, and thanks for implementing the generic approach 👍
testsupport/wait/awaitility.go
Outdated
return false, err | ||
} | ||
} else { | ||
// Update the Spec | ||
if err := w.await.Client.Update(context.TODO(), object); err != nil { | ||
w.t.Logf("Error updating '%v' Spec '%s': %s. Will retry again...", w.gvk, objectName, err.Error()) | ||
return false, err |
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 just noticed that I made a mistake in my suggestion, we should not return an error here; otherwise, the poll loop immediately exists with an error:
return false, err | |
} | |
} else { | |
// Update the Spec | |
if err := w.await.Client.Update(context.TODO(), object); err != nil { | |
w.t.Logf("Error updating '%v' Spec '%s': %s. Will retry again...", w.gvk, objectName, err.Error()) | |
return false, err | |
return false, nil | |
} | |
} else { | |
// Update the Spec | |
if err := w.await.Client.Update(context.TODO(), object); err != nil { | |
w.t.Logf("Error updating '%v' Spec '%s': %s. Will retry again...", w.gvk, objectName, err.Error()) | |
return false, nil |
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.
is this true also for the status update faliure : https://github.com/codeready-toolchain/toolchain-e2e/pull/1074/files#diff-4abc90985c7fe1e595e0d6f5131e1f4757a6f00c9239f40ae09375d12f15e530R916
should we not return an error here as well and retry ?
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.
Yes, it is addressed in line 916 of @MatousJobanek suggestion! Goinggggg!!
Locally, it passed for me. That's why I did not notice it. Sorry!
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.
oh nice, sorry I've missed that from the suggestion, never mind 👍
Quality Gate passedIssues Measures |
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.
Great Job 👏
I like the new generic update functions 👍
I have only one minor comment/question.
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: MatousJobanek, mfrancisc, rsoaresd The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
/retest hitting known flaky test SANDBOX-837 |
Description
#1071 addressed a potential fix, but to ensure we do not face it in the future, we should do the update call in a loop.
Since other update calls are not being done in a loop, this PR addressed it as well.
Issue ticket number and link
SANDBOX-838