Skip to content

Commit 330bbcc

Browse files
ChaunceyctxChaunceyctx
authored and
Chaunceyctx
committed
add CodecFactoryOptions for codecfactory
1 parent 1947a94 commit 330bbcc

File tree

4 files changed

+96
-29
lines changed

4 files changed

+96
-29
lines changed

pkg/cache/cache.go

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,9 @@ type Options struct {
140140
// Scheme is the scheme to use for mapping objects to GroupVersionKinds
141141
Scheme *runtime.Scheme
142142

143+
// CodecFactoryOptionsByObject are used to indicate whether enable strict/pretty mode of codecFactory for specific object
144+
CodecFactoryOptionsByObject map[client.Object]client.CodecFactoryOptions
145+
143146
// Mapper is the RESTMapper to use for mapping GroupVersionKinds to Resources
144147
Mapper meta.RESTMapper
145148

@@ -420,11 +423,12 @@ func newCache(restConfig *rest.Config, opts Options) newCacheFunc {
420423
return &informerCache{
421424
scheme: opts.Scheme,
422425
Informers: internal.NewInformers(restConfig, &internal.InformersOpts{
423-
HTTPClient: opts.HTTPClient,
424-
Scheme: opts.Scheme,
425-
Mapper: opts.Mapper,
426-
ResyncPeriod: *opts.SyncPeriod,
427-
Namespace: namespace,
426+
HTTPClient: opts.HTTPClient,
427+
Scheme: opts.Scheme,
428+
CodecFactoryOptionsByObject: opts.CodecFactoryOptionsByObject,
429+
Mapper: opts.Mapper,
430+
ResyncPeriod: *opts.SyncPeriod,
431+
Namespace: namespace,
428432
Selector: internal.Selector{
429433
Label: config.LabelSelector,
430434
Field: config.FieldSelector,

pkg/cache/internal/informers.go

Lines changed: 43 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -36,23 +36,25 @@ import (
3636
"k8s.io/client-go/metadata"
3737
"k8s.io/client-go/rest"
3838
"k8s.io/client-go/tools/cache"
39+
"sigs.k8s.io/controller-runtime/pkg/client"
3940
"sigs.k8s.io/controller-runtime/pkg/client/apiutil"
4041
"sigs.k8s.io/controller-runtime/pkg/internal/syncs"
4142
)
4243

4344
// InformersOpts configures an InformerMap.
4445
type InformersOpts struct {
45-
HTTPClient *http.Client
46-
Scheme *runtime.Scheme
47-
Mapper meta.RESTMapper
48-
ResyncPeriod time.Duration
49-
Namespace string
50-
NewInformer func(cache.ListerWatcher, runtime.Object, time.Duration, cache.Indexers) cache.SharedIndexInformer
51-
Selector Selector
52-
Transform cache.TransformFunc
53-
UnsafeDisableDeepCopy bool
54-
EnableWatchBookmarks bool
55-
WatchErrorHandler cache.WatchErrorHandler
46+
HTTPClient *http.Client
47+
Scheme *runtime.Scheme
48+
CodecFactoryOptionsByObject map[client.Object]client.CodecFactoryOptions
49+
Mapper meta.RESTMapper
50+
ResyncPeriod time.Duration
51+
Namespace string
52+
NewInformer func(cache.ListerWatcher, runtime.Object, time.Duration, cache.Indexers) cache.SharedIndexInformer
53+
Selector Selector
54+
Transform cache.TransformFunc
55+
UnsafeDisableDeepCopy bool
56+
EnableWatchBookmarks bool
57+
WatchErrorHandler cache.WatchErrorHandler
5658
}
5759

5860
// NewInformers creates a new InformersMap that can create informers under the hood.
@@ -61,6 +63,23 @@ func NewInformers(config *rest.Config, options *InformersOpts) *Informers {
6163
if options.NewInformer != nil {
6264
newInformer = options.NewInformer
6365
}
66+
67+
codecFactories := make(map[schema.GroupVersionKind]serializer.CodecFactory)
68+
for obj, codecFactoryOptions := range options.CodecFactoryOptionsByObject {
69+
gvk, err := apiutil.GVKForObject(obj, options.Scheme)
70+
if err != nil {
71+
continue
72+
}
73+
var mutators []serializer.CodecFactoryOptionsMutator
74+
if codecFactoryOptions.Strict {
75+
mutators = append(mutators, serializer.EnableStrict)
76+
}
77+
if codecFactoryOptions.Pretty {
78+
mutators = append(mutators, serializer.EnablePretty)
79+
}
80+
codecFactories[gvk] = serializer.NewCodecFactory(options.Scheme, mutators...)
81+
}
82+
6483
return &Informers{
6584
config: config,
6685
httpClient: options.HTTPClient,
@@ -71,7 +90,8 @@ func NewInformers(config *rest.Config, options *InformersOpts) *Informers {
7190
Unstructured: make(map[schema.GroupVersionKind]*Cache),
7291
Metadata: make(map[schema.GroupVersionKind]*Cache),
7392
},
74-
codecs: serializer.NewCodecFactory(options.Scheme),
93+
defaultCodecs: serializer.NewCodecFactory(options.Scheme),
94+
codecsByObject: codecFactories,
7595
paramCodec: runtime.NewParameterCodec(options.Scheme),
7696
resync: options.ResyncPeriod,
7797
startWait: make(chan struct{}),
@@ -139,8 +159,11 @@ type Informers struct {
139159
// tracker tracks informers keyed by their type and groupVersionKind
140160
tracker tracker
141161

142-
// codecs is used to create a new REST client
143-
codecs serializer.CodecFactory
162+
// codecsByObject is used to override defaultCodecs for specific GroupVersionKind(object)
163+
codecsByObject map[schema.GroupVersionKind]serializer.CodecFactory
164+
165+
// defaultCodecs is used to create a new REST client
166+
defaultCodecs serializer.CodecFactory
144167

145168
// paramCodec is used by list and watch
146169
paramCodec runtime.ParameterCodec
@@ -512,7 +535,12 @@ func (ip *Informers) makeListWatcher(gvk schema.GroupVersionKind, obj runtime.Ob
512535
// Structured.
513536
//
514537
default:
515-
client, err := apiutil.RESTClientForGVK(gvk, false, ip.config, ip.codecs, ip.httpClient)
538+
codecFactory := ip.defaultCodecs
539+
if override, ok := ip.codecsByObject[gvk]; ok {
540+
codecFactory = override
541+
}
542+
543+
client, err := apiutil.RESTClientForGVK(gvk, false, ip.config, codecFactory, ip.httpClient)
516544
if err != nil {
517545
return nil, err
518546
}

pkg/client/client.go

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ type Options struct {
4444
// Scheme, if provided, will be used to map go structs to GroupVersionKinds
4545
Scheme *runtime.Scheme
4646

47+
// CodecFactoryOptionsByObject, if provided, will be used to indicate whether enable strict/pretty mode of CodecFactory for specific obj
48+
CodecFactoryOptionsByObject map[Object]CodecFactoryOptions
49+
4750
// Mapper, if provided, will be used to map GroupVersionKinds to Resources
4851
Mapper meta.RESTMapper
4952

@@ -68,6 +71,15 @@ type CacheOptions struct {
6871
Unstructured bool
6972
}
7073

74+
// CodecFactoryOptions holds the options for configuring CodecFactory behavior which is same as serializer.CodecFactoryOptions
75+
type CodecFactoryOptions struct {
76+
// Strict configures all serializers in strict mode
77+
Strict bool
78+
// Pretty includes a pretty serializer along with the non-pretty one
79+
Pretty bool
80+
// drop serializers field in serializer.CodecFactoryOptions just for passing go-apidiff test
81+
}
82+
7183
// NewClientFunc allows a user to define how to create a client.
7284
type NewClientFunc func(config *rest.Config, options Options) (Client, error)
7385

@@ -145,13 +157,29 @@ func newClient(config *rest.Config, options Options) (*client, error) {
145157
}
146158
}
147159

148-
resources := &clientRestResources{
149-
httpClient: options.HTTPClient,
150-
config: config,
151-
scheme: options.Scheme,
152-
mapper: options.Mapper,
153-
codecs: serializer.NewCodecFactory(options.Scheme),
160+
codecFactories := make(map[schema.GroupVersionKind]serializer.CodecFactory)
161+
for obj, codecFactoryOptions := range options.CodecFactoryOptionsByObject {
162+
gvk, err := apiutil.GVKForObject(obj, options.Scheme)
163+
if err != nil {
164+
continue
165+
}
166+
var mutators []serializer.CodecFactoryOptionsMutator
167+
if codecFactoryOptions.Strict {
168+
mutators = append(mutators, serializer.EnableStrict)
169+
}
170+
if codecFactoryOptions.Pretty {
171+
mutators = append(mutators, serializer.EnablePretty)
172+
}
173+
codecFactories[gvk] = serializer.NewCodecFactory(options.Scheme, mutators...)
174+
}
154175

176+
resources := &clientRestResources{
177+
httpClient: options.HTTPClient,
178+
config: config,
179+
scheme: options.Scheme,
180+
mapper: options.Mapper,
181+
defaultCodecs: serializer.NewCodecFactory(options.Scheme),
182+
codecsByObject: codecFactories,
155183
structuredResourceByType: make(map[schema.GroupVersionKind]*resourceMeta),
156184
unstructuredResourceByType: make(map[schema.GroupVersionKind]*resourceMeta),
157185
}

pkg/client/client_rest_resources.go

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,11 @@ type clientRestResources struct {
4444
// mapper maps GroupVersionKinds to Resources
4545
mapper meta.RESTMapper
4646

47-
// codecs are used to create a REST client for a gvk
48-
codecs serializer.CodecFactory
47+
// codecsByObject is used to override defaultCodecs for specific GroupVersionKind(object)
48+
codecsByObject map[schema.GroupVersionKind]serializer.CodecFactory
49+
50+
// defaultCodecs are used to create a REST client for a gvk
51+
defaultCodecs serializer.CodecFactory
4952

5053
// structuredResourceByType stores structured type metadata
5154
structuredResourceByType map[schema.GroupVersionKind]*resourceMeta
@@ -62,7 +65,11 @@ func (c *clientRestResources) newResource(gvk schema.GroupVersionKind, isList, i
6265
gvk.Kind = gvk.Kind[:len(gvk.Kind)-4]
6366
}
6467

65-
client, err := apiutil.RESTClientForGVK(gvk, isUnstructured, c.config, c.codecs, c.httpClient)
68+
codecFactory := c.defaultCodecs
69+
if override, ok := c.codecsByObject[gvk]; ok {
70+
codecFactory = override
71+
}
72+
client, err := apiutil.RESTClientForGVK(gvk, isUnstructured, c.config, codecFactory, c.httpClient)
6673
if err != nil {
6774
return nil, err
6875
}

0 commit comments

Comments
 (0)