* Refactor webhook to allow adding conversion support
* pr feedback
* fix memory leak
* We can use mux.Handle
* move admission integration tests to separate file
By combining our validation logic into our mutating webhook we were previously allowing for mutating webhooks evaluated after our own to modify our resources into invalid shapes. There are no guarantees around ordering of mutating webhooks (that I could find), so the only way to remedy this properly is to split apart the two into separate webhook configurations:
- `defaulting`: which runs during the mutating admission webhook phase
- `validation`: which runs during the validating admission webhook phase.
The diagram in [this post](https://kubernetes.io/blog/2019/03/21/a-guide-to-kubernetes-admission-controllers/) is very helpful in illustrating the flow of webhooks.
Fixes: https://github.com/knative/pkg/issues/847
GetCertificate allows us to start in TLS mode and dynamically fetch new certificates as they change. This will eventually allow us to decouple the cert creation process from the core webhook logic, and in a subsequent change service this from a secret lister cache.
This builds on https://github.com/knative/pkg/pull/817 and makes further
breaking changes. The options pertinent to each admission controller are
now passed to their respective constructors, which leads to a cleaner
options struct, and better prepares for greater webhook diversity.
* Stop using OwnerRefs for webhook config lifecycle
This changes the model by which we manage the lifecycle of our
`{mutating,validating}webhookconfiguration`, which previously used an owner ref
from the cluster-scoped configuration to the namespace-scoped Deployment. The
new model adds an explicit yaml file for the webhook, which omits the fields
filled in by the deployment as it starts.
A few notable elements of this change:
1. Clear out OwnerReferences explicitly (avoids the linked bug),
2. Periodically reruna `Register()` to ensure our webhook exists,
3. Simplified logic around registration (all we need now is update!).
Related: https://github.com/knative/serving/issues/5845
* Incorporate feedback from @dgerd and a few other nits I noticed.
* Prevent nil StatsReporter for existing webhook package consumers
* Pass StatsReporter by pointer and have tests test constructor
* Make constructor return error instead of panicking
* Move StatsReporter to ControllerOptions to consolidate constructors
* Add metrics to webhook package
Add metricstest package for shared helper functions for testing metrics
* Address PR
* Cleanup
* Fix import paths to fix build issues
* Fix import package path for test file
* Remove unnecessary formatting from error message
* Remove helper function only used once
* Add metric name to all error messages, make checkRowTags testing helper function
* Add common histogram bucket generator function to metrics package
* Fix CheckStatsNotReported check
* Reset metrics before each test so the tests are idempotent
* Make CheckStatsNotReported conditional clearer
* #457 Duck type user annotation logic
* #457 Duck type user annotation logic - tests
* #457 Revert updater annotation key from lastModifier to updater
* #457 Rename HasSpec#GetSpec() to HasSpec#GetUntypedSpec()
* #457 Fix some indentation
* #457 Get group for user info annotations from the request
* #457 Reduce confusuion in webhook testing by using same group
* have simple tests. working on impl.
* strict setting, reflection based.
* ran codegen.
* adding license.
* update based on feedback and merge better.
* getting closer to something simpler assuming shallow reflect.
* adding validation test.
* use the json tag.
* Golang things nil typed pointers are not nil.
* Use real value of reflect invalid.
* add a missing test.
* two methods, one for update, one for single check.
* checkdep is now in apis.
* fix pkg.
* Update apis/deprecated_test.go
Co-Authored-By: n3wscott <32305648+n3wscott@users.noreply.github.com>
* add code clarity.
* include inlined struct objects recursively.
* Update commnets and add a flatten error test for inlined.
This deprecates the `apis.Immutable` and `apis.Annotatable` interfaces,
which were both awkward niche extensions of `apis.Validatable` and
`apis.SetDefaults` for specific contexts that the former set didn't
cover well.
With this change, the expectation is that types that want to check
for immutability will instead access the "baseline" object via the
context from within updates. For example:
```
func (new *Type) Validate(ctx context.Context) *apis.FieldError {
if apis.IsInUpdate(ctx) {
old := apis.GetBaseline(ctx).(*Type)
// Update specific validation based on new and old.
}
}
```
For applying user annotations, the type writer can write:
```
func (new *Type) SetDefaults(ctx context.Context) {
if apis.IsInCreate(ctx) {
ui := apis.GetUserInfo(ctx)
// Set creator annotation from ui
}
if apis.IsInUpdate(ctx) {
ui := apis.GetUserInfo(ctx)
old := apis.GetBaseline(ctx).(*Type)
// Compare old.Spec vs. new.Spec and on changes
// update the "updater" annotation from ui.
}
}
```
One of the key motivations for this refactoring was to enable us
to do more powerful validation in `apis.Validate` beyond the niche
of immutability checking (and without introducing yet-another
one-off niche interface). In the BYO Revision name PoC I abused
`apis.Immutable` to do more arbitrary before/after validation,
which with this can simply be a part of `apis.Validatable`.
See: https://github.com/knative/serving/pull/3562
The general stance on deprecating interfaces such as these will be
to deprecate them in a non-breaking way (via a comment for now). They
will be hollowed out when the functionality is removed from the webhook,
but left in because of diamond dependency problems. In this change
we remove the `apis.Annotatable` functionality and deprecate the
`apis.Immutable` functionality.
Clients of webhook can now decorate the request context with additional metadata
via:
```
ac := &AdmissionController{
... // As before
WithContext: func(ctx context.Context) context.Context {
// logic to attach stuff to ctx
}
}
```
This metadata can then be accessed off of the context in methods like
`SetDefaults` and `Validate` on types registered as webhook handlers.
Fixes: https://github.com/knative/pkg/issues/306
* Modify the webhook to allow the use of duck types.
This change enables us to define a duck type that applies to a whole class of GroupVersionKinds and leverage it to perform generic validation, defaulting, etc.
Fixes: #322
* Fix typo
* Drop webhook logic to increment spec.generation
With Kubernetes 1.11+ metadata.generation now increments properly
when the status subresource is enabled on CRDs
For more details see: https://github.com/knative/serving/issues/643
* Drop the generational duck type
* Initial commit for the webhook to set the annotations about mutator.
The user that created or updated the resource will be set in the
annotations.
* update comments
* remove debug logging
* logging :/
* logging :/, returns
* logging :/ III
* error wrap
* simplify test
* rename the test
* add pkg/errors to the deps for better errors
* do not require CRD to implement Annotatable
* review issues
* fix interface as required by review
* Cleanup the webhook code.
- add more tests
- fix formatting
- fix logging and errors
- use shorthands
- some optimizations in types
- make code more Go'ey from C'ey.
* raise test coverage
* Webhook creates a patch for all fields generated by round tripping the JSON through Golang types.
* Add unit tests for InnerDefaultResource.
* Linter errors.
* PR comments - test changes
* t.Helper()
* PR comments.
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.
This enables us to make additive changes without breaking downgrades.
Unfortunate side effect is that we don't get a nice typo checker in the
webhook :(
* Change VerifyType to return an error instead of panicking
Signed-off-by: Vincent Demeester <vdemeest@redhat.com>
* Move the use of `VerifyType` in tests
Those calls to `duck.VerifyType` are done at runtime and thus could be
costly at program startup. Putting them under tests ensure we still
assert those types but during unit testing.
Signed-off-by: Vincent Demeester <vdemeest@redhat.com>
* 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.