Skip to content

Commit

Permalink
add configCenter module, support aliyun mse instance and config query
Browse files Browse the repository at this point in the history
  • Loading branch information
liuxinwang committed Dec 6, 2023
1 parent 21564d8 commit 17606f7
Show file tree
Hide file tree
Showing 9 changed files with 633 additions and 1 deletion.
6 changes: 6 additions & 0 deletions config/parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,19 @@ type Log struct {
Level string
}

type Aliyun struct {
AccessKeyId string
AccessKeySecret string
}

type Config struct {
General General
Mysql Mysql
Prometheus Prometheus
DingWebhook DingWebhook
GoInception GoInception
Log Log
Aliyun Aliyun
}

var Conf Config
Expand Down
13 changes: 12 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,15 @@ go 1.20

require (
github.com/BurntSushi/toml v1.3.2
github.com/alibabacloud-go/darabonba-openapi/v2 v2.0.5
github.com/alibabacloud-go/openapi-util v0.1.0
github.com/alibabacloud-go/tea v1.2.1
github.com/alibabacloud-go/tea-utils/v2 v2.0.4
github.com/appleboy/gin-jwt/v2 v2.8.0
github.com/gin-gonic/gin v1.8.1
github.com/go-demo/version v0.0.0-20200109120206-2cde9473fd92
github.com/json-iterator/go v1.1.12
github.com/pingcap/tidb v1.1.0-beta.0.20230808082424-40b72e7a9a4f
github.com/pingcap/tidb/parser v0.0.0-20230808082424-40b72e7a9a4f
github.com/prometheus/client_golang v1.16.0
github.com/robfig/cron/v3 v3.0.1
github.com/shopspring/decimal v1.3.1
Expand All @@ -28,9 +31,15 @@ require (
github.com/DataDog/go-tuf v0.3.0--fix-localmeta-fork // indirect
github.com/DataDog/sketches-go v1.4.1 // indirect
github.com/Microsoft/go-winio v0.6.0 // indirect
github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.4 // indirect
github.com/alibabacloud-go/debug v0.0.0-20190504072949-9472017b5c68 // indirect
github.com/alibabacloud-go/tea-utils v1.3.1 // indirect
github.com/alibabacloud-go/tea-xml v1.1.3 // indirect
github.com/aliyun/credentials-go v1.3.1 // indirect
github.com/benbjohnson/clock v1.3.5 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/clbanning/mxj/v2 v2.5.5 // indirect
github.com/cloudfoundry/gosigar v1.3.6 // indirect
github.com/cockroachdb/errors v1.8.1 // indirect
github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f // indirect
Expand Down Expand Up @@ -85,6 +94,7 @@ require (
github.com/pingcap/kvproto v0.0.0-20230728080053-8a9db88bc88a // indirect
github.com/pingcap/log v1.1.1-0.20230317032135-a0d097d16e22 // indirect
github.com/pingcap/sysutil v1.0.1-0.20230407040306-fb007c5aff21 // indirect
github.com/pingcap/tidb/parser v0.0.0-20230808082424-40b72e7a9a4f // indirect
github.com/pingcap/tipb v0.0.0-20230607071926-bda24015c2d6 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b // indirect
Expand All @@ -106,6 +116,7 @@ require (
github.com/tikv/client-go/v2 v2.0.8-0.20230731032349-719e6456f7d5 // indirect
github.com/tikv/pd/client v0.0.0-20230724080549-de985b8e0afc // indirect
github.com/tinylib/msgp v1.1.8 // indirect
github.com/tjfoc/gmsm v1.3.2 // indirect
github.com/tklauser/go-sysconf v0.3.11 // indirect
github.com/tklauser/numcpus v0.6.0 // indirect
github.com/twmb/murmur3 v1.1.6 // indirect
Expand Down
18 changes: 18 additions & 0 deletions handler/ConfigCenterHandler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package handler

import (
"github.com/gin-gonic/gin"
"horizon/service"
)

func ConfigCenterInstanceGet(c *gin.Context) {
service.ConfigCenterInstanceSelectByList(c)
}

func ConfigCenterInstanceConfigGet(c *gin.Context) {
service.ConfigCenterInstanceConfigSelectByList(c)
}

func ConfigCenterInstanceConfigDataGet(c *gin.Context) {
service.ConfigCenterInstanceConfigSelectByData(c)
}
53 changes: 53 additions & 0 deletions model/ConfigCenter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package model

type ConfigCenterInstance struct {
MseVersion string `json:"mseVersion"`
InternetAddress string `json:"internetAddress"`
ResourceGroupId string `json:"resourceGroupId"`
InstanceId string `json:"instanceId"`
ClusterId string `json:"clusterId"`
CreateTime string `json:"createTime"`
ClusterType string `json:"clusterType"`
EndDate string `json:"endDate"`
ClusterAliasName string `json:"clusterAliasName"`
AppVersion string `json:"appVersion"`
VersionCode string `json:"versionCode"`
InstanceCount int `json:"instanceCount"`
IntranetAddress string `json:"intranetAddress"`
CanUpdate bool `json:"canUpdate"`
VpcId string `json:"vpcId"`
ChargeType string `json:"chargeType"`
ClusterName string `json:"clusterName"`
InitStatus string `json:"initStatus"`
MaintenancePeriod struct {
} `json:"maintenancePeriod"`
IntranetDomain string `json:"intranetDomain"`
Tags struct {
AcsRmRgId string `json:"acs:rm:rgId"`
} `json:"tags"`
Namespaces []ConfigCenterNamespace `json:"namespaces"`
}

type ConfigCenterNamespace struct {
Type int `json:"type"`
Quota int `json:"quota"`
ConfigCount int `json:"configCount"`
SourceType string `json:"sourceType"`
NamespaceShowName string `json:"namespaceShowName"`
Namespace string `json:"namespace"`
ServiceCount int `json:"serviceCount"`
NamespaceId string `json:"namespaceId" form:"namespaceId"`
}

type ConfigCenterInstanceConfig struct {
Group string `json:"group" form:"group"`
Desc string `json:"desc" form:"desc"`
Type string `json:"type" form:"type"`
DataId string `json:"dataId" form:"dataId"`
EncryptedDataKey string `json:"encryptedDataKey" form:"encryptedDataKey"`
Content string `json:"content" form:"content"`
AppName string `json:"appName" form:"appName"`
Md5 string `json:"md5" form:"md5"`
InstanceId string `json:"instanceId" form:"instanceId"`
NamespaceId string `json:"namespaceId" form:"namespaceId"`
}
23 changes: 23 additions & 0 deletions model/DataMigrate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package model

import "time"

type DataMigrateJob struct {
ID uint `gorm:"primaryKey;comment:主键ID" json:"id"`
Name string `gorm:"type:varchar(50);not null;comment:任务名称" json:"name"`
SourceInstId string `gorm:"type:varchar(20);not null;comment:源实例ID" json:"sourceInstId"`
SourceDb string `gorm:"type:varchar(20);not null;comment:源数据库" json:"sourceDb"`
TargetInstId string `gorm:"type:varchar(20);not null;comment:目的实例ID" json:"targetInstId"`
TargetDb string `gorm:"type:varchar(20);not null;comment:目的数据库" json:"targetDb"`
Status string `gorm:"type:enum('Start', 'Stop', 'Running', 'Error', 'Finished');default:'Running';not null;comment:任务状态" json:"status"`
CreatedAt time.Time `gorm:"type:datetime;not null;default:current_timestamp;comment:创建时间" json:"createdAt"`
UpdatedAt time.Time `gorm:"type:datetime;not null;default:current_timestamp on update current_timestamp;comment:修改时间" json:"updatedAt"`
}

type DataMigrateJobDetail struct {
ID uint `gorm:"primaryKey;comment:主键ID" json:"id"`
TableName string `gorm:"type:varchar(50);not null;comment:表名称" json:"tableName"`
Status string `gorm:"type:enum('Start', 'Stop', 'Running', 'Error');default:'Running';not null;comment:同步状态" json:"status"`
CreatedAt time.Time `gorm:"type:datetime;not null;default:current_timestamp;comment:创建时间" json:"createdAt"`
UpdatedAt time.Time `gorm:"type:datetime;not null;default:current_timestamp on update current_timestamp;comment:修改时间" json:"updatedAt"`
}
9 changes: 9 additions & 0 deletions router/Router.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,4 +120,13 @@ func commonRouter(r *gin.Engine) {
workflowTemplate.PUT("edit", handler.WorkflowTemplatePut)
workflowTemplate.DELETE("/:id", handler.WorkflowTemplateDelete)
workflowTemplate.POST("/config", handler.WorkflowTemplateConfigPost)

// configCenter group
configCenter := api.Group("/configCenter", authMiddleware.MiddlewareFunc())
configCenterInstance := configCenter.Group("/instance", authMiddleware.MiddlewareFunc())
configCenterInstance.GET("query", handler.ConfigCenterInstanceGet)

configCenterInstanceConfig := configCenter.Group("/config", authMiddleware.MiddlewareFunc())
configCenterInstanceConfig.GET("query", handler.ConfigCenterInstanceConfigGet)
configCenterInstanceConfig.GET("detail", handler.ConfigCenterInstanceConfigDataGet)
}
208 changes: 208 additions & 0 deletions service/ConfigCenterService.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
package service

import (
"encoding/json"
"github.com/gin-gonic/gin"
"github.com/mitchellh/mapstructure"
"gopkg.in/yaml.v3"
"horizon/model"
"horizon/utils"
"math"
"net/http"
"strconv"
"strings"
)

// ConfigCenterInstanceSelectByList 查询实例列表
func ConfigCenterInstanceSelectByList(c *gin.Context) {
// 变量初始化
pageNo, _ := strconv.Atoi(c.Query("pageNo"))
pageSize, _ := strconv.Atoi(c.Query("pageSize"))
clusterAliasName := c.Query("clusterAliasName")
var configCenterInstances []model.ConfigCenterInstance
var totalCount int64
data := gin.H{"totalCount": 0, "data": &[]model.ConfigCenterInstance{}, "pageNo": pageNo, "pageSize": pageSize, "totalPage": 0}

clusters, err := utils.ListClusters(pageNo, pageSize, clusterAliasName)
if err != nil {
c.JSON(http.StatusOK, gin.H{"code": 0, "msg": "fail", "data": data, "err": err.Error()})
return
}
body := clusters["body"]
if b, ok := body.(map[string]interface{}); ok {
instanceData := b["Data"]
if tc, isInt := b["TotalCount"].(json.Number); isInt {
totalCount, _ = tc.Int64()
}
if d, ok2 := instanceData.([]interface{}); ok2 {
for _, cluster := range d {
var configCenterInstance model.ConfigCenterInstance
err := mapstructure.Decode(cluster, &configCenterInstance)
if err != nil {
c.JSON(http.StatusOK, gin.H{"code": 0, "msg": "fail", "data": data, "err": err.Error()})
return
}
// 查询实例空间
namespaces, err := configCenterInstanceNamespaceSelectByList(configCenterInstance.InstanceId)
if err != nil {
c.JSON(http.StatusOK, gin.H{"code": 0, "msg": "fail", "data": data, "err": err.Error()})
return
}
configCenterInstance.Namespaces = namespaces
configCenterInstances = append(configCenterInstances, configCenterInstance)
}
}
}

// 处理结果集并返回
totalPage := math.Ceil(float64(totalCount) / float64(pageSize))
if totalCount > 0 {
data = gin.H{"totalCount": totalCount, "data": &configCenterInstances, "pageNo": pageNo, "pageSize": pageSize, "totalPage": totalPage}
}
c.JSON(http.StatusOK, gin.H{"code": 1, "msg": "success", "data": data, "err": ""})
}

// configCenterInstanceNamespaceSelectByList 查询实例命名空间列表
func configCenterInstanceNamespaceSelectByList(instanceId string) ([]model.ConfigCenterNamespace, error) {
var configCenterNamespaces []model.ConfigCenterNamespace
namespaces, err := utils.ListEngineNamespaces(instanceId)
if err != nil {
return nil, err
}
body := namespaces["body"]
if b, ok := body.(map[string]interface{}); ok {
namespaceData := b["Data"]
if d, ok2 := namespaceData.([]interface{}); ok2 {
for _, namespace := range d {
var configCenterNamespace model.ConfigCenterNamespace
err := mapstructure.Decode(namespace, &configCenterNamespace)
if err != nil {
return nil, err
}
configCenterNamespace.NamespaceId = configCenterNamespace.NamespaceShowName
configCenterNamespaces = append(configCenterNamespaces, configCenterNamespace)
}
}
}
return configCenterNamespaces, nil
}

// ConfigCenterInstanceConfigSelectByList 查询实例配置列表
func ConfigCenterInstanceConfigSelectByList(c *gin.Context) {
// 变量初始化
pageNo, _ := strconv.Atoi(c.Query("pageNo"))
pageSize, _ := strconv.Atoi(c.Query("pageSize"))
instanceId := c.Query("instanceId")
namespaceId := c.Query("namespaceId")
dataId := c.Query("dataId")
var configCenterInstanceConfigs []model.ConfigCenterInstanceConfig
var totalCount int64
data := gin.H{"totalCount": 0, "data": &[]model.ConfigCenterInstanceConfig{}, "pageNo": pageNo, "pageSize": pageSize, "totalPage": 0}

configs, err := utils.ListNacosConfigs(pageNo, pageSize, instanceId, namespaceId, dataId)
if err != nil {
c.JSON(http.StatusOK, gin.H{"code": 0, "msg": "fail", "data": data, "err": err.Error()})
return
}
body := configs["body"]
if b, ok := body.(map[string]interface{}); ok {
instanceConfigData := b["Configurations"]
if tc, isInt := b["TotalCount"].(json.Number); isInt {
totalCount, _ = tc.Int64()
}
if d, ok2 := instanceConfigData.([]interface{}); ok2 {
for _, config := range d {
var configCenterInstanceConfig model.ConfigCenterInstanceConfig
err := mapstructure.Decode(config, &configCenterInstanceConfig)
if err != nil {
c.JSON(http.StatusOK, gin.H{"code": 0, "msg": "fail", "data": data, "err": err.Error()})
return
}
configCenterInstanceConfig.InstanceId = instanceId
configCenterInstanceConfig.NamespaceId = namespaceId
configCenterInstanceConfigs = append(configCenterInstanceConfigs, configCenterInstanceConfig)
}
}
}

// 处理结果集并返回
totalPage := math.Ceil(float64(totalCount) / float64(pageSize))
if totalCount > 0 {
data = gin.H{"totalCount": totalCount, "data": &configCenterInstanceConfigs, "pageNo": pageNo, "pageSize": pageSize, "totalPage": totalPage}
}
c.JSON(http.StatusOK, gin.H{"code": 1, "msg": "success", "data": data, "err": ""})
}

// ConfigCenterInstanceConfigSelectByData 查看实例配置详情
func ConfigCenterInstanceConfigSelectByData(c *gin.Context) {
var configCenterInstanceConfig model.ConfigCenterInstanceConfig
err := c.ShouldBind(&configCenterInstanceConfig)
if err != nil {
c.JSON(http.StatusOK, gin.H{"code": 0, "msg": "fail", "data": "", "err": err.Error()})
return
}
config, err := utils.GetNacosConfig(
configCenterInstanceConfig.InstanceId,
configCenterInstanceConfig.NamespaceId,
configCenterInstanceConfig.DataId,
configCenterInstanceConfig.Group)

if err != nil {
c.JSON(http.StatusOK, gin.H{"code": 0, "msg": "fail", "data": nil, "err": err.Error()})
return
}
body := config["body"]
if b, ok := body.(map[string]interface{}); ok {
instanceConfigData := b["Configuration"]
err := mapstructure.Decode(instanceConfigData, &configCenterInstanceConfig)
if err != nil {
c.JSON(http.StatusOK, gin.H{"code": 0, "msg": "fail", "data": nil, "err": err.Error()})
return
}
}
desensitizedContent, err := desensitizedYamlConfig(configCenterInstanceConfig.Content)
if err != nil {
c.JSON(http.StatusOK, gin.H{"code": 0, "msg": "fail", "data": nil, "err": err.Error()})
return
}
configCenterInstanceConfig.Content = strings.ReplaceAll(desensitizedContent, " ", " ")
// 返回结果集
c.JSON(http.StatusOK, gin.H{"code": 1, "msg": "success", "data": &configCenterInstanceConfig, "err": ""})
}

func desensitizedYamlConfig(content string) (string, error) {
var dataNode yaml.Node
err := yaml.Unmarshal([]byte(content), &dataNode)
if err != nil {
return "", err
}

flag := 0
iterNode(&dataNode, &flag)
marshal, err := yaml.Marshal(&dataNode)
if err != nil {
return "", err
}
return string(marshal), err
}

func iterNode(node *yaml.Node, flag *int) {
if node.Content != nil && len(node.Content) > 0 {
for _, n := range node.Content {
iterNode(n, flag)
}
} else {
if node.Value == "password" || node.Value == "appSecret" {
*flag = 1
return
}
if *flag == 1 {
desensitizedNode(node)
*flag = 0
}
}
}

func desensitizedNode(node *yaml.Node) {
node.Value = "******"
}
Loading

0 comments on commit 17606f7

Please sign in to comment.