-
Notifications
You must be signed in to change notification settings - Fork 391
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
🌱 cache: add replicateAPIResourceSchema test scenario #2240
🌱 cache: add replicateAPIResourceSchema test scenario #2240
Conversation
return kcpShardClusterClient.Cluster(cluster).ApisV1alpha1().APIResourceSchemas().Update(ctx, apiResSchema, metav1.UpdateOptions{}) | ||
}, | ||
updateSpecForSourceResource: func(res interface{}) error { | ||
// no-op |
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.
seems like all fields are immutable, checking . . .
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, there is an admission enforcing immutability.
879041f
to
d95e92a
Compare
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.
Seems reasonable, but would love to have it land after #2104
/hold will merge after #2104 lands |
/unhold |
52c86c3
to
70259dd
Compare
// TestAllAgainstInProcessCacheServer runs all test scenarios against a cache server that runs with a kcp server | ||
func TestAllAgainstInProcessCacheServer(t *testing.T) { | ||
// TestAllReplicationScenariosAgainstInProcessCacheServer runs all test scenarios against a cache server that runs with a kcp server | ||
func TestAllReplicationScenariosAgainstInProcessCacheServer(t *testing.T) { | ||
t.Parallel() |
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.
This makes the suite parallel with the rest of the suites, but does not make each test case parallel - is that intentional? Do we want a t.Parallel()
call in the t.Run()
?
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 don't think so, too much concurrency can negatively impact a CPU.
There is no difference on my local machine: 53
s vs 52
s
// TestAllAgainstInProcessCacheServer runs all test scenarios against a cache server that runs with a kcp server | ||
func TestAllAgainstInProcessCacheServer(t *testing.T) { | ||
// TestAllReplicationScenariosAgainstInProcessCacheServer runs all test scenarios against a cache server that runs with a kcp server | ||
func TestAllReplicationScenariosAgainstInProcessCacheServer(t *testing.T) { |
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.
can we make these e.g. TestCacheServerInProcess
and TestCacheServerStandalone
? there's not real use to explaining that it's all scenarios, and there is nothing except for replication scenarios here
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.
sure, np
@@ -60,109 +61,264 @@ type testScenario struct { | |||
// scenarios all test scenarios that will be run against in-process and standalone cache server | |||
var scenarios = []testScenario{ | |||
{"TestReplicateAPIExport", replicateAPIExportScenario}, | |||
{"TestReplicateAPIResourceSchema", replicateAPIResourceSchemaScenario}, |
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 don't need to format this as a Go test name, much more common to have e.g. "replicate APIResourceSchema"
which will then turn into TestCacheServerInProcess/replicate_APIResourceSchema
resourceKind string | ||
|
||
createSourceResource func(logicalcluster.Name) error | ||
getSourceResource func(logicalcluster.Name) (interface{}, error) |
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 we talked about this before, but there's nothing more specific that this can be, like runtime.Object
? and we don't want to use generics, because?
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 this particular case, we don't need strong types, we operate on meta.Accessor
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.
Can we use meta.Accessor
then?
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.
sure, will change it.
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.
changed to runtime.Object
because I've realized we need full object for comparison.
updateSourceResource: func(cluster logicalcluster.Name, res interface{}) (interface{}, error) { | ||
apiResSchema, ok := res.(*apisv1alpha1.APIResourceSchema) | ||
if !ok { | ||
return nil, fmt.Errorf("%T is not *APIResourceSchema", res) |
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.
With generics you don't need to write this code
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.
yeah, this is the only case that would benefit from using generics, I can look into that in a follow-up PR.
} | ||
|
||
// replicateAPIExportNegativeScenario checks if modified or even deleted cached APIExport will be reconciled to match the original object | ||
func replicateAPIExportNegativeScenario(ctx context.Context, t *testing.T, server framework.RunningServer, kcpShardClusterClient clientset.ClusterInterface, cacheKcpClusterClient clientset.ClusterInterface) { |
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.
Why is this APIExport-specific?
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.
added the case for APIResourceSchema
if diff := cmp.Diff(cachedWildAPIExport, wildAPIExport, cmpopts.IgnoreFields(metav1.ObjectMeta{}, "ResourceVersion")); len(diff) > 0 { | ||
return false, fmt.Sprintf("replicated APIExport root/%s/%s is different that the original", cluster, wildAPIExport.Name) | ||
delete(cachedResourceMeta.GetAnnotations(), genericapirequest.AnnotationKey) | ||
if diff := cmp.Diff(cachedResource, originalResource, cmpopts.IgnoreFields(metav1.ObjectMeta{}, "ResourceVersion")); len(diff) > 0 { |
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.
Love to see cmpopts - nice! I think you could likely get the annotation key in there too if you cared
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 tried but couldn't make it to work on the annotation key
return false, fmt.Sprintf("replicated APIExport root/%s/%s is different that the original", cluster, wildAPIExport.Name) | ||
delete(cachedResourceMeta.GetAnnotations(), genericapirequest.AnnotationKey) | ||
if diff := cmp.Diff(cachedResource, originalResource, cmpopts.IgnoreFields(metav1.ObjectMeta{}, "ResourceVersion")); len(diff) > 0 { | ||
return false, fmt.Sprintf("replicated %s root|%s/%s is different that the original", scenario.resourceKind, cluster, cachedResourceMeta.GetName()) | ||
} | ||
return true, "" | ||
}, wait.ForeverTestTimeout, 400*time.Millisecond) |
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.
How did we arrive at this poll period?
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.
just a random number
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.
Let's use 100ms like the rest of the tests unless we really need to change it - for folks with fast workstations, 300ms extra poll time might double or triple test runtime :)
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 folks with fast workstations, 300ms extra poll time might double or triple test runtime :)
that's why you want to use t.Parallel
everywhere :)
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.
Hey, what takes 65 minutes in GitHub Actions takes 54seconds on my machine ... ;)
70259dd
to
084e18e
Compare
084e18e
to
808ca68
Compare
} | ||
|
||
// baseScenario an auxiliary struct that is used by replicateResourceScenario | ||
type baseScenario struct { |
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.
am always getting a little nervous when seeing data structures like this and constructors in e2e tests. It's most often a sign for too complex tests, or for a lack of a DSL like builder language to construct the test cases in the actual Test*
funcs.
Rule of thumb: if I look at some Test*
func I want to know what it is doing without looking outside of this func. Builder pattern (with local funcs) is great way to provide the helpers to specify the test input in a precise and short way.
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.
updated to use the builder pattern, ptal
…cateResourceScenario
tests if an APIResourceSchema is propagated to the cache server. The test exercises creation, modification and removal of the APIExport object.
8262ef3
to
7137372
Compare
7137372
to
c1fbe65
Compare
/lgtm |
[APPROVALNOTIFIER] This PR is APPROVED Approval requirements bypassed by manually added approval. This pull-request has been approved by: 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 |
Summary
The new test checks if an APIResourceSchema is propagated to the cache server.
The test exercises a creation, modification and removal of the APIExport object.
Related issue(s)
part of #342