add conformance test for labels#2039
Conversation
|
any comments about this test? anything else we need to cover? |
|
/assign @mattmoor |
|
/assign @evankanderson I'll take a look shortly. Do you want to also write up a change to the spec, or do you want me to try to write that up? I'd be happy to help with wordsmithing if you want to make the spec change (Probably https://github.com/knative/serving/blob/master/docs/spec/spec.md and maybe https://github.com/knative/serving/blob/master/docs/runtime-contract.md#process). |
evankanderson
left a comment
There was a problem hiding this comment.
Looking further at this test, this should be spelled out better in the spec document: we have a completely different set of labels on the object right now. (And the "type" label can probably go, as it was advisory rather than mandatory.)
It may also be worth adding a small amount of text above the sample YAML explaining how each objects labels are derived from its relations.
| var imagePath = test.ImagePath("helloworld") | ||
|
|
||
| var names test.ResourceNames | ||
| names.Service = test.AppendRandomString("pizzaplanet-service", logger) |
There was a problem hiding this comment.
Prefer:
names := test.ResourceNames{Service: test.AppendRandomString("pizzaplanet-service", logger)| // Add test case specific name to its own logger. | ||
| logger := logging.GetContextLogger("TestLabelsPropagation") | ||
|
|
||
| var imagePath = test.ImagePath("helloworld") |
There was a problem hiding this comment.
Move this below the initialization of "names" so that the setup of clients and names are as close as possible to the deferred tearDown.
| names.Config = serviceresourcenames.Configuration(svc) | ||
|
|
||
| logger.Info("The Service will be updated with the name of the Revision once it is created") | ||
| var revisionName string |
There was a problem hiding this comment.
I don't think we need this revisionName here, since we overwrite it on line 62?
| } | ||
| return false, nil | ||
| }, "ServiceUpdatedWithRevision") | ||
| revisionName, err = waitForServiceLatestCreatedRevision(clients, names) |
There was a problem hiding this comment.
Why do we have both WaitForServiceState and waitForServiceLatestCreatedRevision?
| revisionName = s.Status.LatestCreatedRevisionName | ||
| return true, nil | ||
| } | ||
| return false, nil |
There was a problem hiding this comment.
If you don't need to capture revisionName, this can be:
return s.Status.LatestCreatedRevisionname != names.Revision, nil| if err != nil { | ||
| t.Fatalf("Service %s was not updated with the new revision: %v", names.Service, err) | ||
| } | ||
| names.Revision = revisionName |
There was a problem hiding this comment.
Why not assign to names.Revision on line 62?
| t.Fatalf("The Service %s was not marked as Ready to serve traffic to Revision %s: %v", names.Service, names.Revision, err) | ||
| } | ||
|
|
||
| logger.Info("Validate Labels on Revision Object") |
There was a problem hiding this comment.
Add a comment here that the setup is complete, and what we're intending to test (possibly as a reference to the spec)?
| } | ||
| } else { | ||
| t.Fatalf("Failed to get configuration name from Revision label") | ||
| } |
There was a problem hiding this comment.
Totally optional: golang will return a empty value from a map lookup if you use the single-assignment form. Assuming that you know that names.Config is non-empty, you could write this as:
if revision.Labels["serving.knative.dev/configuration"] != names.Config {
t.Fatalf(...)
} There was a problem hiding this comment.
Also, I'd suggest using t.Errorf() here, to fail the test but allow it to keep executing. This will allow additional conditions to be tested and debugged at one time.
There was a problem hiding this comment.
This might also be an opportunity for a table-driven test; ala:
struct TestCase {
Name string
Fetcher func(string, metav1.Options) (interface, error) // Must be an object
Labels map[string]string
}
expectedLabels := []TestCase{
{
Name: names.Revision,
Fetcher: clients.ServingClient.Revisions.Get,
Labels: {
"serving.knative.dev/configuration": names.Config,
"serving.knative.dev/service": names.Service,
},
},
...
}There was a problem hiding this comment.
- I believe the table test would not work as your example above because Go doesn't allow covariant return types (language: covariance support golang/go#7512) as mentioned in a similar conversation in PR Reconciler configs are snapshotted at the start of each reconciliation #2009
- The
Fetcherfunc can't return a generic interface, and the needed objects here do not confirm to any common interface. - The other option is to use kubernetes dynamic client to return
*unstructured.Unstructuredobject and get the Labels from that. - I feel this would be complicating this test too much since we have to change the client used, WDYT?
There was a problem hiding this comment.
Thanks, I'd missed that the conversion between clients.ServingClient.Revisions.Get and the Fetcher wouldn't work. Given that, I agree that this is the most reasonable formulation.
|
@evankanderson addressed comments |
evankanderson
left a comment
There was a problem hiding this comment.
/approve
A few small corrections, but this looks good. Thanks!
| namespace: default | ||
| labels: | ||
| knative.dev/type: ... # +optional convention: function|app | ||
| knative.dev/service: ... # name of the service |
There was a problem hiding this comment.
Mention this is filled in automatically.
| namespace: default | ||
|
|
||
| labels: | ||
| knative.dev/service: ... # name of the service |
| t.Fatalf("The Service %s was not marked as Ready to serve traffic to Revision %s: %v", names.Service, names.Revision, err) | ||
| } | ||
|
|
||
| // Now that the serive is ready, we can validate the Labels on the Revision, Configuration |
| } | ||
|
|
||
| if revision.Labels["serving.knative.dev/configuration"] != names.Config { | ||
| t.Errorf("Expect confguration name in revision label %q but got %q ", names.Config, revision.Labels["serving.knative.dev/configuration"]) |
| } | ||
|
|
||
| if route.Labels["serving.knative.dev/service"] != names.Service { | ||
|
|
| } | ||
| } else { | ||
| t.Fatalf("Failed to get configuration name from Revision label") | ||
| } |
There was a problem hiding this comment.
Thanks, I'd missed that the conversion between clients.ServingClient.Revisions.Get and the Fetcher wouldn't work. Given that, I agree that this is the most reasonable formulation.
|
@evankanderson addressed comments |
evankanderson
left a comment
There was a problem hiding this comment.
/lgtm
/approve
Thanks for doing this, and your patience with my reviews!
|
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: evankanderson, pivotal-nader-ziada The full list of commands accepted by this bot can be found here. The pull request process is described here DetailsNeeds approval from an approver in each of these files:
Approvers can indicate their approval by writing |
Fixes #2021
Proposed Changes
Release Note