Merge pull request #12022 from influxdata/feat/tasklookup-orgname

feat(tasks): look up tasks by orgname
pull/12172/head
Jorge Landivar 2019-02-25 17:54:24 -06:00 committed by GitHub
commit 70a54e1f4c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 181 additions and 10 deletions

View File

@ -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

View File

@ -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())

View File

@ -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)

View File

@ -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)
}
})
}