Merge pull request #13552 from influxdata/kv_log_time

feat(http): add audit log
pull/13941/head
kelwang 2019-05-16 11:10:56 -04:00 committed by GitHub
commit 4bbfa8c6f4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 148 additions and 84 deletions

View File

@ -29,7 +29,7 @@ type Client struct {
IDGenerator platform.IDGenerator
TokenGenerator platform.TokenGenerator
time func() time.Time
platform.TimeGenerator
}
// NewClient returns an instance of a Client.
@ -38,7 +38,7 @@ func NewClient() *Client {
Logger: zap.NewNop(),
IDGenerator: snowflake.NewIDGenerator(),
TokenGenerator: rand.NewTokenGenerator(64),
time: time.Now,
TimeGenerator: platform.RealTimeGenerator{},
}
}
@ -53,12 +53,6 @@ func (c *Client) WithLogger(l *zap.Logger) {
c.Logger = l
}
// WithTime sets the function for computing the current time. Used for updating meta data
// about objects stored. Should only be used in tests for mocking.
func (c *Client) WithTime(fn func() time.Time) {
c.time = fn
}
// Open / create boltDB file.
func (c *Client) Open(ctx context.Context) error {
// Ensure the required directory structure exists.

View File

@ -676,5 +676,5 @@ func (c *Client) appendBucketEventToLog(ctx context.Context, tx *bolt.Tx, id pla
return err
}
return c.addLogEntry(ctx, tx, k, v, c.time())
return c.addLogEntry(ctx, tx, k, v, c.Now())
}

View File

@ -286,7 +286,7 @@ func (c *Client) CreateDashboard(ctx context.Context, d *platform.Dashboard) err
}
// TODO(desa): don't populate this here. use the first/last methods of the oplog to get meta fields.
d.Meta.CreatedAt = c.time()
d.Meta.CreatedAt = c.Now()
return c.putDashboardWithMeta(ctx, tx, d)
})
@ -698,7 +698,7 @@ func (c *Client) putDashboard(ctx context.Context, tx *bolt.Tx, d *platform.Dash
func (c *Client) putDashboardWithMeta(ctx context.Context, tx *bolt.Tx, d *platform.Dashboard) error {
// TODO(desa): don't populate this here. use the first/last methods of the oplog to get meta fields.
d.Meta.UpdatedAt = c.time()
d.Meta.UpdatedAt = c.Now()
return c.putDashboard(ctx, tx, d)
}
@ -907,5 +907,5 @@ func (c *Client) appendDashboardEventToLog(ctx context.Context, tx *bolt.Tx, id
return err
}
return c.addLogEntry(ctx, tx, k, v, c.time())
return c.addLogEntry(ctx, tx, k, v, c.Now())
}

View File

@ -3,7 +3,6 @@ package bolt_test
import (
"context"
"testing"
"time"
platform "github.com/influxdata/influxdb"
"github.com/influxdata/influxdb/bolt"
@ -16,12 +15,13 @@ func initDashboardService(f platformtesting.DashboardFields, t *testing.T) (plat
t.Fatalf("failed to create new bolt client: %v", err)
}
if f.NowFn == nil {
f.NowFn = time.Now
if f.TimeGenerator == nil {
f.TimeGenerator = platform.RealTimeGenerator{}
}
c.IDGenerator = f.IDGenerator
c.WithTime(f.NowFn)
c.TimeGenerator = f.TimeGenerator
ctx := context.TODO()
for _, b := range f.Dashboards {
if err := c.PutDashboard(ctx, b); err != nil {

View File

@ -501,7 +501,7 @@ func (c *Client) appendOrganizationEventToLog(ctx context.Context, tx *bolt.Tx,
return err
}
return c.addLogEntry(ctx, tx, k, v, c.time())
return c.addLogEntry(ctx, tx, k, v, c.Now())
}
func (c *Client) FindResourceOrganizationID(ctx context.Context, rt influxdb.ResourceType, id influxdb.ID) (influxdb.ID, error) {

View File

@ -476,5 +476,5 @@ func (c *Client) appendUserEventToLog(ctx context.Context, tx *bolt.Tx, id platf
return err
}
return c.addLogEntry(ctx, tx, k, v, c.time())
return c.addLogEntry(ctx, tx, k, v, c.Now())
}

View File

@ -45,7 +45,7 @@ import (
_ "github.com/influxdata/influxdb/tsdb/tsm1" // needed for tsm1
"github.com/influxdata/influxdb/vault"
pzap "github.com/influxdata/influxdb/zap"
"github.com/opentracing/opentracing-go"
opentracing "github.com/opentracing/opentracing-go"
"github.com/prometheus/client_golang/prometheus"
"github.com/spf13/cobra"
jaegerconfig "github.com/uber/jaeger-client-go/config"

25
crud_log.go Normal file
View File

@ -0,0 +1,25 @@
package influxdb
import (
"time"
)
// CRUDLog is the struct to store crud related ops.
type CRUDLog struct {
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
}
// TimeGenerator represents a generator for now.
type TimeGenerator interface {
// Now creates the generated time.
Now() time.Time
}
// RealTimeGenerator will generate the real time.
type RealTimeGenerator struct{}
// Now returns the current time.
func (g RealTimeGenerator) Now() time.Time {
return time.Now()
}

View File

@ -28,6 +28,7 @@ type DocumentMeta struct {
Type string `json:"type,omitempty"`
Description string `json:"description,omitempty"`
Version string `json:"version,omitempty"`
CRUDLog
}
// DocumentStore is used to perform CRUD operations on documents. It follows an options

View File

@ -1363,7 +1363,7 @@ func initDashboardService(f platformtesting.DashboardFields, t *testing.T) (plat
t.Helper()
svc := inmem.NewService()
svc.IDGenerator = f.IDGenerator
svc.WithTime(f.NowFn)
svc.TimeGenerator = f.TimeGenerator
ctx := context.Background()
for _, d := range f.Dashboards {
if err := svc.PutDashboard(ctx, d); err != nil {

View File

@ -140,6 +140,8 @@ func (h *DocumentHandler) handlePostDocument(w http.ResponseWriter, r *http.Requ
return
}
h.Logger.Info("document created")
if err := encodeResponse(ctx, w, http.StatusCreated, newDocumentResponse(req.Namespace, req.Document)); err != nil {
logEncodingError(h.Logger, r, err)
return
@ -459,6 +461,8 @@ func (h *DocumentHandler) handleDeleteDocument(w http.ResponseWriter, r *http.Re
return
}
h.Logger.Info("document deleted")
w.WriteHeader(http.StatusNoContent)
}
@ -526,6 +530,8 @@ func (h *DocumentHandler) handlePutDocument(w http.ResponseWriter, r *http.Reque
return
}
h.Logger.Info("document updated")
ds, err := s.FindDocuments(ctx, influxdb.WhereID(req.Document.ID), influxdb.IncludeContent)
if err != nil {
EncodeError(ctx, err, w)

View File

@ -8,6 +8,7 @@ import (
"net/http"
"net/http/httptest"
"testing"
"time"
"github.com/influxdata/influxdb"
pcontext "github.com/influxdata/influxdb/context"
@ -43,6 +44,9 @@ var (
label3MappingJSON, _ = json.Marshal(influxdb.LabelMapping{
LabelID: label3ID,
})
mockGen = mock.TimeGenerator{
FakeValue: time.Date(2006, 5, 24, 1, 2, 3, 4, time.UTC),
}
doc1 = influxdb.Document{
ID: doc1ID,
Meta: influxdb.DocumentMeta{
@ -127,6 +131,8 @@ var (
"meta": {
"name": "doc1",
"type": "typ1",
"createdAt": "0001-01-01T00:00:00Z",
"updatedAt": "0001-01-01T00:00:00Z",
"description": "desc1"
}
},
@ -137,7 +143,9 @@ var (
},
"content": "content2",
"meta": {
"name": "doc2"
"name": "doc2",
"createdAt": "0001-01-01T00:00:00Z",
"updatedAt": "0001-01-01T00:00:00Z"
}
}
]
@ -427,6 +435,7 @@ func TestService_handlePostDocumentLabel(t *testing.T) {
DocumentService: &mock.DocumentService{
FindDocumentStoreFn: func(context.Context, string) (influxdb.DocumentStore, error) {
return &mock.DocumentStore{
TimeGenerator: mockGen,
FindDocumentsFn: func(ctx context.Context, opts ...influxdb.DocumentFindOptions) ([]*influxdb.Document, error) {
return []*influxdb.Document{&doc4}, nil
},
@ -801,7 +810,9 @@ func TestService_handlePostDocuments(t *testing.T) {
DocumentService: &mock.DocumentService{
FindDocumentStoreFn: func(context.Context, string) (influxdb.DocumentStore, error) {
return &mock.DocumentStore{
TimeGenerator: mockGen,
CreateDocumentFn: func(ctx context.Context, d *influxdb.Document, opts ...influxdb.DocumentOptions) error {
d.Meta.CreatedAt = mockGen.Now()
return nil
},
}, nil
@ -826,7 +837,9 @@ func TestService_handlePostDocuments(t *testing.T) {
"self": "/api/v2/documents/template/020f755c3c082014"
},
"meta": {
"name": "doc5"
"name": "doc5",
"createdAt": "2006-05-24T01:02:03.000000004Z",
"updatedAt": "0001-01-01T00:00:00Z"
}}`,
},
},
@ -836,8 +849,10 @@ func TestService_handlePostDocuments(t *testing.T) {
DocumentService: &mock.DocumentService{
FindDocumentStoreFn: func(context.Context, string) (influxdb.DocumentStore, error) {
return &mock.DocumentStore{
TimeGenerator: mockGen,
CreateDocumentFn: func(ctx context.Context, d *influxdb.Document, opts ...influxdb.DocumentOptions) error {
d.Labels = []*influxdb.Label{&label1, &label2}
d.Meta.CreatedAt = mockGen.Now()
return nil
},
}, nil
@ -877,7 +892,9 @@ func TestService_handlePostDocuments(t *testing.T) {
"name": "l2"
}],
"meta": {
"name": "doc6"
"name": "doc6",
"createdAt": "2006-05-24T01:02:03.000000004Z",
"updatedAt": "0001-01-01T00:00:00Z"
}}`,
},
},

View File

@ -6983,6 +6983,14 @@ components:
type: string
version:
type: string
createdAt:
type: string
format: date-time
readOnly: true
updatedAt:
type: string
format: date-time
readOnly: true
required:
- name
- version

View File

@ -129,7 +129,7 @@ func (s *Service) FindDashboards(ctx context.Context, filter platform.DashboardF
// CreateDashboard implements platform.DashboardService interface.
func (s *Service) CreateDashboard(ctx context.Context, d *platform.Dashboard) error {
d.ID = s.IDGenerator.ID()
d.Meta.CreatedAt = s.time()
d.Meta.CreatedAt = s.Now()
err := s.PutDashboardWithMeta(ctx, d)
if err != nil {
return &platform.Error{
@ -160,7 +160,7 @@ func (s *Service) PutCellView(ctx context.Context, cell *platform.Cell) error {
// PutDashboardWithMeta sets a dashboard while updating the meta field of a dashboard.
func (s *Service) PutDashboardWithMeta(ctx context.Context, d *platform.Dashboard) error {
d.Meta.UpdatedAt = s.time()
d.Meta.UpdatedAt = s.Now()
return s.PutDashboard(ctx, d)
}

View File

@ -11,8 +11,8 @@ import (
func initDashboardService(f platformtesting.DashboardFields, t *testing.T) (platform.DashboardService, string, func()) {
s := NewService()
s.IDGenerator = f.IDGenerator
s.TimeGenerator = f.TimeGenerator
ctx := context.Background()
s.WithTime(f.NowFn)
for _, b := range f.Dashboards {
if err := s.PutDashboard(ctx, b); err != nil {
t.Fatalf("failed to populate Dashboards")

View File

@ -3,7 +3,6 @@ package inmem
import (
"context"
"sync"
"time"
platform "github.com/influxdata/influxdb"
"github.com/influxdata/influxdb/rand"
@ -35,7 +34,7 @@ type Service struct {
TokenGenerator platform.TokenGenerator
IDGenerator platform.IDGenerator
time func() time.Time
platform.TimeGenerator
}
// NewService creates an instance of a Service.
@ -43,18 +42,12 @@ func NewService() *Service {
s := &Service{
TokenGenerator: rand.NewTokenGenerator(64),
IDGenerator: snowflake.NewIDGenerator(),
time: time.Now,
TimeGenerator: platform.RealTimeGenerator{},
}
s.initializeSources(context.TODO())
return s
}
// WithTime sets the function for computing the current time. Used for updating meta data
// about objects stored. Should only be used in tests for mocking.
func (s *Service) WithTime(fn func() time.Time) {
s.time = fn
}
// Flush removes all data from the in-memory store
func (s *Service) Flush() {
s.flush(&s.authorizationKV)

View File

@ -759,7 +759,7 @@ func (s *Service) appendBucketEventToLog(ctx context.Context, tx Tx, id influxdb
return err
}
return s.addLogEntry(ctx, tx, k, v, s.time())
return s.addLogEntry(ctx, tx, k, v, s.Now())
}
// UnexpectedBucketError is used when the error comes from an internal system.

View File

@ -301,7 +301,7 @@ func (s *Service) CreateDashboard(ctx context.Context, d *influxdb.Dashboard) er
}
// TODO(desa): don't populate this here. use the first/last methods of the oplog to get meta fields.
d.Meta.CreatedAt = s.time()
d.Meta.CreatedAt = s.Now()
if err := s.putDashboardWithMeta(ctx, tx, d); err != nil {
return err
@ -752,7 +752,7 @@ func (s *Service) putDashboard(ctx context.Context, tx Tx, d *influxdb.Dashboard
func (s *Service) putDashboardWithMeta(ctx context.Context, tx Tx, d *influxdb.Dashboard) error {
// TODO(desa): don't populate this here. use the first/last methods of the oplog to get meta fields.
d.Meta.UpdatedAt = s.time()
d.Meta.UpdatedAt = s.Now()
return s.putDashboard(ctx, tx, d)
}
@ -972,5 +972,5 @@ func (s *Service) appendDashboardEventToLog(ctx context.Context, tx Tx, id influ
return err
}
return s.addLogEntry(ctx, tx, k, v, s.time())
return s.addLogEntry(ctx, tx, k, v, s.Now())
}

View File

@ -3,7 +3,6 @@ package kv_test
import (
"context"
"testing"
"time"
"github.com/influxdata/influxdb"
"github.com/influxdata/influxdb/kv"
@ -46,12 +45,12 @@ func initInmemDashboardService(f influxdbtesting.DashboardFields, t *testing.T)
func initDashboardService(s kv.Store, f influxdbtesting.DashboardFields, t *testing.T) (influxdb.DashboardService, string, func()) {
if f.NowFn == nil {
f.NowFn = time.Now
if f.TimeGenerator == nil {
f.TimeGenerator = influxdb.RealTimeGenerator{}
}
svc := kv.NewService(s)
svc.IDGenerator = f.IDGenerator
svc.WithTime(f.NowFn)
svc.TimeGenerator = f.TimeGenerator
ctx := context.Background()
if err := svc.Initialize(ctx); err != nil {

View File

@ -348,7 +348,7 @@ func (i *DocumentIndex) GetAccessorsDocuments(ownerType string, ownerID influxdb
func (s *Service) createDocument(ctx context.Context, tx Tx, ns string, d *influxdb.Document) error {
d.ID = s.IDGenerator.ID()
d.Meta.CreatedAt = s.Now()
if err := s.putDocument(ctx, tx, ns, d); err != nil {
return err
}
@ -357,7 +357,7 @@ func (s *Service) createDocument(ctx context.Context, tx Tx, ns string, d *influ
}
func (s *Service) putDocument(ctx context.Context, tx Tx, ns string, d *influxdb.Document) error {
if err := s.putDocumentMeta(ctx, tx, ns, d.ID, &d.Meta); err != nil {
if err := s.putDocumentMeta(ctx, tx, ns, d.ID, d.Meta); err != nil {
return err
}
@ -397,7 +397,7 @@ func (s *Service) putDocumentContent(ctx context.Context, tx Tx, ns string, id i
return s.putAtID(ctx, tx, path.Join(ns, documentContentBucket), id, data)
}
func (s *Service) putDocumentMeta(ctx context.Context, tx Tx, ns string, id influxdb.ID, m *influxdb.DocumentMeta) error {
func (s *Service) putDocumentMeta(ctx context.Context, tx Tx, ns string, id influxdb.ID, m influxdb.DocumentMeta) error {
return s.putAtID(ctx, tx, path.Join(ns, documentMetaBucket), id, m)
}
@ -735,7 +735,7 @@ func (s *DocumentStore) UpdateDocument(ctx context.Context, d *influxdb.Document
func (s *Service) updateDocument(ctx context.Context, tx Tx, ns string, d *influxdb.Document) error {
// TODO(desa): deindex meta
d.Meta.UpdatedAt = s.Now()
if err := s.putDocument(ctx, tx, ns, d); err != nil {
return err
}

View File

@ -108,7 +108,10 @@ func (s *Service) initializeKVLog(ctx context.Context, tx Tx) error {
return nil
}
var errKeyValueLogBoundsNotFound = fmt.Errorf("oplog not found")
var errKeyValueLogBoundsNotFound = &platform.Error{
Code: platform.ENotFound,
Msg: "oplog not found",
}
func (s *Service) getKeyValueLogBounds(ctx context.Context, tx Tx, key []byte) (*keyValueLogBounds, error) {
k := encodeKeyValueIndexKey(key)
@ -381,7 +384,7 @@ func (s *Service) LastLogEntry(ctx context.Context, k []byte) ([]byte, time.Time
func (s *Service) firstLogEntry(ctx context.Context, tx Tx, k []byte) ([]byte, time.Time, error) {
bounds, err := s.getKeyValueLogBounds(ctx, tx, k)
if err != nil {
return nil, bounds.StartTime(), err
return nil, time.Time{}, err
}
return s.getLogEntry(ctx, tx, k, bounds.StartTime())
@ -390,7 +393,7 @@ func (s *Service) firstLogEntry(ctx context.Context, tx Tx, k []byte) ([]byte, t
func (s *Service) lastLogEntry(ctx context.Context, tx Tx, k []byte) ([]byte, time.Time, error) {
bounds, err := s.getKeyValueLogBounds(ctx, tx, k)
if err != nil {
return nil, bounds.StopTime(), err
return nil, time.Time{}, err
}
return s.getLogEntry(ctx, tx, k, bounds.StopTime())

View File

@ -570,7 +570,7 @@ func (s *Service) appendOrganizationEventToLog(ctx context.Context, tx Tx, id in
return err
}
return s.addLogEntry(ctx, tx, k, v, s.time())
return s.addLogEntry(ctx, tx, k, v, s.Now())
}
// FindResourceOrganizationID is used to find the organization that a resource belongs to five the id of a resource and a resource type.

View File

@ -2,7 +2,6 @@ package kv
import (
"context"
"time"
"go.uber.org/zap"
@ -26,9 +25,8 @@ type Service struct {
IDGenerator influxdb.IDGenerator
TokenGenerator influxdb.TokenGenerator
influxdb.TimeGenerator
Hash Crypt
time func() time.Time
}
// NewService returns an instance of a Service.
@ -39,7 +37,7 @@ func NewService(kv Store, configs ...ServiceConfig) *Service {
TokenGenerator: rand.NewTokenGenerator(64),
Hash: &Bcrypt{},
kv: kv,
time: time.Now,
TimeGenerator: influxdb.RealTimeGenerator{},
}
if len(configs) > 0 {
@ -131,12 +129,6 @@ func (s *Service) Initialize(ctx context.Context) error {
})
}
// WithTime sets the function for computing the current time. Used for updating meta data
// about objects stored. Should only be used in tests for mocking.
func (s *Service) WithTime(fn func() time.Time) {
s.time = fn
}
// WithStore sets kv store for the service.
// Should only be used in tests for mocking.
func (s *Service) WithStore(store Store) {

View File

@ -515,7 +515,7 @@ func (s *Service) appendUserEventToLog(ctx context.Context, tx Tx, id influxdb.I
return err
}
return s.addLogEntry(ctx, tx, k, v, s.time())
return s.addLogEntry(ctx, tx, k, v, s.Now())
}
var (

View File

@ -38,6 +38,7 @@ func NewDocumentService() *DocumentService {
// DocumentStore is the mocked document store.
type DocumentStore struct {
TimeGenerator TimeGenerator
CreateDocumentFn func(ctx context.Context, d *influxdb.Document, opts ...influxdb.DocumentOptions) error
UpdateDocumentFn func(ctx context.Context, d *influxdb.Document, opts ...influxdb.DocumentOptions) error
FindDocumentsFn func(ctx context.Context, opts ...influxdb.DocumentFindOptions) ([]*influxdb.Document, error)

View File

@ -2,6 +2,7 @@ package mock
import (
"testing"
"time"
platform "github.com/influxdata/influxdb"
)
@ -47,3 +48,13 @@ type TokenGenerator struct {
func (g TokenGenerator) Token() (string, error) {
return g.TokenFn()
}
// TimeGenerator stores a fake value of time.
type TimeGenerator struct {
FakeValue time.Time
}
// Now will return the FakeValue stored in the struct.
func (g TimeGenerator) Now() time.Time {
return g.FakeValue
}

View File

@ -32,7 +32,7 @@ var dashboardCmpOptions = cmp.Options{
// DashboardFields will include the IDGenerator, and dashboards
type DashboardFields struct {
IDGenerator platform.IDGenerator
NowFn func() time.Time
TimeGenerator platform.TimeGenerator
Dashboards []*platform.Dashboard
Views []*platform.View
}
@ -125,7 +125,7 @@ func CreateDashboard(
return MustIDBase16(dashTwoID)
},
},
NowFn: func() time.Time { return time.Date(2009, time.November, 10, 24, 0, 0, 0, time.UTC) },
TimeGenerator: mock.TimeGenerator{FakeValue: time.Date(2009, time.November, 10, 24, 0, 0, 0, time.UTC)},
Dashboards: []*platform.Dashboard{
{
ID: MustIDBase16(dashOneID),
@ -168,7 +168,7 @@ func CreateDashboard(
return MustIDBase16(dashTwoID)
},
},
NowFn: func() time.Time { return time.Date(2009, time.November, 10, 24, 0, 0, 0, time.UTC) },
TimeGenerator: mock.TimeGenerator{FakeValue: time.Date(2009, time.November, 10, 24, 0, 0, 0, time.UTC)},
Dashboards: []*platform.Dashboard{
{
ID: MustIDBase16(dashOneID),
@ -253,7 +253,7 @@ func AddDashboardCell(
return MustIDBase16(dashTwoID)
},
},
NowFn: func() time.Time { return time.Date(2009, time.November, 10, 24, 0, 0, 0, time.UTC) },
TimeGenerator: mock.TimeGenerator{FakeValue: time.Date(2009, time.November, 10, 24, 0, 0, 0, time.UTC)},
Dashboards: []*platform.Dashboard{
{
ID: MustIDBase16(dashOneID),
@ -296,7 +296,7 @@ func AddDashboardCell(
{
name: "add cell with no id",
fields: DashboardFields{
NowFn: func() time.Time { return time.Date(2009, time.November, 10, 24, 0, 0, 0, time.UTC) },
TimeGenerator: mock.TimeGenerator{FakeValue: time.Date(2009, time.November, 10, 24, 0, 0, 0, time.UTC)},
IDGenerator: &mock.IDGenerator{
IDFn: func() platform.ID {
return MustIDBase16(dashTwoID)
@ -342,7 +342,7 @@ func AddDashboardCell(
{
name: "add cell with id not exist",
fields: DashboardFields{
NowFn: func() time.Time { return time.Date(2009, time.November, 10, 24, 0, 0, 0, time.UTC) },
TimeGenerator: mock.TimeGenerator{FakeValue: time.Date(2009, time.November, 10, 24, 0, 0, 0, time.UTC)},
IDGenerator: &mock.IDGenerator{
IDFn: func() platform.ID {
return MustIDBase16(dashTwoID)
@ -1059,7 +1059,7 @@ func UpdateDashboard(
{
name: "update name",
fields: DashboardFields{
NowFn: func() time.Time { return time.Date(2009, time.November, 10, 24, 0, 0, 0, time.UTC) },
TimeGenerator: mock.TimeGenerator{FakeValue: time.Date(2009, time.November, 10, 24, 0, 0, 0, time.UTC)},
Dashboards: []*platform.Dashboard{
{
ID: MustIDBase16(dashOneID),
@ -1091,7 +1091,7 @@ func UpdateDashboard(
{
name: "update description",
fields: DashboardFields{
NowFn: func() time.Time { return time.Date(2009, time.November, 10, 24, 0, 0, 0, time.UTC) },
TimeGenerator: mock.TimeGenerator{FakeValue: time.Date(2009, time.November, 10, 24, 0, 0, 0, time.UTC)},
Dashboards: []*platform.Dashboard{
{
ID: MustIDBase16(dashOneID),
@ -1124,7 +1124,7 @@ func UpdateDashboard(
{
name: "update description and name",
fields: DashboardFields{
NowFn: func() time.Time { return time.Date(2009, time.November, 10, 24, 0, 0, 0, time.UTC) },
TimeGenerator: mock.TimeGenerator{FakeValue: time.Date(2009, time.November, 10, 24, 0, 0, 0, time.UTC)},
Dashboards: []*platform.Dashboard{
{
ID: MustIDBase16(dashOneID),
@ -1158,7 +1158,7 @@ func UpdateDashboard(
{
name: "update with id not exist",
fields: DashboardFields{
NowFn: func() time.Time { return time.Date(2009, time.November, 10, 24, 0, 0, 0, time.UTC) },
TimeGenerator: mock.TimeGenerator{FakeValue: time.Date(2009, time.November, 10, 24, 0, 0, 0, time.UTC)},
Dashboards: []*platform.Dashboard{
{
ID: MustIDBase16(dashOneID),
@ -1234,7 +1234,7 @@ func RemoveDashboardCell(
{
name: "basic remove cell",
fields: DashboardFields{
NowFn: func() time.Time { return time.Date(2009, time.November, 10, 24, 0, 0, 0, time.UTC) },
TimeGenerator: mock.TimeGenerator{FakeValue: time.Date(2009, time.November, 10, 24, 0, 0, 0, time.UTC)},
IDGenerator: &mock.IDGenerator{
IDFn: func() platform.ID {
return MustIDBase16(dashTwoID)
@ -1332,7 +1332,7 @@ func UpdateDashboardCell(
{
name: "basic update cell",
fields: DashboardFields{
NowFn: func() time.Time { return time.Date(2009, time.November, 10, 24, 0, 0, 0, time.UTC) },
TimeGenerator: mock.TimeGenerator{FakeValue: time.Date(2009, time.November, 10, 24, 0, 0, 0, time.UTC)},
IDGenerator: &mock.IDGenerator{
IDFn: func() platform.ID {
return MustIDBase16(dashTwoID)
@ -1388,7 +1388,7 @@ func UpdateDashboardCell(
{
name: "invalid cell update without attribute",
fields: DashboardFields{
NowFn: func() time.Time { return time.Date(2009, time.November, 10, 24, 0, 0, 0, time.UTC) },
TimeGenerator: mock.TimeGenerator{FakeValue: time.Date(2009, time.November, 10, 24, 0, 0, 0, time.UTC)},
IDGenerator: &mock.IDGenerator{
IDFn: func() platform.ID {
return MustIDBase16(dashTwoID)
@ -1441,7 +1441,7 @@ func UpdateDashboardCell(
{
name: "invalid cell update cell id not exist",
fields: DashboardFields{
NowFn: func() time.Time { return time.Date(2009, time.November, 10, 24, 0, 0, 0, time.UTC) },
TimeGenerator: mock.TimeGenerator{FakeValue: time.Date(2009, time.November, 10, 24, 0, 0, 0, time.UTC)},
IDGenerator: &mock.IDGenerator{
IDFn: func() platform.ID {
return MustIDBase16(dashTwoID)
@ -1539,7 +1539,7 @@ func ReplaceDashboardCells(
{
name: "basic replace cells",
fields: DashboardFields{
NowFn: func() time.Time { return time.Date(2009, time.November, 10, 24, 0, 0, 0, time.UTC) },
TimeGenerator: mock.TimeGenerator{FakeValue: time.Date(2009, time.November, 10, 24, 0, 0, 0, time.UTC)},
IDGenerator: &mock.IDGenerator{
IDFn: func() platform.ID {
return MustIDBase16(dashTwoID)
@ -1620,7 +1620,7 @@ func ReplaceDashboardCells(
{
name: "try to add a cell that didn't previously exist",
fields: DashboardFields{
NowFn: func() time.Time { return time.Date(2009, time.November, 10, 24, 0, 0, 0, time.UTC) },
TimeGenerator: mock.TimeGenerator{FakeValue: time.Date(2009, time.November, 10, 24, 0, 0, 0, time.UTC)},
IDGenerator: &mock.IDGenerator{
IDFn: func() platform.ID {
return MustIDBase16(dashTwoID)

View File

@ -5,11 +5,13 @@ import (
"context"
"sort"
"testing"
"time"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"github.com/influxdata/influxdb"
"github.com/influxdata/influxdb/kv"
"github.com/influxdata/influxdb/mock"
)
// NewDocumentIntegrationTest will test the documents related funcs.
@ -17,10 +19,13 @@ func NewDocumentIntegrationTest(store kv.Store) func(t *testing.T) {
return func(t *testing.T) {
ctx := context.Background()
svc := kv.NewService(store)
mockTimeGen := new(mock.TimeGenerator)
if err := svc.Initialize(ctx); err != nil {
t.Fatalf("failed to initialize service: %v", err)
}
svc.TimeGenerator = mockTimeGen
s, err := svc.CreateDocumentStore(ctx, "testing")
if err != nil {
t.Fatalf("failed to create document store: %v", err)
@ -68,6 +73,7 @@ func NewDocumentIntegrationTest(store kv.Store) func(t *testing.T) {
"v1": "v1",
},
}
mockTimeGen.FakeValue = time.Date(2009, 1, 2, 3, 0, 0, 0, time.UTC)
if err := s.CreateDocument(ctx, d1, influxdb.AuthorizedWithOrg(s1, o1.Name), influxdb.WithLabel(l1.ID)); err != nil {
t.Errorf("failed to create document: %v", err)
}
@ -82,10 +88,12 @@ func NewDocumentIntegrationTest(store kv.Store) func(t *testing.T) {
"i2": "i2",
},
}
mockTimeGen.FakeValue = time.Date(2009, 1, 2, 3, 0, 1, 0, time.UTC)
if err := s.CreateDocument(ctx, d2, influxdb.AuthorizedWithOrg(s2, o1.Name), influxdb.WithLabel(l2.ID)); err == nil {
t.Fatalf("should not have be authorized to create document")
}
mockTimeGen.FakeValue = time.Date(2009, 1, 2, 3, 0, 1, 0, time.UTC)
if err := s.CreateDocument(ctx, d2, influxdb.AuthorizedWithOrg(s2, o2.Name)); err != nil {
t.Errorf("should have been authorized to create document: %v", err)
}
@ -100,6 +108,7 @@ func NewDocumentIntegrationTest(store kv.Store) func(t *testing.T) {
"k2": "v2",
},
}
mockTimeGen.FakeValue = time.Date(2009, 1, 2, 3, 0, 2, 0, time.UTC)
if err := s.CreateDocument(ctx, d3, influxdb.AuthorizedWithOrg(s1, o2.Name)); err == nil {
t.Errorf("should not have be authorized to create document")
}
@ -107,6 +116,7 @@ func NewDocumentIntegrationTest(store kv.Store) func(t *testing.T) {
t.Run("can create unowned document", func(t *testing.T) {
// TODO(desa): should this be allowed?
mockTimeGen.FakeValue = time.Date(2009, 1, 2, 3, 0, 2, 0, time.UTC)
if err := s.CreateDocument(ctx, d3); err != nil {
t.Fatalf("should have been able to create document: %v", err)
}
@ -128,14 +138,18 @@ func NewDocumentIntegrationTest(store kv.Store) func(t *testing.T) {
})
})
d1.Meta.CreatedAt = time.Date(2009, 1, 2, 3, 0, 0, 0, time.UTC)
dl1 := new(influxdb.Document)
*dl1 = *d1
dl1.Labels = append([]*influxdb.Label{}, l1)
d2.Meta.CreatedAt = time.Date(2009, 1, 2, 3, 0, 1, 0, time.UTC)
dl2 := new(influxdb.Document)
*dl2 = *d2
dl2.Labels = append([]*influxdb.Label{}, d2.Labels...)
d3.Meta.CreatedAt = time.Date(2009, 1, 2, 3, 0, 2, 0, time.UTC)
t.Run("bare call to find returns all documents", func(t *testing.T) {
ds, err := ss.FindDocuments(ctx)
if err != nil {
@ -153,8 +167,8 @@ func NewDocumentIntegrationTest(store kv.Store) func(t *testing.T) {
t.Fatalf("failed to retrieve documents: %v", err)
}
if exp, got := []*influxdb.Document{dl1}, ds; !docsEqual(exp, got) {
t.Errorf("documents are different -got/+want\ndiff %s", docsDiff(exp, got))
if exp, got := []*influxdb.Document{dl1}, ds; !docsEqual(got, exp) {
t.Errorf("documents are different -got/+want\ndiff %s", docsDiff(got, exp))
}
})