add cluster register page
This commit is contained in:
parent
82a1c63233
commit
3aeef79fe0
|
@ -20,11 +20,9 @@ type APIHandler struct {
|
||||||
func (h *APIHandler) HandleCreateClusterAction(w http.ResponseWriter, req *http.Request, ps httprouter.Params){
|
func (h *APIHandler) HandleCreateClusterAction(w http.ResponseWriter, req *http.Request, ps httprouter.Params){
|
||||||
var conf = &model.ClusterConfig{}
|
var conf = &model.ClusterConfig{}
|
||||||
resBody := map[string] interface{}{
|
resBody := map[string] interface{}{
|
||||||
"status": true,
|
|
||||||
}
|
}
|
||||||
err := h.DecodeJSON(req, conf)
|
err := h.DecodeJSON(req, conf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
resBody["status"] = false
|
|
||||||
resBody["error"] = err
|
resBody["error"] = err
|
||||||
h.WriteJSON(w, resBody, http.StatusOK)
|
h.WriteJSON(w, resBody, http.StatusOK)
|
||||||
return
|
return
|
||||||
|
@ -34,7 +32,6 @@ func (h *APIHandler) HandleCreateClusterAction(w http.ResponseWriter, req *http.
|
||||||
id := util.GetUUID()
|
id := util.GetUUID()
|
||||||
ir, err := esClient.Index(orm.GetIndexName(model.ClusterConfig{}), "", id, conf)
|
ir, err := esClient.Index(orm.GetIndexName(model.ClusterConfig{}), "", id, conf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
resBody["status"] = false
|
|
||||||
resBody["error"] = err
|
resBody["error"] = err
|
||||||
h.WriteJSON(w, resBody, http.StatusOK)
|
h.WriteJSON(w, resBody, http.StatusOK)
|
||||||
return
|
return
|
||||||
|
@ -46,11 +43,9 @@ func (h *APIHandler) HandleCreateClusterAction(w http.ResponseWriter, req *http.
|
||||||
func (h *APIHandler) HandleUpdateClusterAction(w http.ResponseWriter, req *http.Request, ps httprouter.Params){
|
func (h *APIHandler) HandleUpdateClusterAction(w http.ResponseWriter, req *http.Request, ps httprouter.Params){
|
||||||
var conf = map[string]interface{}{}
|
var conf = map[string]interface{}{}
|
||||||
resBody := map[string] interface{}{
|
resBody := map[string] interface{}{
|
||||||
"status": true,
|
|
||||||
}
|
}
|
||||||
err := h.DecodeJSON(req, conf)
|
err := h.DecodeJSON(req, conf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
resBody["status"] = false
|
|
||||||
resBody["error"] = err
|
resBody["error"] = err
|
||||||
h.WriteJSON(w, resBody, http.StatusOK)
|
h.WriteJSON(w, resBody, http.StatusOK)
|
||||||
return
|
return
|
||||||
|
@ -60,7 +55,6 @@ func (h *APIHandler) HandleUpdateClusterAction(w http.ResponseWriter, req *http.
|
||||||
indexName := orm.GetIndexName(model.ClusterConfig{})
|
indexName := orm.GetIndexName(model.ClusterConfig{})
|
||||||
originConf, err := esClient.Get(indexName, "", id)
|
originConf, err := esClient.Get(indexName, "", id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
resBody["status"] = false
|
|
||||||
resBody["error"] = err
|
resBody["error"] = err
|
||||||
h.WriteJSON(w, resBody, http.StatusOK)
|
h.WriteJSON(w, resBody, http.StatusOK)
|
||||||
return
|
return
|
||||||
|
@ -74,36 +68,33 @@ func (h *APIHandler) HandleUpdateClusterAction(w http.ResponseWriter, req *http.
|
||||||
}
|
}
|
||||||
ir, err := esClient.Index(indexName, "", id, source)
|
ir, err := esClient.Index(indexName, "", id, source)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
resBody["status"] = false
|
|
||||||
resBody["error"] = err
|
resBody["error"] = err
|
||||||
h.WriteJSON(w, resBody, http.StatusOK)
|
h.WriteJSON(w, resBody, http.StatusOK)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
resBody["acknowledged"] = true
|
||||||
resBody["payload"] = ir
|
resBody["payload"] = ir
|
||||||
h.WriteJSON(w, resBody, http.StatusOK)
|
h.WriteJSON(w, resBody, http.StatusOK)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *APIHandler) HandleDeleteClusterAction(w http.ResponseWriter, req *http.Request, ps httprouter.Params){
|
func (h *APIHandler) HandleDeleteClusterAction(w http.ResponseWriter, req *http.Request, ps httprouter.Params){
|
||||||
resBody := map[string] interface{}{
|
resBody := map[string] interface{}{
|
||||||
"status": true,
|
|
||||||
}
|
}
|
||||||
id := ps.ByName("id")
|
id := ps.ByName("id")
|
||||||
esClient := elastic.GetClient(h.Config.Elasticsearch)
|
esClient := elastic.GetClient(h.Config.Elasticsearch)
|
||||||
_, err := esClient.Delete(orm.GetIndexName(model.ClusterConfig{}), "", id)
|
_, err := esClient.Delete(orm.GetIndexName(model.ClusterConfig{}), "", id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
resBody["status"] = false
|
|
||||||
resBody["error"] = err
|
resBody["error"] = err
|
||||||
h.WriteJSON(w, resBody, http.StatusOK)
|
h.WriteJSON(w, resBody, http.StatusOK)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
resBody["payload"] = true
|
resBody["acknowledged"] = true
|
||||||
h.WriteJSON(w, resBody, http.StatusOK)
|
h.WriteJSON(w, resBody, http.StatusOK)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *APIHandler) HandleSearchClusterAction(w http.ResponseWriter, req *http.Request, ps httprouter.Params){
|
func (h *APIHandler) HandleSearchClusterAction(w http.ResponseWriter, req *http.Request, ps httprouter.Params){
|
||||||
resBody := map[string] interface{}{
|
resBody := map[string] interface{}{
|
||||||
"status": true,
|
|
||||||
}
|
}
|
||||||
var (
|
var (
|
||||||
name = h.GetParameterOrDefault(req, "name", "")
|
name = h.GetParameterOrDefault(req, "name", "")
|
||||||
|
@ -123,12 +114,10 @@ func (h *APIHandler) HandleSearchClusterAction(w http.ResponseWriter, req *http.
|
||||||
esClient := elastic.GetClient(h.Config.Elasticsearch)
|
esClient := elastic.GetClient(h.Config.Elasticsearch)
|
||||||
res, err := esClient.SearchWithRawQueryDSL(orm.GetIndexName(model.ClusterConfig{}), []byte(queryDSL))
|
res, err := esClient.SearchWithRawQueryDSL(orm.GetIndexName(model.ClusterConfig{}), []byte(queryDSL))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
resBody["status"] = false
|
|
||||||
resBody["error"] = err
|
resBody["error"] = err
|
||||||
h.WriteJSON(w, resBody, http.StatusOK)
|
h.WriteJSON(w, resBody, http.StatusOK)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
resBody["payload"] = res
|
h.WriteJSON(w, res, http.StatusOK)
|
||||||
h.WriteJSON(w, resBody, http.StatusOK)
|
|
||||||
}
|
}
|
|
@ -39,6 +39,10 @@ export default [
|
||||||
name: 'monitoring',
|
name: 'monitoring',
|
||||||
component: './Cluster/ClusterList',
|
component: './Cluster/ClusterList',
|
||||||
}, {
|
}, {
|
||||||
|
path: '/cluster/logging',
|
||||||
|
name: 'logging',
|
||||||
|
component: './Cluster/SearchMonitor',
|
||||||
|
},{
|
||||||
path: '/cluster/settings',
|
path: '/cluster/settings',
|
||||||
name: 'settings',
|
name: 'settings',
|
||||||
component: './Cluster/Settings/Base',
|
component: './Cluster/Settings/Base',
|
||||||
|
@ -52,12 +56,7 @@ export default [
|
||||||
component: './Cluster/Settings/Repository',
|
component: './Cluster/Settings/Repository',
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}, {
|
|
||||||
path: '/cluster/logging',
|
|
||||||
name: 'logging',
|
|
||||||
component: './Cluster/SearchMonitor',
|
|
||||||
},
|
},
|
||||||
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -89,11 +88,11 @@ export default [
|
||||||
{
|
{
|
||||||
path: '/data/overview',
|
path: '/data/overview',
|
||||||
name: 'overview',
|
name: 'overview',
|
||||||
component: './DataManagement/Indices',
|
component: './DataManagement/IndexSummary',
|
||||||
}, {
|
}, {
|
||||||
path: '/data/index',
|
path: '/data/index',
|
||||||
name: 'index',
|
name: 'index',
|
||||||
component: './DataManagement/Indices',
|
component: './DataManagement/Index',
|
||||||
},{
|
},{
|
||||||
path: '/data/document',
|
path: '/data/document',
|
||||||
name: 'document',
|
name: 'document',
|
||||||
|
@ -101,18 +100,12 @@ export default [
|
||||||
}, {
|
}, {
|
||||||
path: '/data/template',
|
path: '/data/template',
|
||||||
name: 'template',
|
name: 'template',
|
||||||
component: './DataManagement/Indices',
|
component: './DataManagement/IndexTemplate',
|
||||||
},
|
},
|
||||||
// {
|
|
||||||
// path: '/data/rebuild/new',
|
|
||||||
// name: 'rebuild',
|
|
||||||
// component: './DataManagement/Rebuild',
|
|
||||||
// hideInMenu: true,
|
|
||||||
// },
|
|
||||||
{
|
{
|
||||||
path: '/data/lifecycle',
|
path: '/data/lifecycle',
|
||||||
name: 'lifecycle',
|
name: 'lifecycle',
|
||||||
component: './DataManagement/Indices',
|
component: './DataManagement/IndexLifeCycle',
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -249,7 +242,7 @@ export default [
|
||||||
routes: [
|
routes: [
|
||||||
{
|
{
|
||||||
path: '/sync/pipeline',
|
path: '/sync/pipeline',
|
||||||
redirect: '/sync/pipeline',
|
redirect: '/sync/pipeline/logstash',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/sync/pipeline/ingestpipeline',
|
path: '/sync/pipeline/ingestpipeline',
|
||||||
|
@ -262,6 +255,11 @@ export default [
|
||||||
path: '/sync/rebuild',
|
path: '/sync/rebuild',
|
||||||
name: 'rebuild',
|
name: 'rebuild',
|
||||||
component: './Synchronize/RebuildList',
|
component: './Synchronize/RebuildList',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/sync/rebuild/new',
|
||||||
|
component: './Synchronize/Rebuild',
|
||||||
|
hideInMenu: true,
|
||||||
},{
|
},{
|
||||||
path: '/sync/inout',
|
path: '/sync/inout',
|
||||||
name: 'inout',
|
name: 'inout',
|
||||||
|
@ -302,7 +300,13 @@ export default [
|
||||||
{
|
{
|
||||||
path: '/system/cluster',
|
path: '/system/cluster',
|
||||||
name: 'cluster',
|
name: 'cluster',
|
||||||
component: './System/Settings/Base',
|
component: './System/Cluster/Index',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/system/cluster/new',
|
||||||
|
name: 'new-cluster',
|
||||||
|
component: './System/Cluster/Form',
|
||||||
|
hideInMenu: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/system/settings',
|
path: '/system/settings',
|
||||||
|
|
|
@ -93,7 +93,7 @@ export default {
|
||||||
'menu.home': '首页',
|
'menu.home': '首页',
|
||||||
|
|
||||||
'menu.cluster': '集群管理',
|
'menu.cluster': '集群管理',
|
||||||
'menu.cluster.overview': '集群概览',
|
'menu.cluster.overview': '概览',
|
||||||
'menu.cluster.monitoring': '集群监控',
|
'menu.cluster.monitoring': '集群监控',
|
||||||
'menu.cluster.settings': '集群设置',
|
'menu.cluster.settings': '集群设置',
|
||||||
'menu.cluster.logging': '集群日志',
|
'menu.cluster.logging': '集群日志',
|
||||||
|
@ -103,8 +103,8 @@ export default {
|
||||||
'menu.data.overview': '概览',
|
'menu.data.overview': '概览',
|
||||||
'menu.data.index': '索引管理',
|
'menu.data.index': '索引管理',
|
||||||
'menu.data.document': '文档管理',
|
'menu.data.document': '文档管理',
|
||||||
'menu.data.template': '索引模版管理',
|
'menu.data.template': '模版管理',
|
||||||
'menu.data.lifecycle': '索引生命周期管理',
|
'menu.data.lifecycle': '周期管理',
|
||||||
|
|
||||||
'menu.search': '搜索管理',
|
'menu.search': '搜索管理',
|
||||||
'menu.search.overview': '概览',
|
'menu.search.overview': '概览',
|
||||||
|
|
|
@ -153,7 +153,7 @@ class RebuildList extends React.Component {
|
||||||
<Divider style={{marginBottom:0}} />
|
<Divider style={{marginBottom:0}} />
|
||||||
<Card
|
<Card
|
||||||
bodyStyle={{padding:0}}
|
bodyStyle={{padding:0}}
|
||||||
extra={<div><Button onClick={this.handleRefreshClick} icon="redo">Refresh</Button><Link to="/data/rebuild/new"> <Button type="primary" icon="plus">New</Button></Link></div>}
|
extra={<div><Button onClick={this.handleRefreshClick} icon="redo">Refresh</Button><Link to="/sync/rebuild/new"> <Button type="primary" icon="plus">New</Button></Link></div>}
|
||||||
bordered={false}>
|
bordered={false}>
|
||||||
<Table columns={this.columns}
|
<Table columns={this.columns}
|
||||||
loading={rebuildlist.isLoading}
|
loading={rebuildlist.isLoading}
|
||||||
|
|
|
@ -0,0 +1,129 @@
|
||||||
|
import React from 'react';
|
||||||
|
import {Card, Form, Icon, Input, InputNumber, Button, Switch} from 'antd';
|
||||||
|
|
||||||
|
@Form.create()
|
||||||
|
class ClusterForm extends React.Component{
|
||||||
|
state = {
|
||||||
|
confirmDirty: false,
|
||||||
|
}
|
||||||
|
compareToFirstPassword = (rule, value, callback) => {
|
||||||
|
const { form } = this.props;
|
||||||
|
if (value && value !== form.getFieldValue('password')) {
|
||||||
|
callback('Two passwords that you enter is inconsistent!');
|
||||||
|
} else {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
validateToNextPassword = (rule, value, callback) => {
|
||||||
|
const { form } = this.props;
|
||||||
|
if (value && this.state.confirmDirty) {
|
||||||
|
form.validateFields(['confirm'], { force: true });
|
||||||
|
}
|
||||||
|
callback();
|
||||||
|
};
|
||||||
|
render() {
|
||||||
|
const {getFieldDecorator} = this.props.form;
|
||||||
|
const formItemLayout = {
|
||||||
|
labelCol: {
|
||||||
|
xs: { span: 24 },
|
||||||
|
sm: { span: 6 },
|
||||||
|
},
|
||||||
|
wrapperCol: {
|
||||||
|
xs: { span: 24 },
|
||||||
|
sm: { span: 16 },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const tailFormItemLayout = {
|
||||||
|
wrapperCol: {
|
||||||
|
xs: {
|
||||||
|
span: 24,
|
||||||
|
offset: 0,
|
||||||
|
},
|
||||||
|
sm: {
|
||||||
|
span: 16,
|
||||||
|
offset: 6,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<Card>
|
||||||
|
<Form {...formItemLayout} onSubmit={this.handleSubmit}>
|
||||||
|
<Form.Item label="集群名称">
|
||||||
|
{getFieldDecorator('name', {
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: 'Please input cluster name!',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})(<Input />)}
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item label="集群 URL">
|
||||||
|
{getFieldDecorator('endpoint', {
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
type: 'url', //https://github.com/yiminghe/async-validator#type
|
||||||
|
message: 'The input is not valid url!',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: 'Please input cluster name!',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})(<Input />)}
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item label="ES 用户名">
|
||||||
|
{getFieldDecorator('username', {
|
||||||
|
rules: [
|
||||||
|
],
|
||||||
|
})(<Input />)}
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item label="ES 密码" hasFeedback>
|
||||||
|
{getFieldDecorator('password', {
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
validator: this.validateToNextPassword,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})(<Input.Password />)}
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item label="ES 确认密码" hasFeedback>
|
||||||
|
{getFieldDecorator('confirm', {
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
validator: this.compareToFirstPassword,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})(<Input.Password onBlur={this.handleConfirmBlur} />)}
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item label="排序权重">
|
||||||
|
{getFieldDecorator('order', {
|
||||||
|
initialValue: 0
|
||||||
|
})(<InputNumber />)}
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item label="描述">
|
||||||
|
{getFieldDecorator('order', {
|
||||||
|
})(<Input.TextArea />)}
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item label="是否启用">
|
||||||
|
{getFieldDecorator('enabled', {
|
||||||
|
valuePropName: 'checked',
|
||||||
|
initialValue: true
|
||||||
|
})(<Switch
|
||||||
|
checkedChildren={<Icon type="check" />}
|
||||||
|
unCheckedChildren={<Icon type="close" />}
|
||||||
|
/>)}
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item {...tailFormItemLayout}>
|
||||||
|
<Button type="primary" htmlType="submit">
|
||||||
|
Register
|
||||||
|
</Button>
|
||||||
|
</Form.Item>
|
||||||
|
</Form>
|
||||||
|
</Card>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ClusterForm;
|
|
@ -0,0 +1,87 @@
|
||||||
|
import React from 'react';
|
||||||
|
import {Button, Card, Col, Divider, Form, Input, Row, Table,Switch, Icon} from "antd";
|
||||||
|
import Link from "_umi@2.13.16@umi/link";
|
||||||
|
|
||||||
|
@Form.create()
|
||||||
|
class Index extends React.Component {
|
||||||
|
columns = [{
|
||||||
|
title: '集群名称',
|
||||||
|
dataIndex: 'name',
|
||||||
|
key: 'name',
|
||||||
|
},{
|
||||||
|
title: '集群访问URL',
|
||||||
|
dataIndex: 'endpoint',
|
||||||
|
key: 'endpoint',
|
||||||
|
},{
|
||||||
|
title: '用户名',
|
||||||
|
dataIndex: 'username',
|
||||||
|
key: 'username',
|
||||||
|
},{
|
||||||
|
title: '密码',
|
||||||
|
dataIndex: 'password',
|
||||||
|
key: 'password',
|
||||||
|
},{
|
||||||
|
title: '排序权重',
|
||||||
|
dataIndex: 'order',
|
||||||
|
key: 'order',
|
||||||
|
},{
|
||||||
|
title: '描述',
|
||||||
|
dataIndex: 'description',
|
||||||
|
key: 'description',
|
||||||
|
},{
|
||||||
|
title: '是否启用',
|
||||||
|
dataIndex: 'enabled',
|
||||||
|
key: 'enabled',
|
||||||
|
}]
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const {getFieldDecorator} = this.props.form;
|
||||||
|
const formItemLayout = {
|
||||||
|
labelCol: { span: 10 },
|
||||||
|
wrapperCol: { span: 14 },
|
||||||
|
style: {marginBottom: 0}
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<Card>
|
||||||
|
<Form>
|
||||||
|
<Row gutter={{md:16, sm:8}}>
|
||||||
|
<Col md={8} sm={10}>
|
||||||
|
<Form.Item {...formItemLayout} label="集群名称">
|
||||||
|
{getFieldDecorator('name')(<Input placeholder="please input cluster name" />)}
|
||||||
|
</Form.Item>
|
||||||
|
</Col>
|
||||||
|
<Col md={8} sm={8}>
|
||||||
|
<div style={{paddingTop:4}}>
|
||||||
|
<Button type="primary" icon="search" onClick={this.handleSearch}>
|
||||||
|
Search
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</Form>
|
||||||
|
<Divider style={{marginBottom:0}} />
|
||||||
|
<Card
|
||||||
|
bodyStyle={{padding:0}}
|
||||||
|
extra={<div>
|
||||||
|
<span style={{marginRight:24}}><Switch
|
||||||
|
checkedChildren={<Icon type="check" />}
|
||||||
|
unCheckedChildren={<Icon type="close" />}
|
||||||
|
defaultChecked
|
||||||
|
/>是否启用</span>
|
||||||
|
<Link to='/system/cluster/new'> <Button type="primary" icon="plus">New</Button></Link>
|
||||||
|
</div>}
|
||||||
|
bordered={false}>
|
||||||
|
<Table
|
||||||
|
bordered
|
||||||
|
columns={this.columns}
|
||||||
|
dataSource={[]}
|
||||||
|
rowKey='id'
|
||||||
|
/>
|
||||||
|
</Card>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Index;
|
Loading…
Reference in New Issue