Create & Init Project...

This commit is contained in:
2019-04-22 18:49:16 +08:00
commit fc4fa37393
25440 changed files with 4054998 additions and 0 deletions

22
app/admin/ep/melloi/BUILD Normal file
View File

@@ -0,0 +1,22 @@
package(default_visibility = ["//visibility:public"])
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//app/admin/ep/melloi/cmd:all-srcs",
"//app/admin/ep/melloi/conf:all-srcs",
"//app/admin/ep/melloi/dao:all-srcs",
"//app/admin/ep/melloi/http:all-srcs",
"//app/admin/ep/melloi/model:all-srcs",
"//app/admin/ep/melloi/service:all-srcs",
],
tags = ["automanaged"],
)

View File

@@ -0,0 +1,340 @@
##### ep-melloi
##### Version 1.9.7
1.业务断言支持
2.用户上传脚本默认生成场景类型报告
3.增加测试报告的开始和结束时间
4.修复场景脚本无法修改成功问题
5.紧急修复sceneId bug
6.key-value 容错
7.fmt
##### Version 1.9.6
1.压测审批通知增加依赖服务
2.修改服务bug
##### Version 1.9.5
1. 压测时间段走审批
##### Version 1.9.4
1.gRPC 自助压测页面支持保存
##### Version 1.9.3
1.支持permit配置超时
2.配合caster 新增容器修改
##### Version 1.9.2
1.压测执行代码重构
2.重新合master
##### Version 1.9.1
1.上传脚本压测功能
2.添加cookie
##### Version 1.9.0
1.压测熔断提示后端
2.script 局部更新
##### Version 1.8.10
1.删除咸鱼容器
##### Version 1.8.9
1.新增定时器功能
##### Version 1.8.8
1.场景压测自助压测及我的脚本中,均支持熔断成功率的配置
##### Version 1.8.7
1.remove mail password
2.alter wechat notify content
##### Version 1.8.6
1.对加压逻辑改造,压测停止后,没添加的容器的不再添加
2.优化平均响应时间统计算法
##### Version 1.8.5
1.场景脚本排序逻辑调整
2.添加ttp、grpc以及场景脚本的删除功能
##### Version 1.8.4
1.运行接口增加cookie
##### Version 1.8.3
1.微信通知增加依赖服务通知
2.微信群通知增加服务依赖
3.压测容器详情
##### Version 1.8.2
1.微信通知增加依赖服务通知
##### Version 1.8.1
1.压测接口url请求参数包含json格式时自动encode
2.修改脚本后保存时断言、数据文件删不掉的问题修复
##### Version 1.8.0
1. 增加 ping 功能和显示
2. 修复keepAlive 修改失败问题
3. 日志查询优化
##### Version 1.7.9
1. 添加grpc debug 标签
##### Version 1.7.8
1.强制删除容器修改为双层删除逻辑自身接口删除失败会调用paas接口来删除
##### Version 1.7.7
1. 多断言
2. 修复报告不更新问题
3. 删除main二进制文件
##### Version 1.7.6
1.首页bugfix&数据清洗
##### Version 1.7.5
1.场景压测支持绑定非默认172.22.22.222的其他ip
##### Version 1.7.4
1.修改grpc returnType 包含. 的问题
##### Version 1.7.3
1.场景复制功能
##### Version 1.7.2
1.强制删除容器不依赖caster平台
##### Version 1.7.1
1.melloi 服务树增加nil判断
##### Version 1.7.0
1.melloi首页统计、场景压测增加UT
##### Version 1.6.9
1.melloi部分代码增加UT
2.更新db.sql
3.report 更新策略优化
##### Version 1.6.8
1. 下载功能
##### Version 1.6.7
1. 对获取不到物理机ip 的容器 添加补偿机制
2. 解除查询job 限制
##### Version 1.6.6
1. http 压测增加301302 code
#### Version 1.6.5
1. 修复场景压测post接口编辑时不展示header和form的问题
2. 修复不同分组添加接口跑到同一组的问题
3. 修复场景接口 json 解析失败
4. 修复jmeter报的 json 错误
##### Version 1.6.4
1. url 解析错误提示
#### Version 1.6.3
1. 选择已有接口支持选择到服务树
##### Version 1.6.2
1. 场景脚本批量执行
##### Version 1.6.1
1. grpc 脚本详情支持白名单用户查看
#### Version 1.6.0
1. 场景名称支持输入中文,脚本路径命名调整
#### Version 1.5.9
1. 获取压测job容器所在的物理机ip并落地
##### Version 1.5.8
1. 批量增加容器
2. headers 和 argument-param 初始化
##### Version 1.5.7
1. 修复reportSummary 状态问题
##### Version 1.5.6
1. 获取压测job容器所在的物理机ip并落地
##### Version 1.5.5
1. 压测报告支持百分位显示
##### Version 1.5.4
1.获取压测job容器所在的物理机ip并落地
#### Version 1.5.3
1. 修复只显示queryFree 10 个的问题
2. 修改 sign
3. 增加 sign
##### Version 1.5.2
1.修复场景分组问题
2.hostinfo配置化
##### Version 1.5.1
1.域名支持绑定用户指定的非172.16.1.1的host
#### Version 1.5.0
1. 定义 script.TestType
##### Version 1.4.9
1.支持grpc复制功能
##### Version 1.4.8
1.解析grpc 支持 java_package
##### Version 1.4.7
1.首页压测次数统计增加压测类型维度
##### Version 1.4.6
1.首页优化支持grpc、场景相关数据统计
#### Version 1.4.5
1. defer close file
#### Version 1.4.4
1. 删除容器时更新测试报告状态
#### Version 1.4.3
1. 优化grpc执行代码
#### Version 1.4.2
1.修改grpc通知 压测人BUG
##### Version 1.4.1
1.调整grpc解析将 method aa_bb 转成 aaBb
####Version 1.4.0
1. 增加http 短连接配置
##### Version 1.3.9
1.添加压测配置查询接口
2.修复添加场景时草稿箱状态错误问题
##### Version 1.3.8
1. 场景模块上传数据文件改造
2. 批量停止压测优化
##### Version 1.3.7
1.支持场景上传数据文件
##### Version 1.3.6
1.场景压测删除草稿、清空草稿箱功能
##### Version 1.3.5
1.output_params 初始化
2.停止所有容器接口
##### Version 1.3.4
1.GRPC 更新bug修复支持上传新的文件
##### Version 1.3.3
1.支持压测熔断参数用户可配置
2.重构部分代码
##### Version 1.3.2
1.GRPC压测支持参数化
2.GRPC压测支持路径
##### Version 1.3.1
1.场景压测中编辑接口并保存后执行顺序问题修复
##### Version 1.3.0
1.修复生成多余的文件夹 和 jmx 文件
2.修复post 请求的 body 丢失问题
##### Version 1.2.9
1.修复场景压测未绑定容器host问题
##### Version 1.2.8
1. 场景 post 请求增加3个模板
2. 解决 参数依赖模块写入jmx 文件发生 html 转义问题
3. 修复修复输出参数兼容性引起的排序问题
##### Version 1.2.7
1.修复 quick-start 批量选择接口自动生成场景多余的 scene.jmx 文件问题
2.修复 script-list 批量选择接口生成场景的 script 表无 sceneId 问题
##### Version 1.2.6
1.接口输出参数新老数据兼容性处理
2.TestType配置化
3.可选参数列表bugfix
##### Version 1.2.5
1.修复单接口修改脚本的报错问题
##### Version 1.2.4
1.修复单接口调试、执行压测的502报错问题
##### Version 1.2.3
1.GRPC优化支持多个proto文件编译
2.GRPC 编译&执行分离
##### Version 1.2.2
1.场景压测输出参数结构调整
2.可用参数列表接口调整
3.排序逻辑调整
##### Version 1.2.1
1.修复拿服务树节点的bug
##### Version 1.2.0
1.接口之间多个参数依赖
2.Cpu 核心数配置化
##### Version 1.1.9
1.场景压测预览图接口开发,支持前端层级关系图模式
2.从草稿箱选择一个场景后,再选择已有接口,接口报错问题修复
3.部分接口查询条件添加有效数据的过滤条件
4.场景压测相关的bug修复
##### Version 1.1.8
1.修复根据id 查询报告bug
##### Version 1.1.7
1.修复脚本登录状态 和 异步压测脚本无法修改问题
2.压测快照增加 binary 信息和展示
3.场景脚本 debug 线程数优化
4.修复新用户登录404 bug
##### Version 1.1.6
1.整拖拽功能底层逻辑,配合前端
2.选择已有接口逻辑调整
3.场景压测增加预览图接口,支持层级关系图模式
4.一些接口的bug修复
##### Version 1.1.5
1.grpc 场景脚本查询增加白名单
2.压测时间段校验忽略白名单
3.修复 grpc 压测微信通知报告地址bug
4.脚本快照增加 post 请求的 multipart/form-data 类型
5.优化场景脚本生成逻辑
##### Version 1.1.4
1.场景压测调试
2.异步压测脚本修改
3.post IO 流请求脚本新增和修改
##### Version 1.1.3
1.将jmx模板路径放到配置文件
##### Version 1.1.2
1. 新增脚本详情页压测入口
2. http 异步压测脚本生成
3. grpc 异步压测脚本生成
##### Version 1.1.1
1. 修复程序占用大量内存和 cpu 问题
##### Version 1.1
1. 脚本复制,脚本修改
2. 压测微信通知,错误熔断
##### Version 1.0.0
1 自助压测填写接口、QPS、压测时长快速开始压测
2 自测报告,查询压测中以及压测完成的报告
3 手工压测填写压测申请由ep部门辅助进行压测
4 脚本列表,已创建成功的压测脚本,可选择重复执行
5 集群资源,查询压测机器资源利用情况

View File

@@ -0,0 +1,9 @@
# Owner
hujianping
gongmenglei
yuanmin
# Author
# Reviewer

View File

@@ -0,0 +1,12 @@
# See the OWNERS docs at https://go.k8s.io/owners
approvers:
- gongmenglei
- hujianping
- yuanmin
labels:
- admin
- admin/ep/melloi
- ep
options:
no_parent_owners: true

View File

@@ -0,0 +1,11 @@
# melloi
# 项目简介
melloi 自助平台压测系统
- 统一服务代码改动,频繁压测,压测人力不足,与大型活动压测需求并行时,难以保证及时响应日常压测需求。
- 压测服务器资源会变更为k8s统一调度形式随压测任务生成与销毁。
- 日常压测任务前置,将由开发自行调试压测脚本,并通过平台执行压测
Melloi会基于Caster/PaaS的底层资源提供压测环境的自助创建和销毁压测平台主要进行压测数据的管理和任务调度

View File

@@ -0,0 +1,46 @@
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 = [
"convey-test.toml",
"melloi-test.toml",
],
importpath = "go-common/app/admin/ep/melloi/cmd",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/admin/ep/melloi/conf:go_default_library",
"//app/admin/ep/melloi/http:go_default_library",
"//app/admin/ep/melloi/service:go_default_library",
"//library/ecode/tip: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"],
)

View File

@@ -0,0 +1,236 @@
# This is a TOML document. Boom
version = "1.0.0"
user = "nobody"
pid = "/tmp/melloi.pid"
dir = "./"
perf = "0.0.0.0:8884"
trace = false
debug = true
[tracer]
family = "melloi"
proto = "udp"
addr = "172.16.33.46:5140"
[PermitGRPC]
timeout = "500ms"
[serviceTree]
host ="http://easyst.bilibili.co"
[bfsConf]
host ="http://uat-bfs.bilibili.co"
[serviceCluster]
testHost="http://uat-caster.bilibili.co"
uatHost="http://uat-caster.bilibili.co"
queryJobCpuHost = "http://merak.bilibili.co"
[bm]
addr = "0.0.0.0:8881"
maxListen = 10000
timeout = "5s"
[identify]
whiteAccessKey = ""
whiteMid = 0
[identify.app]
key = "6a29f8ed87407c11"
secret = "d3c5a85f5b895a03735b5d20a273bc57"
[identify.memcache]
name = "go-business/identify"
proto = "tcp"
addr = "172.16.33.54:11211"
active = 50
idle = 10
dialTimeout = "1s"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "80s"
[identify.host]
auth = "http://passport.bilibili.com"
secret = "http://open.bilibili.com"
[identify.httpClient]
key = "f022126a8a365e20"
secret = "b7b86838145d634b487e67b811b8fab2"
dial = "30ms"
timeout = "100ms"
keepAlive = "60s"
[identify.httpClient.breaker]
window = "10s"
sleep = "100ms"
bucket = 10
ratio = 0.5
request = 100
[identify.httpClient.url]
"http://passport.bilibili.co/intranet/auth/tokenInfo" = {timeout = "100ms"}
"http://passport.bilibili.co/intranet/auth/cookieInfo" = {timeout = "100ms"}
"http://open.bilibili.co/api/getsecret" = {timeout = "500ms"}
[managerAuth]
servicetreeHost = "http://easyst.bilibili.co"
dashboardHost = "http://dashboard-mng.bilibili.co"
dashboardCaller = "melloi"
[managerAuth.memcache]
name = "go-business/auth"
proto = "tcp"
addr = "172.16.33.54:11211"
idle = 5
active = 10
dialTimeout = "1s"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "10s"
expire = "1h"
[managerAuth.dsHTTPClient]
key = "melloi"
secret = "d3c5a85f5b895a03735b5d20a273bc57"
dial = "2s"
timeout = "3s"
keepAlive = "60s"
timer = 1000
[managerAuth.dsHTTPClient.breaker]
window ="3s"
sleep ="200ms"
bucket = 10
ratio = 0.5
request = 100
[managerAuth.stHTTPClient]
key = "melloi"
secret = "d3c5a85f5b895a03735b5d20a273bc57"
dial = "2s"
timeout = "3s"
keepAlive = "60s"
timer = 1000
[managerAuth.stHTTPClient.breaker]
window ="3s"
sleep ="100ms"
bucket = 10
ratio = 0.5
request = 100
[redis]
name = "melloi"
proto = "tcp"
addr = ""
idle = 10
active = 10
dialTimeout = "1s"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "10s"
expire = "1m"
[httpClient]
key = "c05dd4e1638a8af0"
secret = "7daa7f8c06cd33c5c3067063c746fdcb"
dial = "2s"
timeout = "10s"
keepAlive = "60s"
timer = 1000
[httpClient.breaker]
window = "10s"
sleep = "2000ms"
bucket = 10
ratio = 0.5
request = 100
[memcache]
name = "melloi"
proto = "tcp"
addr = "172.18.33.61:11232"
active = 50
idle = 10
dialTimeout = "1s"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "10s"
expire = "24h"
[orm]
dsn = "root:root@tcp(172.22.33.22:3306)/test?timeout=200ms&readTimeout=200ms&writeTimeout=200ms&parseTime=true&loc=Local&charset=utf8,utf8mb4"
active = 5
idle = 5
idleTimeout = "4h"
[permit]
[permit.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"
[melloi]
apiToken="sfy3gGVkX19XQrg1NBksyt7zZQo692Mmnctq"
platformID="melloi"
businessUnit="test"
project= "ep"
app= "melloi-launch"
env= "dev"
image= "docker-reg.bilibili.co/jmeter4.0"
imageVersion="4.0"
volumes="/data/jmeter-log:/data/jmeter-log:RW"
resourcePoolId="7"
completions=1
retriesLimit=6
networkId=22
clusterId=1
treeId=39400
hostInfo=""
action="GetCurrentPromData"
publicKey="9c178e51a7d4dc8aa1dbef0c790b06e7574c4d0etracehubtuhui@bilibili.com"
signature=1
dataSource="docker"
query="job:cpu_used_total{container_env_app_id=~'test.ep.melloi-launch', container_env_deploy_env='dev',container_env_pod_name='{{.JobNamed}}'} / job:cpu_core_total{container_env_app_id=~'test.ep.melloi-launch', container_env_deploy_env='dev',container_env_pod_name='{{.JobNamed}'}"
appkeyProd="2cc31960f9bffa4e"
secretProd="9011a2ba8eb7ab7e5d43fcbc7cca8aff"
appkeyUat="4daf6715162cb3a6"
secretUat="6317d22e47d49f36c1c5ce1f4791650f"
executor=["gongmenglei","chenmeng","hujianping","yuanmin","maojian","hukai"]
checkTime=false
defaultHost="172.16.1.1"
maxFileSize=1638400
maxDowloadSize = 8192000
[wechat]
wechatHost="http://172.16.63.43:8000"
chatid="wuweitest"
msgtype="text"
safe=0
senMessage=true
[mail]
host = "smtp.exmail.qq.com"
port = 465
username = "melloi@bilibili.com"
password = "TestEP20180624"
noticeOwner = ["hujianping@bilibili.com"]
[BFSBucket]
keyID="t18aomj1b1k6plhn"
keySecret="v9j7hzvwfqwy7bb5bk9hvq35pxqnpp"
[jmeter]
jmeterExtLibPath="/opt/apache-jmeter-4.0/lib/ext"
jmeterExtLibPathContainer = "/mnt/storage00/bperf_test/gongmenglei/home/apache-jmeter-4.0/lib/ext/"
grpcTemplatePath = "/data/peter/melloi/test/ep/melloi/grpc.jmx"
testTimeLimit = 1800
threadGroupPort = 8881
jmeterScUcodedTmp = "D:\\ptzy_www_urlencoded.jmx"
jmeterScTmp = "D:\\ptzy.jmx"
jmeterSampleTmp = "D:\\jmeterSample.jmx"
jmeterSamplePostTmp = "D:\\jmeterSamplePost.jmx"
jmeterThGroupTmp = "D:\\ThreadGroup.jmx"
jmeterThGroupPostTmp = "D:\\ThreadGroupPost.jmx"
jmeterThGroupDuliTmp = "D:\\ThreadGroupDuli.jmx"
jmeterThGroupPostDuliTmp = "D:\\ThreadGroupPostDuli.jmx"
jmeterSceneTmp = "D:\\jmeterScene.jmx"
JSONExtractorTmp = "D:\\JSONExtractor.jmx"
[grpc]
protoJavaPluginPath = "/opt/protoc-gen-grpc-java-1.15.1-linux-x86_64.exe"

View File

@@ -0,0 +1,54 @@
package main
import (
"flag"
"os"
"os/signal"
"syscall"
"time"
"go-common/app/admin/ep/melloi/conf"
"go-common/app/admin/ep/melloi/http"
"go-common/app/admin/ep/melloi/service"
ecode "go-common/library/ecode/tip"
"go-common/library/log"
)
const (
_durationForClosingServer = 2000
)
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("melloi start")
// ecode init
ecode.Init(conf.Conf.Ecode)
// service init
s := service.New(conf.Conf)
http.Init(conf.Conf, s)
// init pprof conf.Conf.Perf
// init signal
c := make(chan os.Signal, 1)
signal.Notify(c, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT)
for {
si := <-c
log.Info("melloi get a signal %s", si.String())
switch si {
case syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT:
log.Info("melloi exit")
s.Close()
time.Sleep(_durationForClosingServer)
return
case syscall.SIGHUP:
default:
return
}
}
}

View File

@@ -0,0 +1,250 @@
# This is a TOML document. Boom
version = "1.0.0"
user = "nobody"
pid = "/tmp/melloi.pid"
dir = "./"
perf = "0.0.0.0:8884"
trace = false
debug = true
[log]
dir = "D:\\melloi_log"
stdout = true
[tracer]
family = "melloi"
proto = "udp"
addr = "172.16.33.46:5140"
[dapper]
host ="http://api.bilibili.co"
[PermitGRPC]
timeout = "500ms"
[serviceTree]
host ="http://easyst.bilibili.co"
[bfsConf]
host ="http://uat-bfs.bilibili.co"
[serviceCluster]
testHost="http://uat-caster.bilibili.co"
uatHost="http://uat-caster.bilibili.co"
queryJobCpuHost = "http://merak.bilibili.co"
[bm]
addr = "0.0.0.0:8881"
maxListen = 10000
timeout = "5s"
[identify]
whiteAccessKey = ""
whiteMid = 0
[identify.app]
key = "6a29f8ed87407c11"
secret = "d3c5a85f5b895a03735b5d20a273bc57"
[identify.memcache]
name = "go-business/identify"
proto = "tcp"
addr = "172.16.33.54:11211"
active = 50
idle = 10
dialTimeout = "1s"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "80s"
[identify.host]
auth = "http://passport.bilibili.com"
secret = "http://open.bilibili.com"
[identify.httpClient]
key = "f022126a8a365e20"
secret = "b7b86838145d634b487e67b811b8fab2"
dial = "30ms"
timeout = "100ms"
keepAlive = "60s"
[identify.httpClient.breaker]
window = "10s"
sleep = "100ms"
bucket = 10
ratio = 0.5
request = 100
[identify.httpClient.url]
"http://passport.bilibili.co/intranet/auth/tokenInfo" = {timeout = "100ms"}
"http://passport.bilibili.co/intranet/auth/cookieInfo" = {timeout = "100ms"}
"http://open.bilibili.co/api/getsecret" = {timeout = "500ms"}
[managerAuth]
servicetreeHost = "http://easyst.bilibili.co"
dashboardHost = "http://dashboard-mng.bilibili.co"
dashboardCaller = "melloi"
[managerAuth.memcache]
name = "go-business/auth"
proto = "tcp"
addr = "172.16.33.54:11211"
idle = 5
active = 10
dialTimeout = "1s"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "10s"
expire = "1h"
[managerAuth.dsHTTPClient]
key = "melloi"
secret = "d3c5a85f5b895a03735b5d20a273bc57"
dial = "2s"
timeout = "3s"
keepAlive = "60s"
timer = 1000
[managerAuth.dsHTTPClient.breaker]
window ="3s"
sleep ="200ms"
bucket = 10
ratio = 0.5
request = 100
[managerAuth.stHTTPClient]
key = "melloi"
secret = "d3c5a85f5b895a03735b5d20a273bc57"
dial = "2s"
timeout = "3s"
keepAlive = "60s"
timer = 1000
[managerAuth.stHTTPClient.breaker]
window ="3s"
sleep ="100ms"
bucket = 10
ratio = 0.5
request = 100
[redis]
name = "melloi"
proto = "tcp"
addr = ""
idle = 10
active = 10
dialTimeout = "1s"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "10s"
expire = "1m"
[httpClient]
key = "c05dd4e1638a8af0"
secret = "7daa7f8c06cd33c5c3067063c746fdcb"
dial = "2s"
timeout = "10s"
keepAlive = "60s"
timer = 1000
[httpClient.breaker]
window = "10s"
sleep = "2000ms"
bucket = 10
ratio = 0.5
request = 100
[memcache]
name = "melloi"
proto = "tcp"
addr = "172.18.33.61:11232"
active = 50
idle = 10
dialTimeout = "1s"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "10s"
expire = "24h"
[orm]
dsn = "root:root@tcp(172.22.33.22:3306)/test?timeout=200ms&readTimeout=200ms&writeTimeout=200ms&parseTime=true&loc=Local&charset=utf8,utf8mb4"
active = 5
idle = 5
idleTimeout = "4h"
[permit]
[permit.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"
[paas]
apiToken="sfy3gGVkX19XQrg1NBksyt7zZQo692Mmnctq"
platformID="melloi"
businessUnit="test"
project= "ep"
app= "melloi-launch"
env= "dev"
image= "docker-reg.bilibili.co/jmeter4.0"
imageVersion="4.0"
volumes="/data/jmeter-log:/data/jmeter-log:RW"
resourcePoolId="7"
completions=1
retriesLimit=6
networkId=22
clusterId=1
treeId=39400
hostInfo=""
action="GetCurrentPromData"
publicKey="9c178e51a7d4dc8aa1dbef0c790b06e7574c4d0etracehubtuhui@bilibili.com"
signature=1
dataSource="docker"
query="job:cpu_used_total{container_env_app_id=~'test.ep.melloi-launch', container_env_deploy_env='dev',container_env_pod_name='{{.JobNamed}}'} / job:cpu_core_total{container_env_app_id=~'test.ep.melloi-launch', container_env_deploy_env='dev',container_env_pod_name='{{.JobNamed}'}"
[melloi]
appkeyProd="2cc31960f9bffa4e"
secretProd="9011a2ba8eb7ab7e5d43fcbc7cca8aff"
appkeyUat="4daf6715162cb3a6"
secretUat="6317d22e47d49f36c1c5ce1f4791650f"
executor=["gongmenglei","chenmeng","hujianping","yuanmin","maojian","hukai"]
checkTime=false
defaultHost="172.22.22.222"
maxFileSize=1638400
maxDowloadSize = 8192000
recent = 4
[wechat]
wechatHost="http://172.16.63.43:8000"
chatid="wuweitest"
msgtype="text"
safe=0
senMessage=true
[mail]
host = "smtp.exmail.qq.com"
port = 465
username = "melloi@bilibili.com"
password = "*******"
noticeOwner = ["hujianping@bilibili.com"]
[BFSBucket]
keyID="t18aomj1b1k6plhn"
keySecret="v9j7hzvwfqwy7bb5bk9hvq35pxqnpp"
[jmeter]
jmeterExtLibPath="/opt/apache-jmeter-4.0/lib/ext"
jmeterExtLibPathContainer = "/mnt/storage00/bperf_test/gongmenglei/home/apache-jmeter-4.0/lib/ext/"
grpcTemplatePath = "/data/peter/melloi/test/ep/melloi/grpc.jmx"
testTimeLimit = 1800
jmeterScUcodedTmp = "D:\\work\\EP\\Melloi\\ptzy_www_urlencoded.jmx"
jmeterScTmp = "D:\\work\\EP\\Melloi\\ptzy.jmx"
jmeterSampleTmp = "D:\\work\\EP\\Melloi\\jmeterSample.jmx"
jmeterSamplePostTmp = "D:\\work\\EP\\Melloi\\jmeterSamplePost.jmx"
jmeterThGroupTmp = "D:\\work\\EP\\Melloi\\ThreadGroup.jmx"
jmeterThGroupPostTmp = "D:\\work\\EP\\Melloi\\ThreadGroupPost.jmx"
jmeterThGroupDuliTmp = "D:\\work\\EP\\Melloi\\ThreadGroupDuli.jmx"
jmeterThGroupPostDuliTmp = "D:\\work\\EP\\Melloi\\ThreadGroupPostDuli.jmx"
jmeterSceneTmp = "D:\\work\\EP\\Melloi\\jmeterScene.jmx"
JSONExtractorTmp = "D:\\work\\EP\\Melloi\\JSONExtractor.jmx"
[grpc]
protoJavaPluginPath = "/opt/protoc-gen-grpc-java-1.15.1-linux-x86_64.exe"
[dockerStatus]
host = "http://172.22.33.22"
port = 8999

View File

@@ -0,0 +1,42 @@
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/ep/melloi/conf",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/admin/ep/melloi/model:go_default_library",
"//library/cache/memcache:go_default_library",
"//library/cache/redis:go_default_library",
"//library/conf:go_default_library",
"//library/database/orm:go_default_library",
"//library/ecode/tip: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/warden:go_default_library",
"//library/net/trace: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"],
)

View File

@@ -0,0 +1,193 @@
package conf
import (
"errors"
"flag"
"go-common/app/admin/ep/melloi/model"
"go-common/library/cache/memcache"
"go-common/library/cache/redis"
"go-common/library/conf"
"go-common/library/database/orm"
ecode "go-common/library/ecode/tip"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/http/blademaster/middleware/permit"
"go-common/library/net/rpc/warden"
"go-common/library/net/trace"
"github.com/BurntSushi/toml"
)
var (
confPath string
client *conf.Client
// Conf config
Conf = &Config{}
)
// Config .
type Config struct {
Log *log.Config
//BM *HTTPServers
Tracer *trace.Config
Redis *redis.Config
Memcache *memcache.Config
Ecode *ecode.Config
ORM *orm.Config
Permit *permit.Config2
PermitGRPC *warden.ClientConfig
HTTPClient *bm.ClientConfig
ServiceTree *model.TreeConf
Dapper *Dapper
BfsConf *model.BFSConf
ServiceCluster *model.ClusterConf
Melloi *Melloi
BM *bm.ServerConfig
Wechat *Wechat
Mail *Mail
Paas *Paas
Grpc *Grpc
Jmeter *Jmeter
DockerStatus *DockerStatus
}
// Dapper conf
type Dapper struct {
Host string
}
// DockerStatus conf
type DockerStatus struct {
Host string // ip
Port int // port
}
//Paas conf
type Paas struct {
APIToken string // PaaS token获取
PlatformID string //PaaS token获取
BusinessUnit string //BU
Project string //项目
App string //应用
Env string //环境
Image string //镜像名称
ImageVersion string //镜像版本
Volumes string //PaaS 创建job
ResourcePoolID string //PaaS 创建job
Completions int //PaaS 创建job
RetriesLimit int //PaaS 创建job
NetworkID int
ClusterID int
TreeID int //服务树ID
HostInfo string //PaaS 创建job
Action string //paas 查询容器cpu
PublicKey string //key
Signature int //paas 查询容器cpu
DataSource string //数据源
Query string //paas 查询容器cpu语句
CPUCore int //cpu 核数
CPUCoreDebug int //debug cpu 核数
}
//Melloi melloi config
type Melloi struct {
AppkeyProd string //线上appkey
SecretProd string //线上sceret
AppkeyUat string //uat appkey
SecretUat string //uat secret
Executor []string //白名单
CheckTime bool //是否校验压测时间
MaxFileSize int64
DefaultHost string
MaxDowloadSize int64
DefaultFusing int //默认熔断成功率
DefaultBusinessRate int //默认业务熔断阈值
Recent int //最近的qps取数
}
//Wechat wechat config
type Wechat struct {
Host string //微信通知id
Chatid string
Msgtype string
Safe int
SendMessage bool //是否发送通知
}
// Mail mail
type Mail struct {
Host string
Port int
Username string
Password string
NoticeOwner []string
}
// Grpc grpc
type Grpc struct {
ProtoJavaPluginPath string
}
// Jmeter jmeter
type Jmeter struct {
JmeterExtLibPath string
JmeterExtLibPathContainer string
GRPCTemplatePath string
TestTimeLimit int
ThreadGroupPort int //执行生成线程组的接口的端口号
JmeterScUcodedTmp string
JmeterScTmp string
JmeterSampleTmp string
JmeterSamplePostTmp string
JmeterThGroupTmp string
JmeterThGroupPostTmp string
JmeterThGroupDuliTmp string
JmeterThGroupPostDuliTmp string
JmeterSceneTmp string
JSONExtractorTmp string
}
// init init
func init() {
flag.StringVar(&confPath, "conf", "", "default config path")
}
// Init init conf
func Init() error {
if confPath != "" {
return local()
}
return remote()
}
// local local
func local() (err error) {
_, err = toml.DecodeFile(confPath, &Conf)
return
}
// remote remote
func remote() (err error) {
if client, err = conf.New(); err != nil {
return
}
return load()
}
// load load
func load() (err error) {
var (
s string
ok bool
tmpConf *Config
)
if s, ok = client.Value("melloi.toml"); !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
}

View File

@@ -0,0 +1,89 @@
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",
"order_admin_test.go",
"order_test.go",
"rank_test.go",
"scene_test.go",
"user_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/admin/ep/melloi/conf:go_default_library",
"//app/admin/ep/melloi/model:go_default_library",
"//vendor/github.com/go-sql-driver/mysql: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 = [
"apply.go",
"bfs.go",
"clientmoni.go",
"cluster.go",
"comment.go",
"dao.go",
"dapper.go",
"job.go",
"label.go",
"mail.go",
"mysql_grpc.go",
"mysql_grpc_snap.go",
"order.go",
"order_admin.go",
"order_report.go",
"ptestjob.go",
"rank.go",
"report.go",
"reportgraph.go",
"scene.go",
"script.go",
"tree.go",
"user.go",
"wechat.go",
],
importpath = "go-common/app/admin/ep/melloi/dao",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/admin/ep/melloi/conf:go_default_library",
"//app/admin/ep/melloi/model:go_default_library",
"//library/cache/memcache: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",
"//library/stat/prom:go_default_library",
"//vendor/github.com/jinzhu/gorm:go_default_library",
"//vendor/github.com/pkg/errors:go_default_library",
"//vendor/gopkg.in/gomail.v2: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"],
)

View File

@@ -0,0 +1,46 @@
package dao
import (
"go-common/app/admin/ep/melloi/model"
)
// QueryApply query apply list
func (d *Dao) QueryApply(apply *model.Apply, pn, ps int32) (qar *model.QueryApplyResponse, err error) {
qar = &model.QueryApplyResponse{}
err = d.DB.Table(model.Apply{}.TableName()).Where(model.Apply{
ID: apply.ID, From: apply.From, To: apply.To, Status: apply.Status, Active: model.ApplyValid}).
Count(&qar.TotalSize).Offset((pn - 1) * ps).Limit(ps).Order("id desc").Find(&qar.ApplyList).Error
qar.PageSize = ps
qar.PageNum = pn
return
}
// QueryUserApplyList query user apply list
func (d *Dao) QueryUserApplyList(userName string) (applyList []*model.Apply, err error) {
applyList = []*model.Apply{}
err = d.DB.Table(model.Apply{}.TableName()).Where("`from`=?", userName).
Where("`active`=?", 1).Where("`status`=?", model.ApplyValid).Find(&applyList).Error
return
}
//QueryApplyByID query apply by id
func (d *Dao) QueryApplyByID(id int64) (apply *model.Apply, err error) {
apply = &model.Apply{}
err = d.DB.Table(model.Apply{}.TableName()).Where("id = ?", id).First(apply).Error
return
}
//AddApply add apply
func (d *Dao) AddApply(apply *model.Apply) error {
return d.DB.Model(&model.Apply{}).Create(apply).Error
}
// UpdateApply update apply info
func (d *Dao) UpdateApply(apply *model.Apply) error {
return d.DB.Model(&model.Apply{}).Updates(apply).Where("ID=?", apply.ID).Error
}
// DeleteApply delete apply info
func (d *Dao) DeleteApply(id int64) error {
return d.DB.Model(&model.Apply{}).Where("ID=?", id).Update("active", model.ApplyInvalid).Error
}

View File

@@ -0,0 +1,102 @@
package dao
import (
"bytes"
"context"
"crypto/hmac"
"crypto/sha1"
"encoding/base64"
"fmt"
"hash"
"net/http"
"strconv"
"time"
"go-common/library/ecode"
"go-common/library/log"
)
const (
_bucketName = "melloi"
_melloiURI = "/bfs/" + _bucketName
)
// UploadImg upload img
func (d *Dao) UploadImg(c context.Context, imgContent []byte, imgName string) (location string, err error) {
var (
req *http.Request
reqURL = d.c.BfsConf.Host + _melloiURI + "/" + imgName
resp *http.Response
code int
)
buf := new(bytes.Buffer)
if _, err = buf.Write(imgContent); err != nil {
log.Error("Upload.buf.Write.error(%v)", err)
return
}
if req, err = http.NewRequest("PUT", reqURL, buf); err != nil {
err = ecode.RequestErr
return
}
authorization := d.Authorize(d.c.BfsConf.AccessKey, d.c.BfsConf.AccessSecret, http.MethodPut, _bucketName, imgName, time.Now().Unix())
req.Header.Set("Authorization", authorization)
req.Header.Set("Content-Type", "image/png")
if resp, err = d.client.Do(req); err != nil {
log.Error("Upload.client.Do.error(%v)", err)
return
}
defer resp.Body.Close()
switch resp.StatusCode {
case http.StatusOK:
case http.StatusBadRequest:
err = ecode.RequestErr
return
case http.StatusUnauthorized:
// 验证不通过
err = ecode.BfsUploadAuthErr
return
case http.StatusRequestEntityTooLarge:
err = ecode.FileTooLarge
return
case http.StatusNotFound:
err = ecode.NothingFound
return
case http.StatusMethodNotAllowed:
err = ecode.MethodNotAllowed
return
case http.StatusServiceUnavailable:
err = ecode.BfsUploadServiceUnavailable
return
case http.StatusInternalServerError:
err = ecode.ServerErr
return
default:
err = ecode.BfsUploadStatusErr
return
}
if code, err = strconv.Atoi(resp.Header.Get("code")); err != nil || code != 200 {
err = ecode.BfsUploadCodeErr
return
}
location = resp.Header.Get("location")
return
}
// Authorize .
func (d *Dao) Authorize(key, secret, method, bucket, fileName string, expire int64) (authorization string) {
var (
content string
mac hash.Hash
signature string
)
content = fmt.Sprintf("%s\n%s\n%s\n%d\n", method, bucket, fileName, expire)
mac = hmac.New(sha1.New, []byte(secret))
mac.Write([]byte(content))
signature = base64.StdEncoding.EncodeToString(mac.Sum(nil))
authorization = fmt.Sprintf("%s:%s:%d", key, signature, expire)
return
}

View File

@@ -0,0 +1,16 @@
package dao
import "go-common/app/admin/ep/melloi/model"
//AddClientMoni add ClientMoni
func (d *Dao) AddClientMoni(clientMoni *model.ClientMoni) (clientMoniID int, err error) {
err = d.DB.Create(clientMoni).Error
clientMoniID = clientMoni.ID
return
}
//QueryClientMoni query ClientMoni
func (d *Dao) QueryClientMoni(clientMoni *model.ClientMoni) (clm []*model.ClientMoni, err error) {
err = d.DB.Table(model.ClientMoni{}.TableName()).Where(clientMoni).Find(&clm).Error
return
}

View File

@@ -0,0 +1,70 @@
package dao
import (
"context"
"net/http"
"go-common/app/admin/ep/melloi/conf"
"go-common/app/admin/ep/melloi/model"
"go-common/library/ecode"
"go-common/library/log"
)
const (
_rmTokenURI = "/api/v1/auth"
_clusterNodeURI = "/api/v1/clusters?env=uat"
)
//RmToken get PaaS token
func (d *Dao) RmToken(c context.Context) (token string, err error) {
var (
req *http.Request
tokenURL = d.c.ServiceCluster.TestHost + _rmTokenURI
res = &model.ClusterRmTokenResponse{}
rmTokenPost = &model.RmTokenPost{
APIToken: conf.Conf.Paas.APIToken,
PlatformID: conf.Conf.Paas.PlatformID,
}
)
if req, err = d.newRequest(http.MethodPost, tokenURL, rmTokenPost); err != nil {
log.Error("query paas machine url(%s) err(%v)", tokenURL, err)
return
}
if err = d.httpClient.Do(c, req, &res); err != nil {
log.Error("RmToken error :(%v)", err)
err = ecode.MelloiPaasRequestErr
return
}
if err = res.CheckStatus(); err != nil {
return
}
token = res.Data.Token
return
}
//NetInfo get melloi server use
func (d *Dao) NetInfo(c context.Context, token string) (cluster []*model.ClusterResponseItemsSon, err error) {
var (
url = d.c.ServiceCluster.UatHost + _clusterNodeURI
req *http.Request
resCluster = &model.ClusterResponse{}
)
if req, err = d.newRequest(http.MethodGet, url, nil); err != nil {
return
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-Authorization-Token", token)
if err = d.httpClient.Do(c, req, &resCluster); err != nil {
log.Error("d.Token url(%s) res($s) err(%v)", url, err)
err = ecode.MelloiPaasRequestErr
return
}
if err = resCluster.CheckStatus(); err != nil {
return
}
cluster = resCluster.Data.Items
return
}

View File

@@ -0,0 +1,30 @@
package dao
import (
"go-common/app/admin/ep/melloi/model"
)
//AddComment add comment for performance test task
func (d *Dao) AddComment(comment *model.Comment) error {
//comment.Status = 1
return d.DB.Table(model.Comment{}.TableName()).Create(comment).Error
}
//QueryComment query comment
func (d *Dao) QueryComment(comment *model.Comment) (res *model.QueryCommentResponse, err error) {
res = &model.QueryCommentResponse{}
//comment.Status = 1
err = d.DB.Table(model.Comment{}.TableName()).Where(comment).Count(&res.Total).Order("id desc").Find(&res.Comments).Error
return
}
//UpdateComment update comment
func (d *Dao) UpdateComment(comment *model.Comment) error {
//return d.DB.Table(model.Comment{}.TableName()).Update(comment).Where("ID=?", comment.ID).Error
return d.DB.Model(&model.Comment{}).Update(comment).Where("ID=?", comment.ID).Error
}
//DeleteComment delete comment
func (d *Dao) DeleteComment(id int64) error {
return d.DB.Model(&model.Comment{}).Where("ID=?", id).Update("status", 2).Error
}

View File

@@ -0,0 +1,79 @@
package dao
import (
"bytes"
"context"
"encoding/json"
"net/http"
"go-common/app/admin/ep/melloi/conf"
"go-common/library/cache/memcache"
"go-common/library/database/orm"
"go-common/library/log"
xhttp "go-common/library/net/http/blademaster"
"go-common/library/stat/prom"
"github.com/jinzhu/gorm"
"gopkg.in/gomail.v2"
)
// Prometheus
var (
errorsCount = prom.BusinessErrCount
)
// Dao dao
type Dao struct {
c *conf.Config
DB *gorm.DB
httpClient *xhttp.Client
client *http.Client
MC *memcache.Pool
email *gomail.Dialer
}
// New init mysql db
func New(c *conf.Config) (dao *Dao) {
dao = &Dao{
c: c,
httpClient: xhttp.NewClient(c.HTTPClient),
email: gomail.NewDialer(c.Mail.Host, c.Mail.Port, c.Mail.Username, c.Mail.Password),
client: new(http.Client),
DB: orm.NewMySQL(c.ORM),
MC: memcache.NewPool(c.Memcache),
}
return
}
// Ping verify server is ok.
func (d *Dao) Ping(c context.Context) (err error) {
if err = d.DB.DB().Ping(); err != nil {
log.Error("dao.cloudDB.Ping() error(%v)", err)
return
}
return
}
func (d *Dao) newRequest(method, url string, v interface{}) (req *http.Request, err error) {
body := &bytes.Buffer{}
if method != http.MethodGet {
if err = json.NewEncoder(body).Encode(v); err != nil {
log.Error("json encode value(%s), error(%v) ", v, err)
return
}
}
if req, err = http.NewRequest(method, url, body); err != nil {
log.Error("http new request url(%s), error(%v)", url, err)
}
return
}
// PromError prom error
func PromError(name string) {
errorsCount.Incr(name)
}
// Close close the resource.
func (d *Dao) Close() {
d.DB.Close()
}

View File

@@ -0,0 +1,30 @@
package dao
import (
"context"
"flag"
"path/filepath"
"go-common/app/admin/ep/melloi/conf"
_ "github.com/go-sql-driver/mysql"
"gopkg.in/h2non/gock.v1"
)
var (
d *Dao
c context.Context
)
func init() {
dir, _ := filepath.Abs("../cmd/convey-test.toml")
flag.Set("conf", dir)
conf.Init()
d = New(conf.Conf)
d.httpClient.SetTransport(gock.DefaultTransport)
c = ctx()
}
func ctx() context.Context {
return context.Background()
}

View File

@@ -0,0 +1,48 @@
package dao
import (
"context"
"net/http"
"go-common/app/admin/ep/melloi/model"
"go-common/library/ecode"
"go-common/library/log"
)
const (
_dapperDependUri = "/x/internal/dapper/service-depend?service_name="
_dapperRspCode = 0
)
// QueryServiceDepend query service depend
func (d *Dao) QueryServiceDepend(c context.Context, serviceName string) (ret []string, err error) {
var (
req *http.Request
DependURL = d.c.Dapper.Host + _dapperDependUri + serviceName
res struct {
Code int `json:"code"`
Data *model.DependResponse `json:"data"`
Message string `json:"message"`
}
)
if req, err = d.newRequest(http.MethodGet, DependURL, nil); err != nil {
return
}
if err = d.httpClient.Do(c, req, &res); err != nil {
log.Error("d.Depend url(%s) res($s) error(%v)", DependURL, res, err)
return
}
if res.Code != _dapperRspCode {
err = ecode.MelloiTreeRequestErr
log.Error("d.Tree.Response url(%s) resCode(%s) error(%v)", DependURL, res.Code, err)
return
}
for _, item := range res.Data.Items {
ret = append(ret, item.ServiceName)
}
return
}

View File

@@ -0,0 +1,226 @@
package dao
import (
"context"
"encoding/json"
"fmt"
"net/http"
"strings"
"go-common/app/admin/ep/melloi/conf"
"go-common/app/admin/ep/melloi/model"
"go-common/library/ecode"
"go-common/library/log"
)
const (
_rmJob = "/api/rm/job"
_jobNodeURI = "/api/rm/jobs"
statsPort = "8999"
statsPath = "/ep/docker/stats"
_clearableDockers = "/ep/docker/get"
_dockerKeyword = "run"
)
//AddJob add perf job
func (d *Dao) AddJob(c context.Context, token string, jobInfo *model.Job) (cluster *model.PaasJobResponse, err error) {
var (
url = d.c.ServiceCluster.TestHost + _jobNodeURI
req *http.Request
passDetail []byte
)
paasJobDetail := &model.PaasJobDetail{
BusinessUnit: conf.Conf.Paas.BusinessUnit,
Project: conf.Conf.Paas.Project,
App: conf.Conf.Paas.App,
Env: conf.Conf.Paas.Env,
Name: jobInfo.Name,
Image: conf.Conf.Paas.Image,
ImageVersion: conf.Conf.Paas.ImageVersion,
Volumes: conf.Conf.Paas.Volumes,
CPURequest: jobInfo.CPU / 4,
CPULimit: jobInfo.CPU,
MemoryRequest: jobInfo.Memory,
Command: jobInfo.Command,
ResourcePoolID: conf.Conf.Paas.ResourcePoolID,
Parallelism: jobInfo.Parallelism,
Completions: conf.Conf.Paas.Completions,
RetriesLimit: conf.Conf.Paas.RetriesLimit,
NetworkID: conf.Conf.Paas.NetworkID,
ClusterID: conf.Conf.Paas.ClusterID,
TreeID: conf.Conf.Paas.TreeID,
HostInfo: conf.Conf.Paas.HostInfo,
EnvInfo: jobInfo.EnvInfo,
}
log.Info("Command:(%s)", paasJobDetail.Command)
if passDetail, err = json.Marshal(paasJobDetail); err != nil {
return
}
log.Info("passDetail:(%s)", string(passDetail))
if req, err = d.newRequest(http.MethodPost, url, paasJobDetail); err != nil {
return
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-Authorization-Token", token)
if err = d.httpClient.Do(c, req, &cluster); err != nil {
log.Error("d.AddJob url(%s) res($s) error(%v)", url, err)
return
}
return
}
//DeleteJob force stop perf job
func (d *Dao) DeleteJob(c context.Context, token, name string) (cluster *model.PaasJobResponse, err error) {
log.Info("删除job -------- token:(%s), job_name(%s) ", token, name)
var (
url = d.c.ServiceCluster.TestHost + _rmJob
req *http.Request
)
if req, err = d.newRequest(http.MethodDelete, url, nil); err != nil {
return
}
req.Header.Set("X-Authorization-Token", token)
q := req.URL.Query()
q.Add("business_unit", "test")
q.Add("project", "ep")
q.Add("app", "melloi-launch")
q.Add("env", "dev")
q.Add("name", name)
q.Add("cluster_id", "1")
q.Add("tree_id", "39400")
req.URL.RawQuery = q.Encode()
if err = d.httpClient.Do(c, req, &cluster); err != nil {
log.Error("d.Job url(%s) res($s) error(%v)", url, err)
err = ecode.MelloiPaasRequestErr
return
}
// 此处不return
if err = d.DeletePtestJobByJobName(name); err != nil {
log.Error("d.DeletePtestJobByJobName uerror(%v)", name)
}
return
}
// QueryCleanableDocker query clearable docker list
func (d *Dao) QueryCleanableDocker(c context.Context) (dockers []*model.CleanableDocker, err error) {
var (
url = fmt.Sprintf("%s:%d%s", d.c.DockerStatus.Host, d.c.DockerStatus.Port, _clearableDockers)
req *http.Request
bs []byte
result []string
)
if req, err = d.newRequest(http.MethodGet, url, nil); err != nil {
return
}
if bs, err = d.httpClient.Raw(c, req, ""); err != nil {
log.Error("d.job query clearable docker url(%s) error (%v)", url, err)
return
}
result = strings.Split(string(bs), "\n")
for _, item := range result {
var docker = &model.CleanableDocker{}
if strings.Contains(item, _dockerKeyword) {
docker.Name = item
dockers = append(dockers, docker)
}
}
return
}
//QueryJobCPU query job cpu status
func (d *Dao) QueryJobCPU(c context.Context, token, jobName string) (responseBody *model.PaasQueryJobCPUResult, err error) {
Query := strings.Replace(conf.Conf.Paas.Query, "JobNamed", jobName, -1)
var (
url = d.c.ServiceCluster.QueryJobCPUHost
req *http.Request
paasQueryJobPostCPUDetail = &model.PaasQueryJobCPUPostDetail{
Action: conf.Conf.Paas.Action,
PublicKey: conf.Conf.Paas.PublicKey,
Signature: conf.Conf.Paas.Signature,
DataSource: conf.Conf.Paas.DataSource,
Query: Query,
}
)
if req, err = d.newRequest(http.MethodPost, url, paasQueryJobPostCPUDetail); err != nil {
return
}
req.Header.Set("X-Authorization-Token", token)
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-Authorization-Token", token)
if err = d.httpClient.Do(c, req, &responseBody); err != nil {
log.Error("d.Job url(%s) res($s) error(%v)", url, err)
err = ecode.MelloiPaasRequestErr
return
}
return
}
//QueryJobCPUByEP query job cup by ep
func (d *Dao) QueryJobCPUByEP(c context.Context, id, hostIP string) (dokcerStats *model.DockerStats, err error) {
var (
req *http.Request
)
url := "http://" + hostIP + ":" + statsPort + statsPath
if req, err = d.newRequest(http.MethodGet, url, nil); err != nil {
return
}
q := req.URL.Query()
q.Add("id", id)
req.URL.RawQuery = q.Encode()
if err = d.httpClient.Do(c, req, &dokcerStats); err != nil {
log.Error("d.queryJobCPU By EP err : url(%s) error(%v)", url, err)
return
}
return
}
//Job get job info
func (d *Dao) Job(c context.Context, token, name string) (responseBody *model.PaasJobQueryStatus, err error) {
var (
url = d.c.ServiceCluster.TestHost + _rmJob
req *http.Request
)
if req, err = d.newRequest(http.MethodGet, url, nil); err != nil {
return
}
q := req.URL.Query()
q.Add("business_unit", "test")
q.Add("project", "ep")
q.Add("app", "melloi-launch")
q.Add("env", "dev")
q.Add("name", name)
q.Add("cluster_id", "1")
q.Add("tree_id", "39400")
req.Header.Set("X-Authorization-Token", token)
req.URL.RawQuery = q.Encode()
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-Authorization-Token", token)
if err = d.httpClient.Do(c, req, &responseBody); err != nil {
log.Error("d.Job url(%s) res($s) error(%v)", url, err)
err = ecode.MelloiPaasRequestErr
return
}
return
}
//ForceDeleteJob Force Delete Job
func (d *Dao) ForceDeleteJob(reportSuId int) (jobList *model.JobInfoList, err error) {
jobList = &model.JobInfoList{}
err = d.DB.Table("ptest_job").Select("host_ip, job_name").Where("report_su_id = ?", reportSuId).Find(&jobList.JobList).Error
return
}
//UpdateJobStatus Update Job Status
func (d *Dao) UpdateJobStatus(reportSuId int) (err error) {
if err = d.DB.Model(&model.PtestJob{}).Where("report_su_id = ?", reportSuId).Update("active", -1).Error; err != nil {
return
}
return d.DB.Table("report_summary").Where("id = ?", reportSuId).Update("test_status", 3).Error
}

View File

@@ -0,0 +1,76 @@
package dao
import (
"context"
"go-common/app/admin/ep/melloi/model"
)
// AddLabel add new label
func (d *Dao) AddLabel(label *model.Label) error {
return d.DB.Table(model.Label{}.LabelName()).Create(label).Error
}
// QueryLabels query all labels
func (d *Dao) QueryLabels(c context.Context) (labels []*model.Label, err error) {
err = d.DB.Table(model.Label{}.LabelName()).Where("active = ?", 1).Find(&labels).Error
return
}
// QueryLabel query label by label name and id
func (d *Dao) QueryLabel(lb *model.Label) (label *model.Label, err error) {
label = &model.Label{}
err = d.DB.Table(model.Label{}.LabelName()).Where("active = ?", 1).
Where(model.Label{Name: lb.Name, ID: lb.ID}).First(label).Error
return
}
// DeleteLabel delete label
func (d *Dao) DeleteLabel(id int64) error {
return d.DB.Table(model.Label{}.LabelName()).Where("id = ?", id).Update("active", 0).Error
}
// AddLabelRelation add label relation of target
func (d *Dao) AddLabelRelation(relation *model.LabelRelation) error {
return d.DB.Table(model.LabelRelation{}.LabelRelationName()).Create(relation).Error
}
// QueryLabelRelation query label relation
func (d *Dao) QueryLabelRelation(lre *model.LabelRelation) (lr []*model.LabelRelation, err error) {
err = d.DB.Table(model.LabelRelation{}.LabelRelationName()).
Where("active = ?", 1).
Where(model.LabelRelation{Type: lre.Type, LabelID: lre.LabelID, TargetID: lre.TargetID}).Find(&lr).Error
return
}
// QueryLabelRelationByIDs Query label relation by ids
func (d *Dao) QueryLabelRelationByIDs(ids []int64) (lr []*model.LabelRelation, err error) {
err = d.DB.Table(model.LabelRelation{}.LabelRelationName()).Where(" active = ? ", 1).
Where("id in (?)", ids).Find(lr).Error
return
}
// CheckLabelRelationExist check label relation exist
func (d *Dao) CheckLabelRelationExist(id int64) (result bool, err error) {
result = false
lr := &model.LabelRelation{}
err = d.DB.Table(model.LabelRelation{}.LabelRelationName()).Where("active = ?", 1).Where(" id = ?", id).First(lr).Error
if lr.ID > 0 {
result = true
}
return
}
// QueryLabelExist check label exist
func (d *Dao) QueryLabelExist(lre *model.LabelRelation) (lr *model.LabelRelation, err error) {
lr = &model.LabelRelation{}
err = d.DB.Table(model.LabelRelation{}.LabelRelationName()).
Where("active = ?", 1).
Where(model.LabelRelation{Type: lre.Type, LabelID: lre.LabelID, TargetID: lre.TargetID}).First(lr).Error
return
}
// DeleteLabelRelation delete relation of label
func (d *Dao) DeleteLabelRelation(id int64) (err error) {
return d.DB.Table(model.LabelRelation{}.LabelRelationName()).Where(" id = ?", id).Update("active", 0).Error
}

View File

@@ -0,0 +1,17 @@
package dao
import (
"go-common/library/log"
"gopkg.in/gomail.v2"
)
// SendMail asynchronous send mail.
func (d *Dao) SendMail(message *gomail.Message) (err error) {
message.SetAddressHeader("From", d.email.Username, "melloi")
err = d.email.DialAndSend(message)
if err != nil {
log.Error("send email error :(%v)", err)
}
return
}

View File

@@ -0,0 +1,62 @@
package dao
import (
"go-common/app/admin/ep/melloi/model"
pkgerr "github.com/pkg/errors"
)
// QueryGRPC Query grpc
func (d *Dao) QueryGRPC(grpc *model.GRPC, pn, ps int32, treeNodes []string) (qgr *model.QueryGRPCResponse, err error) {
qgr = &model.QueryGRPCResponse{}
grpc.Active = 1
gDB := d.DB.Table(model.GRPC{}.TableName()).Where("app in (?)", treeNodes)
if grpc.Department != "" && grpc.Project != "" && grpc.APP != "" {
gDB = gDB.Where("department = ? and project = ? and app = ?", grpc.Department, grpc.Project, grpc.APP)
} else if grpc.Department != "" && grpc.Project != "" {
gDB = gDB.Where("department = ? and project = ?", grpc.Department, grpc.Project)
} else if grpc.Department != "" {
gDB = gDB.Where("department = ?", grpc.Department)
}
err = gDB.Where(grpc).Count(&qgr.TotalSize).Offset((pn - 1) * ps).
Limit(ps).Order("id desc").Find(&qgr.GRPCS).Error
qgr.PageNum = pn
qgr.PageSize = ps
return
}
// QueryGRPCByWhiteName Query grpc By WhiteName
func (d *Dao) QueryGRPCByWhiteName(grpc *model.GRPC, pn, ps int32) (qgr *model.QueryGRPCResponse, err error) {
qgr = &model.QueryGRPCResponse{}
grpc.Active = 1
err = d.DB.Table(model.GRPC{}.TableName()).Where(grpc).Count(&qgr.TotalSize).Offset((pn - 1) * ps).
Limit(ps).Order("id desc").Find(&qgr.GRPCS).Error
qgr.PageNum = pn
qgr.PageSize = ps
return
}
// QueryGRPCByID Query GRPC By ID
func (d *Dao) QueryGRPCByID(id int) (grpc *model.GRPC, err error) {
grpc = &model.GRPC{}
err = pkgerr.WithStack(d.DB.Where("id = ?", id).First(grpc).Error)
return
}
// UpdateGRPC Update grpc
func (d *Dao) UpdateGRPC(grpc *model.GRPC) error {
return d.DB.Table(model.GRPC{}.TableName()).Where("id=?", grpc.ID).Update(grpc).Error
}
//CreateGRPC new grpc
func (d *Dao) CreateGRPC(grpc *model.GRPC) (g *model.GRPC, err error) {
grpc.Active = 1
return grpc, pkgerr.WithStack(d.DB.Create(grpc).Error)
}
// DeleteGRPC Delete grpc
func (d *Dao) DeleteGRPC(id int) error {
return d.DB.Table(model.GRPC{}.TableName()).Where("id=?", id).Update("active", -1).Error
}

View File

@@ -0,0 +1,30 @@
package dao
import (
"go-common/app/admin/ep/melloi/model"
pkgerr "github.com/pkg/errors"
)
// QueryGRPCSnapByID query grpcsnap by id
func (d *Dao) QueryGRPCSnapByID(id int) (grpcSnap *model.GRPCSnap, err error) {
grpcSnap = &model.GRPCSnap{}
err = pkgerr.WithStack(d.DB.Table(model.GRPCSnap{}.TableName()).Where("id = ?", id).First(grpcSnap).Error)
return
}
// UpdateGRPCSnap Update grpc
func (d *Dao) UpdateGRPCSnap(grpcSnap *model.GRPCSnap) error {
return d.DB.Table(model.GRPCSnap{}.TableName()).Where("id=?", grpcSnap.ID).Update(grpcSnap).Error
}
// CreateGRPCSnap CreateGRPC new grpc
func (d *Dao) CreateGRPCSnap(grpcSnap *model.GRPCSnap) (err error) {
grpcSnap.Active = 1
return pkgerr.WithStack(d.DB.Table(model.GRPCSnap{}.TableName()).Create(grpcSnap).Error)
}
// DeleteGRPCSnap Delete grpc snap
func (d *Dao) DeleteGRPCSnap(id int) error {
return pkgerr.WithStack(d.DB.Table(model.GRPCSnap{}.TableName()).Where("id=?", id).Update("active", -1).Error)
}

View File

@@ -0,0 +1,32 @@
package dao
import (
"go-common/app/admin/ep/melloi/model"
)
// QueryOrder query order info: ps : pageNumber pn: pageSize
func (d *Dao) QueryOrder(order *model.Order, pn int32, ps int32) (qor *model.QueryOrderResponse, err error) {
qor = &model.QueryOrderResponse{}
err = d.DB.Table(model.Order{}.TableName()).Where(model.Order{
ID: order.ID, Name: order.Name, Broker: order.Broker, Type: order.Type, TestType: order.TestType,
Project: order.Project, Department: order.Department, App: order.App, Status: order.Status, UpdateBy: order.UpdateBy,
Active: 1, Handler: order.Handler}).Count(&qor.TotalSize).Offset((pn - 1) * ps).Limit(ps).Order("id desc").Find(&qor.Orders).Error
qor.PageSize = ps
qor.PageNum = pn
return
}
// AddOrder add order by order object
func (d *Dao) AddOrder(order *model.Order) error {
return d.DB.Table(model.Order{}.TableName()).Create(order).Error
}
// UpdateOrder update order by order object
func (d *Dao) UpdateOrder(order *model.Order) error {
return d.DB.Model(&model.Order{}).Update(order).Where("ID=?", order.ID).Error
}
// DelOrder delete order by orderID
func (d *Dao) DelOrder(id int64) error {
return d.DB.Model(&model.Order{}).Where("ID=?", id).Update("active", -1).Error
}

View File

@@ -0,0 +1,17 @@
package dao
import (
"go-common/app/admin/ep/melloi/model"
)
// QueryOrderAdmin get administrator for Order of this project
func (d *Dao) QueryOrderAdmin(userName string) (admin *model.OrderAdmin, err error) {
admin = &model.OrderAdmin{}
err = d.DB.Table(model.OrderAdmin{}.TableName()).Where("user_name = ?", userName).First(admin).Error
return
}
// AddOrderAdmin add order of admin
func (d *Dao) AddOrderAdmin(admin *model.OrderAdmin) error {
return d.DB.Create(admin).Error
}

View File

@@ -0,0 +1,29 @@
package dao
import (
"testing"
"go-common/app/admin/ep/melloi/model"
. "github.com/smartystreets/goconvey/convey"
)
var (
oa = model.OrderAdmin{
UserName: "hujianping",
}
)
func Test_OrderAdmin(t *testing.T) {
Convey("test AddOrderAdmin", t, func() {
err := d.AddOrderAdmin(&oa)
So(err, ShouldBeNil)
})
Convey("test QueryOrderAdmin", t, func() {
var admin *model.OrderAdmin
admin, _ = d.QueryOrderAdmin(oa.UserName)
So(admin, ShouldNotBeNil)
})
}

View File

@@ -0,0 +1,22 @@
package dao
import (
"go-common/app/admin/ep/melloi/model"
)
// AddReport add manual report
func (d *Dao) AddReport(report *model.OrderReport) (err error) {
return d.DB.Model(&model.OrderReport{}).Create(report).Error
}
// QueryReportByOrderID query report by order id
func (d *Dao) QueryReportByOrderID(orderID int64) (report *model.OrderReport, err error) {
report = &model.OrderReport{}
err = d.DB.Table(model.OrderReport{}.TableName()).Where("order_id=? ", orderID).Find(&report).Error
return
}
// UpdateReportByID update report by id
func (d *Dao) UpdateReportByID(report *model.OrderReport) error {
return d.DB.Table(model.OrderReport{}.TableName()).Where("ID=?", report.ID).Update("content", report.Content).Error
}

View File

@@ -0,0 +1,42 @@
package dao
import (
"testing"
"time"
"go-common/app/admin/ep/melloi/model"
. "github.com/smartystreets/goconvey/convey"
)
var (
testOrder = model.Order{
ApplyDate: time.Now(),
ID: 1,
}
pageNum int32 = 1
pageSize int32 = 2
)
func Test_Order(t *testing.T) {
Convey("test QueryOrder", t, func() {
var workOrders *model.QueryOrderResponse
order := model.Order{ID: testOrder.ID}
workOrders, _ = d.QueryOrder(&order, pageNum, pageSize)
So(workOrders, ShouldBeEmpty)
})
Convey("test DeleteOrder", t, func() {
order := model.Order{ID: testOrder.ID}
err := d.DelOrder(order.ID)
So(err, ShouldBeNil)
})
Convey("test UpdateOrder", t, func() {
order := model.Order{ID: testOrder.ID, ApplyDate: testOrder.ApplyDate}
err := d.UpdateOrder(&order)
So(err, ShouldBeNil)
})
}

View File

@@ -0,0 +1,37 @@
package dao
import "go-common/app/admin/ep/melloi/model"
//AddPtestJob add PtestJob
func (d *Dao) AddPtestJob(ptestJob *model.PtestJob) (ptestJobID int, err error) {
err = d.DB.Create(ptestJob).Error
ptestJobID = ptestJob.ID
return
}
//CountPtestJob add PtestJob
func (d *Dao) CountPtestJob(ptestJob *model.PtestJob) (total int, err error) {
err = d.DB.Table(model.PtestJob{}.TableName()).Where(ptestJob).Count(&total).Error
return
}
//QueryPtestJob query PtestJob
func (d *Dao) QueryPtestJob(ptestJob *model.PtestJob) (pJob []*model.PtestJob, err error) {
err = d.DB.Table(model.PtestJob{}.TableName()).Where(ptestJob).Order("ctime asc").Find(&pJob).Error
return
}
//DeletePtestJob delete PtestJob
func (d *Dao) DeletePtestJob(id int) error {
return d.DB.Model(&model.PtestJob{}).Where("ID = ?", id).Update("active", -1).Error
}
//DeletePtestJobByJobName delete PtestJob
func (d *Dao) DeletePtestJobByJobName(jobName string) error {
return d.DB.Model(&model.PtestJob{}).Where("job_name = ?", jobName).Update("active", -1).Error
}
//UpdatePtestJob Update PtestJob
func (d *Dao) UpdatePtestJob(ptestJob model.PtestJob) error {
return d.DB.Model(&model.PtestJob{}).Where("id = ?", ptestJob.ID).Updates(ptestJob).Error
}

View File

@@ -0,0 +1,147 @@
package dao
import (
"go-common/app/admin/ep/melloi/model"
)
//TreesQuery query department and performance test count of department
func (d *Dao) TreesQuery() (res *model.TreeList, err error) {
res = &model.TreeList{}
//select department, count(department) as count from report_summary where department != '' GROUP BY department ORDER BY count desc
err = d.DB.Table("report_summary").Select("department, project, app").Group("app").
Having("department != ''").Order("department").Scan(&res.TreeList).Error
return
}
//TreeNumQuery query department
func (d *Dao) TreeNumQuery() (res *model.NumList, err error) { /**/
res = &model.NumList{}
//select count(DISTINCT department) as count from report_summary where department != ''
if err = d.DB.Table("report_summary").Select("department, count(DISTINCT department) as dept_num").
Where("department != ''").Scan(&res.NumList).Error; err != nil {
return
}
if err = d.DB.Table("report_summary").Select("project, count(DISTINCT project) as pro_num").
Where("project != ''").Scan(&res.NumList).Error; err != nil {
return
}
if err = d.DB.Table("report_summary").Select("app, count(DISTINCT app) as app_num").
Where("app != ''").Scan(&res.NumList).Error; err != nil {
return
}
return
}
//TopHttpQuery query performance test top api
func (d *Dao) TopHttpQuery() (res *model.TopAPIRes, err error) {
res = &model.TopAPIRes{}
//select s.url, count(r.script_id) as count from report_summary r INNER JOIN script s on r.script_id = s.id GROUP BY s.url having url != '' ORDER BY count desc
err = d.DB.Limit(10).Table("report_summary").Select("script.url, count(report_summary.script_id) as count").
Joins("inner join script on report_summary.script_id = script.id").
Where("report_summary.active = 1 and report_summary.debug != 1 and script.test_type = 1 and report_summary.type = 0").
Group("script.url").Having("script.url != ''").Order("count desc").Scan(&res.APIList).Error
return
}
//TopGrpcQuery Top Grpc Query
func (d *Dao) TopGrpcQuery() (res *model.GrpcRes, err error) {
res = &model.GrpcRes{}
//select g.service_name, g.request_method, count(r.script_id) as count from report_summary r INNER JOIN grpc g on r.script_id = g.id
//where g.service_name != '' and r.active = 1 and r.debug != 1 and r.type = 1
//GROUP BY g.service_name ORDER BY count desc
err = d.DB.Limit(10).Table("report_summary").Select("grpc.service_name, grpc.request_method, count(report_summary.script_id) as count").
Joins("inner join grpc on report_summary.script_id = grpc.id").
Where("report_summary.active = 1 and report_summary.debug != 1 and grpc.service_name != '' and report_summary.type = 1").
Group("grpc.service_name").Order("count desc").Scan(&res.GrpcList).Error
return
}
//TopSceneQuery Top Scene Query
func (d *Dao) TopSceneQuery() (res *model.SceneRes, err error) {
res = &model.SceneRes{}
//select s.scene_name, count(r.script_id) as count from report_summary r INNER JOIN scene s on r.scene_id = s.id
//where s.scene_name != '' and s.is_active = 1 and s.is_draft = 0 and r.active = 1 and r.debug != 1 and r.scene_id != 0 and r.type = 2
//GROUP BY s.scene_name ORDER BY count desc
err = d.DB.Limit(10).Table("report_summary").Select("scene.department, scene.scene_name, count(report_summary.script_id) as count").
Joins("inner join scene on report_summary.scene_id = scene.id").
Where("report_summary.active = 1 and report_summary.debug != 1 and scene.scene_name != '' and scene.is_active = 1 and scene.is_draft = 0 and report_summary.scene_id != 0 and report_summary.type = 2").
Group("scene.scene_name").Order("count desc").Scan(&res.SceneList).Error
return
}
//TopDeptQuery query performance test top department
func (d *Dao) TopDeptQuery() (res *model.TopDeptRes, err error) {
res = &model.TopDeptRes{}
//select department, count(department) as count from report_summary where department != '' GROUP BY department ORDER BY count desc
err = d.DB.Limit(10).Table("report_summary").Select("department, count(department) as count").
Where("report_summary.active = 1 and report_summary.debug != 1").
Group("department").Having("department != ''").Order("count desc").Scan(&res.DeptList).Error
return
}
//BuildLineQuery query performance test count by time
func (d *Dao) BuildLineQuery(rank *model.Rank, summary *model.ReportSummary) (res *model.BuildLineRes, err error) {
res = &model.BuildLineRes{}
//select DATE_FORMAT(ctime, '%H') as count from report_summary where ctime >= date_sub(now(), interval 24 hour) AND ctime <= NOW()
//switch rank.TimeDegree {
//case "H":
// err = d.DB.Table("report_summary").Select("DATE_FORMAT(ctime, '%Y-%m-%d %H') as date").
// Where(summary).Where("active = 1 and debug != 1").
// Where("ctime >= ? AND ctime <= ?", rank.StartTime, rank.EndTime).Order("date").
// Scan(&res.BuildList).Error
//case "d":
// err = d.DB.Table("report_summary").Select("DATE_FORMAT(ctime, '%Y-%m-%d') as date").Where(summary).
// Where("active = 1 and debug != 1").
// Where("ctime >= ? AND ctime <= ?", rank.StartTime, rank.EndTime).Order("date").Scan(&res.BuildList).Error
//case "m":
// err = d.DB.Table("report_summary").Select("DATE_FORMAT(ctime, '%Y-%m') as date").Where(summary).
// Where("active = 1 and debug != 1").
// Where("ctime >= ? AND ctime <= ?", rank.StartTime, rank.EndTime).Order("date").Scan(&res.BuildList).Error
//case "Y":
// err = d.DB.Table("report_summary").Select("DATE_FORMAT(ctime, '%Y') as date").Where(summary).
// Where("active = 1 and debug != 1").
// Where("ctime >= ? AND ctime <= ?", rank.StartTime, rank.EndTime).Order("date").Scan(&res.BuildList).Error
//default:
// err = d.DB.Table("report_summary").Select("DATE_FORMAT(ctime, '%Y-%m-%d %H') as date").Where(summary).
// Where("active = 1 and debug != 1").
// Where("ctime >= ? AND ctime <= ?", rank.StartTime, rank.EndTime).Order("date").Scan(&res.BuildList).Error
//}
gDB := d.DB.Table(model.ReportSummary{}.TableName())
switch rank.TimeDegree {
case "H":
gDB = gDB.Select("DATE_FORMAT(ctime, '%Y-%m-%d %H') as date").
Where("active = 1 and debug != 1").
Where("ctime >= ? AND ctime <= ?", rank.StartTime, rank.EndTime)
case "d":
gDB = d.DB.Table("report_summary").Select("DATE_FORMAT(ctime, '%Y-%m-%d') as date").
Where("active = 1 and debug != 1").
Where("ctime >= ? AND ctime <= ?", rank.StartTime, rank.EndTime)
case "m":
gDB = d.DB.Table("report_summary").Select("DATE_FORMAT(ctime, '%Y-%m') as date").
Where("active = 1 and debug != 1").
Where("ctime >= ? AND ctime <= ?", rank.StartTime, rank.EndTime)
case "Y":
gDB = d.DB.Table("report_summary").Select("DATE_FORMAT(ctime, '%Y') as date").
Where("active = 1 and debug != 1").
Where("ctime >= ? AND ctime <= ?", rank.StartTime, rank.EndTime)
default:
gDB = d.DB.Table("report_summary").Select("DATE_FORMAT(ctime, '%Y-%m-%d %H') as date").
Where("active = 1 and debug != 1").
Where("ctime >= ? AND ctime <= ?", rank.StartTime, rank.EndTime)
}
if rank.SearchAll {
err = gDB.Where("type in (0, 1, 2)").Order("date").Scan(&res.BuildList).Error
} else {
err = gDB.Where("type = ?", summary.Type).Order("date").Scan(&res.BuildList).Error
}
return
}
//StateLineQuery query statistic of state
func (d *Dao) StateLineQuery() (res *model.StateLineRes, err error) {
res = &model.StateLineRes{}
//select test_status, count(test_status) as count from report_summary GROUP BY test_status
err = d.DB.Table("report_summary").Select("test_status, count(test_status) as count").Where("test_status != 0").
Where("active = 1 and debug != 1").Group("test_status").Scan(&res.StateList).Error
return
}

View File

@@ -0,0 +1,108 @@
package dao
import (
"go-common/app/admin/ep/melloi/model"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoTreesQuery(t *testing.T) {
convey.Convey("TreesQuery", t, func(convCtx convey.C) {
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
res, err := d.TreesQuery()
convCtx.Convey("Then err should be nil.res should not be nil.", func(convCtx convey.C) {
convCtx.So(err, convey.ShouldBeNil)
convCtx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoTreeNumQuery(t *testing.T) {
convey.Convey("TreeNumQuery", t, func(convCtx convey.C) {
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
res, err := d.TreeNumQuery()
convCtx.Convey("Then err should be nil.res should not be nil.", func(convCtx convey.C) {
convCtx.So(err, convey.ShouldBeNil)
convCtx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoTopHttpQuery(t *testing.T) {
convey.Convey("TopHttpQuery", t, func(convCtx convey.C) {
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
res, err := d.TopHttpQuery()
convCtx.Convey("Then err should be nil.res should not be nil.", func(convCtx convey.C) {
convCtx.So(err, convey.ShouldBeNil)
convCtx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoTopGrpcQuery(t *testing.T) {
convey.Convey("TopGrpcQuery", t, func(convCtx convey.C) {
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
res, err := d.TopGrpcQuery()
convCtx.Convey("Then err should be nil.res should not be nil.", func(convCtx convey.C) {
convCtx.So(err, convey.ShouldBeNil)
convCtx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoTopSceneQuery(t *testing.T) {
convey.Convey("TopSceneQuery", t, func(convCtx convey.C) {
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
res, err := d.TopSceneQuery()
convCtx.Convey("Then err should be nil.res should not be nil.", func(convCtx convey.C) {
convCtx.So(err, convey.ShouldBeNil)
convCtx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoTopDeptQuery(t *testing.T) {
convey.Convey("TopDeptQuery", t, func(convCtx convey.C) {
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
res, err := d.TopDeptQuery()
convCtx.Convey("Then err should be nil.res should not be nil.", func(convCtx convey.C) {
convCtx.So(err, convey.ShouldBeNil)
convCtx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoBuildLineQuery(t *testing.T) {
convey.Convey("BuildLineQuery", t, func(convCtx convey.C) {
var (
rank = &model.Rank{}
summary = &model.ReportSummary{}
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
res, err := d.BuildLineQuery(rank, summary)
convCtx.Convey("Then err should be nil.res should not be nil.", func(convCtx convey.C) {
convCtx.So(err, convey.ShouldBeNil)
convCtx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoStateLineQuery(t *testing.T) {
convey.Convey("StateLineQuery", t, func(convCtx convey.C) {
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
res, err := d.StateLineQuery()
convCtx.Convey("Then err should be nil.res should not be nil.", func(convCtx convey.C) {
convCtx.So(err, convey.ShouldBeNil)
convCtx.So(res, convey.ShouldNotBeNil)
})
})
})
}

View File

@@ -0,0 +1,137 @@
package dao
import (
"go-common/app/admin/ep/melloi/model"
)
// QueryReportSummarys query reportSummarys
func (d *Dao) QueryReportSummarys(reportSummary *model.ReportSummary, searchAll bool, pn, ps int32, treeNodes []string) (qrsr *model.QueryReportSuResponse, err error) {
qrsr = &model.QueryReportSuResponse{}
reportSummary.Active = 1
reportSummary.Debug = -1
gDB := d.DB.Table(model.ReportSummary{}.TableName()) //.Where("app in (?)", treeNodes)
if reportSummary.TestName != "" && reportSummary.ScriptID != 0 {
gDB = gDB.Where("test_name LIKE ? and active = ? and debug = ? and script_id = ?", "%"+reportSummary.TestName+"%", 1, -1, reportSummary.ScriptID)
}
if reportSummary.UserName != "" && reportSummary.ScriptID != 0 {
gDB = gDB.Where("user_name LIKE ? and active = ? and debug = ? and script_id = ?", "%"+reportSummary.UserName+"%", 1, -1, reportSummary.ScriptID)
}
if reportSummary.TestName != "" {
gDB = gDB.Where("test_name LIKE ? and active = ? and debug = ?", "%"+reportSummary.TestName+"%", 1, -1)
}
if reportSummary.UserName != "" {
gDB = gDB.Where("user_name LIKE ? and active = ? and debug = ?", "%"+reportSummary.UserName+"%", 1, -1)
}
if searchAll {
gDB = gDB.Where("type in (0, 1, 2)")
} else {
if reportSummary.ID == 0 {
gDB = gDB.Where("type = ?", reportSummary.Type)
}
}
if reportSummary.TestName == "" && reportSummary.UserName == "" {
gDB = gDB.Where(reportSummary)
}
err = gDB.Count(&qrsr.TotalSize).
Order("ctime desc").Offset((pn - 1) * ps).Limit(ps).Find(&qrsr.ReportSummarys).Error
qrsr.PageSize = ps /**/
qrsr.PageNum = pn
return
}
// QueryReportSummarysWhiteName query reportSummarys by whiteName
func (d *Dao) QueryReportSummarysWhiteName(reportSummary *model.ReportSummary, searchAll bool, pn, ps int32) (qrsr *model.QueryReportSuResponse, err error) {
qrsr = &model.QueryReportSuResponse{}
reportSummary.Active = 1
reportSummary.Debug = -1
gDB := d.DB.Table(model.ReportSummary{}.TableName())
if reportSummary.TestName != "" && reportSummary.ScriptID != 0 {
gDB = gDB.Where("test_name LIKE ? and active = ? and debug = ? and script_id = ?", "%"+reportSummary.TestName+"%", 1, -1, reportSummary.ScriptID)
}
if reportSummary.UserName != "" && reportSummary.ScriptID != 0 {
gDB = gDB.Where("user_name LIKE ? and active = ? and debug = ? and script_id = ?", "%"+reportSummary.UserName+"%", 1, -1, reportSummary.ScriptID)
}
if reportSummary.TestName != "" {
gDB = gDB.Where("test_name LIKE ? and active = ? and debug = ?", "%"+reportSummary.TestName+"%", 1, -1)
}
if reportSummary.UserName != "" {
gDB = gDB.Where("user_name LIKE ? and active = ? and debug = ?", "%"+reportSummary.UserName+"%", 1, -1)
}
if searchAll {
gDB = gDB.Where("type in (0, 1, 2)")
} else {
if reportSummary.ID == 0 {
gDB = gDB.Where("type = ?", reportSummary.Type)
}
}
if reportSummary.TestName == "" && reportSummary.UserName == "" {
gDB = gDB.Where(reportSummary)
}
err = gDB.Count(&qrsr.TotalSize).
Order("ctime desc").Offset((pn - 1) * ps).Limit(ps).Find(&qrsr.ReportSummarys).Error
qrsr.PageSize = ps /**/
qrsr.PageNum = pn
return
}
// QueryReportSurys query reportSummarys
func (d *Dao) QueryReportSurys(reportSummary *model.ReportSummary) (res []*model.ReportSummary, err error) {
err = d.DB.Table(model.ReportSummary{}.TableName()).Where(reportSummary).Find(&res).Error
return
}
// QueryReportSuryByID query reportSummary by id
func (d *Dao) QueryReportSuryByID(id int) (res *model.ReportSummary, err error) {
reportSummary := model.ReportSummary{ID: id}
res = &model.ReportSummary{}
err = d.DB.Table(model.ReportSummary{}.TableName()).Where(reportSummary).First(&res).Error
return
}
//CountQueryReportSummarys count queryReportSummarys
func (d *Dao) CountQueryReportSummarys(reportSummary *model.ReportSummary) (total int, err error) {
err = d.DB.Table(model.ReportSummary{}.TableName()).Where(reportSummary).Count(&total).Error
return
}
//AddReportSummary add reportSummary
func (d *Dao) AddReportSummary(reportSummary *model.ReportSummary) (reportSuID int, err error) {
err = d.DB.Create(reportSummary).Error
reportSuID = reportSummary.ID
return
}
//UpdateReportSummary update Report
func (d *Dao) UpdateReportSummary(reportSummary *model.ReportSummary) error {
return d.DB.Model(&model.ReportSummary{}).Where("id = ?", reportSummary.ID).Updates(reportSummary).Error
}
//UpdateReportStatusByID update report status
func (d *Dao) UpdateReportStatusByID(ID, testStatus int) error {
return d.DB.Exec("update report_summary set test_status = ? where id = ? ", testStatus, ID).Error
}
//UpdateReportStatus update Report
func (d *Dao) UpdateReportStatus(status int) error {
return d.DB.Model(&model.ReportSummary{}).Where("test_status = 2").Update("test_status", 1).Error
}
//UpdateReportDockByID update Report
func (d *Dao) UpdateReportDockByID(ID, dockerSum int) error {
return d.DB.Model(&model.ReportSummary{}).Where("id =?", ID).Updates(model.ReportSummary{DockerSum: dockerSum}).Error
}
//DelReportSummary delete reportSummary
func (d *Dao) DelReportSummary(id int) error {
return d.DB.Model(&model.ReportSummary{}).Where("ID=?", id).Update("active", 0).Error
}
//QueryReTimely query rueryReTimely
func (d *Dao) QueryReTimely(testName, beginTime, afterTime string, podNames []string) (reportTimelys []*model.ReportTimely, err error) {
err = d.DB.Model(&model.ReportTimely{}).Where("test_name = ? and mtime >= ? and mtime <= ? and pod_name in (?)", testName, beginTime, afterTime, podNames).Find(&reportTimelys).Error
return
}

View File

@@ -0,0 +1,16 @@
package dao
import (
"go-common/app/admin/ep/melloi/model"
)
//AddReportGraph add reportGraph
func (d *Dao) AddReportGraph(reportGraph *model.ReportGraph) error {
return d.DB.Create(reportGraph).Error
}
//QueryReportGraph query reportGraph
func (d *Dao) QueryReportGraph(testNameNicks []string) (reportGraphs []model.ReportGraph, err error) {
err = d.DB.Model(&model.ReportGraph{}).Where(" test_name_nick in (?) ", testNameNicks).Order("elapsd_time asc").Find(&reportGraphs).Error
return
}

View File

@@ -0,0 +1,278 @@
package dao
import (
"strconv"
"strings"
"go-common/app/admin/ep/melloi/conf"
"go-common/app/admin/ep/melloi/model"
)
// AddScene Add Scene
func (d *Dao) AddScene(scene *model.Scene) (sceneId int, err error) {
scene.IsActive = true
err = d.DB.Table("scene").Create(scene).Error
sceneId = scene.ID
return
}
// QueryDraft Query Draft
func (d *Dao) QueryDraft(scene *model.Scene) (res *model.QueryDraft, err error) {
res = &model.QueryDraft{}
err = d.DB.Table("scene").Select("id as scene_id, scene_name").Where(scene).Where("is_draft = 1 and is_active = 1").Count(&res.Total).Order("mtime desc").Find(&res.Drafts).Error
return
}
// UpdateScene Update Scene
func (d *Dao) UpdateScene(scene *model.Scene, scriptIDList []int) (fusing int, err error) {
if err = d.DB.Exec("update scene set fusing = ? where id = ?", scene.Fusing, scene.ID).Error; err != nil {
return
}
if err = d.DB.Model(&model.Scene{}).Where("ID = ?", scene.ID).Update(scene).Error; err != nil {
return
}
if scene.IsBatch { //选择已有接口点击确定时执行
if scene.Fusing == 0 {
err = d.DB.Model(&model.Script{}).Where("scene_id = ? and id in (?)", scene.ID, scriptIDList).Update("fusing", conf.Conf.Melloi.DefaultFusing).Error
} else {
err = d.DB.Model(&model.Script{}).Where("scene_id = ? and id in (?)", scene.ID, scriptIDList).Update("fusing", scene.Fusing).Error
}
} else if scene.IsUpdate { //
err = d.DB.Model(&model.Script{}).Where("scene_id = ?", scene.ID).Update("fusing", scene.Fusing).Error
}
fusing = scene.Fusing
return
}
// SaveScene Save Scene
func (d *Dao) SaveScene(scene *model.Scene) error {
return d.DB.Model(&model.Scene{}).Where("ID = ?", scene.ID).Update("is_draft", 0).Update("scene_type", scene.SceneType).Error
}
// SaveOrder Save Order
func (d *Dao) SaveOrder(reqList []*model.GroupOrder, scene *model.Scene) (err error) {
for _, req := range reqList {
if scene.SceneType == 1 {
err = d.DB.Model(&model.Script{}).Where("ID = ?", req.ID).Update("group_id", req.GroupID).Error
} else {
err = d.DB.Model(&model.Script{}).Where("ID = ?", req.ID).Update("run_order", req.RunOrder).Error
}
}
return
}
// QueryGroupId Query GroupId
func (d *Dao) QueryGroupId(script *model.Script) (res *model.QueryRelation, groupId int, err error) {
res = &model.QueryRelation{}
//select group_id, count(group_id) as count from script where scene_id = 1 and group_id in (select group_id from script where id = 777) group by group_id
err = d.DB.Table("script").Select("group_id").Where("id = ?", script.ID).Find(&res.RelationList).Error
groupId = res.RelationList[0].GroupID
return
}
// QueryRelation Query Relation
func (d *Dao) QueryRelation(groupId int, script *model.Script) (res *model.QueryRelation, err error) {
res = &model.QueryRelation{}
err = d.DB.Table("script").Select("group_id, count(group_id) as count").Where("scene_id = ? and group_id = ?", script.SceneID, groupId).Find(&res.RelationList).Error
return
}
// QueryAPI Query API
func (d *Dao) QueryAPI(scene *model.Scene) (res *model.QueryAPIs, err error) {
res = &model.QueryAPIs{}
if err = d.DB.Table(model.Script{}.TableName()).Select("id").Where("scene_id = ? and active = 1", scene.ID).Count(&res.Total).Error; err != nil {
return
}
if res.Total > 0 {
//select scene.scene_name, scene.scene_type, scene.department, scene.project, scene.app, script.group_id, script.run_order, script.id as test_id, script.test_name
//from scene INNER JOIN script on scene.id = script.scene_id and script.active = 1 where script.scene_id = 1
gDB := d.DB.Table(model.Scene{}.TableName()).Select("scene.id as scene_id, scene.scene_name, scene.scene_type, scene.department, " +
"scene.project, scene.app, script.group_id, script.run_order, script.id, script.test_name, script.url, script.output_params, script.threads_sum, script.load_time").
Joins("inner join script on scene.id = script.scene_id and script.active = 1")
if scene.SceneType == 2 {
err = gDB.Where(scene).Count(&res.Total).Order("group_id, run_order").Find(&res).Find(&res.APIs).Error
res.SceneType = 2
} else {
err = gDB.Where(scene).Count(&res.Total).Order("script.id").Find(&res).Find(&res.APIs).Error
res.SceneType = 1
}
} else {
gDB := d.DB.Table(model.Scene{}.TableName()).Select("id as scene_id, scene_name, department, project, app")
err = gDB.Where("id = ?", scene.ID).Find(&res).Error
//查询无结果时APIs返回空数组
res.APIs = []*model.TestAPI{}
}
return
}
// DeleteAPI Delete API
func (d *Dao) DeleteAPI(script *model.Script) error {
return d.DB.Model(&model.Script{}).Where("ID = ?", script.ID).Update("active", 0).Error
}
// AddConfig Add Config
func (d *Dao) AddConfig(script *model.Script) error {
return d.DB.Exec("update script set threads_sum = ?, load_time = ?, ready_time = ? where scene_id = ? and group_id = ?", script.ThreadsSum, script.LoadTime, script.ReadyTime, script.SceneID, script.GroupID).Error
}
// QueryTree Query Tree
func (d *Dao) QueryTree(script *model.Script) (res *model.ShowTree, err error) {
res = &model.ShowTree{}
err = d.DB.Table(model.Script{}.TableName()).Select("department, project, app").Where(script).Count(&res.IsShow).Order("id").Limit(1).Find(&res.Tree).Error
if res.IsShow > 1 {
res.IsShow = 1
}
return
}
//QueryScenesByPage query scripts by page
func (d *Dao) QueryScenesByPage(scene *model.Scene, pn, ps int32, treeNodes []string) (qsr *model.QuerySceneResponse, err error) {
qsr = &model.QuerySceneResponse{}
gDB := d.DB.Table(model.Scene{}.TableName()).Where("app in (?)", treeNodes).Where("is_draft = 0")
if scene.Department != "" && scene.Project != "" && scene.APP != "" {
gDB = gDB.Where("department = ? and project = ? and app = ?", scene.Department, scene.Project, scene.APP)
}
if scene.Department != "" && scene.Project != "" {
gDB = gDB.Where("department = ? and project = ?", scene.Department, scene.Project)
}
if scene.Department != "" {
gDB = gDB.Where("department = ?", scene.Department)
}
if scene.SceneName != "" {
gDB = gDB.Where("scene_name LIKE ? ", "%"+scene.SceneName+"%")
}
if scene.UserName != "" {
gDB = gDB.Where("user_name LIKE ? ", "%"+scene.UserName+"%")
}
if scene.SceneName == "" && scene.UserName == "" && scene.Department == "" && scene.Project == "" && scene.APP == "" {
gDB = gDB.Where(scene)
}
err = gDB.Where("is_active = 1").Count(&qsr.TotalSize).Order("ctime desc").Offset((pn - 1) * ps).Limit(ps).
Find(&qsr.Scenes).Error
qsr.PageSize = ps /**/
qsr.PageNum = pn
return
}
//QueryScenesByPageWhiteName query scripts by page white name
func (d *Dao) QueryScenesByPageWhiteName(scene *model.Scene, pn, ps int32) (qsr *model.QuerySceneResponse, err error) {
qsr = &model.QuerySceneResponse{}
gDB := d.DB.Table(model.Scene{}.TableName()).Where("is_draft = 0")
if scene.SceneName != "" {
gDB = gDB.Where("scene_name LIKE ? ", "%"+scene.SceneName+"%")
}
if scene.UserName != "" {
gDB = gDB.Where("user_name LIKE ? ", "%"+scene.UserName+"%")
}
if scene.SceneName == "" && scene.UserName == "" {
gDB = gDB.Where(scene)
}
err = gDB.Where("is_active = 1").Count(&qsr.TotalSize).Order("mtime desc").Offset((pn - 1) * ps).Limit(ps).
Find(&qsr.Scenes).Error
qsr.PageSize = ps /**/
qsr.PageNum = pn
return
}
//QueryScenes query scene
func (d *Dao) QueryScenes(scene *model.Scene, pn int, ps int) (scenes []*model.Scene, err error) {
err = d.DB.Table(model.Scene{}.TableName()).Where(scene).Order("mtime desc").Offset((pn - 1) * ps).Limit(ps).Find(&scenes).Error
return
}
// QueryExistAPI Query Exist API
func (d *Dao) QueryExistAPI(script *model.Script, pageNum int32, pageSize int32, sceneId int, treeNodes []string) (res *model.APIInfoList, err error) {
res = &model.APIInfoList{}
gDB := d.DB.Table(model.Script{}.TableName()).Where("app in (?)", treeNodes)
if pageSize == 0 && pageNum == 0 {
err = gDB.Where(script).Where("active = 1 and scene_id = 0").Count(&res.TotalSize).Order("id desc").Find(&res.ScriptList).Error
} else {
err = gDB.Where(script).Where("active = 1 and scene_id = 0").Count(&res.TotalSize).Order("id desc").Offset((pageNum - 1) * pageSize).Limit(pageSize).Find(&res.ScriptList).Error
res.PageNum = pageNum
res.PageSize = pageSize
}
res.SceneID = sceneId
return
}
// QueryGroup Query Group
func (d *Dao) QueryGroup(sceneId int) (res *model.GroupList, err error) {
res = &model.GroupList{}
gDB := d.DB.Table(model.Script{}.TableName())
//select group_id, count(group_id) from script where scene_id = 1 GROUP BY group_id order by group_id
err = gDB.Select("group_id, threads_sum, load_time, ready_time").Where("scene_id = ? and active = 1", sceneId).Group("group_id").Order("group_id").Find(&res.GroupList).Error
return
}
// QueryPreview Query Preview
func (d *Dao) QueryPreview(sceneId, groupId int) (res *model.PreviewList, err error) {
res = &model.PreviewList{}
gDB := d.DB.Table(model.Script{}.TableName())
//select id as test_id, test_name, run_order from script where scene_id = 1 and group_id = 1 order by run_order
err = gDB.Select("id, test_name, run_order, group_id, const_timer, random_timer").Where("scene_id = ? and group_id = ? and active = 1", sceneId, groupId).Order("run_order").Find(&res.PreList).Error
return
}
// QueryUsefulParams Query Useful Params
func (d *Dao) QueryUsefulParams(sceneId int) (res *model.UsefulParamsList, err error) {
res = &model.UsefulParamsList{}
gDB := d.DB.Table(model.Script{}.TableName())
err = gDB.Select("output_params").Where("scene_id = ?", sceneId).Where("active = 1 and output_params != '[{\"\":\"\"}]'").Order("id desc").Find(&res.ParamsList).Error
return
}
// UpdateBindScene Update Bind Scene
func (d *Dao) UpdateBindScene(bindScene *model.BindScene) (err error) {
var id int
tempList := strings.Split(bindScene.ID, ",")
for _, tempId := range tempList {
if id, err = strconv.Atoi(tempId); err != nil {
return err
}
err = d.DB.Model(&model.Script{}).Where("id =?", id).Updates(model.Script{SceneID: bindScene.SceneID}).Error
}
return
}
// QueryDrawRelation Query Draw Relation
func (d *Dao) QueryDrawRelation(scene *model.Scene) (res *model.SaveOrderReq, err error) {
res = &model.SaveOrderReq{}
gDB := d.DB.Table(model.Script{}.TableName())
err = gDB.Select("id, test_name, group_id, run_order").Where("scene_id = ? and active = 1", scene.ID).Order("group_id, run_order").Find(&res.GroupOrderList).Error
return
}
// DeleteDraft Delete Draft
func (d *Dao) DeleteDraft(scene *model.Scene) error {
if scene.ID == 0 {
return d.DB.Model(&model.Scene{}).Where("user_name = ? and is_draft = 1", scene.UserName).Update("is_active", 0).Error
}
return d.DB.Model(&model.Scene{}).Where("user_name = ? and id = ? and is_draft = 1", scene.UserName, scene.ID).Update("is_active", 0).Error
}
// QueryConfig Query Config
func (d *Dao) QueryConfig(script *model.Script) (res *model.GroupInfo, err error) {
res = &model.GroupInfo{}
gDB := d.DB.Table(model.Script{}.TableName())
// select distinct group_id, threads_sum, ready_time, load_time from script where scene_id = 282 and active = 1 and group_id = 2
err = gDB.Select("distinct group_id, threads_sum, ready_time, load_time").Where("scene_id = ? and group_id = ? and active = 1", script.SceneID, script.GroupID).Find(&res).Error
return
}
// DeleteScene Delete Scene
func (d *Dao) DeleteScene(scene *model.Scene) error {
return d.DB.Model(&model.Scene{}).Where("id = ?", scene.ID).Update("is_active", 0).Error
}
// QueryFusing Query Fusing
func (d *Dao) QueryFusing(script *model.Script) (res *model.FusingInfoList, err error) {
res = &model.FusingInfoList{}
gDB := d.DB.Table(model.Script{}.TableName())
//select id as test_id, test_name, run_order from script where scene_id = 1 and group_id = 1 order by run_order
err = gDB.Select("fusing").Where("scene_id = ? and active = 1", script.SceneID).Find(&res.FusingList).Error
return
}

View File

@@ -0,0 +1,470 @@
package dao
import (
"go-common/app/admin/ep/melloi/model"
"testing"
"github.com/smartystreets/goconvey/convey"
)
func TestDaoAddScene(t *testing.T) {
convey.Convey("AddScene", t, func(convCtx convey.C) {
var (
scene = &model.Scene{
SceneName: "CMTest001",
UserName: "chenmeng",
Department: "test",
Project: "ep",
APP: "melloi",
IsDraft: 1,
}
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
sceneId, err := d.AddScene(scene)
convCtx.Convey("Then err should be nil.sceneId should not be nil.", func(convCtx convey.C) {
convCtx.So(err, convey.ShouldBeNil)
convCtx.So(sceneId, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoQueryDraft(t *testing.T) {
convey.Convey("QueryDraft", t, func(convCtx convey.C) {
var (
scene = &model.Scene{
UserName: "chenmeng",
}
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
res, err := d.QueryDraft(scene)
convCtx.Convey("Then err should be nil.res should not be nil.", func(convCtx convey.C) {
convCtx.So(err, convey.ShouldBeNil)
convCtx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoUpdateScene(t *testing.T) {
convey.Convey("UpdateScene", t, func(convCtx convey.C) {
var (
scene = &model.Scene{
ID: 66,
}
scriptIDList = []int{1831, 1832, 1833, 1834, 1835}
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
fusing, err := d.UpdateScene(scene, scriptIDList)
convCtx.Convey("Then err should be nil.", func(convCtx convey.C) {
convCtx.So(err, convey.ShouldBeNil)
convCtx.So(fusing, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoSaveScene(t *testing.T) {
convey.Convey("SaveScene", t, func(convCtx convey.C) {
var (
scene = &model.Scene{
ID: 66,
IsDraft: 0,
SceneType: 2,
}
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
err := d.SaveScene(scene)
convCtx.Convey("Then err should be nil.", func(convCtx convey.C) {
convCtx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoSaveOrderAuto(t *testing.T) {
convey.Convey("SaveOrder", t, func(convCtx convey.C) {
var (
reqList = []*model.GroupOrder{
{
GroupID: 1,
RunOrder: 2,
ID: 980,
TestName: "cm-test",
},
{
GroupID: 1,
RunOrder: 1,
ID: 973,
TestName: "status111",
},
}
sceneAuto = &model.Scene{
SceneType: 1,
}
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
err := d.SaveOrder(reqList, sceneAuto)
convCtx.Convey("Then err should be nil.", func(convCtx convey.C) {
convCtx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoSaveOrderGroup(t *testing.T) {
convey.Convey("SaveOrder", t, func(convCtx convey.C) {
var (
reqList = []*model.GroupOrder{
{
GroupID: 1,
RunOrder: 2,
ID: 980,
TestName: "cm-test",
},
{
GroupID: 1,
RunOrder: 1,
ID: 973,
TestName: "status111",
},
}
sceneGroup = &model.Scene{
SceneType: 2,
}
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
err := d.SaveOrder(reqList, sceneGroup)
convCtx.Convey("Then err should be nil.", func(convCtx convey.C) {
convCtx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoQueryGroupId(t *testing.T) {
convey.Convey("QueryGroupId", t, func(convCtx convey.C) {
var (
script = &model.Script{
ID: 1568,
}
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
res, groupId, err := d.QueryGroupId(script)
convCtx.Convey("Then err should be nil.res,groupId should not be nil.", func(convCtx convey.C) {
convCtx.So(err, convey.ShouldBeNil)
convCtx.So(groupId, convey.ShouldNotBeNil)
convCtx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoQueryRelation(t *testing.T) {
convey.Convey("QueryRelation", t, func(convCtx convey.C) {
var (
groupId = 11
script = &model.Script{
ID: 1568,
}
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
res, err := d.QueryRelation(groupId, script)
convCtx.Convey("Then err should be nil.res should not be nil.", func(convCtx convey.C) {
convCtx.So(err, convey.ShouldBeNil)
convCtx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoQueryAPI(t *testing.T) {
convey.Convey("QueryAPI", t, func(convCtx convey.C) {
var (
scene = &model.Scene{
ID: 325,
SceneType: 1,
}
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
res, err := d.QueryAPI(scene)
convCtx.Convey("Then err should be nil.res should not be nil.", func(convCtx convey.C) {
convCtx.So(err, convey.ShouldBeNil)
convCtx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoDeleteAPI(t *testing.T) {
d.DB.Model(&model.Script{}).Where("ID = 1568").Update("active", 1)
convey.Convey("DeleteAPI", t, func(convCtx convey.C) {
var (
script = &model.Script{
ID: 1568,
}
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
err := d.DeleteAPI(script)
convCtx.Convey("Then err should be nil.", func(convCtx convey.C) {
convCtx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoAddConfig(t *testing.T) {
d.DB.Exec("update script set threads_sum = 10, load_time = 10, ready_time = 10 where scene_id = 325 and group_id = 1")
convey.Convey("AddConfig", t, func(convCtx convey.C) {
var (
script = &model.Script{
ThreadsSum: 120,
LoadTime: 300,
ReadyTime: 10,
SceneID: 325,
GroupID: 1,
}
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
err := d.AddConfig(script)
convCtx.Convey("Then err should be nil.", func(convCtx convey.C) {
convCtx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoQueryTree(t *testing.T) {
convey.Convey("QueryTree", t, func(convCtx convey.C) {
var (
script = &model.Script{
SceneID: 325,
}
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
res, err := d.QueryTree(script)
convCtx.Convey("Then err should be nil.res should not be nil.", func(convCtx convey.C) {
convCtx.So(err, convey.ShouldBeNil)
convCtx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoQueryScenesByPage(t *testing.T) {
convey.Convey("QueryScenesByPage", t, func(convCtx convey.C) {
var (
scene = &model.Scene{
Department: "test",
Project: "ep",
APP: "melloi",
SceneName: "场景压测cmtest01",
UserName: "chenmeng",
}
pn = int32(1)
ps = int32(20)
treeNodes = []string{}
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
qsr, err := d.QueryScenesByPage(scene, pn, ps, treeNodes)
convCtx.Convey("Then err should be nil.qsr should not be nil.", func(convCtx convey.C) {
convCtx.So(err, convey.ShouldBeNil)
convCtx.So(qsr, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoQueryScenesByPageWhiteName(t *testing.T) {
convey.Convey("QueryScenesByPageWhiteName", t, func(convCtx convey.C) {
var (
scene = &model.Scene{
Department: "test",
Project: "ep",
APP: "melloi",
SceneName: "场景压测cmtest01",
UserName: "chenmeng",
}
pn = int32(1)
ps = int32(20)
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
qsr, err := d.QueryScenesByPageWhiteName(scene, pn, ps)
convCtx.Convey("Then err should be nil.qsr should not be nil.", func(convCtx convey.C) {
convCtx.So(err, convey.ShouldBeNil)
convCtx.So(qsr, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoQueryScenes(t *testing.T) {
convey.Convey("QueryScenes", t, func(convCtx convey.C) {
var (
scene = &model.Scene{
UserName: "chenmeng",
}
pn = 1
ps = 10
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
scenes, err := d.QueryScenes(scene, pn, ps)
convCtx.Convey("Then err should be nil.scenes should not be nil.", func(convCtx convey.C) {
convCtx.So(err, convey.ShouldBeNil)
convCtx.So(scenes, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoQueryExistAPI(t *testing.T) {
convey.Convey("QueryExistAPI", t, func(convCtx convey.C) {
var (
script = &model.Script{
SceneID: 325,
}
pageNum = int32(1)
pageSize = int32(10)
sceneId = int(325)
treeNodes = []string{}
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
res, err := d.QueryExistAPI(script, pageNum, pageSize, sceneId, treeNodes)
convCtx.Convey("Then err should be nil.res should not be nil.", func(convCtx convey.C) {
convCtx.So(err, convey.ShouldBeNil)
convCtx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoQueryGroup(t *testing.T) {
convey.Convey("QueryGroup", t, func(convCtx convey.C) {
var (
sceneId = 325
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
res, err := d.QueryGroup(sceneId)
convCtx.Convey("Then err should be nil.res should not be nil.", func(convCtx convey.C) {
convCtx.So(err, convey.ShouldBeNil)
convCtx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoQueryPreview(t *testing.T) {
convey.Convey("QueryPreview", t, func(convCtx convey.C) {
var (
sceneId = 325
groupId = 1
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
res, err := d.QueryPreview(sceneId, groupId)
convCtx.Convey("Then err should be nil.res should not be nil.", func(convCtx convey.C) {
convCtx.So(err, convey.ShouldBeNil)
convCtx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoQueryUsefulParams(t *testing.T) {
convey.Convey("QueryUsefulParams", t, func(convCtx convey.C) {
var (
sceneId = 325
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
res, err := d.QueryUsefulParams(sceneId)
convCtx.Convey("Then err should be nil.res should not be nil.", func(convCtx convey.C) {
convCtx.So(err, convey.ShouldBeNil)
convCtx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoUpdateBindScene(t *testing.T) {
convey.Convey("UpdateBindScene", t, func(convCtx convey.C) {
var (
bindScene = &model.BindScene{
SceneID: 325,
ID: "2000",
}
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
err := d.UpdateBindScene(bindScene)
convCtx.Convey("Then err should be nil.", func(convCtx convey.C) {
convCtx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoQueryDrawRelation(t *testing.T) {
convey.Convey("QueryDrawRelation", t, func(convCtx convey.C) {
var (
scene = &model.Scene{
ID: 980,
}
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
res, err := d.QueryDrawRelation(scene)
convCtx.Convey("Then err should be nil.res should not be nil.", func(convCtx convey.C) {
convCtx.So(err, convey.ShouldBeNil)
convCtx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoDeleteDraft(t *testing.T) {
convey.Convey("DeleteDraft", t, func(convCtx convey.C) {
var (
scene = &model.Scene{
UserName: "chenmeng",
ID: 980,
}
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
err := d.DeleteDraft(scene)
convCtx.Convey("Then err should be nil.", func(convCtx convey.C) {
convCtx.So(err, convey.ShouldBeNil)
})
})
})
}
func TestDaoQueryConfig(t *testing.T) {
convey.Convey("QueryConfig", t, func(convCtx convey.C) {
var (
script = &model.Script{
SceneID: 325,
GroupID: 1,
}
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
res, err := d.QueryConfig(script)
convCtx.Convey("Then err should be nil.res should not be nil.", func(convCtx convey.C) {
convCtx.So(err, convey.ShouldBeNil)
convCtx.So(res, convey.ShouldNotBeNil)
})
})
})
}
func TestDaoDeleteScene(t *testing.T) {
convey.Convey("DeleteScene", t, func(convCtx convey.C) {
var (
scene = &model.Scene{
ID: 325,
}
)
convCtx.Convey("When everything goes positive", func(convCtx convey.C) {
err := d.DeleteScene(scene)
convCtx.Convey("Then err should be nil.", func(convCtx convey.C) {
convCtx.So(err, convey.ShouldBeNil)
})
})
})
}

View File

@@ -0,0 +1,197 @@
package dao
import (
"time"
"go-common/app/admin/ep/melloi/model"
)
//QueryScripts query script
func (d *Dao) QueryScripts(script *model.Script, pn int, ps int) (scripts []*model.Script, err error) {
script.Active = 1
err = d.DB.Table(model.Script{}.TableName()).Where(script).Order("id asc").Offset((pn - 1) * ps).Limit(ps).Find(&scripts).Error
return
}
//QueryScriptsByPage query scripts by page
func (d *Dao) QueryScriptsByPage(script *model.Script, pn, ps int32, treeNodes []string) (qsr *model.QueryScriptResponse, err error) {
script.TestType = 1
qsr = &model.QueryScriptResponse{}
gDB := d.DB.Table(model.Script{}.TableName()).Where("app in (?)", treeNodes)
if script.Department != "" && script.Project != "" && script.App != "" {
gDB = gDB.Where("department = ? and project = ? and app = ?", script.Department, script.Project, script.App)
}
if script.Department != "" && script.Project != "" {
gDB = gDB.Where("department = ? and project = ?", script.Department, script.Project)
}
if script.Department != "" {
gDB = gDB.Where("department = ?", script.Department)
}
if script.TestName != "" {
gDB = gDB.Where("test_name LIKE ? and test_type = ?", "%"+script.TestName+"%", 1)
}
if script.UpdateBy != "" {
gDB = gDB.Where("update_by LIKE ? and test_type = ?", "%"+script.UpdateBy+"%", 1)
}
if script.TestName == "" && script.UpdateBy == "" {
gDB = gDB.Where(script)
}
err = gDB.Where("active = 1").Count(&qsr.TotalSize).Order("ctime desc").Offset((pn - 1) * ps).Limit(ps).
Find(&qsr.Scripts).Error
qsr.PageSize = ps /**/
qsr.PageNum = pn
return
}
//QueryScriptsByPageWhiteName query by whiteName
func (d *Dao) QueryScriptsByPageWhiteName(script *model.Script, pn, ps int32) (qsr *model.QueryScriptResponse, err error) {
qsr = &model.QueryScriptResponse{}
script.TestType = 1
gDB := d.DB.Table(model.Script{}.TableName())
if script.TestName != "" {
gDB = gDB.Where("test_name LIKE ? and test_type = ?", "%"+script.TestName+"%", 1)
}
if script.UpdateBy != "" {
gDB = gDB.Where("update_by LIKE ? and test_type = ?", "%"+script.UpdateBy+"%", 1)
}
if script.TestName == "" && script.UpdateBy == "" {
gDB = gDB.Where(script)
}
err = gDB.Where("active = 1").Count(&qsr.TotalSize).Order("ctime desc").Offset((pn - 1) * ps).Limit(ps).
Find(&qsr.Scripts).Error
qsr.PageSize = ps /**/
qsr.PageNum = pn
return
}
//QueryScriptByID get script by id
func (d *Dao) QueryScriptByID(id int) (script *model.Script, err error) {
script = &model.Script{}
err = d.DB.Table(model.Script{}.TableName()).Where("id = ? and active = 1", id).First(script).Error
return
}
//QueryScriptsInID get script by id
func (d *Dao) QueryScriptsInID(id []int) (scripts []*model.Script, err error) {
err = d.DB.Table(model.Script{}.TableName()).Where("id in (?) and active = 1", id).Find(&scripts).Error
return
}
//CountQueryScripts count query scripts
func (d *Dao) CountQueryScripts(script *model.Script) (total int) {
d.DB.Table(model.Script{}.TableName()).Where(script).Count(&total)
return
}
//AddScript add script
func (d *Dao) AddScript(script *model.Script) (id int, groupId int, runOrder int, err error) {
if script.OutputParams == "[]" || script.OutputParams == "" {
script.OutputParams = "[{\"\":\"\"}]"
}
if script.APIHeader == "[]" || script.APIHeader == "" {
script.APIHeader = "[{\"\":\"\"}]"
}
if script.ArgumentString == "[]" || script.AssertionString == "" {
script.ArgumentString = "[{\"\":\"\"}]"
}
script.Active = 1
err = d.DB.Create(script).Error
id = script.ID
groupId = script.GroupID
runOrder = script.RunOrder
return
}
//QueryParams query params
func (d *Dao) QueryParams(script *model.Script, scene *model.Scene) (paramList *model.ParamList, err error) {
paramList = new(model.ParamList)
if scene.SceneType == 1 || scene.SceneType == 0 {
err = d.DB.Table(model.Script{}.TableName()).Select("id, group_id, run_order, output_params").Where("scene_id = ? and active = 1", script.SceneID).Order("group_id, run_order").Find(&paramList.ParamList).Error
} else if scene.SceneType == 2 {
err = d.DB.Table(model.Script{}.TableName()).Select("id, group_id, run_order, output_params").Where("scene_id = ? and group_id = ? and active = 1", script.SceneID, script.GroupID).Order("group_id, run_order").Find(&paramList.ParamList).Error
}
return
}
//AddScriptSnap add script snap
func (d *Dao) AddScriptSnap(scriptSnap *model.ScriptSnap) (id int, err error) {
scriptSnap.Ctime = time.Now()
scriptSnap.Mtime = time.Now()
err = d.DB.Create(scriptSnap).Error
id = scriptSnap.ID
return
}
//UpdateScript update script
func (d *Dao) UpdateScript(script *model.Script) (err error) {
script.Mtime = time.Now()
if err = d.DB.Exec("update script set is_async = ?, login = ?, keep_alive = ?, use_sign = ?, assertion = ?, conn_time_out = ?, resp_time_out = ?, "+
"use_data_file = ?, file_name = ?, params_name = ?, delimiter = ?, fusing = ?, use_business_stop = ?, business_stop_percent = ? where id = ?",
script.IsAsync, script.Login, script.KeepAlive, script.UseSign, script.Assertion, script.ConnTimeOut, script.RespTimeOut,
script.UseDataFile, script.FileName, script.ParamsName, script.Delimiter, script.Fusing, script.UseBusinessStop, script.BusinessStopPercent, script.ID).Error; err != nil {
return
}
if script.OutputParams == "[]" {
script.OutputParams = "[{\"\":\"\"}]"
}
if script.APIHeader == "[]" {
script.APIHeader = "[{\"\":\"\"}]"
}
if script.ArgumentString == "[]" {
script.ArgumentString = "[{\"\":\"\"}]"
}
//script.Active = 1
//return d.DB.Model(&model.Script{}).Save(script).Error
return d.DB.Model(&model.Script{}).Updates(script).Error
}
//UpdateScriptPart update scriptPart
func (d *Dao) UpdateScriptPart(script *model.Script) (err error) {
script.Mtime = time.Now()
if script.OutputParams == "[]" {
script.OutputParams = "[{\"\":\"\"}]"
}
if script.APIHeader == "[]" {
script.APIHeader = "[{\"\":\"\"}]"
}
if script.ArgumentString == "[]" {
script.ArgumentString = "[{\"\":\"\"}]"
}
//script.Active = 1
//return d.DB.Model(&model.Script{}).Save(script).Error
return d.DB.Model(&model.Script{}).Updates(script).Error
}
//AddScriptTimer add script timer
func (d *Dao) AddScriptTimer(script *model.Script) error {
return d.DB.Exec("update script set const_timer = ?, random_timer = ? where id = ?", script.ConstTimer, script.RandomTimer, script.ID).Error
}
//DelScript delete script
func (d *Dao) DelScript(id int) error {
return d.DB.Model(&model.Script{}).Where("id = ?", id).Update("active", 0).Error
}
//QueryScriptSnap query script snap
func (d *Dao) QueryScriptSnap(snap *model.ScriptSnap) (scriptSnap []*model.ScriptSnap, err error) {
err = d.DB.Table(model.ScriptSnap{}.TableName()).Where(snap).Find(&scriptSnap).Error
return
}
//ScriptHost query api domain name in script
func (d *Dao) ScriptHost(script *model.Script) (host string, err error) {
err = d.DB.Create(script).Error
host = script.Domain
return
}
////UpdateRunOrder Update Run Order
//func (d *Dao) UpdateRunOrder(runOrder int) error {
// return d.DB.Model(&model.Script{}).Where("ID=?", script.ID).Updates(script).Error
//}

View File

@@ -0,0 +1,129 @@
package dao
import (
"context"
"net/http"
"go-common/app/admin/ep/melloi/model"
"go-common/library/ecode"
"go-common/library/log"
)
const (
_treeTokenURI = "/v1/auth"
_treeNodeURI = "/v1/node/apptree"
_ajSessionID = "_AJSESSIONID"
_treeAdminURI = "/v1/node/role/"
_treeRoleAppURI = "/v1/node/role/app"
_treeRspCode = 90000
)
// QueryServiceTreeToken query service tree token by sessionID
func (d *Dao) QueryServiceTreeToken(c context.Context, sessionID string) (token string, err error) {
var (
req *http.Request
tokenURL = d.c.ServiceTree.Host + _treeTokenURI
res struct {
Code int `json:"code"`
Data *model.TokenResponse `json:"data"`
Message string `json:"message"`
Status int `json:"status"`
}
)
if req, err = d.newRequest(http.MethodGet, tokenURL, nil); err != nil {
return
}
req.Header.Set("Cookie", _ajSessionID+"="+sessionID)
if err = d.httpClient.Do(c, req, &res); err != nil {
log.Error("d.Token url(%s) res($s) error(%v)", tokenURL, res, err)
return
}
if res.Code != _treeRspCode {
err = ecode.MelloiTreeRequestErr
log.Error("d.Tree.Response url(%s) resCode(%s) error(%v)", tokenURL, res.Code, err)
return
}
token = res.Data.Token
return
}
// QueryUserTree query user tree by user token
func (d *Dao) QueryUserTree(c context.Context, token string) (tree *model.UserTree, err error) {
var (
url = d.c.ServiceTree.Host + _treeNodeURI
req *http.Request
res = &model.TreeResponse{}
)
if req, err = d.newRequest(http.MethodGet, url, nil); err != nil {
return
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-Authorization-Token", token)
if err = d.httpClient.Do(c, req, &res); err != nil {
log.Error("d.Token url(%s) error(%v)", url, err)
err = ecode.MerlinTreeRequestErr
return
}
if res.Code != _treeRspCode {
err = ecode.MelloiTreeRequestErr
log.Error("Get tree error(%v)", err)
return
}
tree = &res.Data
return
}
// QueryUserRoleApp query User role app
func (d *Dao) QueryUserRoleApp(c context.Context, token string) (ra []*model.RoleApp, err error) {
var (
url = d.c.ServiceTree.Host + _treeRoleAppURI
req *http.Request
res = &model.TreeRoleApp{}
)
if req, err = d.newRequest(http.MethodGet, url, nil); err != nil {
return
}
req.Header.Set("Context-Type", "application/json")
req.Header.Set("X-Authorization-Token", token)
if err = d.httpClient.Do(c, req, &res); err != nil {
log.Error("d.Token url(%s) error(%v)", url, err)
return
}
if res.Code != _treeRspCode {
err = ecode.MelloiTreeRequestErr
log.Error("get tree admin error(%v)", err)
return
}
ra = res.Data
return
}
//QueryTreeAdmin query tree admin
func (d *Dao) QueryTreeAdmin(c context.Context, path string, token string) (ta *model.TreeAdminResponse, err error) {
var (
url = d.c.ServiceTree.Host + _treeAdminURI + path
req *http.Request
)
if req, err = d.newRequest(http.MethodGet, url, nil); err != nil {
return
}
req.Header.Set("Context-Type", "application/json")
req.Header.Set("X-Authorization-Token", token)
if err = d.httpClient.Do(c, req, &ta); err != nil {
log.Error("d.Token url(%s) error(%v)", url, err)
return
}
if ta.Code != _treeRspCode {
err = ecode.MelloiTreeRequestErr
log.Error("get tree admin error(%v)", err)
return
}
return
}

View File

@@ -0,0 +1,25 @@
package dao
import (
"go-common/app/admin/ep/melloi/model"
"go-common/library/log"
)
// AddUser add user by user object
func (d *Dao) AddUser(user *model.User) error {
return d.DB.Create(user).Error
}
// QueryUserByUserName query user info by userName
func (d *Dao) QueryUserByUserName(userName string) (rows *model.User, err error) {
rows = &model.User{}
if err = d.DB.Where("name = ?", userName).First(rows).Error; err != nil {
log.Error("d.db.Where error(%v)", err)
}
return
}
// UpdateUser update user info
func (d *Dao) UpdateUser(user *model.User) error {
return d.DB.Model(&model.User{}).Update(user).Where("ID=?", user.ID).Error
}

View File

@@ -0,0 +1,14 @@
package dao
import (
"testing"
. "github.com/smartystreets/goconvey/convey"
)
func Test_User(t *testing.T) {
Convey("test QueryUser", t, func() {
_, err := d.QueryUserByUserName("hujianping")
So(err, ShouldBeNil)
})
}

View File

@@ -0,0 +1,65 @@
package dao
import (
"context"
"net/http"
"go-common/app/admin/ep/melloi/conf"
"go-common/app/admin/ep/melloi/model"
"go-common/library/log"
)
const (
_wechatGroup = "/ep/admin/saga/v2/wechat/appchat/send"
_wechatPerson = "/ep/admin/saga/v2/wechat/message/send"
)
//AddWechatSend send msg to group
func (d *Dao) AddWechatSend(c context.Context, cookie, content string) (msgSendRes *model.MsgSendRes, err error) {
var (
url = conf.Conf.Wechat.Host + _wechatGroup
req *http.Request
msgSendReq = &model.MsgSendReq{
ChatID: conf.Conf.Wechat.Chatid,
MsgType: conf.Conf.Wechat.Msgtype,
Text: model.MsgSendReqText{Content: content},
Safe: conf.Conf.Wechat.Safe,
}
)
if req, err = d.newRequest(http.MethodPost, url, msgSendReq); err != nil {
return
}
req.Header.Set("Cookie", cookie)
req.Header.Set("Content-Type", "application/json")
if err = d.httpClient.Do(c, req, &msgSendRes); err != nil {
log.Error("d.AddWechatSend url(%s) res($s) error(%v)", url, msgSendRes, err)
return
}
return
}
// PushWechatMsgToPerson send msg to users
func (d *Dao) PushWechatMsgToPerson(c context.Context, cookie string, users []string, msg string) (msgSendRes *model.MsgSendRes, err error) {
var (
url = conf.Conf.Wechat.Host + _wechatPerson
req *http.Request
msgSendReq = &model.MsgSendPersonReq{
Users: users,
Content: msg,
}
)
if req, err = d.newRequest(http.MethodPost, url, msgSendReq); err != nil {
return
}
req.Header.Set("Cookie", cookie)
req.Header.Set("Content-Type", "application/json")
if err = d.httpClient.Do(c, req, &msgSendRes); err != nil {
log.Error("d.WeChatPerson url(%s) res($s) error(%v)", url, msgSendRes, err)
return
}
return
}

667
app/admin/ep/melloi/db.sql Normal file
View File

@@ -0,0 +1,667 @@
/*
Navicat Premium Data Transfer
Source Server : 172.22.33.22
Source Server Type : MySQL
Source Server Version : 50633
Source Host : 172.22.33.22:3306
Source Schema : test
Target Server Type : MySQL
Target Server Version : 50633
File Encoding : 65001
Date: 17/12/2018 11:48:32
*/
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for apply
-- ----------------------------
DROP TABLE IF EXISTS `apply`;
CREATE TABLE `apply` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
`from` varchar(16) NOT NULL DEFAULT '' COMMENT '申请人',
`path` varchar(50) NOT NULL DEFAULT '' COMMENT '服务树path',
`to` varchar(16) NOT NULL DEFAULT '' COMMENT '操作人',
`status` tinyint(4) NOT NULL DEFAULT '-1' COMMENT '状态 -1 申请中 1 生效',
`active` tinyint(4) NOT NULL DEFAULT '-1' COMMENT '-1 無效 1生效',
`ctime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`mtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
`start_time` varchar(16) NOT NULL DEFAULT '' COMMENT '压测开始时间',
`end_time` varchar(16) NOT NULL DEFAULT '' COMMENT '压测结束时间',
PRIMARY KEY (`id`),
KEY `ix_mtime` (`mtime`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='权限申请表';
-- ----------------------------
-- Table structure for client_moni
-- ----------------------------
DROP TABLE IF EXISTS `client_moni`;
CREATE TABLE `client_moni` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
`script_id` int(11) NOT NULL DEFAULT '0' COMMENT '脚本ID',
`report_su_id` int(11) NOT NULL DEFAULT '0' COMMENT '报告ID',
`job_name` varchar(20) NOT NULL DEFAULT '' COMMENT '容器名',
`job_name_all` varchar(25) NOT NULL DEFAULT '' COMMENT '容器全名',
`cpu_used` varchar(25) NOT NULL DEFAULT '' COMMENT 'cpu使用率',
`elapsd_time` int(11) NOT NULL DEFAULT '0' COMMENT '执行时间',
`ctime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '创建时间',
`mtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
PRIMARY KEY (`id`),
KEY `ix_report_su_id` (`report_su_id`) USING BTREE,
KEY `ix_job_name` (`job_name`) USING BTREE,
KEY `ix_ctime` (`ctime`) USING BTREE,
KEY `ix_mtime` (`mtime`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='客户端监控表';
-- ----------------------------
-- Table structure for comment
-- ----------------------------
DROP TABLE IF EXISTS `comment`;
CREATE TABLE `comment` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '评论编号',
`report_id` int(11) NOT NULL DEFAULT '0' COMMENT '压测报告id',
`content` varchar(100) NOT NULL DEFAULT '' COMMENT '评论内容',
`user_name` varchar(500) NOT NULL DEFAULT '' COMMENT '用户名',
`status` tinyint(4) NOT NULL DEFAULT '1' COMMENT '评论状态 1 正常 2 已删除',
`submit_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '评论提交时间',
`ctime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`mtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`id`),
KEY `ix_report_id` (`report_id`),
KEY `ix_mtime` (`mtime`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='评论表';
-- ----------------------------
-- Table structure for draft
-- ----------------------------
DROP TABLE IF EXISTS `draft`;
CREATE TABLE `draft` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '草稿箱id',
`scene_id` int(11) NOT NULL COMMENT '场景id',
`user_name` varchar(30) NOT NULL DEFAULT '' COMMENT '用户名',
`is_active` tinyint(4) NOT NULL COMMENT '是否有效 0 无效 1 有效',
`ctime` datetime NOT NULL ON UPDATE CURRENT_TIMESTAMP,
`mtime` datetime NOT NULL ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
-- ----------------------------
-- Table structure for grpc
-- ----------------------------
DROP TABLE IF EXISTS `grpc`;
CREATE TABLE `grpc` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
`task_name` varchar(50) NOT NULL DEFAULT '' COMMENT '任务名称',
`department` varchar(50) NOT NULL DEFAULT '' COMMENT '部门',
`project` varchar(50) NOT NULL DEFAULT '' COMMENT '项目',
`app` varchar(50) NOT NULL DEFAULT '' COMMENT '应用',
`threads_sum` int(11) NOT NULL DEFAULT '1' COMMENT '线程数',
`ramp_up` int(11) NOT NULL DEFAULT '5' COMMENT '预热时间',
`loops` int(11) NOT NULL DEFAULT '-1' COMMENT '循环次数:-1:永久',
`load_time` int(11) NOT NULL DEFAULT '0' COMMENT '运行时长',
`host_name` varchar(50) NOT NULL DEFAULT '' COMMENT '域名|IP',
`port` int(6) NOT NULL DEFAULT '9000' COMMENT '端口',
`service_name` varchar(50) NOT NULL DEFAULT '' COMMENT '服务名称',
`proto_class_name` varchar(50) NOT NULL DEFAULT '' COMMENT 'proto类名称',
`pkg_path` varchar(50) NOT NULL DEFAULT '' COMMENT '包名称',
`asyn_call` tinyint(4) NOT NULL DEFAULT '-1' COMMENT '-1:false 1:true, 0:--',
`request_type` varchar(50) NOT NULL DEFAULT '' COMMENT '请求函数',
`request_method` varchar(50) NOT NULL DEFAULT '' COMMENT 'grpc方法',
`request_content` varchar(500) NOT NULL DEFAULT '' COMMENT 'grpc请求内容',
`response_type` varchar(50) NOT NULL DEFAULT '' COMMENT '返回函数',
`script_path` varchar(200) NOT NULL DEFAULT '' COMMENT 'proto文件路径',
`jar_path` varchar(255) NOT NULL COMMENT 'jar文件路径',
`jmx_path` varchar(200) NOT NULL DEFAULT '' COMMENT '生成jmx文件路径',
`jmx_log` varchar(200) NOT NULL DEFAULT '' COMMENT 'jmx执行log',
`jtl_log` varchar(200) NOT NULL DEFAULT '' COMMENT 'jtl log',
`ctime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`mtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
`active` tinyint(4) NOT NULL DEFAULT '1' COMMENT '0 失效 1 生效',
`update_by` varchar(20) NOT NULL DEFAULT '' COMMENT '更新人',
`is_async` varchar(4) NOT NULL DEFAULT '' COMMENT '是否异步',
`param_file_path` varchar(200) NOT NULL DEFAULT '' COMMENT '参数文件路径',
`param_names` varchar(100) NOT NULL DEFAULT '' COMMENT '参数名称,以逗号分隔',
`param_delimiter` varchar(5) NOT NULL DEFAULT '' COMMENT '参数分隔符,默认,',
`param_enable` varchar(16) NOT NULL DEFAULT '' COMMENT '是否可用',
PRIMARY KEY (`id`) USING BTREE,
KEY `ix_app` (`app`) USING BTREE,
KEY `ix_department_project_app` (`app`,`department`,`project`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='grpc脚本表';
-- ----------------------------
-- Table structure for grpc_snap
-- ----------------------------
DROP TABLE IF EXISTS `grpc_snap`;
CREATE TABLE `grpc_snap` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
`grpc_id` int(11) NOT NULL COMMENT '复制的脚本id',
`task_name` varchar(50) NOT NULL DEFAULT '' COMMENT '任务名称',
`department` varchar(50) NOT NULL DEFAULT '' COMMENT '部门',
`project` varchar(50) NOT NULL DEFAULT '' COMMENT '项目',
`app` varchar(50) NOT NULL DEFAULT '' COMMENT '应用',
`threads_sum` int(11) NOT NULL DEFAULT '1' COMMENT '线程数',
`ramp_up` int(11) NOT NULL DEFAULT '5' COMMENT '预热时间',
`loops` int(11) NOT NULL DEFAULT '-1' COMMENT '循环次数:-1:永久',
`load_time` int(11) NOT NULL DEFAULT '0' COMMENT '运行时长',
`host_name` varchar(50) NOT NULL DEFAULT '' COMMENT '域名|IP',
`port` int(6) NOT NULL DEFAULT '9000' COMMENT '端口',
`service_name` varchar(50) NOT NULL DEFAULT '' COMMENT '服务名称',
`proto_class_name` varchar(50) NOT NULL DEFAULT '' COMMENT 'proto类名称',
`pkg_path` varchar(50) NOT NULL DEFAULT '' COMMENT '包名称',
`asyn_call` tinyint(4) NOT NULL DEFAULT '-1' COMMENT '-1:false 1:true, 0:--',
`request_type` varchar(50) NOT NULL DEFAULT '' COMMENT '请求函数',
`request_method` varchar(50) NOT NULL DEFAULT '' COMMENT 'grpc方法',
`request_content` varchar(500) NOT NULL DEFAULT '' COMMENT 'grpc请求内容',
`response_type` varchar(50) NOT NULL DEFAULT '' COMMENT '返回函数',
`script_path` varchar(200) NOT NULL DEFAULT '' COMMENT 'proto文件路径',
`jar_path` varchar(255) NOT NULL COMMENT 'jar文件路径',
`jmx_path` varchar(200) NOT NULL DEFAULT '' COMMENT '生成jmx文件路径',
`jmx_log` varchar(200) NOT NULL DEFAULT '' COMMENT 'jmx执行log',
`jtl_log` varchar(200) NOT NULL DEFAULT '' COMMENT 'jtl log',
`ctime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`mtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
`active` tinyint(4) NOT NULL DEFAULT '1' COMMENT '0 失效 1 生效',
`update_by` varchar(20) NOT NULL DEFAULT '' COMMENT '更新人',
`execute_id` varchar(20) NOT NULL COMMENT '执行id',
`is_async` varchar(4) NOT NULL DEFAULT '' COMMENT '是否异步',
`param_file_path` varchar(200) NOT NULL DEFAULT '' COMMENT '参数文件路径',
`param_names` varchar(100) NOT NULL DEFAULT '' COMMENT '参数名称,以逗号分隔',
`param_delimiter` varchar(5) NOT NULL DEFAULT '' COMMENT '参数分隔符,默认,',
`param_enable` varchar(16) NOT NULL DEFAULT '' COMMENT '是否支持参数化',
PRIMARY KEY (`id`) USING BTREE,
KEY `ix_app` (`app`) USING BTREE,
KEY `ix_department_project_app` (`app`,`department`,`project`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='grpc脚本表';
-- ----------------------------
-- Table structure for label
-- ----------------------------
DROP TABLE IF EXISTS `label`;
CREATE TABLE `label` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
`name` varchar(50) NOT NULL DEFAULT '' COMMENT '标签名称',
`description` varchar(100) NOT NULL DEFAULT '' COMMENT '描述',
`color` varchar(100) NOT NULL DEFAULT '' COMMENT '标签颜色',
`ctime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`mtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
`active` tinyint(4) NOT NULL DEFAULT '1' COMMENT '0 失效 1 生效',
PRIMARY KEY (`id`),
KEY `ix_name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='标签表';
-- ----------------------------
-- Table structure for label_relation
-- ----------------------------
DROP TABLE IF EXISTS `label_relation`;
CREATE TABLE `label_relation` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
`label_id` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '标签ID label.id',
`label_name` varchar(50) NOT NULL DEFAULT '' COMMENT '标签名称',
`target_id` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '目标ID',
`type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '0 默认 1 脚本 2报告',
`ctime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`mtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
`active` tinyint(4) NOT NULL DEFAULT '1' COMMENT '0 失效 1 生效',
PRIMARY KEY (`id`),
KEY `ix_type` (`type`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='标签关系表';
-- ----------------------------
-- Table structure for order
-- ----------------------------
DROP TABLE IF EXISTS `order`;
CREATE TABLE `order` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '工单编号',
`name` varchar(500) NOT NULL DEFAULT '' COMMENT '工单名称',
`broker` varchar(100) NOT NULL DEFAULT '' COMMENT '研发对接人',
`test_background` varchar(500) NOT NULL DEFAULT '' COMMENT '测试背景',
`type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '0: 开发自测, 1:工程效能团队测试',
`test_type` tinyint(4) NOT NULL DEFAULT '1' COMMENT '1压力测试 2负载测试 3 容量测试 4 健壮性测试 5 恢复性测试 6 浪涌测试 7配置选型测试 8 稳定性测试 9 特殊业务场景测试',
`test_target` text NOT NULL COMMENT '测试指标',
`api_list` text NOT NULL COMMENT '接口列 隔开',
`api_doc` varchar(500) NOT NULL COMMENT '接口文档',
`limit_user` varchar(500) NOT NULL DEFAULT '' COMMENT '用户限制',
`limit_ip` varchar(100) NOT NULL DEFAULT '' COMMENT 'ip限制',
`limit_visit` varchar(100) NOT NULL DEFAULT '' COMMENT '访问次数限制',
`server_conf` varchar(100) NOT NULL DEFAULT '' COMMENT '服务器配置',
`dependent_component` varchar(500) NOT NULL DEFAULT '' COMMENT '依赖组件',
`dependent_business` varchar(500) NOT NULL DEFAULT '' COMMENT '依赖业务方',
`test_data_from` varchar(500) NOT NULL DEFAULT '' COMMENT '测试数据获取',
`test_host` varchar(100) NOT NULL DEFAULT '' COMMENT '测试机器地址',
`moni_redis` varchar(200) NOT NULL COMMENT 'redis moni address',
`moni_memcache` varchar(200) NOT NULL COMMENT 'memcache moni address',
`moni_docker` varchar(200) NOT NULL COMMENT 'docker moni address',
`moni_api` varchar(200) NOT NULL COMMENT 'api moni address',
`moni_mysql` varchar(200) NOT NULL COMMENT 'mysql moni address',
`moni_elasticsearch` varchar(200) NOT NULL COMMENT 'elasticsearch moni address',
`moni_other` varchar(200) NOT NULL COMMENT 'other moni address',
`test_cycles` int(11) NOT NULL COMMENT '测试周期',
`script_id` varchar(500) NOT NULL DEFAULT '',
`machine_id` varchar(200) NOT NULL DEFAULT '' COMMENT '机器编号',
`department` varchar(20) NOT NULL COMMENT '部门',
`project` varchar(20) NOT NULL COMMENT '项目',
`app` varchar(20) NOT NULL COMMENT '应用',
`status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '工单状态 0 申请中 -1 打回 1 排期中 2 进行中 3 测试完成',
`update_by` int(11) NOT NULL DEFAULT '0' COMMENT '更新者',
`apply_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '申请日期',
`handler` varchar(50) NOT NULL DEFAULT '' COMMENT '处理人',
`active` tinyint(4) NOT NULL DEFAULT '-1' COMMENT '状态 -1 无效 1 生效',
`ctime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`mtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`id`),
KEY `ix_name` (`name`(255)),
KEY `ix_active` (`active`),
KEY `ix_apply_date` (`apply_date`),
KEY `ix_mtime` (`mtime`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='工单表';
-- ----------------------------
-- Table structure for order_admin
-- ----------------------------
DROP TABLE IF EXISTS `order_admin`;
CREATE TABLE `order_admin` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
`user_name` varchar(16) NOT NULL DEFAULT '' COMMENT '用户姓名',
`ctime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '创建时间',
`mtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`id`),
KEY `ix_mtime` (`mtime`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='工单管理员';
-- ----------------------------
-- Table structure for project
-- ----------------------------
DROP TABLE IF EXISTS `project`;
CREATE TABLE `project` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '项目id',
`name` varchar(120) NOT NULL COMMENT '项目名称',
`update_by` bigint(20) NOT NULL COMMENT '修改人员id',
`create_time` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT '创建时间',
`manager` varchar(100) DEFAULT '' COMMENT '项目管理员',
`active` tinyint(4) NOT NULL DEFAULT '-1' COMMENT '-1:失效1:生效',
PRIMARY KEY (`id`),
KEY `idx_name` (`name`),
KEY `idx_create_time` (`create_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='项目表';
-- ----------------------------
-- Table structure for ptest_job
-- ----------------------------
DROP TABLE IF EXISTS `ptest_job`;
CREATE TABLE `ptest_job` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
`script_id` int(11) NOT NULL DEFAULT '0' COMMENT '脚本id',
`report_su_id` int(11) NOT NULL DEFAULT '0' COMMENT '报告ID',
`job_name` varchar(20) NOT NULL DEFAULT '' COMMENT 'job 名',
`active` int(11) NOT NULL DEFAULT '1' COMMENT '是否有效,1 有效,-1 无效',
`ctime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '创建时间',
`mtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
`execute_id` varchar(50) NOT NULL COMMENT '执行id',
`host_ip` varchar(50) NOT NULL DEFAULT '',
PRIMARY KEY (`id`),
KEY `ix_report_su_id` (`report_su_id`) USING BTREE,
KEY `ix_script_id` (`script_id`) USING BTREE,
KEY `ix_mtime` (`mtime`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='报告脚本容器关联表';
-- ----------------------------
-- Table structure for report_graph
-- ----------------------------
DROP TABLE IF EXISTS `report_graph`;
CREATE TABLE `report_graph` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
`test_name` varchar(50) NOT NULL DEFAULT '' COMMENT '接口名',
`test_name_nick` varchar(50) NOT NULL DEFAULT '' COMMENT '接口别名',
`count` bigint(20) NOT NULL DEFAULT '0' COMMENT '总请求数',
`qps` int(11) NOT NULL DEFAULT '0' COMMENT 'qps',
`avg_time` int(11) NOT NULL DEFAULT '0' COMMENT '平均时间',
`min` int(11) NOT NULL DEFAULT '0' COMMENT '最小时间',
`max` int(11) NOT NULL DEFAULT '0' COMMENT '最大时间',
`error` int(11) NOT NULL DEFAULT '0' COMMENT '错误数',
`fail_percent` varchar(11) NOT NULL DEFAULT '' COMMENT '失败率',
`ninety_time` int(11) NOT NULL DEFAULT '0' COMMENT '90 分位',
`ninety_five_time` int(11) NOT NULL DEFAULT '0' COMMENT '95分位',
`ninety_nine_time` int(11) NOT NULL DEFAULT '0' COMMENT '99分位',
`net_io` int(11) NOT NULL DEFAULT '0' COMMENT '网络流量',
`code_ell` int(11) NOT NULL DEFAULT '0' COMMENT 'code200',
`code_wll` int(11) NOT NULL DEFAULT '0' COMMENT 'code500',
`code_wly` int(11) NOT NULL DEFAULT '0' COMMENT 'code501',
`code_wle` int(11) NOT NULL DEFAULT '0' COMMENT 'code502',
`code_wls` int(11) NOT NULL DEFAULT '0' COMMENT 'code504',
`code_sll` int(11) NOT NULL DEFAULT '0' COMMENT 'code400',
`code_sly` int(11) NOT NULL DEFAULT '0' COMMENT 'code401',
`code_sls` int(11) NOT NULL DEFAULT '0' COMMENT 'code404',
`code_kong` int(11) NOT NULL DEFAULT '0' COMMENT 'code_kong',
`code_non_http` int(11) NOT NULL DEFAULT '0' COMMENT 'code_non_http',
`code_others` int(11) NOT NULL DEFAULT '0' COMMENT 'code_others',
`pod_name` varchar(25) NOT NULL DEFAULT '' COMMENT '容器全名',
`threads_sum` int(11) NOT NULL DEFAULT '0' COMMENT '实时线程数',
`elapsd_time` int(11) NOT NULL DEFAULT '0' COMMENT '持续时间',
`ctime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '创建时间',
`mtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`fifty_time` int(11) NOT NULL DEFAULT '0' COMMENT '50分位',
`code301` int(11) NOT NULL DEFAULT '0' COMMENT 'code301',
`code302` int(11) NOT NULL DEFAULT '0' COMMENT 'code302',
PRIMARY KEY (`id`),
KEY `ix_test_name_nick` (`test_name_nick`) USING BTREE,
KEY `ix_test_name` (`test_name`) USING BTREE,
KEY `ix_mtime` (`mtime`) USING BTREE,
KEY `ix_pod_name` (`pod_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='报告图表';
-- ----------------------------
-- Table structure for report_info
-- ----------------------------
DROP TABLE IF EXISTS `report_info`;
CREATE TABLE `report_info` (
`id` int(20) NOT NULL AUTO_INCREMENT COMMENT '报告id',
`job_name` varchar(100) DEFAULT '',
`project_name` varchar(100) DEFAULT '',
`test_name` varchar(200) DEFAULT '' COMMENT '接口名',
`request_count` varchar(200) DEFAULT '' COMMENT '总请求数',
`avg_time` varchar(200) DEFAULT '' COMMENT '平均响应时间',
`mid_time` varchar(200) DEFAULT '' COMMENT '中分位',
`ninety_time` varchar(200) DEFAULT '' COMMENT '90分位',
`ninety_five_time` varchar(200) DEFAULT '' COMMENT '95分位',
`ninety_nine_time` varchar(200) DEFAULT '' COMMENT '收件人',
`min` varchar(200) DEFAULT '',
`max` varchar(200) DEFAULT '',
`fail_percent` varchar(200) DEFAULT '' COMMENT '失败率',
`qps` varchar(200) DEFAULT '' COMMENT 'qps',
`net_io` varchar(200) DEFAULT '' COMMENT '网络流量',
`ctime` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP COMMENT '创建时间',
`src_name` varchar(100) DEFAULT '' COMMENT '测试报告源文件',
`update_by` varchar(20) DEFAULT '' COMMENT '创建人',
`final` int(4) DEFAULT '0' COMMENT '0 中间报告1 最终报告',
`active` tinyint(4) DEFAULT '1' COMMENT '状态0 无效1 生效',
`mtime` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `job_name` (`job_name`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='报告表';
-- ----------------------------
-- Table structure for report_summary
-- ----------------------------
DROP TABLE IF EXISTS `report_summary`;
CREATE TABLE `report_summary` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
`script_id` int(11) NOT NULL,
`script_snap_id` int(11) NOT NULL,
`execute_id` varchar(50) NOT NULL,
`department` varchar(50) NOT NULL,
`project` varchar(50) NOT NULL,
`app` varchar(50) NOT NULL,
`test_name` varchar(50) NOT NULL DEFAULT '' COMMENT '接口名',
`test_name_nick` varchar(2000) NOT NULL DEFAULT '' COMMENT '接口别名',
`job_name` varchar(20) NOT NULL DEFAULT '' COMMENT '容器名',
`count` bigint(20) NOT NULL DEFAULT '0' COMMENT '总请求数',
`qps` int(11) NOT NULL DEFAULT '0' COMMENT 'qps',
`avg_time` int(11) NOT NULL DEFAULT '0' COMMENT '平均时间',
`min` int(11) NOT NULL DEFAULT '0' COMMENT '最小时间',
`max` int(11) NOT NULL DEFAULT '0' COMMENT '最大时间',
`error` int(11) NOT NULL DEFAULT '0' COMMENT '错误数',
`fail_percent` varchar(11) NOT NULL DEFAULT '' COMMENT '失败率',
`ninety_time` int(11) NOT NULL DEFAULT '0' COMMENT '90 分位',
`ninety_five_time` int(11) NOT NULL DEFAULT '0' COMMENT '95分位',
`ninety_nine_time` int(11) NOT NULL DEFAULT '0' COMMENT '99分位',
`net_io` int(11) NOT NULL DEFAULT '0' COMMENT '网络流量',
`elapsd_time` int(11) NOT NULL DEFAULT '0' COMMENT '持续时间',
`test_status` int(11) NOT NULL DEFAULT '2' COMMENT '1 :完成, 2 :执行中3 中断',
`user_name` varchar(20) NOT NULL DEFAULT '' COMMENT '执行人',
`res_jtl` varchar(500) NOT NULL,
`jmeter_log` varchar(500) DEFAULT NULL,
`docker_sum` int(11) NOT NULL DEFAULT '0' COMMENT '容器数',
`ctime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`mtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
`debug` int(4) NOT NULL,
`active` tinyint(4) NOT NULL DEFAULT '0' COMMENT '是否有效 1 有效',
`scene_id` int(11) NOT NULL DEFAULT '0' COMMENT '场景id',
`type` tinyint(4) DEFAULT '0',
`load_time` int(11) NOT NULL DEFAULT '0' COMMENT '执行时间',
`fifty_time` int(11) NOT NULL DEFAULT '0' COMMENT '50分位',
PRIMARY KEY (`id`),
KEY `ix_test_name` (`test_name`) USING BTREE,
KEY `ix_mtime` (`mtime`) USING BTREE,
KEY `ix_excute_id` (`execute_id`) USING BTREE,
KEY `ix_scene_id` (`scene_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='报告汇总表';
-- ----------------------------
-- Table structure for report_timely
-- ----------------------------
DROP TABLE IF EXISTS `report_timely`;
CREATE TABLE `report_timely` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'id',
`test_name` varchar(50) CHARACTER SET utf8mb4 DEFAULT '' COMMENT '接口名',
`count` bigint(20) NOT NULL DEFAULT '0' COMMENT '总请求数',
`qps` int(11) NOT NULL DEFAULT '0' COMMENT 'qps',
`avg_time` int(11) NOT NULL DEFAULT '0' COMMENT '平均响应时间',
`min` int(11) NOT NULL DEFAULT '0' COMMENT '最小时间',
`max` int(11) NOT NULL DEFAULT '0' COMMENT '最大时间',
`error` int(11) NOT NULL DEFAULT '0' COMMENT '错误数',
`fail_percent` varchar(11) NOT NULL DEFAULT '' COMMENT '失败率',
`ninety_time` int(11) NOT NULL DEFAULT '0' COMMENT '90分位',
`ninety_five_time` int(11) NOT NULL DEFAULT '0' COMMENT '95分位',
`ninety_nine_time` int(11) NOT NULL DEFAULT '0' COMMENT '99分位',
`net_io` int(11) NOT NULL DEFAULT '0' COMMENT '网络流量',
`code_ell` int(11) NOT NULL,
`code_wll` int(11) NOT NULL,
`code_wly` int(11) DEFAULT NULL,
`code_wle` int(11) DEFAULT NULL,
`code_wls` int(11) DEFAULT NULL,
`code_sll` int(11) DEFAULT NULL,
`code_sly` int(11) DEFAULT NULL,
`code_sls` int(11) DEFAULT NULL,
`code_kong` int(11) DEFAULT NULL,
`code_non_http` int(11) DEFAULT NULL,
`code_others` int(11) DEFAULT NULL,
`pod_name` varchar(25) NOT NULL DEFAULT '' COMMENT '容器全名',
`threads_sum` int(11) NOT NULL DEFAULT '0' COMMENT '实时线程数',
`ctime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`mtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
`fifty_time` int(11) NOT NULL DEFAULT '0' COMMENT '50分位',
`code301` int(11) NOT NULL DEFAULT '0' COMMENT 'code301',
`code302` int(11) NOT NULL DEFAULT '0' COMMENT 'code302',
PRIMARY KEY (`id`),
KEY `ix_test_name` (`test_name`) USING BTREE,
KEY `ix_pod_name` (`pod_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Table structure for scene
-- ----------------------------
DROP TABLE IF EXISTS `scene`;
CREATE TABLE `scene` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '场景id',
`scene_name` varchar(255) CHARACTER SET utf8 NOT NULL DEFAULT '' COMMENT '场景名称',
`scene_type` tinyint(4) NOT NULL COMMENT '场景类型 1 自动分组 2 自定义分组 根据最后保存接口/接口组设置的页面类型来更新该字段的值',
`user_name` varchar(30) CHARACTER SET utf8 NOT NULL DEFAULT '' COMMENT '用户名',
`is_draft` varchar(4) NOT NULL COMMENT '是否为草稿 0非草稿 1草稿',
`is_debug` varchar(4) NOT NULL COMMENT 'is_debug 是否调试 0 执行压测 1 调试',
`jmeter_file_path` varchar(100) DEFAULT NULL,
`department` varchar(20) DEFAULT NULL,
`project` varchar(20) DEFAULT NULL,
`app` varchar(20) DEFAULT NULL,
`jmeter_log` varchar(100) DEFAULT NULL,
`res_jtl` varchar(100) DEFAULT NULL,
`ctime` datetime NOT NULL ON UPDATE CURRENT_TIMESTAMP,
`mtime` datetime NOT NULL ON UPDATE CURRENT_TIMESTAMP,
`is_active` varchar(4) NOT NULL COMMENT '草稿是否有效',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
-- ----------------------------
-- Table structure for script
-- ----------------------------
DROP TABLE IF EXISTS `script`;
CREATE TABLE `script` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`tree_id` bigint(20) DEFAULT NULL,
`project_id` bigint(20) DEFAULT NULL COMMENT '脚本id',
`type` int(2) DEFAULT NULL COMMENT '脚本类型,默认 1 为 jmeter',
`project_name` varchar(100) DEFAULT NULL COMMENT '项目名称',
`test_name` varchar(50) DEFAULT NULL COMMENT '接口名称',
`threads_sum` int(6) DEFAULT NULL COMMENT '总线程数',
`ready_time` int(6) DEFAULT NULL,
`load_time` int(6) DEFAULT NULL COMMENT '压测持续时间',
`proc_type` varchar(16) DEFAULT '' COMMENT '脚本协议类型',
`url` varchar(500) DEFAULT '',
`domain` varchar(50) DEFAULT '' COMMENT '被测试的域名',
`port` varchar(16) NOT NULL DEFAULT '' COMMENT '端口',
`login` varchar(16) NOT NULL DEFAULT '' COMMENT '是否登录',
`path` varchar(500) DEFAULT NULL COMMENT '路径',
`method` varchar(10) DEFAULT NULL COMMENT '方法post 或者 get ',
`content_type` varchar(50) CHARACTER SET latin1 DEFAULT '',
`cookie` varchar(500) CHARACTER SET latin1 DEFAULT '',
`data` varchar(1000) DEFAULT NULL COMMENT 'json body',
`assertion` varchar(50) DEFAULT NULL COMMENT '断言',
`update_by` varchar(50) DEFAULT NULL COMMENT '更新人',
`save_path` varchar(200) DEFAULT NULL,
`res_jtl` varchar(100) DEFAULT '',
`jmeter_log` varchar(100) DEFAULT NULL,
`ctime` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
`active` tinyint(4) DEFAULT '1' COMMENT '状态 1 为有效 -1 为无效',
`upload` varchar(16) DEFAULT '' COMMENT '是否上传',
`mtime` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
`department` varchar(50) NOT NULL DEFAULT '' COMMENT '部門',
`project` varchar(50) NOT NULL DEFAULT '' COMMENT '项目',
`app` varchar(50) NOT NULL DEFAULT '' COMMENT '应用',
`api_header` varchar(500) NOT NULL DEFAULT '' COMMENT '请求头',
`argument_map` varchar(500) NOT NULL DEFAULT '' COMMENT 'POST提交参数',
`use_data_file` varchar(16) NOT NULL DEFAULT '' COMMENT '使用文件: 0 不使用 1 使用',
`file_name` varchar(100) NOT NULL DEFAULT '' COMMENT '文件名称',
`params_name` varchar(16) NOT NULL DEFAULT '' COMMENT '参数名称',
`delimiter` varchar(16) NOT NULL DEFAULT '' COMMENT '文本切割符',
`loops` tinyint(4) NOT NULL DEFAULT '-1' COMMENT '脚本循环次数:-1 永久循环',
`file_split` varchar(16) NOT NULL DEFAULT '' COMMENT '是否切割文件0不切割 1切割',
`split_num` tinyint(4) NOT NULL,
`use_sign` varchar(2) NOT NULL DEFAULT '' COMMENT '是否需要签名',
`conn_time_out` int(6) NOT NULL DEFAULT '0' COMMENT '连接超时时间',
`resp_time_out` int(6) NOT NULL DEFAULT '0' COMMENT '响应超时时间',
`test_type` tinyint(4) NOT NULL COMMENT '压测类型 0 http 1 grpc 2 场景',
`scene_id` int(11) NOT NULL COMMENT '场景id 关联scene表中的自增长id',
`output_params` varchar(255) NOT NULL DEFAULT '' COMMENT '接口输出参数,多个用英文,隔开',
`group_id` int(11) NOT NULL,
`run_order` int(11) NOT NULL,
`script_path` varchar(200) NOT NULL DEFAULT '' COMMENT '脚本路径',
`json_path` varchar(100) NOT NULL DEFAULT '' COMMENT 'JSON 解析参数路径',
`is_async` varchar(4) NOT NULL DEFAULT '' COMMENT '是否异步',
`multipart_path` varchar(100) NOT NULL DEFAULT '' COMMENT 'multipart 路径',
`multipart_file` varchar(50) NOT NULL DEFAULT '' COMMENT 'multipart 文件名',
`multipart_param` varchar(50) NOT NULL DEFAULT '' COMMENT 'multipart 参数',
`mime_type` varchar(50) NOT NULL DEFAULT '' COMMENT 'mime_type 类型',
`fusing` int(4) NOT NULL DEFAULT '0' COMMENT '自动熔断成功率',
`keep_alive` varchar(4) NOT NULL DEFAULT '1' COMMENT '是否使用长连接',
PRIMARY KEY (`id`),
KEY `tree_id` (`tree_id`) USING BTREE,
KEY `project_id` (`project_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Table structure for script_snap
-- ----------------------------
DROP TABLE IF EXISTS `script_snap`;
CREATE TABLE `script_snap` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`script_id` int(11) NOT NULL DEFAULT '0' COMMENT '脚本id',
`tree_id` bigint(20) DEFAULT NULL,
`project_id` bigint(20) DEFAULT NULL COMMENT '脚本id',
`execute_id` varchar(50) DEFAULT NULL,
`type` tinyint(2) DEFAULT NULL COMMENT '脚本类型,默认 1 为 jmeter',
`project_name` varchar(100) DEFAULT NULL COMMENT '项目名称',
`test_name` varchar(50) DEFAULT NULL COMMENT '接口名称',
`threads_sum` int(6) DEFAULT NULL COMMENT '总线程数',
`ready_time` int(6) DEFAULT NULL,
`load_time` int(6) DEFAULT NULL COMMENT '压测持续时间',
`proc_type` varchar(16) DEFAULT '' COMMENT '脚本协议类型',
`url` varchar(500) DEFAULT '',
`domain` varchar(50) DEFAULT '' COMMENT '被测试的域名',
`port` varchar(16) NOT NULL DEFAULT '' COMMENT '端口',
`login` varchar(16) NOT NULL DEFAULT '' COMMENT '是否登录',
`path` varchar(500) DEFAULT NULL COMMENT '路径',
`method` varchar(10) DEFAULT NULL COMMENT '方法post 或者 get ',
`content_type` varchar(50) CHARACTER SET latin1 DEFAULT '',
`cookie` varchar(500) CHARACTER SET latin1 DEFAULT '',
`data` varchar(1000) DEFAULT NULL COMMENT 'json body',
`assertion` varchar(50) DEFAULT NULL COMMENT '断言',
`update_by` varchar(50) DEFAULT NULL COMMENT '更新人',
`save_path` varchar(200) DEFAULT NULL,
`res_jtl` varchar(100) DEFAULT '',
`jmeter_log` varchar(100) DEFAULT NULL,
`ctime` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
`active` tinyint(4) DEFAULT '1' COMMENT '状态 1 为有效 -1 为无效',
`upload` varchar(16) DEFAULT '' COMMENT '是否上传',
`mtime` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
`department` varchar(50) NOT NULL DEFAULT '' COMMENT '部門',
`project` varchar(50) NOT NULL DEFAULT '' COMMENT '项目',
`app` varchar(50) NOT NULL DEFAULT '' COMMENT '应用',
`api_header` varchar(500) NOT NULL DEFAULT '' COMMENT '请求头',
`argument_map` varchar(500) NOT NULL DEFAULT '' COMMENT 'POST提交参数',
`use_data_file` varchar(16) NOT NULL DEFAULT '' COMMENT '使用文件: 0 不使用 1 使用',
`file_name` varchar(200) NOT NULL DEFAULT '' COMMENT '文件名',
`params_name` varchar(16) NOT NULL DEFAULT '' COMMENT '参数名称',
`delimiter` varchar(16) NOT NULL DEFAULT '' COMMENT '文本切割符',
`loops` tinyint(4) NOT NULL DEFAULT '-1' COMMENT '脚本循环次数:-1 永久循环',
`file_split` varchar(16) NOT NULL,
`split_num` tinyint(4) NOT NULL,
`use_sign` varchar(16) NOT NULL,
`conn_time_out` int(6) NOT NULL DEFAULT '0' COMMENT '连接超时时间',
`scene_id` int(11) NOT NULL,
`resp_time_out` int(6) NOT NULL DEFAULT '0' COMMENT '响应超时时间',
`json_path` varchar(100) NOT NULL DEFAULT '' COMMENT 'JSON 解析参数路径',
`group_id` int(11) NOT NULL DEFAULT '0' COMMENT '分组id',
`is_async` varchar(4) NOT NULL DEFAULT '' COMMENT '是否异步',
`multipart_path` varchar(100) NOT NULL DEFAULT '' COMMENT 'multipart 路径',
`multipart_file` varchar(50) NOT NULL DEFAULT '' COMMENT 'multipart 文件名',
`multipart_param` varchar(50) NOT NULL DEFAULT '' COMMENT 'multipart 参数',
`mime_type` varchar(50) NOT NULL DEFAULT '' COMMENT 'mime_type 类型',
`fusing` int(4) NOT NULL DEFAULT '0' COMMENT '自动熔断成功率',
`keep_alive` varchar(4) NOT NULL DEFAULT '1' COMMENT '是否使用长连接',
PRIMARY KEY (`id`),
KEY `tree_id` (`tree_id`) USING BTREE,
KEY `project_id` (`project_id`) USING BTREE,
KEY `excute_id` (`execute_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='脚本快照表';
-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '用户id',
`name` varchar(100) NOT NULL DEFAULT '' COMMENT '用户名字',
`email` varchar(50) NOT NULL DEFAULT '' COMMENT '用户邮箱',
`active` tinyint(4) NOT NULL DEFAULT '-1' COMMENT '是否有效:-1 无效1 有效',
`accept` tinyint(4) NOT NULL DEFAULT '-1' COMMENT '-1 不允许访问 1 允许访问',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户表';
-- ----------------------------
-- Table structure for work_order
-- ----------------------------
DROP TABLE IF EXISTS `work_order`;
CREATE TABLE `work_order` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '工单id',
`name` varchar(1000) NOT NULL COMMENT '工单名称',
`content` mediumtext COMMENT '工单正文',
`type` tinyint(4) DEFAULT '0' COMMENT '0: 开发自测, 1:EP测试',
`script_id` bigint(20) DEFAULT '0' COMMENT '脚本id默认0',
`machine_id` bigint(20) DEFAULT '0' COMMENT '机器id默认0',
`project_id` bigint(20) NOT NULL COMMENT '项目id',
`status` tinyint(4) DEFAULT '0' COMMENT '工单状态:0申请中-1打回1排期中2进行中3、测试完成',
`update_by` bigint(20) NOT NULL COMMENT '更新者',
`apply_date` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT '申请日期',
`active` tinyint(4) DEFAULT '-1' COMMENT '状态:-1 无效1 生效',
PRIMARY KEY (`id`),
KEY `idx_name` (`name`(255)),
KEY `idx_machine_id` (`machine_id`),
KEY `idx_project_id` (`project_id`),
KEY `idx_active` (`active`),
KEY `idx_apply_date` (`apply_date`)
) ENGINE=InnoDB CHARSET=utf8 COMMENT='工单表';
SET FOREIGN_KEY_CHECKS = 1;

View File

@@ -0,0 +1,57 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = [
"apply.go",
"clientmoni.go",
"cluster.go",
"comment.go",
"file.go",
"grpc.go",
"http.go",
"job.go",
"label.go",
"order.go",
"order_admin.go",
"ptest.go",
"rank.go",
"report.go",
"scene.go",
"script.go",
"tree.go",
"user.go",
],
importpath = "go-common/app/admin/ep/melloi/http",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/admin/ep/melloi/conf:go_default_library",
"//app/admin/ep/melloi/model:go_default_library",
"//app/admin/ep/melloi/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/binding:go_default_library",
"//library/net/http/blademaster/middleware/permit: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"],
)

View File

@@ -0,0 +1,52 @@
package http
import (
"go-common/app/admin/ep/melloi/model"
"go-common/library/ecode"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/http/blademaster/binding"
)
func queryApply(c *bm.Context) {
qar := model.QueryApplyRequest{}
if err := c.BindWith(&qar, binding.Form); err != nil {
c.JSON(nil, err)
return
}
if err := qar.Verify(); err != nil {
c.JSON(nil, err)
return
}
c.JSON(srv.QueryApply(&qar))
}
func addApply(c *bm.Context) {
apply := model.Apply{}
if err := c.BindWith(&apply, binding.JSON); err != nil {
c.JSON(nil, err)
return
}
cookie := c.Request.Header.Get("Cookie")
c.JSON(nil, srv.AddApply(c, cookie, &apply))
}
func updateApply(c *bm.Context) {
apply := model.Apply{}
if err := c.BindWith(&apply, binding.JSON); err != nil {
c.JSON(nil, err)
return
}
cookie := c.Request.Header.Get("Cookie")
c.JSON(nil, srv.UpdateApply(cookie, &apply))
}
func delApply(c *bm.Context) {
v := new(struct {
ID int64 `form:"id"`
})
if err := c.Bind(v); err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
c.JSON(nil, srv.DeleteApply(v.ID))
}

View File

@@ -0,0 +1,27 @@
package http
import (
"go-common/app/admin/ep/melloi/model"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/http/blademaster/binding"
)
func queryClientMoni(c *bm.Context) {
var (
cli model.ClientMoni
resMap = make(map[string]interface{})
)
if err := c.BindWith(&cli, binding.Form); err != nil {
c.JSON(nil, err)
return
}
clientMonis, err := srv.QueryClientMoni(&cli)
if err != nil {
log.Error("srv.QueryClientMoni err (%v)", err)
return
}
resMap["clientMonis"] = clientMonis
c.JSON(resMap, err)
}

View File

@@ -0,0 +1,10 @@
package http
import (
bm "go-common/library/net/http/blademaster"
)
//ClusterInfo get cluster infomation
func ClusterInfo(c *bm.Context) {
c.JSON(srv.ClusterInfo(c))
}

View File

@@ -0,0 +1,46 @@
package http
import (
"go-common/app/admin/ep/melloi/model"
"go-common/library/ecode"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/http/blademaster/binding"
)
func queryComment(c *bm.Context) {
comment := model.Comment{}
if err := c.BindWith(&comment, binding.Form); err != nil {
c.JSON(nil, err)
return
}
c.JSON(srv.QueryComment(&comment))
}
func addComment(c *bm.Context) {
comment := model.Comment{}
if err := c.BindWith(&comment, binding.JSON); err != nil {
c.JSON(nil, err)
return
}
c.JSON(nil, srv.AddComment(&comment))
}
func updateComment(c *bm.Context) {
comment := model.Comment{}
if err := c.BindWith(&comment, binding.JSON); err != nil {
c.JSON(nil, err)
return
}
c.JSON(nil, srv.UpdateComment(&comment))
}
func deleteComment(c *bm.Context) {
v := new(struct {
ID int64 `form:"id"`
})
if err := c.Bind(v); err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
c.JSON(nil, srv.DeleteComment(v.ID))
}

View File

@@ -0,0 +1,118 @@
package http
import (
"bytes"
"io"
"mime/multipart"
"path"
"strconv"
"time"
"go-common/app/admin/ep/melloi/model"
"go-common/library/ecode"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/http/blademaster/binding"
)
const (
_upLoadSuccess = "上传成功"
_upLoadFail = "上传失败"
)
func upload(c *bm.Context) {
uploadParam := model.UploadParam{}
if err := c.BindWith(&uploadParam, binding.Form); err != nil {
c.JSON(nil, err)
return
}
formFile, header, err := c.Request.FormFile("file")
if err != nil {
log.Error("Get form file failed,error(%v)", err)
c.JSON(nil, err)
return
}
var upLoadResultMap = make(map[string]string)
upLoadResultMap["result"] = _upLoadSuccess
scriptID, scriptPath, err := srv.Upload(c, &uploadParam, formFile, header)
if err != nil {
log.Error("Write file failed, error(%v)", err)
upLoadResultMap["result"] = _upLoadFail
c.JSON(upLoadResultMap, err)
return
}
upLoadResultMap["script_id"] = strconv.Itoa(scriptID)
upLoadResultMap["script_path"] = scriptPath
upLoadResultMap["full_path"] = path.Join(scriptPath, header.Filename)
c.JSON(upLoadResultMap, nil)
}
func uploadDependProto(c *bm.Context) {
var (
upParam = &model.UploadParam{}
header *multipart.FileHeader
formFile multipart.File
err error
)
if err = c.BindWith(upParam, binding.Form); err != nil {
return
}
if formFile, header, err = c.Request.FormFile("file"); err != nil {
c.JSON(nil, err)
return
}
c.JSON(srv.UploadAndGetProtoInfo(c, upParam, formFile, header))
}
func compileProtoFile(c *bm.Context) {
uploadParam := model.UploadParam{}
if err := c.BindWith(&uploadParam, binding.JSON); err != nil {
c.JSON(nil, err)
return
}
fileName := strconv.FormatInt(time.Now().UTC().UnixNano(), 10)
c.JSON(srv.CompileProtoFile(uploadParam.ScriptPath, fileName))
}
func uploadImg(c *bm.Context) {
file, header, err := c.Request.FormFile("file")
if err != nil {
log.Error("get IMG file error (%v)", err)
c.JSON(nil, err)
return
}
defer file.Close()
buff := new(bytes.Buffer)
if _, err = io.Copy(buff, file); err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
c.JSON(srv.UploadImg(c, buff.Bytes(), header.Filename))
}
func readFile(c *bm.Context) {
file := c.Request.Form.Get("file")
limit := c.Request.Form.Get("limit")
var upLoadResultMap = make(map[string]string)
data, err := srv.ReadFile(c, file, limit)
if err != nil {
return
}
upLoadResultMap["data"] = data
c.JSON(upLoadResultMap, nil)
}
func downloadFile(c *bm.Context) {
filePath := c.Request.Form.Get("file_path")
c.JSON(nil, srv.DownloadFile(c, filePath, c.Writer))
}
func isFileExists(c *bm.Context) {
fileName := c.Request.Form.Get("file_name")
exists, err := srv.IsFileExists(c, fileName)
var ResultMap = make(map[string]string)
ResultMap["fileExists"] = strconv.FormatBool(exists)
c.JSON(ResultMap, err)
}

View File

@@ -0,0 +1,209 @@
package http
import (
"net/http"
"path/filepath"
"go-common/app/admin/ep/melloi/model"
"go-common/library/ecode"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/http/blademaster/binding"
)
func getProto(c *bm.Context) {
v := new(struct {
Path string `form:"path"`
})
if err := c.Bind(v); err != nil {
return
}
path, fileName := filepath.Split(v.Path)
var (
res = make(map[string]interface{})
err error
)
if res, err = srv.ProtoParsing(path, fileName); err != nil {
log.Error("parser grpc error(%v)", err)
c.JSON(nil, err)
return
}
if err = srv.CreateGRPCImportDir(res, path); err != nil {
c.JSON(nil, err)
return
}
c.JSON(res, err)
}
func createDependencyPath(c *bm.Context) {
protoPath := &model.ProtoPathModel{}
if err := c.BindWith(protoPath, binding.JSON); err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
c.JSON(nil, srv.CreateProtoImportDir(protoPath))
}
func grpcQuickStart(c *bm.Context) {
var (
userName *http.Cookie
qsReq = &model.GRPCQuickStartRequest{}
err error
cookie string
)
cookie = c.Request.Header.Get("Cookie")
if err = c.BindWith(qsReq, binding.JSON); err != nil {
c.JSON(nil, err)
return
}
if userName, err = c.Request.Cookie("username"); err != nil {
c.JSON(nil, ecode.AccessKeyErr)
return
}
c.JSON(srv.GRPCQuickStart(c, qsReq, userName.Value, cookie))
}
func saveGrpc(c *bm.Context) {
var (
qsReq = &model.GRPCQuickStartRequest{}
err error
)
if err = c.BindWith(qsReq, binding.JSON); err != nil {
c.JSON(nil, err)
return
}
c.JSON(nil, srv.SaveGRPCQuickStart(c, qsReq))
}
func runGrpc(c *bm.Context) {
var (
grpc = model.GRPC{}
err error
userName *http.Cookie
cookie string
)
cookie = c.Request.Header.Get("Cookie")
if err = c.BindWith(&grpc, binding.JSON); nil != err {
c.JSON(nil, err)
return
}
if userName, err = c.Request.Cookie("username"); err != nil {
c.JSON(nil, ecode.AccessKeyErr)
return
}
c.JSON(srv.GRPCRunByModel(c, &grpc, userName.Value, cookie))
}
func runGrpcByScriptId(c *bm.Context) {
var (
userName *http.Cookie
err error
grpcExeReq = &model.GRPCExecuteScriptRequest{}
cookie string
)
cookie = c.Request.Header.Get("Cookie")
if err = c.BindWith(grpcExeReq, binding.JSON); err != nil {
return
}
if userName, err = c.Request.Cookie("username"); err != nil {
c.JSON(nil, ecode.AccessKeyErr)
return
}
c.JSON(srv.GRPCRunByScriptID(c, grpcExeReq, userName.Value, cookie))
}
func grpcAddScript(c *bm.Context) {
grpcReq := model.GRPCAddScriptRequest{}
if err := c.BindWith(&grpcReq, binding.JSON); err != nil {
c.JSON(nil, err)
return
}
c.JSON(srv.GRPCAddScript(c, &grpcReq))
}
func queryGrpc(c *bm.Context) {
qgr := model.QueryGRPCRequest{}
if err := c.BindWith(&qgr, binding.Form); err != nil {
c.JSON(nil, err)
}
if err := qgr.Verify(); err != nil {
c.JSON(nil, err)
return
}
sessionID, err := c.Request.Cookie("_AJSESSIONID")
if err != nil {
c.JSON(nil, err)
return
}
c.JSON(srv.QueryGrpc(c, sessionID.Value, &qgr))
}
func deleteGrpc(c *bm.Context) {
v := new(struct {
ID int `form:"id"`
})
if err := c.Bind(v); err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
c.JSON(nil, srv.DeleteGrpc(v.ID))
}
func updateGrpc(c *bm.Context) {
grpc := model.GRPC{}
if err := c.BindWith(&grpc, binding.JSON); err != nil {
c.JSON(nil, err)
return
}
qgr := &model.GRPCAddScriptRequest{}
qgr.ThreadsSum = grpc.ThreadsSum
qgr.RampUp = grpc.RampUp
qgr.Loops = grpc.Loops
qgr.LoadTime = grpc.LoadTime
qgr.HostName = grpc.HostName
qgr.Port = grpc.Port
qgr.ServiceName = grpc.ServiceName
qgr.ProtoClassName = grpc.ProtoClassName
qgr.PkgPath = grpc.PkgPath
qgr.RequestType = grpc.RequestType
qgr.ResponseType = grpc.ResponseType
qgr.ScriptPath = grpc.ScriptPath
qgr.RequestMethod = grpc.RequestMethod
qgr.RequestContent = grpc.RequestContent
qgr.TaskName = grpc.TaskName
qgr.ParamFilePath = grpc.ParamFilePath
qgr.ParamNames = grpc.ParamNames
qgr.ParamDelimiter = grpc.ParamDelimiter
g, err := srv.CreateJmx(c, qgr)
if err != nil {
c.JSON(nil, err)
return
}
grpc.JmxPath = g.JmxPath
grpc.JtlLog = g.JtlLog
grpc.JmxLog = g.JmxLog
c.JSON(nil, srv.UpdateGrpc(&grpc))
}
func queryGrpcSnap(c *bm.Context) {
v := new(struct {
ID int `form:"id"`
})
if err := c.Bind(v); err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
c.JSON(srv.QueryGRPCSnapByID(v.ID))
}

View File

@@ -0,0 +1,235 @@
package http
import (
"net/http"
"go-common/app/admin/ep/melloi/conf"
"go-common/app/admin/ep/melloi/service"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/http/blademaster/middleware/permit"
)
var (
srv *service.Service
// AuthSrv Auth Service
AuthSrv *permit.Permit
)
// Init init
func Init(c *conf.Config, s *service.Service) {
srv = s
AuthSrv = permit.New2(c.PermitGRPC)
engine := bm.NewServer(c.BM)
engine.Ping(ping)
router(engine)
if err := engine.Start(); err != nil {
log.Error("xhttp.Serve2 error(%v)", err)
panic(err)
}
}
// router init outer router api path
func router(e *bm.Engine) {
e.Register(register)
version := e.Group("/ep/admin/melloi/v1", AuthSrv.Permit2(""))
{
home := version.Group("/rank")
{
home.GET("/trees/query", treesQuery)
home.GET("/top/http/query", topHttpQuery)
home.GET("/top/dept/query", topDeptQuery)
home.GET("/treenum/query", treeNumQuery)
home.GET("/buildline/query", buildLineQuery)
home.GET("/stateline/query", stateLineQuery)
home.GET("/top/grpc/query", topGrpcQuery)
home.GET("/top/scene/query", topSceneQuery)
}
user := version.Group("/user")
{
user.GET("/query", queryUser)
user.POST("/update", updateUser)
}
//手工压测
order := version.Group("/order")
{
order.GET("/query", queryOrder)
order.POST("/add", addOrder)
order.POST("/update", updateOrder)
order.GET("/del", delOrder)
order.POST("/report/add", addOrderReport)
order.GET("/report/query", queryOrderReport)
}
//非压测时间段压测申请
apply := version.Group("/apply")
{
apply.GET("/query", queryApply)
apply.POST("/add", addApply)
apply.POST("/update", updateApply)
apply.GET("/del", delApply)
}
orderAdmin := version.Group("/admin")
{
orderAdmin.GET("/query", queryOrderAdmin)
orderAdmin.GET("/add", addOrderAdmin)
}
script := version.Group("/script")
{
script.POST("/gettgroup", getThreadGroup)
script.POST("/add", addAndExecuteScript)
script.POST("/grpc/add", grpcAddScript)
script.POST("/update", updateScript)
script.POST("/updateall", updateScriptAll)
script.GET("/delete", delScript)
script.GET("/query", queryScripts)
script.GET("/query/free", queryScripysFree)
script.GET("/querysnap", queryScriptSnap)
script.POST("/url/check", urlCheck)
script.POST("/addtimer", addTimer)
}
scene := version.Group("/scene")
{
scene.POST("/addscene/auto", AddAndExecuScene)
scene.GET("/draft/query", queryDraft)
scene.POST("/update", updateScene)
scene.POST("/add", addScene)
scene.POST("/save", saveScene)
scene.POST("/saveorder", saveOrder)
scene.GET("/relation/query", queryRelation)
scene.GET("/api/query", queryAPI)
scene.POST("/api/delete", deleteAPI)
scene.POST("/group/config/add", addConfig)
scene.GET("/tree/query", queryTree)
scene.GET("/query", queryScenes)
scene.POST("/doptest", doScenePtest)
scene.POST("/doptest/batch", doScenePtestBatch)
scene.GET("/existapi/query", queryExistAPI)
scene.GET("/preview/query", queryPreview)
scene.GET("/params/query", queryParams)
scene.POST("/bindScene/update", updateBindScene)
scene.GET("/drawrelation/query", queryDrawRelation)
scene.POST("/script/add", addSceneScript)
scene.POST("/draft/delete", deleteDraft)
scene.GET("/group/config/query", queryConfig)
scene.GET("/delete", deleteScene)
scene.POST("/copy", copyScene)
scene.GET("/fusing/query", queryFusing)
}
run := version.Group("/run")
{
run.GET("/time/check", runTimeCheck)
run.POST("/grpc/run", runGrpc)
run.GET("/grpc/query", queryGrpc)
run.POST("/grpc/update", updateGrpc)
run.GET("/grpc/delete", deleteGrpc)
run.GET("/grpc/snap/query", queryGrpcSnap)
run.GET("/proto/query", getProto)
}
file := version.Group("/file")
{
file.POST("/upload", upload)
file.POST("/proto/refer/upload", uploadDependProto)
file.GET("/read", readFile)
file.GET("/download", downloadFile)
file.GET("/exists", isFileExists)
file.POST("/img", uploadImg)
file.POST("/proto/compile", compileProtoFile)
}
tree := version.Group("/tree")
{
tree.GET("/query", queryUserTree)
tree.GET("/admin", queryTreeAdmin)
}
report := version.Group("report")
{
report.POST("/update/summary", updateReportSummary)
report.GET("/query", queryReportSummarys)
report.POST("/query/regraph", queryReGraph)
report.POST("/query/regraphavg", queryReGraphAvg)
report.GET("/update/status", updateReportStatus)
report.GET("/del", delReport)
report.GET("/query/id", queryReportByID)
}
moni := version.Group("moni")
{
moni.GET("/client", queryClientMoni)
}
ptest := version.Group("ptest")
{
ptest.GET("/add", addPtest)
ptest.GET("/reduce", reducePtest)
ptest.GET("/queryalljob", queryAllJob)
ptest.GET("/queryalljob/free", queryAllJobFree)
ptest.GET("/stop", stopPtest)
ptest.GET("/stopall", stopAllPtest)
ptest.GET("/doptest", doPtest)
ptest.GET("/doptest/scriptid", doPtestByScriptId)
ptest.POST("/grpc/quickstart", grpcQuickStart)
ptest.POST("/grpc/qksave", saveGrpc)
ptest.POST("/grpc/run", runGrpcByScriptId)
ptest.POST("/grpc/createpath", createDependencyPath)
ptest.POST("/doptestfile", doPtestByFile)
ptest.POST("/dobatchptest", doPtestBatch)
ptest.POST("/dodebug", doDebug)
}
cluster := version.Group("/cluster")
{
cluster.GET("/info", ClusterInfo)
job := version.Group("/job")
{
job.POST("/add", addJob)
job.POST("/delete/batch", deleteJobBatch)
job.DELETE("/delete", deleteJob)
job.GET("/get", Job)
job.GET("/clean/query", queryClearnableDocker)
job.GET("/clean", cleanNotRunningJob)
}
}
comment := version.Group("/comment")
{
comment.GET("/query", queryComment)
comment.POST("/add", addComment)
comment.POST("/update", updateComment)
comment.GET("/delete", deleteComment)
}
label := version.Group("/label")
{
label.GET("/query", queryLabels)
label.POST("/add", addLabel)
label.GET("/del", delLabel)
label.POST("/relation/add", addLabelRelation)
label.GET("/relation/del", delLabelRelation)
}
}
versiond := e.Group("/ep/admin/melloi/v2")
{
script := versiond.Group("script")
{
script.POST("/addsample", addJmeterSample)
script.POST("/addtgroup", addThreadGroup)
}
file := versiond.Group("/file")
{
file.GET("/download", downloadFile)
}
job := versiond.Group("/job")
{
job.GET("/force/delete", forceDelete)
}
}
}
func register(c *bm.Context) {
c.JSON(map[string]interface{}{}, nil)
}
func ping(c *bm.Context) {
if err := srv.Ping(c); err != nil {
log.Error("ping error(%v)", err)
c.AbortWithStatus(http.StatusServiceUnavailable)
}
}

View File

@@ -0,0 +1,52 @@
package http
import (
"go-common/app/admin/ep/melloi/model"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/http/blademaster/binding"
)
func addJob(c *bm.Context) {
job := model.Job{}
if err := c.BindWith(&job, binding.JSON); nil != err {
c.JSON(nil, err)
return
}
c.JSON(srv.AddJob(c, job))
}
func deleteJob(c *bm.Context) {
name := c.Request.Form.Get("name")
c.JSON(srv.DeleteJob(c, name))
}
func deleteJobBatch(c *bm.Context) {
JobBatch := model.JobBatch{}
if err := c.BindWith(&JobBatch, binding.JSON); nil != err {
c.JSON(nil, err)
return
}
c.JSON(srv.DeleteJobBatch(c, JobBatch), nil)
}
//Job get job info
func Job(c *bm.Context) {
name := c.Request.Form.Get("name")
c.JSON(srv.Job(c, name))
}
func forceDelete(c *bm.Context) {
ptestJob := model.PtestJob{}
if err := c.BindWith(&ptestJob, binding.Form); err != nil {
c.JSON(nil, err)
return
}
c.JSON(srv.ForceDeleteJob(c, ptestJob.ReportSuID))
}
func queryClearnableDocker(c *bm.Context) {
c.JSON(srv.QueryCleanableDocker(c))
}
func cleanNotRunningJob(c *bm.Context) {
c.JSON(nil, srv.CleanJob(c))
}

View File

@@ -0,0 +1,53 @@
package http
import (
"go-common/app/admin/ep/melloi/model"
"go-common/library/ecode"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/http/blademaster/binding"
)
func queryLabels(c *bm.Context) {
c.JSON(srv.QueryLabel(c))
}
func addLabel(c *bm.Context) {
label := model.Label{}
if err := c.BindWith(&label, binding.JSON); err != nil {
c.JSON(nil, err)
return
}
c.JSON(nil, srv.AddLabel(&label))
}
func delLabel(c *bm.Context) {
v := new(struct {
ID int64 `form:"id"`
})
if err := c.Bind(v); err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
c.JSON(nil, srv.DeleteLabel(v.ID))
}
func addLabelRelation(c *bm.Context) {
lr := model.LabelRelation{}
if err := c.BindWith(&lr, binding.JSON); err != nil {
c.JSON(nil, err)
return
}
c.JSON(nil, srv.AddLabelRelation(&lr))
}
func delLabelRelation(c *bm.Context) {
v := new(struct {
ID int64 `form:"id"`
})
if err := c.Bind(v); err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
c.JSON(nil, srv.DeleteLabelRelation(v.ID))
}

View File

@@ -0,0 +1,77 @@
package http
import (
"strconv"
"go-common/app/admin/ep/melloi/model"
"go-common/library/ecode"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/http/blademaster/binding"
)
func queryOrder(c *bm.Context) {
qor := model.QueryOrderRequest{}
if err := c.BindWith(&qor, binding.Form); err != nil {
c.JSON(nil, err)
return
}
if err := qor.Verify(); err != nil {
c.JSON(nil, err)
return
}
c.JSON(srv.QueryOrder(&qor))
}
func addOrder(c *bm.Context) {
order := model.Order{}
if err := c.BindWith(&order, binding.JSON); err != nil {
c.JSON(nil, err)
return
}
c.JSON(nil, srv.AddOrder(&order))
}
func updateOrder(c *bm.Context) {
order := model.Order{}
if err := c.BindWith(&order, binding.JSON); err != nil {
c.JSON(nil, err)
return
}
c.JSON(nil, srv.UpdateOrder(&order))
}
func delOrder(c *bm.Context) {
v := new(struct {
ID int64 `form:"id"`
})
if err := c.Bind(v); err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
c.JSON(nil, srv.DelOrder(v.ID))
}
func addOrderReport(c *bm.Context) {
report := new(model.OrderReport)
if err := c.BindWith(&report, binding.JSON); err != nil {
c.JSON(nil, err)
return
}
nameStr := ""
if username, err := c.Request.Cookie("username"); err == nil || username != nil {
nameStr = username.Value
}
c.JSON(nil, srv.AddReport(nameStr, report))
}
func queryOrderReport(c *bm.Context) {
params := c.Request.Form
orderID := params.Get("order_id")
oid, err := strconv.ParseInt(orderID, 10, 64)
if err != nil || oid <= 0 {
c.JSON(nil, ecode.RequestErr)
return
}
c.JSON(srv.QueryReportByOrderID(oid))
}

View File

@@ -0,0 +1,22 @@
package http
import (
"go-common/app/admin/ep/melloi/model"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/http/blademaster/binding"
)
// get administrator for order by current username
func queryOrderAdmin(c *bm.Context) {
userName, _ := c.Request.Cookie("username")
c.JSON(srv.QueryOrderAdmin(userName.Value))
}
// add administrator for order
func addOrderAdmin(c *bm.Context) {
admin := model.OrderAdmin{}
if err := c.BindWith(&admin, binding.Form); err != nil {
return
}
c.JSON(nil, srv.AddOrderAdmin(&admin))
}

View File

@@ -0,0 +1,243 @@
package http
import (
"encoding/json"
"go-common/app/admin/ep/melloi/model"
"go-common/app/admin/ep/melloi/service"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/http/blademaster/binding"
)
//excute performTest
func doPtest(c *bm.Context) {
var (
script model.Script
ptestParam model.DoPtestParam
)
userName := c.Request.Form.Get("userName")
param := c.Request.Form.Get("param")
resJtl := c.Request.Form.Get("resJtl")
jmeterLog := c.Request.Form.Get("jmeterLog")
cookie := c.Request.Header.Get("Cookie")
if err := json.Unmarshal([]byte(param), &script); err != nil {
log.Error("sorry,script err(%v)", err)
c.JSON(nil, err)
return
}
log.Info("接口名:(%s),压测脚本路径:(%s)", script.TestName, script.SavePath)
if script.Upload {
testNames := service.QueryTestNamesByJmfile(script.SavePath)
ptestParam = model.DoPtestParam{
TestNames: testNames,
FileName: script.SavePath,
LoadTime: 1800,
UserName: userName,
Upload: true,
ProjectName: script.ProjectName,
FileSplit: script.FileSplit,
SplitNum: script.SplitNum,
APIHeader: script.APIHeader,
}
} else {
ptestParam = model.DoPtestParam{
TestNames: service.StringToSlice(script.TestName),
FileName: script.SavePath,
LoadTime: script.LoadTime,
UserName: userName,
URL: script.URL,
FileSplit: script.FileSplit,
SplitNum: script.SplitNum,
APIHeader: script.APIHeader,
}
}
ptestParam.Department = script.Department
ptestParam.Project = script.Project
ptestParam.APP = script.App
ptestParam.Domain = script.Domain
ptestParam.Cookie = cookie
ptestParam.JmeterLog = jmeterLog
ptestParam.ResJtl = resJtl
ptestParam.ScriptID = script.ID
ptestParam.UseBusinessStop = script.UseBusinessStop
ptestParam.BusinessStopPercent = script.BusinessStopPercent
ptestParam.Fusing = script.Fusing
c.JSON(srv.DoPtest(c, ptestParam))
}
//addPtest 加压
func addPtest(c *bm.Context) {
var ptestAdd model.PtestAdd
if err := c.BindWith(&ptestAdd, binding.Form); err != nil {
c.JSON(nil, err)
return
}
log.Info("AddPtest ----")
c.JSON(nil, srv.AddPtest(c, ptestAdd))
}
//stopPtest
func stopPtest(c *bm.Context) {
var ptestJob model.PtestJob
if err := c.BindWith(&ptestJob, binding.Form); err != nil {
c.JSON(nil, err)
return
}
c.JSON(nil, srv.StopPtest(c, ptestJob))
}
//stopAllPtest
func stopAllPtest(c *bm.Context) {
var allPtestStop model.AllPtestStop
if err := c.BindWith(&allPtestStop, binding.Form); err != nil {
c.JSON(nil, err)
return
}
c.JSON(srv.QueryOrStopAllPtestByJobName(c, allPtestStop.ReportSuID, true, 3))
}
//reducePtest
func reducePtest(c *bm.Context) {
var (
reducePtest model.ReducePtest
resMap = make(map[string]interface{})
)
if err := c.BindWith(&reducePtest, binding.Form); err != nil {
c.JSON(nil, err)
return
}
message, err := srv.ReducePtest(c, reducePtest)
if err != nil {
return
}
resMap["message"] = message
c.JSON(resMap, err)
}
//queryAllJob
func queryAllJob(c *bm.Context) {
var (
ptestJob model.PtestJob
resMap = make(map[string]interface{})
)
if err := c.BindWith(&ptestJob, binding.Form); err != nil {
c.JSON(nil, err)
return
}
ptestJobs, err := srv.QueryOrStopAllPtestByJobName(c, ptestJob.ReportSuID, false, 3)
if err != nil {
log.Error("query ptestJob err", err)
return
}
resMap["ptest_jobs"] = ptestJobs
c.JSON(resMap, err)
}
//queryAllJobFree queryAll JobFree
func queryAllJobFree(c *bm.Context) {
var (
ptestJob model.PtestJob
resMap = make(map[string]interface{})
)
if err := c.BindWith(&ptestJob, binding.Form); err != nil {
c.JSON(nil, err)
return
}
ptestJobs, err := srv.QueryAllJobFree(c, &ptestJob)
if err != nil {
log.Error("query ptestJob err", err)
return
}
resMap["ptest_jobs"] = ptestJobs
c.JSON(resMap, err)
}
//doDebug
func doDebug(c *bm.Context) {
var script model.Script
var ptestParam model.DoPtestParam
param := c.Request.Form.Get("param")
userName := c.Request.Form.Get("userName")
if err := json.Unmarshal([]byte(param), &script); err != nil {
log.Error("sorry,script err(%v)", err)
c.JSON(nil, err)
return
}
log.Info("接口名:(%s),压测脚本路径:(%s)", script.TestName, script.SavePath)
if script.Upload {
ptestParam = model.DoPtestParam{
TestNames: service.QueryTestNamesByJmfile(script.SavePath),
FileName: script.SavePath,
LoadTime: 1800,
UserName: userName,
Upload: true,
ProjectName: script.ProjectName,
ResJtl: script.ResJtl,
JmeterLog: script.JmeterLog,
Department: script.Department,
Project: script.Project,
APP: script.App,
ScriptID: script.ID,
}
} else {
ptestParam = model.DoPtestParam{
TestNames: service.StringToSlice(script.TestName),
FileName: script.SavePath,
LoadTime: script.LoadTime,
UserName: userName,
ResJtl: script.ResJtl,
JmeterLog: script.JmeterLog,
Department: script.Department,
Project: script.Project,
APP: script.App,
ScriptID: script.ID,
Domain: script.Domain,
}
}
c.JSON(srv.DoPtest(c, ptestParam))
}
func doPtestByFile(c *bm.Context) {
var script model.Script
if err := c.BindWith(&script, binding.JSON); err != nil {
c.JSON(nil, err)
return
}
resJtl := script.ResJtl
jmeterLog := script.JmeterLog
script.ResJtl = ""
script.JmeterLog = ""
resp, err := srv.DoPtestByFile(c, script, resJtl, jmeterLog)
if err != nil {
c.JSON(err, nil)
return
}
c.JSON(resp, err)
}
//excute batch ptest
func doPtestBatch(c *bm.Context) {
var PtestBatch model.PtestBatch
if err := c.BindWith(&PtestBatch, binding.JSON); err != nil {
c.JSON(nil, err)
return
}
cookie := c.Request.Header.Get("Cookie")
status, _ := srv.DoPtestArr(c, PtestBatch, cookie)
var doPostMap = make(map[string]string)
doPostMap["status"] = status
c.JSON(doPostMap, nil)
}
//doPtestByScriptId
func doPtestByScriptId(c *bm.Context) {
var script model.Script
if err := c.BindWith(&script, binding.Form); err != nil {
c.JSON(nil, err)
return
}
cookie := c.Request.Header.Get("Cookie")
executor := c.Request.Form.Get("executor")
c.JSON(srv.DoPtestByScriptId(c, &script, cookie, executor))
}

View File

@@ -0,0 +1,49 @@
package http
import (
"go-common/app/admin/ep/melloi/model"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/http/blademaster/binding"
)
func treesQuery(c *bm.Context) {
c.JSON(srv.TreesQuery())
}
func treeNumQuery(c *bm.Context) {
c.JSON(srv.TreeNumQuery())
}
func topHttpQuery(c *bm.Context) {
c.JSON(srv.TopHttpQuery())
}
func topGrpcQuery(c *bm.Context) {
c.JSON(srv.TopGrpcQuery())
}
func topSceneQuery(c *bm.Context) {
c.JSON(srv.TopSceneQuery())
}
func topDeptQuery(c *bm.Context) {
c.JSON(srv.TopDeptQuery())
}
func buildLineQuery(c *bm.Context) {
rank := model.Rank{}
summary := model.ReportSummary{}
if err := c.BindWith(&rank, binding.Form); err != nil {
c.JSON(nil, err)
return
}
if err := c.BindWith(&summary, binding.Form); err != nil {
c.JSON(nil, err)
return
}
c.JSON(srv.BuildLineQuery(&rank, &summary))
}
func stateLineQuery(c *bm.Context) {
c.JSON(srv.StateLineQuery())
}

View File

@@ -0,0 +1,106 @@
package http
import (
"strconv"
"go-common/app/admin/ep/melloi/model"
"go-common/library/ecode"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/http/blademaster/binding"
)
func updateReportSummary(c *bm.Context) {
reportSummary := model.ReportSummary{}
if err := c.BindWith(&reportSummary, binding.JSON); nil != err {
c.JSON(nil, err)
return
}
var ResultMap = make(map[string]string)
status, err := srv.UpdateReportSummary(&reportSummary)
ResultMap["status"] = status
c.JSON(ResultMap, err)
}
func queryReportSummarys(c *bm.Context) {
qrsr := model.QueryReportSuRequest{}
if err := c.BindWith(&qrsr, binding.Form); err != nil {
c.JSON(nil, err)
return
}
if err := qrsr.Verify(); err != nil {
c.JSON(nil, err)
return
}
sessionID, err := c.Request.Cookie("_AJSESSIONID")
if err != nil {
c.JSON(nil, err)
return
}
res, err := srv.QueryReportSummarys(c, sessionID.Value, &qrsr)
if err != nil {
log.Error("queryScripts Error", err)
return
}
c.JSON(res, err)
}
func queryReportByID(c *bm.Context) {
v := new(struct {
ID int `form:"id"`
})
if err := c.Bind(v); err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
c.JSON(srv.QueryReportByID(v.ID))
}
func queryReGraph(c *bm.Context) {
reGraphParam := model.QueryReGraphParam{}
if err := c.BindWith(&reGraphParam, binding.JSON); err != nil {
c.JSON(nil, err)
return
}
log.Info("TestNameNicks:(%s)", reGraphParam.TestNameNicks)
reportGraphs, err := srv.QueryReGraph(reGraphParam.TestNameNicks)
var resultGraphMap = make(map[string][][]model.ReportGraph)
resultGraphMap["reportGraphs"] = reportGraphs
c.JSON(resultGraphMap, err)
}
func queryReGraphAvg(c *bm.Context) {
reGraphParam := model.QueryReGraphParam{}
if err := c.BindWith(&reGraphParam, binding.JSON); err != nil {
c.JSON(nil, err)
return
}
log.Info("TestNameNicks:(%s)", reGraphParam.TestNameNicks)
reportGraphs, err := srv.QueryReGraphAvg(reGraphParam.TestNameNicks)
var resultGraphMap = make(map[string][]model.ReportGraph)
resultGraphMap["reportGraphs"] = reportGraphs
c.JSON(resultGraphMap, err)
}
func updateReportStatus(c *bm.Context) {
testStatus := c.Request.Form.Get("test_status")
status, err := strconv.Atoi(testStatus)
if err != nil {
log.Error("test_status 输入错误,(%s)", err)
return
}
c.JSON(srv.UpdateReportStatus(status), nil)
}
func delReport(c *bm.Context) {
v := new(struct {
ID int `form:"id"`
})
if err := c.Bind(v); err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
c.JSON(nil, srv.DelReportSummary(v.ID))
}

View File

@@ -0,0 +1,266 @@
package http
import (
"go-common/app/admin/ep/melloi/model"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/http/blademaster/binding"
)
// AddAndExecuScene Add And Execu Scene
func AddAndExecuScene(c *bm.Context) {
scene := model.Scene{}
if err := c.BindWith(&scene, binding.JSON); err != nil {
c.JSON(nil, err)
return
}
cookie := c.Request.Header.Get("Cookie")
c.JSON(srv.AddAndExecuScene(c, scene, cookie))
}
func queryDraft(c *bm.Context) {
scene := model.Scene{}
if err := c.BindWith(&scene, binding.Form); err != nil {
c.JSON(nil, err)
return
}
c.JSON(srv.QueryDraft(&scene))
}
func updateScene(c *bm.Context) {
scene := model.Scene{}
if err := c.BindWith(&scene, binding.JSON); err != nil {
c.JSON(nil, err)
return
}
c.JSON(srv.UpdateScene(&scene))
}
func addScene(c *bm.Context) {
scene := model.Scene{}
if err := c.BindWith(&scene, binding.JSON); err != nil {
c.JSON(nil, err)
return
}
id, _ := srv.AddScene(&scene)
c.JSON(id, nil)
}
func saveScene(c *bm.Context) {
scene := model.Scene{}
if err := c.BindWith(&scene, binding.JSON); err != nil {
c.JSON(nil, err)
return
}
c.JSON(nil, srv.SaveScene(&scene))
}
func saveOrder(c *bm.Context) {
scene := model.Scene{}
if err := c.BindWith(&scene, binding.Form); err != nil {
c.JSON(nil, err)
return
}
var req model.SaveOrderReq
if err := c.BindWith(&req, binding.JSON); err != nil {
c.JSON(nil, err)
return
}
c.JSON(nil, srv.SaveOrder(req, &scene))
}
func queryRelation(c *bm.Context) {
script := model.Script{}
if err := c.BindWith(&script, binding.Form); err != nil {
c.JSON(nil, err)
return
}
c.JSON(srv.QueryRelation(&script))
}
func queryAPI(c *bm.Context) {
scene := model.Scene{}
if err := c.BindWith(&scene, binding.Form); err != nil {
c.JSON(nil, err)
return
}
c.JSON(srv.QueryAPI(&scene))
}
func deleteAPI(c *bm.Context) {
script := model.Script{}
if err := c.BindWith(&script, binding.JSON); err != nil {
c.JSON(nil, err)
return
}
c.JSON(nil, srv.DeleteAPI(&script))
}
func addConfig(c *bm.Context) {
script := model.Script{}
if err := c.BindWith(&script, binding.JSON); err != nil {
c.JSON(nil, err)
return
}
c.JSON(nil, srv.AddConfig(&script))
}
func queryTree(c *bm.Context) {
script := model.Script{}
if err := c.BindWith(&script, binding.Form); err != nil {
c.JSON(nil, err)
return
}
c.JSON(srv.QueryTree(&script))
}
func queryScenes(c *bm.Context) {
qsr := model.QuerySceneRequest{}
if err := c.BindWith(&qsr, binding.Form); err != nil {
c.JSON(nil, err)
return
}
if err := qsr.Verify(); err != nil {
c.JSON(nil, err)
return
}
sessionID, err := c.Request.Cookie("_AJSESSIONID")
if err != nil {
c.JSON(nil, err)
return
}
res, err := srv.QueryScenesByPage(c, sessionID.Value, &qsr)
if err != nil {
return
}
c.JSON(res, err)
}
func doScenePtest(c *bm.Context) {
ptestScene := model.DoPtestSceneParam{}
if err := c.BindWith(&ptestScene, binding.JSON); err != nil {
c.JSON(nil, err)
return
}
cookie := c.Request.Header.Get("Cookie")
c.JSON(srv.DoScenePtest(c, ptestScene, false, cookie))
}
func doScenePtestBatch(c *bm.Context) {
ptestScenes := model.DoPtestSceneParams{}
if err := c.BindWith(&ptestScenes, binding.JSON); err != nil {
c.JSON(nil, err)
return
}
cookie := c.Request.Header.Get("Cookie")
c.JSON(nil, srv.DoScenePtestBatch(c, ptestScenes, cookie))
}
func queryExistAPI(c *bm.Context) {
apiInfoReq := model.APIInfoRequest{}
if err := c.BindWith(&apiInfoReq, binding.Form); err != nil {
c.JSON(nil, err)
return
}
sessionID, err := c.Request.Cookie("_AJSESSIONID")
if err != nil {
c.JSON(nil, err)
return
}
c.JSON(srv.QueryExistAPI(c, sessionID.Value, &apiInfoReq))
}
func queryPreview(c *bm.Context) {
script := model.Script{}
if err := c.BindWith(&script, binding.Form); err != nil {
c.JSON(nil, err)
}
c.JSON(srv.QueryPreview(&script))
}
func queryParams(c *bm.Context) {
script := model.Script{}
if err := c.BindWith(&script, binding.Form); err != nil {
c.JSON(nil, err)
}
res, _, err := srv.QueryParams(&script)
c.JSON(res, err)
}
func updateBindScene(c *bm.Context) {
bindScene := model.BindScene{}
if err := c.BindWith(&bindScene, binding.JSON); err != nil {
c.JSON(nil, err)
return
}
c.JSON(nil, srv.UpdateBindScene(&bindScene))
}
func queryDrawRelation(c *bm.Context) {
scene := model.Scene{}
if err := c.BindWith(&scene, binding.Form); err != nil {
c.JSON(nil, err)
}
res, _, err := srv.QueryDrawRelation(&scene)
c.JSON(res, err)
}
func addSceneScript(c *bm.Context) {
script := model.Script{}
if err := c.BindWith(&script, binding.JSON); err != nil {
c.JSON(nil, err)
return
}
scene := model.Scene{}
if err := c.BindWith(&scene, binding.Form); err != nil {
c.JSON(nil, err)
return
}
cookie := c.Request.Header.Get("Cookie")
c.JSON(srv.AddAndExcuScript(c, &script, cookie, &scene, false, false))
}
func deleteDraft(c *bm.Context) {
scene := model.Scene{}
if err := c.BindWith(&scene, binding.JSON); err != nil {
c.JSON(nil, err)
return
}
c.JSON(nil, srv.DeleteDraft(&scene))
}
func queryConfig(c *bm.Context) {
script := model.Script{}
if err := c.BindWith(&script, binding.Form); err != nil {
c.JSON(nil, err)
return
}
c.JSON(srv.QueryConfig(&script))
}
func deleteScene(c *bm.Context) {
scene := model.Scene{}
if err := c.BindWith(&scene, binding.Form); err != nil {
c.JSON(nil, err)
return
}
c.JSON(nil, srv.DeleteScene(&scene))
}
func copyScene(c *bm.Context) {
scene := model.Scene{}
if err := c.BindWith(&scene, binding.JSON); err != nil {
c.JSON(nil, err)
return
}
cookie := c.Request.Header.Get("Cookie")
c.JSON(srv.CopyScene(c, &scene, cookie))
}
func queryFusing(c *bm.Context) {
script := model.Script{}
if err := c.BindWith(&script, binding.Form); err != nil {
c.JSON(nil, err)
return
}
c.JSON(srv.QueryFusing(&script))
}

View File

@@ -0,0 +1,226 @@
package http
import (
"encoding/json"
"strconv"
"go-common/app/admin/ep/melloi/conf"
"go-common/app/admin/ep/melloi/model"
"go-common/library/ecode"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/http/blademaster/binding"
)
func queryScripts(c *bm.Context) {
qsr := model.QueryScriptRequest{}
if err := c.BindWith(&qsr, binding.Form); err != nil {
c.JSON(nil, err)
return
}
qsr.Active = 1
if err := qsr.Verify(); err != nil {
c.JSON(nil, err)
return
}
sessionID, err := c.Request.Cookie("_AJSESSIONID")
if err != nil {
c.JSON(nil, err)
return
}
res, err := srv.QueryScriptsByPage(c, sessionID.Value, &qsr)
if err != nil {
log.Error("queryScripts Error", err)
return
}
c.JSON(res, err)
}
func queryScripysFree(c *bm.Context) {
script := model.Script{}
if err := c.BindWith(&script, binding.Form); err != nil {
c.JSON(nil, err)
return
}
script.Active = 1
res, err := srv.QueryScripts(&script, 1, 200)
if err != nil {
log.Error("queryScripts Error", err)
return
}
var resMap = make(map[string]interface{})
resMap["scripts"] = res
c.JSON(resMap, err)
}
func queryScriptSnap(c *bm.Context) {
scriptSnap := model.ScriptSnap{}
if err := c.BindWith(&scriptSnap, binding.Form); err != nil {
c.JSON(nil, err)
return
}
scriptSnaps, err := srv.QueryScriptSnap(&scriptSnap)
if err != nil {
log.Error("QueryScriptSnap Error", err)
return
}
var resMap = make(map[string]interface{})
resMap["scriptSnaps"] = scriptSnaps
c.JSON(resMap, nil)
}
func addJmeterSample(c *bm.Context) {
script := model.Script{}
if err := c.BindWith(&script, binding.JSON); err != nil {
c.JSON(nil, err)
return
}
c.JSON(srv.AddJmeterSample(&script))
}
func addThreadGroup(c *bm.Context) {
script := model.Script{}
sceneTyped := c.Request.Form.Get("scene_type")
sceneType, err := strconv.Atoi(sceneTyped)
if err != nil {
log.Error("your string cannot strconv to int ")
return
}
if err := c.BindWith(&script, binding.JSON); err != nil {
c.JSON(nil, err)
return
}
c.JSON(srv.AddThreadGroup(&script, sceneType))
}
func getThreadGroup(c *bm.Context) {
scrThreadGroup := model.ScrThreadGroup{}
if err := c.BindWith(&scrThreadGroup, binding.JSON); err != nil {
c.JSON(nil, err)
return
}
c.JSON(srv.GetThreadGroup(scrThreadGroup))
}
func addAndExecuteScript(c *bm.Context) {
script := model.Script{}
if err := c.BindWith(&script, binding.JSON); err != nil {
c.JSON(nil, err)
return
}
scene := model.Scene{}
if err := c.BindWith(&scene, binding.Form); err != nil {
c.JSON(nil, err)
return
}
// 压测时间段检查
userName, _ := c.Request.Cookie("username")
// 非debug逻辑 && 需要检查 && 非保存 && 非复制
if !script.IsDebug && conf.Conf.Melloi.CheckTime && !script.IsSave && !script.IsCopy {
//if !srv.CheckRunTime() {
// if !srv.CheckRunPermission(userName.Value) {
// c.JSON("Non-working time", ecode.MelloiRunNotInTime)
// return
// }
//}
if !srv.CheckRunPermission(userName.Value) {
c.JSON("Non-working time", ecode.MelloiRunNotInTime)
return
}
}
JSON, _ := json.Marshal(script)
log.Info("script:----------", string(JSON))
cookie := c.Request.Header.Get("Cookie")
resp, err := srv.AddAndExcuScript(c, &script, cookie, &scene, true, false)
if err != nil {
c.JSON(nil, err)
return
}
c.JSON(resp, err)
}
func delScript(c *bm.Context) {
id := c.Request.Form.Get("id")
ID, err := strconv.Atoi(id)
if err != nil {
c.JSON(nil, err)
return
}
c.JSON(nil, srv.DelScript(ID))
}
func updateScript(c *bm.Context) {
script := model.Script{}
if err := c.BindWith(&script, binding.JSON); err != nil {
c.JSON(nil, err)
return
}
updateResult, err := srv.UpdateScript(&script)
if err != nil {
log.Error("UpdateScript err (%v)", err)
return
}
var resMap = make(map[string]string)
resMap["update_result"] = updateResult
c.JSON(resMap, err)
}
func updateScriptAll(c *bm.Context) {
script := model.Script{}
if err := c.BindWith(&script, binding.JSON); err != nil {
c.JSON(nil, err)
return
}
scene := model.Scene{}
if err := c.BindWith(&scene, binding.Form); err != nil {
c.JSON(nil, err)
return
}
updateResult, err := srv.UpdateScriptAll(&script, &scene)
if err != nil {
log.Error("UpdateScriptAll err (%v)", err)
return
}
var resMap = make(map[string]string)
resMap["update_result"] = updateResult
c.JSON(resMap, err)
}
func runTimeCheck(c *bm.Context) {
// 压测时间段检查
userName, _ := c.Request.Cookie("username")
// 暂时去掉压测时间
//if !srv.CheckRunTime() {
// if !srv.CheckRunPermission(userName.Value) {
// c.JSON("Non-working time", ecode.MelloiRunNotInTime)
// return
// }
//}
if !srv.CheckRunPermission(userName.Value) {
c.JSON("Non-working time", ecode.MelloiRunNotInTime)
return
}
c.JSON(nil, nil)
}
func urlCheck(c *bm.Context) {
// 检查url是否包含json串
script := model.Script{}
if err := c.BindWith(&script, binding.JSON); err != nil {
c.JSON(nil, err)
return
}
c.JSON(srv.URLCheck(&script))
}
// 增加定时器配置
func addTimer(c *bm.Context) {
script := model.Script{}
if err := c.BindWith(&script, binding.JSON); err != nil {
c.JSON(nil, err)
return
}
c.JSON(nil, srv.AddTimer(&script))
}

View File

@@ -0,0 +1,31 @@
package http
import (
"go-common/library/ecode"
bm "go-common/library/net/http/blademaster"
)
func queryUserTree(c *bm.Context) {
session, err := c.Request.Cookie("_AJSESSIONID")
if err != nil {
c.JSON(nil, err)
return
}
c.JSON(srv.QueryUserTree(c, session.Value))
}
func queryTreeAdmin(c *bm.Context) {
v := new(struct {
Path string `form:"path"`
})
if err := c.Bind(v); err != nil {
c.JSON(nil, ecode.RequestErr)
return
}
session, err := c.Request.Cookie("_AJSESSIONID")
if err != nil {
c.JSON(nil, err)
return
}
c.JSON(srv.QueryTreeAdmin(c, v.Path, session.Value))
}

View File

@@ -0,0 +1,40 @@
package http
import (
"go-common/app/admin/ep/melloi/model"
"go-common/library/ecode"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/http/blademaster/binding"
)
func queryUser(c *bm.Context) {
// 验证登录sessionID
session, err := c.Request.Cookie("_AJSESSIONID")
if err != nil {
c.JSON(nil, ecode.AccessKeyErr)
return
}
token, _ := srv.QueryServiceTreeToken(c, session.Value)
if token == "" {
c.JSON(nil, ecode.AccessKeyErr)
return
}
// 获取用户名
userName, err := c.Request.Cookie("username")
if err != nil {
c.JSON(nil, ecode.AccessKeyErr)
return
}
c.JSON(srv.QueryUser(userName.Value))
}
func updateUser(c *bm.Context) {
user := model.User{}
if err := c.BindWith(&user, binding.JSON); err != nil {
c.JSON(nil, err)
return
}
c.JSON(nil, srv.UpdateUser(&user))
}

View File

@@ -0,0 +1,59 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = [
"apply.go",
"bfs.go",
"clientmoni.go",
"cluster.go",
"comment.go",
"const.go",
"dto.go",
"grpc.go",
"job.go",
"label.go",
"melloi.go",
"order.go",
"order_admin.go",
"order_report.go",
"ptestjob.go",
"rank.go",
"report_graph.go",
"report_summary.go",
"report_timely.go",
"scene.go",
"script.go",
"script_snap.go",
"tree.go",
"user.go",
"wechat.go",
],
importpath = "go-common/app/admin/ep/melloi/model",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//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"],
)

View File

@@ -0,0 +1,36 @@
package model
//Apply apply model
type Apply struct {
ID int64 `json:"id" gorm:"AUTO_INCREMENT;primary_key;" form:"id"`
Path string `json:"path"`
From string `json:"from" form:"from"`
To string `json:"to" form:"to"`
Status int32 `json:"status" form:"status"`
StartTime string `json:"start_time" form:"start_time"`
EndTime string `json:"end_time" form:"end_time"`
Active int32 `json:"active"`
}
//const definition
const (
ApplyValid = 1 // active=1 有效
ApplyInvalid = -1 // active=-1 无效
)
// QueryApplyResponse response model
type QueryApplyResponse struct {
ApplyList []*Apply `json:"apply_list"`
Pagination
}
// QueryApplyRequest request model
type QueryApplyRequest struct {
Apply
Pagination
}
// TableName get table name model
func (w Apply) TableName() string {
return "apply"
}

View File

@@ -0,0 +1,8 @@
package model
// BFSConf service bfs conf model
type BFSConf struct {
Host string
AccessKey string
AccessSecret string
}

View File

@@ -0,0 +1,21 @@
package model
import "time"
//ClientMoni model for performance test container cpu monitor
type ClientMoni struct {
ID int `json:"id" gorm:"AUTO_INCREMENT;primary_key;" form:"id"`
ScriptID int `json:"script_id" form:"script_id"`
ReportSuID int `json:"report_su_id" form:"report_su_id"`
JobName string `json:"job_name" form:"job_name"`
JobNameAll string `json:"job_name_all" form:"job_name_all"`
CPUUsed string `json:"cpu_used" form:"cpu_used"`
ElapsdTime int `json:"elapsd_time"`
Ctime time.Time `json:"ctime" form:"ctime"`
Mtime time.Time `json:"mtime" form:"mtime"`
}
//TableName table name of client moni model
func (c ClientMoni) TableName() string {
return "client_moni"
}

View File

@@ -0,0 +1,118 @@
package model
import (
"net/http"
"go-common/library/ecode"
"go-common/library/log"
)
//ClusterItems cluster items
type ClusterItems struct {
Items map[string]interface{} `json:"items"`
}
//RmTokenPost get token
type RmTokenPost = struct {
APIToken string `json:"api_token"`
PlatformID string `json:"platform_id"`
}
//ClusterResponse json body
type ClusterResponse struct {
ExcludeDataResponse
Count int `json:"count"`
Data *ClusterResponseItems `json:"data"`
}
//ClusterResponseItems json body
type ClusterResponseItems struct {
Items []*ClusterResponseItemsSon `json:"items"`
}
//ClusterResponseItemsSon json body
type ClusterResponseItemsSon struct {
Configuration ClusterConfiguration `json:"configuration"`
Resources ClusterPoolResourcesUsage `json:"resources"`
PoolResourcesUsage PoolResourcesUsageSon `json:"pool_resources_usage"`
}
//PoolResourcesUsageSon json body
type PoolResourcesUsageSon struct {
Ep ClusterPoolResourcesUsage `json:"ep"`
Melloi ClusterPoolResourcesUsage `json:"melloi"`
Public ClusterPoolResourcesUsage `json:"public"`
}
//ClusterConf visit PaaS
type ClusterConf struct {
TestHost string
UatHost string
QueryJobCPUHost string
}
// ClusterRmTokenResponse query token response.
type ClusterRmTokenResponse struct {
ExcludeDataResponse
Data AuthData `json:"data"`
}
// ExcludeDataResponse no data field response.
type ExcludeDataResponse struct {
Status int `json:"status"`
Message string `json:"message"`
}
// CheckStatus check status.
func (e *ExcludeDataResponse) CheckStatus() (err error) {
if e.Status >= http.StatusMultipleChoices || e.Status < http.StatusOK {
log.Error("The status(%d) of paas may represent a request error(%s)", e.Status, e.Message)
err = ecode.MelloiPaasRequestErr
}
return
}
//AuthData AuthData stuct
type AuthData struct {
Token string `json:"token"`
PlatformID string `json:"platform_id"`
UserName string `json:"user_name"`
Secret string `json:"secret"`
Expired int `json:"expired"`
Admin bool `json:"admin"`
}
//ClusterPoolResourcesUsage ClusterPoolResourcesUsage stuct
type ClusterPoolResourcesUsage struct {
CPURequest int `json:"cpu_request"`
CPULimit int `json:"cpu_limit"`
CPUCapacity int `json:"cpu_capacity"`
CPUAllocatable int `json:"cpu_allocatable"`
MemoryRequest int `json:"memory_request"`
MemoryLimit int `json:"memory_limit"`
MemoryCapacity int `json:"memory_capacity"`
MemoryAllocatable int `json:"memory_allocatable"`
PodRunning int `json:"pod_running"`
PodTotal int `json:"pod_total"`
PodCapacity int `json:"pod_capacity"`
PodAllocatable int `json:"pod_allocatable"`
NodesNum int `json:"nodes_num"`
}
//ClusterConfiguration ClusterConfiguration stuct
type ClusterConfiguration struct {
ID int `json:"id"`
Name string `json:"name"`
Desc string `json:"desc"`
Region string `json:"region"`
Zone string `json:"zone"`
Idc string `json:"idc"`
Envs string `json:"envs"`
CloudProvider string `json:"cloud_provider"`
Orchestrator string `json:"orchestrator"`
APITarget string `json:"api_target"`
Register string `json:"register"`
DefaultRegistry string `json:"default_registry"`
Ctime string `json:"ctime"`
Mtime string `json:"mtime"`
}

View File

@@ -0,0 +1,24 @@
package model
import "time"
//Comment model for performance test job comment
type Comment struct {
ID int `json:"id" gorm:"AUTO_INCREMENT;primary_key;" form:"id"`
ReportID int `json:"report_id" form:"report_id"`
Content string `json:"content" gorm:"content"`
UserName string `json:"user_name" form:"user_name" gorm:"user_name"`
Status int `json:"status" form:"status"`
SubmitDate time.Time `json:"submit_date"`
}
//QueryCommentResponse model for QueryCommentResponse
type QueryCommentResponse struct {
Total int `json:"total"`
Comments []*Comment `json:"comment_list"`
}
//TableName db table name of Comment
func (w Comment) TableName() string {
return "comment"
}

View File

@@ -0,0 +1,71 @@
package model
// const const
const (
PROTOCOL_HTTP = 0
PROTOCOL_GRPC = 1
PROTOCOL_SCENE = 2
HTTP_SCRIPT_TYPE = 1
SCENE_SCRIPT_TYPE = 2
//HeaderStart header start
HeaderStart = "<elementProp name=\"\" elementType=\"Header\"><stringProp name=\"Header.name\">"
//HeaderMid header mid
HeaderMid = "</stringProp><stringProp name=\"Header.value\">"
//HeaderEnd header end
HeaderEnd = "</stringProp></elementProp>"
//ElementPropName element propname
ElementPropName = "<elementProp name=\""
//HTTPArgument http arg
HTTPArgument = "\" elementType=\"HTTPArgument\">"
//HTTPArgumentEncode http arg code
HTTPArgumentEncode = "<boolProp name=\"HTTPArgument.always_encode\">false</boolProp>"
//ArgumentStart arg start
ArgumentStart = "<stringProp name=\"Argument.value\">"
//ArgumentMid arg mid
ArgumentMid = "</stringProp><stringProp name=\"Argument.metadata\">=</stringProp><boolProp name=\"HTTPArgument.use_equals\"" +
">true</boolProp><stringProp name=\"Argument.name\">"
//ArgumentEnd arg end
ArgumentEnd = "</stringProp></elementProp>"
//AsyncInfo async info
AsyncInfo = "<boolProp name=\"asyncCall\">true</boolProp>"
//MultipartName Multipart Name
MultipartName = "<elementProp name=\"HTTPsampler.Files\" elementType=\"HTTPFileArgs\"><collectionProp name=\"HTTPFileArgs.files\"><elementProp name=\""
//MultipartFilePath MultipartFile Path
MultipartFilePath = "\" elementType=\"HTTPFileArg\"><stringProp name=\"File.path\">"
//MultipartFilePathd MultipartFile Pathd
MultipartFilePathd = "</stringProp><stringProp name=\"File.paramname\">"
//MultipartMime type
MultipartMimetype = "</stringProp><stringProp name=\"File.mimetype\">"
//Multipart End
MultipartEnd = "</stringProp></elementProp></collectionProp></elementProp>"
//Assertion start
AssertionStart = "<stringProp name=\"927604211\">"
//Assertion End
AssertionEnd = "</stringProp>"
//ConstTimer const timer
ConstTimer = "<ConstantTimer guiclass=\"ConstantTimerGui\" testclass=\"ConstantTimer\" testname=\"固定定时器\" enabled=\"true\">" +
"<stringProp name=\"ConstantTimer.delay\">1000</stringProp>" +
"</ConstantTimer>" +
"<hashTree/>"
//Randomtimer Random Timer
RandomTimer = "<GaussianRandomTimer guiclass=\"GaussianRandomTimerGui\" testclass=\"GaussianRandomTimer\" testname=\"高斯随机定时器\" enabled=\"true\">" +
"<stringProp name=\"ConstantTimer.delay\">1000</stringProp>" +
"<stringProp name=\"RandomTimer.range\">500</stringProp>" +
"</GaussianRandomTimer>" +
"<hashTree/>"
//
)

View File

@@ -0,0 +1,95 @@
package model
import "go-common/library/time"
// GRPC grpc model
type GRPC struct {
ID int `json:"id" form:"id" gorm:"AUTO_INCREMENT;primary_key;"`
TaskName string `json:"task_name" form:"task_name" gorm:"task_name"`
Department string `json:"department" form:"department" gorm:"department"`
Project string `json:"project" form:"project" gorm:"project"`
APP string `json:"app" form:"app" gorm:"app"`
Active int `json:"active" form:"active" gorm:"active"`
HostName string `json:"host_name," form:"host_name" gorm:"host_name"`
Port int `json:"port" form:"port" gorm:"port"`
ServiceName string `json:"service_name" form:"service_name" gorm:"service_name"`
ProtoClassName string `json:"proto_class_name" form:"proto_class_name" gorm:"proto_class_name"`
PkgPath string `json:"pkg_path" form:"pkg_path" gorm:"pkg_path"`
AsynCall int `json:"asyn_call" form:"asyn_call" gorm:"asyn_call"`
RequestType string `json:"request_type" form:"request_type" gorm:"request_type"`
RequestMethod string `json:"request_method" form:"request_method" gorm:"request_method"`
RequestContent string `json:"request_content" form:"request_content" gorm:"request_content"`
ResponseType string `json:"response_type" form:"response_type" gorm:"response_type"`
ScriptPath string `json:"script_path" form:"script_path" gorm:"script_path"`
JarPath string `json:"jar_path" form:"jar_path" gorm:"jar_path"`
JmxPath string `json:"jmx_path" form:"jmx_path" gorm:"jmx_path"`
JmxLog string `json:"jmx_log" form:"jmx_log" gorm:"jmx_log"`
JtlLog string `json:"jtl_log" form:"jtl_log" gorm:"jtl_log"`
ThreadsSum int `json:"threads_sum" form:"threads_sum" gorm:"threads_sum"`
RampUp int `json:"ramp_up" form:"ramp_up" gorm:"ramp_up"`
Loops int `json:"loops" form:"loop" gorm:"loops"`
LoadTime int `json:"load_time" form:"load_time" gorm:"load_time"`
UpdateBy string `json:"update_by" form:"update_by" gorm:"update_by"`
Ctime time.Time `json:"ctime"`
Mtime time.Time `json:"mtime"`
IsDebug int `json:"is_debug" gorm:"-"`
IsAsync bool `json:"is_async" form:"is_async" gorm:"is_async"`
AsyncInfo interface{} `json:"async_info" gorm:"-"`
ParamEnable string `json:"param_enable" `
ParamDelimiter string `json:"param_delimiter"`
ParamFilePath string `json:"param_file_path" gorm:"param_file_path"`
ParamNames string `json:"param_names"`
}
// GRPCSnap grpc snap model
type GRPCSnap struct {
ID int `json:"id" form:"id" gorm:"AUTO_INCREMENT;primary_key;"`
GRPCID int `json:"grpc_id" form:"grpc_id" gorm:"column:grpc_id"`
TaskName string `json:"task_name" form:"task_name" gorm:"task_name"`
Department string `json:"department" form:"department" gorm:"department"`
Project string `json:"project" form:"project" gorm:"project"`
APP string `json:"app" form:"app" gorm:"app"`
Active int `json:"active" form:"active" gorm:"active"`
HostName string `json:"host_name," form:"host_name" gorm:"host_name"`
Port int `json:"port" form:"port" gorm:"port"`
ServiceName string `json:"service_name" form:"service_name" gorm:"service_name"`
ProtoClassName string `json:"proto_class_name" form:"proto_class_name" gorm:"proto_class_name"`
PkgPath string `json:"pkg_path" form:"pkg_path" gorm:"pkg_path"`
AsynCall int `json:"asyn_call" form:"asyn_call" gorm:"asyn_call"`
RequestType string `json:"request_type" form:"request_type" gorm:"request_type"`
RequestMethod string `json:"request_method" form:"request_method" gorm:"request_method"`
RequestContent string `json:"request_content" form:"request_content" gorm:"request_content"`
ResponseType string `json:"response_type" form:"response_type" gorm:"response_type"`
ScriptPath string `json:"script_path" form:"script_path" gorm:"script_path"`
JarPath string `json:"jar_path" form:"jar_path" gorm:"jar_path"`
JmxPath string `json:"jmx_path" form:"jmx_path" gorm:"jmx_path"`
JmxLog string `json:"jmx_log" form:"jmx_log" gorm:"jmx_log"`
JtlLog string `json:"jtl_log" form:"jtl_log" gorm:"jtl_log"`
ThreadsSum int `json:"threads_sum" form:"threads_sum" gorm:"threads_sum"`
RampUp int `json:"ramp_up" form:"ramp_up" gorm:"ramp_up"`
Loops int `json:"loops" form:"loop" gorm:"loops"`
LoadTime int `json:"load_time" form:"load_time" gorm:"load_time"`
UpdateBy string `json:"update_by" form:"update_by" gorm:"update_by"`
ExecuteID string `json:"execute_id" gorm:"execute_id"`
IsAsync bool `json:"is_async" form:"is_async" gorm:"is_async"`
ParamEnable string `json:"param_enable" `
ParamDelimiter string `json:"param_delimiter"`
ParamFilePath string `json:"param_file_path" gorm:"param_file_path"`
ParamNames string `json:"param_names"`
}
// ProtoPathModel create proto dependency path
type ProtoPathModel struct {
RootPath string `json:"root_path"`
ExtraPath string `json:"extra_path"`
}
// DependResponse depend reponse
type DependResponse struct {
Items []Item `json:"items"`
}
// Item serivce name
type Item struct {
ServiceName string `json:"service_name"`
}

View File

@@ -0,0 +1,111 @@
package model
import "go-common/library/time"
// GRPCQuickStartRequest GRPCModel grpc models
type GRPCQuickStartRequest struct {
GRPCAddScriptRequest
}
// GRPCAddScriptRequest GRPC Add Script Request
type GRPCAddScriptRequest struct {
TaskName string `json:"task_name"`
Department string `json:"department"`
Project string `json:"project"`
APP string `json:"app"`
Active int `json:"active"`
HostName string `json:"host_name,"`
Port int `json:"port"`
ServiceName string `json:"service_name"`
ProtoClassName string `json:"proto_class_name"`
PkgPath string `json:"pkg_path"`
AsynCall int `json:"asyn_call"`
RequestType string `json:"request_type"`
RequestMethod string `json:"request_method"`
RequestContent string `json:"request_content"`
ResponseType string `json:"response_type"`
ScriptPath string `json:"script_path"`
JarPath string `json:"jar_path"`
ThreadsSum int `json:"threads_sum"`
RampUp int `json:"ramp_up"`
Loops int `json:"loops"`
LoadTime int `json:"load_time"`
UpdateBy string `json:"update_by"`
Ctime time.Time `json:"ctime"`
Mtime time.Time `json:"mtime"`
IsDebug int `json:"is_debug" gorm:"-"` // 判断是否调试,不落库
IsAsync bool `json:"is_async" form:"is_async"`
AsyncInfo interface{} `json:"async_info" gorm:"-"`
ParamEnable string `json:"param_enable" `
ParamDelimiter string `json:"param_delimiter"`
ParamFilePath string `json:"param_file_path" gorm:"param_file_path"`
ParamNames string `json:"param_names"`
}
// GRPCUpdateScriptRequest GRPC Update Script Request
type GRPCUpdateScriptRequest struct {
ID int `json:"id"`
GRPCAddScriptRequest
}
// GRPCExecuteScriptRequest GRPC Execute Script Request
type GRPCExecuteScriptRequest struct {
ScriptID int `json:"script_id"`
}
// TableName Table Name
func (g GRPC) TableName() string {
return "grpc"
}
// TableName Table Name
func (g GRPCSnap) TableName() string {
return "grpc_snap"
}
// QueryGRPCRequest grpc of query request
type QueryGRPCRequest struct {
Executor string `json:"executor" form:"executor"`
GRPC
Pagination
}
// QueryGRPCResponse grpc of query response
type QueryGRPCResponse struct {
GRPCS []*GRPC `json:"grpcs"`
Pagination
}
// GRPCReqToGRPC GRPC Req To GRPC
func GRPCReqToGRPC(grpcReq *GRPCAddScriptRequest) (grpc *GRPC) {
grpc = &GRPC{}
grpc.TaskName = grpcReq.TaskName
grpc.Department = grpcReq.Department
grpc.Project = grpcReq.Project
grpc.APP = grpcReq.APP
grpc.Active = grpcReq.Active
grpc.HostName = grpcReq.HostName
grpc.Port = grpcReq.Port
grpc.ServiceName = grpcReq.ServiceName
grpc.ProtoClassName = grpcReq.ProtoClassName
grpc.PkgPath = grpcReq.PkgPath
grpc.AsynCall = grpcReq.AsynCall
grpc.RequestType = grpcReq.RequestType
grpc.RequestMethod = grpcReq.RequestMethod
grpc.RequestContent = grpcReq.RequestContent
grpc.ResponseType = grpcReq.ResponseType
grpc.ScriptPath = grpcReq.ScriptPath
grpc.JarPath = grpcReq.JarPath
grpc.ThreadsSum = grpcReq.ThreadsSum
grpc.RampUp = grpcReq.RampUp
grpc.Loops = grpcReq.Loops
grpc.LoadTime = grpcReq.LoadTime
grpc.UpdateBy = grpcReq.UpdateBy
grpc.IsAsync = grpcReq.IsAsync
grpc.AsyncInfo = grpcReq.AsyncInfo
grpc.ParamEnable = grpcReq.ParamEnable
grpc.ParamDelimiter = grpcReq.ParamDelimiter
grpc.ParamFilePath = grpcReq.ParamFilePath
grpc.ParamNames = grpcReq.ParamNames
return
}

View File

@@ -0,0 +1,139 @@
package model
// PaasJobResponse create job response in paas.
type PaasJobResponse struct {
ExcludeDataResponse
Data interface{} `json:"data"`
}
//Job job json
type Job struct {
Name string `json:"name"`
CPU int `json:"cpu"`
Memory int `json:"memory"`
Parallelism int `json:"parallelism"`
FileName string `json:"file_name"`
ResJtl string `json:"res_jtl"`
ResLog string `json:"res_log"`
JmeterLog string `json:"jmeter_log"`
EnvInfo string `json:"env_info"`
JarPath string `json:"jar_path"`
Command string `json:"command"`
}
// CleanableDocker docker clearable container list
type CleanableDocker struct {
Name string `json:"name"`
}
//PaasQueryAndDelJob query and del machines request.
type PaasQueryAndDelJob struct {
BusinessUnit string `json:"business_unit"`
Project string `json:"project"`
App string `json:"app"`
Env string `json:"env"`
Name string `json:"name"`
ClusterID int `json:"cluster_id"`
TreeID int `json:"tree_id"`
}
// PaasJobDetail machine detail.
type PaasJobDetail struct {
BusinessUnit string `json:"business_unit"`
Project string `json:"project"`
App string `json:"app"`
Env string `json:"env"`
Name string `json:"name"`
Image string `json:"image"`
ImageVersion string `json:"image_version"`
Volumes string `json:"volumes"`
CPURequest int `json:"cpu_request"`
CPULimit int `json:"cpu_limit"`
MemoryRequest int `json:"memory_request"`
Command string `json:"command"`
ResourcePoolID string `json:"resource_pool_id"`
Parallelism int `json:"parallelism"`
Completions int `json:"completions"`
RetriesLimit int `json:"retries_limit"`
NetworkID int `json:"network_id"`
ClusterID int `json:"cluster_id"`
TreeID int `json:"tree_id"`
HostInfo string `json:"host_info"`
EnvInfo string `json:"env_info"`
}
// PaasJobQueryStatus machine detail.
type PaasJobQueryStatus struct {
ExcludeDataResponse
Data PaasJobQueryData `json:"data"`
}
// PaasJobQueryData machine detail.
type PaasJobQueryData struct {
StartTime string `json:"start_time"`
CompletionTime string `json:"completion_time"`
ActiveNum int `json:"active_num"`
SucceededNum int `json:"succeeded_num"`
FailedNum int `json:"failed_num"`
Conditions PaasJobQueryConditions `json:"conditions"`
Pods []PodInfo `json:"pods"`
}
//PaasQueryJobCPUPostDetail query job cpu detail
type PaasQueryJobCPUPostDetail struct {
Action string `json:"Action"`
PublicKey string `json:"PublicKey"`
Signature int `json:"Signature"`
DataSource string `json:"DataSource"`
Query string `json:"Query"`
}
//PaasQueryJobCPUResult paas query cpu result
type PaasQueryJobCPUResult struct {
ReqID string `json:"ReqId"`
Action string `json:"Action"`
RetCode int `json:"RetCode"`
Data []CPUResult `json:"Data"`
}
//CPUResult cpu result
type CPUResult struct {
JobMetric JobMetric `json:"metric"`
Value []interface{} `json:"value"`
}
//JobMetric job metric
type JobMetric struct {
ContainerEnvAppID string `json:"container_env_app_id"`
ContainerEnvDeployEnv string `json:"container_env_deploy_env"`
ContainerEnvPodCon string `json:"container_env_pod_container"`
ContainerEnvPodName string `json:"container_env_pod_name"`
Job string `json:"job"`
Pro string `json:"pro"`
}
// PodInfo pod info
type PodInfo struct {
AppID string `json:"app_id"`
AppType string `json:"app_type"`
ContainerID string `json:"container_id"`
ContainerStatuses interface{} `json:"container_statuses"`
CreateTime string `json:"create_time"`
DeployEnv string `json:"deploy_env"`
DiscoveryStatus interface{} `json:"discovery_status"`
Health string `json:"health"`
HostIP string `json:"host_ip"`
Image string `json:"image"`
IP string `json:"ip"`
Lables interface{} `json:"lables"`
Name string `json:"name"`
Namespace string `json:"namespace"`
Port interface{} `json:"port"`
StartTime string `json:"start_time"`
Status string `json:"status"`
}
// PaasJobQueryConditions machine detail.
type PaasJobQueryConditions struct {
Complete string `json:"complete"`
}

View File

@@ -0,0 +1,39 @@
package model
//Label label
type Label struct {
ID int64 `json:"id" form:"id" gorm:"AUTO_INCREMENT;primary_key;"`
Name string `json:"label_name"`
Description string `json:"description"`
Color string `json:"color"`
Active int `json:"active"`
}
//LabelName db table name for label
func (l Label) LabelName() string {
return "label"
}
//LabelRelation label relation
type LabelRelation struct {
ID int64 `json:"id" form:"id" gorm:"AUTO_INCREMENT;primary_key;"`
LabelID int64 `json:"label_id" form:"label_id"`
LabelName string `json:"label_name" form:"label_name"`
Color string `json:"color" form:"color"`
Description string `json:"description" form:"description"`
TargetID int64 `json:"target_id" form:"target_id"`
Type int `json:"type"`
Active int `json:"active"`
}
// LabelRelation type const
const (
DefaultType = iota
ScriptType
ReportType
)
//LabelRelationName db table name of label relation
func (l LabelRelation) LabelRelationName() string {
return "label_relation"
}

View File

@@ -0,0 +1,149 @@
package model
//PaginateScripts page script
type PaginateScripts struct {
Total int `json:"total"`
Pn int `json:"page_num"`
Ps int `json:"page_size"`
Scripts []*Script `json:"scripts"`
}
//PaginateReports page report
type PaginateReports struct {
Total int `json:"total"`
Pn int `json:"page_num"`
Ps int `json:"page_size"`
ReportSummarys []*ReportSummary `json:"reportInfos"`
}
//ReducePtest model for test stress reduce
type ReducePtest struct {
ID int `json:"id" form:"id"`
JobName string `json:"job_name" form:"job_name"`
}
//PtestBatch ptest batch
type PtestBatch struct {
UserName string `json:"user_name"`
IDArr []int `json:"id_arr"`
}
//JobBatch batch job
type JobBatch struct {
JobNames []string `json:"job_names"`
ReportSuIDs []int `json:"report_su_ids" form:"report_su_ids"`
}
//DockerStats model for container status
type DockerStats struct {
Container string `json:"container" form:"container"`
Memory interface{} `json:"memory" form:"memory"`
CPU string `json:"cpu" form:"cpu"`
}
//DoPtestParam ptest param
type DoPtestParam struct {
UserName string `json:"user_name"`
LoadTime int `json:"load_time"`
TestNames []string `json:"test_names"` // 人工上传的脚本,可能会有很多接口名
SceneName string `json:"scene_name"`
TestNameNick string `json:"test_name_nick"`
TestNameNicks []string `json:"test_name_nicks"`
FileName string `json:"file_name"`
Upload bool `json:"upload"`
ProjectName string `json:"project_name"`
ResLog string `json:"res_log"`
ResJtl string `json:"res_jtl"`
JmeterLog string `json:"jmeter_log"`
Department string `json:"department"`
Project string `json:"project"`
APP string `json:"app"`
ScriptID int `json:"script_id"`
AddPtest bool `json:"add_ptest"`
IsDebug bool `json:"is_debug"`
Cookie string `json:"cookie"`
URL string `json:"url"`
Domain string `json:"domain"`
LabelIDs []int `json:"label_ids"`
FileSplit bool `json:"file_split"`
SplitNum int `json:"split_num"`
DockerSum int `json:"docker_sum"`
JarPath string `json:"jar_path"`
EnvInfo string `json:"env_info"`
IsScene bool `json:"is_scene"` //场景压测
Type int `json:"type"` // 0.http单接口 1.场景报告 2.grpc报告 3.全链路
Scripts []*Script `json:"scripts"`
SceneID int `json:"scene_id"`
Fusing int `json:"fusing"`
APIHeader string `json:"api_header"`
ExecuDockerSum int `json:"execu_docker_sum"`
UseBusinessStop bool `json:"use_business_stop"`
BusinessStopPercent int `json:"business_stop_percent"`
}
//QueryReGraphParam query ReGraphParam
type QueryReGraphParam struct {
TestNameNicks []string `json:"test_name_nicks" form:"test_name_nicks"`
}
//UploadParam uplaod param
type UploadParam struct {
Path string `json:"path" form:"path" params:"path"`
IsPtest bool `json:"is_ptest" form:"is_ptest" params:"is_ptest"`
UserName string `json:"user_name" form:"user_name" params:"user_name"`
TestName string `json:"test_name" form:"test_name" params:"test_name"`
Department string `json:"department" form:"department" params:"department"`
Project string `json:"project" form:"project" params:"project"`
APP string `json:"app" form:"app" params:"app"`
ScriptPath string `json:"script_path" form:"script_path" params:"script_path"`
Domains string `json:"domains" form:"domains" params:"domains"`
Fusing int `json:"fusing" form:"fusing"`
UseBusinessStop bool `json:"use_business_stop" form:"use_business_stop"`
BusinessStopPercent int `json:"business_stop_percent" form:"business_stop_percent"`
}
//QueryReportsRequest query report request
type QueryReportsRequest struct {
ID string `params:"id" form:"id" json:"id"`
TestNameNick string `params:"test_name_nick" form:"test_name_nick" json:"test_name_nick"`
TestName string `params:"test_name" form:"test_name" json:"test_name"`
Ps int `params:"page_size" form:"page_size" json:"page_size"`
Pn int `params:"page_num" form:"page_num" json:"page_num"`
}
//BfsUploadParam bfs upload param
type BfsUploadParam struct {
BfsIP string `json:"bfs_ip" form:"bfs_ip" params:"bfs_ip"`
BfsPort int `json:"bfs_port" form:"bfs_port" params:"bfs_port"`
BucketName string `json:"bucket_name" form:"bucket_name" params:"bucket_name"`
FileName string `json:"file_name" form:"file_name" params:"file_name"`
AccessKey string `json:"access_key" form:"access_key" params:"access_key"`
AccessSecret string `json:"access_secret" form:"access_secret" params:"access_secret"`
Method string `json:"method" form:"method" params:"method"`
}
//JSONExtractor JSON Extractor
type JSONExtractor struct {
JSONName string `json:"json_name"`
JSONPath string `json:"json_path"`
}
//ReportGraphAdd Report Graph Add
type ReportGraphAdd struct {
ReportSuID int `json:"report_su_id"`
JobName string `json:"job_name"`
TestName string `json:"test_name"`
BeginTime string `json:"begin_time"`
AfterTime string `json:"after_time"`
TestNameNick string `json:"test_name_nick"`
PodNames []string `json:"pod_names"`
ElapsedTime int `json:"elapsed_time"`
Fusing int `json:"fusing"`
UseBusinessStop bool `json:"use_business_stop"`
BusinessStopPercent int `json:"business_stop_percent"`
}
//AllPtestStop all ptest stop
type AllPtestStop struct {
ReportSuID int `json:"report_su_id" form:"report_su_id"`
}

View File

@@ -0,0 +1,85 @@
package model
import (
"time"
"go-common/library/ecode"
)
// Order perf order model
type Order struct {
ID int64 `json:"id" gorm:"AUTO_INCREMENT;primary_key;" form:"id"`
Name string `json:"name" form:"name"`
Broker string `json:"broker" form:"broker"`
TestBackGround string `json:"test_background" form:"test_background" gorm:"column:test_background"`
Type int32 `json:"type" form:"type" gorm:"type"`
TestType int32 `json:"test_type" form:"test_type" gorm:"test_type"`
TestTarget string `json:"test_target" gorm:"test_target"`
APIList string `json:"api_list" gorm:"api_list"`
APIDoc string `json:"api_doc" gorm:"api_doc"`
LimitUser string `json:"limit_user" gorm:"limit_user"`
LimitIP string `json:"limit_ip" gorm:"limit_ip"`
LimitVisit string `json:"limit_visit" gorm:"limit_visit"`
ServerConf string `json:"server_conf" gorm:"server_conf"`
DependentComponent string `json:"dependent_component" gorm:"dependent_component"`
DependentBusiness string `json:"dependent_business" gorm:"dependent_business"`
TestDataFrom string `json:"test_data_from" gorm:"test_data_from"`
TestHost string `json:"test_host" gorm:"test_host"`
MoniRedis string `json:"moni_redis" gorm:"moni_redis"`
MoniMemcache string `json:"moni_memcache" gorm:"moni_memcache"`
MoniDocker string `json:"moni_docker" gorm:"moni_docker"`
MoniAPI string `json:"moni_api" gorm:"moni_api"`
MoniMysql string `json:"moni_mysql" gorm:"moni_mysql"`
MoniElasticsearch string `json:"moni_elasticsearch" gorm:"moni_elasticsearch"`
MoniOther string `json:"moni_other" gorm:"moni_other"`
TestCycles string `json:"test_cycles" gorm:"moni_cycles"`
ScriptID string `json:"script_id" gorm:"script_id"`
MachineID string `json:"machine_id" gorm:"machine_id"`
Department string `json:"department" form:"department" gorm:"department"`
Project string `json:"project" form:"project" gorm:"project"`
App string `json:"app" form:"app" gorm:"app"`
Status int32 `json:"status" form:"status" gorm:"status"`
UpdateBy string `json:"update_by" form:"update_by" gorm:"update_by"`
Handler string `json:"handler" form:"handler" gorm:"handler"`
ApplyDate time.Time `json:"apply_date" gorm:"apply_date"`
Active int32 `json:"active" gorm:"active"`
}
// QueryOrderRequest queryOrderRequest
type QueryOrderRequest struct {
Order
Pagination
}
// QueryOrderResponse queryOrderResponse
type QueryOrderResponse struct {
Orders []*Order `json:"orders"`
Pagination
}
// Verify verify the value of pageNum and pageSize.
func (p *Pagination) Verify() error {
if p.PageNum < 0 {
return ecode.MeilloiIllegalPageNumErr
} else if p.PageNum == 0 {
p.PageNum = 1
}
if p.PageSize < 0 {
return ecode.MeilloillegalPageSizeErr
} else if p.PageSize == 0 {
p.PageSize = 10
}
return nil
}
// Pagination page num
type Pagination struct {
PageNum int32 `form:"page_num" json:"page_num"`
PageSize int32 `form:"page_size" json:"page_size"`
TotalSize int32 `form:"total_size" json:"total_size"`
}
// TableName get table name model
func (w Order) TableName() string {
return "order"
}

View File

@@ -0,0 +1,12 @@
package model
// OrderAdmin perf administrator model for perf order
type OrderAdmin struct {
ID int64 `json:"id" gorm:"AUTO_INCREMENT;primary_key;" form:"id"`
UserName string `json:"user_name" form:"user_name"`
}
// TableName get table name
func (w OrderAdmin) TableName() string {
return "order_admin"
}

View File

@@ -0,0 +1,16 @@
package model
// OrderReport order(manual) report model
type OrderReport struct {
ID int32 `json:"id"`
OrderID int64 `json:"order_id"`
Name string `json:"name"`
Content string `json:"content"`
UpdateBy string `json:"update_by" column:"update_by"`
Active int32 `json:"active"`
}
// TableName get table name model
func (w OrderReport) TableName() string {
return "order_report"
}

View File

@@ -0,0 +1,93 @@
package model
import "time"
//PtestJob performance test job
type PtestJob struct {
ID int `json:"id" gorm:"AUTO_INCREMENT;primary_key;" form:"id"`
ScriptID int `json:"script_id" form:"script_id"`
ReportSuID int `json:"report_su_id" form:"report_su_id"`
JobName string `json:"job_name" form:"job_name"`
Active int `json:"active" form:"active"`
ExecuteID string `json:"execute_id" form:"execute_id"`
HostIP string `json:"host_ip"`
JobIP string `json:"job_ip"`
JobID string `json:"job_id"`
Ctime time.Time `json:"ctime"`
Mtime time.Time `json:"mtime"`
}
//PtestAdd model for adding performance test job
type PtestAdd struct {
ReportSuID int `json:"report_su_id" form:"report_su_id"`
ScriptID int `json:"script_id" form:"script_id"`
JmeterLog string `json:"jmeter_log" form:"jmeter_log"`
ResJtl string `json:"res_jtl" form:"res_jtl"`
JobName string `json:"job_name" form:"job_name"`
DockerSum int `json:"docker_sum" form:"docker_sum"`
ScriptType int `json:"script_type" form:"script_type"`
ExecuteID string `json:"execute_id" form:"execute_id"`
SceneId int `json:"scene_id" form:"scene_id"`
UserName string `json:"user_name" form:"user_name"`
DockerNum int `json:"docker_num" form:"docker_num"`
SleepTime int `json:"sleep_time" form:"sleep_time"`
}
//AddReGraphTimer model for report graph timer
type AddReGraphTimer struct {
ScriptID int `json:"script_id" form:"script_id"`
ReportSuID int `json:"report_su_id" form:"report_su_id"`
JobName string `json:"job_name" form:"job_name"`
BeginTime string `json:"begin_time" form:"begin_time"`
Token string `json:"token" form:"token"`
TestNames []string `json:"test_names" form:"test_names"`
TestNameNicks []string `json:"test_name_nicks" form:"test_name_nicks"`
Fusing int `json:"fusing"`
FusingList []int `json:"fusing_list"`
TestType int `json:"test_type"`
UseBusinessStop bool `json:"use_business_stop"`
BusinessStopPercent int `json:"business_stop_percent"`
UseBusiStopList []bool `json:"use_busi_stop_list"`
BusiStopPercentList []int `json:"busi_stop_percent_list"`
}
//DoPtestResp doptest response
type DoPtestResp struct {
BeginTime string `json:"begin_time"`
JobName string `json:"job_name"`
ReportSuID int `json:"report_su_id"`
ScriptSnapIDs []int `json:"script_snap_ids"`
ScriptID int `json:"script_id"`
Message string `json:"message"`
ScriptSnapID int `json:"script_snap_id"`
JmeterLog string `json:"jmeter_log"`
JtlLog string `json:"jtl_log"`
JmxFile string `json:"jmx_file"`
GroupID int `json:"group_id"`
RunOrder int `json:"run_order"`
LoadTime int `json:"load_time"`
HostIP string `json:"host_ip"`
SOS string `json:"sos"`
}
//AddScene add scene
type AddScene struct {
SceneID int `json:"scene_id" form:"scene_id"`
UserName string `json:"user_name" form:"user_name"`
}
//TableName tablename
func (r PtestJob) TableName() string {
return "ptest_job"
}
// JobInfo Job Info
type JobInfo struct {
HostIp string `json:"host_ip" form:"host_ip"`
JobName string `json:"job_name" form:"job_name"`
}
// JobInfoList Job Info List
type JobInfoList struct {
JobList []JobInfo `json:"job_list"`
}

View File

@@ -0,0 +1,103 @@
package model
//Rank rank
type Rank struct {
Duration int `json:"duration" form:"duration"`
TimeDegree string `json:"time_degree" form:"time_degree"`
StartTime string `json:"start_time" form:"start_time"`
EndTime string `json:"end_time" form:"end_time"`
SearchAll bool `json:"search_all" form:"search_all"`
}
//Tree node in service tree
type Tree struct {
Department string `json:"department" form:"department"`
Project string `json:"project" form:"project"`
App string `json:"app" form:"app"`
}
//TreeNum model for department, project and app performance test count statistic
type TreeNum struct {
DeptNum int `json:"dept_num" form:"dept_num"`
ProNum int `json:"pro_num" form:"pro_num"`
AppNum int `json:"app_num" form:"app_num"`
}
//TreeList tree list
type TreeList struct {
TreeList []*Tree `json:"tree_list"`
}
//NumList num list
type NumList struct {
NumList TreeNum `json:"num"`
}
//API api
type API struct {
URL string `json:"url" form:"url"`
Count int `json:"count" form:"count"`
}
// GrpcInfo Grpc Info
type GrpcInfo struct {
ServiceName string `json:"service_name" form:"service_name"`
RequestMethod string `json:"request_method" form:"request_method"`
Count int `json:"count" form:"count"`
}
// GrpcRes Grpc Res
type GrpcRes struct {
GrpcList []*GrpcInfo `json:"grpc_list" form:"grpc_list"`
}
// SceneCount Scene Count
type SceneCount struct {
Department string `json:"department" form:"department"`
SceneName string `json:"scene_name" form:"scene_name"`
Count int `json:"count" form:"count"`
}
// SceneRes SceneRes
type SceneRes struct {
SceneList []*SceneCount `json:"scene_list" form:"scene_list"`
}
//Department department
type Department struct {
Department string `json:"department" form:"department"`
Count int `json:"count" form:"count"`
}
//Build performance test count by date
type Build struct {
Date string `json:"date" form:"date"`
Count int `json:"count" form:"count"`
}
//State model for test status
type State struct {
TestStatus int `json:"test_status" form:"test_status"`
Count int `json:"count" form:"count"`
}
//TopAPIRes performance test top apis
type TopAPIRes struct {
//Total int `json:"total"`
APIList []*API `json:"api_list"`
}
//TopDeptRes performance test top departments
type TopDeptRes struct {
DeptList []*Department `json:"dept_list"`
}
//BuildLineRes test line
type BuildLineRes struct {
BuildList []*Build `json:"build_list"`
}
//StateLineRes test state chart
type StateLineRes struct {
StateList []*State `json:"state_list"`
}

View File

@@ -0,0 +1,49 @@
package model
import (
"time"
)
//ReportGraph reportgraph
type ReportGraph struct {
ID int `json:"id" gorm:"AUTO_INCREMENT;primary_key;" form:"id"`
TestName string `json:"test_name" form:"test_name"`
TestNameNick string `json:"test_name_nick" form:"test_name_nick"`
Count int `json:"count"`
QPS int `json:"qps"`
AvgTime int `json:"avg_time"`
Min int `json:"min"`
Max int `json:"max"`
Error int `json:"error"`
FailPercent string `json:"fail_percent"`
NinetyTime int `json:"ninety_time"`
NinetyFiveTime int `json:"ninety_five_time"`
NinetyNineTime int `json:"ninety_nine_time"`
NetIo int `json:"net_io"`
CodeEll int `json:"code_ell"`
CodeWll int `json:"code_wll"`
CodeWly int `json:"code_wly"`
CodeWle int `json:"code_wle"`
CodeWls int `json:"code_wls"`
CodeSll int `json:"code_sll"`
CodeSly int `json:"code_sly"`
CodeSls int `json:"code_sls"`
CodeKong int `json:"code_kong"`
CodeNonHTTP int `json:"code_non_http"`
CodeOthers int `json:"code_others"`
ElapsdTime int `json:"elapsd_time"`
PodName string `json:"pod_name" form:"pod_name"`
ThreadsSum int `json:"threads_sum"`
Ctime time.Time `json:"ctime"`
Mtime time.Time `json:"mtime"`
FiftyTime int `json:"fifty_time"`
Code301 int `json:"code301"`
Code302 int `json:"code302"`
BeginTime time.Time `json:"begin_time" gorm:"-"`
QpsRecent int `json:"qps_recent" gorm:"-"`
}
//TableName table name
func (r ReportGraph) TableName() string {
return "report_graph"
}

View File

@@ -0,0 +1,77 @@
package model
import (
"time"
)
//ReportSummary report summary
type ReportSummary struct {
ID int `json:"id" gorm:"AUTO_INCREMENT;primary_key;" form:"id"`
ScriptID int `json:"script_id" form:"script_id"`
ScriptSnapID int `json:"script_snap_id" form:"script_snap_id"`
ExecuteID string `json:"execute_id" form:"execute_id"`
Department string `json:"department" form:"department"`
Project string `json:"project" form:"project"`
APP string `json:"app" form:"app"`
TestName string `json:"test_name" form:"test_name" param:"test_name"`
TestNameNick string `json:"test_name_nick" form:"test_name_nick"`
JobName string `json:"job_name" form:"job_name"`
Count int `json:"count"`
QPS int `json:"qps"`
AvgTime int `json:"avg_time"`
Min int `json:"min"`
Max int `json:"max"`
Error int `json:"error"`
FailPercent string `json:"fail_percent"`
NinetyTime int `json:"ninety_time"`
NinetyFiveTime int `json:"ninety_five_time"`
NinetyNineTime int `json:"ninety_nine_time"`
NetIo int `json:"net_io"`
ElapsdTime int `json:"elapsd_time"`
TestStatus int `json:"test_status"`
UserName string `json:"user_name" form:"user_name"`
ResJtl string `json:"res_jtl"`
JmeterLog string `json:"jmeter_log"`
DockerSum int `json:"docker_sum"`
Ctime time.Time `json:"ctime"`
Mtime time.Time `json:"mtime"`
Debug int `json:"debug"`
Active int `json:"active" form:"active"`
SceneID int `json:"scene_id" form:"scene_id"`
Type int `json:"type" form:"type"` // 0.http单接口 1.grpc报告 2.场景报告 3.全链路
LoadTime int `json:"load_time"` //执行时间
FiftyTime int `json:"fifty_time"`
IsFusing bool `json:"is_fusing"` //是否熔断
FusingTestName string `json:"fusing_test_name"` //被熔断接口
SuccessCodeRate int `json:"success_code_rate"` //熔断时接口的httpcode
SuccessBusinessRate int `json:"success_business_rate"` //熔断时接口的成功率
FusingValue int `json:"fusing_value"` //熔断阈值
BusinessValue int `json:"business_value"` //业务熔断阈值
UseBusinessStop bool `json:"use_business_stop"` //是否使用业务熔断
}
//QueryReportSuRequest query report summary request
type QueryReportSuRequest struct {
ReportSummary
//Script
Pagination
Executor string `json:"executor" form:"executor"`
SearchAll bool `json:"search_all" form:"search_all"`
}
//QueryReportSuResponse query report summary response
type QueryReportSuResponse struct {
ReportSummarys []*ReportLabels `json:"reports"`
Pagination
}
//ReportLabels report labels
type ReportLabels struct {
ReportSummary
Labels []*LabelRelation `json:"labels"`
}
//TableName tablename
func (r ReportSummary) TableName() string {
return "report_summary"
}

View File

@@ -0,0 +1,43 @@
package model
import "time"
//ReportTimely report timely
type ReportTimely struct {
ID int `json:"id" gorm:"AUTO_INCREMENT;primary_key;" form:"id"`
TestName string `json:"test_name" form:"test_name"`
Count int `json:"count"`
QPS int `json:"qps"`
AvgTime int `json:"avg_time"`
Min int `json:"min"`
Max int `json:"max"`
Error int `json:"error"`
FailPercent string `json:"fail_percent"`
NinetyTime int `json:"ninety_time"`
NinetyFiveTime int `json:"ninety_five_time"`
NinetyNineTime int `json:"ninety_nine_time"`
NetIo int `json:"net_io"`
CodeEll int `json:"code_ell"`
CodeWll int `json:"code_wll"`
CodeWly int `json:"code_wly"`
CodeWle int `json:"code_wle"`
CodeWls int `json:"code_wls"`
CodeSll int `json:"code_sll"`
CodeSly int `json:"code_sly"`
CodeSls int `json:"code_sls"`
CodeKong int `json:"code_kong"`
CodeNonHTTP int `json:"code_non_http"`
CodeOthers int `json:"code_others"`
PodName string `json:"pod_name" form:"pod_name"`
ThreadsSum int `json:"threads_sum"`
Ctime time.Time `json:"ctime"`
Mtime time.Time `json:"mtime"`
FiftyTime int `json:"fifty_time"`
Code301 int `json:"code301"`
Code302 int `json:"code302"`
}
//TableName table name
func (r ReportTimely) TableName() string {
return "report_timely"
}

View File

@@ -0,0 +1,266 @@
package model
import (
"time"
)
// Scene GRPCReqToGRPC
type Scene struct {
ID int `json:"id" gorm:"AUTO_INCREMENT;primary_key;" form:"id"`
SceneName string `json:"scene_name" form:"scene_name"`
SceneType int `json:"scene_type" form:"scene_type"`
UserName string `json:"user_name" form:"user_name"`
IsDraft int `json:"is_draft" form:"is_draft"`
IsDebug bool `json:"is_debug" form:"is_debug"`
IsBatch bool `json:"is_batch" gorm:"-"`
Scripts []*Script `json:"scripts" gorm:"-"`
ThreadGroup interface{} `json:"thread_group" gorm:"-"`
ScriptPath string `json:"script_path" gorm:"-"`
IsExecute bool `json:"is_execute" gorm:"-"`
JmeterFilePath string `json:"jmeter_file_path"`
Department string `json:"department" form:"department"`
Project string `json:"project" form:"project"`
APP string `json:"app" form:"app"`
Fusing int `json:"fusing" form:"fusing"`
IsUpdate bool `json:"is_update" form:"is_update" gorm:"-"`
JmeterLog string `json:"jmeter_log"`
ResJtl string `json:"res_jtl"`
IsActive bool `json:"is_active" form:"is_active"`
Ctime time.Time `json:"ctime" form:"ctime"`
Mtime time.Time `json:"mtime" form:"mtime"`
}
// Draft Draft
type Draft struct {
SceneID int `json:"scene_id" form:"scene_id"`
SceneName string `json:"scene_name" form:"scene_name"`
}
// QueryDraft QueryDraft
type QueryDraft struct {
Total int `json:"total"`
Drafts []*Draft `json:"draft_list"`
}
// Relation Relation
type Relation struct {
GroupID int `json:"group_id"`
Count int `json:"count"`
}
// QueryRelation Query Relation
type QueryRelation struct {
RelationList []*Relation `json:"relation_list"`
}
// QueryAPIs Query APIs
type QueryAPIs struct {
Total int `json:"total"`
SceneID int `json:"scene_id"`
SceneName string `json:"scene_name"`
SceneType int `json:"scene_type"`
Department string `json:"department"`
Project string `json:"project"`
App string `json:"app"`
APIs []*TestAPI `json:"api_list"`
}
// TestAPI Test API
type TestAPI struct {
GroupID int `json:"group_id" form:"group_id"`
RunOrder int `json:"run_order" form:"run_order"`
ID int `json:"id" form:"id"`
TestName string `json:"test_name" form:"test_name"`
URL string `json:"url" form:"url"`
OutputParams string `json:"output_params" form:"output_params"`
ThreadsSum string `json:"threads_sum" form:"threads_sum"`
LoadTime string `json:"load_time" form:"load_time"`
}
// ShowTree Show Tree
type ShowTree struct {
IsShow int `json:"is_show" form:"is_show"`
Tree []*Tree `json:"tree" form:"tree"`
}
// RunOrder Run Order
type RunOrder struct {
SceneID int `json:"scene_id" form:"scene_id"`
SceneType int `json:"scene_type" form:"scene_type"`
}
// RunOrderList Run Order List
type RunOrderList struct {
Total int `json:"total"`
RunOrders []*RunOrder `json:"run_order_list"`
}
// Params Params
type Params struct {
ID int `json:"id" form:"id"`
GroupID int `json:"group_id" form:"group_id"`
RunOrder int `json:"run_order" form:"run_order"`
OutputParams string `json:"output_params" form:"output_params"`
}
// ParamList ParamList
type ParamList struct {
ParamList []*Params `json:"param_list" form:"param_list"`
}
// SaveOrderReq Save Order Req
type SaveOrderReq struct {
GroupOrderList []*GroupOrder `json:"group_order_list"`
}
// GroupOrder Group Order
type GroupOrder struct {
ID int `json:"id"`
TestName string `json:"test_name"`
GroupID int `json:"group_id"`
RunOrder int `json:"run_order"`
}
// TableName Table Name
func (w Scene) TableName() string {
return "scene"
}
//QuerySceneResponse query scene response
type QuerySceneResponse struct {
Scenes []*Scene `json:"scenes"`
Pagination
}
//QuerySceneRequest query script request
type QuerySceneRequest struct {
Scene
Pagination
Executor string `json:"executor" form:"executor"`
}
// DoPtestSceneParam Do Ptest Scene Param
type DoPtestSceneParam struct {
SceneID int `json:"scene_id" form:"scene_id"`
UserName string `json:"user_name" form:"user_name"`
}
// DoPtestSceneParams Do Ptests Scene Param
type DoPtestSceneParams struct {
SceneIDs []int `json:"scene_ids" form:"scene_ids"`
UserName string `json:"user_name" form:"user_name"`
}
// SceneInfo Scene Info
type SceneInfo struct {
MaxLoadTime int `json:"max_load_time" form:"max_load_time"`
TestNames []string `json:"test_names"`
TestNameNicks []string `json:"test_name_nicks"`
JmeterLog string `json:"jmeter_log"`
ResJtl string `json:"res_jtl"`
LoadTimes []int `json:"load_times"`
SceneName string `json:"scene_name"`
Scripts []*Script `json:"scripts"`
}
// APIInfo API Info
type APIInfo struct {
ID int `json:"id" form:"id"`
TestName string `json:"test_name" form:"test_name"`
URL string `json:"url" form:"url"`
ThreadsSum int `json:"threads_sum" form:"threads_sum"`
LoadTime int `json:"load_time" form:"load_time"`
}
// APIInfoList API Info List
type APIInfoList struct {
SceneID int `json:"scene_id" form:"scene_id"`
Pagination
ScriptList []*Script `json:"script_list"`
}
// APIInfoRequest API Info Request
type APIInfoRequest struct {
Script
Pagination
//DeliverySceneID int `json:"delivery_scene_id" form:"delivery_scene_id"`
}
// PreviewInfoList Preview Info List
type PreviewInfoList struct {
PreviewInfoList []*PreviewInfo `json:"preview_info_list"`
}
// PreviewInfo Preview Info
type PreviewInfo struct {
GroupInfo
InfoList []*Preview `json:"info_list"`
}
// Preview Preview
type Preview struct {
ID int `json:"id"`
TestName string `json:"test_name"`
RunOrder int `json:"run_order"`
GroupID int `json:"group_id"`
ConstTimer int `json:"const_timer"`
RandomTimer int `json:"random_timer"`
}
// PreviewList Preview List
type PreviewList struct {
PreList []*Preview `json:"pre_list"`
}
// GroupList Group List
type GroupList struct {
GroupList []*GroupInfo `json:"group_list"`
}
// GroupInfo Group Info
type GroupInfo struct {
GroupID int `json:"group_id"`
ThreadsSum int `json:"threads_sum"`
LoadTime int `json:"load_time"`
ReadyTime int `json:"ready_time"`
}
// UsefulParams Useful Params
type UsefulParams struct {
OutputParams string `json:"output_params"`
}
// UsefulParamsList Useful Params
type UsefulParamsList struct {
ParamsList []*UsefulParams `json:"params_list"`
}
// Test test
type Test struct {
Count int `json:"count"`
}
// BindScene Bind Scene
type BindScene struct {
SceneID int `json:"scene_id"`
ID string `json:"id"`
}
// DrawRelationList Draw Relation List
type DrawRelationList struct {
//Nodes []*string `json:"nodes"`
Nodes []*Node `json:"nodes"`
Edges []*Edge `json:"edges"`
}
// Node Node
type Node struct {
ID int `json:"id"`
Name string `json:"name"`
}
// Edge Edge
type Edge struct {
Source string `json:"source"`
Target string `json:"target"`
}

View File

@@ -0,0 +1,159 @@
package model
import (
"time"
)
//Script script
type Script struct {
ID int `json:"id" gorm:"AUTO_INCREMENT;primary_key;" form:"id"`
TreeID int `json:"tree_id"`
ProjectID int `json:"project_id" form:"project_id"`
Type int `json:"type" form:"type"`
ProjectName string `json:"project_name" form:"project_name"`
TestName string `json:"test_name" form:"test_name"`
ThreadsSum int `json:"threads_sum" form:"threads_sum"`
LoadTime int `json:"load_time"`
ReadyTime int `json:"ready_time"`
ProcType string `json:"proc_type"`
URL string `json:"url" form:"url" gorm:"url"`
Domain string `json:"domain" form:"domain"`
Port string `json:"port"`
Login bool `json:"login"`
Path string `json:"path"`
Method string `json:"method" form:"method"`
Cookie string `json:"cookie" form:"cookie"`
ContentType string `json:"content_type"`
Data string `json:"data" form:"data"`
Assertion string `json:"assertion"`
AssertionString interface{} `json:"assertion_string" gorm:"-"`
UseAssertion bool `json:"use_assertion" gorm:"-"`
UseBuiltinParam bool `json:"use_builtin_param" gorm:"-"`
SavePath string `json:"save_path" form:"save_path"`
ResJtl string `json:"res_jtl" form:"res_jtl"`
JmeterLog string `json:"jmeter_log"`
UpdateBy string `json:"update_by" form:"update_by"`
Ctime time.Time `json:"ctime" form:"ctime"`
Mtime time.Time `json:"mtime" form:"mtime"`
Active int `json:"active"`
Upload bool `json:"upload" form:"upload"`
Headers []map[string]string `json:"headers" form:"headers" gorm:"-"` // true
APIHeader string `json:"api_header"`
ArgumentsMap []map[string]string `json:"arguments_map" gorm:"-"` // true
ArgumentString string `gorm:"column:argument_map"`
RowQuery string `json:"row_query" form:"row_query" gorm:"-"`
UseSign bool `json:"use_sign" form:"use_sign"`
LabelIds []int `json:"label_ids" form:"label_ids" gorm:"-"`
IsCopy bool `json:"is_copy" form:"is_copy" gorm:"-"`
ConnTimeOut int `json:"conn_time_out"`
RespTimeOut int `json:"resp_time_out"`
IsSave bool `json:"is_save" gorm:"-"`
TestType int `json:"test_type" form:"test_type"`
SceneID int `json:"scene_id" form:"scene_id"`
OutputParamsMap []map[string]string `json:"output_params_map" form:"output_params_map" gorm:"-"`
OutputParams string `json:"output_params" form:"output_params"`
JSONPath string `json:"json_path"`
GroupID int `json:"group_id" form:"group_id"`
RunOrder int `json:"run_order" form:"run_order"`
ScriptPath string `json:"script_path" form:"script_path"`
JmeterSample interface{} `json:"jmeter_sample" gorm:"-"`
JSONExtractor interface{} `json:"json_extractor" gorm:"-"`
IsAsync bool `json:"is_async" form:"is_async"`
AsyncInfo interface{} `json:"async_info" gorm:"-"`
MultiPartInfo interface{} `json:"multi_part_info" gorm:"-"`
UseMultipart bool `json:"use_multipart" gorm:"-"`
MultipartPath string `json:"multipart_path"`
MultipartFile string `json:"multipart_file"`
MultipartParam string `json:"multipart_param"`
MimeType string `json:"mime_type"`
Fusing int `json:"fusing"`
UseBusinessStop bool `json:"use_business_stop" form:"use_business_stop"`
BusinessStopPercent int `json:"business_stop_percent" form:"business_stop_percent"`
KeepAlive bool `json:"keep_alive" form:"keep_alive"`
ExecuDockerSum int `json:"execu_docker_sum" gorm:"-"`
ConstTimer int `json:"const_timer"`
ConstTimerInfo interface{} `json:"const_timer_info" gorm:"-"`
RandomTimer int `json:"random_timer"`
RandomTimerInfo interface{} `json:"random_timer_info" gorm:"-"`
DataFile
TreePath
}
//APIH api headers
type APIH struct {
APIHeader []map[string]string `json:"api_header"`
}
//ScriptScene script scene
type ScriptScene struct {
Scripts []Script `json:"scripts" form:"scripts"`
}
// TreePath service tree
type TreePath struct {
Department string `json:"department" form:"department"`
Project string `json:"project" form:"project"`
App string `json:"app" form:"app"`
}
//QueryScriptResponse query script response
type QueryScriptResponse struct {
Scripts []*ScriptLabels `json:"scripts"`
Pagination
}
//ScriptLabels script labels
type ScriptLabels struct {
Script
Labels []*LabelRelation `json:"labels"`
}
//DataFile ignore db
type DataFile struct {
UseDataFile bool `json:"use_data_file" gorm:"use_data_file"` // true
FileName string `json:"file_name" gorm:"file_name"` // true
ParamsName string `json:"params_name" gorm:"params_name"` // true
Delimiter string `json:"delimiter" gorm:"delimiter"` // true
Loops int `json:"loops" gorm:"loops"` // true
ResLog string `json:"res_log" gorm:"-"`
BeginTestName string `json:"begin_test_name" gorm:"-"`
IsDebug bool `json:"is_debug" gorm:"-"`
HeaderString interface{} `json:"header_string" gorm:"-"`
Arguments interface{} `json:"arguments" gorm:"-"`
FileSplit bool `json:"file_split" form:"file_split"`
SplitNum int `json:"split_num" form:"split_num"`
}
//QueryScriptRequest query script request
type QueryScriptRequest struct {
Script
Pagination
Executor string `json:"executor" form:"executor"`
}
//ScrThreadGroup script thread group
type ScrThreadGroup struct {
Scripts []*Script `json:"scripts"`
}
//URLEncode URL Encode
type URLEncode struct {
ParamsType string `json:"params_type"`
NewUrl string `json:"new_url"`
}
//TableName db table name of script
func (st Script) TableName() string {
return "script"
}
// FusingInfo Fusing List
type FusingInfo struct {
Fusing int `json:"fusing"`
}
// FusingInfoList Fusing Info List
type FusingInfoList struct {
FusingList []FusingInfo `json:"fusing_list"`
SetNull bool `json:"set_null"`
}

View File

@@ -0,0 +1,62 @@
package model
import (
"time"
)
//ScriptSnap script snap
type ScriptSnap struct {
ID int `json:"id" gorm:"AUTO_INCREMENT;primary_key;" form:"id"`
ScriptID int `json:"script_id"`
TreeID int `json:"tree_id"`
ProjectID int `json:"project_id" form:"project_id"`
ExecuteID string `json:"execute_id" form:"execute_id"`
Type int `json:"type" form:"type"`
ProjectName string `json:"project_name" form:"project_name"`
TestName string `json:"test_name" form:"test_name"`
ThreadsSum int `json:"threads_sum" form:"threads_sum"`
LoadTime int `json:"load_time"`
ReadyTime int `json:"ready_time"`
ProcType string `json:"proc_type"`
URL string `json:"url"`
Domain string `json:"domain" form:"domain"`
Port string `json:"port"`
Login bool `json:"login"`
Path string `json:"path"`
Method string `json:"method" form:"method"`
Cookie string `json:"cookie" form:"cookie"`
ContentType string `json:"content_type"`
Data string `json:"data" form:"data"`
Assertion string `json:"assertion"`
SavePath string `json:"save_path" form:"save_path"`
ResJtl string `json:"res_jtl" form:"res_jtl"`
JmeterLog string `json:"jmeter_log"`
UpdateBy string `json:"update_by" form:"update_by"`
Ctime time.Time `json:"ctime" form:"ctime"`
Mtime time.Time `json:"mtime" form:"mtime"`
Active int `json:"active"`
Upload bool `json:"upload" form:"upload"`
Headers []map[string]string `json:"headers" form:"headers" gorm:"-"` // true
APIHeader string `json:"api_header" gorm:"column:api_header"`
ArgumentsMap []map[string]string `json:"arguments_map" gorm:"-"` // true
ArgumentString string `gorm:"column:argument_map"`
ConnTimeOut int `json:"conn_time_out"`
RespTimeOut int `json:"resp_time_out"`
UseSign bool `json:"use_sign" form:"use_sign"`
SceneID int `json:"scene_id" form:"scene_id"`
GroupID int `json:"group_id" form:"group_id"`
IsAsync bool `json:"is_async" form:"is_async"`
MultipartPath string `json:"multipart_path"`
MultipartFile string `json:"multipart_file"`
MultipartParam string `json:"multipart_param"`
MimeType string `json:"mime_type"`
Fusing int `json:"fusing"`
KeepAlive bool `json:"keep_alive" form:"keep_alive"`
DataFile
TreePath
}
//TableName script
func (st ScriptSnap) TableName() string {
return "script_snap"
}

View File

@@ -0,0 +1,59 @@
package model
// TreeResponse service tree response model
type TreeResponse struct {
Code int `json:"code"`
Data UserTree `json:"data"`
}
// UserTree user tree model
type UserTree struct {
Bilibili map[string]interface{} `json:"bilibili"`
}
// TreeSonResponse tree son response model
type TreeSonResponse struct {
Code int `json:"code"`
Data map[string]interface{} `json:"data"`
}
// TreeConf service tree conf model
type TreeConf struct {
Host string
}
// TokenResponse service tree token response model
type TokenResponse struct {
Token string `json:"token"`
UserName string `json:"user_name"`
Secret string `json:"secret"`
Expired int64 `json:"expired"`
}
// TreeAdminResponse service tree admin response model
type TreeAdminResponse struct {
Code int `json:"code"`
Data []*TreeRole `json:"data"`
}
// TreeRole service tree role
type TreeRole struct {
UserName string `json:"user_name"`
Role int `json:"role"`
OldRole int `json:"old_role"`
}
// TreeRoleApp tree role app
type TreeRoleApp struct {
Code int `json:"code"`
Data []*RoleApp `json:"data"`
}
// RoleApp role app
type RoleApp struct {
ID int `json:"id"`
Name string `json:"name"`
Path string `json:"path"`
Type int `json:"type"` // Type 1.公司 2.部门 3.项目 4. 应用 5.环境 6.挂载点
Role int `json:"role"` // Role 1:管理员 2:研发 3:测试 4:运维 5:访客
}

View File

@@ -0,0 +1,15 @@
package model
// User user model for login
type User struct {
ID int64 `json:"id" gorm:"AUTO_INCREMENT;primary_key;"`
Name string `json:"name"`
Email string `json:"email"`
Accept int32 `json:"accept"`
Active string `json:"active"`
}
// TableName get user model name
func (u User) TableName() string {
return "user"
}

View File

@@ -0,0 +1,34 @@
package model
//MsgSendReq message send request of wechat
type MsgSendReq struct {
ChatID string `json:"chatid" form:"chatid"`
MsgType string `json:"msgtype" form:"msgtype"`
Text MsgSendReqText `json:"text" form:"test"`
Safe int `json:"safe" form:"safe"`
}
// MsgSendPersonReq send msg to person request model
type MsgSendPersonReq struct {
Users []string `json:"touser"`
Content string `json:"content"`
}
//MsgSendReqText MegSendReq test
type MsgSendReqText struct {
Content string `json:"content"`
}
//MsgSendRes message send response
type MsgSendRes struct {
Code int `json:"code"`
Message string `json:"message"`
TTL int `json:"ttl"`
Data WechatMegSendResData `json:"data"`
}
//WechatMegSendResData message send response data of wechat
type WechatMegSendResData struct {
Errcode int `json:"errcode"`
Errmsg string `json:"errmsg"`
}

View File

@@ -0,0 +1,99 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = [
"apply_test.go",
"grpc_snap_test.go",
"grpc_test.go",
"label_test.go",
"mail_test.go",
"order_admin_test.go",
"order_test.go",
"rank_test.go",
"report_test.go",
"scene_test.go",
"script_test.go",
"service_test.go",
"user_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/admin/ep/melloi/conf:go_default_library",
"//app/admin/ep/melloi/model:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"apply.go",
"bfs.go",
"clientmoni.go",
"cluster.go",
"comment.go",
"dapper.go",
"file.go",
"grpc.go",
"grpc_snap.go",
"job.go",
"label.go",
"mail.go",
"order.go",
"order_admin.go",
"order_report.go",
"ptest.go",
"rank.go",
"report.go",
"scene.go",
"script.go",
"script_snap.go",
"service.go",
"tools.go",
"tree.go",
"user.go",
"wechat.go",
],
importpath = "go-common/app/admin/ep/melloi/service",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/admin/ep/melloi/conf:go_default_library",
"//app/admin/ep/melloi/dao:go_default_library",
"//app/admin/ep/melloi/model:go_default_library",
"//app/admin/ep/melloi/service/proto: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",
"//vendor/github.com/pkg/errors:go_default_library",
"//vendor/github.com/robfig/cron:go_default_library",
"//vendor/gopkg.in/gomail.v2:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//app/admin/ep/melloi/service/proto:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,175 @@
package service
import (
"context"
"encoding/base64"
"fmt"
"strconv"
"strings"
"time"
"go-common/app/admin/ep/melloi/model"
"go-common/library/ecode"
"go-common/library/log"
)
// QueryApply query apply by apply object
func (s *Service) QueryApply(qar *model.QueryApplyRequest) (*model.QueryApplyResponse, error) {
return s.dao.QueryApply(&qar.Apply, qar.PageNum, qar.PageSize)
}
// QueryUserApplyList query user apply list
func (s *Service) QueryUserApplyList(userName string) ([]*model.Apply, error) {
return s.dao.QueryUserApplyList(userName)
}
// CheckRunPermission check user run permission
func (s *Service) CheckRunPermission(userName string) (ret bool) {
var (
startTime int64
err error
endTime int64
applyList []*model.Apply
)
currentTime := time.Now().Unix()
//白名单的人不需要做check直接返回true
if ExistsInSlice(userName, s.c.Melloi.Executor) {
ret = true
return
}
if applyList, err = s.dao.QueryUserApplyList(userName); err != nil {
log.Error("s.dao.QueryUserApplyList err :(%v)", err)
return
}
for _, apply := range applyList {
if startTime, err = strconv.ParseInt(apply.StartTime, 10, 64); err != nil {
return
}
if endTime, err = strconv.ParseInt(apply.EndTime, 10, 64); err != nil {
return
}
if currentTime >= startTime && currentTime <= endTime {
ret = true
break
}
}
return ret
}
// CheckRunTime check perf time
func (s *Service) CheckRunTime() (ret bool) {
currentTime := time.Now()
// 1:30 ~ 12:00
if currentTime.Hour() >= 1 && currentTime.Hour() < 12 {
ret = true
}
// 14:00 ~ 17:00
if currentTime.Hour() >= 14 && currentTime.Hour() < 17 {
ret = true
}
return
}
// UpdateApply update apply info
func (s *Service) UpdateApply(cookie string, apply *model.Apply) (err error) {
var user *model.User
if apply.ID == 0 {
return ecode.MelloiApplyRequestErr
}
if user, err = s.QueryUser(apply.From); err != nil {
log.Error("update apply query user error:%v)", err)
return
}
if user.ID != 0 {
user.Accept = apply.Status
if err = s.dao.UpdateUser(user); err != nil {
return err
}
// 判断是审批操作,发送微信通知
if apply.Status == 1 {
applyMsg, _ := s.dao.QueryApplyByID(apply.ID)
startTime, _ := strconv.Atoi(applyMsg.StartTime)
st := time.Unix(int64(startTime), 0)
endTime, _ := strconv.Atoi(applyMsg.EndTime)
et := time.Unix(int64(endTime), 0)
content := "[MELLOI]压测申请处理完成 通知 \n 压测服务: " + applyMsg.Path + "\n" + "压测时间:" + st.Format("2006-01-02 15:04:05") + "\n" + "压测结束时间:" + et.Format("2006-01-02 15:04:05") + "\n" + "申请人:" +
applyMsg.From + "\n" + "审批人:" + applyMsg.To + "\n" + "审批时间:" + time.Now().Format("2006-01-02 15:04:05")
log.Info("content:(%s)", content)
// 发送申请通过到群
go s.AddWechatSend(context.TODO(), cookie, content)
// 给申请人发送邮件
go s.SendMail(apply.From+"@bilibili.com", "[MELLOI]压测申请通知", content)
}
return s.dao.UpdateApply(apply)
}
return ecode.MelloiUpdateUserErr
}
// AddApply add new apply
func (s *Service) AddApply(c context.Context, cookie string, apply *model.Apply) (err error) {
apply.Status = -1
apply.Active = 1
// 添加apply到db
if err = s.dao.AddApply(apply); err != nil {
return ecode.MelloiApplyRequestErr
}
// 发送微信消息 & 发送邮件通知
//加密 apply.id|apply.from|apply.to
applyID := strconv.FormatInt(apply.ID, 10)
beStr := applyID + "|" + apply.From + "|" + apply.To
base64Str := base64.StdEncoding.EncodeToString([]byte(beStr))
// 将时间戳转成日期
startTime, _ := strconv.Atoi(apply.StartTime)
st := time.Unix(int64(startTime), 0)
endTime, _ := strconv.Atoi(apply.EndTime)
et := time.Unix(int64(endTime), 0)
// 增加依赖服务列表
var (
userService map[string][]string
serviceList = make(map[string][]string)
serviceDep string
serviceName string
)
serviceName = strings.Replace(apply.Path, "bilibili.", "", 1)
if userService, err = s.QueryDependServiceAdmins(c, serviceName, s.getSessionInCookie(cookie)); err != nil {
log.Error("query depend service admin error(%v)", err)
return
}
for _, v := range userService {
for _, service := range v {
serviceList[service] = nil
}
}
for k := range serviceList {
serviceDep += "\n" + k
}
// 拼接消息体amd=base64Str
content := fmt.Sprintf("[MELLOI]压测申请处理 通知 \n 压测服务:%s\n压测开始时间段:%s\n压测结束时间段:%s\n申请人:%s\n申请时间:%s\n依赖服务:%s\n审批地址:http://melloi.bilibili.co#/apply-m?platform=mb&amd=%s",
apply.Path, st.Format("2006-01-02 15:04:05"), et.Format("2006-01-02 15:04:05"),
apply.From, time.Now().Format("2006-01-02 15:04:05"), serviceDep, base64Str)
// 消息接收人
var touser []string
touser = append(touser, apply.To)
// 发送微信
go s.dao.PushWechatMsgToPerson(context.TODO(), cookie, touser, content)
// 发送邮件
subject := "Melloi压测申请"
go s.SendMail(apply.To+"@bilibili.com", subject, content)
return
}
// DeleteApply delete apply
func (s *Service) DeleteApply(id int64) error {
return s.dao.DeleteApply(id)
}

View File

@@ -0,0 +1,47 @@
package service
import (
"testing"
. "github.com/smartystreets/goconvey/convey"
"go-common/app/admin/ep/melloi/model"
)
var (
apply = model.Apply{ID: 1, Path: "bilibili.test.ep.melloi", From: "hujianping",
To: "hujianping", Status: 1, Active: 1, StartTime: "1541007000", EndTime: "1541235600"}
qar = model.QueryApplyRequest{
Apply: apply,
Pagination: model.Pagination{PageNum: 1, PageSize: 1, TotalSize: 1},
}
userName = "hujianping"
cookie = "_AJSESSIONID=e2df43ed324d20811e8d1be1a9fb36d5"
)
func Test_Apply(t *testing.T) {
Convey("query apply info", t, func() {
_, err := s.QueryApply(&qar)
So(err, ShouldBeNil)
})
Convey("query user applyList", t, func() {
_, err := s.QueryUserApplyList(userName)
So(err, ShouldBeNil)
})
Convey("add apply", t, func() {
err := s.AddApply(c, cookie, &apply)
So(err, ShouldBeNil)
})
Convey("update apply", t, func() {
err := s.UpdateApply(cookie, &apply)
So(err, ShouldBeNil)
})
Convey("delete apply", t, func() {
err := s.DeleteApply(apply.ID)
So(err, ShouldBeNil)
})
}

View File

@@ -0,0 +1,8 @@
package service
import "context"
// UploadImg upload img
func (s *Service) UploadImg(c context.Context, imgContent []byte, imgName string) (location string, err error) {
return s.dao.UploadImg(c, imgContent, imgName)
}

View File

@@ -0,0 +1,8 @@
package service
import "go-common/app/admin/ep/melloi/model"
//AddClientMoni add ClientMoni
func (s *Service) AddClientMoni(clm *model.ClientMoni) (int, error) {
return s.dao.AddClientMoni(clm)
}

View File

@@ -0,0 +1,28 @@
package service
import (
"context"
"go-common/app/admin/ep/melloi/model"
"go-common/library/ecode"
)
//RmToken Get PaaS token
func (s *Service) RmToken(c context.Context) (token string, err error) {
return s.dao.RmToken(c)
}
//ClusterInfo get melloi server use
func (s *Service) ClusterInfo(c context.Context) (firstRetMap []*model.ClusterResponseItemsSon, err error) {
var token string
if token, err = s.RmToken(c); err != nil {
//err = ecode.MelloiGetTreeTokenErr
return
}
if firstRetMap, err = s.dao.NetInfo(c, token); err != nil {
err = ecode.MerlinGetUserTreeFailed
return
}
return
}

View File

@@ -0,0 +1,29 @@
package service
import (
"time"
"go-common/app/admin/ep/melloi/model"
)
//AddComment add comment for test job
func (s *Service) AddComment(comment *model.Comment) error {
comment.Status = 1
comment.SubmitDate = time.Now()
return s.dao.AddComment(comment)
}
//QueryComment query comment
func (s *Service) QueryComment(comment *model.Comment) (*model.QueryCommentResponse, error) {
return s.dao.QueryComment(comment)
}
//UpdateComment update comment
func (s *Service) UpdateComment(comment *model.Comment) error {
return s.dao.UpdateComment(comment)
}
//DeleteComment delete comment
func (s *Service) DeleteComment(id int64) error {
return s.dao.DeleteComment(id)
}

View File

@@ -0,0 +1,43 @@
package service
import (
"context"
"go-common/app/admin/ep/melloi/model"
"go-common/library/log"
)
// QueryDependServiceAdmins query depend Service admin
func (s *Service) QueryDependServiceAdmins(c context.Context, serviceName string, sessionValue string) (map[string][]string, error) {
var (
biliPrex = "bilibili."
err error
roles []*model.TreeRole
dependService []string
olesMap = make(map[string][]string)
)
if dependService, err = s.dao.QueryServiceDepend(c, serviceName); err != nil {
log.Error("query service depend error(%v)", err)
return nil, err
}
dependService = append(dependService, serviceName)
for _, service := range dependService {
var userService []string
if roles, err = s.QueryTreeAdmin(c, biliPrex+service, sessionValue); err != nil {
log.Warn("query tree admin of service (%s) depend error (%v)", biliPrex+service, err)
continue
}
for _, role := range roles {
// 增加多个service
userService = append(olesMap[role.UserName], biliPrex+service)
olesMap[role.UserName] = userService
}
}
return olesMap, err
}

View File

@@ -0,0 +1,297 @@
package service
import (
"bufio"
"context"
"fmt"
"io"
"mime/multipart"
"net/http"
"os"
"os/exec"
"path"
"path/filepath"
"strings"
"go-common/app/admin/ep/melloi/conf"
"go-common/app/admin/ep/melloi/model"
"go-common/library/ecode"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"github.com/pkg/errors"
)
// Upload upload file
func (s *Service) Upload(c context.Context, uploadParam *model.UploadParam, formFile multipart.File, header *multipart.FileHeader) (id int, scriptPath string, err error) {
var destFile *os.File
//创建脚本保存路径
if uploadParam.ScriptPath == "" {
if scriptPath, err = s.uniqueFolderPath(uploadParam.Path); err != nil {
return
}
} else {
scriptPath = uploadParam.ScriptPath
}
//创建保存文件
if destFile, err = os.Create(scriptPath + header.Filename); err != nil {
log.Error("Create failed,error(%v)", err)
return
}
defer destFile.Close()
// 读取表单文件,写入保存文件
if _, err = io.Copy(destFile, formFile); err != nil {
log.Error("write file error (%v)", err)
return
}
// jmx文件
if strings.Contains(header.Filename, ".jmx") {
treePath := model.TreePath{Department: uploadParam.Department, Project: uploadParam.Project, App: uploadParam.APP}
script := model.Script{
ProjectName: uploadParam.TestName,
//TestName: uploadParam.TestName,
SavePath: destFile.Name(),
UpdateBy: uploadParam.UserName,
TreePath: treePath,
Upload: true,
Active: 1,
ResJtl: scriptPath + "jtl",
JmeterLog: scriptPath + "jmg",
ScriptPath: scriptPath,
ArgumentString: "[{\"\":\"\"}]",
TestType: 1,
Domain: uploadParam.Domains,
Fusing: uploadParam.Fusing,
UseBusinessStop: uploadParam.UseBusinessStop,
BusinessStopPercent: uploadParam.BusinessStopPercent,
}
if id, _, _, err = s.dao.AddScript(&script); err != nil {
log.Error("s.dao.AddScript err :(%v)", err)
return
}
}
return
}
// UploadAndGetProtoInfo upload and get proto info
func (s *Service) UploadAndGetProtoInfo(c context.Context, uploadParam *model.UploadParam, formFile multipart.File, header *multipart.FileHeader) (res map[string]interface{}, err error) {
// 获取上传路径, Path 为root_path ,ScriptPath 为 root_path + import路径
_, scriptPath, err := s.Upload(c, uploadParam, formFile, header)
if err != nil {
log.Error("Write file failed, error(%v)", err)
return
}
// 解析proto文件
path, fileName := filepath.Split(path.Join(scriptPath, header.Filename))
if res, err = s.ProtoParsing(path, fileName); err != nil {
log.Error("parser grpc error(%v)", err)
return
}
// 生成import文件路径
if err = s.CreateGRPCImportDir(res, uploadParam.Path); err != nil {
return
}
return
}
// CreateGRPCImportDir create grpc import path
func (s *Service) CreateGRPCImportDir(res map[string]interface{}, rootPath string) (err error) {
if ipts, ok := res["import"]; ok {
for _, ipt := range ipts.([]string) {
iptPath, _ := filepath.Split(ipt)
protoPath := &model.ProtoPathModel{RootPath: rootPath, ExtraPath: iptPath}
if err = s.CreateProtoImportDir(protoPath); err != nil {
log.Error("create proto import dir error(%v)", err)
return
}
}
}
return
}
// CompileProtoFile compile proto file get jar path
func (s *Service) CompileProtoFile(protoPath, filename string) (jarPath string, err error) {
return s.createGrpcJar(protoPath, filename)
}
//protocFile protoc file
func (s *Service) protocFile(scriptPath, protoPath string) (err error) {
var (
protoCMD string
protoJava string
protoFileList []string
line string
protoFiles = fmt.Sprintf("cd %s && find . -name '*.proto' | awk -F '\\.\\/' '{print $2}'", scriptPath)
stdout io.ReadCloser
)
// 获取scriptPath 目录下所有 proto文件
cmd := exec.Command("/bin/bash", "-c", protoFiles)
if stdout, err = cmd.StdoutPipe(); err != nil {
log.Error("run protoFiles (%s) error(%v)", protoFiles, err)
return
}
cmd.Start()
reader := bufio.NewReader(stdout)
for {
if line, err = reader.ReadString('\n'); err != nil || io.EOF == err {
break
}
if line != "" {
protoFileList = append(protoFileList, line)
}
}
// 编译所有proto文件
for _, line := range protoFileList {
protoCMD = fmt.Sprintf("protoc -I %s --java_out=%s %s", scriptPath, protoPath, path.Join(scriptPath, line))
protoJava = fmt.Sprintf("protoc --plugin=protoc-gen-grpc-java=%s --grpc-java_out=%s -I %s %s",
s.c.Grpc.ProtoJavaPluginPath, protoPath, scriptPath, path.Join(scriptPath, line))
if err = exec.Command("/bin/bash", "-c", protoCMD).Run(); err != nil {
log.Error("protoc --proto_path (%s) error (%v)", protoCMD, err)
return ecode.MelloiProtocError
}
// 编译所有proto文件
for _, line := range protoFileList {
protoCMD = fmt.Sprintf("protoc -I %s --java_out=%s %s", scriptPath, protoPath, path.Join(scriptPath, line))
protoJava = fmt.Sprintf("protoc --plugin=protoc-gen-grpc-java=%s --grpc-java_out=%s -I %s %s",
s.c.Grpc.ProtoJavaPluginPath, protoPath, scriptPath, path.Join(scriptPath, line))
if err = exec.Command("/bin/bash", "-c", protoCMD).Run(); err != nil {
log.Error("protoc --proto_path (%s) error (%v)", protoCMD, err)
return ecode.MelloiProtocError
}
if err = exec.Command("/bin/bash", "-c", protoJava).Run(); err != nil {
log.Error("protoc java (%s) error (%v)", protoCMD, err)
return ecode.MelloiProtocError
}
}
if err = exec.Command("/bin/bash", "-c", protoJava).Run(); err != nil {
log.Error("protoc java (%s) error (%v)", protoCMD, err)
return ecode.MelloiProtocError
}
}
return
}
//createGrpcJar crate grpc jar
func (s *Service) createGrpcJar(scriptPath, filename string) (jarPath string, err error) {
protoPath := path.Join(scriptPath, "proto")
if err = os.MkdirAll(protoPath, pathPerm); err != nil {
log.Error("create proto path err ... (%v)", err)
return
}
var (
cmdJava = fmt.Sprintf(" cd %s && find . -name '*.java' |grep -v '^\\./\\.' > sources.txt ", protoPath)
cmdJavac = fmt.Sprintf("cd %s && javac -Djava.ext.dirs=%s -encoding utf-8 @sources.txt ", protoPath, s.c.Jmeter.JmeterExtLibPath)
jarFilename = strings.Replace(filename, ".proto", "", -1) + ".jar"
cmdJar = fmt.Sprintf("cd %s && jar -cvf %s .", protoPath, jarFilename)
)
if err = s.protocFile(scriptPath, protoPath); err != nil {
log.Error("protoc error (%v)", err)
return
}
// 编译java文件
if err = exec.Command("/bin/bash", "-c", cmdJava).Run(); err != nil {
log.Error("find *.java (%s) error(%+v)", cmdJava, errors.WithStack(err))
return
}
if err = exec.Command("/bin/bash", "-c", cmdJavac).Run(); err != nil {
log.Error("javac protoc javac (%s) error(%v)", cmdJavac, err)
err = ecode.MelloiJavacCompileError
return
}
// 生成jar文件
if err = exec.Command("/bin/bash", "-c", cmdJar).Run(); err != nil {
log.Error("protoc jar (%s) error(%v)", cmdJar, err)
err = ecode.MelloiJarError
return
}
jarPath = path.Join(protoPath, jarFilename)
return
}
//DownloadFile Download File
func (s *Service) DownloadFile(c *bm.Context, filePath string, w http.ResponseWriter) (err error) {
var (
Fi *os.File
info os.FileInfo
)
if info, err = os.Stat(filePath); err != nil {
return
}
//如果文件太大,就禁止下载
if info.Size() > conf.Conf.Melloi.MaxDowloadSize {
err = ecode.MelloiBeyondFileSize
return
}
if Fi, err = os.Open(filePath); err != nil {
log.Error("open file err :(%v)", err)
return
}
defer Fi.Close()
w.Header().Set("Content-Disposition", "attachment; filename="+Fi.Name())
if _, err = io.Copy(w, io.Reader(Fi)); err != nil {
log.Error("copy file err :(%v)", err)
err = ecode.MelloiCopyFileErr
return
}
return
}
//ReadFile read file
func (s *Service) ReadFile(c *bm.Context, file, limit string) (data string, err error) {
var (
info os.FileInfo
buff []byte
cmd *exec.Cmd
)
log.Info("开始读取文件--------- : (%s)", file)
if info, err = os.Stat(file); err != nil {
return
}
if info.Size() > conf.Conf.Melloi.MaxFileSize {
cmd = exec.Command("/bin/bash", "-c", "tail -1500 "+file)
} else {
cmd = exec.Command("/bin/bash", "-c", "cat "+file)
}
buff, err = cmd.Output()
if err != nil {
return
}
data = string(buff)
return
}
//IsFileExists is file exists
func (s *Service) IsFileExists(c *bm.Context, fileName string) (bool, error) {
return exists(fileName)
}
// exists exists
func exists(path string) (bool, error) {
_, err := os.Stat(path)
if err == nil {
return true, nil
}
if os.IsNotExist(err) {
return false, nil
}
return false, err
}

View File

@@ -0,0 +1,322 @@
package service
import (
"context"
"fmt"
"html/template"
"io"
"os"
"os/exec"
"path"
"strconv"
"strings"
"time"
"go-common/app/admin/ep/melloi/model"
"go-common/app/admin/ep/melloi/service/proto"
"go-common/library/ecode"
"go-common/library/log"
)
const (
_upCase = 1
_downCase = 0
)
// capitalize 首字母大小写处理
func (s *Service) capitalize(str string, tp int) string {
b := []rune(str)
if tp == _upCase {
if b[0] >= 97 && b[1] <= 122 {
b[0] -= 32
}
} else {
if b[0] >= 64 && b[0] <= 90 {
b[0] += 32
}
}
return string(b)
}
// ProtoParsing analyze proto file
func (s *Service) ProtoParsing(protoPath, protoName string) (res map[string]interface{}, err error) {
var pkgRetMap []string
res = make(map[string]interface{})
reader, err := os.Open(path.Join(protoPath, protoName))
if err != nil {
log.Error("open proto file error(%v)", err)
return nil, err
}
defer reader.Close()
parser := proto.NewParser(reader)
var proto *proto.Proto
proto, err = parser.Parse()
if err != nil {
log.Error("parse proto file error(%v)", err)
return nil, err
}
res["fileName"] = protoName
proto.Filename = strings.TrimSuffix(protoName, ".proto")
res["protoClass"] = s.capitalize(proto.Filename, _upCase)
if len(proto.Imports) > 0 {
var retImportMap []string
for _, impt := range proto.Imports {
retImportMap = append(retImportMap, impt.Filename)
}
res["import"] = retImportMap
}
if len(proto.Package) > 0 {
for _, pkg := range proto.Package {
pkgRetMap = append(pkgRetMap, pkg.Name)
}
res["package"] = pkgRetMap
}
if len(proto.Options) > 0 {
var retOptionsList []string
for _, opt := range proto.Options {
retOptionsList = append(retOptionsList, opt.Name)
// java_package proto
if opt.Name == "java_package" && len(proto.Package) <= 0 {
pkgRetMap = append(pkgRetMap, opt.Constant.Source)
}
}
res["package"] = pkgRetMap
res["options"] = retOptionsList
}
if len(proto.Services) > 0 {
var retImportMap []map[string]interface{}
for _, srv := range proto.Services {
firstTmp := make(map[string]interface{})
firstTmp["name"] = srv.Name
var secondMapTmp []map[string]interface{}
for _, rpc := range srv.RPCElements {
secondTmp := make(map[string]interface{})
method := s.capitalize(rpc.Name, _downCase)
// transfer get_by_uid to getByUid
if strings.ContainsAny(method, "_") {
var nmethod string
methodStrs := strings.Split(method, "_")
for i, item := range methodStrs {
if i != 0 {
item = s.capitalize(item, _upCase)
}
nmethod += item
}
method = nmethod
}
secondTmp["method"] = method
secondTmp["requestType"] = rpc.RequestType
secondTmp["returnType"] = rpc.ReturnsType
secondMapTmp = append(secondMapTmp, secondTmp)
}
firstTmp["rpc"] = secondMapTmp
retImportMap = append(retImportMap, firstTmp)
}
res["service"] = retImportMap
}
return
}
// CreateProtoImportDir create import dir
func (s *Service) CreateProtoImportDir(pathModel *model.ProtoPathModel) (err error) {
cMakeDir := fmt.Sprintf("mkdir -p %s ", path.Join(pathModel.RootPath, pathModel.ExtraPath))
if err = exec.Command("/bin/bash", "-c", cMakeDir).Run(); err != nil {
log.Error("create proto import dir error(%v)", err)
}
return
}
//GRPCQuickStart grpc quickstart
func (s *Service) GRPCQuickStart(c context.Context, request *model.GRPCQuickStartRequest, runUser string, cookies string) (ret map[string]string, err error) {
var (
g *model.GRPC
reportID int
)
addScriptReq := request.GRPCAddScriptRequest
ret = make(map[string]string)
if g, err = s.GRPCAddScript(c, &addScriptReq); err != nil {
log.Error("Save grpc script failed, (%v)", err)
return
}
if reportID, err = s.GRPCRunByModel(c, g, runUser, cookies); err != nil {
log.Error("performance test execution failed, (%v)", err)
return
}
ret["report_id"] = strconv.Itoa(reportID)
return
}
// SaveGRPCQuickStart save gRPC script of quick start
func (s *Service) SaveGRPCQuickStart(c context.Context, request *model.GRPCQuickStartRequest) (err error) {
addScriptReq := request.GRPCAddScriptRequest
_, err = s.GRPCAddScript(c, &addScriptReq)
return err
}
//GRPCAddScript create grpc script
func (s *Service) GRPCAddScript(c context.Context, request *model.GRPCAddScriptRequest) (g *model.GRPC, err error) {
// 若是debug ,则执行固定次数
if request.IsDebug == 1 {
request.Loops = 4
request.ThreadsSum = 1
request.TaskName += "_perf_debug" // debug tag
}
if g, err = s.CreateJmx(c, request); err != nil {
log.Error("create jmeter file error (%v)", err)
return
}
g.IsDebug = request.IsDebug
return s.dao.CreateGRPC(g)
}
// CreateJmx create jmx
func (s *Service) CreateJmx(c context.Context, request *model.GRPCAddScriptRequest) (g *model.GRPC, err error) {
if g, err = s.createJmeterFile(request); err != nil {
log.Error("create jmeter file error (%v)", err)
return
}
return
}
//GRPCRunByScriptID grpc execution by id
func (s *Service) GRPCRunByScriptID(c context.Context, request *model.GRPCExecuteScriptRequest, runUser string, cookie string) (reportId int, err error) {
var grpc *model.GRPC
if grpc, err = s.dao.QueryGRPCByID(request.ScriptID); err != nil {
return
}
return s.GRPCRunByModel(c, grpc, runUser, cookie)
}
//GRPCRunByModel execute grpc by model data
func (s *Service) GRPCRunByModel(c context.Context, grpc *model.GRPC, runUser string, cookie string) (reportId int, err error) {
var resp model.DoPtestResp
tim := strconv.FormatInt(time.Now().Unix(), 10)
testNameNick := grpc.TaskName + tim
log.Info("开始调用压测grpc job-------\n")
ptestParam := model.DoPtestParam{
UserName: runUser, // 用户名
LoadTime: grpc.LoadTime, //运行时间
TestNames: StringToSlice(grpc.TaskName), //接口名转数组
FileName: grpc.JmxPath, // jmx文件
ResJtl: grpc.JtlLog, // jtl时间戳
JmeterLog: grpc.JmxLog, // jmeterlog时间戳
Department: grpc.Department,
Project: grpc.Project,
IsDebug: false,
APP: grpc.APP,
ScriptID: grpc.ID,
Cookie: cookie, // 用不到
URL: grpc.ServiceName, // 用于微信通知
LabelIDs: nil,
Domain: grpc.HostName, // 微信通知Domain
FileSplit: false, // 文件切割
SplitNum: 0, // 切割数量
JarPath: grpc.JarPath,
Type: model.PROTOCOL_GRPC, //grpc
}
if grpc.IsDebug == 1 {
ptestParam.IsDebug = true
}
if resp, err = s.DoPtestByJmeter(c, ptestParam, StringToSlice(testNameNick)); err != nil {
log.Error("s.DoPtestByJmeter err :(%v)", err)
return
}
reportId = resp.ReportSuID
return
}
//QueryGrpc query grpc list
func (s *Service) QueryGrpc(c context.Context, sessionID string, qgr *model.QueryGRPCRequest) (res *model.QueryGRPCResponse, err error) {
// 获取服务树节点
var (
treeNodes []string
treeNodesd []string
)
if treeNodesd, err = s.QueryUserRoleNode(c, sessionID); err != nil {
log.Error("QueryUserRoleNode err (%v):", err)
return
}
treeNodes = append(treeNodesd, "")
if ExistsInSlice(qgr.Executor, s.c.Melloi.Executor) {
return s.dao.QueryGRPCByWhiteName(&qgr.GRPC, qgr.PageNum, qgr.PageSize)
}
return s.dao.QueryGRPC(&qgr.GRPC, qgr.PageNum, qgr.PageSize, treeNodes)
}
//QueryGrpcById query grpc by id
func (s *Service) QueryGrpcById(id int) (*model.GRPC, error) {
return s.dao.QueryGRPCByID(id)
}
// UpdateGrpc update grpc
func (s *Service) UpdateGrpc(grpc *model.GRPC) error {
return s.dao.UpdateGRPC(grpc)
}
// DeleteGrpc delete grpc by id
func (s *Service) DeleteGrpc(id int) error {
return s.dao.DeleteGRPC(id)
}
//createJmx create jmx file, jtl file, jmx_log file
func (s *Service) createJmeterFile(grpcReq *model.GRPCAddScriptRequest) (g *model.GRPC, err error) {
var (
buff *template.Template
file *os.File
)
if buff, err = template.ParseFiles(s.c.Jmeter.GRPCTemplatePath); err != nil {
log.Error("open grpc.jmx failed! (%v)", err)
return nil, ecode.MelloiJmeterGenerateErr
}
g = model.GRPCReqToGRPC(grpcReq)
// 脚本执行限制
if g.LoadTime > s.c.Jmeter.TestTimeLimit {
g.LoadTime = s.c.Jmeter.TestTimeLimit
}
if g.Loops <= 0 {
g.Loops = -1
}
if g.IsAsync {
g.AsyncInfo = unescaped(model.AsyncInfo)
}
// 生成jmx文件
if grpcReq.ScriptPath == "" {
log.Error("proto file is not uploaded.")
return nil, ecode.MelloiProtoFileNotUploaded
}
g.JmxPath = path.Join(grpcReq.ScriptPath, grpcReq.TaskName+".jmx")
g.JmxLog = path.Join(grpcReq.ScriptPath, grpcReq.TaskName+".log") // 定义好即可,运行时生成
g.JtlLog = path.Join(grpcReq.ScriptPath, grpcReq.TaskName+".jtl") // 定义好即可,运行时生成
if g.ParamFilePath != "" {
g.ParamEnable = "true"
}
if file, err = os.Create(g.JmxPath); err != nil {
log.Error("create jmx file error :(%v)", err)
return nil, ecode.MelloiJmeterGenerateErr
}
defer file.Close()
// 写入模板数据
buff = buff.Funcs(template.FuncMap{"unescaped": unescaped})
if err = buff.Execute(io.Writer(file), g); err != nil {
log.Error("write jmeter file failed, (%v)", err)
return nil, ecode.MelloiJmeterGenerateErr
}
return
}

View File

@@ -0,0 +1,23 @@
package service
import "go-common/app/admin/ep/melloi/model"
// QueryGRPCSnapByID query grpcsnap by id
func (s *Service) QueryGRPCSnapByID(id int) (*model.GRPCSnap, error) {
return s.dao.QueryGRPCSnapByID(id)
}
// UpdateGRPCSnap update grpc snap
func (s *Service) UpdateGRPCSnap(grpcSnap *model.GRPCSnap) error {
return s.dao.UpdateGRPCSnap(grpcSnap)
}
// CreateGRPCSnap Create GRPC Snap
func (s *Service) CreateGRPCSnap(grpcSnap *model.GRPCSnap) error {
return s.dao.CreateGRPCSnap(grpcSnap)
}
// DeleteGRPCSnap Delete GRPC Snap
func (s *Service) DeleteGRPCSnap(id int) error {
return s.dao.DeleteGRPCSnap(id)
}

View File

@@ -0,0 +1,59 @@
package service
import (
. "github.com/smartystreets/goconvey/convey"
"go-common/app/admin/ep/melloi/model"
"testing"
)
var (
gs = model.GRPCSnap{
ID: 1,
GRPCID: 1,
TaskName: "test",
Department: "test",
Project: "ep",
APP: "melloi",
Active: 1,
HostName: "172.22.33.22",
Port: 9000,
ServiceName: "get",
ProtoClassName: "code",
PkgPath: "book",
RequestType: "reqmsg",
RequestMethod: "reqmethod",
RequestContent: "reqcontent",
ResponseType: "returnmsg",
ScriptPath: "sp",
JarPath: "jp",
JmxPath: "jmxpat",
JmxLog: "hnxkig",
JtlLog: "ht.lgo",
ThreadsSum: 1,
RampUp: 1,
Loops: -1,
LoadTime: 1,
UpdateBy: "hujianping",
}
)
func Test_GrpcSnap(t *testing.T) {
Convey("query grpc snap", t, func() {
_, err := s.QueryGRPCSnapByID(gs.ID)
So(err, ShouldBeNil)
})
Convey("update grpc snap", t, func() {
err := s.UpdateGRPCSnap(&gs)
So(err, ShouldBeNil)
})
Convey("create grpc snap", t, func() {
err := s.CreateGRPCSnap(&gs)
So(err, ShouldBeNil)
})
Convey("delete grpc snap", t, func() {
err := s.DeleteGRPCSnap(gs.ID)
So(err, ShouldBeNil)
})
}

Some files were not shown because too many files have changed in this diff Show More