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

🌱 cache: add replicateAPIResourceSchema test scenario #2240

Conversation

p0lyn0mial
Copy link
Contributor

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

return kcpShardClusterClient.Cluster(cluster).ApisV1alpha1().APIResourceSchemas().Update(ctx, apiResSchema, metav1.UpdateOptions{})
},
updateSpecForSourceResource: func(res interface{}) error {
// no-op
Copy link
Contributor Author

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 . . .

Copy link
Contributor Author

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.

@p0lyn0mial p0lyn0mial force-pushed the cache-replication-e2e-apiresourceschema branch from 879041f to d95e92a Compare October 20, 2022 13:39
Copy link
Contributor

@stevekuznetsov stevekuznetsov left a 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

@p0lyn0mial
Copy link
Contributor Author

/hold

will merge after #2104 lands

@openshift-ci openshift-ci bot added the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Oct 20, 2022
@nrb
Copy link
Contributor

nrb commented Oct 21, 2022

/unhold
2104 is in

@openshift-ci openshift-ci bot removed the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Oct 21, 2022
@p0lyn0mial p0lyn0mial force-pushed the cache-replication-e2e-apiresourceschema branch 2 times, most recently from 52c86c3 to 70259dd Compare October 26, 2022 11:28
// 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()
Copy link
Contributor

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()?

Copy link
Contributor Author

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: 53s vs 52s

// 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) {
Copy link
Contributor

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

Copy link
Contributor Author

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},
Copy link
Contributor

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)
Copy link
Contributor

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?

Copy link
Contributor Author

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

Copy link
Contributor

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?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

sure, will change it.

Copy link
Contributor Author

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)
Copy link
Contributor

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

Copy link
Contributor Author

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) {
Copy link
Contributor

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?

Copy link
Contributor Author

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 {
Copy link
Contributor

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

Copy link
Contributor Author

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)
Copy link
Contributor

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?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

just a random number

Copy link
Contributor

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 :)

Copy link
Contributor Author

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 :)

Copy link
Contributor

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 ... ;)

@openshift-merge-robot openshift-merge-robot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Oct 27, 2022
@p0lyn0mial p0lyn0mial force-pushed the cache-replication-e2e-apiresourceschema branch from 70259dd to 084e18e Compare October 28, 2022 09:58
@openshift-merge-robot openshift-merge-robot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Oct 28, 2022
@p0lyn0mial p0lyn0mial force-pushed the cache-replication-e2e-apiresourceschema branch from 084e18e to 808ca68 Compare October 28, 2022 10:04
}

// baseScenario an auxiliary struct that is used by replicateResourceScenario
type baseScenario struct {
Copy link
Member

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.

Copy link
Contributor Author

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

@p0lyn0mial p0lyn0mial force-pushed the cache-replication-e2e-apiresourceschema branch 2 times, most recently from 8262ef3 to 7137372 Compare November 3, 2022 14:51
@p0lyn0mial p0lyn0mial force-pushed the cache-replication-e2e-apiresourceschema branch from 7137372 to c1fbe65 Compare November 3, 2022 16:33
@sttts
Copy link
Member

sttts commented Nov 4, 2022

/lgtm
/approved

@openshift-ci openshift-ci bot added the lgtm Indicates that a PR is ready to be merged. label Nov 4, 2022
@p0lyn0mial p0lyn0mial added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Nov 4, 2022
@openshift-ci
Copy link
Contributor

openshift-ci bot commented Nov 4, 2022

[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 /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved Indicates a PR has been approved by an approver from all required OWNERS files. lgtm Indicates that a PR is ready to be merged.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants