mirror of
https://gitee.com/rainbond/Rainbond.git
synced 2024-11-29 18:27:58 +08:00
[ADD] add plugin share code (#74)
This commit is contained in:
parent
1e5f063f98
commit
6d810cd810
@ -114,6 +114,8 @@ type PluginInterface interface {
|
||||
GePluginEnvWhichCanBeSet(w http.ResponseWriter, r *http.Request)
|
||||
UpdateVersionEnv(w http.ResponseWriter, r *http.Request)
|
||||
GetPluginDefaultEnvs(w http.ResponseWriter, r *http.Request)
|
||||
SharePlugin(w http.ResponseWriter, r *http.Request)
|
||||
SharePluginResult(w http.ResponseWriter, r *http.Request)
|
||||
}
|
||||
|
||||
//RulesInterface RulesInterface
|
||||
|
@ -78,6 +78,8 @@ func (v2 *V2) tenantNameRouter() chi.Router {
|
||||
//创建应用
|
||||
r.Post("/services", controller.GetManager().CreateService)
|
||||
r.Post("/plugin", controller.GetManager().PluginAction)
|
||||
r.Post("/plugins/{plugin_id}/share", controller.GetManager().SharePlugin)
|
||||
r.Post("/plugins/{plugin_id}/share/{share_id}", controller.GetManager().SharePluginResult)
|
||||
r.Get("/plugin", controller.GetManager().PluginAction)
|
||||
r.Post("/services_status", controller.GetManager().StatusServiceList)
|
||||
r.Mount("/services/{service_alias}", v2.serviceRouter())
|
||||
|
@ -21,10 +21,12 @@ package controller
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/goodrain/rainbond/api/handler"
|
||||
"github.com/goodrain/rainbond/api/middleware"
|
||||
"github.com/goodrain/rainbond/api/handler/share"
|
||||
|
||||
"github.com/go-chi/chi"
|
||||
"github.com/goodrain/rainbond/api/handler"
|
||||
"github.com/goodrain/rainbond/api/middleware"
|
||||
"github.com/goodrain/rainbond/util"
|
||||
|
||||
api_model "github.com/goodrain/rainbond/api/model"
|
||||
httputil "github.com/goodrain/rainbond/util/http"
|
||||
@ -611,3 +613,35 @@ func (t *TenantStruct) UpdateVersionEnv(w http.ResponseWriter, r *http.Request)
|
||||
}
|
||||
httputil.ReturnSuccess(r, w, nil)
|
||||
}
|
||||
|
||||
//SharePlugin share tenants plugin
|
||||
func (t *TenantStruct) SharePlugin(w http.ResponseWriter, r *http.Request) {
|
||||
var sp share.PluginShare
|
||||
ok := httputil.ValidatorRequestStructAndErrorResponse(r, w, &sp.Body, nil)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
tenantID := r.Context().Value(middleware.ContextKey("tenant_id")).(string)
|
||||
sp.TenantID = tenantID
|
||||
sp.PluginID = chi.URLParam(r, "plugin_id")
|
||||
if sp.Body.EventID == "" {
|
||||
sp.Body.EventID = util.NewUUID()
|
||||
}
|
||||
res, errS := handler.GetPluginShareHandle().Share(sp)
|
||||
if errS != nil {
|
||||
errS.Handle(r, w)
|
||||
return
|
||||
}
|
||||
httputil.ReturnSuccess(r, w, res)
|
||||
}
|
||||
|
||||
//SharePluginResult SharePluginResult
|
||||
func (t *TenantStruct) SharePluginResult(w http.ResponseWriter, r *http.Request) {
|
||||
shareID := chi.URLParam(r, "share_id")
|
||||
res, errS := handler.GetPluginShareHandle().ShareResult(shareID)
|
||||
if errS != nil {
|
||||
errS.Handle(r, w)
|
||||
return
|
||||
}
|
||||
httputil.ReturnSuccess(r, w, res)
|
||||
}
|
||||
|
@ -70,6 +70,7 @@ func InitHandle(conf option.Config, statusCli *client.AppRuntimeSyncClient) erro
|
||||
//需要使用etcd v2 API
|
||||
defaultEventHandler = CreateLogManager(conf.EtcdEndpoint)
|
||||
shareHandler = &share.ServiceShareHandle{MQClient: mqClient, EtcdCli: etcdCli}
|
||||
pluginShareHandler = &share.PluginShareHandle{MQClient: mqClient, EtcdCli: etcdCli}
|
||||
if err := CreateTokenIdenHandler(conf); err != nil {
|
||||
logrus.Errorf("create token identification mannager error, %v", err)
|
||||
return err
|
||||
@ -79,12 +80,18 @@ func InitHandle(conf option.Config, statusCli *client.AppRuntimeSyncClient) erro
|
||||
|
||||
var defaultServieHandler ServiceHandler
|
||||
var shareHandler *share.ServiceShareHandle
|
||||
var pluginShareHandler *share.PluginShareHandle
|
||||
|
||||
//GetShareHandle get share handle
|
||||
func GetShareHandle() *share.ServiceShareHandle {
|
||||
return shareHandler
|
||||
}
|
||||
|
||||
//GetPluginShareHandle get plugin share handle
|
||||
func GetPluginShareHandle() *share.PluginShareHandle {
|
||||
return pluginShareHandler
|
||||
}
|
||||
|
||||
//GetServiceManager get manager
|
||||
func GetServiceManager() ServiceHandler {
|
||||
return defaultServieHandler
|
||||
|
@ -20,14 +20,10 @@ package handler
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/md5"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/jinzhu/gorm"
|
||||
|
||||
api_db "github.com/goodrain/rainbond/api/db"
|
||||
api_model "github.com/goodrain/rainbond/api/model"
|
||||
"github.com/goodrain/rainbond/api/util"
|
||||
@ -35,6 +31,7 @@ import (
|
||||
dbmodel "github.com/goodrain/rainbond/db/model"
|
||||
"github.com/goodrain/rainbond/event"
|
||||
"github.com/goodrain/rainbond/mq/api/grpc/pb"
|
||||
core_util "github.com/goodrain/rainbond/util"
|
||||
|
||||
"github.com/pquerna/ffjson/ffjson"
|
||||
|
||||
@ -217,23 +214,9 @@ func (p *PluginAction) BuildPluginManual(bps *api_model.BuildPluginStruct) (*dbm
|
||||
if err != nil {
|
||||
return nil, util.CreateAPIHandleErrorFromDBError(fmt.Sprintf("get plugin by %v", bps.PluginID), err)
|
||||
}
|
||||
if bps.Body.PluginFrom != "" {
|
||||
switch bps.Body.PluginFrom {
|
||||
case "yb":
|
||||
pbv, err := p.InstallPluginFromYB(bps, plugin)
|
||||
if err != nil {
|
||||
logrus.Debugf("install plugin from yb error %s", err.Error())
|
||||
return nil, util.CreateAPIHandleError(500, fmt.Errorf("install plugin from yb error"))
|
||||
}
|
||||
return pbv, nil
|
||||
case "ys":
|
||||
default:
|
||||
return nil, util.CreateAPIHandleError(400, fmt.Errorf("unexpect plugin from"))
|
||||
}
|
||||
}
|
||||
switch plugin.BuildModel {
|
||||
case "image":
|
||||
pbv, err := p.ImageBuildPlugin(bps, plugin)
|
||||
pbv, err := p.buildPlugin(bps, plugin)
|
||||
if err != nil {
|
||||
logrus.Error("build plugin from image error ", err.Error())
|
||||
logger.Error("从镜像构建插件任务发送失败 "+err.Error(), map[string]string{"step": "callback", "status": "failure"})
|
||||
@ -242,7 +225,7 @@ func (p *PluginAction) BuildPluginManual(bps *api_model.BuildPluginStruct) (*dbm
|
||||
logger.Info("从镜像构建插件任务发送成功 ", map[string]string{"step": "image-plugin", "status": "starting"})
|
||||
return pbv, nil
|
||||
case "dockerfile":
|
||||
pbv, err := p.DockerfileBuildPlugin(bps, plugin)
|
||||
pbv, err := p.buildPlugin(bps, plugin)
|
||||
if err != nil {
|
||||
logrus.Error("build plugin from image error ", err.Error())
|
||||
logger.Error("从dockerfile构建插件任务发送失败 "+err.Error(), map[string]string{"step": "callback", "status": "failure"})
|
||||
@ -255,42 +238,8 @@ func (p *PluginAction) BuildPluginManual(bps *api_model.BuildPluginStruct) (*dbm
|
||||
}
|
||||
}
|
||||
|
||||
func createVersionID(s []byte) string {
|
||||
h := md5.New()
|
||||
h.Write(s)
|
||||
return hex.EncodeToString(h.Sum(nil))
|
||||
}
|
||||
|
||||
//InstallPluginFromYB InstallPluginFromYB
|
||||
func (p *PluginAction) InstallPluginFromYB(b *api_model.BuildPluginStruct, plugin *dbmodel.TenantPlugin) (
|
||||
*dbmodel.TenantPluginBuildVersion, error) {
|
||||
if b.Body.Operator == "" {
|
||||
b.Body.Operator = "define"
|
||||
}
|
||||
pbv := &dbmodel.TenantPluginBuildVersion{
|
||||
VersionID: b.Body.BuildVersion,
|
||||
PluginID: b.PluginID,
|
||||
Kind: plugin.BuildModel,
|
||||
BaseImage: plugin.ImageURL,
|
||||
BuildLocalImage: b.Body.BuildImage,
|
||||
ContainerCPU: b.Body.PluginCPU,
|
||||
ContainerMemory: b.Body.PluginMemory,
|
||||
ContainerCMD: b.Body.PluginCMD,
|
||||
BuildTime: time.Now().Format(time.RFC3339),
|
||||
Info: b.Body.Info,
|
||||
Status: "complete",
|
||||
}
|
||||
if err := db.GetManager().TenantPluginBuildVersionDao().AddModel(pbv); err != nil {
|
||||
if !strings.Contains(err.Error(), "exist") {
|
||||
logrus.Errorf("build plugin error: %s", err.Error())
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return pbv, nil
|
||||
}
|
||||
|
||||
//ImageBuildPlugin ImageBuildPlugin
|
||||
func (p *PluginAction) ImageBuildPlugin(b *api_model.BuildPluginStruct, plugin *dbmodel.TenantPlugin) (
|
||||
//buildPlugin buildPlugin
|
||||
func (p *PluginAction) buildPlugin(b *api_model.BuildPluginStruct, plugin *dbmodel.TenantPlugin) (
|
||||
*dbmodel.TenantPluginBuildVersion, error) {
|
||||
if plugin.ImageURL == "" {
|
||||
return nil, fmt.Errorf("need image url")
|
||||
@ -298,66 +247,42 @@ func (p *PluginAction) ImageBuildPlugin(b *api_model.BuildPluginStruct, plugin *
|
||||
if b.Body.Operator == "" {
|
||||
b.Body.Operator = "define"
|
||||
}
|
||||
//TODO: build_version create in console
|
||||
//diffStr := fmt.Sprintf("%s%s%s%s", b.TenantName, plugin.ImageURL, b.PluginID, time.Now().Format(time.RFC3339))
|
||||
//buildVersion := createVersionID([]byte(diffStr))
|
||||
rebuild := false
|
||||
tpbv, err := db.GetManager().TenantPluginBuildVersionDao().GetBuildVersionByVersionID(
|
||||
b.PluginID, b.Body.BuildVersion)
|
||||
if err != nil {
|
||||
if err.Error() == gorm.ErrRecordNotFound.Error() {
|
||||
rebuild = false
|
||||
} else {
|
||||
if b.Body.BuildVersion == "" {
|
||||
return nil, fmt.Errorf("build version can not be empty")
|
||||
}
|
||||
if b.Body.DeployVersion == "" {
|
||||
b.Body.DeployVersion = core_util.CreateVersionByTime()
|
||||
}
|
||||
pbv := &dbmodel.TenantPluginBuildVersion{
|
||||
VersionID: b.Body.BuildVersion,
|
||||
DeployVersion: b.Body.DeployVersion,
|
||||
PluginID: b.PluginID,
|
||||
Kind: plugin.BuildModel,
|
||||
Repo: b.Body.RepoURL,
|
||||
GitURL: plugin.GitURL,
|
||||
BaseImage: plugin.ImageURL,
|
||||
ContainerCPU: b.Body.PluginCPU,
|
||||
ContainerMemory: b.Body.PluginMemory,
|
||||
ContainerCMD: b.Body.PluginCMD,
|
||||
BuildTime: time.Now().Format(time.RFC3339),
|
||||
Info: b.Body.Info,
|
||||
Status: "building",
|
||||
}
|
||||
if b.Body.PluginCPU == 0 {
|
||||
pbv.ContainerCPU = 125
|
||||
}
|
||||
if b.Body.PluginMemory == 0 {
|
||||
pbv.ContainerMemory = 50
|
||||
}
|
||||
if err := db.GetManager().TenantPluginBuildVersionDao().AddModel(pbv); err != nil {
|
||||
if !strings.Contains(err.Error(), "exist") {
|
||||
logrus.Errorf("build plugin error: %s", err.Error())
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
rebuild = true
|
||||
}
|
||||
tx := db.GetManager().Begin()
|
||||
if rebuild {
|
||||
tpbv.Info = b.Body.Info
|
||||
tpbv.Status = "building"
|
||||
tpbv.BuildTime = time.Now().Format(time.RFC3339)
|
||||
if b.Body.PluginCPU == 0 {
|
||||
tpbv.ContainerCPU = 125
|
||||
}
|
||||
if b.Body.PluginMemory == 0 {
|
||||
tpbv.ContainerMemory = 50
|
||||
}
|
||||
if err := db.GetManager().TenantPluginBuildVersionDaoTransactions(tx).UpdateModel(tpbv); err != nil {
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
logrus.Errorf("build plugin error: %s", err.Error())
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
pbv := &dbmodel.TenantPluginBuildVersion{
|
||||
VersionID: b.Body.BuildVersion,
|
||||
PluginID: b.PluginID,
|
||||
Kind: plugin.BuildModel,
|
||||
BaseImage: plugin.ImageURL,
|
||||
ContainerCPU: b.Body.PluginCPU,
|
||||
ContainerMemory: b.Body.PluginMemory,
|
||||
ContainerCMD: b.Body.PluginCMD,
|
||||
BuildTime: time.Now().Format(time.RFC3339),
|
||||
Info: b.Body.Info,
|
||||
Status: "building",
|
||||
}
|
||||
if b.Body.PluginCPU == 0 {
|
||||
pbv.ContainerCPU = 125
|
||||
}
|
||||
if b.Body.PluginMemory == 0 {
|
||||
pbv.ContainerMemory = 50
|
||||
}
|
||||
if err := db.GetManager().TenantPluginBuildVersionDaoTransactions(tx).AddModel(pbv); err != nil {
|
||||
if !strings.Contains(err.Error(), "exist") {
|
||||
tx.Rollback()
|
||||
logrus.Errorf("build plugin error: %s", err.Error())
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
tpbv = pbv
|
||||
var updateVersion = func() {
|
||||
pbv.Status = "failure"
|
||||
db.GetManager().TenantPluginBuildVersionDao().UpdateModel(pbv)
|
||||
}
|
||||
taskBody := &builder_model.BuildPluginTaskBody{
|
||||
TenantID: b.Body.TenantID,
|
||||
@ -371,161 +296,41 @@ func (p *PluginAction) ImageBuildPlugin(b *api_model.BuildPluginStruct, plugin *
|
||||
PluginCPU: b.Body.PluginCPU,
|
||||
PluginMemory: b.Body.PluginMemory,
|
||||
VersionID: b.Body.BuildVersion,
|
||||
ImageInfo: b.Body.ImageInfo,
|
||||
Repo: b.Body.RepoURL,
|
||||
GitURL: plugin.GitURL,
|
||||
}
|
||||
jtask, errJ := ffjson.Marshal(taskBody)
|
||||
if errJ != nil {
|
||||
tx.Rollback()
|
||||
logrus.Debugf("unmarshall jtask error, %v", errJ)
|
||||
updateVersion()
|
||||
return nil, errJ
|
||||
}
|
||||
taskType := "plugin_image_build"
|
||||
if plugin.BuildModel == "dockerfile" {
|
||||
taskType = "plugin_dockerfile_build"
|
||||
}
|
||||
ts := &api_db.BuildTaskStruct{
|
||||
TaskType: "plugin_image_build",
|
||||
TaskType: taskType,
|
||||
TaskBody: jtask,
|
||||
User: b.Body.Operator,
|
||||
}
|
||||
eq, err := api_db.BuildTaskBuild(ts)
|
||||
if err != nil {
|
||||
logrus.Errorf("build equeue build plugin from image error, %v", err)
|
||||
tx.Rollback()
|
||||
updateVersion()
|
||||
return nil, err
|
||||
}
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
_, err = p.MQClient.Enqueue(ctx, eq)
|
||||
cancel()
|
||||
if err != nil {
|
||||
updateVersion()
|
||||
logrus.Errorf("equque mq error, %v", err)
|
||||
tx.Rollback()
|
||||
return nil, err
|
||||
}
|
||||
if err := tx.Commit().Error; err != nil {
|
||||
tx.Rollback()
|
||||
logrus.Debugf("commit mysql error, %v", err)
|
||||
return nil, nil
|
||||
}
|
||||
logrus.Debugf("equeue mq build plugin from image success")
|
||||
return tpbv, nil
|
||||
}
|
||||
|
||||
//DockerfileBuildPlugin DockerfileBuildPlugin
|
||||
func (p *PluginAction) DockerfileBuildPlugin(b *api_model.BuildPluginStruct, plugin *dbmodel.TenantPlugin) (
|
||||
*dbmodel.TenantPluginBuildVersion, error) {
|
||||
if plugin.GitURL == "" {
|
||||
return nil, fmt.Errorf("need git url")
|
||||
}
|
||||
if b.Body.RepoURL == "" {
|
||||
b.Body.RepoURL = "master"
|
||||
}
|
||||
if b.Body.Operator == "" {
|
||||
b.Body.Operator = "define"
|
||||
}
|
||||
// TODO: build_version create in console
|
||||
// diffStr := fmt.Sprintf("%s%s%s%s", b.TenantName, b.Body.RepoURL, b.PluginID, time.Now().Format(time.RFC3339))
|
||||
// buildVersion := createVersionID([]byte(diffStr))
|
||||
rebuild := false
|
||||
tpbv, err := db.GetManager().TenantPluginBuildVersionDao().GetBuildVersionByVersionID(
|
||||
b.PluginID, b.Body.BuildVersion)
|
||||
if err != nil {
|
||||
if err.Error() == gorm.ErrRecordNotFound.Error() {
|
||||
rebuild = false
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
rebuild = true
|
||||
}
|
||||
tx := db.GetManager().Begin()
|
||||
if rebuild {
|
||||
tpbv.Info = b.Body.Info
|
||||
tpbv.Status = "building"
|
||||
tpbv.BuildTime = time.Now().Format(time.RFC3339)
|
||||
if b.Body.PluginCPU == 0 {
|
||||
tpbv.ContainerCPU = 125
|
||||
}
|
||||
if b.Body.PluginMemory == 0 {
|
||||
tpbv.ContainerMemory = 50
|
||||
}
|
||||
if err := db.GetManager().TenantPluginBuildVersionDaoTransactions(tx).UpdateModel(tpbv); err != nil {
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
logrus.Errorf("build plugin error: %s", err.Error())
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
pbv := &dbmodel.TenantPluginBuildVersion{
|
||||
VersionID: b.Body.BuildVersion,
|
||||
PluginID: b.PluginID,
|
||||
Kind: plugin.BuildModel,
|
||||
Repo: b.Body.RepoURL,
|
||||
GitURL: plugin.GitURL,
|
||||
Info: b.Body.Info,
|
||||
ContainerCPU: b.Body.PluginCPU,
|
||||
ContainerMemory: b.Body.PluginMemory,
|
||||
ContainerCMD: b.Body.PluginCMD,
|
||||
BuildTime: time.Now().Format(time.RFC3339),
|
||||
Status: "building",
|
||||
}
|
||||
if b.Body.PluginCPU == 0 {
|
||||
pbv.ContainerCPU = 125
|
||||
}
|
||||
if b.Body.PluginMemory == 0 {
|
||||
pbv.ContainerMemory = 50
|
||||
}
|
||||
if err := db.GetManager().TenantPluginBuildVersionDaoTransactions(tx).AddModel(pbv); err != nil {
|
||||
if !strings.Contains(err.Error(), "exist") {
|
||||
tx.Rollback()
|
||||
logrus.Errorf("build plugin error: %s", err.Error())
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
tpbv = pbv
|
||||
}
|
||||
taskBody := &builder_model.BuildPluginTaskBody{
|
||||
TenantID: b.Body.TenantID,
|
||||
PluginID: b.PluginID,
|
||||
Operator: b.Body.Operator,
|
||||
EventID: b.Body.EventID,
|
||||
Repo: b.Body.RepoURL,
|
||||
GitURL: plugin.GitURL,
|
||||
Kind: plugin.BuildModel,
|
||||
VersionID: b.Body.BuildVersion,
|
||||
DeployVersion: b.Body.BuildVersion,
|
||||
PluginCMD: b.Body.PluginCMD,
|
||||
PluginCPU: b.Body.PluginCPU,
|
||||
PluginMemory: b.Body.PluginMemory,
|
||||
}
|
||||
jtask, errJ := ffjson.Marshal(taskBody)
|
||||
if errJ != nil {
|
||||
tx.Rollback()
|
||||
logrus.Debugf("unmarshall jtask error, %v", errJ)
|
||||
return nil, errJ
|
||||
}
|
||||
ts := &api_db.BuildTaskStruct{
|
||||
TaskType: "plugin_dockerfile_build",
|
||||
TaskBody: jtask,
|
||||
User: b.Body.Operator,
|
||||
}
|
||||
eq, err := api_db.BuildTaskBuild(ts)
|
||||
if err != nil {
|
||||
logrus.Errorf("build equeue build plugin from dockerfile error, %v", err)
|
||||
tx.Rollback()
|
||||
return nil, err
|
||||
}
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
_, errE := p.MQClient.Enqueue(ctx, eq)
|
||||
cancel()
|
||||
if errE != nil {
|
||||
logrus.Errorf("equque mq error, %v", err)
|
||||
tx.Rollback()
|
||||
return nil, err
|
||||
}
|
||||
if err := tx.Commit().Error; err != nil {
|
||||
tx.Rollback()
|
||||
logrus.Debugf("commit mysql error, %v", err)
|
||||
return nil, nil
|
||||
}
|
||||
logrus.Debugf("equeue mq build plugin from dockerfile success")
|
||||
return tpbv, nil
|
||||
return pbv, nil
|
||||
}
|
||||
|
||||
//GetAllPluginBuildVersions GetAllPluginBuildVersions
|
||||
|
@ -17,3 +17,118 @@
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package share
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/coreos/etcd/clientv3"
|
||||
api_db "github.com/goodrain/rainbond/api/db"
|
||||
"github.com/goodrain/rainbond/api/util"
|
||||
"github.com/goodrain/rainbond/builder/exector"
|
||||
"github.com/goodrain/rainbond/db"
|
||||
"github.com/goodrain/rainbond/mq/api/grpc/pb"
|
||||
"github.com/pquerna/ffjson/ffjson"
|
||||
"github.com/twinj/uuid"
|
||||
)
|
||||
|
||||
//PluginShareHandle plugin share
|
||||
type PluginShareHandle struct {
|
||||
MQClient pb.TaskQueueClient
|
||||
EtcdCli *clientv3.Client
|
||||
}
|
||||
|
||||
//PluginResult share plugin api return
|
||||
type PluginResult struct {
|
||||
EventID string `json:"event_id"`
|
||||
ShareID string `json:"share_id"`
|
||||
ImageName string `json:"image_name,omitempty"`
|
||||
}
|
||||
|
||||
//PluginShare PluginShare
|
||||
type PluginShare struct {
|
||||
// in: path
|
||||
// required: true
|
||||
TenantName string `json:"tenant_name"`
|
||||
TenantID string
|
||||
// in: path
|
||||
// required: true
|
||||
PluginID string `json:"plugin_id"`
|
||||
//in: body
|
||||
Body struct {
|
||||
//in: body
|
||||
//应用分享Key
|
||||
PluginKey string `json:"plugin_key" validate:"plugin_key|required"`
|
||||
PluginVersion string `json:"plugin_version" validate:"plugin_version|required"`
|
||||
EventID string `json:"event_id"`
|
||||
ShareUser string `json:"share_user"`
|
||||
ShareScope string `json:"share_scope"`
|
||||
ImageInfo struct {
|
||||
HubURL string `json:"hub_url"`
|
||||
HubUser string `json:"hub_user"`
|
||||
HubPassword string `json:"hub_password"`
|
||||
Namespace string `json:"namespace"`
|
||||
} `json:"image_info,omitempty"`
|
||||
}
|
||||
}
|
||||
|
||||
//Share 分享应用
|
||||
func (s *PluginShareHandle) Share(ss PluginShare) (*PluginResult, *util.APIHandleError) {
|
||||
_, err := db.GetManager().TenantPluginDao().GetPluginByID(ss.PluginID, ss.TenantID)
|
||||
if err != nil {
|
||||
return nil, util.CreateAPIHandleErrorFromDBError("query plugin error", err)
|
||||
}
|
||||
//query new build version
|
||||
version, err := db.GetManager().TenantPluginBuildVersionDao().GetLastBuildVersionByVersionID(ss.PluginID, ss.Body.PluginVersion)
|
||||
if err != nil {
|
||||
logrus.Error("query service deploy version error", err.Error())
|
||||
return nil, util.CreateAPIHandleErrorFromDBError("query plugin version error", err)
|
||||
}
|
||||
shareID := uuid.NewV4().String()
|
||||
var bs api_db.BuildTaskStruct
|
||||
shareImageName, err := version.CreateShareImage(ss.Body.ImageInfo.HubURL, ss.Body.ImageInfo.Namespace)
|
||||
if err != nil {
|
||||
return nil, util.CreateAPIHandleErrorf(500, "create share image name error", err)
|
||||
}
|
||||
info := map[string]interface{}{
|
||||
"image_info": ss.Body.ImageInfo,
|
||||
"event_id": ss.Body.EventID,
|
||||
"tenant_name": ss.TenantName,
|
||||
"image_name": shareImageName,
|
||||
"share_id": shareID,
|
||||
"local_image_name": version.BuildLocalImage,
|
||||
}
|
||||
body, _ := ffjson.Marshal(info)
|
||||
bs.TaskType = "share-plugin"
|
||||
bs.TaskBody = body
|
||||
bs.User = ss.Body.ShareUser
|
||||
eq, _ := api_db.BuildTaskBuild(&bs)
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
_, err = s.MQClient.Enqueue(ctx, eq)
|
||||
if err != nil {
|
||||
logrus.Errorf("equque mq error, %v", err)
|
||||
return nil, util.CreateAPIHandleError(502, err)
|
||||
}
|
||||
return &PluginResult{EventID: ss.Body.EventID, ShareID: shareID, ImageName: shareImageName}, nil
|
||||
}
|
||||
|
||||
//ShareResult 分享应用结果查询
|
||||
func (s *PluginShareHandle) ShareResult(shareID string) (i exector.ShareStatus, e *util.APIHandleError) {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
res, err := s.EtcdCli.Get(ctx, fmt.Sprintf("/rainbond/shareresult/%s", shareID))
|
||||
if err != nil {
|
||||
e = util.CreateAPIHandleError(500, err)
|
||||
} else {
|
||||
if res.Count == 0 {
|
||||
i.ShareID = "shareID"
|
||||
} else {
|
||||
if err := ffjson.Unmarshal(res.Kvs[0].Value, &i); err != nil {
|
||||
return i, util.CreateAPIHandleError(500, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
@ -206,10 +206,14 @@ type BuildPluginStruct struct {
|
||||
// in: body
|
||||
// required: false
|
||||
PluginCMD string `json:"plugin_cmd" validate:"plugin_cmd"`
|
||||
// 部署的版本号
|
||||
// 插件的版本号
|
||||
// in: body
|
||||
// required: true
|
||||
BuildVersion string `json:"build_version" validate:"build_version|required"`
|
||||
// 插件构建版本号
|
||||
// in: body
|
||||
// required: true
|
||||
DeployVersion string `json:"deploy_version" validate:"deploy_version"`
|
||||
// git地址分支信息,默认为master
|
||||
// in: body
|
||||
// required: false
|
||||
@ -226,14 +230,18 @@ type BuildPluginStruct struct {
|
||||
// in: body
|
||||
// required: true
|
||||
TenantID string `json:"tenant_id" validate:"tenant_id"`
|
||||
//安装来源
|
||||
// in: body
|
||||
// required: false
|
||||
PluginFrom string `json:"plugin_from" validate:"plugin_from"`
|
||||
// 镜像地址
|
||||
// in: body
|
||||
// required: false
|
||||
BuildImage string `json:"build_image" validate:"build_image"`
|
||||
//ImageInfo
|
||||
ImageInfo struct {
|
||||
HubURL string `json:"hub_url"`
|
||||
HubUser string `json:"hub_user"`
|
||||
HubPassword string `json:"hub_password"`
|
||||
Namespace string `json:"namespace"`
|
||||
IsTrust bool `json:"is_trust,omitempty"`
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -64,7 +64,7 @@ func (e *exectorManager) pluginDockerfileBuild(in []byte) {
|
||||
return
|
||||
}
|
||||
}
|
||||
version, err := db.GetManager().TenantPluginBuildVersionDao().GetBuildVersionByVersionID(tb.PluginID, tb.VersionID)
|
||||
version, err := db.GetManager().TenantPluginBuildVersionDao().GetBuildVersionByDeployVersion(tb.PluginID, tb.VersionID, tb.DeployVersion)
|
||||
if err != nil {
|
||||
logrus.Errorf("get version error, %v", err)
|
||||
}
|
||||
@ -127,7 +127,7 @@ func (e *exectorManager) runD(t *model.BuildPluginTaskBody, logger event.Logger)
|
||||
return err
|
||||
}
|
||||
logger.Info("推送镜像完成", map[string]string{"step": "build-exector"})
|
||||
version, err := db.GetManager().TenantPluginBuildVersionDao().GetBuildVersionByVersionID(t.PluginID, t.VersionID)
|
||||
version, err := db.GetManager().TenantPluginBuildVersionDao().GetBuildVersionByDeployVersion(t.PluginID, t.VersionID, t.DeployVersion)
|
||||
if err != nil {
|
||||
logrus.Errorf("get version error, %v", err)
|
||||
return err
|
||||
|
@ -55,7 +55,7 @@ func (e *exectorManager) pluginImageBuild(in []byte) {
|
||||
return
|
||||
}
|
||||
}
|
||||
version, err := db.GetManager().TenantPluginBuildVersionDao().GetBuildVersionByVersionID(tb.PluginID, tb.VersionID)
|
||||
version, err := db.GetManager().TenantPluginBuildVersionDao().GetBuildVersionByDeployVersion(tb.PluginID, tb.VersionID, tb.DeployVersion)
|
||||
if err != nil {
|
||||
logrus.Errorf("get version error, %v", err)
|
||||
}
|
||||
@ -74,7 +74,6 @@ func (e *exectorManager) run(t *model.BuildPluginTaskBody, logger event.Logger)
|
||||
logger.Error("拉取镜像失败", map[string]string{"step": "builder-exector", "status": "failure"})
|
||||
return err
|
||||
}
|
||||
|
||||
logger.Info("拉取镜像完成", map[string]string{"step": "build-exector", "status": "complete"})
|
||||
newTag := createPluginImageTag(t.ImageURL, t.PluginID, t.DeployVersion)
|
||||
err := sources.ImageTag(e.DockerClient, t.ImageURL, newTag, logger, 1)
|
||||
@ -89,7 +88,7 @@ func (e *exectorManager) run(t *model.BuildPluginTaskBody, logger event.Logger)
|
||||
logger.Error("推送镜像失败", map[string]string{"step": "builder-exector", "status": "failure"})
|
||||
return err
|
||||
}
|
||||
version, err := db.GetManager().TenantPluginBuildVersionDao().GetBuildVersionByVersionID(t.PluginID, t.VersionID)
|
||||
version, err := db.GetManager().TenantPluginBuildVersionDao().GetBuildVersionByDeployVersion(t.PluginID, t.VersionID, t.DeployVersion)
|
||||
if err != nil {
|
||||
logger.Error("更新插件版本信息错误", map[string]string{"step": "builder-exector", "status": "failure"})
|
||||
return err
|
||||
|
141
builder/exector/share_plugin.go
Normal file
141
builder/exector/share_plugin.go
Normal file
@ -0,0 +1,141 @@
|
||||
// Copyright (C) 2014-2018 Goodrain Co., Ltd.
|
||||
// RAINBOND, Application Management Platform
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version. For any non-GPL usage of Rainbond,
|
||||
// one or multiple Commercial Licenses authorized by Goodrain Co., Ltd.
|
||||
// must be obtained first.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package exector
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/coreos/etcd/clientv3"
|
||||
"github.com/docker/engine-api/client"
|
||||
"github.com/goodrain/rainbond/builder/sources"
|
||||
"github.com/goodrain/rainbond/event"
|
||||
"github.com/pquerna/ffjson/ffjson"
|
||||
"github.com/tidwall/gjson"
|
||||
)
|
||||
|
||||
//PluginShareItem PluginShareItem
|
||||
type PluginShareItem struct {
|
||||
EventID string `json:"event_id"`
|
||||
ImageName string `json:"image_name"`
|
||||
LocalImageName string `json:"local_image_name"`
|
||||
ShareID string `json:"share_id"`
|
||||
Logger event.Logger
|
||||
ImageInfo struct {
|
||||
HubURL string `json:"hub_url"`
|
||||
HubUser string `json:"hub_user"`
|
||||
HubPassword string `json:"hub_password"`
|
||||
Namespace string `json:"namespace"`
|
||||
IsTrust bool `json:"is_trust,omitempty"`
|
||||
} `json:"image_info,omitempty"`
|
||||
DockerClient *client.Client
|
||||
EtcdCli *clientv3.Client
|
||||
}
|
||||
|
||||
func init() {
|
||||
RegisterWorker("share-plugin", SharePluginItemCreater)
|
||||
}
|
||||
|
||||
//SharePluginItemCreater create
|
||||
func SharePluginItemCreater(in []byte, m *exectorManager) (TaskWorker, error) {
|
||||
eventID := gjson.GetBytes(in, "event_id").String()
|
||||
logger := event.GetManager().GetLogger(eventID)
|
||||
pluginShare := &PluginShareItem{
|
||||
Logger: logger,
|
||||
EventID: eventID,
|
||||
DockerClient: m.DockerClient,
|
||||
}
|
||||
if err := ffjson.Unmarshal(in, &pluginShare); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return pluginShare, nil
|
||||
}
|
||||
|
||||
//Run Run
|
||||
func (i *PluginShareItem) Run(timeout time.Duration) error {
|
||||
_, err := sources.ImagePull(i.DockerClient, i.LocalImageName, "", "", i.Logger, 10)
|
||||
if err != nil {
|
||||
logrus.Errorf("pull image %s error: %s", i.LocalImageName, err.Error())
|
||||
i.Logger.Error(fmt.Sprintf("拉取应用镜像: %s失败", i.LocalImageName), map[string]string{"step": "builder-exector", "status": "failure"})
|
||||
return err
|
||||
}
|
||||
if err := sources.ImageTag(i.DockerClient, i.LocalImageName, i.ImageName, i.Logger, 1); err != nil {
|
||||
logrus.Errorf("change image tag error: %s", err.Error())
|
||||
i.Logger.Error(fmt.Sprintf("修改镜像tag: %s -> %s 失败", i.LocalImageName, i.ImageName), map[string]string{"step": "builder-exector", "status": "failure"})
|
||||
return err
|
||||
}
|
||||
if i.ImageInfo.IsTrust {
|
||||
err = sources.TrustedImagePush(i.DockerClient, i.ImageName, i.ImageInfo.HubUser, i.ImageInfo.HubPassword, i.Logger, 10)
|
||||
} else {
|
||||
err = sources.ImagePush(i.DockerClient, i.ImageName, i.ImageInfo.HubUser, i.ImageInfo.HubPassword, i.Logger, 10)
|
||||
}
|
||||
if err != nil {
|
||||
if err.Error() == "authentication required" {
|
||||
i.Logger.Error("镜像仓库授权失败", map[string]string{"step": "builder-exector", "status": "failure"})
|
||||
return err
|
||||
}
|
||||
logrus.Errorf("push image into registry error: %s", err.Error())
|
||||
i.Logger.Error("推送镜像至镜像仓库失败", map[string]string{"step": "builder-exector", "status": "failure"})
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
//Stop stop
|
||||
func (i *PluginShareItem) Stop() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
//Name return worker name
|
||||
func (i *PluginShareItem) Name() string {
|
||||
return "share-plugin"
|
||||
}
|
||||
|
||||
//GetLogger GetLogger
|
||||
func (i *PluginShareItem) GetLogger() event.Logger {
|
||||
return i.Logger
|
||||
}
|
||||
|
||||
//ErrorCallBack if run error will callback
|
||||
func (i *PluginShareItem) ErrorCallBack(err error) {
|
||||
i.updateShareStatus("failure")
|
||||
}
|
||||
|
||||
//updateShareStatus update share task result
|
||||
func (i *PluginShareItem) updateShareStatus(status string) error {
|
||||
var ss = ShareStatus{
|
||||
ShareID: i.ShareID,
|
||||
Status: status,
|
||||
}
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
_, err := i.EtcdCli.Put(ctx, fmt.Sprintf("/rainbond/shareresult/%s", i.ShareID), ss.String())
|
||||
if err != nil {
|
||||
logrus.Errorf("put shareresult %s into etcd error, %v", i.ShareID, err)
|
||||
i.Logger.Error("存储分享结果失败。", map[string]string{"step": "callback", "status": "failure"})
|
||||
}
|
||||
if status == "success" {
|
||||
i.Logger.Info("创建分享结果成功,分享成功", map[string]string{"step": "last", "status": "success"})
|
||||
} else {
|
||||
i.Logger.Info("创建分享结果成功,分享失败", map[string]string{"step": "callback", "status": "failure"})
|
||||
}
|
||||
return nil
|
||||
}
|
@ -33,6 +33,13 @@ type BuildPluginTaskBody struct {
|
||||
PluginCMD string `json:"plugin_cmd"`
|
||||
PluginCPU int `json:"plugin_cpu"`
|
||||
PluginMemory int `json:"plugin_memory"`
|
||||
ImageInfo struct {
|
||||
HubURL string `json:"hub_url"`
|
||||
HubUser string `json:"hub_user"`
|
||||
HubPassword string `json:"hub_password"`
|
||||
Namespace string `json:"namespace"`
|
||||
IsTrust bool `json:"is_trust,omitempty"`
|
||||
} `json:"image_info,omitempty"`
|
||||
}
|
||||
|
||||
//BuildPluginVersion BuildPluginVersion
|
||||
|
@ -128,6 +128,8 @@ type TenantPluginBuildVersionDao interface {
|
||||
DeleteBuildVersionByPluginID(pluginID string) error
|
||||
GetBuildVersionByPluginID(pluginID string) ([]*model.TenantPluginBuildVersion, error)
|
||||
GetBuildVersionByVersionID(pluginID, versionID string) (*model.TenantPluginBuildVersion, error)
|
||||
GetLastBuildVersionByVersionID(pluginID, versionID string) (*model.TenantPluginBuildVersion, error)
|
||||
GetBuildVersionByDeployVersion(pluginID, versionID, deployVersion string) (*model.TenantPluginBuildVersion, error)
|
||||
}
|
||||
|
||||
//TenantPluginVersionEnvDao TenantPluginVersionEnvDao
|
||||
|
@ -18,6 +18,11 @@
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/distribution/reference"
|
||||
)
|
||||
|
||||
//TenantPlugin plugin model
|
||||
type TenantPlugin struct {
|
||||
Model
|
||||
@ -96,6 +101,24 @@ func (t *TenantPluginBuildVersion) TableName() string {
|
||||
return "tenant_plugin_build_version"
|
||||
}
|
||||
|
||||
//CreateShareImage CreateShareImage
|
||||
func (t *TenantPluginBuildVersion) CreateShareImage(hubURL, namespace string) (string, error) {
|
||||
_, err := reference.ParseAnyReference(t.BuildLocalImage)
|
||||
if err != nil {
|
||||
logrus.Errorf("reference image error: %s", err.Error())
|
||||
return "", err
|
||||
}
|
||||
image := ParseImage(t.BuildLocalImage)
|
||||
if hubURL != "" {
|
||||
image.Host = hubURL
|
||||
}
|
||||
if namespace != "" {
|
||||
image.Namespace = namespace
|
||||
}
|
||||
image.Name = image.Name + "_" + t.VersionID + ":" + t.DeployVersion
|
||||
return image.String(), nil
|
||||
}
|
||||
|
||||
//TenantPluginVersionEnv TenantPluginVersionEnv
|
||||
type TenantPluginVersionEnv struct {
|
||||
Model
|
||||
|
@ -256,6 +256,24 @@ func (t *PluginBuildVersionDaoImpl) GetBuildVersionByVersionID(pluginID, version
|
||||
return &version, nil
|
||||
}
|
||||
|
||||
//GetBuildVersionByDeployVersion GetBuildVersionByDeployVersion
|
||||
func (t *PluginBuildVersionDaoImpl) GetBuildVersionByDeployVersion(pluginID, versionID, deployVersion string) (*model.TenantPluginBuildVersion, error) {
|
||||
var version model.TenantPluginBuildVersion
|
||||
if err := t.DB.Where("plugin_id=? and version_id = ? and deploy_version=?", pluginID, versionID, deployVersion).Find(&version).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &version, nil
|
||||
}
|
||||
|
||||
//GetLastBuildVersionByVersionID get last success build version
|
||||
func (t *PluginBuildVersionDaoImpl) GetLastBuildVersionByVersionID(pluginID, versionID string) (*model.TenantPluginBuildVersion, error) {
|
||||
var version model.TenantPluginBuildVersion
|
||||
if err := t.DB.Where("plugin_id=? and version_id = ? and status=?", pluginID, versionID, "complete").Order("ID desc").Limit("1").Find(&version).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &version, nil
|
||||
}
|
||||
|
||||
//PluginVersionEnvDaoImpl PluginVersionEnvDaoImpl
|
||||
type PluginVersionEnvDaoImpl struct {
|
||||
DB *gorm.DB
|
||||
|
@ -512,3 +512,10 @@ func Rename(old, new string) error {
|
||||
}
|
||||
return os.Rename(old, new)
|
||||
}
|
||||
|
||||
//CreateVersionByTime create version number
|
||||
func CreateVersionByTime() string {
|
||||
now := time.Now()
|
||||
re := fmt.Sprintf("%d%d%d%d%d%d%d", now.Year(), now.Month(), now.Day(), now.Hour(), now.Minute(), now.Second(), now.Nanosecond())
|
||||
return re
|
||||
}
|
||||
|
@ -60,3 +60,9 @@ func TestUnzip(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateVersionByTime(t *testing.T) {
|
||||
if re := CreateVersionByTime(); re != "" {
|
||||
t.Log(re)
|
||||
}
|
||||
}
|
||||
|
@ -784,7 +784,7 @@ func (p *PodTemplateSpecBuild) createPluginsContainer(volumeMounts []v1.VolumeMo
|
||||
if pluginR.Switch == false {
|
||||
continue
|
||||
}
|
||||
versionInfo, err := p.dbmanager.TenantPluginBuildVersionDao().GetBuildVersionByVersionID(pluginR.PluginID, pluginR.VersionID)
|
||||
versionInfo, err := p.dbmanager.TenantPluginBuildVersionDao().GetLastBuildVersionByVersionID(pluginR.PluginID, pluginR.VersionID)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user