diff --git a/managed/models/database.go b/managed/models/database.go index f1d59ddde78..953fb72e698 100644 --- a/managed/models/database.go +++ b/managed/models/database.go @@ -923,8 +923,8 @@ var databaseSchema = [][]string{ id VARCHAR NOT NULL, status VARCHAR NOT NULL CHECK (status <> ''), service_names VARCHAR[], - start_time TIMESTAMP NOT NULL, - end_time TIMESTAMP NOT NULL, + start_time TIMESTAMP, + end_time TIMESTAMP, export_qan BOOLEAN NOT NULL, ignore_load BOOLEAN NOT NULL, created_at TIMESTAMP NOT NULL, diff --git a/managed/models/dump.go b/managed/models/dump.go index 85515e329c0..d7adcee5c7d 100644 --- a/managed/models/dump.go +++ b/managed/models/dump.go @@ -57,8 +57,8 @@ type Dump struct { ID string `reform:"id,pk"` Status DumpStatus `reform:"status"` ServiceNames pq.StringArray `reform:"service_names"` - StartTime time.Time `reform:"start_time"` - EndTime time.Time `reform:"end_time"` + StartTime *time.Time `reform:"start_time"` + EndTime *time.Time `reform:"end_time"` ExportQAN bool `reform:"export_qan"` IgnoreLoad bool `reform:"ignore_load"` CreatedAt time.Time `reform:"created_at"` diff --git a/managed/models/dump_helpers.go b/managed/models/dump_helpers.go index 990f7518f99..b5c0626ef17 100644 --- a/managed/models/dump_helpers.go +++ b/managed/models/dump_helpers.go @@ -52,13 +52,25 @@ type DumpFilters struct { type CreateDumpParams struct { ServiceNames []string - StartTime time.Time - EndTime time.Time + StartTime *time.Time + EndTime *time.Time ExportQAN bool IgnoreLoad bool } +func (p *CreateDumpParams) Validate() error { + if p.StartTime != nil && p.EndTime != nil && p.StartTime.After(*p.EndTime) { + return errors.Errorf("dump start time can't be greater than end time") + } + + return nil +} + func CreateDump(q *reform.Querier, params CreateDumpParams) (*Dump, error) { + if err := params.Validate(); err != nil { + return nil, errors.Wrap(err, "invalid dump creation params") + } + id := uuid.New().String() if err := checkUniqueDumpID(q, id); err != nil { return nil, err diff --git a/managed/models/dump_helpers_test.go b/managed/models/dump_helpers_test.go index e8a96d2e9b3..f387d900e8b 100644 --- a/managed/models/dump_helpers_test.go +++ b/managed/models/dump_helpers_test.go @@ -37,26 +37,45 @@ func TestDumps(t *testing.T) { require.NoError(t, err) t.Cleanup(func() { require.NoError(t, tx.Rollback()) - require.NoError(t, sqlDB.Close()) }) t.Run("create", func(t *testing.T) { - createDumpParams := models.CreateDumpParams{ - ServiceNames: []string{"foo", "bar"}, - StartTime: time.Now(), - EndTime: time.Now().Add(10 * time.Minute), - ExportQAN: false, - IgnoreLoad: true, - } - dump, err := models.CreateDump(tx.Querier, createDumpParams) - require.NoError(t, err) - assert.NotEmpty(t, dump.ID) - assert.Equal(t, models.DumpStatusInProgress, dump.Status) - assert.ElementsMatch(t, createDumpParams.ServiceNames, dump.ServiceNames) - assert.Equal(t, createDumpParams.StartTime, dump.StartTime) - assert.Equal(t, createDumpParams.EndTime, dump.EndTime) - assert.Equal(t, createDumpParams.ExportQAN, dump.ExportQAN) - assert.Equal(t, createDumpParams.IgnoreLoad, dump.IgnoreLoad) + t.Run("normal", func(t *testing.T) { + endTime := time.Now() + startTime := endTime.Add(-10 * time.Minute) + + createDumpParams := models.CreateDumpParams{ + ServiceNames: []string{"foo", "bar"}, + StartTime: &startTime, + EndTime: &endTime, + ExportQAN: false, + IgnoreLoad: true, + } + dump, err := models.CreateDump(tx.Querier, createDumpParams) + require.NoError(t, err) + assert.NotEmpty(t, dump.ID) + assert.Equal(t, models.DumpStatusInProgress, dump.Status) + assert.ElementsMatch(t, createDumpParams.ServiceNames, dump.ServiceNames) + assert.Equal(t, createDumpParams.StartTime, dump.StartTime) + assert.Equal(t, createDumpParams.EndTime, dump.EndTime) + assert.Equal(t, createDumpParams.ExportQAN, dump.ExportQAN) + assert.Equal(t, createDumpParams.IgnoreLoad, dump.IgnoreLoad) + }) + + t.Run("invalid start and end time", func(t *testing.T) { + endTime := time.Now() + startTime := endTime.Add(10 * time.Minute) + + createDumpParams := models.CreateDumpParams{ + ServiceNames: []string{"foo", "bar"}, + StartTime: &startTime, + EndTime: &endTime, + ExportQAN: false, + IgnoreLoad: true, + } + _, err := models.CreateDump(tx.Querier, createDumpParams) + require.EqualError(t, err, "invalid dump creation params: dump start time can't be greater than end time") + }) }) t.Run("find", func(t *testing.T) { @@ -64,10 +83,13 @@ func TestDumps(t *testing.T) { require.NoError(t, err) defer findTX.Rollback() //nolint:errcheck + endTime := time.Now() + startTime := endTime.Add(-10 * time.Minute) + dump1, err := models.CreateDump(findTX.Querier, models.CreateDumpParams{ ServiceNames: []string{"foo", "bar"}, - StartTime: time.Now(), - EndTime: time.Now().Add(10 * time.Minute), + StartTime: &startTime, + EndTime: &endTime, ExportQAN: false, IgnoreLoad: true, }) @@ -75,8 +97,8 @@ func TestDumps(t *testing.T) { dump2, err := models.CreateDump(findTX.Querier, models.CreateDumpParams{ ServiceNames: []string{"foo", "bar"}, - StartTime: time.Now(), - EndTime: time.Now().Add(10 * time.Minute), + StartTime: &startTime, + EndTime: &endTime, ExportQAN: false, IgnoreLoad: true, }) @@ -87,8 +109,8 @@ func TestDumps(t *testing.T) { dump3, err := models.CreateDump(findTX.Querier, models.CreateDumpParams{ ServiceNames: []string{"foo", "bar"}, - StartTime: time.Now(), - EndTime: time.Now().Add(10 * time.Minute), + StartTime: &startTime, + EndTime: &endTime, ExportQAN: false, IgnoreLoad: true, }) diff --git a/managed/models/dump_reform.go b/managed/models/dump_reform.go index d62d7411ec3..a78ca52e9a6 100644 --- a/managed/models/dump_reform.go +++ b/managed/models/dump_reform.go @@ -64,8 +64,8 @@ var DumpTable = &dumpTableType{ {Name: "ID", Type: "string", Column: "id"}, {Name: "Status", Type: "DumpStatus", Column: "status"}, {Name: "ServiceNames", Type: "pq.StringArray", Column: "service_names"}, - {Name: "StartTime", Type: "time.Time", Column: "start_time"}, - {Name: "EndTime", Type: "time.Time", Column: "end_time"}, + {Name: "StartTime", Type: "*time.Time", Column: "start_time"}, + {Name: "EndTime", Type: "*time.Time", Column: "end_time"}, {Name: "ExportQAN", Type: "bool", Column: "export_qan"}, {Name: "IgnoreLoad", Type: "bool", Column: "ignore_load"}, {Name: "CreatedAt", Type: "time.Time", Column: "created_at"}, diff --git a/managed/services/dump/dump.go b/managed/services/dump/dump.go index a3b6137a7cd..a0bb194da84 100644 --- a/managed/services/dump/dump.go +++ b/managed/services/dump/dump.go @@ -68,8 +68,8 @@ type Params struct { User string Password string ServiceNames []string - StartTime time.Time - EndTime time.Time + StartTime *time.Time + EndTime *time.Time ExportQAN bool IgnoreLoad bool } @@ -123,11 +123,11 @@ func (s *Service) StartDump(params *Params) (string, error) { pmmDumpCmd.Args = append(pmmDumpCmd.Args, fmt.Sprintf("--instance=%s", serviceName)) } - if !params.StartTime.IsZero() { + if params.StartTime != nil { pmmDumpCmd.Args = append(pmmDumpCmd.Args, fmt.Sprintf("--start-ts=%s", params.StartTime.Format(time.RFC3339))) } - if !params.EndTime.IsZero() { + if params.EndTime != nil { pmmDumpCmd.Args = append(pmmDumpCmd.Args, fmt.Sprintf("--end-ts=%s", params.EndTime.Format(time.RFC3339))) } diff --git a/managed/services/management/dump/dump.go b/managed/services/management/dump/dump.go index 9a64d337abb..503a0cef2b2 100644 --- a/managed/services/management/dump/dump.go +++ b/managed/services/management/dump/dump.go @@ -114,11 +114,19 @@ func (s *Service) StartDump(ctx context.Context, req *dumpv1beta1.StartDumpReque } if req.StartTime != nil { - params.StartTime = req.StartTime.AsTime() + startTime := req.StartTime.AsTime() + params.StartTime = &startTime } if req.EndTime != nil { - params.EndTime = req.EndTime.AsTime() + endTime := req.EndTime.AsTime() + params.EndTime = &endTime + } + + if params.StartTime != nil && params.EndTime != nil { + if params.StartTime.After(*params.EndTime) { + return nil, status.Error(codes.InvalidArgument, "Dump start time can't be greater enc time") + } } dumpID, err := s.dumpService.StartDump(params) @@ -262,14 +270,22 @@ func convertDump(dump *models.Dump) (*dumpv1beta1.Dump, error) { return nil, errors.Wrap(err, "failed to convert dump ds") } - return &dumpv1beta1.Dump{ + d := &dumpv1beta1.Dump{ DumpId: dump.ID, Status: ds, ServiceNames: dump.ServiceNames, - StartTime: timestamppb.New(dump.StartTime), - EndTime: timestamppb.New(dump.EndTime), CreatedAt: timestamppb.New(dump.CreatedAt), - }, nil + } + + if dump.StartTime != nil { + d.StartTime = timestamppb.New(*dump.StartTime) + } + + if dump.EndTime != nil { + d.EndTime = timestamppb.New(*dump.EndTime) + } + + return d, nil } func convertDumpStatus(status models.DumpStatus) (dumpv1beta1.DumpStatus, error) {