mirror of
https://gitee.com/rainbond/Rainbond.git
synced 2024-12-05 21:27:47 +08:00
161 lines
5.8 KiB
Go
161 lines
5.8 KiB
Go
// Copyright (C) 2014-2018 Goodrain Co., Ltd.
|
||
// RAINBOND, Application Management Platform
|
||
|
||
// This program is free software: you can redistribute it and/or modify
|
||
// it under the terms of the GNU General Public License as published by
|
||
// the Free Software Foundation, either version 3 of the License, or
|
||
// (at your option) any later version. For any non-GPL usage of Rainbond,
|
||
// one or multiple Commercial Licenses authorized by Goodrain Co., Ltd.
|
||
// must be obtained first.
|
||
|
||
// This program is distributed in the hope that it will be useful,
|
||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
// GNU General Public License for more details.
|
||
|
||
// You should have received a copy of the GNU General Public License
|
||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
|
||
package exector
|
||
|
||
import (
|
||
"context"
|
||
"fmt"
|
||
"runtime/debug"
|
||
|
||
"github.com/ghodss/yaml"
|
||
|
||
"github.com/goodrain/rainbond/builder/parser"
|
||
"github.com/goodrain/rainbond/event"
|
||
"github.com/goodrain/rainbond/mq/api/grpc/pb"
|
||
"github.com/pquerna/ffjson/ffjson"
|
||
"github.com/sirupsen/logrus"
|
||
)
|
||
|
||
//ServiceCheckInput 任务输入数据
|
||
type ServiceCheckInput struct {
|
||
CheckUUID string `json:"uuid"`
|
||
//检测来源类型
|
||
SourceType string `json:"source_type"`
|
||
|
||
// 检测来源定义,
|
||
// 代码: https://github.com/shurcooL/githubql.git master
|
||
// docker-run: docker run --name xxx nginx:latest nginx
|
||
// docker-compose: compose全文
|
||
SourceBody string `json:"source_body"`
|
||
Username string `json:"username"`
|
||
Password string `json:"password"`
|
||
TenantID string
|
||
EventID string `json:"event_id"`
|
||
}
|
||
|
||
//ServiceCheckResult 应用检测结果
|
||
type ServiceCheckResult struct {
|
||
//检测状态 Success Failure
|
||
CheckStatus string `json:"check_status"`
|
||
ErrorInfos parser.ParseErrorList `json:"error_infos"`
|
||
ServiceInfo []parser.ServiceInfo `json:"service_info"`
|
||
}
|
||
|
||
//CreateResult 创建检测结果
|
||
func CreateResult(ErrorInfos parser.ParseErrorList, ServiceInfo []parser.ServiceInfo) (ServiceCheckResult, error) {
|
||
var sr ServiceCheckResult
|
||
if ErrorInfos != nil && ErrorInfos.IsFatalError() {
|
||
sr = ServiceCheckResult{
|
||
CheckStatus: "Failure",
|
||
ErrorInfos: ErrorInfos,
|
||
ServiceInfo: ServiceInfo,
|
||
}
|
||
} else {
|
||
sr = ServiceCheckResult{
|
||
CheckStatus: "Success",
|
||
ErrorInfos: ErrorInfos,
|
||
ServiceInfo: ServiceInfo,
|
||
}
|
||
}
|
||
//save result
|
||
return sr, nil
|
||
}
|
||
|
||
//serviceCheck 应用创建源检测
|
||
func (e *exectorManager) serviceCheck(task *pb.TaskMessage) {
|
||
//step1 判断应用源类型
|
||
//step2 获取应用源介质,镜像Or源码
|
||
//step3 解析判断应用源规范
|
||
//完成
|
||
var input ServiceCheckInput
|
||
if err := ffjson.Unmarshal(task.TaskBody, &input); err != nil {
|
||
logrus.Error("Unmarshal service check input data error.", err.Error())
|
||
return
|
||
}
|
||
logger := event.GetManager().GetLogger(input.EventID)
|
||
defer event.GetManager().ReleaseLogger(logger)
|
||
defer func() {
|
||
if r := recover(); r != nil {
|
||
logrus.Errorf("service check error: %v", r)
|
||
debug.PrintStack()
|
||
logger.Error("The back-end service has deserted, please try again.", map[string]string{"step": "callback", "status": "failure"})
|
||
}
|
||
}()
|
||
logger.Info("Start component deploy source check.", map[string]string{"step": "starting"})
|
||
logrus.Infof("start check service by type: %s ", input.SourceType)
|
||
var pr parser.Parser
|
||
switch input.SourceType {
|
||
case "docker-run":
|
||
pr = parser.CreateDockerRunOrImageParse(input.Username, input.Password, input.SourceBody, e.DockerClient, logger)
|
||
case "docker-compose":
|
||
var yamlbody = input.SourceBody
|
||
if input.SourceBody[0] == '{' {
|
||
yamlbyte, err := yaml.JSONToYAML([]byte(input.SourceBody))
|
||
if err != nil {
|
||
logrus.Errorf("json bytes format is error, %s", input.SourceBody)
|
||
logger.Error("The dockercompose file is not in the correct format", map[string]string{"step": "callback", "status": "failure"})
|
||
return
|
||
}
|
||
yamlbody = string(yamlbyte)
|
||
}
|
||
pr = parser.CreateDockerComposeParse(yamlbody, e.DockerClient, input.Username, input.Password, logger)
|
||
case "sourcecode":
|
||
pr = parser.CreateSourceCodeParse(input.SourceBody, logger)
|
||
case "third-party-service":
|
||
pr = parser.CreateThirdPartyServiceParse(input.SourceBody, logger)
|
||
}
|
||
if pr == nil {
|
||
logger.Error("Creating component source types is not supported", map[string]string{"step": "callback", "status": "failure"})
|
||
return
|
||
}
|
||
errList := pr.Parse()
|
||
if errList != nil {
|
||
for i, err := range errList {
|
||
if err.SolveAdvice == "" && input.SourceType != "sourcecode" {
|
||
errList[i].SolveAdvice = fmt.Sprintf("解析器认为镜像名为:%s,请确认是否正确或镜像是否存在", pr.GetImage())
|
||
}
|
||
if err.SolveAdvice == "" && input.SourceType == "sourcecode" {
|
||
errList[i].SolveAdvice = fmt.Sprintf("源码智能解析失败,请联系客服")
|
||
}
|
||
}
|
||
}
|
||
serviceInfos := pr.GetServiceInfo()
|
||
sr, err := CreateResult(errList, serviceInfos)
|
||
if err != nil {
|
||
logrus.Errorf("create check result error,%s", err.Error())
|
||
logger.Error("创建检测结果失败。", map[string]string{"step": "callback", "status": "failure"})
|
||
}
|
||
k := fmt.Sprintf("/servicecheck/%s", input.CheckUUID)
|
||
v := sr
|
||
vj, err := ffjson.Marshal(&v)
|
||
if err != nil {
|
||
logrus.Errorf("mashal servicecheck value error, %v", err)
|
||
logger.Error("格式化检测结果失败。", map[string]string{"step": "callback", "status": "failure"})
|
||
}
|
||
ctx, cancel := context.WithCancel(context.Background())
|
||
_, err = e.EtcdCli.Put(ctx, k, string(vj))
|
||
cancel()
|
||
if err != nil {
|
||
logrus.Errorf("put servicecheck k %s into etcd error, %v", k, err)
|
||
logger.Error("存储检测结果失败。", map[string]string{"step": "callback", "status": "failure"})
|
||
}
|
||
logrus.Infof("check service by type: %s success", input.SourceType)
|
||
logger.Info("创建检测结果成功。", map[string]string{"step": "last", "status": "success"})
|
||
}
|