Skip to content

Commit

Permalink
ResettableRESTMapper to make it possible to reset wrapped mappers
Browse files Browse the repository at this point in the history
  • Loading branch information
ash2k committed Nov 5, 2021
1 parent 88c000e commit de4598d
Show file tree
Hide file tree
Showing 11 changed files with 71 additions and 17 deletions.
14 changes: 3 additions & 11 deletions pkg/controller/garbagecollector/garbagecollector.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ import (
"sync"
"time"

"k8s.io/klog/v2"

v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/meta"
Expand All @@ -45,6 +43,7 @@ import (
"k8s.io/client-go/util/workqueue"
"k8s.io/controller-manager/controller"
"k8s.io/controller-manager/pkg/informerfactory"
"k8s.io/klog/v2"
c "k8s.io/kubernetes/pkg/controller"
"k8s.io/kubernetes/pkg/controller/apis/config/scheme"

Expand All @@ -67,7 +66,7 @@ const ResourceResyncTime time.Duration = 0
// ensures that the garbage collector operates with a graph that is at least as
// up to date as the notification is sent.
type GarbageCollector struct {
restMapper resettableRESTMapper
restMapper meta.ResettableRESTMapper
metadataClient metadata.Interface
// garbage collector attempts to delete the items in attemptToDelete queue when the time is ripe.
attemptToDelete workqueue.RateLimitingInterface
Expand All @@ -87,7 +86,7 @@ var _ controller.Debuggable = (*GarbageCollector)(nil)
func NewGarbageCollector(
kubeClient clientset.Interface,
metadataClient metadata.Interface,
mapper resettableRESTMapper,
mapper meta.ResettableRESTMapper,
ignoredResources map[schema.GroupResource]struct{},
sharedInformers informerfactory.InformerFactory,
informersStarted <-chan struct{},
Expand Down Expand Up @@ -164,13 +163,6 @@ func (gc *GarbageCollector) Run(ctx context.Context, workers int) {
<-ctx.Done()
}

// resettableRESTMapper is a RESTMapper which is capable of resetting itself
// from discovery.
type resettableRESTMapper interface {
meta.RESTMapper
Reset()
}

// Sync periodically resyncs the garbage collector when new resources are
// observed from discovery. When new resources are detected, Sync will stop all
// GC workers, reset gc.restMapper, and resync the monitors.
Expand Down
4 changes: 3 additions & 1 deletion pkg/controller/garbagecollector/garbagecollector_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,9 @@ type testRESTMapper struct {
meta.RESTMapper
}

func (*testRESTMapper) Reset() {}
func (m *testRESTMapper) Reset() {
meta.MaybeResetRESTMapper(m.RESTMapper)
}

func TestGarbageCollectorConstruction(t *testing.T) {
config := &restclient.Config{}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ import (
utilerrors "k8s.io/apimachinery/pkg/util/errors"
)

var (
_ ResettableRESTMapper = &FirstHitRESTMapper{}
)

// FirstHitRESTMapper is a wrapper for multiple RESTMappers which returns the
// first successful result for the singular requests
type FirstHitRESTMapper struct {
Expand Down Expand Up @@ -75,6 +79,10 @@ func (m FirstHitRESTMapper) RESTMapping(gk schema.GroupKind, versions ...string)
return nil, collapseAggregateErrors(errors)
}

func (m FirstHitRESTMapper) Reset() {
m.MultiRESTMapper.Reset()
}

// collapseAggregateErrors returns the minimal errors. it handles empty as nil, handles one item in a list
// by returning the item, and collapses all NoMatchErrors to a single one (since they should all be the same)
func collapseAggregateErrors(errors []error) error {
Expand Down
9 changes: 9 additions & 0 deletions staging/src/k8s.io/apimachinery/pkg/api/meta/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,3 +132,12 @@ type RESTMapper interface {

ResourceSingularizer(resource string) (singular string, err error)
}

// ResettableRESTMapper is a RESTMapper which is capable of resetting itself
// from discovery.
// All rest mappers that delegate to other rest mappers must implement this interface and dynamically
// check if the delegate mapper supports the Reset() operation.
type ResettableRESTMapper interface {
RESTMapper
Reset()
}
12 changes: 10 additions & 2 deletions staging/src/k8s.io/apimachinery/pkg/api/meta/lazy.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ type lazyObject struct {
mapper RESTMapper
}

// NewLazyObjectLoader handles unrecoverable errors when creating a RESTMapper / ObjectTyper by
// NewLazyRESTMapperLoader handles unrecoverable errors when creating a RESTMapper / ObjectTyper by
// returning those initialization errors when the interface methods are invoked. This defers the
// initialization and any server calls until a client actually needs to perform the action.
func NewLazyRESTMapperLoader(fn func() (RESTMapper, error)) RESTMapper {
Expand All @@ -52,7 +52,7 @@ func (o *lazyObject) init() error {
return o.err
}

var _ RESTMapper = &lazyObject{}
var _ ResettableRESTMapper = &lazyObject{}

func (o *lazyObject) KindFor(resource schema.GroupVersionResource) (schema.GroupVersionKind, error) {
if err := o.init(); err != nil {
Expand Down Expand Up @@ -102,3 +102,11 @@ func (o *lazyObject) ResourceSingularizer(resource string) (singular string, err
}
return o.mapper.ResourceSingularizer(resource)
}

func (o *lazyObject) Reset() {
o.lock.Lock()
defer o.lock.Unlock()
if o.loaded && o.err == nil {
MaybeResetRESTMapper(o.mapper)
}
}
12 changes: 11 additions & 1 deletion staging/src/k8s.io/apimachinery/pkg/api/meta/multirestmapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,15 @@ import (
utilerrors "k8s.io/apimachinery/pkg/util/errors"
)

var (
_ ResettableRESTMapper = MultiRESTMapper{}
)

// MultiRESTMapper is a wrapper for multiple RESTMappers.
type MultiRESTMapper []RESTMapper

func (m MultiRESTMapper) String() string {
nested := []string{}
nested := make([]string, 0, len(m))
for _, t := range m {
currString := fmt.Sprintf("%v", t)
splitStrings := strings.Split(currString, "\n")
Expand Down Expand Up @@ -208,3 +212,9 @@ func (m MultiRESTMapper) RESTMappings(gk schema.GroupKind, versions ...string) (
}
return allMappings, nil
}

func (m MultiRESTMapper) Reset() {
for _, t := range m {
MaybeResetRESTMapper(t)
}
}
8 changes: 8 additions & 0 deletions staging/src/k8s.io/apimachinery/pkg/api/meta/priority.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ const (
AnyKind = "*"
)

var (
_ ResettableRESTMapper = PriorityRESTMapper{}
)

// PriorityRESTMapper is a wrapper for automatically choosing a particular Resource or Kind
// when multiple matches are possible
type PriorityRESTMapper struct {
Expand Down Expand Up @@ -220,3 +224,7 @@ func (m PriorityRESTMapper) ResourcesFor(partiallySpecifiedResource schema.Group
func (m PriorityRESTMapper) KindsFor(partiallySpecifiedResource schema.GroupVersionResource) (gvk []schema.GroupVersionKind, err error) {
return m.Delegate.KindsFor(partiallySpecifiedResource)
}

func (m PriorityRESTMapper) Reset() {
MaybeResetRESTMapper(m.Delegate)
}
9 changes: 9 additions & 0 deletions staging/src/k8s.io/apimachinery/pkg/api/meta/restmapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -519,3 +519,12 @@ func (m *DefaultRESTMapper) RESTMappings(gk schema.GroupKind, versions ...string
}
return mappings, nil
}

// MaybeResetRESTMapper calls Reset() on the mapper if it is a ResettableRESTMapper.
func MaybeResetRESTMapper(mapper RESTMapper) bool {
m, ok := mapper.(ResettableRESTMapper)
if ok {
m.Reset()
}
return ok
}
4 changes: 4 additions & 0 deletions staging/src/k8s.io/cli-runtime/pkg/resource/builder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,10 @@ func (l *errorRestMapper) RESTMapping(gk schema.GroupKind, versions ...string) (
return nil, l.err
}

func (l *errorRestMapper) Reset() {
meta.MaybeResetRESTMapper(l.RESTMapper)
}

func newDefaultBuilderWithMapperError(fakeClientFn FakeClientFunc, err error) *Builder {
return NewFakeBuilder(
fakeClientFn,
Expand Down
2 changes: 1 addition & 1 deletion staging/src/k8s.io/client-go/restmapper/discovery.go
Original file line number Diff line number Diff line change
Expand Up @@ -335,4 +335,4 @@ func (d *DeferredDiscoveryRESTMapper) String() string {
}

// Make sure it satisfies the interface
var _ meta.RESTMapper = &DeferredDiscoveryRESTMapper{}
var _ meta.ResettableRESTMapper = &DeferredDiscoveryRESTMapper{}
6 changes: 5 additions & 1 deletion staging/src/k8s.io/client-go/restmapper/shortcut.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ type shortcutExpander struct {
discoveryClient discovery.DiscoveryInterface
}

var _ meta.RESTMapper = &shortcutExpander{}
var _ meta.ResettableRESTMapper = shortcutExpander{}

// NewShortcutExpander wraps a restmapper in a layer that expands shortcuts found via discovery
func NewShortcutExpander(delegate meta.RESTMapper, client discovery.DiscoveryInterface) meta.RESTMapper {
Expand Down Expand Up @@ -164,6 +164,10 @@ func (e shortcutExpander) expandResourceShortcut(resource schema.GroupVersionRes
return resource
}

func (e shortcutExpander) Reset() {
meta.MaybeResetRESTMapper(e.RESTMapper)
}

// ResourceShortcuts represents a structure that holds the information how to
// transition from resource's shortcut to its full name.
type resourceShortcuts struct {
Expand Down

0 comments on commit de4598d

Please sign in to comment.