feat(cluster): 增加集群导入

This commit is contained in:
wangzhengkun
2021-06-03 17:28:44 +08:00
parent 672f9968c5
commit 6e1e8e734f
11 changed files with 272 additions and 18 deletions

View File

@@ -0,0 +1,101 @@
package cluster
import (
kContext "context"
"fmt"
v1 "github.com/KubeOperator/ekko/internal/model/v1"
v1Cluster "github.com/KubeOperator/ekko/internal/model/v1/cluster"
"github.com/KubeOperator/ekko/internal/service/v1/cluster"
"github.com/KubeOperator/ekko/internal/util/kubernetes"
"github.com/asdine/storm/v3"
"github.com/google/uuid"
"github.com/kataras/iris/v12"
"github.com/kataras/iris/v12/context"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
type Handler struct {
clusterService cluster.Cluster
}
func NewHandler() *Handler {
return &Handler{
clusterService: cluster.NewClusterService(),
}
}
func (h *Handler) Create() iris.Handler {
return func(ctx *context.Context) {
var clusterImport Import
if err := ctx.ReadJSON(&clusterImport); err != nil {
ctx.StatusCode(iris.StatusBadRequest)
ctx.Values().Set("message", err.Error())
return
}
c, err := h.clusterService.Get(clusterImport.Name)
if err != nil && err != storm.ErrNotFound {
ctx.StatusCode(iris.StatusBadRequest)
ctx.Values().Set("message", fmt.Sprintf("error: %s", err.Error()))
return
}
if c != nil && c.Name != "" {
ctx.StatusCode(iris.StatusBadRequest)
ctx.Values().Set("message", fmt.Sprintf("cluster name %s is alerady exist", clusterImport.Name))
return
}
client, err := kubernetes.NewKubernetesClient(&kubernetes.Config{
Host: clusterImport.ApiServer,
Token: clusterImport.Token,
})
if err != nil {
ctx.StatusCode(iris.StatusBadRequest)
ctx.Values().Set("message", fmt.Sprintf("import cluster filed: %s", err.Error()))
return
}
_, err = client.CoreV1().Namespaces().List(kContext.TODO(), metav1.ListOptions{})
if err != nil {
ctx.StatusCode(iris.StatusBadRequest)
ctx.Values().Set("message", fmt.Sprintf("import cluster failed: %s", err.Error()))
return
}
cs := v1Cluster.Cluster{
Metadata: v1.Metadata{
Name: clusterImport.Name,
UUID: uuid.New().String(),
},
Token: clusterImport.Token,
Router: clusterImport.Router,
ApiServer: clusterImport.ApiServer,
Status: "Running",
}
err = h.clusterService.Create(&cs)
if err != nil {
ctx.StatusCode(iris.StatusBadRequest)
ctx.Values().Set("message", fmt.Sprintf("create cluster failed: %s", err.Error()))
return
}
ctx.StatusCode(iris.StatusOK)
ctx.Values().Set("data", cs)
}
}
func (h *Handler) ListAll() iris.Handler {
return func(ctx *context.Context) {
var clusters []v1Cluster.Cluster
clusters, err := h.clusterService.All()
if err != nil {
ctx.StatusCode(iris.StatusBadRequest)
ctx.Values().Set("message", fmt.Sprintf("get clusters failed: %s", err.Error()))
return
}
ctx.StatusCode(iris.StatusOK)
ctx.Values().Set("data", clusters)
}
}
func Install(parent iris.Party) {
handler := NewHandler()
sp := parent.Party("/clusters")
sp.Post("", handler.Create())
sp.Get("", handler.ListAll())
}

View File

@@ -0,0 +1,8 @@
package cluster
type Import struct {
Name string `json:"name"`
ApiServer string `json:"apiServer"`
Router string `json:"router"`
Token string `json:"token"`
}

View File

@@ -1,6 +1,7 @@
package v1
import (
"github.com/KubeOperator/ekko/internal/api/v1/cluster"
"github.com/KubeOperator/ekko/internal/api/v1/session"
"github.com/kataras/iris/v12"
)
@@ -8,4 +9,5 @@ import (
func AddV1Route(app iris.Party) {
v1Party := app.Party("/v1")
session.Install(v1Party)
cluster.Install(v1Party)
}

View File

@@ -0,0 +1,12 @@
package cluster
import v1 "github.com/KubeOperator/ekko/internal/model/v1"
type Cluster struct {
v1.BaseModel `storm:"inline"`
v1.Metadata `storm:"inline"`
ApiServer string `json:"apiServer"`
Router string `json:"router"`
Token string `json:"token"`
Status string `json:"status"`
}

View File

@@ -0,0 +1,42 @@
package cluster
import (
v1Cluster "github.com/KubeOperator/ekko/internal/model/v1/cluster"
"github.com/KubeOperator/ekko/internal/server"
)
type Cluster interface {
Create(cluster *v1Cluster.Cluster) error
Get(name string) (*v1Cluster.Cluster, error)
All() ([]v1Cluster.Cluster, error)
}
func NewClusterService() Cluster {
return &cluster{}
}
type cluster struct {
}
func (c *cluster) Create(cluster *v1Cluster.Cluster) error {
db := server.DB()
return db.Save(cluster)
}
func (c *cluster) Get(name string) (*v1Cluster.Cluster, error) {
db := server.DB()
var cluster v1Cluster.Cluster
if err := db.One("Name", name, &cluster); err != nil {
return nil, err
}
return &cluster, nil
}
func (c *cluster) All() ([]v1Cluster.Cluster, error) {
db := server.DB()
var clusters []v1Cluster.Cluster
if err := db.All(&clusters); err != nil {
return nil, err
}
return clusters, nil
}

View File

@@ -0,0 +1,23 @@
package kubernetes
import (
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
)
type Config struct {
Host string
Token string
}
func NewKubernetesClient(c *Config) (*kubernetes.Clientset, error) {
kubeConf := &rest.Config{
Host: c.Host,
BearerToken: c.Token,
TLSClientConfig: rest.TLSClientConfig{
Insecure: true,
},
}
return kubernetes.NewForConfig(kubeConf)
}

View File

@@ -0,0 +1,23 @@
package kubernetes
import (
"context"
"fmt"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"testing"
)
func TestNewKubernetesClient(t *testing.T) {
c, err := NewKubernetesClient(&Config{
Host: "172.16.10.125:8443",
Token: "eyJhbGciOiJSUzI1NiIsImtpZCI6Ii1odW5XaTdXY1ZTZmdRWVJFLTN4aUhLemttN21mOV83TG9jbmp5dzJtR1kifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJrby1hZG1pbi10b2tlbi05c21kMiIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hbWUiOiJrby1hZG1pbiIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjhjYTNlZjExLWU3YTMtNGU2Zi1iNzljLTI2NzMzZDY1MmQ5ZiIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDprdWJlLXN5c3RlbTprby1hZG1pbiJ9.ntgCFo_UL8Hah69Nba__RwJbUGEvznUFAWX2XRXII5kexC_av5isAp3rJyv-Lqq_qGd9mJcDGm0TodMo4sP46qsMuKQ-LM6-lvCK77-y5wnGuqyXjT9C6-h7nOfP55gCaOX9mNY40l2fgjVVLcaaTklB9-QceRFgOzfjRZGwcExyL-JNepw78yMnRM_g1fV4w1VduBqniOgoM5uzACJPO-viyoZPmedCadMlnKhJnETshAe_zNZT9yZ90ujwprI9znrJLt6szLmQgK24EbcG4KF3T9PLyIBO_K0clG_U36Q14DowCLRenKZw9HOsU-AbAzwIGMjj2x8QohGDMZglRw",
})
if err != nil {
fmt.Println(err)
}
l, err := c.CoreV1().ServiceAccounts("default").List(context.TODO(), metav1.ListOptions{})
if err != nil {
fmt.Println(err)
}
fmt.Println(l)
}

11
ui/src/api/clusters.js Normal file
View File

@@ -0,0 +1,11 @@
import {post,get} from "@/plugins/request"
const authUrl = "/api/v1/clusters"
export function create(data) {
return post(authUrl, data)
}
export function listAll(){
return get(authUrl)
}

View File

@@ -1,18 +1,32 @@
<template>
<layout-content :header="$t('business.cluster.import')" :back-to="{ name: 'ClusterList' }">
<layout-content :header="$t('business.cluster.import')" :back-to="{ name: 'ClusterList' }">
<el-row>
<el-col :span="4"><br/></el-col>
<el-col :span="10">
<div class="grid-content bg-purple-light">
<el-form :model="form" label-position="left" :rules="rules" label-width="120px">
<el-form-item :label="$t('commons.table.name')" prop="name">
<el-input style="width: 100%" v-model="form.name" clearable></el-input>
</el-form-item>
<el-form-item style="float: right">
<el-button @click="onCancel()">{{ $t("commons.button.cancel") }}</el-button>
<el-button v-loading="loading" @click="onSubmit" type="primary">{{ $t("commons.button.create") }}</el-button>
</el-form-item>
</el-form>
<el-form :model="form" label-position="left" :rules="rules" label-width="120px">
<el-form-item :label="$t('commons.table.name')" prop="name">
<el-input v-model="form.name" clearable></el-input>
</el-form-item>
<el-form-item label="apiServer" prop="apiServer">
<el-input v-model="form.apiServer" :placeholder="$t('business.cluster.api_server_help')"
clearable></el-input>
</el-form-item>
<el-form-item label="router" prop="router">
<el-input v-model="form.router" :placeholder="$t('business.cluster.router_help')" clearable></el-input>
</el-form-item>
<el-form-item label="token" prop="token">
<el-input type="textarea" :autosize="{ minRows: 2}" style="width: 100%" v-model="form.token"
clearable></el-input>
</el-form-item>
<el-form-item style="float: right">
<el-button @click="onCancel()">{{ $t("commons.button.cancel") }}</el-button>
<el-button v-loading="loading" @click="onSubmit" type="primary">{{
$t("commons.button.create")
}}
</el-button>
</el-form-item>
</el-form>
</div>
</el-col>
</el-row>
@@ -21,26 +35,35 @@
<script>
import LayoutContent from "@/components/layout/LayoutContent"
import {create} from "@/api/clusters"
export default {
name: "ClusterImport",
components: { LayoutContent },
data() {
data () {
return {
form: {
name: ""
name: "",
apiServer: "",
router: "",
token: ""
},
rules: {},
loading: false
}
},
methods: {
onCancel() {
onCancel () {
this.$router.push({ name: "ClusterList" })
},
onSubmit() {
onSubmit () {
create(this.form).then(() => {
this.$message({
type: "success",
message: this.$t("创建成功")
})
})
}
},
}

View File

@@ -25,6 +25,7 @@
<script>
import LayoutContent from "@/components/layout/LayoutContent"
import ComplexTable from "@/components/complex-table"
import {listAll} from "@/api/clusters"
export default {
name: "ClusterList",
@@ -50,8 +51,6 @@ export default {
],
},
data: [
{ name: "测试" },
{ name: "测试2" }
],
selects: []
}
@@ -60,6 +59,14 @@ export default {
onImport () {
this.$router.push({ name: "ClusterImport" })
},
list() {
listAll().then(res => {
this.data =res.data
})
}
},
created () {
this.list()
}
}
</script>

View File

@@ -58,7 +58,9 @@ const message = {
cluster: {
cluster: "集群",
list: "集群列表",
import: "导入集群"
import: "导入集群",
api_server_help: "例如: https://172.16.10.100:8443",
router_help: "装有 kube-proxy 的任意节点的且可以被访问到的 IP 地址",
},
workload: {
workload: "工作量"