Skip to content

Commit

Permalink
Split apart defaulting and validation webhook
Browse files Browse the repository at this point in the history
  • Loading branch information
mattmoor committed Nov 6, 2019
1 parent 37e66fc commit e56196e
Show file tree
Hide file tree
Showing 45 changed files with 615 additions and 2,016 deletions.
11 changes: 8 additions & 3 deletions Gopkg.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion Gopkg.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,10 @@ required = [
# Our master branch tracks knative/pkg master or a release.
[[override]]
name = "knative.dev/pkg"
branch = "master"
#TODO(mattmoor): DO NOT SUBMIT
source = "github.com/mattmoor/pkg-1"
revision = "3f9bcd4d73fb89a1976eed9d7a5c6dd023435e3f"
# branch = "master"

# TODO why is this overridden?
[[override]]
Expand Down
74 changes: 51 additions & 23 deletions cmd/webhook/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,30 @@ import (
"knative.dev/pkg/webhook"
"knative.dev/pkg/webhook/certificates"
"knative.dev/pkg/webhook/resourcesemantics"
"knative.dev/pkg/webhook/resourcesemantics/defaulting"
"knative.dev/pkg/webhook/resourcesemantics/validation"
)

func NewResourceAdmissionController(ctx context.Context, cmw configmap.Watcher) *controller.Impl {
var types = map[schema.GroupVersionKind]resourcesemantics.GenericCRD{
// For group eventing.knative.dev,
eventingv1alpha1.SchemeGroupVersion.WithKind("Broker"): &eventingv1alpha1.Broker{},
eventingv1alpha1.SchemeGroupVersion.WithKind("Trigger"): &eventingv1alpha1.Trigger{},
eventingv1alpha1.SchemeGroupVersion.WithKind("EventType"): &eventingv1alpha1.EventType{},

// For group messaging.knative.dev.
messagingv1alpha1.SchemeGroupVersion.WithKind("InMemoryChannel"): &messagingv1alpha1.InMemoryChannel{},
messagingv1alpha1.SchemeGroupVersion.WithKind("Sequence"): &messagingv1alpha1.Sequence{},
messagingv1alpha1.SchemeGroupVersion.WithKind("Parallel"): &messagingv1alpha1.Parallel{},
messagingv1alpha1.SchemeGroupVersion.WithKind("Channel"): &messagingv1alpha1.Channel{},
messagingv1alpha1.SchemeGroupVersion.WithKind("Subscription"): &messagingv1alpha1.Subscription{},

// For group sources.eventing.knative.dev
sourcesv1alpha1.SchemeGroupVersion.WithKind("ApiServerSource"): &sourcesv1alpha1.ApiServerSource{},
sourcesv1alpha1.SchemeGroupVersion.WithKind("ContainerSource"): &sourcesv1alpha1.ContainerSource{},
sourcesv1alpha1.SchemeGroupVersion.WithKind("CronJobSource"): &sourcesv1alpha1.CronJobSource{},
}

func NewDefaultingAdmissionController(ctx context.Context, cmw configmap.Watcher) *controller.Impl {
logger := logging.FromContext(ctx)

// Decorate contexts with the current state of the config.
Expand All @@ -56,33 +77,16 @@ func NewResourceAdmissionController(ctx context.Context, cmw configmap.Watcher)
eventingduckv1alpha1.ChannelDefaulterSingleton = chDefaulter
cmw.Watch(defaultchannel.ConfigMapName, chDefaulter.UpdateConfigMap)

return resourcesemantics.NewAdmissionController(ctx,
return defaulting.NewAdmissionController(ctx,

// Name of the resource webhook.
"webhook.eventing.knative.dev",
"defaulting.webhook.eventing.knative.dev",

// The path on which to serve the webhook.
"/",
"/defaulting",

// The resources to validate and default.
map[schema.GroupVersionKind]resourcesemantics.GenericCRD{
// For group eventing.knative.dev,
eventingv1alpha1.SchemeGroupVersion.WithKind("Broker"): &eventingv1alpha1.Broker{},
eventingv1alpha1.SchemeGroupVersion.WithKind("Trigger"): &eventingv1alpha1.Trigger{},
eventingv1alpha1.SchemeGroupVersion.WithKind("EventType"): &eventingv1alpha1.EventType{},

// For group messaging.knative.dev.
messagingv1alpha1.SchemeGroupVersion.WithKind("InMemoryChannel"): &messagingv1alpha1.InMemoryChannel{},
messagingv1alpha1.SchemeGroupVersion.WithKind("Sequence"): &messagingv1alpha1.Sequence{},
messagingv1alpha1.SchemeGroupVersion.WithKind("Parallel"): &messagingv1alpha1.Parallel{},
messagingv1alpha1.SchemeGroupVersion.WithKind("Channel"): &messagingv1alpha1.Channel{},
messagingv1alpha1.SchemeGroupVersion.WithKind("Subscription"): &messagingv1alpha1.Subscription{},

// For group sources.eventing.knative.dev
sourcesv1alpha1.SchemeGroupVersion.WithKind("ApiServerSource"): &sourcesv1alpha1.ApiServerSource{},
sourcesv1alpha1.SchemeGroupVersion.WithKind("ContainerSource"): &sourcesv1alpha1.ContainerSource{},
sourcesv1alpha1.SchemeGroupVersion.WithKind("CronJobSource"): &sourcesv1alpha1.CronJobSource{},
},
types,

// A function that infuses the context passed to Validate/SetDefaults with custom metadata.
ctxFunc,
Expand All @@ -92,6 +96,29 @@ func NewResourceAdmissionController(ctx context.Context, cmw configmap.Watcher)
)
}

func NewValidationAdmissionController(ctx context.Context, cmw configmap.Watcher) *controller.Impl {
return validation.NewAdmissionController(ctx,

// Name of the resource webhook.
"validation.webhook.eventing.knative.dev",

// The path on which to serve the webhook.
"/validation",

// The resources to validate and default.
types,

// A function that infuses the context passed to Validate/SetDefaults with custom metadata.
func(ctx context.Context) context.Context {
// return v1.WithUpgradeViaDefaulting(store.ToContext(ctx))
return ctx
},

// Whether to disallow unknown fields.
true,
)
}

func main() {
// Set up a signal context with our webhook options
ctx := webhook.WithOptions(signals.NewContext(), webhook.Options{
Expand All @@ -102,7 +129,8 @@ func main() {

sharedmain.MainWithContext(ctx, logconfig.WebhookName(),
certificates.NewController,
NewResourceAdmissionController,
NewDefaultingAdmissionController,
NewValidationAdmissionController,
// TODO(mattmoor): Support config validation in eventing.
)
}
20 changes: 18 additions & 2 deletions config/500-webhook-configuration.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
apiVersion: admissionregistration.k8s.io/v1beta1
kind: MutatingWebhookConfiguration
metadata:
name: webhook.eventing.knative.dev
name: defaulting.webhook.eventing.knative.dev
labels:
eventing.knative.dev/release: devel
webhooks:
Expand All @@ -26,7 +26,23 @@ webhooks:
name: eventing-webhook
namespace: knative-eventing
failurePolicy: Fail
name: webhook.eventing.knative.dev
name: defaulting.webhook.eventing.knative.dev
---
apiVersion: admissionregistration.k8s.io/v1beta1
kind: ValidatingWebhookConfiguration
metadata:
name: validation.webhook.eventing.knative.dev
labels:
eventing.knative.dev/release: devel
webhooks:
- admissionReviewVersions:
- v1beta1
clientConfig:
service:
name: eventing-webhook
namespace: knative-eventing
failurePolicy: Fail
name: validation.webhook.eventing.knative.dev
---
apiVersion: v1
kind: Secret
Expand Down
9 changes: 2 additions & 7 deletions pkg/apis/eventing/v1alpha1/eventtype_validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,16 +48,11 @@ func (ets *EventTypeSpec) Validate(ctx context.Context) *apis.FieldError {
return errs
}

func (et *EventType) CheckImmutableFields(ctx context.Context, og apis.Immutable) *apis.FieldError {
if og == nil {
func (et *EventType) CheckImmutableFields(ctx context.Context, original *EventType) *apis.FieldError {
if original == nil {
return nil
}

original, ok := og.(*EventType)
if !ok {
return &apis.FieldError{Message: "The provided original was not an EventType"}
}

// All but Description field immutable.
ignoreArguments := cmpopts.IgnoreFields(EventTypeSpec{}, "Description")
if diff, err := kmp.ShortDiff(original.Spec, et.Spec, ignoreArguments); err != nil {
Expand Down
17 changes: 2 additions & 15 deletions pkg/apis/eventing/v1alpha1/eventtype_validation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,8 @@ func TestEventTypeSpecValidation(t *testing.T) {
func TestEventTypeImmutableFields(t *testing.T) {
tests := []struct {
name string
current apis.Immutable
original apis.Immutable
current *EventType
original *EventType
want *apis.FieldError
}{{
name: "good (no change)",
Expand Down Expand Up @@ -133,19 +133,6 @@ func TestEventTypeImmutableFields(t *testing.T) {
},
original: nil,
want: nil,
}, {
name: "invalid type",
current: &EventType{
Spec: EventTypeSpec{
Type: "test-type",
Source: "test-source",
Broker: "test-broker",
},
},
original: &Trigger{},
want: &apis.FieldError{
Message: "The provided original was not an EventType",
},
}, {
name: "bad (broker change)",
current: &EventType{
Expand Down
9 changes: 2 additions & 7 deletions pkg/apis/eventing/v1alpha1/trigger_validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,16 +100,11 @@ func (ts *TriggerSpec) Validate(ctx context.Context) *apis.FieldError {
}

// CheckImmutableFields checks that any immutable fields were not changed.
func (t *Trigger) CheckImmutableFields(ctx context.Context, og apis.Immutable) *apis.FieldError {
if og == nil {
func (t *Trigger) CheckImmutableFields(ctx context.Context, original *Trigger) *apis.FieldError {
if original == nil {
return nil
}

original, ok := og.(*Trigger)
if !ok {
return &apis.FieldError{Message: "The provided original was not a Trigger"}
}

if diff, err := kmp.ShortDiff(original.Spec.Broker, t.Spec.Broker); err != nil {
return &apis.FieldError{
Message: "Failed to diff Trigger",
Expand Down
15 changes: 2 additions & 13 deletions pkg/apis/eventing/v1alpha1/trigger_validation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -438,8 +438,8 @@ func TestTriggerSpecValidation(t *testing.T) {
func TestTriggerImmutableFields(t *testing.T) {
tests := []struct {
name string
current apis.Immutable
original apis.Immutable
current *Trigger
original *Trigger
want *apis.FieldError
}{{
name: "good (no change)",
Expand All @@ -463,17 +463,6 @@ func TestTriggerImmutableFields(t *testing.T) {
},
original: nil,
want: nil,
}, {
name: "invalid type",
current: &Trigger{
Spec: TriggerSpec{
Broker: "broker",
},
},
original: &Broker{},
want: &apis.FieldError{
Message: "The provided original was not a Trigger",
},
}, {
name: "good (filter change)",
current: &Trigger{
Expand Down
9 changes: 2 additions & 7 deletions pkg/apis/messaging/v1alpha1/channel_validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,16 +67,11 @@ func isValidChannelTemplate(ct *eventingduck.ChannelTemplateSpec) *apis.FieldErr
return errs
}

func (c *Channel) CheckImmutableFields(ctx context.Context, og apis.Immutable) *apis.FieldError {
if og == nil {
func (c *Channel) CheckImmutableFields(ctx context.Context, original *Channel) *apis.FieldError {
if original == nil {
return nil
}

original, ok := og.(*Channel)
if !ok {
return &apis.FieldError{Message: "The provided original was not a Channel"}
}

ignoreArguments := cmpopts.IgnoreFields(ChannelSpec{}, "Subscribable")
if diff, err := kmp.ShortDiff(original.Spec, c.Spec, ignoreArguments); err != nil {
return &apis.FieldError{
Expand Down
4 changes: 2 additions & 2 deletions pkg/apis/messaging/v1alpha1/channel_validation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,8 +159,8 @@ func TestChannelValidation(t *testing.T) {
func TestChannelImmutableFields(t *testing.T) {
tests := []struct {
name string
current apis.Immutable
original apis.Immutable
current *Channel
original *Channel
want *apis.FieldError
}{{
name: "good (no change)",
Expand Down
1 change: 0 additions & 1 deletion vendor/knative.dev/pkg/Gopkg.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions vendor/knative.dev/pkg/RELEASING.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,13 @@ their own release branches, so to update the `knative/pkg` dependency we run:
dep ensure -update knative.dev/pkg
./hack/update-deps.sh
```

## Revert to Master

Post release, reverse the process. `Gopkg.toml` should look like:

```toml
[[override]]
name = "knative.dev/pkg"
branch = "master"
```
6 changes: 1 addition & 5 deletions vendor/knative.dev/pkg/apis/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,7 @@ type Convertible interface {
// Immutable indicates that a particular type has fields that should
// not change after creation.
// DEPRECATED: Use WithinUpdate / GetBaseline from within Validatable instead.
type Immutable interface {
// CheckImmutableFields checks that the current instance's immutable
// fields haven't changed from the provided original.
CheckImmutableFields(ctx context.Context, original Immutable) *FieldError
}
type Immutable interface{}

// Listable indicates that a particular type can be returned via the returned
// list type by the API server.
Expand Down
Loading

0 comments on commit e56196e

Please sign in to comment.