mirror of
https://github.com/ceph/ceph-csi.git
synced 2025-06-13 02:33:34 +00:00
build: move e2e dependencies into e2e/go.mod
Several packages are only used while running the e2e suite. These packages are less important to update, as the they can not influence the final executable that is part of the Ceph-CSI container-image. By moving these dependencies out of the main Ceph-CSI go.mod, it is easier to identify if a reported CVE affects Ceph-CSI, or only the testing (like most of the Kubernetes CVEs). Signed-off-by: Niels de Vos <ndevos@ibm.com>
This commit is contained in:
committed by
mergify[bot]
parent
15da101b1b
commit
bec6090996
188
e2e/vendor/k8s.io/client-go/dynamic/dynamicinformer/informer.go
generated
vendored
Normal file
188
e2e/vendor/k8s.io/client-go/dynamic/dynamicinformer/informer.go
generated
vendored
Normal file
@ -0,0 +1,188 @@
|
||||
/*
|
||||
Copyright 2018 The Kubernetes 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 dynamicinformer
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
"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/dynamic/dynamiclister"
|
||||
"k8s.io/client-go/informers"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
// NewDynamicSharedInformerFactory constructs a new instance of dynamicSharedInformerFactory for all namespaces.
|
||||
func NewDynamicSharedInformerFactory(client dynamic.Interface, defaultResync time.Duration) DynamicSharedInformerFactory {
|
||||
return NewFilteredDynamicSharedInformerFactory(client, defaultResync, metav1.NamespaceAll, nil)
|
||||
}
|
||||
|
||||
// NewFilteredDynamicSharedInformerFactory constructs a new instance of dynamicSharedInformerFactory.
|
||||
// Listers obtained via this factory will be subject to the same filters as specified here.
|
||||
func NewFilteredDynamicSharedInformerFactory(client dynamic.Interface, defaultResync time.Duration, namespace string, tweakListOptions TweakListOptionsFunc) DynamicSharedInformerFactory {
|
||||
return &dynamicSharedInformerFactory{
|
||||
client: client,
|
||||
defaultResync: defaultResync,
|
||||
namespace: namespace,
|
||||
informers: map[schema.GroupVersionResource]informers.GenericInformer{},
|
||||
startedInformers: make(map[schema.GroupVersionResource]bool),
|
||||
tweakListOptions: tweakListOptions,
|
||||
}
|
||||
}
|
||||
|
||||
type dynamicSharedInformerFactory struct {
|
||||
client dynamic.Interface
|
||||
defaultResync time.Duration
|
||||
namespace string
|
||||
|
||||
lock sync.Mutex
|
||||
informers map[schema.GroupVersionResource]informers.GenericInformer
|
||||
// startedInformers is used for tracking which informers have been started.
|
||||
// This allows Start() to be called multiple times safely.
|
||||
startedInformers map[schema.GroupVersionResource]bool
|
||||
tweakListOptions TweakListOptionsFunc
|
||||
|
||||
// wg tracks how many goroutines were started.
|
||||
wg sync.WaitGroup
|
||||
// shuttingDown is true when Shutdown has been called. It may still be running
|
||||
// because it needs to wait for goroutines.
|
||||
shuttingDown bool
|
||||
}
|
||||
|
||||
var _ DynamicSharedInformerFactory = &dynamicSharedInformerFactory{}
|
||||
|
||||
func (f *dynamicSharedInformerFactory) ForResource(gvr schema.GroupVersionResource) informers.GenericInformer {
|
||||
f.lock.Lock()
|
||||
defer f.lock.Unlock()
|
||||
|
||||
key := gvr
|
||||
informer, exists := f.informers[key]
|
||||
if exists {
|
||||
return informer
|
||||
}
|
||||
|
||||
informer = NewFilteredDynamicInformer(f.client, gvr, f.namespace, f.defaultResync, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
|
||||
f.informers[key] = informer
|
||||
|
||||
return informer
|
||||
}
|
||||
|
||||
// Start initializes all requested informers.
|
||||
func (f *dynamicSharedInformerFactory) Start(stopCh <-chan struct{}) {
|
||||
f.lock.Lock()
|
||||
defer f.lock.Unlock()
|
||||
|
||||
if f.shuttingDown {
|
||||
return
|
||||
}
|
||||
|
||||
for informerType, informer := range f.informers {
|
||||
if !f.startedInformers[informerType] {
|
||||
f.wg.Add(1)
|
||||
// We need a new variable in each loop iteration,
|
||||
// otherwise the goroutine would use the loop variable
|
||||
// and that keeps changing.
|
||||
informer := informer.Informer()
|
||||
go func() {
|
||||
defer f.wg.Done()
|
||||
informer.Run(stopCh)
|
||||
}()
|
||||
f.startedInformers[informerType] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// WaitForCacheSync waits for all started informers' cache were synced.
|
||||
func (f *dynamicSharedInformerFactory) WaitForCacheSync(stopCh <-chan struct{}) map[schema.GroupVersionResource]bool {
|
||||
informers := func() map[schema.GroupVersionResource]cache.SharedIndexInformer {
|
||||
f.lock.Lock()
|
||||
defer f.lock.Unlock()
|
||||
|
||||
informers := map[schema.GroupVersionResource]cache.SharedIndexInformer{}
|
||||
for informerType, informer := range f.informers {
|
||||
if f.startedInformers[informerType] {
|
||||
informers[informerType] = informer.Informer()
|
||||
}
|
||||
}
|
||||
return informers
|
||||
}()
|
||||
|
||||
res := map[schema.GroupVersionResource]bool{}
|
||||
for informType, informer := range informers {
|
||||
res[informType] = cache.WaitForCacheSync(stopCh, informer.HasSynced)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func (f *dynamicSharedInformerFactory) Shutdown() {
|
||||
// Will return immediately if there is nothing to wait for.
|
||||
defer f.wg.Wait()
|
||||
|
||||
f.lock.Lock()
|
||||
defer f.lock.Unlock()
|
||||
f.shuttingDown = true
|
||||
}
|
||||
|
||||
// NewFilteredDynamicInformer constructs a new informer for a dynamic type.
|
||||
func NewFilteredDynamicInformer(client dynamic.Interface, gvr schema.GroupVersionResource, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions TweakListOptionsFunc) informers.GenericInformer {
|
||||
return &dynamicInformer{
|
||||
gvr: gvr,
|
||||
informer: cache.NewSharedIndexInformerWithOptions(
|
||||
&cache.ListWatch{
|
||||
ListFunc: func(options metav1.ListOptions) (runtime.Object, error) {
|
||||
if tweakListOptions != nil {
|
||||
tweakListOptions(&options)
|
||||
}
|
||||
return client.Resource(gvr).Namespace(namespace).List(context.TODO(), options)
|
||||
},
|
||||
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
|
||||
if tweakListOptions != nil {
|
||||
tweakListOptions(&options)
|
||||
}
|
||||
return client.Resource(gvr).Namespace(namespace).Watch(context.TODO(), options)
|
||||
},
|
||||
},
|
||||
&unstructured.Unstructured{},
|
||||
cache.SharedIndexInformerOptions{
|
||||
ResyncPeriod: resyncPeriod,
|
||||
Indexers: indexers,
|
||||
ObjectDescription: gvr.String(),
|
||||
},
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
type dynamicInformer struct {
|
||||
informer cache.SharedIndexInformer
|
||||
gvr schema.GroupVersionResource
|
||||
}
|
||||
|
||||
var _ informers.GenericInformer = &dynamicInformer{}
|
||||
|
||||
func (d *dynamicInformer) Informer() cache.SharedIndexInformer {
|
||||
return d.informer
|
||||
}
|
||||
|
||||
func (d *dynamicInformer) Lister() cache.GenericLister {
|
||||
return dynamiclister.NewRuntimeObjectShim(dynamiclister.New(d.informer.GetIndexer(), d.gvr))
|
||||
}
|
53
e2e/vendor/k8s.io/client-go/dynamic/dynamicinformer/interface.go
generated
vendored
Normal file
53
e2e/vendor/k8s.io/client-go/dynamic/dynamicinformer/interface.go
generated
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
Copyright 2018 The Kubernetes 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 dynamicinformer
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/client-go/informers"
|
||||
)
|
||||
|
||||
// DynamicSharedInformerFactory provides access to a shared informer and lister for dynamic client
|
||||
type DynamicSharedInformerFactory interface {
|
||||
// Start initializes all requested informers. They are handled in goroutines
|
||||
// which run until the stop channel gets closed.
|
||||
Start(stopCh <-chan struct{})
|
||||
|
||||
// ForResource gives generic access to a shared informer of the matching type.
|
||||
ForResource(gvr schema.GroupVersionResource) informers.GenericInformer
|
||||
|
||||
// WaitForCacheSync blocks until all started informers' caches were synced
|
||||
// or the stop channel gets closed.
|
||||
WaitForCacheSync(stopCh <-chan struct{}) map[schema.GroupVersionResource]bool
|
||||
|
||||
// Shutdown marks a factory as shutting down. At that point no new
|
||||
// informers can be started anymore and Start will return without
|
||||
// doing anything.
|
||||
//
|
||||
// In addition, Shutdown blocks until all goroutines have terminated. For that
|
||||
// to happen, the close channel(s) that they were started with must be closed,
|
||||
// either before Shutdown gets called or while it is waiting.
|
||||
//
|
||||
// Shutdown may be called multiple times, even concurrently. All such calls will
|
||||
// block until all goroutines have terminated.
|
||||
Shutdown()
|
||||
}
|
||||
|
||||
// TweakListOptionsFunc defines the signature of a helper function
|
||||
// that wants to provide more listing options to API
|
||||
type TweakListOptionsFunc func(*metav1.ListOptions)
|
40
e2e/vendor/k8s.io/client-go/dynamic/dynamiclister/interface.go
generated
vendored
Normal file
40
e2e/vendor/k8s.io/client-go/dynamic/dynamiclister/interface.go
generated
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
Copyright 2018 The Kubernetes 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 dynamiclister
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
)
|
||||
|
||||
// Lister helps list resources.
|
||||
type Lister interface {
|
||||
// List lists all resources in the indexer.
|
||||
List(selector labels.Selector) (ret []*unstructured.Unstructured, err error)
|
||||
// Get retrieves a resource from the indexer with the given name
|
||||
Get(name string) (*unstructured.Unstructured, error)
|
||||
// Namespace returns an object that can list and get resources in a given namespace.
|
||||
Namespace(namespace string) NamespaceLister
|
||||
}
|
||||
|
||||
// NamespaceLister helps list and get resources.
|
||||
type NamespaceLister interface {
|
||||
// List lists all resources in the indexer for a given namespace.
|
||||
List(selector labels.Selector) (ret []*unstructured.Unstructured, err error)
|
||||
// Get retrieves a resource from the indexer for a given namespace and name.
|
||||
Get(name string) (*unstructured.Unstructured, error)
|
||||
}
|
91
e2e/vendor/k8s.io/client-go/dynamic/dynamiclister/lister.go
generated
vendored
Normal file
91
e2e/vendor/k8s.io/client-go/dynamic/dynamiclister/lister.go
generated
vendored
Normal file
@ -0,0 +1,91 @@
|
||||
/*
|
||||
Copyright 2018 The Kubernetes 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 dynamiclister
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
var _ Lister = &dynamicLister{}
|
||||
var _ NamespaceLister = &dynamicNamespaceLister{}
|
||||
|
||||
// dynamicLister implements the Lister interface.
|
||||
type dynamicLister struct {
|
||||
indexer cache.Indexer
|
||||
gvr schema.GroupVersionResource
|
||||
}
|
||||
|
||||
// New returns a new Lister.
|
||||
func New(indexer cache.Indexer, gvr schema.GroupVersionResource) Lister {
|
||||
return &dynamicLister{indexer: indexer, gvr: gvr}
|
||||
}
|
||||
|
||||
// List lists all resources in the indexer.
|
||||
func (l *dynamicLister) List(selector labels.Selector) (ret []*unstructured.Unstructured, err error) {
|
||||
err = cache.ListAll(l.indexer, selector, func(m interface{}) {
|
||||
ret = append(ret, m.(*unstructured.Unstructured))
|
||||
})
|
||||
return ret, err
|
||||
}
|
||||
|
||||
// Get retrieves a resource from the indexer with the given name
|
||||
func (l *dynamicLister) Get(name string) (*unstructured.Unstructured, error) {
|
||||
obj, exists, err := l.indexer.GetByKey(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !exists {
|
||||
return nil, errors.NewNotFound(l.gvr.GroupResource(), name)
|
||||
}
|
||||
return obj.(*unstructured.Unstructured), nil
|
||||
}
|
||||
|
||||
// Namespace returns an object that can list and get resources from a given namespace.
|
||||
func (l *dynamicLister) Namespace(namespace string) NamespaceLister {
|
||||
return &dynamicNamespaceLister{indexer: l.indexer, namespace: namespace, gvr: l.gvr}
|
||||
}
|
||||
|
||||
// dynamicNamespaceLister implements the NamespaceLister interface.
|
||||
type dynamicNamespaceLister struct {
|
||||
indexer cache.Indexer
|
||||
namespace string
|
||||
gvr schema.GroupVersionResource
|
||||
}
|
||||
|
||||
// List lists all resources in the indexer for a given namespace.
|
||||
func (l *dynamicNamespaceLister) List(selector labels.Selector) (ret []*unstructured.Unstructured, err error) {
|
||||
err = cache.ListAllByNamespace(l.indexer, l.namespace, selector, func(m interface{}) {
|
||||
ret = append(ret, m.(*unstructured.Unstructured))
|
||||
})
|
||||
return ret, err
|
||||
}
|
||||
|
||||
// Get retrieves a resource from the indexer for a given namespace and name.
|
||||
func (l *dynamicNamespaceLister) Get(name string) (*unstructured.Unstructured, error) {
|
||||
obj, exists, err := l.indexer.GetByKey(l.namespace + "/" + name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !exists {
|
||||
return nil, errors.NewNotFound(l.gvr.GroupResource(), name)
|
||||
}
|
||||
return obj.(*unstructured.Unstructured), nil
|
||||
}
|
87
e2e/vendor/k8s.io/client-go/dynamic/dynamiclister/shim.go
generated
vendored
Normal file
87
e2e/vendor/k8s.io/client-go/dynamic/dynamiclister/shim.go
generated
vendored
Normal file
@ -0,0 +1,87 @@
|
||||
/*
|
||||
Copyright 2018 The Kubernetes 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 dynamiclister
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
var _ cache.GenericLister = &dynamicListerShim{}
|
||||
var _ cache.GenericNamespaceLister = &dynamicNamespaceListerShim{}
|
||||
|
||||
// dynamicListerShim implements the cache.GenericLister interface.
|
||||
type dynamicListerShim struct {
|
||||
lister Lister
|
||||
}
|
||||
|
||||
// NewRuntimeObjectShim returns a new shim for Lister.
|
||||
// It wraps Lister so that it implements cache.GenericLister interface
|
||||
func NewRuntimeObjectShim(lister Lister) cache.GenericLister {
|
||||
return &dynamicListerShim{lister: lister}
|
||||
}
|
||||
|
||||
// List will return all objects across namespaces
|
||||
func (s *dynamicListerShim) List(selector labels.Selector) (ret []runtime.Object, err error) {
|
||||
objs, err := s.lister.List(selector)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ret = make([]runtime.Object, len(objs))
|
||||
for index, obj := range objs {
|
||||
ret[index] = obj
|
||||
}
|
||||
return ret, err
|
||||
}
|
||||
|
||||
// Get will attempt to retrieve assuming that name==key
|
||||
func (s *dynamicListerShim) Get(name string) (runtime.Object, error) {
|
||||
return s.lister.Get(name)
|
||||
}
|
||||
|
||||
func (s *dynamicListerShim) ByNamespace(namespace string) cache.GenericNamespaceLister {
|
||||
return &dynamicNamespaceListerShim{
|
||||
namespaceLister: s.lister.Namespace(namespace),
|
||||
}
|
||||
}
|
||||
|
||||
// dynamicNamespaceListerShim implements the NamespaceLister interface.
|
||||
// It wraps NamespaceLister so that it implements cache.GenericNamespaceLister interface
|
||||
type dynamicNamespaceListerShim struct {
|
||||
namespaceLister NamespaceLister
|
||||
}
|
||||
|
||||
// List will return all objects in this namespace
|
||||
func (ns *dynamicNamespaceListerShim) List(selector labels.Selector) (ret []runtime.Object, err error) {
|
||||
objs, err := ns.namespaceLister.List(selector)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ret = make([]runtime.Object, len(objs))
|
||||
for index, obj := range objs {
|
||||
ret[index] = obj
|
||||
}
|
||||
return ret, err
|
||||
}
|
||||
|
||||
// Get will attempt to retrieve by namespace and name
|
||||
func (ns *dynamicNamespaceListerShim) Get(name string) (runtime.Object, error) {
|
||||
return ns.namespaceLister.Get(name)
|
||||
}
|
539
e2e/vendor/k8s.io/client-go/dynamic/fake/simple.go
generated
vendored
Normal file
539
e2e/vendor/k8s.io/client-go/dynamic/fake/simple.go
generated
vendored
Normal file
@ -0,0 +1,539 @@
|
||||
/*
|
||||
Copyright 2018 The Kubernetes 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 fake
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
"k8s.io/client-go/dynamic"
|
||||
"k8s.io/client-go/testing"
|
||||
)
|
||||
|
||||
func NewSimpleDynamicClient(scheme *runtime.Scheme, objects ...runtime.Object) *FakeDynamicClient {
|
||||
unstructuredScheme := runtime.NewScheme()
|
||||
for gvk := range scheme.AllKnownTypes() {
|
||||
if unstructuredScheme.Recognizes(gvk) {
|
||||
continue
|
||||
}
|
||||
if strings.HasSuffix(gvk.Kind, "List") {
|
||||
unstructuredScheme.AddKnownTypeWithName(gvk, &unstructured.UnstructuredList{})
|
||||
continue
|
||||
}
|
||||
unstructuredScheme.AddKnownTypeWithName(gvk, &unstructured.Unstructured{})
|
||||
}
|
||||
|
||||
objects, err := convertObjectsToUnstructured(scheme, objects)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
for _, obj := range objects {
|
||||
gvk := obj.GetObjectKind().GroupVersionKind()
|
||||
if !unstructuredScheme.Recognizes(gvk) {
|
||||
unstructuredScheme.AddKnownTypeWithName(gvk, &unstructured.Unstructured{})
|
||||
}
|
||||
gvk.Kind += "List"
|
||||
if !unstructuredScheme.Recognizes(gvk) {
|
||||
unstructuredScheme.AddKnownTypeWithName(gvk, &unstructured.UnstructuredList{})
|
||||
}
|
||||
}
|
||||
|
||||
return NewSimpleDynamicClientWithCustomListKinds(unstructuredScheme, nil, objects...)
|
||||
}
|
||||
|
||||
// NewSimpleDynamicClientWithCustomListKinds try not to use this. In general you want to have the scheme have the List types registered
|
||||
// and allow the default guessing for resources match. Sometimes that doesn't work, so you can specify a custom mapping here.
|
||||
func NewSimpleDynamicClientWithCustomListKinds(scheme *runtime.Scheme, gvrToListKind map[schema.GroupVersionResource]string, objects ...runtime.Object) *FakeDynamicClient {
|
||||
// In order to use List with this client, you have to have your lists registered so that the object tracker will find them
|
||||
// in the scheme to support the t.scheme.New(listGVK) call when it's building the return value.
|
||||
// Since the base fake client needs the listGVK passed through the action (in cases where there are no instances, it
|
||||
// cannot look up the actual hits), we need to know a mapping of GVR to listGVK here. For GETs and other types of calls,
|
||||
// there is no return value that contains a GVK, so it doesn't have to know the mapping in advance.
|
||||
|
||||
// first we attempt to invert known List types from the scheme to auto guess the resource with unsafe guesses
|
||||
// this covers common usage of registering types in scheme and passing them
|
||||
completeGVRToListKind := map[schema.GroupVersionResource]string{}
|
||||
for listGVK := range scheme.AllKnownTypes() {
|
||||
if !strings.HasSuffix(listGVK.Kind, "List") {
|
||||
continue
|
||||
}
|
||||
nonListGVK := listGVK.GroupVersion().WithKind(listGVK.Kind[:len(listGVK.Kind)-4])
|
||||
plural, _ := meta.UnsafeGuessKindToResource(nonListGVK)
|
||||
completeGVRToListKind[plural] = listGVK.Kind
|
||||
}
|
||||
|
||||
for gvr, listKind := range gvrToListKind {
|
||||
if !strings.HasSuffix(listKind, "List") {
|
||||
panic("coding error, listGVK must end in List or this fake client doesn't work right")
|
||||
}
|
||||
listGVK := gvr.GroupVersion().WithKind(listKind)
|
||||
|
||||
// if we already have this type registered, just skip it
|
||||
if _, err := scheme.New(listGVK); err == nil {
|
||||
completeGVRToListKind[gvr] = listKind
|
||||
continue
|
||||
}
|
||||
|
||||
scheme.AddKnownTypeWithName(listGVK, &unstructured.UnstructuredList{})
|
||||
completeGVRToListKind[gvr] = listKind
|
||||
}
|
||||
|
||||
codecs := serializer.NewCodecFactory(scheme)
|
||||
o := testing.NewObjectTracker(scheme, codecs.UniversalDecoder())
|
||||
for _, obj := range objects {
|
||||
if err := o.Add(obj); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
cs := &FakeDynamicClient{scheme: scheme, gvrToListKind: completeGVRToListKind, tracker: o}
|
||||
cs.AddReactor("*", "*", testing.ObjectReaction(o))
|
||||
cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) {
|
||||
gvr := action.GetResource()
|
||||
ns := action.GetNamespace()
|
||||
watch, err := o.Watch(gvr, ns)
|
||||
if err != nil {
|
||||
return false, nil, err
|
||||
}
|
||||
return true, watch, nil
|
||||
})
|
||||
|
||||
return cs
|
||||
}
|
||||
|
||||
// Clientset implements clientset.Interface. Meant to be embedded into a
|
||||
// struct to get a default implementation. This makes faking out just the method
|
||||
// you want to test easier.
|
||||
type FakeDynamicClient struct {
|
||||
testing.Fake
|
||||
scheme *runtime.Scheme
|
||||
gvrToListKind map[schema.GroupVersionResource]string
|
||||
tracker testing.ObjectTracker
|
||||
}
|
||||
|
||||
type dynamicResourceClient struct {
|
||||
client *FakeDynamicClient
|
||||
namespace string
|
||||
resource schema.GroupVersionResource
|
||||
listKind string
|
||||
}
|
||||
|
||||
var (
|
||||
_ dynamic.Interface = &FakeDynamicClient{}
|
||||
_ testing.FakeClient = &FakeDynamicClient{}
|
||||
)
|
||||
|
||||
func (c *FakeDynamicClient) Tracker() testing.ObjectTracker {
|
||||
return c.tracker
|
||||
}
|
||||
|
||||
func (c *FakeDynamicClient) Resource(resource schema.GroupVersionResource) dynamic.NamespaceableResourceInterface {
|
||||
return &dynamicResourceClient{client: c, resource: resource, listKind: c.gvrToListKind[resource]}
|
||||
}
|
||||
|
||||
func (c *dynamicResourceClient) Namespace(ns string) dynamic.ResourceInterface {
|
||||
ret := *c
|
||||
ret.namespace = ns
|
||||
return &ret
|
||||
}
|
||||
|
||||
func (c *dynamicResourceClient) Create(ctx context.Context, obj *unstructured.Unstructured, opts metav1.CreateOptions, subresources ...string) (*unstructured.Unstructured, error) {
|
||||
var uncastRet runtime.Object
|
||||
var err error
|
||||
switch {
|
||||
case len(c.namespace) == 0 && len(subresources) == 0:
|
||||
uncastRet, err = c.client.Fake.
|
||||
Invokes(testing.NewRootCreateAction(c.resource, obj), obj)
|
||||
|
||||
case len(c.namespace) == 0 && len(subresources) > 0:
|
||||
var accessor metav1.Object // avoid shadowing err
|
||||
accessor, err = meta.Accessor(obj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
name := accessor.GetName()
|
||||
uncastRet, err = c.client.Fake.
|
||||
Invokes(testing.NewRootCreateSubresourceAction(c.resource, name, strings.Join(subresources, "/"), obj), obj)
|
||||
|
||||
case len(c.namespace) > 0 && len(subresources) == 0:
|
||||
uncastRet, err = c.client.Fake.
|
||||
Invokes(testing.NewCreateAction(c.resource, c.namespace, obj), obj)
|
||||
|
||||
case len(c.namespace) > 0 && len(subresources) > 0:
|
||||
var accessor metav1.Object // avoid shadowing err
|
||||
accessor, err = meta.Accessor(obj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
name := accessor.GetName()
|
||||
uncastRet, err = c.client.Fake.
|
||||
Invokes(testing.NewCreateSubresourceAction(c.resource, name, strings.Join(subresources, "/"), c.namespace, obj), obj)
|
||||
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if uncastRet == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ret := &unstructured.Unstructured{}
|
||||
if err := c.client.scheme.Convert(uncastRet, ret, nil); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ret, err
|
||||
}
|
||||
|
||||
func (c *dynamicResourceClient) Update(ctx context.Context, obj *unstructured.Unstructured, opts metav1.UpdateOptions, subresources ...string) (*unstructured.Unstructured, error) {
|
||||
var uncastRet runtime.Object
|
||||
var err error
|
||||
switch {
|
||||
case len(c.namespace) == 0 && len(subresources) == 0:
|
||||
uncastRet, err = c.client.Fake.
|
||||
Invokes(testing.NewRootUpdateAction(c.resource, obj), obj)
|
||||
|
||||
case len(c.namespace) == 0 && len(subresources) > 0:
|
||||
uncastRet, err = c.client.Fake.
|
||||
Invokes(testing.NewRootUpdateSubresourceAction(c.resource, strings.Join(subresources, "/"), obj), obj)
|
||||
|
||||
case len(c.namespace) > 0 && len(subresources) == 0:
|
||||
uncastRet, err = c.client.Fake.
|
||||
Invokes(testing.NewUpdateAction(c.resource, c.namespace, obj), obj)
|
||||
|
||||
case len(c.namespace) > 0 && len(subresources) > 0:
|
||||
uncastRet, err = c.client.Fake.
|
||||
Invokes(testing.NewUpdateSubresourceAction(c.resource, strings.Join(subresources, "/"), c.namespace, obj), obj)
|
||||
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if uncastRet == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ret := &unstructured.Unstructured{}
|
||||
if err := c.client.scheme.Convert(uncastRet, ret, nil); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ret, err
|
||||
}
|
||||
|
||||
func (c *dynamicResourceClient) UpdateStatus(ctx context.Context, obj *unstructured.Unstructured, opts metav1.UpdateOptions) (*unstructured.Unstructured, error) {
|
||||
var uncastRet runtime.Object
|
||||
var err error
|
||||
switch {
|
||||
case len(c.namespace) == 0:
|
||||
uncastRet, err = c.client.Fake.
|
||||
Invokes(testing.NewRootUpdateSubresourceAction(c.resource, "status", obj), obj)
|
||||
|
||||
case len(c.namespace) > 0:
|
||||
uncastRet, err = c.client.Fake.
|
||||
Invokes(testing.NewUpdateSubresourceAction(c.resource, "status", c.namespace, obj), obj)
|
||||
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if uncastRet == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ret := &unstructured.Unstructured{}
|
||||
if err := c.client.scheme.Convert(uncastRet, ret, nil); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ret, err
|
||||
}
|
||||
|
||||
func (c *dynamicResourceClient) Delete(ctx context.Context, name string, opts metav1.DeleteOptions, subresources ...string) error {
|
||||
var err error
|
||||
switch {
|
||||
case len(c.namespace) == 0 && len(subresources) == 0:
|
||||
_, err = c.client.Fake.
|
||||
Invokes(testing.NewRootDeleteAction(c.resource, name), &metav1.Status{Status: "dynamic delete fail"})
|
||||
|
||||
case len(c.namespace) == 0 && len(subresources) > 0:
|
||||
_, err = c.client.Fake.
|
||||
Invokes(testing.NewRootDeleteSubresourceAction(c.resource, strings.Join(subresources, "/"), name), &metav1.Status{Status: "dynamic delete fail"})
|
||||
|
||||
case len(c.namespace) > 0 && len(subresources) == 0:
|
||||
_, err = c.client.Fake.
|
||||
Invokes(testing.NewDeleteAction(c.resource, c.namespace, name), &metav1.Status{Status: "dynamic delete fail"})
|
||||
|
||||
case len(c.namespace) > 0 && len(subresources) > 0:
|
||||
_, err = c.client.Fake.
|
||||
Invokes(testing.NewDeleteSubresourceAction(c.resource, strings.Join(subresources, "/"), c.namespace, name), &metav1.Status{Status: "dynamic delete fail"})
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *dynamicResourceClient) DeleteCollection(ctx context.Context, opts metav1.DeleteOptions, listOptions metav1.ListOptions) error {
|
||||
var err error
|
||||
switch {
|
||||
case len(c.namespace) == 0:
|
||||
action := testing.NewRootDeleteCollectionAction(c.resource, listOptions)
|
||||
_, err = c.client.Fake.Invokes(action, &metav1.Status{Status: "dynamic deletecollection fail"})
|
||||
|
||||
case len(c.namespace) > 0:
|
||||
action := testing.NewDeleteCollectionAction(c.resource, c.namespace, listOptions)
|
||||
_, err = c.client.Fake.Invokes(action, &metav1.Status{Status: "dynamic deletecollection fail"})
|
||||
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *dynamicResourceClient) Get(ctx context.Context, name string, opts metav1.GetOptions, subresources ...string) (*unstructured.Unstructured, error) {
|
||||
var uncastRet runtime.Object
|
||||
var err error
|
||||
switch {
|
||||
case len(c.namespace) == 0 && len(subresources) == 0:
|
||||
uncastRet, err = c.client.Fake.
|
||||
Invokes(testing.NewRootGetAction(c.resource, name), &metav1.Status{Status: "dynamic get fail"})
|
||||
|
||||
case len(c.namespace) == 0 && len(subresources) > 0:
|
||||
uncastRet, err = c.client.Fake.
|
||||
Invokes(testing.NewRootGetSubresourceAction(c.resource, strings.Join(subresources, "/"), name), &metav1.Status{Status: "dynamic get fail"})
|
||||
|
||||
case len(c.namespace) > 0 && len(subresources) == 0:
|
||||
uncastRet, err = c.client.Fake.
|
||||
Invokes(testing.NewGetAction(c.resource, c.namespace, name), &metav1.Status{Status: "dynamic get fail"})
|
||||
|
||||
case len(c.namespace) > 0 && len(subresources) > 0:
|
||||
uncastRet, err = c.client.Fake.
|
||||
Invokes(testing.NewGetSubresourceAction(c.resource, c.namespace, strings.Join(subresources, "/"), name), &metav1.Status{Status: "dynamic get fail"})
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if uncastRet == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ret := &unstructured.Unstructured{}
|
||||
if err := c.client.scheme.Convert(uncastRet, ret, nil); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ret, err
|
||||
}
|
||||
|
||||
func (c *dynamicResourceClient) List(ctx context.Context, opts metav1.ListOptions) (*unstructured.UnstructuredList, error) {
|
||||
if len(c.listKind) == 0 {
|
||||
panic(fmt.Sprintf("coding error: you must register resource to list kind for every resource you're going to LIST when creating the client. See NewSimpleDynamicClientWithCustomListKinds or register the list into the scheme: %v out of %v", c.resource, c.client.gvrToListKind))
|
||||
}
|
||||
listGVK := c.resource.GroupVersion().WithKind(c.listKind)
|
||||
listForFakeClientGVK := c.resource.GroupVersion().WithKind(c.listKind[:len(c.listKind)-4]) /*base library appends List*/
|
||||
|
||||
var obj runtime.Object
|
||||
var err error
|
||||
switch {
|
||||
case len(c.namespace) == 0:
|
||||
obj, err = c.client.Fake.
|
||||
Invokes(testing.NewRootListAction(c.resource, listForFakeClientGVK, opts), &metav1.Status{Status: "dynamic list fail"})
|
||||
|
||||
case len(c.namespace) > 0:
|
||||
obj, err = c.client.Fake.
|
||||
Invokes(testing.NewListAction(c.resource, listForFakeClientGVK, c.namespace, opts), &metav1.Status{Status: "dynamic list fail"})
|
||||
|
||||
}
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
label, _, _ := testing.ExtractFromListOptions(opts)
|
||||
if label == nil {
|
||||
label = labels.Everything()
|
||||
}
|
||||
|
||||
retUnstructured := &unstructured.Unstructured{}
|
||||
if err := c.client.scheme.Convert(obj, retUnstructured, nil); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
entireList, err := retUnstructured.ToList()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
list := &unstructured.UnstructuredList{}
|
||||
list.SetRemainingItemCount(entireList.GetRemainingItemCount())
|
||||
list.SetResourceVersion(entireList.GetResourceVersion())
|
||||
list.SetContinue(entireList.GetContinue())
|
||||
list.GetObjectKind().SetGroupVersionKind(listGVK)
|
||||
for i := range entireList.Items {
|
||||
item := &entireList.Items[i]
|
||||
metadata, err := meta.Accessor(item)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if label.Matches(labels.Set(metadata.GetLabels())) {
|
||||
list.Items = append(list.Items, *item)
|
||||
}
|
||||
}
|
||||
return list, nil
|
||||
}
|
||||
|
||||
func (c *dynamicResourceClient) Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) {
|
||||
switch {
|
||||
case len(c.namespace) == 0:
|
||||
return c.client.Fake.
|
||||
InvokesWatch(testing.NewRootWatchAction(c.resource, opts))
|
||||
|
||||
case len(c.namespace) > 0:
|
||||
return c.client.Fake.
|
||||
InvokesWatch(testing.NewWatchAction(c.resource, c.namespace, opts))
|
||||
|
||||
}
|
||||
|
||||
panic("math broke")
|
||||
}
|
||||
|
||||
// TODO: opts are currently ignored.
|
||||
func (c *dynamicResourceClient) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (*unstructured.Unstructured, error) {
|
||||
var uncastRet runtime.Object
|
||||
var err error
|
||||
switch {
|
||||
case len(c.namespace) == 0 && len(subresources) == 0:
|
||||
uncastRet, err = c.client.Fake.
|
||||
Invokes(testing.NewRootPatchAction(c.resource, name, pt, data), &metav1.Status{Status: "dynamic patch fail"})
|
||||
|
||||
case len(c.namespace) == 0 && len(subresources) > 0:
|
||||
uncastRet, err = c.client.Fake.
|
||||
Invokes(testing.NewRootPatchSubresourceAction(c.resource, name, pt, data, subresources...), &metav1.Status{Status: "dynamic patch fail"})
|
||||
|
||||
case len(c.namespace) > 0 && len(subresources) == 0:
|
||||
uncastRet, err = c.client.Fake.
|
||||
Invokes(testing.NewPatchAction(c.resource, c.namespace, name, pt, data), &metav1.Status{Status: "dynamic patch fail"})
|
||||
|
||||
case len(c.namespace) > 0 && len(subresources) > 0:
|
||||
uncastRet, err = c.client.Fake.
|
||||
Invokes(testing.NewPatchSubresourceAction(c.resource, c.namespace, name, pt, data, subresources...), &metav1.Status{Status: "dynamic patch fail"})
|
||||
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if uncastRet == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ret := &unstructured.Unstructured{}
|
||||
if err := c.client.scheme.Convert(uncastRet, ret, nil); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ret, err
|
||||
}
|
||||
|
||||
// TODO: opts are currently ignored.
|
||||
func (c *dynamicResourceClient) Apply(ctx context.Context, name string, obj *unstructured.Unstructured, options metav1.ApplyOptions, subresources ...string) (*unstructured.Unstructured, error) {
|
||||
outBytes, err := runtime.Encode(unstructured.UnstructuredJSONScheme, obj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var uncastRet runtime.Object
|
||||
switch {
|
||||
case len(c.namespace) == 0 && len(subresources) == 0:
|
||||
uncastRet, err = c.client.Fake.
|
||||
Invokes(testing.NewRootPatchAction(c.resource, name, types.ApplyPatchType, outBytes), &metav1.Status{Status: "dynamic patch fail"})
|
||||
|
||||
case len(c.namespace) == 0 && len(subresources) > 0:
|
||||
uncastRet, err = c.client.Fake.
|
||||
Invokes(testing.NewRootPatchSubresourceAction(c.resource, name, types.ApplyPatchType, outBytes, subresources...), &metav1.Status{Status: "dynamic patch fail"})
|
||||
|
||||
case len(c.namespace) > 0 && len(subresources) == 0:
|
||||
uncastRet, err = c.client.Fake.
|
||||
Invokes(testing.NewPatchAction(c.resource, c.namespace, name, types.ApplyPatchType, outBytes), &metav1.Status{Status: "dynamic patch fail"})
|
||||
|
||||
case len(c.namespace) > 0 && len(subresources) > 0:
|
||||
uncastRet, err = c.client.Fake.
|
||||
Invokes(testing.NewPatchSubresourceAction(c.resource, c.namespace, name, types.ApplyPatchType, outBytes, subresources...), &metav1.Status{Status: "dynamic patch fail"})
|
||||
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if uncastRet == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ret := &unstructured.Unstructured{}
|
||||
if err := c.client.scheme.Convert(uncastRet, ret, nil); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (c *dynamicResourceClient) ApplyStatus(ctx context.Context, name string, obj *unstructured.Unstructured, options metav1.ApplyOptions) (*unstructured.Unstructured, error) {
|
||||
return c.Apply(ctx, name, obj, options, "status")
|
||||
}
|
||||
|
||||
func convertObjectsToUnstructured(s *runtime.Scheme, objs []runtime.Object) ([]runtime.Object, error) {
|
||||
ul := make([]runtime.Object, 0, len(objs))
|
||||
|
||||
for _, obj := range objs {
|
||||
u, err := convertToUnstructured(s, obj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ul = append(ul, u)
|
||||
}
|
||||
return ul, nil
|
||||
}
|
||||
|
||||
func convertToUnstructured(s *runtime.Scheme, obj runtime.Object) (runtime.Object, error) {
|
||||
var (
|
||||
err error
|
||||
u unstructured.Unstructured
|
||||
)
|
||||
|
||||
u.Object, err = runtime.DefaultUnstructuredConverter.ToUnstructured(obj)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to convert to unstructured: %w", err)
|
||||
}
|
||||
|
||||
gvk := u.GroupVersionKind()
|
||||
if gvk.Group == "" || gvk.Kind == "" {
|
||||
gvks, _, err := s.ObjectKinds(obj)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to convert to unstructured - unable to get GVK %w", err)
|
||||
}
|
||||
apiv, k := gvks[0].ToAPIVersionAndKind()
|
||||
u.SetAPIVersion(apiv)
|
||||
u.SetKind(k)
|
||||
}
|
||||
return &u, nil
|
||||
}
|
63
e2e/vendor/k8s.io/client-go/dynamic/interface.go
generated
vendored
Normal file
63
e2e/vendor/k8s.io/client-go/dynamic/interface.go
generated
vendored
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
Copyright 2016 The Kubernetes 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 dynamic
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
)
|
||||
|
||||
type Interface interface {
|
||||
Resource(resource schema.GroupVersionResource) NamespaceableResourceInterface
|
||||
}
|
||||
|
||||
type ResourceInterface interface {
|
||||
Create(ctx context.Context, obj *unstructured.Unstructured, options metav1.CreateOptions, subresources ...string) (*unstructured.Unstructured, error)
|
||||
Update(ctx context.Context, obj *unstructured.Unstructured, options metav1.UpdateOptions, subresources ...string) (*unstructured.Unstructured, error)
|
||||
UpdateStatus(ctx context.Context, obj *unstructured.Unstructured, options metav1.UpdateOptions) (*unstructured.Unstructured, error)
|
||||
Delete(ctx context.Context, name string, options metav1.DeleteOptions, subresources ...string) error
|
||||
DeleteCollection(ctx context.Context, options metav1.DeleteOptions, listOptions metav1.ListOptions) error
|
||||
Get(ctx context.Context, name string, options metav1.GetOptions, subresources ...string) (*unstructured.Unstructured, error)
|
||||
List(ctx context.Context, opts metav1.ListOptions) (*unstructured.UnstructuredList, error)
|
||||
Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error)
|
||||
Patch(ctx context.Context, name string, pt types.PatchType, data []byte, options metav1.PatchOptions, subresources ...string) (*unstructured.Unstructured, error)
|
||||
Apply(ctx context.Context, name string, obj *unstructured.Unstructured, options metav1.ApplyOptions, subresources ...string) (*unstructured.Unstructured, error)
|
||||
ApplyStatus(ctx context.Context, name string, obj *unstructured.Unstructured, options metav1.ApplyOptions) (*unstructured.Unstructured, error)
|
||||
}
|
||||
|
||||
type NamespaceableResourceInterface interface {
|
||||
Namespace(string) ResourceInterface
|
||||
ResourceInterface
|
||||
}
|
||||
|
||||
// APIPathResolverFunc knows how to convert a groupVersion to its API path. The Kind field is optional.
|
||||
// TODO find a better place to move this for existing callers
|
||||
type APIPathResolverFunc func(kind schema.GroupVersionKind) string
|
||||
|
||||
// LegacyAPIPathResolverFunc can resolve paths properly with the legacy API.
|
||||
// TODO find a better place to move this for existing callers
|
||||
func LegacyAPIPathResolverFunc(kind schema.GroupVersionKind) string {
|
||||
if len(kind.Group) == 0 {
|
||||
return "/api"
|
||||
}
|
||||
return "/apis"
|
||||
}
|
144
e2e/vendor/k8s.io/client-go/dynamic/scheme.go
generated
vendored
Normal file
144
e2e/vendor/k8s.io/client-go/dynamic/scheme.go
generated
vendored
Normal file
@ -0,0 +1,144 @@
|
||||
/*
|
||||
Copyright 2018 The Kubernetes 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 dynamic
|
||||
|
||||
import (
|
||||
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/runtime/serializer/cbor"
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer/json"
|
||||
"k8s.io/client-go/features"
|
||||
)
|
||||
|
||||
var basicScheme = runtime.NewScheme()
|
||||
var parameterScheme = runtime.NewScheme()
|
||||
var dynamicParameterCodec = runtime.NewParameterCodec(parameterScheme)
|
||||
|
||||
var versionV1 = schema.GroupVersion{Version: "v1"}
|
||||
|
||||
func init() {
|
||||
metav1.AddToGroupVersion(basicScheme, versionV1)
|
||||
metav1.AddToGroupVersion(parameterScheme, versionV1)
|
||||
}
|
||||
|
||||
func newBasicNegotiatedSerializer() basicNegotiatedSerializer {
|
||||
supportedMediaTypes := []runtime.SerializerInfo{
|
||||
{
|
||||
MediaType: "application/json",
|
||||
MediaTypeType: "application",
|
||||
MediaTypeSubType: "json",
|
||||
EncodesAsText: true,
|
||||
Serializer: json.NewSerializerWithOptions(json.DefaultMetaFactory, unstructuredCreater{basicScheme}, unstructuredTyper{basicScheme}, json.SerializerOptions{}),
|
||||
PrettySerializer: json.NewSerializerWithOptions(json.DefaultMetaFactory, unstructuredCreater{basicScheme}, unstructuredTyper{basicScheme}, json.SerializerOptions{Pretty: true}),
|
||||
StreamSerializer: &runtime.StreamSerializerInfo{
|
||||
EncodesAsText: true,
|
||||
Serializer: json.NewSerializerWithOptions(json.DefaultMetaFactory, basicScheme, basicScheme, json.SerializerOptions{}),
|
||||
Framer: json.Framer,
|
||||
},
|
||||
},
|
||||
}
|
||||
if features.FeatureGates().Enabled(features.ClientsAllowCBOR) {
|
||||
supportedMediaTypes = append(supportedMediaTypes, runtime.SerializerInfo{
|
||||
MediaType: "application/cbor",
|
||||
MediaTypeType: "application",
|
||||
MediaTypeSubType: "cbor",
|
||||
Serializer: cbor.NewSerializer(unstructuredCreater{basicScheme}, unstructuredTyper{basicScheme}),
|
||||
StreamSerializer: &runtime.StreamSerializerInfo{
|
||||
Serializer: cbor.NewSerializer(basicScheme, basicScheme, cbor.Transcode(false)),
|
||||
Framer: cbor.NewFramer(),
|
||||
},
|
||||
})
|
||||
}
|
||||
return basicNegotiatedSerializer{supportedMediaTypes: supportedMediaTypes}
|
||||
}
|
||||
|
||||
type basicNegotiatedSerializer struct {
|
||||
supportedMediaTypes []runtime.SerializerInfo
|
||||
}
|
||||
|
||||
func (s basicNegotiatedSerializer) SupportedMediaTypes() []runtime.SerializerInfo {
|
||||
return s.supportedMediaTypes
|
||||
}
|
||||
|
||||
func (s basicNegotiatedSerializer) EncoderForVersion(encoder runtime.Encoder, gv runtime.GroupVersioner) runtime.Encoder {
|
||||
return runtime.WithVersionEncoder{
|
||||
Version: gv,
|
||||
Encoder: encoder,
|
||||
ObjectTyper: permissiveTyper{basicScheme},
|
||||
}
|
||||
}
|
||||
|
||||
func (s basicNegotiatedSerializer) DecoderToVersion(decoder runtime.Decoder, gv runtime.GroupVersioner) runtime.Decoder {
|
||||
return decoder
|
||||
}
|
||||
|
||||
type unstructuredCreater struct {
|
||||
nested runtime.ObjectCreater
|
||||
}
|
||||
|
||||
func (c unstructuredCreater) New(kind schema.GroupVersionKind) (runtime.Object, error) {
|
||||
out, err := c.nested.New(kind)
|
||||
if err == nil {
|
||||
return out, nil
|
||||
}
|
||||
out = &unstructured.Unstructured{}
|
||||
out.GetObjectKind().SetGroupVersionKind(kind)
|
||||
return out, nil
|
||||
}
|
||||
|
||||
type unstructuredTyper struct {
|
||||
nested runtime.ObjectTyper
|
||||
}
|
||||
|
||||
func (t unstructuredTyper) ObjectKinds(obj runtime.Object) ([]schema.GroupVersionKind, bool, error) {
|
||||
kinds, unversioned, err := t.nested.ObjectKinds(obj)
|
||||
if err == nil {
|
||||
return kinds, unversioned, nil
|
||||
}
|
||||
if _, ok := obj.(runtime.Unstructured); ok && !obj.GetObjectKind().GroupVersionKind().Empty() {
|
||||
return []schema.GroupVersionKind{obj.GetObjectKind().GroupVersionKind()}, false, nil
|
||||
}
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
func (t unstructuredTyper) Recognizes(gvk schema.GroupVersionKind) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// The dynamic client has historically accepted Unstructured objects with missing or empty
|
||||
// apiVersion and/or kind as arguments to its write request methods. This typer will return the type
|
||||
// of a runtime.Unstructured with no error, even if the type is missing or empty.
|
||||
type permissiveTyper struct {
|
||||
nested runtime.ObjectTyper
|
||||
}
|
||||
|
||||
func (t permissiveTyper) ObjectKinds(obj runtime.Object) ([]schema.GroupVersionKind, bool, error) {
|
||||
kinds, unversioned, err := t.nested.ObjectKinds(obj)
|
||||
if err == nil {
|
||||
return kinds, unversioned, nil
|
||||
}
|
||||
if _, ok := obj.(runtime.Unstructured); ok {
|
||||
return []schema.GroupVersionKind{obj.GetObjectKind().GroupVersionKind()}, false, nil
|
||||
}
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
func (t permissiveTyper) Recognizes(gvk schema.GroupVersionKind) bool {
|
||||
return true
|
||||
}
|
406
e2e/vendor/k8s.io/client-go/dynamic/simple.go
generated
vendored
Normal file
406
e2e/vendor/k8s.io/client-go/dynamic/simple.go
generated
vendored
Normal file
@ -0,0 +1,406 @@
|
||||
/*
|
||||
Copyright 2018 The Kubernetes 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 dynamic
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
"k8s.io/client-go/features"
|
||||
"k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/util/apply"
|
||||
"k8s.io/client-go/util/consistencydetector"
|
||||
"k8s.io/client-go/util/watchlist"
|
||||
"k8s.io/klog/v2"
|
||||
)
|
||||
|
||||
type DynamicClient struct {
|
||||
client rest.Interface
|
||||
}
|
||||
|
||||
var _ Interface = &DynamicClient{}
|
||||
|
||||
// ConfigFor returns a copy of the provided config with the
|
||||
// appropriate dynamic client defaults set.
|
||||
func ConfigFor(inConfig *rest.Config) *rest.Config {
|
||||
config := rest.CopyConfig(inConfig)
|
||||
|
||||
config.ContentType = "application/json"
|
||||
config.AcceptContentTypes = "application/json"
|
||||
if features.FeatureGates().Enabled(features.ClientsAllowCBOR) {
|
||||
config.AcceptContentTypes = "application/json;q=0.9,application/cbor;q=1"
|
||||
if features.FeatureGates().Enabled(features.ClientsPreferCBOR) {
|
||||
config.ContentType = "application/cbor"
|
||||
}
|
||||
}
|
||||
|
||||
config.NegotiatedSerializer = newBasicNegotiatedSerializer()
|
||||
if config.UserAgent == "" {
|
||||
config.UserAgent = rest.DefaultKubernetesUserAgent()
|
||||
}
|
||||
return config
|
||||
}
|
||||
|
||||
// New creates a new DynamicClient for the given RESTClient.
|
||||
func New(c rest.Interface) *DynamicClient {
|
||||
return &DynamicClient{client: c}
|
||||
}
|
||||
|
||||
// NewForConfigOrDie creates a new DynamicClient for the given config and
|
||||
// panics if there is an error in the config.
|
||||
func NewForConfigOrDie(c *rest.Config) *DynamicClient {
|
||||
ret, err := NewForConfig(c)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// NewForConfig creates a new dynamic client or returns an error.
|
||||
// NewForConfig is equivalent to NewForConfigAndClient(c, httpClient),
|
||||
// where httpClient was generated with rest.HTTPClientFor(c).
|
||||
func NewForConfig(inConfig *rest.Config) (*DynamicClient, error) {
|
||||
config := ConfigFor(inConfig)
|
||||
|
||||
httpClient, err := rest.HTTPClientFor(config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return NewForConfigAndClient(config, httpClient)
|
||||
}
|
||||
|
||||
// NewForConfigAndClient creates a new dynamic client for the given config and http client.
|
||||
// Note the http client provided takes precedence over the configured transport values.
|
||||
func NewForConfigAndClient(inConfig *rest.Config, h *http.Client) (*DynamicClient, error) {
|
||||
config := ConfigFor(inConfig)
|
||||
config.GroupVersion = nil
|
||||
config.APIPath = "/if-you-see-this-search-for-the-break"
|
||||
|
||||
restClient, err := rest.UnversionedRESTClientForConfigAndClient(config, h)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &DynamicClient{client: restClient}, nil
|
||||
}
|
||||
|
||||
type dynamicResourceClient struct {
|
||||
client *DynamicClient
|
||||
namespace string
|
||||
resource schema.GroupVersionResource
|
||||
}
|
||||
|
||||
func (c *DynamicClient) Resource(resource schema.GroupVersionResource) NamespaceableResourceInterface {
|
||||
return &dynamicResourceClient{client: c, resource: resource}
|
||||
}
|
||||
|
||||
func (c *dynamicResourceClient) Namespace(ns string) ResourceInterface {
|
||||
ret := *c
|
||||
ret.namespace = ns
|
||||
return &ret
|
||||
}
|
||||
|
||||
func (c *dynamicResourceClient) Create(ctx context.Context, obj *unstructured.Unstructured, opts metav1.CreateOptions, subresources ...string) (*unstructured.Unstructured, error) {
|
||||
name := ""
|
||||
if len(subresources) > 0 {
|
||||
accessor, err := meta.Accessor(obj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
name = accessor.GetName()
|
||||
if len(name) == 0 {
|
||||
return nil, fmt.Errorf("name is required")
|
||||
}
|
||||
}
|
||||
if err := validateNamespaceWithOptionalName(c.namespace, name); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var out unstructured.Unstructured
|
||||
if err := c.client.client.
|
||||
Post().
|
||||
AbsPath(append(c.makeURLSegments(name), subresources...)...).
|
||||
Body(obj).
|
||||
SpecificallyVersionedParams(&opts, dynamicParameterCodec, versionV1).
|
||||
Do(ctx).Into(&out); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &out, nil
|
||||
}
|
||||
|
||||
func (c *dynamicResourceClient) Update(ctx context.Context, obj *unstructured.Unstructured, opts metav1.UpdateOptions, subresources ...string) (*unstructured.Unstructured, error) {
|
||||
accessor, err := meta.Accessor(obj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
name := accessor.GetName()
|
||||
if len(name) == 0 {
|
||||
return nil, fmt.Errorf("name is required")
|
||||
}
|
||||
if err := validateNamespaceWithOptionalName(c.namespace, name); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var out unstructured.Unstructured
|
||||
if err := c.client.client.
|
||||
Put().
|
||||
AbsPath(append(c.makeURLSegments(name), subresources...)...).
|
||||
Body(obj).
|
||||
SpecificallyVersionedParams(&opts, dynamicParameterCodec, versionV1).
|
||||
Do(ctx).Into(&out); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &out, nil
|
||||
}
|
||||
|
||||
func (c *dynamicResourceClient) UpdateStatus(ctx context.Context, obj *unstructured.Unstructured, opts metav1.UpdateOptions) (*unstructured.Unstructured, error) {
|
||||
accessor, err := meta.Accessor(obj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
name := accessor.GetName()
|
||||
if len(name) == 0 {
|
||||
return nil, fmt.Errorf("name is required")
|
||||
}
|
||||
if err := validateNamespaceWithOptionalName(c.namespace, name); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var out unstructured.Unstructured
|
||||
if err := c.client.client.
|
||||
Put().
|
||||
AbsPath(append(c.makeURLSegments(name), "status")...).
|
||||
Body(obj).
|
||||
SpecificallyVersionedParams(&opts, dynamicParameterCodec, versionV1).
|
||||
Do(ctx).Into(&out); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &out, nil
|
||||
}
|
||||
|
||||
func (c *dynamicResourceClient) Delete(ctx context.Context, name string, opts metav1.DeleteOptions, subresources ...string) error {
|
||||
if len(name) == 0 {
|
||||
return fmt.Errorf("name is required")
|
||||
}
|
||||
if err := validateNamespaceWithOptionalName(c.namespace, name); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
result := c.client.client.
|
||||
Delete().
|
||||
AbsPath(append(c.makeURLSegments(name), subresources...)...).
|
||||
Body(&opts).
|
||||
Do(ctx)
|
||||
return result.Error()
|
||||
}
|
||||
|
||||
func (c *dynamicResourceClient) DeleteCollection(ctx context.Context, opts metav1.DeleteOptions, listOptions metav1.ListOptions) error {
|
||||
if err := validateNamespaceWithOptionalName(c.namespace); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
result := c.client.client.
|
||||
Delete().
|
||||
AbsPath(c.makeURLSegments("")...).
|
||||
Body(&opts).
|
||||
SpecificallyVersionedParams(&listOptions, dynamicParameterCodec, versionV1).
|
||||
Do(ctx)
|
||||
return result.Error()
|
||||
}
|
||||
|
||||
func (c *dynamicResourceClient) Get(ctx context.Context, name string, opts metav1.GetOptions, subresources ...string) (*unstructured.Unstructured, error) {
|
||||
if len(name) == 0 {
|
||||
return nil, fmt.Errorf("name is required")
|
||||
}
|
||||
if err := validateNamespaceWithOptionalName(c.namespace, name); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var out unstructured.Unstructured
|
||||
if err := c.client.client.
|
||||
Get().
|
||||
AbsPath(append(c.makeURLSegments(name), subresources...)...).
|
||||
SpecificallyVersionedParams(&opts, dynamicParameterCodec, versionV1).
|
||||
Do(ctx).Into(&out); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &out, nil
|
||||
}
|
||||
|
||||
func (c *dynamicResourceClient) List(ctx context.Context, opts metav1.ListOptions) (*unstructured.UnstructuredList, error) {
|
||||
if watchListOptions, hasWatchListOptionsPrepared, watchListOptionsErr := watchlist.PrepareWatchListOptionsFromListOptions(opts); watchListOptionsErr != nil {
|
||||
klog.Warningf("Failed preparing watchlist options for %v, falling back to the standard LIST semantics, err = %v", c.resource, watchListOptionsErr)
|
||||
} else if hasWatchListOptionsPrepared {
|
||||
result, err := c.watchList(ctx, watchListOptions)
|
||||
if err == nil {
|
||||
consistencydetector.CheckWatchListFromCacheDataConsistencyIfRequested(ctx, fmt.Sprintf("watchlist request for %v", c.resource), c.list, opts, result)
|
||||
return result, nil
|
||||
}
|
||||
klog.Warningf("The watchlist request for %v ended with an error, falling back to the standard LIST semantics, err = %v", c.resource, err)
|
||||
}
|
||||
result, err := c.list(ctx, opts)
|
||||
if err == nil {
|
||||
consistencydetector.CheckListFromCacheDataConsistencyIfRequested(ctx, fmt.Sprintf("list request for %v", c.resource), c.list, opts, result)
|
||||
}
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (c *dynamicResourceClient) list(ctx context.Context, opts metav1.ListOptions) (*unstructured.UnstructuredList, error) {
|
||||
if err := validateNamespaceWithOptionalName(c.namespace); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var out unstructured.UnstructuredList
|
||||
if err := c.client.client.
|
||||
Get().
|
||||
AbsPath(c.makeURLSegments("")...).
|
||||
SpecificallyVersionedParams(&opts, dynamicParameterCodec, versionV1).
|
||||
Do(ctx).Into(&out); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &out, nil
|
||||
}
|
||||
|
||||
// watchList establishes a watch stream with the server and returns an unstructured list.
|
||||
func (c *dynamicResourceClient) watchList(ctx context.Context, opts metav1.ListOptions) (*unstructured.UnstructuredList, error) {
|
||||
if err := validateNamespaceWithOptionalName(c.namespace); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var timeout time.Duration
|
||||
if opts.TimeoutSeconds != nil {
|
||||
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
|
||||
}
|
||||
|
||||
result := &unstructured.UnstructuredList{}
|
||||
err := c.client.client.Get().AbsPath(c.makeURLSegments("")...).
|
||||
SpecificallyVersionedParams(&opts, dynamicParameterCodec, versionV1).
|
||||
Timeout(timeout).
|
||||
WatchList(ctx).
|
||||
Into(result)
|
||||
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (c *dynamicResourceClient) Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) {
|
||||
opts.Watch = true
|
||||
if err := validateNamespaceWithOptionalName(c.namespace); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return c.client.client.Get().AbsPath(c.makeURLSegments("")...).
|
||||
SpecificallyVersionedParams(&opts, dynamicParameterCodec, versionV1).
|
||||
Watch(ctx)
|
||||
}
|
||||
|
||||
func (c *dynamicResourceClient) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (*unstructured.Unstructured, error) {
|
||||
if len(name) == 0 {
|
||||
return nil, fmt.Errorf("name is required")
|
||||
}
|
||||
if err := validateNamespaceWithOptionalName(c.namespace, name); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var out unstructured.Unstructured
|
||||
if err := c.client.client.
|
||||
Patch(pt).
|
||||
AbsPath(append(c.makeURLSegments(name), subresources...)...).
|
||||
Body(data).
|
||||
SpecificallyVersionedParams(&opts, dynamicParameterCodec, versionV1).
|
||||
Do(ctx).Into(&out); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &out, nil
|
||||
}
|
||||
|
||||
func (c *dynamicResourceClient) Apply(ctx context.Context, name string, obj *unstructured.Unstructured, opts metav1.ApplyOptions, subresources ...string) (*unstructured.Unstructured, error) {
|
||||
if len(name) == 0 {
|
||||
return nil, fmt.Errorf("name is required")
|
||||
}
|
||||
if err := validateNamespaceWithOptionalName(c.namespace, name); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
accessor, err := meta.Accessor(obj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
managedFields := accessor.GetManagedFields()
|
||||
if len(managedFields) > 0 {
|
||||
return nil, fmt.Errorf(`cannot apply an object with managed fields already set.
|
||||
Use the client-go/applyconfigurations "UnstructructuredExtractor" to obtain the unstructured ApplyConfiguration for the given field manager that you can use/modify here to apply`)
|
||||
}
|
||||
patchOpts := opts.ToPatchOptions()
|
||||
|
||||
request, err := apply.NewRequest(c.client.client, obj.Object)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var out unstructured.Unstructured
|
||||
if err := request.
|
||||
AbsPath(append(c.makeURLSegments(name), subresources...)...).
|
||||
SpecificallyVersionedParams(&patchOpts, dynamicParameterCodec, versionV1).
|
||||
Do(ctx).Into(&out); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &out, nil
|
||||
}
|
||||
|
||||
func (c *dynamicResourceClient) ApplyStatus(ctx context.Context, name string, obj *unstructured.Unstructured, opts metav1.ApplyOptions) (*unstructured.Unstructured, error) {
|
||||
return c.Apply(ctx, name, obj, opts, "status")
|
||||
}
|
||||
|
||||
func validateNamespaceWithOptionalName(namespace string, name ...string) error {
|
||||
if msgs := rest.IsValidPathSegmentName(namespace); len(msgs) != 0 {
|
||||
return fmt.Errorf("invalid namespace %q: %v", namespace, msgs)
|
||||
}
|
||||
if len(name) > 1 {
|
||||
panic("Invalid number of names")
|
||||
} else if len(name) == 1 {
|
||||
if msgs := rest.IsValidPathSegmentName(name[0]); len(msgs) != 0 {
|
||||
return fmt.Errorf("invalid resource name %q: %v", name[0], msgs)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *dynamicResourceClient) makeURLSegments(name string) []string {
|
||||
url := []string{}
|
||||
if len(c.resource.Group) == 0 {
|
||||
url = append(url, "api")
|
||||
} else {
|
||||
url = append(url, "apis", c.resource.Group)
|
||||
}
|
||||
url = append(url, c.resource.Version)
|
||||
|
||||
if len(c.namespace) > 0 {
|
||||
url = append(url, "namespaces", c.namespace)
|
||||
}
|
||||
url = append(url, c.resource.Resource)
|
||||
|
||||
if len(name) > 0 {
|
||||
url = append(url, name)
|
||||
}
|
||||
|
||||
return url
|
||||
}
|
Reference in New Issue
Block a user