mirror of https://github.com/grafana/grafana
parent
0118c7666a
commit
df148ca9ea
@ -0,0 +1,30 @@ |
||||
package resource |
||||
|
||||
import ( |
||||
"github.com/fullstorydev/grpchan" |
||||
"github.com/fullstorydev/grpchan/inprocgrpc" |
||||
grpcAuth "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/auth" |
||||
"google.golang.org/grpc" |
||||
|
||||
grpcUtils "github.com/grafana/grafana/pkg/services/store/entity/grpc" |
||||
) |
||||
|
||||
func NewResourceStoreClientLocal(server ResourceStoreServer) ResourceStoreClient { |
||||
channel := &inprocgrpc.Channel{} |
||||
|
||||
auth := &grpcUtils.Authenticator{} |
||||
|
||||
channel.RegisterService( |
||||
grpchan.InterceptServer( |
||||
&ResourceStore_ServiceDesc, |
||||
grpcAuth.UnaryServerInterceptor(auth.Authenticate), |
||||
grpcAuth.StreamServerInterceptor(auth.Authenticate), |
||||
), |
||||
server, |
||||
) |
||||
return NewResourceStoreClient(grpchan.InterceptClientConn(channel, grpcUtils.UnaryClientInterceptor, grpcUtils.StreamClientInterceptor)) |
||||
} |
||||
|
||||
func NewEntityStoreClientGRPC(channel *grpc.ClientConn) ResourceStoreClient { |
||||
return NewResourceStoreClient(grpchan.InterceptClientConn(channel, grpcUtils.UnaryClientInterceptor, grpcUtils.StreamClientInterceptor)) |
||||
} |
@ -0,0 +1,105 @@ |
||||
package resource_server_tests |
||||
|
||||
import ( |
||||
"context" |
||||
"testing" |
||||
|
||||
"github.com/stretchr/testify/require" |
||||
|
||||
"github.com/grafana/grafana/pkg/infra/tracing" |
||||
|
||||
"github.com/grafana/grafana/pkg/components/satokengen" |
||||
"github.com/grafana/grafana/pkg/infra/appcontext" |
||||
"github.com/grafana/grafana/pkg/server" |
||||
"github.com/grafana/grafana/pkg/services/featuremgmt" |
||||
"github.com/grafana/grafana/pkg/services/org" |
||||
saAPI "github.com/grafana/grafana/pkg/services/serviceaccounts/api" |
||||
saTests "github.com/grafana/grafana/pkg/services/serviceaccounts/tests" |
||||
"github.com/grafana/grafana/pkg/services/store/entity/db/dbimpl" |
||||
"github.com/grafana/grafana/pkg/services/store/resource" |
||||
"github.com/grafana/grafana/pkg/services/store/resource/sqlstash" |
||||
"github.com/grafana/grafana/pkg/services/user" |
||||
"github.com/grafana/grafana/pkg/tests/testinfra" |
||||
"github.com/grafana/grafana/pkg/tests/testsuite" |
||||
) |
||||
|
||||
func TestMain(m *testing.M) { |
||||
testsuite.Run(m) |
||||
} |
||||
|
||||
func createServiceAccountAdminToken(t *testing.T, env *server.TestEnv) (string, *user.SignedInUser) { |
||||
t.Helper() |
||||
|
||||
account := saTests.SetupUserServiceAccount(t, env.SQLStore, env.Cfg, saTests.TestUser{ |
||||
Name: "grpc-server-sa", |
||||
Role: string(org.RoleAdmin), |
||||
Login: "grpc-server-sa", |
||||
IsServiceAccount: true, |
||||
}) |
||||
|
||||
keyGen, err := satokengen.New(saAPI.ServiceID) |
||||
require.NoError(t, err) |
||||
|
||||
_ = saTests.SetupApiKey(t, env.SQLStore, env.Cfg, saTests.TestApiKey{ |
||||
Name: "grpc-server-test", |
||||
Role: org.RoleAdmin, |
||||
OrgId: account.OrgID, |
||||
Key: keyGen.HashedKey, |
||||
ServiceAccountID: &account.ID, |
||||
}) |
||||
|
||||
return keyGen.ClientSecret, &user.SignedInUser{ |
||||
UserID: account.ID, |
||||
Email: account.Email, |
||||
Name: account.Name, |
||||
Login: account.Login, |
||||
OrgID: account.OrgID, |
||||
IsServiceAccount: account.IsServiceAccount, |
||||
} |
||||
} |
||||
|
||||
type testContext struct { |
||||
authToken string |
||||
client resource.ResourceStoreClient |
||||
user *user.SignedInUser |
||||
ctx context.Context |
||||
} |
||||
|
||||
func createTestContext(t *testing.T) testContext { |
||||
t.Helper() |
||||
|
||||
dir, path := testinfra.CreateGrafDir(t, testinfra.GrafanaOpts{ |
||||
EnableFeatureToggles: []string{ |
||||
featuremgmt.FlagGrpcServer, |
||||
featuremgmt.FlagUnifiedStorage, |
||||
}, |
||||
AppModeProduction: false, // required for migrations to run
|
||||
GRPCServerAddress: "127.0.0.1:0", // :0 for choosing the port automatically
|
||||
}) |
||||
|
||||
_, env := testinfra.StartGrafanaEnv(t, dir, path) |
||||
|
||||
authToken, serviceAccountUser := createServiceAccountAdminToken(t, env) |
||||
|
||||
eDB, err := dbimpl.ProvideEntityDB(env.SQLStore, env.Cfg, env.FeatureToggles, nil) |
||||
require.NoError(t, err) |
||||
|
||||
err = eDB.Init() |
||||
require.NoError(t, err) |
||||
|
||||
traceConfig, err := tracing.ParseTracingConfig(env.Cfg) |
||||
require.NoError(t, err) |
||||
tracer, err := tracing.ProvideService(traceConfig) |
||||
require.NoError(t, err) |
||||
store, err := sqlstash.ProvideSQLResourceServer(eDB, tracer) |
||||
require.NoError(t, err) |
||||
|
||||
client := resource.NewResourceStoreClientLocal(store) |
||||
|
||||
return testContext{ |
||||
authToken: authToken, |
||||
client: client, |
||||
user: serviceAccountUser, |
||||
ctx: appcontext.WithUser(context.Background(), serviceAccountUser), |
||||
} |
||||
} |
@ -0,0 +1,84 @@ |
||||
package resource_server_tests |
||||
|
||||
import ( |
||||
_ "embed" |
||||
"encoding/json" |
||||
"fmt" |
||||
"net/http" |
||||
"testing" |
||||
|
||||
"github.com/stretchr/testify/require" |
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" |
||||
"k8s.io/apimachinery/pkg/types" |
||||
|
||||
"github.com/grafana/grafana/pkg/apis/playlist/v0alpha1" |
||||
"github.com/grafana/grafana/pkg/infra/appcontext" |
||||
"github.com/grafana/grafana/pkg/services/store/resource" |
||||
) |
||||
|
||||
var ( |
||||
//go:embed testdata/dashboard-with-tags-b-g.json
|
||||
dashboardWithTagsBlueGreen string |
||||
//go:embed testdata/dashboard-with-tags-r-g.json
|
||||
dashboardWithTagsRedGreen string |
||||
) |
||||
|
||||
func TestIntegrationEntityServer(t *testing.T) { |
||||
if testing.Short() { |
||||
t.Skip("skipping integration test") |
||||
} |
||||
|
||||
testCtx := createTestContext(t) |
||||
ctx := appcontext.WithUser(testCtx.ctx, testCtx.user) |
||||
|
||||
t.Run("should not retrieve non-existent objects", func(t *testing.T) { |
||||
resp, err := testCtx.client.GetResource(ctx, &resource.GetResourceRequest{ |
||||
Key: &resource.Key{ |
||||
Group: "X", |
||||
Namespace: "X", |
||||
}, |
||||
}) |
||||
require.NoError(t, err) |
||||
require.NotNil(t, resp) |
||||
require.NotNil(t, resp.Status) |
||||
require.Nil(t, resp.Value) |
||||
require.Equal(t, int32(http.StatusBadRequest), resp.Status.Code) |
||||
}) |
||||
|
||||
t.Run("insert an object", func(t *testing.T) { |
||||
var err error |
||||
key := &resource.Key{ |
||||
Namespace: "default", |
||||
Group: "playlists.grafana.app", |
||||
Resource: "Playlist", |
||||
Name: "x123", |
||||
} |
||||
sample := v0alpha1.Playlist{ |
||||
ObjectMeta: metav1.ObjectMeta{ |
||||
Name: key.Name, |
||||
Namespace: key.Namespace, |
||||
UID: types.UID("xyz"), |
||||
}, |
||||
TypeMeta: metav1.TypeMeta{ |
||||
Kind: key.Resource, |
||||
APIVersion: key.Group + "/v0alpha1", |
||||
}, |
||||
Spec: v0alpha1.Spec{ |
||||
Title: "hello", |
||||
}, |
||||
} |
||||
req := &resource.CreateRequest{ |
||||
Key: key, |
||||
} |
||||
req.Value, err = json.Marshal(sample) |
||||
require.NoError(t, err) |
||||
|
||||
fmt.Printf("%s", string(req.Value)) |
||||
|
||||
resp, err := testCtx.client.Create(ctx, req) |
||||
require.NoError(t, err) |
||||
require.NotNil(t, resp) |
||||
require.Nil(t, resp.Status) |
||||
require.True(t, resp.ResourceVersion > 0) // that it has a positive resource version
|
||||
}) |
||||
} |
@ -0,0 +1,39 @@ |
||||
{ |
||||
"tags": [ |
||||
"blue", |
||||
"green" |
||||
], |
||||
"editable": true, |
||||
"fiscalYearStartMonth": 0, |
||||
"graphTooltip": 0, |
||||
"id": 221, |
||||
"links": [], |
||||
"liveNow": false, |
||||
"panels": [ |
||||
{ |
||||
"gridPos": { |
||||
"h": 1, |
||||
"w": 24, |
||||
"x": 0, |
||||
"y": 8 |
||||
}, |
||||
"id": 8, |
||||
"title": "Row title", |
||||
"type": "row" |
||||
} |
||||
], |
||||
"schemaVersion": 36, |
||||
"templating": { |
||||
"list": [] |
||||
}, |
||||
"time": { |
||||
"from": "now-6h", |
||||
"to": "now" |
||||
}, |
||||
"timepicker": {}, |
||||
"timezone": "", |
||||
"title": "special ds", |
||||
"uid": "mocpwtR4k", |
||||
"version": 1, |
||||
"weekStart": "" |
||||
} |
@ -0,0 +1,39 @@ |
||||
{ |
||||
"tags": [ |
||||
"red", |
||||
"green" |
||||
], |
||||
"editable": true, |
||||
"fiscalYearStartMonth": 0, |
||||
"graphTooltip": 0, |
||||
"id": 221, |
||||
"links": [], |
||||
"liveNow": false, |
||||
"panels": [ |
||||
{ |
||||
"gridPos": { |
||||
"h": 1, |
||||
"w": 24, |
||||
"x": 0, |
||||
"y": 8 |
||||
}, |
||||
"id": 8, |
||||
"title": "Row title", |
||||
"type": "row" |
||||
} |
||||
], |
||||
"schemaVersion": 36, |
||||
"templating": { |
||||
"list": [] |
||||
}, |
||||
"time": { |
||||
"from": "now-6h", |
||||
"to": "now" |
||||
}, |
||||
"timepicker": {}, |
||||
"timezone": "", |
||||
"title": "special ds", |
||||
"uid": "mocpwtR4k", |
||||
"version": 1, |
||||
"weekStart": "" |
||||
} |
@ -0,0 +1,14 @@ |
||||
package resource |
||||
|
||||
import ( |
||||
"fmt" |
||||
"net/http" |
||||
) |
||||
|
||||
func badRequest(format string, a ...any) *StatusResult { |
||||
return &StatusResult{ |
||||
Status: "Failure", |
||||
Message: fmt.Sprintf(format, a...), |
||||
Code: http.StatusBadRequest, |
||||
} |
||||
} |
Loading…
Reference in new issue