diff --git a/pkg/builder/controller.go b/pkg/builder/controller.go index 2663398fd8..047fc6d410 100644 --- a/pkg/builder/controller.go +++ b/pkg/builder/controller.go @@ -21,9 +21,9 @@ import ( "strings" "github.com/go-logr/logr" - "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/client-go/rest" + "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client/apiutil" "sigs.k8s.io/controller-runtime/pkg/controller" "sigs.k8s.io/controller-runtime/pkg/handler" @@ -57,7 +57,7 @@ func ControllerManagedBy(m manager.Manager) *Builder { // ForInput represents the information set by For method. type ForInput struct { - object runtime.Object + object client.Object predicates []predicate.Predicate err error } @@ -66,7 +66,7 @@ type ForInput struct { // update events by *reconciling the object*. // This is the equivalent of calling // Watches(&source.Kind{Type: apiType}, &handler.EnqueueRequestForObject{}) -func (blder *Builder) For(object runtime.Object, opts ...ForOption) *Builder { +func (blder *Builder) For(object client.Object, opts ...ForOption) *Builder { if blder.forInput.object != nil { blder.forInput.err = fmt.Errorf("For(...) should only be called once, could not assign multiple objects for reconciliation") return blder @@ -82,14 +82,14 @@ func (blder *Builder) For(object runtime.Object, opts ...ForOption) *Builder { // OwnsInput represents the information set by Owns method. type OwnsInput struct { - object runtime.Object + object client.Object predicates []predicate.Predicate } // Owns defines types of Objects being *generated* by the ControllerManagedBy, and configures the ControllerManagedBy to respond to // create / delete / update events by *reconciling the owner object*. This is the equivalent of calling // Watches(&source.Kind{Type: }, &handler.EnqueueRequestForOwner{OwnerType: apiType, IsController: true}) -func (blder *Builder) Owns(object runtime.Object, opts ...OwnsOption) *Builder { +func (blder *Builder) Owns(object client.Object, opts ...OwnsOption) *Builder { input := OwnsInput{object: object} for _, opt := range opts { opt.ApplyToOwns(&input) diff --git a/pkg/builder/controller_test.go b/pkg/builder/controller_test.go index 2b6a49789f..057efa4a36 100644 --- a/pkg/builder/controller_test.go +++ b/pkg/builder/controller_test.go @@ -458,7 +458,10 @@ func doReconcileTest(nameSuffix string, stop chan struct{}, blder *Builder, mgr var _ runtime.Object = &fakeType{} -type fakeType struct{} +type fakeType struct { + metav1.TypeMeta + metav1.ObjectMeta +} func (*fakeType) GetObjectKind() schema.ObjectKind { return nil } func (*fakeType) DeepCopyObject() runtime.Object { return nil } diff --git a/pkg/builder/webhook_test.go b/pkg/builder/webhook_test.go index 102d9f6d7b..4ccca4f1eb 100644 --- a/pkg/builder/webhook_test.go +++ b/pkg/builder/webhook_test.go @@ -27,6 +27,7 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "sigs.k8s.io/controller-runtime/pkg/controller" @@ -465,6 +466,9 @@ func (v *TestValidator) ValidateDelete() error { var _ runtime.Object = &TestDefaultValidator{} type TestDefaultValidator struct { + metav1.TypeMeta + metav1.ObjectMeta + Replica int `json:"replica,omitempty"` } diff --git a/pkg/cache/cache.go b/pkg/cache/cache.go index 3fcef4f592..71dfbd0454 100644 --- a/pkg/cache/cache.go +++ b/pkg/cache/cache.go @@ -52,7 +52,7 @@ type Cache interface { type Informers interface { // GetInformer fetches or constructs an informer for the given object that corresponds to a single // API kind and resource. - GetInformer(ctx context.Context, obj runtime.Object) (Informer, error) + GetInformer(ctx context.Context, obj client.Object) (Informer, error) // GetInformerForKind is similar to GetInformer, except that it takes a group-version-kind, instead // of the underlying object. diff --git a/pkg/cache/cache_test.go b/pkg/cache/cache_test.go index bdcf458c16..2da27eb7ec 100644 --- a/pkg/cache/cache_test.go +++ b/pkg/cache/cache_test.go @@ -26,7 +26,6 @@ import ( "k8s.io/apimachinery/pkg/api/errors" kmetav1 "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" kscheme "k8s.io/client-go/kubernetes/scheme" "k8s.io/client-go/rest" @@ -42,7 +41,7 @@ const testNamespaceThree = "test-namespace-3" // TODO(community): Pull these helper functions into testenv. // Restart policy is included to allow indexing on that field. -func createPod(name, namespace string, restartPolicy kcorev1.RestartPolicy) runtime.Object { +func createPod(name, namespace string, restartPolicy kcorev1.RestartPolicy) client.Object { three := int64(3) pod := &kcorev1.Pod{ ObjectMeta: kmetav1.ObjectMeta{ @@ -65,7 +64,7 @@ func createPod(name, namespace string, restartPolicy kcorev1.RestartPolicy) runt return pod } -func deletePod(pod runtime.Object) { +func deletePod(pod client.Object) { cl, err := client.New(cfg, client.Options{}) Expect(err).NotTo(HaveOccurred()) err = cl.Delete(context.Background(), pod) @@ -86,10 +85,10 @@ func CacheTest(createCacheFunc func(config *rest.Config, opts cache.Options) (ca informerCache cache.Cache informerCacheCtx context.Context informerCacheCancel context.CancelFunc - knownPod1 runtime.Object - knownPod2 runtime.Object - knownPod3 runtime.Object - knownPod4 runtime.Object + knownPod1 client.Object + knownPod2 client.Object + knownPod3 client.Object + knownPod4 client.Object ) BeforeEach(func() { @@ -566,7 +565,7 @@ func CacheTest(createCacheFunc func(config *rest.Config, opts cache.Options) (ca By("indexing the restartPolicy field of the Pod object before starting") pod := &kcorev1.Pod{} - indexFunc := func(obj runtime.Object) []string { + indexFunc := func(obj client.Object) []string { return []string{string(obj.(*kcorev1.Pod).Spec.RestartPolicy)} } Expect(informer.IndexField(context.TODO(), pod, "spec.restartPolicy", indexFunc)).To(Succeed()) @@ -684,7 +683,7 @@ func CacheTest(createCacheFunc func(config *rest.Config, opts cache.Options) (ca Version: "v1", Kind: "Pod", }) - indexFunc := func(obj runtime.Object) []string { + indexFunc := func(obj client.Object) []string { s, ok := obj.(*unstructured.Unstructured).Object["spec"] if !ok { return []string{} diff --git a/pkg/cache/informer_cache.go b/pkg/cache/informer_cache.go index 043c295f0a..8ec3b921d9 100644 --- a/pkg/cache/informer_cache.go +++ b/pkg/cache/informer_cache.go @@ -51,7 +51,7 @@ type informerCache struct { } // Get implements Reader -func (ip *informerCache) Get(ctx context.Context, key client.ObjectKey, out runtime.Object) error { +func (ip *informerCache) Get(ctx context.Context, key client.ObjectKey, out client.Object) error { gvk, err := apiutil.GVKForObject(out, ip.Scheme) if err != nil { return err @@ -69,7 +69,7 @@ func (ip *informerCache) Get(ctx context.Context, key client.ObjectKey, out runt } // List implements Reader -func (ip *informerCache) List(ctx context.Context, out runtime.Object, opts ...client.ListOption) error { +func (ip *informerCache) List(ctx context.Context, out client.ObjectList, opts ...client.ListOption) error { gvk, cacheTypeObj, err := ip.objectTypeForListObject(out) if err != nil { @@ -91,7 +91,7 @@ func (ip *informerCache) List(ctx context.Context, out runtime.Object, opts ...c // objectTypeForListObject tries to find the runtime.Object and associated GVK // for a single object corresponding to the passed-in list type. We need them // because they are used as cache map key. -func (ip *informerCache) objectTypeForListObject(list runtime.Object) (*schema.GroupVersionKind, runtime.Object, error) { +func (ip *informerCache) objectTypeForListObject(list client.ObjectList) (*schema.GroupVersionKind, runtime.Object, error) { gvk, err := apiutil.GVKForObject(list, ip.Scheme) if err != nil { return nil, nil, err @@ -146,7 +146,7 @@ func (ip *informerCache) GetInformerForKind(ctx context.Context, gvk schema.Grou } // GetInformer returns the informer for the obj -func (ip *informerCache) GetInformer(ctx context.Context, obj runtime.Object) (Informer, error) { +func (ip *informerCache) GetInformer(ctx context.Context, obj client.Object) (Informer, error) { gvk, err := apiutil.GVKForObject(obj, ip.Scheme) if err != nil { return nil, err @@ -170,7 +170,7 @@ func (ip *informerCache) NeedLeaderElection() bool { // to List. For one-to-one compatibility with "normal" field selectors, only return one value. // The values may be anything. They will automatically be prefixed with the namespace of the // given object, if present. The objects passed are guaranteed to be objects of the correct type. -func (ip *informerCache) IndexField(ctx context.Context, obj runtime.Object, field string, extractValue client.IndexerFunc) error { +func (ip *informerCache) IndexField(ctx context.Context, obj client.Object, field string, extractValue client.IndexerFunc) error { informer, err := ip.GetInformer(ctx, obj) if err != nil { return err @@ -181,7 +181,7 @@ func (ip *informerCache) IndexField(ctx context.Context, obj runtime.Object, fie func indexByField(indexer Informer, field string, extractor client.IndexerFunc) error { indexFunc := func(objRaw interface{}) ([]string, error) { // TODO(directxman12): check if this is the correct type? - obj, isObj := objRaw.(runtime.Object) + obj, isObj := objRaw.(client.Object) if !isObj { return nil, fmt.Errorf("object of type %T is not an Object", objRaw) } diff --git a/pkg/cache/informer_cache_unit_test.go b/pkg/cache/informer_cache_unit_test.go index 4728143eee..f4ddda0cd8 100644 --- a/pkg/cache/informer_cache_unit_test.go +++ b/pkg/cache/informer_cache_unit_test.go @@ -25,12 +25,6 @@ var _ = Describe("ip.objectTypeForListObject", func() { InformersMap: &internal.InformersMap{Scheme: scheme.Scheme}, } - It("should error on non-list types", func() { - _, _, err := ip.objectTypeForListObject(&corev1.Pod{}) - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(Equal(`non-list type *v1.Pod (kind "/v1, Kind=Pod") passed as output`)) - }) - It("should find the object type for unstructured lists", func() { unstructuredList := &unstructured.UnstructuredList{} unstructuredList.SetAPIVersion("v1") diff --git a/pkg/cache/informertest/fake_cache.go b/pkg/cache/informertest/fake_cache.go index 4e7bb5bc7f..eb78e0bb65 100644 --- a/pkg/cache/informertest/fake_cache.go +++ b/pkg/cache/informertest/fake_cache.go @@ -67,7 +67,7 @@ func (c *FakeInformers) FakeInformerForKind(ctx context.Context, gvk schema.Grou } // GetInformer implements Informers -func (c *FakeInformers) GetInformer(ctx context.Context, obj runtime.Object) (cache.Informer, error) { +func (c *FakeInformers) GetInformer(ctx context.Context, obj client.Object) (cache.Informer, error) { if c.Scheme == nil { c.Scheme = scheme.Scheme } @@ -126,16 +126,16 @@ func (c *FakeInformers) Start(ctx context.Context) error { } // IndexField implements Cache -func (c *FakeInformers) IndexField(ctx context.Context, obj runtime.Object, field string, extractValue client.IndexerFunc) error { +func (c *FakeInformers) IndexField(ctx context.Context, obj client.Object, field string, extractValue client.IndexerFunc) error { return nil } // Get implements Cache -func (c *FakeInformers) Get(ctx context.Context, key client.ObjectKey, obj runtime.Object) error { +func (c *FakeInformers) Get(ctx context.Context, key client.ObjectKey, obj client.Object) error { return nil } // List implements Cache -func (c *FakeInformers) List(ctx context.Context, list runtime.Object, opts ...client.ListOption) error { +func (c *FakeInformers) List(ctx context.Context, list client.ObjectList, opts ...client.ListOption) error { return nil } diff --git a/pkg/cache/internal/cache_reader.go b/pkg/cache/internal/cache_reader.go index 5c3fac9228..630a4b131e 100644 --- a/pkg/cache/internal/cache_reader.go +++ b/pkg/cache/internal/cache_reader.go @@ -45,7 +45,7 @@ type CacheReader struct { } // Get checks the indexer for the object and writes a copy of it if found -func (c *CacheReader) Get(_ context.Context, key client.ObjectKey, out runtime.Object) error { +func (c *CacheReader) Get(_ context.Context, key client.ObjectKey, out client.Object) error { storeKey := objectKeyToStoreKey(key) // Lookup the object from the indexer cache @@ -87,7 +87,7 @@ func (c *CacheReader) Get(_ context.Context, key client.ObjectKey, out runtime.O } // List lists items out of the indexer and writes them to out -func (c *CacheReader) List(_ context.Context, out runtime.Object, opts ...client.ListOption) error { +func (c *CacheReader) List(_ context.Context, out client.ObjectList, opts ...client.ListOption) error { var objs []interface{} var err error diff --git a/pkg/cache/multi_namespace_cache.go b/pkg/cache/multi_namespace_cache.go index ec5dd1fe5b..f0e18c09b0 100644 --- a/pkg/cache/multi_namespace_cache.go +++ b/pkg/cache/multi_namespace_cache.go @@ -70,7 +70,7 @@ type multiNamespaceCache struct { var _ Cache = &multiNamespaceCache{} // Methods for multiNamespaceCache to conform to the Informers interface -func (c *multiNamespaceCache) GetInformer(ctx context.Context, obj runtime.Object) (Informer, error) { +func (c *multiNamespaceCache) GetInformer(ctx context.Context, obj client.Object) (Informer, error) { informers := map[string]Informer{} for ns, cache := range c.namespaceToCache { informer, err := cache.GetInformer(ctx, obj) @@ -117,7 +117,7 @@ func (c *multiNamespaceCache) WaitForCacheSync(ctx context.Context) bool { return synced } -func (c *multiNamespaceCache) IndexField(ctx context.Context, obj runtime.Object, field string, extractValue client.IndexerFunc) error { +func (c *multiNamespaceCache) IndexField(ctx context.Context, obj client.Object, field string, extractValue client.IndexerFunc) error { for _, cache := range c.namespaceToCache { if err := cache.IndexField(ctx, obj, field, extractValue); err != nil { return err @@ -126,7 +126,7 @@ func (c *multiNamespaceCache) IndexField(ctx context.Context, obj runtime.Object return nil } -func (c *multiNamespaceCache) Get(ctx context.Context, key client.ObjectKey, obj runtime.Object) error { +func (c *multiNamespaceCache) Get(ctx context.Context, key client.ObjectKey, obj client.Object) error { cache, ok := c.namespaceToCache[key.Namespace] if !ok { return fmt.Errorf("unable to get: %v because of unknown namespace for the cache", key) @@ -135,7 +135,7 @@ func (c *multiNamespaceCache) Get(ctx context.Context, key client.ObjectKey, obj } // List multi namespace cache will get all the objects in the namespaces that the cache is watching if asked for all namespaces. -func (c *multiNamespaceCache) List(ctx context.Context, list runtime.Object, opts ...client.ListOption) error { +func (c *multiNamespaceCache) List(ctx context.Context, list client.ObjectList, opts ...client.ListOption) error { listOpts := client.ListOptions{} listOpts.ApplyOptions(opts) if listOpts.Namespace != corev1.NamespaceAll { @@ -157,7 +157,7 @@ func (c *multiNamespaceCache) List(ctx context.Context, list runtime.Object, opt } var resourceVersion string for _, cache := range c.namespaceToCache { - listObj := list.DeepCopyObject() + listObj := list.DeepCopyObject().(client.ObjectList) err = cache.List(ctx, listObj, opts...) if err != nil { return err diff --git a/pkg/client/client.go b/pkg/client/client.go index ba4efce513..bd6d6a40f6 100644 --- a/pkg/client/client.go +++ b/pkg/client/client.go @@ -124,7 +124,7 @@ func (c *client) RESTMapper() meta.RESTMapper { } // Create implements client.Client -func (c *client) Create(ctx context.Context, obj runtime.Object, opts ...CreateOption) error { +func (c *client) Create(ctx context.Context, obj Object, opts ...CreateOption) error { _, ok := obj.(*unstructured.Unstructured) if ok { return c.unstructuredClient.Create(ctx, obj, opts...) @@ -133,7 +133,7 @@ func (c *client) Create(ctx context.Context, obj runtime.Object, opts ...CreateO } // Update implements client.Client -func (c *client) Update(ctx context.Context, obj runtime.Object, opts ...UpdateOption) error { +func (c *client) Update(ctx context.Context, obj Object, opts ...UpdateOption) error { defer c.resetGroupVersionKind(obj, obj.GetObjectKind().GroupVersionKind()) _, ok := obj.(*unstructured.Unstructured) if ok { @@ -143,7 +143,7 @@ func (c *client) Update(ctx context.Context, obj runtime.Object, opts ...UpdateO } // Delete implements client.Client -func (c *client) Delete(ctx context.Context, obj runtime.Object, opts ...DeleteOption) error { +func (c *client) Delete(ctx context.Context, obj Object, opts ...DeleteOption) error { _, ok := obj.(*unstructured.Unstructured) if ok { return c.unstructuredClient.Delete(ctx, obj, opts...) @@ -152,7 +152,7 @@ func (c *client) Delete(ctx context.Context, obj runtime.Object, opts ...DeleteO } // DeleteAllOf implements client.Client -func (c *client) DeleteAllOf(ctx context.Context, obj runtime.Object, opts ...DeleteAllOfOption) error { +func (c *client) DeleteAllOf(ctx context.Context, obj Object, opts ...DeleteAllOfOption) error { _, ok := obj.(*unstructured.Unstructured) if ok { return c.unstructuredClient.DeleteAllOf(ctx, obj, opts...) @@ -161,7 +161,7 @@ func (c *client) DeleteAllOf(ctx context.Context, obj runtime.Object, opts ...De } // Patch implements client.Client -func (c *client) Patch(ctx context.Context, obj runtime.Object, patch Patch, opts ...PatchOption) error { +func (c *client) Patch(ctx context.Context, obj Object, patch Patch, opts ...PatchOption) error { defer c.resetGroupVersionKind(obj, obj.GetObjectKind().GroupVersionKind()) _, ok := obj.(*unstructured.Unstructured) if ok { @@ -171,7 +171,7 @@ func (c *client) Patch(ctx context.Context, obj runtime.Object, patch Patch, opt } // Get implements client.Client -func (c *client) Get(ctx context.Context, key ObjectKey, obj runtime.Object) error { +func (c *client) Get(ctx context.Context, key ObjectKey, obj Object) error { _, ok := obj.(*unstructured.Unstructured) if ok { return c.unstructuredClient.Get(ctx, key, obj) @@ -180,7 +180,7 @@ func (c *client) Get(ctx context.Context, key ObjectKey, obj runtime.Object) err } // List implements client.Client -func (c *client) List(ctx context.Context, obj runtime.Object, opts ...ListOption) error { +func (c *client) List(ctx context.Context, obj ObjectList, opts ...ListOption) error { _, ok := obj.(*unstructured.UnstructuredList) if ok { return c.unstructuredClient.List(ctx, obj, opts...) @@ -202,7 +202,7 @@ type statusWriter struct { var _ StatusWriter = &statusWriter{} // Update implements client.StatusWriter -func (sw *statusWriter) Update(ctx context.Context, obj runtime.Object, opts ...UpdateOption) error { +func (sw *statusWriter) Update(ctx context.Context, obj Object, opts ...UpdateOption) error { defer sw.client.resetGroupVersionKind(obj, obj.GetObjectKind().GroupVersionKind()) _, ok := obj.(*unstructured.Unstructured) if ok { @@ -212,7 +212,7 @@ func (sw *statusWriter) Update(ctx context.Context, obj runtime.Object, opts ... } // Patch implements client.Client -func (sw *statusWriter) Patch(ctx context.Context, obj runtime.Object, patch Patch, opts ...PatchOption) error { +func (sw *statusWriter) Patch(ctx context.Context, obj Object, patch Patch, opts ...PatchOption) error { defer sw.client.resetGroupVersionKind(obj, obj.GetObjectKind().GroupVersionKind()) _, ok := obj.(*unstructured.Unstructured) if ok { diff --git a/pkg/client/client_test.go b/pkg/client/client_test.go index 1a5fc58c0c..99a491509a 100644 --- a/pkg/client/client_test.go +++ b/pkg/client/client_test.go @@ -2815,12 +2815,12 @@ type fakeReader struct { Called int } -func (f *fakeReader) Get(ctx context.Context, key client.ObjectKey, obj runtime.Object) error { +func (f *fakeReader) Get(ctx context.Context, key client.ObjectKey, obj client.Object) error { f.Called = f.Called + 1 return nil } -func (f *fakeReader) List(ctx context.Context, list runtime.Object, opts ...client.ListOption) error { +func (f *fakeReader) List(ctx context.Context, list client.ObjectList, opts ...client.ListOption) error { f.Called = f.Called + 1 return nil } diff --git a/pkg/client/dryrun.go b/pkg/client/dryrun.go index 187f0fe1eb..67e80e0551 100644 --- a/pkg/client/dryrun.go +++ b/pkg/client/dryrun.go @@ -47,37 +47,37 @@ func (c *dryRunClient) RESTMapper() meta.RESTMapper { } // Create implements client.Client -func (c *dryRunClient) Create(ctx context.Context, obj runtime.Object, opts ...CreateOption) error { +func (c *dryRunClient) Create(ctx context.Context, obj Object, opts ...CreateOption) error { return c.client.Create(ctx, obj, append(opts, DryRunAll)...) } // Update implements client.Client -func (c *dryRunClient) Update(ctx context.Context, obj runtime.Object, opts ...UpdateOption) error { +func (c *dryRunClient) Update(ctx context.Context, obj Object, opts ...UpdateOption) error { return c.client.Update(ctx, obj, append(opts, DryRunAll)...) } // Delete implements client.Client -func (c *dryRunClient) Delete(ctx context.Context, obj runtime.Object, opts ...DeleteOption) error { +func (c *dryRunClient) Delete(ctx context.Context, obj Object, opts ...DeleteOption) error { return c.client.Delete(ctx, obj, append(opts, DryRunAll)...) } // DeleteAllOf implements client.Client -func (c *dryRunClient) DeleteAllOf(ctx context.Context, obj runtime.Object, opts ...DeleteAllOfOption) error { +func (c *dryRunClient) DeleteAllOf(ctx context.Context, obj Object, opts ...DeleteAllOfOption) error { return c.client.DeleteAllOf(ctx, obj, append(opts, DryRunAll)...) } // Patch implements client.Client -func (c *dryRunClient) Patch(ctx context.Context, obj runtime.Object, patch Patch, opts ...PatchOption) error { +func (c *dryRunClient) Patch(ctx context.Context, obj Object, patch Patch, opts ...PatchOption) error { return c.client.Patch(ctx, obj, patch, append(opts, DryRunAll)...) } // Get implements client.Client -func (c *dryRunClient) Get(ctx context.Context, key ObjectKey, obj runtime.Object) error { +func (c *dryRunClient) Get(ctx context.Context, key ObjectKey, obj Object) error { return c.client.Get(ctx, key, obj) } // List implements client.Client -func (c *dryRunClient) List(ctx context.Context, obj runtime.Object, opts ...ListOption) error { +func (c *dryRunClient) List(ctx context.Context, obj ObjectList, opts ...ListOption) error { return c.client.List(ctx, obj, opts...) } @@ -96,11 +96,11 @@ type dryRunStatusWriter struct { } // Update implements client.StatusWriter -func (sw *dryRunStatusWriter) Update(ctx context.Context, obj runtime.Object, opts ...UpdateOption) error { +func (sw *dryRunStatusWriter) Update(ctx context.Context, obj Object, opts ...UpdateOption) error { return sw.client.Update(ctx, obj, append(opts, DryRunAll)...) } // Patch implements client.StatusWriter -func (sw *dryRunStatusWriter) Patch(ctx context.Context, obj runtime.Object, patch Patch, opts ...PatchOption) error { +func (sw *dryRunStatusWriter) Patch(ctx context.Context, obj Object, patch Patch, opts ...PatchOption) error { return sw.client.Patch(ctx, obj, patch, append(opts, DryRunAll)...) } diff --git a/pkg/client/example_test.go b/pkg/client/example_test.go index 345bf28a24..1be098bbbb 100644 --- a/pkg/client/example_test.go +++ b/pkg/client/example_test.go @@ -25,7 +25,6 @@ import ( corev1 "k8s.io/api/core/v1" 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/types" @@ -238,7 +237,7 @@ func ExampleClient_deleteAllOf() { _ = c.DeleteAllOf(context.Background(), &corev1.Pod{}, client.InNamespace("foo"), client.MatchingLabels{"app": "foo"}) // Using an unstructured Object - u := &unstructured.UnstructuredList{} + u := &unstructured.Unstructured{} u.SetGroupVersionKind(schema.GroupVersionKind{ Group: "apps", Kind: "Deployment", @@ -250,7 +249,7 @@ func ExampleClient_deleteAllOf() { // This example shows how to set up and consume a field selector over a pod's volumes' secretName field. func ExampleFieldIndexer_secretName() { // someIndexer is a FieldIndexer over a Cache - _ = someIndexer.IndexField(context.TODO(), &corev1.Pod{}, "spec.volumes.secret.secretName", func(o runtime.Object) []string { + _ = someIndexer.IndexField(context.TODO(), &corev1.Pod{}, "spec.volumes.secret.secretName", func(o client.Object) []string { var res []string for _, vol := range o.(*corev1.Pod).Spec.Volumes { if vol.Secret == nil { diff --git a/pkg/client/fake/client.go b/pkg/client/fake/client.go index 2292843e56..e4f286e733 100644 --- a/pkg/client/fake/client.go +++ b/pkg/client/fake/client.go @@ -58,14 +58,14 @@ const ( // NewFakeClient creates a new fake client for testing. // You can choose to initialize it with a slice of runtime.Object. -func NewFakeClient(initObjs ...runtime.Object) client.Client { +func NewFakeClient(initObjs ...client.Object) client.Client { return NewFakeClientWithScheme(scheme.Scheme, initObjs...) } // NewFakeClientWithScheme creates a new fake client with the given scheme // for testing. // You can choose to initialize it with a slice of runtime.Object. -func NewFakeClientWithScheme(clientScheme *runtime.Scheme, initObjs ...runtime.Object) client.Client { +func NewFakeClientWithScheme(clientScheme *runtime.Scheme, initObjs ...client.Object) client.Client { tracker := testing.NewObjectTracker(clientScheme, scheme.Codecs.UniversalDecoder()) for _, obj := range initObjs { err := tracker.Add(obj) @@ -149,7 +149,7 @@ func (t versionedTracker) Update(gvr schema.GroupVersionResource, obj runtime.Ob return t.ObjectTracker.Update(gvr, obj, ns) } -func (c *fakeClient) Get(ctx context.Context, key client.ObjectKey, obj runtime.Object) error { +func (c *fakeClient) Get(ctx context.Context, key client.ObjectKey, obj client.Object) error { gvr, err := getGVRFromObject(obj, c.scheme) if err != nil { return err @@ -179,7 +179,7 @@ func (c *fakeClient) Get(ctx context.Context, key client.ObjectKey, obj runtime. return err } -func (c *fakeClient) List(ctx context.Context, obj runtime.Object, opts ...client.ListOption) error { +func (c *fakeClient) List(ctx context.Context, obj client.ObjectList, opts ...client.ListOption) error { gvk, err := apiutil.GVKForObject(obj, c.scheme) if err != nil { return err @@ -245,7 +245,7 @@ func (c *fakeClient) RESTMapper() meta.RESTMapper { return nil } -func (c *fakeClient) Create(ctx context.Context, obj runtime.Object, opts ...client.CreateOption) error { +func (c *fakeClient) Create(ctx context.Context, obj client.Object, opts ...client.CreateOption) error { createOptions := &client.CreateOptions{} createOptions.ApplyOptions(opts) @@ -275,7 +275,7 @@ func (c *fakeClient) Create(ctx context.Context, obj runtime.Object, opts ...cli return c.tracker.Create(gvr, obj, accessor.GetNamespace()) } -func (c *fakeClient) Delete(ctx context.Context, obj runtime.Object, opts ...client.DeleteOption) error { +func (c *fakeClient) Delete(ctx context.Context, obj client.Object, opts ...client.DeleteOption) error { gvr, err := getGVRFromObject(obj, c.scheme) if err != nil { return err @@ -291,7 +291,7 @@ func (c *fakeClient) Delete(ctx context.Context, obj runtime.Object, opts ...cli return c.tracker.Delete(gvr, accessor.GetNamespace(), accessor.GetName()) } -func (c *fakeClient) DeleteAllOf(ctx context.Context, obj runtime.Object, opts ...client.DeleteAllOfOption) error { +func (c *fakeClient) DeleteAllOf(ctx context.Context, obj client.Object, opts ...client.DeleteAllOfOption) error { gvk, err := apiutil.GVKForObject(obj, c.scheme) if err != nil { return err @@ -327,7 +327,7 @@ func (c *fakeClient) DeleteAllOf(ctx context.Context, obj runtime.Object, opts . return nil } -func (c *fakeClient) Update(ctx context.Context, obj runtime.Object, opts ...client.UpdateOption) error { +func (c *fakeClient) Update(ctx context.Context, obj client.Object, opts ...client.UpdateOption) error { updateOptions := &client.UpdateOptions{} updateOptions.ApplyOptions(opts) @@ -348,7 +348,7 @@ func (c *fakeClient) Update(ctx context.Context, obj runtime.Object, opts ...cli return c.tracker.Update(gvr, obj, accessor.GetNamespace()) } -func (c *fakeClient) Patch(ctx context.Context, obj runtime.Object, patch client.Patch, opts ...client.PatchOption) error { +func (c *fakeClient) Patch(ctx context.Context, obj client.Object, patch client.Patch, opts ...client.PatchOption) error { patchOptions := &client.PatchOptions{} patchOptions.ApplyOptions(opts) @@ -417,13 +417,13 @@ type fakeStatusWriter struct { client *fakeClient } -func (sw *fakeStatusWriter) Update(ctx context.Context, obj runtime.Object, opts ...client.UpdateOption) error { +func (sw *fakeStatusWriter) Update(ctx context.Context, obj client.Object, opts ...client.UpdateOption) error { // TODO(droot): This results in full update of the obj (spec + status). Need // a way to update status field only. return sw.client.Update(ctx, obj, opts...) } -func (sw *fakeStatusWriter) Patch(ctx context.Context, obj runtime.Object, patch client.Patch, opts ...client.PatchOption) error { +func (sw *fakeStatusWriter) Patch(ctx context.Context, obj client.Object, patch client.Patch, opts ...client.PatchOption) error { // TODO(droot): This results in full update of the obj (spec + status). Need // a way to update status field only. return sw.client.Patch(ctx, obj, patch, opts...) diff --git a/pkg/client/interfaces.go b/pkg/client/interfaces.go index e83a89381c..cb4c8db2b7 100644 --- a/pkg/client/interfaces.go +++ b/pkg/client/interfaces.go @@ -53,32 +53,32 @@ type Reader interface { // Get retrieves an obj for the given object key from the Kubernetes Cluster. // obj must be a struct pointer so that obj can be updated with the response // returned by the Server. - Get(ctx context.Context, key ObjectKey, obj runtime.Object) error + Get(ctx context.Context, key ObjectKey, obj Object) error // List retrieves list of objects for a given namespace and list options. On a // successful call, Items field in the list will be populated with the // result returned from the server. - List(ctx context.Context, list runtime.Object, opts ...ListOption) error + List(ctx context.Context, list ObjectList, opts ...ListOption) error } // Writer knows how to create, delete, and update Kubernetes objects. type Writer interface { // Create saves the object obj in the Kubernetes cluster. - Create(ctx context.Context, obj runtime.Object, opts ...CreateOption) error + Create(ctx context.Context, obj Object, opts ...CreateOption) error // Delete deletes the given obj from Kubernetes cluster. - Delete(ctx context.Context, obj runtime.Object, opts ...DeleteOption) error + Delete(ctx context.Context, obj Object, opts ...DeleteOption) error // Update updates the given obj in the Kubernetes cluster. obj must be a // struct pointer so that obj can be updated with the content returned by the Server. - Update(ctx context.Context, obj runtime.Object, opts ...UpdateOption) error + Update(ctx context.Context, obj Object, opts ...UpdateOption) error // Patch patches the given obj in the Kubernetes cluster. obj must be a // struct pointer so that obj can be updated with the content returned by the Server. - Patch(ctx context.Context, obj runtime.Object, patch Patch, opts ...PatchOption) error + Patch(ctx context.Context, obj Object, patch Patch, opts ...PatchOption) error // DeleteAllOf deletes all objects of the given type matching the given options. - DeleteAllOf(ctx context.Context, obj runtime.Object, opts ...DeleteAllOfOption) error + DeleteAllOf(ctx context.Context, obj Object, opts ...DeleteAllOfOption) error } // StatusClient knows how to create a client which can update status subresource @@ -92,12 +92,12 @@ type StatusWriter interface { // Update updates the fields corresponding to the status subresource for the // given obj. obj must be a struct pointer so that obj can be updated // with the content returned by the Server. - Update(ctx context.Context, obj runtime.Object, opts ...UpdateOption) error + Update(ctx context.Context, obj Object, opts ...UpdateOption) error // Patch patches the given object's subresource. obj must be a struct // pointer so that obj can be updated with the content returned by the // Server. - Patch(ctx context.Context, obj runtime.Object, patch Patch, opts ...PatchOption) error + Patch(ctx context.Context, obj Object, patch Patch, opts ...PatchOption) error } // Client knows how to perform CRUD operations on Kubernetes objects. @@ -115,7 +115,7 @@ type Client interface { // IndexerFunc knows how to take an object and turn it into a series // of non-namespaced keys. Namespaced objects are automatically given // namespaced and non-spaced variants, so keys do not need to include namespace. -type IndexerFunc func(runtime.Object) []string +type IndexerFunc func(Object) []string // FieldIndexer knows how to index over a particular "field" such that it // can later be used by a field selector. @@ -127,7 +127,7 @@ type FieldIndexer interface { // and "equality" in the field selector means that at least one key matches the value. // The FieldIndexer will automatically take care of indexing over namespace // and supporting efficient all-namespace queries. - IndexField(ctx context.Context, obj runtime.Object, field string, extractValue IndexerFunc) error + IndexField(ctx context.Context, obj Object, field string, extractValue IndexerFunc) error } // IgnoreNotFound returns nil on NotFound errors. diff --git a/pkg/client/object.go b/pkg/client/object.go new file mode 100644 index 0000000000..9b2e97f668 --- /dev/null +++ b/pkg/client/object.go @@ -0,0 +1,36 @@ +/* +Copyright 2020 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 client + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" +) + +// Object is a Kubernetes object, allows functions to work indistinctly with any resource that +// implements both Object interfaces. +type Object interface { + metav1.Object + runtime.Object +} + +// ObjectList is a Kubernetes object list, allows functions to work indistinctly with any resource that +// implements both runtime.Object and metav1.ListInterface interfaces. +type ObjectList interface { + metav1.ListInterface + runtime.Object +} diff --git a/pkg/client/split.go b/pkg/client/split.go index 2bd086d1c4..00f84ccb84 100644 --- a/pkg/client/split.go +++ b/pkg/client/split.go @@ -78,7 +78,7 @@ type delegatingReader struct { } // Get retrieves an obj for a given object key from the Kubernetes Cluster. -func (d *delegatingReader) Get(ctx context.Context, key ObjectKey, obj runtime.Object) error { +func (d *delegatingReader) Get(ctx context.Context, key ObjectKey, obj Object) error { _, isUnstructured := obj.(*unstructured.Unstructured) if isUnstructured { return d.ClientReader.Get(ctx, key, obj) @@ -87,7 +87,7 @@ func (d *delegatingReader) Get(ctx context.Context, key ObjectKey, obj runtime.O } // List retrieves list of objects for a given namespace and list options. -func (d *delegatingReader) List(ctx context.Context, list runtime.Object, opts ...ListOption) error { +func (d *delegatingReader) List(ctx context.Context, list ObjectList, opts ...ListOption) error { _, isUnstructured := list.(*unstructured.UnstructuredList) if isUnstructured { return d.ClientReader.List(ctx, list, opts...) diff --git a/pkg/client/typed_client.go b/pkg/client/typed_client.go index d65f04fe9b..a1b32653ca 100644 --- a/pkg/client/typed_client.go +++ b/pkg/client/typed_client.go @@ -22,6 +22,10 @@ import ( "k8s.io/apimachinery/pkg/runtime" ) +var _ Reader = &typedClient{} +var _ Writer = &typedClient{} +var _ StatusWriter = &typedClient{} + // client is a client.Client that reads and writes directly from/to an API server. It lazily initializes // new clients at the time they are used, and caches the client. type typedClient struct { @@ -30,7 +34,7 @@ type typedClient struct { } // Create implements client.Client -func (c *typedClient) Create(ctx context.Context, obj runtime.Object, opts ...CreateOption) error { +func (c *typedClient) Create(ctx context.Context, obj Object, opts ...CreateOption) error { o, err := c.cache.getObjMeta(obj) if err != nil { return err @@ -48,7 +52,7 @@ func (c *typedClient) Create(ctx context.Context, obj runtime.Object, opts ...Cr } // Update implements client.Client -func (c *typedClient) Update(ctx context.Context, obj runtime.Object, opts ...UpdateOption) error { +func (c *typedClient) Update(ctx context.Context, obj Object, opts ...UpdateOption) error { o, err := c.cache.getObjMeta(obj) if err != nil { return err @@ -67,7 +71,7 @@ func (c *typedClient) Update(ctx context.Context, obj runtime.Object, opts ...Up } // Delete implements client.Client -func (c *typedClient) Delete(ctx context.Context, obj runtime.Object, opts ...DeleteOption) error { +func (c *typedClient) Delete(ctx context.Context, obj Object, opts ...DeleteOption) error { o, err := c.cache.getObjMeta(obj) if err != nil { return err @@ -86,7 +90,7 @@ func (c *typedClient) Delete(ctx context.Context, obj runtime.Object, opts ...De } // DeleteAllOf implements client.Client -func (c *typedClient) DeleteAllOf(ctx context.Context, obj runtime.Object, opts ...DeleteAllOfOption) error { +func (c *typedClient) DeleteAllOf(ctx context.Context, obj Object, opts ...DeleteAllOfOption) error { o, err := c.cache.getObjMeta(obj) if err != nil { return err @@ -105,7 +109,7 @@ func (c *typedClient) DeleteAllOf(ctx context.Context, obj runtime.Object, opts } // Patch implements client.Client -func (c *typedClient) Patch(ctx context.Context, obj runtime.Object, patch Patch, opts ...PatchOption) error { +func (c *typedClient) Patch(ctx context.Context, obj Object, patch Patch, opts ...PatchOption) error { o, err := c.cache.getObjMeta(obj) if err != nil { return err @@ -128,7 +132,7 @@ func (c *typedClient) Patch(ctx context.Context, obj runtime.Object, patch Patch } // Get implements client.Client -func (c *typedClient) Get(ctx context.Context, key ObjectKey, obj runtime.Object) error { +func (c *typedClient) Get(ctx context.Context, key ObjectKey, obj Object) error { r, err := c.cache.getResource(obj) if err != nil { return err @@ -140,7 +144,7 @@ func (c *typedClient) Get(ctx context.Context, key ObjectKey, obj runtime.Object } // List implements client.Client -func (c *typedClient) List(ctx context.Context, obj runtime.Object, opts ...ListOption) error { +func (c *typedClient) List(ctx context.Context, obj ObjectList, opts ...ListOption) error { r, err := c.cache.getResource(obj) if err != nil { return err @@ -156,7 +160,7 @@ func (c *typedClient) List(ctx context.Context, obj runtime.Object, opts ...List } // UpdateStatus used by StatusWriter to write status. -func (c *typedClient) UpdateStatus(ctx context.Context, obj runtime.Object, opts ...UpdateOption) error { +func (c *typedClient) UpdateStatus(ctx context.Context, obj Object, opts ...UpdateOption) error { o, err := c.cache.getObjMeta(obj) if err != nil { return err @@ -177,7 +181,7 @@ func (c *typedClient) UpdateStatus(ctx context.Context, obj runtime.Object, opts } // PatchStatus used by StatusWriter to write status. -func (c *typedClient) PatchStatus(ctx context.Context, obj runtime.Object, patch Patch, opts ...PatchOption) error { +func (c *typedClient) PatchStatus(ctx context.Context, obj Object, patch Patch, opts ...PatchOption) error { o, err := c.cache.getObjMeta(obj) if err != nil { return err diff --git a/pkg/client/unstructured_client.go b/pkg/client/unstructured_client.go index 5613791b9f..f8fb3ccec1 100644 --- a/pkg/client/unstructured_client.go +++ b/pkg/client/unstructured_client.go @@ -25,6 +25,10 @@ import ( "k8s.io/apimachinery/pkg/runtime" ) +var _ Reader = &unstructuredClient{} +var _ Writer = &unstructuredClient{} +var _ StatusWriter = &unstructuredClient{} + // client is a client.Client that reads and writes directly from/to an API server. It lazily initializes // new clients at the time they are used, and caches the client. type unstructuredClient struct { @@ -33,7 +37,7 @@ type unstructuredClient struct { } // Create implements client.Client -func (uc *unstructuredClient) Create(ctx context.Context, obj runtime.Object, opts ...CreateOption) error { +func (uc *unstructuredClient) Create(ctx context.Context, obj Object, opts ...CreateOption) error { u, ok := obj.(*unstructured.Unstructured) if !ok { return fmt.Errorf("unstructured client did not understand object: %T", obj) @@ -61,7 +65,7 @@ func (uc *unstructuredClient) Create(ctx context.Context, obj runtime.Object, op } // Update implements client.Client -func (uc *unstructuredClient) Update(ctx context.Context, obj runtime.Object, opts ...UpdateOption) error { +func (uc *unstructuredClient) Update(ctx context.Context, obj Object, opts ...UpdateOption) error { u, ok := obj.(*unstructured.Unstructured) if !ok { return fmt.Errorf("unstructured client did not understand object: %T", obj) @@ -90,7 +94,7 @@ func (uc *unstructuredClient) Update(ctx context.Context, obj runtime.Object, op } // Delete implements client.Client -func (uc *unstructuredClient) Delete(ctx context.Context, obj runtime.Object, opts ...DeleteOption) error { +func (uc *unstructuredClient) Delete(ctx context.Context, obj Object, opts ...DeleteOption) error { _, ok := obj.(*unstructured.Unstructured) if !ok { return fmt.Errorf("unstructured client did not understand object: %T", obj) @@ -113,7 +117,7 @@ func (uc *unstructuredClient) Delete(ctx context.Context, obj runtime.Object, op } // DeleteAllOf implements client.Client -func (uc *unstructuredClient) DeleteAllOf(ctx context.Context, obj runtime.Object, opts ...DeleteAllOfOption) error { +func (uc *unstructuredClient) DeleteAllOf(ctx context.Context, obj Object, opts ...DeleteAllOfOption) error { _, ok := obj.(*unstructured.Unstructured) if !ok { return fmt.Errorf("unstructured client did not understand object: %T", obj) @@ -136,7 +140,7 @@ func (uc *unstructuredClient) DeleteAllOf(ctx context.Context, obj runtime.Objec } // Patch implements client.Client -func (uc *unstructuredClient) Patch(ctx context.Context, obj runtime.Object, patch Patch, opts ...PatchOption) error { +func (uc *unstructuredClient) Patch(ctx context.Context, obj Object, patch Patch, opts ...PatchOption) error { _, ok := obj.(*unstructured.Unstructured) if !ok { return fmt.Errorf("unstructured client did not understand object: %T", obj) @@ -164,7 +168,7 @@ func (uc *unstructuredClient) Patch(ctx context.Context, obj runtime.Object, pat } // Get implements client.Client -func (uc *unstructuredClient) Get(ctx context.Context, key ObjectKey, obj runtime.Object) error { +func (uc *unstructuredClient) Get(ctx context.Context, key ObjectKey, obj Object) error { u, ok := obj.(*unstructured.Unstructured) if !ok { return fmt.Errorf("unstructured client did not understand object: %T", obj) @@ -190,7 +194,7 @@ func (uc *unstructuredClient) Get(ctx context.Context, key ObjectKey, obj runtim } // List implements client.Client -func (uc *unstructuredClient) List(ctx context.Context, obj runtime.Object, opts ...ListOption) error { +func (uc *unstructuredClient) List(ctx context.Context, obj ObjectList, opts ...ListOption) error { u, ok := obj.(*unstructured.UnstructuredList) if !ok { return fmt.Errorf("unstructured client did not understand object: %T", obj) @@ -217,7 +221,7 @@ func (uc *unstructuredClient) List(ctx context.Context, obj runtime.Object, opts Into(obj) } -func (uc *unstructuredClient) UpdateStatus(ctx context.Context, obj runtime.Object, opts ...UpdateOption) error { +func (uc *unstructuredClient) UpdateStatus(ctx context.Context, obj Object, opts ...UpdateOption) error { _, ok := obj.(*unstructured.Unstructured) if !ok { return fmt.Errorf("unstructured client did not understand object: %T", obj) @@ -239,7 +243,7 @@ func (uc *unstructuredClient) UpdateStatus(ctx context.Context, obj runtime.Obje Into(obj) } -func (uc *unstructuredClient) PatchStatus(ctx context.Context, obj runtime.Object, patch Patch, opts ...PatchOption) error { +func (uc *unstructuredClient) PatchStatus(ctx context.Context, obj Object, patch Patch, opts ...PatchOption) error { u, ok := obj.(*unstructured.Unstructured) if !ok { return fmt.Errorf("unstructured client did not understand object: %T", obj) diff --git a/pkg/controller/controllerutil/controllerutil.go b/pkg/controller/controllerutil/controllerutil.go index 478dda5180..7932c658f8 100644 --- a/pkg/controller/controllerutil/controllerutil.go +++ b/pkg/controller/controllerutil/controllerutil.go @@ -194,7 +194,7 @@ const ( // They should complete the sentence "Deployment default/foo has been .. // The MutateFn is called regardless of creating or updating an object. // // It returns the executed operation and an error. -func CreateOrUpdate(ctx context.Context, c client.Client, obj runtime.Object, f MutateFn) (OperationResult, error) { +func CreateOrUpdate(ctx context.Context, c client.Client, obj client.Object, f MutateFn) (OperationResult, error) { key, err := client.ObjectKeyFromObject(obj) if err != nil { return OperationResultNone, err @@ -235,7 +235,7 @@ func CreateOrUpdate(ctx context.Context, c client.Client, obj runtime.Object, f // The MutateFn is called regardless of creating or updating an object. // // It returns the executed operation and an error. -func CreateOrPatch(ctx context.Context, c client.Client, obj runtime.Object, f MutateFn) (OperationResult, error) { +func CreateOrPatch(ctx context.Context, c client.Client, obj client.Object, f MutateFn) (OperationResult, error) { key, err := client.ObjectKeyFromObject(obj) if err != nil { return OperationResultNone, err @@ -345,7 +345,7 @@ func mutate(f MutateFn, key client.ObjectKey, obj runtime.Object) error { type MutateFn func() error // AddFinalizer accepts an Object and adds the provided finalizer if not present. -func AddFinalizer(o Object, finalizer string) { +func AddFinalizer(o client.Object, finalizer string) { f := o.GetFinalizers() for _, e := range f { if e == finalizer { @@ -356,7 +356,7 @@ func AddFinalizer(o Object, finalizer string) { } // RemoveFinalizer accepts an Object and removes the provided finalizer if present. -func RemoveFinalizer(o Object, finalizer string) { +func RemoveFinalizer(o client.Object, finalizer string) { f := o.GetFinalizers() for i := 0; i < len(f); i++ { if f[i] == finalizer { @@ -368,7 +368,7 @@ func RemoveFinalizer(o Object, finalizer string) { } // ContainsFinalizer checks an Object that the provided finalizer is present. -func ContainsFinalizer(o Object, finalizer string) bool { +func ContainsFinalizer(o client.Object, finalizer string) bool { f := o.GetFinalizers() for _, e := range f { if e == finalizer { @@ -380,7 +380,6 @@ func ContainsFinalizer(o Object, finalizer string) bool { // Object allows functions to work indistinctly with any resource that // implements both Object interfaces. -type Object interface { - metav1.Object - runtime.Object -} +// +// Deprecated: Use client.Object instead. +type Object = client.Object diff --git a/pkg/controller/controllerutil/controllerutil_test.go b/pkg/controller/controllerutil/controllerutil_test.go index 737771601b..840f9a1f49 100644 --- a/pkg/controller/controllerutil/controllerutil_test.go +++ b/pkg/controller/controllerutil/controllerutil_test.go @@ -723,6 +723,6 @@ type errorReader struct { client.Client } -func (e errorReader) Get(ctx context.Context, key client.ObjectKey, into runtime.Object) error { +func (e errorReader) Get(ctx context.Context, key client.ObjectKey, into client.Object) error { return fmt.Errorf("unexpected error") } diff --git a/pkg/event/event.go b/pkg/event/event.go index 59abd91bd4..271b3c00fb 100644 --- a/pkg/event/event.go +++ b/pkg/event/event.go @@ -16,32 +16,30 @@ limitations under the License. package event -import ( - "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" -) +import "sigs.k8s.io/controller-runtime/pkg/client" // CreateEvent is an event where a Kubernetes object was created. CreateEvent should be generated // by a source.Source and transformed into a reconcile.Request by an handler.EventHandler. type CreateEvent struct { // Object is the object from the event - Object controllerutil.Object + Object client.Object } // UpdateEvent is an event where a Kubernetes object was updated. UpdateEvent should be generated // by a source.Source and transformed into a reconcile.Request by an handler.EventHandler. type UpdateEvent struct { // ObjectOld is the object from the event - ObjectOld controllerutil.Object + ObjectOld client.Object // ObjectNew is the object from the event - ObjectNew controllerutil.Object + ObjectNew client.Object } // DeleteEvent is an event where a Kubernetes object was deleted. DeleteEvent should be generated // by a source.Source and transformed into a reconcile.Request by an handler.EventHandler. type DeleteEvent struct { // Object is the object from the event - Object controllerutil.Object + Object client.Object // DeleteStateUnknown is true if the Delete event was missed but we identified the object // as having been deleted. @@ -53,5 +51,5 @@ type DeleteEvent struct { // handler.EventHandler. type GenericEvent struct { // Object is the object from the event - Object controllerutil.Object + Object client.Object } diff --git a/pkg/handler/enqueue_mapped.go b/pkg/handler/enqueue_mapped.go index 3111daee42..24fe3877c9 100644 --- a/pkg/handler/enqueue_mapped.go +++ b/pkg/handler/enqueue_mapped.go @@ -18,7 +18,7 @@ package handler import ( "k8s.io/client-go/util/workqueue" - "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" + "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/event" "sigs.k8s.io/controller-runtime/pkg/reconcile" "sigs.k8s.io/controller-runtime/pkg/runtime/inject" @@ -90,5 +90,5 @@ func (e *enqueueRequestsFromMapFunc) InjectFunc(f inject.Func) error { // MapObject contains information from an event to be transformed into a Request. type MapObject struct { - Object controllerutil.Object + Object client.Object } diff --git a/pkg/predicate/predicate.go b/pkg/predicate/predicate.go index 93a7bf0d0e..079ef23df0 100644 --- a/pkg/predicate/predicate.go +++ b/pkg/predicate/predicate.go @@ -19,7 +19,7 @@ package predicate import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" - "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" + "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/event" logf "sigs.k8s.io/controller-runtime/pkg/internal/log" ) @@ -97,7 +97,7 @@ func (p Funcs) Generic(e event.GenericEvent) bool { // NewPredicateFuncs returns a predicate funcs that applies the given filter function // on CREATE, UPDATE, DELETE and GENERIC events. For UPDATE events, the filter is applied // to the new object. -func NewPredicateFuncs(filter func(object controllerutil.Object) bool) Funcs { +func NewPredicateFuncs(filter func(object client.Object) bool) Funcs { return Funcs{ CreateFunc: func(e event.CreateEvent) bool { return filter(e.Object) @@ -278,7 +278,7 @@ func LabelSelectorPredicate(s metav1.LabelSelector) (Predicate, error) { if err != nil { return Funcs{}, err } - return NewPredicateFuncs(func(o controllerutil.Object) bool { + return NewPredicateFuncs(func(o client.Object) bool { return selector.Matches(labels.Set(o.GetLabels())) }), nil } diff --git a/pkg/predicate/predicate_test.go b/pkg/predicate/predicate_test.go index ddf5e15391..c4419a6435 100644 --- a/pkg/predicate/predicate_test.go +++ b/pkg/predicate/predicate_test.go @@ -22,7 +22,7 @@ import ( corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" + "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/event" "sigs.k8s.io/controller-runtime/pkg/predicate" ) @@ -468,8 +468,8 @@ var _ = Describe("Predicate", func() { }) Describe("NewPredicateFuncs with a namespace filter function", func() { - byNamespaceFilter := func(namespace string) func(object controllerutil.Object) bool { - return func(object controllerutil.Object) bool { + byNamespaceFilter := func(namespace string) func(object client.Object) bool { + return func(object client.Object) bool { return object.GetNamespace() == namespace } } diff --git a/pkg/source/internal/eventsource.go b/pkg/source/internal/eventsource.go index df2fb515c6..33c4c41348 100644 --- a/pkg/source/internal/eventsource.go +++ b/pkg/source/internal/eventsource.go @@ -21,11 +21,11 @@ import ( "k8s.io/client-go/tools/cache" "k8s.io/client-go/util/workqueue" + "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/event" "sigs.k8s.io/controller-runtime/pkg/handler" logf "sigs.k8s.io/controller-runtime/pkg/internal/log" - "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" "sigs.k8s.io/controller-runtime/pkg/predicate" ) @@ -45,7 +45,7 @@ func (e EventHandler) OnAdd(obj interface{}) { c := event.CreateEvent{} // Pull Object out of the object - if o, ok := obj.(controllerutil.Object); ok { + if o, ok := obj.(client.Object); ok { c.Object = o } else { log.Error(nil, "OnAdd missing Object", @@ -67,7 +67,7 @@ func (e EventHandler) OnAdd(obj interface{}) { func (e EventHandler) OnUpdate(oldObj, newObj interface{}) { u := event.UpdateEvent{} - if o, ok := oldObj.(controllerutil.Object); ok { + if o, ok := oldObj.(client.Object); ok { u.ObjectOld = o } else { log.Error(nil, "OnUpdate missing ObjectOld", @@ -76,7 +76,7 @@ func (e EventHandler) OnUpdate(oldObj, newObj interface{}) { } // Pull Object out of the object - if o, ok := newObj.(controllerutil.Object); ok { + if o, ok := newObj.(client.Object); ok { u.ObjectNew = o } else { log.Error(nil, "OnUpdate missing ObjectNew", @@ -104,7 +104,7 @@ func (e EventHandler) OnDelete(obj interface{}) { // This should never happen if we aren't missing events, which we have concluded that we are not // and made decisions off of this belief. Maybe this shouldn't be here? var ok bool - if _, ok = obj.(controllerutil.Object); !ok { + if _, ok = obj.(client.Object); !ok { // If the object doesn't have Metadata, assume it is a tombstone object of type DeletedFinalStateUnknown tombstone, ok := obj.(cache.DeletedFinalStateUnknown) if !ok { @@ -119,7 +119,7 @@ func (e EventHandler) OnDelete(obj interface{}) { } // Pull Object out of the object - if o, ok := obj.(controllerutil.Object); ok { + if o, ok := obj.(client.Object); ok { d.Object = o } else { log.Error(nil, "OnDelete missing Object", diff --git a/pkg/source/source.go b/pkg/source/source.go index 5eff2177b5..fe0e47150a 100644 --- a/pkg/source/source.go +++ b/pkg/source/source.go @@ -23,8 +23,8 @@ import ( "sync" "k8s.io/apimachinery/pkg/api/meta" - "k8s.io/apimachinery/pkg/runtime" "k8s.io/client-go/util/workqueue" + "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/event" "sigs.k8s.io/controller-runtime/pkg/handler" logf "sigs.k8s.io/controller-runtime/pkg/internal/log" @@ -67,7 +67,7 @@ type SyncingSource interface { // NewKindWithCache creates a Source without InjectCache, so that it is assured that the given cache is used // and not overwritten. It can be used to watch objects in a different cluster by passing the cache // from that other cluster -func NewKindWithCache(object runtime.Object, cache cache.Cache) SyncingSource { +func NewKindWithCache(object client.Object, cache cache.Cache) SyncingSource { return &kindWithCache{kind: Kind{Type: object, cache: cache}} } @@ -87,7 +87,7 @@ func (ks *kindWithCache) WaitForSync(ctx context.Context) error { // Kind is used to provide a source of events originating inside the cluster from Watches (e.g. Pod Create) type Kind struct { // Type is the type of object to watch. e.g. &v1.Pod{} - Type runtime.Object + Type client.Object // cache used to watch APIs cache cache.Cache diff --git a/pkg/source/source_integration_test.go b/pkg/source/source_integration_test.go index 2a19729097..087cdbcb4c 100644 --- a/pkg/source/source_integration_test.go +++ b/pkg/source/source_integration_test.go @@ -20,6 +20,7 @@ import ( "fmt" "time" + "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/event" "sigs.k8s.io/controller-runtime/pkg/handler" "sigs.k8s.io/controller-runtime/pkg/runtime/inject" @@ -30,7 +31,6 @@ import ( appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" kubeinformers "k8s.io/client-go/informers" toolscache "k8s.io/client-go/tools/cache" "k8s.io/client-go/util/workqueue" @@ -38,7 +38,7 @@ import ( var _ = Describe("Source", func() { var instance1, instance2 *source.Kind - var obj runtime.Object + var obj client.Object var q workqueue.RateLimitingInterface var c1, c2 chan interface{} var ns string