go-common/app/admin/ep/melloi/service/scene.go

614 lines
18 KiB
Go
Raw Normal View History

2019-04-22 10:49:16 +00:00
package service
import (
"context"
"encoding/json"
"html/template"
"io"
"os"
"sort"
"strconv"
"strings"
"time"
"go-common/app/admin/ep/melloi/conf"
"go-common/app/admin/ep/melloi/model"
"go-common/library/log"
)
// QueryDraft Query Draft
func (s *Service) QueryDraft(scene *model.Scene) (*model.QueryDraft, error) {
return s.dao.QueryDraft(scene)
}
// UpdateScene Update Scene
func (s *Service) UpdateScene(scene *model.Scene) (fusing int, err error) {
scriptIDList := make([]int, len(scene.Scripts))
for index, script := range scene.Scripts {
scriptIDList[index] = script.ID
}
fusing, err = s.dao.UpdateScene(scene, scriptIDList)
return
}
// AddScene Add Scene
func (s *Service) AddScene(scene *model.Scene) (id int, err error) {
id, err = s.dao.AddScene(scene)
return
}
// QueryAPI Query API
func (s *Service) QueryAPI(scene *model.Scene) (*model.QueryAPIs, error) {
return s.dao.QueryAPI(scene)
}
// AddConfig Add Config
func (s *Service) AddConfig(script *model.Script) error {
return s.dao.AddConfig(script)
}
// QueryTree Query Tree
func (s *Service) QueryTree(script *model.Script) (*model.ShowTree, error) {
return s.dao.QueryTree(script)
}
// QueryScenesByPage Query Scene By Page
func (s *Service) QueryScenesByPage(c context.Context, sessionID string, qsrq *model.QuerySceneRequest) (rsp *model.QuerySceneResponse, err error) {
// 获取服务树节点
var (
treeNodes []string
treeNodesd []string
)
if treeNodesd, err = s.QueryUserRoleNode(c, sessionID); err != nil {
log.Error("QueryUserRoleNode err (%v):", err)
}
treeNodes = append(treeNodesd, "")
if ExistsInSlice(qsrq.Executor, conf.Conf.Melloi.Executor) {
if rsp, err = s.dao.QueryScenesByPageWhiteName(&qsrq.Scene, qsrq.PageNum, qsrq.PageSize); err != nil {
return
}
} else {
if rsp, err = s.dao.QueryScenesByPage(&qsrq.Scene, qsrq.PageNum, qsrq.PageSize, treeNodes); err != nil {
return
}
}
return
}
//AddAndExecuScene AddSceneAuto add scene auto
func (s *Service) AddAndExecuScene(c context.Context, scene model.Scene, cookie string) (resp model.DoPtestResp, err error) {
var (
buff *template.Template
file *os.File
scrThreadGroup model.ScrThreadGroup
fileName string
testNames []string
testNameNicks []string
loadTimes []int
scripts []*model.Script
jmeterLog string
resJtl string
sceneID int
threadGroup string
)
// id 不是0 说明是输入接口创建的场景根据sceneID 查询到接口列表再根据接口列表生成jmx
// 不是前端 quick-start 页的批量选择,走如下逻辑
if scene.ID != 0 && !scene.IsBatch {
script := model.Script{SceneID: scene.ID}
if scripts, err = s.dao.QueryScripts(&script, 1, 200); err != nil {
log.Error("s.dao.QueryScripts err :(%v)", err)
return
}
scene.Scripts = scripts
}
if scene.IsDebug {
for _, script := range scene.Scripts {
script.ThreadsSum = 1
script.Loops = 5
script.TestName = script.TestName + "_perf_debug"
}
scene.SceneName = scene.SceneName + "_perf_debug"
}
// 非 quick-start 页面的批量选择,走如下逻辑,即 quick-start 页面的批量选择,不生成 scene.jmx 文件
sceneSuffix := strconv.FormatInt(time.Now().Unix(), 10)
if !scene.IsBatch {
scrThreadGroup.Scripts = scene.Scripts
if threadGroup, err = s.GetThreadGroup(scrThreadGroup); err != nil {
log.Error("s.dao.GetThreadGroup (%v)", err)
return
}
scene.ThreadGroup = unescaped(threadGroup)
if buff, err = template.ParseFiles(s.c.Jmeter.JmeterSceneTmp); err != nil {
log.Error("file is not exists (%v)", err)
return
}
scene.ScriptPath = "/data/jmeter-log/" + scene.Department + "/" + scene.Project + "/" + scene.APP + "/" + "scene" + "/" + sceneSuffix + "/"
if err = os.MkdirAll(scene.ScriptPath, 0755); err != nil {
log.Error("Create SavePath Err (%v)", err)
return
}
// 创建脚本文件 脚本路径+场景名+后缀.jmx
if file, err = os.Create(scene.ScriptPath + sceneSuffix + ".jmx"); err != nil {
log.Error("os.Create file err :(%v)", err)
return
}
defer file.Close()
buff = buff.Funcs(template.FuncMap{"unescaped": unescaped})
buff.Execute(io.Writer(file), scene)
fileName = file.Name()
jmeterLog = scene.ScriptPath + "jmg" + sceneSuffix
resJtl = scene.ScriptPath + "jtl" + sceneSuffix
}
scene.JmeterLog = jmeterLog
scene.JmeterFilePath = fileName
scene.ResJtl = resJtl
sceneID = scene.ID
// 批量选择脚本执行场景压测,则走如下逻辑,写 script 表
if scene.ID == 0 || scene.IsBatch {
//前端传入的scene 有 scripts , sceneId 没有传,走如下逻辑,写入scene 表
if !scene.IsBatch {
scene.SceneType = 1
if sceneID, err = s.AddScene(&scene); err != nil {
log.Error("s.AddScene err :(%v)", err)
return
}
scene.ID = sceneID
}
for _, script := range scene.Scripts {
script.IsSave = true
script.SceneID = sceneID
script.ID = 0
script.TestType = model.SCENE_SCRIPT_TYPE
//脚本落库
if resp, err = s.AddAndExcuScript(c, script, "", &scene, false, true); err != nil {
log.Error("s.AddAndExcuScript err :(%v)", err)
return
}
script.ID = resp.ScriptID
scripts = append(scripts, script)
}
scene.Scripts = scripts
}
// 有id需要更新数据库
if scene.ID != 0 && !scene.IsDebug {
if _, err = s.UpdateScene(&scene); err != nil {
log.Error("s.UpdateScene error :(%v)", err)
return
}
}
//获取 testNames testNameNicks loadTimes
for _, script := range scene.Scripts {
testNames = append(testNames, script.TestName)
testNameNicks = append(testNameNicks, script.TestName+sceneSuffix)
loadTimes = append(loadTimes, script.LoadTime)
}
sort.Ints(loadTimes)
//执行压测
if scene.IsExecute && len(scene.Scripts) > 0 {
ptestParam := model.DoPtestParam{
TestNames: testNames,
SceneName: scene.SceneName,
UserName: scene.UserName,
LoadTime: loadTimes[len(loadTimes)-1],
FileName: fileName,
Upload: false,
ProjectName: scene.SceneName,
JmeterLog: scene.JmeterLog,
ResJtl: scene.ResJtl,
Department: scene.Department,
Project: scene.Project,
APP: scene.APP,
ScriptID: 0,
DockerSum: 1,
TestNameNick: SliceToString(testNameNicks, ","),
TestNameNicks: testNameNicks,
Scripts: scene.Scripts,
SceneID: sceneID,
Type: model.PROTOCOL_SCENE, // 场景
IsDebug: scene.IsDebug,
Cookie: cookie,
Fusing: scene.Fusing,
}
if resp, err = s.DoPtest(c, ptestParam); err != nil {
log.Error("s.DoPtest err :(%v)", err)
return
}
//临时写法
resp.ScriptID = sceneID
}
return
}
// SaveScene Save Scene
func (s *Service) SaveScene(scene *model.Scene) error {
return s.dao.SaveScene(scene)
}
// SaveOrder Save Order
func (s *Service) SaveOrder(req model.SaveOrderReq, scene *model.Scene) error {
var (
flag = 1
length = len(req.GroupOrderList)
index = length - 1
bak int
)
if scene.SceneType == 1 {
for i := 0; i < length; i++ {
bak = req.GroupOrderList[i].GroupID
req.GroupOrderList[i].GroupID = flag
//防止越界
if i == index {
break
}
if bak != req.GroupOrderList[i+1].GroupID {
flag++
}
}
} else {
for i := 0; i < length; i++ {
bak = req.GroupOrderList[i].RunOrder
req.GroupOrderList[i].RunOrder = flag
//防止越界
if i == index {
break
}
if bak != req.GroupOrderList[i+1].RunOrder {
flag++
}
}
}
return s.dao.SaveOrder(req.GroupOrderList, scene)
}
// QueryRelation Query Relation
func (s *Service) QueryRelation(script *model.Script) (*model.QueryRelation, error) {
var (
groupId int
err error
)
if _, groupId, err = s.dao.QueryGroupId(script); err != nil {
log.Error("s.dao.QueryGroupId err :(%v)", err)
return nil, err
}
return s.dao.QueryRelation(groupId, script)
}
// DeleteAPI Delete API
func (s *Service) DeleteAPI(script *model.Script) error {
return s.dao.DeleteAPI(script)
}
// DoScenePtest Do Scene Ptest
func (s *Service) DoScenePtest(c context.Context, ptestScene model.DoPtestSceneParam, addPtest bool, cookie string) (resp model.DoPtestResp, err error) {
var (
scenes []*model.Scene
scripts []*model.Script
)
scene := model.Scene{ID: ptestScene.SceneID}
if scenes, err = s.dao.QueryScenes(&scene, 1, 1); err != nil {
log.Error("s.dao.QueryScenes err :(%v)", err)
return
}
script := model.Script{SceneID: ptestScene.SceneID}
if scripts, err = s.dao.QueryScripts(&script, 1, 300); err != nil {
log.Error("s.dao.QueryScripts err :(%v)", err)
return
}
scenes[0].Scripts = scripts
if len(scenes) > 0 {
sceneInfo := GetSceneInfo(scenes[0])
ptestParam := model.DoPtestParam{
TestNames: sceneInfo.TestNames,
SceneName: sceneInfo.SceneName,
UserName: ptestScene.UserName,
LoadTime: sceneInfo.MaxLoadTime,
FileName: scenes[0].JmeterFilePath,
Upload: false,
ProjectName: sceneInfo.SceneName,
ResJtl: sceneInfo.ResJtl,
JmeterLog: sceneInfo.JmeterLog,
Department: scenes[0].Department,
Project: scenes[0].Project,
APP: scenes[0].APP,
ScriptID: 0,
DockerSum: 1,
TestNameNick: SliceToString(sceneInfo.TestNameNicks, ","),
TestNameNicks: sceneInfo.TestNameNicks,
Scripts: sceneInfo.Scripts,
SceneID: ptestScene.SceneID,
Type: model.PROTOCOL_SCENE, // 场景
AddPtest: addPtest,
Cookie: cookie,
}
return s.DoPtest(c, ptestParam)
}
return
}
//DoScenePtestBatch dosceneptest batch
func (s *Service) DoScenePtestBatch(c context.Context, ptestScenes model.DoPtestSceneParams, cookie string) (err error) {
for _, SceneID := range ptestScenes.SceneIDs {
ptestScene := model.DoPtestSceneParam{SceneID: SceneID, UserName: ptestScenes.UserName}
go s.DoScenePtest(context.TODO(), ptestScene, false, cookie)
}
return
}
//GetSceneInfo get sceneInfo
func GetSceneInfo(scene *model.Scene) (sceneInfo model.SceneInfo) {
var (
loadTimes []int
testNames []string
testNameNicks []string
scripts []*model.Script
)
if scene == nil {
return
}
sceneSuffix := strconv.FormatInt(time.Now().Unix(), 10)
for _, script := range scene.Scripts {
loadTimes = append(loadTimes, script.LoadTime)
testNames = append(testNames, script.TestName)
testNameNicks = append(testNameNicks, script.TestName+sceneSuffix)
scripts = append(scripts, script)
}
sort.Ints(loadTimes)
sceneInfo = model.SceneInfo{
MaxLoadTime: loadTimes[len(loadTimes)-1],
JmeterLog: scene.JmeterLog + sceneSuffix,
ResJtl: scene.ResJtl + sceneSuffix,
LoadTimes: loadTimes,
TestNames: testNames,
TestNameNicks: testNameNicks,
SceneName: scene.SceneName,
Scripts: scripts,
}
return
}
// QueryExistAPI Query Exist API
func (s *Service) QueryExistAPI(c context.Context, sessionID string, req *model.APIInfoRequest) (res *model.APIInfoList, err error) {
// 获取服务树节点
var (
treeNodes []string
treeNodesd []string
)
if treeNodesd, err = s.QueryUserRoleNode(c, sessionID); err != nil {
log.Error("QueryUserRoleNode err (%v):", err)
}
treeNodes = append(treeNodesd, "")
if res, err = s.dao.QueryExistAPI(&req.Script, req.PageNum, req.PageSize, req.SceneID, treeNodes); err != nil {
return
}
for _, script := range res.ScriptList {
if script.APIHeader != "" {
if err = json.Unmarshal([]byte(script.APIHeader), &script.Headers); err != nil {
log.Error("get script header err : (%v),scriptId:(%d)", err, script.ID)
}
}
if script.ArgumentString != "" {
if err = json.Unmarshal([]byte(script.ArgumentString), &script.ArgumentsMap); err != nil {
log.Error("get script argument err: (%v), scriptId:(%d)", err, script.ID)
}
}
if script.OutputParams != "" {
if err = json.Unmarshal([]byte(script.OutputParams), &script.OutputParamsMap); err != nil {
log.Error("get script OutputParams err: (%v),scriptId:(%d)", err, script.ID)
}
}
}
return
}
// QueryPreview Query Preview
func (s *Service) QueryPreview(req *model.Script) (preRes *model.PreviewInfoList, err error) {
var (
list *model.GroupList
preList *model.PreviewList
preResd model.PreviewInfoList
)
if list, err = s.dao.QueryGroup(req.SceneID); err != nil {
return
}
for i := 0; i < len(list.GroupList); i++ {
// 或者使用var preInfo = &model.PreviewInfo{}
preInfo := new(model.PreviewInfo)
groupId := list.GroupList[i].GroupID
threadsSum := list.GroupList[i].ThreadsSum
loadTime := list.GroupList[i].LoadTime
readyTime := list.GroupList[i].ReadyTime
if preList, err = s.dao.QueryPreview(req.SceneID, groupId); err != nil {
return
}
preInfo.GroupID = groupId
preInfo.ThreadsSum = threadsSum
preInfo.LoadTime = loadTime
preInfo.ReadyTime = readyTime
preInfo.InfoList = preList.PreList
preResd.PreviewInfoList = append(preResd.PreviewInfoList, preInfo)
preRes = &preResd
}
return
}
// QueryParams Query Params
func (s *Service) QueryParams(req *model.Script) (res *model.UsefulParamsList, tempRes *model.UsefulParamsList, err error) {
//var paramList []string
var (
uParam *model.UsefulParams
)
res = &model.UsefulParamsList{}
if tempRes, err = s.dao.QueryUsefulParams(req.SceneID); err != nil {
return
}
if len(tempRes.ParamsList) > 0 {
for _, tempParam := range tempRes.ParamsList {
if strings.Contains(tempParam.OutputParams, ",") {
tempParamList := strings.Split(tempParam.OutputParams, ",")
for _, param := range tempParamList {
uParam = &model.UsefulParams{}
uParam.OutputParams = strings.Split(strings.Split(param, "\":\"")[0], "\"")[1]
res.ParamsList = append(res.ParamsList, uParam)
}
} else {
uParam = &model.UsefulParams{}
uParam.OutputParams = strings.Split(strings.Split(tempParam.OutputParams, "\":\"")[0], "\"")[1]
res.ParamsList = append(res.ParamsList, uParam)
}
}
} else {
// 赋值空数组
res.ParamsList = []*model.UsefulParams{}
}
return
}
// UpdateBindScene Update Bind Scene
func (s *Service) UpdateBindScene(bindScene *model.BindScene) (err error) {
return s.dao.UpdateBindScene(bindScene)
}
// QueryDrawRelation Query Draw Relation
func (s *Service) QueryDrawRelation(scene *model.Scene) (res model.DrawRelationList, tempRes *model.SaveOrderReq, err error) {
var (
//relationList model.DrawRelationList
edges []*model.Edge
edge *model.Edge
tempEdge *model.Edge
//nodes []*model.Node
node *model.Node
)
if tempRes, err = s.dao.QueryDrawRelation(scene); err != nil {
return
}
for k := 0; k < len(tempRes.GroupOrderList); k++ {
node = &model.Node{}
node.ID = tempRes.GroupOrderList[k].ID
node.Name = tempRes.GroupOrderList[k].TestName
res.Nodes = append(res.Nodes, node)
}
for i := 0; i < len(tempRes.GroupOrderList)-1; i++ {
edge = &model.Edge{}
tempEdge = &model.Edge{}
if tempRes.GroupOrderList[i].GroupID == tempRes.GroupOrderList[i+1].GroupID && tempRes.GroupOrderList[i].RunOrder == tempRes.GroupOrderList[i+1].RunOrder {
edge.Source = tempRes.GroupOrderList[i].TestName
edges = append(edges, edge)
if len(edges) > 0 {
//edges[i+1].Source =
tempEdge.Source = edges[i-1].Source
tempEdge.Target = tempRes.GroupOrderList[i+1].TestName
edges = append(edges, tempEdge)
}
} else if tempRes.GroupOrderList[i].GroupID == tempRes.GroupOrderList[i+1].GroupID && tempRes.GroupOrderList[i].RunOrder != tempRes.GroupOrderList[i+1].RunOrder {
edge.Source = tempRes.GroupOrderList[i].TestName
edge.Target = tempRes.GroupOrderList[i+1].TestName
edges = append(edges, edge)
} else if tempRes.GroupOrderList[i].GroupID != tempRes.GroupOrderList[i+1].GroupID {
edge.Source = tempRes.GroupOrderList[i].TestName
edges = append(edges, edge)
}
}
for j := 0; j < len(edges); j++ {
if edges[j].Target != "" {
//relationList.Edges = append(relationList.Edges, edges[j])
res.Edges = append(res.Edges, edges[j])
}
}
return
}
// DeleteDraft Delete Draft
func (s *Service) DeleteDraft(scene *model.Scene) error {
return s.dao.DeleteDraft(scene)
}
// QueryConfig Query Config
func (s *Service) QueryConfig(script *model.Script) (*model.GroupInfo, error) {
return s.dao.QueryConfig(script)
}
// DeleteScene Delete Scene
func (s *Service) DeleteScene(scene *model.Scene) error {
return s.dao.DeleteScene(scene)
}
//CopyScene copy scene
func (s *Service) CopyScene(c context.Context, scene *model.Scene, cookie string) (addScene model.AddScene, err error) {
var (
scripts []*model.Script
scenes []*model.Scene
sceneID int
resp model.DoPtestResp
)
script := model.Script{SceneID: scene.ID}
scened := model.Scene{ID: scene.ID}
//先根据 scene.ID 查询 scenes 和 scripts
if scenes, err = s.dao.QueryScenes(&scened, 1, 10); err != nil {
log.Error("s.dao.QueryScenes err :(%v)", err)
return
}
if scripts, err = s.dao.QueryScripts(&script, 1, 200); err != nil {
log.Error("s.dao.QueryScripts err :(%v)", err)
return
}
if len(scenes) != 0 {
scenes[0].ID = 0
scenes[0].UserName = scene.UserName
scenes[0].SceneName = scene.SceneName
//将新的scene 写入 数据库,并返回 sceneID
if sceneID, err = s.dao.AddScene(scenes[0]); err != nil {
log.Error("s.dao.AddScene err :(%v)", err)
return
}
// 将新的 script 写入 script 表
for _, sctd := range scripts {
sctd.SceneID = sceneID
sctd.ID = 0
if _, _, _, err = s.dao.AddScript(sctd); err != nil {
return
}
}
sce := model.Scene{
APP: scenes[0].APP,
Department: scenes[0].Department,
Project: scenes[0].Project,
ID: sceneID,
IsDebug: false,
IsExecute: false,
UserName: scene.UserName,
SceneName: scene.SceneName,
}
if resp, err = s.AddAndExecuScene(c, sce, cookie); err != nil {
log.Error("s.AddAndExecuScene err :(%v), (%v)", err, resp)
return
}
addScene.SceneID = sceneID
addScene.UserName = scene.UserName
}
return
}
// QueryFusing Query Fusing
func (s *Service) QueryFusing(script *model.Script) (res *model.FusingInfoList, err error) {
res, err = s.dao.QueryFusing(script)
for i := 0; i < len(res.FusingList)-1; i++ {
if res.FusingList[i] != res.FusingList[i+1] {
res.SetNull = true
return
}
}
return
}