Skip to content

Commit c2ae465

Browse files
committed
Use protobuf for core clients
Signed-off-by: Monis Khan <[email protected]>
1 parent fe1eda0 commit c2ae465

File tree

10 files changed

+119
-22
lines changed

10 files changed

+119
-22
lines changed

hack/update-codegen.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -645,6 +645,7 @@ function codegen::clients() {
645645
--input-base="k8s.io/api" \
646646
--plural-exceptions "${PLURAL_EXCEPTIONS}" \
647647
--apply-configuration-package "${APPLYCONFIG_PKG}" \
648+
--prefers-protobuf \
648649
$(printf -- " --input %s" "${gv_dirs[@]}") \
649650
"$@"
650651

staging/src/k8s.io/apiextensions-apiserver/hack/update-codegen.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,4 +52,5 @@ kube::codegen::gen_client \
5252
--output-pkg "${THIS_PKG}/pkg/client" \
5353
--versioned-name "clientset" \
5454
--boilerplate "${SCRIPT_ROOT}/hack/boilerplate.go.txt" \
55+
--prefers-protobuf \
5556
"${SCRIPT_ROOT}/pkg/apis"

staging/src/k8s.io/client-go/gentype/type.go

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ type Client[T objectWithMeta] struct {
5151
namespace string // "" for non-namespaced clients
5252
newObject func() T
5353
parameterCodec runtime.ParameterCodec
54+
55+
prefersProtobuf bool
5456
}
5557

5658
// ClientWithList represents a client with support for lists.
@@ -82,26 +84,37 @@ type alsoApplier[T objectWithMeta, C namedObject] struct {
8284
client *Client[T]
8385
}
8486

87+
type Option[T objectWithMeta] func(*Client[T])
88+
89+
func PrefersProtobuf[T objectWithMeta]() Option[T] {
90+
return func(c *Client[T]) { c.prefersProtobuf = true }
91+
}
92+
8593
// NewClient constructs a client, namespaced or not, with no support for lists or apply.
8694
// Non-namespaced clients are constructed by passing an empty namespace ("").
8795
func NewClient[T objectWithMeta](
8896
resource string, client rest.Interface, parameterCodec runtime.ParameterCodec, namespace string, emptyObjectCreator func() T,
97+
options ...Option[T],
8998
) *Client[T] {
90-
return &Client[T]{
99+
c := &Client[T]{
91100
resource: resource,
92101
client: client,
93102
parameterCodec: parameterCodec,
94103
namespace: namespace,
95104
newObject: emptyObjectCreator,
96105
}
106+
for _, option := range options {
107+
option(c)
108+
}
109+
return c
97110
}
98111

99112
// NewClientWithList constructs a namespaced client with support for lists.
100113
func NewClientWithList[T objectWithMeta, L runtime.Object](
101114
resource string, client rest.Interface, parameterCodec runtime.ParameterCodec, namespace string, emptyObjectCreator func() T,
102-
emptyListCreator func() L,
115+
emptyListCreator func() L, options ...Option[T],
103116
) *ClientWithList[T, L] {
104-
typeClient := NewClient[T](resource, client, parameterCodec, namespace, emptyObjectCreator)
117+
typeClient := NewClient[T](resource, client, parameterCodec, namespace, emptyObjectCreator, options...)
105118
return &ClientWithList[T, L]{
106119
typeClient,
107120
alsoLister[T, L]{typeClient, emptyListCreator},
@@ -111,8 +124,9 @@ func NewClientWithList[T objectWithMeta, L runtime.Object](
111124
// NewClientWithApply constructs a namespaced client with support for apply declarative configurations.
112125
func NewClientWithApply[T objectWithMeta, C namedObject](
113126
resource string, client rest.Interface, parameterCodec runtime.ParameterCodec, namespace string, emptyObjectCreator func() T,
127+
options ...Option[T],
114128
) *ClientWithApply[T, C] {
115-
typeClient := NewClient[T](resource, client, parameterCodec, namespace, emptyObjectCreator)
129+
typeClient := NewClient[T](resource, client, parameterCodec, namespace, emptyObjectCreator, options...)
116130
return &ClientWithApply[T, C]{
117131
typeClient,
118132
alsoApplier[T, C]{typeClient},
@@ -122,9 +136,9 @@ func NewClientWithApply[T objectWithMeta, C namedObject](
122136
// NewClientWithListAndApply constructs a client with support for lists and applying declarative configurations.
123137
func NewClientWithListAndApply[T objectWithMeta, L runtime.Object, C namedObject](
124138
resource string, client rest.Interface, parameterCodec runtime.ParameterCodec, namespace string, emptyObjectCreator func() T,
125-
emptyListCreator func() L,
139+
emptyListCreator func() L, options ...Option[T],
126140
) *ClientWithListAndApply[T, L, C] {
127-
typeClient := NewClient[T](resource, client, parameterCodec, namespace, emptyObjectCreator)
141+
typeClient := NewClient[T](resource, client, parameterCodec, namespace, emptyObjectCreator, options...)
128142
return &ClientWithListAndApply[T, L, C]{
129143
typeClient,
130144
alsoLister[T, L]{typeClient, emptyListCreator},
@@ -146,6 +160,7 @@ func (c *Client[T]) GetNamespace() string {
146160
func (c *Client[T]) Get(ctx context.Context, name string, options metav1.GetOptions) (T, error) {
147161
result := c.newObject()
148162
err := c.client.Get().
163+
UseProtobufAsDefaultIfPreferred(c.prefersProtobuf).
149164
NamespaceIfScoped(c.namespace, c.namespace != "").
150165
Resource(c.resource).
151166
Name(name).
@@ -181,6 +196,7 @@ func (l *alsoLister[T, L]) list(ctx context.Context, opts metav1.ListOptions) (L
181196
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
182197
}
183198
err := l.client.client.Get().
199+
UseProtobufAsDefaultIfPreferred(l.client.prefersProtobuf).
184200
NamespaceIfScoped(l.client.namespace, l.client.namespace != "").
185201
Resource(l.client.resource).
186202
VersionedParams(&opts, l.client.parameterCodec).
@@ -198,6 +214,7 @@ func (l *alsoLister[T, L]) watchList(ctx context.Context, opts metav1.ListOption
198214
}
199215
result = l.newList()
200216
err = l.client.client.Get().
217+
UseProtobufAsDefaultIfPreferred(l.client.prefersProtobuf).
201218
NamespaceIfScoped(l.client.namespace, l.client.namespace != "").
202219
Resource(l.client.resource).
203220
VersionedParams(&opts, l.client.parameterCodec).
@@ -215,6 +232,7 @@ func (c *Client[T]) Watch(ctx context.Context, opts metav1.ListOptions) (watch.I
215232
}
216233
opts.Watch = true
217234
return c.client.Get().
235+
UseProtobufAsDefaultIfPreferred(c.prefersProtobuf).
218236
NamespaceIfScoped(c.namespace, c.namespace != "").
219237
Resource(c.resource).
220238
VersionedParams(&opts, c.parameterCodec).
@@ -226,6 +244,7 @@ func (c *Client[T]) Watch(ctx context.Context, opts metav1.ListOptions) (watch.I
226244
func (c *Client[T]) Create(ctx context.Context, obj T, opts metav1.CreateOptions) (T, error) {
227245
result := c.newObject()
228246
err := c.client.Post().
247+
UseProtobufAsDefaultIfPreferred(c.prefersProtobuf).
229248
NamespaceIfScoped(c.namespace, c.namespace != "").
230249
Resource(c.resource).
231250
VersionedParams(&opts, c.parameterCodec).
@@ -239,6 +258,7 @@ func (c *Client[T]) Create(ctx context.Context, obj T, opts metav1.CreateOptions
239258
func (c *Client[T]) Update(ctx context.Context, obj T, opts metav1.UpdateOptions) (T, error) {
240259
result := c.newObject()
241260
err := c.client.Put().
261+
UseProtobufAsDefaultIfPreferred(c.prefersProtobuf).
242262
NamespaceIfScoped(c.namespace, c.namespace != "").
243263
Resource(c.resource).
244264
Name(obj.GetName()).
@@ -253,6 +273,7 @@ func (c *Client[T]) Update(ctx context.Context, obj T, opts metav1.UpdateOptions
253273
func (c *Client[T]) UpdateStatus(ctx context.Context, obj T, opts metav1.UpdateOptions) (T, error) {
254274
result := c.newObject()
255275
err := c.client.Put().
276+
UseProtobufAsDefaultIfPreferred(c.prefersProtobuf).
256277
NamespaceIfScoped(c.namespace, c.namespace != "").
257278
Resource(c.resource).
258279
Name(obj.GetName()).
@@ -267,6 +288,7 @@ func (c *Client[T]) UpdateStatus(ctx context.Context, obj T, opts metav1.UpdateO
267288
// Delete takes name of the resource and deletes it. Returns an error if one occurs.
268289
func (c *Client[T]) Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error {
269290
return c.client.Delete().
291+
UseProtobufAsDefaultIfPreferred(c.prefersProtobuf).
270292
NamespaceIfScoped(c.namespace, c.namespace != "").
271293
Resource(c.resource).
272294
Name(name).
@@ -282,6 +304,7 @@ func (l *alsoLister[T, L]) DeleteCollection(ctx context.Context, opts metav1.Del
282304
timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second
283305
}
284306
return l.client.client.Delete().
307+
UseProtobufAsDefaultIfPreferred(l.client.prefersProtobuf).
285308
NamespaceIfScoped(l.client.namespace, l.client.namespace != "").
286309
Resource(l.client.resource).
287310
VersionedParams(&listOpts, l.client.parameterCodec).
@@ -295,6 +318,7 @@ func (l *alsoLister[T, L]) DeleteCollection(ctx context.Context, opts metav1.Del
295318
func (c *Client[T]) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (T, error) {
296319
result := c.newObject()
297320
err := c.client.Patch(pt).
321+
UseProtobufAsDefaultIfPreferred(c.prefersProtobuf).
298322
NamespaceIfScoped(c.namespace, c.namespace != "").
299323
Resource(c.resource).
300324
Name(name).
@@ -321,6 +345,7 @@ func (a *alsoApplier[T, C]) Apply(ctx context.Context, obj C, opts metav1.ApplyO
321345
return *new(T), fmt.Errorf("obj.Name must be provided to Apply")
322346
}
323347
err = a.client.client.Patch(types.ApplyPatchType).
348+
UseProtobufAsDefaultIfPreferred(a.client.prefersProtobuf).
324349
NamespaceIfScoped(a.client.namespace, a.client.namespace != "").
325350
Resource(a.client.resource).
326351
Name(*obj.GetName()).
@@ -348,6 +373,7 @@ func (a *alsoApplier[T, C]) ApplyStatus(ctx context.Context, obj C, opts metav1.
348373

349374
result := a.client.newObject()
350375
err = a.client.client.Patch(types.ApplyPatchType).
376+
UseProtobufAsDefaultIfPreferred(a.client.prefersProtobuf).
351377
NamespaceIfScoped(a.client.namespace, a.client.namespace != "").
352378
Resource(a.client.resource).
353379
Name(*obj.GetName()).

staging/src/k8s.io/client-go/rest/request.go

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -176,12 +176,7 @@ func NewRequest(c *RESTClient) *Request {
176176
contentTypeNotSet: contentTypeNotSet,
177177
}
178178

179-
switch {
180-
case len(c.content.AcceptContentTypes) > 0:
181-
r.SetHeader("Accept", c.content.AcceptContentTypes)
182-
case len(c.content.ContentType) > 0:
183-
r.SetHeader("Accept", c.content.ContentType+", */*")
184-
}
179+
r.setAcceptHeader()
185180
return r
186181
}
187182

@@ -195,6 +190,31 @@ func NewRequestWithClient(base *url.URL, versionedAPIPath string, content Client
195190
})
196191
}
197192

193+
func (r *Request) UseProtobufAsDefaultIfPreferred(prefersProtobuf bool) *Request {
194+
if prefersProtobuf {
195+
return r.UseProtobufAsDefault()
196+
}
197+
return r
198+
}
199+
200+
func (r *Request) UseProtobufAsDefault() *Request {
201+
if r.contentTypeNotSet && len(r.contentConfig.AcceptContentTypes) == 0 {
202+
r.contentConfig.AcceptContentTypes = "application/vnd.kubernetes.protobuf,application/json"
203+
r.contentConfig.ContentType = "application/vnd.kubernetes.protobuf"
204+
r.setAcceptHeader()
205+
}
206+
return r
207+
}
208+
209+
func (r *Request) setAcceptHeader() {
210+
switch {
211+
case len(r.contentConfig.AcceptContentTypes) > 0:
212+
r.SetHeader("Accept", r.contentConfig.AcceptContentTypes)
213+
case len(r.contentConfig.ContentType) > 0:
214+
r.SetHeader("Accept", r.contentConfig.ContentType+", */*")
215+
}
216+
}
217+
198218
// Verb sets the verb this request will use.
199219
func (r *Request) Verb(verb string) *Request {
200220
r.verb = verb

staging/src/k8s.io/code-generator/cmd/client-gen/args/args.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ type Args struct {
6161
// If non-empty, Apply functions are generated for each type and reference the apply builders.
6262
// If empty (""), Apply functions are not generated.
6363
ApplyConfigurationPackage string
64+
65+
// PrefersProtobuf determines if the generated clientset uses protobuf for API requests.
66+
PrefersProtobuf bool
6467
}
6568

6669
func New() *Args {
@@ -99,6 +102,8 @@ func (args *Args) AddFlags(fs *pflag.FlagSet, inputBase string) {
99102
"list of comma separated plural exception definitions in Type:PluralizedType form")
100103
fs.StringVar(&args.ApplyConfigurationPackage, "apply-configuration-package", args.ApplyConfigurationPackage,
101104
"optional package of apply configurations, generated by applyconfiguration-gen, that are required to generate Apply functions for each type in the clientset. By default Apply functions are not generated.")
105+
fs.BoolVar(&args.PrefersProtobuf, "prefers-protobuf", args.PrefersProtobuf,
106+
"when set, client-gen will generate a clientset that uses protobuf for API requests")
102107

103108
// support old flags
104109
fs.SetNormalizeFunc(mapFlagName("clientset-path", "output-pkg", fs.GetNormalizeFunc()))

staging/src/k8s.io/code-generator/cmd/client-gen/generators/client_generator.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ func DefaultNameSystem() string {
128128
return "public"
129129
}
130130

131-
func targetForGroup(gv clientgentypes.GroupVersion, typeList []*types.Type, clientsetDir, clientsetPkg string, groupPkgName string, groupGoName string, apiPath string, inputPkg string, applyBuilderPkg string, boilerplate []byte) generator.Target {
131+
func targetForGroup(gv clientgentypes.GroupVersion, typeList []*types.Type, clientsetDir, clientsetPkg string, groupPkgName string, groupGoName string, apiPath string, inputPkg string, applyBuilderPkg string, boilerplate []byte, prefersProtobuf bool) generator.Target {
132132
subdir := []string{"typed", strings.ToLower(groupPkgName), strings.ToLower(gv.Version.NonEmpty())}
133133
gvDir := filepath.Join(clientsetDir, filepath.Join(subdir...))
134134
gvPkg := path.Join(clientsetPkg, path.Join(subdir...))
@@ -160,6 +160,7 @@ func targetForGroup(gv clientgentypes.GroupVersion, typeList []*types.Type, clie
160160
group: gv.Group.NonEmpty(),
161161
version: gv.Version.String(),
162162
groupGoName: groupGoName,
163+
prefersProtobuf: prefersProtobuf,
163164
typeToMatch: t,
164165
imports: generator.NewImportTrackerForPackage(gvPkg),
165166
})
@@ -424,7 +425,7 @@ func GetTargets(context *generator.Context, args *args.Args) []generator.Target
424425
targetForGroup(
425426
gv, orderer.OrderTypes(types), clientsetDir, clientsetPkg,
426427
group.PackageName, groupGoNames[gv], args.ClientsetAPIPath,
427-
inputPath, args.ApplyConfigurationPackage, boilerplate))
428+
inputPath, args.ApplyConfigurationPackage, boilerplate, args.PrefersProtobuf))
428429
if args.FakeClient {
429430
targetList = append(targetList,
430431
fake.TargetForGroup(gv, orderer.OrderTypes(types), clientsetDir, clientsetPkg, group.PackageName, groupGoNames[gv], inputPath, args.ApplyConfigurationPackage, boilerplate))

0 commit comments

Comments
 (0)