From 669c464335ca782512da7fbf38231fbdde7a7f2f Mon Sep 17 00:00:00 2001 From: "docmerlin (j. Emrys Landivar)" Date: Wed, 20 Feb 2019 11:04:46 -0600 Subject: [PATCH] feat(tasks): look up tasks by orgname --- http/swagger.yml | 5 ++ http/task_service.go | 27 +++++-- http/task_service_test.go | 143 ++++++++++++++++++++++++++++++++++++-- task_test.go | 16 +++++ 4 files changed, 181 insertions(+), 10 deletions(-) diff --git a/http/swagger.yml b/http/swagger.yml index 08f133b9fa..bf1a84e3f6 100644 --- a/http/swagger.yml +++ b/http/swagger.yml @@ -3788,6 +3788,11 @@ paths: description: filter tasks to a specific user ID - in: query name: org + schema: + type: string + description: filter tasks to a specific organization name + - in: query + name: orgID schema: type: string description: filter tasks to a specific organization ID diff --git a/http/task_service.go b/http/task_service.go index c3f419e977..cd923eec0f 100644 --- a/http/task_service.go +++ b/http/task_service.go @@ -17,6 +17,7 @@ import ( platform "github.com/influxdata/influxdb" "github.com/influxdata/influxdb/authorizer" pcontext "github.com/influxdata/influxdb/context" + "github.com/influxdata/influxdb/kv" "github.com/influxdata/influxdb/query" "github.com/influxdata/influxdb/task/backend" "github.com/influxdata/influxdb/task/options" @@ -259,7 +260,7 @@ func newRunsResponse(rs []*platform.Run, taskID platform.ID) runsResponse { func (h *TaskHandler) handleGetTasks(w http.ResponseWriter, r *http.Request) { ctx := r.Context() - req, err := decodeGetTasksRequest(ctx, r) + req, err := decodeGetTasksRequest(ctx, r, h.OrganizationService) if err != nil { err = &platform.Error{ Err: err, @@ -323,7 +324,7 @@ type getTasksRequest struct { filter platform.TaskFilter } -func decodeGetTasksRequest(ctx context.Context, r *http.Request) (*getTasksRequest, error) { +func decodeGetTasksRequest(ctx context.Context, r *http.Request, orgs platform.OrganizationService) (*getTasksRequest, error) { qp := r.URL.Query() req := &getTasksRequest{} @@ -335,12 +336,26 @@ func decodeGetTasksRequest(ctx context.Context, r *http.Request) (*getTasksReque req.filter.After = id } - if orgID := qp.Get("organization"); orgID != "" { - id, err := platform.IDFromString(orgID) + if orgName := qp.Get("org"); orgName != "" { + o, err := orgs.FindOrganization(ctx, platform.OrganizationFilter{Name: &orgName}) + if err != nil { + if pErr, ok := err.(*platform.Error); ok && pErr != nil { + if kv.IsNotFound(err) || pErr.Code == platform.EUnauthorized { + return nil, &platform.Error{ + Err: errors.New("org not found or unauthorized"), + Msg: "org " + orgName + " not found or unauthorized", + } + } + } + return nil, err + } + req.filter.Organization = &o.ID + } else if oid := qp.Get("orgID"); oid != "" { + orgID, err := platform.IDFromString(oid) if err != nil { return nil, err } - req.filter.Organization = id + req.filter.Organization = orgID } if userID := qp.Get("user"); userID != "" { @@ -1409,7 +1424,7 @@ func (t TaskService) FindTasks(ctx context.Context, filter platform.TaskFilter) val.Add("after", filter.After.String()) } if filter.Organization != nil { - val.Add("organization", filter.Organization.String()) + val.Add("orgID", filter.Organization.String()) } if filter.User != nil { val.Add("user", filter.User.String()) diff --git a/http/task_service_test.go b/http/task_service_test.go index d3d39f38f5..dda01aa85e 100644 --- a/http/task_service_test.go +++ b/http/task_service_test.go @@ -4,6 +4,7 @@ import ( "bytes" "context" "encoding/json" + "errors" "fmt" "io/ioutil" "net/http" @@ -38,6 +39,13 @@ func NewMockTaskBackend(t *testing.T) *TaskBackend { FindOrganizationF: func(ctx context.Context, filter platform.OrganizationFilter) (*platform.Organization, error) { org := &platform.Organization{} if filter.Name != nil { + if *filter.Name == "non-existant-org" { + return nil, &platform.Error{ + Err: errors.New("org not found or unauthorized"), + Msg: "org " + *filter.Name + " not found or unauthorized", + Code: platform.ENotFound, + } + } org.Name = *filter.Name } if filter.ID != nil { @@ -65,9 +73,10 @@ func TestTaskHandler_handleGetTasks(t *testing.T) { } tests := []struct { - name string - fields fields - wants wants + name string + getParams string + fields fields + wants wants }{ { name: "get tasks", @@ -170,6 +179,132 @@ func TestTaskHandler_handleGetTasks(t *testing.T) { "flux": "" } ] +}`, + }, + }, + { + name: "get tasks by org name", + getParams: "org=test2", + fields: fields{ + taskService: &mock.TaskService{ + FindTasksFn: func(ctx context.Context, f platform.TaskFilter) ([]*platform.Task, int, error) { + tasks := []*platform.Task{ + { + ID: 2, + Name: "task2", + OrganizationID: 2, + Organization: "test2", + AuthorizationID: 0x200, + }, + } + return tasks, len(tasks), nil + }, + }, + labelService: &mock.LabelService{ + FindResourceLabelsFn: func(ctx context.Context, f platform.LabelMappingFilter) ([]*platform.Label, error) { + labels := []*platform.Label{ + { + ID: platformtesting.MustIDBase16("fc3dc670a4be9b9a"), + Name: "label", + Properties: map[string]string{ + "color": "fff000", + }, + }, + } + return labels, nil + }, + }, + }, + wants: wants{ + statusCode: http.StatusOK, + contentType: "application/json; charset=utf-8", + body: ` +{ + "links": { + "self": "/api/v2/tasks" + }, + "tasks": [ + { + "links": { + "self": "/api/v2/tasks/0000000000000002", + "owners": "/api/v2/tasks/0000000000000002/owners", + "members": "/api/v2/tasks/0000000000000002/members", + "labels": "/api/v2/tasks/0000000000000002/labels", + "runs": "/api/v2/tasks/0000000000000002/runs", + "logs": "/api/v2/tasks/0000000000000002/logs" + }, + "id": "0000000000000002", + "name": "task2", + "labels": [ + { + "id": "fc3dc670a4be9b9a", + "name": "label", + "properties": { + "color": "fff000" + } + } + ], + "orgID": "0000000000000002", + "org": "test2", + "status": "", + "authorizationID": "0000000000000200", + "flux": "" + } + ] +}`, + }, + }, + { + name: "get tasks by org name bad", + getParams: "org=non-existant-org", + fields: fields{ + taskService: &mock.TaskService{ + FindTasksFn: func(ctx context.Context, f platform.TaskFilter) ([]*platform.Task, int, error) { + tasks := []*platform.Task{ + { + ID: 1, + Name: "task1", + OrganizationID: 1, + Organization: "test2", + AuthorizationID: 0x100, + }, + { + ID: 2, + Name: "task2", + OrganizationID: 2, + Organization: "test2", + AuthorizationID: 0x200, + }, + } + return tasks, len(tasks), nil + }, + }, + labelService: &mock.LabelService{ + FindResourceLabelsFn: func(ctx context.Context, f platform.LabelMappingFilter) ([]*platform.Label, error) { + labels := []*platform.Label{ + { + ID: platformtesting.MustIDBase16("fc3dc670a4be9b9a"), + Name: "label", + Properties: map[string]string{ + "color": "fff000", + }, + }, + } + return labels, nil + }, + }, + }, + wants: wants{ + statusCode: http.StatusBadRequest, + contentType: "application/json; charset=utf-8", + body: `{ +"code": "invalid", +"error": { +"code": "not found", +"error": "org not found or unauthorized", +"message": "org non-existant-org not found or unauthorized" +}, +"message": "failed to decode request" }`, }, }, @@ -177,7 +312,7 @@ func TestTaskHandler_handleGetTasks(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - r := httptest.NewRequest("GET", "http://any.url", nil) + r := httptest.NewRequest("GET", "http://any.url?"+tt.getParams, nil) w := httptest.NewRecorder() taskBackend := NewMockTaskBackend(t) diff --git a/task_test.go b/task_test.go index 7f3fce7636..ee1d53dcf9 100644 --- a/task_test.go +++ b/task_test.go @@ -64,4 +64,20 @@ from(bucket:"x") t.Fail() } }) + t.Run("test add new option", func(t *testing.T) { + tu := &platform.TaskUpdate{} + tu.Options.Offset = 30 * time.Second + if err := tu.UpdateFlux(`option task = {every: 20s, name: "foo"} from(bucket:"x") |> range(start:-1h)`); err != nil { + t.Fatal(err) + } + + op, err := options.FromScript(*tu.Flux) + if err != nil { + t.Error(err) + } + if op.Offset != 30*time.Second { + t.Fatalf("expected every to be 30s but was %s", op.Every) + } + }) + }