Initial commit

This commit is contained in:
Donny
2019-04-22 20:46:32 +08:00
commit 49ab8aadd1
25441 changed files with 4055000 additions and 0 deletions

44
vendor/github.com/knative/pkg/apis/BUILD generated vendored Normal file
View File

@@ -0,0 +1,44 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = [
"doc.go",
"field_error.go",
"interfaces.go",
"kind2resource.go",
"volatile_time.go",
"zz_generated.deepcopy.go",
],
importpath = "github.com/knative/pkg/apis",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//vendor/github.com/knative/pkg/apis/duck:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

18
vendor/github.com/knative/pkg/apis/doc.go generated vendored Normal file
View File

@@ -0,0 +1,18 @@
/*
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 apis

55
vendor/github.com/knative/pkg/apis/duck/BUILD generated vendored Normal file
View File

@@ -0,0 +1,55 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = [
"cached.go",
"doc.go",
"enqueue.go",
"interface.go",
"patch.go",
"proxy.go",
"register.go",
"typed.go",
"unstructured.go",
"verify.go",
],
importpath = "github.com/knative/pkg/apis/duck",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//vendor/github.com/evanphx/json-patch:go_default_library",
"//vendor/github.com/google/go-cmp/cmp:go_default_library",
"//vendor/github.com/knative/pkg/apis:go_default_library",
"//vendor/github.com/mattbaird/jsonpatch:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/watch:go_default_library",
"//vendor/k8s.io/client-go/dynamic:go_default_library",
"//vendor/k8s.io/client-go/tools/cache:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//vendor/github.com/knative/pkg/apis/duck/v1alpha1:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

72
vendor/github.com/knative/pkg/apis/duck/cached.go generated vendored Normal file
View File

@@ -0,0 +1,72 @@
/*
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 duck
import (
"sync"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/client-go/tools/cache"
)
// CachedInformerFactory implements InformerFactory by delegating to another
// InformerFactory, but memoizing the results.
type CachedInformerFactory struct {
Delegate InformerFactory
m sync.Mutex
cache map[schema.GroupVersionResource]*result
}
// Check that CachedInformerFactory implements InformerFactory.
var _ InformerFactory = (*CachedInformerFactory)(nil)
// Get implements InformerFactory.
func (cif *CachedInformerFactory) Get(gvr schema.GroupVersionResource) (cache.SharedIndexInformer, cache.GenericLister, error) {
cif.m.Lock()
if cif.cache == nil {
cif.cache = make(map[schema.GroupVersionResource]*result)
}
elt, ok := cif.cache[gvr]
if !ok {
elt = &result{}
elt.init = func() {
elt.inf, elt.lister, elt.err = cif.Delegate.Get(gvr)
}
cif.cache[gvr] = elt
}
// If this were done via "defer", then TestDifferentGVRs will fail.
cif.m.Unlock()
// The call to the delegate could be slow because it syncs informers, so do
// this outside of the main lock.
return elt.Get()
}
type result struct {
sync.Once
init func()
inf cache.SharedIndexInformer
lister cache.GenericLister
err error
}
func (t *result) Get() (cache.SharedIndexInformer, cache.GenericLister, error) {
t.Do(t.init)
return t.inf, t.lister, t.err
}

23
vendor/github.com/knative/pkg/apis/duck/doc.go generated vendored Normal file
View File

@@ -0,0 +1,23 @@
/*
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 duck defines logic for defining and consuming "duck typed"
// Kubernetes resources. Producers define partial resource definitions
// that resource authors may choose to implement to interoperate with
// consumers of these "duck typed" interfaces.
// For more information see:
// https://docs.google.com/document/d/16j8C91jML4fQRQPhnHihNJUJDcbvW0RM1YAX2REHgyY/edit#
package duck

44
vendor/github.com/knative/pkg/apis/duck/enqueue.go generated vendored Normal file
View File

@@ -0,0 +1,44 @@
/*
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 duck
import (
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/client-go/tools/cache"
)
// EnqueueInformerFactory implements InformerFactory by delegating to another
// InformerFactory, but attaching a ResourceEventHandler to the informer.
type EnqueueInformerFactory struct {
Delegate InformerFactory
EventHandler cache.ResourceEventHandler
}
// Check that EnqueueInformerFactory implements InformerFactory.
var _ InformerFactory = (*EnqueueInformerFactory)(nil)
// Get implements InformerFactory.
func (cif *EnqueueInformerFactory) Get(gvr schema.GroupVersionResource) (cache.SharedIndexInformer, cache.GenericLister, error) {
inf, lister, err := cif.Delegate.Get(gvr)
if err != nil {
return nil, nil, err
}
// If there is an informer, attach our event handler.
inf.AddEventHandler(cif.EventHandler)
return inf, lister, nil
}

28
vendor/github.com/knative/pkg/apis/duck/interface.go generated vendored Normal file
View File

@@ -0,0 +1,28 @@
/*
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 duck
import (
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/client-go/tools/cache"
)
// InformerFactory is used to create Informer/Lister pairs for a schema.GroupVersionResource
type InformerFactory interface {
// Get returns a synced Informer/Lister pair for the provided schema.GroupVersionResource.
Get(schema.GroupVersionResource) (cache.SharedIndexInformer, cache.GenericLister, error)
}

60
vendor/github.com/knative/pkg/apis/duck/patch.go generated vendored Normal file
View File

@@ -0,0 +1,60 @@
/*
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 duck
import (
"encoding/json"
jsonmergepatch "github.com/evanphx/json-patch"
"github.com/mattbaird/jsonpatch"
)
func marshallBeforeAfter(before, after interface{}) ([]byte, []byte, error) {
rawBefore, err := json.Marshal(before)
if err != nil {
return nil, nil, err
}
rawAfter, err := json.Marshal(after)
if err != nil {
return rawBefore, nil, err
}
return rawBefore, rawAfter, nil
}
func CreateMergePatch(before, after interface{}) ([]byte, error) {
rawBefore, rawAfter, err := marshallBeforeAfter(before, after)
if err != nil {
return nil, err
}
return jsonmergepatch.CreateMergePatch(rawBefore, rawAfter)
}
func CreatePatch(before, after interface{}) (JSONPatch, error) {
rawBefore, rawAfter, err := marshallBeforeAfter(before, after)
if err != nil {
return nil, err
}
return jsonpatch.CreatePatch(rawBefore, rawAfter)
}
type JSONPatch []jsonpatch.JsonPatchOperation
func (p JSONPatch) MarshalJSON() ([]byte, error) {
return json.Marshal([]jsonpatch.JsonPatchOperation(p))
}

74
vendor/github.com/knative/pkg/apis/duck/proxy.go generated vendored Normal file
View File

@@ -0,0 +1,74 @@
/*
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 duck
import (
"sync"
"k8s.io/apimachinery/pkg/watch"
)
// NewProxyWatcher is based on the same concept from Kubernetes apimachinery in 1.12 here:
// https://github.com/kubernetes/apimachinery/blob/c6dd271be/pkg/watch/watch.go#L272
// Replace this copy once we've update our client libraries.
// proxyWatcher lets you wrap your channel in watch.Interface. Threadsafe.
type proxyWatcher struct {
result chan watch.Event
stopCh chan struct{}
mutex sync.Mutex
stopped bool
}
var _ watch.Interface = (*proxyWatcher)(nil)
// NewProxyWatcher creates new proxyWatcher by wrapping a channel
func NewProxyWatcher(ch chan watch.Event) watch.Interface {
return &proxyWatcher{
result: ch,
stopCh: make(chan struct{}),
stopped: false,
}
}
// Stop implements Interface
func (pw *proxyWatcher) Stop() {
pw.mutex.Lock()
defer pw.mutex.Unlock()
if !pw.stopped {
pw.stopped = true
close(pw.stopCh)
}
}
// Stopping returns true if Stop() has been called
func (pw *proxyWatcher) Stopping() bool {
pw.mutex.Lock()
defer pw.mutex.Unlock()
return pw.stopped
}
// ResultChan implements watch.Interface
func (pw *proxyWatcher) ResultChan() <-chan watch.Event {
return pw.result
}
// StopChan returns stop channel
func (pw *proxyWatcher) StopChan() <-chan struct{} {
return pw.stopCh
}

21
vendor/github.com/knative/pkg/apis/duck/register.go generated vendored Normal file
View File

@@ -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 duck
const (
GroupName = "duck.knative.dev"
)

141
vendor/github.com/knative/pkg/apis/duck/typed.go generated vendored Normal file
View File

@@ -0,0 +1,141 @@
/*
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 duck
import (
"fmt"
"net/http"
"time"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/watch"
"k8s.io/client-go/dynamic"
"k8s.io/client-go/tools/cache"
"github.com/knative/pkg/apis"
)
// TypedInformerFactory implements InformerFactory such that the elements
// tracked by the informer/lister have the type of the canonical "obj".
type TypedInformerFactory struct {
Client dynamic.Interface
Type apis.Listable
ResyncPeriod time.Duration
StopChannel <-chan struct{}
}
// Check that TypedInformerFactory implements InformerFactory.
var _ InformerFactory = (*TypedInformerFactory)(nil)
// Get implements InformerFactory.
func (dif *TypedInformerFactory) Get(gvr schema.GroupVersionResource) (cache.SharedIndexInformer, cache.GenericLister, error) {
listObj := dif.Type.GetListType()
lw := &cache.ListWatch{
ListFunc: asStructuredLister(dif.Client.Resource(gvr).List, listObj),
WatchFunc: AsStructuredWatcher(dif.Client.Resource(gvr).Watch, dif.Type),
}
inf := cache.NewSharedIndexInformer(lw, dif.Type, dif.ResyncPeriod, cache.Indexers{
cache.NamespaceIndex: cache.MetaNamespaceIndexFunc,
})
lister := cache.NewGenericLister(inf.GetIndexer(), gvr.GroupResource())
go inf.Run(dif.StopChannel)
if ok := cache.WaitForCacheSync(dif.StopChannel, inf.HasSynced); !ok {
return nil, nil, fmt.Errorf("Failed starting shared index informer for %v with type %T", gvr, dif.Type)
}
return inf, lister, nil
}
type unstructuredLister func(metav1.ListOptions) (*unstructured.UnstructuredList, error)
func asStructuredLister(ulist unstructuredLister, listObj runtime.Object) cache.ListFunc {
return func(opts metav1.ListOptions) (runtime.Object, error) {
ul, err := ulist(opts)
if err != nil {
return nil, err
}
res := listObj.DeepCopyObject()
if err := FromUnstructured(ul, res); err != nil {
return nil, err
}
return res, nil
}
}
// AsStructuredWatcher is public for testing only.
// TODO(mattmoor): Move tests for this to `package duck` and make private.
func AsStructuredWatcher(wf cache.WatchFunc, obj runtime.Object) cache.WatchFunc {
return func(lo metav1.ListOptions) (watch.Interface, error) {
uw, err := wf(lo)
if err != nil {
return nil, err
}
structuredCh := make(chan watch.Event)
go func() {
defer close(structuredCh)
unstructuredCh := uw.ResultChan()
for {
select {
case ue, ok := <-unstructuredCh:
if !ok {
// Channel is closed.
return
}
unstructuredObj, ok := ue.Object.(*unstructured.Unstructured)
if !ok {
// If it isn't an unstructured object, then forward the
// event as-is. This is likely to happen when the event's
// Type is an Error.
structuredCh <- ue
continue
}
structuredObj := obj.DeepCopyObject()
err := FromUnstructured(unstructuredObj, structuredObj)
if err != nil {
// Pass back an error indicating that the object we got
// was invalid.
structuredCh <- watch.Event{
Type: watch.Error,
Object: &metav1.Status{
Status: metav1.StatusFailure,
Code: http.StatusUnprocessableEntity,
Reason: metav1.StatusReasonInvalid,
Message: err.Error(),
},
}
continue
}
// Send the structured event.
structuredCh <- watch.Event{
Type: ue.Type,
Object: structuredObj,
}
}
}
}()
return NewProxyWatcher(structuredCh), nil
}
}

View File

@@ -0,0 +1,37 @@
/*
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 duck
import (
"encoding/json"
)
// Marshallable is implementated by the Unstructured K8s types.
type Marshalable interface {
MarshalJSON() ([]byte, error)
}
// FromUnstructured takes unstructured object from (say from client-go/dynamic) and
// converts it into our duck types.
func FromUnstructured(obj Marshalable, target interface{}) error {
// Use the unstructured marshaller to ensure it's proper JSON
raw, err := obj.MarshalJSON()
if err != nil {
return err
}
return json.Unmarshal(raw, &target)
}

46
vendor/github.com/knative/pkg/apis/duck/v1alpha1/BUILD generated vendored Normal file
View File

@@ -0,0 +1,46 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = [
"addressable_types.go",
"condition_set.go",
"conditions_types.go",
"doc.go",
"generational_types.go",
"legacy_targetable_types.go",
"register.go",
"retired_targetable_types.go",
"zz_generated.deepcopy.go",
],
importpath = "github.com/knative/pkg/apis/duck/v1alpha1",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//vendor/github.com/knative/pkg/apis:go_default_library",
"//vendor/github.com/knative/pkg/apis/duck:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,95 @@
/*
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 (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"github.com/knative/pkg/apis"
"github.com/knative/pkg/apis/duck"
)
// Addressable provides a generic mechanism for a custom resource
// definition to indicate a destination for message delivery.
// (Currently, only hostname is supported, and HTTP is implied. In the
// future, additional schemes may be supported, and path components
// ala UI may also be supported.)
// Addressable is the schema for the destination information. This is
// typically stored in the object's `status`, as this information may
// be generated by the controller.
type Addressable struct {
Hostname string `json:"hostname,omitempty"`
}
// Addressable is an Implementable "duck type".
var _ duck.Implementable = (*Addressable)(nil)
// +genclient
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// AddressableType is a skeleton type wrapping Addressable in the manner we expect
// resource writers defining compatible resources to embed it. We will
// typically use this type to deserialize Addressable ObjectReferences and
// access the Addressable data. This is not a real resource.
type AddressableType struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Status AddressStatus `json:"status"`
}
// AddressStatus shows how we expect folks to embed Addressable in
// their Status field.
type AddressStatus struct {
Address *Addressable `json:"address,omitempty"`
}
// Verify AddressableType resources meet duck contracts.
var _ duck.Populatable = (*AddressableType)(nil)
var _ apis.Listable = (*AddressableType)(nil)
// GetFullType implements duck.Implementable
func (_ *Addressable) GetFullType() duck.Populatable {
return &AddressableType{}
}
// Populate implements duck.Populatable
func (t *AddressableType) Populate() {
t.Status = AddressStatus{
&Addressable{
// Populate ALL fields
Hostname: "this is not empty",
},
}
}
// GetListType implements apis.Listable
func (r *AddressableType) GetListType() runtime.Object {
return &AddressableTypeList{}
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// AddressableTypeList is a list of AddressableType resources
type AddressableTypeList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata"`
Items []AddressableType `json:"items"`
}

View File

@@ -0,0 +1,382 @@
/*
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"
"sort"
"time"
"fmt"
"github.com/knative/pkg/apis"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// Conditions is the interface for a Resource that implements the getter and
// setter for accessing a Condition collection.
// +k8s:deepcopy-gen=true
type ConditionsAccessor interface {
GetConditions() Conditions
SetConditions(Conditions)
}
// ConditionSet is an abstract collection of the possible ConditionType values
// that a particular resource might expose. It also holds the "happy condition"
// for that resource, which we define to be one of Ready or Succeeded depending
// on whether it is a Living or Batch process respectively.
// +k8s:deepcopy-gen=false
type ConditionSet struct {
happy ConditionType
dependents []ConditionType
}
// ConditionManager allows a resource to operate on its Conditions using higher
// order operations.
type ConditionManager interface {
// IsHappy looks at the happy condition and returns true if that condition is
// set to true.
IsHappy() bool
// GetCondition finds and returns the Condition that matches the ConditionType
// previously set on Conditions.
GetCondition(t ConditionType) *Condition
// SetCondition sets or updates the Condition on Conditions for Condition.Type.
// If there is an update, Conditions are stored back sorted.
SetCondition(new Condition)
// MarkTrue sets the status of t to true, and then marks the happy condition to
// true if all dependents are true.
MarkTrue(t ConditionType)
// MarkUnknown sets the status of t to Unknown and also sets the happy condition
// to Unknown if no other dependent condition is in an error state.
MarkUnknown(t ConditionType, reason, messageFormat string, messageA ...interface{})
// MarkFalse sets the status of t and the happy condition to False.
MarkFalse(t ConditionType, reason, messageFormat string, messageA ...interface{})
// InitializeConditions updates all Conditions in the ConditionSet to Unknown
// if not set.
InitializeConditions()
// InitializeCondition updates a Condition to Unknown if not set.
InitializeCondition(t ConditionType)
}
// NewLivingConditionSet returns a ConditionSet to hold the conditions for the
// living resource. ConditionReady is used as the happy condition.
// The set of condition types provided are those of the terminal subconditions.
func NewLivingConditionSet(d ...ConditionType) ConditionSet {
return newConditionSet(ConditionReady, d...)
}
// NewBatchConditionSet returns a ConditionSet to hold the conditions for the
// batch resource. ConditionSucceeded is used as the happy condition.
// The set of condition types provided are those of the terminal subconditions.
func NewBatchConditionSet(d ...ConditionType) ConditionSet {
return newConditionSet(ConditionSucceeded, d...)
}
// newConditionSet returns a ConditionSet to hold the conditions that are
// important for the caller. The first ConditionType is the overarching status
// for that will be used to signal the resources' status is Ready or Succeeded.
func newConditionSet(happy ConditionType, dependents ...ConditionType) ConditionSet {
var deps []ConditionType
for _, d := range dependents {
// Skip duplicates
if d == happy || contains(deps, d) {
continue
}
deps = append(deps, d)
}
return ConditionSet{
happy: happy,
dependents: deps,
}
}
func contains(ct []ConditionType, t ConditionType) bool {
for _, c := range ct {
if c == t {
return true
}
}
return false
}
// Check that conditionsImpl implements ConditionManager.
var _ ConditionManager = (*conditionsImpl)(nil)
// conditionsImpl implements the helper methods for evaluating Conditions.
// +k8s:deepcopy-gen=false
type conditionsImpl struct {
ConditionSet
accessor ConditionsAccessor
}
// Manage creates a ConditionManager from a accessor object using the original
// ConditionSet as a reference. Status must be or point to a struct.
func (r ConditionSet) Manage(status interface{}) ConditionManager {
// First try to see if status implements ConditionsAccessor
ca, ok := status.(ConditionsAccessor)
if ok {
return conditionsImpl{
accessor: ca,
ConditionSet: r,
}
}
// Next see if we can use reflection to gain access to Conditions
ca = NewReflectedConditionsAccessor(status)
if ca != nil {
return conditionsImpl{
accessor: ca,
ConditionSet: r,
}
}
// We tried. This object is not understood by the the condition manager.
//panic(fmt.Sprintf("Error converting %T into a ConditionsAccessor", status))
// TODO: not sure which way. using panic above means passing nil status panics the system.
return conditionsImpl{
ConditionSet: r,
}
}
// IsHappy looks at the happy condition and returns true if that condition is
// set to true.
func (r conditionsImpl) IsHappy() bool {
if c := r.GetCondition(r.happy); c == nil || !c.IsTrue() {
return false
}
return true
}
// GetCondition finds and returns the Condition that matches the ConditionType
// previously set on Conditions.
func (r conditionsImpl) GetCondition(t ConditionType) *Condition {
if r.accessor == nil {
return nil
}
for _, c := range r.accessor.GetConditions() {
if c.Type == t {
return &c
}
}
return nil
}
// SetCondition sets or updates the Condition on Conditions for Condition.Type.
// If there is an update, Conditions are stored back sorted.
func (r conditionsImpl) SetCondition(new Condition) {
if r.accessor == nil {
return
}
t := new.Type
var conditions Conditions
for _, c := range r.accessor.GetConditions() {
if c.Type != t {
conditions = append(conditions, c)
} else {
// If we'd only update the LastTransitionTime, then return.
new.LastTransitionTime = c.LastTransitionTime
if reflect.DeepEqual(&new, &c) {
return
}
}
}
new.LastTransitionTime = apis.VolatileTime{Inner: metav1.NewTime(time.Now())}
conditions = append(conditions, new)
// Sorted for convenience of the consumer, i.e. kubectl.
sort.Slice(conditions, func(i, j int) bool { return conditions[i].Type < conditions[j].Type })
r.accessor.SetConditions(conditions)
}
func (r conditionsImpl) isTerminal(t ConditionType) bool {
for _, cond := range append(r.dependents, r.happy) {
if cond == t {
return true
}
}
return false
}
func (r conditionsImpl) severity(t ConditionType) ConditionSeverity {
if r.isTerminal(t) {
return ConditionSeverityError
}
return ConditionSeverityInfo
}
// MarkTrue sets the status of t to true, and then marks the happy condition to
// true if all other dependents are also true.
func (r conditionsImpl) MarkTrue(t ConditionType) {
// set the specified condition
r.SetCondition(Condition{
Type: t,
Status: corev1.ConditionTrue,
Severity: r.severity(t),
})
// check the dependents.
for _, cond := range r.dependents {
c := r.GetCondition(cond)
// Failed or Unknown conditions trump true conditions
if !c.IsTrue() {
return
}
}
// set the happy condition
r.SetCondition(Condition{
Type: r.happy,
Status: corev1.ConditionTrue,
Severity: r.severity(r.happy),
})
}
// MarkUnknown sets the status of t to Unknown and also sets the happy condition
// to Unknown if no other dependent condition is in an error state.
func (r conditionsImpl) MarkUnknown(t ConditionType, reason, messageFormat string, messageA ...interface{}) {
// set the specified condition
r.SetCondition(Condition{
Type: t,
Status: corev1.ConditionUnknown,
Reason: reason,
Message: fmt.Sprintf(messageFormat, messageA...),
Severity: r.severity(t),
})
// check the dependents.
isDependent := false
for _, cond := range r.dependents {
c := r.GetCondition(cond)
// Failed conditions trump Unknown conditions
if c.IsFalse() {
// Double check that the happy condition is also false.
happy := r.GetCondition(r.happy)
if !happy.IsFalse() {
r.MarkFalse(r.happy, reason, messageFormat, messageA)
}
return
}
if cond == t {
isDependent = true
}
}
if isDependent {
// set the happy condition, if it is one of our dependent subconditions.
r.SetCondition(Condition{
Type: r.happy,
Status: corev1.ConditionUnknown,
Reason: reason,
Message: fmt.Sprintf(messageFormat, messageA...),
Severity: r.severity(r.happy),
})
}
}
// MarkFalse sets the status of t and the happy condition to False.
func (r conditionsImpl) MarkFalse(t ConditionType, reason, messageFormat string, messageA ...interface{}) {
types := []ConditionType{t}
for _, cond := range r.dependents {
if cond == t {
types = append(types, r.happy)
}
}
for _, t := range types {
r.SetCondition(Condition{
Type: t,
Status: corev1.ConditionFalse,
Reason: reason,
Message: fmt.Sprintf(messageFormat, messageA...),
Severity: r.severity(t),
})
}
}
// InitializeConditions updates all Conditions in the ConditionSet to Unknown
// if not set.
func (r conditionsImpl) InitializeConditions() {
for _, t := range append(r.dependents, r.happy) {
r.InitializeCondition(t)
}
}
// InitializeCondition updates a Condition to Unknown if not set.
func (r conditionsImpl) InitializeCondition(t ConditionType) {
if c := r.GetCondition(t); c == nil {
r.SetCondition(Condition{
Type: t,
Status: corev1.ConditionUnknown,
Severity: r.severity(t),
})
}
}
// NewReflectedConditionsAccessor uses reflection to return a ConditionsAccessor
// to access the field called "Conditions".
func NewReflectedConditionsAccessor(status interface{}) ConditionsAccessor {
statusValue := reflect.Indirect(reflect.ValueOf(status))
// If status is not a struct, don't even try to use it.
if statusValue.Kind() != reflect.Struct {
return nil
}
conditionsField := statusValue.FieldByName("Conditions")
if conditionsField.IsValid() && conditionsField.CanInterface() && conditionsField.CanSet() {
if _, ok := conditionsField.Interface().(Conditions); ok {
return &reflectedConditionsAccessor{
conditions: conditionsField,
}
}
}
return nil
}
// reflectedConditionsAccessor is an internal wrapper object to act as the
// ConditionsAccessor for status objects that do not implement ConditionsAccessor
// directly, but do expose the field using the "Conditions" field name.
type reflectedConditionsAccessor struct {
conditions reflect.Value
}
// GetConditions uses reflection to return Conditions from the held status object.
func (r *reflectedConditionsAccessor) GetConditions() Conditions {
if r != nil && r.conditions.IsValid() && r.conditions.CanInterface() {
if conditions, ok := r.conditions.Interface().(Conditions); ok {
return conditions
}
}
return Conditions(nil)
}
// SetConditions uses reflection to set Conditions on the held status object.
func (r *reflectedConditionsAccessor) SetConditions(conditions Conditions) {
if r != nil && r.conditions.IsValid() && r.conditions.CanSet() {
r.conditions.Set(reflect.ValueOf(conditions))
}
}

View File

@@ -0,0 +1,186 @@
/*
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 (
"time"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"github.com/knative/pkg/apis"
"github.com/knative/pkg/apis/duck"
)
// Conditions is the schema for the conditions portion of the payload
type Conditions []Condition
// ConditionType is a camel-cased condition type.
type ConditionType string
const (
// ConditionReady specifies that the resource is ready.
// For long-running resources.
ConditionReady ConditionType = "Ready"
// ConditionSucceeded specifies that the resource has finished.
// For resource which run to completion.
ConditionSucceeded ConditionType = "Succeeded"
)
// ConditionSeverity expresses the severity of a Condition Type failing.
type ConditionSeverity string
const (
// ConditionSeverityError specifies that a failure of a condition type
// should be viewed as an error.
ConditionSeverityError ConditionSeverity = "Error"
// ConditionSeverityWarning specifies that a failure of a condition type
// should be viewed as a warning, but that things could still work.
ConditionSeverityWarning ConditionSeverity = "Warning"
// ConditionSeverityInfo specifies that a failure of a condition type
// should be viewed as purely informational, and that things could still work.
ConditionSeverityInfo ConditionSeverity = "Info"
)
// Conditions defines a readiness condition for a Knative resource.
// See: https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md#typical-status-properties
// +k8s:deepcopy-gen=true
type Condition struct {
// Type of condition.
// +required
Type ConditionType `json:"type" description:"type of status condition"`
// Status of the condition, one of True, False, Unknown.
// +required
Status corev1.ConditionStatus `json:"status" description:"status of the condition, one of True, False, Unknown"`
// Severity with which to treat failures of this type of condition.
// When this is not specified, it defaults to Error.
// +optional
Severity ConditionSeverity `json:"severity,omitempty" description:"how to interpret failures of this condition, one of Error, Warning, Info"`
// LastTransitionTime is the last time the condition transitioned from one status to another.
// We use VolatileTime in place of metav1.Time to exclude this from creating equality.Semantic
// differences (all other things held constant).
// +optional
LastTransitionTime apis.VolatileTime `json:"lastTransitionTime,omitempty" description:"last time the condition transit from one status to another"`
// The reason for the condition's last transition.
// +optional
Reason string `json:"reason,omitempty" description:"one-word CamelCase reason for the condition's last transition"`
// A human readable message indicating details about the transition.
// +optional
Message string `json:"message,omitempty" description:"human-readable message indicating details about last transition"`
}
// IsTrue is true if the condition is True
func (c *Condition) IsTrue() bool {
if c == nil {
return false
}
return c.Status == corev1.ConditionTrue
}
// IsFalse is true if the condition is False
func (c *Condition) IsFalse() bool {
if c == nil {
return false
}
return c.Status == corev1.ConditionFalse
}
// IsUnknown is true if the condition is Unknown
func (c *Condition) IsUnknown() bool {
if c == nil {
return true
}
return c.Status == corev1.ConditionUnknown
}
// Conditions is an Implementable "duck type".
var _ duck.Implementable = (*Conditions)(nil)
// +genclient
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// KResource is a skeleton type wrapping Conditions in the manner we expect
// resource writers defining compatible resources to embed it. We will
// typically use this type to deserialize Conditions ObjectReferences and
// access the Conditions data. This is not a real resource.
type KResource struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Status KResourceStatus `json:"status"`
}
// KResourceStatus shows how we expect folks to embed Conditions in
// their Status field.
type KResourceStatus struct {
Conditions Conditions `json:"conditions,omitempty"`
}
func (krs *KResourceStatus) GetConditions() Conditions {
return krs.Conditions
}
func (krs *KResourceStatus) SetConditions(conditions Conditions) {
krs.Conditions = conditions
}
// Ensure KResourceStatus satisfies ConditionsAccessor
var _ ConditionsAccessor = (*KResourceStatus)(nil)
// In order for Conditions to be Implementable, KResource must be Populatable.
var _ duck.Populatable = (*KResource)(nil)
// Ensure KResource satisfies apis.Listable
var _ apis.Listable = (*KResource)(nil)
// GetFullType implements duck.Implementable
func (_ *Conditions) GetFullType() duck.Populatable {
return &KResource{}
}
// Populate implements duck.Populatable
func (t *KResource) Populate() {
t.Status.Conditions = Conditions{{
// Populate ALL fields
Type: "Birthday",
Status: corev1.ConditionTrue,
LastTransitionTime: apis.VolatileTime{Inner: metav1.NewTime(time.Date(1984, 02, 28, 18, 52, 00, 00, time.UTC))},
Reason: "Celebrate",
Message: "n3wScott, find your party hat :tada:",
}}
}
// GetListType implements apis.Listable
func (r *KResource) GetListType() runtime.Object {
return &KResourceList{}
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// KResourceList is a list of KResource resources
type KResourceList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata"`
Items []KResource `json:"items"`
}

View File

@@ -0,0 +1,23 @@
/*
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.
*/
// Api versions allow the api contract for a resource to be changed while keeping
// backward compatibility by support multiple concurrent versions
// of the same resource
// +k8s:deepcopy-gen=package
// +groupName=duck.knative.dev
package v1alpha1

View File

@@ -0,0 +1,82 @@
/*
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 (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"github.com/knative/pkg/apis"
"github.com/knative/pkg/apis/duck"
)
// Generation is the schema for the generational portion of the payload
type Generation int64
// Generation is an Implementable "duck type".
var _ duck.Implementable = (*Generation)(nil)
// +genclient
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// Generational is a skeleton type wrapping Generation in the manner we expect
// resource writers defining compatible resources to embed it. We will
// typically use this type to deserialize Generation ObjectReferences and
// access the Generation data. This is not a real resource.
type Generational struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec GenerationalSpec `json:"spec"`
}
// GenerationalSpec shows how we expect folks to embed Generation in
// their Spec field.
type GenerationalSpec struct {
Generation Generation `json:"generation,omitempty"`
}
// In order for Generation to be Implementable, Generational must be Populatable.
var _ duck.Populatable = (*Generational)(nil)
// Ensure Generational satisfies apis.Listable
var _ apis.Listable = (*Generational)(nil)
// GetFullType implements duck.Implementable
func (_ *Generation) GetFullType() duck.Populatable {
return &Generational{}
}
// Populate implements duck.Populatable
func (t *Generational) Populate() {
t.Spec.Generation = 1234
}
// GetListType implements apis.Listable
func (r *Generational) GetListType() runtime.Object {
return &GenerationalList{}
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// GenerationalList is a list of Generational resources
type GenerationalList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata"`
Items []Generational `json:"items"`
}

View File

@@ -0,0 +1,95 @@
/*
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 (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"github.com/knative/pkg/apis"
"github.com/knative/pkg/apis/duck"
)
// LegacyTargetable left around until we migrate to Addressable in the
// dependent resources. Addressable has more structure in the way it
// defines the fields. LegacyTargetable only assumed a single string
// in the Status field and we're moving towards defining proper structs
// under Status rather than strings.
// This is to support existing resources until they migrate.
//
// Do not use this for anything new, use Addressable
// LegacyTargetable is the old schema for the addressable portion
// of the payload
//
// For new resources use Addressable.
type LegacyTargetable struct {
DomainInternal string `json:"domainInternal,omitempty"`
}
// LegacyTargetable is an Implementable "duck type".
var _ duck.Implementable = (*LegacyTargetable)(nil)
// +genclient
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// LegacyTarget is a skeleton type wrapping LegacyTargetable in the manner we
// want to support unless they get migrated into supporting Legacy.
// We will typically use this type to deserialize LegacyTargetable
// ObjectReferences and access the LegacyTargetable data. This is not a
// real resource.
// ** Do not use this for any new resources **
type LegacyTarget struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Status LegacyTargetable `json:"status"`
}
// In order for LegacyTargetable to be Implementable, LegacyTarget must be Populatable.
var _ duck.Populatable = (*LegacyTarget)(nil)
// Ensure LegacyTarget satisfies apis.Listable
var _ apis.Listable = (*LegacyTarget)(nil)
// GetFullType implements duck.Implementable
func (_ *LegacyTargetable) GetFullType() duck.Populatable {
return &LegacyTarget{}
}
// Populate implements duck.Populatable
func (t *LegacyTarget) Populate() {
t.Status = LegacyTargetable{
// Populate ALL fields
DomainInternal: "this is not empty",
}
}
// GetListType implements apis.Listable
func (r *LegacyTarget) GetListType() runtime.Object {
return &LegacyTargetList{}
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// LegacyTargetList is a list of LegacyTarget resources
type LegacyTargetList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata"`
Items []LegacyTarget `json:"items"`
}

View File

@@ -0,0 +1,61 @@
/*
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/pkg/apis/duck"
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: duck.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,
&KResource{},
(&KResource{}).GetListType(),
&Generational{},
(&Generational{}).GetListType(),
&AddressableType{},
(&AddressableType{}).GetListType(),
&Target{},
(&Target{}).GetListType(),
&LegacyTarget{},
(&LegacyTarget{}).GetListType(),
)
metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
return nil
}

View File

@@ -0,0 +1,97 @@
/*
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 (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"github.com/knative/pkg/apis"
"github.com/knative/pkg/apis/duck"
)
// Targetable is an earlier version of the Callable interface.
// Callable is a higher-level interface which implements Addressable
// but further promises that the destination may synchronously return
// response messages in reply to a message.
//
// Targetable implementations should instead implement Addressable and
// include an `eventing.knative.dev/returns=any` annotation.
// Targetable is retired; implement Addressable for now.
type Targetable struct {
DomainInternal string `json:"domainInternal,omitempty"`
}
// Targetable is an Implementable "duck type".
var _ duck.Implementable = (*Targetable)(nil)
// +genclient
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// Target is a skeleton type wrapping Targetable in the manner we expect
// resource writers defining compatible resources to embed it. We will
// typically use this type to deserialize Targetable ObjectReferences and
// access the Targetable data. This is not a real resource.
type Target struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Status TargetStatus `json:"status"`
}
// TargetStatus shows how we expect folks to embed Targetable in
// their Status field.
type TargetStatus struct {
Targetable *Targetable `json:"targetable,omitempty"`
}
// In order for Targetable to be Implementable, Target must be Populatable.
var _ duck.Populatable = (*Target)(nil)
// Ensure Target satisfies apis.Listable
var _ apis.Listable = (*Target)(nil)
// GetFullType implements duck.Implementable
func (_ *Targetable) GetFullType() duck.Populatable {
return &Target{}
}
// Populate implements duck.Populatable
func (t *Target) Populate() {
t.Status = TargetStatus{
&Targetable{
// Populate ALL fields
DomainInternal: "this is not empty",
},
}
}
// GetListType implements apis.Listable
func (r *Target) GetListType() runtime.Object {
return &TargetList{}
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// TargetList is a list of Target resources
type TargetList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata"`
Items []Target `json:"items"`
}

View File

@@ -0,0 +1,493 @@
// +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 (
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 *AddressStatus) DeepCopyInto(out *AddressStatus) {
*out = *in
if in.Address != nil {
in, out := &in.Address, &out.Address
*out = new(Addressable)
**out = **in
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AddressStatus.
func (in *AddressStatus) DeepCopy() *AddressStatus {
if in == nil {
return nil
}
out := new(AddressStatus)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Addressable) DeepCopyInto(out *Addressable) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Addressable.
func (in *Addressable) DeepCopy() *Addressable {
if in == nil {
return nil
}
out := new(Addressable)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *AddressableType) DeepCopyInto(out *AddressableType) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
in.Status.DeepCopyInto(&out.Status)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AddressableType.
func (in *AddressableType) DeepCopy() *AddressableType {
if in == nil {
return nil
}
out := new(AddressableType)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *AddressableType) 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 *AddressableTypeList) DeepCopyInto(out *AddressableTypeList) {
*out = *in
out.TypeMeta = in.TypeMeta
out.ListMeta = in.ListMeta
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]AddressableType, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AddressableTypeList.
func (in *AddressableTypeList) DeepCopy() *AddressableTypeList {
if in == nil {
return nil
}
out := new(AddressableTypeList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *AddressableTypeList) 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 *Condition) DeepCopyInto(out *Condition) {
*out = *in
in.LastTransitionTime.DeepCopyInto(&out.LastTransitionTime)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Condition.
func (in *Condition) DeepCopy() *Condition {
if in == nil {
return nil
}
out := new(Condition)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in Conditions) DeepCopyInto(out *Conditions) {
{
in := &in
*out = make(Conditions, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
return
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Conditions.
func (in Conditions) DeepCopy() Conditions {
if in == nil {
return nil
}
out := new(Conditions)
in.DeepCopyInto(out)
return *out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Generational) DeepCopyInto(out *Generational) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
out.Spec = in.Spec
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Generational.
func (in *Generational) DeepCopy() *Generational {
if in == nil {
return nil
}
out := new(Generational)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *Generational) 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 *GenerationalList) DeepCopyInto(out *GenerationalList) {
*out = *in
out.TypeMeta = in.TypeMeta
out.ListMeta = in.ListMeta
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]Generational, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GenerationalList.
func (in *GenerationalList) DeepCopy() *GenerationalList {
if in == nil {
return nil
}
out := new(GenerationalList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *GenerationalList) 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 *GenerationalSpec) DeepCopyInto(out *GenerationalSpec) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GenerationalSpec.
func (in *GenerationalSpec) DeepCopy() *GenerationalSpec {
if in == nil {
return nil
}
out := new(GenerationalSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *KResource) DeepCopyInto(out *KResource) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
in.Status.DeepCopyInto(&out.Status)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KResource.
func (in *KResource) DeepCopy() *KResource {
if in == nil {
return nil
}
out := new(KResource)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *KResource) 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 *KResourceList) DeepCopyInto(out *KResourceList) {
*out = *in
out.TypeMeta = in.TypeMeta
out.ListMeta = in.ListMeta
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]KResource, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KResourceList.
func (in *KResourceList) DeepCopy() *KResourceList {
if in == nil {
return nil
}
out := new(KResourceList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *KResourceList) 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 *KResourceStatus) DeepCopyInto(out *KResourceStatus) {
*out = *in
if in.Conditions != nil {
in, out := &in.Conditions, &out.Conditions
*out = make(Conditions, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KResourceStatus.
func (in *KResourceStatus) DeepCopy() *KResourceStatus {
if in == nil {
return nil
}
out := new(KResourceStatus)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *LegacyTarget) DeepCopyInto(out *LegacyTarget) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
out.Status = in.Status
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LegacyTarget.
func (in *LegacyTarget) DeepCopy() *LegacyTarget {
if in == nil {
return nil
}
out := new(LegacyTarget)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *LegacyTarget) 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 *LegacyTargetList) DeepCopyInto(out *LegacyTargetList) {
*out = *in
out.TypeMeta = in.TypeMeta
out.ListMeta = in.ListMeta
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]LegacyTarget, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LegacyTargetList.
func (in *LegacyTargetList) DeepCopy() *LegacyTargetList {
if in == nil {
return nil
}
out := new(LegacyTargetList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *LegacyTargetList) 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 *LegacyTargetable) DeepCopyInto(out *LegacyTargetable) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LegacyTargetable.
func (in *LegacyTargetable) DeepCopy() *LegacyTargetable {
if in == nil {
return nil
}
out := new(LegacyTargetable)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Target) DeepCopyInto(out *Target) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
in.Status.DeepCopyInto(&out.Status)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Target.
func (in *Target) DeepCopy() *Target {
if in == nil {
return nil
}
out := new(Target)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *Target) 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 *TargetList) DeepCopyInto(out *TargetList) {
*out = *in
out.TypeMeta = in.TypeMeta
out.ListMeta = in.ListMeta
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]Target, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TargetList.
func (in *TargetList) DeepCopy() *TargetList {
if in == nil {
return nil
}
out := new(TargetList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *TargetList) 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 *TargetStatus) DeepCopyInto(out *TargetStatus) {
*out = *in
if in.Targetable != nil {
in, out := &in.Targetable, &out.Targetable
*out = new(Targetable)
**out = **in
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TargetStatus.
func (in *TargetStatus) DeepCopy() *TargetStatus {
if in == nil {
return nil
}
out := new(TargetStatus)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Targetable) DeepCopyInto(out *Targetable) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Targetable.
func (in *Targetable) DeepCopy() *Targetable {
if in == nil {
return nil
}
out := new(Targetable)
in.DeepCopyInto(out)
return out
}

85
vendor/github.com/knative/pkg/apis/duck/verify.go generated vendored Normal file
View File

@@ -0,0 +1,85 @@
/*
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 duck
import (
"encoding/json"
"fmt"
"github.com/google/go-cmp/cmp"
)
// Implementable is implemented by the Fooable duck type that consumers
// are expected to embed as a `.status.fooable` field.
type Implementable interface {
// GetFullType returns an instance of a full resource wrapping
// an instance of this Implementable that can populate its fields
// to verify json roundtripping.
GetFullType() Populatable
}
// Populatable is implemented by a skeleton resource wrapping an Implementable
// duck type. It will generally have TypeMeta, ObjectMeta, and a Status field
// wrapping a Fooable field.
type Populatable interface {
// Populate fills in all possible fields, so that we can verify that
// they roundtrip properly through JSON.
Populate()
}
// VerifyType verifies that a particular concrete resource properly implements
// the provided Implementable duck type. It is expected that under the resource
// definition implementing a particular "Fooable" that one would write:
//
// type ConcreteResource struct { ... }
//
// // Check that ConcreteResource properly implement Fooable.
// err := duck.VerifyType(&ConcreteResource{}, &something.Fooable{})
//
// This will return an error if the duck typing is not satisfied.
func VerifyType(instance interface{}, iface Implementable) error {
// Create instances of the full resource for our input and ultimate result
// that we will compare at the end.
input, output := iface.GetFullType(), iface.GetFullType()
// Populate our input resource with values we will roundtrip.
input.Populate()
// Serialize the input to JSON and deserialize that into the provided instance
// of the type that we are checking.
if before, err := json.Marshal(input); err != nil {
return fmt.Errorf("error serializing duck type %T", input)
} else if err := json.Unmarshal(before, instance); err != nil {
return fmt.Errorf("error deserializing duck type %T into %T", input, instance)
}
// Serialize the instance we are checking to JSON and deserialize that into the
// output resource.
if after, err := json.Marshal(instance); err != nil {
return fmt.Errorf("error serializing %T", instance)
} else if err := json.Unmarshal(after, output); err != nil {
return fmt.Errorf("error deserializing %T into dock type %T", instance, output)
}
// Now verify that we were able to roundtrip all of our fields through the type
// we are checking.
if diff := cmp.Diff(input, output); diff != "" {
return fmt.Errorf("%T does not implement the duck type %T, the following fields were lost: %s",
instance, iface, diff)
}
return nil
}

346
vendor/github.com/knative/pkg/apis/field_error.go generated vendored Normal file
View File

@@ -0,0 +1,346 @@
/*
Copyright 2017 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 apis
import (
"fmt"
"sort"
"strings"
)
// CurrentField is a constant to supply as a fieldPath for when there is
// a problem with the current field itself.
const CurrentField = ""
// FieldError is used to propagate the context of errors pertaining to
// specific fields in a manner suitable for use in a recursive walk, so
// that errors contain the appropriate field context.
// FieldError methods are non-mutating.
// +k8s:deepcopy-gen=true
type FieldError struct {
Message string
Paths []string
// Details contains an optional longer payload.
// +optional
Details string
errors []FieldError
}
// FieldError implements error
var _ error = (*FieldError)(nil)
// ViaField is used to propagate a validation error along a field access.
// For example, if a type recursively validates its "spec" via:
// if err := foo.Spec.Validate(); err != nil {
// // Augment any field paths with the context that they were accessed
// // via "spec".
// return err.ViaField("spec")
// }
func (fe *FieldError) ViaField(prefix ...string) *FieldError {
if fe == nil {
return nil
}
// Copy over message and details, paths will be updated and errors come
// along using .Also().
newErr := &FieldError{
Message: fe.Message,
Details: fe.Details,
}
// Prepend the Prefix to existing errors.
newPaths := make([]string, 0, len(fe.Paths))
for _, oldPath := range fe.Paths {
newPaths = append(newPaths, flatten(append(prefix, oldPath)))
}
newErr.Paths = newPaths
for _, e := range fe.errors {
newErr = newErr.Also(e.ViaField(prefix...))
}
return newErr
}
// ViaIndex is used to attach an index to the next ViaField provided.
// For example, if a type recursively validates a parameter that has a collection:
// for i, c := range spec.Collection {
// if err := doValidation(c); err != nil {
// return err.ViaIndex(i).ViaField("collection")
// }
// }
func (fe *FieldError) ViaIndex(index int) *FieldError {
return fe.ViaField(asIndex(index))
}
// ViaFieldIndex is the short way to chain: err.ViaIndex(bar).ViaField(foo)
func (fe *FieldError) ViaFieldIndex(field string, index int) *FieldError {
return fe.ViaIndex(index).ViaField(field)
}
// ViaKey is used to attach a key to the next ViaField provided.
// For example, if a type recursively validates a parameter that has a collection:
// for k, v := range spec.Bag. {
// if err := doValidation(v); err != nil {
// return err.ViaKey(k).ViaField("bag")
// }
// }
func (fe *FieldError) ViaKey(key string) *FieldError {
return fe.ViaField(asKey(key))
}
// ViaFieldKey is the short way to chain: err.ViaKey(bar).ViaField(foo)
func (fe *FieldError) ViaFieldKey(field string, key string) *FieldError {
return fe.ViaKey(key).ViaField(field)
}
// Also collects errors, returns a new collection of existing errors and new errors.
func (fe *FieldError) Also(errs ...*FieldError) *FieldError {
var newErr *FieldError
// collect the current objects errors, if it has any
if !fe.isEmpty() {
newErr = fe.DeepCopy()
} else {
newErr = &FieldError{}
}
// and then collect the passed in errors
for _, e := range errs {
if !e.isEmpty() {
newErr.errors = append(newErr.errors, *e)
}
}
if newErr.isEmpty() {
return nil
}
return newErr
}
func (fe *FieldError) isEmpty() bool {
if fe == nil {
return true
}
return fe.Message == "" && fe.Details == "" && len(fe.errors) == 0 && len(fe.Paths) == 0
}
func (fe *FieldError) getNormalizedErrors() []FieldError {
// in case we call getNormalizedErrors on a nil object, return just an empty
// list. This can happen when .Error() is called on a nil object.
if fe == nil {
return []FieldError(nil)
}
var errors []FieldError
// if this FieldError is a leaf,
if fe.Message != "" {
err := FieldError{
Message: fe.Message,
Paths: fe.Paths,
Details: fe.Details,
}
errors = append(errors, err)
}
// and then collect all other errors recursively.
for _, e := range fe.errors {
errors = append(errors, e.getNormalizedErrors()...)
}
return errors
}
// Error implements error
func (fe *FieldError) Error() string {
var errs []string
// Get the list of errors as a flat merged list.
normedErrors := merge(fe.getNormalizedErrors())
for _, e := range normedErrors {
if e.Details == "" {
errs = append(errs, fmt.Sprintf("%v: %v", e.Message, strings.Join(e.Paths, ", ")))
} else {
errs = append(errs, fmt.Sprintf("%v: %v\n%v", e.Message, strings.Join(e.Paths, ", "), e.Details))
}
}
return strings.Join(errs, "\n")
}
// Helpers ---
func asIndex(index int) string {
return fmt.Sprintf("[%d]", index)
}
func isIndex(part string) bool {
return strings.HasPrefix(part, "[") && strings.HasSuffix(part, "]")
}
func asKey(key string) string {
return fmt.Sprintf("[%s]", key)
}
// flatten takes in a array of path components and looks for chances to flatten
// objects that have index prefixes, examples:
// err([0]).ViaField(bar).ViaField(foo) -> foo.bar.[0] converts to foo.bar[0]
// err(bar).ViaIndex(0).ViaField(foo) -> foo.[0].bar converts to foo[0].bar
// err(bar).ViaField(foo).ViaIndex(0) -> [0].foo.bar converts to [0].foo.bar
// err(bar).ViaIndex(0).ViaIndex[1].ViaField(foo) -> foo.[1].[0].bar converts to foo[1][0].bar
func flatten(path []string) string {
var newPath []string
for _, part := range path {
for _, p := range strings.Split(part, ".") {
if p == CurrentField {
continue
} else if len(newPath) > 0 && isIndex(p) {
newPath[len(newPath)-1] = fmt.Sprintf("%s%s", newPath[len(newPath)-1], p)
} else {
newPath = append(newPath, p)
}
}
}
return strings.Join(newPath, ".")
}
// mergePaths takes in two string slices and returns the combination of them
// without any duplicate entries.
func mergePaths(a, b []string) []string {
newPaths := make([]string, 0, len(a)+len(b))
newPaths = append(newPaths, a...)
for _, bi := range b {
if !containsString(newPaths, bi) {
newPaths = append(newPaths, bi)
}
}
return newPaths
}
// containsString takes in a string slice and looks for the provided string
// within the slice.
func containsString(slice []string, s string) bool {
for _, item := range slice {
if item == s {
return true
}
}
return false
}
// merge takes in a flat list of FieldErrors and returns back a merged list of
// FiledErrors. FieldErrors have their Paths combined (and de-duped) if their
// Message and Details are the same. Merge will not inspect FieldError.errors.
// Merge will also sort the .Path slice, and the errors slice before returning.
func merge(errs []FieldError) []FieldError {
// make a map big enough for all the errors.
m := make(map[string]FieldError, len(errs))
// Convert errs to a map where the key is <message>-<details> and the value
// is the error. If an error already exists in the map with the same key,
// then the paths will be merged.
for _, e := range errs {
k := key(&e)
if v, ok := m[k]; ok {
// Found a match, merge the keys.
v.Paths = mergePaths(v.Paths, e.Paths)
m[k] = v
} else {
// Does not exist in the map, save the error.
m[k] = e
}
}
// Take the map made previously and flatten it back out again.
newErrs := make([]FieldError, 0, len(m))
for _, v := range m {
// While we have access to the merged paths, sort them too.
sort.Slice(v.Paths, func(i, j int) bool { return v.Paths[i] < v.Paths[j] })
newErrs = append(newErrs, v)
}
// Sort the flattened map.
sort.Slice(newErrs, func(i, j int) bool {
if newErrs[i].Message == newErrs[j].Message {
return newErrs[i].Details < newErrs[j].Details
}
return newErrs[i].Message < newErrs[j].Message
})
// return back the merged list of sorted errors.
return newErrs
}
// key returns the key using the fields .Message and .Details.
func key(err *FieldError) string {
return fmt.Sprintf("%s-%s", err.Message, err.Details)
}
// Public helpers ---
// ErrMissingField is a variadic helper method for constructing a FieldError for
// a set of missing fields.
func ErrMissingField(fieldPaths ...string) *FieldError {
return &FieldError{
Message: "missing field(s)",
Paths: fieldPaths,
}
}
// ErrDisallowedFields is a variadic helper method for constructing a FieldError
// for a set of disallowed fields.
func ErrDisallowedFields(fieldPaths ...string) *FieldError {
return &FieldError{
Message: "must not set the field(s)",
Paths: fieldPaths,
}
}
// ErrInvalidValue constructs a FieldError for a field that has received an
// invalid string value.
func ErrInvalidValue(value, fieldPath string) *FieldError {
return &FieldError{
Message: fmt.Sprintf("invalid value %q", value),
Paths: []string{fieldPath},
}
}
// ErrMissingOneOf is a variadic helper method for constructing a FieldError for
// not having at least one field in a mutually exclusive field group.
func ErrMissingOneOf(fieldPaths ...string) *FieldError {
return &FieldError{
Message: "expected exactly one, got neither",
Paths: fieldPaths,
}
}
// ErrMultipleOneOf is a variadic helper method for constructing a FieldError
// for having more than one field set in a mutually exclusive field group.
func ErrMultipleOneOf(fieldPaths ...string) *FieldError {
return &FieldError{
Message: "expected exactly one, got both",
Paths: fieldPaths,
}
}
// ErrInvalidKeyName is a variadic helper method for constructing a FieldError
// that specifies a key name that is invalid.
func ErrInvalidKeyName(value, fieldPath string, details ...string) *FieldError {
return &FieldError{
Message: fmt.Sprintf("invalid key name %q", value),
Paths: []string{fieldPath},
Details: strings.Join(details, ", "),
}
}
// ErrOutOFBoundsValue constructs a FieldError for a field that has received an
// out of bound value.
func ErrOutOfBoundsValue(value, lower, upper, fieldPath string) *FieldError {
return &FieldError{
Message: fmt.Sprintf("expected %s <= %s <= %s", lower, value, upper),
Paths: []string{fieldPath},
}
}

49
vendor/github.com/knative/pkg/apis/interfaces.go generated vendored Normal file
View File

@@ -0,0 +1,49 @@
/*
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 apis
import (
"k8s.io/apimachinery/pkg/runtime"
)
// Defaultable defines an interface for setting the defaults for the
// uninitialized fields of this instance.
type Defaultable interface {
SetDefaults()
}
// Validatable indicates that a particular type may have its fields validated.
type Validatable interface {
// Validate checks the validity of this types fields.
Validate() *FieldError
}
// Immutable indicates that a particular type has fields that should
// not change after creation.
type Immutable interface {
// CheckImmutableFields checks that the current instance's immutable
// fields haven't changed from the provided original.
CheckImmutableFields(original Immutable) *FieldError
}
// Listable indicates that a particular type can be returned via the returned
// list type by the API server.
type Listable interface {
runtime.Object
GetListType() runtime.Object
}

47
vendor/github.com/knative/pkg/apis/kind2resource.go generated vendored Normal file
View File

@@ -0,0 +1,47 @@
/*
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 apis
import (
"fmt"
"strings"
"k8s.io/apimachinery/pkg/runtime/schema"
)
// KindToResource converts a GroupVersionKind to a GroupVersionResource
// through the world's simplest (worst) pluralizer.
func KindToResource(gvk schema.GroupVersionKind) schema.GroupVersionResource {
return schema.GroupVersionResource{
Group: gvk.Group,
Version: gvk.Version,
Resource: pluralizeKind(gvk.Kind),
}
}
// Takes a kind and pluralizes it. This is super terrible, but I am
// not aware of a generic way to do this.
// I am not alone in thinking this and I haven't found a better solution:
// This seems relevant:
// https://github.com/kubernetes/kubernetes/issues/18622
func pluralizeKind(kind string) string {
ret := strings.ToLower(kind)
if strings.HasSuffix(ret, "s") {
return fmt.Sprintf("%ses", ret)
}
return fmt.Sprintf("%ss", ret)
}

46
vendor/github.com/knative/pkg/apis/volatile_time.go generated vendored Normal file
View File

@@ -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.
*/
package apis
import (
"k8s.io/apimachinery/pkg/api/equality"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// VolatileTime wraps metav1.Time
type VolatileTime struct {
Inner metav1.Time
}
// MarshalJSON implements the json.Marshaler interface.
func (t VolatileTime) MarshalJSON() ([]byte, error) {
return t.Inner.MarshalJSON()
}
// UnmarshalJSON implements the json.Unmarshaller interface.
func (t *VolatileTime) UnmarshalJSON(b []byte) error {
return t.Inner.UnmarshalJSON(b)
}
func init() {
equality.Semantic.AddFunc(
// Always treat VolatileTime fields as equivalent.
func(a, b VolatileTime) bool {
return true
},
)
}

View File

@@ -0,0 +1,66 @@
// +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 apis
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *FieldError) DeepCopyInto(out *FieldError) {
*out = *in
if in.Paths != nil {
in, out := &in.Paths, &out.Paths
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.errors != nil {
in, out := &in.errors, &out.errors
*out = make([]FieldError, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FieldError.
func (in *FieldError) DeepCopy() *FieldError {
if in == nil {
return nil
}
out := new(FieldError)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *VolatileTime) DeepCopyInto(out *VolatileTime) {
*out = *in
in.Inner.DeepCopyInto(&out.Inner)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VolatileTime.
func (in *VolatileTime) DeepCopy() *VolatileTime {
if in == nil {
return nil
}
out := new(VolatileTime)
in.DeepCopyInto(out)
return out
}