2020-09-17 15:45:46 +08:00
|
|
|
package handler
|
|
|
|
|
|
|
|
import (
|
2020-09-28 16:43:27 +08:00
|
|
|
"context"
|
2020-09-27 16:27:46 +08:00
|
|
|
"fmt"
|
2020-09-28 16:43:27 +08:00
|
|
|
"strconv"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/goodrain/rainbond/api/client/prometheus"
|
2020-09-17 15:45:46 +08:00
|
|
|
"github.com/goodrain/rainbond/api/model"
|
2020-09-20 01:09:29 +08:00
|
|
|
"github.com/goodrain/rainbond/api/util/bcode"
|
2020-09-17 15:45:46 +08:00
|
|
|
"github.com/goodrain/rainbond/db"
|
|
|
|
dbmodel "github.com/goodrain/rainbond/db/model"
|
2020-09-18 10:31:35 +08:00
|
|
|
"github.com/goodrain/rainbond/util"
|
2020-09-28 16:43:27 +08:00
|
|
|
"github.com/goodrain/rainbond/worker/client"
|
|
|
|
"github.com/goodrain/rainbond/worker/server/pb"
|
2020-09-27 16:27:46 +08:00
|
|
|
"github.com/sirupsen/logrus"
|
2020-09-17 15:45:46 +08:00
|
|
|
)
|
|
|
|
|
2020-09-21 13:58:08 +08:00
|
|
|
// ApplicationAction -
|
2020-09-28 16:43:27 +08:00
|
|
|
type ApplicationAction struct {
|
|
|
|
statusCli *client.AppRuntimeSyncClient
|
|
|
|
promClient prometheus.Interface
|
|
|
|
}
|
2020-09-17 15:45:46 +08:00
|
|
|
|
2020-09-21 13:58:08 +08:00
|
|
|
// ApplicationHandler defines handler methods to TenantApplication.
|
|
|
|
type ApplicationHandler interface {
|
2020-09-17 15:45:46 +08:00
|
|
|
CreateApp(req *model.Application) (*model.Application, error)
|
2020-11-10 16:12:40 +08:00
|
|
|
BatchCreateApp(req *model.CreateAppRequest, tenantID string) ([]model.CreateAppResponse, error)
|
2020-09-19 20:11:52 +08:00
|
|
|
UpdateApp(srcApp *dbmodel.Application, req model.UpdateAppRequest) (*dbmodel.Application, error)
|
2020-09-20 02:07:10 +08:00
|
|
|
ListApps(tenantID, appName string, page, pageSize int) (*model.ListAppResponse, error)
|
2020-09-18 11:26:01 +08:00
|
|
|
GetAppByID(appID string) (*dbmodel.Application, error)
|
2020-10-23 13:53:12 +08:00
|
|
|
BatchBindService(appID string, req model.BindServiceRequest) error
|
2020-09-18 18:08:32 +08:00
|
|
|
DeleteApp(appID string) error
|
2020-09-28 16:43:27 +08:00
|
|
|
|
2020-09-22 15:51:57 +08:00
|
|
|
AddConfigGroup(appID string, req *model.ApplicationConfigGroup) (*model.ApplicationConfigGroupResp, error)
|
2020-09-24 14:30:34 +08:00
|
|
|
UpdateConfigGroup(appID, configGroupName string, req *model.UpdateAppConfigGroupReq) (*model.ApplicationConfigGroupResp, error)
|
2020-09-28 16:43:27 +08:00
|
|
|
|
2020-09-30 11:03:14 +08:00
|
|
|
BatchUpdateComponentPorts(appID string, ports []*model.AppPort) error
|
2020-09-28 16:43:27 +08:00
|
|
|
GetStatus(appID string) (*model.AppStatus, error)
|
2020-10-09 09:12:34 +08:00
|
|
|
|
2020-09-24 14:30:34 +08:00
|
|
|
DeleteConfigGroup(appID, configGroupName string) error
|
|
|
|
ListConfigGroups(appID string, page, pageSize int) (*model.ListApplicationConfigGroupResp, error)
|
2020-09-17 15:45:46 +08:00
|
|
|
}
|
|
|
|
|
2020-09-21 13:58:08 +08:00
|
|
|
// NewApplicationHandler creates a new Tenant Application Handler.
|
2020-09-28 16:43:27 +08:00
|
|
|
func NewApplicationHandler(statusCli *client.AppRuntimeSyncClient, promClient prometheus.Interface) ApplicationHandler {
|
|
|
|
return &ApplicationAction{
|
|
|
|
statusCli: statusCli,
|
|
|
|
promClient: promClient,
|
|
|
|
}
|
2020-09-17 15:45:46 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// CreateApp -
|
2020-09-21 13:58:08 +08:00
|
|
|
func (a *ApplicationAction) CreateApp(req *model.Application) (*model.Application, error) {
|
2020-09-17 15:45:46 +08:00
|
|
|
appReq := &dbmodel.Application{
|
|
|
|
AppName: req.AppName,
|
2020-09-18 10:31:35 +08:00
|
|
|
AppID: util.NewUUID(),
|
2020-09-17 15:45:46 +08:00
|
|
|
TenantID: req.TenantID,
|
|
|
|
}
|
2020-09-18 14:05:48 +08:00
|
|
|
req.AppID = appReq.AppID
|
2020-10-23 13:53:12 +08:00
|
|
|
|
|
|
|
tx := db.GetManager().Begin()
|
|
|
|
defer func() {
|
|
|
|
if r := recover(); r != nil {
|
|
|
|
logrus.Errorf("Unexpected panic occurred, rollback transaction: %v", r)
|
|
|
|
tx.Rollback()
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
2020-09-23 15:30:31 +08:00
|
|
|
if err := db.GetManager().ApplicationDao().AddModel(appReq); err != nil {
|
2020-10-23 13:53:12 +08:00
|
|
|
tx.Rollback()
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if len(req.ServiceIDs) != 0 {
|
|
|
|
if err := db.GetManager().TenantServiceDao().BindAppByServiceIDs(appReq.AppID, req.ServiceIDs); err != nil {
|
|
|
|
tx.Rollback()
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := tx.Commit().Error; err != nil {
|
|
|
|
tx.Rollback()
|
2020-09-17 15:45:46 +08:00
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return req, nil
|
|
|
|
}
|
2020-09-17 16:43:53 +08:00
|
|
|
|
2020-11-10 16:12:40 +08:00
|
|
|
// BatchCreateApp -
|
|
|
|
func (a *ApplicationAction) BatchCreateApp(apps *model.CreateAppRequest, tenantID string) ([]model.CreateAppResponse, error) {
|
|
|
|
var (
|
|
|
|
resp model.CreateAppResponse
|
|
|
|
respList []model.CreateAppResponse
|
|
|
|
)
|
|
|
|
for _, app := range apps.AppsInfo {
|
|
|
|
app.TenantID = tenantID
|
|
|
|
regionApp, err := GetApplicationHandler().CreateApp(&app)
|
|
|
|
if err != nil {
|
|
|
|
logrus.Errorf("Batch Create App [%v] error is [%v] ", app.AppName, err)
|
2020-11-10 16:47:44 +08:00
|
|
|
continue
|
2020-11-10 16:12:40 +08:00
|
|
|
}
|
|
|
|
resp.AppID = app.ConsoleAppID
|
|
|
|
resp.RegionAppID = regionApp.AppID
|
|
|
|
respList = append(respList, resp)
|
|
|
|
}
|
|
|
|
return respList, nil
|
|
|
|
}
|
|
|
|
|
2020-09-18 11:39:05 +08:00
|
|
|
// UpdateApp -
|
2020-09-21 13:58:08 +08:00
|
|
|
func (a *ApplicationAction) UpdateApp(srcApp *dbmodel.Application, req model.UpdateAppRequest) (*dbmodel.Application, error) {
|
2020-11-07 10:11:33 +08:00
|
|
|
if req.AppName != "" {
|
|
|
|
srcApp.AppName = req.AppName
|
|
|
|
}
|
|
|
|
if req.GovernanceMode != "" {
|
|
|
|
if !dbmodel.IsGovernanceModeValid(req.GovernanceMode) {
|
|
|
|
return nil, bcode.NewBadRequest(fmt.Sprintf("governance mode '%s' is valid", req.GovernanceMode))
|
|
|
|
}
|
|
|
|
srcApp.GovernanceMode = req.GovernanceMode
|
|
|
|
}
|
2020-09-23 15:30:31 +08:00
|
|
|
if err := db.GetManager().ApplicationDao().UpdateModel(srcApp); err != nil {
|
2020-09-18 11:39:05 +08:00
|
|
|
return nil, err
|
|
|
|
}
|
2020-09-19 20:11:52 +08:00
|
|
|
return srcApp, nil
|
2020-09-18 11:39:05 +08:00
|
|
|
}
|
|
|
|
|
2020-09-17 16:43:53 +08:00
|
|
|
// ListApps -
|
2020-09-21 13:58:08 +08:00
|
|
|
func (a *ApplicationAction) ListApps(tenantID, appName string, page, pageSize int) (*model.ListAppResponse, error) {
|
2020-09-19 21:17:40 +08:00
|
|
|
var resp model.ListAppResponse
|
2020-09-23 15:30:31 +08:00
|
|
|
apps, total, err := db.GetManager().ApplicationDao().ListApps(tenantID, appName, page, pageSize)
|
2020-09-19 21:17:40 +08:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
2020-09-17 16:43:53 +08:00
|
|
|
}
|
2020-09-19 21:17:40 +08:00
|
|
|
if apps != nil {
|
|
|
|
resp.Apps = apps
|
|
|
|
} else {
|
|
|
|
resp.Apps = make([]*dbmodel.Application, 0)
|
|
|
|
}
|
|
|
|
|
|
|
|
resp.Page = page
|
|
|
|
resp.Total = total
|
|
|
|
resp.PageSize = pageSize
|
|
|
|
return &resp, nil
|
2020-09-17 16:43:53 +08:00
|
|
|
}
|
2020-09-18 11:26:01 +08:00
|
|
|
|
|
|
|
// GetAppByID -
|
2020-09-21 13:58:08 +08:00
|
|
|
func (a *ApplicationAction) GetAppByID(appID string) (*dbmodel.Application, error) {
|
2020-09-23 15:30:31 +08:00
|
|
|
app, err := db.GetManager().ApplicationDao().GetAppByID(appID)
|
2020-09-18 11:26:01 +08:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return app, nil
|
|
|
|
}
|
2020-09-18 18:08:32 +08:00
|
|
|
|
|
|
|
// DeleteApp -
|
2020-09-21 13:58:08 +08:00
|
|
|
func (a *ApplicationAction) DeleteApp(appID string) error {
|
2020-09-19 22:06:53 +08:00
|
|
|
// Get the number of services under the application
|
|
|
|
total, err := db.GetManager().TenantServiceDao().CountServiceByAppID(appID)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if total != 0 {
|
2020-09-20 01:09:29 +08:00
|
|
|
return bcode.ErrDeleteDueToBindService
|
2020-09-19 22:06:53 +08:00
|
|
|
}
|
2020-09-23 15:30:31 +08:00
|
|
|
return db.GetManager().ApplicationDao().DeleteApp(appID)
|
2020-09-18 18:08:32 +08:00
|
|
|
}
|
2020-10-08 14:01:37 +08:00
|
|
|
|
2020-09-30 11:03:14 +08:00
|
|
|
// BatchUpdateComponentPorts -
|
|
|
|
func (a *ApplicationAction) BatchUpdateComponentPorts(appID string, ports []*model.AppPort) error {
|
2020-09-27 16:27:46 +08:00
|
|
|
if err := a.checkPorts(appID, ports); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
tx := db.GetManager().Begin()
|
|
|
|
defer func() {
|
|
|
|
if r := recover(); r != nil {
|
|
|
|
logrus.Errorf("Unexpected panic occurred, rollback transaction: %v", r)
|
|
|
|
tx.Rollback()
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
|
|
|
// update port
|
|
|
|
for _, p := range ports {
|
|
|
|
port, err := db.GetManager().TenantServicesPortDaoTransactions(tx).GetPort(p.ServiceID, p.ContainerPort)
|
|
|
|
if err != nil {
|
|
|
|
tx.Rollback()
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
port.PortAlias = p.PortAlias
|
|
|
|
port.K8sServiceName = p.K8sServiceName
|
|
|
|
err = db.GetManager().TenantServicesPortDaoTransactions(tx).UpdateModel(port)
|
|
|
|
if err != nil {
|
|
|
|
tx.Rollback()
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := tx.Commit().Error; err != nil {
|
|
|
|
tx.Rollback()
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (a *ApplicationAction) checkPorts(appID string, ports []*model.AppPort) error {
|
|
|
|
// check if the ports are belong to the given appID
|
|
|
|
services, err := db.GetManager().TenantServiceDao().ListByAppID(appID)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
set := make(map[string]struct{})
|
|
|
|
for _, svc := range services {
|
|
|
|
set[svc.ServiceID] = struct{}{}
|
|
|
|
}
|
|
|
|
var k8sServiceNames []string
|
|
|
|
key2ports := make(map[string]*model.AppPort)
|
|
|
|
for i := range ports {
|
|
|
|
port := ports[i]
|
|
|
|
if _, ok := set[port.ServiceID]; !ok {
|
|
|
|
return bcode.NewBadRequest(fmt.Sprintf("port(%s) is not belong to app(%s)", port.ServiceID, appID))
|
|
|
|
}
|
|
|
|
k8sServiceNames = append(k8sServiceNames, port.ServiceID)
|
|
|
|
key2ports[port.ServiceID+strconv.Itoa(port.ContainerPort)] = port
|
|
|
|
}
|
|
|
|
|
|
|
|
// check if k8s_service_name is unique
|
|
|
|
servicesPorts, err := db.GetManager().TenantServicesPortDao().ListByK8sServiceNames(k8sServiceNames)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
for _, port := range servicesPorts {
|
|
|
|
// check if the port is as same as the one in request
|
|
|
|
if _, ok := key2ports[port.ServiceID+strconv.Itoa(port.ContainerPort)]; !ok {
|
|
|
|
logrus.Errorf("kubernetes service name(%s) already exists", port.K8sServiceName)
|
|
|
|
return bcode.ErrK8sServiceNameExists
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
2020-09-28 16:43:27 +08:00
|
|
|
|
2020-09-30 11:03:14 +08:00
|
|
|
// GetStatus -
|
2020-09-28 16:43:27 +08:00
|
|
|
func (a *ApplicationAction) GetStatus(appID string) (*model.AppStatus, error) {
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
|
|
|
defer cancel()
|
|
|
|
|
|
|
|
status, err := a.statusCli.GetAppStatus(ctx, &pb.AppStatusReq{
|
|
|
|
AppId: appID,
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
diskUsage := a.getDiskUsage(appID)
|
|
|
|
|
|
|
|
res := &model.AppStatus{
|
|
|
|
Status: status.Status.String(),
|
|
|
|
Cpu: status.Cpu,
|
|
|
|
Memory: status.Memory,
|
|
|
|
Disk: int64(diskUsage),
|
|
|
|
}
|
|
|
|
return res, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (a *ApplicationAction) getDiskUsage(appID string) float64 {
|
|
|
|
var result float64
|
2020-09-30 11:03:14 +08:00
|
|
|
query := fmt.Sprintf(`sum(max(app_resource_appfs{app_id=~"%s"}) by(app_id))`, appID)
|
2020-09-28 16:43:27 +08:00
|
|
|
metric := a.promClient.GetMetric(query, time.Now())
|
|
|
|
for _, m := range metric.MetricData.MetricValues {
|
|
|
|
result += m.Sample.Value()
|
|
|
|
}
|
|
|
|
return result
|
|
|
|
}
|
2020-10-09 09:12:34 +08:00
|
|
|
|
2020-11-07 10:11:33 +08:00
|
|
|
// BatchBindService -
|
2020-10-23 13:53:12 +08:00
|
|
|
func (a *ApplicationAction) BatchBindService(appID string, req model.BindServiceRequest) error {
|
2020-11-09 15:48:35 +08:00
|
|
|
for _, sid := range req.ServiceIDs {
|
2020-10-23 14:17:30 +08:00
|
|
|
if _, err := db.GetManager().TenantServiceDao().GetServiceByID(sid); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
2020-10-23 13:53:12 +08:00
|
|
|
if err := db.GetManager().TenantServiceDao().BindAppByServiceIDs(appID, req.ServiceIDs); err != nil {
|
2020-10-08 14:01:37 +08:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
return nil
|
2020-10-09 09:15:21 +08:00
|
|
|
}
|