Create & Init Project...
This commit is contained in:
22
app/admin/main/config/BUILD
Normal file
22
app/admin/main/config/BUILD
Normal file
@ -0,0 +1,22 @@
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [
|
||||
":package-srcs",
|
||||
"//app/admin/main/config/cmd:all-srcs",
|
||||
"//app/admin/main/config/conf:all-srcs",
|
||||
"//app/admin/main/config/dao:all-srcs",
|
||||
"//app/admin/main/config/http:all-srcs",
|
||||
"//app/admin/main/config/model:all-srcs",
|
||||
"//app/admin/main/config/pkg/lint:all-srcs",
|
||||
"//app/admin/main/config/service:all-srcs",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
128
app/admin/main/config/CHANGELOG.md
Normal file
128
app/admin/main/config/CHANGELOG.md
Normal file
@ -0,0 +1,128 @@
|
||||
### config-admin
|
||||
#### Version 1.5.21
|
||||
>1. 增加历史版本文件的diff接口
|
||||
>2. 修改lintConfig方法
|
||||
#### Version 1.5.20
|
||||
>1. 修复创建应用时status为0的bug
|
||||
#### Version 1.5.19
|
||||
>1. 应用名显示和隐藏功能
|
||||
#### Version 1.5.17
|
||||
>1. 优化 lint 错误信息
|
||||
>2. 添加 identity lint
|
||||
#### Version 1.5.16
|
||||
>1. 按环境搜索正在使用文件的服务名
|
||||
#### Version 1.5.15
|
||||
>1. 配置中心api接口home/tag/update支持强制更新
|
||||
#### Version 1.5.13
|
||||
>1. 移除检查 toml 文件顶层 kv
|
||||
#### Version 1.5.12
|
||||
>1. 服务树项目权限验证取缓存
|
||||
#### Version 1.5.11
|
||||
>1. 服务树项目权限验证时如果没有任何权限则返回404避免后续方法applist空指针
|
||||
#### Version 1.5.10
|
||||
>1. toml 配置文件后端lint, 语法检查, 不允许顶层KV, 不允许老的 app config
|
||||
>2. json 配置文件后端lint, 语法检查
|
||||
#### Version 1.5.9
|
||||
>1. 保存拷贝的文件时,进行最新源文件判断,最新文件非自己建立的时候进行提示,开启默认验证
|
||||
#### Version 1.5.8
|
||||
>1. 发版获取文件接口更新,从最多获取每个文件6个版本改成20个,同时如果当前发布的文件版本不在其中的话就单独加入
|
||||
>2. 保存拷贝的文件时,进行最新源文件判断,最新文件非自己建立的时候进行提示
|
||||
#### Version 1.5.7
|
||||
>1. 全局面强制发版本时清除单机强制
|
||||
>2. 配置中心app服务名同步
|
||||
#### Version 1.5.6
|
||||
>1. 添加caster获取token接口
|
||||
>2. 修复app接口时间显示的问题
|
||||
>3. 回滚操作更改为重新发一个新版本
|
||||
#### Version 1.5.5
|
||||
>1. 修复权限验证时user获取不到的bug
|
||||
>2. 增加缓存有效时间60秒一更新
|
||||
>3. 增加手动更新缓存功能
|
||||
#### Version 1.5.4
|
||||
>1. 优化返回的message信息
|
||||
#### Version 1.5.3
|
||||
>1. zone复制取消机房值的验证
|
||||
#### Version 1.5.2
|
||||
>1. 公共配置多服务推送bug修复
|
||||
#### Version 1.5.1
|
||||
>1. 公共配置多服务推送
|
||||
#### Version 1.4.4
|
||||
>1. 修复获取文件列表中如果有引用公共配置可能出现的404问题
|
||||
#### Version 1.4.3
|
||||
>1. 修复连续删除的文件会出现在发版中
|
||||
>2. 删除未配置文件导致无法再添加该文件,因此改为只要是删除统一状态改为配置完成
|
||||
#### Version 1.4.2
|
||||
>1. 增加sh003和sh004机房
|
||||
#### Version 1.4.1
|
||||
>1. 添加全局面强制更新及选择主机强制更新功能
|
||||
#### Version 1.3.2
|
||||
>1. configservice client
|
||||
|
||||
#### Version 1.3.1
|
||||
>1. 增加hz001机房
|
||||
#### Version 1.3.0
|
||||
>1. 增加对canal的接口支持
|
||||
>2. req结构体放入model
|
||||
#### Version 1.2.9
|
||||
>1. 修复ctx阻塞连接泄露
|
||||
|
||||
#### Version 1.2.8
|
||||
>1. 修复事务回滚用错的bug
|
||||
#### Version 1.2.7
|
||||
>1. 修复configs接口上一个发版文件id不正确的问题
|
||||
#### Version 1.2.6
|
||||
>1. 修复新项目无法建build的问题
|
||||
|
||||
|
||||
#### Version 1.2.6
|
||||
>1. 平台管理透传功能
|
||||
|
||||
#### Version 1.2.5
|
||||
>1. 修复配置中心文件添加无法成功的问题,form值为0的bind验证有坑
|
||||
|
||||
#### Version 1.2.4
|
||||
>1. 配置获取接口安全权限增加
|
||||
>2. sh001的配置复制到sh002功能
|
||||
>3. 添加文件中选择公共文件的列表只显业配置完成
|
||||
>4. 修改验证模式从pr变为bm的
|
||||
#### Version 1.2.1
|
||||
>1. 修复添加文件时公共文件不是最新的bug
|
||||
|
||||
#### Version 1.2.0
|
||||
>1. bm架构
|
||||
>2. 通过接口添加文件和发版
|
||||
|
||||
#### Version 1.1.3
|
||||
>1. 己删文件隐藏
|
||||
|
||||
#### Version 1.1.2
|
||||
>1. 公共配置
|
||||
|
||||
#### Version 1.1.1
|
||||
>1. configs接口加入is_delete字段显示
|
||||
|
||||
#### Version 1.1.0
|
||||
>1. build删除
|
||||
>2. 文件删除
|
||||
>3. 发版界面改版
|
||||
|
||||
#### Version 1.0.5
|
||||
>1. 迁目录加diff接口
|
||||
|
||||
#### Version 1.0.4
|
||||
>1. bug修复,模糊查询只查询项目名,部门和项目组非模糊查询
|
||||
|
||||
#### Version 1.0.3
|
||||
>1. 修复配置中心的模糊查询功能
|
||||
|
||||
#### Version 1.0.2
|
||||
>1. 修复app列表错误
|
||||
|
||||
#### Version 1.0.1
|
||||
>1. 增加删除版本接口
|
||||
>2. 修复环境列表token错误的bug
|
||||
|
||||
#### Version 1.0.0
|
||||
>1. 提供sven 配置中心模块接口
|
||||
>2. 配置变更通知config-service
|
||||
>3. 从config-service获取主机信息列表
|
14
app/admin/main/config/CONTRIBUTORS.md
Normal file
14
app/admin/main/config/CONTRIBUTORS.md
Normal file
@ -0,0 +1,14 @@
|
||||
# Owner
|
||||
haoguanwei
|
||||
lintanghui
|
||||
chenzhihui
|
||||
|
||||
# Author
|
||||
zhoujixiang
|
||||
lintanghui
|
||||
linli
|
||||
# Reviewer
|
||||
haoguanwei
|
||||
linli
|
||||
lintanghui
|
||||
chenzhihui
|
20
app/admin/main/config/OWNERS
Normal file
20
app/admin/main/config/OWNERS
Normal file
@ -0,0 +1,20 @@
|
||||
# See the OWNERS docs at https://go.k8s.io/owners
|
||||
|
||||
approvers:
|
||||
- chenzhihui
|
||||
- haoguanwei
|
||||
- linli
|
||||
- lintanghui
|
||||
- zhoujixiang
|
||||
labels:
|
||||
- admin
|
||||
- admin/main/config
|
||||
- main
|
||||
options:
|
||||
no_parent_owners: true
|
||||
reviewers:
|
||||
- chenzhihui
|
||||
- haoguanwei
|
||||
- linli
|
||||
- lintanghui
|
||||
- zhoujixiang
|
21
app/admin/main/config/README.md
Normal file
21
app/admin/main/config/README.md
Normal file
@ -0,0 +1,21 @@
|
||||
# go-common/app/admin/config
|
||||
|
||||
##### 项目简介
|
||||
> 1. sven配置中心模块接口
|
||||
> 2. 配置中心推送和主机列表
|
||||
|
||||
##### 编译环境
|
||||
> 1. 请只用golang v1.7.x以上版本编译执行。
|
||||
|
||||
##### 依赖包
|
||||
> 1. 公共依赖
|
||||
|
||||
##### 编译执行
|
||||
> 1. 启动执行
|
||||
> 2. 项目文档http://info.bilibili.co/pages/viewpage.action?pageId=1742325
|
||||
|
||||
##### 测试
|
||||
> 1. 执行当前目录下所有测试文件,测试所有功能
|
||||
|
||||
##### 特别说明
|
||||
> 2. 管理平台地址 http://sven.bilibili.co
|
44
app/admin/main/config/cmd/BUILD
Normal file
44
app/admin/main/config/cmd/BUILD
Normal file
@ -0,0 +1,44 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_binary",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_binary(
|
||||
name = "cmd",
|
||||
embed = [":go_default_library"],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["main.go"],
|
||||
data = ["config-admin-example.toml"],
|
||||
importpath = "go-common/app/admin/main/config/cmd",
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//app/admin/main/config/conf:go_default_library",
|
||||
"//app/admin/main/config/http:go_default_library",
|
||||
"//app/admin/main/config/pkg/lint/json:go_default_library",
|
||||
"//app/admin/main/config/pkg/lint/toml:go_default_library",
|
||||
"//app/admin/main/config/service:go_default_library",
|
||||
"//library/log:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
81
app/admin/main/config/cmd/config-admin-example.toml
Normal file
81
app/admin/main/config/cmd/config-admin-example.toml
Normal file
@ -0,0 +1,81 @@
|
||||
|
||||
[log]
|
||||
dir = "/data/log/config-admin/"
|
||||
|
||||
[auth]
|
||||
managerHost = "http://uat-manager.bilibili.co"
|
||||
dashboardHost = "http://dashboard-mng.bilibili.co"
|
||||
dashboardCaller = "sven"
|
||||
[auth.DsHTTPClient]
|
||||
key = "sven"
|
||||
secret = "a9564ebc3289b7a14551baf8ad5ec60a"
|
||||
dial = "1s"
|
||||
timeout = "1s"
|
||||
keepAlive = "60s"
|
||||
[auth.DsHTTPClient.breaker]
|
||||
window = "3s"
|
||||
sleep = "100ms"
|
||||
bucket = 10
|
||||
ratio = 0.5
|
||||
request = 100
|
||||
[auth.MaHTTPClient]
|
||||
key = "f6433799dbd88751"
|
||||
secret = "36f8ddb1806207fe07013ab6a77a3935"
|
||||
dial = "1s"
|
||||
timeout = "1s"
|
||||
keepAlive = "60s"
|
||||
[auth.MaHTTPClient.breaker]
|
||||
window = "3s"
|
||||
sleep = "100ms"
|
||||
bucket = 10
|
||||
ratio = 0.5
|
||||
request = 100
|
||||
[auth.session]
|
||||
sessionIDLength = 32
|
||||
cookieLifeTime = 1800
|
||||
cookieName = "sven-apm"
|
||||
domain = ".bilibili.co"
|
||||
[auth.session.Memcache]
|
||||
name = "go-business/auth"
|
||||
proto = "tcp"
|
||||
addr = "172.18.33.61:11232"
|
||||
active = 10
|
||||
idle = 10
|
||||
dialTimeout = "1s"
|
||||
readTimeout = "1s"
|
||||
writeTimeout = "1s"
|
||||
idleTimeout = "80s"
|
||||
|
||||
|
||||
|
||||
[httpClient]
|
||||
key = "test"
|
||||
secret = "e6c4c252dc7e3d8a90805eecd7c73396"
|
||||
dial = "1s"
|
||||
timeout = "10s"
|
||||
keepAlive = "60s"
|
||||
timer = 1000
|
||||
[httpClient.breaker]
|
||||
window = "10s"
|
||||
sleep = "100ms"
|
||||
bucket = 10
|
||||
ratio = 0.5
|
||||
request = 100
|
||||
|
||||
[orm]
|
||||
dsn = "test:test@tcp(172.16.33.205:3308)/bilibili_config?timeout=5s&readTimeout=5s&writeTimeout=5s&parseTime=true&loc=Local&charset=utf8,utf8mb4"
|
||||
active = 5
|
||||
idle = 5
|
||||
idleTimeout = "4h"
|
||||
|
||||
[ormapm]
|
||||
dsn = "test:test@tcp(172.16.33.205:3308)/bilibili_apm?timeout=5s&readTimeout=5s&writeTimeout=5s&parseTime=true&loc=Local&charset=utf8,utf8mb4"
|
||||
active = 5
|
||||
idle = 5
|
||||
idleTimeout = "4h"
|
||||
|
||||
[tree]
|
||||
platform = "2F3b8fDVGlMnj8aCDlMaW"
|
||||
|
||||
[ConfSvr]
|
||||
timeout = "1s"
|
47
app/admin/main/config/cmd/main.go
Normal file
47
app/admin/main/config/cmd/main.go
Normal file
@ -0,0 +1,47 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
"go-common/app/admin/main/config/conf"
|
||||
"go-common/app/admin/main/config/http"
|
||||
"go-common/app/admin/main/config/service"
|
||||
"go-common/library/log"
|
||||
|
||||
// register config lint
|
||||
_ "go-common/app/admin/main/config/pkg/lint/json"
|
||||
_ "go-common/app/admin/main/config/pkg/lint/toml"
|
||||
)
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
if err := conf.Init(); err != nil {
|
||||
log.Error("conf.Init() error(%v)", err)
|
||||
panic(err)
|
||||
}
|
||||
// init log
|
||||
log.Init(conf.Conf.Log)
|
||||
defer log.Close()
|
||||
log.Info("config-admin start")
|
||||
svr := service.New(conf.Conf)
|
||||
http.Init(conf.Conf, svr)
|
||||
c := make(chan os.Signal, 1)
|
||||
signal.Notify(c, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT)
|
||||
for {
|
||||
s := <-c
|
||||
log.Info("config-admin get a signal %s", s.String())
|
||||
switch s {
|
||||
case syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT:
|
||||
svr.Close()
|
||||
log.Info("config-admin exit")
|
||||
return
|
||||
case syscall.SIGHUP:
|
||||
// TODO reload
|
||||
default:
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
37
app/admin/main/config/conf/BUILD
Normal file
37
app/admin/main/config/conf/BUILD
Normal file
@ -0,0 +1,37 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["conf.go"],
|
||||
importpath = "go-common/app/admin/main/config/conf",
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//library/conf:go_default_library",
|
||||
"//library/database/orm:go_default_library",
|
||||
"//library/log:go_default_library",
|
||||
"//library/net/http/blademaster:go_default_library",
|
||||
"//library/net/http/blademaster/middleware/permit:go_default_library",
|
||||
"//library/net/rpc:go_default_library",
|
||||
"//vendor/github.com/BurntSushi/toml:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
98
app/admin/main/config/conf/conf.go
Normal file
98
app/admin/main/config/conf/conf.go
Normal file
@ -0,0 +1,98 @@
|
||||
package conf
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"flag"
|
||||
|
||||
"go-common/library/conf"
|
||||
"go-common/library/database/orm"
|
||||
"go-common/library/log"
|
||||
bm "go-common/library/net/http/blademaster"
|
||||
"go-common/library/net/http/blademaster/middleware/permit"
|
||||
"go-common/library/net/rpc"
|
||||
|
||||
"github.com/BurntSushi/toml"
|
||||
)
|
||||
|
||||
var (
|
||||
confPath string
|
||||
// Conf conf
|
||||
Conf = &Config{}
|
||||
client *conf.Client
|
||||
)
|
||||
|
||||
// Config config
|
||||
type Config struct {
|
||||
// identify
|
||||
Auth *permit.Config
|
||||
// log
|
||||
Log *log.Config
|
||||
// orm
|
||||
ORM *orm.Config
|
||||
// http client
|
||||
HTTPClient *bm.ClientConfig
|
||||
//ConfSvr
|
||||
ConfSvr *rpc.ClientConfig
|
||||
//tree
|
||||
Tree *ServiceTree
|
||||
// db apm
|
||||
ORMApm *orm.Config
|
||||
//BM
|
||||
BM *bm.ServerConfig
|
||||
}
|
||||
|
||||
// ServiceTree service tree.
|
||||
type ServiceTree struct {
|
||||
Platform string
|
||||
}
|
||||
|
||||
func init() {
|
||||
flag.StringVar(&confPath, "conf", "", "config file")
|
||||
}
|
||||
|
||||
// Init init.
|
||||
func Init() (err error) {
|
||||
if confPath != "" {
|
||||
return local()
|
||||
}
|
||||
return remote()
|
||||
}
|
||||
|
||||
func local() (err error) {
|
||||
_, err = toml.DecodeFile(confPath, &Conf)
|
||||
return
|
||||
}
|
||||
|
||||
func remote() (err error) {
|
||||
if client, err = conf.New(); err != nil {
|
||||
return
|
||||
}
|
||||
if err = load(); err != nil {
|
||||
return
|
||||
}
|
||||
go func() {
|
||||
for range client.Event() {
|
||||
log.Info("config reload")
|
||||
if err := load(); err != nil {
|
||||
log.Error("config reload error (%v)", err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
return
|
||||
}
|
||||
|
||||
func load() (err error) {
|
||||
var (
|
||||
s string
|
||||
ok bool
|
||||
tmpConf *Config
|
||||
)
|
||||
if s, ok = client.Toml2(); !ok {
|
||||
return errors.New("load config center error")
|
||||
}
|
||||
if _, err = toml.Decode(s, &tmpConf); err != nil {
|
||||
return errors.New("could not decode config")
|
||||
}
|
||||
*Conf = *tmpConf
|
||||
return
|
||||
}
|
57
app/admin/main/config/dao/BUILD
Normal file
57
app/admin/main/config/dao/BUILD
Normal file
@ -0,0 +1,57 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_test",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = [
|
||||
"dao_test.go",
|
||||
"tree_test.go",
|
||||
],
|
||||
embed = [":go_default_library"],
|
||||
rundir = ".",
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//app/admin/main/config/conf:go_default_library",
|
||||
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
|
||||
"//vendor/gopkg.in/h2non/gock.v1:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"dao.go",
|
||||
"tree.go",
|
||||
],
|
||||
importpath = "go-common/app/admin/main/config/dao",
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//app/admin/main/config/conf:go_default_library",
|
||||
"//app/admin/main/config/model:go_default_library",
|
||||
"//library/database/orm:go_default_library",
|
||||
"//library/ecode:go_default_library",
|
||||
"//library/log:go_default_library",
|
||||
"//library/net/http/blademaster:go_default_library",
|
||||
"//vendor/github.com/jinzhu/gorm:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
54
app/admin/main/config/dao/dao.go
Normal file
54
app/admin/main/config/dao/dao.go
Normal file
@ -0,0 +1,54 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"go-common/app/admin/main/config/conf"
|
||||
"go-common/library/database/orm"
|
||||
bm "go-common/library/net/http/blademaster"
|
||||
|
||||
"github.com/jinzhu/gorm"
|
||||
)
|
||||
|
||||
// Dao dao.
|
||||
type Dao struct {
|
||||
c *conf.Config
|
||||
DB *gorm.DB
|
||||
DBApm *gorm.DB
|
||||
client *bm.Client
|
||||
}
|
||||
|
||||
// New new a dao and return.
|
||||
func New(c *conf.Config) (d *Dao) {
|
||||
d = &Dao{
|
||||
c: c,
|
||||
DB: orm.NewMySQL(c.ORM),
|
||||
DBApm: orm.NewMySQL(c.ORMApm),
|
||||
client: bm.NewClient(c.HTTPClient),
|
||||
}
|
||||
d.initORM()
|
||||
return
|
||||
}
|
||||
|
||||
func (d *Dao) initORM() {
|
||||
d.DB.LogMode(true)
|
||||
d.DBApm.LogMode(true)
|
||||
}
|
||||
|
||||
// Ping check connection of db , mc.
|
||||
func (d *Dao) Ping(c context.Context) (err error) {
|
||||
if d.DB != nil {
|
||||
err = d.DB.DB().PingContext(c)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Close close connection of db , mc.
|
||||
func (d *Dao) Close() {
|
||||
if d.DB != nil {
|
||||
d.DB.Close()
|
||||
}
|
||||
if d.DBApm != nil {
|
||||
d.DBApm.Close()
|
||||
}
|
||||
}
|
45
app/admin/main/config/dao/dao_test.go
Normal file
45
app/admin/main/config/dao/dao_test.go
Normal file
@ -0,0 +1,45 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"go-common/app/admin/main/config/conf"
|
||||
|
||||
gock "gopkg.in/h2non/gock.v1"
|
||||
)
|
||||
|
||||
var (
|
||||
d *Dao
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
if os.Getenv("DEPLOY_ENV") != "" {
|
||||
flag.Set("app_id", "main.common-arch.config-admin")
|
||||
flag.Set("conf_token", "0OuIaZNZU2Yfa4lXM6e4p2XeGtiQuwyF")
|
||||
flag.Set("tree_id", "9366")
|
||||
flag.Set("conf_version", "docker-1")
|
||||
flag.Set("deploy_env", "uat")
|
||||
flag.Set("conf_host", "config.bilibili.co")
|
||||
flag.Set("conf_path", "/tmp")
|
||||
flag.Set("region", "sh")
|
||||
flag.Set("zone", "sh001")
|
||||
} else {
|
||||
flag.Set("conf", "../cmd/config-admin-example.toml")
|
||||
}
|
||||
flag.Parse()
|
||||
if err := conf.Init(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
d = New(conf.Conf)
|
||||
m.Run()
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
func httpMock(method, url string) *gock.Request {
|
||||
r := gock.New(url)
|
||||
r.Method = strings.ToUpper(method)
|
||||
return r
|
||||
}
|
201
app/admin/main/config/dao/tree.go
Normal file
201
app/admin/main/config/dao/tree.go
Normal file
@ -0,0 +1,201 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"go-common/app/admin/main/config/model"
|
||||
"go-common/library/ecode"
|
||||
"go-common/library/log"
|
||||
)
|
||||
|
||||
var (
|
||||
tokenURI = "http://easyst.bilibili.co/v1/token"
|
||||
dataURI = "http://easyst.bilibili.co/v1/node/apptree"
|
||||
authURI = "http://easyst.bilibili.co/v1/auth"
|
||||
nodeURI = "http://easyst.bilibili.co/v1/node/bilibili%s"
|
||||
appsURI = "http://easyst.bilibili.co/v1/node/role/app"
|
||||
prefix = []byte("bilibili.")
|
||||
)
|
||||
|
||||
// Token get Token.
|
||||
func (d *Dao) Token(c context.Context, body string) (msg map[string]interface{}, err error) {
|
||||
var (
|
||||
req *http.Request
|
||||
)
|
||||
if req, err = http.NewRequest("POST", tokenURI, strings.NewReader(body)); err != nil {
|
||||
log.Error("Token url(%s) error(%v)", tokenURI, err)
|
||||
return
|
||||
}
|
||||
var res struct {
|
||||
Code int `json:"code"`
|
||||
Data map[string]interface{} `json:"data"`
|
||||
Message string `json:"message"`
|
||||
Status int `json:"status"`
|
||||
}
|
||||
if err = d.client.Do(c, req, &res); err != nil {
|
||||
log.Error("d.Token url(%s) res(%+v) err(%v)", tokenURI, res, err)
|
||||
return
|
||||
}
|
||||
if res.Code != 90000 {
|
||||
err = fmt.Errorf("error code :%d", res.Code)
|
||||
log.Error("Status url(%s) res(%v)", tokenURI, res)
|
||||
return
|
||||
}
|
||||
msg = res.Data
|
||||
return
|
||||
}
|
||||
|
||||
// Auth get Token.
|
||||
func (d *Dao) Auth(c context.Context, cookie string) (msg map[string]interface{}, err error) {
|
||||
var (
|
||||
req *http.Request
|
||||
)
|
||||
if req, err = http.NewRequest("GET", authURI, nil); err != nil {
|
||||
log.Error("Token url(%s) error(%v)", tokenURI, err)
|
||||
return
|
||||
}
|
||||
req.Header.Set("Cookie", cookie)
|
||||
var res struct {
|
||||
Code int `json:"code"`
|
||||
Data map[string]interface{} `json:"data"`
|
||||
Message string `json:"message"`
|
||||
Status int `json:"status"`
|
||||
}
|
||||
if err = d.client.Do(c, req, &res); err != nil {
|
||||
log.Error("d.Token url(%s) res($s) err(%v)", tokenURI, res, err)
|
||||
return
|
||||
}
|
||||
if res.Code != 90000 {
|
||||
err = fmt.Errorf("error code :%d", res.Code)
|
||||
log.Error("Status url(%s) res(%v)", tokenURI, res)
|
||||
return
|
||||
}
|
||||
msg = res.Data
|
||||
return
|
||||
}
|
||||
|
||||
// Tree get service tree.
|
||||
func (d *Dao) Tree(c context.Context, token string) (data interface{}, err error) {
|
||||
var (
|
||||
req *http.Request
|
||||
tmp map[string]interface{}
|
||||
ok bool
|
||||
)
|
||||
if req, err = http.NewRequest("GET", dataURI, nil); err != nil {
|
||||
log.Error("Status url(%s) error(%v)", dataURI, err)
|
||||
return
|
||||
}
|
||||
req.Header.Set("X-Authorization-Token", token)
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
var res struct {
|
||||
Code int `json:"code"`
|
||||
Data map[string]map[string]interface{} `json:"data"`
|
||||
Message string `json:"message"`
|
||||
Status int `json:"status"`
|
||||
}
|
||||
if err = d.client.Do(c, req, &res); err != nil {
|
||||
log.Error("d.Status url(%s) res($s) err(%v)", dataURI, res, err)
|
||||
return
|
||||
}
|
||||
if res.Code != 90000 {
|
||||
err = fmt.Errorf("error code :%d", res.Code)
|
||||
log.Error("Status url(%s) res(%v)", dataURI, res)
|
||||
return
|
||||
}
|
||||
if tmp, ok = res.Data["bilibili"]; ok {
|
||||
data, ok = tmp["children"]
|
||||
}
|
||||
if !ok {
|
||||
err = ecode.NothingFound
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Role get service tree.
|
||||
func (d *Dao) Role(c context.Context, user, token string) (nodes *model.CacheData, err error) {
|
||||
var (
|
||||
req *http.Request
|
||||
)
|
||||
if req, err = http.NewRequest("GET", appsURI, nil); err != nil {
|
||||
log.Error("Status url(%s) error(%v)", dataURI, err)
|
||||
return
|
||||
}
|
||||
req.Header.Set("X-Authorization-Token", token)
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
var res struct {
|
||||
Code int `json:"code"`
|
||||
Data []*model.RoleNode `json:"data"`
|
||||
Message string `json:"message"`
|
||||
Status int `json:"status"`
|
||||
}
|
||||
if err = d.client.Do(c, req, &res); err != nil {
|
||||
log.Error("d.Status url(%s) res($s) err(%v)", dataURI, res, err)
|
||||
return
|
||||
}
|
||||
if res.Code != 90000 {
|
||||
err = fmt.Errorf("error code :%d", res.Code)
|
||||
log.Error("Status url(%s) res(%v)", dataURI, res)
|
||||
return
|
||||
}
|
||||
nodes = &model.CacheData{Data: make(map[int64]*model.RoleNode)}
|
||||
nodes.CTime = time.Now()
|
||||
for _, node := range res.Data {
|
||||
if bytes.Equal(prefix, []byte(node.Path)[0:9]) {
|
||||
node.Path = string([]byte(node.Path)[9:])
|
||||
}
|
||||
nodes.Data[node.ID] = node
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// NodeTree get service tree.
|
||||
func (d *Dao) NodeTree(c context.Context, token, bu, team string) (nodes []*model.Node, err error) {
|
||||
var (
|
||||
req *http.Request
|
||||
node string
|
||||
)
|
||||
if len(bu) != 0 {
|
||||
node = "." + bu
|
||||
}
|
||||
if len(team) != 0 {
|
||||
node = "." + team
|
||||
}
|
||||
if len(node) == 0 {
|
||||
nodes = append(nodes, &model.Node{Name: "main", Path: "main"})
|
||||
nodes = append(nodes, &model.Node{Name: "ai", Path: "ai"})
|
||||
return
|
||||
}
|
||||
if req, err = http.NewRequest("GET", fmt.Sprintf(nodeURI, node), nil); err != nil {
|
||||
log.Error("Status url(%s) error(%v)", dataURI, err)
|
||||
return
|
||||
}
|
||||
req.Header.Set("X-Authorization-Token", token)
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
var res struct {
|
||||
Code int `json:"code"`
|
||||
Data *model.Res `json:"data"`
|
||||
Message string `json:"message"`
|
||||
Status int `json:"status"`
|
||||
}
|
||||
if err = d.client.Do(c, req, &res); err != nil {
|
||||
log.Error("d.Status url(%s) res($s) err(%v)", dataURI, res, err)
|
||||
return
|
||||
}
|
||||
if res.Code != 90000 {
|
||||
err = fmt.Errorf("error code :%d", res.Code)
|
||||
log.Error("Status url(%s) error(%v)", dataURI, err)
|
||||
return
|
||||
}
|
||||
for _, tnode := range res.Data.Data {
|
||||
if bytes.Equal(prefix, []byte(tnode.Path)[0:9]) {
|
||||
tnode.Path = string([]byte(tnode.Path)[9:])
|
||||
}
|
||||
nodes = append(nodes, &model.Node{Name: tnode.Name, Path: tnode.Path})
|
||||
}
|
||||
return
|
||||
}
|
137
app/admin/main/config/dao/tree_test.go
Normal file
137
app/admin/main/config/dao/tree_test.go
Normal file
@ -0,0 +1,137 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/smartystreets/goconvey/convey"
|
||||
gock "gopkg.in/h2non/gock.v1"
|
||||
)
|
||||
|
||||
var token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX25hbWUiOiJtYWluIiwicGxhdGZvcm1faWQiOiIyRjNiOGZEVkdsTW5qOGFDRGxNYVciLCJleHAiOjE1NDA2NDE3MjQsImlzcyI6Im1haW4ifQ.SxKceDl69N1su3kDO70c4P1NuPhXOxp5rXpM3n8Jyig"
|
||||
|
||||
func TestToken(t *testing.T) {
|
||||
d.client.SetTransport(gock.DefaultTransport)
|
||||
convey.Convey("get token", t, func(ctx convey.C) {
|
||||
ctx.Convey("When http response code != 0", func(ctx convey.C) {
|
||||
httpMock("POST", "http://easyst.bilibili.co/v1/token").Reply(200).JSON(`{
|
||||
"code": 90000,
|
||||
"data": {
|
||||
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX25hbWUiOiJtYWluIiwicGxhdGZvcm1faWQiOiIyRjNiOGZEVkdsTW5qOGFDRGxNYVciLCJleHAiOjE1NDA2NDE3MjQsImlzcyI6Im1haW4ifQ.SxKceDl69N1su3kDO70c4P1NuPhXOxp5rXpM3n8Jyig",
|
||||
"user_name": "main",
|
||||
"secret": "",
|
||||
"expired": 1540641724
|
||||
},
|
||||
"message": "success",
|
||||
"status": 200
|
||||
}`)
|
||||
data, err := d.Token(context.Background(), "")
|
||||
ctx.Convey("Then err should not be nil", func(ctx convey.C) {
|
||||
ctx.So(err, convey.ShouldBeNil)
|
||||
ctx.So(data, convey.ShouldNotBeNil)
|
||||
})
|
||||
})
|
||||
ctx.Reset(func() {
|
||||
gock.Off()
|
||||
d.client.SetTransport(http.DefaultClient.Transport)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestAuth(t *testing.T) {
|
||||
d.client.SetTransport(gock.DefaultTransport)
|
||||
convey.Convey("get auth", t, func(ctx convey.C) {
|
||||
ctx.Convey("When http response code != 0", func(ctx convey.C) {
|
||||
httpMock("GET", "http://easyst.bilibili.co/v1/auth").Reply(200).JSON(`{"code":90000,"message":"success"}`)
|
||||
_, err := d.Auth(context.Background(), "sven-apm=afab110001a20fa3a1c9b5bd67564ccd71c6253406725184bfa5d88c7ece9d17; Path=/; Domain=bilibili.co; Expires=Tue, 23 Oct 2018 07:25:02 GMT; Max-Age=1800; HttpOnly")
|
||||
ctx.Convey("Then err should not be nil", func(ctx convey.C) {
|
||||
ctx.So(err, convey.ShouldBeNil)
|
||||
// ctx.So(data, convey.ShouldNotBeNil)
|
||||
})
|
||||
})
|
||||
ctx.Reset(func() {
|
||||
gock.Off()
|
||||
d.client.SetTransport(http.DefaultClient.Transport)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestRole(t *testing.T) {
|
||||
d.client.SetTransport(gock.DefaultTransport)
|
||||
convey.Convey("TestRole", t, func(ctx convey.C) {
|
||||
ctx.Convey("When http response code != 0", func(ctx convey.C) {
|
||||
httpMock("GET", "http://easyst.bilibili.co/v1/node/role/app").Reply(200).JSON(`{"code":90000,"message":"success"}`)
|
||||
data, err := d.Role(context.Background(), "linli", token)
|
||||
ctx.Convey("Then err should not be nil", func(ctx convey.C) {
|
||||
ctx.So(err, convey.ShouldBeNil)
|
||||
ctx.So(data, convey.ShouldNotBeNil)
|
||||
})
|
||||
})
|
||||
ctx.Reset(func() {
|
||||
gock.Off()
|
||||
d.client.SetTransport(http.DefaultClient.Transport)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestNodeTree(t *testing.T) {
|
||||
d.client.SetTransport(gock.DefaultTransport)
|
||||
convey.Convey("NodeTree", t, func(ctx convey.C) {
|
||||
ctx.Convey("When http response code != 0", func(ctx convey.C) {
|
||||
httpMock("GET", "http://easyst.bilibili.co/v1/node/bilibili.main.common-arch").Reply(200).JSON(`{
|
||||
"status": 200,
|
||||
"message": "success",
|
||||
"code": 90000,
|
||||
"data": {
|
||||
"count": 0,
|
||||
"results": 20,
|
||||
"page": 1,
|
||||
"data": null
|
||||
}
|
||||
}`)
|
||||
_, err := d.NodeTree(context.Background(), token, "main.common-arch", "")
|
||||
ctx.Convey("Then err should not be nil", func(ctx convey.C) {
|
||||
ctx.So(err, convey.ShouldBeNil)
|
||||
// ctx.So(data, convey.ShouldNotBeNil)
|
||||
})
|
||||
})
|
||||
ctx.Reset(func() {
|
||||
gock.Off()
|
||||
d.client.SetTransport(http.DefaultClient.Transport)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestTree(t *testing.T) {
|
||||
d.client.SetTransport(gock.DefaultTransport)
|
||||
convey.Convey("TestTree", t, func(ctx convey.C) {
|
||||
ctx.Convey("When http response code != 0", func(ctx convey.C) {
|
||||
httpMock("GET", "http://easyst.bilibili.co/v1/node/apptree").Reply(200).JSON(`{
|
||||
"code": 90000,
|
||||
"data": {
|
||||
"bilibili": {
|
||||
"id": 0,
|
||||
"name": "bilibili",
|
||||
"alias": "哔哩哔哩",
|
||||
"type": 1,
|
||||
"path": "bilibili",
|
||||
"tags": {},
|
||||
"children": null
|
||||
}
|
||||
},
|
||||
"message": "success",
|
||||
"status": 200
|
||||
}`)
|
||||
_, err := d.Tree(context.Background(), token)
|
||||
ctx.Convey("Then err should not be nil", func(ctx convey.C) {
|
||||
ctx.So(err, convey.ShouldBeNil)
|
||||
// ctx.So(data, convey.ShouldNotBeNil)
|
||||
})
|
||||
})
|
||||
ctx.Reset(func() {
|
||||
gock.Off()
|
||||
d.client.SetTransport(http.DefaultClient.Transport)
|
||||
})
|
||||
})
|
||||
}
|
49
app/admin/main/config/http/BUILD
Normal file
49
app/admin/main/config/http/BUILD
Normal file
@ -0,0 +1,49 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"apm.go",
|
||||
"app.go",
|
||||
"build.go",
|
||||
"common.go",
|
||||
"conf_svr.go",
|
||||
"config.go",
|
||||
"http.go",
|
||||
"tag.go",
|
||||
"tree.go",
|
||||
],
|
||||
importpath = "go-common/app/admin/main/config/http",
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//app/admin/main/config/conf:go_default_library",
|
||||
"//app/admin/main/config/model:go_default_library",
|
||||
"//app/admin/main/config/service:go_default_library",
|
||||
"//library/ecode:go_default_library",
|
||||
"//library/log:go_default_library",
|
||||
"//library/net/http/blademaster:go_default_library",
|
||||
"//library/net/http/blademaster/middleware/permit:go_default_library",
|
||||
"//library/time:go_default_library",
|
||||
"//vendor/github.com/jinzhu/gorm:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
36
app/admin/main/config/http/apm.go
Normal file
36
app/admin/main/config/http/apm.go
Normal file
@ -0,0 +1,36 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"go-common/app/admin/main/config/model"
|
||||
"go-common/library/log"
|
||||
bm "go-common/library/net/http/blademaster"
|
||||
)
|
||||
|
||||
func apmCopy(c *bm.Context) {
|
||||
res := map[string]interface{}{}
|
||||
user := user(c)
|
||||
v := new(model.ApmCopyReq)
|
||||
err := c.Bind(v)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if _, err = svr.AuthApp(c, user, c.Request.Header.Get("Cookie"), v.TreeID); err != nil {
|
||||
res["message"] = "服务树权限不足"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
cnt := 0
|
||||
if err = svr.DB.Model(&model.App{}).Where("tree_id=?", v.TreeID).Count(&cnt).Error; err != nil {
|
||||
log.Error("svr.ApmCopy count error(%v)", err)
|
||||
res["message"] = "查询该服务失败"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
if cnt <= 0 {
|
||||
log.Error("svr.ApmCopy count (%v)", cnt)
|
||||
res["message"] = "未找到该服务"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
c.JSON(nil, svr.Apm(v.TreeID, v.Name, v.ApmName, user))
|
||||
}
|
277
app/admin/main/config/http/app.go
Normal file
277
app/admin/main/config/http/app.go
Normal file
@ -0,0 +1,277 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"go-common/app/admin/main/config/model"
|
||||
"go-common/library/ecode"
|
||||
"go-common/library/log"
|
||||
bm "go-common/library/net/http/blademaster"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func updateToken(c *bm.Context) {
|
||||
v := new(model.UpdateTokenReq)
|
||||
err := c.Bind(v)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if _, err = svr.AuthApp(c, user(c), c.Request.Header.Get("Cookie"), v.TreeID); err != nil {
|
||||
c.JSON(nil, err)
|
||||
return
|
||||
}
|
||||
if err = svr.UpdateToken(c, v.Env, v.Zone, v.TreeID); err != nil {
|
||||
c.JSON(nil, err)
|
||||
return
|
||||
}
|
||||
c.JSON(nil, err)
|
||||
}
|
||||
|
||||
func create(c *bm.Context) {
|
||||
res := map[string]interface{}{}
|
||||
v := new(model.CreateReq)
|
||||
err := c.Bind(v)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if _, err = svr.AuthApp(c, user(c), c.Request.Header.Get("Cookie"), v.TreeID); err != nil {
|
||||
res["message"] = "服务树权限不足"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
creates := []string{"dev", "fat1", "uat", "pre", "prod"}
|
||||
for _, val := range creates {
|
||||
if err = svr.CreateApp(v.AppName, val, model.DefaultZone, v.TreeID); err != nil {
|
||||
res["message"] = "创建app失败"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
c.JSON(nil, err)
|
||||
}
|
||||
|
||||
func appList(c *bm.Context) {
|
||||
res := map[string]interface{}{}
|
||||
v := new(model.AppListReq)
|
||||
err := c.Bind(v)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
nodes, err := svr.AuthApps(c, user(c), c.Request.Header.Get("Cookie"))
|
||||
if err != nil {
|
||||
res["message"] = "服务树权限不足"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
app, err := svr.AppList(c, v.Bu, v.Team, v.AppName, model.DefaultEnv, model.DefaultZone, v.Ps, v.Pn, nodes, v.Status)
|
||||
if err != nil {
|
||||
res["message"] = "数据获取失败"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
result := app
|
||||
c.JSON(result, nil)
|
||||
}
|
||||
|
||||
func envsByTeam(c *bm.Context) {
|
||||
res := map[string]interface{}{}
|
||||
v := new(model.EnvsByTeamReq)
|
||||
err := c.Bind(v)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
nodes, err := svr.AuthApps(c, user(c), c.Request.Header.Get("Cookie"))
|
||||
if err != nil {
|
||||
res["message"] = "服务树权限不足"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
data, err := svr.EnvsByTeam(c, v.AppName, v.Zone, nodes)
|
||||
if err != nil {
|
||||
c.JSON(nil, err)
|
||||
return
|
||||
}
|
||||
result := data
|
||||
c.JSON(result, nil)
|
||||
}
|
||||
|
||||
func envs(c *bm.Context) {
|
||||
res := map[string]interface{}{}
|
||||
v := new(model.EnvsReq)
|
||||
err := c.Bind(v)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
user := user(c)
|
||||
nodes, err := svr.AuthApps(c, user, c.Request.Header.Get("Cookie"))
|
||||
if err != nil {
|
||||
res["message"] = "服务树权限不足"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
c.JSON(svr.Envs(c, user, v.AppName, v.Zone, v.TreeID, nodes))
|
||||
}
|
||||
|
||||
func nodeTree(c *bm.Context) {
|
||||
res := map[string]interface{}{}
|
||||
v := new(model.NodeTreeReq)
|
||||
err := c.Bind(v)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
cookie := c.Request.Header.Get("Cookie")
|
||||
user := user(c)
|
||||
nodes, err := svr.AuthApps(c, user, cookie)
|
||||
if err != nil {
|
||||
res["message"] = "服务树权限不足"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
c.JSON(svr.Node(c, user, v.Node, v.Team, cookie, nodes))
|
||||
}
|
||||
|
||||
func zoneCopy(c *bm.Context) {
|
||||
res := map[string]interface{}{}
|
||||
v := new(model.ZoneCopyReq)
|
||||
err := c.Bind(v)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if v.From == v.To {
|
||||
res["message"] = "来源机房和目标机房不能是同一个"
|
||||
c.JSONMap(res, ecode.RequestErr)
|
||||
return
|
||||
}
|
||||
if _, err = svr.AuthApp(c, user(c), c.Request.Header.Get("Cookie"), v.TreeID); err != nil {
|
||||
res["message"] = "服务树权限不足"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
if err = svr.ZoneCopy(c, v.AppName, v.From, v.To, v.TreeID); err != nil {
|
||||
res["message"] = "拷贝失败"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
c.JSON(nil, err)
|
||||
}
|
||||
|
||||
func casterEnvs(c *bm.Context) {
|
||||
v := new(model.CasterEnvsReq)
|
||||
err := c.Bind(v)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if v.Auth != "caster_envs_all" {
|
||||
c.JSON(nil, ecode.RequestErr)
|
||||
return
|
||||
}
|
||||
c.JSON(svr.CasterEnvs(v.Zone, v.TreeID))
|
||||
}
|
||||
|
||||
func rename(c *bm.Context) {
|
||||
res := map[string]interface{}{}
|
||||
v := new(struct {
|
||||
TreeID int64 `form:"tree_id" validate:"required"`
|
||||
})
|
||||
err := c.Bind(v)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if _, err = svr.AuthApp(c, user(c), c.Request.Header.Get("Cookie"), v.TreeID); err != nil {
|
||||
res["message"] = "服务树权限不足"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
c.JSON(nil, svr.AppRename(v.TreeID, user(c), c.Request.Header.Get("Cookie")))
|
||||
}
|
||||
|
||||
func getApps(c *bm.Context) {
|
||||
v := new(struct {
|
||||
Name string `form:"name" validate:"required"`
|
||||
Env string `form:"env" validate:"required"`
|
||||
})
|
||||
err := c.Bind(v)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
apps, err := svr.GetApps(v.Env)
|
||||
if err != nil {
|
||||
c.JSON(nil, err)
|
||||
return
|
||||
}
|
||||
var appIDS []int64
|
||||
for _, val := range apps {
|
||||
appIDS = append(appIDS, val.ID)
|
||||
}
|
||||
if len(appIDS) == 0 {
|
||||
c.JSON(nil, ecode.RequestErr)
|
||||
return
|
||||
}
|
||||
builds, err := svr.AllBuilds(appIDS)
|
||||
if err != nil {
|
||||
c.JSON(nil, err)
|
||||
return
|
||||
}
|
||||
var tagIDS []int64
|
||||
for _, val := range builds {
|
||||
tagIDS = append(tagIDS, val.TagID)
|
||||
}
|
||||
tags, err := svr.GetConfigIDS(tagIDS)
|
||||
if err != nil {
|
||||
c.JSON(nil, err)
|
||||
return
|
||||
}
|
||||
var configIDS []int64
|
||||
for _, val := range tags {
|
||||
tmpIDs := strings.Split(val.ConfigIDs, ",")
|
||||
for _, vv := range tmpIDs {
|
||||
id, err := strconv.ParseInt(vv, 10, 64)
|
||||
if err != nil {
|
||||
log.Error("strconv.ParseInt() error(%v)", err)
|
||||
return
|
||||
}
|
||||
configIDS = append(configIDS, id)
|
||||
}
|
||||
}
|
||||
var appids []int64
|
||||
var appslist []*model.App
|
||||
var names []string
|
||||
if len(configIDS) > 0 {
|
||||
configs, err := svr.GetConfigs(configIDS, v.Name)
|
||||
if err != nil {
|
||||
c.JSON(nil, err)
|
||||
return
|
||||
}
|
||||
for _, val := range configs {
|
||||
appids = append(appids, val.AppID)
|
||||
}
|
||||
appslist, err = svr.IdsGetApps(appids)
|
||||
if err != nil {
|
||||
c.JSON(nil, err)
|
||||
return
|
||||
}
|
||||
for _, val := range appslist {
|
||||
names = append(names, val.Name)
|
||||
}
|
||||
}
|
||||
c.JSON(names, nil)
|
||||
}
|
||||
|
||||
func upAppStatus(c *bm.Context) {
|
||||
res := map[string]interface{}{}
|
||||
v := new(model.AppStatusReq)
|
||||
err := c.Bind(v)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if !(v.Status == model.StatusShow || v.Status == model.StatusHidden) {
|
||||
c.JSON(nil, ecode.RequestErr)
|
||||
return
|
||||
}
|
||||
_, err = svr.AuthApps(c, user(c), c.Request.Header.Get("Cookie"))
|
||||
if err != nil {
|
||||
res["message"] = "服务树权限不足"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
c.JSON(nil, svr.UpAppStatus(c, v.Status, v.TreeID))
|
||||
}
|
94
app/admin/main/config/http/build.go
Normal file
94
app/admin/main/config/http/build.go
Normal file
@ -0,0 +1,94 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"go-common/app/admin/main/config/model"
|
||||
"go-common/library/ecode"
|
||||
bm "go-common/library/net/http/blademaster"
|
||||
)
|
||||
|
||||
func createBuild(c *bm.Context) {
|
||||
res := map[string]interface{}{}
|
||||
v := new(model.CreateBuildReq)
|
||||
err := c.Bind(v)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
name := user(c)
|
||||
if _, err = svr.AuthApp(c, name, c.Request.Header.Get("Cookie"), v.TreeID); err != nil {
|
||||
res["message"] = "服务树权限不足"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
if len(strings.TrimSpace(v.Name)) == 0 {
|
||||
res["message"] = "name不能为空"
|
||||
c.JSONMap(res, ecode.RequestErr)
|
||||
return
|
||||
}
|
||||
build := &model.Build{}
|
||||
build.TagID = v.TagID
|
||||
build.Operator = name
|
||||
build.Name = v.Name
|
||||
if err = svr.CreateBuild(build, v.TreeID, v.Env, v.Zone); err != nil {
|
||||
res["message"] = "创建build失败"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
c.JSON(nil, err)
|
||||
}
|
||||
|
||||
func builds(c *bm.Context) {
|
||||
res := map[string]interface{}{}
|
||||
v := new(model.BuildsReq)
|
||||
err := c.Bind(v)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if _, err = svr.AuthApp(c, user(c), c.Request.Header.Get("Cookie"), v.TreeID); err != nil {
|
||||
res["message"] = "服务树权限不足"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
c.JSON(svr.Builds(v.TreeID, v.AppName, v.Env, v.Zone))
|
||||
}
|
||||
|
||||
func build(c *bm.Context) {
|
||||
res := map[string]interface{}{}
|
||||
v := new(model.BuildReq)
|
||||
err := c.Bind(v)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if _, err = svr.AuthApps(c, user(c), c.Request.Header.Get("Cookie")); err != nil {
|
||||
res["message"] = "服务树权限不足"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
c.JSON(svr.Build(v.BuildID))
|
||||
}
|
||||
|
||||
func buildDel(c *bm.Context) {
|
||||
res := map[string]interface{}{}
|
||||
v := new(model.BuildReq)
|
||||
err := c.Bind(v)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if _, err = svr.AuthApps(c, user(c), c.Request.Header.Get("Cookie")); err != nil {
|
||||
res["message"] = "服务树权限不足"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
if err = svr.GetDelInfos(c, v.BuildID); err != nil {
|
||||
res["message"] = "主机列表中有正在使用该build的机器,请让主机离线3小时自动清除后再删除"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
if err = svr.Delete(v.BuildID); err != nil {
|
||||
res["message"] = "删除build失败"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
c.JSON(nil, err)
|
||||
}
|
164
app/admin/main/config/http/common.go
Normal file
164
app/admin/main/config/http/common.go
Normal file
@ -0,0 +1,164 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"go-common/app/admin/main/config/model"
|
||||
bm "go-common/library/net/http/blademaster"
|
||||
"go-common/library/time"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func createComConfig(c *bm.Context) {
|
||||
res := map[string]interface{}{}
|
||||
v := new(model.CreateComConfigReq)
|
||||
err := c.Bind(v)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
name := user(c)
|
||||
if _, err = svr.AuthApps(c, name, c.Request.Header.Get("Cookie")); err != nil {
|
||||
res["message"] = "服务树权限不足"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
conf := &model.CommonConf{}
|
||||
conf.Operator = name
|
||||
conf.State = v.State
|
||||
conf.Comment = v.Comment
|
||||
conf.Mark = v.Mark
|
||||
conf.Name = v.Name
|
||||
c.JSON(nil, svr.CreateComConf(conf, v.Team, v.Env, v.Zone, v.SkipLint))
|
||||
}
|
||||
|
||||
func comValue(c *bm.Context) {
|
||||
res := map[string]interface{}{}
|
||||
v := new(model.ComValueReq)
|
||||
err := c.Bind(v)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if _, err = svr.AuthApps(c, user(c), c.Request.Header.Get("Cookie")); err != nil {
|
||||
res["message"] = "服务树权限不足"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
c.JSON(svr.ComConfig(v.ConfigID))
|
||||
}
|
||||
|
||||
func configsByTeam(c *bm.Context) {
|
||||
res := map[string]interface{}{}
|
||||
v := new(model.ConfigsByTeamReq)
|
||||
err := c.Bind(v)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if _, err = svr.AuthApps(c, user(c), c.Request.Header.Get("Cookie")); err != nil {
|
||||
res["message"] = "服务树权限不足"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
c.JSON(svr.ComConfigsByTeam(v.Team, v.Env, v.Zone, v.Ps, v.Pn))
|
||||
}
|
||||
|
||||
func comConfigsByName(c *bm.Context) {
|
||||
res := map[string]interface{}{}
|
||||
v := new(model.ComConfigsByNameReq)
|
||||
err := c.Bind(v)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if _, err = svr.AuthApps(c, user(c), c.Request.Header.Get("Cookie")); err != nil {
|
||||
res["message"] = "服务树权限不足"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
c.JSON(svr.ComConfigsByName(v.Team, v.Env, v.Zone, v.Name))
|
||||
}
|
||||
|
||||
func updateComConfValue(c *bm.Context) {
|
||||
res := map[string]interface{}{}
|
||||
v := new(model.UpdateComConfValueReq)
|
||||
err := c.Bind(v)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
user := user(c)
|
||||
if _, err = svr.AuthApps(c, user, c.Request.Header.Get("Cookie")); err != nil {
|
||||
res["message"] = "服务树权限不足"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
conf := &model.CommonConf{}
|
||||
conf.Mtime = time.Time(v.Mtime)
|
||||
conf.Mark = v.Mark
|
||||
conf.ID = v.ID
|
||||
conf.State = v.State
|
||||
conf.Comment = v.Comment
|
||||
conf.Operator = user
|
||||
conf.Name = v.Name
|
||||
c.JSON(nil, svr.UpdateComConfValue(conf, v.SkipLint))
|
||||
}
|
||||
|
||||
func namesByTeam(c *bm.Context) {
|
||||
res := map[string]interface{}{}
|
||||
v := new(model.NamesByTeamReq)
|
||||
err := c.Bind(v)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if _, err = svr.AuthApps(c, user(c), c.Request.Header.Get("Cookie")); err != nil {
|
||||
res["message"] = "服务树权限不足"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
c.JSON(svr.NamesByTeam(v.Team, v.Env, v.Zone))
|
||||
}
|
||||
|
||||
func appByTeam(c *bm.Context) {
|
||||
v := new(struct {
|
||||
CommonConfigID int64 `form:"common_config_id" validate:"required"`
|
||||
})
|
||||
err := c.Bind(v)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
tagMap, err := svr.AppByTeam(v.CommonConfigID)
|
||||
if err != nil {
|
||||
c.JSON(nil, err)
|
||||
return
|
||||
}
|
||||
c.JSON(tagMap, nil)
|
||||
}
|
||||
|
||||
func tagPush(c *bm.Context) {
|
||||
v := new(struct {
|
||||
CommonConfigID int64 `form:"common_config_id" validate:"required"`
|
||||
Tags string `form:"tags" validate:"required"`
|
||||
})
|
||||
err := c.Bind(v)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
user := user(c)
|
||||
tagMap, err := svr.AppByTeam(v.CommonConfigID)
|
||||
if err != nil {
|
||||
c.JSON(nil, err)
|
||||
return
|
||||
}
|
||||
res := make(map[int64]interface{})
|
||||
tagIDS := strings.Split(v.Tags, ",")
|
||||
for _, val := range tagIDS {
|
||||
val, _ := strconv.ParseInt(val, 10, 64)
|
||||
if _, ok := tagMap[val]; ok {
|
||||
err = svr.CommonPush(c, val, v.CommonConfigID, user)
|
||||
if err == nil {
|
||||
res[val] = "success"
|
||||
} else {
|
||||
res[val] = "fail"
|
||||
}
|
||||
} else {
|
||||
res[val] = "data error"
|
||||
}
|
||||
}
|
||||
c.JSON(res, nil)
|
||||
}
|
59
app/admin/main/config/http/conf_svr.go
Normal file
59
app/admin/main/config/http/conf_svr.go
Normal file
@ -0,0 +1,59 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"go-common/app/admin/main/config/model"
|
||||
bm "go-common/library/net/http/blademaster"
|
||||
)
|
||||
|
||||
func setToken(c *bm.Context) {
|
||||
res := map[string]interface{}{}
|
||||
v := new(model.SetTokenReq)
|
||||
err := c.Bind(v)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if _, err = svr.AuthApp(c, user(c), c.Request.Header.Get("Cookie"), v.TreeID); err != nil {
|
||||
res["message"] = "服务树权限不足"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
// update & write cache
|
||||
if err = svr.SetToken(c, v.TreeID, v.Env, v.Zone, v.Token); err != nil {
|
||||
res["message"] = "重置token失败"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
c.JSON(nil, err)
|
||||
}
|
||||
|
||||
// hosts client hosts
|
||||
func hosts(c *bm.Context) {
|
||||
res := map[string]interface{}{}
|
||||
v := new(model.HostsReq)
|
||||
err := c.Bind(v)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if _, err = svr.AuthApp(c, user(c), c.Request.Header.Get("Cookie"), v.TreeID); err != nil {
|
||||
res["message"] = "服务树权限不足"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
c.JSON(svr.Hosts(c, v.TreeID, v.App, v.Env, v.Zone))
|
||||
}
|
||||
|
||||
//clear host in redis
|
||||
func clearhost(c *bm.Context) {
|
||||
res := map[string]interface{}{}
|
||||
v := new(model.HostsReq)
|
||||
err := c.Bind(v)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if _, err = svr.AuthApp(c, user(c), c.Request.Header.Get("Cookie"), v.TreeID); err != nil {
|
||||
res["message"] = "服务树权限不足"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
c.JSON(nil, svr.ClearHost(c, v.TreeID, v.Env, v.Zone))
|
||||
}
|
617
app/admin/main/config/http/config.go
Normal file
617
app/admin/main/config/http/config.go
Normal file
@ -0,0 +1,617 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"go-common/app/admin/main/config/model"
|
||||
"go-common/library/ecode"
|
||||
"go-common/library/log"
|
||||
bm "go-common/library/net/http/blademaster"
|
||||
"go-common/library/time"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/jinzhu/gorm"
|
||||
)
|
||||
|
||||
func createConfig(c *bm.Context) {
|
||||
res := map[string]interface{}{}
|
||||
v := new(model.CreateConfigReq)
|
||||
err := c.Bind(v)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
user := user(c)
|
||||
if _, err = svr.AuthApp(c, user, c.Request.Header.Get("Cookie"), v.TreeID); err != nil {
|
||||
res["message"] = "服务树权限不足"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
conf := &model.Config{}
|
||||
conf.Operator = user
|
||||
conf.Name = v.Name
|
||||
conf.Mark = v.Mark
|
||||
conf.Comment = v.Comment
|
||||
conf.State = v.State
|
||||
conf.From = v.From
|
||||
c.JSON(nil, svr.CreateConf(conf, v.TreeID, v.Env, v.Zone, v.SkipLint))
|
||||
}
|
||||
|
||||
func lintConfig(c *bm.Context) {
|
||||
var req struct {
|
||||
Name string `form:"name" validate:"required"`
|
||||
Comment string `form:"comment" validate:"required"`
|
||||
}
|
||||
if err := c.Bind(&req); err != nil {
|
||||
// ignore error
|
||||
return
|
||||
}
|
||||
c.JSON(svr.LintConfig(req.Name, req.Comment))
|
||||
}
|
||||
|
||||
func updateConfValue(c *bm.Context) {
|
||||
res := map[string]interface{}{}
|
||||
v := new(model.UpdateConfValueReq)
|
||||
err := c.Bind(v)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
user := user(c)
|
||||
if _, err = svr.AuthApps(c, user, c.Request.Header.Get("Cookie")); err != nil {
|
||||
res["message"] = "服务树权限不足"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
conf := &model.Config{}
|
||||
conf.Name = v.Name
|
||||
conf.ID = v.ID
|
||||
conf.Operator = user
|
||||
conf.Mark = v.Mark
|
||||
conf.Comment = v.Comment
|
||||
conf.State = v.State
|
||||
conf.Mtime = time.Time(v.Mtime)
|
||||
var configs *model.Config
|
||||
configs, err = svr.Value(v.ID)
|
||||
if err != nil {
|
||||
res["message"] = "未找到源文件"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
if v.NewCommon > 0 {
|
||||
common := &model.CommonConf{}
|
||||
common2 := &model.CommonConf{}
|
||||
if err = svr.DB.Where("id = ?", configs.From).First(common).Error; err != nil {
|
||||
res["message"] = "未找到公共源文件"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
if err = svr.DB.Where("team_id = ? and name = ? and state = 2 and id = ?", common.TeamID, common.Name, v.NewCommon).Order("id desc").First(common2).Error; err != nil {
|
||||
res["message"] = "未找到最新的公共文件"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
conf.From = v.NewCommon
|
||||
}
|
||||
//验证是否最新源文件
|
||||
newConfig := &model.Config{}
|
||||
if err = svr.DB.Where("app_id = ? and name = ?", configs.AppID, configs.Name).Order("id desc").First(newConfig).Error; err != nil {
|
||||
res["message"] = "未找到最新文件"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
//默认验证ignore 0
|
||||
if newConfig.ID != v.ID && v.Ignore == 0 && user != newConfig.Operator {
|
||||
err = ecode.ConfigNotNow
|
||||
res["message"] = fmt.Sprintf("当前源文件:(%d)有最新源文件版本(%d)操作人:%s是否继续提交?", v.ID, newConfig.ID, newConfig.Operator)
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
c.JSON(nil, svr.UpdateConfValue(conf, v.SkipLint))
|
||||
}
|
||||
|
||||
func value(c *bm.Context) {
|
||||
res := map[string]interface{}{}
|
||||
v := new(model.ValueReq)
|
||||
err := c.Bind(v)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
var TreeID int64
|
||||
TreeID, err = svr.ConfigGetTreeID(v.ConfigID)
|
||||
if err != nil {
|
||||
res["message"] = "未找到tree_id"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
if _, err = svr.AuthApp(c, user(c), c.Request.Header.Get("Cookie"), TreeID); err != nil {
|
||||
res["message"] = "服务树权限不足"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
c.JSON(svr.Value(v.ConfigID))
|
||||
}
|
||||
|
||||
func configsByBuildID(c *bm.Context) {
|
||||
res := map[string]interface{}{}
|
||||
v := new(model.ConfigsByBuildIDReq)
|
||||
err := c.Bind(v)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if _, err = svr.AuthApps(c, user(c), c.Request.Header.Get("Cookie")); err != nil {
|
||||
res["message"] = "服务树权限不足"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
c.JSON(svr.ConfigsByBuildID(v.BuildID))
|
||||
}
|
||||
|
||||
func configsByTagID(c *bm.Context) {
|
||||
res := map[string]interface{}{}
|
||||
v := new(model.ConfigsByTagIDReq)
|
||||
err := c.Bind(v)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if _, err = svr.AuthApps(c, user(c), c.Request.Header.Get("Cookie")); err != nil {
|
||||
res["message"] = "服务树权限不足"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
c.JSON(svr.ConfigsByTagID(v.TagID))
|
||||
}
|
||||
|
||||
func configsByAppName(c *bm.Context) {
|
||||
res := map[string]interface{}{}
|
||||
v := new(model.ConfigsByAppNameReq)
|
||||
err := c.Bind(v)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if _, err = svr.AuthApp(c, user(c), c.Request.Header.Get("Cookie"), v.TreeID); err != nil {
|
||||
res["message"] = "服务树权限不足"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
c.JSON(svr.ConfigsByAppName(v.AppName, v.Env, v.Zone, v.TreeID, 0))
|
||||
}
|
||||
|
||||
func configSearchAll(c *bm.Context) {
|
||||
res := map[string]interface{}{}
|
||||
v := new(model.ConfigSearchAllReq)
|
||||
err := c.Bind(v)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
nodes, err := svr.AuthApps(c, user(c), c.Request.Header.Get("Cookie"))
|
||||
if err != nil {
|
||||
res["message"] = "服务树权限不足"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
c.JSON(svr.ConfigSearchAll(c, v.Env, v.Zone, v.Like, nodes))
|
||||
}
|
||||
|
||||
func configSearchApp(c *bm.Context) {
|
||||
res := map[string]interface{}{}
|
||||
v := new(model.ConfigSearchAppReq)
|
||||
err := c.Bind(v)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if _, err = svr.AuthApp(c, user(c), c.Request.Header.Get("Cookie"), v.TreeID); err != nil {
|
||||
res["message"] = "服务树权限不足"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
c.JSON(svr.ConfigSearchApp(c, v.AppName, v.Env, v.Zone, v.Like, v.BuildID, v.TreeID))
|
||||
}
|
||||
|
||||
func configsByName(c *bm.Context) {
|
||||
res := map[string]interface{}{}
|
||||
v := new(model.ConfigsByNameReq)
|
||||
err := c.Bind(v)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if _, err = svr.AuthApp(c, user(c), c.Request.Header.Get("Cookie"), v.TreeID); err != nil {
|
||||
res["message"] = "服务树权限不足"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
c.JSON(svr.ConfigsByTree(v.TreeID, v.Env, v.Zone, v.Name))
|
||||
}
|
||||
|
||||
func configs(c *bm.Context) {
|
||||
res := map[string]interface{}{}
|
||||
v := new(model.ConfigsReq)
|
||||
err := c.Bind(v)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if _, err = svr.AuthApp(c, user(c), c.Request.Header.Get("Cookie"), v.TreeID); err != nil {
|
||||
res["message"] = "服务树权限不足"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
c.JSON(svr.Configs(v.AppName, v.Env, v.Zone, v.BuildID, v.TreeID))
|
||||
}
|
||||
|
||||
func configRefs(c *bm.Context) {
|
||||
res := map[string]interface{}{}
|
||||
v := new(model.ConfigRefsReq)
|
||||
err := c.Bind(v)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if _, err = svr.AuthApp(c, user(c), c.Request.Header.Get("Cookie"), v.TreeID); err != nil {
|
||||
res["message"] = "服务树权限不足"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
c.JSON(svr.ConfigRefs(v.AppName, v.Env, v.Zone, v.BuildID, v.TreeID))
|
||||
}
|
||||
|
||||
func namesByAppName(c *bm.Context) {
|
||||
res := map[string]interface{}{}
|
||||
v := new(model.NamesByAppNameReq)
|
||||
err := c.Bind(v)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if _, err = svr.AuthApp(c, user(c), c.Request.Header.Get("Cookie"), v.TreeID); err != nil {
|
||||
res["message"] = "服务树权限不足"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
c.JSON(svr.NamesByAppTree(v.AppName, v.Env, v.Zone, v.TreeID))
|
||||
}
|
||||
|
||||
func diff(c *bm.Context) {
|
||||
res := map[string]interface{}{}
|
||||
v := new(model.DiffReq)
|
||||
err := c.Bind(v)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if _, err = svr.AuthApps(c, user(c), c.Request.Header.Get("Cookie")); err != nil {
|
||||
res["message"] = "服务树权限不足"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
c.JSON(svr.Diff(v.ConfigID, v.BuildID))
|
||||
}
|
||||
|
||||
func configDel(c *bm.Context) {
|
||||
res := map[string]interface{}{}
|
||||
v := new(model.ConfigDelReq)
|
||||
err := c.Bind(v)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if _, err = svr.AuthApps(c, user(c), c.Request.Header.Get("Cookie")); err != nil {
|
||||
res["message"] = "服务树权限不足"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
c.JSON(nil, svr.ConfigDel(v.ConfigID))
|
||||
}
|
||||
|
||||
func configBuildInfos(c *bm.Context) {
|
||||
res := map[string]interface{}{}
|
||||
v := new(model.ConfigBuildInfosReq)
|
||||
err := c.Bind(v)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if _, err = svr.AuthApp(c, user(c), c.Request.Header.Get("Cookie"), v.TreeID); err != nil {
|
||||
res["message"] = "服务树权限不足"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
c.JSON(svr.BuildConfigInfos(v.AppName, v.Env, v.Zone, v.BuildID, v.TreeID))
|
||||
}
|
||||
|
||||
func configUpdate(c *bm.Context) {
|
||||
res := map[string]interface{}{}
|
||||
v := new(model.ConfigUpdateReq)
|
||||
err := c.Bind(v)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
app := &model.App{}
|
||||
if err = svr.DB.Where("name = ? and env = ? and zone = ? and tree_id = ? and token = ?", v.AppName, v.Env, v.Zone, v.TreeID, v.Token).First(app).Error; err != nil {
|
||||
res["message"] = "参数不正确,未找到该服务"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
var obj []map[string]string
|
||||
err = json.Unmarshal([]byte(v.Data), &obj)
|
||||
tx := svr.DB.Begin()
|
||||
for _, val := range obj {
|
||||
if len(val["name"]) > 0 {
|
||||
config := &model.Config{}
|
||||
if err = tx.Where("app_id = ? and name = ? and state = 1", app.ID, val["name"]).First(config).Error; err != nil {
|
||||
if err != gorm.ErrRecordNotFound {
|
||||
c.JSON(nil, err)
|
||||
tx.Rollback()
|
||||
return
|
||||
}
|
||||
} else {
|
||||
//把老的更新了再加新的
|
||||
ups := map[string]interface{}{
|
||||
"state": 2,
|
||||
}
|
||||
if err = tx.Model(&model.App{}).Where("id = ? ", config.ID).Updates(ups).Error; err != nil {
|
||||
c.JSON(nil, err)
|
||||
tx.Rollback()
|
||||
return
|
||||
}
|
||||
}
|
||||
//加新的
|
||||
m := &model.Config{
|
||||
AppID: app.ID,
|
||||
Name: val["name"],
|
||||
Comment: val["comment"],
|
||||
State: 2,
|
||||
Mark: val["mark"],
|
||||
Operator: v.User,
|
||||
}
|
||||
db := tx.Create(m)
|
||||
if err = db.Error; err != nil {
|
||||
res["message"] = "创建失败"
|
||||
c.JSONMap(res, err)
|
||||
tx.Rollback()
|
||||
return
|
||||
}
|
||||
} else {
|
||||
c.JSON(nil, ecode.RequestErr)
|
||||
tx.Rollback()
|
||||
return
|
||||
}
|
||||
}
|
||||
tx.Commit()
|
||||
c.JSON(nil, err)
|
||||
}
|
||||
|
||||
func tagUpdate(c *bm.Context) {
|
||||
res := map[string]interface{}{}
|
||||
v := new(model.TagUpdateReq)
|
||||
err := c.Bind(v)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if len(strings.TrimSpace(v.Build)) == 0 {
|
||||
c.JSON(nil, ecode.RequestErr)
|
||||
return
|
||||
}
|
||||
app := &model.App{}
|
||||
if err = svr.DB.Where("name = ? and env = ? and zone = ? and tree_id = ? and token = ?", v.AppName, v.Env, v.Zone, v.TreeID, v.Token).First(app).Error; err != nil {
|
||||
res["message"] = "参数不正确,未找到该服务"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
confs := []*model.Config{}
|
||||
tags := &model.Tag{}
|
||||
tag := &model.Tag{}
|
||||
build := &model.Build{}
|
||||
tagConfigs := []*model.Config{}
|
||||
var in []string
|
||||
var in2 []string
|
||||
var nameString string
|
||||
tmp := make(map[string]struct{})
|
||||
if v.ConfigIDs == "" && v.Names == "" {
|
||||
c.JSON(nil, ecode.RequestErr)
|
||||
return
|
||||
} else if v.Names != "" {
|
||||
in = strings.Split(v.Names, ",")
|
||||
if err = svr.DB.Select("max(id) as id,name").Where("app_id = ? and state = 2 and is_delete = 0 and name in (?)", app.ID, in).Group("name").Find(&confs).Error; err != nil {
|
||||
res["message"] = "未找到发版文件"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
for _, vv := range confs {
|
||||
if len(nameString) > 0 {
|
||||
nameString = nameString + ","
|
||||
}
|
||||
nameString = nameString + strconv.FormatInt(vv.ID, 10)
|
||||
}
|
||||
tag.ConfigIDs = nameString
|
||||
} else if v.ConfigIDs != "" {
|
||||
in = strings.Split(v.ConfigIDs, ",")
|
||||
if err = svr.DB.Where("app_id = ? and state = 2 and is_delete = 0 and id in (?)", app.ID, in).Find(&confs).Error; err != nil {
|
||||
res["message"] = "未找到发版文件"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
tag.ConfigIDs = v.ConfigIDs
|
||||
}
|
||||
if v.Names != "" && v.Increment == 1 {
|
||||
if err = svr.DB.Where("app_id = ? and name = ?", app.ID, v.Build).Order("id desc").First(build).Error; err != nil {
|
||||
res["message"] = "未找到对应的build"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
if err = svr.DB.Where("app_id = ? and build_id = ?", app.ID, build.ID).Order("id desc").First(tags).Error; err != nil {
|
||||
res["message"] = "未找到对应的tag"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
in2 = strings.Split(tags.ConfigIDs, ",")
|
||||
if err = svr.DB.Where("app_id = ? and state = 2 and id in (?)", app.ID, in2).Find(&tagConfigs).Error; err != nil {
|
||||
res["message"] = "未找到tag中的文件"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
for _, vv := range tagConfigs {
|
||||
tss := 0
|
||||
for _, vvv := range confs {
|
||||
if vv.Name == vvv.Name {
|
||||
tss = 1
|
||||
}
|
||||
}
|
||||
if tss != 1 {
|
||||
if len(nameString) > 0 {
|
||||
nameString = nameString + ","
|
||||
}
|
||||
nameString = nameString + strconv.FormatInt(vv.ID, 10)
|
||||
}
|
||||
}
|
||||
tag.ConfigIDs = nameString
|
||||
} else {
|
||||
if len(confs) != len(in) {
|
||||
res["message"] = "发版数据不符"
|
||||
c.JSONMap(res, ecode.RequestErr)
|
||||
return
|
||||
}
|
||||
for _, vv := range confs {
|
||||
if _, ok := tmp[vv.Name]; !ok {
|
||||
tmp[vv.Name] = struct{}{}
|
||||
}
|
||||
}
|
||||
if len(tmp) != len(confs) {
|
||||
res["message"] = "有重复的文件名"
|
||||
c.JSONMap(res, ecode.RequestErr)
|
||||
return
|
||||
}
|
||||
}
|
||||
tag.Operator = v.User
|
||||
tag.Mark = v.Mark
|
||||
if v.Force == 1 {
|
||||
tag.Force = 1
|
||||
}
|
||||
c.JSON(nil, svr.UpdateTag(c, v.TreeID, v.Env, v.Zone, v.Build, tag))
|
||||
}
|
||||
|
||||
func canalTagUpdate(c *bm.Context) {
|
||||
res := map[string]interface{}{}
|
||||
v := new(model.CanalTagUpdateReq)
|
||||
err := c.Bind(v)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if v.Force != 1 {
|
||||
v.Force = 0
|
||||
}
|
||||
if len(strings.TrimSpace(v.Build)) == 0 {
|
||||
c.JSON(nil, ecode.RequestErr)
|
||||
return
|
||||
}
|
||||
app := &model.App{}
|
||||
if err = svr.DB.Where("name = ? and env = ? and zone = ? and tree_id = ? and token = ?", v.AppName, v.Env, v.Zone, v.TreeID, v.Token).First(app).Error; err != nil {
|
||||
res["message"] = "参数不正确,未找到该服务"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
confs := []*model.Config{}
|
||||
configs := []*model.Config{}
|
||||
tags := &model.Tag{}
|
||||
tag := &model.Tag{}
|
||||
build := &model.Build{}
|
||||
tagConfigs := []*model.Config{}
|
||||
var in []string
|
||||
var in2 []string
|
||||
var nameString string
|
||||
tmp := make(map[string]struct{})
|
||||
in = strings.Split(v.ConfigIDs, ",")
|
||||
if err = svr.DB.Where("app_id = ? and state = 2 and id in(?)", app.ID, in).Find(&configs).Error; err != nil {
|
||||
res["message"] = "未找到文件"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
if len(configs) != len(in) {
|
||||
res["message"] = fmt.Sprintf("数据不匹配,传的数据为(%v)条,查到的数据为(%v)条,app_id(%v),config_ids(%v),in(%v)", len(in), len(configs), app.ID, v.ConfigIDs, in)
|
||||
err = ecode.RequestErr
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
if err = svr.DB.Where("app_id = ? and name = ?", app.ID, v.Build).Order("id desc").First(build).Error; err != nil {
|
||||
res["message"] = "未找到对应的build"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
if err = svr.DB.Where("app_id = ? and build_id = ?", app.ID, build.ID).Order("id desc").First(tags).Error; err != nil {
|
||||
res["message"] = "未找到对应的tag"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
in2 = strings.Split(tags.ConfigIDs, ",")
|
||||
if err = svr.DB.Where("app_id = ? and state = 2 and id in (?)", app.ID, in2).Find(&tagConfigs).Error; err != nil {
|
||||
res["message"] = "未找到tag中的文件"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
if err = svr.DB.Select("id,app_id,name,`from`,state,mark,operator,ctime,mtime").Where(in2).Find(&confs).Error; err != nil {
|
||||
log.Error("ConfigsByIDs(%v) error(%v)", in2, err)
|
||||
res["message"] = "config文件未找到"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
for _, val := range confs {
|
||||
for _, vv := range configs {
|
||||
if val.Name == vv.Name {
|
||||
if len(nameString) > 0 {
|
||||
nameString = nameString + ","
|
||||
}
|
||||
nameString = nameString + strconv.FormatInt(vv.ID, 10)
|
||||
tmp[vv.Name] = struct{}{}
|
||||
}
|
||||
}
|
||||
if _, ok := tmp[val.Name]; !ok {
|
||||
if len(nameString) > 0 {
|
||||
nameString = nameString + ","
|
||||
}
|
||||
nameString = nameString + strconv.FormatInt(val.ID, 10)
|
||||
}
|
||||
}
|
||||
for _, val := range configs {
|
||||
if _, ok := tmp[val.Name]; !ok {
|
||||
if len(nameString) > 0 {
|
||||
nameString = nameString + ","
|
||||
}
|
||||
nameString = nameString + strconv.FormatInt(val.ID, 10)
|
||||
}
|
||||
}
|
||||
tag.ConfigIDs = nameString
|
||||
tag.Operator = v.User
|
||||
tag.Mark = v.Mark
|
||||
tag.Force = v.Force
|
||||
c.JSON(nil, svr.UpdateTag(c, v.TreeID, v.Env, v.Zone, v.Build, tag))
|
||||
}
|
||||
|
||||
func canalConfigCreate(c *bm.Context) {
|
||||
res := map[string]interface{}{}
|
||||
v := new(model.CanalConfigCreateReq)
|
||||
err := c.Bind(v)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if err = svr.CanalCheckToken(v.AppName, v.Env, v.Zone, v.Token); err != nil {
|
||||
res["message"] = "未找到数据"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
conf := &model.Config{}
|
||||
conf.Operator = v.User
|
||||
conf.Name = v.Name
|
||||
conf.Mark = v.Mark
|
||||
conf.Comment = v.Comment
|
||||
conf.State = v.State
|
||||
conf.From = v.From
|
||||
c.JSON(nil, svr.CreateConf(conf, v.TreeID, v.Env, v.Zone, true))
|
||||
}
|
||||
|
||||
func canalNameConfigs(c *bm.Context) {
|
||||
res := map[string]interface{}{}
|
||||
v := new(model.CanalNameConfigsReq)
|
||||
err := c.Bind(v)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if err = svr.CanalCheckToken(v.AppName, v.Env, v.Zone, v.Token); err != nil {
|
||||
res["message"] = "未找到数据"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
c.JSON(svr.ConfigsByTree(v.TreeID, v.Env, v.Zone, v.Name))
|
||||
}
|
136
app/admin/main/config/http/http.go
Normal file
136
app/admin/main/config/http/http.go
Normal file
@ -0,0 +1,136 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"go-common/app/admin/main/config/conf"
|
||||
"go-common/app/admin/main/config/service"
|
||||
"go-common/library/log"
|
||||
bm "go-common/library/net/http/blademaster"
|
||||
"go-common/library/net/http/blademaster/middleware/permit"
|
||||
)
|
||||
|
||||
var (
|
||||
svr *service.Service
|
||||
authSrv *permit.Permit
|
||||
)
|
||||
|
||||
// Init init config.
|
||||
func Init(c *conf.Config, s *service.Service) {
|
||||
svr = s
|
||||
authSrv = permit.New(c.Auth)
|
||||
engine := bm.DefaultServer(c.BM)
|
||||
innerRouter(engine)
|
||||
if err := engine.Start(); err != nil {
|
||||
log.Error("engine.Start error(%v)", err)
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// innerRouter init inner router.
|
||||
func innerRouter(e *bm.Engine) {
|
||||
e.Ping(ping)
|
||||
b := e.Group("x/admin/config", authSrv.Verify())
|
||||
d := e.Group("x/admin/config")
|
||||
{
|
||||
notAuth := d.Group("/")
|
||||
{
|
||||
notAuth.POST("home/config/update", configUpdate)
|
||||
notAuth.POST("home/tag/update", tagUpdate)
|
||||
notAuth.POST("canal/tag/update", canalTagUpdate)
|
||||
notAuth.POST("canal/name/configs", canalNameConfigs)
|
||||
notAuth.POST("canal/config/create", canalConfigCreate)
|
||||
notAuth.POST("caster/envs", casterEnvs)
|
||||
notAuth.GET("get/apps", getApps)
|
||||
}
|
||||
service := b.Group("/service")
|
||||
{
|
||||
service.POST("/token/set", setToken)
|
||||
service.GET("/host/infos", hosts)
|
||||
service.POST("/delete", clearhost)
|
||||
}
|
||||
app := b.Group("/app")
|
||||
{
|
||||
app.POST("/token/update", updateToken)
|
||||
app.POST("/create", create)
|
||||
app.GET("/apps", appList)
|
||||
app.GET("/envs", envs)
|
||||
app.GET("/nodeTree", nodeTree)
|
||||
app.POST("/zone/copy", zoneCopy)
|
||||
app.POST("/rename", rename)
|
||||
app.POST("/status", upAppStatus)
|
||||
}
|
||||
bu := b.Group("/build")
|
||||
{
|
||||
bu.POST("/create", createBuild)
|
||||
bu.POST("/tag/update", updateTag)
|
||||
bu.POST("/tagid/update", updateTagID)
|
||||
bu.GET("/builds", builds)
|
||||
bu.GET("/build", build)
|
||||
bu.POST("/delete", buildDel)
|
||||
bu.POST("/hosts/force", hostsForce)
|
||||
bu.POST("/clear/force", clearForce)
|
||||
}
|
||||
config := b.Group("/config")
|
||||
{
|
||||
config.POST("/create", createConfig)
|
||||
config.POST("/lint", lintConfig)
|
||||
config.POST("/value/update", updateConfValue)
|
||||
config.GET("/app/configs", configsByAppName)
|
||||
config.GET("/build/configs", configsByBuildID)
|
||||
config.GET("/tag/configs", configsByTagID)
|
||||
config.GET("/name/configs", configsByName)
|
||||
config.GET("/names", namesByAppName)
|
||||
config.GET("/configs", configs)
|
||||
config.GET("/all/search", configSearchAll)
|
||||
config.GET("/app/search", configSearchApp)
|
||||
config.GET("/refs", configRefs)
|
||||
config.GET("/value", value)
|
||||
config.GET("/diff", diff)
|
||||
config.POST("/delete", configDel)
|
||||
config.GET("/build/infos", configBuildInfos)
|
||||
}
|
||||
common := b.Group("/common")
|
||||
{
|
||||
common.POST("/create", createComConfig)
|
||||
common.POST("/value/update", updateComConfValue)
|
||||
common.GET("/name/configs", comConfigsByName)
|
||||
common.GET("/configs", configsByTeam)
|
||||
common.GET("/names", namesByTeam)
|
||||
common.GET("/value", comValue)
|
||||
common.GET("/envs", envsByTeam)
|
||||
common.GET("/app", appByTeam)
|
||||
common.GET("/tag/push", tagPush)
|
||||
}
|
||||
tags := b.Group("/tag")
|
||||
{
|
||||
tags.POST("/create", createTag)
|
||||
tags.GET("/last/tags", lastTags)
|
||||
tags.GET("/build/tags", tagsByBuild)
|
||||
tags.GET("/tag", tag)
|
||||
tags.GET("/config/diff", tagConfigDiff)
|
||||
}
|
||||
apm := b.Group("/apm")
|
||||
{
|
||||
apm.GET("/copy", apmCopy)
|
||||
}
|
||||
tree := b.Group("/tree")
|
||||
{
|
||||
tree.GET("/update", syncTree)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ping check server ok.
|
||||
func ping(ctx *bm.Context) {
|
||||
if err := svr.Ping(); err != nil {
|
||||
log.Error("service ping error(%v)", err)
|
||||
ctx.AbortWithStatus(http.StatusServiceUnavailable)
|
||||
}
|
||||
}
|
||||
|
||||
func user(c *bm.Context) (username string) {
|
||||
usernameI, _ := c.Get("username")
|
||||
username, _ = usernameI.(string)
|
||||
return
|
||||
}
|
222
app/admin/main/config/http/tag.go
Normal file
222
app/admin/main/config/http/tag.go
Normal file
@ -0,0 +1,222 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"go-common/app/admin/main/config/model"
|
||||
"go-common/library/ecode"
|
||||
"go-common/library/log"
|
||||
bm "go-common/library/net/http/blademaster"
|
||||
)
|
||||
|
||||
func createTag(c *bm.Context) {
|
||||
res := map[string]interface{}{}
|
||||
v := new(model.CreateTagReq)
|
||||
err := c.Bind(v)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
user := user(c)
|
||||
if _, err = svr.AuthApp(c, user, c.Request.Header.Get("Cookie"), v.TreeID); err != nil {
|
||||
res["message"] = "服务树权限不足"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
tag := &model.Tag{}
|
||||
tag.Mark = v.Mark
|
||||
tag.ConfigIDs = v.ConfigIDs
|
||||
tag.Operator = user
|
||||
c.JSON(nil, svr.CreateTag(tag, v.TreeID, v.Env, v.Zone))
|
||||
}
|
||||
|
||||
func lastTags(c *bm.Context) {
|
||||
res := map[string]interface{}{}
|
||||
v := new(model.LastTagsReq)
|
||||
err := c.Bind(v)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if _, err = svr.AuthApp(c, user(c), c.Request.Header.Get("Cookie"), v.TreeID); err != nil {
|
||||
res["message"] = "服务树权限不足"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
c.JSON(svr.LastTags(v.TreeID, v.Env, v.Zone, v.Build))
|
||||
}
|
||||
|
||||
func tagsByBuild(c *bm.Context) {
|
||||
res := map[string]interface{}{}
|
||||
v := new(model.TagsByBuildReq)
|
||||
err := c.Bind(v)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if _, err = svr.AuthApp(c, user(c), c.Request.Header.Get("Cookie"), v.TreeID); err != nil {
|
||||
res["message"] = "服务树权限不足"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
c.JSON(svr.TagsByBuild(v.AppName, v.Env, v.Zone, v.Build, v.Ps, v.Pn, v.TreeID))
|
||||
}
|
||||
|
||||
func tag(c *bm.Context) {
|
||||
res := map[string]interface{}{}
|
||||
v := new(model.TagReq)
|
||||
err := c.Bind(v)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if _, err = svr.AuthApps(c, user(c), c.Request.Header.Get("Cookie")); err != nil {
|
||||
res["message"] = "服务树权限不足"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
c.JSON(svr.Tag(v.TagID))
|
||||
}
|
||||
|
||||
func updateTag(c *bm.Context) {
|
||||
res := map[string]interface{}{}
|
||||
v := new(model.UpdatetagReq)
|
||||
err := c.Bind(v)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if v.Force != 1 {
|
||||
v.Force = 0
|
||||
}
|
||||
user := user(c)
|
||||
if _, err = svr.AuthApp(c, user, c.Request.Header.Get("Cookie"), v.TreeID); err != nil {
|
||||
res["message"] = "服务树权限不足"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
if len(strings.TrimSpace(v.Build)) == 0 {
|
||||
res["message"] = "build不能为空"
|
||||
c.JSONMap(res, ecode.RequestErr)
|
||||
return
|
||||
}
|
||||
tag := &model.Tag{}
|
||||
tag.Operator = user
|
||||
tag.Mark = v.Mark
|
||||
tag.ConfigIDs = v.ConfigIDs
|
||||
tag.Force = v.Force
|
||||
c.JSON(nil, svr.UpdateTag(c, v.TreeID, v.Env, v.Zone, v.Build, tag))
|
||||
}
|
||||
|
||||
func updateTagID(c *bm.Context) {
|
||||
res := map[string]interface{}{}
|
||||
v := new(model.UpdateTagIDReq)
|
||||
err := c.Bind(v)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
user := user(c)
|
||||
if _, err = svr.AuthApp(c, user, c.Request.Header.Get("Cookie"), v.TreeID); err != nil {
|
||||
res["message"] = "服务树权限不足"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
if len(strings.TrimSpace(v.Build)) == 0 {
|
||||
res["message"] = "build不能为空"
|
||||
c.JSONMap(res, ecode.RequestErr)
|
||||
return
|
||||
}
|
||||
tag := &model.Tag{}
|
||||
if tag, err = svr.RollBackTag(v.TagID); err != nil {
|
||||
res["message"] = "tag_id有误"
|
||||
c.JSONMap(res, ecode.RequestErr)
|
||||
return
|
||||
}
|
||||
tag.Operator = user
|
||||
tag.Mark = fmt.Sprintf("回滚操作:原tag_id:%d", v.TagID)
|
||||
c.JSON(nil, svr.UpdateTag(c, v.TreeID, v.Env, v.Zone, v.Build, tag))
|
||||
}
|
||||
|
||||
func hostsForce(c *bm.Context) {
|
||||
res := map[string]interface{}{}
|
||||
v := new(model.CreateForceReq)
|
||||
err := c.Bind(v)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
user := user(c)
|
||||
if _, err = svr.AuthApp(c, user, c.Request.Header.Get("Cookie"), v.TreeID); err != nil {
|
||||
res["message"] = "服务树权限不足"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
var mHosts model.MapHosts
|
||||
err = json.Unmarshal([]byte(v.Hosts), &mHosts)
|
||||
if err != nil {
|
||||
res["message"] = "解析hosts失败"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
c.JSON(nil, svr.UpdateForce(c, v.TreeID, v.Version, v.Env, v.Zone, v.Build, user, mHosts))
|
||||
}
|
||||
|
||||
func clearForce(c *bm.Context) {
|
||||
res := map[string]interface{}{}
|
||||
v := new(model.ClearForceReq)
|
||||
err := c.Bind(v)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
user := user(c)
|
||||
if _, err = svr.AuthApp(c, user, c.Request.Header.Get("Cookie"), v.TreeID); err != nil {
|
||||
res["message"] = "服务树权限不足"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
var mHosts model.MapHosts
|
||||
err = json.Unmarshal([]byte(v.Hosts), &mHosts)
|
||||
if err != nil {
|
||||
res["message"] = "解析hosts失败"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
c.JSON(nil, svr.ClearForce(c, v.TreeID, v.Env, v.Zone, v.Build, mHosts))
|
||||
}
|
||||
|
||||
func tagConfigDiff(c *bm.Context) {
|
||||
res := map[string]interface{}{}
|
||||
v := new(model.TagConfigDiff)
|
||||
err := c.Bind(v)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if _, err = svr.AuthApp(c, user(c), c.Request.Header.Get("Cookie"), v.TreeID); err != nil {
|
||||
res["message"] = "服务树权限不足"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
tag, err := svr.LastTasConfigDiff(v.TagID, v.AppID, v.BuildID)
|
||||
if err != nil {
|
||||
res["message"] = "版本未找到"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
var config *model.Config
|
||||
var configIDS []int64
|
||||
if len(tag.ConfigIDs) > 0 {
|
||||
tmpIDs := strings.Split(tag.ConfigIDs, ",")
|
||||
for _, vv := range tmpIDs {
|
||||
id, err := strconv.ParseInt(vv, 10, 64)
|
||||
if err != nil {
|
||||
log.Error("strconv.ParseInt() error(%v)", err)
|
||||
return
|
||||
}
|
||||
configIDS = append(configIDS, id)
|
||||
}
|
||||
config, err = svr.GetConfig(configIDS, v.Name)
|
||||
if err != nil {
|
||||
res["message"] = "配置文件未找到"
|
||||
c.JSONMap(res, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
c.JSON(config, err)
|
||||
}
|
10
app/admin/main/config/http/tree.go
Normal file
10
app/admin/main/config/http/tree.go
Normal file
@ -0,0 +1,10 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
bm "go-common/library/net/http/blademaster"
|
||||
)
|
||||
|
||||
func syncTree(c *bm.Context) {
|
||||
svr.SyncTree(c, user(c), c.Request.Header.Get("Cookie"))
|
||||
c.JSON(nil, nil)
|
||||
}
|
38
app/admin/main/config/model/BUILD
Normal file
38
app/admin/main/config/model/BUILD
Normal file
@ -0,0 +1,38 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"apm.go",
|
||||
"app.go",
|
||||
"build.go",
|
||||
"common.go",
|
||||
"config.go",
|
||||
"force.go",
|
||||
"tag.go",
|
||||
"team.go",
|
||||
],
|
||||
importpath = "go-common/app/admin/main/config/model",
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = ["//library/time:go_default_library"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
84
app/admin/main/config/model/apm.go
Normal file
84
app/admin/main/config/model/apm.go
Normal file
@ -0,0 +1,84 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
xtime "go-common/library/time"
|
||||
)
|
||||
|
||||
// TableName case tablename.
|
||||
func (*ServiceName) TableName() string {
|
||||
return "service_name"
|
||||
}
|
||||
|
||||
// ServiceName service name.
|
||||
type ServiceName struct {
|
||||
ID int `gorm:"column:id" json:"id"`
|
||||
Name string `gorm:"column:name" json:"name"`
|
||||
Remark string `gorm:"column:remark" json:"remark"`
|
||||
Token string `gorm:"column:token" json:"token"`
|
||||
ConfigID string `gorm:"column:config_id" json:"config_id"`
|
||||
ProjectTeamID string `gorm:"column:project_team_id" json:"project_team_id"`
|
||||
Environment int8 `gorm:"column:environment" json:"environment"`
|
||||
Public string `gorm:"column:public" json:"public"`
|
||||
CTime xtime.Time `gorm:"column:ctime" json:"ctime"`
|
||||
MTime xtime.Time `gorm:"column:mtime" json:"mtime"`
|
||||
}
|
||||
|
||||
// TableName case tablename.
|
||||
func (*ServiceConfig) TableName() string {
|
||||
return "service_config"
|
||||
}
|
||||
|
||||
// ServiceConfig service config.
|
||||
type ServiceConfig struct {
|
||||
ID int `gorm:"column:id" json:"id"`
|
||||
ServiceID int `gorm:"column:service_id" json:"service_id"`
|
||||
Suffix string `gorm:"column:suffix" json:"suffix"`
|
||||
Config string `gorm:"column:config" json:"config"`
|
||||
State int8 `gorm:"column:state" json:"state"`
|
||||
Operator string `gorm:"column:operator" json:"operator"`
|
||||
Remark string `gorm:"column:remark" json:"remark"`
|
||||
CTime xtime.Time `gorm:"column:ctime" json:"ctime"`
|
||||
MTime xtime.Time `gorm:"column:mtime" json:"mtime"`
|
||||
}
|
||||
|
||||
// TableName case tablename.
|
||||
func (*ServiceConfigValue) TableName() string {
|
||||
return "service_config_value"
|
||||
}
|
||||
|
||||
// ServiceConfigValue service config value.
|
||||
type ServiceConfigValue struct {
|
||||
ID int `gorm:"column:id" json:"id"`
|
||||
ConfigID int `gorm:"column:config_id" json:"config_id"`
|
||||
Name string `gorm:"column:name" json:"name"`
|
||||
Config string `gorm:"column:config" json:"config"`
|
||||
State int8 `gorm:"column:state" json:"state"`
|
||||
Operator string `gorm:"column:operator" json:"operator"`
|
||||
NamespaceID int `gorm:"column:namespace_id" json:"namespace_id"`
|
||||
CTime xtime.Time `gorm:"column:ctime" json:"ctime"`
|
||||
MTime xtime.Time `gorm:"column:mtime" json:"mtime"`
|
||||
}
|
||||
|
||||
// TableName case tablename.
|
||||
func (*BuildVersion) TableName() string {
|
||||
return "build_version"
|
||||
}
|
||||
|
||||
// BuildVersion build version.
|
||||
type BuildVersion struct {
|
||||
ID int `gorm:"column:id" json:"id"`
|
||||
ServiceID int `gorm:"column:service_id" json:"service_id"`
|
||||
Version string `gorm:"column:version" json:"version"`
|
||||
Remark string `gorm:"column:remark" json:"remark"`
|
||||
State int8 `gorm:"column:state" json:"state"`
|
||||
ConfigID int `gorm:"column:config_id" json:"config_id"`
|
||||
CTime xtime.Time `gorm:"column:ctime" json:"ctime"`
|
||||
MTime xtime.Time `gorm:"column:mtime" json:"mtime"`
|
||||
}
|
||||
|
||||
//ApmCopyReq ...
|
||||
type ApmCopyReq struct {
|
||||
Name string `form:"name" validate:"required"`
|
||||
TreeID int64 `form:"tree_id" validate:"required"`
|
||||
ApmName string `form:"apmname" validate:"required"`
|
||||
}
|
180
app/admin/main/config/model/app.go
Normal file
180
app/admin/main/config/model/app.go
Normal file
@ -0,0 +1,180 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
xtime "go-common/library/time"
|
||||
)
|
||||
|
||||
const (
|
||||
// Ops ops.
|
||||
Ops = 3
|
||||
// Rds rds.
|
||||
Rds = 2
|
||||
// DefaultEnv defaultEnv.
|
||||
DefaultEnv = "dev"
|
||||
// DefaultZone defaultzone.
|
||||
DefaultZone = "sh001"
|
||||
//StatusShow status show
|
||||
StatusShow = 1
|
||||
//StatusHidden status hidden
|
||||
StatusHidden = 2
|
||||
)
|
||||
|
||||
//App app.
|
||||
type App struct {
|
||||
ID int64 `json:"id" gorm:"primary_key"`
|
||||
Name string `json:"name"`
|
||||
TreeID int64 `json:"tree_id"`
|
||||
Env string `json:"env"`
|
||||
Zone string `json:"zone"`
|
||||
Token string `json:"token"`
|
||||
Status int8 `json:"status"`
|
||||
Ctime xtime.Time `json:"ctime"`
|
||||
Mtime xtime.Time `json:"mtime"`
|
||||
}
|
||||
|
||||
// TableName app
|
||||
func (App) TableName() string {
|
||||
return "app"
|
||||
}
|
||||
|
||||
// Node node.
|
||||
type Node struct {
|
||||
Name string `json:"name"`
|
||||
Path string `json:"path"`
|
||||
TreeID int64 `json:"tree_id"`
|
||||
}
|
||||
|
||||
// TreeNode TreeNode.
|
||||
type TreeNode struct {
|
||||
Alias string `json:"alias"`
|
||||
CreatedAt string `json:"created_at"`
|
||||
Name string `json:"name"`
|
||||
Path string `json:"path"`
|
||||
Tags interface{} `json:"tags"`
|
||||
Type int `json:"type"`
|
||||
}
|
||||
|
||||
// Res res.
|
||||
type Res struct {
|
||||
Count int `json:"count"`
|
||||
Data []*TreeNode `json:"data"`
|
||||
Page int `json:"page"`
|
||||
Results int `json:"results"`
|
||||
}
|
||||
|
||||
// AppPager app pager
|
||||
type AppPager struct {
|
||||
Total int64 `json:"total"`
|
||||
Pn int64 `json:"pn"`
|
||||
Ps int64 `json:"ps"`
|
||||
Items []*App `json:"items"`
|
||||
}
|
||||
|
||||
// Resp tree resp
|
||||
type Resp struct {
|
||||
Data map[string]*Tree `json:"data"`
|
||||
}
|
||||
|
||||
// Tree node.
|
||||
type Tree struct {
|
||||
Name string `json:"name"`
|
||||
Type int `json:"type"`
|
||||
Path string `json:"path"`
|
||||
Tags *TreeTag `json:"tags"`
|
||||
Children map[string]*Tree `json:"children"`
|
||||
}
|
||||
|
||||
//TreeTag tree tag.
|
||||
type TreeTag struct {
|
||||
Ops string `json:"ops"`
|
||||
Rds string `json:"rds"`
|
||||
}
|
||||
|
||||
//Env env.
|
||||
type Env struct {
|
||||
Name string `json:"name"`
|
||||
NikeName string `json:"nike_name"`
|
||||
Token string `json:"token"`
|
||||
}
|
||||
|
||||
//RoleNode roleNode .
|
||||
type RoleNode struct {
|
||||
ID int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Path string `json:"path"`
|
||||
Type int8 `json:"type"`
|
||||
Role int8 `json:"role"`
|
||||
}
|
||||
|
||||
//UpdateTokenReq ...
|
||||
type UpdateTokenReq struct {
|
||||
AppName string `form:"app_name" validate:"required"`
|
||||
Env string `form:"env" validate:"required"`
|
||||
Zone string `form:"zone" validate:"required"`
|
||||
TreeID int64 `form:"tree_id" validate:"required"`
|
||||
}
|
||||
|
||||
//CreateReq ...
|
||||
type CreateReq struct {
|
||||
AppName string `form:"app_name" validate:"required"`
|
||||
TreeID int64 `form:"tree_id" validate:"required"`
|
||||
}
|
||||
|
||||
//AppListReq ...
|
||||
type AppListReq struct {
|
||||
AppName string `form:"app_name"`
|
||||
Bu string `form:"bu"`
|
||||
Team string `form:"team"`
|
||||
Pn int64 `form:"pn" default:"1" validate:"min=1"`
|
||||
Ps int64 `form:"ps" default:"20" validate:"min=1"`
|
||||
Status int8 `form:"status"`
|
||||
}
|
||||
|
||||
//EnvsByTeamReq ...
|
||||
type EnvsByTeamReq struct {
|
||||
AppName string `form:"app_name"`
|
||||
Zone string `form:"zone"`
|
||||
Team string `form:"team"`
|
||||
}
|
||||
|
||||
//EnvsReq ...
|
||||
type EnvsReq struct {
|
||||
AppName string `form:"app_name" validate:"required"`
|
||||
TreeID int64 `form:"tree_id" validate:"required"`
|
||||
Zone string `form:"zone" validate:"required"`
|
||||
}
|
||||
|
||||
//NodeTreeReq ...
|
||||
type NodeTreeReq struct {
|
||||
Node string `form:"node"`
|
||||
Team string `form:"team"`
|
||||
}
|
||||
|
||||
//ZoneCopyReq ...
|
||||
type ZoneCopyReq struct {
|
||||
AppName string `form:"app_name" validate:"required"`
|
||||
From string `form:"from_zone" validate:"required"`
|
||||
To string `form:"to_zone" validate:"required"`
|
||||
TreeID int64 `form:"tree_id" validate:"required"`
|
||||
}
|
||||
|
||||
//CasterEnvsReq ...
|
||||
type CasterEnvsReq struct {
|
||||
TreeID int64 `form:"tree_id" validate:"required"`
|
||||
Zone string `form:"zone" validate:"required"`
|
||||
Auth string `form:"auth" validate:"required"`
|
||||
}
|
||||
|
||||
//CacheData ...
|
||||
type CacheData struct {
|
||||
Data map[int64]*RoleNode `json:"data"`
|
||||
CTime time.Time `json:"ctime"`
|
||||
}
|
||||
|
||||
//AppStatusReq ...
|
||||
type AppStatusReq struct {
|
||||
TreeID int64 `form:"tree_id" validate:"required"`
|
||||
Status int8 `form:"status" default:"1"`
|
||||
}
|
43
app/admin/main/config/model/build.go
Normal file
43
app/admin/main/config/model/build.go
Normal file
@ -0,0 +1,43 @@
|
||||
package model
|
||||
|
||||
import "go-common/library/time"
|
||||
|
||||
//Build build.
|
||||
type Build struct {
|
||||
ID int64 `json:"id"`
|
||||
AppID int64 `json:"app_id"`
|
||||
Name string `json:"name"`
|
||||
TagID int64 `json:"tag_id"`
|
||||
Mark string `json:"mark"`
|
||||
Operator string `json:"operator"`
|
||||
Ctime time.Time `json:"ctime"`
|
||||
Mtime time.Time `json:"mtime"`
|
||||
}
|
||||
|
||||
// TableName build.
|
||||
func (Build) TableName() string {
|
||||
return "build"
|
||||
}
|
||||
|
||||
//CreateBuildReq ...
|
||||
type CreateBuildReq struct {
|
||||
AppName string `form:"app_name" validate:"required"`
|
||||
Env string `form:"env" validate:"required"`
|
||||
Zone string `form:"zone" validate:"required"`
|
||||
Name string `form:"name" validate:"required"`
|
||||
TagID int64 `form:"tag_id" validate:"required"`
|
||||
TreeID int64 `form:"tree_id" validate:"required"`
|
||||
}
|
||||
|
||||
//BuildsReq ...
|
||||
type BuildsReq struct {
|
||||
AppName string `form:"app_name" validate:"required"`
|
||||
Env string `form:"env" validate:"required"`
|
||||
Zone string `form:"zone" validate:"required"`
|
||||
TreeID int64 `form:"tree_id" validate:"required"`
|
||||
}
|
||||
|
||||
//BuildReq ...
|
||||
type BuildReq struct {
|
||||
BuildID int64 `form:"build_id" validate:"required"`
|
||||
}
|
106
app/admin/main/config/model/common.go
Normal file
106
app/admin/main/config/model/common.go
Normal file
@ -0,0 +1,106 @@
|
||||
package model
|
||||
|
||||
import "go-common/library/time"
|
||||
|
||||
// CommonConf commonConf.
|
||||
type CommonConf struct {
|
||||
ID int64 `json:"id" gorm:"primary_key"`
|
||||
TeamID int64 `json:"team_id"`
|
||||
Name string `json:"name"`
|
||||
Comment string `json:"comment"`
|
||||
State int8 `json:"state"`
|
||||
Mark string `json:"mark"`
|
||||
Operator string `json:"operator"`
|
||||
Ctime time.Time `json:"ctime"`
|
||||
Mtime time.Time `json:"mtime"`
|
||||
}
|
||||
|
||||
// TableName commonConfig.
|
||||
func (CommonConf) TableName() string {
|
||||
return "common_config"
|
||||
}
|
||||
|
||||
// CommonConfPager app pager
|
||||
type CommonConfPager struct {
|
||||
Total int64 `json:"total"`
|
||||
Pn int64 `json:"pn"`
|
||||
Ps int64 `json:"ps"`
|
||||
Items []*CommonConf `json:"items"`
|
||||
}
|
||||
|
||||
// CommonName app pager
|
||||
type CommonName struct {
|
||||
Name string `json:"name"`
|
||||
ID int64 `json:"id"`
|
||||
}
|
||||
|
||||
// CommonTemp app temp
|
||||
type CommonTemp struct {
|
||||
ID int64 `json:"id"`
|
||||
}
|
||||
|
||||
// CommonCounts app counts
|
||||
type CommonCounts struct {
|
||||
Counts int64 `json:"counts"`
|
||||
}
|
||||
|
||||
//CreateComConfigReq ...
|
||||
type CreateComConfigReq struct {
|
||||
Team string `form:"team" validate:"required"`
|
||||
Env string `form:"env" validate:"required"`
|
||||
Zone string `form:"zone" validate:"required"`
|
||||
Name string `form:"name" validate:"required"`
|
||||
State int8 `form:"state" validate:"required"`
|
||||
Comment string `form:"comment" validate:"required"`
|
||||
Mark string `form:"mark" validate:"required"`
|
||||
SkipLint bool `form:"skiplint"`
|
||||
}
|
||||
|
||||
//ComValueReq ...
|
||||
type ComValueReq struct {
|
||||
ConfigID int64 `form:"config_id" validate:"required"`
|
||||
}
|
||||
|
||||
//ConfigsByTeamReq ...
|
||||
type ConfigsByTeamReq struct {
|
||||
Env string `form:"env" validate:"required"`
|
||||
Zone string `form:"zone" validate:"required"`
|
||||
Team string `form:"team" validate:"required"`
|
||||
Pn int64 `form:"pn" default:"1" validate:"min=1"`
|
||||
Ps int64 `form:"ps" default:"20" validate:"min=1"`
|
||||
}
|
||||
|
||||
//ComConfigsByNameReq ...
|
||||
type ComConfigsByNameReq struct {
|
||||
Env string `form:"env" validate:"required"`
|
||||
Zone string `form:"zone" validate:"required"`
|
||||
Team string `form:"team" validate:"required"`
|
||||
Name string `form:"name" validate:"required"`
|
||||
}
|
||||
|
||||
//UpdateComConfValueReq ...
|
||||
type UpdateComConfValueReq struct {
|
||||
ID int64 `form:"config_id" validate:"required"`
|
||||
State int8 `form:"state" validate:"required"`
|
||||
ConfigID int64 `form:"config_id" validate:"required"`
|
||||
Name string `form:"name" validate:"required"`
|
||||
Comment string `form:"comment" validate:"required"`
|
||||
Mark string `form:"mark" validate:"required"`
|
||||
Mtime int64 `form:"mtime" validate:"required"`
|
||||
SkipLint bool `form:"skiplint"`
|
||||
}
|
||||
|
||||
//NamesByTeamReq ...
|
||||
type NamesByTeamReq struct {
|
||||
Env string `form:"env" validate:"required"`
|
||||
Zone string `form:"zone" validate:"required"`
|
||||
Team string `form:"team" validate:"required"`
|
||||
}
|
||||
|
||||
// TagMap ...
|
||||
type TagMap struct {
|
||||
*Tag
|
||||
AppName string `json:"app_name"`
|
||||
BuildName string `json:"build_name"`
|
||||
TreeID int64 `json:"tree_id"`
|
||||
}
|
275
app/admin/main/config/model/config.go
Normal file
275
app/admin/main/config/model/config.go
Normal file
@ -0,0 +1,275 @@
|
||||
package model
|
||||
|
||||
import "go-common/library/time"
|
||||
|
||||
var (
|
||||
//ConfigIng config ing.
|
||||
ConfigIng = int8(1)
|
||||
//ConfigEnd config end.
|
||||
ConfigEnd = int8(2)
|
||||
)
|
||||
|
||||
// Config config.
|
||||
type Config struct {
|
||||
ID int64 `json:"id" gorm:"primary_key"`
|
||||
AppID int64 `json:"app_id"`
|
||||
Name string `json:"name"`
|
||||
Comment string `json:"comment"`
|
||||
From int64 `json:"from"`
|
||||
State int8 `json:"state"`
|
||||
Mark string `json:"mark"`
|
||||
Operator string `json:"operator"`
|
||||
IsDelete int8 `json:"is_delete"`
|
||||
NewCommon int64 `gorm:"-" json:"new_common"`
|
||||
Ctime time.Time `json:"ctime"`
|
||||
Mtime time.Time `json:"mtime"`
|
||||
}
|
||||
|
||||
// TableName config.
|
||||
func (Config) TableName() string {
|
||||
return "config"
|
||||
}
|
||||
|
||||
//BuildFile file.
|
||||
type BuildFile struct {
|
||||
*Config
|
||||
LastConf *Config `json:"last_conf"`
|
||||
}
|
||||
|
||||
//ConfigRes configRes.
|
||||
type ConfigRes struct {
|
||||
Files []*Config `json:"files"`
|
||||
BuildFiles []*BuildFile `json:"build_files"`
|
||||
BuildNewFile []*Config `json:"build_new_file"`
|
||||
}
|
||||
|
||||
//ConfigRefs ConfigRefs.
|
||||
type ConfigRefs struct {
|
||||
Configs []*ConfigRef `json:"configs"`
|
||||
Ref *ConfigRef `json:"ref"`
|
||||
Name string `json:"name"`
|
||||
DeleteMAX int64 `json:"delete_max"`
|
||||
}
|
||||
|
||||
//ConfigRef configRef.
|
||||
type ConfigRef struct {
|
||||
ID int64 `json:"id"`
|
||||
Mark string `json:"mark"`
|
||||
IsDelete int8 `json:"is_delete"`
|
||||
}
|
||||
|
||||
//ConfigSearch config search resp.
|
||||
type ConfigSearch struct {
|
||||
App string `json:"app"`
|
||||
TreeID int64 `json:"tree_id"`
|
||||
Builds []string `json:"build"`
|
||||
ConfID int64 `json:"config_id"`
|
||||
Mark string `json:"mark"`
|
||||
ConfName string `json:"conf_name"`
|
||||
ConfValues []string `json:"conf_value"`
|
||||
}
|
||||
|
||||
//CanalTagUpdateReq ...
|
||||
type CanalTagUpdateReq struct {
|
||||
AppName string `form:"app_name" validate:"required"`
|
||||
Env string `form:"env" validate:"required"`
|
||||
Zone string `form:"zone" validate:"required"`
|
||||
ConfigIDs string `form:"config_ids"`
|
||||
TreeID int64 `form:"tree_id" validate:"required"`
|
||||
Token string `form:"token" validate:"required"`
|
||||
User string `form:"user" validate:"required"`
|
||||
Mark string `form:"mark" default:"canal发版"`
|
||||
Build string `form:"build" default:"docker-1"`
|
||||
Force int8 `form:"force"`
|
||||
}
|
||||
|
||||
//CanalNameConfigsReq ...
|
||||
type CanalNameConfigsReq struct {
|
||||
Env string `form:"env" validate:"required"`
|
||||
Zone string `form:"zone" validate:"required"`
|
||||
AppName string `form:"app_name" validate:"required"`
|
||||
Name string `form:"name" validate:"required"`
|
||||
TreeID int64 `form:"tree_id" validate:"required"`
|
||||
Token string `form:"token" validate:"required"`
|
||||
}
|
||||
|
||||
//CanalConfigCreateReq ...
|
||||
type CanalConfigCreateReq struct {
|
||||
AppName string `form:"app_name" validate:"required"`
|
||||
Env string `form:"env" validate:"required"`
|
||||
Zone string `form:"zone" validate:"required"`
|
||||
Name string `form:"name" validate:"required"`
|
||||
State int8 `form:"state" validate:"required"`
|
||||
From int64 `form:"from" default:"0"`
|
||||
Comment string `form:"comment" validate:"required"`
|
||||
Mark string `form:"mark" validate:"required"`
|
||||
TreeID int64 `form:"tree_id" validate:"required"`
|
||||
User string `form:"user" validate:"required"`
|
||||
Token string `form:"token" valildate:"required"`
|
||||
}
|
||||
|
||||
//CreateConfigReq ...
|
||||
type CreateConfigReq struct {
|
||||
AppName string `form:"app_name" validate:"required"`
|
||||
Env string `form:"env" validate:"required"`
|
||||
Zone string `form:"zone" validate:"required"`
|
||||
Name string `form:"name" validate:"required"`
|
||||
State int8 `form:"state" validate:"required"`
|
||||
From int64 `form:"from" default:"0"`
|
||||
Comment string `form:"comment" validate:"required"`
|
||||
Mark string `form:"mark" validate:"required"`
|
||||
TreeID int64 `form:"tree_id" validate:"required"`
|
||||
SkipLint bool `form:"skiplint"`
|
||||
}
|
||||
|
||||
//UpdateConfValueReq ...
|
||||
type UpdateConfValueReq struct {
|
||||
Name string `form:"name"`
|
||||
ID int64 `form:"config_id" validate:"required"`
|
||||
Mtime int64 `form:"mtime" validate:"required"`
|
||||
State int8 `form:"state" validate:"required"`
|
||||
Comment string `form:"comment" validate:"required"`
|
||||
Mark string `form:"mark" validate:"required"`
|
||||
NewCommon int64 `form:"new_common"`
|
||||
Ignore int8 `form:"ignore"`
|
||||
SkipLint bool `form:"skiplint"`
|
||||
}
|
||||
|
||||
//ValueReq ...
|
||||
type ValueReq struct {
|
||||
ConfigID int64 `form:"config_id" validate:"required"`
|
||||
}
|
||||
|
||||
//ConfigsByBuildIDReq ...
|
||||
type ConfigsByBuildIDReq struct {
|
||||
BuildID int64 `form:"build_id" validate:"required"`
|
||||
}
|
||||
|
||||
//ConfigsByTagIDReq ...
|
||||
type ConfigsByTagIDReq struct {
|
||||
TagID int64 `form:"tag_id" validate:"required"`
|
||||
}
|
||||
|
||||
//ConfigsByAppNameReq ...
|
||||
type ConfigsByAppNameReq struct {
|
||||
Env string `form:"env" validate:"required"`
|
||||
Zone string `form:"zone" validate:"required"`
|
||||
AppName string `form:"app_name" validate:"required"`
|
||||
TreeID int64 `form:"tree_id" validate:"required"`
|
||||
}
|
||||
|
||||
//ConfigSearchAllReq ...
|
||||
type ConfigSearchAllReq struct {
|
||||
Env string `form:"env" validate:"required"`
|
||||
Zone string `form:"zone" validate:"required"`
|
||||
Like string `form:"like" validate:"required"`
|
||||
}
|
||||
|
||||
//ConfigSearchAppReq ...
|
||||
type ConfigSearchAppReq struct {
|
||||
Env string `form:"env" validate:"required"`
|
||||
Zone string `form:"zone" validate:"required"`
|
||||
AppName string `form:"app_name" validate:"required"`
|
||||
Like string `form:"like" validate:"required"`
|
||||
BuildID int64 `form:"build_id" validate:"required"`
|
||||
TreeID int64 `form:"tree_id" validate:"required"`
|
||||
}
|
||||
|
||||
//ConfigsByNameReq ...
|
||||
type ConfigsByNameReq struct {
|
||||
Env string `form:"env" validate:"required"`
|
||||
Zone string `form:"zone" validate:"required"`
|
||||
AppName string `form:"app_name" validate:"required"`
|
||||
Name string `form:"name" validate:"required"`
|
||||
TreeID int64 `form:"tree_id" validate:"required"`
|
||||
}
|
||||
|
||||
//ConfigsReq ...
|
||||
type ConfigsReq struct {
|
||||
Env string `form:"env" validate:"required"`
|
||||
Zone string `form:"zone" validate:"required"`
|
||||
AppName string `form:"app_name" validate:"required"`
|
||||
BuildID int64 `form:"build_id"`
|
||||
TreeID int64 `form:"tree_id" validate:"required"`
|
||||
}
|
||||
|
||||
//ConfigRefsReq ...
|
||||
type ConfigRefsReq struct {
|
||||
Env string `form:"env" validate:"required"`
|
||||
Zone string `form:"zone" validate:"required"`
|
||||
AppName string `form:"app_name" validate:"required"`
|
||||
BuildID int64 `form:"build_id" validate:"required"`
|
||||
TreeID int64 `form:"tree_id" validate:"required"`
|
||||
}
|
||||
|
||||
//NamesByAppNameReq ...
|
||||
type NamesByAppNameReq struct {
|
||||
Env string `form:"env" validate:"required"`
|
||||
Zone string `form:"zone" validate:"required"`
|
||||
AppName string `form:"app_name" validate:"required"`
|
||||
TreeID int64 `form:"tree_id" validate:"required"`
|
||||
}
|
||||
|
||||
//DiffReq ...
|
||||
type DiffReq struct {
|
||||
ConfigID int64 `form:"config_id" validate:"required"`
|
||||
BuildID int64 `form:"build_id"`
|
||||
}
|
||||
|
||||
//ConfigDelReq ...
|
||||
type ConfigDelReq struct {
|
||||
ConfigID int64 `form:"config_id" validate:"required"`
|
||||
}
|
||||
|
||||
//ConfigBuildInfosReq ...
|
||||
type ConfigBuildInfosReq struct {
|
||||
Env string `form:"env" validate:"required"`
|
||||
Zone string `form:"zone" validate:"required"`
|
||||
AppName string `form:"app_name" validate:"required"`
|
||||
BuildID int64 `form:"build_id"`
|
||||
TreeID int64 `form:"tree_id" validate:"required"`
|
||||
}
|
||||
|
||||
//ConfigUpdateReq ...
|
||||
type ConfigUpdateReq struct {
|
||||
AppName string `form:"app_name" validate:"required"`
|
||||
Env string `form:"env" validate:"required"`
|
||||
Zone string `form:"zone" validate:"required"`
|
||||
TreeID int64 `form:"tree_id" validate:"required"`
|
||||
Data string `form:"data" validate:"required"`
|
||||
Token string `form:"token" validate:"required"`
|
||||
User string `form:"user" validate:"required"`
|
||||
}
|
||||
|
||||
//TagUpdateReq ...
|
||||
type TagUpdateReq struct {
|
||||
AppName string `form:"app_name" validate:"required"`
|
||||
Env string `form:"env" validate:"required"`
|
||||
Zone string `form:"zone" validate:"required"`
|
||||
ConfigIDs string `form:"config_ids"`
|
||||
Mark string `form:"mark" validate:"required"`
|
||||
Build string `form:"build" validate:"required"`
|
||||
TreeID int64 `form:"tree_id" validate:"required"`
|
||||
Token string `form:"token" validate:"required"`
|
||||
User string `form:"user" validate:"required"`
|
||||
Names string `form:"names"`
|
||||
Increment int `form:"increment"`
|
||||
Force int8 `form:"force"`
|
||||
}
|
||||
|
||||
//SetTokenReq ...
|
||||
type SetTokenReq struct {
|
||||
Env string `form:"env" validate:"required"`
|
||||
Zone string `form:"zone" validate:"required"`
|
||||
App string `form:"service" validate:"required"`
|
||||
Token string `form:"token" validate:"required"`
|
||||
TreeID int64 `form:"tree_id" validate:"required"`
|
||||
}
|
||||
|
||||
//HostsReq ...
|
||||
type HostsReq struct {
|
||||
Env string `form:"env" validate:"required"`
|
||||
Zone string `form:"zone" validate:"required"`
|
||||
App string `form:"service" validate:"required"`
|
||||
TreeID int64 `form:"tree_id" validate:"required"`
|
||||
}
|
42
app/admin/main/config/model/force.go
Normal file
42
app/admin/main/config/model/force.go
Normal file
@ -0,0 +1,42 @@
|
||||
package model
|
||||
|
||||
import "go-common/library/time"
|
||||
|
||||
//Force ...
|
||||
type Force struct {
|
||||
ID int64 `json:"id"`
|
||||
AppID int64 `json:"app_id"`
|
||||
Hostname string `json:"hostname"`
|
||||
IP string `json:"ip"`
|
||||
Version int64 `json:"version"`
|
||||
Operator string `json:"operator"`
|
||||
Ctime time.Time `json:"ctime"`
|
||||
Mtime time.Time `json:"mtime"`
|
||||
}
|
||||
|
||||
// TableName force.
|
||||
func (Force) TableName() string {
|
||||
return "force"
|
||||
}
|
||||
|
||||
//CreateForceReq ...
|
||||
type CreateForceReq struct {
|
||||
Env string `form:"env" validate:"required"`
|
||||
Zone string `form:"zone" validate:"required"`
|
||||
Build string `form:"build" validate:"required"`
|
||||
TreeID int64 `form:"tree_id" validate:"required"`
|
||||
Version int64 `form:"version"`
|
||||
Hosts string `form:"hosts"`
|
||||
}
|
||||
|
||||
//ClearForceReq ...
|
||||
type ClearForceReq struct {
|
||||
Env string `form:"env" validate:"required"`
|
||||
Zone string `form:"zone" validate:"required"`
|
||||
Build string `form:"build" validate:"required"`
|
||||
TreeID int64 `form:"tree_id" validate:"required"`
|
||||
Hosts string `form:"hosts"`
|
||||
}
|
||||
|
||||
//MapHosts ...
|
||||
type MapHosts map[string]string
|
109
app/admin/main/config/model/tag.go
Normal file
109
app/admin/main/config/model/tag.go
Normal file
@ -0,0 +1,109 @@
|
||||
package model
|
||||
|
||||
import "go-common/library/time"
|
||||
|
||||
//Tag db table tag.
|
||||
type Tag struct {
|
||||
ID int64 `json:"id" gorm:"primary_key"`
|
||||
AppID int64 `json:"app_id"`
|
||||
BuildID int64 `json:"build_id"`
|
||||
ConfigIDs string `json:"config_ids"`
|
||||
Mark string `json:"mark"`
|
||||
Operator string `json:"operator"`
|
||||
Ctime time.Time `json:"ctime"`
|
||||
Mtime time.Time `json:"mtime"`
|
||||
Force int8 `json:"force"`
|
||||
}
|
||||
|
||||
// TableName tag.
|
||||
func (Tag) TableName() string {
|
||||
return "tag"
|
||||
}
|
||||
|
||||
// TagPager tag pager
|
||||
type TagPager struct {
|
||||
Total int64 `json:"total"`
|
||||
Pn int64 `json:"pn"`
|
||||
Ps int64 `json:"ps"`
|
||||
Items []*Tag `json:"items"`
|
||||
}
|
||||
|
||||
//TagConfig tagConfig.
|
||||
type TagConfig struct {
|
||||
*Tag
|
||||
Confs []*Config `json:"confs"`
|
||||
}
|
||||
|
||||
// TagConfigPager tag configs pager.
|
||||
type TagConfigPager struct {
|
||||
Total int64 `json:"total"`
|
||||
Pn int64 `json:"pn"`
|
||||
Ps int64 `json:"ps"`
|
||||
Items []*TagConfig `json:"items"`
|
||||
}
|
||||
|
||||
//CreateTagReq ...
|
||||
type CreateTagReq struct {
|
||||
AppName string `form:"app_name" validate:"required"`
|
||||
Env string `form:"env" validate:"required"`
|
||||
Zone string `form:"zone" validate:"required"`
|
||||
ConfigIDs string `form:"config_ids" validate:"required"`
|
||||
Mark string `form:"mark" validate:"required"`
|
||||
TreeID int64 `form:"tree_id" validate:"required"`
|
||||
}
|
||||
|
||||
//LastTagsReq ...
|
||||
type LastTagsReq struct {
|
||||
AppName string `form:"app_name" validate:"required"`
|
||||
Zone string `form:"zone" validate:"required"`
|
||||
Env string `form:"env" validate:"required"`
|
||||
Build string `form:"build" validate:"required"`
|
||||
TreeID int64 `form:"tree_id" validate:"required"`
|
||||
}
|
||||
|
||||
//TagsByBuildReq ...
|
||||
type TagsByBuildReq struct {
|
||||
AppName string `form:"app_name" validate:"required"`
|
||||
Zone string `form:"zone" validate:"required"`
|
||||
Env string `form:"env" validate:"required"`
|
||||
Build string `form:"build" validate:"required"`
|
||||
Pn int64 `form:"pn" default:"1" validate:"min=1"`
|
||||
Ps int64 `form:"ps" default:"20" validate:"min=1"`
|
||||
TreeID int64 `form:"tree_id" validate:"required"`
|
||||
}
|
||||
|
||||
//TagReq ...
|
||||
type TagReq struct {
|
||||
TagID int64 `form:"tag_id" validate:"required"`
|
||||
}
|
||||
|
||||
//UpdatetagReq ...
|
||||
type UpdatetagReq struct {
|
||||
AppName string `form:"app_name" validate:"required"`
|
||||
Env string `form:"env" validate:"required"`
|
||||
Zone string `form:"zone" validate:"required"`
|
||||
ConfigIDs string `form:"config_ids" validate:"required"`
|
||||
Mark string `form:"mark" validate:"required"`
|
||||
Build string `form:"build" validate:"required"`
|
||||
TreeID int64 `form:"tree_id" validate:"required"`
|
||||
Force int8 `form:"force"`
|
||||
}
|
||||
|
||||
//UpdateTagIDReq ...
|
||||
type UpdateTagIDReq struct {
|
||||
AppName string `form:"app_name" validate:"required"`
|
||||
Zone string `form:"zone" validate:"required"`
|
||||
Env string `form:"env" validate:"required"`
|
||||
Build string `form:"build" validate:"required"`
|
||||
TreeID int64 `form:"tree_id" validate:"required"`
|
||||
TagID int64 `form:"tag_id" validate:"required"`
|
||||
}
|
||||
|
||||
//TagConfigDiff ...
|
||||
type TagConfigDiff struct {
|
||||
TagID int64 `form:"tag_id" validate:"required"`
|
||||
Name string `form:"name" validate:"required"`
|
||||
TreeID int64 `form:"tree_id" validate:"required"`
|
||||
AppID int64 `form:"app_id" validate:"required"`
|
||||
BuildID int64 `form:"build_id" validate:"required"`
|
||||
}
|
18
app/admin/main/config/model/team.go
Normal file
18
app/admin/main/config/model/team.go
Normal file
@ -0,0 +1,18 @@
|
||||
package model
|
||||
|
||||
import "go-common/library/time"
|
||||
|
||||
//Team team.
|
||||
type Team struct {
|
||||
ID int64 `json:"id" gorm:"primary_key"`
|
||||
Name string `json:"name"`
|
||||
Env string `json:"env"`
|
||||
Zone string `json:"zone"`
|
||||
Ctime time.Time `json:"ctime"`
|
||||
Mtime time.Time `json:"mtime"`
|
||||
}
|
||||
|
||||
// TableName team.
|
||||
func (Team) TableName() string {
|
||||
return "project_team"
|
||||
}
|
44
app/admin/main/config/pkg/lint/BUILD
Normal file
44
app/admin/main/config/pkg/lint/BUILD
Normal file
@ -0,0 +1,44 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["lint.go"],
|
||||
importpath = "go-common/app/admin/main/config/pkg/lint",
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_xtest",
|
||||
srcs = ["lint_test.go"],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//app/admin/main/config/pkg/lint:go_default_library",
|
||||
"//app/admin/main/config/pkg/lint/json:go_default_library",
|
||||
"//app/admin/main/config/pkg/lint/toml:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [
|
||||
":package-srcs",
|
||||
"//app/admin/main/config/pkg/lint/json:all-srcs",
|
||||
"//app/admin/main/config/pkg/lint/toml:all-srcs",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
37
app/admin/main/config/pkg/lint/json/BUILD
Normal file
37
app/admin/main/config/pkg/lint/json/BUILD
Normal file
@ -0,0 +1,37 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_test",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["jsonlint_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["jsonlint.go"],
|
||||
importpath = "go-common/app/admin/main/config/pkg/lint/json",
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = ["//app/admin/main/config/pkg/lint:go_default_library"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
26
app/admin/main/config/pkg/lint/json/jsonlint.go
Normal file
26
app/admin/main/config/pkg/lint/json/jsonlint.go
Normal file
@ -0,0 +1,26 @@
|
||||
package jsonlint
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
|
||||
"go-common/app/admin/main/config/pkg/lint"
|
||||
)
|
||||
|
||||
const filetype = "json"
|
||||
|
||||
type jsonlint struct{}
|
||||
|
||||
func (jsonlint) Lint(r io.Reader) lint.Error {
|
||||
var v interface{}
|
||||
dec := json.NewDecoder(r)
|
||||
err := dec.Decode(&v)
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
return lint.Error{{Line: -1, Message: err.Error()}}
|
||||
}
|
||||
|
||||
func init() {
|
||||
lint.RegisterLinter(filetype, jsonlint{})
|
||||
}
|
38
app/admin/main/config/pkg/lint/json/jsonlint_test.go
Normal file
38
app/admin/main/config/pkg/lint/json/jsonlint_test.go
Normal file
@ -0,0 +1,38 @@
|
||||
package jsonlint
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var testdata = `
|
||||
{
|
||||
"a1": "a1",
|
||||
"b2":
|
||||
}
|
||||
`
|
||||
|
||||
var testdataok = `
|
||||
{
|
||||
"hello": "world"
|
||||
}
|
||||
`
|
||||
|
||||
func TestJsonLint(t *testing.T) {
|
||||
lint := jsonlint{}
|
||||
r := bytes.NewBufferString(testdata)
|
||||
lintErr := lint.Lint(r)
|
||||
if lintErr == nil {
|
||||
t.Fatalf("expect lintErr != nil")
|
||||
}
|
||||
t.Logf("%s", lintErr.Error())
|
||||
}
|
||||
|
||||
func TestJsonLintOk(t *testing.T) {
|
||||
lint := jsonlint{}
|
||||
r := bytes.NewBufferString(testdataok)
|
||||
lintErr := lint.Lint(r)
|
||||
if lintErr != nil {
|
||||
t.Error(lintErr)
|
||||
}
|
||||
}
|
63
app/admin/main/config/pkg/lint/lint.go
Normal file
63
app/admin/main/config/pkg/lint/lint.go
Normal file
@ -0,0 +1,63 @@
|
||||
package lint
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var linterMap map[string]Linter
|
||||
|
||||
// ErrLintNotExists .
|
||||
var ErrLintNotExists = errors.New("linter not exists")
|
||||
|
||||
func init() {
|
||||
linterMap = make(map[string]Linter)
|
||||
}
|
||||
|
||||
// RegisterLinter register linter for a kind of file
|
||||
func RegisterLinter(filetype string, linter Linter) {
|
||||
if _, ok := linterMap[filetype]; ok {
|
||||
panic("linter for filetype " + filetype + " already exists")
|
||||
}
|
||||
linterMap[filetype] = linter
|
||||
}
|
||||
|
||||
// LineErr error contains line number
|
||||
type LineErr struct {
|
||||
Line int `json:"line"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
// Error lint error
|
||||
type Error []LineErr
|
||||
|
||||
func (errs Error) Error() string {
|
||||
messages := make([]string, 0, len(errs))
|
||||
for _, err := range errs {
|
||||
messages = append(messages, fmt.Sprintf("%d:%s", err.Line, err.Message))
|
||||
}
|
||||
return strings.Join(messages, "\n")
|
||||
}
|
||||
|
||||
func (errs Error) String() string {
|
||||
return errs.Error()
|
||||
}
|
||||
|
||||
// Linter lint config file
|
||||
type Linter interface {
|
||||
Lint(r io.Reader) Error
|
||||
}
|
||||
|
||||
// Lint config file,
|
||||
func Lint(filetype string, r io.Reader) error {
|
||||
lint, ok := linterMap[filetype]
|
||||
if !ok {
|
||||
return ErrLintNotExists
|
||||
}
|
||||
if lintErr := lint.Lint(r); lintErr != nil {
|
||||
return lintErr
|
||||
}
|
||||
return nil
|
||||
}
|
35
app/admin/main/config/pkg/lint/lint_test.go
Normal file
35
app/admin/main/config/pkg/lint/lint_test.go
Normal file
@ -0,0 +1,35 @@
|
||||
package lint_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
|
||||
"go-common/app/admin/main/config/pkg/lint"
|
||||
_ "go-common/app/admin/main/config/pkg/lint/json"
|
||||
_ "go-common/app/admin/main/config/pkg/lint/toml"
|
||||
)
|
||||
|
||||
func TestLint(t *testing.T) {
|
||||
jsonRead := bytes.NewBufferString(`{"hello": "world", "a1":"ab"}`)
|
||||
err := lint.Lint("json", jsonRead)
|
||||
if err != nil {
|
||||
t.Errorf("%v", err)
|
||||
}
|
||||
tomlRead := bytes.NewBufferString(`[owner]
|
||||
name = "Tom Preston-Werner"
|
||||
dob = 1979-05-27T07:32:00-08:00 # First class dates
|
||||
|
||||
[database]
|
||||
server = "192.168.1.1"
|
||||
ports = [ 8001, 8001, 8002 ]
|
||||
connection_max = 5000
|
||||
enabled = true`)
|
||||
err = lint.Lint("toml", tomlRead)
|
||||
if err != nil {
|
||||
t.Errorf("%v", err)
|
||||
}
|
||||
err = lint.Lint("test", tomlRead)
|
||||
if err != lint.ErrLintNotExists {
|
||||
t.Errorf("%v", err)
|
||||
}
|
||||
}
|
43
app/admin/main/config/pkg/lint/toml/BUILD
Normal file
43
app/admin/main/config/pkg/lint/toml/BUILD
Normal file
@ -0,0 +1,43 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_test",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = [
|
||||
"testdata_test.go",
|
||||
"tomllint_test.go",
|
||||
],
|
||||
embed = [":go_default_library"],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["tomllint.go"],
|
||||
importpath = "go-common/app/admin/main/config/pkg/lint/toml",
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//app/admin/main/config/pkg/lint:go_default_library",
|
||||
"//vendor/github.com/BurntSushi/toml:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
62
app/admin/main/config/pkg/lint/toml/testdata_test.go
Normal file
62
app/admin/main/config/pkg/lint/toml/testdata_test.go
Normal file
@ -0,0 +1,62 @@
|
||||
package tomllint
|
||||
|
||||
var synataxerrordata = `
|
||||
[owner]
|
||||
name = "Tom Preston-Werner"
|
||||
dob 1979-05-27T07:32:00-08:00 # First class dates
|
||||
|
||||
`
|
||||
var normaldata = `
|
||||
[owner]
|
||||
name = "Tom Preston-Werner"
|
||||
dob = 1979-05-27T07:32:00-08:00 # First class dates
|
||||
|
||||
[database]
|
||||
server = "192.168.1.1"
|
||||
ports = [ 8001, 8001, 8002 ]
|
||||
connection_max = 5000
|
||||
enabled = true
|
||||
|
||||
[servers]
|
||||
|
||||
# Indentation (tabs and/or spaces) is allowed but not required
|
||||
[servers.alpha]
|
||||
ip = "10.0.0.1"
|
||||
dc = "eqdc10"
|
||||
|
||||
[servers.beta]
|
||||
ip = "10.0.0.2"
|
||||
dc = "eqdc10"
|
||||
|
||||
[clients]
|
||||
data = [ ["gamma", "delta"], [1, 2] ]
|
||||
|
||||
# Line breaks are OK when inside arrays
|
||||
hosts = [
|
||||
"alpha",
|
||||
"omega"
|
||||
]
|
||||
`
|
||||
|
||||
var notopkvdata = `
|
||||
title = "test123"
|
||||
age = 123
|
||||
array = [1,2,3]
|
||||
[clients]
|
||||
data = "helo"
|
||||
`
|
||||
|
||||
var nocommondata = `
|
||||
version = "v1.1"
|
||||
user = "nobody"
|
||||
`
|
||||
|
||||
var noidentify = `
|
||||
[identify]
|
||||
xxx = 123
|
||||
`
|
||||
|
||||
var noapp = `
|
||||
[app]
|
||||
xxx = 123
|
||||
`
|
100
app/admin/main/config/pkg/lint/toml/tomllint.go
Normal file
100
app/admin/main/config/pkg/lint/toml/tomllint.go
Normal file
@ -0,0 +1,100 @@
|
||||
package tomllint
|
||||
|
||||
import (
|
||||
"io"
|
||||
"regexp"
|
||||
"strconv"
|
||||
|
||||
"github.com/BurntSushi/toml"
|
||||
|
||||
"go-common/app/admin/main/config/pkg/lint"
|
||||
)
|
||||
|
||||
var lineNumberRe *regexp.Regexp
|
||||
|
||||
const filetype = "toml"
|
||||
|
||||
type lintFn func(metadata toml.MetaData) []lint.LineErr
|
||||
|
||||
var lintFns []lintFn
|
||||
|
||||
type tomllint struct{}
|
||||
|
||||
// Lint toml file return lint.Error
|
||||
func (tomllint) Lint(r io.Reader) lint.Error {
|
||||
var v interface{}
|
||||
var lintErr lint.Error
|
||||
metadata, err := toml.DecodeReader(r, &v)
|
||||
if err != nil {
|
||||
line := -1
|
||||
if match := lineNumberRe.FindStringSubmatch(err.Error()); len(match) == 2 {
|
||||
line, _ = strconv.Atoi(match[1])
|
||||
}
|
||||
lintErr = append(lintErr, lint.LineErr{Line: line, Message: err.Error()})
|
||||
return lintErr
|
||||
}
|
||||
for _, fn := range lintFns {
|
||||
if lineErrs := fn(metadata); lineErrs != nil {
|
||||
lintErr = append(lintErr, lineErrs...)
|
||||
}
|
||||
}
|
||||
if len(lintErr) == 0 {
|
||||
return nil
|
||||
}
|
||||
return lintErr
|
||||
}
|
||||
|
||||
// not allowed defined kv that type is not Hash at top level
|
||||
//func noTopKV(metadata toml.MetaData) []lint.LineErr {
|
||||
// var lineErrs []lint.LineErr
|
||||
// for _, keys := range metadata.Keys() {
|
||||
// if len(keys) != 1 {
|
||||
// continue
|
||||
// }
|
||||
// typeName := metadata.Type(keys...)
|
||||
// if typeName != "Hash" {
|
||||
// lineErrs = append(lineErrs, lint.LineErr{
|
||||
// Line: -1,
|
||||
// Message: fmt.Sprintf("top level value must be Object, key: %s type is %s", keys[0], typeName),
|
||||
// })
|
||||
// }
|
||||
// }
|
||||
// return lineErrs
|
||||
//}
|
||||
|
||||
// noApp not allowed app section exists
|
||||
func noApp(metadata toml.MetaData) []lint.LineErr {
|
||||
if metadata.IsDefined("app") {
|
||||
return []lint.LineErr{{Line: -1, Message: "请删除无用 App 配置 see: http://git.bilibili.co/platform/go-common/issues/310 (゜-゜)つロ"}}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// noIdentify not allowed identify config
|
||||
func noIdentify(metadata toml.MetaData) []lint.LineErr {
|
||||
if metadata.IsDefined("identify") {
|
||||
return []lint.LineErr{{Line: -1, Message: "请删除无用 Identify 配置 see: http://git.bilibili.co/platform/go-common/issues/310 (゜-゜)つロ"}}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// noCommon not allowed common config
|
||||
func noCommon(metadata toml.MetaData) []lint.LineErr {
|
||||
count := 0
|
||||
commonKey := []string{"version", "user", "pid", "dir", "perf"}
|
||||
for _, key := range commonKey {
|
||||
if metadata.IsDefined(key) {
|
||||
count++
|
||||
}
|
||||
}
|
||||
if count > 0 {
|
||||
return []lint.LineErr{{Line: -1, Message: "请删除无用 Common 配置 see: http://git.bilibili.co/platform/go-common/issues/310 (゜-゜)つロ"}}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
lint.RegisterLinter(filetype, tomllint{})
|
||||
lintFns = []lintFn{noApp, noIdentify, noCommon}
|
||||
lineNumberRe = regexp.MustCompile("^Near line (\\d+)")
|
||||
}
|
67
app/admin/main/config/pkg/lint/toml/tomllint_test.go
Normal file
67
app/admin/main/config/pkg/lint/toml/tomllint_test.go
Normal file
@ -0,0 +1,67 @@
|
||||
package tomllint
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSyntaxError(t *testing.T) {
|
||||
lint := &tomllint{}
|
||||
r := bytes.NewBufferString(synataxerrordata)
|
||||
lintErr := lint.Lint(r)
|
||||
if lintErr == nil {
|
||||
t.Fatalf("expect lintErr != nil")
|
||||
}
|
||||
if lintErr[0].Line == -1 {
|
||||
t.Errorf("expect get line number")
|
||||
}
|
||||
}
|
||||
|
||||
func TestTomlLintOK(t *testing.T) {
|
||||
lint := &tomllint{}
|
||||
r := bytes.NewBufferString(normaldata)
|
||||
lintErr := lint.Lint(r)
|
||||
if lintErr != nil {
|
||||
t.Errorf("error %v", lintErr)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNoCommon(t *testing.T) {
|
||||
lint := &tomllint{}
|
||||
r := bytes.NewBufferString(nocommondata)
|
||||
lintErr := lint.Lint(r)
|
||||
if lintErr == nil {
|
||||
t.Fatalf("expect lintErr != nil")
|
||||
}
|
||||
message := lintErr.Error()
|
||||
if !strings.Contains(message, "Common") {
|
||||
t.Errorf("expect error contains common")
|
||||
}
|
||||
}
|
||||
|
||||
func TestNoIdentify(t *testing.T) {
|
||||
lint := &tomllint{}
|
||||
r := bytes.NewBufferString(noidentify)
|
||||
lintErr := lint.Lint(r)
|
||||
if lintErr == nil {
|
||||
t.Fatalf("expect lintErr != nil")
|
||||
}
|
||||
message := lintErr.Error()
|
||||
if !strings.Contains(message, "Identify") {
|
||||
t.Errorf("expect error Identify common")
|
||||
}
|
||||
}
|
||||
|
||||
func TestNoApp(t *testing.T) {
|
||||
lint := &tomllint{}
|
||||
r := bytes.NewBufferString(noapp)
|
||||
lintErr := lint.Lint(r)
|
||||
if lintErr == nil {
|
||||
t.Fatalf("expect lintErr != nil")
|
||||
}
|
||||
message := lintErr.Error()
|
||||
if !strings.Contains(message, "App") {
|
||||
t.Errorf("expect error App common")
|
||||
}
|
||||
}
|
74
app/admin/main/config/service/BUILD
Normal file
74
app/admin/main/config/service/BUILD
Normal file
@ -0,0 +1,74 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_test",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = [
|
||||
"app_test.go",
|
||||
"build_test.go",
|
||||
"common_test.go",
|
||||
"conf_svr_test.go",
|
||||
"config_test.go",
|
||||
"tag_test.go",
|
||||
],
|
||||
embed = [":go_default_library"],
|
||||
rundir = ".",
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//app/admin/main/config/conf:go_default_library",
|
||||
"//app/admin/main/config/model:go_default_library",
|
||||
"//vendor/github.com/BurntSushi/toml:go_default_library",
|
||||
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"apm.go",
|
||||
"app.go",
|
||||
"build.go",
|
||||
"common.go",
|
||||
"conf_svr.go",
|
||||
"config.go",
|
||||
"force.go",
|
||||
"service.go",
|
||||
"tag.go",
|
||||
"team.go",
|
||||
],
|
||||
importpath = "go-common/app/admin/main/config/service",
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//app/admin/main/config/conf:go_default_library",
|
||||
"//app/admin/main/config/dao:go_default_library",
|
||||
"//app/admin/main/config/model:go_default_library",
|
||||
"//app/admin/main/config/pkg/lint:go_default_library",
|
||||
"//app/infra/config/model:go_default_library",
|
||||
"//app/infra/config/rpc/client:go_default_library",
|
||||
"//library/database/sql:go_default_library",
|
||||
"//library/ecode:go_default_library",
|
||||
"//library/log:go_default_library",
|
||||
"//vendor/github.com/jinzhu/gorm:go_default_library",
|
||||
"//vendor/github.com/satori/go.uuid:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
159
app/admin/main/config/service/apm.go
Normal file
159
app/admin/main/config/service/apm.go
Normal file
@ -0,0 +1,159 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"go-common/app/admin/main/config/model"
|
||||
"go-common/library/ecode"
|
||||
"go-common/library/log"
|
||||
|
||||
"github.com/jinzhu/gorm"
|
||||
)
|
||||
|
||||
//Apm apm.
|
||||
func (s *Service) Apm(treeID int64, name, apmname, username string) (err error) {
|
||||
sns := []*model.ServiceName{}
|
||||
if err = s.DBApm.Where("name=?", apmname).Find(&sns).Error; err != nil {
|
||||
log.Error("svr.service.Apm name(%d) apmname(%d) error(%v)", name, apmname, err)
|
||||
return
|
||||
}
|
||||
for _, val := range sns {
|
||||
if err = s.ApmBuild(val, name, username, treeID); err != nil {
|
||||
log.Error("svr.service.ApmBuild val(%d) apmname(%d) error(%v)", val, apmname, err)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
//ApmBuild apmBuild.
|
||||
func (s *Service) ApmBuild(val *model.ServiceName, name, username string, treeID int64) (err error) {
|
||||
bvs := []*model.BuildVersion{}
|
||||
mtime := time.Now().Unix() - (3600 * 24 * 60)
|
||||
if err = s.DBApm.Where("service_id=? and mtime > ?", val.ID, mtime).Find(&bvs).Error; err != nil {
|
||||
log.Error("svr.service.ApmBuild val(%v) id(%d) error(%v)", val, val.ID, err)
|
||||
return
|
||||
}
|
||||
if len(bvs) <= 0 {
|
||||
err = ecode.NothingFound
|
||||
return
|
||||
}
|
||||
for _, v := range bvs {
|
||||
var ver string
|
||||
scvs := []*model.ServiceConfigValue{}
|
||||
if err = s.DBApm.Where("config_id=?", v.ConfigID).Find(&scvs).Error; err != nil {
|
||||
log.Error("svr.service.ServiceConfigValue val(%d) ConfigID(%d) error(%v)", val, v.ConfigID, err)
|
||||
return
|
||||
}
|
||||
if len(scvs) <= 0 {
|
||||
err = ecode.NothingFound
|
||||
return
|
||||
}
|
||||
var env string
|
||||
switch val.Environment {
|
||||
case 10:
|
||||
env = "dev"
|
||||
case 11:
|
||||
env = "fat1"
|
||||
case 13:
|
||||
env = "uat"
|
||||
case 14:
|
||||
env = "pre"
|
||||
case 3:
|
||||
env = "prod"
|
||||
default:
|
||||
continue
|
||||
}
|
||||
version := strings.Split(v.Version, "-")
|
||||
if len(version) != 3 {
|
||||
continue
|
||||
}
|
||||
ver = version[1] + "-" + version[2]
|
||||
zone := version[0]
|
||||
switch zone {
|
||||
case "shylf":
|
||||
zone = "sh001"
|
||||
case "hzxs":
|
||||
zone = "sh001"
|
||||
case "shsb":
|
||||
zone = "sh001"
|
||||
default:
|
||||
continue
|
||||
}
|
||||
app := &model.App{
|
||||
Name: name,
|
||||
TreeID: treeID,
|
||||
Env: env,
|
||||
Zone: zone,
|
||||
Token: val.Token,
|
||||
}
|
||||
var tx *gorm.DB
|
||||
if tx = s.DB.Begin(); err != nil {
|
||||
log.Error("begin tran error(%v)", err)
|
||||
return
|
||||
}
|
||||
if err = tx.Where("tree_id=? and env=? and zone=?", treeID, env, zone).Find(&app).Error; err != nil {
|
||||
if err = tx.Create(&app).Error; err != nil {
|
||||
log.Error("svr.service.addapp create error(%v)", err)
|
||||
tx.Rollback()
|
||||
return
|
||||
}
|
||||
}
|
||||
configIds := ""
|
||||
for _, vv := range scvs {
|
||||
config := &model.Config{
|
||||
AppID: app.ID,
|
||||
Name: vv.Name,
|
||||
Comment: vv.Config,
|
||||
From: 0,
|
||||
State: 2,
|
||||
Mark: "一键迁移",
|
||||
Operator: username,
|
||||
}
|
||||
if err = tx.Create(&config).Error; err != nil {
|
||||
log.Error("svr.service.addconfig create error(%v)", err)
|
||||
tx.Rollback()
|
||||
return
|
||||
}
|
||||
if len(configIds) > 0 {
|
||||
configIds += ","
|
||||
}
|
||||
configIds += fmt.Sprint(config.ID)
|
||||
}
|
||||
tag := &model.Tag{
|
||||
AppID: app.ID,
|
||||
BuildID: 0,
|
||||
ConfigIDs: configIds,
|
||||
Mark: v.Remark,
|
||||
Operator: username,
|
||||
}
|
||||
if err = tx.Create(&tag).Error; err != nil {
|
||||
log.Error("svr.service.addtag create error(%v)", err)
|
||||
tx.Rollback()
|
||||
return
|
||||
}
|
||||
buildNew := &model.Build{
|
||||
AppID: app.ID,
|
||||
Name: ver,
|
||||
TagID: tag.ID,
|
||||
Mark: v.Remark,
|
||||
Operator: username,
|
||||
}
|
||||
if err = tx.Create(&buildNew).Error; err != nil {
|
||||
log.Error("svr.service.addbuild create error(%v)", err)
|
||||
tx.Rollback()
|
||||
return
|
||||
}
|
||||
ups := map[string]interface{}{
|
||||
"build_id": buildNew.ID,
|
||||
}
|
||||
if err = tx.Model(tag).Where("id = ?", tag.ID).Updates(ups).Error; err != nil {
|
||||
log.Error("svr.service.edittag updates error(%v)", err)
|
||||
tx.Rollback()
|
||||
return
|
||||
}
|
||||
tx.Commit()
|
||||
}
|
||||
return
|
||||
}
|
533
app/admin/main/config/service/app.go
Normal file
533
app/admin/main/config/service/app.go
Normal file
@ -0,0 +1,533 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/md5"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"go-common/app/admin/main/config/model"
|
||||
"go-common/library/database/sql"
|
||||
"go-common/library/ecode"
|
||||
"go-common/library/log"
|
||||
|
||||
"github.com/jinzhu/gorm"
|
||||
"github.com/satori/go.uuid"
|
||||
)
|
||||
|
||||
var (
|
||||
rdsEnvs = []*model.Env{
|
||||
{Name: "dev", NikeName: "开发环境"},
|
||||
{Name: "fat1", NikeName: "功能环境1"},
|
||||
{Name: "uat", NikeName: "集成环境"},
|
||||
{Name: "pre", NikeName: "预发环境"},
|
||||
{Name: "prod", NikeName: "线上环境"},
|
||||
}
|
||||
opsEnvs = []*model.Env{
|
||||
{Name: "dev", NikeName: "开发环境"},
|
||||
{Name: "fat1", NikeName: "功能环境1"},
|
||||
{Name: "uat", NikeName: "集成环境"},
|
||||
}
|
||||
)
|
||||
|
||||
// CreateApp create App.
|
||||
func (s *Service) CreateApp(name, env, zone string, treeID int64) error {
|
||||
bytes := [16]byte(uuid.NewV1())
|
||||
token := md5.Sum([]byte(hex.EncodeToString(bytes[:])))
|
||||
app := &model.App{Name: name, Env: env, Zone: zone, Token: hex.EncodeToString(token[:]), TreeID: treeID, Status: model.StatusShow}
|
||||
return s.dao.DB.Create(app).Error
|
||||
}
|
||||
|
||||
// UpdateToken update token.
|
||||
func (s *Service) UpdateToken(c context.Context, env, zone string, treeID int64) (err error) {
|
||||
bytes := [16]byte(uuid.NewV1())
|
||||
token := hex.EncodeToString(bytes[:])
|
||||
if err = s.dao.DB.Model(&model.App{}).Where("tree_id =? AND env=? AND zone=?", treeID, env, zone).Update("token", token).Error; err != nil {
|
||||
return
|
||||
}
|
||||
err = s.SetToken(c, treeID, env, zone, token)
|
||||
return
|
||||
}
|
||||
|
||||
// AppByTree get token by Name.
|
||||
func (s *Service) AppByTree(treeID int64, env, zone string) (app *model.App, err error) {
|
||||
app = &model.App{}
|
||||
row := s.dao.DB.Select("id,token").Where("tree_id=? AND env=? AND zone=?", treeID, env, zone).Model(&model.App{}).Row()
|
||||
if err = row.Scan(&app.ID, &app.Token); err != nil {
|
||||
log.Error("AppByTree(%v) err(%v)", treeID, err)
|
||||
if err == sql.ErrNoRows {
|
||||
err = ecode.NothingFound
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// AppsByTreeZone get token by Name and zone.
|
||||
func (s *Service) AppsByTreeZone(treeID int64, zone string) (apps []*model.App, err error) {
|
||||
if err = s.dao.DB.Select("id,env,token").Where("tree_id=? AND zone=?", treeID, zone).Find(&apps).Error; err != nil {
|
||||
log.Error("AppsByTreezone(%d) error(%v)", treeID, err)
|
||||
if err == sql.ErrNoRows {
|
||||
err = ecode.NothingFound
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// AppList get token by Name.
|
||||
func (s *Service) AppList(ctx context.Context, bu, team, name, env, zone string, ps, pn int64, nodes *model.CacheData, status int8) (pager *model.AppPager, err error) {
|
||||
var (
|
||||
like string
|
||||
apps []*model.App
|
||||
total int64
|
||||
ids []int64
|
||||
statusIn []int8
|
||||
)
|
||||
like = "%"
|
||||
if len(bu) != 0 {
|
||||
like = bu + ".%"
|
||||
}
|
||||
if len(team) != 0 {
|
||||
like = team + ".%"
|
||||
}
|
||||
if len(name) != 0 {
|
||||
like = "%.%.%" + name + "%"
|
||||
}
|
||||
if len(name) != 0 && len(team) != 0 {
|
||||
like = team + ".%" + name + "%"
|
||||
} else if len(name) != 0 && len(bu) != 0 {
|
||||
like = bu + ".%.%" + name + "%"
|
||||
}
|
||||
if status > 0 {
|
||||
statusIn = append(statusIn, status)
|
||||
} else {
|
||||
statusIn = []int8{model.StatusShow, model.StatusHidden}
|
||||
}
|
||||
for _, node := range nodes.Data {
|
||||
ids = append(ids, node.ID)
|
||||
}
|
||||
if err = s.dao.DB.Where("env=? AND zone=? AND name like ? AND tree_id in (?) And status in (?)", env, zone, like, ids, statusIn).
|
||||
Offset((pn - 1) * ps).Limit(ps).Find(&apps).Error; err != nil {
|
||||
log.Error("AppList() find page apps() error(%v)", err)
|
||||
return
|
||||
}
|
||||
if err = s.dao.DB.Model(&model.App{}).Where("env=? AND zone=? AND name like ? AND tree_id in (?) And status in (?)", env, zone, like, ids, statusIn).
|
||||
Count(&total).Error; err != nil {
|
||||
log.Error("AppList() count page apps() error(%v)", err)
|
||||
return
|
||||
}
|
||||
pager = &model.AppPager{Total: total, Pn: pn, Ps: ps, Items: apps}
|
||||
return
|
||||
}
|
||||
|
||||
// Tree get service tree.
|
||||
func (s *Service) Tree(ctx context.Context, user string) (data interface{}, err error) {
|
||||
var (
|
||||
parme []byte
|
||||
msg map[string]interface{}
|
||||
tmp interface{}
|
||||
token string
|
||||
ok bool
|
||||
)
|
||||
if parme, err = json.Marshal(map[string]string{"user_name": user, "platform_id": s.c.Tree.Platform}); err != nil {
|
||||
log.Error("json.Marshal() error(%v)", err)
|
||||
return
|
||||
}
|
||||
if msg, err = s.dao.Token(ctx, string(parme)); err != nil {
|
||||
return
|
||||
}
|
||||
if tmp, ok = msg["token"]; !ok {
|
||||
err = ecode.NothingFound
|
||||
return
|
||||
}
|
||||
if token, ok = tmp.(string); !ok {
|
||||
err = ecode.NothingFound
|
||||
return
|
||||
}
|
||||
return s.dao.Tree(ctx, token)
|
||||
}
|
||||
|
||||
// Node node.
|
||||
func (s *Service) Node(ctx context.Context, user, node, team, cookie string, nodes *model.CacheData) (res []*model.Node, err error) {
|
||||
var nNodes *model.CacheData
|
||||
//bu list.
|
||||
if node == "" && team == "" {
|
||||
if nNodes, err = s.SyncTree(ctx, user, cookie); err == nil {
|
||||
nodes = nNodes
|
||||
}
|
||||
tmp := make(map[string]struct{})
|
||||
for _, app := range nodes.Data {
|
||||
idx := strings.Index(app.Path, ".")
|
||||
bu := string([]byte(app.Path)[:idx])
|
||||
if _, ok := tmp[bu]; ok {
|
||||
continue
|
||||
}
|
||||
n := new(model.Node)
|
||||
n.Name = bu
|
||||
n.Path = bu
|
||||
res = append(res, n)
|
||||
tmp[bu] = struct{}{}
|
||||
}
|
||||
return
|
||||
}
|
||||
//team list.
|
||||
if node != "" && team == "" {
|
||||
tmp := make(map[string]struct{})
|
||||
for _, app := range nodes.Data {
|
||||
s := []byte(app.Path)
|
||||
sep := []byte(".")
|
||||
fidx := bytes.Index(s, sep)
|
||||
lidx := bytes.LastIndex(s, sep)
|
||||
team = string(s[:lidx])
|
||||
if node == string(s[:fidx]) {
|
||||
if _, ok := tmp[team]; ok {
|
||||
continue
|
||||
}
|
||||
n := new(model.Node)
|
||||
n.Name = string([]byte(app.Path)[fidx+1 : lidx])
|
||||
n.Path = team
|
||||
tmp[team] = struct{}{}
|
||||
res = append(res, n)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
//app list.
|
||||
if team == "" {
|
||||
return
|
||||
}
|
||||
for _, app := range nodes.Data {
|
||||
s := []byte(app.Path)
|
||||
sep := []byte(".")
|
||||
lidx := bytes.LastIndex(s, sep)
|
||||
t := string(s[:lidx])
|
||||
if team != t {
|
||||
continue
|
||||
}
|
||||
n := new(model.Node)
|
||||
n.Name = string(s[lidx+1:])
|
||||
n.Path = app.Path
|
||||
n.TreeID = app.ID
|
||||
res = append(res, n)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
//Envs envs.
|
||||
func (s *Service) Envs(ctx context.Context, user, appName, zone string, treeID int64, nodes *model.CacheData) (envs []*model.Env, err error) {
|
||||
var (
|
||||
ok bool
|
||||
node *model.RoleNode
|
||||
apps []*model.App
|
||||
)
|
||||
envs = rdsEnvs
|
||||
if node, ok = nodes.Data[treeID]; !ok {
|
||||
return
|
||||
}
|
||||
if node.Role == model.Ops {
|
||||
envs = opsEnvs
|
||||
}
|
||||
apps, err = s.AppsByTreeZone(treeID, zone)
|
||||
for _, env := range envs {
|
||||
env.Token = ""
|
||||
for _, app := range apps {
|
||||
if app.Env == env.Name {
|
||||
env.Token = app.Token
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
//EnvsByTeam envs.
|
||||
func (s *Service) EnvsByTeam(ctx context.Context, appName, zone string, nodes *model.CacheData) (envs []*model.Env, err error) {
|
||||
envs = rdsEnvs
|
||||
return
|
||||
}
|
||||
|
||||
//SyncTree syncTree.
|
||||
func (s *Service) SyncTree(ctx context.Context, user string, cookie string) (nodes *model.CacheData, err error) {
|
||||
var (
|
||||
msg map[string]interface{}
|
||||
tmp interface{}
|
||||
token string
|
||||
ok bool
|
||||
)
|
||||
|
||||
if msg, err = s.dao.Auth(ctx, cookie); err != nil {
|
||||
return
|
||||
}
|
||||
if tmp, ok = msg["token"]; !ok {
|
||||
err = ecode.NothingFound
|
||||
return
|
||||
}
|
||||
if token, ok = tmp.(string); !ok {
|
||||
err = ecode.NothingFound
|
||||
return
|
||||
}
|
||||
if nodes, err = s.dao.Role(ctx, user, token); err != nil {
|
||||
return
|
||||
}
|
||||
s.cLock.Lock()
|
||||
s.cache[user] = nodes
|
||||
s.cLock.Unlock()
|
||||
return
|
||||
}
|
||||
|
||||
//AuthApps authApps.
|
||||
func (s *Service) AuthApps(ctx context.Context, user, cookie string) (nodes *model.CacheData, err error) {
|
||||
if len(user) == 0 {
|
||||
err = ecode.NothingFound
|
||||
return
|
||||
}
|
||||
var ok bool
|
||||
s.cLock.RLock()
|
||||
nodes, ok = s.cache[user]
|
||||
s.cLock.RUnlock()
|
||||
if !ok || (time.Since(nodes.CTime) > 60*time.Second) {
|
||||
s.SyncTree(ctx, user, cookie)
|
||||
s.cLock.RLock()
|
||||
nodes, ok = s.cache[user]
|
||||
s.cLock.RUnlock()
|
||||
if !ok {
|
||||
err = ecode.NothingFound
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
//AuthApp authApp.
|
||||
func (s *Service) AuthApp(ctx context.Context, user, cookie string, treeID int64) (rule int8, err error) {
|
||||
var (
|
||||
ok bool
|
||||
node *model.RoleNode
|
||||
nodes *model.CacheData
|
||||
)
|
||||
if nodes, err = s.AuthApps(ctx, user, cookie); err != nil {
|
||||
return
|
||||
}
|
||||
if node, ok = nodes.Data[treeID]; !ok {
|
||||
err = ecode.AccessDenied
|
||||
return
|
||||
}
|
||||
return node.Role, nil
|
||||
}
|
||||
|
||||
//ConfigGetTreeID ...
|
||||
func (s *Service) ConfigGetTreeID(configID int64) (TreeID int64, err error) {
|
||||
conf := new(model.Config)
|
||||
if err = s.dao.DB.First(&conf, configID).Error; err != nil {
|
||||
log.Error("ConfigGetTreeID(%v) error(%v)", configID, err)
|
||||
return
|
||||
}
|
||||
TreeID, err = s.AppIDGetTreeID(conf.AppID)
|
||||
return
|
||||
}
|
||||
|
||||
//AppIDGetTreeID ...
|
||||
func (s *Service) AppIDGetTreeID(appID int64) (TreeID int64, err error) {
|
||||
app := new(model.App)
|
||||
if err = s.dao.DB.First(&app, appID).Error; err != nil {
|
||||
log.Error("AppIDGetTreeID(%v) error(%v)", appID, err)
|
||||
return
|
||||
}
|
||||
TreeID = app.TreeID
|
||||
return
|
||||
}
|
||||
|
||||
//BuildGetTreeID ...
|
||||
func (s *Service) BuildGetTreeID(buildID int64) (TreeID int64, err error) {
|
||||
build := new(model.Build)
|
||||
if err = s.dao.DB.First(&build, buildID).Error; err != nil {
|
||||
log.Error("BuildGetTreeID(%v) error(%v)", buildID, err)
|
||||
return
|
||||
}
|
||||
TreeID, err = s.AppIDGetTreeID(build.AppID)
|
||||
return
|
||||
}
|
||||
|
||||
//TagGetTreeID ...
|
||||
func (s *Service) TagGetTreeID(tagID int64) (TreeID int64, err error) {
|
||||
tag := new(model.Tag)
|
||||
if err = s.dao.DB.First(&tag, tagID).Error; err != nil {
|
||||
log.Error("TagGetTreeID(%v) error(%v)", tagID, err)
|
||||
return
|
||||
}
|
||||
TreeID, err = s.AppIDGetTreeID(tag.AppID)
|
||||
return
|
||||
}
|
||||
|
||||
//ZoneCopy ...
|
||||
func (s *Service) ZoneCopy(ctx context.Context, AppName, From, To string, TreeID int64) (err error) {
|
||||
apps := []*model.App{}
|
||||
if err = s.dao.DB.Where("name = ? and tree_id = ? and zone = ?", AppName, TreeID, From).Find(&apps).Error; err != nil {
|
||||
log.Error("ZoneCopy from apps error(%v)", err)
|
||||
return
|
||||
}
|
||||
tx := s.dao.DB.Begin()
|
||||
for _, v := range apps {
|
||||
app := &model.App{}
|
||||
if err = s.dao.DB.Where("name = ? and tree_id = ? and zone = ? and env = ?", AppName, TreeID, To, v.Env).First(app).Error; err != nil {
|
||||
if err != gorm.ErrRecordNotFound {
|
||||
log.Error("ZoneCopy to app error(%v)", err)
|
||||
return
|
||||
}
|
||||
//add app
|
||||
if err = s.CreateApp(AppName, v.Env, To, TreeID); err != nil {
|
||||
log.Error("ZoneCopy add app error(%v)", err)
|
||||
return
|
||||
}
|
||||
if err = s.dao.DB.Where("name = ? and tree_id = ? and zone = ? and env = ?", AppName, TreeID, To, v.Env).First(app).Error; err != nil {
|
||||
log.Error("ZoneCopy first app error(%v)", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
//
|
||||
configs := []*model.Config{}
|
||||
if err = tx.Where("app_id = ?", app.ID).Find(&configs).Error; err != nil {
|
||||
log.Error("ZoneCopy find configs error(%v)", err)
|
||||
tx.Rollback()
|
||||
return
|
||||
}
|
||||
|
||||
builds := []*model.Build{}
|
||||
if err = tx.Where("app_id = ?", v.ID).Find(&builds).Error; err != nil {
|
||||
log.Error("ZoneCopy find builds error(%v)", err)
|
||||
tx.Rollback()
|
||||
return
|
||||
}
|
||||
for _, val := range builds {
|
||||
tag := &model.Tag{}
|
||||
if err = tx.First(tag, val.TagID).Error; err != nil {
|
||||
log.Error("ZoneCopy find tag error(%v)", err)
|
||||
tx.Rollback()
|
||||
return
|
||||
}
|
||||
configs = []*model.Config{}
|
||||
in := strings.Split(tag.ConfigIDs, ",")
|
||||
if err = tx.Where("id in (?)", in).Find(&configs).Error; err != nil {
|
||||
log.Error("ZoneCopy find build configs error(%v)", err)
|
||||
tx.Rollback()
|
||||
return
|
||||
}
|
||||
config := &model.Config{}
|
||||
var configIDS string
|
||||
for _, vvv := range configs {
|
||||
config = &model.Config{}
|
||||
config.Operator = vvv.Operator
|
||||
config.Name = vvv.Name
|
||||
config.Mark = vvv.Mark
|
||||
config.Comment = vvv.Comment
|
||||
config.State = vvv.State
|
||||
config.From = 0 //公共文件变私人文件
|
||||
if err = s.CreateConf(config, TreeID, v.Env, To, true); err != nil {
|
||||
log.Error("ZoneCopy config create error(%v)", err)
|
||||
tx.Rollback()
|
||||
return
|
||||
}
|
||||
if len(configIDS) > 0 {
|
||||
configIDS += ","
|
||||
}
|
||||
configIDS += strconv.FormatInt(config.ID, 10)
|
||||
}
|
||||
newTag := &model.Tag{}
|
||||
newTag.Operator = tag.Operator
|
||||
newTag.Mark = tag.Mark
|
||||
newTag.ConfigIDs = configIDS
|
||||
s.UpdateTag(ctx, TreeID, v.Env, To, val.Name, newTag)
|
||||
}
|
||||
}
|
||||
tx.Commit()
|
||||
return
|
||||
}
|
||||
|
||||
// CanalCheckToken ...
|
||||
func (s *Service) CanalCheckToken(AppName, Env, Zone, Token string) (err error) {
|
||||
app := &model.App{}
|
||||
if err = s.dao.DB.Where("name = ? and env = ? and zone = ? and tree_id = ? and token = ?", AppName, Env, Zone, 3766, Token).First(app).Error; err != nil {
|
||||
log.Error("canalCheckToken error(%v)", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// CasterEnvs ...
|
||||
func (s *Service) CasterEnvs(zone string, treeID int64) (envs []*model.Env, err error) {
|
||||
var (
|
||||
apps []*model.App
|
||||
)
|
||||
envs = rdsEnvs
|
||||
apps, err = s.AppsByTreeZone(treeID, zone)
|
||||
for _, env := range envs {
|
||||
env.Token = ""
|
||||
for _, app := range apps {
|
||||
if app.Env == env.Name {
|
||||
env.Token = app.Token
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// AppRename ...
|
||||
func (s *Service) AppRename(treeID int64, user, cookie string) (err error) {
|
||||
var (
|
||||
ok bool
|
||||
node *model.RoleNode
|
||||
nodes *model.CacheData
|
||||
)
|
||||
s.cLock.RLock()
|
||||
nodes, ok = s.cache[user]
|
||||
s.cLock.RUnlock()
|
||||
if !ok {
|
||||
err = ecode.NothingFound
|
||||
return
|
||||
}
|
||||
if node, ok = nodes.Data[treeID]; !ok {
|
||||
err = ecode.AccessDenied
|
||||
return
|
||||
}
|
||||
if len(node.Path) == 0 {
|
||||
err = ecode.NothingFound
|
||||
return
|
||||
}
|
||||
if err = s.dao.DB.Model(&model.App{}).Where("tree_id =?", treeID).Update("name", node.Path).Error; err != nil {
|
||||
log.Error("AppRename update error(%v)", err)
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// GetApps ...
|
||||
func (s *Service) GetApps(env string) (apps []*model.App, err error) {
|
||||
if err = s.dao.DB.Where("env = ?", env).Find(&apps).Error; err != nil {
|
||||
log.Error("GetApps error(%v)", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// IdsGetApps ...
|
||||
func (s *Service) IdsGetApps(ids []int64) (apps []*model.App, err error) {
|
||||
if err = s.dao.DB.Where("id in (?)", ids).Find(&apps).Error; err != nil {
|
||||
log.Error("IdsGetApps error(%v)", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// UpAppStatus edit status.
|
||||
func (s *Service) UpAppStatus(ctx context.Context, status int8, treeID int64) (err error) {
|
||||
var (
|
||||
apps []*model.App
|
||||
)
|
||||
ups := map[string]interface{}{
|
||||
"status": status,
|
||||
}
|
||||
if err = s.dao.DB.Model(apps).Where("tree_id = ?", treeID).Updates(ups).Error; err != nil {
|
||||
log.Error("AppStatus error(%v) status(%v)", err, status)
|
||||
}
|
||||
return
|
||||
}
|
40
app/admin/main/config/service/app_test.go
Normal file
40
app/admin/main/config/service/app_test.go
Normal file
@ -0,0 +1,40 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"go-common/app/admin/main/config/conf"
|
||||
|
||||
"github.com/BurntSushi/toml"
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func svr(t *testing.T) (svr *Service) {
|
||||
var (
|
||||
confPath = "../cmd/config-admin-example.toml"
|
||||
conf *conf.Config
|
||||
)
|
||||
Convey("should decodeFile file", t, func() {
|
||||
_, err := toml.DecodeFile(confPath, &conf)
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
return New(conf)
|
||||
}
|
||||
|
||||
func TestService_UpdateToken(t *testing.T) {
|
||||
svr := svr(t)
|
||||
Convey("should update token", t, func() {
|
||||
err := svr.UpdateToken(context.Background(), "dev", "sh001", 2888)
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
}
|
||||
|
||||
func TestService_AppByName(t *testing.T) {
|
||||
svr := svr(t)
|
||||
Convey("should get app by name", t, func() {
|
||||
app, err := svr.AppByTree(2888, "dev", "sh001")
|
||||
So(err, ShouldBeNil)
|
||||
So(app, ShouldNotBeEmpty)
|
||||
})
|
||||
}
|
215
app/admin/main/config/service/build.go
Normal file
215
app/admin/main/config/service/build.go
Normal file
@ -0,0 +1,215 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
|
||||
"go-common/app/admin/main/config/model"
|
||||
"go-common/library/ecode"
|
||||
"go-common/library/log"
|
||||
)
|
||||
|
||||
// CreateBuild create build.
|
||||
func (s *Service) CreateBuild(build *model.Build, treeID int64, env, zone string) (err error) {
|
||||
var app *model.App
|
||||
if app, err = s.AppByTree(treeID, env, zone); err != nil {
|
||||
return
|
||||
}
|
||||
build.AppID = app.ID
|
||||
return s.dao.DB.Create(build).Error
|
||||
}
|
||||
|
||||
//UpdateTag update tag.
|
||||
func (s *Service) UpdateTag(ctx context.Context, treeID int64, env, zone, name string, tag *model.Tag) (err error) {
|
||||
var (
|
||||
app *model.App
|
||||
build *model.Build
|
||||
)
|
||||
if app, err = s.AppByTree(treeID, env, zone); err != nil {
|
||||
return
|
||||
}
|
||||
if build, err = s.BuildByName(app.ID, name); err != nil {
|
||||
if err != ecode.NothingFound {
|
||||
return
|
||||
}
|
||||
build = &model.Build{AppID: app.ID, Name: name, Mark: tag.Mark, Operator: tag.Operator}
|
||||
if err = s.dao.DB.Create(build).Error; err != nil {
|
||||
log.Error("CreateBuild(%s) error(%v)", build.Name, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
tag.AppID = app.ID
|
||||
tag.BuildID = build.ID
|
||||
if err = s.dao.DB.Create(&tag).Error; err != nil {
|
||||
log.Error("CreateTag(%s) error(%v)", tag.Mark, err)
|
||||
return
|
||||
}
|
||||
if tag.Force == 1 {
|
||||
//Clear stand-alone force
|
||||
forces := []*model.Force{}
|
||||
if err = s.dao.DB.Where("app_id = ?", app.ID).Find(&forces).Error; err != nil {
|
||||
log.Error("select forces(%s) error(%v)", app.ID, err)
|
||||
return
|
||||
}
|
||||
mHosts := model.MapHosts{}
|
||||
for _, val := range forces {
|
||||
mHosts[val.Hostname] = val.IP
|
||||
}
|
||||
if len(mHosts) > 0 {
|
||||
if err = s.ClearForce(ctx, treeID, env, zone, name, mHosts); err != nil {
|
||||
log.Error("clear forces(%s) error(%v)", app.ID, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tx := s.dao.DB.Begin()
|
||||
if err = tx.Model(&model.Build{ID: build.ID}).Update(map[string]interface{}{
|
||||
"tag_id": tag.ID,
|
||||
"operator": tag.Operator,
|
||||
}).Error; err != nil {
|
||||
tx.Rollback()
|
||||
log.Error("updateTagID(%d) error(%v)", tag.ID, err)
|
||||
return
|
||||
}
|
||||
//push
|
||||
if err = s.Push(ctx, treeID, env, zone, build.Name, tag.ID); err != nil {
|
||||
tx.Rollback()
|
||||
return
|
||||
}
|
||||
tx.Commit()
|
||||
return
|
||||
}
|
||||
|
||||
//UpdateTagID update tag.
|
||||
func (s *Service) UpdateTagID(ctx context.Context, env, zone, bName string, tag, TreeID int64) (err error) {
|
||||
build := new(model.Build)
|
||||
build.Name = bName
|
||||
build.TagID = tag
|
||||
var app *model.App
|
||||
if app, err = s.AppByTree(TreeID, env, zone); err != nil {
|
||||
return
|
||||
}
|
||||
tx := s.dao.DB.Begin()
|
||||
if err = tx.Model(&model.Build{}).Where("app_id = ? and name = ?", app.ID, build.Name).Update(map[string]interface{}{
|
||||
"tag_id": build.TagID,
|
||||
"operator": build.Operator,
|
||||
}).Error; err != nil {
|
||||
tx.Rollback()
|
||||
log.Error("updateTagID(%d) error(%v)", build.TagID, err)
|
||||
return
|
||||
}
|
||||
if err = s.Push(ctx, TreeID, env, zone, build.Name, build.TagID); err != nil {
|
||||
tx.Rollback()
|
||||
return
|
||||
}
|
||||
tx.Commit()
|
||||
return
|
||||
}
|
||||
|
||||
//Builds get builds by app id.
|
||||
func (s *Service) Builds(treeID int64, appName, env, zone string) (builds []*model.Build, err error) {
|
||||
var (
|
||||
app *model.App
|
||||
tag *model.Tag
|
||||
)
|
||||
if app, err = s.AppByTree(treeID, env, zone); err != nil {
|
||||
if err == ecode.NothingFound {
|
||||
if err = s.CreateApp(appName, env, zone, treeID); err == nil {
|
||||
builds = make([]*model.Build, 0)
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
if builds, err = s.BuildsByApp(app.ID); err != nil {
|
||||
return
|
||||
}
|
||||
for _, build := range builds {
|
||||
if tag, err = s.Tag(build.TagID); err != nil {
|
||||
if err == ecode.NothingFound {
|
||||
err = nil
|
||||
}
|
||||
}
|
||||
build.Mark = tag.Mark
|
||||
build.Operator = tag.Operator
|
||||
build.Mtime = tag.Mtime
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
//BuildsByApp buildsByApp.
|
||||
func (s *Service) BuildsByApp(appID int64) (builds []*model.Build, err error) {
|
||||
if err = s.dao.DB.Find(&builds, "app_id = ? ", appID).Error; err != nil {
|
||||
log.Error("BuildsByApp(%s) error(%v)", appID, err)
|
||||
if err == sql.ErrNoRows {
|
||||
err = nil
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
//Build get Build by build ID.
|
||||
func (s *Service) Build(ID int64) (build *model.Build, err error) {
|
||||
build = new(model.Build)
|
||||
if err = s.dao.DB.First(&build, ID).Error; err != nil {
|
||||
log.Error("Build(%v) error(%v)", ID, err)
|
||||
if err == sql.ErrNoRows {
|
||||
err = ecode.NothingFound
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
//Delete delete Build by build ID.
|
||||
func (s *Service) Delete(ID int64) (err error) {
|
||||
if err = s.dao.DB.Delete(&model.Build{}, ID).Error; err != nil {
|
||||
log.Error("Delete(%v) error(%v)", ID, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
//BuildByName get Build by build ID.
|
||||
func (s *Service) BuildByName(appID int64, name string) (build *model.Build, err error) {
|
||||
build = new(model.Build)
|
||||
if err = s.dao.DB.First(&build, "app_id = ? and name = ?", appID, name).Error; err != nil {
|
||||
log.Error("BuildByName(%s) error(%v)", name, err)
|
||||
if err == sql.ErrNoRows {
|
||||
err = ecode.NothingFound
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
//GetDelInfos get delete info.
|
||||
func (s *Service) GetDelInfos(c context.Context, BuildID int64) (err error) {
|
||||
build := &model.Build{}
|
||||
if err = s.dao.DB.Where("id = ?", BuildID).First(build).Error; err != nil {
|
||||
log.Error("GetDelInfos BuildID(%v) error(%v)", BuildID, err)
|
||||
return
|
||||
}
|
||||
app := &model.App{}
|
||||
if err = s.dao.DB.Where("id = ?", build.AppID).First(app).Error; err != nil {
|
||||
log.Error("GetDelInfos AppID(%v) error(%v)", build.AppID, err)
|
||||
return
|
||||
}
|
||||
hosts, err := s.Hosts(c, app.TreeID, app.Name, app.Env, app.Zone)
|
||||
if err != nil {
|
||||
log.Error("GetDelInfos hosts(%v) error(%v)", hosts, err)
|
||||
return
|
||||
}
|
||||
for _, v := range hosts {
|
||||
if v.BuildVersion == build.Name {
|
||||
err = ecode.NothingFound
|
||||
return
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// AllBuilds ...
|
||||
func (s *Service) AllBuilds(appIDS []int64) (builds []*model.Build, err error) {
|
||||
if err = s.dao.DB.Where("app_id in (?)", appIDS).Find(&builds).Error; err != nil {
|
||||
log.Error("AllBuild error(%v)", err)
|
||||
}
|
||||
return
|
||||
}
|
25
app/admin/main/config/service/build_test.go
Normal file
25
app/admin/main/config/service/build_test.go
Normal file
@ -0,0 +1,25 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestService_BuildsByAppName(t *testing.T) {
|
||||
svr := svr(t)
|
||||
Convey("should app by name", t, func() {
|
||||
res, err := svr.Builds(2888, "main.common-arch.msm-service", "dev", "sh001")
|
||||
So(err, ShouldBeNil)
|
||||
So(res, ShouldNotBeEmpty)
|
||||
})
|
||||
}
|
||||
|
||||
func TestService_BuildByID(t *testing.T) {
|
||||
svr := svr(t)
|
||||
Convey("should app by name", t, func() {
|
||||
res, err := svr.Build(1)
|
||||
So(err, ShouldBeNil)
|
||||
So(res, ShouldNotBeEmpty)
|
||||
})
|
||||
}
|
311
app/admin/main/config/service/common.go
Normal file
311
app/admin/main/config/service/common.go
Normal file
@ -0,0 +1,311 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"go-common/app/admin/main/config/model"
|
||||
"go-common/library/ecode"
|
||||
"go-common/library/log"
|
||||
)
|
||||
|
||||
// CreateComConf create config.
|
||||
func (s *Service) CreateComConf(conf *model.CommonConf, name, env, zone string, skiplint bool) (err error) {
|
||||
if !skiplint {
|
||||
if err = lintConfig(conf.Name, conf.Comment); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
var team *model.Team
|
||||
if team, err = s.TeamByName(name, env, zone); err != nil {
|
||||
return
|
||||
}
|
||||
conf.TeamID = team.ID
|
||||
return s.dao.DB.Create(conf).Error
|
||||
}
|
||||
|
||||
// ComConfig get common config by id.
|
||||
func (s *Service) ComConfig(id int64) (conf *model.CommonConf, err error) {
|
||||
conf = new(model.CommonConf)
|
||||
if err = s.dao.DB.First(&conf, "id = ?", id).Error; err != nil {
|
||||
log.Error("ComConfig() error(%v)", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// ComConfigsByTeam common config by team.
|
||||
func (s *Service) ComConfigsByTeam(name, env, zone string, ps, pn int64) (pager *model.CommonConfPager, err error) {
|
||||
var (
|
||||
team *model.Team
|
||||
confs []*model.CommonConf
|
||||
temp []*model.CommonTemp
|
||||
counts model.CommonCounts
|
||||
array []int64
|
||||
)
|
||||
if team, err = s.TeamByName(name, env, zone); err != nil {
|
||||
return
|
||||
}
|
||||
if err = s.dao.DB.Raw("select max(id) as id,count(distinct name) as counts from common_config where team_id =? group by name order by id desc", team.ID).Scan(&temp).Error; err != nil {
|
||||
log.Error("NamesByTeam(%v) error(%v)", team.ID, err)
|
||||
if err == sql.ErrNoRows {
|
||||
err = nil
|
||||
}
|
||||
}
|
||||
if err = s.dao.DB.Raw("select count(distinct name) as counts from common_config where team_id = ?", team.ID).Scan(&counts).Error; err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
err = nil
|
||||
}
|
||||
return
|
||||
}
|
||||
for _, v := range temp {
|
||||
array = append(array, v.ID)
|
||||
}
|
||||
if err = s.dao.DB.Raw("select id,team_id,name,state,mark,operator,ctime,mtime from common_config where id in (?) limit ?,?", array, (pn-1)*ps, ps).Scan(&confs).Error; err != nil {
|
||||
log.Error("NamesByTeam(%v) temp(%v) error(%v)", team.ID, temp, err)
|
||||
return
|
||||
}
|
||||
return &model.CommonConfPager{Total: counts.Counts, Pn: pn, Ps: ps, Items: confs}, nil
|
||||
}
|
||||
|
||||
//ComConfigsByName get Config by Config name.
|
||||
func (s *Service) ComConfigsByName(teamName, env, zone, name string) (confs []*model.CommonConf, err error) {
|
||||
var team *model.Team
|
||||
if team, err = s.TeamByName(teamName, env, zone); err != nil {
|
||||
return
|
||||
}
|
||||
if err = s.dao.DB.Select("id,team_id,name,state,mark,operator,ctime,mtime").Where("name = ? and team_id = ?",
|
||||
name, team.ID).Order("id desc").Limit(10).Find(&confs).Error; err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateComConfValue update config value.
|
||||
func (s *Service) UpdateComConfValue(conf *model.CommonConf, skiplint bool) (err error) {
|
||||
if !skiplint {
|
||||
if err = lintConfig(conf.Name, conf.Comment); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
var confDB *model.CommonConf
|
||||
if confDB, err = s.ComConfig(conf.ID); err != nil {
|
||||
return
|
||||
}
|
||||
if confDB.State == model.ConfigIng { //judge config is configIng.
|
||||
if conf.Mtime != confDB.Mtime {
|
||||
err = ecode.TargetBlocked
|
||||
return
|
||||
}
|
||||
conf.Mtime = 0
|
||||
err = s.dao.DB.Model(&model.CommonConf{ID: confDB.ID}).Updates(conf).Error
|
||||
return
|
||||
}
|
||||
if _, err = s.comConfigIng(confDB.Name, confDB.TeamID); err == nil { //judge have configing.
|
||||
err = ecode.TargetBlocked
|
||||
return
|
||||
}
|
||||
if err == sql.ErrNoRows || err == ecode.NothingFound {
|
||||
conf.ID = 0
|
||||
conf.TeamID = confDB.TeamID
|
||||
conf.Name = confDB.Name
|
||||
conf.Mtime = 0
|
||||
return s.dao.DB.Create(conf).Error
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (s *Service) comConfigIng(name string, teamID int64) (conf *model.CommonConf, err error) {
|
||||
conf = new(model.CommonConf)
|
||||
if err = s.dao.DB.Select("id").Where("name = ? and team_id = ? and state=?", name, teamID, model.ConfigIng).First(&conf).Error; err != nil {
|
||||
log.Error("configIng(%v) error(%v)", name, err)
|
||||
if err == sql.ErrNoRows {
|
||||
err = ecode.NothingFound
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// NamesByTeam get configs by team name.
|
||||
func (s *Service) NamesByTeam(teamName, env, zone string) (names []*model.CommonName, err error) {
|
||||
var (
|
||||
team *model.Team
|
||||
confs []*model.CommonConf
|
||||
)
|
||||
if team, err = s.TeamByName(teamName, env, zone); err != nil {
|
||||
if err == ecode.NothingFound {
|
||||
err = s.CreateTeam(teamName, env, zone)
|
||||
return
|
||||
}
|
||||
}
|
||||
if err = s.dao.DB.Where("team_id = ? and state = 2", team.ID).Order("id desc").Find(&confs).Error; err != nil {
|
||||
log.Error("NamesByTeam(%v) error(%v)", team.ID, err)
|
||||
if err == sql.ErrNoRows {
|
||||
err = nil
|
||||
}
|
||||
}
|
||||
tmp := make(map[string]struct{})
|
||||
for _, conf := range confs {
|
||||
if _, ok := tmp[conf.Name]; !ok {
|
||||
names = append(names, &model.CommonName{Name: conf.Name, ID: conf.ID})
|
||||
tmp[conf.Name] = struct{}{}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
//AppByTeam get tagMap
|
||||
func (s *Service) AppByTeam(commonConfigID int64) (tagMap map[int64]*model.TagMap, err error) {
|
||||
var commonConfig *model.CommonConf
|
||||
if commonConfig, err = s.ComConfig(commonConfigID); err != nil {
|
||||
return
|
||||
}
|
||||
team := &model.Team{}
|
||||
if err = s.dao.DB.Where("id = ?", commonConfig.TeamID).First(team).Error; err != nil {
|
||||
return
|
||||
}
|
||||
commonConf := []*model.CommonConf{}
|
||||
if err = s.dao.DB.Select("id").Where("name = ? and team_id = ? and state = 2", commonConfig.Name, commonConfig.TeamID).Find(&commonConf).Error; err != nil {
|
||||
log.Error("AppByTeam() common_config error(%v)", err)
|
||||
}
|
||||
var commonConfTmp []int64
|
||||
for _, val := range commonConf {
|
||||
commonConfTmp = append(commonConfTmp, val.ID)
|
||||
}
|
||||
app := []*model.App{}
|
||||
if err = s.dao.DB.Where("name like ? and env = ? and zone = ?", team.Name+".%", team.Env, team.Zone).Find(&app).Error; err != nil {
|
||||
log.Error("AppByTeam() app error(%v)", err)
|
||||
}
|
||||
var appTmp []int64
|
||||
appMap := make(map[int64]*model.App)
|
||||
for _, val := range app {
|
||||
appMap[val.ID] = val
|
||||
appTmp = append(appTmp, val.ID)
|
||||
}
|
||||
conf := []*model.Config{}
|
||||
if err = s.dao.DB.Where("`from` in (?) and app_id in (?) and state = 2 and is_delete = 0", commonConfTmp, appTmp).Find(&conf).Error; err != nil {
|
||||
log.Error("AppByTeam() config error(%v)", err)
|
||||
}
|
||||
confMap := make(map[int64]struct{})
|
||||
for _, val := range conf {
|
||||
confMap[val.ID] = struct{}{}
|
||||
}
|
||||
build := []*model.Build{}
|
||||
if err = s.dao.DB.Where("app_id in (?)", appTmp).Find(&build).Error; err != nil {
|
||||
log.Error("AppByTeam() build error(%v)", err)
|
||||
}
|
||||
var buildTmp []int64
|
||||
buildMap := make(map[int64]string)
|
||||
for _, val := range build {
|
||||
buildMap[val.ID] = val.Name
|
||||
buildTmp = append(buildTmp, val.TagID)
|
||||
}
|
||||
tagMap = make(map[int64]*model.TagMap)
|
||||
tag := []*model.Tag{}
|
||||
if err = s.dao.DB.Where("id in (?)", buildTmp).Find(&tag).Error; err != nil {
|
||||
log.Error("AppByTeam() tag error(%v)", err)
|
||||
}
|
||||
for _, val := range tag {
|
||||
tmp := strings.Split(val.ConfigIDs, ",")
|
||||
for _, vv := range tmp {
|
||||
vv, _ := strconv.ParseInt(vv, 10, 64)
|
||||
if _, ok := confMap[vv]; !ok {
|
||||
continue
|
||||
}
|
||||
tagMap[val.ID] = &model.TagMap{Tag: val}
|
||||
if _, ok := appMap[val.AppID]; ok {
|
||||
tagMap[val.ID].AppName = appMap[val.AppID].Name
|
||||
tagMap[val.ID].TreeID = appMap[val.AppID].TreeID
|
||||
}
|
||||
if _, ok := buildMap[val.BuildID]; ok {
|
||||
tagMap[val.ID].BuildName = buildMap[val.BuildID]
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// CommonPush ...
|
||||
func (s *Service) CommonPush(ctx context.Context, tagID, commonConfigID int64, user string) (err error) {
|
||||
var tag *model.Tag
|
||||
tag, err = s.Tag(tagID)
|
||||
if err != nil {
|
||||
log.Error("CommonPush() tagid(%v) error(%v)", tagID, err)
|
||||
return
|
||||
}
|
||||
configIDS := strings.Split(tag.ConfigIDs, ",")
|
||||
app := &model.App{}
|
||||
if err = s.dao.DB.Where("id = ?", tag.AppID).First(app).Error; err != nil {
|
||||
log.Error("CommonPush() app error(%v)", err)
|
||||
return
|
||||
}
|
||||
build := &model.Build{}
|
||||
if err = s.dao.DB.Where("id = ?", tag.BuildID).First(build).Error; err != nil {
|
||||
log.Error("CommonPush() build error(%v)", err)
|
||||
return
|
||||
}
|
||||
var commonConfig *model.CommonConf
|
||||
if commonConfig, err = s.ComConfig(commonConfigID); err != nil {
|
||||
return
|
||||
}
|
||||
team := &model.Team{}
|
||||
if err = s.dao.DB.Where("id = ?", commonConfig.TeamID).First(team).Error; err != nil {
|
||||
log.Error("CommonPush() team error(%v)", err)
|
||||
return
|
||||
}
|
||||
commonConf := []*model.CommonConf{}
|
||||
if err = s.dao.DB.Select("id").Where("name = ? and team_id = ? and state = 2", commonConfig.Name, commonConfig.TeamID).Find(&commonConf).Error; err != nil {
|
||||
log.Error("CommonPush() common_config error(%v)", err)
|
||||
return
|
||||
}
|
||||
var commonConfTmp []int64
|
||||
for _, val := range commonConf {
|
||||
commonConfTmp = append(commonConfTmp, val.ID)
|
||||
}
|
||||
conf := []*model.Config{}
|
||||
if err = s.dao.DB.Where("id in (?) and `from` in (?)", configIDS, commonConfTmp).Find(&conf).Error; err != nil {
|
||||
log.Error("CommonPush() config error(%v)", err)
|
||||
return
|
||||
}
|
||||
if len(conf) != 1 {
|
||||
log.Error("CommonPush() count config(%v) error(数据有误更新数据非1条)", conf)
|
||||
return
|
||||
}
|
||||
var newConfigIDS string
|
||||
for _, val := range conf {
|
||||
newConf := &model.Config{}
|
||||
newConf.AppID = val.AppID
|
||||
newConf.Comment = commonConfig.Comment
|
||||
newConf.Mark = commonConfig.Mark
|
||||
newConf.Name = val.Name
|
||||
newConf.State = 2
|
||||
newConf.From = commonConfigID
|
||||
newConf.Operator = user
|
||||
if _, err = s.configIng(newConf.Name, app.ID); err == nil { // judge config is configIng
|
||||
err = ecode.TargetBlocked
|
||||
return
|
||||
}
|
||||
if err = s.dao.DB.Create(newConf).Error; err != nil {
|
||||
log.Error("CommonPush() create newConf error(%v)", err)
|
||||
return
|
||||
}
|
||||
newConfigIDS = strconv.FormatInt(newConf.ID, 10)
|
||||
for _, vv := range configIDS {
|
||||
if strconv.FormatInt(val.ID, 10) != vv {
|
||||
if len(newConfigIDS) > 0 {
|
||||
newConfigIDS += ","
|
||||
}
|
||||
newConfigIDS += vv
|
||||
}
|
||||
}
|
||||
//tag发版
|
||||
newTag := &model.Tag{}
|
||||
newTag.Operator = user
|
||||
newTag.Mark = tag.Mark
|
||||
newTag.ConfigIDs = newConfigIDS
|
||||
newTag.Force = 1
|
||||
err = s.UpdateTag(ctx, app.TreeID, app.Env, app.Zone, build.Name, newTag)
|
||||
}
|
||||
return
|
||||
}
|
25
app/admin/main/config/service/common_test.go
Normal file
25
app/admin/main/config/service/common_test.go
Normal file
@ -0,0 +1,25 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestService_ComConfigsByTagID(t *testing.T) {
|
||||
svr := svr(t)
|
||||
Convey("should app by name", t, func() {
|
||||
res, err := svr.ConfigsByTagID(1)
|
||||
So(err, ShouldBeNil)
|
||||
So(res, ShouldNotBeEmpty)
|
||||
})
|
||||
}
|
||||
|
||||
func TestService_ComConfigsByTeam(t *testing.T) {
|
||||
svr := svr(t)
|
||||
Convey("should get common config by team", t, func() {
|
||||
res, err := svr.ComConfigsByTeam("main.common-arch", "dev", "shd", 1, 1)
|
||||
So(err, ShouldBeNil)
|
||||
So(res, ShouldNotBeEmpty)
|
||||
})
|
||||
}
|
83
app/admin/main/config/service/conf_svr.go
Normal file
83
app/admin/main/config/service/conf_svr.go
Normal file
@ -0,0 +1,83 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"go-common/app/infra/config/model"
|
||||
"go-common/library/log"
|
||||
)
|
||||
|
||||
// Push push new ver to config-service.
|
||||
func (s *Service) Push(c context.Context, treeID int64, env, zone, bver string, ver int64) (err error) {
|
||||
svr := svrFmt(treeID, env, zone)
|
||||
arg := &model.ArgConf{
|
||||
App: svr,
|
||||
BuildVer: bver,
|
||||
Ver: ver,
|
||||
}
|
||||
if err = s.confSvr.PushV4(c, arg); err != nil {
|
||||
log.Error("PushV4(%v) error(%v)", arg, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// SetToken set token to config-service.
|
||||
func (s *Service) SetToken(c context.Context, treeID int64, env, zone, token string) (err error) {
|
||||
svr := svrFmt(treeID, env, zone)
|
||||
arg := &model.ArgToken{
|
||||
App: svr,
|
||||
Token: token,
|
||||
}
|
||||
if err = s.confSvr.SetTokenV4(c, arg); err != nil {
|
||||
log.Error("SetToken(%v) error(%v)", arg, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Hosts get hosts.
|
||||
func (s *Service) Hosts(c context.Context, treeID int64, appName, env, zone string) (hosts []*model.Host, err error) {
|
||||
svr := svrFmt(treeID, env, zone)
|
||||
if hosts, err = s.confSvr.Hosts(c, svr); err != nil {
|
||||
log.Error("Hosts(%v) error(%v)", svr, err)
|
||||
return
|
||||
}
|
||||
if len(hosts) == 0 {
|
||||
hosts = make([]*model.Host, 0)
|
||||
return
|
||||
}
|
||||
for _, host := range hosts {
|
||||
host.Service = appName
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// ClearHost clear hosts.
|
||||
func (s *Service) ClearHost(c context.Context, treeID int64, env, zone string) (err error) {
|
||||
svr := svrFmt(treeID, env, zone)
|
||||
if err = s.confSvr.ClearHost(c, svr); err != nil {
|
||||
log.Error("Hosts(%v) error(%v)", svr, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func svrFmt(treeID int64, env, zone string) string {
|
||||
return fmt.Sprintf("%d_%s_%s", treeID, env, zone)
|
||||
}
|
||||
|
||||
// PushForce push new ver to config-service.
|
||||
func (s *Service) PushForce(c context.Context, treeID int64, env, zone, bver string, ver int64, hosts map[string]string, sType int8) (err error) {
|
||||
svr := svrFmt(treeID, env, zone)
|
||||
arg := &model.ArgConf{
|
||||
App: svr,
|
||||
BuildVer: bver,
|
||||
Ver: ver,
|
||||
Env: env,
|
||||
Hosts: hosts,
|
||||
SType: sType,
|
||||
}
|
||||
if err = s.confSvr.Force(c, arg); err != nil {
|
||||
log.Error("PushForce(%v) error(%v)", arg, err)
|
||||
}
|
||||
return
|
||||
}
|
40
app/admin/main/config/service/conf_svr_test.go
Normal file
40
app/admin/main/config/service/conf_svr_test.go
Normal file
@ -0,0 +1,40 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestService_Push(t *testing.T) {
|
||||
svr := svr(t)
|
||||
Convey("should push", t, func() {
|
||||
err := svr.Push(context.Background(), 2888, "dev", "sh001", "server-1", 1)
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
}
|
||||
|
||||
func TestService_SetToken(t *testing.T) {
|
||||
svr := svr(t)
|
||||
Convey("should set token", t, func() {
|
||||
err := svr.SetToken(context.Background(), 2888, "dev", "sh001", "84c0c277f13111e79d54522233017188")
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
}
|
||||
|
||||
func TestService_Hosts(t *testing.T) {
|
||||
svr := svr(t)
|
||||
Convey("should get hosts", t, func() {
|
||||
_, err := svr.Hosts(context.Background(), 2888, "main.common-arch.msm-service", "dev", "sh001")
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
}
|
||||
|
||||
func TestService_ClearHost(t *testing.T) {
|
||||
svr := svr(t)
|
||||
Convey("should clear host", t, func() {
|
||||
err := svr.ClearHost(context.Background(), 2888, "dev", "sh001")
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
}
|
920
app/admin/main/config/service/config.go
Normal file
920
app/admin/main/config/service/config.go
Normal file
@ -0,0 +1,920 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"context"
|
||||
"database/sql"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"go-common/app/admin/main/config/model"
|
||||
"go-common/app/admin/main/config/pkg/lint"
|
||||
"go-common/library/ecode"
|
||||
"go-common/library/log"
|
||||
|
||||
"github.com/jinzhu/gorm"
|
||||
)
|
||||
|
||||
func lintConfig(filename, content string) error {
|
||||
ext := strings.TrimLeft(filepath.Ext(filename), ".")
|
||||
err := lint.Lint(ext, bytes.NewBufferString(content))
|
||||
if err != nil && err != lint.ErrLintNotExists {
|
||||
return ecode.Error(ecode.RequestErr, err.Error())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CreateConf create config.
|
||||
func (s *Service) CreateConf(conf *model.Config, treeID int64, env, zone string, skiplint bool) error {
|
||||
// lint config
|
||||
if !skiplint {
|
||||
if err := lintConfig(conf.Name, conf.Comment); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
app, err := s.AppByTree(treeID, env, zone)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
conf.AppID = app.ID
|
||||
if _, err := s.configIng(conf.Name, app.ID); err == nil { // judge config is configIng
|
||||
return ecode.TargetBlocked
|
||||
}
|
||||
return s.dao.DB.Create(conf).Error
|
||||
}
|
||||
|
||||
// LintConfig lint config file
|
||||
func (s *Service) LintConfig(filename, content string) ([]lint.LineErr, error) {
|
||||
ext := strings.TrimLeft(filepath.Ext(filename), ".")
|
||||
err := lint.Lint(ext, bytes.NewBufferString(content))
|
||||
if err == nil || err == lint.ErrLintNotExists {
|
||||
return make([]lint.LineErr, 0), nil
|
||||
}
|
||||
lintErr, ok := err.(lint.Error)
|
||||
if !ok {
|
||||
return nil, lintErr
|
||||
}
|
||||
return []lint.LineErr(lintErr), nil
|
||||
}
|
||||
|
||||
// UpdateConfValue update config state.
|
||||
func (s *Service) UpdateConfValue(conf *model.Config, skiplint bool) (err error) {
|
||||
// lint config
|
||||
if !skiplint {
|
||||
if err := lintConfig(conf.Name, conf.Comment); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
var confDB *model.Config
|
||||
if confDB, err = s.Config(conf.ID); err != nil {
|
||||
return
|
||||
}
|
||||
if confDB.State == model.ConfigIng { //judge config is configIng.
|
||||
if conf.Mtime != confDB.Mtime {
|
||||
err = ecode.TargetBlocked
|
||||
return
|
||||
}
|
||||
conf.Mtime = 0
|
||||
err = s.dao.DB.Model(&model.Config{State: model.ConfigIng}).Updates(conf).Error
|
||||
return
|
||||
}
|
||||
if _, err = s.configIng(confDB.Name, confDB.AppID); err == nil {
|
||||
err = ecode.TargetBlocked
|
||||
return
|
||||
}
|
||||
if err == sql.ErrNoRows || err == ecode.NothingFound {
|
||||
conf.ID = 0
|
||||
conf.AppID = confDB.AppID
|
||||
conf.Name = confDB.Name
|
||||
if conf.From == 0 {
|
||||
conf.From = confDB.From
|
||||
}
|
||||
conf.Mtime = 0
|
||||
|
||||
return s.dao.DB.Create(conf).Error
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateConfState update config state.
|
||||
func (s *Service) UpdateConfState(ID int64) (err error) {
|
||||
err = s.dao.DB.Model(&model.Config{ID: ID}).Update("state", model.ConfigEnd).Error
|
||||
return
|
||||
}
|
||||
|
||||
// ConfigsByIDs get Config by IDs.
|
||||
func (s *Service) ConfigsByIDs(ids []int64) (confs []*model.Config, err error) {
|
||||
if err = s.dao.DB.Select("id,app_id,name,`from`,state,mark,operator,ctime,mtime,is_delete").Where(ids).Find(&confs).Error; err != nil {
|
||||
log.Error("ConfigsByIDs(%v) error(%v)", ids, err)
|
||||
if err == sql.ErrNoRows {
|
||||
err = nil
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// ConfigsByAppName get configs by app name.
|
||||
func (s *Service) ConfigsByAppName(appName, env, zone string, treeID int64, state int8) (confs []*model.Config, err error) {
|
||||
var app *model.App
|
||||
if app, err = s.AppByTree(treeID, env, zone); err != nil {
|
||||
if err == ecode.NothingFound {
|
||||
err = s.CreateApp(appName, env, zone, treeID)
|
||||
return
|
||||
}
|
||||
}
|
||||
if state != 0 {
|
||||
err = s.dao.DB.Select("id,app_id,name,`from`,state,mark,operator,is_delete,ctime,mtime").Where("app_id = ? and state =?", app.ID, state).Order("id desc").Find(&confs).Error
|
||||
} else {
|
||||
err = s.dao.DB.Select("id,app_id,name,`from`,state,mark,operator,is_delete,ctime,mtime").Where("app_id = ? ", app.ID).Order("id desc").Find(&confs).Error
|
||||
}
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
err = nil
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// ConfigsByAppID configs by app ID.
|
||||
func (s *Service) ConfigsByAppID(appID int64, state int8) (confs []*model.Config, err error) {
|
||||
if state != 0 {
|
||||
err = s.dao.DB.Select("id,app_id,name,`from`,state,mark,operator,is_delete,ctime,mtime").Where("app_id = ? and state =?", appID, state).Order("id desc").Find(&confs).Error
|
||||
} else {
|
||||
err = s.dao.DB.Select("id,app_id,name,`from`,state,mark,operator,is_delete,ctime,mtime").Where("app_id = ? ", appID).Order("id desc").Find(&confs).Error
|
||||
}
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
err = nil
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
//ConfigSearchApp configSearchApp.
|
||||
func (s *Service) ConfigSearchApp(ctx context.Context, appName, env, zone, like string, buildID, treeID int64) (searchs []*model.ConfigSearch, err error) {
|
||||
var (
|
||||
app *model.App
|
||||
builds []*model.Build
|
||||
tags []*model.Tag
|
||||
confs []*model.Config
|
||||
tagIDs []int64
|
||||
confIDs []int64
|
||||
)
|
||||
if app, err = s.AppByTree(treeID, env, zone); err != nil {
|
||||
return
|
||||
}
|
||||
if builds, err = s.BuildsByApp(app.ID); err != nil {
|
||||
return
|
||||
}
|
||||
if len(builds) == 0 {
|
||||
return
|
||||
}
|
||||
for _, build := range builds {
|
||||
tagIDs = append(tagIDs, build.TagID)
|
||||
}
|
||||
if err = s.dao.DB.Where("id in(?)", tagIDs).Find(&tags).Error; err != nil {
|
||||
log.Error("tagsByIDs(%v) error(%v)", tagIDs, err)
|
||||
if err == sql.ErrNoRows {
|
||||
err = nil
|
||||
}
|
||||
return
|
||||
}
|
||||
tmp := make(map[int64]struct{})
|
||||
for _, tag := range tags {
|
||||
tmpIDs := strings.Split(tag.ConfigIDs, ",")
|
||||
for _, tmpID := range tmpIDs {
|
||||
var id int64
|
||||
if id, err = strconv.ParseInt(tmpID, 10, 64); err != nil {
|
||||
log.Error("strconv.ParseInt() error(%v)", err)
|
||||
return
|
||||
}
|
||||
if _, ok := tmp[id]; !ok {
|
||||
tmp[id] = struct{}{}
|
||||
confIDs = append(confIDs, id)
|
||||
}
|
||||
}
|
||||
}
|
||||
if err = s.dao.DB.Where("id in (?) AND comment like(?) ", confIDs, "%"+like+"%").Find(&confs).Error; err != nil {
|
||||
log.Error("confsByIDs(%v) error(%v)", confIDs, err)
|
||||
if err == sql.ErrNoRows {
|
||||
err = nil
|
||||
}
|
||||
return
|
||||
}
|
||||
for _, conf := range confs {
|
||||
search := new(model.ConfigSearch)
|
||||
search.App = appName
|
||||
for _, tag := range tags {
|
||||
tmpIDs := strings.Split(tag.ConfigIDs, ",")
|
||||
for _, tmpID := range tmpIDs {
|
||||
var id int64
|
||||
if id, err = strconv.ParseInt(tmpID, 10, 64); err != nil {
|
||||
log.Error("strconv.ParseInt() error(%v)", err)
|
||||
return
|
||||
}
|
||||
if id != conf.ID { //judge config is in build.
|
||||
continue
|
||||
}
|
||||
for _, build := range builds {
|
||||
if build.ID == tag.BuildID {
|
||||
search.Builds = append(search.Builds, build.Name)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//generate comment.
|
||||
search.ConfValues = genComments(conf.Comment, like)
|
||||
search.ConfID = conf.ID
|
||||
search.Mark = conf.Mark
|
||||
search.ConfName = conf.Name
|
||||
searchs = append(searchs, search)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
//ConfigSearchAll configSearchAll.
|
||||
func (s *Service) ConfigSearchAll(ctx context.Context, env, zone, like string, nodes *model.CacheData) (searchs []*model.ConfigSearch, err error) {
|
||||
var (
|
||||
apps []*model.App
|
||||
builds []*model.Build
|
||||
tags []*model.Tag
|
||||
confs []*model.Config
|
||||
names []string
|
||||
appIDs []int64
|
||||
tagIDs []int64
|
||||
configIDs []int64
|
||||
)
|
||||
searchs = make([]*model.ConfigSearch, 0)
|
||||
if len(nodes.Data) == 0 {
|
||||
return
|
||||
}
|
||||
for _, node := range nodes.Data {
|
||||
names = append(names, node.Path)
|
||||
}
|
||||
if err = s.dao.DB.Where("env =? and zone =? and name in(?)", env, zone, names).Find(&apps).Error; err != nil {
|
||||
log.Error("AppList() find apps() error(%v)", err)
|
||||
if err == sql.ErrNoRows {
|
||||
err = nil
|
||||
}
|
||||
return
|
||||
}
|
||||
for _, app := range apps {
|
||||
appIDs = append(appIDs, app.ID)
|
||||
}
|
||||
if err = s.dao.DB.Where("app_id in(?) ", appIDs).Find(&builds).Error; err != nil {
|
||||
log.Error("BuildsByAppIDs(%v) error(%v)", appIDs, err)
|
||||
if err == sql.ErrNoRows {
|
||||
err = nil
|
||||
}
|
||||
return
|
||||
}
|
||||
for _, build := range builds {
|
||||
tagIDs = append(tagIDs, build.TagID)
|
||||
}
|
||||
if err = s.dao.DB.Where("id in(?)", tagIDs).Find(&tags).Error; err != nil {
|
||||
log.Error("tagsByIDs(%v) error(%v)", tagIDs, err)
|
||||
if err == sql.ErrNoRows {
|
||||
err = nil
|
||||
}
|
||||
return
|
||||
}
|
||||
tmp := make(map[int64]struct{})
|
||||
for _, tag := range tags {
|
||||
tmpIDs := strings.Split(tag.ConfigIDs, ",")
|
||||
for _, tmpID := range tmpIDs {
|
||||
var id int64
|
||||
if id, err = strconv.ParseInt(tmpID, 10, 64); err != nil {
|
||||
log.Error("strconv.ParseInt() error(%v)", err)
|
||||
return
|
||||
}
|
||||
if _, ok := tmp[id]; !ok {
|
||||
tmp[id] = struct{}{}
|
||||
configIDs = append(configIDs, id)
|
||||
}
|
||||
}
|
||||
}
|
||||
if err = s.dao.DB.Where("id in (?) and comment like(?) ", configIDs, "%"+like+"%").Find(&confs).Error; err != nil {
|
||||
log.Error("confsByIDs(%v) error(%v)", configIDs, err)
|
||||
if err == sql.ErrNoRows {
|
||||
err = nil
|
||||
}
|
||||
return
|
||||
}
|
||||
if len(confs) == 0 {
|
||||
return
|
||||
}
|
||||
// convert confs to confSearch.
|
||||
for _, conf := range confs {
|
||||
search := new(model.ConfigSearch)
|
||||
for _, app := range apps {
|
||||
if app.ID == conf.AppID {
|
||||
search.App = app.Name
|
||||
search.TreeID = app.TreeID
|
||||
}
|
||||
}
|
||||
for _, tag := range tags {
|
||||
tmpIDs := strings.Split(tag.ConfigIDs, ",")
|
||||
for _, tmpID := range tmpIDs {
|
||||
var id int64
|
||||
if id, err = strconv.ParseInt(tmpID, 10, 64); err != nil {
|
||||
log.Error("strconv.ParseInt() error(%v)", err)
|
||||
return
|
||||
}
|
||||
if id != conf.ID { //judge config is in build.
|
||||
continue
|
||||
}
|
||||
for _, build := range builds {
|
||||
if build.ID == tag.BuildID {
|
||||
search.Builds = append(search.Builds, build.Name)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//generate comment.
|
||||
search.ConfValues = genComments(conf.Comment, like)
|
||||
search.ConfID = conf.ID
|
||||
search.Mark = conf.Mark
|
||||
search.ConfName = conf.Name
|
||||
searchs = append(searchs, search)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func genComments(comment, like string) (comments []string) {
|
||||
var (
|
||||
line []byte
|
||||
l, cur []byte
|
||||
err error
|
||||
)
|
||||
wbuf := new(bytes.Buffer)
|
||||
rbuf := bufio.NewReader(strings.NewReader(comment))
|
||||
for {
|
||||
l = line
|
||||
if line, _, err = rbuf.ReadLine(); err != nil {
|
||||
break
|
||||
}
|
||||
if bytes.Contains(line, []byte(like)) {
|
||||
cur = line
|
||||
wbuf.Write(l)
|
||||
wbuf.WriteString("\n")
|
||||
wbuf.Write(cur)
|
||||
wbuf.WriteString("\n")
|
||||
line, _, _ = rbuf.ReadLine()
|
||||
wbuf.Write(line)
|
||||
wbuf.WriteString("\n")
|
||||
comments = append(comments, wbuf.String())
|
||||
wbuf.Reset()
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
//Configs configs.
|
||||
func (s *Service) Configs(appName, env, zone string, buildID, treeID int64) (res *model.ConfigRes, err error) {
|
||||
var (
|
||||
allConfs []*model.Config
|
||||
buildConfs []*model.Config
|
||||
lastConfs []*model.Config
|
||||
app *model.App
|
||||
build *model.Build
|
||||
)
|
||||
if app, err = s.AppByTree(treeID, env, zone); err != nil {
|
||||
if err == ecode.NothingFound {
|
||||
err = s.CreateApp(appName, env, zone, treeID)
|
||||
return
|
||||
}
|
||||
}
|
||||
if allConfs, err = s.ConfigsByAppID(app.ID, 0); err != nil {
|
||||
return
|
||||
}
|
||||
if buildID != 0 {
|
||||
if build, err = s.Build(buildID); err != nil {
|
||||
return
|
||||
}
|
||||
if build.AppID != app.ID {
|
||||
err = ecode.NothingFound
|
||||
return
|
||||
}
|
||||
tagID := build.TagID
|
||||
if tagID == 0 {
|
||||
return
|
||||
}
|
||||
if buildConfs, err = s.ConfigsByTagID(tagID); err != nil {
|
||||
return
|
||||
}
|
||||
if lastConfs, err = s.LastBuildConfigConfigs(build.AppID, buildID); err != nil {
|
||||
if err != ecode.NothingFound {
|
||||
return
|
||||
}
|
||||
err = nil
|
||||
}
|
||||
}
|
||||
tmpMap := make(map[string]struct{})
|
||||
res = new(model.ConfigRes)
|
||||
for _, conf := range allConfs {
|
||||
if _, ok := tmpMap[conf.Name]; ok {
|
||||
continue
|
||||
}
|
||||
//new common
|
||||
if conf.From > 0 {
|
||||
conf.NewCommon, _ = s.NewCommon(conf.From)
|
||||
}
|
||||
tmpMap[conf.Name] = struct{}{}
|
||||
var bool bool
|
||||
for _, bconf := range buildConfs {
|
||||
//new common
|
||||
if bconf.From > 0 {
|
||||
bconf.NewCommon, _ = s.NewCommon(bconf.From)
|
||||
}
|
||||
if bconf.Name == conf.Name {
|
||||
if bconf.ID != conf.ID {
|
||||
if conf.IsDelete != 1 {
|
||||
res.BuildNewFile = append(res.BuildNewFile, conf)
|
||||
}
|
||||
}
|
||||
bf := &model.BuildFile{Config: bconf}
|
||||
if bf.IsDelete == 0 {
|
||||
res.BuildFiles = append(res.BuildFiles, bf)
|
||||
}
|
||||
for _, lconf := range lastConfs {
|
||||
if lconf.Name == bconf.Name {
|
||||
if lconf.ID != bconf.ID {
|
||||
bf.LastConf = lconf
|
||||
}
|
||||
}
|
||||
}
|
||||
bool = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !bool {
|
||||
if conf.IsDelete != 1 {
|
||||
res.Files = append(res.Files, conf)
|
||||
}
|
||||
continue
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// NewCommon get new common id
|
||||
func (s *Service) NewCommon(from int64) (new int64, err error) {
|
||||
common := &model.CommonConf{}
|
||||
newCommon := &model.CommonConf{}
|
||||
if err = s.dao.DB.First(&common, from).Error; err != nil {
|
||||
log.Error("NewCommon.First.from(%d) error(%v)", from, err)
|
||||
return
|
||||
}
|
||||
if err = s.dao.DB.Where("team_id = ? and name = ? and state = 2", common.TeamID, common.Name).Order("id desc").First(&newCommon).Error; err != nil {
|
||||
log.Error("NewCommon.Order.First.common(%v) error(%v)", common, err)
|
||||
return
|
||||
}
|
||||
new = newCommon.ID
|
||||
return
|
||||
}
|
||||
|
||||
//ConfigRefs configRefs.
|
||||
func (s *Service) ConfigRefs(appName, env, zone string, buildID, treeID int64) (res []*model.ConfigRefs, err error) {
|
||||
var (
|
||||
allConfs []*model.Config
|
||||
buildConfs []*model.Config
|
||||
num int
|
||||
ok bool
|
||||
ref *model.ConfigRefs
|
||||
)
|
||||
if allConfs, err = s.ConfigsByAppName(appName, env, zone, treeID, model.ConfigEnd); err != nil {
|
||||
return
|
||||
}
|
||||
if buildID != 0 {
|
||||
if buildConfs, err = s.ConfigsByBuildID(buildID); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
tmpMap := make(map[string]int)
|
||||
refs := make(map[string]*model.ConfigRefs)
|
||||
for _, conf := range allConfs {
|
||||
if num, ok = tmpMap[conf.Name]; !ok {
|
||||
ref = new(model.ConfigRefs)
|
||||
refs[conf.Name] = ref
|
||||
tmpMap[conf.Name] = num
|
||||
} else {
|
||||
ref = refs[conf.Name]
|
||||
}
|
||||
if num <= 5 {
|
||||
ref.Configs = append(ref.Configs, &model.ConfigRef{ID: conf.ID, Mark: conf.Mark})
|
||||
tmpMap[conf.Name] = num + 1
|
||||
}
|
||||
if ref.Ref != nil {
|
||||
continue
|
||||
}
|
||||
for _, bconf := range buildConfs {
|
||||
if bconf.Name == conf.Name {
|
||||
ref.Ref = &model.ConfigRef{ID: bconf.ID, Mark: bconf.Mark}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
for k, v := range refs {
|
||||
v.Name = k
|
||||
res = append(res, v)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// ConfigsByBuildID get configs by build ID.
|
||||
func (s *Service) ConfigsByBuildID(buildID int64) (confs []*model.Config, err error) {
|
||||
var (
|
||||
build *model.Build
|
||||
)
|
||||
if build, err = s.Build(buildID); err != nil {
|
||||
return
|
||||
}
|
||||
tagID := build.TagID
|
||||
if tagID == 0 {
|
||||
return
|
||||
}
|
||||
return s.ConfigsByTagID(tagID)
|
||||
}
|
||||
|
||||
// LastBuildConfigs get configs by build ID.
|
||||
func (s *Service) LastBuildConfigs(appID, buildID int64) (confs []*model.Config, err error) {
|
||||
var (
|
||||
tag *model.Tag
|
||||
ids []int64
|
||||
id int64
|
||||
)
|
||||
if tag, err = s.LastTagByAppBuild(appID, buildID); err != nil {
|
||||
return
|
||||
}
|
||||
confIDs := tag.ConfigIDs
|
||||
if len(confIDs) == 0 {
|
||||
return
|
||||
}
|
||||
tmpIDs := strings.Split(confIDs, ",")
|
||||
for _, tmpID := range tmpIDs {
|
||||
if id, err = strconv.ParseInt(tmpID, 10, 64); err != nil {
|
||||
log.Error("strconv.ParseInt(%s) error(%v)", tmpID, err)
|
||||
return
|
||||
}
|
||||
ids = append(ids, id)
|
||||
}
|
||||
return s.ConfigsByIDs(ids)
|
||||
}
|
||||
|
||||
// LastBuildConfigConfigs get configs by build ID.
|
||||
func (s *Service) LastBuildConfigConfigs(appID, buildID int64) (confs []*model.Config, err error) {
|
||||
var (
|
||||
tag *model.Tag
|
||||
ids []int64
|
||||
id int64
|
||||
tmps []*model.Config
|
||||
cids []int64
|
||||
lastIDS []int64
|
||||
)
|
||||
if tag, err = s.TagByAppBuild(appID, buildID); err != nil {
|
||||
return
|
||||
}
|
||||
confIDs := tag.ConfigIDs
|
||||
if len(confIDs) == 0 {
|
||||
return
|
||||
}
|
||||
tmpIDs := strings.Split(confIDs, ",")
|
||||
for _, tmpID := range tmpIDs {
|
||||
if id, err = strconv.ParseInt(tmpID, 10, 64); err != nil {
|
||||
log.Error("strconv.ParseInt(%s) error(%v)", tmpID, err)
|
||||
return
|
||||
}
|
||||
ids = append(ids, id)
|
||||
}
|
||||
tmps, err = s.ConfigsByIDs(ids)
|
||||
if err != nil {
|
||||
log.Error("LastBuildConfigConfigs ids(%v) error(%v)", ids, err)
|
||||
return
|
||||
}
|
||||
for _, val := range tmps {
|
||||
cs, err := s.ConfigList(val.AppID, val.Name)
|
||||
if err == nil {
|
||||
cids = nil
|
||||
csloop:
|
||||
for _, vv := range cs {
|
||||
for _, vvv := range ids {
|
||||
if vvv == vv.ID {
|
||||
continue csloop
|
||||
}
|
||||
}
|
||||
cids = append(cids, vv.ID)
|
||||
}
|
||||
if configID, err := s.TagByAppBuildLastConfig(appID, buildID, tag.ID, cids); err == nil {
|
||||
lastIDS = append(lastIDS, configID)
|
||||
}
|
||||
}
|
||||
}
|
||||
return s.ConfigsByIDs(lastIDS)
|
||||
}
|
||||
|
||||
// ConfigList ...
|
||||
func (s *Service) ConfigList(appID int64, name string) (confs []*model.Config, err error) {
|
||||
if err = s.dao.DB.Where("app_id = ? and name = ?", appID, name).Order("id desc").Find(&confs).Error; err != nil {
|
||||
log.Error("ConfigList appid(%v) name(%v) error(%v)", appID, name, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// ConfigsByTagID get configs by tag id.
|
||||
func (s *Service) ConfigsByTagID(tagID int64) (confs []*model.Config, err error) {
|
||||
var (
|
||||
tag *model.Tag
|
||||
ids []int64
|
||||
id int64
|
||||
)
|
||||
if tag, err = s.Tag(tagID); err != nil {
|
||||
return
|
||||
}
|
||||
confIDs := tag.ConfigIDs
|
||||
if len(confIDs) == 0 {
|
||||
err = ecode.NothingFound
|
||||
return
|
||||
}
|
||||
tmpIDs := strings.Split(confIDs, ",")
|
||||
for _, tmpID := range tmpIDs {
|
||||
if id, err = strconv.ParseInt(tmpID, 10, 64); err != nil {
|
||||
log.Error("strconv.ParseInt(%s) error(%v)", tmpID, err)
|
||||
return
|
||||
}
|
||||
ids = append(ids, id)
|
||||
}
|
||||
return s.ConfigsByIDs(ids)
|
||||
}
|
||||
|
||||
//Config get Config by Config ID.
|
||||
func (s *Service) Config(ID int64) (conf *model.Config, err error) {
|
||||
conf = new(model.Config)
|
||||
err = s.dao.DB.First(&conf, ID).Error
|
||||
return
|
||||
}
|
||||
|
||||
func (s *Service) configIng(name string, appID int64) (conf *model.Config, err error) {
|
||||
conf = new(model.Config)
|
||||
if err = s.dao.DB.Select("id").Where("name = ? and app_id = ? and state=?", name, appID, model.ConfigIng).First(&conf).Error; err != nil {
|
||||
log.Error("configIng(%v) error(%v)", name, err)
|
||||
if err == sql.ErrNoRows {
|
||||
err = ecode.NothingFound
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
//Value get value by Config ID.
|
||||
func (s *Service) Value(ID int64) (conf *model.Config, err error) {
|
||||
conf = new(model.Config)
|
||||
if err = s.dao.DB.First(&conf, ID).Error; err != nil {
|
||||
log.Error("Value() error(%v)", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
//ConfigsByTree get Config by Config name.
|
||||
func (s *Service) ConfigsByTree(treeID int64, env, zone, name string) (confs []*model.Config, err error) {
|
||||
var app *model.App
|
||||
if app, err = s.AppByTree(treeID, env, zone); err != nil {
|
||||
return
|
||||
}
|
||||
if err = s.dao.DB.Order("id desc").Limit(10).Find(&confs, "name = ? and app_id = ?", name, app.ID).Error; err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
err = nil
|
||||
}
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// NamesByAppTree get configs by app name.
|
||||
func (s *Service) NamesByAppTree(appName, env, zone string, treeID int64) (names []string, err error) {
|
||||
var (
|
||||
app *model.App
|
||||
confs []*model.Config
|
||||
)
|
||||
if app, err = s.AppByTree(treeID, env, zone); err != nil {
|
||||
if err == ecode.NothingFound {
|
||||
err = s.CreateApp(appName, env, zone, treeID)
|
||||
return
|
||||
}
|
||||
}
|
||||
if err = s.dao.DB.Select("name").Where("app_id = ?", app.ID).Order("id desc").Group("name").Find(&confs).Error; err != nil {
|
||||
log.Error("NamesByAppName(%v) error(%v)", app.ID, err)
|
||||
if err == sql.ErrNoRows {
|
||||
err = nil
|
||||
}
|
||||
return
|
||||
}
|
||||
for _, conf := range confs {
|
||||
names = append(names, conf.Name)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
//Diff get value by Config ID.
|
||||
func (s *Service) Diff(ID, BuildID int64) (data *model.Config, err error) {
|
||||
var tmpID int64
|
||||
var idArr []string
|
||||
conf := new(model.Config)
|
||||
if err = s.dao.DB.First(&conf, ID).Error; err != nil {
|
||||
log.Error("Diff() config_id(%v) error(%v)", ID, err)
|
||||
return
|
||||
}
|
||||
config := []*model.Config{}
|
||||
if err = s.dao.DB.Where("`app_id` = ? and `name` = ? and `state` = 2", conf.AppID, conf.Name).Order("id desc").Find(&config).Error; err != nil {
|
||||
log.Error("Diff() app_id(%v) name(%v) error(%v)", conf.AppID, conf.Name, err)
|
||||
return
|
||||
}
|
||||
build := &model.Build{}
|
||||
if err = s.dao.DB.First(build, BuildID).Error; err != nil && err != gorm.ErrRecordNotFound {
|
||||
log.Error("Diff() build_id(%v) error(%v)", BuildID, err)
|
||||
return
|
||||
}
|
||||
err = nil
|
||||
if build.ID > 0 {
|
||||
tag := &model.Tag{}
|
||||
if err = s.dao.DB.First(tag, build.TagID).Error; err != nil {
|
||||
log.Error("Diff() tag_id(%v) error(%v)", build.TagID, err)
|
||||
return
|
||||
}
|
||||
idArr = strings.Split(tag.ConfigIDs, ",")
|
||||
}
|
||||
if len(idArr) > 0 {
|
||||
for _, val := range config {
|
||||
for _, vv := range idArr {
|
||||
tmpID, _ = strconv.ParseInt(vv, 10, 64)
|
||||
if tmpID == val.ID {
|
||||
data = val
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, val2 := range config {
|
||||
if val2.ID < ID {
|
||||
data = val2
|
||||
return
|
||||
}
|
||||
}
|
||||
data = conf
|
||||
return
|
||||
}
|
||||
|
||||
//ConfigDel config is delete.
|
||||
func (s *Service) ConfigDel(ID int64) (err error) {
|
||||
conf := &model.Config{}
|
||||
if err = s.dao.DB.First(conf, ID).Error; err != nil {
|
||||
log.Error("ConfigDel first id(%v) error(%v)", ID, err)
|
||||
return
|
||||
}
|
||||
confs := []*model.Config{}
|
||||
if err = s.dao.DB.Where("app_id = ? and name = ?", conf.AppID, conf.Name).Find(&confs).Error; err != nil {
|
||||
log.Error("ConfigDel find error(%v)", err)
|
||||
return
|
||||
}
|
||||
build := []*model.Build{}
|
||||
if err = s.dao.DB.Where("app_id = ?", conf.AppID).Find(&build).Error; err != nil {
|
||||
log.Error("ConfigDel find app_id(%v) error(%v)", conf.AppID, err)
|
||||
return
|
||||
}
|
||||
for _, val := range build {
|
||||
tag := &model.Tag{}
|
||||
if err = s.dao.DB.Where("id = ?", val.TagID).First(tag).Error; err != nil {
|
||||
log.Error("ConfigDel first tag_id(%v) error(%v)", val.TagID, err)
|
||||
return
|
||||
}
|
||||
arr := strings.Split(tag.ConfigIDs, ",")
|
||||
for _, vv := range arr {
|
||||
for _, vvv := range confs {
|
||||
if vv == strconv.FormatInt(vvv.ID, 10) {
|
||||
err = ecode.NothingFound
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ups := map[string]interface{}{
|
||||
"is_delete": 1,
|
||||
"state": 2,
|
||||
}
|
||||
if err = s.dao.DB.Model(conf).Where("id = ?", ID).Updates(ups).Error; err != nil {
|
||||
log.Error("ConfigDel updates error(%v)", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
//BuildConfigInfos configRefs.
|
||||
func (s *Service) BuildConfigInfos(appName, env, zone string, buildID, treeID int64) (res map[string][]*model.ConfigRefs, err error) {
|
||||
var (
|
||||
allConfs []*model.Config
|
||||
buildConfs []*model.Config
|
||||
num int
|
||||
ok bool
|
||||
ref *model.ConfigRefs
|
||||
)
|
||||
if allConfs, err = s.ConfigsByAppName(appName, env, zone, treeID, model.ConfigEnd); err != nil {
|
||||
return
|
||||
}
|
||||
if buildID != 0 {
|
||||
if buildConfs, err = s.ConfigsByBuildID(buildID); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
tmpMap := make(map[string]int)
|
||||
tmpBuildConfs := make(map[string]map[int64]struct{})
|
||||
refs := make(map[string]*model.ConfigRefs)
|
||||
for _, conf := range allConfs {
|
||||
if num, ok = tmpMap[conf.Name]; !ok {
|
||||
ref = new(model.ConfigRefs)
|
||||
refs[conf.Name] = ref
|
||||
tmpMap[conf.Name] = num
|
||||
} else {
|
||||
ref = refs[conf.Name]
|
||||
}
|
||||
if num <= 20 {
|
||||
ref.Configs = append(ref.Configs, &model.ConfigRef{ID: conf.ID, Mark: conf.Mark, IsDelete: conf.IsDelete})
|
||||
tmpMap[conf.Name] = num + 1
|
||||
if tmpBuildConfs[conf.Name] == nil {
|
||||
tmpBuildConfs[conf.Name] = make(map[int64]struct{})
|
||||
}
|
||||
tmpBuildConfs[conf.Name][conf.ID] = struct{}{}
|
||||
} else {
|
||||
for _, bconf := range buildConfs {
|
||||
if bconf.Name == conf.Name {
|
||||
if _, ok = tmpBuildConfs[conf.Name][bconf.ID]; !ok {
|
||||
tmpBuildConfs[conf.Name][bconf.ID] = struct{}{}
|
||||
ref.Configs = append(ref.Configs, &model.ConfigRef{ID: bconf.ID, Mark: bconf.Mark, IsDelete: bconf.IsDelete})
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if ref.Ref != nil {
|
||||
continue
|
||||
}
|
||||
for _, bconf := range buildConfs {
|
||||
if bconf.Name == conf.Name {
|
||||
ref.Ref = &model.ConfigRef{ID: bconf.ID, Mark: bconf.Mark, IsDelete: bconf.IsDelete}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
res = make(map[string][]*model.ConfigRefs)
|
||||
var tp int64
|
||||
var IsDelete int64
|
||||
capacity := len(refs)
|
||||
res["new"] = make([]*model.ConfigRefs, 0, capacity)
|
||||
res["nothing"] = make([]*model.ConfigRefs, 0, capacity)
|
||||
res["notused"] = make([]*model.ConfigRefs, 0, capacity)
|
||||
for k, v := range refs {
|
||||
v.Name = k
|
||||
IsDelete = 0
|
||||
for i, tv := range v.Configs {
|
||||
if tv.IsDelete == 1 && tv.ID > IsDelete {
|
||||
IsDelete = tv.ID
|
||||
v.Configs = v.Configs[:i]
|
||||
}
|
||||
}
|
||||
v.DeleteMAX = IsDelete
|
||||
if len(v.Configs) == 0 {
|
||||
continue
|
||||
}
|
||||
if v.Ref != nil {
|
||||
tp = 0
|
||||
for _, vv := range v.Configs {
|
||||
if vv.ID > v.Ref.ID {
|
||||
tp = vv.ID
|
||||
}
|
||||
}
|
||||
if tp > 0 {
|
||||
res["new"] = append(res["new"], v)
|
||||
} else {
|
||||
res["nothing"] = append(res["nothing"], v)
|
||||
}
|
||||
} else {
|
||||
res["notused"] = append(res["notused"], v)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// GetConfigs ...
|
||||
func (s *Service) GetConfigs(ids []int64, name string) (configs []*model.Config, err error) {
|
||||
if err = s.dao.DB.Where("name = ? AND id in (?)", name, ids).Find(&configs).Error; err != nil {
|
||||
log.Error("GetConfigs error(%v)", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// GetConfig ...
|
||||
func (s *Service) GetConfig(ids []int64, name string) (config *model.Config, err error) {
|
||||
config = new(model.Config)
|
||||
if err = s.dao.DB.Where("name = ? AND id in (?)", name, ids).First(config).Error; err != nil {
|
||||
log.Error("GetConfigs error(%v)", err)
|
||||
}
|
||||
return
|
||||
}
|
68
app/admin/main/config/service/config_test.go
Normal file
68
app/admin/main/config/service/config_test.go
Normal file
@ -0,0 +1,68 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestService_ConfigsByIDs(t *testing.T) {
|
||||
svr := svr(t)
|
||||
Convey("should configs by ids", t, func() {
|
||||
res, err := svr.ConfigsByIDs([]int64{1, 2})
|
||||
So(err, ShouldBeNil)
|
||||
So(res, ShouldNotBeEmpty)
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
func TestService_UpdateConfState(t *testing.T) {
|
||||
svr := svr(t)
|
||||
Convey("should update state", t, func() {
|
||||
err := svr.UpdateConfState(2)
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
}
|
||||
|
||||
func TestService_ConfigsByBuildID(t *testing.T) {
|
||||
svr := svr(t)
|
||||
Convey("should get config by build id", t, func() {
|
||||
res, err := svr.ConfigsByBuildID(1)
|
||||
So(err, ShouldBeNil)
|
||||
So(res, ShouldNotBeEmpty)
|
||||
})
|
||||
}
|
||||
|
||||
func TestService_ConfigsByAppName(t *testing.T) {
|
||||
svr := svr(t)
|
||||
Convey("should get configs by app name", t, func() {
|
||||
res, err := svr.ConfigsByAppName("main.common-arch.msm-service", "dev", "shd", 2888, 0)
|
||||
So(err, ShouldBeNil)
|
||||
So(res, ShouldNotBeEmpty)
|
||||
})
|
||||
}
|
||||
func TestService_Configs(t *testing.T) {
|
||||
svr := svr(t)
|
||||
Convey("should configs", t, func() {
|
||||
res, err := svr.Configs("main.account.open-svr-mng", "fat1", "shd", 0, 2888)
|
||||
So(err, ShouldBeNil)
|
||||
So(res, ShouldNotBeEmpty)
|
||||
})
|
||||
}
|
||||
|
||||
func TestService_Diff(t *testing.T) {
|
||||
svr := svr(t)
|
||||
Convey("should configs", t, func() {
|
||||
res, err := svr.Diff(1, 1)
|
||||
So(err, ShouldBeNil)
|
||||
So(res, ShouldNotBeEmpty)
|
||||
})
|
||||
}
|
||||
func TestService_Value(t *testing.T) {
|
||||
svr := svr(t)
|
||||
Convey("should configs", t, func() {
|
||||
res, err := svr.Value(1)
|
||||
So(err, ShouldBeNil)
|
||||
So(res, ShouldNotBeEmpty)
|
||||
})
|
||||
}
|
89
app/admin/main/config/service/force.go
Normal file
89
app/admin/main/config/service/force.go
Normal file
@ -0,0 +1,89 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"go-common/app/admin/main/config/model"
|
||||
"go-common/library/log"
|
||||
|
||||
"github.com/jinzhu/gorm"
|
||||
)
|
||||
|
||||
//UpdateForce update force.
|
||||
func (s *Service) UpdateForce(ctx context.Context, treeID, version int64, env, zone, build, username string, hosts map[string]string) (err error) {
|
||||
var (
|
||||
app *model.App
|
||||
force *model.Force
|
||||
ups map[string]interface{}
|
||||
)
|
||||
if app, err = s.AppByTree(treeID, env, zone); err != nil {
|
||||
return
|
||||
}
|
||||
tx := s.dao.DB.Begin()
|
||||
for key, val := range hosts {
|
||||
force = &model.Force{}
|
||||
force.Hostname = key
|
||||
force.AppID = app.ID
|
||||
force.IP = val
|
||||
force.Operator = username
|
||||
force.Version = version
|
||||
if err = s.dao.DB.Where("app_id = ? and hostname = ? and ip = ?", app.ID, key, val).First(&model.Force{}).Error; err != nil {
|
||||
if err != gorm.ErrRecordNotFound {
|
||||
tx.Rollback()
|
||||
log.Error("UpdateForce first error(%v)", err)
|
||||
return
|
||||
}
|
||||
//create
|
||||
if err = s.dao.DB.Create(force).Error; err != nil {
|
||||
tx.Rollback()
|
||||
log.Error("UpdateForce(%s) error(%v)", force, err)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
//update
|
||||
ups = map[string]interface{}{
|
||||
"hostname": key,
|
||||
"app_id": app.ID,
|
||||
"ip": val,
|
||||
"operator": username,
|
||||
"version": version,
|
||||
}
|
||||
if err = s.dao.DB.Model(&model.Force{}).Where("app_id = ? and hostname = ? and ip = ?", app.ID, key, val).Updates(ups).Error; err != nil {
|
||||
tx.Rollback()
|
||||
log.Error("UpdateForce(%s) error(%v)", force, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if err = s.PushForce(ctx, treeID, env, zone, build, version, hosts, 1); err != nil {
|
||||
tx.Rollback()
|
||||
return
|
||||
}
|
||||
tx.Commit()
|
||||
return
|
||||
}
|
||||
|
||||
//ClearForce delete force.
|
||||
func (s *Service) ClearForce(ctx context.Context, treeID int64, env, zone, build string, hosts map[string]string) (err error) {
|
||||
var (
|
||||
app *model.App
|
||||
)
|
||||
if app, err = s.AppByTree(treeID, env, zone); err != nil {
|
||||
return
|
||||
}
|
||||
tx := s.dao.DB.Begin()
|
||||
for key, val := range hosts {
|
||||
if err = s.dao.DB.Where("app_id = ? and hostname = ?", app.ID, key).Delete(model.Force{}).Error; err != nil {
|
||||
tx.Rollback()
|
||||
log.Error("ClearForce hostname(%s) ip(%v) error(%v)", key, val, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
if err = s.PushForce(ctx, treeID, env, zone, build, 0, hosts, 0); err != nil {
|
||||
tx.Rollback()
|
||||
return
|
||||
}
|
||||
tx.Commit()
|
||||
return
|
||||
}
|
52
app/admin/main/config/service/service.go
Normal file
52
app/admin/main/config/service/service.go
Normal file
@ -0,0 +1,52 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"go-common/app/admin/main/config/conf"
|
||||
"go-common/app/admin/main/config/dao"
|
||||
confrpc "go-common/app/infra/config/rpc/client"
|
||||
|
||||
"go-common/app/admin/main/config/model"
|
||||
|
||||
"github.com/jinzhu/gorm"
|
||||
)
|
||||
|
||||
// Service service
|
||||
type Service struct {
|
||||
c *conf.Config
|
||||
|
||||
// rpcconf config service Rpc
|
||||
confSvr *confrpc.Service2
|
||||
dao *dao.Dao
|
||||
|
||||
cLock sync.RWMutex
|
||||
cache map[string]*model.CacheData
|
||||
//apm gorm
|
||||
DBApm *gorm.DB
|
||||
//db gorm
|
||||
DB *gorm.DB
|
||||
}
|
||||
|
||||
// New new a service
|
||||
func New(c *conf.Config) (s *Service) {
|
||||
s = &Service{
|
||||
c: c,
|
||||
confSvr: confrpc.New2(c.ConfSvr),
|
||||
dao: dao.New(c),
|
||||
}
|
||||
s.cache = make(map[string]*model.CacheData)
|
||||
s.DBApm = s.dao.DBApm
|
||||
s.DB = s.dao.DB
|
||||
return
|
||||
}
|
||||
|
||||
// Ping check server ok.
|
||||
func (s *Service) Ping() (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// Close close resource
|
||||
func (s *Service) Close() {
|
||||
s.dao.Close()
|
||||
}
|
222
app/admin/main/config/service/tag.go
Normal file
222
app/admin/main/config/service/tag.go
Normal file
@ -0,0 +1,222 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"go-common/app/admin/main/config/model"
|
||||
"go-common/library/ecode"
|
||||
"go-common/library/log"
|
||||
)
|
||||
|
||||
// CreateTag create App.
|
||||
func (s *Service) CreateTag(tag *model.Tag, treeID int64, env, zone string) (err error) {
|
||||
var app *model.App
|
||||
if app, err = s.AppByTree(treeID, env, zone); err != nil {
|
||||
return
|
||||
}
|
||||
tag.AppID = app.ID
|
||||
return s.dao.DB.Create(tag).Error
|
||||
}
|
||||
|
||||
//LastTags get tags by app name.
|
||||
func (s *Service) LastTags(treeID int64, env, zone, bName string) (tags []*model.Tag, err error) {
|
||||
var (
|
||||
app *model.App
|
||||
build *model.Build
|
||||
)
|
||||
if app, err = s.AppByTree(treeID, env, zone); err != nil {
|
||||
return
|
||||
}
|
||||
if build, err = s.BuildByName(app.ID, bName); err != nil {
|
||||
return
|
||||
}
|
||||
if err = s.dao.DB.Where("app_id = ? and build_id = ?", app.ID, build.ID).Order("id desc").Limit(10).Find(&tags).Error; err != nil {
|
||||
log.Error("Tags(%v) error(%v)", app.ID, err)
|
||||
if err == sql.ErrNoRows {
|
||||
err = nil
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
//TagsByBuild get tags by app name.
|
||||
func (s *Service) TagsByBuild(appName, env, zone, name string, ps, pn, treeID int64) (tagPager *model.TagConfigPager, err error) {
|
||||
var (
|
||||
app *model.App
|
||||
build *model.Build
|
||||
tags []*model.Tag
|
||||
confIDs []int64
|
||||
confs []*model.Config
|
||||
total int64
|
||||
)
|
||||
tagConfigs := make([]*model.TagConfig, 0)
|
||||
if app, err = s.AppByTree(treeID, env, zone); err != nil {
|
||||
if err == ecode.NothingFound {
|
||||
err = s.CreateApp(appName, env, zone, treeID)
|
||||
return
|
||||
}
|
||||
}
|
||||
if build, err = s.BuildByName(app.ID, name); err != nil {
|
||||
if err == ecode.NothingFound {
|
||||
err = nil
|
||||
}
|
||||
return
|
||||
}
|
||||
if err = s.dao.DB.Where("app_id = ? and build_id =?", app.ID, build.ID).Order("id desc").Offset((pn - 1) * ps).Limit(ps).Find(&tags).Error; err != nil {
|
||||
log.Error("TagsByBuild() findTags() error(%v)", err)
|
||||
if err == sql.ErrNoRows {
|
||||
err = nil
|
||||
}
|
||||
return
|
||||
}
|
||||
tmp := make(map[int64]struct{})
|
||||
for _, tag := range tags {
|
||||
tmpIDs := strings.Split(tag.ConfigIDs, ",")
|
||||
for _, tmpID := range tmpIDs {
|
||||
var id int64
|
||||
if id, err = strconv.ParseInt(tmpID, 10, 64); err != nil {
|
||||
log.Error("strconv.ParseInt() error(%v)", err)
|
||||
return
|
||||
}
|
||||
if _, ok := tmp[id]; !ok {
|
||||
tmp[id] = struct{}{}
|
||||
confIDs = append(confIDs, id)
|
||||
}
|
||||
}
|
||||
}
|
||||
if confs, err = s.ConfigsByIDs(confIDs); err != nil {
|
||||
return
|
||||
}
|
||||
for _, tag := range tags {
|
||||
tagConfig := new(model.TagConfig)
|
||||
tagConfig.Tag = tag
|
||||
tagConfigs = append(tagConfigs, tagConfig)
|
||||
tmpIDs := strings.Split(tag.ConfigIDs, ",")
|
||||
for _, tmpID := range tmpIDs {
|
||||
var id int64
|
||||
if id, err = strconv.ParseInt(tmpID, 10, 64); err != nil {
|
||||
log.Error("strconv.ParseInt() error(%v)", err)
|
||||
return
|
||||
}
|
||||
for _, conf := range confs {
|
||||
if id != conf.ID { //judge config is in build.
|
||||
continue
|
||||
}
|
||||
tagConfig.Confs = append(tagConfig.Confs, conf)
|
||||
}
|
||||
}
|
||||
}
|
||||
if err = s.dao.DB.Where("app_id = ? and build_id =?", app.ID, build.ID).Model(&model.Tag{}).Count(&total).Error; err != nil {
|
||||
log.Error("TagsByBuild() count() error(%v)", err)
|
||||
return
|
||||
}
|
||||
tagPager = &model.TagConfigPager{Ps: ps, Pn: pn, Total: total, Items: tagConfigs}
|
||||
return
|
||||
}
|
||||
|
||||
//LastTagByAppBuild get tags by app and build.
|
||||
func (s *Service) LastTagByAppBuild(appID, buildID int64) (tag *model.Tag, err error) {
|
||||
var (
|
||||
tags []*model.Tag
|
||||
)
|
||||
if err = s.dao.DB.Where("app_id = ? and build_id =?", appID, buildID).Order("id desc").Limit(2).Find(&tags).Error; err != nil {
|
||||
log.Error("LastTagByAppBuild() error(%v)", err)
|
||||
if err == sql.ErrNoRows {
|
||||
err = nil
|
||||
}
|
||||
return
|
||||
}
|
||||
if len(tags) != 2 {
|
||||
err = ecode.NothingFound
|
||||
return
|
||||
}
|
||||
return tags[1], nil
|
||||
}
|
||||
|
||||
//Tag get tag by id.
|
||||
func (s *Service) Tag(ID int64) (tag *model.Tag, err error) {
|
||||
tag = new(model.Tag)
|
||||
if err = s.dao.DB.First(&tag, ID).Error; err != nil {
|
||||
log.Error("Tag(%v) error(%v)", ID, err)
|
||||
if err == sql.ErrNoRows {
|
||||
err = ecode.NothingFound
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
//TagByAppBuild ...
|
||||
func (s *Service) TagByAppBuild(appID, buildID int64) (tag *model.Tag, err error) {
|
||||
tag = new(model.Tag)
|
||||
if err = s.dao.DB.Where("app_id = ? and build_id =?", appID, buildID).Order("id desc").First(&tag).Error; err != nil {
|
||||
log.Error("TagByAppBuild() error(%v)", err)
|
||||
if err == sql.ErrNoRows {
|
||||
err = nil
|
||||
}
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// TagByAppBuildLastConfig ...
|
||||
func (s *Service) TagByAppBuildLastConfig(appID, buildID, tagID int64, cids []int64) (configID int64, err error) {
|
||||
tags := []*model.Tag{}
|
||||
if err = s.dao.DB.Where("app_id = ? and build_id = ? and id != ?", appID, buildID, tagID).Order("id desc").Find(&tags).Error; err != nil {
|
||||
log.Error("TagByAppBuildLastConfig() error(%v)", err)
|
||||
return
|
||||
}
|
||||
var id int64
|
||||
for _, v := range tags {
|
||||
tmpIDs := strings.Split(v.ConfigIDs, ",")
|
||||
for _, tmpID := range tmpIDs {
|
||||
id, err = strconv.ParseInt(tmpID, 10, 64)
|
||||
if err != nil {
|
||||
log.Error("strconv.ParseInt(%s) error(%v)", tmpID, err)
|
||||
continue
|
||||
}
|
||||
for _, vv := range cids {
|
||||
if vv == id {
|
||||
configID = id
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
//RollBackTag ...
|
||||
func (s *Service) RollBackTag(tagID int64) (tag *model.Tag, err error) {
|
||||
tag = &model.Tag{}
|
||||
row := s.dao.DB.Select("`app_id`,`build_id`,`config_ids`,`force`,`mark`,`operator`").Where("id=?", tagID).Model(&model.Tag{}).Row()
|
||||
if err = row.Scan(&tag.AppID, &tag.BuildID, &tag.ConfigIDs, &tag.Force, &tag.Mark, &tag.Operator); err != nil {
|
||||
log.Error("RollBackTag(%v) err(%v)", tagID, err)
|
||||
if err == sql.ErrNoRows {
|
||||
err = ecode.NothingFound
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// GetConfigIDS ...
|
||||
func (s *Service) GetConfigIDS(tagIDS []int64) (tags []*model.Tag, err error) {
|
||||
if err = s.dao.DB.Where("id in (?)", tagIDS).Find(&tags).Error; err != nil {
|
||||
log.Error("GetConfigIDS err(%v)", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// LastTasConfigDiff ...
|
||||
func (s *Service) LastTasConfigDiff(tagID, appID, buildID int64) (tag *model.Tag, err error) {
|
||||
tag = new(model.Tag)
|
||||
if err = s.dao.DB.Where("id < ? and app_id = ? and build_id = ?", tagID, appID, buildID).Order("id desc").First(tag).Error; err != nil {
|
||||
log.Error("LastTasConfigDiff() error(%v)", err)
|
||||
if err == sql.ErrNoRows {
|
||||
err = nil
|
||||
}
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
35
app/admin/main/config/service/tag_test.go
Normal file
35
app/admin/main/config/service/tag_test.go
Normal file
@ -0,0 +1,35 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"go-common/app/admin/main/config/model"
|
||||
"testing"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestService_TagByID(t *testing.T) {
|
||||
svr := svr(t)
|
||||
Convey("should tag by id", t, func() {
|
||||
res, err := svr.Tag(2)
|
||||
So(err, ShouldBeNil)
|
||||
So(res, ShouldNotBeEmpty)
|
||||
})
|
||||
}
|
||||
|
||||
func TestService_TagsByAppID(t *testing.T) {
|
||||
svr := svr(t)
|
||||
Convey("should get tags by app id", t, func() {
|
||||
res, err := svr.TagsByBuild("main.common-arch.msm-service", "dev", "shd", "server-1", 2, 1, 2888)
|
||||
So(err, ShouldBeNil)
|
||||
So(res, ShouldNotBeEmpty)
|
||||
})
|
||||
}
|
||||
|
||||
func TestService_UpdateTag(t *testing.T) {
|
||||
svr := svr(t)
|
||||
Convey("should update tag", t, func() {
|
||||
err := svr.UpdateTag(context.Background(), 2888, "dev", "shd", "server-1", &model.Tag{ConfigIDs: "212,260", Mark: "test", Operator: "zjx"})
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
}
|
21
app/admin/main/config/service/team.go
Normal file
21
app/admin/main/config/service/team.go
Normal file
@ -0,0 +1,21 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"go-common/app/admin/main/config/model"
|
||||
"go-common/library/log"
|
||||
)
|
||||
|
||||
// CreateTeam create App.
|
||||
func (s *Service) CreateTeam(name, env, zone string) error {
|
||||
app := &model.Team{Name: name, Env: env, Zone: zone}
|
||||
return s.dao.DB.Create(app).Error
|
||||
}
|
||||
|
||||
//TeamByName get team by Name.
|
||||
func (s *Service) TeamByName(name, env, zone string) (team *model.Team, err error) {
|
||||
team = &model.Team{}
|
||||
if err = s.dao.DB.FirstOrCreate(&team, &model.Team{Name: name, Env: env, Zone: zone}).Error; err != nil {
|
||||
log.Error("TeamByName() error(%v)", err)
|
||||
}
|
||||
return
|
||||
}
|
Reference in New Issue
Block a user