Add generated API code and use for task creation

Co-authored-by: Deniz Kusefoglu <deniz@influxdata.com>
pull/10616/head
Brandon Farmer 2018-11-19 14:03:28 -08:00
parent 0bdb3414ae
commit b4aa8ff1d6
17 changed files with 15474 additions and 126 deletions

6
.gitignore vendored
View File

@ -22,3 +22,9 @@ ui/node_modules
ui/yarn-error.log
ui/build
ui/.cache
ui/src/api/.gitignore
ui/src/api/.openapi-generator-ignore
ui/src/api/.openapi-generator/VERSION
ui/src/api/git_push.sh

View File

@ -149,6 +149,10 @@ chronogiraffe: subdirs generate $(CMDS)
run: chronogiraffe
./bin/$(GOOS)/influxd --developer-mode=true
generate-typescript-client:
cat http/cur_swagger.yml | yq read -j - > openapi.json
openapi-generator generate -g typescript-axios -o ui/src/api -i openapi.json
rm openapi.json
# .PHONY targets represent actions that do not create an actual file.
.PHONY: all subdirs $(SUBDIRS) ui run fmt checkfmt tidy checktidy test test-go test-js test-go-race bench clean node_modules vet nightly chronogiraffe

View File

@ -3,7 +3,7 @@ info:
title: Influx API Service
version: 0.1.0
servers:
- url: /api/v2
- url: "http://localhost:9999/api/v2"
paths:
/signin:
post:
@ -1490,8 +1490,6 @@ paths:
responses:
'200':
description: Abstract syntax tree of flux query.
content:
application/json: #TODO(goller): document the AST JSON schema
default:
description: Any response other than 200 is an internal server error
content:
@ -3452,24 +3450,23 @@ components:
annotations:
description: https://www.w3.org/TR/2015/REC-tabular-data-model-20151217/#columns
type: array
default: []
items:
type: string
enum:
- group
- datatype
- default
- "group"
- "datatype"
- "default"
uniqueItems: true
commentPrefix:
description: character prefixed to comment strings
type: string
default: \#
default: "#"
maxLength: 1
minLength: 0
dateTimeFormat:
description: format of timestamps
type: string
default: RFC3339
default: "RFC3339"
enum:
- RFC3339
- RFC3339Nano
@ -3764,7 +3761,7 @@ components:
id:
readOnly: true
type: string
organization:
organizationId:
description: The ID of the organization that owns this Task.
type: string
name:
@ -3976,75 +3973,6 @@ components:
type: integer
format: int32
required: [code, message, maxLength]
InfluxQLResults:
properties:
error:
description: error during processing of the message
type: string
results:
type: array
description: result for each query
items:
type: object
properties:
error:
type: string
description: error during processing of the message
partial:
type: boolean
description: If a max row limit has been placed in the configuration file and the number of returned values is larger, this will be set to true and values truncated.
statement_id:
type: integer
description: statement's position in the query.
series:
description: The collection of data in InfluxDBs data structure that share a measurement, tag set, and retention policy.
type: array
items:
type: object
description: values for a unique series
properties:
name:
description: The part of InfluxDBs structure that describes the data stored in the associated fields. Measurements are strings.
type: string
tags:
description: The key-value pairs in InfluxDBs data structure that records metadata.
type: object
columns:
description: list of columns describing the content of a single value array
type: array
items:
type: string
values:
description: array of arrays of the values return from the query
type: array
items:
type: array
description: single row of results in the order of the columns field.
items:
oneOf:
- type: string
- type: number
- type: integer
partial:
type: boolean
messages:
type: array
description: represents a user-facing message to be included with the result.
items:
type: object
properties:
level:
type: string
text:
type: string
InfluxqlQueryError:
properties:
error:
description: message describing why the query was rejected
readOnly: true
type: string
required:
- error
Field:
type: object
properties:
@ -4782,14 +4710,6 @@ components:
type: array
items:
type: string
TelegrafPluginInputNginx:
type: object
properties:
urls:
type: array
items:
type: string
format: uri
TelegrafPluginInputProcstat:
type: object
properties:

View File

@ -215,11 +215,7 @@ func (h *TaskHandler) handlePostTask(w http.ResponseWriter, r *http.Request) {
}
if !req.Task.Owner.ID.Valid() {
if err != nil {
EncodeError(ctx, kerrors.Wrap(err, "invalid token", kerrors.InvalidData), w)
return
}
req.Task.Owner.ID = auth.Identifier()
req.Task.Owner.ID = auth.GetUserID()
}
if err := h.TaskService.CreateTask(ctx, req.Task); err != nil {

15291
ui/src/api/api.ts Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,74 @@
// tslint:disable
/**
* Influx API Service
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* OpenAPI spec version: 0.1.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
export interface ConfigurationParameters {
apiKey?: string | ((name: string) => string);
username?: string;
password?: string;
accessToken?: string | ((name: string, scopes?: string[]) => string);
basePath?: string;
baseOptions?: any;
}
export class Configuration {
/**
* parameter for apiKey security
* @param name security name
* @memberof Configuration
*/
apiKey?: string | ((name: string) => string);
/**
* parameter for basic security
*
* @type {string}
* @memberof Configuration
*/
username?: string;
/**
* parameter for basic security
*
* @type {string}
* @memberof Configuration
*/
password?: string;
/**
* parameter for oauth2 security
* @param name security name
* @param scopes oauth2 scope
* @memberof Configuration
*/
accessToken?: string | ((name: string, scopes?: string[]) => string);
/**
* override base path
*
* @type {string}
* @memberof Configuration
*/
basePath?: string;
/**
* base options for axios calls
*
* @type {any}
* @memberof Configuration
*/
baseOptions?: any;
constructor(param: ConfigurationParameters = {}) {
this.apiKey = param.apiKey;
this.username = param.username;
this.password = param.password;
this.accessToken = param.accessToken;
this.basePath = param.basePath;
}
}

1
ui/src/api/custom.d.ts vendored Normal file
View File

@ -0,0 +1 @@
declare module 'url';

16
ui/src/api/index.ts Normal file
View File

@ -0,0 +1,16 @@
// tslint:disable
/**
* Influx API Service
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* OpenAPI spec version: 0.1.0
*
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
export * from "./api";
export * from "./configuration";

View File

@ -1,7 +1,7 @@
import {AppState} from 'src/types/v2'
import {push} from 'react-router-redux'
import {Task} from 'src/types/v2/tasks'
import {Task as TaskAPI, Organization} from 'src/api'
import {
submitNewTask,
updateTaskFlux,
@ -19,6 +19,7 @@ import {
taskNotFound,
taskUpdateFailed,
} from 'src/shared/copy/v2/notifications'
import {getDeep} from 'src/utils/wrappers'
import {taskOptionsToFluxScript} from 'src/utils/taskOptionsToFluxScript'
@ -37,7 +38,19 @@ export type Action =
| SetScheduleUnit
type GetStateFunc = () => AppState
interface Task extends TaskAPI {
organization: Organization
}
export enum ActionTypes {
SetNewScript = 'SET_NEW_SCRIPT',
SetTasks = 'SET_TASKS',
SetSearchTerm = 'SET_TASKS_SEARCH_TERM',
SetCurrentScript = 'SET_CURRENT_SCRIPT',
SetCurrentTask = 'SET_CURRENT_TASK',
SetShowInactive = 'SET_TASKS_SHOW_INACTIVE',
SetDropdownOrgID = 'SET_DROPDOWN_ORG_ID',
}
export interface ClearTaskOptions {
type: 'CLEAR_TASK_OPTIONS'
}
@ -221,9 +234,11 @@ export const populateTasks = () => async (
const tasks = await getUserTasks(url, user)
const mappedTasks = tasks.map(task => {
const org = orgs.find(org => org.id === task.organizationId)
return {
...task,
organization: orgs.find(org => org.id === task.organizationId),
organization: org,
}
})
@ -240,12 +255,15 @@ export const selectTaskByID = (id: string) => async (
): Promise<void> => {
try {
const {
orgs,
links: {tasks: url},
} = getState()
const org = orgs.find(org => org.id === task.organizationId)
const task = await getTask(url, id)
return dispatch(setCurrentTask(task))
return dispatch(setCurrentTask({...task, organization: org}))
} catch (e) {
console.error(e)
dispatch(goToTasks())
@ -290,15 +308,12 @@ export const saveNewScript = () => async (
try {
const {
orgs,
links: {tasks: url, me: meUrl},
tasks: {newScript: script, taskOptions},
} = await getState()
const fluxTaskOptions = taskOptionsToFluxScript(taskOptions)
const scriptWithOptions = `${fluxTaskOptions}\n${script}`
const user = await getMe(meUrl)
let org = orgs.find(org => {
return org.id === taskOptions.orgID
})
@ -307,7 +322,7 @@ export const saveNewScript = () => async (
org = orgs[0]
}
await submitNewTask(url, user, org, scriptWithOptions)
await submitNewTask(getDeep<string>(org, 'id', ''), scriptWithOptions)
dispatch(setNewScript(''))
dispatch(clearTaskOptions())

View File

@ -1,20 +1,21 @@
import AJAX from 'src/utils/ajax'
import {Task} from 'src/types/v2/tasks'
import {Task, TasksApi} from 'src/api'
const getBasePath = () => {
const host = window.location.hostname
const port = window.location.port
const protocol = window.location.protocol
return `${protocol}//${host}:${port}/api/v2`
}
export const submitNewTask = async (
url,
owner,
org,
organizationId: string,
flux: string
): Promise<Task> => {
const request = {
flux,
organizationId: org.id,
status: 'active',
owner,
}
const {data} = await AJAX({url, data: request, method: 'POST'})
const api = new TasksApi({basePath: getBasePath()})
const {data} = await api.tasksPost({organizationId, flux})
return data
}

View File

@ -15,7 +15,7 @@ import TaskScheduleFormField from 'src/tasks/components/TaskScheduleFormField'
import {TaskOptions, TaskSchedule} from 'src/utils/taskOptionsToFluxScript'
import {Organization} from 'src/types/v2'
import {Organization} from 'src/api'
import {Alignment, Direction} from 'src/clockface/types'
interface Props {

View File

@ -15,9 +15,13 @@ import {
// Utils
import {downloadTextFile} from 'src/shared/utils/download'
import {Task as TaskAPI, User, Organization} from 'src/api'
// Types
import {Task, TaskStatus} from 'src/types/v2/tasks'
interface Task extends TaskAPI {
organization: Organization
owner?: User
delay?: string
}
interface Props {
task: Task
@ -91,7 +95,7 @@ class TaskRow extends PureComponent<Props & WithRouterProps> {
private get isTaskActive(): boolean {
const {task} = this.props
if (task.status === TaskStatus.Active) {
if (task.status === TaskAPI.StatusEnum.Active) {
return true
}
return false
@ -99,10 +103,10 @@ class TaskRow extends PureComponent<Props & WithRouterProps> {
private changeToggle = () => {
const {task, onActivate} = this.props
if (task.status === TaskStatus.Active) {
task.status = TaskStatus.Inactive
if (task.status === TaskAPI.StatusEnum.Active) {
task.status = TaskAPI.StatusEnum.Inactive
} else {
task.status = TaskStatus.Active
task.status = TaskAPI.StatusEnum.Active
}
onActivate(task)
}

View File

@ -6,8 +6,13 @@ import {IndexList} from 'src/clockface'
import TaskRow from 'src/tasks/components/TaskRow'
// Types
import {Task} from 'src/types/v2/tasks'
import EmptyTasksList from 'src/tasks/components/EmptyTasksList'
import {Task as TaskAPI, User, Organization} from 'src/api'
interface Task extends TaskAPI {
organization: Organization
owner?: User
}
interface Props {
tasks: Task[]

View File

@ -6,7 +6,7 @@ import _ from 'lodash'
import {Dropdown} from 'src/clockface'
// Types
import {Organization} from 'src/types/v2'
import {Organization} from 'src/api'
interface Props {
orgs: Organization[]

View File

@ -5,8 +5,14 @@ import {connect} from 'react-redux'
import TaskForm from 'src/tasks/components/TaskForm'
import TaskHeader from 'src/tasks/components/TaskHeader'
import {Task} from 'src/types/v2/tasks'
import {Page} from 'src/pageLayout'
import {Task as TaskAPI, User, Organization} from 'src/api'
interface Task extends TaskAPI {
organization: Organization
owner?: User
delay?: string
}
import {Links} from 'src/types/v2/links'
import {State as TasksState} from 'src/tasks/reducers/v2'
@ -19,7 +25,6 @@ import {
setScheduleUnit,
} from 'src/tasks/actions/v2'
import {TaskOptions, TaskSchedule} from 'src/utils/taskOptionsToFluxScript'
import {Organization} from 'src/types/v2'
interface PassedInProps {
router: InjectedRouter

View File

@ -24,8 +24,13 @@ import {
import {allOrganizationsID} from 'src/tasks/constants'
// Types
import {Task, TaskStatus} from 'src/types/v2/tasks'
import {Organization} from 'src/types/v2'
import {Task as TaskAPI, User, Organization} from 'src/api'
interface Task extends TaskAPI {
organization: Organization
owner?: User
delay?: string
}
interface PassedInProps {
router: InjectedRouter
@ -119,7 +124,7 @@ class TasksPage extends PureComponent<Props> {
.includes(searchTerm.toLowerCase())
let activeFilter = true
if (!showInactive) {
activeFilter = t.status === TaskStatus.Active
activeFilter = t.status === TaskAPI.StatusEnum.Active
}
let orgIDFilter = true
if (dropdownOrgID && dropdownOrgID !== allOrganizationsID) {

View File

@ -1,7 +1,12 @@
import {Action} from 'src/tasks/actions/v2'
import {Task} from 'src/types/v2/tasks'
import {TaskOptions, TaskSchedule} from 'src/utils/taskOptionsToFluxScript'
import {Task as TaskAPI, User, Organization} from 'src/api'
interface Task extends TaskAPI {
organization: Organization
owner?: User
delay?: string
}
export interface State {
newScript: string
currentScript: string