My prior change added sorting to the duck.CreatePatch method to try and stabilize the result of jsonpatch.CreatePatch, which is otherwise non-deterministic (probably walking a map?).
My bad assumption was that the patch operations this generated wouldn't conflict, e.g. it should use `replace` vs. `remove` and `add`.
Clearly this was bad because we start getting really strange errors trying to import this into knative/serving, e.g.
https://gubernator.knative.dev/build/knative-prow/pr-logs/pull/knative_serving/2646/pull-knative-serving-integration-tests/1070435951391543298/
Immutable fields with default values may now be changed iff they change is to populate their default value. This is to support defaulting in the scenario where an object was created long ago and a new field (with a default!) is added. When controllers attempt to mutate the object status today, this would create a webhook rejection! With this change, we compare against a freshly defaulted "old" object to exclude newly defaulted fields from the immutability check.
We saw this in knative/serving for the newly added TimeoutSeconds field in Revision (otherwise immutable), which I believe it leading to upgrade testing flakes since post-upgrade Revision status updates will fail.
* Prune the GenericCRD spec to what is used.
Encapsulate our change detection slightly.
* Support common spec mutations via duck typing.
This adds support for performing common mutations to objects via duck types and JSON patching.
Fixes: https://github.com/knative/pkg/issues/76
* Eliminate getSpecJSON thru schemaless duck typing.
This leverages a one-off trick to get the JSON of the spec field from arbitrary types.
In order to have a single webhook support multiple domain contexts, this reworks the `Handlers` argument to embed the `schema.GroupVersion` by wrapping the existing keys with it as a `schema.GroupVersionKind`.
This is mostly straightforward, but one oddity is that I discovered that `AdmissionRequest` gets this same tuple as the less capable `metav1.GroupVersionKind`, so there's a silly conversion we have to do.
I tried this manually vendored in serving with KPA and things worked great.
This pulls the Knative webhook logic (oriented around the interfaces in `knative/pkg/apis`) into `knative/pkg`.
The code is largely copied as-is, with `keep.go` excluded. The main changes are to the test code, which in `knative/serving` still operate in terms of the serving types.
Fixes: https://github.com/knative/pkg/issues/9