mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-09 12:07:47 +00:00
Generify lister-gen
This adds a generic implementation of a lister, and uses it to replace the template code in generated listers. The corresponding templates are no longer used and are removed. Listers are reduced to their interfaces (non-namespaced and namespaced if appropriate), their specific structs, and their constructors. All method implementations are provided by the generic implementation. The dedicated interface is preserved so that each lister can have its own set of methods (e.g. the method returning the namespaced lister if appropriate), and the dedicated struct is preserved to allow expansions to be defined where necessary. The external interface is unchanged and doesn't expose generics. Signed-off-by: Stephen Kitt <skitt@redhat.com>
This commit is contained in:
parent
44d7267bd6
commit
2e9adcd14a
72
staging/src/k8s.io/client-go/listers/generic_helpers.go
Normal file
72
staging/src/k8s.io/client-go/listers/generic_helpers.go
Normal file
@ -0,0 +1,72 @@
|
||||
/*
|
||||
Copyright 2023 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 listers
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
// ResourceIndexer wraps an indexer, resource, and optional namespace for a given type.
|
||||
// This is intended for use by listers (generated by lister-gen) only.
|
||||
type ResourceIndexer[T runtime.Object] struct {
|
||||
indexer cache.Indexer
|
||||
resource schema.GroupResource
|
||||
namespace string // empty for non-namespaced types
|
||||
}
|
||||
|
||||
// New returns a new instance of a lister (resource indexer) wrapping the given indexer and resource for the specified type.
|
||||
// This is intended for use by listers (generated by lister-gen) only.
|
||||
func New[T runtime.Object](indexer cache.Indexer, resource schema.GroupResource) ResourceIndexer[T] {
|
||||
return ResourceIndexer[T]{indexer: indexer, resource: resource}
|
||||
}
|
||||
|
||||
// NewNamespaced returns a new instance of a namespaced lister (resource indexer) wrapping the given parent and namespace for the specified type.
|
||||
// This is intended for use by listers (generated by lister-gen) only.
|
||||
func NewNamespaced[T runtime.Object](parent ResourceIndexer[T], namespace string) ResourceIndexer[T] {
|
||||
return ResourceIndexer[T]{indexer: parent.indexer, resource: parent.resource, namespace: namespace}
|
||||
}
|
||||
|
||||
// List lists all resources in the indexer matching the given selector.
|
||||
func (l ResourceIndexer[T]) List(selector labels.Selector) (ret []T, err error) {
|
||||
// ListAllByNamespace reverts to ListAll on empty namespaces
|
||||
err = cache.ListAllByNamespace(l.indexer, l.namespace, selector, func(m interface{}) {
|
||||
ret = append(ret, m.(T))
|
||||
})
|
||||
return ret, err
|
||||
}
|
||||
|
||||
// Get retrieves the resource from the index for a given name.
|
||||
func (l ResourceIndexer[T]) Get(name string) (T, error) {
|
||||
var key string
|
||||
if l.namespace == "" {
|
||||
key = name
|
||||
} else {
|
||||
key = l.namespace + "/" + name
|
||||
}
|
||||
obj, exists, err := l.indexer.GetByKey(key)
|
||||
if err != nil {
|
||||
return *new(T), err
|
||||
}
|
||||
if !exists {
|
||||
return *new(T), errors.NewNotFound(l.resource, name)
|
||||
}
|
||||
return obj.(T), nil
|
||||
}
|
@ -215,6 +215,7 @@ func (g *listerGenerator) Imports(c *generator.Context) (imports []string) {
|
||||
imports = append(imports, g.imports.ImportLines()...)
|
||||
imports = append(imports, "k8s.io/apimachinery/pkg/api/errors")
|
||||
imports = append(imports, "k8s.io/apimachinery/pkg/labels")
|
||||
imports = append(imports, "k8s.io/client-go/listers")
|
||||
// for Indexer
|
||||
imports = append(imports, "k8s.io/client-go/tools/cache")
|
||||
return
|
||||
@ -243,18 +244,14 @@ func (g *listerGenerator) GenerateType(c *generator.Context, t *types.Type, w io
|
||||
|
||||
sw.Do(typeListerStruct, m)
|
||||
sw.Do(typeListerConstructor, m)
|
||||
sw.Do(typeListerList, m)
|
||||
|
||||
if tags.NonNamespaced {
|
||||
sw.Do(typeListerNonNamespacedGet, m)
|
||||
return sw.Error()
|
||||
}
|
||||
|
||||
sw.Do(typeListerNamespaceLister, m)
|
||||
sw.Do(namespaceListerInterface, m)
|
||||
sw.Do(namespaceListerStruct, m)
|
||||
sw.Do(namespaceListerList, m)
|
||||
sw.Do(namespaceListerGet, m)
|
||||
|
||||
return sw.Error()
|
||||
}
|
||||
@ -286,48 +283,27 @@ type $.type|public$Lister interface {
|
||||
}
|
||||
`
|
||||
|
||||
// This embeds a typed resource indexer instead of aliasing, so that the struct
|
||||
// is available as a receiver for methods specific to the generated type
|
||||
// (from the corresponding expansion interface).
|
||||
var typeListerStruct = `
|
||||
// $.type|private$Lister implements the $.type|public$Lister interface.
|
||||
type $.type|private$Lister struct {
|
||||
indexer cache.Indexer
|
||||
listers.ResourceIndexer[*$.type|raw$]
|
||||
}
|
||||
`
|
||||
|
||||
var typeListerConstructor = `
|
||||
// New$.type|public$Lister returns a new $.type|public$Lister.
|
||||
func New$.type|public$Lister(indexer cache.Indexer) $.type|public$Lister {
|
||||
return &$.type|private$Lister{indexer: indexer}
|
||||
}
|
||||
`
|
||||
|
||||
var typeListerList = `
|
||||
// List lists all $.type|publicPlural$ in the indexer.
|
||||
func (s *$.type|private$Lister) List(selector labels.Selector) (ret []*$.type|raw$, err error) {
|
||||
err = cache.ListAll(s.indexer, selector, func(m interface{}) {
|
||||
ret = append(ret, m.(*$.type|raw$))
|
||||
})
|
||||
return ret, err
|
||||
return &$.type|private$Lister{listers.New[*$.type|raw$](indexer, $.Resource|raw$("$.type|lowercaseSingular$"))}
|
||||
}
|
||||
`
|
||||
|
||||
var typeListerNamespaceLister = `
|
||||
// $.type|publicPlural$ returns an object that can list and get $.type|publicPlural$.
|
||||
func (s *$.type|private$Lister) $.type|publicPlural$(namespace string) $.type|public$NamespaceLister {
|
||||
return $.type|private$NamespaceLister{indexer: s.indexer, namespace: namespace}
|
||||
}
|
||||
`
|
||||
|
||||
var typeListerNonNamespacedGet = `
|
||||
// Get retrieves the $.type|public$ from the index for a given name.
|
||||
func (s *$.type|private$Lister) Get(name string) (*$.type|raw$, error) {
|
||||
obj, exists, err := s.indexer.GetByKey(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !exists {
|
||||
return nil, errors.NewNotFound($.Resource|raw$("$.type|lowercaseSingular$"), name)
|
||||
}
|
||||
return obj.(*$.type|raw$), nil
|
||||
return $.type|private$NamespaceLister{listers.NewNamespaced[*$.type|raw$](s.ResourceIndexer, namespace)}
|
||||
}
|
||||
`
|
||||
|
||||
@ -345,35 +321,13 @@ type $.type|public$NamespaceLister interface {
|
||||
}
|
||||
`
|
||||
|
||||
// This embeds a typed namespaced resource indexer instead of aliasing, so that the struct
|
||||
// is available as a receiver for methods specific to the generated type
|
||||
// (from the corresponding expansion interface).
|
||||
var namespaceListerStruct = `
|
||||
// $.type|private$NamespaceLister implements the $.type|public$NamespaceLister
|
||||
// interface.
|
||||
type $.type|private$NamespaceLister struct {
|
||||
indexer cache.Indexer
|
||||
namespace string
|
||||
}
|
||||
`
|
||||
|
||||
var namespaceListerList = `
|
||||
// List lists all $.type|publicPlural$ in the indexer for a given namespace.
|
||||
func (s $.type|private$NamespaceLister) List(selector labels.Selector) (ret []*$.type|raw$, err error) {
|
||||
err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) {
|
||||
ret = append(ret, m.(*$.type|raw$))
|
||||
})
|
||||
return ret, err
|
||||
}
|
||||
`
|
||||
|
||||
var namespaceListerGet = `
|
||||
// Get retrieves the $.type|public$ from the indexer for a given namespace and name.
|
||||
func (s $.type|private$NamespaceLister) Get(name string) (*$.type|raw$, error) {
|
||||
obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !exists {
|
||||
return nil, errors.NewNotFound($.Resource|raw$("$.type|lowercaseSingular$"), name)
|
||||
}
|
||||
return obj.(*$.type|raw$), nil
|
||||
listers.ResourceIndexer[*$.type|raw$]
|
||||
}
|
||||
`
|
||||
|
Loading…
Reference in New Issue
Block a user