Skip to content

Commit caa3e39

Browse files
ChaunceyctxChaunceyctx
authored and
Chaunceyctx
committed
add CodecFactoryOptions for codecfactory
1 parent a9b7c2d commit caa3e39

File tree

4 files changed

+97
-29
lines changed

4 files changed

+97
-29
lines changed

pkg/cache/cache.go

+9-5
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

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

pkg/cache/internal/informers.go

+44-15
Original file line numberDiff line numberDiff line change
@@ -36,23 +36,26 @@ 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+
Test map[bool]map[bool]string
50+
Mapper meta.RESTMapper
51+
ResyncPeriod time.Duration
52+
Namespace string
53+
NewInformer *func(cache.ListerWatcher, runtime.Object, time.Duration, cache.Indexers) cache.SharedIndexInformer
54+
Selector Selector
55+
Transform cache.TransformFunc
56+
UnsafeDisableDeepCopy bool
57+
EnableWatchBookmarks bool
58+
WatchErrorHandler cache.WatchErrorHandler
5659
}
5760

5861
// NewInformers creates a new InformersMap that can create informers under the hood.
@@ -61,6 +64,23 @@ func NewInformers(config *rest.Config, options *InformersOpts) *Informers {
6164
if options.NewInformer != nil {
6265
newInformer = *options.NewInformer
6366
}
67+
68+
codecFactories := make(map[schema.GroupVersionKind]serializer.CodecFactory)
69+
for obj, codecFactoryOptions := range options.CodecFactoryOptionsByObject {
70+
gvk, err := apiutil.GVKForObject(obj, options.Scheme)
71+
if err != nil {
72+
continue
73+
}
74+
var mutators []serializer.CodecFactoryOptionsMutator
75+
if codecFactoryOptions.Strict {
76+
mutators = append(mutators, serializer.EnableStrict)
77+
}
78+
if codecFactoryOptions.Pretty {
79+
mutators = append(mutators, serializer.EnablePretty)
80+
}
81+
codecFactories[gvk] = serializer.NewCodecFactory(options.Scheme, mutators...)
82+
}
83+
6484
return &Informers{
6585
config: config,
6686
httpClient: options.HTTPClient,
@@ -71,7 +91,8 @@ func NewInformers(config *rest.Config, options *InformersOpts) *Informers {
7191
Unstructured: make(map[schema.GroupVersionKind]*Cache),
7292
Metadata: make(map[schema.GroupVersionKind]*Cache),
7393
},
74-
codecs: serializer.NewCodecFactory(options.Scheme),
94+
defaultCodecs: serializer.NewCodecFactory(options.Scheme),
95+
codecsByObject: codecFactories,
7596
paramCodec: runtime.NewParameterCodec(options.Scheme),
7697
resync: options.ResyncPeriod,
7798
startWait: make(chan struct{}),
@@ -139,8 +160,11 @@ type Informers struct {
139160
// tracker tracks informers keyed by their type and groupVersionKind
140161
tracker tracker
141162

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

145169
// paramCodec is used by list and watch
146170
paramCodec runtime.ParameterCodec
@@ -512,7 +536,12 @@ func (ip *Informers) makeListWatcher(gvk schema.GroupVersionKind, obj runtime.Ob
512536
// Structured.
513537
//
514538
default:
515-
client, err := apiutil.RESTClientForGVK(gvk, false, ip.config, ip.codecs, ip.httpClient)
539+
codecFactory := ip.defaultCodecs
540+
if override, ok := ip.codecsByObject[gvk]; ok {
541+
codecFactory = override
542+
}
543+
544+
client, err := apiutil.RESTClientForGVK(gvk, false, ip.config, codecFactory, ip.httpClient)
516545
if err != nil {
517546
return nil, err
518547
}

pkg/client/client.go

+34-6
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

+10-3
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)