Skip to content

Commit

Permalink
feature: add alarm list and disarm support for kstone-api
Browse files Browse the repository at this point in the history
  • Loading branch information
lianghao208 committed Dec 18, 2021
1 parent c7553fa commit 8bc9f4e
Show file tree
Hide file tree
Showing 7 changed files with 416 additions and 211 deletions.
73 changes: 73 additions & 0 deletions pkg/clusterprovider/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ import (
"tkestack.io/kstone/pkg/etcd"
)

type EtcdAlarm struct {
MemberID uint64
AlarmType string
}

// GetStorageMemberEndpoints get member of cluster status
func GetStorageMemberEndpoints(cluster *kstoneapiv1.EtcdCluster) []string {
members := cluster.Status.Members
Expand Down Expand Up @@ -182,3 +187,71 @@ func GetEtcdClusterMemberStatus(

return newMembers, clusterStatus
}

// GetEtcdAlarms get alarm list of etcd
func GetEtcdAlarms(
endpoints []string,
tls *transport.TLSInfo) ([]EtcdAlarm, error) {
etcdAlarms := make([]EtcdAlarm, 0)

ca, cert, key := "", "", ""
if tls != nil {
ca, cert, key = tls.TrustedCAFile, tls.CertFile, tls.KeyFile
}

// GetAlarmList
client, err := etcd.NewClientv3(ca, cert, key, endpoints)
if err != nil {
klog.Errorf("failed to get new etcd clientv3, err is %v ", err)
return etcdAlarms, err
}
defer client.Close()

alarmRsp, err := etcd.AlarmList(client)
if err != nil {
klog.Errorf("failed to get alarm list, err is %v", err)
return etcdAlarms, err
}

for _, a := range alarmRsp.Alarms {
etcdAlarms = append(etcdAlarms, EtcdAlarm{
MemberID: a.MemberID,
AlarmType: a.Alarm.String(),
})
}
return etcdAlarms, nil
}

// DisarmEtcdAlarms disarm alarm of etcd
func DisarmEtcdAlarm(
endpoints []string,
tls *transport.TLSInfo) ([]EtcdAlarm, error) {
etcdAlarms := make([]EtcdAlarm, 0)

ca, cert, key := "", "", ""
if tls != nil {
ca, cert, key = tls.TrustedCAFile, tls.CertFile, tls.KeyFile
}

// DisarmEtcdAlarm
client, err := etcd.NewClientv3(ca, cert, key, endpoints)
if err != nil {
klog.Errorf("failed to get new etcd clientv3, err is %v ", err)
return etcdAlarms, err
}
defer client.Close()

disarmRsp, err := etcd.AlarmDisarm(client)
if err != nil {
klog.Errorf("failed to get member list, err is %v", endpoints, err)
return etcdAlarms, err
}

for _, a := range disarmRsp.Alarms {
etcdAlarms = append(etcdAlarms, EtcdAlarm{
MemberID: a.MemberID,
AlarmType: a.Alarm.String(),
})
}
return etcdAlarms, nil
}
28 changes: 28 additions & 0 deletions pkg/etcd/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -305,3 +305,31 @@ func getTransport(dialTimeout, totalTimeout time.Duration, scfg *secureConfig, s
DisableKeepAlives: true,
}, nil
}

// AlarmList list etcd alarm
func AlarmList(cli *clientv3.Client) (*clientv3.AlarmResponse, error) {
ctx, cancel := context.WithTimeout(context.Background(), DefaultDialTimeout)
defer cancel()

rsp, err := cli.AlarmList(ctx)
if err != nil {
klog.Errorf("failed list etcd alarm,err is %v", err)
return rsp, err
}
klog.V(6).Infof("list etcd alarm succ,resp info %v", rsp)
return rsp, err
}

// AlarmDisarm disarm etcd alarm
func AlarmDisarm(cli *clientv3.Client) (*clientv3.AlarmResponse, error) {
ctx, cancel := context.WithTimeout(context.Background(), DefaultDialTimeout)
defer cancel()

rsp, err := cli.AlarmDisarm(ctx, &clientv3.AlarmMember{})
if err != nil {
klog.Errorf("failed disarm etcd alarm,err is %v", err)
return rsp, err
}
klog.V(6).Infof("disarm etcd alarm succ,resp info %v", rsp)
return rsp, err
}
37 changes: 37 additions & 0 deletions pkg/router/alarm.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* Tencent is pleased to support the open source community by making TKEStack
* available.
*
* Copyright (C) 2012-2023 Tencent. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use
* this file except in compliance with the License. You may obtain a copy of the
* License at
*
* https://opensource.org/licenses/Apache-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/

package router

import (
"github.com/gin-gonic/gin"

"tkestack.io/kstone/pkg/clusterprovider"
)

// AlarmList returns alarm list
func AlarmList(ctx *gin.Context) {
cluster, tlsConfig := GetEtcdClusterInfo(ctx)
clusterprovider.GetEtcdAlarms([]string{cluster.Status.ServiceName}, tlsConfig)
}

// AlarmList returns alarm list
func AlarmDisarm(ctx *gin.Context) {
cluster, tlsConfig := GetEtcdClusterInfo(ctx)
clusterprovider.DisarmEtcdAlarm([]string{cluster.Status.ServiceName}, tlsConfig)
}
73 changes: 73 additions & 0 deletions pkg/router/backup.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
* Tencent is pleased to support the open source community by making TKEStack
* available.
*
* Copyright (C) 2012-2023 Tencent. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use
* this file except in compliance with the License. You may obtain a copy of the
* License at
*
* https://opensource.org/licenses/Apache-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/

package router

import (
"encoding/json"
"fmt"
"net/http"

"github.com/gin-gonic/gin"
"k8s.io/klog/v2"

"tkestack.io/kstone/pkg/backup"
)

// BackupList returns backup list
func BackupList(ctx *gin.Context) {
cluster, _ := GetEtcdClusterInfo(ctx)

// generate backup config
strCfg, found := cluster.Annotations[backup.AnnoBackupConfig]
if !found || strCfg == "" {
err := fmt.Errorf(
"backup config not found, annotation key %s not exists, namespace is %s, name is %s",
backup.AnnoBackupConfig,
cluster.Namespace,
cluster.Name,
)
klog.Errorf(err.Error())
ctx.JSON(http.StatusOK, []interface{}{})
return
}
backupConfig := &backup.Config{}
err := json.Unmarshal([]byte(strCfg), backupConfig)
if err != nil {
klog.Errorf(err.Error())
ctx.JSON(http.StatusInternalServerError, err)
return
}

// generate backup provider
backupProvider, err := backup.GetBackupProvider(string(backupConfig.StorageType), &backup.ProviderConfig{
Kubeconfig: "",
})
if err != nil {
klog.Errorf(err.Error())
ctx.JSON(http.StatusInternalServerError, err)
return
}
resp, err := backupProvider.List(cluster)
if err != nil {
klog.Errorf(err.Error())
ctx.JSON(http.StatusInternalServerError, err)
return
}
ctx.JSON(http.StatusOK, resp)
}
122 changes: 122 additions & 0 deletions pkg/router/key.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
/*
* Tencent is pleased to support the open source community by making TKEStack
* available.
*
* Copyright (C) 2012-2023 Tencent. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use
* this file except in compliance with the License. You may obtain a copy of the
* License at
*
* https://opensource.org/licenses/Apache-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/

package router

import (
"context"
"net/http"

"github.com/gin-gonic/gin"
clientv3 "go.etcd.io/etcd/client/v3"
"k8s.io/klog/v2"

"tkestack.io/kstone/pkg/etcd"
)

// EtcdKeyList returns etcd key list
func EtcdKeyList(ctx *gin.Context) {
etcdKey := ctx.DefaultQuery("key", "")

cluster, tlsConfig := GetEtcdClusterInfo(ctx)

ca, cert, key := "", "", ""
if tlsConfig != nil {
ca, cert, key = tlsConfig.TrustedCAFile, tlsConfig.CertFile, tlsConfig.KeyFile
}
klog.Infof("endpoint: %s, ca: %s, cert: %s, key: %s", cluster.Status.ServiceName, ca, cert, key)
client, err := etcd.NewClientv3(ca, cert, key, []string{cluster.Status.ServiceName})
if err != nil {
klog.Errorf(err.Error())
ctx.JSON(http.StatusInternalServerError, err)
return
}
defer client.Close()

if etcdKey == "" {
resp, err := client.Get(context.TODO(), "", clientv3.WithPrefix(), clientv3.WithKeysOnly())
if err != nil {
klog.Errorf(err.Error())
ctx.JSON(http.StatusInternalServerError, err)
return
}

data := make([]string, 0)
for _, value := range resp.Kvs {
data = append(data, string(value.Key))
}

ctx.JSON(http.StatusOK, map[string]interface{}{
"code": 0,
"data": data,
})
return
}
klog.Infof("get value by key: %s", etcdKey)
resp, err := client.Get(context.TODO(), etcdKey, clientv3.WithPrefix())
if err != nil {
klog.Errorf(err.Error())
ctx.JSON(http.StatusInternalServerError, err)
return
}
if resp.Count == 0 {
ctx.JSON(http.StatusNotFound, map[string]interface{}{
"code": 1,
"data": "",
})
} else {
result := map[string]interface{}{
"code": 0,
"err": "",
}
if cluster.Annotations["kubernetes"] == "true" && etcdKey != "compact_rev_key" {
jsonValue := etcd.ConvertToJSON(resp.Kvs[0])
inMediaType, in, err := etcd.DetectAndExtract(resp.Kvs[0].Value)
if err != nil {
klog.Errorf(err.Error())
ctx.JSON(http.StatusInternalServerError, err)
return
}
respData, err := etcd.ConvertToData(inMediaType, in)
if err != nil {
klog.Errorf(err.Error())
if respData == nil {
respData = make(map[string]string)
}
result["err"] = err.Error()
}
respData["json"] = jsonValue
respDataList := make([]map[string]string, 0)
for dataType, value := range respData {
respDataList = append(respDataList, map[string]string{
"type": dataType,
"data": value,
})
}
result["data"] = respDataList
} else {
result["data"] = []map[string]string{
{
"type": "javascript",
"data": string(resp.Kvs[0].Value),
},
}
}
ctx.JSON(http.StatusOK, result)
}
}
Loading

0 comments on commit 8bc9f4e

Please sign in to comment.