mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
now with dashboard history
This commit is contained in:
parent
7345ece8ef
commit
999cd506c0
@ -19,6 +19,7 @@ import (
|
|||||||
"github.com/grafana/grafana/pkg/services/apiserver/endpoints/request"
|
"github.com/grafana/grafana/pkg/services/apiserver/endpoints/request"
|
||||||
gapiutil "github.com/grafana/grafana/pkg/services/apiserver/utils"
|
gapiutil "github.com/grafana/grafana/pkg/services/apiserver/utils"
|
||||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||||
|
dashver "github.com/grafana/grafana/pkg/services/dashboardversion"
|
||||||
"github.com/grafana/grafana/pkg/services/provisioning"
|
"github.com/grafana/grafana/pkg/services/provisioning"
|
||||||
"github.com/grafana/grafana/pkg/services/sqlstore/session"
|
"github.com/grafana/grafana/pkg/services/sqlstore/session"
|
||||||
"github.com/grafana/grafana/pkg/storage/unified/resource"
|
"github.com/grafana/grafana/pkg/storage/unified/resource"
|
||||||
@ -55,19 +56,25 @@ type dashboardSqlAccess struct {
|
|||||||
namespacer request.NamespaceMapper
|
namespacer request.NamespaceMapper
|
||||||
dashStore dashboards.Store
|
dashStore dashboards.Store
|
||||||
provisioning provisioning.ProvisioningService
|
provisioning provisioning.ProvisioningService
|
||||||
|
versions dashver.Service
|
||||||
|
|
||||||
// Typically one... the server wrapper
|
// Typically one... the server wrapper
|
||||||
subscribers []chan *resource.WrittenEvent
|
subscribers []chan *resource.WrittenEvent
|
||||||
mutex sync.Mutex
|
mutex sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDashboardAccess(sql db.DB, namespacer request.NamespaceMapper, dashStore dashboards.Store, provisioning provisioning.ProvisioningService) DashboardAccess {
|
func NewDashboardAccess(sql db.DB,
|
||||||
|
namespacer request.NamespaceMapper,
|
||||||
|
dashStore dashboards.Store,
|
||||||
|
provisioning provisioning.ProvisioningService,
|
||||||
|
versions dashver.Service) DashboardAccess {
|
||||||
return &dashboardSqlAccess{
|
return &dashboardSqlAccess{
|
||||||
sql: sql,
|
sql: sql,
|
||||||
sess: sql.GetSqlxSession(),
|
sess: sql.GetSqlxSession(),
|
||||||
namespacer: namespacer,
|
namespacer: namespacer,
|
||||||
dashStore: dashStore,
|
dashStore: dashStore,
|
||||||
provisioning: provisioning,
|
provisioning: provisioning,
|
||||||
|
versions: versions,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,9 +6,12 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/apimachinery/utils"
|
"github.com/grafana/grafana/pkg/apimachinery/utils"
|
||||||
dashboard "github.com/grafana/grafana/pkg/apis/dashboard/v0alpha1"
|
dashboard "github.com/grafana/grafana/pkg/apis/dashboard/v0alpha1"
|
||||||
"github.com/grafana/grafana/pkg/services/apiserver/endpoints/request"
|
"github.com/grafana/grafana/pkg/services/apiserver/endpoints/request"
|
||||||
|
dashver "github.com/grafana/grafana/pkg/services/dashboardversion"
|
||||||
"github.com/grafana/grafana/pkg/storage/unified/resource"
|
"github.com/grafana/grafana/pkg/storage/unified/resource"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -241,7 +244,7 @@ func (a *dashboardSqlAccess) SupportsSignedURLs() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *dashboardSqlAccess) PutBlob(context.Context, *resource.PutBlobRequest) (*resource.PutBlobResponse, error) {
|
func (a *dashboardSqlAccess) PutBlob(context.Context, *resource.PutBlobRequest) (*resource.PutBlobResponse, error) {
|
||||||
return nil, fmt.Errorf("not implemented yet")
|
return nil, fmt.Errorf("put blob not implemented yet")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *dashboardSqlAccess) GetBlob(ctx context.Context, key *resource.ResourceKey, info *utils.BlobInfo, mustProxy bool) (*resource.GetBlobResponse, error) {
|
func (a *dashboardSqlAccess) GetBlob(ctx context.Context, key *resource.ResourceKey, info *utils.BlobInfo, mustProxy bool) (*resource.GetBlobResponse, error) {
|
||||||
@ -262,3 +265,51 @@ func (a *dashboardSqlAccess) GetBlob(ctx context.Context, key *resource.Resource
|
|||||||
rsp.Value, err = json.Marshal(dash.Spec)
|
rsp.Value, err = json.Marshal(dash.Spec)
|
||||||
return rsp, err
|
return rsp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *dashboardSqlAccess) History(ctx context.Context, req *resource.HistoryRequest) (*resource.HistoryResponse, error) {
|
||||||
|
ns, err := request.ParseNamespace(req.Key.Namespace)
|
||||||
|
if err == nil {
|
||||||
|
err = isDashboardKey(req.Key, true)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
versions, err := a.versions.List(ctx, &dashver.ListDashboardVersionsQuery{
|
||||||
|
OrgID: ns.OrgID,
|
||||||
|
DashboardUID: req.Key.Name,
|
||||||
|
Limit: 100,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
rsp := &resource.HistoryResponse{}
|
||||||
|
for _, version := range versions {
|
||||||
|
partial := &metav1.PartialObjectMetadata{}
|
||||||
|
meta, err := utils.MetaAccessor(partial)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
meta.SetName(version.DashboardUID)
|
||||||
|
meta.SetCreationTimestamp(metav1.NewTime(version.Created)) // ???
|
||||||
|
meta.SetUpdatedTimestampMillis(version.Created.UnixMilli())
|
||||||
|
meta.SetMessage(version.Message)
|
||||||
|
meta.SetResourceVersionInt64(version.Created.UnixMilli())
|
||||||
|
|
||||||
|
bytes, err := json.Marshal(partial)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
rsp.Items = append(rsp.Items, &resource.ResourceMeta{
|
||||||
|
ResourceVersion: version.Created.UnixMilli(),
|
||||||
|
PartialObjectMeta: bytes,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return rsp, err
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Used for efficient provisioning
|
||||||
|
func (a *dashboardSqlAccess) Origin(context.Context, *resource.OriginRequest) (*resource.OriginResponse, error) {
|
||||||
|
return nil, fmt.Errorf("not yet (origin)")
|
||||||
|
}
|
||||||
|
@ -23,6 +23,7 @@ type DashboardQuery struct {
|
|||||||
type DashboardAccess interface {
|
type DashboardAccess interface {
|
||||||
resource.AppendingStore
|
resource.AppendingStore
|
||||||
resource.BlobStore
|
resource.BlobStore
|
||||||
|
resource.ResourceSearchServer
|
||||||
|
|
||||||
GetDashboard(ctx context.Context, orgId int64, uid string) (*dashboardsV0.Dashboard, int64, error)
|
GetDashboard(ctx context.Context, orgId int64, uid string) (*dashboardsV0.Dashboard, int64, error)
|
||||||
|
|
||||||
|
@ -17,12 +17,15 @@ type dashboardStorage struct {
|
|||||||
resource common.ResourceInfo
|
resource common.ResourceInfo
|
||||||
access access.DashboardAccess
|
access access.DashboardAccess
|
||||||
tableConverter rest.TableConvertor
|
tableConverter rest.TableConvertor
|
||||||
|
|
||||||
|
server resource.ResourceServer
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *dashboardStorage) newStore(scheme *runtime.Scheme, defaultOptsGetter generic.RESTOptionsGetter) (rest.Storage, error) {
|
func (s *dashboardStorage) newStore(scheme *runtime.Scheme, defaultOptsGetter generic.RESTOptionsGetter) (rest.Storage, error) {
|
||||||
server, err := resource.NewResourceServer(resource.ResourceServerOptions{
|
server, err := resource.NewResourceServer(resource.ResourceServerOptions{
|
||||||
Store: s.access,
|
Store: s.access,
|
||||||
Blob: s.access,
|
Search: s.access,
|
||||||
|
Blob: s.access,
|
||||||
// WriteAccess: resource.WriteAccessHooks{
|
// WriteAccess: resource.WriteAccessHooks{
|
||||||
// Folder: func(ctx context.Context, user identity.Requester, uid string) bool {
|
// Folder: func(ctx context.Context, user identity.Requester, uid string) bool {
|
||||||
// // ???
|
// // ???
|
||||||
@ -32,6 +35,7 @@ func (s *dashboardStorage) newStore(scheme *runtime.Scheme, defaultOptsGetter ge
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
s.server = server
|
||||||
|
|
||||||
resourceInfo := s.resource
|
resourceInfo := s.resource
|
||||||
defaultOpts, err := defaultOptsGetter.GetRESTOptions(resourceInfo.GroupResource())
|
defaultOpts, err := defaultOptsGetter.GetRESTOptions(resourceInfo.GroupResource())
|
||||||
|
@ -39,9 +39,8 @@ var _ builder.APIGroupBuilder = (*DashboardsAPIBuilder)(nil)
|
|||||||
type DashboardsAPIBuilder struct {
|
type DashboardsAPIBuilder struct {
|
||||||
dashboardService dashboards.DashboardService
|
dashboardService dashboards.DashboardService
|
||||||
|
|
||||||
dashboardVersionService dashver.Service
|
accessControl accesscontrol.AccessControl
|
||||||
accessControl accesscontrol.AccessControl
|
store *dashboardStorage
|
||||||
store *dashboardStorage
|
|
||||||
|
|
||||||
log log.Logger
|
log log.Logger
|
||||||
}
|
}
|
||||||
@ -65,13 +64,12 @@ func RegisterAPIService(cfg *setting.Cfg, features featuremgmt.FeatureToggles,
|
|||||||
builder := &DashboardsAPIBuilder{
|
builder := &DashboardsAPIBuilder{
|
||||||
log: log.New("grafana-apiserver.dashboards"),
|
log: log.New("grafana-apiserver.dashboards"),
|
||||||
|
|
||||||
dashboardService: dashboardService,
|
dashboardService: dashboardService,
|
||||||
dashboardVersionService: dashboardVersionService,
|
accessControl: accessControl,
|
||||||
accessControl: accessControl,
|
|
||||||
|
|
||||||
store: &dashboardStorage{
|
store: &dashboardStorage{
|
||||||
resource: dashboard.DashboardResourceInfo,
|
resource: dashboard.DashboardResourceInfo,
|
||||||
access: access.NewDashboardAccess(sql, namespacer, dashStore, provisioning),
|
access: access.NewDashboardAccess(sql, namespacer, dashStore, provisioning, dashboardVersionService),
|
||||||
tableConverter: gapiutil.NewTableConverter(
|
tableConverter: gapiutil.NewTableConverter(
|
||||||
dashboard.DashboardResourceInfo.GroupResource(),
|
dashboard.DashboardResourceInfo.GroupResource(),
|
||||||
[]metav1.TableColumnDefinition{
|
[]metav1.TableColumnDefinition{
|
||||||
@ -114,6 +112,8 @@ func addKnownTypes(scheme *runtime.Scheme, gv schema.GroupVersion) {
|
|||||||
&v0alpha1.DashboardWithAccessInfo{},
|
&v0alpha1.DashboardWithAccessInfo{},
|
||||||
&v0alpha1.DashboardVersionList{},
|
&v0alpha1.DashboardVersionList{},
|
||||||
&v0alpha1.VersionsQueryOptions{},
|
&v0alpha1.VersionsQueryOptions{},
|
||||||
|
&metav1.PartialObjectMetadata{},
|
||||||
|
&metav1.PartialObjectMetadataList{},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -158,7 +158,7 @@ func (b *DashboardsAPIBuilder) GetAPIGroupInfo(
|
|||||||
builder: b,
|
builder: b,
|
||||||
}
|
}
|
||||||
storage[dash.StoragePath("versions")] = &VersionsREST{
|
storage[dash.StoragePath("versions")] = &VersionsREST{
|
||||||
builder: b,
|
search: b.store.server, // resource.NewLocalResourceSearchClient(b.store.server),
|
||||||
}
|
}
|
||||||
|
|
||||||
// // Dual writes if a RESTOptionsGetter is provided
|
// // Dual writes if a RESTOptionsGetter is provided
|
||||||
|
@ -2,7 +2,7 @@ package dashboard
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"encoding/json"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@ -11,21 +11,21 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apiserver/pkg/registry/rest"
|
"k8s.io/apiserver/pkg/registry/rest"
|
||||||
|
|
||||||
common "github.com/grafana/grafana/pkg/apimachinery/apis/common/v0alpha1"
|
"github.com/grafana/grafana/pkg/apimachinery/utils"
|
||||||
dashboard "github.com/grafana/grafana/pkg/apis/dashboard/v0alpha1"
|
dashboard "github.com/grafana/grafana/pkg/apis/dashboard/v0alpha1"
|
||||||
"github.com/grafana/grafana/pkg/services/apiserver/endpoints/request"
|
"github.com/grafana/grafana/pkg/services/apiserver/endpoints/request"
|
||||||
dashver "github.com/grafana/grafana/pkg/services/dashboardversion"
|
"github.com/grafana/grafana/pkg/storage/unified/resource"
|
||||||
)
|
)
|
||||||
|
|
||||||
type VersionsREST struct {
|
type VersionsREST struct {
|
||||||
builder *DashboardsAPIBuilder
|
search resource.ResourceSearchServer // should be a client!
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ = rest.Connecter(&VersionsREST{})
|
var _ = rest.Connecter(&VersionsREST{})
|
||||||
var _ = rest.StorageMetadata(&VersionsREST{})
|
var _ = rest.StorageMetadata(&VersionsREST{})
|
||||||
|
|
||||||
func (r *VersionsREST) New() runtime.Object {
|
func (r *VersionsREST) New() runtime.Object {
|
||||||
return &dashboard.DashboardVersionList{}
|
return &metav1.PartialObjectMetadataList{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *VersionsREST) Destroy() {
|
func (r *VersionsREST) Destroy() {
|
||||||
@ -40,7 +40,7 @@ func (r *VersionsREST) ProducesMIMETypes(verb string) []string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *VersionsREST) ProducesObject(verb string) interface{} {
|
func (r *VersionsREST) ProducesObject(verb string) interface{} {
|
||||||
return &dashboard.DashboardVersionList{}
|
return &metav1.PartialObjectMetadataList{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *VersionsREST) NewConnectOptions() (runtime.Object, bool, string) {
|
func (r *VersionsREST) NewConnectOptions() (runtime.Object, bool, string) {
|
||||||
@ -52,66 +52,74 @@ func (r *VersionsREST) Connect(ctx context.Context, uid string, opts runtime.Obj
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
key := &resource.ResourceKey{
|
||||||
|
Namespace: info.Value,
|
||||||
|
Group: dashboard.GROUP,
|
||||||
|
Resource: dashboard.DashboardResourceInfo.GroupResource().Resource,
|
||||||
|
Name: uid,
|
||||||
|
}
|
||||||
|
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
||||||
path := req.URL.Path
|
path := req.URL.Path
|
||||||
idx := strings.LastIndex(path, "/versions/")
|
idx := strings.LastIndex(path, "/versions/")
|
||||||
if idx > 0 {
|
if idx > 0 {
|
||||||
key := path[strings.LastIndex(path, "/")+1:]
|
vkey := path[strings.LastIndex(path, "/")+1:]
|
||||||
version, err := strconv.Atoi(key)
|
version, err := strconv.ParseInt(vkey, 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
responder.Error(err)
|
responder.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
dto, err := r.builder.dashboardVersionService.Get(ctx, &dashver.GetDashboardVersionQuery{
|
dashbytes, err := r.search.Read(ctx, &resource.ReadRequest{
|
||||||
DashboardUID: uid,
|
Key: key,
|
||||||
OrgID: info.OrgID,
|
ResourceVersion: version,
|
||||||
Version: version,
|
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
responder.Error(err)
|
responder.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
data, _ := dto.Data.Map()
|
|
||||||
|
|
||||||
// Convert the version to a regular dashboard
|
// Convert the version to a regular dashboard
|
||||||
dash := &dashboard.Dashboard{
|
dash := &dashboard.Dashboard{}
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
json.Unmarshal(dashbytes.Value, dash)
|
||||||
Name: uid,
|
meta, err := utils.MetaAccessor(dash)
|
||||||
CreationTimestamp: metav1.NewTime(dto.Created),
|
if err != nil {
|
||||||
},
|
responder.Error(err)
|
||||||
Spec: common.Unstructured{Object: data},
|
return
|
||||||
}
|
}
|
||||||
|
meta.SetResourceVersionInt64(dashbytes.ResourceVersion)
|
||||||
responder.Object(100, dash)
|
responder.Object(100, dash)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Or list versions
|
rsp, err := r.search.History(ctx, &resource.HistoryRequest{
|
||||||
rsp, err := r.builder.dashboardVersionService.List(ctx, &dashver.ListDashboardVersionsQuery{
|
NextPageToken: "", // TODO!
|
||||||
DashboardUID: uid,
|
Limit: 100,
|
||||||
OrgID: info.OrgID,
|
Key: key,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
responder.Error(err)
|
responder.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
versions := &dashboard.DashboardVersionList{}
|
|
||||||
for _, v := range rsp {
|
list := &metav1.PartialObjectMetadataList{
|
||||||
info := dashboard.DashboardVersionInfo{
|
ListMeta: metav1.ListMeta{
|
||||||
Version: v.Version,
|
Continue: rsp.NextPageToken,
|
||||||
Created: v.Created.UnixMilli(),
|
},
|
||||||
Message: v.Message,
|
|
||||||
}
|
|
||||||
if v.ParentVersion != v.Version {
|
|
||||||
info.ParentVersion = v.ParentVersion
|
|
||||||
}
|
|
||||||
if v.CreatedBy > 0 {
|
|
||||||
info.CreatedBy = fmt.Sprintf("%d", v.CreatedBy)
|
|
||||||
}
|
|
||||||
versions.Items = append(versions.Items, info)
|
|
||||||
}
|
}
|
||||||
responder.Object(http.StatusOK, versions)
|
if rsp.ResourceVersion > 0 {
|
||||||
|
list.ResourceVersion = strconv.FormatInt(rsp.ResourceVersion, 10)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, v := range rsp.Items {
|
||||||
|
partial := metav1.PartialObjectMetadata{}
|
||||||
|
err = json.Unmarshal(v.PartialObjectMeta, &partial)
|
||||||
|
if err != nil {
|
||||||
|
responder.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
list.Items = append(list.Items, partial)
|
||||||
|
}
|
||||||
|
responder.Object(http.StatusOK, list)
|
||||||
}), nil
|
}), nil
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,22 @@ func NewLocalResourceStoreClient(server ResourceStoreServer) ResourceStoreClient
|
|||||||
return NewResourceStoreClient(grpchan.InterceptClientConn(channel, grpcUtils.UnaryClientInterceptor, grpcUtils.StreamClientInterceptor))
|
return NewResourceStoreClient(grpchan.InterceptClientConn(channel, grpcUtils.UnaryClientInterceptor, grpcUtils.StreamClientInterceptor))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewLocalResourceSearchClient(server ResourceStoreServer) ResourceSearchClient {
|
||||||
|
channel := &inprocgrpc.Channel{}
|
||||||
|
|
||||||
|
auth := &grpcUtils.Authenticator{}
|
||||||
|
|
||||||
|
channel.RegisterService(
|
||||||
|
grpchan.InterceptServer(
|
||||||
|
&ResourceStore_ServiceDesc,
|
||||||
|
grpcAuth.UnaryServerInterceptor(auth.Authenticate),
|
||||||
|
grpcAuth.StreamServerInterceptor(auth.Authenticate),
|
||||||
|
),
|
||||||
|
server,
|
||||||
|
)
|
||||||
|
return NewResourceSearchClient(grpchan.InterceptClientConn(channel, grpcUtils.UnaryClientInterceptor, grpcUtils.StreamClientInterceptor))
|
||||||
|
}
|
||||||
|
|
||||||
func NewResourceStoreClientGRPC(channel *grpc.ClientConn) ResourceStoreClient {
|
func NewResourceStoreClientGRPC(channel *grpc.ClientConn) ResourceStoreClient {
|
||||||
return NewResourceStoreClient(grpchan.InterceptClientConn(channel, grpcUtils.UnaryClientInterceptor, grpcUtils.StreamClientInterceptor))
|
return NewResourceStoreClient(grpchan.InterceptClientConn(channel, grpcUtils.UnaryClientInterceptor, grpcUtils.StreamClientInterceptor))
|
||||||
}
|
}
|
||||||
|
@ -140,7 +140,7 @@ func NewResourceServer(opts ResourceServerOptions) (ResourceServer, error) {
|
|||||||
opts.Blob = &noopService{}
|
opts.Blob = &noopService{}
|
||||||
}
|
}
|
||||||
if opts.Diagnostics == nil {
|
if opts.Diagnostics == nil {
|
||||||
opts.Search = &noopService{}
|
opts.Diagnostics = &noopService{}
|
||||||
}
|
}
|
||||||
if opts.Now == nil {
|
if opts.Now == nil {
|
||||||
opts.Now = func() int64 {
|
opts.Now = func() int64 {
|
||||||
|
@ -23,7 +23,7 @@ import (
|
|||||||
|
|
||||||
// Package-level errors.
|
// Package-level errors.
|
||||||
var (
|
var (
|
||||||
ErrNotImplementedYet = errors.New("not implemented yet")
|
ErrNotImplementedYet = errors.New("not implemented yet (sqlnext)")
|
||||||
)
|
)
|
||||||
|
|
||||||
func ProvideSQLResourceServer(db db.EntityDBInterface, tracer tracing.Tracer) (resource.ResourceServer, error) {
|
func ProvideSQLResourceServer(db db.EntityDBInterface, tracer tracing.Tracer) (resource.ResourceServer, error) {
|
||||||
|
Loading…
Reference in New Issue
Block a user