Ensure transformers have access to the resource via request info

This guarantees that logs and metrics that rely on this information
work as expected.

Signed-off-by: Monis Khan <mok@microsoft.com>
This commit is contained in:
Monis Khan 2024-08-14 10:33:36 -04:00
parent ba604434a8
commit 49d7b4c97e
No known key found for this signature in database
2 changed files with 51 additions and 2 deletions

View File

@ -40,6 +40,7 @@ import (
"k8s.io/apiserver/pkg/apis/apiserver"
apiserverv1 "k8s.io/apiserver/pkg/apis/apiserver/v1"
"k8s.io/apiserver/pkg/apis/apiserver/validation"
"k8s.io/apiserver/pkg/endpoints/request"
"k8s.io/apiserver/pkg/features"
"k8s.io/apiserver/pkg/server/healthz"
"k8s.io/apiserver/pkg/server/options/encryptionconfig/metrics"
@ -1013,7 +1014,9 @@ var anyGroupAnyResource = schema.GroupResource{
Resource: "*",
}
func transformerFromOverrides(transformerOverrides map[schema.GroupResource]storagevalue.Transformer, resource schema.GroupResource) storagevalue.Transformer {
func transformerFromOverrides(transformerOverrides map[schema.GroupResource]storagevalue.Transformer, resource schema.GroupResource) (out storagevalue.Transformer) {
defer func() { out = newRequestInfoTransformer(resource, out) }()
if transformer := transformerOverrides[resource]; transformer != nil {
return transformer
}
@ -1039,3 +1042,41 @@ func grYAMLString(gr schema.GroupResource) string {
return gr.String()
}
var _ storagevalue.Transformer = &requestInfoTransformer{}
type requestInfoTransformer struct {
baseValueCtx context.Context
delegate storagevalue.Transformer
}
func newRequestInfoTransformer(resource schema.GroupResource, delegate storagevalue.Transformer) *requestInfoTransformer {
return &requestInfoTransformer{
baseValueCtx: request.WithRequestInfo(context.Background(), &request.RequestInfo{IsResourceRequest: true, APIGroup: resource.Group, Resource: resource.Resource}),
delegate: delegate,
}
}
func (l *requestInfoTransformer) TransformFromStorage(ctx context.Context, data []byte, dataCtx storagevalue.Context) ([]byte, bool, error) {
return l.delegate.TransformFromStorage(l.withBaseValueCtx(ctx), data, dataCtx)
}
func (l *requestInfoTransformer) TransformToStorage(ctx context.Context, data []byte, dataCtx storagevalue.Context) ([]byte, error) {
return l.delegate.TransformToStorage(l.withBaseValueCtx(ctx), data, dataCtx)
}
func (l *requestInfoTransformer) withBaseValueCtx(ctx context.Context) context.Context {
return &joinValueContext{Context: ctx, baseValueCtx: l.baseValueCtx}
}
type joinValueContext struct {
context.Context
baseValueCtx context.Context
}
func (j *joinValueContext) Value(key any) any {
if val := j.Context.Value(key); val != nil {
return val
}
return j.baseValueCtx.Value(key)
}

View File

@ -1428,7 +1428,15 @@ func TestWildcardStructure(t *testing.T) {
for resource, expectedTransformerName := range tc.expectedResourceTransformers {
transformer := transformerFromOverrides(transformers, schema.ParseGroupResource(resource))
transformerName := string(
reflect.ValueOf(transformer).Elem().FieldByName("transformers").Index(0).FieldByName("Prefix").Bytes(),
reflect.ValueOf(transformer).
Elem().
FieldByName("delegate").
Elem().
Elem().
FieldByName("transformers").
Index(0).
FieldByName("Prefix").
Bytes(),
)
if transformerName != expectedTransformerName {