Merge pull request #653 from LinuxSuRen/feat/iotdb
feat: add iotdb support
This commit is contained in:
commit
34eeb2a253
|
@ -6,13 +6,14 @@ import type { Pair } from './types'
|
|||
import { ElMessage } from 'element-plus'
|
||||
import { Codemirror } from 'vue-codemirror'
|
||||
import HistoryInput from '../components/HistoryInput.vue'
|
||||
import type { Ref } from 'vue'
|
||||
|
||||
const stores = ref([] as Store[])
|
||||
const stores: Ref<Store[]> = ref([])
|
||||
const kind = ref('')
|
||||
const store = ref('')
|
||||
const sqlQuery = ref('')
|
||||
const queryResult = ref([] as any[])
|
||||
const queryResultAsJSON= ref('')
|
||||
const queryResultAsJSON = ref('')
|
||||
const columns = ref([] as string[])
|
||||
const queryTip = ref('')
|
||||
const loadingStores = ref(true)
|
||||
|
@ -20,7 +21,10 @@ const dataFormat = ref('table')
|
|||
const dataFormatOptions = ['table', 'json']
|
||||
const queryDataMeta = ref({} as QueryDataMeta)
|
||||
|
||||
const tablesTree = ref([])
|
||||
interface TreeItem {
|
||||
label: string
|
||||
}
|
||||
const tablesTree = ref([] as TreeItem[])
|
||||
watch(store, (s) => {
|
||||
kind.value = ''
|
||||
stores.value.forEach((e: Store) => {
|
||||
|
@ -60,6 +64,7 @@ const queryTables = () => {
|
|||
watch(kind, (k) => {
|
||||
switch (k) {
|
||||
case 'atest-store-orm':
|
||||
case 'atest-store-iotdb':
|
||||
queryTip.value = 'Enter SQL query'
|
||||
executeQuery()
|
||||
break;
|
||||
|
@ -144,6 +149,7 @@ const executeQuery = async () => {
|
|||
const data = await API.DataQueryAsync(store.value, kind.value, queryDataMeta.value.currentDatabase, sqlQuery.value);
|
||||
switch (kind.value) {
|
||||
case 'atest-store-orm':
|
||||
case 'atest-store-iotdb':
|
||||
ormDataHandler(data)
|
||||
success = true
|
||||
break;
|
||||
|
@ -174,13 +180,15 @@ const executeQuery = async () => {
|
|||
<template>
|
||||
<div>
|
||||
<el-container style="height: calc(100vh - 50px);">
|
||||
<el-aside v-if="kind === 'atest-store-orm'">
|
||||
<el-aside v-if="kind === 'atest-store-orm' || kind === 'atest-store-iotdb'">
|
||||
<el-scrollbar>
|
||||
<el-select v-model="queryDataMeta.currentDatabase" placeholder="Select database" @change="queryTables" filterable>
|
||||
<el-select v-model="queryDataMeta.currentDatabase" placeholder="Select database"
|
||||
@change="queryTables" filterable>
|
||||
<el-option v-for="item in queryDataMeta.databases" :key="item" :label="item"
|
||||
:value="item"></el-option>
|
||||
</el-select>
|
||||
<el-tree :data="tablesTree" node-key="label" @node-click="queryDataFromTable" highlight-current draggable/>
|
||||
<el-tree :data="tablesTree" node-key="label" @node-click="queryDataFromTable" highlight-current
|
||||
draggable />
|
||||
</el-scrollbar>
|
||||
</el-aside>
|
||||
<el-container>
|
||||
|
@ -189,15 +197,17 @@ const executeQuery = async () => {
|
|||
<el-row :gutter="10">
|
||||
<el-col :span="4">
|
||||
<el-form-item>
|
||||
<el-select v-model="store" placeholder="Select store" filterable :loading="loadingStores">
|
||||
<el-select v-model="store" placeholder="Select store" filterable
|
||||
:loading="loadingStores">
|
||||
<el-option v-for="item in stores" :key="item.name" :label="item.name"
|
||||
:value="item.name" :disabled="!item.ready" :kind="item.kind.name"></el-option>
|
||||
:value="item.name" :disabled="!item.ready"
|
||||
:kind="item.kind.name"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="16">
|
||||
<el-form-item>
|
||||
<HistoryInput :placeholder="queryTip" :callback="executeQuery" v-model="sqlQuery"/>
|
||||
<HistoryInput :placeholder="queryTip" :callback="executeQuery" v-model="sqlQuery" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="2">
|
||||
|
@ -207,7 +217,8 @@ const executeQuery = async () => {
|
|||
</el-col>
|
||||
<el-col :span="2">
|
||||
<el-select v-model="dataFormat" placeholder="Select data format">
|
||||
<el-option v-for="item in dataFormatOptions" :key="item" :label="item" :value="item"></el-option>
|
||||
<el-option v-for="item in dataFormatOptions" :key="item" :label="item"
|
||||
:value="item"></el-option>
|
||||
</el-select>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
@ -220,10 +231,9 @@ const executeQuery = async () => {
|
|||
<el-tag type="primary" v-for="label in queryDataMeta.labels">{{ label.value }}</el-tag>
|
||||
</div>
|
||||
<el-table :data="queryResult" stripe v-if="dataFormat === 'table'">
|
||||
<el-table-column v-for="col in columns" :key="col" :prop="col" :label="col" sortable/>
|
||||
<el-table-column v-for="col in columns" :key="col" :prop="col" :label="col" sortable />
|
||||
</el-table>
|
||||
<Codemirror v-else-if="dataFormat === 'json'"
|
||||
v-model="queryResultAsJSON"/>
|
||||
<Codemirror v-else-if="dataFormat === 'json'" v-model="queryResultAsJSON" />
|
||||
</el-main>
|
||||
</el-container>
|
||||
</el-container>
|
||||
|
|
|
@ -14,12 +14,12 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import {SupportedExtension, SupportedExtensions} from "../store";
|
||||
import { SupportedExtension, SupportedExtensions } from "../store";
|
||||
|
||||
describe("SupportedExtensions", () => {
|
||||
test('length check', () => {
|
||||
const extensions = SupportedExtensions()
|
||||
expect(extensions.length).toBe(6)
|
||||
expect(extensions.length).toBe(7)
|
||||
})
|
||||
|
||||
for (const extension of SupportedExtensions()) {
|
||||
|
|
|
@ -23,7 +23,7 @@ async function DefaultResponseProcess(response: any) {
|
|||
throw new Error("Unauthenticated")
|
||||
}
|
||||
|
||||
const message = await response.json().then((data :any) => data.message)
|
||||
const message = await response.json().then((data: any) => data.message)
|
||||
throw new Error(message)
|
||||
} else {
|
||||
return response.json()
|
||||
|
@ -38,7 +38,7 @@ interface AppVersion {
|
|||
|
||||
function safeToggleFunc(toggle?: (e: boolean) => void) {
|
||||
if (!toggle) {
|
||||
return (e: boolean) => {}
|
||||
return (e: boolean) => { }
|
||||
}
|
||||
return toggle
|
||||
}
|
||||
|
@ -205,7 +205,7 @@ export interface TestCase {
|
|||
}
|
||||
|
||||
interface HistoryTestCase {
|
||||
historyCaseID : string,
|
||||
historyCaseID: string,
|
||||
suiteName: string
|
||||
caseName: string
|
||||
}
|
||||
|
@ -367,7 +367,7 @@ const BatchRunTestCase = (request: BatchRunTestCaseRequest,
|
|||
|
||||
function DuplicateTestCase(sourceSuiteName: string, targetSuiteName: string,
|
||||
sourceTestCaseName: string, targetTestCaseName: string,
|
||||
callback: (d: any) => void, errHandle?: ((reason: any) => PromiseLike<never>) | undefined | null ) {
|
||||
callback: (d: any) => void, errHandle?: ((reason: any) => PromiseLike<never>) | undefined | null) {
|
||||
const requestOptions = {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
|
@ -388,7 +388,7 @@ function DuplicateTestCase(sourceSuiteName: string, targetSuiteName: string,
|
|||
|
||||
function RenameTestCase(sourceSuiteName: string, targetSuiteName: string,
|
||||
sourceTestCaseName: string, targetTestCaseName: string,
|
||||
callback: (d: any) => void, errHandle?: ((reason: any) => PromiseLike<never>) | undefined | null ) {
|
||||
callback: (d: any) => void, errHandle?: ((reason: any) => PromiseLike<never>) | undefined | null) {
|
||||
const requestOptions = {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
|
@ -675,7 +675,7 @@ function emptyOrDefault(fn: any) {
|
|||
if (fn) {
|
||||
return fn
|
||||
}
|
||||
return () => {}
|
||||
return () => { }
|
||||
}
|
||||
|
||||
function GetHistoryTestCaseWithResult(req: HistoryTestCase,
|
||||
|
@ -713,7 +713,7 @@ function DeleteHistoryTestCase(req: HistoryTestCase,
|
|||
'X-Auth': getToken()
|
||||
},
|
||||
body: JSON.stringify({
|
||||
ID : req.historyCaseID
|
||||
ID: req.historyCaseID
|
||||
})
|
||||
}
|
||||
fetch(`/api/v1/historyTestCase/${req.historyCaseID}`, requestOptions)
|
||||
|
@ -729,7 +729,7 @@ function DeleteAllHistoryTestCase(suiteName: string, caseName: string,
|
|||
'X-Auth': getToken()
|
||||
},
|
||||
body: JSON.stringify({
|
||||
suiteName : suiteName,
|
||||
suiteName: suiteName,
|
||||
caseName: caseName,
|
||||
})
|
||||
}
|
||||
|
@ -791,6 +791,10 @@ var DataQueryAsync = (store: string, kind: string, currentDatabase: string, quer
|
|||
queryObj['sql'] = query;
|
||||
queryObj['key'] = currentDatabase;
|
||||
break;
|
||||
case 'atest-store-iotdb':
|
||||
queryObj['sql'] = query;
|
||||
queryObj['key'] = currentDatabase;
|
||||
break;
|
||||
case 'atest-store-etcd':
|
||||
queryObj['key'] = query;
|
||||
break;
|
||||
|
@ -811,7 +815,35 @@ var DataQueryAsync = (store: string, kind: string, currentDatabase: string, quer
|
|||
}
|
||||
|
||||
var DataQuery = (store: string, kind: string, currentDatabase: string, query: string, callback: (d: any) => void, errHandler: (d: any) => void) => {
|
||||
DataQueryAsync(store, kind, currentDatabase, query).then(callback).catch(errHandler)
|
||||
const queryObj = {} as QueryObject
|
||||
switch (kind) {
|
||||
case 'atest-store-orm':
|
||||
queryObj['sql'] = query;
|
||||
queryObj['key'] = currentDatabase;
|
||||
break;
|
||||
case 'atest-store-iotdb':
|
||||
queryObj['sql'] = query;
|
||||
queryObj['key'] = currentDatabase;
|
||||
break;
|
||||
case 'atest-store-etcd':
|
||||
queryObj['key'] = query;
|
||||
break;
|
||||
case 'atest-store-redis':
|
||||
queryObj['key'] = query;
|
||||
break;
|
||||
}
|
||||
const requestOptions = {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-Store-Name': store,
|
||||
'X-Database': currentDatabase
|
||||
},
|
||||
body: JSON.stringify(queryObj)
|
||||
}
|
||||
fetch(`/api/v1/data/query`, requestOptions)
|
||||
.then(DefaultResponseProcess)
|
||||
.then(callback)
|
||||
.catch(errHandler)
|
||||
}
|
||||
|
||||
export const API = {
|
||||
|
@ -819,7 +851,7 @@ export const API = {
|
|||
GetVersion,
|
||||
CreateTestSuite, UpdateTestSuite, ImportTestSuite, GetTestSuite, DeleteTestSuite, ConvertTestSuite, DuplicateTestSuite, RenameTestSuite, GetTestSuiteYaml,
|
||||
CreateTestCase, UpdateTestCase, GetTestCase, ListTestCase, DeleteTestCase, DuplicateTestCase, RenameTestCase, RunTestCase, BatchRunTestCase,
|
||||
GetHistoryTestCaseWithResult, DeleteHistoryTestCase,GetHistoryTestCase, GetTestCaseAllHistory, DeleteAllHistoryTestCase, DownloadResponseFile,
|
||||
GetHistoryTestCaseWithResult, DeleteHistoryTestCase, GetHistoryTestCase, GetTestCaseAllHistory, DeleteAllHistoryTestCase, DownloadResponseFile,
|
||||
GenerateCode, ListCodeGenerator, HistoryGenerateCode,
|
||||
PopularHeaders,
|
||||
CreateOrUpdateStore, GetStores, DeleteStore, VerifyStore,
|
||||
|
|
|
@ -83,6 +83,11 @@ const storeExtensions = [
|
|||
}],
|
||||
link: 'https://github.com/LinuxSuRen/atest-ext-store-orm'
|
||||
},
|
||||
{
|
||||
name: 'atest-store-iotdb',
|
||||
params: [],
|
||||
link: 'https://github.com/LinuxSuRen/atest-ext-store-iotdb'
|
||||
},
|
||||
{
|
||||
name: 'atest-store-etcd',
|
||||
params: [],
|
||||
|
|
|
@ -8,6 +8,7 @@ Ports in extensions:
|
|||
| Store | [git](https://github.com/LinuxSuRen/atest-ext-store-git) | 4074 |
|
||||
| Store | [mongodb](https://github.com/LinuxSuRen/atest-ext-store-mongodb) | 4075 |
|
||||
| Store | [redis](https://github.com/LinuxSuRen/atest-ext-store-redis) | |
|
||||
| Store | [iotdb](https://github.com/LinuxSuRen/atest-ext-store-iotdb) | |
|
||||
| Monitor | [docker-monitor](https://github.com/LinuxSuRen/atest-ext-monitor-docker) | |
|
||||
| Agent | [collector](https://github.com/LinuxSuRen/atest-ext-collector) | |
|
||||
| Secret | [Vault](https://github.com/LinuxSuRen/api-testing-vault-extension) | |
|
||||
|
@ -20,6 +21,7 @@ Ports in extensions:
|
|||
* Finally, add the extension's name into function [SupportedExtensions](../console/atest-ui/src/views/store.ts).
|
||||
|
||||
## Naming conventions
|
||||
|
||||
Please follow the following conventions if you want to add a new store extension:
|
||||
|
||||
`store-xxx`
|
||||
|
|
|
@ -1157,6 +1157,9 @@ func (s *server) GetStores(ctx context.Context, in *Empty) (reply *Stores, err e
|
|||
}
|
||||
for _, item := range stores {
|
||||
grpcStore := ToGRPCStore(item)
|
||||
if item.Disabled {
|
||||
continue
|
||||
}
|
||||
|
||||
storeStatus, sErr := s.VerifyStore(ctx, &SimpleQuery{Name: item.Name})
|
||||
grpcStore.Ready = sErr == nil && storeStatus.Ready
|
||||
|
|
Loading…
Reference in New Issue