hack hack hack... but working from kubectl

This commit is contained in:
Ryan McKinley 2024-06-15 00:26:45 +03:00
parent 2f64556cf1
commit 31a05d5666
8 changed files with 116 additions and 48 deletions

View File

@ -19,5 +19,24 @@ func GetRequester(ctx context.Context) (Requester, error) {
if ok && u != nil {
return u, nil
}
// HACK for now...
if true {
return &StaticRequester{
OrgID: 1,
IsGrafanaAdmin: true,
UserID: 1,
Namespace: NamespaceUser,
UserUID: "abc",
Name: "hello",
Login: "justme",
Permissions: map[int64]map[string][]string{
1: {
"*": {"*"}, // all resources, all scopes
},
},
}, nil
}
return nil, fmt.Errorf("a Requester was not found in the context")
}

View File

@ -261,19 +261,14 @@ func (s *service) start(ctx context.Context) error {
return fmt.Errorf("unified storage requires the unifiedStorage feature flag")
}
eDB, err := dbimpl.ProvideEntityDB(s.db, s.cfg, s.features, s.tracing)
resourceServer, err := entitybridge.ProvideResourceServer(s.db, s.cfg, s.features, s.tracing)
if err != nil {
return err
}
storeServer, err := entitybridge.ProvideEntityStoreResources(eDB, s.tracing)
if err != nil {
return err
}
store := resource.NewResourceStoreClientLocal(storeServer)
serverConfig.Config.RESTOptionsGetter = apistore.NewRESTOptionsGetter(s.cfg, store, o.RecommendedOptions.Etcd.StorageConfig.Codec)
store := resource.NewResourceStoreClientLocal(resourceServer)
serverConfig.Config.RESTOptionsGetter = apistore.NewRESTOptionsGetter(s.cfg, store,
o.RecommendedOptions.Etcd.StorageConfig.Codec)
case grafanaapiserveroptions.StorageTypeUnified:
if !s.features.IsEnabledGlobally(featuremgmt.FlagUnifiedStorage) {

View File

@ -32,6 +32,7 @@ import (
"github.com/grafana/grafana/pkg/apimachinery/utils"
"github.com/grafana/grafana/pkg/infra/appcontext"
"github.com/grafana/grafana/pkg/storage/unified/resource"
"github.com/grafana/grafana/pkg/util"
)
const SortByKey = "grafana.app/sortBy"
@ -136,6 +137,16 @@ func (s *Storage) Create(ctx context.Context, _ string, obj runtime.Object, out
}
meta.SetOriginInfo(origin)
// Set a unique name
if meta.GetGenerateName() != "" {
if key.Name != "" {
return apierrors.NewBadRequest("both generate name and name are set")
}
key.Name = util.GenerateShortUID()
meta.SetName(key.Name)
meta.SetGenerateName("")
}
var buf bytes.Buffer
err = s.codec.Encode(obj, &buf)
if err != nil {

View File

@ -3,18 +3,53 @@ package entitybridge
import (
"context"
"fmt"
"os"
"github.com/hack-pad/hackpadfs"
hackos "github.com/hack-pad/hackpadfs/os"
"github.com/grafana/grafana/pkg/infra/db"
"github.com/grafana/grafana/pkg/infra/tracing"
"github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/grafana/grafana/pkg/services/store/entity"
"github.com/grafana/grafana/pkg/services/store/entity/db"
"github.com/grafana/grafana/pkg/services/store/entity/db/dbimpl"
"github.com/grafana/grafana/pkg/services/store/entity/sqlstash"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/storage/unified/resource"
)
// Creates a ResourceServer using the existing entity tables
// NOTE: most of the field values are ignored
func ProvideEntityStoreResources(db db.EntityDBInterface, tracer tracing.Tracer) (resource.ResourceServer, error) {
entity, err := sqlstash.ProvideSQLEntityServer(db, tracer)
func ProvideResourceServer(db db.DB, cfg *setting.Cfg, features featuremgmt.FeatureToggles, tracer tracing.Tracer) (resource.ResourceServer, error) {
if true {
var root hackpadfs.FS
if false {
tmp, err := os.MkdirTemp("", "xxx-*")
if err != nil {
return nil, err
}
root, err = hackos.NewFS().Sub(tmp[1:])
if err != nil {
return nil, err
}
fmt.Printf("ROOT: %s\n", tmp)
}
return resource.NewResourceServer(resource.ResourceServerOptions{
Store: resource.NewFileSystemStore(resource.FileSystemOptions{
Root: root,
}),
})
}
eDB, err := dbimpl.ProvideEntityDB(db, cfg, features, tracer)
if err != nil {
return nil, err
}
entity, err := sqlstash.ProvideSQLEntityServer(eDB, tracer)
if err != nil {
return nil, err
}
@ -22,7 +57,6 @@ func ProvideEntityStoreResources(db db.EntityDBInterface, tracer tracing.Tracer)
store := &entityBridge{
entity: entity,
}
return resource.NewResourceServer(resource.ResourceServerOptions{
Tracer: tracer,
Store: store,

View File

@ -11,7 +11,6 @@ import (
"github.com/hack-pad/hackpadfs"
"github.com/hack-pad/hackpadfs/mem"
"go.opentelemetry.io/otel/trace"
"go.opentelemetry.io/otel/trace/noop"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/runtime/schema"
)
@ -24,31 +23,21 @@ type FileSystemOptions struct {
Root hackpadfs.FS
}
func NewFileSystemStore(opts FileSystemOptions) (AppendingStore, error) {
if opts.Tracer == nil {
opts.Tracer = noop.NewTracerProvider().Tracer("fs")
}
var err error
func NewFileSystemStore(opts FileSystemOptions) AppendingStore {
root := opts.Root
if root == nil {
root, err = mem.NewFS()
if err != nil {
return nil, err
}
root, _ = mem.NewFS()
}
return &fsStore{
tracer: opts.Tracer,
root: root,
keys: &simpleConverter{}, // not tenant isolated
}, nil
root: root,
keys: &simpleConverter{}, // not tenant isolated
}
}
type fsStore struct {
tracer trace.Tracer
root hackpadfs.FS
keys KeyConversions
root hackpadfs.FS
keys KeyConversions
}
type fsEvent struct {
@ -157,10 +146,10 @@ func (f *fsStore) List(ctx context.Context, req *ListRequest) (*ListResponse, er
group: req.Options.Key.Group,
resource: req.Options.Key.Resource,
}
err := tree.read(f.root, req.Options.Key)
if err != nil {
return nil, err
}
_ = tree.read(f.root, req.Options.Key)
// if err != nil {
// return nil, err
// }
return tree.list(f, req.ResourceVersion)
}

View File

@ -23,6 +23,11 @@ const (
)
func (f *Authenticator) Authenticate(ctx context.Context) (context.Context, error) {
rrr, _ := identity.GetRequester(ctx)
if rrr != nil {
return ctx, nil
}
md, ok := metadata.FromIncomingContext(ctx)
if !ok {
return nil, fmt.Errorf("no metadata found")
@ -46,15 +51,15 @@ func (f *Authenticator) Authenticate(ctx context.Context) (context.Context, erro
login := md.Get(keyLogin)[0]
if login == "" {
return nil, fmt.Errorf("no login found in context")
return nil, fmt.Errorf("no login found in grpc context")
}
userID, err := strconv.ParseInt(md.Get(keyUserID)[0], 10, 64)
if err != nil {
return nil, fmt.Errorf("invalid user id: %w", err)
return nil, fmt.Errorf("invalid grpc user id: %w", err)
}
orgID, err := strconv.ParseInt(md.Get(keyOrgID)[0], 10, 64)
if err != nil {
return nil, fmt.Errorf("invalid org id: %w", err)
return nil, fmt.Errorf("invalid grpc org id: %w", err)
}
return identity.WithRequester(ctx, &identity.StaticRequester{

View File

@ -18,6 +18,10 @@ import (
"github.com/grafana/grafana/pkg/apimachinery/utils"
)
// HACK!!! since requester is not behaving as expected....
// we are not getting the same names right now
const CHECK_USER_MATCH = false
// Package-level errors.
var (
ErrNotFound = errors.New("entity not found")
@ -280,8 +284,10 @@ func (s *server) Create(ctx context.Context, req *CreateRequest) (*CreateRespons
// Make sure the created by user is accurate
//----------------------------------------
val := event.Object.GetCreatedBy()
if val != "" && val != event.Requester.GetUID().String() {
return nil, apierrors.NewBadRequest("created by annotation does not match: metadata.annotations#" + utils.AnnoKeyCreatedBy)
if val != "" && val != event.Requester.GetUID().String() && CHECK_USER_MATCH {
return nil, apierrors.NewBadRequest(fmt.Sprintf(
"created by annotation do not match (%s != %s)", val, event.Requester.GetUID().String(),
))
}
// Create can not have updated properties
@ -363,7 +369,7 @@ func (s *server) Update(ctx context.Context, req *UpdateRequest) (*UpdateRespons
// Make sure the update user is accurate
//----------------------------------------
val := event.Object.GetUpdatedBy()
if val != "" && val != event.Requester.GetUID().String() {
if val != "" && val != event.Requester.GetUID().String() && CHECK_USER_MATCH {
return nil, apierrors.NewBadRequest("updated by annotation does not match: metadata.annotations#" + utils.AnnoKeyUpdatedBy)
}

View File

@ -18,7 +18,7 @@ import (
"github.com/grafana/grafana/pkg/apimachinery/utils"
)
func TestWriter(t *testing.T) {
func TestSimpleServer(t *testing.T) {
testUserA := &identity.StaticRequester{
Namespace: identity.NamespaceUser,
UserID: 123,
@ -37,13 +37,11 @@ func TestWriter(t *testing.T) {
require.NoError(t, err)
fmt.Printf("ROOT: %s\n\n", tmp)
}
tmp, err := NewFileSystemStore(FileSystemOptions{
Root: root,
})
require.NoError(t, err)
server, err := NewResourceServer(ResourceServerOptions{
Store: tmp,
Store: NewFileSystemStore(FileSystemOptions{
Root: root,
}),
})
require.NoError(t, err)
@ -55,6 +53,17 @@ func TestWriter(t *testing.T) {
Namespace: "default",
Name: "fdgsv37qslr0ga",
}
// Should be empty when we start
all, err := server.List(ctx, &ListRequest{Options: &ListOptions{
Key: &ResourceKey{
Group: key.Group,
Resource: key.Resource,
},
}})
require.NoError(t, err)
require.Len(t, all.Items, 0)
created, err := server.Create(ctx, &CreateRequest{
Value: raw,
Key: key,
@ -93,7 +102,7 @@ func TestWriter(t *testing.T) {
require.NoError(t, err)
require.Equal(t, updated.ResourceVersion, found.ResourceVersion)
all, err := server.List(ctx, &ListRequest{Options: &ListOptions{
all, err = server.List(ctx, &ListRequest{Options: &ListOptions{
Key: &ResourceKey{
Group: key.Group,
Resource: key.Resource,