diff --git a/Gopkg.lock b/Gopkg.lock index 958d97db59a..5b50b3a3b33 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -310,7 +310,7 @@ [[projects]] branch = "master" - digest = "1:36968d4eb1d52090841ae868d7125d8ff10afabdea0d6b622c1f4a662f94be58" + digest = "1:849fc53918b4658b896a43881305d60afc0d6a51d87c0d5b065afd631415f1d4" name = "github.com/knative/test-infra" packages = ["."] pruneopts = "T" @@ -1041,8 +1041,10 @@ "github.com/knative/pkg/webhook", "github.com/knative/serving/pkg/apis/serving/v1alpha1", "github.com/knative/serving/pkg/client/clientset/versioned", + "github.com/knative/test-infra", "github.com/prometheus/client_golang/prometheus/promhttp", "go.uber.org/zap", + "go.uber.org/zap/zapcore", "golang.org/x/net/context", "golang.org/x/oauth2", "google.golang.org/grpc/codes", diff --git a/hack/update-codegen.sh b/hack/update-codegen.sh index ea164dfe467..9a177fae61e 100755 --- a/hack/update-codegen.sh +++ b/hack/update-codegen.sh @@ -28,7 +28,7 @@ CODEGEN_PKG=${CODEGEN_PKG:-$(cd ${REPO_ROOT_DIR}; ls -d -1 ./vendor/k8s.io/code- # instead of the $GOPATH directly. For normal projects this can be dropped. ${CODEGEN_PKG}/generate-groups.sh "deepcopy,client,informer,lister" \ github.com/knative/eventing/pkg/client github.com/knative/eventing/pkg/apis \ - "channels:v1alpha1 feeds:v1alpha1 flows:v1alpha1" \ + "channels:v1alpha1 feeds:v1alpha1 flows:v1alpha1 eventing:v1alpha1" \ --go-header-file ${REPO_ROOT_DIR}/hack/boilerplate/boilerplate.go.txt # Make sure our dependencies are up-to-date diff --git a/pkg/apis/eventing/register.go b/pkg/apis/eventing/register.go new file mode 100644 index 00000000000..49493ed5772 --- /dev/null +++ b/pkg/apis/eventing/register.go @@ -0,0 +1,21 @@ +/* +Copyright 2018 The Knative Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package eventing + +const ( + GroupName = "eventing.knative.dev" +) diff --git a/pkg/apis/eventing/v1alpha1/doc.go b/pkg/apis/eventing/v1alpha1/doc.go new file mode 100644 index 00000000000..b2c114bfe8a --- /dev/null +++ b/pkg/apis/eventing/v1alpha1/doc.go @@ -0,0 +1,16 @@ +/* +Copyright 2018 The Knative Authors +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +// +k8s:deepcopy-gen=package +// Package v1alpha1 is the v1alpha1 version of the API. +// +groupName=eventing.knative.dev +package v1alpha1 diff --git a/pkg/apis/eventing/v1alpha1/register.go b/pkg/apis/eventing/v1alpha1/register.go new file mode 100644 index 00000000000..3f24f758a88 --- /dev/null +++ b/pkg/apis/eventing/v1alpha1/register.go @@ -0,0 +1,53 @@ +/* +Copyright 2018 The Knative Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha1 + +import ( + "github.com/knative/eventing/pkg/apis/eventing" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +// SchemeGroupVersion is group version used to register these objects +var SchemeGroupVersion = schema.GroupVersion{Group: eventing.GroupName, Version: "v1alpha1"} + +// Kind takes an unqualified kind and returns back a Group qualified GroupKind +func Kind(kind string) schema.GroupKind { + return SchemeGroupVersion.WithKind(kind).GroupKind() +} + +// Resource takes an unqualified resource and returns a Group qualified GroupResource +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} + +var ( + SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) + AddToScheme = SchemeBuilder.AddToScheme +) + +// Adds the list of known types to Scheme. +func addKnownTypes(scheme *runtime.Scheme) error { + scheme.AddKnownTypes(SchemeGroupVersion, + &Subscription{}, + &SubscriptionList{}, + ) + metav1.AddToGroupVersion(scheme, SchemeGroupVersion) + return nil +} diff --git a/pkg/apis/eventing/v1alpha1/subscription_defaults.go b/pkg/apis/eventing/v1alpha1/subscription_defaults.go new file mode 100644 index 00000000000..ed8fdf5b16f --- /dev/null +++ b/pkg/apis/eventing/v1alpha1/subscription_defaults.go @@ -0,0 +1,25 @@ +/* +Copyright 2018 The Knative Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha1 + +func (s *Subscription) SetDefaults() { + s.Spec.SetDefaults() +} + +func (ss *SubscriptionSpec) SetDefaults() { + // TODO anything? +} diff --git a/pkg/apis/eventing/v1alpha1/subscription_types.go b/pkg/apis/eventing/v1alpha1/subscription_types.go new file mode 100644 index 00000000000..28067323807 --- /dev/null +++ b/pkg/apis/eventing/v1alpha1/subscription_types.go @@ -0,0 +1,210 @@ +/* + * Copyright 2018 The Knative Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package v1alpha1 + +import ( + "encoding/json" + + "github.com/knative/pkg/apis" + "github.com/knative/pkg/webhook" + "k8s.io/api/core/v1" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" +) + +// +genclient +// +genclient:noStatus +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +k8s:defaulter-gen=true + +// Subscription routes events received on a Channel to a DNS name and +// corresponds to the subscriptions.channels.knative.dev CRD. +type Subscription struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata"` + Spec SubscriptionSpec `json:"spec"` + Status SubscriptionStatus `json:"status,omitempty"` +} + +// Check that Subscription can be validated, can be defaulted, and has immutable fields. +var _ apis.Validatable = (*Subscription)(nil) +var _ apis.Defaultable = (*Subscription)(nil) +var _ apis.Immutable = (*Subscription)(nil) +var _ runtime.Object = (*Subscription)(nil) +var _ webhook.GenericCRD = (*Subscription)(nil) + +// SubscriptionSpec specifies the Channel for incoming events, a Call target for +// processing those events and where to put the result of the processing. Only +// From (where the events are coming from) is always required. You can optionally +// only Process the events (results in no output events) by leaving out the Result. +// You can also perform an identity transformation on the invoming events by leaving +// out the Call and only specifying Result. +// +// The following are all valid specifications: +// from --[call]--> result +// Sink, no outgoing events: +// from -- call +// no-op function (identity transformation): +// from --> result +type SubscriptionSpec struct { + // TODO: Generation used to not work correctly with CRD. They were scrubbed + // by the APIserver (https://github.com/kubernetes/kubernetes/issues/58778) + // So, we add Generation here. Once the above bug gets rolled out to production + // clusters, remove this and use ObjectMeta.Generation instead. + // +optional + Generation int64 `json:"generation,omitempty"` + + // Reference to an object that will be used to create the subscription + // for receiving events. The object must have spec.subscriptions + // list which will then be modified accordingly. + // + // This object must fulfill the Subscribable contract. + // + // You can specify only the following fields of the ObjectReference: + // - Kind + // - APIVersion + // - Name + // Currently Kind must be "Channel" and + // APIVersion must be "channels.knative.dev/v1alpha1" + // + // This field is immutable. We have no good answer on what happens to + // the events that are currently in the channel being consumed from + // and what the semantics there should be. For now, you can always + // delete the Subscription and recreate it to point to a different + // channel, giving the user more control over what semantics should + // be used (drain the channel first, possibly have events dropped, + // etc.) + From corev1.ObjectReference `json:"from"` + + // Call is reference to (optional) function for processing events. + // Events from the From channel will be delivered here and replies + // are sent to a channel as specified by the Result. + // +optional + Call *Callable `json:"call,omitempty"` + + // Result specifies (optionally) how to handle events returned from + // the Call target. + // +optional + Result *ResultStrategy `json:"result,omitempty"` +} + +// Callable specifies the reference to an object that's expected to +// provide the resolved target of the action. +// Currently we inspect the objects Status and see if there's a predefined +// Status field that we will then use to dispatch events to be processed by +// the target. Currently must resolve to a k8s service or Istio virtual +// service. +// Note that in the future we should try to utilize subresources (/resolve ?) to +// make this cleaner, but CRDs do not support subresources yet, so we need +// to rely on a specified Status field today. By relying on this behaviour +// we can utilize a dynamic client instead of having to understand all +// kinds of different types of objects. As long as they adhere to this +// particular contract, they can be used as a Target. +// +// This ensures that we can support external targets and for ease of use +// we also allow for an URI to be specified. +// There of course is also a requirement for the resolved Callable to +// behave properly at the data plane level. +// TODO: Add a pointer to a real spec for this. +// For now, this means: Receive an event payload, and respond with one of: +// success and an optional response event, or failure. +// Delivery failures may be retried by the from Channel +type Callable struct { + // Only one of these can be specified + + // Reference to an object that will be used to find the target + // endpoint. + // For example, this could be a reference to a Route resource + // or a Knative Service resource. + // TODO: Specify the required fields the target object must + // have in the status. + // You can specify only the following fields of the ObjectReference: + // - Kind + // - APIVersion + // - Name + // +optional + Target *corev1.ObjectReference `json:"target,omitempty"` + + // Reference to a 'known' endpoint where no resolving is done. + // http://k8s-service for example + // http://myexternalhandler.example.com/foo/bar + // +optional + TargetURI *string `json:"targetURI,omitempty"` +} + +type ResultStrategy struct { + // This object must fulfill the Sinkable contract. + // + // TODO: Specify the required fields the target object must + // have in the status. + // You can specify only the following fields of the ObjectReference: + // - Kind + // - APIVersion + // - Name + // +optional + Target *corev1.ObjectReference `json:"target,omitempty"` +} + +type SubscriptionConditionType string + +const ( + // SubscriptionReady is when the From,Call and Result have been reconciled successfully. + SubscriptionReady SubscriptionConditionType = "Ready" +) + +// SubscriptionCondition describes the state of a subscription at a point in time. +type SubscriptionCondition struct { + // Type of subscription condition. + Type SubscriptionConditionType `json:"type"` + // Status of the condition, one of True, False, Unknown. + Status v1.ConditionStatus `json:"status"` + // The reason for the condition's last transition. + Reason string `json:"reason,omitempty"` + // A human readable message indicating details about the transition. + Message string `json:"message,omitempty"` +} + +// SubscriptionStatus (computed) for a subscription +type SubscriptionStatus struct { + // Represents the latest available observations of a subscription's current state. + // +patchMergeKey=type + // +patchStrategy=merge + Conditions []SubscriptionCondition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"` +} + +func (ss *SubscriptionStatus) GetCondition(t SubscriptionConditionType) *SubscriptionCondition { + for _, cond := range ss.Conditions { + if cond.Type == t { + return &cond + } + } + return nil +} + +func (s *Subscription) GetSpecJSON() ([]byte, error) { + return json.Marshal(s.Spec) +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// SubscriptionList returned in list operations +type SubscriptionList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata"` + Items []Subscription `json:"items"` +} diff --git a/pkg/apis/eventing/v1alpha1/subscription_validation.go b/pkg/apis/eventing/v1alpha1/subscription_validation.go new file mode 100644 index 00000000000..6327f25ea9d --- /dev/null +++ b/pkg/apis/eventing/v1alpha1/subscription_validation.go @@ -0,0 +1,202 @@ +/* +Copyright 2018 The Knative Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha1 + +import ( + "reflect" + // "strings" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/knative/pkg/apis" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/equality" +) + +func (s *Subscription) Validate() *apis.FieldError { + return s.Spec.Validate().ViaField("spec") +} + +// We require always From +// Also at least one of 'call' and 'result' must be defined (non-nill and non-empty) +func (ss *SubscriptionSpec) Validate() *apis.FieldError { + if isFromEmpty(ss.From) { + fe := apis.ErrMissingField("from") + fe.Details = "the Subscription must reference a from channel" + return fe + } + + if fe := isValidFrom(ss.From); fe != nil { + return fe.ViaField("from") + } + + missingCallable := isCallableNilOrEmpty(ss.Call) + missingResultStrategy := isResultStrategyNilOrEmpty(ss.Result) + if missingCallable && missingResultStrategy { + fe := apis.ErrMissingField("result", "call") + fe.Details = "the Subscription must reference at least one of (result channel or a call)" + return fe + } + + if !missingCallable { + if fe := isValidCallable(*ss.Call); fe != nil { + return fe.ViaField("call") + } + } + + if !missingResultStrategy { + if fe := isValidResultStrategy(ss.Result); fe != nil { + return fe.ViaField("result") + } + } + + return nil +} + +func isCallableNilOrEmpty(c *Callable) bool { + return c == nil || equality.Semantic.DeepEqual(c, &Callable{}) || + (equality.Semantic.DeepEqual(c.Target, &corev1.ObjectReference{}) && c.TargetURI == nil) + +} + +func isValidCallable(c Callable) *apis.FieldError { + if c.TargetURI != nil && *c.TargetURI != "" && c.Target != nil && !equality.Semantic.DeepEqual(c.Target, &corev1.ObjectReference{}) { + return apis.ErrMultipleOneOf("target", "targetURI") + } + + // If Target given, check the fields. + if c.Target != nil && !equality.Semantic.DeepEqual(c.Target, &corev1.ObjectReference{}) { + fe := isValidObjectReference(*c.Target) + if fe != nil { + return fe.ViaField("target") + } + } + return nil +} + +func isFromEmpty(f corev1.ObjectReference) bool { + return equality.Semantic.DeepEqual(f, corev1.ObjectReference{}) +} + +// Valid from only contains the following fields: +// - Kind == 'Channel' +// - APIVersion == 'channels.knative.dev/v1alpha1' +// - Name == not empty +func isValidFrom(f corev1.ObjectReference) *apis.FieldError { + fe := isValidObjectReference(f) + if fe != nil { + return fe + } + if f.Kind != "Channel" { + fe := apis.ErrInvalidValue(f.Kind, "kind") + fe.Paths = []string{"kind"} + fe.Details = "only 'Channel' kind is allowed" + return fe + } + if f.APIVersion != "channels.knative.dev/v1alpha1" { + fe := apis.ErrInvalidValue(f.APIVersion, "apiVersion") + fe.Details = "only channels.knative.dev/v1alpha1 is allowed for apiVersion" + return fe + } + return nil +} + +func isResultStrategyNilOrEmpty(r *ResultStrategy) bool { + return r == nil || equality.Semantic.DeepEqual(r, &ResultStrategy{}) || equality.Semantic.DeepEqual(r.Target, &corev1.ObjectReference{}) +} + +func isValidResultStrategy(r *ResultStrategy) *apis.FieldError { + fe := isValidObjectReference(*r.Target) + if fe != nil { + return fe.ViaField("target") + } + return nil + +} + +func isValidObjectReference(f corev1.ObjectReference) *apis.FieldError { + fe := checkRequiredFields(f) + if fe != nil { + return fe + } + return checkDisallowedFields(f) +} + +// Check the corev1.ObjectReference to make sure it has the required fields. They +// are not checked for anything more except that they are set. +func checkRequiredFields(f corev1.ObjectReference) *apis.FieldError { + if f.Name == "" { + return apis.ErrMissingField("name") + } + if f.APIVersion == "" { + return apis.ErrMissingField("apiVersion") + } + if f.Kind == "" { + return apis.ErrMissingField("kind") + } + return nil +} + +// Check the corev1.ObjectReference to make sure it only has the following fields set: +// Name, Kind, APIVersion +// If any other fields are set and is not the Zero value, returns an apis.FieldError +// with the fieldpaths for all those fields. +func checkDisallowedFields(f corev1.ObjectReference) *apis.FieldError { + disallowedFields := []string{} + // See if there are any fields that have been set that should not be. + // TODO: Hoist this kind of stuff into pkg repository. + s := reflect.ValueOf(f) + typeOf := s.Type() + for i := 0; i < s.NumField(); i++ { + field := s.Field(i) + fieldName := typeOf.Field(i).Name + if fieldName == "Name" || fieldName == "Kind" || fieldName == "APIVersion" { + continue + } + if !cmp.Equal(field.Interface(), reflect.Zero(field.Type()).Interface()) { + disallowedFields = append(disallowedFields, fieldName) + } + } + if len(disallowedFields) > 0 { + fe := apis.ErrDisallowedFields(disallowedFields...) + fe.Details = "only name, apiVersion and kind are supported fields" + return fe + } + return nil + +} + +func (current *Subscription) CheckImmutableFields(og apis.Immutable) *apis.FieldError { + original, ok := og.(*Subscription) + if !ok { + return &apis.FieldError{Message: "The provided original was not a Subscription"} + } + if original == nil { + return nil + } + + // Only Call and Result are mutable. + ignoreArguments := cmpopts.IgnoreFields(SubscriptionSpec{}, "Call", "Result") + if diff := cmp.Diff(original.Spec, current.Spec, ignoreArguments); diff != "" { + return &apis.FieldError{ + Message: "Immutable fields changed (-old +new)", + Paths: []string{"spec"}, + Details: diff, + } + } + return nil +} diff --git a/pkg/apis/eventing/v1alpha1/subscription_validation_test.go b/pkg/apis/eventing/v1alpha1/subscription_validation_test.go new file mode 100644 index 00000000000..e83e9c27f47 --- /dev/null +++ b/pkg/apis/eventing/v1alpha1/subscription_validation_test.go @@ -0,0 +1,700 @@ +/* +Copyright 2018 The Knative Authors. All Rights Reserved. +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha1 + +import ( + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/knative/pkg/apis" + corev1 "k8s.io/api/core/v1" +) + +const ( + channelKind = "Channel" + channelAPIVersion = "channels.knative.dev/v1alpha1" + routeKind = "Route" + routeAPIVersion = "serving.knative.dev/v1alpha1" + fromChannelName = "fromChannel" + resultChannelName = "toChannel" + callName = "call" +) + +func getValidFromRef() corev1.ObjectReference { + return corev1.ObjectReference{ + Name: fromChannelName, + Kind: channelKind, + APIVersion: channelAPIVersion, + } +} + +func getValidResultRef() *ResultStrategy { + return &ResultStrategy{ + Target: &corev1.ObjectReference{ + Name: resultChannelName, + Kind: channelKind, + APIVersion: channelAPIVersion, + }, + } +} + +func getValidCall() *Callable { + return &Callable{ + Target: &corev1.ObjectReference{ + Name: callName, + Kind: routeKind, + APIVersion: routeAPIVersion, + }, + } +} + +type DummyImmutableType struct{} + +func (d *DummyImmutableType) CheckImmutableFields(og apis.Immutable) *apis.FieldError { + return nil +} + +func TestSubscriptionValidation(t *testing.T) { + name := "empty from" + c := &Subscription{ + Spec: SubscriptionSpec{ + From: corev1.ObjectReference{}, + }, + } + want := &apis.FieldError{ + Paths: []string{"spec.from"}, + Message: "missing field(s)", + Details: "the Subscription must reference a from channel", + } + + t.Run(name, func(t *testing.T) { + got := c.Validate() + if diff := cmp.Diff(want, got); diff != "" { + t.Errorf("Subscription.Validate (-want, +got) = %v", diff) + } + }) + +} + +func TestSubscriptionSpecValidation(t *testing.T) { + tests := []struct { + name string + c *SubscriptionSpec + want *apis.FieldError + }{{ + name: "valid", + c: &SubscriptionSpec{ + From: getValidFromRef(), + Call: getValidCall(), + }, + want: nil, + }, { + name: "empty From", + c: &SubscriptionSpec{ + From: corev1.ObjectReference{}, + }, + want: func() *apis.FieldError { + fe := apis.ErrMissingField("from") + fe.Details = "the Subscription must reference a from channel" + return fe + }(), + }, { + name: "missing name in From", + c: &SubscriptionSpec{ + From: corev1.ObjectReference{ + Kind: channelKind, + APIVersion: channelAPIVersion, + }, + }, + want: func() *apis.FieldError { + fe := apis.ErrMissingField("from.name") + return fe + }(), + }, { + name: "missing Call and Result", + c: &SubscriptionSpec{ + From: getValidFromRef(), + }, + want: func() *apis.FieldError { + fe := apis.ErrMissingField("result", "call") + fe.Details = "the Subscription must reference at least one of (result channel or a call)" + return fe + }(), + }, { + name: "empty Call and Result", + c: &SubscriptionSpec{ + From: getValidFromRef(), + Call: &Callable{}, + Result: &ResultStrategy{}, + }, + want: func() *apis.FieldError { + fe := apis.ErrMissingField("result", "call") + fe.Details = "the Subscription must reference at least one of (result channel or a call)" + return fe + }(), + }, { + name: "missing Result", + c: &SubscriptionSpec{ + From: getValidFromRef(), + Call: getValidCall(), + }, + want: nil, + }, { + name: "empty Result", + c: &SubscriptionSpec{ + From: getValidFromRef(), + Call: getValidCall(), + Result: &ResultStrategy{}, + }, + want: nil, + }, { + name: "missing Call", + c: &SubscriptionSpec{ + From: getValidFromRef(), + Result: getValidResultRef(), + }, + want: nil, + }, { + name: "empty Call", + c: &SubscriptionSpec{ + From: getValidFromRef(), + Call: &Callable{}, + Result: getValidResultRef(), + }, + want: nil, + }, { + name: "empty", + c: &SubscriptionSpec{}, + want: func() *apis.FieldError { + fe := apis.ErrMissingField("from") + fe.Details = "the Subscription must reference a from channel" + return fe + }(), + }, { + name: "missing name in Call.Target", + c: &SubscriptionSpec{ + From: getValidFromRef(), + Call: &Callable{ + Target: &corev1.ObjectReference{ + Kind: channelKind, + APIVersion: channelAPIVersion, + }, + }, + }, + want: func() *apis.FieldError { + fe := apis.ErrMissingField("call.target.name") + return fe + }(), + }, { + name: "missing name in Result.Target", + c: &SubscriptionSpec{ + From: getValidFromRef(), + Result: &ResultStrategy{ + Target: &corev1.ObjectReference{ + Kind: channelKind, + APIVersion: channelAPIVersion, + }, + }, + }, + want: func() *apis.FieldError { + fe := apis.ErrMissingField("result.target.name") + return fe + }(), + }} + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + got := test.c.Validate() + if diff := cmp.Diff(test.want, got); diff != "" { + t.Errorf("validateFrom (-want, +got) = %v", diff) + } + }) + } +} + +func TestSubscriptionImmutable(t *testing.T) { + newFrom := getValidFromRef() + newFrom.Name = "newFromChannel" + + newCall := getValidCall() + newCall.Target.Name = "newCall" + + newResult := getValidResultRef() + newResult.Target.Name = "newResultChannel" + + tests := []struct { + name string + c *Subscription + og *Subscription + want *apis.FieldError + }{{ + name: "valid", + c: &Subscription{ + Spec: SubscriptionSpec{ + From: getValidFromRef(), + }, + }, + og: &Subscription{ + Spec: SubscriptionSpec{ + From: getValidFromRef(), + }, + }, + want: nil, + }, { + name: "new nil is ok", + c: &Subscription{ + Spec: SubscriptionSpec{ + From: getValidFromRef(), + Call: getValidCall(), + }, + }, + og: nil, + want: nil, + }, { + name: "valid, new Call", + c: &Subscription{ + Spec: SubscriptionSpec{ + From: getValidFromRef(), + Call: getValidCall(), + }, + }, + og: &Subscription{ + Spec: SubscriptionSpec{ + From: getValidFromRef(), + Call: newCall, + }, + }, + want: nil, + }, { + name: "valid, new Result", + c: &Subscription{ + Spec: SubscriptionSpec{ + From: getValidFromRef(), + Result: getValidResultRef(), + }, + }, + og: &Subscription{ + Spec: SubscriptionSpec{ + From: getValidFromRef(), + Result: newResult, + }, + }, + want: nil, + }, { + name: "valid, have Result, remove and replace with Call", + c: &Subscription{ + Spec: SubscriptionSpec{ + From: getValidFromRef(), + Result: getValidResultRef(), + }, + }, + og: &Subscription{ + Spec: SubscriptionSpec{ + From: getValidFromRef(), + Call: getValidCall(), + }, + }, + want: nil, + }, { + name: "valid, have Call, remove and replace with Result", + c: &Subscription{ + Spec: SubscriptionSpec{ + From: getValidFromRef(), + Call: getValidCall(), + }, + }, + og: &Subscription{ + Spec: SubscriptionSpec{ + From: getValidFromRef(), + Result: getValidResultRef(), + }, + }, + want: nil, + }, { + name: "From changed", + c: &Subscription{ + Spec: SubscriptionSpec{ + From: getValidFromRef(), + }, + }, + og: &Subscription{ + Spec: SubscriptionSpec{ + From: newFrom, + }, + }, + want: &apis.FieldError{ + Message: "Immutable fields changed (-old +new)", + Paths: []string{"spec"}, + Details: `{v1alpha1.SubscriptionSpec}.From.Name: + -: "newFromChannel" + +: "fromChannel" +`, + }, + }} + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + got := test.c.CheckImmutableFields(test.og) + if diff := cmp.Diff(test.want, got); diff != "" { + t.Errorf("CheckImmutableFields (-want, +got) = %v", diff) + } + }) + } +} + +func TestInvalidImmutableType(t *testing.T) { + name := "invalid type" + c := &Subscription{ + Spec: SubscriptionSpec{ + From: getValidFromRef(), + Call: getValidCall(), + }, + } + og := &DummyImmutableType{} + want := &apis.FieldError{ + Message: "The provided original was not a Subscription", + } + t.Run(name, func(t *testing.T) { + got := c.CheckImmutableFields(og) + if diff := cmp.Diff(want, got); diff != "" { + t.Errorf("CheckImmutableFields (-want, +got) = %v", diff) + } + }) +} + +func TestValidFrom(t *testing.T) { + tests := []struct { + name string + c corev1.ObjectReference + want *apis.FieldError + }{{ + name: "valid", + c: corev1.ObjectReference{ + Name: fromChannelName, + APIVersion: channelAPIVersion, + Kind: channelKind, + }, + want: nil, + }, { + name: "missing name", + c: corev1.ObjectReference{ + APIVersion: channelAPIVersion, + Kind: channelKind, + }, + want: func() *apis.FieldError { + fe := apis.ErrMissingField("name") + return fe + }(), + }, { + name: "missing apiVersion", + c: corev1.ObjectReference{ + Name: fromChannelName, + Kind: channelKind, + }, + want: func() *apis.FieldError { + fe := apis.ErrMissingField("apiVersion") + return fe + }(), + }, { + name: "missing kind", + c: corev1.ObjectReference{ + Name: fromChannelName, + APIVersion: channelAPIVersion, + }, + want: func() *apis.FieldError { + fe := apis.ErrMissingField("kind") + return fe + }(), + }, { + name: "invalid kind", + c: corev1.ObjectReference{ + Name: fromChannelName, + APIVersion: channelAPIVersion, + Kind: "subscription", + }, + want: func() *apis.FieldError { + fe := apis.ErrInvalidValue("subscription", "kind") + fe.Details = "only 'Channel' kind is allowed" + return fe + }(), + }, { + name: "invalid apiVersion", + c: corev1.ObjectReference{ + Name: fromChannelName, + APIVersion: "wrongapiversion", + Kind: channelKind, + }, + want: func() *apis.FieldError { + fe := apis.ErrInvalidValue("wrongapiversion", "apiVersion") + fe.Details = "only channels.knative.dev/v1alpha1 is allowed for apiVersion" + return fe + }(), + }, { + name: "extra field, namespace", + c: corev1.ObjectReference{ + Name: fromChannelName, + APIVersion: channelAPIVersion, + Kind: channelKind, + Namespace: "secretnamespace", + }, + want: func() *apis.FieldError { + fe := apis.ErrDisallowedFields("Namespace") + fe.Details = "only name, apiVersion and kind are supported fields" + return fe + }(), + }, { + name: "extra field, namespace and resourceVersion", + c: corev1.ObjectReference{ + Name: fromChannelName, + APIVersion: channelAPIVersion, + Kind: channelKind, + Namespace: "secretnamespace", + ResourceVersion: "myresourceversion", + }, + want: func() *apis.FieldError { + fe := apis.ErrDisallowedFields("Namespace", "ResourceVersion") + fe.Details = "only name, apiVersion and kind are supported fields" + return fe + }(), + }, { + // Make sure that if an empty field for namespace is given, it's treated as not there. + name: "valid extra field, namespace empty", + c: corev1.ObjectReference{ + Name: fromChannelName, + APIVersion: channelAPIVersion, + Kind: channelKind, + Namespace: "", + }, + want: nil, + }} + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + got := isValidFrom(test.c) + if diff := cmp.Diff(test.want, got); diff != "" { + t.Errorf("isValidFrom (-want, +got) = %v", diff) + } + }) + } +} + +func TestValidCallable(t *testing.T) { + targetURI := "http://example.com" + tests := []struct { + name string + c Callable + want *apis.FieldError + }{{ + name: "valid target", + c: *getValidCall(), + want: nil, + }, { + name: "valid targetURI", + c: Callable{ + TargetURI: &targetURI, + }, + want: nil, + }, { + name: "both target and targetURI given", + c: Callable{ + Target: &corev1.ObjectReference{ + APIVersion: channelAPIVersion, + Kind: channelKind, + }, + TargetURI: &targetURI, + }, + want: func() *apis.FieldError { + fe := apis.ErrMultipleOneOf("target", "targetURI") + return fe + }(), + }, { + name: "missing name in target", + c: Callable{ + Target: &corev1.ObjectReference{ + APIVersion: channelAPIVersion, + Kind: channelKind, + }, + }, + want: func() *apis.FieldError { + fe := apis.ErrMissingField("target.name") + return fe + }(), + }, { + name: "missing apiVersion in target", + c: Callable{ + Target: &corev1.ObjectReference{ + Name: fromChannelName, + Kind: channelKind, + }, + }, + want: func() *apis.FieldError { + fe := apis.ErrMissingField("target.apiVersion") + return fe + }(), + }, { + name: "missing kind in target", + c: Callable{ + Target: &corev1.ObjectReference{ + Name: fromChannelName, + APIVersion: channelAPIVersion, + }, + }, + want: func() *apis.FieldError { + fe := apis.ErrMissingField("target.kind") + return fe + }(), + }, { + name: "extra field, namespace", + c: Callable{ + Target: &corev1.ObjectReference{ + Name: fromChannelName, + APIVersion: channelAPIVersion, + Kind: channelKind, + Namespace: "secretnamespace", + }, + }, + want: func() *apis.FieldError { + fe := apis.ErrDisallowedFields("target.Namespace") + fe.Details = "only name, apiVersion and kind are supported fields" + return fe + }(), + }, { + // Make sure that if an empty field for namespace is given, it's treated as not there. + name: "valid extra field, namespace empty", + c: Callable{ + Target: &corev1.ObjectReference{ + Name: fromChannelName, + APIVersion: channelAPIVersion, + Kind: channelKind, + Namespace: "", + }, + }, + want: nil, + }} + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + got := isValidCallable(test.c) + if diff := cmp.Diff(test.want, got); diff != "" { + t.Errorf("isValidFrom (-want, +got) = %v", diff) + } + }) + } +} + +func TestValidResultStrategy(t *testing.T) { + targetURI := "http://example.com" + tests := []struct { + name string + c Callable + want *apis.FieldError + }{{ + name: "valid target", + c: *getValidCall(), + want: nil, + }, { + name: "valid targetURI", + c: Callable{ + TargetURI: &targetURI, + }, + want: nil, + }, { + name: "both target and targetURI given", + c: Callable{ + Target: &corev1.ObjectReference{ + APIVersion: channelAPIVersion, + Kind: channelKind, + }, + TargetURI: &targetURI, + }, + want: func() *apis.FieldError { + fe := apis.ErrMultipleOneOf("target", "targetURI") + return fe + }(), + }, { + name: "missing name in target", + c: Callable{ + Target: &corev1.ObjectReference{ + APIVersion: channelAPIVersion, + Kind: channelKind, + }, + }, + want: func() *apis.FieldError { + fe := apis.ErrMissingField("target.name") + return fe + }(), + }, { + name: "missing apiVersion in target", + c: Callable{ + Target: &corev1.ObjectReference{ + Name: fromChannelName, + Kind: channelKind, + }, + }, + want: func() *apis.FieldError { + fe := apis.ErrMissingField("target.apiVersion") + return fe + }(), + }, { + name: "missing kind in target", + c: Callable{ + Target: &corev1.ObjectReference{ + Name: fromChannelName, + APIVersion: channelAPIVersion, + }, + }, + want: func() *apis.FieldError { + fe := apis.ErrMissingField("target.kind") + return fe + }(), + }, { + name: "extra field, namespace", + c: Callable{ + Target: &corev1.ObjectReference{ + Name: fromChannelName, + APIVersion: channelAPIVersion, + Kind: channelKind, + Namespace: "secretnamespace", + }, + }, + want: func() *apis.FieldError { + fe := apis.ErrDisallowedFields("target.Namespace") + fe.Details = "only name, apiVersion and kind are supported fields" + return fe + }(), + }, { + // Make sure that if an empty field for namespace is given, it's treated as not there. + name: "valid extra field, namespace empty", + c: Callable{ + Target: &corev1.ObjectReference{ + Name: fromChannelName, + APIVersion: channelAPIVersion, + Kind: channelKind, + Namespace: "", + }, + }, + want: nil, + }} + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + got := isValidCallable(test.c) + if diff := cmp.Diff(test.want, got); diff != "" { + t.Errorf("isValidFrom (-want, +got) = %v", diff) + } + }) + } +} diff --git a/pkg/apis/eventing/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/eventing/v1alpha1/zz_generated.deepcopy.go new file mode 100644 index 00000000000..a3678bad294 --- /dev/null +++ b/pkg/apis/eventing/v1alpha1/zz_generated.deepcopy.go @@ -0,0 +1,218 @@ +// +build !ignore_autogenerated + +/* +Copyright 2018 The Knative Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by deepcopy-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + v1 "k8s.io/api/core/v1" + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Callable) DeepCopyInto(out *Callable) { + *out = *in + if in.Target != nil { + in, out := &in.Target, &out.Target + if *in == nil { + *out = nil + } else { + *out = new(v1.ObjectReference) + **out = **in + } + } + if in.TargetURI != nil { + in, out := &in.TargetURI, &out.TargetURI + if *in == nil { + *out = nil + } else { + *out = new(string) + **out = **in + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Callable. +func (in *Callable) DeepCopy() *Callable { + if in == nil { + return nil + } + out := new(Callable) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ResultStrategy) DeepCopyInto(out *ResultStrategy) { + *out = *in + if in.Target != nil { + in, out := &in.Target, &out.Target + if *in == nil { + *out = nil + } else { + *out = new(v1.ObjectReference) + **out = **in + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResultStrategy. +func (in *ResultStrategy) DeepCopy() *ResultStrategy { + if in == nil { + return nil + } + out := new(ResultStrategy) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Subscription) DeepCopyInto(out *Subscription) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Subscription. +func (in *Subscription) DeepCopy() *Subscription { + if in == nil { + return nil + } + out := new(Subscription) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Subscription) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SubscriptionCondition) DeepCopyInto(out *SubscriptionCondition) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SubscriptionCondition. +func (in *SubscriptionCondition) DeepCopy() *SubscriptionCondition { + if in == nil { + return nil + } + out := new(SubscriptionCondition) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SubscriptionList) DeepCopyInto(out *SubscriptionList) { + *out = *in + out.TypeMeta = in.TypeMeta + out.ListMeta = in.ListMeta + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Subscription, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SubscriptionList. +func (in *SubscriptionList) DeepCopy() *SubscriptionList { + if in == nil { + return nil + } + out := new(SubscriptionList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *SubscriptionList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SubscriptionSpec) DeepCopyInto(out *SubscriptionSpec) { + *out = *in + out.From = in.From + if in.Call != nil { + in, out := &in.Call, &out.Call + if *in == nil { + *out = nil + } else { + *out = new(Callable) + (*in).DeepCopyInto(*out) + } + } + if in.Result != nil { + in, out := &in.Result, &out.Result + if *in == nil { + *out = nil + } else { + *out = new(ResultStrategy) + (*in).DeepCopyInto(*out) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SubscriptionSpec. +func (in *SubscriptionSpec) DeepCopy() *SubscriptionSpec { + if in == nil { + return nil + } + out := new(SubscriptionSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SubscriptionStatus) DeepCopyInto(out *SubscriptionStatus) { + *out = *in + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]SubscriptionCondition, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SubscriptionStatus. +func (in *SubscriptionStatus) DeepCopy() *SubscriptionStatus { + if in == nil { + return nil + } + out := new(SubscriptionStatus) + in.DeepCopyInto(out) + return out +} diff --git a/pkg/client/clientset/versioned/clientset.go b/pkg/client/clientset/versioned/clientset.go index 2c1872f405a..c9df07b37da 100644 --- a/pkg/client/clientset/versioned/clientset.go +++ b/pkg/client/clientset/versioned/clientset.go @@ -20,6 +20,7 @@ package versioned import ( channelsv1alpha1 "github.com/knative/eventing/pkg/client/clientset/versioned/typed/channels/v1alpha1" + eventingv1alpha1 "github.com/knative/eventing/pkg/client/clientset/versioned/typed/eventing/v1alpha1" feedsv1alpha1 "github.com/knative/eventing/pkg/client/clientset/versioned/typed/feeds/v1alpha1" flowsv1alpha1 "github.com/knative/eventing/pkg/client/clientset/versioned/typed/flows/v1alpha1" discovery "k8s.io/client-go/discovery" @@ -32,6 +33,9 @@ type Interface interface { ChannelsV1alpha1() channelsv1alpha1.ChannelsV1alpha1Interface // Deprecated: please explicitly pick a version if possible. Channels() channelsv1alpha1.ChannelsV1alpha1Interface + EventingV1alpha1() eventingv1alpha1.EventingV1alpha1Interface + // Deprecated: please explicitly pick a version if possible. + Eventing() eventingv1alpha1.EventingV1alpha1Interface FeedsV1alpha1() feedsv1alpha1.FeedsV1alpha1Interface // Deprecated: please explicitly pick a version if possible. Feeds() feedsv1alpha1.FeedsV1alpha1Interface @@ -45,6 +49,7 @@ type Interface interface { type Clientset struct { *discovery.DiscoveryClient channelsV1alpha1 *channelsv1alpha1.ChannelsV1alpha1Client + eventingV1alpha1 *eventingv1alpha1.EventingV1alpha1Client feedsV1alpha1 *feedsv1alpha1.FeedsV1alpha1Client flowsV1alpha1 *flowsv1alpha1.FlowsV1alpha1Client } @@ -60,6 +65,17 @@ func (c *Clientset) Channels() channelsv1alpha1.ChannelsV1alpha1Interface { return c.channelsV1alpha1 } +// EventingV1alpha1 retrieves the EventingV1alpha1Client +func (c *Clientset) EventingV1alpha1() eventingv1alpha1.EventingV1alpha1Interface { + return c.eventingV1alpha1 +} + +// Deprecated: Eventing retrieves the default version of EventingClient. +// Please explicitly pick a version. +func (c *Clientset) Eventing() eventingv1alpha1.EventingV1alpha1Interface { + return c.eventingV1alpha1 +} + // FeedsV1alpha1 retrieves the FeedsV1alpha1Client func (c *Clientset) FeedsV1alpha1() feedsv1alpha1.FeedsV1alpha1Interface { return c.feedsV1alpha1 @@ -102,6 +118,10 @@ func NewForConfig(c *rest.Config) (*Clientset, error) { if err != nil { return nil, err } + cs.eventingV1alpha1, err = eventingv1alpha1.NewForConfig(&configShallowCopy) + if err != nil { + return nil, err + } cs.feedsV1alpha1, err = feedsv1alpha1.NewForConfig(&configShallowCopy) if err != nil { return nil, err @@ -123,6 +143,7 @@ func NewForConfig(c *rest.Config) (*Clientset, error) { func NewForConfigOrDie(c *rest.Config) *Clientset { var cs Clientset cs.channelsV1alpha1 = channelsv1alpha1.NewForConfigOrDie(c) + cs.eventingV1alpha1 = eventingv1alpha1.NewForConfigOrDie(c) cs.feedsV1alpha1 = feedsv1alpha1.NewForConfigOrDie(c) cs.flowsV1alpha1 = flowsv1alpha1.NewForConfigOrDie(c) @@ -134,6 +155,7 @@ func NewForConfigOrDie(c *rest.Config) *Clientset { func New(c rest.Interface) *Clientset { var cs Clientset cs.channelsV1alpha1 = channelsv1alpha1.New(c) + cs.eventingV1alpha1 = eventingv1alpha1.New(c) cs.feedsV1alpha1 = feedsv1alpha1.New(c) cs.flowsV1alpha1 = flowsv1alpha1.New(c) diff --git a/pkg/client/clientset/versioned/fake/clientset_generated.go b/pkg/client/clientset/versioned/fake/clientset_generated.go index 4ad403e5ed2..1a6301babe4 100644 --- a/pkg/client/clientset/versioned/fake/clientset_generated.go +++ b/pkg/client/clientset/versioned/fake/clientset_generated.go @@ -22,6 +22,8 @@ import ( clientset "github.com/knative/eventing/pkg/client/clientset/versioned" channelsv1alpha1 "github.com/knative/eventing/pkg/client/clientset/versioned/typed/channels/v1alpha1" fakechannelsv1alpha1 "github.com/knative/eventing/pkg/client/clientset/versioned/typed/channels/v1alpha1/fake" + eventingv1alpha1 "github.com/knative/eventing/pkg/client/clientset/versioned/typed/eventing/v1alpha1" + fakeeventingv1alpha1 "github.com/knative/eventing/pkg/client/clientset/versioned/typed/eventing/v1alpha1/fake" feedsv1alpha1 "github.com/knative/eventing/pkg/client/clientset/versioned/typed/feeds/v1alpha1" fakefeedsv1alpha1 "github.com/knative/eventing/pkg/client/clientset/versioned/typed/feeds/v1alpha1/fake" flowsv1alpha1 "github.com/knative/eventing/pkg/client/clientset/versioned/typed/flows/v1alpha1" @@ -85,6 +87,16 @@ func (c *Clientset) Channels() channelsv1alpha1.ChannelsV1alpha1Interface { return &fakechannelsv1alpha1.FakeChannelsV1alpha1{Fake: &c.Fake} } +// EventingV1alpha1 retrieves the EventingV1alpha1Client +func (c *Clientset) EventingV1alpha1() eventingv1alpha1.EventingV1alpha1Interface { + return &fakeeventingv1alpha1.FakeEventingV1alpha1{Fake: &c.Fake} +} + +// Eventing retrieves the EventingV1alpha1Client +func (c *Clientset) Eventing() eventingv1alpha1.EventingV1alpha1Interface { + return &fakeeventingv1alpha1.FakeEventingV1alpha1{Fake: &c.Fake} +} + // FeedsV1alpha1 retrieves the FeedsV1alpha1Client func (c *Clientset) FeedsV1alpha1() feedsv1alpha1.FeedsV1alpha1Interface { return &fakefeedsv1alpha1.FakeFeedsV1alpha1{Fake: &c.Fake} diff --git a/pkg/client/clientset/versioned/fake/register.go b/pkg/client/clientset/versioned/fake/register.go index d4f9991e3ca..9c7ef66dd10 100644 --- a/pkg/client/clientset/versioned/fake/register.go +++ b/pkg/client/clientset/versioned/fake/register.go @@ -20,6 +20,7 @@ package fake import ( channelsv1alpha1 "github.com/knative/eventing/pkg/apis/channels/v1alpha1" + eventingv1alpha1 "github.com/knative/eventing/pkg/apis/eventing/v1alpha1" feedsv1alpha1 "github.com/knative/eventing/pkg/apis/feeds/v1alpha1" flowsv1alpha1 "github.com/knative/eventing/pkg/apis/flows/v1alpha1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -53,6 +54,7 @@ func init() { // correctly. func AddToScheme(scheme *runtime.Scheme) { channelsv1alpha1.AddToScheme(scheme) + eventingv1alpha1.AddToScheme(scheme) feedsv1alpha1.AddToScheme(scheme) flowsv1alpha1.AddToScheme(scheme) } diff --git a/pkg/client/clientset/versioned/scheme/register.go b/pkg/client/clientset/versioned/scheme/register.go index 19d55694dd3..b3afb7f218d 100644 --- a/pkg/client/clientset/versioned/scheme/register.go +++ b/pkg/client/clientset/versioned/scheme/register.go @@ -20,6 +20,7 @@ package scheme import ( channelsv1alpha1 "github.com/knative/eventing/pkg/apis/channels/v1alpha1" + eventingv1alpha1 "github.com/knative/eventing/pkg/apis/eventing/v1alpha1" feedsv1alpha1 "github.com/knative/eventing/pkg/apis/feeds/v1alpha1" flowsv1alpha1 "github.com/knative/eventing/pkg/apis/flows/v1alpha1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -53,6 +54,7 @@ func init() { // correctly. func AddToScheme(scheme *runtime.Scheme) { channelsv1alpha1.AddToScheme(scheme) + eventingv1alpha1.AddToScheme(scheme) feedsv1alpha1.AddToScheme(scheme) flowsv1alpha1.AddToScheme(scheme) } diff --git a/pkg/client/clientset/versioned/typed/eventing/v1alpha1/doc.go b/pkg/client/clientset/versioned/typed/eventing/v1alpha1/doc.go new file mode 100644 index 00000000000..75445c17900 --- /dev/null +++ b/pkg/client/clientset/versioned/typed/eventing/v1alpha1/doc.go @@ -0,0 +1,20 @@ +/* +Copyright 2018 The Knative Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +// This package has the automatically generated typed clients. +package v1alpha1 diff --git a/pkg/client/clientset/versioned/typed/eventing/v1alpha1/eventing_client.go b/pkg/client/clientset/versioned/typed/eventing/v1alpha1/eventing_client.go new file mode 100644 index 00000000000..362710dd220 --- /dev/null +++ b/pkg/client/clientset/versioned/typed/eventing/v1alpha1/eventing_client.go @@ -0,0 +1,90 @@ +/* +Copyright 2018 The Knative Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + v1alpha1 "github.com/knative/eventing/pkg/apis/eventing/v1alpha1" + "github.com/knative/eventing/pkg/client/clientset/versioned/scheme" + serializer "k8s.io/apimachinery/pkg/runtime/serializer" + rest "k8s.io/client-go/rest" +) + +type EventingV1alpha1Interface interface { + RESTClient() rest.Interface + SubscriptionsGetter +} + +// EventingV1alpha1Client is used to interact with features provided by the eventing.knative.dev group. +type EventingV1alpha1Client struct { + restClient rest.Interface +} + +func (c *EventingV1alpha1Client) Subscriptions(namespace string) SubscriptionInterface { + return newSubscriptions(c, namespace) +} + +// NewForConfig creates a new EventingV1alpha1Client for the given config. +func NewForConfig(c *rest.Config) (*EventingV1alpha1Client, error) { + config := *c + if err := setConfigDefaults(&config); err != nil { + return nil, err + } + client, err := rest.RESTClientFor(&config) + if err != nil { + return nil, err + } + return &EventingV1alpha1Client{client}, nil +} + +// NewForConfigOrDie creates a new EventingV1alpha1Client for the given config and +// panics if there is an error in the config. +func NewForConfigOrDie(c *rest.Config) *EventingV1alpha1Client { + client, err := NewForConfig(c) + if err != nil { + panic(err) + } + return client +} + +// New creates a new EventingV1alpha1Client for the given RESTClient. +func New(c rest.Interface) *EventingV1alpha1Client { + return &EventingV1alpha1Client{c} +} + +func setConfigDefaults(config *rest.Config) error { + gv := v1alpha1.SchemeGroupVersion + config.GroupVersion = &gv + config.APIPath = "/apis" + config.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: scheme.Codecs} + + if config.UserAgent == "" { + config.UserAgent = rest.DefaultKubernetesUserAgent() + } + + return nil +} + +// RESTClient returns a RESTClient that is used to communicate +// with API server by this client implementation. +func (c *EventingV1alpha1Client) RESTClient() rest.Interface { + if c == nil { + return nil + } + return c.restClient +} diff --git a/pkg/client/clientset/versioned/typed/eventing/v1alpha1/fake/doc.go b/pkg/client/clientset/versioned/typed/eventing/v1alpha1/fake/doc.go new file mode 100644 index 00000000000..128aa183a91 --- /dev/null +++ b/pkg/client/clientset/versioned/typed/eventing/v1alpha1/fake/doc.go @@ -0,0 +1,20 @@ +/* +Copyright 2018 The Knative Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +// Package fake has the automatically generated clients. +package fake diff --git a/pkg/client/clientset/versioned/typed/eventing/v1alpha1/fake/fake_eventing_client.go b/pkg/client/clientset/versioned/typed/eventing/v1alpha1/fake/fake_eventing_client.go new file mode 100644 index 00000000000..005dbd11327 --- /dev/null +++ b/pkg/client/clientset/versioned/typed/eventing/v1alpha1/fake/fake_eventing_client.go @@ -0,0 +1,40 @@ +/* +Copyright 2018 The Knative Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + v1alpha1 "github.com/knative/eventing/pkg/client/clientset/versioned/typed/eventing/v1alpha1" + rest "k8s.io/client-go/rest" + testing "k8s.io/client-go/testing" +) + +type FakeEventingV1alpha1 struct { + *testing.Fake +} + +func (c *FakeEventingV1alpha1) Subscriptions(namespace string) v1alpha1.SubscriptionInterface { + return &FakeSubscriptions{c, namespace} +} + +// RESTClient returns a RESTClient that is used to communicate +// with API server by this client implementation. +func (c *FakeEventingV1alpha1) RESTClient() rest.Interface { + var ret *rest.RESTClient + return ret +} diff --git a/pkg/client/clientset/versioned/typed/eventing/v1alpha1/fake/fake_subscription.go b/pkg/client/clientset/versioned/typed/eventing/v1alpha1/fake/fake_subscription.go new file mode 100644 index 00000000000..85a728524aa --- /dev/null +++ b/pkg/client/clientset/versioned/typed/eventing/v1alpha1/fake/fake_subscription.go @@ -0,0 +1,128 @@ +/* +Copyright 2018 The Knative Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + v1alpha1 "github.com/knative/eventing/pkg/apis/eventing/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + schema "k8s.io/apimachinery/pkg/runtime/schema" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" +) + +// FakeSubscriptions implements SubscriptionInterface +type FakeSubscriptions struct { + Fake *FakeEventingV1alpha1 + ns string +} + +var subscriptionsResource = schema.GroupVersionResource{Group: "eventing.knative.dev", Version: "v1alpha1", Resource: "subscriptions"} + +var subscriptionsKind = schema.GroupVersionKind{Group: "eventing.knative.dev", Version: "v1alpha1", Kind: "Subscription"} + +// Get takes name of the subscription, and returns the corresponding subscription object, and an error if there is any. +func (c *FakeSubscriptions) Get(name string, options v1.GetOptions) (result *v1alpha1.Subscription, err error) { + obj, err := c.Fake. + Invokes(testing.NewGetAction(subscriptionsResource, c.ns, name), &v1alpha1.Subscription{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.Subscription), err +} + +// List takes label and field selectors, and returns the list of Subscriptions that match those selectors. +func (c *FakeSubscriptions) List(opts v1.ListOptions) (result *v1alpha1.SubscriptionList, err error) { + obj, err := c.Fake. + Invokes(testing.NewListAction(subscriptionsResource, subscriptionsKind, c.ns, opts), &v1alpha1.SubscriptionList{}) + + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &v1alpha1.SubscriptionList{ListMeta: obj.(*v1alpha1.SubscriptionList).ListMeta} + for _, item := range obj.(*v1alpha1.SubscriptionList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested subscriptions. +func (c *FakeSubscriptions) Watch(opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewWatchAction(subscriptionsResource, c.ns, opts)) + +} + +// Create takes the representation of a subscription and creates it. Returns the server's representation of the subscription, and an error, if there is any. +func (c *FakeSubscriptions) Create(subscription *v1alpha1.Subscription) (result *v1alpha1.Subscription, err error) { + obj, err := c.Fake. + Invokes(testing.NewCreateAction(subscriptionsResource, c.ns, subscription), &v1alpha1.Subscription{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.Subscription), err +} + +// Update takes the representation of a subscription and updates it. Returns the server's representation of the subscription, and an error, if there is any. +func (c *FakeSubscriptions) Update(subscription *v1alpha1.Subscription) (result *v1alpha1.Subscription, err error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateAction(subscriptionsResource, c.ns, subscription), &v1alpha1.Subscription{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.Subscription), err +} + +// Delete takes name of the subscription and deletes it. Returns an error if one occurs. +func (c *FakeSubscriptions) Delete(name string, options *v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewDeleteAction(subscriptionsResource, c.ns, name), &v1alpha1.Subscription{}) + + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeSubscriptions) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { + action := testing.NewDeleteCollectionAction(subscriptionsResource, c.ns, listOptions) + + _, err := c.Fake.Invokes(action, &v1alpha1.SubscriptionList{}) + return err +} + +// Patch applies the patch and returns the patched subscription. +func (c *FakeSubscriptions) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.Subscription, err error) { + obj, err := c.Fake. + Invokes(testing.NewPatchSubresourceAction(subscriptionsResource, c.ns, name, data, subresources...), &v1alpha1.Subscription{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.Subscription), err +} diff --git a/pkg/client/clientset/versioned/typed/eventing/v1alpha1/generated_expansion.go b/pkg/client/clientset/versioned/typed/eventing/v1alpha1/generated_expansion.go new file mode 100644 index 00000000000..9911c7c289f --- /dev/null +++ b/pkg/client/clientset/versioned/typed/eventing/v1alpha1/generated_expansion.go @@ -0,0 +1,21 @@ +/* +Copyright 2018 The Knative Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +type SubscriptionExpansion interface{} diff --git a/pkg/client/clientset/versioned/typed/eventing/v1alpha1/subscription.go b/pkg/client/clientset/versioned/typed/eventing/v1alpha1/subscription.go new file mode 100644 index 00000000000..dde8b0ac06b --- /dev/null +++ b/pkg/client/clientset/versioned/typed/eventing/v1alpha1/subscription.go @@ -0,0 +1,157 @@ +/* +Copyright 2018 The Knative Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + v1alpha1 "github.com/knative/eventing/pkg/apis/eventing/v1alpha1" + scheme "github.com/knative/eventing/pkg/client/clientset/versioned/scheme" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" +) + +// SubscriptionsGetter has a method to return a SubscriptionInterface. +// A group's client should implement this interface. +type SubscriptionsGetter interface { + Subscriptions(namespace string) SubscriptionInterface +} + +// SubscriptionInterface has methods to work with Subscription resources. +type SubscriptionInterface interface { + Create(*v1alpha1.Subscription) (*v1alpha1.Subscription, error) + Update(*v1alpha1.Subscription) (*v1alpha1.Subscription, error) + Delete(name string, options *v1.DeleteOptions) error + DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error + Get(name string, options v1.GetOptions) (*v1alpha1.Subscription, error) + List(opts v1.ListOptions) (*v1alpha1.SubscriptionList, error) + Watch(opts v1.ListOptions) (watch.Interface, error) + Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.Subscription, err error) + SubscriptionExpansion +} + +// subscriptions implements SubscriptionInterface +type subscriptions struct { + client rest.Interface + ns string +} + +// newSubscriptions returns a Subscriptions +func newSubscriptions(c *EventingV1alpha1Client, namespace string) *subscriptions { + return &subscriptions{ + client: c.RESTClient(), + ns: namespace, + } +} + +// Get takes name of the subscription, and returns the corresponding subscription object, and an error if there is any. +func (c *subscriptions) Get(name string, options v1.GetOptions) (result *v1alpha1.Subscription, err error) { + result = &v1alpha1.Subscription{} + err = c.client.Get(). + Namespace(c.ns). + Resource("subscriptions"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of Subscriptions that match those selectors. +func (c *subscriptions) List(opts v1.ListOptions) (result *v1alpha1.SubscriptionList, err error) { + result = &v1alpha1.SubscriptionList{} + err = c.client.Get(). + Namespace(c.ns). + Resource("subscriptions"). + VersionedParams(&opts, scheme.ParameterCodec). + Do(). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested subscriptions. +func (c *subscriptions) Watch(opts v1.ListOptions) (watch.Interface, error) { + opts.Watch = true + return c.client.Get(). + Namespace(c.ns). + Resource("subscriptions"). + VersionedParams(&opts, scheme.ParameterCodec). + Watch() +} + +// Create takes the representation of a subscription and creates it. Returns the server's representation of the subscription, and an error, if there is any. +func (c *subscriptions) Create(subscription *v1alpha1.Subscription) (result *v1alpha1.Subscription, err error) { + result = &v1alpha1.Subscription{} + err = c.client.Post(). + Namespace(c.ns). + Resource("subscriptions"). + Body(subscription). + Do(). + Into(result) + return +} + +// Update takes the representation of a subscription and updates it. Returns the server's representation of the subscription, and an error, if there is any. +func (c *subscriptions) Update(subscription *v1alpha1.Subscription) (result *v1alpha1.Subscription, err error) { + result = &v1alpha1.Subscription{} + err = c.client.Put(). + Namespace(c.ns). + Resource("subscriptions"). + Name(subscription.Name). + Body(subscription). + Do(). + Into(result) + return +} + +// Delete takes name of the subscription and deletes it. Returns an error if one occurs. +func (c *subscriptions) Delete(name string, options *v1.DeleteOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("subscriptions"). + Name(name). + Body(options). + Do(). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *subscriptions) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("subscriptions"). + VersionedParams(&listOptions, scheme.ParameterCodec). + Body(options). + Do(). + Error() +} + +// Patch applies the patch and returns the patched subscription. +func (c *subscriptions) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.Subscription, err error) { + result = &v1alpha1.Subscription{} + err = c.client.Patch(pt). + Namespace(c.ns). + Resource("subscriptions"). + SubResource(subresources...). + Name(name). + Body(data). + Do(). + Into(result) + return +} diff --git a/pkg/client/informers/externalversions/eventing/interface.go b/pkg/client/informers/externalversions/eventing/interface.go new file mode 100644 index 00000000000..17435a38470 --- /dev/null +++ b/pkg/client/informers/externalversions/eventing/interface.go @@ -0,0 +1,46 @@ +/* +Copyright 2018 The Knative Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by informer-gen. DO NOT EDIT. + +package eventing + +import ( + v1alpha1 "github.com/knative/eventing/pkg/client/informers/externalversions/eventing/v1alpha1" + internalinterfaces "github.com/knative/eventing/pkg/client/informers/externalversions/internalinterfaces" +) + +// Interface provides access to each of this group's versions. +type Interface interface { + // V1alpha1 provides access to shared informers for resources in V1alpha1. + V1alpha1() v1alpha1.Interface +} + +type group struct { + factory internalinterfaces.SharedInformerFactory + namespace string + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// New returns a new Interface. +func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { + return &group{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} +} + +// V1alpha1 returns a new v1alpha1.Interface. +func (g *group) V1alpha1() v1alpha1.Interface { + return v1alpha1.New(g.factory, g.namespace, g.tweakListOptions) +} diff --git a/pkg/client/informers/externalversions/eventing/v1alpha1/interface.go b/pkg/client/informers/externalversions/eventing/v1alpha1/interface.go new file mode 100644 index 00000000000..a6a55a02c9f --- /dev/null +++ b/pkg/client/informers/externalversions/eventing/v1alpha1/interface.go @@ -0,0 +1,45 @@ +/* +Copyright 2018 The Knative Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by informer-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + internalinterfaces "github.com/knative/eventing/pkg/client/informers/externalversions/internalinterfaces" +) + +// Interface provides access to all the informers in this group version. +type Interface interface { + // Subscriptions returns a SubscriptionInformer. + Subscriptions() SubscriptionInformer +} + +type version struct { + factory internalinterfaces.SharedInformerFactory + namespace string + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// New returns a new Interface. +func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { + return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} +} + +// Subscriptions returns a SubscriptionInformer. +func (v *version) Subscriptions() SubscriptionInformer { + return &subscriptionInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} diff --git a/pkg/client/informers/externalversions/eventing/v1alpha1/subscription.go b/pkg/client/informers/externalversions/eventing/v1alpha1/subscription.go new file mode 100644 index 00000000000..4b248675659 --- /dev/null +++ b/pkg/client/informers/externalversions/eventing/v1alpha1/subscription.go @@ -0,0 +1,89 @@ +/* +Copyright 2018 The Knative Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by informer-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + time "time" + + eventing_v1alpha1 "github.com/knative/eventing/pkg/apis/eventing/v1alpha1" + versioned "github.com/knative/eventing/pkg/client/clientset/versioned" + internalinterfaces "github.com/knative/eventing/pkg/client/informers/externalversions/internalinterfaces" + v1alpha1 "github.com/knative/eventing/pkg/client/listers/eventing/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" +) + +// SubscriptionInformer provides access to a shared informer and lister for +// Subscriptions. +type SubscriptionInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1alpha1.SubscriptionLister +} + +type subscriptionInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewSubscriptionInformer constructs a new informer for Subscription type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewSubscriptionInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredSubscriptionInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredSubscriptionInformer constructs a new informer for Subscription type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredSubscriptionInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.EventingV1alpha1().Subscriptions(namespace).List(options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.EventingV1alpha1().Subscriptions(namespace).Watch(options) + }, + }, + &eventing_v1alpha1.Subscription{}, + resyncPeriod, + indexers, + ) +} + +func (f *subscriptionInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredSubscriptionInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *subscriptionInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&eventing_v1alpha1.Subscription{}, f.defaultInformer) +} + +func (f *subscriptionInformer) Lister() v1alpha1.SubscriptionLister { + return v1alpha1.NewSubscriptionLister(f.Informer().GetIndexer()) +} diff --git a/pkg/client/informers/externalversions/factory.go b/pkg/client/informers/externalversions/factory.go index df9d1890b9d..adee6a64b79 100644 --- a/pkg/client/informers/externalversions/factory.go +++ b/pkg/client/informers/externalversions/factory.go @@ -25,6 +25,7 @@ import ( versioned "github.com/knative/eventing/pkg/client/clientset/versioned" channels "github.com/knative/eventing/pkg/client/informers/externalversions/channels" + eventing "github.com/knative/eventing/pkg/client/informers/externalversions/eventing" feeds "github.com/knative/eventing/pkg/client/informers/externalversions/feeds" flows "github.com/knative/eventing/pkg/client/informers/externalversions/flows" internalinterfaces "github.com/knative/eventing/pkg/client/informers/externalversions/internalinterfaces" @@ -175,6 +176,7 @@ type SharedInformerFactory interface { WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool Channels() channels.Interface + Eventing() eventing.Interface Feeds() feeds.Interface Flows() flows.Interface } @@ -183,6 +185,10 @@ func (f *sharedInformerFactory) Channels() channels.Interface { return channels.New(f, f.namespace, f.tweakListOptions) } +func (f *sharedInformerFactory) Eventing() eventing.Interface { + return eventing.New(f, f.namespace, f.tweakListOptions) +} + func (f *sharedInformerFactory) Feeds() feeds.Interface { return feeds.New(f, f.namespace, f.tweakListOptions) } diff --git a/pkg/client/informers/externalversions/generic.go b/pkg/client/informers/externalversions/generic.go index e1e625fd027..ebec1b27cf0 100644 --- a/pkg/client/informers/externalversions/generic.go +++ b/pkg/client/informers/externalversions/generic.go @@ -22,6 +22,7 @@ import ( "fmt" v1alpha1 "github.com/knative/eventing/pkg/apis/channels/v1alpha1" + eventing_v1alpha1 "github.com/knative/eventing/pkg/apis/eventing/v1alpha1" feeds_v1alpha1 "github.com/knative/eventing/pkg/apis/feeds/v1alpha1" flows_v1alpha1 "github.com/knative/eventing/pkg/apis/flows/v1alpha1" schema "k8s.io/apimachinery/pkg/runtime/schema" @@ -64,6 +65,10 @@ func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource case v1alpha1.SchemeGroupVersion.WithResource("subscriptions"): return &genericInformer{resource: resource.GroupResource(), informer: f.Channels().V1alpha1().Subscriptions().Informer()}, nil + // Group=eventing.knative.dev, Version=v1alpha1 + case eventing_v1alpha1.SchemeGroupVersion.WithResource("subscriptions"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Eventing().V1alpha1().Subscriptions().Informer()}, nil + // Group=feeds.knative.dev, Version=v1alpha1 case feeds_v1alpha1.SchemeGroupVersion.WithResource("clustereventsources"): return &genericInformer{resource: resource.GroupResource(), informer: f.Feeds().V1alpha1().ClusterEventSources().Informer()}, nil diff --git a/pkg/client/listers/eventing/v1alpha1/expansion_generated.go b/pkg/client/listers/eventing/v1alpha1/expansion_generated.go new file mode 100644 index 00000000000..68d69ebd2a4 --- /dev/null +++ b/pkg/client/listers/eventing/v1alpha1/expansion_generated.go @@ -0,0 +1,27 @@ +/* +Copyright 2018 The Knative Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by lister-gen. DO NOT EDIT. + +package v1alpha1 + +// SubscriptionListerExpansion allows custom methods to be added to +// SubscriptionLister. +type SubscriptionListerExpansion interface{} + +// SubscriptionNamespaceListerExpansion allows custom methods to be added to +// SubscriptionNamespaceLister. +type SubscriptionNamespaceListerExpansion interface{} diff --git a/pkg/client/listers/eventing/v1alpha1/subscription.go b/pkg/client/listers/eventing/v1alpha1/subscription.go new file mode 100644 index 00000000000..0a834e5ebce --- /dev/null +++ b/pkg/client/listers/eventing/v1alpha1/subscription.go @@ -0,0 +1,94 @@ +/* +Copyright 2018 The Knative Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by lister-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + v1alpha1 "github.com/knative/eventing/pkg/apis/eventing/v1alpha1" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" +) + +// SubscriptionLister helps list Subscriptions. +type SubscriptionLister interface { + // List lists all Subscriptions in the indexer. + List(selector labels.Selector) (ret []*v1alpha1.Subscription, err error) + // Subscriptions returns an object that can list and get Subscriptions. + Subscriptions(namespace string) SubscriptionNamespaceLister + SubscriptionListerExpansion +} + +// subscriptionLister implements the SubscriptionLister interface. +type subscriptionLister struct { + indexer cache.Indexer +} + +// NewSubscriptionLister returns a new SubscriptionLister. +func NewSubscriptionLister(indexer cache.Indexer) SubscriptionLister { + return &subscriptionLister{indexer: indexer} +} + +// List lists all Subscriptions in the indexer. +func (s *subscriptionLister) List(selector labels.Selector) (ret []*v1alpha1.Subscription, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.Subscription)) + }) + return ret, err +} + +// Subscriptions returns an object that can list and get Subscriptions. +func (s *subscriptionLister) Subscriptions(namespace string) SubscriptionNamespaceLister { + return subscriptionNamespaceLister{indexer: s.indexer, namespace: namespace} +} + +// SubscriptionNamespaceLister helps list and get Subscriptions. +type SubscriptionNamespaceLister interface { + // List lists all Subscriptions in the indexer for a given namespace. + List(selector labels.Selector) (ret []*v1alpha1.Subscription, err error) + // Get retrieves the Subscription from the indexer for a given namespace and name. + Get(name string) (*v1alpha1.Subscription, error) + SubscriptionNamespaceListerExpansion +} + +// subscriptionNamespaceLister implements the SubscriptionNamespaceLister +// interface. +type subscriptionNamespaceLister struct { + indexer cache.Indexer + namespace string +} + +// List lists all Subscriptions in the indexer for a given namespace. +func (s subscriptionNamespaceLister) List(selector labels.Selector) (ret []*v1alpha1.Subscription, err error) { + err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.Subscription)) + }) + return ret, err +} + +// Get retrieves the Subscription from the indexer for a given namespace and name. +func (s subscriptionNamespaceLister) Get(name string) (*v1alpha1.Subscription, error) { + obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1alpha1.Resource("subscription"), name) + } + return obj.(*v1alpha1.Subscription), nil +}