2018-03-14 14:12:26 +08:00
|
|
|
|
// Copyright (C) 2014-2018 Goodrain Co., Ltd.
|
2018-01-10 13:35:05 +08:00
|
|
|
|
// RAINBOND, Application Management Platform
|
2018-03-14 14:33:31 +08:00
|
|
|
|
|
2018-01-10 13:35:05 +08:00
|
|
|
|
// 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.
|
2018-03-14 14:33:31 +08:00
|
|
|
|
|
2018-01-10 13:35:05 +08:00
|
|
|
|
// 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.
|
2018-03-14 14:33:31 +08:00
|
|
|
|
|
2018-01-10 13:35:05 +08:00
|
|
|
|
// 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 (
|
2018-01-23 12:13:22 +08:00
|
|
|
|
"context"
|
2018-02-27 22:01:37 +08:00
|
|
|
|
"fmt"
|
2018-03-30 15:37:36 +08:00
|
|
|
|
"runtime/debug"
|
2018-02-27 22:01:37 +08:00
|
|
|
|
|
|
|
|
|
"github.com/ghodss/yaml"
|
2019-04-11 20:14:41 +08:00
|
|
|
|
|
2018-04-24 16:44:59 +08:00
|
|
|
|
"github.com/goodrain/rainbond/builder/parser"
|
|
|
|
|
"github.com/goodrain/rainbond/event"
|
2018-10-18 18:39:21 +08:00
|
|
|
|
"github.com/goodrain/rainbond/mq/api/grpc/pb"
|
2019-02-12 15:40:42 +08:00
|
|
|
|
"github.com/pquerna/ffjson/ffjson"
|
2020-11-25 16:39:38 +08:00
|
|
|
|
"github.com/sirupsen/logrus"
|
2018-01-10 13:35:05 +08:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
//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"`
|
2018-08-10 18:22:23 +08:00
|
|
|
|
Username string `json:"username"`
|
|
|
|
|
Password string `json:"password"`
|
2018-01-10 13:35:05 +08:00
|
|
|
|
TenantID string
|
|
|
|
|
EventID string `json:"event_id"`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//ServiceCheckResult 应用检测结果
|
|
|
|
|
type ServiceCheckResult struct {
|
|
|
|
|
//检测状态 Success Failure
|
2018-02-27 22:01:37 +08:00
|
|
|
|
CheckStatus string `json:"check_status"`
|
2018-02-01 18:07:19 +08:00
|
|
|
|
ErrorInfos parser.ParseErrorList `json:"error_infos"`
|
2018-02-27 22:01:37 +08:00
|
|
|
|
ServiceInfo []parser.ServiceInfo `json:"service_info"`
|
2018-01-10 13:35:05 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//CreateResult 创建检测结果
|
2018-02-01 18:07:19 +08:00
|
|
|
|
func CreateResult(ErrorInfos parser.ParseErrorList, ServiceInfo []parser.ServiceInfo) (ServiceCheckResult, error) {
|
2018-01-10 13:35:05 +08:00
|
|
|
|
var sr ServiceCheckResult
|
|
|
|
|
if ErrorInfos != nil && ErrorInfos.IsFatalError() {
|
|
|
|
|
sr = ServiceCheckResult{
|
|
|
|
|
CheckStatus: "Failure",
|
|
|
|
|
ErrorInfos: ErrorInfos,
|
|
|
|
|
ServiceInfo: ServiceInfo,
|
|
|
|
|
}
|
2018-01-17 22:06:58 +08:00
|
|
|
|
} else {
|
|
|
|
|
sr = ServiceCheckResult{
|
|
|
|
|
CheckStatus: "Success",
|
|
|
|
|
ErrorInfos: ErrorInfos,
|
|
|
|
|
ServiceInfo: ServiceInfo,
|
|
|
|
|
}
|
2018-01-10 13:35:05 +08:00
|
|
|
|
}
|
|
|
|
|
//save result
|
2018-02-01 18:07:19 +08:00
|
|
|
|
return sr, nil
|
2018-01-10 13:35:05 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//serviceCheck 应用创建源检测
|
2018-10-18 18:39:21 +08:00
|
|
|
|
func (e *exectorManager) serviceCheck(task *pb.TaskMessage) {
|
2018-01-10 13:35:05 +08:00
|
|
|
|
//step1 判断应用源类型
|
|
|
|
|
//step2 获取应用源介质,镜像Or源码
|
|
|
|
|
//step3 解析判断应用源规范
|
|
|
|
|
//完成
|
|
|
|
|
var input ServiceCheckInput
|
2018-10-18 18:39:21 +08:00
|
|
|
|
if err := ffjson.Unmarshal(task.TaskBody, &input); err != nil {
|
2018-01-10 13:35:05 +08:00
|
|
|
|
logrus.Error("Unmarshal service check input data error.", err.Error())
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
logger := event.GetManager().GetLogger(input.EventID)
|
2018-03-30 15:37:36 +08:00
|
|
|
|
defer event.GetManager().ReleaseLogger(logger)
|
|
|
|
|
defer func() {
|
|
|
|
|
if r := recover(); r != nil {
|
2018-07-02 18:38:27 +08:00
|
|
|
|
logrus.Errorf("service check error: %v", r)
|
2018-03-30 15:37:36 +08:00
|
|
|
|
debug.PrintStack()
|
2020-03-16 17:10:13 +08:00
|
|
|
|
logger.Error("The back-end service has deserted, please try again.", map[string]string{"step": "callback", "status": "failure"})
|
2018-03-30 15:37:36 +08:00
|
|
|
|
}
|
|
|
|
|
}()
|
2020-03-16 17:10:13 +08:00
|
|
|
|
logger.Info("Start component deploy source check.", map[string]string{"step": "starting"})
|
2018-01-17 22:06:58 +08:00
|
|
|
|
logrus.Infof("start check service by type: %s ", input.SourceType)
|
|
|
|
|
var pr parser.Parser
|
2018-01-10 13:35:05 +08:00
|
|
|
|
switch input.SourceType {
|
|
|
|
|
case "docker-run":
|
2018-08-10 18:23:16 +08:00
|
|
|
|
pr = parser.CreateDockerRunOrImageParse(input.Username, input.Password, input.SourceBody, e.DockerClient, logger)
|
2018-01-10 13:35:05 +08:00
|
|
|
|
case "docker-compose":
|
2019-04-11 20:14:41 +08:00
|
|
|
|
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)
|
2018-02-24 12:04:09 +08:00
|
|
|
|
}
|
2019-04-11 20:14:41 +08:00
|
|
|
|
pr = parser.CreateDockerComposeParse(yamlbody, e.DockerClient, input.Username, input.Password, logger)
|
2018-01-10 13:35:05 +08:00
|
|
|
|
case "sourcecode":
|
2018-01-17 22:06:58 +08:00
|
|
|
|
pr = parser.CreateSourceCodeParse(input.SourceBody, logger)
|
2019-02-24 02:14:27 +08:00
|
|
|
|
case "third-party-service":
|
|
|
|
|
pr = parser.CreateThirdPartyServiceParse(input.SourceBody, logger)
|
2018-01-17 22:06:58 +08:00
|
|
|
|
}
|
|
|
|
|
if pr == nil {
|
2020-03-16 17:10:13 +08:00
|
|
|
|
logger.Error("Creating component source types is not supported", map[string]string{"step": "callback", "status": "failure"})
|
2018-01-17 22:06:58 +08:00
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
errList := pr.Parse()
|
2021-07-28 21:31:58 +08:00
|
|
|
|
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 = "源码智能解析失败"
|
2018-01-17 22:06:58 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
serviceInfos := pr.GetServiceInfo()
|
2018-02-01 18:07:19 +08:00
|
|
|
|
sr, err := CreateResult(errList, serviceInfos)
|
|
|
|
|
if err != nil {
|
2018-01-17 22:06:58 +08:00
|
|
|
|
logrus.Errorf("create check result error,%s", err.Error())
|
|
|
|
|
logger.Error("创建检测结果失败。", map[string]string{"step": "callback", "status": "failure"})
|
2018-01-10 13:35:05 +08:00
|
|
|
|
}
|
2018-01-23 12:13:22 +08:00
|
|
|
|
k := fmt.Sprintf("/servicecheck/%s", input.CheckUUID)
|
2018-02-01 18:07:19 +08:00
|
|
|
|
v := sr
|
2018-01-23 12:13:22 +08:00
|
|
|
|
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"})
|
|
|
|
|
}
|
2018-02-27 22:01:37 +08:00
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
|
|
|
_, err = e.EtcdCli.Put(ctx, k, string(vj))
|
|
|
|
|
cancel()
|
2018-01-23 12:13:22 +08:00
|
|
|
|
if err != nil {
|
|
|
|
|
logrus.Errorf("put servicecheck k %s into etcd error, %v", k, err)
|
|
|
|
|
logger.Error("存储检测结果失败。", map[string]string{"step": "callback", "status": "failure"})
|
|
|
|
|
}
|
2018-03-15 19:46:39 +08:00
|
|
|
|
logrus.Infof("check service by type: %s success", input.SourceType)
|
2018-03-05 16:55:17 +08:00
|
|
|
|
logger.Info("创建检测结果成功。", map[string]string{"step": "last", "status": "success"})
|
2018-01-10 13:35:05 +08:00
|
|
|
|
}
|