Dashboard Versions: Make compatible with app platform (#99327)
This commit is contained in:
@@ -2,7 +2,10 @@ package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
@@ -16,6 +19,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/apiserver"
|
||||
"github.com/grafana/grafana/pkg/services/apiserver/endpoints/request"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/user"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/grafana/grafana/pkg/storage/unified/resource"
|
||||
k8sUser "k8s.io/apiserver/pkg/authentication/user"
|
||||
@@ -24,7 +28,7 @@ import (
|
||||
|
||||
type K8sHandler interface {
|
||||
GetNamespace(orgID int64) string
|
||||
Get(ctx context.Context, name string, orgID int64, subresource ...string) (*unstructured.Unstructured, error)
|
||||
Get(ctx context.Context, name string, orgID int64, options v1.GetOptions, subresource ...string) (*unstructured.Unstructured, error)
|
||||
Create(ctx context.Context, obj *unstructured.Unstructured, orgID int64) (*unstructured.Unstructured, error)
|
||||
Update(ctx context.Context, obj *unstructured.Unstructured, orgID int64) (*unstructured.Unstructured, error)
|
||||
Delete(ctx context.Context, name string, orgID int64, options v1.DeleteOptions) error
|
||||
@@ -32,6 +36,7 @@ type K8sHandler interface {
|
||||
List(ctx context.Context, orgID int64, options v1.ListOptions) (*unstructured.UnstructuredList, error)
|
||||
Search(ctx context.Context, orgID int64, in *resource.ResourceSearchRequest) (*resource.ResourceSearchResponse, error)
|
||||
GetStats(ctx context.Context, orgID int64) (*resource.ResourceStatsResponse, error)
|
||||
GetUserFromMeta(ctx context.Context, userMeta string) (*user.User, error)
|
||||
}
|
||||
|
||||
var _ K8sHandler = (*k8sHandler)(nil)
|
||||
@@ -41,9 +46,10 @@ type k8sHandler struct {
|
||||
gvr schema.GroupVersionResource
|
||||
restConfigProvider apiserver.RestConfigProvider
|
||||
searcher resource.ResourceIndexClient
|
||||
userService user.Service
|
||||
}
|
||||
|
||||
func NewK8sHandler(cfg *setting.Cfg, namespacer request.NamespaceMapper, gvr schema.GroupVersionResource, restConfigProvider apiserver.RestConfigProvider, searcher resource.ResourceIndexClient, dashStore dashboards.Store) K8sHandler {
|
||||
func NewK8sHandler(cfg *setting.Cfg, namespacer request.NamespaceMapper, gvr schema.GroupVersionResource, restConfigProvider apiserver.RestConfigProvider, searcher resource.ResourceIndexClient, dashStore dashboards.Store, userSvc user.Service) K8sHandler {
|
||||
legacySearcher := legacysearcher.NewDashboardSearchClient(dashStore)
|
||||
searchClient := resource.NewSearchClient(cfg, setting.UnifiedStorageConfigKeyDashboard, searcher, legacySearcher)
|
||||
return &k8sHandler{
|
||||
@@ -51,6 +57,7 @@ func NewK8sHandler(cfg *setting.Cfg, namespacer request.NamespaceMapper, gvr sch
|
||||
gvr: gvr,
|
||||
restConfigProvider: restConfigProvider,
|
||||
searcher: searchClient,
|
||||
userService: userSvc,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,7 +65,7 @@ func (h *k8sHandler) GetNamespace(orgID int64) string {
|
||||
return h.namespacer(orgID)
|
||||
}
|
||||
|
||||
func (h *k8sHandler) Get(ctx context.Context, name string, orgID int64, subresource ...string) (*unstructured.Unstructured, error) {
|
||||
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)
|
||||
@@ -73,7 +80,7 @@ func (h *k8sHandler) Get(ctx context.Context, name string, orgID int64, subresou
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return client.Get(newCtx, name, v1.GetOptions{}, subresource...)
|
||||
return client.Get(newCtx, name, options, subresource...)
|
||||
}
|
||||
|
||||
func (h *k8sHandler) Create(ctx context.Context, obj *unstructured.Unstructured, orgID int64) (*unstructured.Unstructured, error) {
|
||||
@@ -191,6 +198,28 @@ func (h *k8sHandler) GetStats(ctx context.Context, orgID int64) (*resource.Resou
|
||||
})
|
||||
}
|
||||
|
||||
// GetUserFromMeta takes what meta accessor gives you from `GetCreatedBy` or `GetUpdatedBy` and returns the user
|
||||
func (h *k8sHandler) GetUserFromMeta(ctx context.Context, userMeta string) (*user.User, error) {
|
||||
parts := strings.Split(userMeta, ":")
|
||||
if len(parts) < 2 {
|
||||
return &user.User{}, nil
|
||||
}
|
||||
meta := parts[1]
|
||||
|
||||
userId, err := strconv.ParseInt(meta, 10, 64)
|
||||
var u *user.User
|
||||
if err == nil {
|
||||
u, err = h.userService.GetByID(ctx, &user.GetUserByIDQuery{ID: userId})
|
||||
} else {
|
||||
u, err = h.userService.GetByUID(ctx, &user.GetUserByUIDQuery{UID: meta})
|
||||
}
|
||||
|
||||
if err != nil && errors.Is(err, user.ErrUserNotFound) {
|
||||
return &user.User{}, nil
|
||||
}
|
||||
return u, err
|
||||
}
|
||||
|
||||
func (h *k8sHandler) getClient(ctx context.Context, orgID int64) (dynamic.ResourceInterface, bool) {
|
||||
cfg := h.restConfigProvider.GetRestConfig(ctx)
|
||||
if cfg == nil {
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
|
||||
"github.com/stretchr/testify/mock"
|
||||
|
||||
"github.com/grafana/grafana/pkg/services/user"
|
||||
"github.com/grafana/grafana/pkg/storage/unified/resource"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
@@ -21,8 +22,8 @@ func (m *MockK8sHandler) GetNamespace(orgID int64) string {
|
||||
return args.String(0)
|
||||
}
|
||||
|
||||
func (m *MockK8sHandler) Get(ctx context.Context, name string, orgID int64, subresource ...string) (*unstructured.Unstructured, error) {
|
||||
args := m.Called(ctx, name, orgID, subresource)
|
||||
func (m *MockK8sHandler) Get(ctx context.Context, name string, orgID int64, options v1.GetOptions, subresource ...string) (*unstructured.Unstructured, error) {
|
||||
args := m.Called(ctx, name, orgID, options, subresource)
|
||||
if args.Get(0) == nil {
|
||||
return nil, args.Error(1)
|
||||
}
|
||||
@@ -79,3 +80,11 @@ func (m *MockK8sHandler) GetStats(ctx context.Context, orgID int64) (*resource.R
|
||||
}
|
||||
return args.Get(0).(*resource.ResourceStatsResponse), args.Error(1)
|
||||
}
|
||||
|
||||
func (m *MockK8sHandler) GetUserFromMeta(ctx context.Context, userMeta string) (*user.User, error) {
|
||||
args := m.Called(ctx, userMeta)
|
||||
if args.Get(0) == nil {
|
||||
return nil, args.Error(1)
|
||||
}
|
||||
return args.Get(0).(*user.User), args.Error(1)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/grafana/grafana/pkg/services/user"
|
||||
"github.com/grafana/grafana/pkg/services/user/usertest"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestGetUserFromMeta(t *testing.T) {
|
||||
userSvcTest := usertest.NewUserServiceFake()
|
||||
userSvcTest.ExpectedUser = &user.User{
|
||||
ID: 1,
|
||||
UID: "uid-value",
|
||||
}
|
||||
client := &k8sHandler{
|
||||
userService: userSvcTest,
|
||||
}
|
||||
t.Run("returns user with valid UID", func(t *testing.T) {
|
||||
result, err := client.GetUserFromMeta(context.Background(), "user:uid-value")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "uid-value", result.UID)
|
||||
require.Equal(t, int64(1), result.ID)
|
||||
})
|
||||
|
||||
t.Run("returns user when id is passed in", func(t *testing.T) {
|
||||
result, err := client.GetUserFromMeta(context.Background(), "user:1")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "uid-value", result.UID)
|
||||
require.Equal(t, int64(1), result.ID)
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user