K8s: Remove new context from client (#103069)

This commit is contained in:
Todd Treece
2025-04-02 14:59:54 -04:00
committed by GitHub
parent 147ae64136
commit ba5c38b078
+12 -107
View File
@@ -5,18 +5,13 @@ import (
"fmt"
"strconv"
"strings"
"time"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
k8sUser "k8s.io/apiserver/pkg/authentication/user"
k8sRequest "k8s.io/apiserver/pkg/endpoints/request"
"k8s.io/client-go/dynamic"
"k8s.io/client-go/rest"
"github.com/grafana/grafana/pkg/apimachinery/identity"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/registry/apis/dashboard/legacysearcher"
"github.com/grafana/grafana/pkg/services/apiserver/endpoints/request"
"github.com/grafana/grafana/pkg/services/dashboards"
@@ -68,111 +63,57 @@ func (h *k8sHandler) GetNamespace(orgID int64) string {
}
func (h *k8sHandler) Get(ctx context.Context, name string, orgID int64, options v1.GetOptions, subresource ...string) (*unstructured.Unstructured, error) {
// create a new context - prevents issues when the request stems from the k8s api itself
// otherwise the context goes through the handlers twice and causes issues
newCtx, cancel, err := h.getK8sContext(ctx)
if err != nil {
return nil, err
} else if cancel != nil {
defer cancel()
}
client, err := h.getClient(newCtx, orgID)
client, err := h.getClient(ctx, orgID)
if err != nil {
return nil, err
}
return client.Get(newCtx, name, options, subresource...)
return client.Get(ctx, name, options, subresource...)
}
func (h *k8sHandler) Create(ctx context.Context, obj *unstructured.Unstructured, orgID int64) (*unstructured.Unstructured, error) {
// create a new context - prevents issues when the request stems from the k8s api itself
// otherwise the context goes through the handlers twice and causes issues
newCtx, cancel, err := h.getK8sContext(ctx)
if err != nil {
return nil, err
} else if cancel != nil {
defer cancel()
}
client, err := h.getClient(newCtx, orgID)
client, err := h.getClient(ctx, orgID)
if err != nil {
return nil, err
}
return client.Create(newCtx, obj, v1.CreateOptions{})
return client.Create(ctx, obj, v1.CreateOptions{})
}
func (h *k8sHandler) Update(ctx context.Context, obj *unstructured.Unstructured, orgID int64) (*unstructured.Unstructured, error) {
// create a new context - prevents issues when the request stems from the k8s api itself
// otherwise the context goes through the handlers twice and causes issues
newCtx, cancel, err := h.getK8sContext(ctx)
if err != nil {
return nil, err
} else if cancel != nil {
defer cancel()
}
client, err := h.getClient(newCtx, orgID)
client, err := h.getClient(ctx, orgID)
if err != nil {
return nil, err
}
return client.Update(newCtx, obj, v1.UpdateOptions{})
return client.Update(ctx, obj, v1.UpdateOptions{})
}
func (h *k8sHandler) Delete(ctx context.Context, name string, orgID int64, options v1.DeleteOptions) error {
// create a new context - prevents issues when the request stems from the k8s api itself
// otherwise the context goes through the handlers twice and causes issues
newCtx, cancel, err := h.getK8sContext(ctx)
if err != nil {
return err
} else if cancel != nil {
defer cancel()
}
client, err := h.getClient(newCtx, orgID)
client, err := h.getClient(ctx, orgID)
if err != nil {
return err
}
return client.Delete(newCtx, name, options)
return client.Delete(ctx, name, options)
}
func (h *k8sHandler) DeleteCollection(ctx context.Context, orgID int64) error {
// create a new context - prevents issues when the request stems from the k8s api itself
// otherwise the context goes through the handlers twice and causes issues
newCtx, cancel, err := h.getK8sContext(ctx)
if err != nil {
return err
} else if cancel != nil {
defer cancel()
}
client, err := h.getClient(newCtx, orgID)
client, err := h.getClient(ctx, orgID)
if err != nil {
return err
}
return client.DeleteCollection(newCtx, v1.DeleteOptions{}, v1.ListOptions{})
return client.DeleteCollection(ctx, v1.DeleteOptions{}, v1.ListOptions{})
}
func (h *k8sHandler) List(ctx context.Context, orgID int64, options v1.ListOptions) (*unstructured.UnstructuredList, error) {
// create a new context - prevents issues when the request stems from the k8s api itself
// otherwise the context goes through the handlers twice and causes issues
newCtx, cancel, err := h.getK8sContext(ctx)
if err != nil {
return nil, err
} else if cancel != nil {
defer cancel()
}
client, err := h.getClient(newCtx, orgID)
client, err := h.getClient(ctx, orgID)
if err != nil {
return nil, err
}
return client.List(newCtx, options)
return client.List(ctx, options)
}
func (h *k8sHandler) Search(ctx context.Context, orgID int64, in *resource.ResourceSearchRequest) (*resource.ResourceSearchResponse, error) {
@@ -262,39 +203,3 @@ func (h *k8sHandler) getClient(ctx context.Context, orgID int64) (dynamic.Resour
return dyn.Resource(h.gvr).Namespace(h.GetNamespace(orgID)), nil
}
func (h *k8sHandler) getK8sContext(ctx context.Context) (context.Context, context.CancelFunc, error) {
requester, requesterErr := identity.GetRequester(ctx)
if requesterErr != nil {
return nil, nil, requesterErr
}
user, exists := k8sRequest.UserFrom(ctx)
if !exists {
// add in k8s user if not there yet
var ok bool
user, ok = requester.(k8sUser.Info)
if !ok {
return nil, nil, fmt.Errorf("could not convert user to k8s user")
}
}
newCtx := k8sRequest.WithUser(context.Background(), user)
newCtx = log.WithContextualAttributes(newCtx, log.FromContext(ctx))
// TODO: after GLSA token workflow is removed, make this return early
// and move the else below to be unconditional
if requesterErr == nil {
newCtxWithRequester := identity.WithRequester(newCtx, requester)
newCtx = newCtxWithRequester
}
// inherit the deadline from the original context, if it exists
deadline, ok := ctx.Deadline()
if ok {
var newCancel context.CancelFunc
newCtx, newCancel = context.WithTimeout(newCtx, time.Until(deadline))
return newCtx, newCancel, nil
}
return newCtx, nil, nil
}