2019-04-09 22:52:54 +00:00
|
|
|
package kv_test
|
|
|
|
|
|
|
|
import (
|
2019-08-23 22:52:55 +00:00
|
|
|
"bytes"
|
2019-04-09 22:52:54 +00:00
|
|
|
"context"
|
2019-08-23 22:52:55 +00:00
|
|
|
"encoding/json"
|
2019-04-09 22:52:54 +00:00
|
|
|
"testing"
|
2019-08-15 21:28:35 +00:00
|
|
|
"time"
|
2019-04-09 22:52:54 +00:00
|
|
|
|
2019-12-06 03:55:26 +00:00
|
|
|
"github.com/benbjohnson/clock"
|
|
|
|
"github.com/google/go-cmp/cmp"
|
2020-04-03 17:39:20 +00:00
|
|
|
"github.com/influxdata/influxdb/v2"
|
2020-08-03 15:33:46 +00:00
|
|
|
"github.com/influxdata/influxdb/v2/authorization"
|
2020-04-03 17:39:20 +00:00
|
|
|
icontext "github.com/influxdata/influxdb/v2/context"
|
2020-11-06 00:54:28 +00:00
|
|
|
_ "github.com/influxdata/influxdb/v2/fluxinit/static"
|
2021-03-08 14:51:21 +00:00
|
|
|
"github.com/influxdata/influxdb/v2/kv"
|
2020-04-06 17:17:47 +00:00
|
|
|
"github.com/influxdata/influxdb/v2/query/fluxlang"
|
2020-06-23 16:22:53 +00:00
|
|
|
"github.com/influxdata/influxdb/v2/task/options"
|
2020-04-03 17:39:20 +00:00
|
|
|
"github.com/influxdata/influxdb/v2/task/servicetest"
|
2020-08-03 15:33:46 +00:00
|
|
|
"github.com/influxdata/influxdb/v2/tenant"
|
2020-06-23 16:22:53 +00:00
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
"github.com/stretchr/testify/require"
|
2019-12-04 23:10:23 +00:00
|
|
|
"go.uber.org/zap/zaptest"
|
2019-04-09 22:52:54 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
func TestBoltTaskService(t *testing.T) {
|
|
|
|
servicetest.TestTaskService(
|
|
|
|
t,
|
|
|
|
func(t *testing.T) (*servicetest.System, context.CancelFunc) {
|
2019-12-04 23:10:23 +00:00
|
|
|
store, close, err := NewTestBoltStore(t)
|
2019-04-09 22:52:54 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2020-08-03 15:33:46 +00:00
|
|
|
tenantStore := tenant.NewStore(store)
|
|
|
|
ts := tenant.NewService(tenantStore)
|
|
|
|
|
|
|
|
authStore, err := authorization.NewStore(store)
|
|
|
|
require.NoError(t, err)
|
|
|
|
authSvc := authorization.NewService(authStore, ts)
|
|
|
|
|
refactor(kv): delete deprecated kv service code
This includes removal of a lot of kv.Service responsibilities. However,
it does not finish the re-wiring. It removes documents, telegrafs,
notification rules + endpoints, checks, orgs, users, buckets, passwords,
urms, labels and authorizations. There are some oustanding pieces that
are needed to get kv service compiling (dashboard service urm
dependency). Then all the call sites for kv service need updating and
the new implementations of telegraf and notification rules + endpoints
needed installing (along with any necessary migrations).
2020-10-20 13:25:36 +00:00
|
|
|
ctx, cancelFunc := context.WithCancel(context.Background())
|
|
|
|
service := kv.NewService(zaptest.NewLogger(t), store, ts, kv.ServiceConfig{
|
|
|
|
FluxLanguageService: fluxlang.DefaultService,
|
|
|
|
})
|
|
|
|
|
2019-04-09 22:52:54 +00:00
|
|
|
go func() {
|
|
|
|
<-ctx.Done()
|
|
|
|
close()
|
|
|
|
}()
|
|
|
|
|
|
|
|
return &servicetest.System{
|
2020-08-03 15:33:46 +00:00
|
|
|
TaskControlService: service,
|
|
|
|
TaskService: service,
|
|
|
|
OrganizationService: ts.OrganizationService,
|
|
|
|
UserService: ts.UserService,
|
|
|
|
UserResourceMappingService: ts.UserResourceMappingService,
|
|
|
|
AuthorizationService: authSvc,
|
|
|
|
Ctx: ctx,
|
2019-04-09 22:52:54 +00:00
|
|
|
}, cancelFunc
|
|
|
|
},
|
|
|
|
"transactional",
|
|
|
|
)
|
|
|
|
}
|
2019-08-15 21:28:35 +00:00
|
|
|
|
2019-12-06 03:55:26 +00:00
|
|
|
type testService struct {
|
|
|
|
Store kv.Store
|
|
|
|
Service *kv.Service
|
|
|
|
Org influxdb.Organization
|
|
|
|
User influxdb.User
|
|
|
|
Auth influxdb.Authorization
|
|
|
|
Clock clock.Clock
|
|
|
|
|
|
|
|
storeCloseFn func()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *testService) Close() {
|
|
|
|
s.storeCloseFn()
|
|
|
|
}
|
|
|
|
|
|
|
|
func newService(t *testing.T, ctx context.Context, c clock.Clock) *testService {
|
|
|
|
t.Helper()
|
|
|
|
|
|
|
|
if c == nil {
|
|
|
|
c = clock.New()
|
|
|
|
}
|
|
|
|
|
2020-07-01 11:08:20 +00:00
|
|
|
var (
|
|
|
|
ts = &testService{}
|
|
|
|
err error
|
|
|
|
store kv.SchemaStore
|
|
|
|
)
|
|
|
|
|
|
|
|
store, ts.storeCloseFn, err = NewTestInmemStore(t)
|
2019-08-23 22:52:55 +00:00
|
|
|
if err != nil {
|
2019-12-06 03:55:26 +00:00
|
|
|
t.Fatal("failed to create InmemStore", err)
|
2019-08-23 22:52:55 +00:00
|
|
|
}
|
|
|
|
|
2020-07-01 11:08:20 +00:00
|
|
|
ts.Store = store
|
|
|
|
|
refactor(kv): delete deprecated kv service code
This includes removal of a lot of kv.Service responsibilities. However,
it does not finish the re-wiring. It removes documents, telegrafs,
notification rules + endpoints, checks, orgs, users, buckets, passwords,
urms, labels and authorizations. There are some oustanding pieces that
are needed to get kv service compiling (dashboard service urm
dependency). Then all the call sites for kv service need updating and
the new implementations of telegraf and notification rules + endpoints
needed installing (along with any necessary migrations).
2020-10-20 13:25:36 +00:00
|
|
|
tenantStore := tenant.NewStore(store)
|
|
|
|
tenantSvc := tenant.NewService(tenantStore)
|
|
|
|
|
|
|
|
authStore, err := authorization.NewStore(store)
|
|
|
|
require.NoError(t, err)
|
|
|
|
authSvc := authorization.NewService(authStore, tenantSvc)
|
|
|
|
|
|
|
|
ts.Service = kv.NewService(zaptest.NewLogger(t), store, tenantSvc, kv.ServiceConfig{
|
2020-03-05 20:36:58 +00:00
|
|
|
Clock: c,
|
|
|
|
FluxLanguageService: fluxlang.DefaultService,
|
|
|
|
})
|
2019-12-06 03:55:26 +00:00
|
|
|
|
|
|
|
ts.User = influxdb.User{Name: t.Name() + "-user"}
|
refactor(kv): delete deprecated kv service code
This includes removal of a lot of kv.Service responsibilities. However,
it does not finish the re-wiring. It removes documents, telegrafs,
notification rules + endpoints, checks, orgs, users, buckets, passwords,
urms, labels and authorizations. There are some oustanding pieces that
are needed to get kv service compiling (dashboard service urm
dependency). Then all the call sites for kv service need updating and
the new implementations of telegraf and notification rules + endpoints
needed installing (along with any necessary migrations).
2020-10-20 13:25:36 +00:00
|
|
|
if err := tenantSvc.CreateUser(ctx, &ts.User); err != nil {
|
2019-08-23 22:52:55 +00:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2019-12-06 03:55:26 +00:00
|
|
|
ts.Org = influxdb.Organization{Name: t.Name() + "-org"}
|
refactor(kv): delete deprecated kv service code
This includes removal of a lot of kv.Service responsibilities. However,
it does not finish the re-wiring. It removes documents, telegrafs,
notification rules + endpoints, checks, orgs, users, buckets, passwords,
urms, labels and authorizations. There are some oustanding pieces that
are needed to get kv service compiling (dashboard service urm
dependency). Then all the call sites for kv service need updating and
the new implementations of telegraf and notification rules + endpoints
needed installing (along with any necessary migrations).
2020-10-20 13:25:36 +00:00
|
|
|
if err := tenantSvc.CreateOrganization(ctx, &ts.Org); err != nil {
|
2019-08-23 22:52:55 +00:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
refactor(kv): delete deprecated kv service code
This includes removal of a lot of kv.Service responsibilities. However,
it does not finish the re-wiring. It removes documents, telegrafs,
notification rules + endpoints, checks, orgs, users, buckets, passwords,
urms, labels and authorizations. There are some oustanding pieces that
are needed to get kv service compiling (dashboard service urm
dependency). Then all the call sites for kv service need updating and
the new implementations of telegraf and notification rules + endpoints
needed installing (along with any necessary migrations).
2020-10-20 13:25:36 +00:00
|
|
|
if err := tenantSvc.CreateUserResourceMapping(ctx, &influxdb.UserResourceMapping{
|
2019-08-23 22:52:55 +00:00
|
|
|
ResourceType: influxdb.OrgsResourceType,
|
2019-12-06 03:55:26 +00:00
|
|
|
ResourceID: ts.Org.ID,
|
|
|
|
UserID: ts.User.ID,
|
2019-08-23 22:52:55 +00:00
|
|
|
UserType: influxdb.Owner,
|
|
|
|
}); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2019-12-06 03:55:26 +00:00
|
|
|
ts.Auth = influxdb.Authorization{
|
|
|
|
OrgID: ts.Org.ID,
|
|
|
|
UserID: ts.User.ID,
|
2019-08-23 22:52:55 +00:00
|
|
|
Permissions: influxdb.OperPermissions(),
|
|
|
|
}
|
refactor(kv): delete deprecated kv service code
This includes removal of a lot of kv.Service responsibilities. However,
it does not finish the re-wiring. It removes documents, telegrafs,
notification rules + endpoints, checks, orgs, users, buckets, passwords,
urms, labels and authorizations. There are some oustanding pieces that
are needed to get kv service compiling (dashboard service urm
dependency). Then all the call sites for kv service need updating and
the new implementations of telegraf and notification rules + endpoints
needed installing (along with any necessary migrations).
2020-10-20 13:25:36 +00:00
|
|
|
if err := authSvc.CreateAuthorization(context.Background(), &ts.Auth); err != nil {
|
2019-08-23 22:52:55 +00:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2019-12-06 03:55:26 +00:00
|
|
|
return ts
|
|
|
|
}
|
2019-08-23 22:52:55 +00:00
|
|
|
|
2019-12-06 03:55:26 +00:00
|
|
|
func TestRetrieveTaskWithBadAuth(t *testing.T) {
|
|
|
|
ctx, cancelFunc := context.WithCancel(context.Background())
|
|
|
|
defer cancelFunc()
|
|
|
|
|
|
|
|
ts := newService(t, ctx, nil)
|
|
|
|
defer ts.Close()
|
|
|
|
|
|
|
|
ctx = icontext.SetAuthorizer(ctx, &ts.Auth)
|
|
|
|
|
|
|
|
task, err := ts.Service.CreateTask(ctx, influxdb.TaskCreate{
|
2019-08-23 22:52:55 +00:00
|
|
|
Flux: `option task = {name: "a task",every: 1h} from(bucket:"test") |> range(start:-1h)`,
|
2019-12-06 03:55:26 +00:00
|
|
|
OrganizationID: ts.Org.ID,
|
|
|
|
OwnerID: ts.User.ID,
|
2020-03-06 22:19:32 +00:00
|
|
|
Status: string(influxdb.TaskActive),
|
2019-08-23 22:52:55 +00:00
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// convert task to old one with a bad auth
|
2019-12-06 03:55:26 +00:00
|
|
|
err = ts.Store.Update(ctx, func(tx kv.Tx) error {
|
2019-08-23 22:52:55 +00:00
|
|
|
b, err := tx.Bucket([]byte("tasksv1"))
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
bID, err := task.ID.Encode()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
task.OwnerID = influxdb.ID(1)
|
|
|
|
tbyte, err := json.Marshal(task)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
// have to actually hack the bytes here because the system doesnt like us to encode bad id's.
|
|
|
|
tbyte = bytes.Replace(tbyte, []byte(`,"ownerID":"0000000000000001"`), []byte{}, 1)
|
|
|
|
if err := b.Put(bID, tbyte); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// lets see if we can list and find the task
|
2019-12-06 03:55:26 +00:00
|
|
|
newTask, err := ts.Service.FindTaskByID(ctx, task.ID)
|
2019-08-23 22:52:55 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if newTask.ID != task.ID {
|
|
|
|
t.Fatal("miss matching taskID's")
|
|
|
|
}
|
|
|
|
|
2020-06-17 14:20:05 +00:00
|
|
|
tasks, _, err := ts.Service.FindTasks(context.Background(), influxdb.TaskFilter{})
|
2019-08-23 22:52:55 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if len(tasks) != 1 {
|
|
|
|
t.Fatal("failed to return task")
|
|
|
|
}
|
2019-12-02 22:16:10 +00:00
|
|
|
|
|
|
|
// test status filter
|
2020-03-06 22:19:32 +00:00
|
|
|
active := string(influxdb.TaskActive)
|
2020-06-17 14:20:05 +00:00
|
|
|
tasksWithActiveFilter, _, err := ts.Service.FindTasks(context.Background(), influxdb.TaskFilter{Status: &active})
|
2019-12-02 22:16:10 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal("could not find tasks")
|
|
|
|
}
|
|
|
|
if len(tasksWithActiveFilter) != 1 {
|
|
|
|
t.Fatal("failed to find active task with filter")
|
|
|
|
}
|
2019-08-23 22:52:55 +00:00
|
|
|
}
|
2019-12-06 03:55:26 +00:00
|
|
|
|
|
|
|
func TestService_UpdateTask_InactiveToActive(t *testing.T) {
|
|
|
|
ctx, cancelFunc := context.WithCancel(context.Background())
|
|
|
|
defer cancelFunc()
|
|
|
|
|
|
|
|
c := clock.NewMock()
|
|
|
|
c.Set(time.Unix(1000, 0))
|
|
|
|
|
|
|
|
ts := newService(t, ctx, c)
|
|
|
|
defer ts.Close()
|
|
|
|
|
|
|
|
ctx = icontext.SetAuthorizer(ctx, &ts.Auth)
|
|
|
|
|
|
|
|
originalTask, err := ts.Service.CreateTask(ctx, influxdb.TaskCreate{
|
|
|
|
Flux: `option task = {name: "a task",every: 1h} from(bucket:"test") |> range(start:-1h)`,
|
|
|
|
OrganizationID: ts.Org.ID,
|
|
|
|
OwnerID: ts.User.ID,
|
2020-03-06 22:19:32 +00:00
|
|
|
Status: string(influxdb.TaskActive),
|
2019-12-06 03:55:26 +00:00
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal("CreateTask", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
v := influxdb.TaskStatusInactive
|
|
|
|
c.Add(1 * time.Second)
|
|
|
|
exp := c.Now()
|
|
|
|
updatedTask, err := ts.Service.UpdateTask(ctx, originalTask.ID, influxdb.TaskUpdate{Status: &v, LatestCompleted: &exp, LatestScheduled: &exp})
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal("UpdateTask", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if got := updatedTask.LatestScheduled; !got.Equal(exp) {
|
|
|
|
t.Fatalf("unexpected -got/+exp\n%s", cmp.Diff(got.String(), exp.String()))
|
|
|
|
}
|
|
|
|
if got := updatedTask.LatestCompleted; !got.Equal(exp) {
|
|
|
|
t.Fatalf("unexpected -got/+exp\n%s", cmp.Diff(got.String(), exp.String()))
|
|
|
|
}
|
|
|
|
|
|
|
|
c.Add(10 * time.Second)
|
|
|
|
exp = c.Now()
|
|
|
|
v = influxdb.TaskStatusActive
|
|
|
|
updatedTask, err = ts.Service.UpdateTask(ctx, originalTask.ID, influxdb.TaskUpdate{Status: &v})
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal("UpdateTask", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if got := updatedTask.LatestScheduled; !got.Equal(exp) {
|
|
|
|
t.Fatalf("unexpected -got/+exp\n%s", cmp.Diff(got.String(), exp.String()))
|
|
|
|
}
|
|
|
|
}
|
2019-12-17 04:08:24 +00:00
|
|
|
|
|
|
|
func TestTaskRunCancellation(t *testing.T) {
|
|
|
|
store, close, err := NewTestBoltStore(t)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
defer close()
|
|
|
|
|
2020-07-01 11:08:20 +00:00
|
|
|
ctx, cancelFunc := context.WithCancel(context.Background())
|
|
|
|
defer cancelFunc()
|
|
|
|
|
refactor(kv): delete deprecated kv service code
This includes removal of a lot of kv.Service responsibilities. However,
it does not finish the re-wiring. It removes documents, telegrafs,
notification rules + endpoints, checks, orgs, users, buckets, passwords,
urms, labels and authorizations. There are some oustanding pieces that
are needed to get kv service compiling (dashboard service urm
dependency). Then all the call sites for kv service need updating and
the new implementations of telegraf and notification rules + endpoints
needed installing (along with any necessary migrations).
2020-10-20 13:25:36 +00:00
|
|
|
tenantStore := tenant.NewStore(store)
|
|
|
|
tenantSvc := tenant.NewService(tenantStore)
|
|
|
|
|
|
|
|
authStore, err := authorization.NewStore(store)
|
|
|
|
require.NoError(t, err)
|
|
|
|
authSvc := authorization.NewService(authStore, tenantSvc)
|
|
|
|
|
|
|
|
service := kv.NewService(zaptest.NewLogger(t), store, tenantSvc, kv.ServiceConfig{
|
2020-03-05 20:36:58 +00:00
|
|
|
FluxLanguageService: fluxlang.DefaultService,
|
|
|
|
})
|
2020-07-01 11:08:20 +00:00
|
|
|
|
2019-12-17 04:08:24 +00:00
|
|
|
u := &influxdb.User{Name: t.Name() + "-user"}
|
refactor(kv): delete deprecated kv service code
This includes removal of a lot of kv.Service responsibilities. However,
it does not finish the re-wiring. It removes documents, telegrafs,
notification rules + endpoints, checks, orgs, users, buckets, passwords,
urms, labels and authorizations. There are some oustanding pieces that
are needed to get kv service compiling (dashboard service urm
dependency). Then all the call sites for kv service need updating and
the new implementations of telegraf and notification rules + endpoints
needed installing (along with any necessary migrations).
2020-10-20 13:25:36 +00:00
|
|
|
if err := tenantSvc.CreateUser(ctx, u); err != nil {
|
2019-12-17 04:08:24 +00:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
o := &influxdb.Organization{Name: t.Name() + "-org"}
|
refactor(kv): delete deprecated kv service code
This includes removal of a lot of kv.Service responsibilities. However,
it does not finish the re-wiring. It removes documents, telegrafs,
notification rules + endpoints, checks, orgs, users, buckets, passwords,
urms, labels and authorizations. There are some oustanding pieces that
are needed to get kv service compiling (dashboard service urm
dependency). Then all the call sites for kv service need updating and
the new implementations of telegraf and notification rules + endpoints
needed installing (along with any necessary migrations).
2020-10-20 13:25:36 +00:00
|
|
|
if err := tenantSvc.CreateOrganization(ctx, o); err != nil {
|
2019-12-17 04:08:24 +00:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
refactor(kv): delete deprecated kv service code
This includes removal of a lot of kv.Service responsibilities. However,
it does not finish the re-wiring. It removes documents, telegrafs,
notification rules + endpoints, checks, orgs, users, buckets, passwords,
urms, labels and authorizations. There are some oustanding pieces that
are needed to get kv service compiling (dashboard service urm
dependency). Then all the call sites for kv service need updating and
the new implementations of telegraf and notification rules + endpoints
needed installing (along with any necessary migrations).
2020-10-20 13:25:36 +00:00
|
|
|
if err := tenantSvc.CreateUserResourceMapping(ctx, &influxdb.UserResourceMapping{
|
2019-12-17 04:08:24 +00:00
|
|
|
ResourceType: influxdb.OrgsResourceType,
|
|
|
|
ResourceID: o.ID,
|
|
|
|
UserID: u.ID,
|
|
|
|
UserType: influxdb.Owner,
|
|
|
|
}); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
authz := influxdb.Authorization{
|
|
|
|
OrgID: o.ID,
|
|
|
|
UserID: u.ID,
|
|
|
|
Permissions: influxdb.OperPermissions(),
|
|
|
|
}
|
refactor(kv): delete deprecated kv service code
This includes removal of a lot of kv.Service responsibilities. However,
it does not finish the re-wiring. It removes documents, telegrafs,
notification rules + endpoints, checks, orgs, users, buckets, passwords,
urms, labels and authorizations. There are some oustanding pieces that
are needed to get kv service compiling (dashboard service urm
dependency). Then all the call sites for kv service need updating and
the new implementations of telegraf and notification rules + endpoints
needed installing (along with any necessary migrations).
2020-10-20 13:25:36 +00:00
|
|
|
if err := authSvc.CreateAuthorization(context.Background(), &authz); err != nil {
|
2019-12-17 04:08:24 +00:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
ctx = icontext.SetAuthorizer(ctx, &authz)
|
|
|
|
|
|
|
|
task, err := service.CreateTask(ctx, influxdb.TaskCreate{
|
|
|
|
Flux: `option task = {name: "a task",cron: "0 * * * *", offset: 20s} from(bucket:"test") |> range(start:-1h)`,
|
|
|
|
OrganizationID: o.ID,
|
|
|
|
OwnerID: u.ID,
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2020-01-02 19:41:21 +00:00
|
|
|
run, err := service.CreateRun(ctx, task.ID, time.Now().Add(time.Hour), time.Now().Add(time.Hour))
|
2019-12-17 04:08:24 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2020-01-02 19:41:21 +00:00
|
|
|
if err := service.CancelRun(ctx, run.TaskID, run.ID); err != nil {
|
2019-12-17 04:08:24 +00:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2020-01-02 19:41:21 +00:00
|
|
|
canceled, err := service.FindRunByID(ctx, run.TaskID, run.ID)
|
2019-12-17 04:08:24 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2020-03-06 22:19:32 +00:00
|
|
|
if canceled.Status != influxdb.RunCanceled.String() {
|
2019-12-17 04:08:24 +00:00
|
|
|
t.Fatalf("expected task run to be cancelled")
|
|
|
|
}
|
|
|
|
}
|
2020-06-17 18:30:37 +00:00
|
|
|
|
2020-08-25 14:44:37 +00:00
|
|
|
func TestService_UpdateTask_RecordLatestSuccessAndFailure(t *testing.T) {
|
|
|
|
ctx, cancelFunc := context.WithCancel(context.Background())
|
|
|
|
defer cancelFunc()
|
|
|
|
|
|
|
|
c := clock.NewMock()
|
|
|
|
c.Set(time.Unix(1000, 0))
|
|
|
|
|
|
|
|
ts := newService(t, ctx, c)
|
|
|
|
defer ts.Close()
|
|
|
|
|
|
|
|
ctx = icontext.SetAuthorizer(ctx, &ts.Auth)
|
|
|
|
|
|
|
|
originalTask, err := ts.Service.CreateTask(ctx, influxdb.TaskCreate{
|
|
|
|
Flux: `option task = {name: "a task",every: 1h} from(bucket:"test") |> range(start:-1h)`,
|
|
|
|
OrganizationID: ts.Org.ID,
|
|
|
|
OwnerID: ts.User.ID,
|
|
|
|
Status: string(influxdb.TaskActive),
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal("CreateTask", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
c.Add(1 * time.Second)
|
|
|
|
exp := c.Now()
|
|
|
|
updatedTask, err := ts.Service.UpdateTask(ctx, originalTask.ID, influxdb.TaskUpdate{
|
|
|
|
LatestCompleted: &exp,
|
|
|
|
LatestScheduled: &exp,
|
|
|
|
|
|
|
|
// These would be updated in a mutually exclusive manner, but we'll set
|
|
|
|
// them both to demonstrate that they do change.
|
|
|
|
LatestSuccess: &exp,
|
|
|
|
LatestFailure: &exp,
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal("UpdateTask", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if got := updatedTask.LatestScheduled; !got.Equal(exp) {
|
|
|
|
t.Fatalf("unexpected -got/+exp\n%s", cmp.Diff(got.String(), exp.String()))
|
|
|
|
}
|
|
|
|
if got := updatedTask.LatestCompleted; !got.Equal(exp) {
|
|
|
|
t.Fatalf("unexpected -got/+exp\n%s", cmp.Diff(got.String(), exp.String()))
|
|
|
|
}
|
|
|
|
if got := updatedTask.LatestSuccess; !got.Equal(exp) {
|
|
|
|
t.Fatalf("unexpected -got/+exp\n%s", cmp.Diff(got.String(), exp.String()))
|
|
|
|
}
|
|
|
|
if got := updatedTask.LatestFailure; !got.Equal(exp) {
|
|
|
|
t.Fatalf("unexpected -got/+exp\n%s", cmp.Diff(got.String(), exp.String()))
|
|
|
|
}
|
|
|
|
|
|
|
|
c.Add(5 * time.Second)
|
|
|
|
exp = c.Now()
|
|
|
|
updatedTask, err = ts.Service.UpdateTask(ctx, originalTask.ID, influxdb.TaskUpdate{
|
|
|
|
LatestCompleted: &exp,
|
|
|
|
LatestScheduled: &exp,
|
|
|
|
|
|
|
|
// These would be updated in a mutually exclusive manner, but we'll set
|
|
|
|
// them both to demonstrate that they do change.
|
|
|
|
LatestSuccess: &exp,
|
|
|
|
LatestFailure: &exp,
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal("UpdateTask", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if got := updatedTask.LatestScheduled; !got.Equal(exp) {
|
|
|
|
t.Fatalf("unexpected -got/+exp\n%s", cmp.Diff(got.String(), exp.String()))
|
|
|
|
}
|
|
|
|
if got := updatedTask.LatestCompleted; !got.Equal(exp) {
|
|
|
|
t.Fatalf("unexpected -got/+exp\n%s", cmp.Diff(got.String(), exp.String()))
|
|
|
|
}
|
|
|
|
if got := updatedTask.LatestSuccess; !got.Equal(exp) {
|
|
|
|
t.Fatalf("unexpected -got/+exp\n%s", cmp.Diff(got.String(), exp.String()))
|
|
|
|
}
|
|
|
|
if got := updatedTask.LatestFailure; !got.Equal(exp) {
|
|
|
|
t.Fatalf("unexpected -got/+exp\n%s", cmp.Diff(got.String(), exp.String()))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-23 16:22:53 +00:00
|
|
|
type taskOptions struct {
|
|
|
|
name string
|
|
|
|
every string
|
|
|
|
cron string
|
|
|
|
offset string
|
|
|
|
concurrency int64
|
|
|
|
retry int64
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestExtractTaskOptions(t *testing.T) {
|
|
|
|
tcs := []struct {
|
|
|
|
name string
|
|
|
|
flux string
|
|
|
|
expected taskOptions
|
|
|
|
errMsg string
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
name: "all parameters",
|
|
|
|
flux: `option task = {name: "whatever", every: 1s, offset: 0s, concurrency: 2, retry: 2}`,
|
|
|
|
expected: taskOptions{
|
|
|
|
name: "whatever",
|
|
|
|
every: "1s",
|
|
|
|
offset: "0s",
|
|
|
|
concurrency: 2,
|
|
|
|
retry: 2,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "some extra whitespace and bad content around it",
|
|
|
|
flux: `howdy()
|
|
|
|
option task = { name:"whatever", cron: "* * * * *" }
|
|
|
|
hello()
|
|
|
|
`,
|
|
|
|
expected: taskOptions{
|
|
|
|
name: "whatever",
|
|
|
|
cron: "* * * * *",
|
|
|
|
concurrency: 1,
|
|
|
|
retry: 1,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "bad options",
|
|
|
|
flux: `option task = {name: "whatever", every: 1s, cron: "* * * * *"}`,
|
|
|
|
errMsg: "cannot use both cron and every in task options",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "no options",
|
|
|
|
flux: `doesntexist()`,
|
|
|
|
errMsg: "no task options defined",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "multiple assignments",
|
|
|
|
flux: `
|
|
|
|
option task = {name: "whatever", every: 1s, offset: 0s, concurrency: 2, retry: 2}
|
|
|
|
option task = {name: "whatever", every: 1s, offset: 0s, concurrency: 2, retry: 2}
|
|
|
|
`,
|
|
|
|
errMsg: "multiple task options defined",
|
|
|
|
},
|
2021-03-08 14:51:21 +00:00
|
|
|
{
|
|
|
|
name: "with script calling tableFind",
|
|
|
|
flux: `
|
|
|
|
import "http"
|
|
|
|
import "json"
|
|
|
|
option task = {name: "Slack Metrics to #Community", cron: "0 9 * * 5"}
|
|
|
|
all_slack_messages = from(bucket: "metrics")
|
|
|
|
|> range(start: -7d, stop: now())
|
|
|
|
|> filter(fn: (r) =>
|
|
|
|
(r._measurement == "slack_channel_message"))
|
|
|
|
total_messages = all_slack_messages
|
|
|
|
|> group()
|
|
|
|
|> count()
|
|
|
|
|> tableFind(fn: (key) => true)
|
|
|
|
all_slack_messages |> yield()
|
|
|
|
`,
|
|
|
|
expected: taskOptions{
|
|
|
|
name: "Slack Metrics to #Community",
|
|
|
|
cron: "0 9 * * 5",
|
|
|
|
concurrency: 1,
|
|
|
|
retry: 1,
|
|
|
|
},
|
|
|
|
},
|
2020-06-23 16:22:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for _, tc := range tcs {
|
|
|
|
t.Run(tc.name, func(t *testing.T) {
|
2021-03-08 14:51:21 +00:00
|
|
|
|
|
|
|
opts, err := options.FromScriptAST(fluxlang.DefaultService, tc.flux)
|
2020-06-23 16:22:53 +00:00
|
|
|
if tc.errMsg != "" {
|
|
|
|
require.Error(t, err)
|
|
|
|
assert.Equal(t, tc.errMsg, err.Error())
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
var offset options.Duration
|
|
|
|
if opts.Offset != nil {
|
|
|
|
offset = *opts.Offset
|
|
|
|
}
|
|
|
|
|
|
|
|
var concur int64
|
|
|
|
if opts.Concurrency != nil {
|
|
|
|
concur = *opts.Concurrency
|
|
|
|
}
|
|
|
|
|
|
|
|
var retry int64
|
|
|
|
if opts.Retry != nil {
|
|
|
|
retry = *opts.Retry
|
|
|
|
}
|
|
|
|
|
|
|
|
assert.Equal(t, tc.expected.name, opts.Name)
|
|
|
|
assert.Equal(t, tc.expected.cron, opts.Cron)
|
|
|
|
assert.Equal(t, tc.expected.every, opts.Every.String())
|
|
|
|
assert.Equal(t, tc.expected.offset, offset.String())
|
|
|
|
assert.Equal(t, tc.expected.concurrency, concur)
|
|
|
|
assert.Equal(t, tc.expected.retry, retry)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|