2018-03-14 14:12:26 +08:00
|
|
|
// Copyright (C) 2014-2018 Goodrain Co., Ltd.
|
2017-11-07 11:40:44 +08:00
|
|
|
// RAINBOND, Application Management Platform
|
2018-03-14 14:33:31 +08:00
|
|
|
|
2017-11-07 11:40:44 +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
|
|
|
|
2017-11-07 11:40:44 +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
|
|
|
|
2017-11-07 11:40:44 +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 controller
|
|
|
|
|
|
|
|
import (
|
2018-12-14 16:40:41 +08:00
|
|
|
"encoding/json"
|
2017-11-19 18:59:41 +08:00
|
|
|
"fmt"
|
|
|
|
"net/http"
|
|
|
|
|
2018-04-24 16:44:59 +08:00
|
|
|
"github.com/goodrain/rainbond/api/middleware"
|
|
|
|
api_model "github.com/goodrain/rainbond/api/model"
|
|
|
|
"github.com/goodrain/rainbond/event"
|
|
|
|
"github.com/goodrain/rainbond/worker/discover/model"
|
2019-03-08 19:22:22 +08:00
|
|
|
validator "github.com/thedevsaddam/govalidator"
|
2017-11-07 11:40:44 +08:00
|
|
|
|
2017-11-16 16:30:22 +08:00
|
|
|
"time"
|
2017-11-19 18:59:41 +08:00
|
|
|
|
2018-08-03 15:17:10 +08:00
|
|
|
"os"
|
|
|
|
|
2018-11-19 18:56:28 +08:00
|
|
|
"io/ioutil"
|
|
|
|
|
2017-11-19 18:59:41 +08:00
|
|
|
"github.com/Sirupsen/logrus"
|
2018-08-03 15:17:10 +08:00
|
|
|
"github.com/go-chi/chi"
|
2018-04-24 16:44:59 +08:00
|
|
|
"github.com/goodrain/rainbond/api/handler"
|
|
|
|
"github.com/goodrain/rainbond/db"
|
|
|
|
dbmodel "github.com/goodrain/rainbond/db/model"
|
|
|
|
tutil "github.com/goodrain/rainbond/util"
|
|
|
|
httputil "github.com/goodrain/rainbond/util/http"
|
2018-06-21 14:30:23 +08:00
|
|
|
"github.com/jinzhu/gorm"
|
2018-10-23 18:11:27 +08:00
|
|
|
"github.com/pquerna/ffjson/ffjson"
|
2017-11-07 11:40:44 +08:00
|
|
|
)
|
|
|
|
|
2017-11-21 14:35:43 +08:00
|
|
|
//TIMELAYOUT timelayout
|
2017-11-19 18:59:41 +08:00
|
|
|
const TIMELAYOUT = "2006-01-02T15:04:05"
|
2017-11-16 16:30:22 +08:00
|
|
|
|
2017-11-19 18:59:41 +08:00
|
|
|
func createEvent(eventID, serviceID, optType, tenantID, deployVersion string) (*dbmodel.ServiceEvent, int, error) {
|
|
|
|
if eventID == "" {
|
|
|
|
eventID = tutil.NewUUID()
|
2017-11-17 09:49:52 +08:00
|
|
|
}
|
2017-11-19 18:59:41 +08:00
|
|
|
event := dbmodel.ServiceEvent{}
|
|
|
|
event.EventID = eventID
|
|
|
|
event.ServiceID = serviceID
|
|
|
|
event.OptType = optType
|
|
|
|
event.TenantID = tenantID
|
|
|
|
now := time.Now()
|
2017-11-16 16:30:22 +08:00
|
|
|
timeNow := now.Format(TIMELAYOUT)
|
2017-11-19 18:59:41 +08:00
|
|
|
event.StartTime = timeNow
|
|
|
|
event.UserName = "system"
|
|
|
|
version := deployVersion
|
|
|
|
oldDeployVersion := ""
|
|
|
|
if deployVersion == "" {
|
|
|
|
service, err := db.GetManager().TenantServiceDao().GetServiceByID(serviceID)
|
2017-11-16 16:30:22 +08:00
|
|
|
if err != nil {
|
2017-11-19 18:59:41 +08:00
|
|
|
return nil, 3, nil
|
2017-11-16 16:30:22 +08:00
|
|
|
}
|
2017-11-19 18:59:41 +08:00
|
|
|
version = service.DeployVersion
|
2017-11-16 16:30:22 +08:00
|
|
|
}
|
2017-11-19 18:59:41 +08:00
|
|
|
events, err := db.GetManager().ServiceEventDao().GetEventByServiceID(serviceID)
|
2017-11-16 16:30:22 +08:00
|
|
|
if err != nil {
|
|
|
|
|
|
|
|
}
|
|
|
|
if len(events) != 0 {
|
2017-11-19 18:59:41 +08:00
|
|
|
latestEvent := events[0]
|
|
|
|
oldDeployVersion = latestEvent.DeployVersion
|
2017-11-16 16:30:22 +08:00
|
|
|
}
|
|
|
|
|
2017-11-19 18:59:41 +08:00
|
|
|
event.DeployVersion = version
|
|
|
|
event.OldDeployVersion = oldDeployVersion
|
2017-11-16 16:30:22 +08:00
|
|
|
|
2017-11-27 18:01:04 +08:00
|
|
|
status, err := checkCanAddEvent(serviceID, event.EventID)
|
2017-11-16 16:30:22 +08:00
|
|
|
if err != nil {
|
2018-11-22 16:22:44 +08:00
|
|
|
logrus.Errorf("error check event %s", err.Error())
|
2017-11-19 18:59:41 +08:00
|
|
|
return nil, status, nil
|
2017-11-16 16:30:22 +08:00
|
|
|
}
|
2017-11-19 18:59:41 +08:00
|
|
|
if status == 0 {
|
2017-11-16 16:30:22 +08:00
|
|
|
db.GetManager().ServiceEventDao().AddModel(&event)
|
2017-11-19 18:59:41 +08:00
|
|
|
return &event, status, nil
|
2017-11-16 16:30:22 +08:00
|
|
|
}
|
2017-11-21 14:35:43 +08:00
|
|
|
return nil, status, nil
|
2017-11-16 16:30:22 +08:00
|
|
|
}
|
|
|
|
|
2017-11-27 18:01:04 +08:00
|
|
|
func checkCanAddEvent(s, eventID string) (int, error) {
|
2017-11-19 18:59:41 +08:00
|
|
|
events, err := db.GetManager().ServiceEventDao().GetEventByServiceID(s)
|
2017-11-16 16:30:22 +08:00
|
|
|
if err != nil {
|
2017-11-19 18:59:41 +08:00
|
|
|
return 3, err
|
2017-11-16 16:30:22 +08:00
|
|
|
}
|
|
|
|
if len(events) == 0 {
|
|
|
|
//service 首个event
|
2017-11-19 18:59:41 +08:00
|
|
|
return 0, nil
|
2017-11-16 16:30:22 +08:00
|
|
|
}
|
2017-11-19 18:59:41 +08:00
|
|
|
latestEvent := events[0]
|
2017-11-27 18:01:04 +08:00
|
|
|
if latestEvent.EventID == eventID {
|
|
|
|
return 0, nil
|
2017-11-23 09:57:25 +08:00
|
|
|
}
|
2017-11-19 18:59:41 +08:00
|
|
|
if latestEvent.FinalStatus == "" {
|
2017-11-16 16:30:22 +08:00
|
|
|
//未完成
|
2017-11-19 18:59:41 +08:00
|
|
|
timeOut, err := checkEventTimeOut(latestEvent)
|
2017-11-16 16:30:22 +08:00
|
|
|
if err != nil {
|
2017-11-19 18:59:41 +08:00
|
|
|
return 3, err
|
2017-11-16 16:30:22 +08:00
|
|
|
}
|
2018-11-22 16:22:44 +08:00
|
|
|
logrus.Debugf("event %s timeOut %v", latestEvent.EventID, timeOut)
|
2017-11-16 16:30:22 +08:00
|
|
|
if timeOut {
|
|
|
|
//未完成,超时
|
2017-11-19 18:59:41 +08:00
|
|
|
return 0, nil
|
2017-11-16 16:30:22 +08:00
|
|
|
}
|
2017-11-21 14:35:43 +08:00
|
|
|
//未完成,未超时
|
|
|
|
return 2, nil
|
2017-11-16 16:30:22 +08:00
|
|
|
}
|
2017-11-21 14:35:43 +08:00
|
|
|
//已完成
|
|
|
|
return 0, nil
|
2017-11-16 16:30:22 +08:00
|
|
|
}
|
2017-11-19 18:59:41 +08:00
|
|
|
func getOrNilEventID(data map[string]interface{}) string {
|
|
|
|
if eventID, ok := data["event_id"]; ok {
|
2017-11-17 09:49:52 +08:00
|
|
|
return eventID.(string)
|
|
|
|
}
|
|
|
|
return ""
|
|
|
|
}
|
2017-11-19 18:59:41 +08:00
|
|
|
func checkEventTimeOut(event *dbmodel.ServiceEvent) (bool, error) {
|
2017-11-16 16:30:22 +08:00
|
|
|
startTime := event.StartTime
|
2018-11-22 16:22:44 +08:00
|
|
|
start, err := time.ParseInLocation(TIMELAYOUT, startTime, time.Local)
|
2017-11-19 18:59:41 +08:00
|
|
|
if err != nil {
|
|
|
|
return true, err
|
2017-11-16 16:30:22 +08:00
|
|
|
}
|
2018-11-22 16:22:44 +08:00
|
|
|
if event.OptType == "deploy" || event.OptType == "create" || event.OptType == "build" {
|
2017-11-19 18:59:41 +08:00
|
|
|
end := start.Add(3 * time.Minute)
|
|
|
|
if time.Now().After(end) {
|
2017-11-16 16:30:22 +08:00
|
|
|
event.FinalStatus = "timeout"
|
2017-11-19 18:59:41 +08:00
|
|
|
err = db.GetManager().ServiceEventDao().UpdateModel(event)
|
|
|
|
return true, err
|
2017-11-16 16:30:22 +08:00
|
|
|
}
|
2017-11-19 18:59:41 +08:00
|
|
|
} else {
|
|
|
|
end := start.Add(30 * time.Second)
|
|
|
|
if time.Now().After(end) {
|
2017-11-16 16:30:22 +08:00
|
|
|
event.FinalStatus = "timeout"
|
2017-11-19 18:59:41 +08:00
|
|
|
err = db.GetManager().ServiceEventDao().UpdateModel(event)
|
|
|
|
return true, err
|
2017-11-16 16:30:22 +08:00
|
|
|
}
|
|
|
|
}
|
2017-11-19 18:59:41 +08:00
|
|
|
return false, nil
|
2017-11-16 16:30:22 +08:00
|
|
|
}
|
|
|
|
|
2017-11-19 18:59:41 +08:00
|
|
|
func handleStatus(status int, err error, w http.ResponseWriter, r *http.Request) {
|
|
|
|
if status != 0 {
|
2017-11-22 16:36:54 +08:00
|
|
|
//logrus.Error("应用启动任务发送失败 "+err.Error(), map[string]string{"step": "callback", "status": "failure"})
|
2017-11-19 18:59:41 +08:00
|
|
|
if status == 2 {
|
2017-11-16 16:30:22 +08:00
|
|
|
httputil.ReturnError(r, w, 400, "last event unfinish.")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
httputil.ReturnError(r, w, 400, "create event info error.")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
2017-11-19 18:59:41 +08:00
|
|
|
|
2017-11-07 11:40:44 +08:00
|
|
|
//StartService StartService
|
2017-11-20 17:29:39 +08:00
|
|
|
// swagger:operation POST /v2/tenants/{tenant_name}/services/{service_alias}/start v2 startService
|
|
|
|
//
|
|
|
|
// 启动应用
|
|
|
|
//
|
2017-11-27 18:01:04 +08:00
|
|
|
// start service
|
2017-11-20 17:29:39 +08:00
|
|
|
//
|
|
|
|
// ---
|
|
|
|
// consumes:
|
|
|
|
// - application/json
|
|
|
|
// - application/x-protobuf
|
|
|
|
//
|
|
|
|
// produces:
|
|
|
|
// - application/json
|
|
|
|
// - application/xml
|
|
|
|
//
|
|
|
|
// responses:
|
|
|
|
// default:
|
|
|
|
// schema:
|
|
|
|
// "$ref": "#/responses/commandResponse"
|
|
|
|
// description: 统一返回格式
|
2017-11-07 11:40:44 +08:00
|
|
|
func (t *TenantStruct) StartService(w http.ResponseWriter, r *http.Request) {
|
2017-11-17 09:49:52 +08:00
|
|
|
rules := validator.MapData{
|
|
|
|
"event_id": []string{},
|
|
|
|
}
|
|
|
|
data, ok := httputil.ValidatorRequestMapAndErrorResponse(r, w, rules, nil)
|
|
|
|
if !ok {
|
|
|
|
return
|
|
|
|
}
|
2018-03-16 12:16:57 +08:00
|
|
|
// TODO:
|
|
|
|
// if os.Getenv("PUBLIC_CLOUD") == "true" {
|
|
|
|
// tenant := r.Context().Value(middleware.ContextKey("tenant")).(*dbmodel.Tenants)
|
|
|
|
// service := r.Context().Value(middleware.ContextKey("service")).(*dbmodel.TenantServices)
|
2019-01-24 11:28:17 +08:00
|
|
|
// if err := cloud.ChargeSverify(tenant, service.ContainerMemory*service.Replicas, "start"); err != nil {
|
2018-03-16 12:16:57 +08:00
|
|
|
// err.Handle(r, w)
|
|
|
|
// return
|
|
|
|
// }
|
|
|
|
// }
|
2017-11-07 11:40:44 +08:00
|
|
|
tenantID := r.Context().Value(middleware.ContextKey("tenant_id")).(string)
|
|
|
|
serviceID := r.Context().Value(middleware.ContextKey("service_id")).(string)
|
2017-11-16 16:30:22 +08:00
|
|
|
|
2017-11-19 18:59:41 +08:00
|
|
|
sEvent, status, err := createEvent(getOrNilEventID(data), serviceID, "start", tenantID, "")
|
|
|
|
handleStatus(status, err, w, r)
|
2018-02-26 11:35:50 +08:00
|
|
|
if status != 0 {
|
|
|
|
return
|
|
|
|
}
|
2017-11-16 16:30:22 +08:00
|
|
|
eventID := sEvent.EventID
|
2017-11-07 11:40:44 +08:00
|
|
|
logger := event.GetManager().GetLogger(eventID)
|
|
|
|
defer event.CloseManager()
|
|
|
|
startStopStruct := &api_model.StartStopStruct{
|
|
|
|
TenantID: tenantID,
|
|
|
|
ServiceID: serviceID,
|
|
|
|
EventID: eventID,
|
|
|
|
TaskType: "start",
|
|
|
|
}
|
|
|
|
if err := handler.GetServiceManager().StartStopService(startStopStruct); err != nil {
|
|
|
|
logger.Error("应用启动任务发送失败 "+err.Error(), map[string]string{"step": "callback", "status": "failure"})
|
|
|
|
httputil.ReturnError(r, w, 500, "get service info error.")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
logger.Info("应用启动任务发送成功 ", map[string]string{"step": "start-service", "status": "starting"})
|
2017-11-19 18:59:41 +08:00
|
|
|
httputil.ReturnSuccess(r, w, sEvent)
|
2017-11-07 11:40:44 +08:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
//StopService StopService
|
2017-11-20 17:29:39 +08:00
|
|
|
// swagger:operation POST /v2/tenants/{tenant_name}/services/{service_alias}/stop v2 stopService
|
|
|
|
//
|
|
|
|
// 关闭应用
|
|
|
|
//
|
2017-11-27 18:01:04 +08:00
|
|
|
// stop service
|
2017-11-20 17:29:39 +08:00
|
|
|
//
|
|
|
|
// ---
|
|
|
|
// consumes:
|
|
|
|
// - application/json
|
|
|
|
// - application/x-protobuf
|
|
|
|
//
|
|
|
|
// produces:
|
|
|
|
// - application/json
|
|
|
|
// - application/xml
|
|
|
|
//
|
|
|
|
// responses:
|
|
|
|
// default:
|
|
|
|
// schema:
|
|
|
|
// "$ref": "#/responses/commandResponse"
|
|
|
|
// description: 统一返回格式
|
2017-11-07 11:40:44 +08:00
|
|
|
func (t *TenantStruct) StopService(w http.ResponseWriter, r *http.Request) {
|
2017-11-17 09:49:52 +08:00
|
|
|
rules := validator.MapData{
|
|
|
|
"event_id": []string{},
|
|
|
|
}
|
|
|
|
data, ok := httputil.ValidatorRequestMapAndErrorResponse(r, w, rules, nil)
|
|
|
|
if !ok {
|
|
|
|
return
|
|
|
|
}
|
2017-11-07 11:40:44 +08:00
|
|
|
tenantID := r.Context().Value(middleware.ContextKey("tenant_id")).(string)
|
|
|
|
serviceID := r.Context().Value(middleware.ContextKey("service_id")).(string)
|
2017-11-19 18:59:41 +08:00
|
|
|
sEvent, status, err := createEvent(getOrNilEventID(data), serviceID, "stop", tenantID, "")
|
|
|
|
handleStatus(status, err, w, r)
|
2018-02-26 11:35:50 +08:00
|
|
|
if status != 0 {
|
|
|
|
return
|
|
|
|
}
|
2017-11-16 16:30:22 +08:00
|
|
|
//save event
|
|
|
|
eventID := sEvent.EventID
|
2017-11-07 11:40:44 +08:00
|
|
|
logger := event.GetManager().GetLogger(eventID)
|
|
|
|
defer event.CloseManager()
|
|
|
|
startStopStruct := &api_model.StartStopStruct{
|
|
|
|
TenantID: tenantID,
|
|
|
|
ServiceID: serviceID,
|
|
|
|
EventID: eventID,
|
|
|
|
TaskType: "stop",
|
|
|
|
}
|
|
|
|
if err := handler.GetServiceManager().StartStopService(startStopStruct); err != nil {
|
|
|
|
logger.Error("应用停止任务发送失败 "+err.Error(), map[string]string{"step": "callback", "status": "failure"})
|
|
|
|
httputil.ReturnError(r, w, 500, "get service info error.")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
logger.Info("应用停止任务发送成功 ", map[string]string{"step": "stop-service", "status": "starting"})
|
2017-11-19 18:59:41 +08:00
|
|
|
httputil.ReturnSuccess(r, w, sEvent)
|
2017-11-07 11:40:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
//RestartService RestartService
|
2017-11-20 17:29:39 +08:00
|
|
|
// swagger:operation POST /v2/tenants/{tenant_name}/services/{service_alias}/restart v2 restartService
|
|
|
|
//
|
|
|
|
// 重启应用
|
|
|
|
//
|
2017-11-27 18:01:04 +08:00
|
|
|
// restart service
|
2017-11-20 17:29:39 +08:00
|
|
|
//
|
|
|
|
// ---
|
|
|
|
// consumes:
|
|
|
|
// - application/json
|
|
|
|
// - application/x-protobuf
|
|
|
|
//
|
|
|
|
// produces:
|
|
|
|
// - application/json
|
|
|
|
// - application/xml
|
|
|
|
//
|
|
|
|
// responses:
|
|
|
|
// default:
|
|
|
|
// schema:
|
|
|
|
// "$ref": "#/responses/commandResponse"
|
|
|
|
// description: 统一返回格式
|
2017-11-07 11:40:44 +08:00
|
|
|
func (t *TenantStruct) RestartService(w http.ResponseWriter, r *http.Request) {
|
2017-11-17 09:49:52 +08:00
|
|
|
rules := validator.MapData{
|
|
|
|
"event_id": []string{},
|
|
|
|
}
|
|
|
|
data, ok := httputil.ValidatorRequestMapAndErrorResponse(r, w, rules, nil)
|
|
|
|
if !ok {
|
|
|
|
return
|
|
|
|
}
|
2017-11-07 11:40:44 +08:00
|
|
|
tenantID := r.Context().Value(middleware.ContextKey("tenant_id")).(string)
|
|
|
|
serviceID := r.Context().Value(middleware.ContextKey("service_id")).(string)
|
2017-11-19 18:59:41 +08:00
|
|
|
sEvent, status, err := createEvent(getOrNilEventID(data), serviceID, "restart", tenantID, "")
|
|
|
|
handleStatus(status, err, w, r)
|
2018-02-26 11:35:50 +08:00
|
|
|
if status != 0 {
|
|
|
|
return
|
|
|
|
}
|
2017-11-16 16:30:22 +08:00
|
|
|
//save event
|
|
|
|
eventID := sEvent.EventID
|
2017-11-07 11:40:44 +08:00
|
|
|
logger := event.GetManager().GetLogger(eventID)
|
|
|
|
defer event.CloseManager()
|
|
|
|
startStopStruct := &api_model.StartStopStruct{
|
|
|
|
TenantID: tenantID,
|
|
|
|
ServiceID: serviceID,
|
|
|
|
EventID: eventID,
|
|
|
|
TaskType: "restart",
|
|
|
|
}
|
2018-04-03 18:21:46 +08:00
|
|
|
|
|
|
|
curStatus := t.StatusCli.GetStatus(serviceID)
|
|
|
|
if curStatus == "closed" {
|
|
|
|
startStopStruct.TaskType = "start"
|
2018-01-02 12:04:36 +08:00
|
|
|
}
|
2017-11-07 11:40:44 +08:00
|
|
|
if err := handler.GetServiceManager().StartStopService(startStopStruct); err != nil {
|
|
|
|
logger.Error("应用重启任务发送失败 "+err.Error(), map[string]string{"step": "callback", "status": "failure"})
|
|
|
|
httputil.ReturnError(r, w, 500, "get service info error.")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
logger.Info("应用重启任务发送成功 ", map[string]string{"step": "restart-service", "status": "starting"})
|
2017-11-19 18:59:41 +08:00
|
|
|
httputil.ReturnSuccess(r, w, sEvent)
|
2017-11-07 11:40:44 +08:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
//VerticalService VerticalService
|
2017-11-20 17:29:39 +08:00
|
|
|
// swagger:operation PUT /v2/tenants/{tenant_name}/services/{service_alias}/vertical v2 verticalService
|
|
|
|
//
|
|
|
|
// 应用垂直伸缩
|
|
|
|
//
|
2017-11-27 18:01:04 +08:00
|
|
|
// service vertical
|
2017-11-20 17:29:39 +08:00
|
|
|
//
|
|
|
|
// ---
|
|
|
|
// consumes:
|
|
|
|
// - application/json
|
|
|
|
// - application/x-protobuf
|
|
|
|
//
|
|
|
|
// produces:
|
|
|
|
// - application/json
|
|
|
|
// - application/xml
|
|
|
|
//
|
|
|
|
// responses:
|
|
|
|
// default:
|
|
|
|
// schema:
|
|
|
|
// "$ref": "#/responses/commandResponse"
|
|
|
|
// description: 统一返回格式
|
2017-11-07 11:40:44 +08:00
|
|
|
func (t *TenantStruct) VerticalService(w http.ResponseWriter, r *http.Request) {
|
|
|
|
rules := validator.MapData{
|
2017-11-20 17:29:39 +08:00
|
|
|
"event_id": []string{},
|
2017-11-07 11:40:44 +08:00
|
|
|
"container_cpu": []string{"required"},
|
|
|
|
"container_memory": []string{"required"},
|
|
|
|
}
|
|
|
|
data, ok := httputil.ValidatorRequestMapAndErrorResponse(r, w, rules, nil)
|
|
|
|
if !ok {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
tenantID := r.Context().Value(middleware.ContextKey("tenant_id")).(string)
|
|
|
|
serviceID := r.Context().Value(middleware.ContextKey("service_id")).(string)
|
2017-11-19 18:59:41 +08:00
|
|
|
sEvent, status, err := createEvent(getOrNilEventID(data), serviceID, "update", tenantID, "")
|
|
|
|
handleStatus(status, err, w, r)
|
2018-02-26 11:35:50 +08:00
|
|
|
if status != 0 {
|
|
|
|
return
|
|
|
|
}
|
2017-11-16 16:30:22 +08:00
|
|
|
eventID := sEvent.EventID
|
2017-11-07 11:40:44 +08:00
|
|
|
logger := event.GetManager().GetLogger(eventID)
|
|
|
|
defer event.CloseManager()
|
|
|
|
cpu := int(data["container_cpu"].(float64))
|
|
|
|
mem := int(data["container_memory"].(float64))
|
|
|
|
verticalTask := &model.VerticalScalingTaskBody{
|
|
|
|
TenantID: tenantID,
|
|
|
|
ServiceID: serviceID,
|
|
|
|
EventID: eventID,
|
|
|
|
ContainerCPU: cpu,
|
|
|
|
ContainerMemory: mem,
|
|
|
|
}
|
|
|
|
if err := handler.GetServiceManager().ServiceVertical(verticalTask); err != nil {
|
|
|
|
logger.Error("应用垂直升级任务发送失败 "+err.Error(), map[string]string{"step": "callback", "status": "failure"})
|
|
|
|
httputil.ReturnError(r, w, 500, fmt.Sprintf("service vertical error. %v", err))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
logger.Info("应用垂直升级任务发送成功 ", map[string]string{"step": "vertical-service", "status": "starting"})
|
2017-11-19 18:59:41 +08:00
|
|
|
httputil.ReturnSuccess(r, w, sEvent)
|
2017-11-07 11:40:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
//HorizontalService HorizontalService
|
2017-11-20 17:29:39 +08:00
|
|
|
// swagger:operation PUT /v2/tenants/{tenant_name}/services/{service_alias}/horizontal v2 horizontalService
|
|
|
|
//
|
|
|
|
// 应用水平伸缩
|
|
|
|
//
|
2017-11-27 18:01:04 +08:00
|
|
|
// service horizontal
|
2017-11-20 17:29:39 +08:00
|
|
|
//
|
|
|
|
// ---
|
|
|
|
// consumes:
|
|
|
|
// - application/json
|
|
|
|
// - application/x-protobuf
|
|
|
|
//
|
|
|
|
// produces:
|
|
|
|
// - application/json
|
|
|
|
// - application/xml
|
|
|
|
//
|
|
|
|
// responses:
|
|
|
|
// default:
|
|
|
|
// schema:
|
|
|
|
// "$ref": "#/responses/commandResponse"
|
|
|
|
// description: 统一返回格式
|
2017-11-07 11:40:44 +08:00
|
|
|
func (t *TenantStruct) HorizontalService(w http.ResponseWriter, r *http.Request) {
|
|
|
|
rules := validator.MapData{
|
|
|
|
"node_num": []string{"required"},
|
|
|
|
}
|
|
|
|
data, ok := httputil.ValidatorRequestMapAndErrorResponse(r, w, rules, nil)
|
|
|
|
if !ok {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
tenantID := r.Context().Value(middleware.ContextKey("tenant_id")).(string)
|
|
|
|
serviceID := r.Context().Value(middleware.ContextKey("service_id")).(string)
|
2017-11-19 18:59:41 +08:00
|
|
|
sEvent, status, err := createEvent(getOrNilEventID(data), serviceID, "update", tenantID, "")
|
|
|
|
handleStatus(status, err, w, r)
|
2018-02-26 11:35:50 +08:00
|
|
|
if status != 0 {
|
|
|
|
return
|
|
|
|
}
|
2017-11-16 16:30:22 +08:00
|
|
|
//save event
|
|
|
|
eventID := sEvent.EventID
|
2017-11-07 11:40:44 +08:00
|
|
|
logger := event.GetManager().GetLogger(eventID)
|
|
|
|
defer event.CloseManager()
|
|
|
|
replicas := int32(data["node_num"].(float64))
|
|
|
|
horizontalTask := &model.HorizontalScalingTaskBody{
|
|
|
|
TenantID: tenantID,
|
|
|
|
ServiceID: serviceID,
|
|
|
|
EventID: eventID,
|
|
|
|
Replicas: replicas,
|
|
|
|
}
|
2018-11-19 18:56:28 +08:00
|
|
|
|
2017-11-07 11:40:44 +08:00
|
|
|
if err := handler.GetServiceManager().ServiceHorizontal(horizontalTask); err != nil {
|
|
|
|
logger.Error("应用水平升级任务发送失败 "+err.Error(), map[string]string{"step": "callback", "status": "failure"})
|
|
|
|
httputil.ReturnError(r, w, 500, fmt.Sprintf("service horizontal error. %v", err))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
logger.Info("应用水平升级任务发送成功 ", map[string]string{"step": "horizontal-service", "status": "starting"})
|
2017-11-19 18:59:41 +08:00
|
|
|
httputil.ReturnSuccess(r, w, sEvent)
|
2017-11-07 11:40:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
//BuildService BuildService
|
2017-11-20 17:29:39 +08:00
|
|
|
// swagger:operation POST /v2/tenants/{tenant_name}/services/{service_alias}/build v2 serviceBuild
|
|
|
|
//
|
|
|
|
// 应用构建
|
|
|
|
//
|
2017-11-27 18:01:04 +08:00
|
|
|
// service build
|
2017-11-20 17:29:39 +08:00
|
|
|
//
|
|
|
|
// ---
|
|
|
|
// consumes:
|
|
|
|
// - application/json
|
|
|
|
// - application/x-protobuf
|
|
|
|
//
|
|
|
|
// produces:
|
|
|
|
// - application/json
|
|
|
|
// - application/xml
|
|
|
|
//
|
|
|
|
// responses:
|
|
|
|
// default:
|
|
|
|
// schema:
|
|
|
|
// "$ref": "#/responses/commandResponse"
|
|
|
|
// description: 统一返回格式
|
2017-11-07 11:40:44 +08:00
|
|
|
func (t *TenantStruct) BuildService(w http.ResponseWriter, r *http.Request) {
|
|
|
|
var build api_model.BuildServiceStruct
|
|
|
|
ok := httputil.ValidatorRequestStructAndErrorResponse(r, w, &build.Body, nil)
|
|
|
|
if !ok {
|
|
|
|
return
|
|
|
|
}
|
2018-12-14 16:40:41 +08:00
|
|
|
b, _ := json.Marshal(build)
|
|
|
|
logrus.Debugf("request uri: %s; body: %s", r.RequestURI, string(b))
|
2018-03-04 22:48:50 +08:00
|
|
|
if len(build.Body.DeployVersion) == 0 {
|
|
|
|
httputil.ReturnError(r, w, 400, "deploy version can not be empty.")
|
|
|
|
return
|
|
|
|
}
|
2017-11-07 11:40:44 +08:00
|
|
|
tenantID := r.Context().Value(middleware.ContextKey("tenant_id")).(string)
|
|
|
|
serviceID := r.Context().Value(middleware.ContextKey("service_id")).(string)
|
|
|
|
tenantName := r.Context().Value(middleware.ContextKey("tenant_name")).(string)
|
|
|
|
serviceAlias := r.Context().Value(middleware.ContextKey("service_alias")).(string)
|
|
|
|
build.Body.TenantName = tenantName
|
|
|
|
build.Body.ServiceAlias = serviceAlias
|
2017-11-17 09:49:52 +08:00
|
|
|
|
2017-11-19 18:59:41 +08:00
|
|
|
sEvent, status, err := createEvent(build.Body.EventID, serviceID, "build", tenantID, build.Body.DeployVersion)
|
|
|
|
handleStatus(status, err, w, r)
|
2018-02-26 11:35:50 +08:00
|
|
|
if status != 0 {
|
|
|
|
return
|
|
|
|
}
|
2018-03-04 22:48:50 +08:00
|
|
|
version := dbmodel.VersionInfo{
|
|
|
|
EventID: sEvent.EventID,
|
|
|
|
ServiceID: serviceID,
|
|
|
|
RepoURL: build.Body.RepoURL,
|
|
|
|
Kind: build.Body.Kind,
|
|
|
|
BuildVersion: build.Body.DeployVersion,
|
2018-11-22 14:33:29 +08:00
|
|
|
Cmd: build.Body.Cmd,
|
2017-11-07 11:40:44 +08:00
|
|
|
}
|
2018-01-02 12:04:36 +08:00
|
|
|
err = db.GetManager().VersionInfoDao().AddModel(&version)
|
2017-12-05 16:03:44 +08:00
|
|
|
if err != nil {
|
2018-01-02 12:04:36 +08:00
|
|
|
logrus.Infof("error add version %v ,details %s", version, err.Error())
|
2018-03-04 22:48:50 +08:00
|
|
|
httputil.ReturnError(r, w, 500, "create service version error.")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
build.Body.EventID = sEvent.EventID
|
|
|
|
if err := handler.GetServiceManager().ServiceBuild(tenantID, serviceID, &build); err != nil {
|
|
|
|
logrus.Error("build service error", err.Error())
|
|
|
|
httputil.ReturnError(r, w, 500, fmt.Sprintf("build service error, %v", err))
|
|
|
|
return
|
2017-12-05 16:03:44 +08:00
|
|
|
}
|
2017-11-19 18:59:41 +08:00
|
|
|
httputil.ReturnSuccess(r, w, sEvent)
|
2017-11-07 11:40:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
//BuildList BuildList
|
|
|
|
func (t *TenantStruct) BuildList(w http.ResponseWriter, r *http.Request) {
|
2018-06-21 12:01:40 +08:00
|
|
|
serviceID := r.Context().Value(middleware.ContextKey("service_id")).(string)
|
2019-02-13 16:30:17 +08:00
|
|
|
|
|
|
|
resp, err := handler.GetServiceManager().ListVersionInfo(serviceID)
|
|
|
|
|
|
|
|
if err != nil {
|
2018-06-21 12:01:40 +08:00
|
|
|
logrus.Error("get version info error", err.Error())
|
|
|
|
httputil.ReturnError(r, w, 500, fmt.Sprintf("get version info erro, %v", err))
|
|
|
|
return
|
|
|
|
}
|
2019-02-13 16:30:17 +08:00
|
|
|
httputil.ReturnSuccess(r, w, resp)
|
2017-11-07 11:40:44 +08:00
|
|
|
}
|
|
|
|
|
2018-06-21 14:30:23 +08:00
|
|
|
func (t *TenantStruct) BuildVersionIsExist(w http.ResponseWriter, r *http.Request) {
|
|
|
|
statusMap := make(map[string]bool)
|
|
|
|
serviceID := r.Context().Value(middleware.ContextKey("service_id")).(string)
|
|
|
|
buildVersion := chi.URLParam(r, "build_version")
|
|
|
|
_, err := db.GetManager().VersionInfoDao().GetVersionByDeployVersion(buildVersion, serviceID)
|
2018-08-03 15:17:10 +08:00
|
|
|
if err != nil && err != gorm.ErrRecordNotFound {
|
2018-06-21 14:35:47 +08:00
|
|
|
httputil.ReturnError(r, w, 500, fmt.Sprintf("get build version status erro, %v", err))
|
|
|
|
return
|
|
|
|
}
|
2018-08-03 15:17:10 +08:00
|
|
|
if err == gorm.ErrRecordNotFound {
|
2018-06-21 14:30:23 +08:00
|
|
|
statusMap["status"] = false
|
2018-08-03 15:17:10 +08:00
|
|
|
} else {
|
2018-06-21 14:30:23 +08:00
|
|
|
statusMap["status"] = true
|
|
|
|
}
|
|
|
|
httputil.ReturnSuccess(r, w, statusMap)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t *TenantStruct) DeleteBuildVersion(w http.ResponseWriter, r *http.Request) {
|
|
|
|
serviceID := r.Context().Value(middleware.ContextKey("service_id")).(string)
|
|
|
|
buildVersion := chi.URLParam(r, "build_version")
|
|
|
|
val, err := db.GetManager().VersionInfoDao().GetVersionByDeployVersion(buildVersion, serviceID)
|
|
|
|
if err != nil && err != gorm.ErrRecordNotFound {
|
|
|
|
httputil.ReturnError(r, w, 500, fmt.Sprintf("delete build version erro, %v", err))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if err == gorm.ErrRecordNotFound {
|
|
|
|
|
|
|
|
} else {
|
|
|
|
if val.DeliveredType == "slug" && val.FinalStatus == "success" {
|
|
|
|
if err := os.Remove(val.DeliveredPath); err != nil {
|
|
|
|
httputil.ReturnError(r, w, 500, fmt.Sprintf("delete build version erro, %v", err))
|
|
|
|
return
|
|
|
|
|
|
|
|
}
|
|
|
|
if err := db.GetManager().VersionInfoDao().DeleteVersionInfo(val); err != nil {
|
|
|
|
httputil.ReturnError(r, w, 500, fmt.Sprintf("delete build version erro, %v", err))
|
|
|
|
return
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if val.DeliveredType == "slug" && val.FinalStatus == "failure" {
|
|
|
|
if err := db.GetManager().VersionInfoDao().DeleteVersionInfo(val); err != nil {
|
|
|
|
httputil.ReturnError(r, w, 500, fmt.Sprintf("delete build version erro, %v", err))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if val.DeliveredType == "image" {
|
|
|
|
if err := db.GetManager().VersionInfoDao().DeleteVersionInfo(val); err != nil {
|
|
|
|
httputil.ReturnError(r, w, 500, fmt.Sprintf("delete build version erro, %v", err))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
httputil.ReturnSuccess(r, w, nil)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t *TenantStruct) BuildVersionInfo(w http.ResponseWriter, r *http.Request) {
|
|
|
|
switch r.Method {
|
|
|
|
case "DELETE":
|
|
|
|
t.DeleteBuildVersion(w, r)
|
|
|
|
case "GET":
|
|
|
|
t.BuildVersionIsExist(w, r)
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2018-08-03 15:17:10 +08:00
|
|
|
//GetDeployVersion GetDeployVersion by service
|
|
|
|
func (t *TenantStruct) GetDeployVersion(w http.ResponseWriter, r *http.Request) {
|
|
|
|
service := r.Context().Value(middleware.ContextKey("service")).(*dbmodel.TenantServices)
|
|
|
|
version, err := db.GetManager().VersionInfoDao().GetVersionByDeployVersion(service.DeployVersion, service.ServiceID)
|
|
|
|
if err != nil && err != gorm.ErrRecordNotFound {
|
|
|
|
httputil.ReturnError(r, w, 500, fmt.Sprintf("get build version status erro, %v", err))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if err == gorm.ErrRecordNotFound {
|
|
|
|
httputil.ReturnError(r, w, 404, fmt.Sprintf("build version do not exist"))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
httputil.ReturnSuccess(r, w, version)
|
|
|
|
}
|
|
|
|
|
|
|
|
//GetManyDeployVersion GetDeployVersion by some service id
|
|
|
|
func (t *TenantStruct) GetManyDeployVersion(w http.ResponseWriter, r *http.Request) {
|
|
|
|
rules := validator.MapData{
|
|
|
|
"service_ids": []string{"required"},
|
|
|
|
}
|
|
|
|
data, ok := httputil.ValidatorRequestMapAndErrorResponse(r, w, rules, nil)
|
|
|
|
if !ok {
|
|
|
|
return
|
|
|
|
}
|
2018-08-03 20:06:23 +08:00
|
|
|
serviceIDs, ok := data["service_ids"].([]interface{})
|
2018-08-03 15:17:10 +08:00
|
|
|
if !ok {
|
|
|
|
httputil.ReturnError(r, w, 400, fmt.Sprintf("service ids must be a array"))
|
|
|
|
return
|
|
|
|
}
|
2018-08-03 20:06:23 +08:00
|
|
|
var list []string
|
|
|
|
for _, s := range serviceIDs {
|
|
|
|
list = append(list, s.(string))
|
|
|
|
}
|
|
|
|
services, err := db.GetManager().TenantServiceDao().GetServiceByIDs(list)
|
2018-08-03 15:17:10 +08:00
|
|
|
if err != nil {
|
|
|
|
httputil.ReturnError(r, w, 500, fmt.Sprintf(err.Error()))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
var versionList []*dbmodel.VersionInfo
|
|
|
|
for _, service := range services {
|
|
|
|
version, err := db.GetManager().VersionInfoDao().GetVersionByDeployVersion(service.DeployVersion, service.ServiceID)
|
|
|
|
if err != nil && err != gorm.ErrRecordNotFound {
|
|
|
|
httputil.ReturnError(r, w, 500, fmt.Sprintf("get build version status erro, %v", err))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
versionList = append(versionList, version)
|
|
|
|
}
|
|
|
|
httputil.ReturnSuccess(r, w, versionList)
|
|
|
|
}
|
|
|
|
|
2017-11-07 11:40:44 +08:00
|
|
|
//DeployService DeployService
|
|
|
|
func (t *TenantStruct) DeployService(w http.ResponseWriter, r *http.Request) {
|
|
|
|
logrus.Debugf("trans deploy service")
|
|
|
|
w.Write([]byte("deploy service"))
|
|
|
|
}
|
|
|
|
|
|
|
|
//UpgradeService UpgradeService
|
2017-11-20 17:29:39 +08:00
|
|
|
// swagger:operation POST /v2/tenants/{tenant_name}/services/{service_alias}/upgrade v2 upgradeService
|
|
|
|
//
|
|
|
|
// 升级应用
|
|
|
|
//
|
2017-11-27 18:01:04 +08:00
|
|
|
// upgrade service
|
2017-11-20 17:29:39 +08:00
|
|
|
//
|
|
|
|
// ---
|
|
|
|
// consumes:
|
|
|
|
// - application/json
|
|
|
|
// - application/x-protobuf
|
|
|
|
//
|
|
|
|
// produces:
|
|
|
|
// - application/json
|
|
|
|
// - application/xml
|
|
|
|
//
|
|
|
|
// responses:
|
|
|
|
// default:
|
|
|
|
// schema:
|
|
|
|
// "$ref": "#/responses/commandResponse"
|
|
|
|
// description: 统一返回格式
|
2017-11-07 11:40:44 +08:00
|
|
|
func (t *TenantStruct) UpgradeService(w http.ResponseWriter, r *http.Request) {
|
|
|
|
rules := validator.MapData{
|
|
|
|
"deploy_version": []string{"required"},
|
|
|
|
}
|
|
|
|
data, ok := httputil.ValidatorRequestMapAndErrorResponse(r, w, rules, nil)
|
|
|
|
if !ok {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
tenantID := r.Context().Value(middleware.ContextKey("tenant_id")).(string)
|
|
|
|
serviceID := r.Context().Value(middleware.ContextKey("service_id")).(string)
|
2017-11-16 16:30:22 +08:00
|
|
|
|
2017-11-19 18:59:41 +08:00
|
|
|
sEvent, status, err := createEvent(getOrNilEventID(data), serviceID, "update", tenantID, data["deploy_version"].(string))
|
|
|
|
handleStatus(status, err, w, r)
|
2018-02-26 11:35:50 +08:00
|
|
|
if status != 0 {
|
|
|
|
return
|
|
|
|
}
|
2017-11-16 16:30:22 +08:00
|
|
|
|
|
|
|
eventID := sEvent.EventID
|
2017-11-07 11:40:44 +08:00
|
|
|
logger := event.GetManager().GetLogger(eventID)
|
|
|
|
defer event.CloseManager()
|
|
|
|
newDeployVersion := data["deploy_version"].(string)
|
|
|
|
//两个deploy version
|
|
|
|
upgradeTask := &model.RollingUpgradeTaskBody{
|
|
|
|
TenantID: tenantID,
|
|
|
|
ServiceID: serviceID,
|
|
|
|
NewDeployVersion: newDeployVersion,
|
|
|
|
EventID: eventID,
|
|
|
|
}
|
|
|
|
if err := handler.GetServiceManager().ServiceUpgrade(upgradeTask); err != nil {
|
|
|
|
logger.Error("应用升级任务发送失败 "+err.Error(), map[string]string{"step": "callback", "status": "failure"})
|
|
|
|
httputil.ReturnError(r, w, 500, fmt.Sprintf("service upgrade error, %v", err))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
logger.Info("应用升级任务发送成功 ", map[string]string{"step": "upgrade-service", "status": "starting"})
|
2017-11-19 18:59:41 +08:00
|
|
|
httputil.ReturnSuccess(r, w, sEvent)
|
2017-11-07 11:40:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
//CheckCode CheckCode
|
2017-11-20 17:29:39 +08:00
|
|
|
// swagger:operation POST /v2/tenants/{tenant_name}/code-check v2 checkCode
|
|
|
|
//
|
|
|
|
// 应用代码检测
|
|
|
|
//
|
2017-11-27 18:01:04 +08:00
|
|
|
// check code
|
2017-11-20 17:29:39 +08:00
|
|
|
//
|
|
|
|
// ---
|
|
|
|
// consumes:
|
|
|
|
// - application/json
|
|
|
|
// - application/x-protobuf
|
|
|
|
//
|
|
|
|
// produces:
|
|
|
|
// - application/json
|
|
|
|
// - application/xml
|
|
|
|
//
|
|
|
|
// responses:
|
|
|
|
// default:
|
|
|
|
// schema:
|
|
|
|
// "$ref": "#/responses/commandResponse"
|
|
|
|
// description: 统一返回格式
|
2017-11-07 11:40:44 +08:00
|
|
|
func (t *TenantStruct) CheckCode(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
|
|
|
var ccs api_model.CheckCodeStruct
|
|
|
|
ok := httputil.ValidatorRequestStructAndErrorResponse(r, w, &ccs.Body, nil)
|
|
|
|
if !ok {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if ccs.Body.TenantID == "" {
|
|
|
|
tenantID := r.Context().Value(middleware.ContextKey("tenant_id")).(string)
|
|
|
|
ccs.Body.TenantID = tenantID
|
|
|
|
}
|
|
|
|
ccs.Body.Action = "code_check"
|
|
|
|
if err := handler.GetServiceManager().CodeCheck(&ccs); err != nil {
|
|
|
|
httputil.ReturnError(r, w, 500, fmt.Sprintf("task code check error,%v", err))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
httputil.ReturnSuccess(r, w, nil)
|
|
|
|
}
|
|
|
|
|
|
|
|
//RollBack RollBack
|
2017-11-20 17:29:39 +08:00
|
|
|
// swagger:operation Post /v2/tenants/{tenant_name}/services/{service_alias}/rollback v2 rollback
|
|
|
|
//
|
|
|
|
// 应用版本回滚
|
|
|
|
//
|
2017-11-27 18:01:04 +08:00
|
|
|
// service rollback
|
2017-11-20 17:29:39 +08:00
|
|
|
//
|
|
|
|
// ---
|
|
|
|
// consumes:
|
|
|
|
// - application/json
|
|
|
|
// - application/x-protobuf
|
|
|
|
//
|
|
|
|
// produces:
|
|
|
|
// - application/json
|
|
|
|
// - application/xml
|
|
|
|
//
|
|
|
|
// responses:
|
|
|
|
// default:
|
|
|
|
// schema:
|
|
|
|
// "$ref": "#/responses/commandResponse"
|
|
|
|
// description: 统一返回格式
|
2017-11-07 11:40:44 +08:00
|
|
|
func (t *TenantStruct) RollBack(w http.ResponseWriter, r *http.Request) {
|
|
|
|
rules := validator.MapData{
|
|
|
|
"deploy_version": []string{"required"},
|
|
|
|
"operator": []string{},
|
|
|
|
}
|
|
|
|
data, ok := httputil.ValidatorRequestMapAndErrorResponse(r, w, rules, nil)
|
|
|
|
if !ok {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
tenantID := r.Context().Value(middleware.ContextKey("tenant_id")).(string)
|
|
|
|
serviceID := r.Context().Value(middleware.ContextKey("service_id")).(string)
|
2017-11-19 18:59:41 +08:00
|
|
|
sEvent, status, err := createEvent(getOrNilEventID(data), serviceID, "rollback", tenantID, data["deploy_version"].(string))
|
|
|
|
handleStatus(status, err, w, r)
|
2018-02-26 11:35:50 +08:00
|
|
|
if status != 0 {
|
|
|
|
return
|
|
|
|
}
|
2017-11-16 16:30:22 +08:00
|
|
|
eventID := sEvent.EventID
|
2017-11-07 11:40:44 +08:00
|
|
|
logger := event.GetManager().GetLogger(eventID)
|
|
|
|
defer event.CloseManager()
|
|
|
|
rs := &api_model.RollbackStruct{
|
2017-11-19 18:59:41 +08:00
|
|
|
TenantID: tenantID,
|
|
|
|
ServiceID: serviceID,
|
|
|
|
EventID: eventID,
|
2017-11-16 16:30:22 +08:00
|
|
|
//todo
|
2017-11-07 11:40:44 +08:00
|
|
|
DeployVersion: data["deploy_version"].(string),
|
|
|
|
}
|
|
|
|
if _, ok := data["operator"]; ok {
|
|
|
|
rs.Operator = data["operator"].(string)
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := handler.GetServiceManager().RollBack(rs); err != nil {
|
|
|
|
logger.Error("应用回滚任务发送失败 "+err.Error(), map[string]string{"step": "callback", "status": "failure"})
|
|
|
|
httputil.ReturnError(r, w, 500, fmt.Sprintf("check deploy version error, %v", err))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
logger.Info("应用回滚任务发送成功 ", map[string]string{"step": "rollback-service", "status": "starting"})
|
2017-11-16 17:04:06 +08:00
|
|
|
httputil.ReturnSuccess(r, w, sEvent)
|
2017-11-07 11:40:44 +08:00
|
|
|
return
|
|
|
|
}
|
2018-10-23 18:11:27 +08:00
|
|
|
|
|
|
|
type limitMemory struct {
|
|
|
|
LimitMemory int `json:"limit_memory"`
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t *TenantStruct) LimitTenantMemory(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
|
|
|
var lm limitMemory
|
|
|
|
body, err := ioutil.ReadAll(r.Body)
|
|
|
|
if err != nil {
|
|
|
|
httputil.ReturnError(r, w, 500, err.Error())
|
|
|
|
return
|
|
|
|
}
|
|
|
|
err = ffjson.Unmarshal(body, &lm)
|
|
|
|
if err != nil {
|
|
|
|
httputil.ReturnError(r, w, 500, err.Error())
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
tenantID := r.Context().Value(middleware.ContextKey("tenant_id")).(string)
|
|
|
|
tenant, err := db.GetManager().TenantDao().GetTenantByUUID(tenantID)
|
|
|
|
if err != nil {
|
|
|
|
httputil.ReturnError(r, w, 400, err.Error())
|
|
|
|
return
|
|
|
|
}
|
|
|
|
tenant.LimitMemory = lm.LimitMemory
|
|
|
|
if err := db.GetManager().TenantDao().UpdateModel(tenant); err != nil {
|
|
|
|
httputil.ReturnError(r, w, 500, err.Error())
|
|
|
|
}
|
|
|
|
httputil.ReturnSuccess(r, w, "success!")
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
type SourcesInfo struct {
|
2018-11-13 13:41:20 +08:00
|
|
|
TenantID string `json:"tenant_id"`
|
2018-10-23 18:11:27 +08:00
|
|
|
AvailableMemory int `json:"available_memory"`
|
|
|
|
Status bool `json:"status"`
|
2018-10-29 18:14:10 +08:00
|
|
|
MemTotal int `json:"mem_total"`
|
|
|
|
MemUsed int `json:"mem_used"`
|
|
|
|
CpuTotal int `json:"cpu_total"`
|
|
|
|
CpuUsed int `json:"cpu_used"`
|
2018-10-23 18:11:27 +08:00
|
|
|
}
|
|
|
|
|
2018-12-07 13:53:43 +08:00
|
|
|
//TenantResourcesStatus tenant resources status
|
2018-10-23 18:11:27 +08:00
|
|
|
func (t *TenantStruct) TenantResourcesStatus(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
|
|
|
tenantID := r.Context().Value(middleware.ContextKey("tenant_id")).(string)
|
|
|
|
tenant, err := db.GetManager().TenantDao().GetTenantByUUID(tenantID)
|
|
|
|
if err != nil {
|
|
|
|
httputil.ReturnError(r, w, 400, err.Error())
|
|
|
|
return
|
|
|
|
}
|
|
|
|
//11ms
|
|
|
|
services, err := handler.GetServiceManager().GetService(tenant.UUID)
|
|
|
|
if err != nil {
|
|
|
|
msg := httputil.ResponseBody{
|
|
|
|
Msg: fmt.Sprintf("get service error, %v", err),
|
|
|
|
}
|
|
|
|
httputil.Return(r, w, 500, msg)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
statsInfo, _ := handler.GetTenantManager().StatsMemCPU(services)
|
|
|
|
|
|
|
|
if tenant.LimitMemory == 0 {
|
|
|
|
sourcesInfo := SourcesInfo{
|
2018-11-13 13:41:20 +08:00
|
|
|
TenantID: tenantID,
|
2018-10-23 18:11:27 +08:00
|
|
|
AvailableMemory: 0,
|
|
|
|
Status: true,
|
2018-10-29 18:14:10 +08:00
|
|
|
MemTotal: tenant.LimitMemory,
|
|
|
|
MemUsed: statsInfo.MEM,
|
|
|
|
CpuTotal: 0,
|
|
|
|
CpuUsed: statsInfo.CPU,
|
2018-10-23 18:11:27 +08:00
|
|
|
}
|
|
|
|
httputil.ReturnSuccess(r, w, sourcesInfo)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if statsInfo.MEM >= tenant.LimitMemory {
|
|
|
|
sourcesInfo := SourcesInfo{
|
2018-11-13 13:41:20 +08:00
|
|
|
TenantID: tenantID,
|
2018-10-23 18:11:27 +08:00
|
|
|
AvailableMemory: tenant.LimitMemory - statsInfo.MEM,
|
|
|
|
Status: false,
|
2018-10-29 18:14:10 +08:00
|
|
|
MemTotal: tenant.LimitMemory,
|
|
|
|
MemUsed: statsInfo.MEM,
|
|
|
|
CpuTotal: tenant.LimitMemory / 4,
|
|
|
|
CpuUsed: statsInfo.CPU,
|
2018-10-23 18:11:27 +08:00
|
|
|
}
|
|
|
|
httputil.ReturnSuccess(r, w, sourcesInfo)
|
|
|
|
} else {
|
|
|
|
sourcesInfo := SourcesInfo{
|
2018-11-13 13:41:20 +08:00
|
|
|
TenantID: tenantID,
|
2018-10-23 18:11:27 +08:00
|
|
|
AvailableMemory: tenant.LimitMemory - statsInfo.MEM,
|
|
|
|
Status: true,
|
2018-10-29 18:14:10 +08:00
|
|
|
MemTotal: tenant.LimitMemory,
|
|
|
|
MemUsed: statsInfo.MEM,
|
|
|
|
CpuTotal: tenant.LimitMemory / 4,
|
|
|
|
CpuUsed: statsInfo.CPU,
|
2018-10-23 18:11:27 +08:00
|
|
|
}
|
|
|
|
httputil.ReturnSuccess(r, w, sourcesInfo)
|
|
|
|
}
|
|
|
|
}
|
2018-12-07 13:53:43 +08:00
|
|
|
|
|
|
|
//GetServiceDeployInfo get service deploy info
|
|
|
|
func GetServiceDeployInfo(w http.ResponseWriter, r *http.Request) {
|
|
|
|
tenantID := r.Context().Value(middleware.ContextKey("tenant_id")).(string)
|
|
|
|
serviceID := r.Context().Value(middleware.ContextKey("service_id")).(string)
|
|
|
|
info, err := handler.GetServiceManager().GetServiceDeployInfo(tenantID, serviceID)
|
|
|
|
if err != nil {
|
|
|
|
err.Handle(r, w)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
httputil.ReturnSuccess(r, w, info)
|
|
|
|
}
|