optimize component batch operation api

This commit is contained in:
GLYASAI 2021-05-25 17:30:10 +08:00
parent eb669d50a1
commit 0ecaeb324b
15 changed files with 879 additions and 512 deletions

View File

@ -22,90 +22,88 @@ import (
"fmt"
"net/http"
"github.com/sirupsen/logrus"
"github.com/goodrain/rainbond/api/handler"
"github.com/goodrain/rainbond/api/middleware"
"github.com/goodrain/rainbond/api/util"
"github.com/goodrain/rainbond/api/model"
dbmodel "github.com/goodrain/rainbond/db/model"
rutil "github.com/goodrain/rainbond/util"
httputil "github.com/goodrain/rainbond/util/http"
"github.com/sirupsen/logrus"
)
//BatchOperation batch operation for tenant
//support operation is : start,build,stop,update
func BatchOperation(w http.ResponseWriter, r *http.Request) {
var build model.BeatchOperationRequestStruct
var build model.BatchOperationReq
ok := httputil.ValidatorRequestStructAndErrorResponse(r, w, &build.Body, nil)
if !ok {
logrus.Errorf("start batch operation validate request body failure")
return
}
tenantName := r.Context().Value(middleware.ContextKey("tenant_name")).(string)
tenantID := r.Context().Value(middleware.ContextKey("tenant_id")).(string)
if logrus.IsLevelEnabled(logrus.DebugLevel) {
defer rutil.Elapsed("BatchOperation-" + build.Body.Operation)()
}
// create event for each operation
eventRe := createBatchEvents(&build, tenantID, build.Operator)
tenant := r.Context().Value(middleware.ContextKey("tenant")).(*dbmodel.Tenants)
var re handler.BatchOperationResult
var res model.BatchOpResult
var err error
// TODO: merge the code below
switch build.Body.Operation {
case "build":
for i := range build.Body.BuildInfos {
build.Body.BuildInfos[i].TenantName = tenantName
var batchOpReqs []model.ComponentOpReq
for _, build := range build.Body.Builds {
build := build
build.TenantName = tenant.Name
batchOpReqs = append(batchOpReqs, build)
}
re = handler.GetBatchOperationHandler().Build(build.Body.BuildInfos)
if len(batchOpReqs) > 1024 {
batchOpReqs = batchOpReqs[0:1024]
}
res, err = handler.GetBatchOperationHandler().Build(r.Context(), tenant, build.Operator, batchOpReqs)
case "start":
re = handler.GetBatchOperationHandler().Start(build.Body.StartInfos)
var batchOpReqs []model.ComponentOpReq
for _, start := range build.Body.Starts {
start := start
batchOpReqs = append(batchOpReqs, start)
}
if len(batchOpReqs) > 1024 {
batchOpReqs = batchOpReqs[0:1024]
}
res, err = handler.GetBatchOperationHandler().Start(r.Context(), tenant, build.Operator, batchOpReqs)
case "stop":
re = handler.GetBatchOperationHandler().Stop(build.Body.StopInfos)
var batchOpReqs []model.ComponentOpReq
for _, stop := range build.Body.Stops {
stop := stop
batchOpReqs = append(batchOpReqs, stop)
}
if len(batchOpReqs) > 1024 {
batchOpReqs = batchOpReqs[0:1024]
}
res, err = handler.GetBatchOperationHandler().Stop(r.Context(), tenant, build.Operator, batchOpReqs)
case "upgrade":
re = handler.GetBatchOperationHandler().Upgrade(build.Body.UpgradeInfos)
var batchOpReqs []model.ComponentOpReq
for _, upgrade := range build.Body.Upgrades {
upgrade := upgrade
batchOpReqs = append(batchOpReqs, upgrade)
}
if len(batchOpReqs) > 1024 {
batchOpReqs = batchOpReqs[0:1024]
}
res, err = handler.GetBatchOperationHandler().Upgrade(r.Context(), tenant, build.Operator, batchOpReqs)
default:
httputil.ReturnError(r, w, 400, fmt.Sprintf("operation %s do not support batch", build.Body.Operation))
return
}
if err != nil {
httputil.ReturnBcodeError(r, w, err)
return
}
// append every create event result to re and then return
re.BatchResult = append(re.BatchResult, eventRe.BatchResult...)
httputil.ReturnSuccess(r, w, re)
}
func createBatchEvents(build *model.BeatchOperationRequestStruct, tenantID, operator string) (re handler.BatchOperationResult) {
for i := range build.Body.BuildInfos {
event, err := util.CreateEvent(dbmodel.TargetTypeService, "build-service", build.Body.BuildInfos[i].ServiceID, tenantID, "", operator, dbmodel.ASYNEVENTTYPE)
if err != nil {
re.BatchResult = append(re.BatchResult, handler.OperationResult{ErrMsg: "create event failure", ServiceID: build.Body.BuildInfos[i].ServiceID})
continue
}
build.Body.BuildInfos[i].EventID = event.EventID
}
for i := range build.Body.StartInfos {
event, err := util.CreateEvent(dbmodel.TargetTypeService, "start-service", build.Body.StartInfos[i].ServiceID, tenantID, "", operator, dbmodel.ASYNEVENTTYPE)
if err != nil {
re.BatchResult = append(re.BatchResult, handler.OperationResult{ErrMsg: "create event failure", ServiceID: build.Body.StartInfos[i].ServiceID})
continue
}
build.Body.StartInfos[i].EventID = event.EventID
}
for i := range build.Body.StopInfos {
event, err := util.CreateEvent(dbmodel.TargetTypeService, "stop-service", build.Body.StopInfos[i].ServiceID, tenantID, "", operator, dbmodel.ASYNEVENTTYPE)
if err != nil {
re.BatchResult = append(re.BatchResult, handler.OperationResult{ErrMsg: "create event failure", ServiceID: build.Body.StopInfos[i].ServiceID})
continue
}
build.Body.StopInfos[i].EventID = event.EventID
}
for i := range build.Body.UpgradeInfos {
event, err := util.CreateEvent(dbmodel.TargetTypeService, "upgrade-service", build.Body.UpgradeInfos[i].ServiceID, tenantID, "", operator, dbmodel.ASYNEVENTTYPE)
if err != nil {
re.BatchResult = append(re.BatchResult, handler.OperationResult{ErrMsg: "create event failure", ServiceID: build.Body.UpgradeInfos[i].ServiceID})
continue
}
build.Body.UpgradeInfos[i].EventID = event.EventID
}
return
httputil.ReturnSuccess(r, w, map[string]interface{}{
"batch_result": res,
})
}

View File

@ -1,96 +0,0 @@
// RAINBOND, Application Management Platform
// Copyright (C) 2014-2019 Goodrain Co., Ltd.
// 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 controller
import (
"encoding/json"
"fmt"
"testing"
"github.com/goodrain/rainbond/api/handler"
"github.com/goodrain/rainbond/api/model"
httputil "github.com/goodrain/rainbond/util/http"
)
func TestBatchOperation(t *testing.T) {
var build = model.BeatchOperationRequestStruct{}
buildInfo := []model.BuildInfoRequestStruct{
model.BuildInfoRequestStruct{
BuildENVs: map[string]string{
"MAVEN_SETTING": "java",
},
Action: "upgrade",
Kind: model.FromCodeBuildKing,
CodeInfo: model.BuildCodeInfo{
RepoURL: "https://github.com/goodrain/java-maven-demo.git",
Branch: "master",
Lang: "Java-maven",
ServerType: "git",
},
ServiceID: "qwertyuiopasdfghjklzxcvbn",
},
model.BuildInfoRequestStruct{
Action: "upgrade",
Kind: model.FromImageBuildKing,
ImageInfo: model.BuildImageInfo{
ImageURL: "hub.goodrain.com/xxx/xxx:latest",
Cmd: "start web",
},
ServiceID: "qwertyuiopasdfghjklzxcvbn",
},
}
startInfo := []model.StartOrStopInfoRequestStruct{
model.StartOrStopInfoRequestStruct{
ServiceID: "qwertyuiopasdfghjkzxcvb",
},
}
upgrade := []model.UpgradeInfoRequestStruct{
model.UpgradeInfoRequestStruct{
ServiceID: "qwertyuiopasdfghjkzxcvb",
UpgradeVersion: "2345678",
},
}
build.Body.BuildInfos = buildInfo
build.Body.StartInfos = startInfo
build.Body.StopInfos = startInfo
build.Body.UpgradeInfos = upgrade
build.Body.Operation = "stop"
out, _ := json.MarshalIndent(build.Body, "", "\t")
fmt.Print(string(out))
result := handler.BatchOperationResult{
BatchResult: []handler.OperationResult{
handler.OperationResult{
ServiceID: "qwertyuiopasdfghjkzxcvb",
Operation: "build",
EventID: "wertyuiodfghjcvbnm",
Status: "success",
ErrMsg: "",
DeployVersion: "1234567890",
},
},
}
rebody := httputil.ResponseBody{
Bean: result,
}
outre, _ := json.MarshalIndent(rebody, "", "\t")
fmt.Print(string(outre))
}

View File

@ -315,7 +315,7 @@ func (t *TenantStruct) HorizontalService(w http.ResponseWriter, r *http.Request)
// "$ref": "#/responses/commandResponse"
// description: 统一返回格式
func (t *TenantStruct) BuildService(w http.ResponseWriter, r *http.Request) {
var build api_model.BuildInfoRequestStruct
var build api_model.ComponentBuildReq
ok := httputil.ValidatorRequestStructAndErrorResponse(r, w, &build, nil)
if !ok {
return
@ -336,12 +336,12 @@ func (t *TenantStruct) BuildService(w http.ResponseWriter, r *http.Request) {
return
}
re := handler.GetOperationHandler().Build(build)
if re.ErrMsg != "" {
httputil.ReturnError(r, w, 500, "build server error: "+re.ErrMsg)
res, err := handler.GetOperationHandler().Build(&build)
if err != nil {
httputil.ReturnBcodeError(r, w, err)
return
}
httputil.ReturnSuccess(r, w, re)
httputil.ReturnSuccess(r, w, res)
}
//BuildList BuildList
@ -532,7 +532,7 @@ func (t *TenantStruct) DeployService(w http.ResponseWriter, r *http.Request) {
// "$ref": "#/responses/commandResponse"
// description: 统一返回格式
func (t *TenantStruct) UpgradeService(w http.ResponseWriter, r *http.Request) {
var upgradeRequest api_model.UpgradeInfoRequestStruct
var upgradeRequest api_model.ComponentUpgradeReq
ok := httputil.ValidatorRequestStructAndErrorResponse(r, w, &upgradeRequest, nil)
if !ok {
logrus.Errorf("start operation validate request body failure")
@ -552,8 +552,12 @@ func (t *TenantStruct) UpgradeService(w http.ResponseWriter, r *http.Request) {
return
}
re := handler.GetOperationHandler().Upgrade(upgradeRequest)
httputil.ReturnSuccess(r, w, re)
res, err := handler.GetOperationHandler().Upgrade(&upgradeRequest)
if err != nil {
httputil.ReturnBcodeError(r, w, err)
return
}
httputil.ReturnSuccess(r, w, res)
}
//CheckCode CheckCode

View File

@ -19,16 +19,21 @@
package handler
import (
"container/list"
"context"
"fmt"
"strings"
"time"
"container/list"
"github.com/goodrain/rainbond/api/model"
apiutil "github.com/goodrain/rainbond/api/util"
"github.com/goodrain/rainbond/db"
dbmodel "github.com/goodrain/rainbond/db/model"
gclient "github.com/goodrain/rainbond/mq/client"
"github.com/goodrain/rainbond/util"
"github.com/goodrain/rainbond/util/retryutil"
"github.com/jinzhu/gorm"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
@ -52,9 +57,6 @@ func CreateBatchOperationHandler(mqCli gclient.MQClient, operationHandler *Opera
}
func setStartupSequenceConfig(configs map[string]string, depsids []string) map[string]string {
if configs == nil {
configs = make(map[string]string, 1)
}
configs["boot_seq_dep_service_ids"] = strings.Join(depsids, ",")
return configs
}
@ -86,127 +88,213 @@ func (b *BatchOperationHandler) serviceStartupSequence(serviceIDs []string) map[
}
//Build build
func (b *BatchOperationHandler) Build(buildInfos []model.BuildInfoRequestStruct) (re BatchOperationResult) {
var serviceIDs []string
for _, info := range buildInfos {
serviceIDs = append(serviceIDs, info.ServiceID)
func (b *BatchOperationHandler) Build(ctx context.Context, tenant *dbmodel.Tenants, operator string, batchOpReqs model.BatchOpRequesters) (model.BatchOpResult, error) {
if logrus.IsLevelEnabled(logrus.DebugLevel) {
defer util.Elapsed("[BatchOperationHandler] build components")()
}
startupSeqConfigs := b.serviceStartupSequence(serviceIDs)
var retrys []model.BuildInfoRequestStruct
for _, buildInfo := range buildInfos {
if err := checkResourceEnough(buildInfo.ServiceID); err != nil {
re.BatchResult = append(re.BatchResult, OperationResult{
ServiceID: buildInfo.ServiceID,
Operation: "build",
EventID: buildInfo.EventID,
Status: "failure",
ErrMsg: err.Error(),
DeployVersion: "",
})
continue
}
buildInfo.Configs = setStartupSequenceConfig(buildInfo.Configs, startupSeqConfigs[buildInfo.ServiceID])
buildre := b.operationHandler.Build(buildInfo)
if buildre.Status != "success" {
retrys = append(retrys, buildInfo)
// setup start sequence config
componentIDs := batchOpReqs.ComponentIDs()
startupSeqConfigs := b.serviceStartupSequence(componentIDs)
// check allocatable memory
allocm, err := NewAllocMemory(ctx, tenant, batchOpReqs)
if err != nil {
return nil, errors.WithMessage(err, "new alloc memory")
}
batchOpResult := allocm.BatchOpResult()
validBuilds := allocm.BatchOpRequests()
batchOpReqs, batchOpResult2 := b.checkEvents(batchOpReqs)
batchOpResult = append(batchOpResult, batchOpResult2...)
// create events
if err := b.createEvents(tenant.UUID, operator, batchOpReqs); err != nil {
return nil, err
}
for _, build := range validBuilds {
build.UpdateConfig("boot_seq_dep_service_ids", strings.Join(startupSeqConfigs[build.GetComponentID()], ","))
err := retryutil.Retry(1*time.Microsecond, 1, func() (bool, error) {
if err := b.operationHandler.build(build); err != nil {
return false, err
}
return true, nil
})
item := build.BatchOpFailureItem()
if err != nil {
item.ErrMsg = err.Error()
} else {
re.BatchResult = append(re.BatchResult, buildre)
item.Success()
}
batchOpResult = append(batchOpResult, item)
}
for _, retry := range retrys {
re.BatchResult = append(re.BatchResult, b.operationHandler.Build(retry))
}
return
return batchOpResult, nil
}
//Start batch start
func (b *BatchOperationHandler) Start(startInfos []model.StartOrStopInfoRequestStruct) (re BatchOperationResult) {
var serviceIDs []string
for _, info := range startInfos {
serviceIDs = append(serviceIDs, info.ServiceID)
func (b *BatchOperationHandler) Start(ctx context.Context, tenant *dbmodel.Tenants, operator string, batchOpReqs model.BatchOpRequesters) (model.BatchOpResult, error) {
if logrus.IsLevelEnabled(logrus.DebugLevel) {
defer util.Elapsed("[BatchOperationHandler] start components")()
}
startupSeqConfigs := b.serviceStartupSequence(serviceIDs)
var retrys []model.StartOrStopInfoRequestStruct
for _, startInfo := range startInfos {
if err := checkResourceEnough(startInfo.ServiceID); err != nil {
re.BatchResult = append(re.BatchResult, OperationResult{
ServiceID: startInfo.ServiceID,
Operation: "start",
EventID: startInfo.EventID,
Status: "failure",
ErrMsg: err.Error(),
DeployVersion: "",
})
continue
}
// setup start sequence config
componentIDs := batchOpReqs.ComponentIDs()
startupSeqConfigs := b.serviceStartupSequence(componentIDs)
// chekc allocatable memory
allocm, err := NewAllocMemory(ctx, tenant, batchOpReqs)
if err != nil {
return nil, errors.WithMessage(err, "new alloc memory")
}
batchOpResult := allocm.BatchOpResult()
validRequestes := allocm.BatchOpRequests()
batchOpReqs, batchOpResult2 := b.checkEvents(batchOpReqs)
batchOpResult = append(batchOpResult, batchOpResult2...)
// create events
if err := b.createEvents(tenant.UUID, operator, batchOpReqs); err != nil {
return nil, err
}
for _, req := range validRequestes {
// startup sequence
startInfo.Configs = setStartupSequenceConfig(startInfo.Configs, startupSeqConfigs[startInfo.ServiceID])
startre := b.operationHandler.Start(startInfo)
if startre.Status != "success" {
retrys = append(retrys, startInfo)
req.UpdateConfig("boot_seq_dep_service_ids", strings.Join(startupSeqConfigs[req.GetComponentID()], ","))
err := retryutil.Retry(1*time.Microsecond, 1, func() (bool, error) {
if err := b.operationHandler.Start(req); err != nil {
return false, err
}
return true, nil
})
item := req.BatchOpFailureItem()
if err != nil {
item.ErrMsg = err.Error()
} else {
re.BatchResult = append(re.BatchResult, startre)
item.Success()
}
batchOpResult = append(batchOpResult, item)
}
for _, retry := range retrys {
re.BatchResult = append(re.BatchResult, b.operationHandler.Start(retry))
}
return
return batchOpResult, nil
}
//Stop batch stop
func (b *BatchOperationHandler) Stop(stopInfos []model.StartOrStopInfoRequestStruct) (re BatchOperationResult) {
var retrys []model.StartOrStopInfoRequestStruct
for _, stopInfo := range stopInfos {
stopre := b.operationHandler.Stop(stopInfo)
if stopre.Status != "success" {
retrys = append(retrys, stopInfo)
func (b *BatchOperationHandler) Stop(ctx context.Context, tenant *dbmodel.Tenants, operator string, batchOpReqs model.BatchOpRequesters) (model.BatchOpResult, error) {
if logrus.IsLevelEnabled(logrus.DebugLevel) {
defer util.Elapsed("[BatchOperationHandler] stop components")()
}
batchOpReqs, batchOpResult := b.checkEvents(batchOpReqs)
// create events
if err := b.createEvents(tenant.UUID, operator, batchOpReqs); err != nil {
return nil, err
}
for _, req := range batchOpReqs {
err := retryutil.Retry(1*time.Microsecond, 1, func() (bool, error) {
if err := b.operationHandler.Stop(req); err != nil {
return false, err
}
return true, nil
})
item := req.BatchOpFailureItem()
if err != nil {
item.ErrMsg = err.Error()
} else {
re.BatchResult = append(re.BatchResult, stopre)
item.Success()
}
batchOpResult = append(batchOpResult, item)
}
for _, retry := range retrys {
re.BatchResult = append(re.BatchResult, b.operationHandler.Stop(retry))
}
return
return batchOpResult, nil
}
//Upgrade batch upgrade
func (b *BatchOperationHandler) Upgrade(upgradeInfos []model.UpgradeInfoRequestStruct) (re BatchOperationResult) {
var serviceIDs []string
for _, info := range upgradeInfos {
serviceIDs = append(serviceIDs, info.ServiceID)
func (b *BatchOperationHandler) Upgrade(ctx context.Context, tenant *dbmodel.Tenants, operator string, batchOpReqs model.BatchOpRequesters) (model.BatchOpResult, error) {
if logrus.IsLevelEnabled(logrus.DebugLevel) {
defer util.Elapsed("[BatchOperationHandler] upgrade components")()
}
startupSeqConfigs := b.serviceStartupSequence(serviceIDs)
var retrys []model.UpgradeInfoRequestStruct
for _, upgradeInfo := range upgradeInfos {
if err := checkResourceEnough(upgradeInfo.ServiceID); err != nil {
re.BatchResult = append(re.BatchResult, OperationResult{
ServiceID: upgradeInfo.ServiceID,
Operation: "upgrade",
EventID: upgradeInfo.EventID,
Status: "failure",
ErrMsg: err.Error(),
DeployVersion: "",
})
// setup start sequence config
componentIDs := batchOpReqs.ComponentIDs()
startupSeqConfigs := b.serviceStartupSequence(componentIDs)
// chekc allocatable memory
allocm, err := NewAllocMemory(ctx, tenant, batchOpReqs)
if err != nil {
return nil, errors.WithMessage(err, "new alloc memory")
}
batchOpResult := allocm.BatchOpResult()
validUpgrades := allocm.BatchOpRequests()
validUpgrades, batchOpResult2 := b.checkEvents(validUpgrades)
batchOpResult = append(batchOpResult, batchOpResult2...)
// create events
if err := b.createEvents(tenant.UUID, operator, batchOpReqs); err != nil {
return nil, err
}
for _, upgrade := range validUpgrades {
upgrade.UpdateConfig("boot_seq_dep_service_ids", strings.Join(startupSeqConfigs[upgrade.GetComponentID()], ","))
err := retryutil.Retry(1*time.Microsecond, 1, func() (bool, error) {
if err := b.operationHandler.upgrade(upgrade); err != nil {
return false, err
}
return true, nil
})
item := upgrade.BatchOpFailureItem()
if err != nil {
item.ErrMsg = err.Error()
} else {
item.Success()
}
batchOpResult = append(batchOpResult, item)
}
return batchOpResult, nil
}
func (b *BatchOperationHandler) checkEvents(batchOpReqs model.BatchOpRequesters) (model.BatchOpRequesters, model.BatchOpResult) {
var validReqs model.BatchOpRequesters
var batchOpResult model.BatchOpResult
for _, req := range batchOpReqs {
req := req
if apiutil.CanDoEvent("", dbmodel.SYNEVENTTYPE, "service", req.GetComponentID()) {
validReqs = append(validReqs, req)
continue
}
upgradeInfo.Configs = setStartupSequenceConfig(upgradeInfo.Configs, startupSeqConfigs[upgradeInfo.ServiceID])
stopre := b.operationHandler.Upgrade(upgradeInfo)
if stopre.Status != "success" {
retrys = append(retrys, upgradeInfo)
} else {
re.BatchResult = append(re.BatchResult, stopre)
item := req.BatchOpFailureItem()
item.ErrMsg = "The last event has not been completed"
batchOpResult = append(batchOpResult, item)
}
return validReqs, batchOpResult
}
func (b *BatchOperationHandler) createEvents(tenantID, operator string, batchOpReqs model.BatchOpRequesters) error {
if logrus.IsLevelEnabled(logrus.DebugLevel) {
defer util.Elapsed("[BatchOperationHandler] create events")()
}
var events []*dbmodel.ServiceEvent
for _, req := range batchOpReqs {
event := &dbmodel.ServiceEvent{
EventID: req.GetEventID(),
TenantID: tenantID,
Target: dbmodel.TargetTypeService,
TargetID: req.GetComponentID(),
UserName: operator,
StartTime: time.Now().Format(time.RFC3339),
SynType: dbmodel.ASYNEVENTTYPE,
OptType: req.OpType(),
}
events = append(events, event)
}
for _, retry := range retrys {
re.BatchResult = append(re.BatchResult, b.operationHandler.Upgrade(retry))
}
return
return db.GetManager().DB().Transaction(func(tx *gorm.DB) error {
return db.GetManager().ServiceEventDaoTransactions(tx).CreateEventsInBatch(events)
})
}
// ServiceDependency documents a set of services and their dependencies.
@ -373,3 +461,108 @@ func alreadyInLinkedList(l *list.List, depsid string) bool {
return false
}
// AllocMemory represents a allocatable memory.
type AllocMemory struct {
tenant *dbmodel.Tenants
tenantResource *model.TenantResource
allcm int64
components map[string]*dbmodel.TenantServices
batchOpResult model.BatchOpResult
batchOpRequests model.BatchOpRequesters
}
// NewAllocMemory creates a new AllocMemory.
func NewAllocMemory(ctx context.Context, tenant *dbmodel.Tenants, batchOpReqs model.BatchOpRequesters) (*AllocMemory, error) {
if logrus.IsLevelEnabled(logrus.DebugLevel) {
defer util.Elapsed("[NewAllocMemory] check allocatable memory")()
}
tenantResource, err := GetServiceManager().GetTenantRes(tenant.UUID)
if err != nil {
return nil, err
}
allcm, err := ClusterAllocMemory(ctx)
if err != nil {
return nil, err
}
am := &AllocMemory{
tenant: tenant,
tenantResource: tenantResource,
allcm: allcm,
}
components, err := am.listComponents(batchOpReqs.ComponentIDs())
if err != nil {
return nil, err
}
am.components = components
// check alloc memory for every components.
var reqs model.BatchOpRequesters
var batchOpResult model.BatchOpResult
for _, req := range batchOpReqs {
req := req
if err := am.check(req.GetComponentID()); err != nil {
item := req.BatchOpFailureItem()
item.ErrMsg = err.Error()
batchOpResult = append(batchOpResult, item)
continue
}
reqs = append(reqs, req)
}
am.batchOpResult = batchOpResult
am.batchOpRequests = reqs
return am, nil
}
// BatchOpResult returns the batchOpResult.
func (a *AllocMemory) BatchOpResult() model.BatchOpResult {
return a.batchOpResult
}
// BatchOpRequests returns the batchOpRequests.
func (a *AllocMemory) BatchOpRequests() model.BatchOpRequesters {
return a.batchOpRequests
}
func (a *AllocMemory) listComponents(componentIDs []string) (map[string]*dbmodel.TenantServices, error) {
components, err := db.GetManager().TenantServiceDao().GetServiceByIDs(componentIDs)
if err != nil {
return nil, err
}
// make a map for compoenents
res := make(map[string]*dbmodel.TenantServices)
for _, cpt := range components {
cpt := cpt
res[cpt.ServiceID] = cpt
}
return res, nil
}
func (a *AllocMemory) check(componentID string) error {
component, ok := a.components[componentID]
if !ok {
return errors.New("component not found")
}
requestMemory := component.ContainerMemory * component.Replicas
if a.tenant.LimitMemory != 0 {
allocm := a.tenant.LimitMemory - a.tenantResource.UsedMEM
if requestMemory > allocm {
logrus.Errorf("no limit tenant memory. request memory is %d, but got %d allocatable memory", requestMemory, allocm)
return errors.New("tenant_lack_of_memory")
}
}
if int64(requestMemory) > a.allcm {
logrus.Errorf("the cluster memory limit is %d, but component(%s) need %d", a.allcm, componentID, requestMemory)
return errors.New("cluster_lack_of_memory")
}
return nil
}

View File

@ -28,6 +28,7 @@ import (
gclient "github.com/goodrain/rainbond/mq/client"
"github.com/goodrain/rainbond/util"
dmodel "github.com/goodrain/rainbond/worker/discover/model"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
@ -55,214 +56,164 @@ func CreateOperationHandler(mqCli gclient.MQClient) *OperationHandler {
//Build service build,will create new version
//if deploy version not define, will create by time
func (o *OperationHandler) Build(buildInfo model.BuildInfoRequestStruct) (re OperationResult) {
service, err := db.GetManager().TenantServiceDao().GetServiceByID(buildInfo.ServiceID)
func (o *OperationHandler) Build(batchOpReq model.ComponentOpReq) (*model.ComponentOpResult, error) {
res := batchOpReq.BatchOpFailureItem()
if err := o.build(batchOpReq); err != nil {
res.ErrMsg = err.Error()
} else {
res.Success()
}
return res, nil
}
func (o *OperationHandler) build(batchOpReq model.ComponentOpReq) error {
service, err := db.GetManager().TenantServiceDao().GetServiceByID(batchOpReq.GetComponentID())
if err != nil {
re.ErrMsg = fmt.Sprintf("find service %s failure", buildInfo.ServiceID)
return
return err
}
if dbmodel.ServiceKind(service.Kind) == dbmodel.ServiceKindThirdParty {
re.ErrMsg = fmt.Sprintf("service %s is thirdpart service", buildInfo.ServiceID)
return
return nil
}
buildInfo.DeployVersion = util.CreateVersionByTime()
re.DeployVersion = buildInfo.DeployVersion
buildReq := batchOpReq.(*model.ComponentBuildReq)
buildReq.DeployVersion = util.CreateVersionByTime()
version := dbmodel.VersionInfo{
EventID: buildInfo.EventID,
ServiceID: buildInfo.ServiceID,
RepoURL: buildInfo.CodeInfo.RepoURL,
Kind: buildInfo.Kind,
BuildVersion: buildInfo.DeployVersion,
Cmd: buildInfo.ImageInfo.Cmd,
Author: buildInfo.Operator,
EventID: buildReq.GetEventID(),
ServiceID: buildReq.ServiceID,
RepoURL: buildReq.CodeInfo.RepoURL,
Kind: buildReq.Kind,
BuildVersion: buildReq.DeployVersion,
Cmd: buildReq.ImageInfo.Cmd,
Author: buildReq.Operator,
FinishTime: time.Now(),
PlanVersion: buildInfo.PlanVersion,
PlanVersion: buildReq.PlanVersion,
}
if buildInfo.CodeInfo.Cmd != "" {
version.Cmd = buildInfo.CodeInfo.Cmd
if buildReq.CodeInfo.Cmd != "" {
version.Cmd = buildReq.CodeInfo.Cmd
}
serviceID := buildInfo.ServiceID
err = db.GetManager().VersionInfoDao().AddModel(&version)
if err != nil {
logrus.Errorf("error add version %v ,details %s", version, err.Error())
re.ErrMsg = fmt.Sprintf("create service %s new version %s failure", serviceID, buildInfo.DeployVersion)
return
if err = db.GetManager().VersionInfoDao().AddModel(&version); err != nil {
return err
}
re.EventID = buildInfo.EventID
re.Operation = "build"
re.ServiceID = service.ServiceID
re.Status = "failure"
switch buildInfo.Kind {
switch buildReq.Kind {
case model.FromImageBuildKing:
if err := o.buildFromImage(buildInfo, service); err != nil {
logrus.Errorf("build service %s failure %s", serviceID, err.Error())
re.ErrMsg = fmt.Sprintf("build service %s failure", serviceID)
return
if err := o.buildFromImage(buildReq, service); err != nil {
return err
}
case model.FromCodeBuildKing:
if err := o.buildFromSourceCode(buildInfo, service); err != nil {
logrus.Errorf("build service %s failure %s", serviceID, err.Error())
re.ErrMsg = fmt.Sprintf("build service %s failure", serviceID)
return
if err := o.buildFromSourceCode(buildReq, service); err != nil {
return err
}
case model.FromMarketImageBuildKing:
if err := o.buildFromImage(buildInfo, service); err != nil {
logrus.Errorf("build service %s failure %s", serviceID, err.Error())
re.ErrMsg = fmt.Sprintf("build service %s failure", serviceID)
return
if err := o.buildFromImage(buildReq, service); err != nil {
return err
}
case model.FromMarketSlugBuildKing:
if err := o.buildFromMarketSlug(buildInfo, service); err != nil {
logrus.Errorf("build service %s failure %s", serviceID, err.Error())
re.ErrMsg = fmt.Sprintf("build service %s failure", serviceID)
return
if err := o.buildFromMarketSlug(buildReq, service); err != nil {
return err
}
default:
re.ErrMsg = fmt.Sprintf("build service %s failure,kind %s is unsupport", serviceID, buildInfo.Kind)
return
return errors.New("unsupported build kind: " + buildReq.Kind)
}
re.Status = "success"
return
return nil
}
//Stop service stop
func (o *OperationHandler) Stop(stopInfo model.StartOrStopInfoRequestStruct) (re OperationResult) {
re.EventID = stopInfo.EventID
re.Operation = "stop"
re.ServiceID = stopInfo.ServiceID
re.Status = "failure"
service, err := db.GetManager().TenantServiceDao().GetServiceByID(stopInfo.ServiceID)
func (o *OperationHandler) Stop(batchOpReq model.ComponentOpReq) error {
service, err := db.GetManager().TenantServiceDao().GetServiceByID(batchOpReq.GetComponentID())
if err != nil {
logrus.Errorf("get service by id error, %v", err)
re.ErrMsg = fmt.Sprintf("get service %s failure", stopInfo.ServiceID)
return
return err
}
if dbmodel.ServiceKind(service.Kind) == dbmodel.ServiceKindThirdParty {
re.ErrMsg = fmt.Sprintf("service %s is thirdpart service", stopInfo.ServiceID)
return
}
TaskBody := dmodel.StopTaskBody{
TenantID: service.TenantID,
ServiceID: service.ServiceID,
DeployVersion: service.DeployVersion,
EventID: re.EventID,
Configs: stopInfo.Configs,
return nil
}
body := batchOpReq.TaskBody(service)
err = o.mqCli.SendBuilderTopic(gclient.TaskStruct{
TaskType: "stop",
TaskBody: TaskBody,
TaskBody: body,
Topic: gclient.WorkerTopic,
})
if err != nil {
logrus.Errorf("equque mq error, %v", err)
re.ErrMsg = fmt.Sprintf("start service %s failure", stopInfo.ServiceID)
return
return err
}
re.Status = "success"
return
return nil
}
//Start service start
func (o *OperationHandler) Start(startInfo model.StartOrStopInfoRequestStruct) (re OperationResult) {
re.Operation = "start"
re.ServiceID = startInfo.ServiceID
re.Status = "failure"
service, err := db.GetManager().TenantServiceDao().GetServiceByID(startInfo.ServiceID)
func (o *OperationHandler) Start(batchOpReq model.ComponentOpReq) error {
service, err := db.GetManager().TenantServiceDao().GetServiceByID(batchOpReq.GetComponentID())
if err != nil {
logrus.Errorf("get service by id error, %v", err)
re.ErrMsg = fmt.Sprintf("get service %s failure", startInfo.ServiceID)
return
return err
}
if dbmodel.ServiceKind(service.Kind) == dbmodel.ServiceKindThirdParty {
re.ErrMsg = fmt.Sprintf("service %s is thirdpart service", startInfo.ServiceID)
return
}
re.EventID = startInfo.EventID
TaskBody := dmodel.StartTaskBody{
TenantID: service.TenantID,
ServiceID: service.ServiceID,
DeployVersion: service.DeployVersion,
EventID: startInfo.EventID,
Configs: startInfo.Configs,
DepServiceIDInBootSeq: startInfo.DepServiceIDInBootSeq,
return nil
}
body := batchOpReq.TaskBody(service)
err = o.mqCli.SendBuilderTopic(gclient.TaskStruct{
TaskType: "start",
TaskBody: TaskBody,
TaskBody: body,
Topic: gclient.WorkerTopic,
})
if err != nil {
logrus.Errorf("equque mq error, %v", err)
re.ErrMsg = fmt.Sprintf("start service %s failure", startInfo.ServiceID)
return
return err
}
re.Status = "success"
return
return nil
}
//Upgrade service upgrade
func (o *OperationHandler) Upgrade(ru model.UpgradeInfoRequestStruct) (re OperationResult) {
re.Operation = "upgrade"
re.ServiceID = ru.ServiceID
re.EventID = ru.EventID
re.Status = "failure"
services, err := db.GetManager().TenantServiceDao().GetServiceByID(ru.ServiceID)
if err != nil {
logrus.Errorf("get service by id %s error %s", ru.ServiceID, err.Error())
re.ErrMsg = fmt.Sprintf("get service %s failure", ru.ServiceID)
return
func (o *OperationHandler) Upgrade(batchOpReq model.ComponentOpReq) (*model.ComponentOpResult, error) {
res := batchOpReq.BatchOpFailureItem()
if err := o.upgrade(batchOpReq); err != nil {
res.ErrMsg = err.Error()
} else {
res.Success()
}
if dbmodel.ServiceKind(services.Kind) == dbmodel.ServiceKindThirdParty {
re.ErrMsg = fmt.Sprintf("service %s is thirdpart service", ru.ServiceID)
return
return res, nil
}
func (o *OperationHandler) upgrade(batchOpReq model.ComponentOpReq) error {
component, err := db.GetManager().TenantServiceDao().GetServiceByID(batchOpReq.GetComponentID())
if err != nil {
return err
}
if dbmodel.ServiceKind(component.Kind) == dbmodel.ServiceKindThirdParty {
return err
}
// By default, the same version is updated
if ru.UpgradeVersion == "" {
ru.UpgradeVersion = services.DeployVersion
}
version, err := db.GetManager().VersionInfoDao().GetVersionByDeployVersion(ru.UpgradeVersion, ru.ServiceID)
batchOpReq.SetVersion(component.DeployVersion)
version, err := db.GetManager().VersionInfoDao().GetVersionByDeployVersion(batchOpReq.GetVersion(), batchOpReq.GetComponentID())
if err != nil {
logrus.Errorf("get service version by id %s version %s error, %s", ru.ServiceID, ru.UpgradeVersion, err.Error())
re.ErrMsg = fmt.Sprintf("get service %s version %s failure", ru.ServiceID, ru.UpgradeVersion)
return
return err
}
oldDeployVersion := services.DeployVersion
oldDeployVersion := component.DeployVersion
var rollback = func() {
services.DeployVersion = oldDeployVersion
_ = db.GetManager().TenantServiceDao().UpdateModel(services)
component.DeployVersion = oldDeployVersion
_ = db.GetManager().TenantServiceDao().UpdateModel(component)
}
if version.FinalStatus != "success" {
logrus.Warnf("deploy version %s is not build success,can not change deploy version in this upgrade event", ru.UpgradeVersion)
logrus.Warnf("deploy version %s is not build success,can not change deploy version in this upgrade event", batchOpReq.GetVersion())
} else {
services.DeployVersion = ru.UpgradeVersion
err = db.GetManager().TenantServiceDao().UpdateModel(services)
component.DeployVersion = batchOpReq.GetVersion()
err = db.GetManager().TenantServiceDao().UpdateModel(component)
if err != nil {
logrus.Errorf("update service deploy version error. %v", err)
re.ErrMsg = fmt.Sprintf("update service %s deploy version failure", ru.ServiceID)
return
return err
}
}
body := batchOpReq.TaskBody(component)
err = o.mqCli.SendBuilderTopic(gclient.TaskStruct{
TaskBody: dmodel.RollingUpgradeTaskBody{
TenantID: services.TenantID,
ServiceID: services.ServiceID,
NewDeployVersion: ru.UpgradeVersion,
EventID: re.EventID,
Configs: ru.Configs,
},
TaskBody: body,
TaskType: "rolling_upgrade",
Topic: gclient.WorkerTopic,
})
if err != nil {
rollback()
logrus.Errorf("equque upgrade message error, %v", err)
re.ErrMsg = fmt.Sprintf("send service %s upgrade message failure", ru.ServiceID)
return
return err
}
re.Status = "success"
return
return nil
}
//RollBack service rollback
@ -316,16 +267,10 @@ func (o *OperationHandler) RollBack(rollback model.RollbackInfoRequestStruct) (r
return
}
//Restart service restart
//TODO
func (o *OperationHandler) Restart(restartInfo model.StartOrStopInfoRequestStruct) (re OperationResult) {
return
}
func (o *OperationHandler) buildFromMarketSlug(r model.BuildInfoRequestStruct, service *dbmodel.TenantServices) error {
func (o *OperationHandler) buildFromMarketSlug(r *model.ComponentBuildReq, service *dbmodel.TenantServices) error {
body := make(map[string]interface{})
body["deploy_version"] = r.DeployVersion
body["event_id"] = r.EventID
body["event_id"] = r.GetEventID()
body["action"] = r.Action
body["tenant_name"] = r.TenantName
body["tenant_id"] = service.TenantID
@ -347,7 +292,7 @@ func (o *OperationHandler) sendBuildTopic(serviceID, taskType string, body map[s
})
}
func (o *OperationHandler) buildFromImage(r model.BuildInfoRequestStruct, service *dbmodel.TenantServices) error {
func (o *OperationHandler) buildFromImage(r *model.ComponentBuildReq, service *dbmodel.TenantServices) error {
if r.ImageInfo.ImageURL == "" || r.DeployVersion == "" {
return fmt.Errorf("build from image failure, args error")
}
@ -356,7 +301,7 @@ func (o *OperationHandler) buildFromImage(r model.BuildInfoRequestStruct, servic
body["service_id"] = service.ServiceID
body["deploy_version"] = r.DeployVersion
body["namespace"] = service.Namespace
body["event_id"] = r.EventID
body["event_id"] = r.GetEventID()
body["tenant_name"] = r.TenantName
body["service_alias"] = service.ServiceAlias
body["action"] = r.Action
@ -369,7 +314,7 @@ func (o *OperationHandler) buildFromImage(r model.BuildInfoRequestStruct, servic
return o.sendBuildTopic(service.ServiceID, "build_from_image", body)
}
func (o *OperationHandler) buildFromSourceCode(r model.BuildInfoRequestStruct, service *dbmodel.TenantServices) error {
func (o *OperationHandler) buildFromSourceCode(r *model.ComponentBuildReq, service *dbmodel.TenantServices) error {
if r.CodeInfo.RepoURL == "" || r.CodeInfo.Branch == "" || r.DeployVersion == "" {
return fmt.Errorf("build from code failure, args error")
}
@ -381,7 +326,7 @@ func (o *OperationHandler) buildFromSourceCode(r model.BuildInfoRequestStruct, s
body["lang"] = r.CodeInfo.Lang
body["runtime"] = r.CodeInfo.Runtime
body["deploy_version"] = r.DeployVersion
body["event_id"] = r.EventID
body["event_id"] = r.GetEventID()
body["envs"] = r.BuildENVs
body["tenant_name"] = r.TenantName
body["branch"] = r.CodeInfo.Branch

View File

@ -22,17 +22,25 @@ func CheckTenantResource(ctx context.Context, tenant *dbmodel.Tenants, needMemor
return errors.New("tenant_lack_of_memory")
}
}
clusterInfo, err := GetTenantManager().GetAllocatableResources(ctx)
allcm, err := ClusterAllocMemory(ctx)
if err != nil {
logrus.Errorf("get cluster resources failure for check tenant resource: %v", err.Error())
return err
}
if clusterInfo != nil {
clusterAvailMemory := clusterInfo.AllMemory - clusterInfo.RequestMemory
logrus.Debugf("cluster allocatedMemory: %v, availmemory %d tenantsUsedMemory; %v", clusterInfo.RequestMemory, clusterAvailMemory, clusterInfo.RequestMemory)
if int64(needMemory) > clusterAvailMemory {
logrus.Errorf("cluster available memory is %d, To apply for %d, not enough", clusterAvailMemory, needMemory)
return errors.New("cluster_lack_of_memory")
}
if int64(needMemory) > allcm {
logrus.Errorf("cluster available memory is %d, To apply for %d, not enough", allcm, needMemory)
return errors.New("cluster_lack_of_memory")
}
return nil
}
// ClusterAllocMemory returns the allocatable memory of the cluster.
func ClusterAllocMemory(ctx context.Context) (int64, error) {
clusterInfo, err := GetTenantManager().GetAllocatableResources(ctx)
if err != nil {
return 0, err
}
return clusterInfo.AllMemory - clusterInfo.RequestMemory, nil
}

173
api/model/batch_service.go Normal file
View File

@ -0,0 +1,173 @@
// Copyright (C) 2014-2021 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 model
import (
dbmodel "github.com/goodrain/rainbond/db/model"
"github.com/goodrain/rainbond/util"
wmodel "github.com/goodrain/rainbond/worker/discover/model"
)
var _ ComponentOpReq = &ComponentStartReq{}
var _ ComponentOpReq = &ComponentStopReq{}
var _ ComponentOpReq = &ComponentBuildReq{}
var _ ComponentOpReq = &ComponentUpgradeReq{}
// BatchOpRequesters -
type BatchOpRequesters []ComponentOpReq
// ComponentIDs returns a list of components ids.
func (b BatchOpRequesters) ComponentIDs() []string {
var componentIDs []string
for _, item := range b {
componentIDs = append(componentIDs, item.GetComponentID())
}
return componentIDs
}
// ComponentOpReq -
type ComponentOpReq interface {
GetComponentID() string
GetEventID() string
TaskBody(component *dbmodel.TenantServices) interface{}
BatchOpFailureItem() *ComponentOpResult
UpdateConfig(key, value string)
OpType() string
SetVersion(version string)
GetVersion() string
}
// BatchOpResult -
type BatchOpResult []*ComponentOpResult
// BatchOpResultItemStatus is the status of ComponentOpResult.
type BatchOpResultItemStatus string
// BatchOpResultItemStatus -
var (
BatchOpResultItemStatusFailure BatchOpResultItemStatus = "failure"
BatchOpResultItemStatusSuccess BatchOpResultItemStatus = "success"
)
// ComponentOpResult -
type ComponentOpResult struct {
ServiceID string `json:"service_id"`
Operation string `json:"operation"`
EventID string `json:"event_id"`
Status BatchOpResultItemStatus `json:"status"`
ErrMsg string `json:"err_message"`
DeployVersion string `json:"deploy_version"`
}
// Success sets the status to success.
func (b *ComponentOpResult) Success() {
b.Status = BatchOpResultItemStatusSuccess
}
// ComponentOpGeneralReq -
type ComponentOpGeneralReq struct {
EventID string `json:"event_id"`
ServiceID string `json:"service_id"`
Configs map[string]string `json:"configs"`
// When determining the startup sequence of services, you need to know the services they depend on
DepServiceIDInBootSeq []string `json:"dep_service_ids_in_boot_seq"`
}
// UpdateConfig -
func (b *ComponentOpGeneralReq) UpdateConfig(key, value string) {
if b.Configs == nil {
b.Configs = make(map[string]string)
}
b.Configs[key] = value
}
// ComponentStartReq -
type ComponentStartReq struct {
ComponentOpGeneralReq
}
// GetEventID -
func (s *ComponentStartReq) GetEventID() string {
if s.EventID == "" {
s.EventID = util.NewUUID()
}
return s.EventID
}
// GetVersion -
func (s *ComponentStartReq) GetVersion() string {
return ""
}
// SetVersion -
func (s *ComponentStartReq) SetVersion(string) {
// no need
}
// GetComponentID -
func (s *ComponentStartReq) GetComponentID() string {
return s.ServiceID
}
// TaskBody -
func (s *ComponentStartReq) TaskBody(cpt *dbmodel.TenantServices) interface{} {
return &wmodel.StartTaskBody{
TenantID: cpt.TenantID,
ServiceID: cpt.ServiceID,
DeployVersion: cpt.DeployVersion,
EventID: s.GetEventID(),
Configs: s.Configs,
DepServiceIDInBootSeq: s.DepServiceIDInBootSeq,
}
}
// OpType -
func (s *ComponentStartReq) OpType() string {
return "start-service"
}
// BatchOpFailureItem -
func (s *ComponentStartReq) BatchOpFailureItem() *ComponentOpResult {
return &ComponentOpResult{
ServiceID: s.ServiceID,
EventID: s.GetEventID(),
Operation: "start",
Status: BatchOpResultItemStatusFailure,
}
}
// ComponentStopReq -
type ComponentStopReq struct {
ComponentStartReq
}
// OpType -
func (s *ComponentStopReq) OpType() string {
return "stop-service"
}
// BatchOpFailureItem -
func (s *ComponentStopReq) BatchOpFailureItem() *ComponentOpResult {
return &ComponentOpResult{
ServiceID: s.ServiceID,
EventID: s.GetEventID(),
Operation: "stop",
Status: BatchOpResultItemStatusFailure,
}
}

View File

@ -22,7 +22,10 @@ import (
"net/url"
"time"
"github.com/goodrain/rainbond/util"
dbmodel "github.com/goodrain/rainbond/db/model"
dmodel "github.com/goodrain/rainbond/worker/discover/model"
)
//ServiceGetCommon path参数
@ -1421,16 +1424,16 @@ type ExportAppStruct struct {
}
}
//BeatchOperationRequestStruct beatch operation request body
type BeatchOperationRequestStruct struct {
// BatchOperationReq beatch operation request body
type BatchOperationReq struct {
Operator string `json:"operator"`
TenantName string `json:"tenant_name"`
Body struct {
Operation string `json:"operation" validate:"operation|required|in:start,stop,build,upgrade"`
BuildInfos []BuildInfoRequestStruct `json:"build_infos,omitempty"`
StartInfos []StartOrStopInfoRequestStruct `json:"start_infos,omitempty"`
StopInfos []StartOrStopInfoRequestStruct `json:"stop_infos,omitempty"`
UpgradeInfos []UpgradeInfoRequestStruct `json:"upgrade_infos,omitempty"`
Operation string `json:"operation" validate:"operation|required|in:start,stop,build,upgrade"`
Builds []*ComponentBuildReq `json:"build_infos,omitempty"`
Starts []*ComponentStartReq `json:"start_infos,omitempty"`
Stops []*ComponentStopReq `json:"stop_infos,omitempty"`
Upgrades []*ComponentUpgradeReq `json:"upgrade_infos,omitempty"`
}
}
@ -1491,8 +1494,9 @@ var FromMarketImageBuildKing = "build_from_market_image"
//FromMarketSlugBuildKing build from market slug
var FromMarketSlugBuildKing = "build_from_market_slug"
//BuildInfoRequestStruct -
type BuildInfoRequestStruct struct {
// ComponentBuildReq -
type ComponentBuildReq struct {
ComponentOpGeneralReq
// 变量
// in: body
// required: false
@ -1505,8 +1509,6 @@ type BuildInfoRequestStruct struct {
// in: body
// required: false
Action string `json:"action" validate:"action"`
//Event trace ID
EventID string `json:"event_id"`
// Plan Version
PlanVersion string `json:"plan_version"`
// Deployed version number, The version is generated by the API
@ -1522,9 +1524,51 @@ type BuildInfoRequestStruct struct {
//用于云市代码包创建
SlugInfo BuildSlugInfo `json:"slug_info,omitempty"`
//tenantName
TenantName string `json:"-"`
ServiceID string `json:"service_id"`
Configs map[string]string `json:"configs"`
TenantName string `json:"-"`
}
// GetEventID -
func (b *ComponentBuildReq) GetEventID() string {
if b.EventID == "" {
b.EventID = util.NewUUID()
}
return b.EventID
}
// BatchOpFailureItem -
func (b *ComponentBuildReq) BatchOpFailureItem() *ComponentOpResult {
return &ComponentOpResult{
ServiceID: b.ServiceID,
EventID: b.EventID,
Operation: "build",
Status: BatchOpResultItemStatusFailure,
}
}
// GetVersion -
func (b *ComponentBuildReq) GetVersion() string {
return b.DeployVersion
}
// SetVersion -
func (b *ComponentBuildReq) SetVersion(string) {
// no need
return
}
// OpType -
func (b *ComponentBuildReq) OpType() string {
return "build-service"
}
// GetComponentID -
func (b *ComponentBuildReq) GetComponentID() string {
return b.ServiceID
}
// TaskBody returns a task body.
func (b *ComponentBuildReq) TaskBody(cpt *dbmodel.TenantServices) interface{} {
return nil
}
// UpdateBuildVersionReq -
@ -1532,15 +1576,63 @@ type UpdateBuildVersionReq struct {
PlanVersion string `json:"plan_version" validate:"required"`
}
//UpgradeInfoRequestStruct -
type UpgradeInfoRequestStruct struct {
//ComponentUpgradeReq -
type ComponentUpgradeReq struct {
ComponentOpGeneralReq
//UpgradeVersion The target version of the upgrade
//If empty, the same version is upgraded
UpgradeVersion string `json:"upgrade_version"`
//Event trace ID
EventID string `json:"event_id"`
ServiceID string `json:"service_id"`
Configs map[string]string `json:"configs"`
}
// GetEventID -
func (u *ComponentUpgradeReq) GetEventID() string {
if u.EventID == "" {
u.EventID = util.NewUUID()
}
return u.EventID
}
// BatchOpFailureItem -
func (u *ComponentUpgradeReq) BatchOpFailureItem() *ComponentOpResult {
return &ComponentOpResult{
ServiceID: u.ServiceID,
EventID: u.GetEventID(),
Operation: "upgrade",
Status: BatchOpResultItemStatusFailure,
}
}
// GetVersion -
func (u *ComponentUpgradeReq) GetVersion() string {
return u.UpgradeVersion
}
// SetVersion -
func (u *ComponentUpgradeReq) SetVersion(version string) {
if u.UpgradeVersion == "" {
u.UpgradeVersion = version
}
}
// GetComponentID -
func (u *ComponentUpgradeReq) GetComponentID() string {
return u.ServiceID
}
// TaskBody returns the task body.
func (u *ComponentUpgradeReq) TaskBody(cpt *dbmodel.TenantServices) interface{} {
return &dmodel.RollingUpgradeTaskBody{
TenantID: cpt.TenantID,
ServiceID: cpt.ServiceID,
NewDeployVersion: u.UpgradeVersion,
EventID: u.GetEventID(),
Configs: u.Configs,
}
}
// OpType -
func (u *ComponentUpgradeReq) OpType() string {
return "upgrade-service"
}
//RollbackInfoRequestStruct -
@ -1553,16 +1645,6 @@ type RollbackInfoRequestStruct struct {
Configs map[string]string `json:"configs"`
}
//StartOrStopInfoRequestStruct -
type StartOrStopInfoRequestStruct struct {
//Event trace ID
EventID string `json:"event_id"`
ServiceID string `json:"service_id"`
Configs map[string]string `json:"configs"`
// When determining the startup sequence of services, you need to know the services they depend on
DepServiceIDInBootSeq []string `json:"dep_service_ids_in_boot_seq"`
}
//BuildMQBodyFrom -
func BuildMQBodyFrom(app *ExportAppStruct) *MQBody {
return &MQBody{

View File

@ -377,6 +377,7 @@ type CodeCheckResultDao interface {
//EventDao EventDao
type EventDao interface {
Dao
CreateEventsInBatch(events []*model.ServiceEvent) error
GetEventByEventID(eventID string) (*model.ServiceEvent, error)
GetEventByEventIDs(eventIDs []string) ([]*model.ServiceEvent, error)
GetEventByServiceID(serviceID string) ([]*model.ServiceEvent, error)

View File

@ -22,8 +22,10 @@ import (
"strings"
"time"
gormbulkups "github.com/atcdot/gorm-bulk-upsert"
"github.com/goodrain/rainbond/db/model"
"github.com/jinzhu/gorm"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
@ -60,6 +62,19 @@ type EventDaoImpl struct {
DB *gorm.DB
}
// CreateEventsInBatch creates events in batch.
func (c *EventDaoImpl) CreateEventsInBatch(events []*model.ServiceEvent) error {
var objects []interface{}
for _, event := range events {
event := event
objects = append(objects, *event)
}
if err := gormbulkups.BulkUpsert(c.DB, objects, 200); err != nil {
return errors.Wrap(err, "create events in batch")
}
return nil
}
//GetEventByEventID get event log message
func (c *EventDaoImpl) GetEventByEventID(eventID string) (*model.ServiceEvent, error) {
var result model.ServiceEvent

17
go.mod
View File

@ -9,6 +9,7 @@ require (
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d // indirect
github.com/alecthomas/units v0.0.0-20201120081800-1786d5ef83d4 // indirect
github.com/aliyun/aliyun-oss-go-sdk v2.1.5+incompatible
github.com/atcdot/gorm-bulk-upsert v1.0.0
github.com/aws/aws-sdk-go v1.36.15
github.com/barnettZQG/gotty v1.0.1-0.20200904091006-a0a1f7d747dc
github.com/beorn7/perks v1.0.1
@ -46,6 +47,8 @@ require (
github.com/golang/protobuf v1.4.3
github.com/goodrain/rainbond-oam v0.0.0-20210206075623-511d0796af43
github.com/goodrain/rainbond-operator v1.3.1-0.20210401055914-f8fe4bf89a21
github.com/google/go-cmp v0.5.4 // indirect
github.com/google/uuid v1.2.0 // indirect
github.com/gopherjs/gopherjs v0.0.0-20191106031601-ce3c9ade29de // indirect
github.com/gorilla/websocket v1.4.2
github.com/gosuri/uitable v0.0.4
@ -64,6 +67,7 @@ require (
github.com/mitchellh/go-wordwrap v1.0.0
github.com/mitchellh/mapstructure v1.3.3
github.com/ncabatoff/process-exporter v0.7.1
github.com/onsi/gomega v1.10.5 // indirect
github.com/opencontainers/go-digest v1.0.0
github.com/opencontainers/runc v1.0.0-rc91.0.20200707015106-819fcc687efb // indirect
github.com/pborman/uuid v1.2.1
@ -84,6 +88,7 @@ require (
github.com/smartystreets/assertions v1.0.1 // indirect
github.com/smartystreets/goconvey v1.6.4
github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.7.0 // indirect
github.com/testcontainers/testcontainers-go v0.8.0
github.com/thejerf/suture v3.0.3+incompatible
github.com/tidwall/gjson v1.6.1
@ -93,21 +98,31 @@ require (
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
github.com/xeipuuv/gojsonschema v1.1.0 // indirect
github.com/yudai/umutex v0.0.0-20150817080136-18216d265c6b
go.uber.org/multierr v1.6.0 // indirect
go.uber.org/zap v1.16.0 // indirect
golang.org/x/crypto v0.0.0-20201208171446-5f87f3452ae9
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5 // indirect
golang.org/x/mod v0.4.1 // indirect
golang.org/x/net v0.0.0-20210119194325-5f4716e94777
golang.org/x/oauth2 v0.0.0-20210201163806-010130855d6c // indirect
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a // indirect
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c
golang.org/x/text v0.3.5 // indirect
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324
golang.org/x/tools v0.1.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20210218151259-fe80b386bf06 // indirect
google.golang.org/grpc v1.35.0
gopkg.in/alecthomas/kingpin.v2 v2.2.6
gopkg.in/src-d/go-git.v4 v4.13.1
gopkg.in/yaml.v2 v2.4.0
istio.io/pkg v0.0.0-20210519012641-d57c32f9ee9c // indirect
k8s.io/api v0.20.1
k8s.io/apiextensions-apiserver v0.20.1
k8s.io/apimachinery v0.20.1
k8s.io/apiserver v0.20.0
k8s.io/client-go v0.20.1
k8s.io/component-base v0.20.1 // indirect
k8s.io/klog/v2 v2.5.0 // indirect
sigs.k8s.io/controller-runtime v0.7.0
)

76
go.sum
View File

@ -1,5 +1,6 @@
bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.37.4/go.mod h1:NHPJ89PdicEuT9hdPXMROBD91xc5uRDxsMtSB16k7hw=
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
@ -13,10 +14,6 @@ cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKV
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI=
cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk=
cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY=
cloud.google.com/go v0.76.0/go.mod h1:r9EvIAvLrunusnetGdQ50M/gKui1x3zdGW/VELGkdpw=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
@ -26,7 +23,6 @@ cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM7
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
cloud.google.com/go/logging v1.2.0/go.mod h1:eefltkCUQrHz8MFKQk3jXusVNJAWvJzi97xCrh3yeM8=
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
@ -120,6 +116,8 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPd
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A=
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
github.com/atcdot/gorm-bulk-upsert v1.0.0 h1:K+lS2jHHwXZjZSdiPjBiyQi8W9nnpTbdz69/YR1CI6s=
github.com/atcdot/gorm-bulk-upsert v1.0.0/go.mod h1:b7/GgeVNbf/SFw4FYIWslxNV5I10C9Mhf/++3jsDk3M=
github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU=
github.com/aws/aws-sdk-go v1.15.78/go.mod h1:E3/ieXAlvM0XWO57iftYVDLLvQ824smPP3ATZkfNZeM=
github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
@ -188,8 +186,6 @@ github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHo
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM=
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-systemd v0.0.0-20161114122254-48702e0da86b h1:+mtZ0WjVZwTX0RVrXMXDwuYVaNeHGvWBW1UwJeMR+2M=
github.com/coreos/go-systemd v0.0.0-20161114122254-48702e0da86b/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf h1:iW4rZ826su+pqaw19uhpSCzhj44qo35pNgKFGqzDKkU=
@ -218,6 +214,7 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/daviddengcn/go-colortext v0.0.0-20160507010035-511bcaf42ccd/go.mod h1:dv4zxwHi5C/8AeI+4gX4dCWOIvNi7I6JCSX0HvlKPgE=
github.com/denisenkom/go-mssqldb v0.0.0-20190515213511-eb9f6a1743f3/go.mod h1:zAg7JM8CkOJ43xKXIj7eRO9kmWm/TW578qo+oDO6tuM=
github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd h1:83Wprp6ROGeiHFAP8WJdI2RoxALQYgdllERc3N5N2DM=
github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
@ -358,6 +355,7 @@ github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GO
github.com/go-redis/redis v6.15.9+incompatible h1:K0pv1D7EQUjfyoMql+r/jZqCLizCGKFlFgcHWWmHQjg=
github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
@ -436,7 +434,6 @@ github.com/google/go-cmp v0.5.1 h1:JFrFEBb2xKufg6XkJsJr+WbKb4FQlURi5RUcBveYu9k=
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
@ -447,7 +444,6 @@ github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/
github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
@ -455,10 +451,6 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
@ -514,7 +506,6 @@ github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjh
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
github.com/hashicorp/go-multierror v0.0.0-20150608033521-56912fb08d85/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I=
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA=
github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
github.com/hashicorp/go-safetemp v1.0.0/go.mod h1:oaerMy3BhqiTbVye6QuFhFtIceqFoDHxNAB65b+Rj1I=
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
@ -541,7 +532,6 @@ github.com/howeyc/fsnotify v0.9.0/go.mod h1:41HzSPxBGeFRQKEEwgh49TRw/nKBsYZ2cF1O
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/imdario/mergo v0.3.7/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
@ -553,6 +543,7 @@ github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jinzhu/gorm v1.9.10/go.mod h1:Kh6hTsSGffh4ui079FHrR5Gg+5D0hgihqDcsDN2BBJY=
github.com/jinzhu/gorm v1.9.16 h1:+IyIjPEABKRpsu/F8OvDPy9fyQlgsg2luMV2ZIH5i5o=
github.com/jinzhu/gorm v1.9.16/go.mod h1:G3LB3wezTOWM2ITLzPxEXgSkOXAntiLHS7UdBefADcs=
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
@ -618,7 +609,6 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o
github.com/klauspost/compress v1.11.6/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8=
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8=
@ -684,6 +674,7 @@ github.com/mattn/go-runewidth v0.0.6 h1:V2iyH+aX9C5fsYCpK60U8BYIvmhqxuOL3JZcqc1N
github.com/mattn/go-runewidth v0.0.6/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-shellwords v1.0.10 h1:Y7Xqm8piKOO3v10Thp7Z36h4FYFjt5xB//6XvOrs2Gw=
github.com/mattn/go-shellwords v1.0.10/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y=
github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/mattn/go-sqlite3 v1.14.0 h1:mLyGNKR8+Vv9CAU7PphKa2hkEqxxhn8i32J6FPj1/QA=
github.com/mattn/go-sqlite3 v1.14.0/go.mod h1:JIl7NbARA7phWnGvh0LKTyg7S9BA+6gx71ShQilpsus=
github.com/mattn/go-xmlrpc v0.0.3 h1:Y6WEMLEsqs3RviBrAa1/7qmbGB7DVD3brZIbqMbQdGY=
@ -740,7 +731,6 @@ github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRW
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
github.com/myesui/uuid v1.0.0 h1:xCBmH4l5KuvLYc5L7AS7SZg9/jKdIFubM7OVoLqaQUI=
github.com/myesui/uuid v1.0.0/go.mod h1:2CDfNgU0LR8mIdO8vdWd8i9gWWxLlcoIGGpSNgafq84=
github.com/natefinch/lumberjack v2.0.0+incompatible/go.mod h1:Wi9p2TTF5DG5oU+6YfsmYQpsTIOm0B1VNzQg9Mw6nPk=
github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg=
github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU=
github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k=
@ -781,6 +771,7 @@ github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.10.2 h1:aY/nuoWlKJud2J6U0E3NWsjlg+0GtwXxgEqthRdzlcs=
github.com/onsi/gomega v1.10.2/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.10.5 h1:7n6FEkpFmfCoo2t+YYqXH0evK+a9ICQz0xcAy9dYcaQ=
github.com/onsi/gomega v1.10.5/go.mod h1:gza4q3jKQJijlu05nKWRCW/GavJumGt8aNRxWg7mt48=
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
github.com/opencontainers/go-digest v1.0.0-rc1 h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2iki3E3Ii+WN7gQ=
@ -884,7 +875,6 @@ github.com/prometheus/procfs v0.1.3 h1:F0+tqvhOksq22sc6iCHF5WGlWjdwj92p0udFh1VFB
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/prometheus/procfs v0.2.0 h1:wH4vA7pcjKuZzjF7lM8awk4fnuJO6idemZXoKnULUx4=
github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/prometheus/prom2json v1.3.0/go.mod h1:rMN7m0ApCowcoDlypBHlkNbp5eJQf/+1isKykIP5ZnM=
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
@ -929,7 +919,6 @@ github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJ
github.com/soundcloud/go-runit v0.0.0-20150630195641-06ad41a06c4a h1:os5OBNhwOwybXZMNLqT96XqtjdTtwRFw2w08uluvNeI=
github.com/soundcloud/go-runit v0.0.0-20150630195641-06ad41a06c4a/go.mod h1:LeFCbQYJ3KJlPs/FvPz2dy1tkpxyeNESVyCNNzRXFR0=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/afero v1.2.2 h1:5jhuqJyZCZf2JRofRvN/nIFgIWNzPa3/Vz8mYylgbWc=
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
@ -939,8 +928,6 @@ github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKv
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI=
github.com/spf13/cobra v1.1.3 h1:xghbfqPkxzxP3C/f3n5DdpAbdKLj4ZE4BWQI362l53M=
github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.1-0.20171106142849-4c012f6dcd95/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
@ -950,7 +937,6 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
github.com/src-d/gcfg v1.4.0 h1:xXbNR5AlLSA315x2UO+fTSSAXCDf+Ar38/6oyGbDKQ4=
github.com/src-d/gcfg v1.4.0/go.mod h1:p/UMsR43ujA89BJY9duynAwIpvqEujIH/jFlfL7jWoI=
github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8=
@ -968,6 +954,7 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
@ -1030,8 +1017,6 @@ go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
go.opencensus.io v0.22.6/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
@ -1054,6 +1039,7 @@ go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
go.uber.org/zap v1.15.0 h1:ZZCA22JRF2gQE5FoNmhmrf7jeJJ2uhqDUNRYKm8dvmM=
go.uber.org/zap v1.15.0/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc=
go.uber.org/zap v1.16.0 h1:uFRZXykJGK9lLY4HtgSw44DnIcAM+kRBP7x5m+NpAOM=
go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ=
golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20180214000028-650f4a345ab4/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
@ -1100,6 +1086,7 @@ golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRu
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b h1:Wh+f8QHJXR411sJR8/vRBTZ7YapZaRvUcLFFJhusH0k=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5 h1:2M3HP5CCK1Si9FQhwnzYhXdG6DXeebvUHFpre8QvbyI=
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
@ -1111,7 +1098,7 @@ golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.1 h1:Kvvh58BN8Y9/lBi7hTekvtMpm07eUZ0ck5pRHpsMWrY=
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@ -1156,13 +1143,9 @@ golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81R
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b h1:uwuIcX0g4Yl1NC5XAz37xsr2lTtcqevgzYNVt49waME=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20201224014010-6772e930b67b h1:iFwSg7t5GZmB/Q5TjiEAsdoLDrdJRC1RiF2WhuV29Qw=
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210119194325-5f4716e94777 h1:003p0dJM77cxMSyCPFphvZf/Y5/NXf5fzg6ufd1/Oew=
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@ -1172,12 +1155,6 @@ golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4Iltr
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5 h1:Lm4OryKCca1vehdsWogr9N4t7NfZxLbJoc/H0w4K4S4=
golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210113160501-8b1d76fa0423/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210113205817-d3ed898aa8a3/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210201163806-010130855d6c h1:HiAZXo96zOhVhtFHchj/ojzoxCFiPrp9/j0GtS38V3g=
golang.org/x/oauth2 v0.0.0-20210201163806-010130855d6c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -1252,16 +1229,11 @@ golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201112073958-5cba982894dd h1:5CtCZbICpIOFdgO940moixOPjc0178IU44m4EjOO5IY=
golang.org/x/sys v0.0.0-20201112073958-5cba982894dd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201214210602-f9fddec55a1e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201223074533-0d417f636930 h1:vRgIt+nup/B/BwIS0g2oC0haq0iqbV3ZA+u6+0TlNCo=
golang.org/x/sys v0.0.0-20201223074533-0d417f636930/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c h1:VwygUrnw9jn88c4u8GD3rZQbqrP/tgas88tPUbBxQrk=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -1349,14 +1321,7 @@ golang.org/x/tools v0.0.0-20200630223951-c138986dd9b9/go.mod h1:EkVYQZoAsY45+roY
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20201228162255-34cd474b9958 h1:8dEW6cGnUF2NIvtKDx8YsMBEw5pUrMEVUrU0jiPgmu8=
golang.org/x/tools v0.0.0-20201228162255-34cd474b9958/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.0 h1:po9/4sTYwZU9lPhi1tOrb4hCv3qrhiQ77LZfGa2OjwY=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@ -1384,9 +1349,6 @@ google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0M
google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE=
google.golang.org/api v0.38.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
@ -1399,6 +1361,7 @@ google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCID
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0NQvRW8DG4Yk3Q6T9cu9RcFQDu1tc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
@ -1430,17 +1393,8 @@ google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7Fc
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a h1:pOwg4OoaRYScjmR4LlLgdtnyoHYTSAVhhqe5uPdpII8=
google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e h1:wYR00/Ht+i/79g/gzhdehBgLIJCklKoc8Q/NebdzzpY=
google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210122163508-8081c04a3579/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210202153253-cf70463f6119/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210218151259-fe80b386bf06 h1:Px6YyLaNKEo5eoniIBAv6Es0jbvyEmSYqOac64iS2Rs=
google.golang.org/genproto v0.0.0-20210218151259-fe80b386bf06/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/grpc v1.29.0 h1:2pJjwYOdkZ9HlN4sWRYBg9ttH5bCOlsueaM+b/oYjwo=
@ -1530,8 +1484,6 @@ honnef.co/go/tools v0.0.1-2020.1.3 h1:sXmLre5bzIR6ypkjXCDI3jHPssRhc8KD/Ome589sc3
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.0.1-2020.1.4 h1:UoveltGrhghAA7ePc+e+QYDHXrBps2PqFZiHkGR/xK8=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
istio.io/pkg v0.0.0-20210519012641-d57c32f9ee9c h1:s3a8zBhbgugTISLVLLUXbvruTFMRgHS/JuapYY3MPoA=
istio.io/pkg v0.0.0-20210519012641-d57c32f9ee9c/go.mod h1:U14DF4p1AViKhOwpVv1UPEWtknGytJyfJw6hqVi0TmM=
k8s.io/api v0.20.0 h1:WwrYoZNM1W1aQEbyl8HNG+oWGzLpZQBlcerS9BQw9yI=
k8s.io/api v0.20.0/go.mod h1:HyLC5l5eoS/ygQYl1BXBgFzWNlkHiAuyNAbevIn+FKg=
k8s.io/apiextensions-apiserver v0.20.0 h1:HmeP9mLET/HlIQ5gjP+1c20tgJrlshY5nUyIand3AVg=

View File

@ -799,3 +799,11 @@ func Getenv(key, def string) string {
}
return value
}
// Elapsed measures the execution time.
func Elapsed(what string) func() {
start := time.Now()
return func() {
logrus.Debugf("%s took %v", what, time.Since(start))
}
}

View File

@ -204,7 +204,7 @@ func ReturnResNotEnough(r *http.Request, w http.ResponseWriter, msg string) {
//ReturnBcodeError bcode error
func ReturnBcodeError(r *http.Request, w http.ResponseWriter, err error) {
berr := bcode.Err2Coder(err)
logrus.Debugf("path %s error code: %d; status: %d; error msg: %s", r.RequestURI, berr.GetCode(), berr.GetStatus(), berr.Error())
logrus.Debugf("path %s error code: %d; status: %d; error msg: %+v", r.RequestURI, berr.GetCode(), berr.GetStatus(), err)
status := berr.GetStatus()
result := Result{

View File

@ -0,0 +1,69 @@
// Copyright (C) 2014-2021 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 retryutil
import (
"fmt"
"time"
)
//RetryError -
type RetryError struct {
n int
}
func (e *RetryError) Error() string {
return fmt.Sprintf("still failing after %d retries", e.n)
}
//IsRetryFailure -
func IsRetryFailure(err error) bool {
_, ok := err.(*RetryError)
return ok
}
//ConditionFunc -
type ConditionFunc func() (bool, error)
// Retry retries f every interval until after maxRetries.
// The interval won't be affected by how long f takes.
// For example, if interval is 3s, f takes 1s, another f will be called 2s later.
// However, if f takes longer than interval, it will be delayed.
func Retry(interval time.Duration, maxRetries int, f ConditionFunc) error {
if maxRetries <= 0 {
return fmt.Errorf("maxRetries (%d) should be > 0", maxRetries)
}
tick := time.NewTicker(interval)
defer tick.Stop()
for i := 0; ; i++ {
ok, err := f()
if err != nil {
return err
}
if ok {
return nil
}
if i == maxRetries {
break
}
<-tick.C
}
return &RetryError{maxRetries}
}