From 3a706d3378aa3626501370352963883fd2783558 Mon Sep 17 00:00:00 2001 From: zhangzengfei <zhangzengfei@smartai.com> Date: 星期二, 28 十一月 2023 11:24:49 +0800 Subject: [PATCH] 添加appcenter,完善算法上传下载功能 --- appcenter-service/models/dictionary.go | 89 + appcenter-service/Makefile | 7 appcenter-service/service/SysService.go | 632 ++++++++ appcenter-service/models/sdkChanSet.go | 61 appcenter-service/service/AppService.go | 317 ++++ appcenter-service/service/SdkInstall.go | 859 +++++++++++ appcenter-service/controllers/app.go | 218 ++ appcenter-service/vo/sdk.go | 102 + appcenter-service/controllers/sdkArg.go | 30 appcenter-service/models/app.go | 152 + appcenter-service/models/sdk.go | 224 ++ appcenter-service/service/Progress.go | 222 ++ appcenter-service/service/SdkDownLoad.go | 564 +++++++ appcenter-service/controllers/sdk.go | 501 ++++++ appcenter-service/service/proc.go | 6 appcenter-service/service/sdkService.go | 170 ++ appcenter-service/service/depend.go | 189 ++ appcenter-service/models/db.go | 49 appcenter-service/main.go | 132 + appcenter-service/models/sdkArg.go | 52 20 files changed, 4,576 insertions(+), 0 deletions(-) diff --git a/appcenter-service/Makefile b/appcenter-service/Makefile new file mode 100644 index 0000000..9d3abe8 --- /dev/null +++ b/appcenter-service/Makefile @@ -0,0 +1,7 @@ +BUILD_VERSION := 1.1.1 +#APP_NAME := myversion + +include ../module.dep + + + diff --git a/appcenter-service/controllers/app.go b/appcenter-service/controllers/app.go new file mode 100644 index 0000000..67fad5c --- /dev/null +++ b/appcenter-service/controllers/app.go @@ -0,0 +1,218 @@ +package controllers + +import ( + "strconv" + "time" + "vamicro/appcenter-service/models" + "vamicro/appcenter-service/service" + + "basic.com/valib/bhomeclient.git" + "basic.com/valib/logger.git" +) + +type AppController struct { + bk bhomeclient.Broker +} + +// @Security ApiKeyAuth +// @Summary 鏌ユ壘宸插畨瑁呭拰鏈畨瑁呯殑搴旂敤鍒楄〃 +// @Description 鏌ユ壘宸插畨瑁呭拰鏈畨瑁呯殑搴旂敤鍒楄〃 +// @Produce json +// @Tags 搴旂敤 +// @Param appName query string true "搴旂敤鍚嶇О" +// @Success 200 {string} json "{"code":200, msg:"", success:true}" +// @Failure 500 {string} json "{"code":500, msg:"", success:false}" +// @Router /data/api-v/app/findAllApp [get] +func (ac AppController) FindAll(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply { + appName := c.Query("appName") + logger.Debug("FindAllApp appName:", appName) + list := service.GetAppList(appName) + if list == nil { + list = make([]service.AppWithShop, 0) + } + return &bhomeclient.Reply{Success: true, Data: list} +} + +type DelApp struct { + AppId string `json:"appId" binding:"required"` +} + +// @Security ApiKeyAuth +// @Summary 鏍规嵁id鑾峰彇app淇℃伅 +// @Description 鏍规嵁id鑾峰彇app淇℃伅 +// @Produce json +// @Tags 搴旂敤 +// @Param id query string true "搴旂敤id" +// @Success 200 {string} json "{"code":200, msg:"", success:true}" +// @Failure 500 {string} json "{"code":500, msg:"", success:false}" +// @Router /data/api-v/app/getAppInfo [get] +func (ac AppController) GetAppInfo(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply { + id := c.Query("id") + logger.Debug("GetAppInfo id:", id) + if id == "" { + return &bhomeclient.Reply{Msg: "鍙傛暟鏈夎"} + } + var app models.App + rows, err := app.SelectById(id) + if err == nil && rows > 0 { + return &bhomeclient.Reply{Success: true, Data: app} + } else { + return &bhomeclient.Reply{Msg: "鑾峰彇澶辫触"} + } +} + +// @Security ApiKeyAuth +// @Summary 搴旂敤鍗歌浇 +// @Description 搴旂敤鍗歌浇 +// @Produce json +// @Tags 搴旂敤 +// @Param arg body controllers.DelApp true "鍗歌浇鍙傛暟" +// @Success 200 {string} json "{"code":200, msg:"", success:true}" +// @Failure 500 {string} json "{"code":500, msg:"", success:false}" +// @Router /data/api-v/app/unInstall [post] +func (ac AppController) UnInstall(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply { + var req DelApp + err := c.BindJSON(&req) + if err != nil { + return &bhomeclient.Reply{Msg: "鍙傛暟鏈夎"} + } + + var sv service.SdkInstallService + if err := sv.PackUninstall(req.AppId); err != nil { + logger.Error("鎵цuninstall.sh 澶辫触", err.Error()) + return &bhomeclient.Reply{Success: false, Msg: "鍗歌浇澶辫触"} + } + + var appE models.App + if appE.DeleteById(req.AppId) { + return &bhomeclient.Reply{Success: true, Msg: "鍗歌浇鎴愬姛"} + } else { + return &bhomeclient.Reply{Success: false, Msg: "鍗歌浇澶辫触"} + } +} + +// @Security ApiKeyAuth +// @Summary 鑾峰彇鏈喘涔扮殑搴旂敤鍒楄〃 +// @Description 鑾峰彇鏈喘涔扮殑搴旂敤鍒楄〃 +// @Produce json +// @Tags 搴旂敤 +// @Success 200 {string} json "{"code":200, msg:"", success:true}" +// @Failure 500 {string} json "{"code":500, msg:"", success:false}" +// @Router /data/api-v/app/buyList [get] +func (ac AppController) BuyList(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply { + appName := c.Query("appName") + logger.Debug("BuyList appName:", appName) + list := service.GetAppBuyList(appName) + if list == nil { + list = make([]models.App, 0) + } + + return &bhomeclient.Reply{Success: true, Data: list} +} + +// @Security ApiKeyAuth +// @Summary 浣跨敤婵�娲荤爜婵�娲诲畨瑁呭簲鐢� +// @Description 浣跨敤婵�娲荤爜婵�娲诲畨瑁呭簲鐢� +// @Produce json +// @Tags 搴旂敤 +// @Param code query string true "婵�娲荤爜" +// @Param appId query string true "搴旂敤id" +// @Success 200 {string} json "{"code":200, msg:"", success:true}" +// @Failure 500 {string} json "{"code":500, msg:"", success:false}" +// @Router /data/api-v/app/active [get] +func (ac AppController) Active(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply { + cod := c.Query("code") + appId := c.Query("appId") + if appId == "" { //code鍙互涓虹┖锛屼负0鍏冭喘 + return &bhomeclient.Reply{Msg: "鍙傛暟鏈夎"} + } + d, err := service.ActiveApp(cod, appId) + if err == nil { + // 婵�娲绘垚鍔� + var app models.App + if err := app.UpdateCode(appId, cod); err != nil { + return &bhomeclient.Reply{Msg: err.Error()} + } + return &bhomeclient.Reply{Success: true, Data: d} + } else { + return &bhomeclient.Reply{Msg: err.Error()} + } +} + +func (ac AppController) Save(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply { + var reqBody models.App + c.BindJSON(&reqBody) + if reqBody.Id == "" { + return &bhomeclient.Reply{Success: false, Msg: "鍙傛暟鏈夎"} + } + reqBody.CreateTime = time.Now().Format("2006-01-02 15:04:05") + reqBody.CreateBy = "basic" + reqBody.UpdateBy = "" + reqBody.UpdateTime = "" + if err := reqBody.Save(); err == nil { + return &bhomeclient.Reply{Success: true, Msg: "淇濆瓨鎴愬姛"} + } else { + return &bhomeclient.Reply{Success: false, Msg: "淇濆瓨澶辫触"} + } +} + +// @Security ApiKeyAuth +// @Summary 鏄剧ず绠楁硶鎴栧簲鐢ㄧ殑浜у搧淇℃伅璇︽儏 +// @Description 鏄剧ず绠楁硶鎴栧簲鐢ㄧ殑浜у搧淇℃伅璇︽儏 +// @Produce json +// @Tags 搴旂敤 +// @Param id query string true "绠楁硶鎴栧簲鐢ㄧ殑id" +// @Success 200 {string} json "{"code":200, msg:"", success:true}" +// @Failure 500 {string} json "{"code":500, msg:"", success:false}" +// @Router /data/api-v/app/detail [get] +func (ac AppController) Detail(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply { + id := c.Query("id") + if id == "" { + return &bhomeclient.Reply{Msg: "鍙傛暟鏈夎"} + } + d, err := service.DetailByAppOrSdkId(id) + if err == nil { + return &bhomeclient.Reply{Success: true, Data: d} + } else { + return &bhomeclient.Reply{Msg: err.Error()} + } +} + +// @Security ApiKeyAuth +// @Summary 鑾峰彇鏇存柊鎻愰啋 +// @Description 鑾峰彇鏇存柊鎻愰啋 +// @Produce json +// @Tags 搴旂敤 +// @Param id query string true "绠楁硶鎴栧簲鐢ㄧ殑id" +// @Success 200 {string} json "{"code":200, msg:"", success:true}" +// @Failure 500 {string} json "{"code":500, msg:"", success:false}" +// @Router /data/api-v/app/upgrade/notice [get] +func (ac AppController) UpgradeNotice(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply { + userId := c.Header("Login_user_id") + notice := service.GetUpdateNotice() + LastNoticeTime, ok := notice.NoticeUser[userId] + if ok { + notice.LastNoticeTime = LastNoticeTime + } + return &bhomeclient.Reply{Success: true, Data: notice} +} + +// @Security ApiKeyAuth +// @Summary 寤惰繜鏇存柊鎻愰啋 +// @Description 寤惰繜鏇存柊鎻愰啋 +// @Produce json +// @Tags 搴旂敤 +// @Param delay query string true "寤惰繜鎻愰啋鐨勭鏁�" +// @Success 200 {string} json "{"code":200, msg:"", success:true}" +// @Failure 500 {string} json "{"code":500, msg:"", success:false}" +// @Router /data/api-v/app/upgrade/notice [get] +func (ac AppController) DelayNotice(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply { + userId := c.Header("Login_user_id") + delay := c.PostForm("delay") + delaySecond, err := strconv.Atoi(delay) + if nil != err { + return &bhomeclient.Reply{Msg: err.Error()} + } + service.DelayNotice(userId, delaySecond) + return &bhomeclient.Reply{Success: true, Msg: "鎿嶄綔鎴愬姛", Data: delaySecond} +} diff --git a/appcenter-service/controllers/sdk.go b/appcenter-service/controllers/sdk.go new file mode 100644 index 0000000..0c66baf --- /dev/null +++ b/appcenter-service/controllers/sdk.go @@ -0,0 +1,501 @@ +package controllers + +import ( + "bytes" + "encoding/json" + "strconv" + "vamicro/appcenter-service/models" + "vamicro/appcenter-service/service" + "vamicro/appcenter-service/vo" + + "basic.com/pubsub/protomsg.git" + "basic.com/valib/bhomeclient.git" + "basic.com/valib/logger.git" +) + +type SdkController struct { +} + +// @Summary 绠楁硶娉ㄥ唽 +// @Description 绠楁硶娉ㄥ唽 +// @Accept json +// @Produce json +// @Tags sdk +// @Param reqMap body vo.SdkVo true "绠楁硶娉ㄥ唽鍙傛暟" +// @Success 200 {string} json "{"code":200, msg:"璇锋眰澶勭悊鎴愬姛",data:"",success:true}" +// @Failure 500 {string} json "{"code":500, msg:"璇锋眰澶辫触",data:"",success:false}" +// @Router /data/api-v/sdk/register [POST] +func (sc SdkController) Register(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply { + var reqBody vo.SdkRegisterVo + + c.BindJSON(&reqBody) + if reqBody.Id == "" || reqBody.SdkType == "" || reqBody.SdkName == "" || reqBody.Icon == "" { + return &bhomeclient.Reply{Success: false, Msg: "鍙傛暟鏈夎"} + } + logger.Debug("sdk register paramBody:", reqBody) + sv := service.NewSdkService(h.Bk) + if sv.Register(&reqBody) { + return &bhomeclient.Reply{Success: true, Msg: "绠楁硶娉ㄥ唽鎴愬姛"} + } else { + return &bhomeclient.Reply{Success: false, Msg: "娉ㄥ唽澶辫触"} + } +} + +// @Summary 鏌ユ壘鎵�鏈夌畻娉� +// @Description 鏌ユ壘鎵�鏈夌畻娉� +// @Produce json +// @Tags sdk +// @Param sdkName query string false "鍙�夊弬鏁�" +// @Success 200 {string} json "{"code":200, msg:"璇锋眰澶勭悊鎴愬姛",data:"绠楁硶鍒楄〃",success:true}" +// @Failure 500 {string} json "{"code":500, msg:"璇锋眰澶辫触",data:"[]",success:false}" +// @Router /data/api-v/sdk/findAllSdk [GET] +func (sc SdkController) FindAllSdk(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply { + sdkName := c.Query("sdkName") + insStr := c.Query("installed") //濡傛灉鏈紶姝ゅ弬鏁帮紝鍒欒〃绀烘煡鎵�鏈� + userId := c.Header("Login_user_id") + ok := false + if insStr != "" { + ok = true + } + logger.Debugf("FindAllSdk sdkName=%v, insStr=%v, ok=%v, userId=%v", sdkName, insStr, ok, userId) + installed, _ := strconv.ParseBool(insStr) + + sdks := service.GetSdkList(sdkName, insStr, userId) //鏈満宸插畨瑁呯殑绠楁硶 + if ok && !installed { //浼犱簡installed鍙傛暟 + nSdks := make([]service.SdkInsOrUpgrade, 0) + for _, s := range sdks { + if !s.Installed { + nSdks = append(nSdks, s) + } + } + return &bhomeclient.Reply{Success: true, Data: nSdks} + } else { + return &bhomeclient.Reply{Success: true, Data: sdks} + } +} + +// @Summary 鏍规嵁id鑾峰彇绠楁硶淇℃伅 +// @Description 鏍规嵁id鑾峰彇绠楁硶淇℃伅 +// @Produce json +// @Tags sdk +// @Param id query string true "绠楁硶id锛屽繀濉�" +// @Success 200 {string} json "{"code":200, msg:"璇锋眰澶勭悊鎴愬姛",data:"绠楁硶淇℃伅",success:true}" +// @Failure 500 {string} json "{"code":500, msg:"璇锋眰澶辫触",data:"",success:false}" +// @Router /data/api-v/sdk/getById [GET] +func (sc SdkController) GetById(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply { + var sdk models.Sdk + + id := c.Query("id") + if id == "" { + return &bhomeclient.Reply{Success: false, Msg: "鍙傛暟鏈夎"} + } + rows, err := sdk.SelectById(id) + if err != nil || rows == 0 { + return &bhomeclient.Reply{Success: false, Msg: "璁板綍涓嶅瓨鍦�"} + } + + var sdkVo = vo.SdkVo{} + sdkVo.Sdk = sdk + sdkVo.Args = sdk.GetSdkArgs(id, models.SCOPE_CAMERARULE) + return &bhomeclient.Reply{Success: true, Data: sdkVo} +} + +// @Summary 鏍规嵁taskId鑾峰彇绠楁硶淇℃伅 +// @Description 鏍规嵁taskId鑾峰彇绠楁硶淇℃伅 +// @Produce json +// @Tags sdk +// @Param taskId query string true "taskId锛屽繀濉�" +// @Success 200 {string} json "{"code":200, msg:"璇锋眰澶勭悊鎴愬姛",data:"绠楁硶淇℃伅",success:true}" +// @Failure 500 {string} json "{"code":500, msg:"璇锋眰澶辫触",data:"",success:false}" +// @Router /data/api-v/sdk/findByTaskId [GET] +func (sc SdkController) FindByTaskId(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply { + taskId := c.Query("taskId") + if taskId == "" { + return &bhomeclient.Reply{Success: false, Msg: "鍙傛暟鏈夎"} + } + var sdk models.Sdk + sdks, err := sdk.FindByTaskId(taskId) + if err != nil { + return &bhomeclient.Reply{Success: false, Msg: "鏌ヨ澶辫触"} + } + var sdkVoArr []vo.SdkVo + for _, sdk := range sdks { + sdkVo := vo.SdkVo{} + sdkVo.Sdk = sdk + sdkVo.Args = sdk.GetSdkArgs(sdk.Id, models.SCOPE_CAMERARULE) + sdkVoArr = append(sdkVoArr, sdkVo) + } + + if err != nil { + return &bhomeclient.Reply{Success: false, Msg: "璁板綍涓嶅瓨鍦�"} + } else { + return &bhomeclient.Reply{Success: true, Data: sdkVoArr} + } +} + +// @Summary 鑾峰彇鎵�鏈夌畻娉曢�氶亾鏁伴噺璁剧疆 +// @Description 鑾峰彇鎵�鏈夌畻娉曢�氶亾鏁伴噺璁剧疆 +// @Produce json +// @Tags sdk +// @Success 200 {string} json "{"code":200, msg:"璇锋眰澶勭悊鎴愬姛",data:"",success:true}" +// @Failure 500 {string} json "{"code":500, msg:"璇锋眰澶辫触",data:"",success:false}" +// @Router /data/api-v/sdk/getAllSdkChanSet [GET] +func (sc SdkController) GetAllSdkChanSet(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply { + var scs models.SdkChanSet + list, err := scs.FindAll() + if err != nil { + return &bhomeclient.Reply{Success: false, Msg: "鍐呴儴閿欒"} + } else { + return &bhomeclient.Reply{Success: true, Data: list} + } +} + +type SdkChanUpdateArg struct { + SdkType string `json:"sdk_type" binding:"required"` + ChanNum int `json:"chan_num" binding:"required"` +} + +// @Summary 鏇存柊绠楁硶閫氶亾鏁伴噺璁剧疆 +// @Description 鏇存柊绠楁硶閫氶亾鏁伴噺璁剧疆 +// @Produce json +// @Tags sdk +// @Param reqBody body controllers.SdkChanUpdateArg true "閫氶亾鏁伴噺璁剧疆鍙傛暟" +// @Success 200 {string} json "{"code":200, msg:"璇锋眰澶勭悊鎴愬姛",data:"",success:true}" +// @Failure 500 {string} json "{"code":500, msg:"璇锋眰澶辫触",data:"",success:false}" +// @Router /data/api-v/sdk/updateSdkChanSet [POST] +func (sc SdkController) UpdateSdkChanSet(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply { + var reqBody SdkChanUpdateArg + err := c.BindJSON(&reqBody) + if err != nil { + return &bhomeclient.Reply{Success: false, Msg: "鍙傛暟鏈夎"} + } + var scs = models.SdkChanSet{ + SdkType: reqBody.SdkType, + ChanNum: reqBody.ChanNum, + } + b, _ := scs.Update() + if b { + pMsg := protomsg.DbChangeMessage{ + Table: protomsg.TableChanged_T_SdkChanSet, + Action: protomsg.DbAction_Update, + } + pb, _ := json.Marshal(pMsg) + h.Bk.Publish("sdk-service", pb) + return &bhomeclient.Reply{Success: true, Msg: "鏇存柊鎴愬姛"} + } else { + return &bhomeclient.Reply{Success: false, Msg: "鏇存柊澶辫触"} + } +} + +// @Summary 鏇存柊绠楁硶榛樿鍦烘櫙鍙傛暟 +// @Description 鏇存柊绠楁硶榛樿鍦烘櫙鍙傛暟 +// @Produce json +// @Tags sdk +// @Param reqBody body vo.SdkArgDefault true "閫氶亾鏁伴噺璁剧疆鍙傛暟" +// @Success 200 {string} json "{"code":200, msg:"璇锋眰澶勭悊鎴愬姛",data:"",success:true}" +// @Failure 500 {string} json "{"code":500, msg:"璇锋眰澶辫触",data:"",success:false}" +// @Router /data/api-v/sdk/updateSdkArgConfig [POST] +func (sc SdkController) UpdateSdkArgConfig(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply { + var reqBody vo.SdkArgDefault + err := c.BindJSON(&reqBody) + if err != nil { + return &bhomeclient.Reply{Success: false, Msg: "鍙傛暟鏈夎"} + } + var sdk models.Sdk + rows, err := sdk.SelectById(reqBody.SdkId) + if err != nil || rows == 0 { + return &bhomeclient.Reply{Success: false, Msg: "绠楁硶id涓嶅瓨鍦�"} + } + bf := bytes.NewBuffer([]byte{}) + jsonEncoder := json.NewEncoder(bf) + jsonEncoder.SetEscapeHTML(false) + jsonEncoder.Encode(reqBody.DefArgs) + sdk.ArgDef = bf.String() + b, err := sdk.Update() + if err != nil { + return &bhomeclient.Reply{Success: false, Msg: err.Error()} + } + if b { + pMsg := protomsg.DbChangeMessage{ + Table: protomsg.TableChanged_T_Sdk, + Action: protomsg.DbAction_Update, + } + pb, _ := json.Marshal(pMsg) + h.Bk.Publish("sdk-service", pb) + return &bhomeclient.Reply{Success: true, Msg: "鏇存柊鎴愬姛"} + } else { + return &bhomeclient.Reply{Success: false, Msg: "鏇存柊澶辫触"} + } +} + +// @Summary 绠楁硶瀹夎鍖呬笂浼�(鍒嗗潡妫�鏌�) +// @Description 绠楁硶瀹夎鍖呬笂浼�(鍒嗗潡妫�鏌�) +// @Accept multipart/form-data +// @Produce json +// @Tags 绠楁硶 +// @Param chunkNumber formData int true "褰撳墠鏄鍑犱釜鍒嗗潡" +// @Param chunkSize formData int true "姣忎竴鍧楃殑澶у皬" +// @Param currentChunkSize formData int true "褰撳墠鍧楃殑澶у皬" +// @Param identifier formData string true "鏁翠釜鏂囦欢鐨勫敮涓�鏍囪瘑锛岀洰鍓嶆槸md5" +// @Param filename formData string true "鏂囦欢鍚嶇О" +// @Param relativePath formData string true "鏂囦欢鍦ㄥ鎴风鐢佃剳鐨勮矾寰�" +// @Param totalChunks formData int true "鏂囦欢鎬诲潡鏁�" +// @Success 200 {string} json "{"code":200, msg:"", success:true}" +// @Failure 500 {string} json "{"code":500, msg:"", success:false}" +// @Router /data/api-v/sdk/upload [get] +func (sc SdkController) Upload(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply { + chunkNumber, e1 := strconv.Atoi(c.Query("chunkNumber")) + chunkSize, e2 := strconv.Atoi(c.Query("chunkSize")) + currentChunkSize, e3 := strconv.Atoi(c.Query("currentChunkSize")) + identifier := c.Query("identifier") + filename := c.Query("filename") + relativePath := c.Query("relativePath") + totalChunks, e5 := strconv.Atoi(c.Query("totalChunks")) + if identifier == "" || e1 != nil || e2 != nil || e3 != nil || e5 != nil { + return &bhomeclient.Reply{Msg: "鍙傛暟鏈夎"} + } + userId := c.Header("Login_user_id") + var arg = service.FileChunkCheckVo{ + UserId: userId, + FileName: filename, + Identifier: identifier, + RelativePath: relativePath, + TotalChunks: totalChunks, + ChunkNumber: chunkNumber, + ChunkSize: chunkSize, + CurrentChunkSize: currentChunkSize, + } + var sv service.SysService + if b := sv.CheckUpdateFile(&arg); b { + //c.String(http.StatusOK,"found") + return &bhomeclient.Reply{Success: true, Data: "found"} + } else { + //c.String(http.StatusNoContent,"") + return &bhomeclient.Reply{Success: true, Data: ""} + } +} + +// @Security ApiKeyAuth +// @Summary 绠楁硶瀹夎鍖呬笂浼� +// @Description 绠楁硶瀹夎鍖呬笂浼� +// @Accept multipart/form-data +// @Produce json +// @Tags 绠楁硶 +// @Param chunkNumber formData int true "褰撳墠鏄鍑犱釜鍒嗗潡" +// @Param chunkSize formData int true "姣忎竴鍧楃殑澶у皬" +// @Param currentChunkSize formData int true "褰撳墠鍧楃殑澶у皬" +// @Param totalSize formData string true "鏂囦欢鎬诲ぇ灏�" +// @Param identifier formData string true "鏁翠釜鏂囦欢鐨勫敮涓�鏍囪瘑锛岀洰鍓嶆槸md5" +// @Param filename formData string true "鏂囦欢鍚嶇О" +// @Param relativePath formData string true "鏂囦欢鍦ㄥ鎴风鐢佃剳鐨勮矾寰�" +// @Param totalChunks formData int true "鏂囦欢鎬诲潡鏁�" +// @Param file formData file true "鏂囦欢鍒嗙墖鍐呭" +// @Success 200 {string} json "{"code":200, msg:"", success:true}" +// @Failure 500 {string} json "{"code":500, msg:"", success:false}" +// @Router /data/api-v/sdk/upload [post] +func (sc SdkController) UploadPack(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply { + chunkNumber, e1 := strconv.Atoi(c.PostForm("chunkNumber")) + chunkSize, e2 := strconv.Atoi(c.PostForm("chunkSize")) + currentChunkSize, e3 := strconv.Atoi(c.PostForm("currentChunkSize")) + totalSize, e4 := strconv.ParseInt(c.PostForm("totalSize"), 10, 64) + identifier := c.PostForm("identifier") + filename := c.PostForm("filename") + relativePath := c.PostForm("relativePath") + totalChunks, e5 := strconv.Atoi(c.PostForm("totalChunks")) + file, e6 := c.FormFile() + //file, header, e6 := c.Request.FormFile("file") + if identifier == "" || e1 != nil || e2 != nil || e3 != nil || e4 != nil || e5 != nil || e6 != nil { + return &bhomeclient.Reply{Msg: "鍙傛暟鏈夎"} + } + userId := c.Header("Login_user_id") + var arg = service.FileUploadVo{ + UserId: userId, + FileName: filename, + Identifier: identifier, + RelativePath: relativePath, + TotalSize: totalSize, + TotalChunks: totalChunks, + ChunkNumber: chunkNumber, + ChunkSize: chunkSize, + CurrentChunkSize: currentChunkSize, + File: file, + //Header: header, + } + var sv service.SysService + if b, _, msg := sv.PatchUpload(&arg); b { + //if isComplete { //涓婁紶瀹屾瘯闇�瑕佽嚜鍔ㄨЕ鍙戝畨瑁� + // var sv service.SdkInstallService + // if b,err := sv.SdkInstall(identifier, filename);b { + // util.ResponseFormat(c,&code.Code{http.StatusOK, true, "绠楁硶瀹夎鎴愬姛"},"绠楁硶瀹夎鎴愬姛") + // return + // } else { + // util.ResponseFormat(c,&code.Code{http.StatusBadRequest, false, "绠楁硶瀹夎澶辫触"},err.Error()) + // return + // } + //} + return &bhomeclient.Reply{Success: true, Msg: "涓婁紶瀹屾垚"} + } else { + return &bhomeclient.Reply{Msg: msg} + } +} + +// @Security ApiKeyAuth +// @Summary 涓婁紶瀹屾垚鑾峰彇瀹夎淇℃伅 +// @Description 涓婁紶瀹屾垚鑾峰彇瀹夎淇℃伅 +// @Produce json +// @Tags 绠楁硶 +// @Param identifier formData string true "鏁翠釜鏂囦欢鐨勫敮涓�鏍囪瘑锛岀洰鍓嶆槸md5" +// @Param filename formData string true "鏂囦欢鍚嶇О" +// @Success 200 {string} json "{"code":200, msg:"", success:true}" +// @Failure 500 {string} json "{"code":500, msg:"", success:false}" +// @Router /data/api-v/sdk/showInstallInfo [post] +func (sc SdkController) ShowInstallInfo(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply { + identifier := c.Query("identifier") + filename := c.Query("filename") + logger.Debug("showInstallInfo identifier:", identifier, "filename:", filename) + if identifier == "" || filename == "" { + return &bhomeclient.Reply{Success: false, Msg: "鍙傛暟鏈夎"} + } + var sv service.SdkInstallService + b, d, err := sv.ShowInstallInfo(identifier, filename) + if b { + return &bhomeclient.Reply{Success: true, Data: d} + } else { + return &bhomeclient.Reply{Msg: err.Error()} + } +} + +// @Security ApiKeyAuth +// @Summary 涓婁紶瀹屾垚寮�濮嬪畨瑁� +// @Description 涓婁紶瀹屾垚寮�濮嬪畨瑁� +// @Produce json +// @Tags 绠楁硶 +// @Param identifier formData string true "鏁翠釜鏂囦欢鐨勫敮涓�鏍囪瘑锛岀洰鍓嶆槸md5" +// @Param filename formData string true "鏂囦欢鍚嶇О" +// @Success 200 {string} json "{"code":200, msg:"", success:true}" +// @Failure 500 {string} json "{"code":500, msg:"", success:false}" +// @Router /data/api-v/sdk/install [post] +func (sc SdkController) Install(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply { + identifier := c.Query("identifier") + filename := c.Query("filename") + logger.Debug("showInstallInfo identifier:", identifier, "filename:", filename) + if identifier == "" || filename == "" { + return &bhomeclient.Reply{Success: false, Msg: "鍙傛暟鏈夎"} + } + + var sv service.SdkInstallService + if b, err := sv.PackInstall(identifier, filename, h); b { + return &bhomeclient.Reply{Success: true, Msg: "瀹夎鎴愬姛"} + } else { + return &bhomeclient.Reply{Msg: err.Error()} + } +} + +// @Security ApiKeyAuth +// @Summary 鍗歌浇绠楁硶 +// @Description 鍗歌浇绠楁硶 +// @Produce json +// @Tags 绠楁硶 +// @Param reqBody body controllers.DelSdk true "鍗歌浇鍙傛暟" +// @Success 200 {string} json "{"code":200, msg:"", success:true}" +// @Failure 500 {string} json "{"code":500, msg:"", success:false}" +// @Router /data/api-v/sdk/unInstall [post] +func (sc SdkController) UnInstall(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply { + var reqBody DelSdk + err := c.BindJSON(&reqBody) + if err != nil { + return &bhomeclient.Reply{Success: false, Msg: "鍙傛暟鏈夎"} + } + var sdkE models.Sdk + if sdkE.DeleteById(reqBody.SdkId) { + pMsg := protomsg.DbChangeMessage{ + Table: protomsg.TableChanged_T_Sdk, + Action: protomsg.DbAction_Delete, + } + pb, _ := json.Marshal(pMsg) + h.Bk.Publish(service.ProcName, pb) + return &bhomeclient.Reply{Success: true, Msg: "鍗歌浇鎴愬姛"} + } else { + return &bhomeclient.Reply{Success: false, Msg: "鍗歌浇澶辫触"} + } +} + +// @Security ApiKeyAuth +// @Summary 浠庡晢鍩庝笅杞芥垨鍗囩骇绠楁硶 +// @Description 浠庡晢鍩庝笅杞芥垨鍗囩骇绠楁硶 +// @Produce json +// @Tags 绠楁硶 +// @Param path query string true "绠楁硶id" +// @Success 200 {string} json "{"code":200, msg:"", success:true}" +// @Failure 500 {string} json "{"code":500, msg:"", success:false}" +// @Router /data/api-v/sdk/sdkDownload [get] +func (sc SdkController) SdkDownLoad(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply { + id := c.Query("path") + if id == "" { + return &bhomeclient.Reply{Msg: "涓嬭浇绠楁硶鍙傛暟鏈夎"} + } + + if service.IsInstalling(id) { + return &bhomeclient.Reply{Success: true, Msg: "瀹夎涓紝璇风◢鍊�..."} + } + + if b, err := service.DownloadOrUpgrade(id, h); b { + return &bhomeclient.Reply{Success: true, Msg: "绠楁硶瀹夎鎴愬姛"} + } else { + return &bhomeclient.Reply{Msg: err.Error()} + } +} + +// @Security ApiKeyAuth +// @Summary 搴旂敤涓績涓湭璐拱鐨勭畻娉曞垪琛� +// @Description 搴旂敤涓績涓湭璐拱鐨勭畻娉曞垪琛� +// @Produce json +// @Tags 绠楁硶 +// @Success 200 {string} json "{"code":200, msg:"", success:true}" +// @Failure 500 {string} json "{"code":500, msg:"", success:false}" +// @Router /data/api-v/sdk/buyList [get] +func (sc SdkController) BuyList(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply { + sdkName := c.Query("sdkName") + logger.Debug("BuyList sdkName:", sdkName) + var sv service.SdkInstallService + list := sv.GetBuyList(sdkName) + if list == nil { + list = make([]service.SdkWithArg, 0) + } + + return &bhomeclient.Reply{Success: true, Data: list} +} + +// @Security ApiKeyAuth +// @Summary 浣跨敤婵�娲荤爜婵�娲诲畨瑁呯畻娉� +// @Description 浣跨敤婵�娲荤爜婵�娲诲畨瑁呯畻娉� +// @Produce json +// @Tags 绠楁硶 +// @Param code query string true "婵�娲荤爜" +// @Param sdkId query string true "绠楁硶id" +// @Success 200 {string} json "{"code":200, msg:"", success:true}" +// @Failure 500 {string} json "{"code":500, msg:"", success:false}" +// @Router /data/api-v/sdk/active [get] +func (sc SdkController) Active(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply { + cod := c.Query("code") + sdkId := c.Query("sdkId") + if sdkId == "" { + return &bhomeclient.Reply{Msg: "绠楁硶id涓嶈兘涓虹┖"} + } + var sv service.SdkInstallService + d, err := sv.Active(cod, sdkId) + if err == nil { + // 婵�娲绘垚鍔� + var sdk models.Sdk + if err := sdk.UpdateCode(sdkId, cod); err != nil { + return &bhomeclient.Reply{Msg: err.Error()} + } + return &bhomeclient.Reply{Success: true, Data: d} + } else { + return &bhomeclient.Reply{Msg: err.Error()} + } +} + +type DelSdk struct { + SdkId string `json:"sdkId" binding:"required"` +} diff --git a/appcenter-service/controllers/sdkArg.go b/appcenter-service/controllers/sdkArg.go new file mode 100644 index 0000000..fd99075 --- /dev/null +++ b/appcenter-service/controllers/sdkArg.go @@ -0,0 +1,30 @@ +package controllers + +import ( + "basic.com/valib/bhomeclient.git" + "vamicro/appcenter-service/models" +) + +type SdkArgController struct { + +} + +// @Summary 鑾峰彇绠楁硶鍙傛暟 +// @Description 鑾峰彇绠楁硶鍙傛暟 +// @Produce json +// @Tags 绠楁硶鍙傛暟 +// @Param sdkId query string true "绠楁硶id" +// @Param scope query string true "绠楁硶鍙傛暟鑼冨洿(TASKRULE銆丆AMERARULE)" +// @Success 200 {string} json "{"code":200, msg:"璇锋眰澶勭悊鎴愬姛",data:"",success:true}" +// @Failure 500 {string} json "{"code":500, msg:"璇锋眰澶辫触",data:"",success:false}" +// @Router /data/api-v/sdkArg/getSdkArgs [get] +func (controller SdkArgController) GetSdkArgs(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply{ + sdkId := c.Query("sdkId") + scope := c.Query("scope") + if sdkId== "" || scope == "" || (scope !=models.SCOPE_TASKRULE && scope !=models.SCOPE_CAMERARULE){ + return &bhomeclient.Reply{Success: false, Msg: "鍙傛暟鏈夎"} + } + var sdk models.Sdk + args := sdk.GetSdkArgs(sdkId, scope) + return &bhomeclient.Reply{Success: true, Data: args} +} \ No newline at end of file diff --git a/appcenter-service/main.go b/appcenter-service/main.go new file mode 100644 index 0000000..2cf2c2d --- /dev/null +++ b/appcenter-service/main.go @@ -0,0 +1,132 @@ +package main + +import ( + "basic.com/valib/bhomeclient.git" + "basic.com/valib/bhomedbapi.git" + "basic.com/valib/logger.git" + "basic.com/valib/version.git" + "context" + "flag" + "net/http" + _ "net/http/pprof" + "os" + "os/signal" + "syscall" + "vamicro/appcenter-service/controllers" + "vamicro/appcenter-service/models" + "vamicro/appcenter-service/service" + "vamicro/config" + versionControlS "vamicro/version-control/service" +) + +var ( + procName = service.ProcName + proc = &bhomeclient.ProcInfo{ + Name: procName, //杩涚▼鍚嶇О + ID: procName, //杩涚▼id + Info: "", //杩涚▼鐨勬弿杩颁俊鎭紝鐢ㄤ簬鍖哄垎鍚屼竴杩涚▼鍚嶇О涓嬪涓繘绋� + } + env = flag.String("e", "pro", "") +) + +func init() { + flag.Parse() + vaversion.Usage() + + config.Init(*env) + // 鏃ュ織鍒濆鍖� + var logFile = config.LogConf.Path + "vamicro-"+procName+".log" + logger.InitLogger(logFile, config.LogConf.Level, config.LogConf.MaxSize, config.LogConf.MaxBackups, config.LogConf.MaxAge) + logger.Info("log init success !") +} + +func main(){ + models.Init() + defer models.CloseDB() + + ctx, cancel := context.WithCancel(context.Background()) + fm,pubTopics := initFuncMap() + var reg = &bhomeclient.RegisterInfo { + Proc: *proc, + Channel: nil, + PubTopic: pubTopics, + SubTopic: []string{versionControlS.SysUpdateConfigTopic}, + } + + q := make(chan os.Signal, 1) + signal.Notify(q, os.Interrupt, os.Kill, syscall.SIGTERM) + + ms, err := bhomeclient.NewMicroNode(ctx, q, config.Server.AnalyServerId, reg, logger.Debug) + if err !=nil { + return + } + + bhomedbapi.InitLog(logger.Debug) + bhomedbapi.InitGetNetNode(ms.GetLocalNetNodeByTopic) + bhomedbapi.InitDoReq(ms.RequestOnly) + go ms.StartServer(fm) + go handleSubMsg(ctx, ms) + go service.SelfUpdateStart(ctx) //鑷姩鏇存柊 + go service.NoticeTick(ctx)//鏇存柊鎻愰啋 + // pprof 鐢ㄤ簬鍒嗘瀽鎬ц兘 + go func() { + logger.Info(http.ListenAndServe("0.0.0.0:7073", nil)) + }() + + <-q + ms.DeRegister() + cancel() + ms.Free() +} + +const urlPrefix = "/data/api-v" +func initFuncMap() (map[string]bhomeclient.MicroFunc,[]string) { + funcMap := make(map[string]bhomeclient.MicroFunc) + sc := new(controllers.SdkController) + sa := new(controllers.SdkArgController) + ac := new(controllers.AppController) + + funcMap[urlPrefix+"/sdk/register"] = sc.Register + funcMap[urlPrefix+"/sdk/getById"] = sc.GetById + funcMap[urlPrefix+"/sdk/findAllSdk"] = sc.FindAllSdk + funcMap[urlPrefix+"/sdk/getAllSdkChanSet"] = sc.GetAllSdkChanSet + funcMap[urlPrefix+"/sdk/findByTaskId"] = sc.FindByTaskId + funcMap[urlPrefix+"/sdk/updateSdkArgConfig"] = sc.UpdateSdkArgConfig + funcMap[urlPrefix+"/sdk/updateSdkChanSet"] = sc.UpdateSdkChanSet + funcMap[urlPrefix+"/sdkArg/getSdkArgs"] = sa.GetSdkArgs + funcMap[urlPrefix+"/sdk/upload"] = sc.Upload + funcMap[urlPrefix+"/sdk/uploadPack"] = sc.UploadPack + funcMap[urlPrefix+"/sdk/install"] = sc.Install + funcMap[urlPrefix+"/sdk/unInstall"] = sc.UnInstall + funcMap[urlPrefix+"/sdk/buyList"] = sc.BuyList + funcMap[urlPrefix+"/sdk/active"] = sc.Active + funcMap[urlPrefix+"/sdk/sdkDownload"] = sc.SdkDownLoad + funcMap[urlPrefix+"/sdk/showInstallInfo"] = sc.ShowInstallInfo + + funcMap[urlPrefix+"/app/findAllApp"] = ac.FindAll + funcMap[urlPrefix+"/app/getAppInfo"] = ac.GetAppInfo + funcMap[urlPrefix+"/app/unInstall"] = ac.UnInstall + funcMap[urlPrefix+"/app/buyList"] = ac.BuyList + funcMap[urlPrefix+"/app/active"] = ac.Active + funcMap[urlPrefix+"/app/detail"] = ac.Detail + funcMap[urlPrefix+"/app/upgrade/notice"] = ac.UpgradeNotice + funcMap[urlPrefix+"/app/upgrade/notice/delay"] = ac.DelayNotice + + var pubTopics []string + for key,_ := range funcMap { + pubTopics = append(pubTopics, key) + } + return funcMap, pubTopics +} + +func handleSubMsg(ctx context.Context, ms *bhomeclient.MicroNode) { + for { + select { + case <-ctx.Done(): + return + case msg := <-ms.SubCh: + logger.Debug("handleSubMsg recv sub msg:", msg) + service.PersistentWrapper(string(msg.Topic), msg.Data) + } + } +} \ No newline at end of file diff --git a/appcenter-service/models/app.go b/appcenter-service/models/app.go new file mode 100644 index 0000000..a877d69 --- /dev/null +++ b/appcenter-service/models/app.go @@ -0,0 +1,152 @@ +package models + +type App struct { + Id string `gorm:"column:id;primary_key;type:varchar(50);unique;not null;" json:"id"` + Name string `gorm:"column:name" json:"name"` //涓枃鍚嶇О,eg:绠楀姏绠$悊 + Package string `gorm:"column:package;unique;not null;" json:"package"` //鑻辨枃鍚嶅瓧 + Type string `gorm:"column:type" json:"type"` //鏂板紑椤甸潰:"1",寮规锛�"2" + Url string `gorm:"column:url" json:"url"` //eg: /view/analysisPower/ + Title string `gorm:"column:title" json:"title"` //鎵撳紑寮规鎴栨柊寮�椤甸潰椤堕儴鏄剧ず + Width int `gorm:"column:width" json:"width"` //瀹氫箟寮规鐨勯粯璁ゅ搴� + Height int `gorm:"column:height" json:"height"` //瀹氫箟寮规鐨勯粯璁ら珮搴� + IconBlob string `gorm:"column:iconBlob" json:"iconBlob"` //鍥剧墖鐨刡ase64 + IconBlob2 string `gorm:"column:iconBlob2" json:"iconBlob2"` //绗簩濂楀浘鐗囩殑base64 + Icon string `gorm:"column:icon" json:"icon"` //鍥剧墖鐩稿璺緞鎴栬�呮槸iconfont + Version string `gorm:"column:version;default:''" json:"version"` + + CreateTime string `gorm:"column:create_time" json:"create_time"` + CreateBy string `gorm:"column:create_by" json:"create_by"` + UpdateTime string `gorm:"column:update_time" json:"update_time"` + UpdateBy string `gorm:"column:update_by" json:"update_by"` + IsDefault bool `gorm:"column:isDefault;default:0;" json:"isDefault"` + + ProcName string `gorm:"column:procName" json:"procName"` //搴旂敤鐨勫悗绔湇鍔″悕锛岀郴缁熺洃鎺у櫒涓渶瑕佺敤,鐢卞晢鍩庣缁存姢 + + Price float32 `json:"price"` //鍟嗗煄绔环鏍� + CanUpOrIns bool `json:"canUpOrIns"` //鏄惁鍙畨瑁呮垨鍗囩骇 + Platforms []PtIns `json:"platforms"` //鍙�傞厤鐨勫钩鍙颁俊鎭� + ActivateCode string `gorm:"column:activateCode" json:"activateCode"` // 婵�娲荤爜 +} + +type PtIns struct { + Platform string `json:"platform"` + Version string `json:"version"` + VGpus string `json:"vGpus"` +} + +func (App) TableName() string { + return "t_app" +} + +func (a *App) SelectById(id string) (rows int64, err error) { + dbSelect := db.Table(a.TableName()).Where("id=?", id).First(&a) + if dbSelect.Error != nil || dbSelect.RowsAffected == 0 { + return 0, dbSelect.Error + } + return dbSelect.RowsAffected, nil +} + +func (a *App) Save() (err error) { + tx := db.Table(a.TableName()).Begin() + if tx.Error != nil { + return tx.Error + } + + if err := tx.Save(&a).Error; err != nil { + tx.Rollback() + return err + } + + err = tx.Commit().Error + if err == nil { + return nil + } + return err +} + +func (a *App) Update() (result bool, err error) { + entity := App{} + + rows, err := entity.SelectById(a.Id) + if err != nil { + return false, err + } + if rows == 0 { + return false, err + } + if err := db.Table("t_app").Where("id=?", a.Id).Update(&a).Error; err != nil { + return false, err + } + return true, nil +} + +func (a *App) UpdateCode(appId, code string) (err error) { + if err := db.Table("t_app").Where("id=?", appId).Update("activateCode", code).Error; err != nil { + return err + } + return nil +} + +func (a *App) DeleteById(id string) (result bool) { + updateResult := db.Exec("delete from "+a.TableName()+" where id=?", id) + if updateResult.Error != nil || updateResult.RowsAffected == 0 { + return false + } + return true +} + +func (a *App) FindAll(name string) (rows []App, err error) { + mutex.Lock() + defer mutex.Unlock() + + if name != "" { + if err := db.Table(a.TableName()).Where("name like ?", name).Order("create_time asc").Find(&rows).Error; err != nil { + return nil, err + } + return rows, nil + } else { + if err := db.Table(a.TableName()).Find(&rows).Error; err != nil { + return nil, err + } + return rows, nil + } +} + +func (a *App) FindAllMap() map[string]App { + m := make(map[string]App) + list, _ := a.FindAll("") + if list != nil { + for _, s := range list { + m[s.Id] = s + } + } + return m +} + +func (a *App) Total(inputText string) (int, error) { + var total int + sql := "select count(1) as total from " + a.TableName() + " where 1=1" + if inputText != "" { + sql += " and name like '%" + inputText + "%'" + } + err := db.Raw(sql).Count(&total).Error + if err != nil { + return 0, err + } + return total, nil +} + +func (a *App) FindByPage(inputText string, page int, size int) (list []App, err error) { + offset := (page - 1) * size + sql := "select * from " + a.TableName() + " where 1=1" + + if inputText != "" { + sql += " and name like '%" + inputText + "%'" + } + sql += " order by create_time desc" + err = db.Raw(sql).Offset(offset).Limit(size).Find(&list).Error + if err != nil { + return nil, err + } + return list, nil +} diff --git a/appcenter-service/models/db.go b/appcenter-service/models/db.go new file mode 100644 index 0000000..bb96b0d --- /dev/null +++ b/appcenter-service/models/db.go @@ -0,0 +1,49 @@ +package models + +import ( + "basic.com/valib/logger.git" + "github.com/jinzhu/gorm" + _ "github.com/jinzhu/gorm/dialects/sqlite" + "strings" + "sync" + "vamicro/config" +) + +var db *gorm.DB +var err error +var mutex sync.Mutex + +// Init creates a connection to mysql database and +// migrates any new models +func Init() { + db, err = gorm.Open(config.DBconf.Name, "../config/appcenter.db") + if err != nil { + logger.Debug("db open error ", err) + } + db.LogMode(true) + //db.SetLogger(&DbLogger{}) + db.AutoMigrate(&Sdk{}, &SdkArgEntity{}, &SdkChanSet{}, &Dictionary{}, &App{}) + + //娣诲姞榛樿鐨勯�氶亾璁剧疆 + addSdkChanSet() +} + +func addSdkChanSet() { + var sqls []string + sqls = append(sqls, "INSERT INTO sdk_chan_set(`sdk_type`,`chan_num`) SELECT 'Yolo',3 where not exists (select 1 from sdk_chan_set where sdk_type='Yolo');") + sqls = append(sqls, "INSERT INTO sdk_chan_set(`sdk_type`,`chan_num`) SELECT 'FaceDetect',9 where not exists (select 1 from sdk_chan_set where sdk_type='FaceDetect');") + sqls = append(sqls, "INSERT INTO sdk_chan_set(`sdk_type`,`chan_num`) SELECT 'Plate',9 where not exists (select 1 from sdk_chan_set where sdk_type='Plate');") + sqls = append(sqls, "INSERT INTO sdk_chan_set(`sdk_type`,`chan_num`) SELECT 'HumanTrack',9 where not exists (select 1 from sdk_chan_set where sdk_type='HumanTrack');") + sqls = append(sqls, "INSERT INTO sdk_chan_set(`sdk_type`,`chan_num`) SELECT 'FaceExtract',200 where not exists (select 1 from sdk_chan_set where sdk_type='FaceExtract');") + sqls = append(sqls, "INSERT INTO sdk_chan_set(`sdk_type`,`chan_num`) SELECT 'FaceCompare',2000 where not exists (select 1 from sdk_chan_set where sdk_type='FaceCompare');") + db.Exec(strings.Join(sqls, "")) +} + +// GetDB ... +func GetDB() *gorm.DB { + return db +} + +func CloseDB() { + db.Close() +} diff --git a/appcenter-service/models/dictionary.go b/appcenter-service/models/dictionary.go new file mode 100644 index 0000000..c274702 --- /dev/null +++ b/appcenter-service/models/dictionary.go @@ -0,0 +1,89 @@ +package models + +type Dictionary struct { + Id string `gorm:"primary_key" json:"id"` + Value string `gorm:"column:value" json:"value"` //鍊� + Name string `gorm:"column:name" json:"name"` //鍚嶇О + Type string `gorm:"column:type" json:"type"` //绫诲瀷 + Description string `gorm:"column:description" json:"description"` //鎻忚堪 + Sort int `gorm:"column:sort;default:1" json:"sort"` + ParentId string `gorm:"column:parent_id;default:0" json:"parent_id"` +} + +const ( + TYPE_RULECOMPUTEBETWEEN = "RULECOMPUTEBETWEEN" + TYPE_RULECOMPUTE = "RULECOMPUTE" + TYPE_TYPECOMPUTE = "TYPECOMPUTE" + TYPE_ALARMLEVEL = "ALARMLEVEL" + TYPE_EVENTRULETOPIC = "EVENTRULETOPIC" //浜嬩欢鎺ㄩ�佷竴绾т富棰� + TYPE_MONITORLEVEL = "MONITORLEVEL" + TYPE_PERSONSEX = "PERSONSEX" + TYPE_AGEDESC = "AGEDESC" + TYPE_PERSONRACE = "PERSONRACE" + TYPE_EVENTTYPECOMPUTE = "EVENTTYPECOMPUTE" +) + +const ( + EVENTRULETOPIC_CAMERA = "camera" //鎽勫儚鏈� + EVENTRULETOPIC_CAMERA_NAME = "name" + EVENTRULETOPIC_CAMERA_ADDR = "addr" + + EVENTRULETOPIC_DBTABLE = "dbtable" //搴曞簱 + EVENTRULETOPIC_TASK = "task" //浠诲姟 + + EVENTRULETOPIC_PERSON = "person" //浜哄憳 + EVENTRULETOPIC_PERSON_MONITORLEVEL = "monitorLevel" //绛夌骇 + EVENTRULETOPIC_PERSON_AGE = "age" //骞撮緞 + EVENTRULETOPIC_PERSON_SEX = "sex" //鎬у埆 + EVENTRULETOPIC_PERSON_RACE = "race" //绉嶆棌 + EVENTRULETOPIC_PERSON_OTHREINFO = "otherInfo" //鍏朵粬淇℃伅 + + EVENTRULETOPIC_ALARMLEVEL = "alarmLevel" //鎶ヨ绛夌骇 +) + +func (Dictionary) TableName() string { + return "dictionary" +} + +func (dic *Dictionary) FindAll() (dics []Dictionary, err error) { + if err := db.Table("dictionary").Find(&dics).Error; err != nil { + return nil, err + } + return dics, nil +} + +func (dic *Dictionary) FindByType(dicType string) (dics []Dictionary, err error) { + if err := db.Table("dictionary").Where("type=?", dicType).Scan(&dics).Error; err != nil { + return nil, err + } + return dics, nil +} + +func (dic *Dictionary) FindByParentId(parentId string) (dics []Dictionary, err error) { + if err := db.Table("dictionary").Where("parent_id=?", parentId).Scan(&dics).Error; err != nil { + return nil, err + } + return dics, nil +} + +func (dic *Dictionary) Insert() (bool, error) { + if err := db.Table("dictionary").Create(&dic).Error; err != nil { + return false, err + } + return true, nil +} + +func (dic *Dictionary) Update() (bool, error) { + if err := db.Table("dictionary").Update(&dic).Error; err != nil { + return false, err + } + return true, nil +} + +func (dic *Dictionary) SelectById(id string) (bool, error) { + result := db.Table("dictionary").Where("id=?", id).First(&dic) + if result.Error != nil { + return false, err + } + return result.RecordNotFound(), nil +} diff --git a/appcenter-service/models/sdk.go b/appcenter-service/models/sdk.go new file mode 100644 index 0000000..8e4e295 --- /dev/null +++ b/appcenter-service/models/sdk.go @@ -0,0 +1,224 @@ +package models + +import ( + "strings" + "time" + + "basic.com/pubsub/protomsg.git" + "basic.com/valib/logger.git" +) + +const ( + RecordNotFound = "record not found" +) + +type Sdk struct { + Id string `gorm:"column:id;primary_key" json:"id"` + IpcId string `gorm:"column:ipc_id" json:"ipc_id"` //鐪熸鐨勭畻娉昳d(瀵逛簬yolo鏉ヨ锛屽彧鍒涘缓涓�涓猧pc) + SdkType string `gorm:"column:sdk_type" json:"sdk_type"` //浜鸿劯妫�娴嬶細FaceDetect,浜鸿劯鎻愬彇锛欶aceExtract,浜鸿劯姣斿锛欶aceCompare,琛屼负锛歒olo + SdkName string `gorm:"column:sdk_name" json:"sdk_name" example:"浜鸿劯妫�娴�"` //绠楁硶鍚嶇О + Icon string `gorm:"column:icon" json:"icon"` //绠楁硶鍥炬爣 + Url string `gorm:"column:url" json:"url" example:"http://ip:port/govideo/sdk/1"` //绠楁硶涓嬭浇鍦板潃 + CreateTime string `gorm:"column:create_time" json:"create_time"` + CreateBy string `gorm:"column:create_by" json:"create_by"` + UpdateTime string `gorm:"column:update_time" json:"update_time"` + Enable bool `gorm:"column:enable;default:1" json:"enable"` //鏄惁鍚敤 + DelFlag int `gorm:"column:del_flag;default:0" json:"del_flag"` //閫昏緫鍒犻櫎 + IconBlob string `gorm:"column:iconBlob;type:text;" json:"iconBlob"` //鍥剧墖 + IconBlob2 string `gorm:"column:iconBlob2;type:text;" json:"iconBlob2"` //绗簩濂楀浘鐗� + Version string `gorm:"column:version;type:varchar(50);default:'1.0.0';" json:"version"` //鐗堟湰鍙� + EnTrack bool `gorm:"column:enTrack;default:1" json:"enTrack"` //鏄惁寮�鍚窡韪� + ArgDef string `gorm:"column:argDef" json:"argDef"` //绠楁硶鍙傛暟榛樿閰嶇疆 + RuleSo string `gorm:"column:rule_so" json:"rule_so"` //瑙勫垯鐢ㄧ殑so鍚嶇О + + AuthState3rd int `gorm:"column:authState3rd;default:0" json:"authState3rd"` //绗笁鏂规巿鏉冪姸鎬� 0:鏈巿鏉冿紝1锛氬凡鎺堟潈锛�2锛氬凡杩囨湡 + MacCode3rd string `gorm:"column:macCode3rd" json:"macCode3rd"` //绗笁鏂圭敓鎴愮殑鏈哄櫒鐮� + License3rd string `gorm:"column:license3rd" json:"license3rd"` //绗笁鏂规巿鏉冪爜 + Expire3rd string `gorm:"column:expire3rd" json:"expire3rd"` //杩囨湡鏃堕棿 + + BaseVersion string `gorm:"column:baseVersion" json:"baseVersion"` //鍩虹绠楁硶鐗堟湰 + Price float32 `json:"price"` //鍟嗗煄绔环鏍� + ActivateCode string `gorm:"column:activateCode" json:"activateCode"` // 婵�娲荤爜 +} + +const ( + AuthState3rd_UnAuth = 0 + AuthState3rd_Authed = 1 + AuthState3rd_expired = 2 +) + +func (sdk Sdk) Copy2ProtoSdk() protomsg.Sdk { + return protomsg.Sdk{ + Id: sdk.Id, + IpcId: sdk.IpcId, + SdkType: sdk.SdkType, + SdkName: sdk.SdkName, + Icon: sdk.Icon, + Url: sdk.Url, + CreateTime: sdk.CreateTime, + UpdateTime: sdk.UpdateTime, + CreateBy: sdk.CreateBy, + Enable: sdk.Enable, + DelFlag: int32(sdk.DelFlag), + IconBlob: sdk.IconBlob, + IconBlob2: sdk.IconBlob2, + Version: sdk.Version, + EnTrack: sdk.EnTrack, + ArgDef: sdk.ArgDef, + RuleSo: sdk.RuleSo, + } +} + +func (Sdk) TableName() string { + return "sdks" +} + +// 鏍规嵁绠楁硶id鏌ユ壘绠楁硶淇℃伅 +func (sdk *Sdk) SelectById(id string) (rows int64, err error) { + dbSelect := db.Table("sdks").Where("id=?", id).First(&sdk) + if dbSelect.Error != nil && dbSelect.Error.Error() != RecordNotFound { + return 0, dbSelect.Error + } + return dbSelect.RowsAffected, nil +} + +func (sdk *Sdk) SelectBySdkType(sdkType string) (exist bool, model Sdk) { + dbSelect := db.Table("sdks").Where("sdk_type=?", sdkType).First(&model) + if dbSelect.Error != nil || dbSelect.RowsAffected == 0 { + return false, model + } + return dbSelect.RecordNotFound(), model +} + +// 鏌ユ壘鎵�鏈夌畻娉� +func (sdk *Sdk) FindAll(name string) (rows []Sdk, err error) { + mutex.Lock() + defer mutex.Unlock() + + t := time.Now() + defer func() { + logger.Debugf("FindAll costTime=%v, name=%v", time.Since(t), name) + }() + + if name != "" { + if err := db.Table("sdks").Where("sdk_name like ?", name).Order("sdk_name asc").Find(&rows).Error; err != nil { + logger.Debug("err: ", err) + return nil, err + } + return rows, nil + } else { + if err := db.Table("sdks").Order("sdk_name asc").Find(&rows).Error; err != nil { + logger.Debug("err: ", err) + return nil, err + } + return rows, nil + } +} + +func (sdk *Sdk) FindAllMap() map[string]Sdk { + m := make(map[string]Sdk) + rows, e := sdk.FindAll("") + if e == nil && rows != nil { + for _, r := range rows { + m[r.Id] = r + } + } + return m +} + +// 鏍规嵁浠诲姟id鏌ユ壘鎵�鏈夌殑绠楁硶 +func (sdk *Sdk) FindByTaskId(taskId string) (sdks []Sdk, err error) { + if err := db.Raw("select * from sdks where id in (select sdkid from task_sdks where taskid=? order by sort asc)", taskId).Scan(&sdks).Error; err != nil { + return sdks, err + } + + return sdks, nil +} + +// 绠楁硶鎻掑叆 +func (sdk *Sdk) Insert() (err error) { + tx := db.Table("sdks").Begin() + if tx.Error != nil { + return tx.Error + } + + if err := tx.Create(&sdk).Error; err != nil { + tx.Rollback() + return err + } + + err = tx.Commit().Error + if err == nil { + return nil + } + return err +} + +// 绠楁硶鏇存柊 +func (sdk *Sdk) Update() (result bool, err error) { + + dbSdk := Sdk{} + + rows, err := dbSdk.SelectById(sdk.Id) + if err != nil { + return false, err + } + if rows == 0 { + return false, err //鏁版嵁搴撹繖鏉¤褰曚笉瀛樺湪 + } + if err := db.Table(sdk.TableName()).Where("id=?", sdk.Id).Update(&sdk).Error; err != nil { + return false, err + } + + return true, nil +} + +func (sdk *Sdk) UpdateCode(sdkId, code string) (err error) { + if err := db.Table(sdk.TableName()).Where("id=?", sdkId).Update("activateCode", code).Error; err != nil { + return err + } + return nil +} + +func (sdk *Sdk) DeleteById(id string) (result bool) { + //鍒犻櫎绠楁硶闇�瑕佸叧鑱斿垹闄ゆ墍鏈変笌绠楁硶鐩稿叧鐨勪换鍔′俊鎭� + updateResult := db.Exec("delete from sdks where id=?", id) + if updateResult.Error != nil || updateResult.RowsAffected == 0 { + return false + } + + return true +} + +// 鏍规嵁鍙傛暟鑼冨洿鑾峰彇绠楁硶鍙傛暟鍒楄〃 +func (sdk *Sdk) GetSdkArgs(sdkId string, scope string) []SdkArg { + var sdkArgEntity SdkArgEntity + argArr := make([]SdkArg, 0) + if sdkArgs, err := sdkArgEntity.FindBySdk(sdkId); err == nil { + for _, argEntity := range sdkArgs { + if strings.Contains(argEntity.Scope, scope) { + argArr = append(argArr, SdkArg{ + Alias: argEntity.Alias, + Name: argEntity.Name, + Type: argEntity.Type, + Must: argEntity.Must, + Range: argEntity.Range, + DefaultValue: argEntity.DefaultValue, + DefaultOperator: argEntity.DefaultOperator, + Sort: argEntity.Sort, + Unit: argEntity.Unit, + ArgType: argEntity.ArgType, + }) + } + } + } + return argArr +} + +func (sdk *Sdk) Update3rdLicense(sdkId string, lce3rd string, state3rd int) bool { + updateResult := db.Exec("update "+sdk.TableName()+" set license3rd=?,authState3rd=? where id=?", lce3rd, state3rd, sdkId) + if updateResult.Error != nil || updateResult.RowsAffected == 0 { + return false + } + return true +} diff --git a/appcenter-service/models/sdkArg.go b/appcenter-service/models/sdkArg.go new file mode 100644 index 0000000..c16c00b --- /dev/null +++ b/appcenter-service/models/sdkArg.go @@ -0,0 +1,52 @@ +package models + +type SdkArgEntity struct { + Id string `gorm:"primary_key;column:id" json:"id"` + SdkId string `gorm:"column:sdk_id" json:"sdk_id"` + Scope string `gorm:"column:scope" json:"scope"` + SdkArg +} + +//绠楁硶鍙傛暟瀹氫箟 +type SdkArg struct { + Alias string `gorm:"column:alias" json:"alias"` //鍙傛暟鐨勫埆鍚� + Name string `gorm:"column:name" json:"name"` //鍙傛暟鍚嶇О + Type string `gorm:"column:type" json:"type"` //鍙傛暟绫诲瀷(鏁存暟锛屽瓧绗︿覆鎴栨暟缁�) + ArgType string `gorm:"column:arg_type" json:"arg_type"` + Must bool `gorm:"column:must" json:"must"` //鏄惁蹇呭~ + Unit string `gorm:"column:unit" json:"unit"` //鍗曚綅 + Range string `gorm:"column:range" json:"range"` //鍊肩殑鑼冨洿锛宔g锛�0,100琛ㄧず浠�0鍒�100 + DefaultValue string `gorm:"column:default_value" json:"default_value"` + DefaultOperator string `gorm:"column:default_operator" json:"default_operator"` + Sort int `gorm:"column:sort;default:1" json:"sort"` //鍙傛暟椤哄簭 +} + +const ( + SCOPE_CAMERARULE ="CAMERARULE"//鍦ㄦ憚鍍忔満瑙勫垯閰嶇疆椤甸潰鏄剧ず鐨勫弬鏁� + SCOPE_TASKRULE = "TASKRULE"//鍦ㄤ换鍔$畻娉曢厤缃〉闈㈡樉绀虹殑鍙傛暟 +) + +func (SdkArgEntity) TableName() string { + return "sdk_arg" +} + +func (entity *SdkArgEntity) Insert() (bool,error){ + if err :=db.Table("sdk_arg").Create(&entity).Error;err!=nil { + return false,err + } + return true,nil +} +func (entity *SdkArgEntity) Update() (bool,error) { + if err :=db.Table("sdk_arg").Update(&entity).Error;err!=nil { + return false,err + } + return true,nil +} + +//鏍规嵁sdk鍜屽弬鏁拌寖鍥存煡鎵惧搴旂殑绠楁硶鍙傛暟 +func (entity *SdkArgEntity) FindBySdk(sdkId string) (arr []SdkArgEntity,err error) { + if err := db.Table("sdk_arg").Where("sdk_id=?",sdkId).Scan(&arr).Error;err !=nil { + return nil,err + } + return arr,nil +} diff --git a/appcenter-service/models/sdkChanSet.go b/appcenter-service/models/sdkChanSet.go new file mode 100644 index 0000000..9394008 --- /dev/null +++ b/appcenter-service/models/sdkChanSet.go @@ -0,0 +1,61 @@ +package models + +type SdkChanSet struct { + SdkType string `gorm:"column:sdk_type;primary_key" json:"sdk_type"` + ChanNum int `gorm:"column:chan_num;default:16" json:"chan_num"` + ConfidenceInc int `gorm:"column:confidenceInc;default:5" json:"confidenceInc"` + MinMovePos int `gorm:"column:minMovePos;default:1" json:"minMovePos"` +} + +func (SdkChanSet) TableName() string { + return "sdk_chan_set" +} + +func (scs *SdkChanSet) FindAll() (list []SdkChanSet,err error) { + if err := db.Table(scs.TableName()).Find(&list).Error; err != nil { + return []SdkChanSet{}, err + } + return list, nil +} + +func (scs *SdkChanSet) SelectBySdkType(sdkType string) (exist bool,model SdkChanSet){ + dbSelect := db.Table(scs.TableName()).Where("sdk_type=?",sdkType).First(&model) + if dbSelect.Error != nil || dbSelect.RowsAffected == 0 { + return false, model + } + return dbSelect.RecordNotFound(), model +} + +func (scs *SdkChanSet) Insert() (err error) { + tx := db.Table(scs.TableName()).Begin() + if tx.Error != nil { + return tx.Error + } + + if err := tx.Create(&scs).Error; err != nil { + tx.Rollback() + return err + } + + err =tx.Commit().Error + if err == nil{ + return nil + } + return err +} + +func (scs *SdkChanSet) Update() (b bool, err error) { + result :=db.Exec("update ? set chan_num=? where sdk_type=?",scs.TableName(), scs.ChanNum, scs.SdkType) + if result.Error != nil { + return false, err + } + return result.RowsAffected>0,nil +} + +func (scs *SdkChanSet) Delete(sdkType string) bool { + updateResult := db.Exec("delete from ? where sdk_type=?", scs.TableName(),sdkType) + if updateResult.Error != nil || updateResult.RowsAffected == 0 { + return false + } + return true +} \ No newline at end of file diff --git a/appcenter-service/service/AppService.go b/appcenter-service/service/AppService.go new file mode 100644 index 0000000..849764c --- /dev/null +++ b/appcenter-service/service/AppService.go @@ -0,0 +1,317 @@ +package service + +import ( + "basic.com/valib/bhomedbapi.git" + "basic.com/valib/licence.git" + "basic.com/valib/logger.git" + "encoding/json" + "errors" + "strconv" + "time" + "vamicro/appcenter-service/models" + "vamicro/config" + "vamicro/extend/util" +) + +type AppWithShop struct { + models.App + RemoteVersion string `json:"remoteVersion"` //鍟嗗煄浠撳簱鐗堟湰鍙� + Installed bool `json:"installed"` //鏄惁宸插畨瑁� + IsUpgrade bool `json:"isUpgrade"` //鏄惁闇�瑕佸崌绾� + ProgressMsg string `json:"progressMsg"` //瀹夎鎴栧崌绾ц繘搴� +} + +type ProtoApps struct { + List []models.App `json:"list"` +} + +func GetAppList(appName string) []AppWithShop { + var api models.App + insList, err := api.FindAll(appName) //鏈湴宸插畨瑁呮墍鏈夊簲鐢�,甯﹂『搴� + if err != nil { + logger.Debug("findall err:", err.Error()) + } + installedApps := make([]AppWithShop, len(insList)) + localAppIdArr := make([]string, 0) + iv := make(map[string]string) + localAppM := make(map[string]AppWithShop) + for idx, ls := range insList { + siou := AppWithShop{ + Installed: true, + } + + siou.App = ls + localAppM[siou.Package] = siou + installedApps[idx] = siou + iv[ls.Id] = ls.Version + + localAppIdArr = append(localAppIdArr, siou.Id) + } + + nInsApps := make([]AppWithShop, 0) + + //杩滅鍙敤鐨勫簲鐢� + remoteApps := findAllMyApp(localAppIdArr, iv, appName) + if remoteApps != nil { + //logger.Debug("len(remoteApps):", len(remoteApps)) + + for _, ap := range remoteApps { + if v, ok := localAppM[ap.Package]; ok { //鏈湴宸插畨瑁� + ls := v + ls.Name = ap.Name //浠ュ晢鍩庝笂鐨勫悕绉颁负鍑� + + ls.Installed = true + + if ap.CanUpOrIns { //鍒ゆ柇鐗堟湰鍙锋槸鍚﹂渶瑕佸崌绾� + ls.ProgressMsg = "" + ls.IsUpgrade = shouldVersionBeUpgrade(ls.Version, ap.Version) + ls.RemoteVersion = ap.Version //杩滅鐨勭増鏈彿 + + if ip, insB := insIngMap.Load(ap.Id); insB { + iPgs := ip.(*InsProgress) + ls.ProgressMsg = iPgs.Status + strconv.Itoa(iPgs.Progress) + "%" + } + } + localAppM[ap.Package] = ls + for index, es := range installedApps { + if es.Package == ap.Package { + installedApps[index] = ls + break + } + } + } else { //鏈湴鏈畨瑁咃紝闇�瑕佸畨瑁� + if ap.CanUpOrIns { + bIns := AppWithShop{ + RemoteVersion: ap.Version, + IsUpgrade: false, + Installed: false, + ProgressMsg: "", + } + if ip, insB := insIngMap.Load(ap.Id); insB { + iPgs := ip.(*InsProgress) + bIns.ProgressMsg = iPgs.Status + strconv.Itoa(iPgs.Progress) + "%" + } + bIns.App = ap + nInsApps = append(nInsApps, bIns) + } + } + } + } + + return append(installedApps, nInsApps...) +} + +func findAllMyApp(localAppIdArr []string, iv map[string]string, inputTxt string) []models.App { + url := "http://" + util.GetShopUrl() + "/data/api-s/app/myApp" + machineCode := licence.GetMachineCode() + //logger.Debug("url:", url, "machineCode:", machineCode) + paramBody := map[string]interface{}{ + "serverId": config.Server.AnalyServerId, + "machineCode": machineCode, + "localAppIdArr": localAppIdArr, + "iv": iv, + "inputTxt": inputTxt, + } + header := map[string]string{ + "Authorization": token, + } + respBody, err := util.DoPostRequest(url, util.CONTENT_TYPE_JSON, paramBody, nil, header, time.Second*20) + if err != nil { + logger.Debug("DoPostRequest err:", err) + return nil + } + var res bhomedbapi.Result + if err = json.Unmarshal(respBody, &res); err != nil { + logger.Debug("unmarshal err:", err) + return nil + } + bytes, _ := json.Marshal(res.Data) + var pa ProtoApps + if err := json.Unmarshal(bytes, &pa); err != nil { + logger.Debug("unmarshal err:", err) + return nil + } + + return pa.List +} + +// inputTxt杩囨护鏉′欢 +func GetAppBuyList(inputTxt string) []models.App { + url := "http://" + util.GetShopUrl() + "/data/api-s/app/buyList" + machineCode := licence.GetMachineCode() + logger.Debug("url:", url, "machineCode:", machineCode) + + var api models.App + localApps, _ := api.FindAll("") //鏈湴宸插畨瑁呮墍鏈夊簲鐢�,甯﹂『搴� + if localApps == nil { + localApps = make([]models.App, 0) + } + + localAppIdArr := make([]string, 0) + iv := make(map[string]string) + for _, ls := range localApps { + iv[ls.Id] = ls.Version + + localAppIdArr = append(localAppIdArr, ls.Id) + } + paramBody := map[string]interface{}{ + "serverId": config.Server.AnalyServerId, + "machineCode": machineCode, + "localAppIdArr": localAppIdArr, + "iv": iv, + "inputTxt": inputTxt, + } + header := map[string]string{ + "Authorization": token, + } + respBody, err := util.DoPostRequest(url, util.CONTENT_TYPE_JSON, paramBody, nil, header, time.Second*20) + if err != nil { + logger.Debug("DoPostRequest err:", err) + return nil + } + var res bhomedbapi.Result + if err = json.Unmarshal(respBody, &res); err != nil { + logger.Debug("unmarshal err:", err) + return nil + } + bytes, _ := json.Marshal(res.Data) + var ss shopApps + if err := json.Unmarshal(bytes, &ss); err != nil { + logger.Debug("unmarshal err:", err) + return nil + } + + var resultArr []models.App + installAppM := make(map[string]models.App) + + for _, ia := range localApps { + installAppM[ia.Package] = ia + } + + if ss.Apps != nil { + for _, rs := range ss.Apps { + if _, ok := installAppM[rs.Package]; !ok { + resultArr = append(resultArr, rs) + } + } + } + + return resultArr +} + +type shopApps struct { + Apps []models.App `json:"apps"` +} + +func ActiveApp(cod string, appId string) (interface{}, error) { + //浣跨敤婵�娲荤爜婵�娲诲簲鐢� + url := "http://" + util.GetShopUrl() + "/data/api-s/app/activeByAINode" + machineCode := licence.GetMachineCode() + if machineCode == "" { + logger.Debug("鑾峰彇鏈哄櫒鐮佸け璐�") + return nil, errors.New("鑾峰彇鏈哄櫒鐮佸け璐�") + } + paramBody := map[string]interface{}{ + "code": cod, + "appId": appId, + "machineCode": machineCode, + "serverId": config.Server.AnalyServerId, + } + header := map[string]string{ + "Authorization": token, + } + respBody, err := util.DoPostRequest(url, util.CONTENT_TYPE_JSON, paramBody, nil, header, time.Second*60) + if err != nil { + logger.Debug("DoPostRequest err:", err) + return nil, err + } + var res bhomedbapi.Result + if err = json.Unmarshal(respBody, &res); err != nil { + logger.Debug("unmarshal err:", err) + return nil, err + } + if !res.Success { + logger.Debug("res.Data:", res.Data) + return nil, errors.New(res.Msg) + } + + return res.Data, nil +} + +func SaveApp(reqBody models.App) bool { + if reqBody.Id == "" { + return false + } + reqBody.CreateTime = time.Now().Format("2006-01-02 15:04:05") + reqBody.CreateBy = "basic" + reqBody.UpdateBy = "" + reqBody.UpdateTime = "" + if err := reqBody.Save(); err == nil { + return true + } else { + logger.Error("娉ㄥ唽搴旂敤澶辫触:", err.Error()) + } + + return false +} + +func DetailByAppOrSdkId(id string) (interface{}, error) { + url := "http://" + util.GetShopUrl() + "/data/api-s/product/detailByAppOrSdkId" + machineCode := licence.GetMachineCode() + if machineCode == "" { + return nil, errors.New("鑾峰彇鏈哄櫒鐮佸け璐�") + } + paramBody := map[string]interface{}{ + "id": id, + "machineCode": machineCode, + "serverId": config.Server.AnalyServerId, + } + header := map[string]string{ + "Authorization": token, + } + respBody, err := util.DoPostRequest(url, util.CONTENT_TYPE_JSON, paramBody, nil, header, time.Second*10) + if err != nil { + logger.Debug("DoPostRequest err:", err) + return nil, errors.New("璇锋眰鍟嗗煄澶辫触") + } + var res bhomedbapi.Result + if err = json.Unmarshal(respBody, &res); err != nil { + logger.Debug("unmarshal err:", err) + return nil, err + } + if !res.Success { + logger.Debug("res.Data:", res.Data) + return nil, errors.New(res.Msg) + } + var app models.App + row, err := app.SelectById(id) + var mapData = res.Data.(map[string]interface{}) + detail := mapData["detail"].(map[string]interface{}) + detail["installed"] = false + detail["isUpgrade"] = false //闇�瑕佸崌绾� + detail["remoteVersion"] = detail["productVersion"].(string) //闇�瑕佸崌绾� + detail["version"] = "" + if row > 0 { + detail["installed"] = true + if shouldVersionBeUpgrade(app.Version, detail["productVersion"].(string)) { //鍒ゆ柇鐗堟湰鍙锋槸鍚﹂渶瑕佸崌绾� + detail["isUpgrade"] = true //闇�瑕佸崌绾� + detail["remoteVersion"] = detail["productVersion"].(string) //闇�瑕佸崌绾� + } + detail["version"] = app.Version + } else { + var sdk models.Sdk + row, err = sdk.SelectById(id) + if row > 0 { + var mapData = res.Data.(map[string]interface{}) + detail["installed"] = true + detail := mapData["detail"].(map[string]interface{}) + if shouldVersionBeUpgrade(sdk.Version, detail["productVersion"].(string)) { //鍒ゆ柇鐗堟湰鍙锋槸鍚﹂渶瑕佸崌绾� + detail["isUpgrade"] = true //闇�瑕佸崌绾� + detail["remoteVersion"] = detail["productVersion"].(string) //闇�瑕佸崌绾� + } + detail["version"] = sdk.Version + } + } + + return res.Data, nil +} diff --git a/appcenter-service/service/Progress.go b/appcenter-service/service/Progress.go new file mode 100644 index 0000000..64eb033 --- /dev/null +++ b/appcenter-service/service/Progress.go @@ -0,0 +1,222 @@ +package service + +import ( + "basic.com/valib/logger.git" + "errors" + "fmt" + "io" + "net/http" + "os" + "path" + "strconv" + "strings" + "sync" + "vamicro/extend/util" +) + +//姝e湪瀹夎鍒楄〃 +var insIngMap sync.Map + +//鍒ゆ柇鏄惁鍦ㄥ畨瑁呬腑 +func IsInstalling(id string) bool { + _, ok := insIngMap.Load(id) + return ok +} + +//瀹夎杩涘害 +type InsProgress struct { + Status string `json:"status"` + Progress int `json:"progress"` + Size uint64 `json:"size"` + IsDone bool `json:"isDone"` //涓嶇鎴愬姛鎴栬�呭け璐ワ紝鏍囧織鏈瀹夎宸插畬鎴� +} + +const ( + InsStatus_Downloading = "涓嬭浇涓�..." + InsStatus_Err = "瀹夎鍖呬笅杞藉け璐�" + InsStatus_UnPackErr = "瀹夎鍖呰В鍘嬪け璐�" + InsStatus_PackageChecking = "瀹夎鍖呮牎楠屼腑..." + InsStatus_CheckErr = "瀹夎鍖呮牎楠屽け璐�" + InsStatus_Installing = "瀹夎涓�..." + InsStatus_InstallErr = "瀹夎澶辫触" + InsStatus_Done = "宸插畨瑁�" +) + +type WriteCounter struct { + Total uint64 + + iPgs *InsProgress +} + +func (wc *WriteCounter) PrintProgress() { + logger.Info(strings.Repeat(" ", 35)) + //logger.Info("Downloading... ",humanize.Bytes(wc.Total)," complete") + + percent := (wc.Total * 100) / wc.iPgs.Size + + wc.iPgs.Progress = int(percent) +} + +func (wc *WriteCounter) Write(p []byte) (int, error) { + n := len(p) + wc.Total += uint64(n) + wc.PrintProgress() + return n, nil +} + +//涓嬭浇鏂囦欢 +func DownloadFile(fPath string, url string, iProgress *InsProgress) error { + f, err := os.Create(fPath) + if err != nil { + return err + } + resp, err := http.Get(url) + if err != nil { + f.Close() + return err + } + defer resp.Body.Close() + counter := &WriteCounter{ + iPgs: iProgress, + } + if _, err = io.Copy(f, io.TeeReader(resp.Body, counter)); err != nil { + f.Close() + return err + } + fmt.Printf("\n") + f.Close() + //if err = os.Rename(fPath, fPath);err != nil { + // return err + //} + return nil +} + +type downPara struct { + URL string //寰呬笅杞芥枃浠剁殑url + FileName string //寰呬笅杞芥枃浠剁殑鍚嶇О +} + +//procPath 涓嬭浇鍒扮洰鐨勬枃浠跺す +func downloadExtraFile(downloadDir string, extra downPara, fb func(length, downLen int64)) error { + if extra.URL == "" { + return nil + } + + var ( + fsize int64 + buf = make([]byte, 32*1024) + written int64 + ) + + // 鍒涘缓搴旂敤涓嬭浇鐩綍, 鍚庣画浼氱洿鎺ュ壀鍒囧埌缂栬瘧鐜 + //downloadDir := path.Join(procPath, "pre-install-sdks") + //err := dirPing(downloadDir) + //if err != nil { + // logger.Warn("pack error: can not create dir.", err) + // return errors.New("can not create dir") + //} + + downloadPath := path.Join(downloadDir, extra.FileName) + tmpFilePath := downloadPath + ".download" + logger.Debug(tmpFilePath) + //鍒涘缓涓�涓猦ttp client + client := new(http.Client) + //client.Timeout = time.Second * 60 //璁剧疆瓒呮椂鏃堕棿 + //get鏂规硶鑾峰彇璧勬簮 + resp, err := client.Get(extra.URL) + if err != nil { + logger.Error("client.Get err:", err) + return err + } + + //璇诲彇鏈嶅姟鍣ㄨ繑鍥炵殑鏂囦欢澶у皬 + fsize, err = strconv.ParseInt(resp.Header.Get("Content-Length"), 10, 32) + if err != nil { + logger.Error("璇诲彇鏈嶅姟鍣ㄨ繑鍥炴枃浠跺ぇ灏廵rr: ", err) + } + + if isFileExist(downloadPath, fsize) { + return err + } + + logger.Debug("fsize", fsize) + //鍒涘缓鏂囦欢 + file, err := os.Create(tmpFilePath) + if err != nil { + logger.Error("os.Create err: ", err) + return err + } + defer file.Close() + if resp.Body == nil { + return errors.New("body is null") + } + defer resp.Body.Close() + //涓嬮潰鏄� io.copyBuffer() 鐨勭畝鍖栫増鏈� + for { + //璇诲彇bytes + nr, er := resp.Body.Read(buf) + if nr > 0 { + //鍐欏叆bytes + nw, ew := file.Write(buf[0:nr]) + //鏁版嵁闀垮害澶т簬0 + if nw > 0 { + written += int64(nw) + } + //鍐欏叆鍑洪敊 + if ew != nil { + err = ew + break + } + //璇诲彇鏄暟鎹暱搴︿笉绛変簬鍐欏叆鐨勬暟鎹暱搴� + if nr != nw { + err = io.ErrShortWrite + break + } + } + if er != nil { + if er != io.EOF { + err = er + } + break + } + //娌℃湁閿欒浜嗗揩浣跨敤 callback + if fb != nil { + fb(fsize, written) + } + } + logger.Debug(err) + if err == nil { + file.Close() + err = os.Rename(tmpFilePath, downloadPath) + logger.Debug(err) + } + return err +} + +// 濡傛灉鏂囦欢澶逛笉瀛樺湪灏变細鍒涘缓 +func dirPing(path string) error { + if !util.DirExists(path) { + e := os.MkdirAll(path, 00777) + if e != nil { + return e + } + } + return nil +} + +func isFileExist(filename string, filesize int64) bool { + info, err := os.Stat(filename) + if os.IsNotExist(err) { + logger.Debug(info) + return false + } + if filesize == info.Size() { + logger.Debug("瀹夎鍖呭凡瀛樺湪锛�", info.Name(), info.Size(), info.ModTime()) + return true + } + del := os.Remove(filename) + if del != nil { + logger.Error(del) + } + return false +} diff --git a/appcenter-service/service/SdkDownLoad.go b/appcenter-service/service/SdkDownLoad.go new file mode 100644 index 0000000..5656cd7 --- /dev/null +++ b/appcenter-service/service/SdkDownLoad.go @@ -0,0 +1,564 @@ +package service + +import ( + "bytes" + "crypto/md5" + "encoding/hex" + "encoding/json" + "errors" + "fmt" + "io" + "io/ioutil" + "net/http" + "os" + "path" + "path/filepath" + "strconv" + "strings" + "time" + "vamicro/appcenter-service/models" + "vamicro/config" + "vamicro/extend/util" + + "basic.com/valib/bhomeclient.git" + "basic.com/valib/bhomedbapi.git" + "basic.com/valib/licence.git" + "basic.com/valib/logger.git" + "github.com/mitchellh/mapstructure" +) + +// 浠庢湇鍔″櫒涓婁笅杞芥枃浠跺埌涓存椂鐩綍锛屾牎楠屼箣鍚庡鏋滃畬鏁村皢鍏舵嫹璐濆埌鐩爣鐩綍涓� +func DownSo(url string) (bool, error) { + resp, err := http.Get(url) + if err != nil { + logger.Error("鑾峰彇鏂囦欢澶辫触") + return false, err + } + // 浠巖esp涓鍑簔ip鏂囦欢瑙e帇缂╋紝瑙e嚭face.so,face.txt,鐒跺悗鎶婅В鍘嬪嚭鐨剆o鐢∕D5缂栫爜鍑轰竴涓猼emp.txt鏂囦欢锛屼笌瑙e帇鍑虹殑so.txt鏂囦欢姣斿锛� + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + logger.Error("璇诲彇resp.body澶辫触") + return false, err + } + CopyFile(body, "/opt/temp/temp.zip") + util.DeCompress("/opt/temp/temp.zip", "/opt/temp") + fileName := GetFileNameFromUrl(url, false) + md5str, err1 := File2md5("/opt/temp/" + fileName + ".so") + if err1 != nil { + logger.Error(err1) + return false, err1 + } + md5str_origin, err2 := ioutil.ReadFile("/opt/temp/" + fileName + ".txt") + if err2 != nil { + logger.Error("璇诲彇瑙e帇鍚庣殑md5鏂囦欢澶辫触") + return false, err2 + } + flag := CompareMd5([]byte(md5str), md5str_origin) + if flag { + logger.Info("涓ゆMD5缂栫爜涓�鑷达紒") + } else { + logger.Debug("涓ゆMD5缂栫爜涓嶄竴鑷达紝璇烽噸鏂颁笅杞�") + return false, nil + } + // 浠巙rl涓埅鍙杝oName + soName := GetFileNameFromUrl(url, true) + f, err := os.Create("/opt/workspace/ruleprocess/algorithm/" + soName) + if err != nil { + logger.Error("鍦ㄩ」鐩洰褰曚笅鍒涘缓so鏂囦欢澶辫触") + return false, err + } + data, _ := ioutil.ReadFile("/opt/temp/" + soName) + _, err4 := f.Write(data) + if err4 != nil { + logger.Error("澶嶅埗鏂囦欢鍑洪敊") + return false, err4 + } + return true, nil +} + +func CopyFile(byte []byte, dst string) (w int64, err error) { + dstFile, err := os.Create(dst) + if err != nil { + logger.Debug(err.Error()) + return + } + defer dstFile.Close() + return io.Copy(dstFile, bytes.NewReader(byte)) +} + +// 鎸囧畾鐩綍鐨勬枃浠剁敓鎴愮浉搴旂殑MD5鐮佹枃浠� +func File2md5(filename string) (string, error) { + // 鏂囦欢鐢熸垚MD5鍔犲瘑鍔犲瘑鏂囦欢 + file, err := os.Open(filename) + if err != nil { + logger.Debug("os Open error") + return "", err + } + md5 := md5.New() + _, err = io.Copy(md5, file) + if err != nil { + logger.Debug("io copy error") + return "", err + } + md5Str := hex.EncodeToString(md5.Sum(nil)) + return md5Str, nil +} + +// 浠巙rl涓埅鍙栧嚭鏂囦欢鍚嶏紝鍙傛暟鏄槸鍚﹀甫鍚庣紑 +func GetFileNameFromUrl(url string, withSuffix bool) string { + fileName := strings.Split(url, "/")[len(strings.Split(url, "/"))-1] + if withSuffix { + return fileName + } else { + withoutSuffix := strings.Split(fileName, ".")[0] + return withoutSuffix + } +} + +// 姣旇緝涓や釜MD5缂栫爜鏄惁涓�鑷� +func CompareMd5(value1 []byte, value2 []byte) bool { + num := bytes.Compare(value1, value2) + if num == 0 { + return true + } else { + return false + } +} + +//installedFlag 濡傛灉鏄痶rue,琛ㄧず鍙煡鏈湴鐨勶紝涓嶉渶瑕佹瘮瀵规煡鐪嬫湭瀹夎鐨勭畻娉� +func GetSdkList(sdkName string, installedFlag, userId string) []SdkInsOrUpgrade { + //logger.Debug("installedFlag:", installedFlag) + t := time.Now() + var api bhomedbapi.UserApi + useIconTyp := 1 + if userId != "" { + found, userInfo := api.GetUserProfile(userId) + logger.Debugf("GetSdkList GetUserProfile userInfo=%v, t=%v", userInfo, time.Since(t)) + if found { + ub, e := json.Marshal(userInfo) + if e == nil { + type UIconDef struct { + UseIconType int `json:"useIconType"` + } + var ucd UIconDef + if e = json.Unmarshal(ub, &ucd); e == nil { + useIconTyp = ucd.UseIconType + logger.Debug("useIconTyp already 2", useIconTyp) + + } + } + } + } + var sdkE models.Sdk + t = time.Now() + sdkAll, _ := sdkE.FindAll(sdkName) //鏈湴宸插畨瑁呮墍鏈夌畻娉�,甯﹂『搴� + logger.Debugf("GetSdkList FindAll sdkName=%v, len(sdkAll)=%v, t=%v", sdkName, len(sdkAll), time.Since(t)) + if sdkAll == nil { + sdkAll = make([]models.Sdk, 0) + } + installedSdks := make([]SdkInsOrUpgrade, len(sdkAll)) + iv := make(map[string]SdkVB) + + localSdkIdArr := make([]string, 0) + localSdkM := make(map[string]SdkInsOrUpgrade) + t = time.Now() + for idx, ls := range sdkAll { + siou := SdkInsOrUpgrade{ + Installed: true, + } + + var sArg models.SdkArgEntity + args, e1 := sArg.FindBySdk(ls.Id) + if e1 == nil { + siou.Args = args + } else { + siou.Args = make([]models.SdkArgEntity, 0) + } + + siou.Sdk = ls + siou.ProtoRuleSo = ls.RuleSo + if useIconTyp == 2 && siou.IconBlob2 != "" { + siou.IconBlob = siou.IconBlob2 + siou.IconBlob2 = "" + } + localSdkM[siou.Id] = siou + iv[siou.Id] = SdkVB{ + Version: ls.Version, + BaseVersion: ls.BaseVersion, + } + installedSdks[idx] = siou + + localSdkIdArr = append(localSdkIdArr, siou.Id) + } + logger.Debugf("GetSdkList FindBySdk len(sdkAll)=%v, t=%v", len(sdkAll), time.Since(t)) + nInsSdks := make([]SdkInsOrUpgrade, 0) + + installedFlagBool, _ := strconv.ParseBool(installedFlag) + if !installedFlagBool { + t = time.Now() + // ***杩欎釜鍦版柟闇�瑕佹湁鏁堢巼闂 + upSdks, insSdks := findAllMySdk(localSdkIdArr, iv, sdkName) + logger.Debugf("GetSdkList findAllMySdk len(localSdkIdArr)=%v, len(iv)=%v, sdkName=%v, t=%v", len(localSdkIdArr), len(iv), sdkName, time.Since(t)) + + t = time.Now() + for _, sdk := range upSdks { + if v, ok := localSdkM[sdk.Id]; ok { //鏈湴宸插畨瑁� + ls := v + ls.SdkName = sdk.SdkName //浠ュ晢鍩庝笂鐨勪骇鍝佸悕绉颁负鍑� + + ls.Installed = true + if sdk.CanUpOrIns { + ls.ProgressMsg = "" + ls.IsUpgrade = shouldVersionBeUpgrade(ls.Version, sdk.Version) + ls.RemoteVersion = sdk.Version //杩滅鐨勭増鏈彿 + + if ip, insB := insIngMap.Load(sdk.Id); insB { + iPgs := ip.(*InsProgress) + ls.ProgressMsg = iPgs.Status + strconv.Itoa(iPgs.Progress) + "%" + } + } + + if useIconTyp == 2 && ls.IconBlob2 != "" { + ls.IconBlob = ls.IconBlob2 + ls.IconBlob2 = "" + } + localSdkM[sdk.Id] = ls + for index, es := range installedSdks { + if es.Id == sdk.Id { + installedSdks[index] = ls + break + } + } + } + } + logger.Debugf("GetSdkList shouldVersionBeUpgrade len(upSdks)=%v, t=%v", len(upSdks), time.Since(t)) + + t = time.Now() + for _, sdk := range insSdks { //鏈湴鏈畨瑁咃紝浣嗗彲浠ュ畨瑁呭垪琛� + if sdk.CanUpOrIns { + bIns := SdkInsOrUpgrade{ + RemoteVersion: sdk.Version, + IsUpgrade: false, + Installed: false, + ProgressMsg: "", + ProtoRuleSo: sdk.RuleSo, + } + if ip, insB := insIngMap.Load(sdk.Id); insB { + iPgs := ip.(*InsProgress) + bIns.ProgressMsg = iPgs.Status + strconv.Itoa(iPgs.Progress) + "%" + } + if useIconTyp == 2 && sdk.Sdk.IconBlob2 != "" { + sdk.Sdk.IconBlob = sdk.Sdk.IconBlob2 + sdk.Sdk.IconBlob2 = "" + } + bIns.Sdk = sdk.Sdk + nInsSdks = append(nInsSdks, bIns) + } + } + logger.Debugf("GetSdkList Load len(insSdks)=%v, t=%v", len(insSdks), time.Since(t)) + } + + // 濡傛灉鍙傛暟涓虹┖, 杩斿洖鍏ㄩ儴 + if installedFlag == "" { + return append(installedSdks, nInsSdks...) + } + + // 杩斿洖鎵�鏈夋湭瀹夎 + if !installedFlagBool { + return nInsSdks + } + + // 杩斿洖鎵�鏈夊凡瀹夎 + return installedSdks +} + +func queryDatabase(sdkName string) ([]map[string]interface{}, map[string]bool) { + var api bhomedbapi.SdkApi + ids := make(map[string]bool) + sdks := []map[string]interface{}{} + + // 鏌ヨ宸茬粡瀹夎鐨勭畻娉� + data := api.FindAll(sdkName) + for _, sdk := range data { + ids[sdk.Id] = true + sdks = append(sdks, map[string]interface{}{ + "id": sdk.Id, + "ipc_id": sdk.IpcId, + "sdk_type": sdk.SdkType, + "sdk_name": sdk.SdkName, + "icon": sdk.Icon, + "enable": sdk.Enable, + "installed": true, + }) + } + + return sdks, ids +} + +type shopSdks struct { + Sdks []SdkWithArg `json:"sdks"` + CanInsList []SdkWithArg `json:"canInsList"` +} + +type SdkVB struct { + Version string `json:"version"` + BaseVersion string `json:"baseVersion"` +} + +const ( + token = "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjQ3NDUwMjU5MjMsInVzZXIiOiJ7XCJpZFwiOlwiZTZjY2QzNmQtNGYxNi00NmZjLTg4ZDUtMDczNjU4NjZkMjA1XCIsXCJwZXJtaXNzaW9uc1wiOltcInByb2R1Y3RNYW5nZTpwdWJsaXNoXCIsXCJjb2RlTWFuZ2U6dmlld1wiLFwiZGV2aWNlTWFuYWdlOmFkZFwiLFwiYWRtaW5NYW5hZ2VcIixcIm9yZGVyTWFuZ2VcIixcImRldmljZU1hbmFnZTp2aWV3XCIsXCJwcm9kdWN0TWFuZ2U6YWRkXCIsXCJhZG1pbk1hbmFnZTp2aWV3XCIsXCJjb2RlTWFuZ2U6YWRkXCIsXCJwcm9kdWN0TWFuZ2U6b2ZmU2FsZVwiLFwib3JkZXJNYW5nZTpjYW5jZWxcIixcInByb2R1Y3RDZW50ZXI6ZG93bmxvYWRcIixcInByb2R1Y3RDZW50ZXI6YnV5XCIsXCJwcm9kdWN0TWFuZ2U6dmlld1wiLFwiYXBpXCIsXCJob21lXCIsXCJvcmRlck1hbmdlOnBheVwiLFwiYWRtaW5NYW5hZ2U6YWRkXCIsXCJvcmRlck1hbmdlOmRvd25sb2FkXCIsXCJwcm9kdWN0Q2VudGVyXCIsXCJkZXZpY2VNYW5hZ2U6dW5iaW5kXCIsXCJvcmRlck1hbmdlOnZpZXdcIixcImFkbWluTWFuYWdlOmVkaXRcIixcImRldmljZU1hbmFnZVwiLFwidmlwTWFuYWdlOmFkZFwiLFwidmlwTWFuYWdlOnZpZXdcIixcInByb2R1Y3RDZW50ZXI6dmlld1wiLFwidmlwTWFuYWdlOmVkaXRcIixcInZpcE1hbmFnZVwiLFwicHJvZHVjdE1hbmdlOmVkaXRcIixcImNvZGVNYW5nZVwiLFwicHJvZHVjdE1hbmdlXCJdLFwidXNlcm5hbWVcIjpcImJhc2ljXCJ9In0.vwjAFkWuEyadRLvIOGK8LFE3MjpY3SQ7j6AlTXnQDG8" +) + +func findAllMySdk(localSdkIdArr []string, iv map[string]SdkVB, inputTxt string) ([]SdkWithArg, []SdkWithArg) { + t := time.Now() + url := "http://" + util.GetShopUrl() + "/data/api-s/sdk/findAllMySdk" + machineCode := licence.GetMachineCode() + defer func() { + logger.Debugf("findAllMySdk url=%v, costTime=%v", url, time.Since(t)) + }() + + //鑾峰彇骞冲彴绫诲瀷 + paramBody := map[string]interface{}{ + "serverId": config.Server.AnalyServerId, + "machineCode": machineCode, + "localSdkIdArr": localSdkIdArr, + "iv": iv, + "inputTxt": inputTxt, + } + header := map[string]string{ + "Authorization": token, + } + respBody, err := util.DoPostRequest(url, util.CONTENT_TYPE_JSON, paramBody, nil, header, time.Second*20) + if err != nil { + logger.Debug("DoPostRequest err:", err) + return nil, nil + } + var res bhomedbapi.Result + if err = json.Unmarshal(respBody, &res); err != nil { + logger.Debug("unmarshal err:", err) + return nil, nil + } + bytes, _ := json.Marshal(res.Data) + var ss shopSdks + if err := json.Unmarshal(bytes, &ss); err != nil { + logger.Debug("unmarshal err:", err) + return nil, nil + } + + return ss.Sdks, ss.CanInsList +} + +func GetLocalSdks() []map[string]interface{} { + var algos = []map[string]interface{}{} + + AlgorithmFiles := "/opt/vasystem/bin/algorithm/*.json" + + files, err := filepath.Glob(AlgorithmFiles) + if err != nil { + fmt.Println("Cannot access algorithm json files: No such file or directory") + return algos + } + + for _, filename := range files { + algo := make(map[string]interface{}) + f, err := ioutil.ReadFile(filename) + if err != nil { + return algos + } + + if err := json.Unmarshal(f, &algo); err != nil { + return algos + } + + algos = append(algos, map[string]interface{}{ + "id": algo["sdkId"], + "ipc_id": algo["ipcId"], + "sdk_type": algo["sdkType"], + "sdk_name": algo["sdkName"], + "icon": algo["icon"], + "args": algo["sdkArgs"], + }) + } + + return algos +} + +func FindLocalSdkSoById(id string) map[string]interface{} { + localAlgos := GetLocalSdks() + for _, sdk := range localAlgos { + if sdk["id"].(string) == id { + return sdk + } + } + + return nil +} + +type downOrUpResp struct { + Url string `json:"url"` + Md5 string `json:"md5"` + Size uint64 `json:"size"` +} + +//涓嬭浇鎴栬�呭崌绾х畻娉� +func DownloadOrUpgrade(id string, h *bhomeclient.WrapperHandler) (bool, error) { + if _, ok := insIngMap.Load(id); ok { + insIngMap.Delete(id) + } + PreDownloading = true //闃叉娓呯悊绋嬪簭鎶婂崌绾у寘娓呯悊浜� + rb := false + ip := &InsProgress{ + Status: InsStatus_Downloading, + Progress: 0, + } + insIngMap.Store(id, ip) //鏀惧埌姝e湪瀹夎鍒楄〃涓� + defer func() { + if !rb { + insIngMap.Delete(id) + } + PreDownloading = false + }() + + ver := "" + baseVer := "" + var apE models.App + r1, _ := apE.SelectById(id) + if r1 > 0 { + ver = apE.Version + } else { + var sdkE models.Sdk + if r2, _ := sdkE.SelectById(id); r2 > 0 { + ver = sdkE.Version + baseVer = sdkE.BaseVersion + } + } + + url := "http://" + util.GetShopUrl() + "/data/api-s/sdk/downloadOrUpgrade" + machineCode := licence.GetMachineCode() + if machineCode == "" { + logger.Debug("鑾峰彇鏈哄櫒鐮佸け璐�") + return rb, errors.New("鑾峰彇鏈哄櫒鐮佸け璐�") + } + paramBody := map[string]interface{}{ + "modId": id, + "machineCode": machineCode, + "serverId": config.Server.AnalyServerId, + "version": ver, + "baseVersion": baseVer, + } + header := map[string]string{ + "Authorization": token, + } + respBody, err := util.DoPostRequest(url, util.CONTENT_TYPE_JSON, paramBody, nil, header, time.Second*60) + if err != nil { + logger.Debug("DoPostRequest err:", err) + return rb, err + } + var res bhomedbapi.Result + if err = json.Unmarshal(respBody, &res); err != nil { + logger.Debug("unmarshal err:", err) + return rb, err + } + if !res.Success { + logger.Debug("res.Data:", res.Data) + return rb, errors.New("璇锋眰鍟嗗煄澶辫触") + } + logger.Debug("res.Data:", res.Data) + var resp downOrUpResp + if err := mapstructure.Decode(res.Data.(map[string]interface{}), &resp); err != nil { + logger.Debug("mapstructure.Decode err:", err) + return rb, err + } + logger.Debug("resp:", resp) + if resp.Url == "" || resp.Md5 == "" { + return rb, errors.New("鑾峰彇涓嬭浇瀹夎鍖呭け璐�") + } + + ip.Size = resp.Size + + //寮傛瀹夎 + go startInstall(resp, id, ip, h) + + rb = true + return rb, nil +} + +//涓嬭浇瀹夎锛堝崌绾э級鍖咃紝楠岃瘉md5鍚庡畨瑁� +func startInstall(dor downOrUpResp, id string, iProgress *InsProgress, h *bhomeclient.WrapperHandler) (bool, error) { + defer func() { + iProgress.IsDone = true + + time.Sleep(10 * time.Second) + insIngMap.Delete(id) + }() + + //1.绗竴姝ュ厛涓嬭浇瀹夎鍖� + configPatchPath := "" + if config.Server.PatchPath != "" { + configPatchPath = config.Server.PatchPath + } else { + configPatchPath = "/opt/vasystem/patch" + } + if !util.DirExists(configPatchPath) { + os.Mkdir(configPatchPath, 0777) + } + filenameWithSuffix := path.Base(dor.Url) + ext := path.Ext(filenameWithSuffix) + downUrl := "http://" + util.GetShopUrl() + "/files/" + dor.Url + + iProgress.Status = InsStatus_Downloading + //濡傛灉妫�鏌ュ埌棰勪笅杞芥枃浠跺垯涓嶉噸澶嶄笅杞� + gzFilePath := configPatchPath + "/" + dor.Md5 + ext + _, err := os.Stat(gzFilePath) + if nil != err { + if os.IsNotExist(err) { + err := DownloadFile(gzFilePath, downUrl, iProgress) + if err != nil { + logger.Error("DownloadFile err:", err, " gzFilePath:", gzFilePath, " downUrl:", downUrl) + iProgress.Status = InsStatus_Err + " 鍘熷洜:" + err.Error() + return false, err + } + } + } + + iProgress.Status = InsStatus_PackageChecking + + //2.涓嬭浇瀹屾垚寮�濮嬪畨瑁� + if unPackB, unPackErr := unPackPatchPackage(dor.Md5, ext); !unPackB { //瑙e帇澶辫触 + iProgress.Status = InsStatus_UnPackErr + " 鍘熷洜:" + unPackErr.Error() + return false, unPackErr + } + //3.鏍¢獙md5 + fileMd5, err := util.FileMd5(gzFilePath) + if err != nil { + logger.Debug("FileMd5 err:", err) + iProgress.Status = InsStatus_CheckErr + " 鍘熷洜:" + err.Error() + return false, err + } + if fileMd5 != dor.Md5 { + logger.Debug("瀹夎鍖卪d5鏍¢獙澶辫触") + iProgress.Status = InsStatus_CheckErr + " 鍘熷洜:md5鏍¢獙澶辫触" + return false, errors.New("瀹夎鍖卪d5鏍¢獙澶辫触") + } else { + logger.Debug("瀹夎鍖卪d5鏍¢獙鎴愬姛") + } + iProgress.Status = InsStatus_Installing + + _, err = installPack(dor.Md5, ext, h) + time.Sleep(2 * time.Second) + if err == nil { + + iProgress.Status = InsStatus_Done + + return true, nil + } else { + iProgress.Status = InsStatus_InstallErr + " 鍘熷洜:" + err.Error() + go func() { + time.Sleep(3 * time.Second) + iProgress.Status = "" + iProgress.Progress = 0 + insIngMap.Delete(id) //瀹夎澶辫触涔熻〃绀哄畨瑁呯粨鏉熶簡 闇�瑕佹竻闄や俊鎭� + }() + return false, err + } +} diff --git a/appcenter-service/service/SdkInstall.go b/appcenter-service/service/SdkInstall.go new file mode 100644 index 0000000..7f3b6a8 --- /dev/null +++ b/appcenter-service/service/SdkInstall.go @@ -0,0 +1,859 @@ +package service + +import ( + "basic.com/valib/bhomeclient.git" + "basic.com/valib/bhomedbapi.git" + "basic.com/valib/licence.git" + "basic.com/valib/logger.git" + "encoding/json" + "errors" + "fmt" + "io/ioutil" + "os" + "path" + "path/filepath" + "strconv" + "strings" + "time" + "vamicro/appcenter-service/models" + "vamicro/appcenter-service/vo" + "vamicro/config" + "vamicro/extend/util" +) + +type SdkInstallService struct { +} + +// inputTxt杩囨护鏉′欢 +func (sv SdkInstallService) GetBuyList(inputTxt string) []SdkWithArg { + url := "http://" + util.GetShopUrl() + "/data/api-s/sdk/buyList" + machineCode := licence.GetMachineCode() + logger.Debug("url:", url, "machineCode:", machineCode) + var sdkE models.Sdk + localSdks, _ := sdkE.FindAll("") //鏈湴宸插畨瑁呮墍鏈夌畻娉�,甯﹂『搴� + if localSdks == nil { + localSdks = make([]models.Sdk, 0) + } + iv := make(map[string]SdkVB) + + localSdkIdArr := make([]string, 0) + for _, ls := range localSdks { + iv[ls.Id] = SdkVB{ + Version: ls.Version, + BaseVersion: ls.BaseVersion, + } + + localSdkIdArr = append(localSdkIdArr, ls.Id) + } + paramBody := map[string]interface{}{ + "serverId": config.Server.AnalyServerId, + "machineCode": machineCode, + "localSdkIdArr": localSdkIdArr, + "iv": iv, + "inputTxt": inputTxt, + } + header := map[string]string{ + "Authorization": token, + } + respBody, err := util.DoPostRequest(url, util.CONTENT_TYPE_JSON, paramBody, nil, header, time.Second*20) + if err != nil { + logger.Debug("DoPostRequest err:", err) + return nil + } + var res bhomedbapi.Result + if err = json.Unmarshal(respBody, &res); err != nil { + logger.Debug("unmarshal err:", err) + return nil + } + bytes, _ := json.Marshal(res.Data) + var ss shopSdks + if err := json.Unmarshal(bytes, &ss); err != nil { + logger.Debug("unmarshal err:", err) + return nil + } + + var resultArr []SdkWithArg + + installSdkM := make(map[string]models.Sdk) + if localSdks != nil { + for _, is := range localSdks { + installSdkM[is.Id] = is + } + } + if ss.Sdks != nil { + for _, rs := range ss.Sdks { + if _, ok := installSdkM[rs.Id]; !ok { + resultArr = append(resultArr, rs) + } + } + } + return resultArr +} + +func (sv SdkInstallService) Active(cod string, sdkId string) (interface{}, error) { + //浣跨敤婵�娲荤爜婵�娲荤畻娉� + url := "http://" + util.GetShopUrl() + "/data/api-s/sdk/activeByAINode" + machineCode := licence.GetMachineCode() + if machineCode == "" { + logger.Debug("鑾峰彇鏈哄櫒鐮佸け璐�") + return nil, errors.New("鑾峰彇鏈哄櫒鐮佸け璐�") + } + paramBody := map[string]interface{}{ + "code": cod, + "sdkId": sdkId, + "machineCode": machineCode, + "serverId": config.Server.AnalyServerId, + } + header := map[string]string{ + "Authorization": token, + } + respBody, err := util.DoPostRequest(url, util.CONTENT_TYPE_JSON, paramBody, nil, header, time.Second*60) + if err != nil { + logger.Debug("DoPostRequest err:", err) + return nil, err + } + var res bhomedbapi.Result + if err = json.Unmarshal(respBody, &res); err != nil { + logger.Debug("unmarshal err:", err) + return nil, err + } + if !res.Success { + logger.Debug("Active Sdk ret false, res: ", res) + return nil, errors.New(res.Msg) + } + // 婵�娲绘垚鍔� + return res.Data, nil +} + +// 绠楁硶(搴旂敤)瀹夎鍖呭畨瑁� +func (sv SdkInstallService) PackInstall(identifier string, filename string, h *bhomeclient.WrapperHandler) (bool, error) { + configPatchPath := "" + if config.Server.PatchPath != "" { + configPatchPath = config.Server.PatchPath + } else { + configPatchPath = "/opt/vasystem/patch" + } + + filenameWithSuffix := path.Base(filename) + ext := path.Ext(filenameWithSuffix) + + zipFilePath := configPatchPath + "/" + identifier + ext + unPackTargetPath := configPatchPath + "/" + identifier + "_basic/" + md5DirPath := configPatchPath + "/" + identifier + if util.Exists(zipFilePath) { + strMd5, e := util.FileMd5(zipFilePath) + if e != nil || strMd5 == "" { + go os.Remove(zipFilePath) + if util.DirExists(unPackTargetPath) { + go os.RemoveAll(unPackTargetPath) + } + if util.DirExists(md5DirPath) { + go os.RemoveAll(md5DirPath) + } + return false, errors.New("鑾峰彇瀹夎鍖卪d5澶辫触") + } + if strMd5 == identifier { + if _, insE := installPack(identifier, ext, h); insE != nil { + logger.Error("PackInstall insE:", insE) + return false, insE + } + + return true, nil + + } else { + go os.Remove(zipFilePath) + if util.DirExists(unPackTargetPath) { + go os.RemoveAll(unPackTargetPath) + } + if util.DirExists(md5DirPath) { + go os.RemoveAll(md5DirPath) + } + logger.Debug("strMd5 is", strMd5, "identifier is", identifier, "not equal") + return false, errors.New("鏍¢獙瀹夎鏂囦欢澶辫触") + } + } else { + return false, errors.New("瀹夎鍖呭凡涓㈠け锛岃閲嶆柊涓婁紶") + } +} + +func (sv SdkInstallService) PackUninstall(appId string) error { + uninstallFile := "/opt/vasystem/package/" + appId + "/uninstall.sh" + if util.Exists(uninstallFile) { + _, err := ExecCmd(uninstallFile) + if err != nil { + logger.Error("瀹夎鑴氭湰鎵ц澶辫触:", err.Error()) + return err + } + } + + return nil +} + +// 瑙e帇涓婁紶鐨勭畻娉曞畨瑁呭寘 +func unPackPatchPackage(identifier string, ext string) (bool, error) { + if ext != ".gz" { + return false, errors.New("闈炴硶鐨勫畨瑁呭寘鏂囦欢,瀹夎鍖呬负.tar.gz鏂囦欢") + } + configPatchPath := "" + if config.Server.PatchPath != "" { + configPatchPath = config.Server.PatchPath + } else { + configPatchPath = "/opt/vasystem/patch" + } + //1.瑙e帇缂╂洿鏂板寘 + unPackTargetPath := configPatchPath + "/" + identifier + "_basic/" + unPackFilePath := configPatchPath + "/" + identifier + ext + + if util.Exists(unPackTargetPath) { + //姝ょ増鏈凡缁忔洿鏂拌繃 + rmErr := os.RemoveAll(unPackTargetPath) + if rmErr != nil { + return false, rmErr + } + } + if !util.CreateDirectory(unPackTargetPath) { + return false, errors.New("鍒涘缓鍘嬬缉鏂囦欢澶瑰け璐�") + } + logger.Debug("unPackFilePath:", unPackFilePath, "unPackPath:", unPackTargetPath) + _, err := util.UnTarGzByCmd(unPackFilePath, unPackTargetPath) + if err != nil { + logger.Debug("UnPack err:", err, "unPackFile:", unPackFilePath) + return false, err + } + return true, nil +} + +func (sv SdkInstallService) ShowInstallInfo(identifier string, filename string) (bool, map[string]interface{}, error) { + configPatchPath := "" + if config.Server.PatchPath != "" { + configPatchPath = config.Server.PatchPath + } else { + configPatchPath = "/opt/vasystem/patch" + } + unPackTargetPath := configPatchPath + "/" + identifier + "_basic/" + isValid := false + defer func() { + if !isValid { + filenameWithSuffix := path.Base(filename) + ext := path.Ext(filenameWithSuffix) + unPackFilePath := configPatchPath + "/" + identifier + ext + md5DirPath := configPatchPath + "/" + identifier + + if util.Exists(unPackTargetPath) { + os.RemoveAll(unPackTargetPath) + } + if util.Exists(unPackFilePath) { + os.RemoveAll(unPackFilePath) + } + if util.DirExists(md5DirPath) { + go os.RemoveAll(md5DirPath) + } + + } + }() + if util.Exists(unPackTargetPath) { + targetFileName := "" + err := filepath.Walk(unPackTargetPath, func(path string, f os.FileInfo, err error) error { + if f == nil { + return err + } + if f.IsDir() { + targetFileName = f.Name() + } + return nil + }) + if err != nil { + return isValid, nil, errors.New("闈炴硶鐨勫畨瑁呭寘") + } else { + unPackPath := unPackTargetPath + targetFileName + "/" + //瑙e帇瀹屾垚锛岃幏鍙栧畨瑁呭寘涓殑鏂囦欢锛屽紑濮嬪畨瑁� + //1.瑙f瀽瀹夎璇存槑ins.inc + incPath := unPackPath + "ins.inc" + if util.Exists(incPath) { + if incB, err := ioutil.ReadFile(incPath); err == nil { + var ins InsInc + if err = json.Unmarshal(incB, &ins); err == nil { + showInfo := map[string]interface{}{ + "productName": ins.ProductName, + "installContent": ins.InstallContent, + } + sdkInfo := make([]map[string]interface{}, 0) + appInfo := make([]map[string]interface{}, 0) + if ins.Sdks != nil { + for _, is := range ins.Sdks { + sdkInfo = append(sdkInfo, map[string]interface{}{ + "sdkId": is.SdkId, + "sdkName": is.SdkName, + "version": is.Version, + }) + } + } + if ins.Modules != nil { + for _, ia := range ins.Modules { + appInfo = append(appInfo, map[string]interface{}{ + "appId": ia.AppId, + "appName": ia.AppName, + "version": ia.Version, + }) + } + } + showInfo["sdks"] = sdkInfo + showInfo["apps"] = appInfo + isValid = true + return true, showInfo, nil + } else { + return false, nil, errors.New("闈炴硶鐨勫畨瑁呭寘") + } + } else { + return false, nil, errors.New("闈炴硶鐨勫畨瑁呭寘") + } + } else { + return false, nil, errors.New("闈炴硶鐨勫畨瑁呭寘") + } + } + } else { + return isValid, nil, errors.New("闈炴硶鐨勫畨瑁呭寘鏍煎紡锛屽畨瑁呭寘宸插垹闄�") + } +} + +// 瀹夎sdk(app) +func installPack(identifier string, ext string, h *bhomeclient.WrapperHandler) (bool, error) { + configPatchPath := "" + if config.Server.PatchPath != "" { + configPatchPath = config.Server.PatchPath + } else { + configPatchPath = "/opt/vasystem/patch" + } + //1.瑙e帇缂╂洿鏂板寘 + unPackTargetPath := configPatchPath + "/" + identifier + "_basic/" + unPackFilePath := configPatchPath + "/" + identifier + ext + md5DirPath := configPatchPath + "/" + identifier + defer func() { + if util.Exists(unPackTargetPath) { + os.RemoveAll(unPackTargetPath) + } + if util.Exists(unPackFilePath) { + os.RemoveAll(unPackFilePath) + } + if util.DirExists(md5DirPath) { + go os.RemoveAll(md5DirPath) + } + }() + + if !util.Exists(unPackTargetPath) { //瀹夎鍖呬笉瀛樺湪 + return false, errors.New("瑙e帇鍚庣殑瀹夎鏂囦欢宸蹭笉瀛樺湪") + } + + // 鏌ユ壘涓嬩竴绾х洰褰� + targetDir := "" + files, err := ioutil.ReadDir(unPackTargetPath) + if err != nil { + return false, err + } + for _, f := range files { + if f.IsDir() && f.Name() != "." && f.Name() != ".." { + targetDir = f.Name() + } + } + + if targetDir == "" { + return false, errors.New("瀹夎鐩綍涓嶅瓨鍦�") + } + + unPackPath := unPackTargetPath + targetDir + "/" + if !util.Exists(unPackPath) { + return false, errors.New("瀹夎鏂囦欢宸蹭笉瀛樺湪") + } + + //瑙e帇瀹屾垚锛岃幏鍙栧畨瑁呭寘涓殑鏂囦欢锛屽紑濮嬪畨瑁� + //1.瑙f瀽瀹夎璇存槑ins.inc + incPath := unPackPath + "ins.inc" + if util.Exists(incPath) { + if incB, err := ioutil.ReadFile(incPath); err == nil { + var ins InsInc + if err = json.Unmarshal(incB, &ins); err == nil { + + // 瀹氬埗鎵嬪姩瀹夎 + if ins.ActivateCode != "*" { + //澶勭悊鎺堟潈淇℃伅,鐪嬪綋鍓嶅畨瑁呭寘鏄惁閫傜敤杩欏彴鏈哄櫒 + curMc := licence.GetMachineCode() + curServerId := config.Server.AnalyServerId + devMatch := false + for _, mc := range ins.Devs { + if mc.DevId == curServerId || mc.MachineCode == curMc { + devMatch = true + break + } + } + if !devMatch { + logger.Debug("curServerId:", curServerId, "curMc:", curMc, "ins.Devs:", ins.Devs) + return false, errors.New("姝ゅ畨瑁呭寘涓庡綋鍓嶈澶囦笉鍖归厤锛岃妫�鏌�") + } + } + + //瀹夎绠楁硶,濡傛灉鏈夌畻娉曞寘 + if len(ins.Sdks) > 0 { + if ie := installSDKInPack(unPackPath, ins.Sdks, h); ie != nil { + return false, errors.New("绠楁硶瀹夎澶辫触,澶辫触鍘熷洜:" + ie.Error() + "") + } + //濡傛灉鏈変緷璧栨枃浠跺垯瀹夎渚濊禆 + if depErr := installDepend(unPackPath); depErr != nil { + logger.Error("installDepend depErr:", depErr) + + //濡傛灉瀹夎鍖呴噷娌℃湁甯︿緷璧栨垨渚濊禆瀹夎澶辫触锛屽垯灏濊瘯鍦ㄧ嚎涓嬭浇渚濊禆 + depErr = downloadDepend(ins.Sdks) + if depErr != nil { + logger.Error("downloadDepend err:", depErr) + } + } + } + + //瀹夎搴旂敤鍖咃紝濡傛灉鏈夊簲鐢� + if len(ins.Modules) > 0 { + if ie := installAppInPack(unPackPath, ins.Modules, h); ie != nil { + return false, errors.New("搴旂敤瀹夎澶辫触,澶辫触鍘熷洜:" + ie.Error() + "") + } + } + } else { + logger.Debug("鍙嶅簭鍒楀寲鎺堟潈淇℃伅澶辫触") + return false, errors.New("閿欒鐨勫畨瑁呭寘") + } + } else { + logger.Debug("璇诲彇鎺堟潈鏂囦欢澶辫触") + return false, errors.New("閿欒鐨勫畨瑁呭寘") + } + } else { + return false, errors.New("閿欒鐨勫畨瑁呭寘") + } + + return true, nil +} + +// 瀹夎瀹夎鍖呬腑鐨勭畻娉� +func installSDKInPack(unPackPath string, sdkDefs []SdkIns, h *bhomeclient.WrapperHandler) error { + sv := NewSdkService(h.Bk) + var insErr error + var insSdkIds []string + defer func() { + if insErr != nil { + //todo 鍥炴粴 + logger.Debug("installSDKInPack err:", insErr, "sdkIds:", insSdkIds) + if len(insSdkIds) > 0 { + //鍒犻櫎绠楁硶 + //for _,id := range insSdkIds { + // + //} + } + } + }() + + defSDKPath := unPackPath + "sdk.def" + if util.Exists(defSDKPath) { + if defB, err := ioutil.ReadFile(defSDKPath); err == nil { + //3.灏嗙畻娉晄o銆佷緷璧栨枃浠躲�亃conf銆� + var skDefArr []SdkDef + if err = json.Unmarshal(defB, &skDefArr); err == nil { + exedFiles := make(map[string]string) + for _, sd := range sdkDefs { + //鍏堟牎楠宲latform鏄惁鍖归厤 + if sd.Platform == "" { + insErr = errors.New("闈炴硶鐨勫畨瑁呭寘锛屾棤platform淇℃伅锛岃涓嬭浇鏈�鏂板畨瑁呭寘") + return insErr + } + if !util.PlatformMatch(sd.Platform) { + insErr = errors.New("绠楁硶platform涓嶅尮閰嶏紝闈炴硶鐨勫畨瑁呭寘") + return insErr + } + + if sd.SdkBaseComponentPath != "" { + bPath := path.Base(sd.SdkBaseComponentPath) + if util.Exists(unPackPath + bPath) { + if _, nIn := exedFiles[bPath]; !nIn { //鏈畨瑁呰繃锛屾墠瀹夎 + //妫�鏌ョ畻娉曟敮鎸佺殑鏄惧崱鍨嬪彿鏄惁鍜屾湰鏈哄尮閰� + if !util.GpuMatch(sd.VGpus) { + insErr = errors.New("绠楁硶鏀寔鐨勬樉鍗″瀷鍙�(" + sd.VGpus + ")涓庡綋鍓嶈澶囦笉鍖归厤") + return insErr + } + if insErr = installComponent(unPackPath, bPath); insErr != nil { + return insErr + } else { + exedFiles[bPath] = bPath + } + } + } else { + insErr = errors.New("鍩虹绠楁硶鍖�" + bPath + "涓㈠け锛岃妫�鏌ュ畨瑁呭寘") + return insErr + } + + } + if sd.ComponentPath != "" { + oPath := path.Base(sd.ComponentPath) + if util.Exists(unPackPath + oPath) { + if _, nIn := exedFiles[oPath]; !nIn { //鏈畨瑁呰繃锛屾墠瀹夎 + if insErr = installComponent(unPackPath, oPath); insErr != nil { + return insErr + } else { + exedFiles[oPath] = oPath + } + } + } else { + insErr = errors.New("缁勪欢" + oPath + "涓㈠け锛岃妫�鏌�") + return insErr + } + } + } + + for _, skd := range skDefArr { + srv := vo.SdkRegisterVo{} + srv.Id = skd.Def.Id + srv.SdkType = skd.Def.SdkType + srv.SdkName = skd.Def.SdkName + srv.Icon = skd.Def.Icon + srv.Url = skd.Def.Url + srv.IconBlob = skd.Def.IconBlob + srv.IconBlob2 = skd.Def.IconBlob2 + srv.Version = skd.Def.Version + srv.EnTrack = skd.Def.EnTrack + srv.ArgDef = skd.Def.ArgDef + srv.RuleSo = skd.Def.RuleSo + srv.BaseVersion = skd.Def.BaseVersion + + for _, ag := range skd.Args { + sra := vo.SdkRegisterArgVo{ + Scope: ag.Scope, + } + sra.SdkArg = models.SdkArg{ + Alias: ag.Alias, + Name: ag.Name, + Type: ag.Type, + ArgType: ag.ArgType, + Must: ag.Must, + Unit: ag.Unit, + Range: ag.Range, + DefaultValue: ag.DefaultValue, + DefaultOperator: ag.DefaultOperator, + Sort: ag.Sort, + } + srv.Args = append(srv.Args, sra) + } + //灏嗙畻娉曟敞鍐屽埌鏁版嵁搴撲腑 + if sv.Register(&srv) { + logger.Debug("娉ㄥ唽鎴愬姛锛宻dkId:", skd.Def.Id) + insSdkIds = append(insSdkIds, skd.Def.Id) + } else { + insErr = errors.New("sdk娉ㄥ唽澶辫触,绠楁硶id:" + skd.Def.Id + "") + logger.Debug(insErr.Error()) + return insErr + } + } + //zconfPath := "./zconf/" + //libPath := "../libs/" + //if !util.DirExists(zconfPath) { + // os.MkdirAll(zconfPath, 0777) + //} + //if !util.DirExists(libPath) { + // os.MkdirAll(libPath, 0777) + //} + //for sdkType,_ := range soM { + // if _,iOk := nInsM[sdkType];iOk { + // //鍏堣В鍘婼dkType.tar.gz鏂囦欢 + // if unTarGzE := util.UnTarGz(unPackPath+sdkType+".tar.gz", unPackPath);unTarGzE == nil { + // //澶嶅埗json鍚姩鏂囦欢 + // if util.Exists(unPackPath+sdkType+"/zconf/"+sdkType+".json") { + // util.CopyFile(unPackPath+sdkType+"/zconf/"+sdkType+".json", zconfPath+sdkType+".json") + // } + // if util.DirExists(unPackPath+sdkType) { + // if _,cE := util.CopyDirByCmd(unPackPath+sdkType, libPath);cE != nil { + // insErr = cE + // return insErr + // } + // } + // if util.DirExists(unPackPath+sdkType+"/models") { + // if _,cE := util.CopyDirByCmd(unPackPath+sdkType+"/models", "./"); cE != nil { + // insErr = cE + // return insErr + // } + // //鎷疯礉瀹屾垚鍚庡垹闄ibs涓媠dkType鏂囦欢澶逛笅models + // } + // if util.DirExists(libPath+sdkType+"/models") { + // os.RemoveAll(libPath+sdkType+"/models") + // } + // if util.DirExists(libPath+sdkType+"/zconf") { + // os.RemoveAll(libPath+sdkType+"/zconf") + // } + // } else { + // logger.Debug("unTarGzE sdkType.tar.gz err:", unTarGzE) + // } + // } else { + // logger.Debug("upper version has been installed") + // } + //} + } else { + logger.Debug("鍙嶅簭鍒楀寲绠楁硶瀹氫箟淇℃伅澶辫触") + insErr = errors.New("閿欒鐨勫畨瑁呭寘") + return insErr + } + } else { + logger.Debug("璇诲彇绠楁硶瀹氫箟淇℃伅澶辫触,err:", err) + insErr = errors.New("閿欒鐨勫畨瑁呭寘") + return insErr + } + } else { + insErr = errors.New("閿欒鐨勫畨瑁呭寘锛岀畻娉曞畾涔夋枃浠朵笉瀛樺湪") + return insErr + } + + return insErr +} + +func installAppInPack(unPackPath string, appDefs []AppIns, h *bhomeclient.WrapperHandler) error { + //1.鍐欏叆鏁版嵁搴� + var appApi models.App + + var insErr error + var insAppIds []string + defer func() { + if insErr != nil { + //todo 鍥炴粴 + logger.Debug("installAppInPack err:", insErr, "appIds:", insAppIds) + if len(insAppIds) > 0 { + //鍒犻櫎搴旂敤 + for _, id := range insAppIds { + appApi.DeleteById(id) + } + } + } + }() + + defAppPath := unPackPath + "app.def" + if util.Exists(defAppPath) { + if defB, err := ioutil.ReadFile(defAppPath); err == nil { + //3.灏嗙畻娉晄o銆佷緷璧栨枃浠躲�亃conf銆� + var appDefArr []models.App + if err = json.Unmarshal(defB, &appDefArr); err == nil { + var appId = "" + for _, ap := range appDefArr { + appId = ap.Id + if !SaveApp(ap) { + insErr = errors.New("娉ㄥ唽搴旂敤澶辫触锛屽簲鐢╥d:" + ap.Id + "") + return insErr + } else { + insAppIds = append(insAppIds, ap.Id) + } + } + + //2.澶勭悊app鏂囦欢鍐呭 + exedFiles := make(map[string]string) + for _, sd := range appDefs { + if sd.ComponentPath != "" { + oPath := path.Base(sd.ComponentPath) + if util.Exists(unPackPath + oPath) { + if _, nIn := exedFiles[oPath]; !nIn { //鏈畨瑁呰繃锛屾墠瀹夎 + insErr = installComponent(unPackPath, oPath) + if insErr != nil { + return insErr + } else { + exedFiles[oPath] = oPath + } + } + } else { + insErr = errors.New("缁勪欢" + oPath + "涓㈠け锛岃妫�鏌�") + return insErr + } + } + } + + // 3 鎵嬪姩瀹夎 + installFile := path.Join(unPackPath, "install.sh") + if util.Exists(installFile) { + // 鍒囨崲鍒板綋鍓嶈繍琛岀洰褰� + os.Chdir(unPackPath) + b, err := ExecCmd(installFile) + if err != nil { + logger.Error("瀹夎鑴氭湰鎵ц澶辫触:", err.Error()) + return err + } + logger.Debug("install component result:", string(b)) + + // 澶嶅埗瀹夎鏂囦欢鍒皃ackage鐩綍, 鍗歌浇鏃惰皟鐢� uninstall + pkgDir := "/opt/vasystem/package/" + appId + ExecCmd(fmt.Sprintf("mkdir -p %s", pkgDir)) + ExecCmd(fmt.Sprintf("cp -rf %s/* %s/", unPackPath, pkgDir)) + + return nil + } + } else { + logger.Debug("鍙嶅簭鍒楀寲搴旂敤瀹氫箟淇℃伅澶辫触") + insErr = errors.New("閿欒鐨勫畨瑁呭寘") + return insErr + } + } else { + insErr = errors.New("璇诲彇搴旂敤瀹氫箟鏂囦欢澶辫触") + return insErr + } + } else { + insErr = errors.New("閿欒鐨勫畨瑁呭寘锛屽簲鐢ㄥ畾涔夋枃浠朵笉瀛樺湪") + return insErr + } + + return nil +} + +func installComponent(unPackPath string, componentFileName string) error { + ext := path.Ext(componentFileName) + if ext == "" { + return errors.New("闈炴硶鐨勫畨瑁呭寘鍚庣紑") + } + cName := strings.ReplaceAll(componentFileName, ext, "") + targetPath := unPackPath + cName + "/" + logger.Debug("installComponent targetPath:", targetPath) + if util.Exists(targetPath) { + rmErr := os.RemoveAll(targetPath) + if rmErr != nil { + return rmErr + } + } + if !util.CreateDirectory(targetPath) { + return errors.New("鍒涘缓鍘嬬缉鏂囦欢澶瑰け璐�") + } + if utzOut, unTarGzE := util.UnTarGzByCmd(unPackPath+componentFileName, targetPath); unTarGzE == nil { + //浣跨敤瀹夎鑴氭湰鎵ц + //targetFileName := "" + //err := filepath.Walk(targetPath, func(path string, f os.FileInfo, err error) error { + // if f == nil { + // return err + // } + // if f.IsDir() { + // targetFileName = f.Name() + // } + // return nil + //}) + //if err != nil { + // return errors.New("瀹夎鍖呬笉鍚堟硶锛岃妫�鏌ワ紝err:"+err.Error()+"") + //} + //logger.Debug("targetFileName:", targetFileName) + if util.Exists(targetPath + "install.sh") { + cmdPath := fmt.Sprintf("%sinstall.sh %s", targetPath, targetPath) + b, err := ExecCmd(cmdPath) + if err != nil { + return err + } + logger.Debug("install component ", componentFileName, " result:", string(b)) + return nil + } else { + return errors.New("瀹夎鎵ц鏂囦欢涓嶅瓨鍦紝璇锋鏌�") + } + } else { + logger.Error("UnTarGzByCmd out:", utzOut) + return unTarGzE + } +} + +func shouldVersionBeUpgrade(curVersion, dstVersion string) bool { + if curVersion == "" { + return true + } + if dstVersion == "" { + return false + } + curIVArr := strings.Split(curVersion, ".") + dstIVArr := strings.Split(dstVersion, ".") + if len(curIVArr) != 3 || len(dstIVArr) != 3 { + return false + } + cH, cEH := strconv.Atoi(curIVArr[0]) + cM, cEM := strconv.Atoi(curIVArr[1]) + cL, cEL := strconv.Atoi(curIVArr[2]) + + dH, dEH := strconv.Atoi(dstIVArr[0]) + dM, dEM := strconv.Atoi(dstIVArr[1]) + dL, dEL := strconv.Atoi(dstIVArr[2]) + if cEH != nil || cEM != nil || cEL != nil || dEH != nil || dEM != nil || dEL != nil { + return false + } + if cH > dH { + return false + } else if cH == dH { + if cM > dM { + return false + } else if cM == dM { + if cL > dL { + return false + } else if cL == dL { + return false + } else { + return true + } + } else { + return true + } + } else { + return true + } +} + +type InsInc struct { + OrderId string `json:"orderId"` //璁㈠崟id + ProductId string `json:"productId"` //浜у搧id + ActivateCode string `json:"activateCode"` //婵�娲荤爜 + Devs []InsDev `json:"devs"` //瀹夎鍖呯粰鍝簺璁惧浣跨敤 + UserId string `json:"userId"` //鐢ㄦ埛id + Sdks []SdkIns `json:"sdks"` //绠楁硶妯″潡 + Modules []AppIns `json:"modules"` //搴旂敤妯″潡 + ChCount int `json:"chCount"` //閫氶亾鏁伴噺 + AuthCount int `json:"authCount"` //鎺堟潈鏁伴噺 + ServeYear int `json:"serveYear"` //鏈嶅姟鏃堕暱 + + ProductName string `json:"productName"` + InstallContent string `json:"installContent"` +} + +type InsDev struct { + DevId string `json:"devId"` + MachineCode string `json:"machineCode"` +} + +type SdkIns struct { + SdkId string `json:"sdkId"` + SdkName string `json:"sdkName"` + SdkType string `json:"sdkType"` + Version string `json:"version"` + BaseVersion string `json:"baseVersion"` + SdkBaseComponentPath string `json:"sdkBase_component_path"` + SdkBaseComponentName string `json:"sdkBase_component_name"` + ComponentPath string `json:"component_path"` + ComponentName string `json:"component_name"` + VGpus string `json:"vGpus"` //姝ょ畻娉曟敮鎸佺殑鏄惧崱鍨嬪彿 + Platform string `json:"platform"` +} + +type AppIns struct { + AppId string `json:"appId"` + AppName string `json:"appName"` + Version string `json:"version"` + ComponentPath string `json:"component_path"` + ComponentName string `json:"component_name"` +} + +// 绠楁硶鍜屽弬鏁板畾涔� +type SdkDef struct { + Def models.Sdk `json:"def"` + Args []models.SdkArgEntity `json:"args"` +} + +type SdkWithArg struct { + models.Sdk + Args []models.SdkArgEntity `json:"args"` + CanUpOrIns bool `json:"canUpOrIns"` + Platforms []models.PtIns `json:"platforms"` //鍙�傞厤鐨勫钩鍙颁俊鎭� +} + +type SdkInsOrUpgrade struct { + SdkWithArg + + RemoteVersion string `json:"remoteVersion"` //鍟嗗煄浠撳簱鐗堟湰鍙� + Installed bool `json:"installed"` //鏄惁宸插畨瑁� + IsUpgrade bool `json:"isUpgrade"` //鏄惁闇�瑕佸崌绾� + ProgressMsg string `json:"progressMsg"` //瀹夎鎴栧崌绾ц繘搴� + ProtoRuleSo string `json:"ruleSo"` //閫傞厤protomsg涓殑ruleSo +} diff --git a/appcenter-service/service/SysService.go b/appcenter-service/service/SysService.go new file mode 100644 index 0000000..14d384b --- /dev/null +++ b/appcenter-service/service/SysService.go @@ -0,0 +1,632 @@ +package service + +import ( + "basic.com/valib/bhomeclient.git" + "basic.com/valib/bhomedbapi.git" + "basic.com/valib/licence.git" + "basic.com/valib/logger.git" + "bufio" + "context" + "encoding/json" + "errors" + "fmt" + "github.com/mitchellh/mapstructure" + "io/ioutil" + "os" + "os/exec" + "path" + "path/filepath" + "strings" + "sync" + "time" + "vamicro/config" + "vamicro/extend/util" + versionControlM "vamicro/version-control/models" +) + +var ( + /** + "app_auto_clean" : "0", + "app_update_notice": "0", + "app_auto_update": "0", + */ + VersionUpdateSetting = map[string]string{"app_auto_clean": "0", "app_update_notice": "0", "app_auto_update": "0"} + + updateNoticeInfo UpdateNoticeInfo + NoticeLock sync.Mutex + PreDownloading bool +) + +type SysService struct { +} + +type FileChunkCheckVo struct { + UserId string + ChunkNumber int //褰撳墠鍒嗙墖涓嬫爣,浠�1寮�濮� + ChunkSize int //姣忎竴鍧楃殑澶у皬 + CurrentChunkSize int //褰撳墠鍒嗗潡鐨勫ぇ灏� + FileName string //鏂囦欢鍚嶇О + Identifier string //鏁翠釜鏂囦欢鍞竴鏍囪瘑,md5 + RelativePath string //鏂囦欢瀹㈡埛绔矾寰� + TotalSize int64 //鏂囦欢鎬诲ぇ灏� + TotalChunks int //鎬诲垎鐗囨暟閲� +} + +type FileUploadVo struct { + Id string + UserId string + ChunkNumber int //褰撳墠鍒嗙墖涓嬫爣,浠�1寮�濮� + ChunkSize int //姣忎竴鍧楃殑澶у皬 + CurrentChunkSize int //褰撳墠鍒嗗潡鐨勫ぇ灏� + FileName string //鏂囦欢鍚嶇О + Identifier string //鏁翠釜鏂囦欢鍞竴鏍囪瘑,md5 + RelativePath string //鏂囦欢瀹㈡埛绔矾寰� + TotalSize int64 //鏂囦欢鎬诲ぇ灏� + TotalChunks int //鎬诲垎鐗囨暟閲� + File *bhomeclient.FileArg //褰撳墠鍒嗙墖鐨勬枃浠跺唴瀹� +} + +type UpdateNoticeInfo struct { + NoticeUser map[string]int + NeedUpdate bool + PreDownUpgrade bool + NoticeStatus bool + AutoClean bool + SdkNeedUpgrade []SdkInsOrUpgrade + AppNeedUpgrade []AppWithShop + LastNoticeTime int +} + +func init() { + updateNoticeInfo.NoticeUser = make(map[string]int) +} + +func (sv SysService) CheckUpdateFile(arg *FileChunkCheckVo) bool { + configPatchPath := "" + if config.Server.PatchPath != "" { + configPatchPath = config.Server.PatchPath + } else { + configPatchPath = "/opt/vasystem/patch" + } + fileTmpPath := configPatchPath + "/" + arg.Identifier + if !util.Exists(fileTmpPath) { + return false + } + //鍒ゆ柇鍚堟垚鐨勬枃浠舵槸鍚﹀瓨鍦� + index := strings.LastIndex(arg.FileName, ".") + subfix := "" + if index > -1 { //鏈夊悗缂� + subfix = arg.FileName[index:] + } + mergedFilePath := fileTmpPath + subfix + if util.Exists(mergedFilePath) { + return true + } + //鍒ゆ柇鍒嗗潡鏂囦欢鏄惁瀛樺湪 + chunkAlignNum := util.FormatNum(arg.TotalChunks, arg.ChunkNumber) + chunkFilePath := fileTmpPath + "/" + arg.Identifier + "_" + chunkAlignNum + if !util.Exists(chunkFilePath) { + return false + } + if arg.ChunkNumber == arg.TotalChunks { + dirFiles, _ := ioutil.ReadDir(fileTmpPath) + if dirFiles != nil && len(dirFiles) == arg.TotalChunks { + //琛ㄧず鎵�鏈夊垎鍧楅兘涓婁紶浜嗭紝闇�瑕乵erge + if b, _ := MergeChunks(fileTmpPath, mergedFilePath); !b { + return false + } + } + } + return true +} + +func (sv SysService) PatchUpload(arg *FileUploadVo) (bool, bool, string) { + configPatchPath := "" + if config.Server.PatchPath != "" { + configPatchPath = config.Server.PatchPath + } else { + configPatchPath = "/opt/vasystem/patch" + } + + if !util.CreateDirectory(configPatchPath) { + return false, false, "鍒涘缓鏂囦欢澶瑰け璐�" + } + + filenameWithSuffix := path.Base(arg.FileName) + subfix := path.Ext(filenameWithSuffix) + MD5Str := arg.Identifier + logger.Debug("Identifier:", MD5Str) + fileTmpPath := configPatchPath + "/" + MD5Str + if !util.Exists(fileTmpPath) { + if !util.CreateDirectory(fileTmpPath) { + return false, false, "鍒涘缓琛ヤ竵鏂囦欢澶瑰け璐�" + } + } + chunkAlignNum := util.FormatNum(arg.TotalChunks, arg.ChunkNumber) + fileSavePath := fileTmpPath + "/" + MD5Str + "_" + chunkAlignNum + if util.Exists(fileSavePath) { + rmErr := os.Remove(fileSavePath) + if rmErr != nil { + logger.Debug("rmErr:", rmErr) + return false, false, rmErr.Error() + } + } + file, e := os.Create(fileSavePath) + if e != nil { + logger.Debug("os.Create err:", e, "fileSavePath:", fileSavePath) + return false, false, e.Error() + } + defer file.Close() + writer := bufio.NewWriter(file) + + nn, err2 := writer.Write(arg.File.Bytes) + if nn == 0 || err2 != nil { + logger.Debug("write chunkData err:", err2, "nn:", nn) + return false, false, "鍐欏叆琛ヤ竵鍖呭け璐�" + } + if err2 = writer.Flush(); err2 != nil { + logger.Debug("write flush err:", err2) + return false, false, err2.Error() + } + isComplete := false + dirFiles, _ := ioutil.ReadDir(fileTmpPath) + if dirFiles != nil && len(dirFiles) == arg.TotalChunks { + isComplete = true + } + if isComplete { + if mergeB, mergeE := MergeChunks(fileTmpPath, fileTmpPath+subfix); mergeB { + logger.Debug("merge all chunks success,identifier:", MD5Str, "fileName:", arg.FileName) + unPackB, unPackErr := unPackPatchPackage(MD5Str, subfix) + logger.Debug("unPackB:", unPackB, "unPackErr:", unPackErr) + if unPackB { + return true, isComplete, "瑙e帇琛ヤ竵鍖呭け璐�,閿欒鐨勮ˉ涓佸寘鏍煎紡" + } + } else { + return false, isComplete, mergeE.Error() + } + } + return true, isComplete, "" +} + +//upgrade +//func (sv SysService) Upgrade(identifier string,filename string) (bool,error) { +// if !bakBeforeUpgrade() { +// return false,errors.New("鏇存柊鍓嶅浠藉け璐�") +// } +// configPatchPath := "" +// if config.Server.PatchPath != "" { +// configPatchPath = config.Server.PatchPath +// } else { +// configPatchPath = "/opt/vasystem/patch" +// } +// +// filenameWithSuffix := path.Base(filename) +// ext := path.Ext(filenameWithSuffix) +// +// zipFilePath := configPatchPath + "/"+identifier+ext +// if util.Exists(zipFilePath) { +// //鏍¢獙md5 +// strMd5, e := util.FileMd5(zipFilePath) +// if e !=nil || strMd5 == "" { +// return false,errors.New("鑾峰彇鍗囩骇鍘嬬缉鍖卪d5澶辫触") +// } +// if strMd5 == identifier { +// if !updatePatch(identifier, ext) { +// return false,errors.New("鎵ц鍗囩骇杩囩▼寮傚父,璇风‘瀹氫笂浼犵殑琛ヤ竵鏄痶ar.gz鏍煎紡") +// } +// return true,nil +// +// } else { +// logger.Debug("strMd5 is", strMd5,"identifier is",identifier,"not equal") +// return false,errors.New("鏍¢獙鍗囩骇鏂囦欢澶辫触") +// } +// } else { +// return false,errors.New("鍗囩骇鏂囦欢宸蹭涪澶憋紝璇烽噸鏂颁笂浼�") +// } +//} +// +//func bakBeforeUpgrade() bool { +// configBakPath := "" +// if config.Server.BakPath != "" { +// configBakPath = config.Server.BakPath +// } else { +// configBakPath = "/opt/vasystem/bak" +// } +// if util.Exists(configBakPath) { +// //鍙繚鐣欐渶鏂扮殑鐗堟湰 +// if err := os.RemoveAll(configBakPath);err != nil { +// return false +// } +// } +// if !util.CreateDirectory(configBakPath) { +// return false +// } +// b, err := ExecCmd("cp -r /opt/vasystem/bin /opt/vasystem/bak") +// if err != nil { +// logger.Debug("bakBeforeUpgrade result:",string(b),"err:",err) +// return false +// } +// return true +//} + +//鏇存柊绯荤粺绋嬪簭 +//func updatePatch(identifier string, ext string) bool { +// configPatchPath := "" +// if config.Server.PatchPath != "" { +// configPatchPath = config.Server.PatchPath +// } else { +// configPatchPath = "/opt/vasystem/patch" +// } +// //1.瑙e帇缂╂洿鏂板寘 +// unPackPath := configPatchPath+"/"+identifier+"_basic/" +// if util.Exists(unPackPath) { +// //姝ょ増鏈凡缁忔洿鏂拌繃 +// rmErr := os.RemoveAll(unPackPath) +// if rmErr !=nil { +// return false +// } +// } +// if !util.CreateDirectory(unPackPath) { +// return false +// } +// +// unPackFilePath := configPatchPath+"/"+identifier+ext +// err := util.UnTarGz(unPackFilePath, unPackPath) +// if err !=nil { +// logger.Debug("UnPack err:",err,"unPackFile:",unPackFilePath) +// return false +// } +// +// //濡傛灉閫氱敤鑴氭湰鏈夋洿鏂帮紝鍒欐洿鏂伴�氱敤鑴氭湰 +// if util.Exists(unPackPath+"updatePatch.sh") { +// cpStr := fmt.Sprintf("cp %s /opt/vasystem/bin",unPackPath+"updatePatch.sh") +// b, err := ExecCmd(cpStr) +// if err != nil { +// logger.Debug("cp updatePatch.sh to bin err:",err,"result:",string(b)) +// return false +// } +// } +// +// //鍒ゆ柇鏇存柊鍖呴噷鏄惁鏈夎ˉ涓佽剼鏈紝濡傛灉鏈夊垯鎵ц锛屽惁鍒欐墽琛寀pdatePatch.sh +// updateCmd := fmt.Sprintf("./updatePatch.sh %s %s %s &",unPackPath,unPackFilePath,configPatchPath+"/"+identifier) +// if util.Exists(unPackPath+"upgrade.sh") { +// updateCmd = fmt.Sprintf("%supgrade.sh %s %s %s &",unPackPath,unPackPath,unPackFilePath,configPatchPath+"/"+identifier) +// } +// //2.鏇存柊绯荤粺 +// b,err := ExecCmd(updateCmd) +// if err != nil { +// logger.Debug("upgrade err:",err,"result:",string(b),"cmd:",updateCmd) +// return false +// } else { +// logger.Debug("upgrade result:",string(b),"cmd:",updateCmd) +// } +// return true +//} + +func MergeChunks(chunkPath string, storePath string) (bool, error) { + var cmd *exec.Cmd + cmd = exec.Command("/bin/sh", "-c", fmt.Sprintf(` + filepath=%s + filestore=%s + echo "filepath: " $filepath + echo "filestorepath: " $filestore + if [ ! -f $filestore ]; then + echo "$filestore not exist" + else + rm -f $filestore + fi + + for item in $(ls $filepath | sort -n) + do + $(cat ${filepath}/${item} >> ${filestore}) + echo "merge ${filepath}/${item} to $filestore ok" + done + + echo "file store ok"`, chunkPath, storePath)) + + if b, err := cmd.Output(); err != nil { + logger.Debug("mergeChunks err:", err, "result:", string(b)) + return false, errors.New("鍚堟垚鍘嬬缉鍖呭け璐�") + } else { + logger.Debug("mergeChunks result:", string(b)) + return true, nil + } + +} + +func ExecCmd(cmdStr string) ([]byte, error) { + var cmd *exec.Cmd + cmd = exec.Command("/bin/sh", "-c", cmdStr) + return cmd.Output() +} + +func NoticeTick(c context.Context) { + tick := time.Tick(1 * time.Second) + for { + select { + case <-c.Done(): + logger.Info("proc close, self update exit") + return + case <-tick: + NoticeLock.Lock() + for uid, _ := range updateNoticeInfo.NoticeUser { + if updateNoticeInfo.NoticeUser[uid] > 0 { + updateNoticeInfo.NoticeUser[uid]-- + } + } + NoticeLock.Unlock() + } + } +} + +//鏇存柊妫�鏌� +func SelfUpdateStart(c context.Context) { + tick := time.Tick(30 * time.Second) + for { + select { + case <-c.Done(): + logger.Info("proc close, self update exit") + return + case <-tick: + NoticeLock.Lock() + //娓呯悊鍗囩骇鏂囦欢 + appAutoClean, ok := VersionUpdateSetting["app_auto_clean"] + if ok && appAutoClean == "1" { + updateNoticeInfo.AutoClean = true + //configPatchPath := "" + //if config.Server.PatchPath != "" { + // configPatchPath = config.Server.PatchPath + //} else { + // configPatchPath = "/opt/vasystem/patch" + //} + //err := os.RemoveAll(configPatchPath) + //if nil != err { + // logger.Error("clean update package failed:", err.Error()) + //} + //_ = os.MkdirAll(configPatchPath, 0777) + } else { + updateNoticeInfo.AutoClean = false + } + //鏇存柊鍗囩骇鎻愰啋 + appUpdateNotice, ok := VersionUpdateSetting["app_update_notice"] + var sdkNeedUp []SdkInsOrUpgrade + var appNeedUp []AppWithShop + if ok && appUpdateNotice == "1" { + sdkNeedUp, appNeedUp = CheckNeedUpgrade() + updateNoticeInfo.NeedUpdate = len(sdkNeedUp) > 0 || len(appNeedUp) > 0 + updateNoticeInfo.NoticeStatus = true + SdkHasModify := SdkNewModify(updateNoticeInfo.SdkNeedUpgrade, sdkNeedUp) + AppHasModify := AppNewModify(updateNoticeInfo.AppNeedUpgrade, appNeedUp) + if SdkHasModify || AppHasModify { + for uid, _ := range updateNoticeInfo.NoticeUser { + if updateNoticeInfo.NoticeUser[uid] <= 0 { + updateNoticeInfo.NoticeUser[uid] = 0 + } + } + } + updateNoticeInfo.SdkNeedUpgrade = sdkNeedUp + updateNoticeInfo.AppNeedUpgrade = appNeedUp + } else { + updateNoticeInfo.NeedUpdate = false + updateNoticeInfo.NoticeStatus = false + } + //棰勪笅杞� + appAutoUpdate, ok := VersionUpdateSetting["app_auto_update"] + if ok && appAutoUpdate == "1" { + updateNoticeInfo.PreDownUpgrade = true + if appUpdateNotice == "0" { + sdkNeedUp, appNeedUp = CheckNeedUpgrade() + } + + if len(sdkNeedUp) > 0 { + for _, item := range sdkNeedUp { + haveDown := CheckPreDown(item.RemoteVersion, item.SdkType) + if !haveDown { + PreDownSdkAndAppUpgradeFile(item.Id) + } + } + } + if len(appNeedUp) > 0 { + for _, item := range appNeedUp { + haveDown := CheckPreDown(item.RemoteVersion, item.Package) + if !haveDown { + PreDownSdkAndAppUpgradeFile(item.Id) + } + } + } + + } else { + updateNoticeInfo.PreDownUpgrade = false + } + NoticeLock.Unlock() + default: + time.Sleep(time.Second) + } + } +} + +//鏄惁鍜屼笂娆℃瘮杈冩湁鏂扮殑鏇存柊 +func SdkNewModify(SdkNeedUpgrade []SdkInsOrUpgrade, sdkNeedUp []SdkInsOrUpgrade) bool { + for _, item := range SdkNeedUpgrade { + for _, item2 := range sdkNeedUp { + if item.Id == item2.Id { + if strings.Compare(item.RemoteVersion, item2.RemoteVersion) == 1 { + return true + } + } + } + } + return false +} + +//鏄惁鍜屼笂娆℃瘮杈冩湁鏂扮殑鏇存柊 +func AppNewModify(AppNeedUpgrade []AppWithShop, appNeedUp []AppWithShop) bool { + for _, item := range AppNeedUpgrade { + for _, item2 := range appNeedUp { + if item.Id == item2.Id { + if strings.Compare(item.RemoteVersion, item2.RemoteVersion) == 1 { + return true + } + } + } + } + return false +} + +/** +棰勪笅杞絊DK鍗囩骇鍖� +*/ +func PreDownSdkAndAppUpgradeFile(id string) { + if IsInstalling(id) { + logger.Debug("绯荤粺姝e湪鍗囩骇") + return + } + PreDownloading = true + ip := &InsProgress{ + Status: InsStatus_Downloading, + Progress: 0, + } + insIngMap.Store(id, ip) //鏀惧埌姝e湪瀹夎鍒楄〃涓� + defer func() { + insIngMap.Delete(id) + PreDownloading = false + }() + url := "http://" + util.GetShopUrl() + "/data/api-s/sdk/downloadOrUpgrade" + machineCode := licence.GetMachineCode() + if machineCode == "" { + logger.Debug("鑾峰彇鏈哄櫒鐮佸け璐�") + return + } + paramBody := map[string]interface{}{ + "modId": id, + "machineCode": machineCode, + "serverId": config.Server.AnalyServerId, + } + header := map[string]string{ + "Authorization": token, + } + respBody, err := util.DoPostRequest(url, util.CONTENT_TYPE_JSON, paramBody, nil, header, time.Second*60) + if err != nil { + logger.Debug("DoPostRequest err:", err) + return + } + var res bhomedbapi.Result + if err = json.Unmarshal(respBody, &res); err != nil { + logger.Debug("unmarshal err:", err) + return + } + if !res.Success { + logger.Debug("res.Data:", res.Data) + return + } + logger.Debug("res.Data:", res.Data) + var resp downOrUpResp + if err := mapstructure.Decode(res.Data.(map[string]interface{}), &resp); err != nil { + logger.Debug("mapstructure.Decode err:", err) + return + } + logger.Debug("resp:", resp) + if resp.Url == "" || resp.Md5 == "" { + return + } + + ip.Size = resp.Size + //涓嬭浇瀹夎鍖� + configPatchPath := "" + if config.Server.PatchPath != "" { + configPatchPath = config.Server.PatchPath + } else { + configPatchPath = "../patch" + } + if !util.DirExists(configPatchPath) { + os.Mkdir(configPatchPath, 0777) + } + filenameWithSuffix := path.Base(resp.Url) + //ext := path.Ext(filenameWithSuffix) + downUrl := "http://" + util.GetShopUrl() + "/files/" + resp.Url + + gzFilePath := configPatchPath + "/" + filenameWithSuffix + _, err = os.Stat(gzFilePath) + if nil != err { + if os.IsNotExist(err) { + err := DownloadFile(gzFilePath, downUrl, ip) + if err != nil { + logger.Debug("DownloadFile err:", err, " gzFilePath:", gzFilePath, " downUrl:", downUrl) + return + } + } else { + return + } + } +} + +//妫�鏌ユ槸鍚﹂渶瑕佹洿鏂� +func CheckNeedUpgrade() ([]SdkInsOrUpgrade, []AppWithShop) { + sdkNeedUp := make([]SdkInsOrUpgrade, 0) + // userId := c.Header("Login_user_id") + appNeedUp := make([]AppWithShop, 0) + sdks := GetSdkList("", "", "") + for _, item := range sdks { + if item.Installed && item.IsUpgrade { + sdkNeedUp = append(sdkNeedUp, item) + } + } + apps := GetAppList("") + for _, item := range apps { + if item.Installed && item.IsUpgrade { + appNeedUp = append(appNeedUp, item) + } + } + + return sdkNeedUp, appNeedUp +} + +//鍚屾鏇存柊璁剧疆 +func PersistentWrapper(topic string, payloads []byte) { + var sysSetting versionControlM.SysSetting + if err := json.Unmarshal(payloads, &sysSetting); nil != err { + logger.Error("handleSubMsg failed to persistent:", topic, string(payloads)) + } + VersionUpdateSetting[sysSetting.Name] = sysSetting.Value +} + +//鑾峰彇鏇存柊鎻愰啋 +func GetUpdateNotice() UpdateNoticeInfo { + return updateNoticeInfo +} + +//寤惰繜鎻愰啋 +func DelayNotice(uid string, second int) UpdateNoticeInfo { + updateNoticeInfo.NoticeUser[uid] = second + return updateNoticeInfo +} + +//鑾峰彇鏂囦欢鐩綍 +func GetDirFiles(path string) ([]string, error) { + files, err := filepath.Glob(filepath.Join(path, "*")) + return files, err +} + +//鑾峰彇棰勪笅杞借矾寰� +func GetPredownPath() string { + configPatchPath := "" + if config.Server.PatchPath != "" { + configPatchPath = config.Server.PatchPath + } else { + configPatchPath = "../patch" + } + return configPatchPath +} + +//妫�鏌ユ槸鍚﹀凡缁忎笅杞� +func CheckPreDown(version string, sdkName string) bool { + predowns, err := GetDirFiles(GetPredownPath()) + if nil == err { + for _, item := range predowns { + if strings.Contains(item, sdkName+"-"+version) { + return true + } + } + } + return false +} diff --git a/appcenter-service/service/depend.go b/appcenter-service/service/depend.go new file mode 100644 index 0000000..5981cc6 --- /dev/null +++ b/appcenter-service/service/depend.go @@ -0,0 +1,189 @@ +package service + +import ( + "basic.com/valib/bhomedbapi.git" + "basic.com/valib/licence.git" + "basic.com/valib/logger.git" + "encoding/json" + "errors" + "github.com/mitchellh/mapstructure" + "io/ioutil" + "os" + "path" + "strings" + "sync" + "time" + "vamicro/config" + "vamicro/extend/util" +) + +//瀹夎渚濊禆 +func installDepend(insDir string) error { + depDir := insDir + "/toolkits" + depDef := depDir + "/depend_enc.def" + if util.DirExists(depDir) && util.FileExists(depDef) { + depB, err := util.CallDecFileContent(depDef) + if err != nil { + logger.Error("CallDecFileContent depDef err:", err) + return err + } + depArr := strings.Split(string(depB), ":") + for _, depName := range depArr { + if util.DirExists(depDir+"/"+depName) && util.DirExists("/opt/toolkits") && !util.DirExists("/opt/toolkits/"+depName) { + _, err = util.CopyDirByCmd(depDir+"/"+depName, "/opt/toolkits/") + if err != nil { + logger.Error("copy dep ", depName, " err:", err) + continue + } + } + } + } + return nil +} + +type sdkConfig struct { + RunTime string `json:"runtime"` +} + +//鍔ㄦ�佺洃娴嬬畻娉曚緷璧栨枃浠舵槸鍚﹀瓨鍦紝涓嶅瓨鍦ㄥ垯灏濊瘯鍦ㄧ嚎涓嬭浇 +const binPath = "/opt/vasystem/bin" + +var depInstallingMap sync.Map + +func downloadDepend(sdks []SdkIns) error { + for _, s := range sdks { + sdkTyp := s.SdkType + jsf := binPath + "/zconf/" + sdkTyp + ".json" + if util.FileExists(jsf) { + fData, err := ioutil.ReadFile(jsf) + if err != nil { + logger.Error("open ", sdkTyp, " config err:", err) + continue + } + var sc sdkConfig + err = json.Unmarshal(fData, &sc) + if err != nil { + logger.Error("unmarshal sdkConfig err:", err) + continue + } + depArr := strings.Split(sc.RunTime, ":") + for _, dep := range depArr { + if dep == "/opt/vasystem/libs/"+sdkTyp { + continue + } + if strings.HasPrefix(dep, "/opt/toolkits/") { + tmp := strings.Replace(dep, "/opt/toolkits", "", -1) + idx := strings.Index(tmp, "/") + if idx > 0 { + depName := tmp[:idx] + if util.DirExists("/opt/toolkits") && !util.DirExists("/opt/toolkits/"+depName) { + _, ok := depInstallingMap.Load(depName) + if !ok { + go depOnline(depName) + } + } + } + } + } + } + } + return nil +} + +//鍦ㄧ嚎涓嬭浇渚濊禆 +func depOnline(depName string) error { + depInstallingMap.Store(depName, depName) + defer depInstallingMap.Delete(depName) + url := "http://" + util.GetShopUrl() + "/data/api-s/sdk/depend" + machineCode := licence.GetMachineCode() + if machineCode == "" { + logger.Debug("depOnline 鑾峰彇鏈哄櫒鐮佸け璐�") + return errors.New("鑾峰彇鏈哄櫒鐮佸け璐�") + } + paramBody := map[string]interface{}{ + "depName": depName, + "machineCode": machineCode, + "serverId": config.Server.AnalyServerId, + } + header := map[string]string{ + "Authorization": token, + } + respBody, err := util.DoPostRequest(url, util.CONTENT_TYPE_JSON, paramBody, nil, header, time.Second*60) + if err != nil { + logger.Debug("DoPostRequest err:", err) + return err + } + var res bhomedbapi.Result + if err = json.Unmarshal(respBody, &res); err != nil { + logger.Debug("unmarshal err:", err) + return err + } + if !res.Success { + logger.Debug("res.Data:", res.Data) + return errors.New("璇锋眰鍟嗗煄澶辫触") + } + logger.Debug("res.Data:", res.Data) + var resp downOrUpResp + if err := mapstructure.Decode(res.Data.(map[string]interface{}), &resp); err != nil { + logger.Debug("mapstructure.Decode err:", err) + return err + } + logger.Debug("resp:", resp) + if resp.Url == "" || resp.Md5 == "" { + return errors.New("鑾峰彇渚濊禆鍖呬笅杞藉湴鍧�澶辫触") + } + logger.Info("渚濊禆椤�:", depName, " 鍦ㄧ嚎瀹夎鍖呭ぇ灏�:", resp.Size) + configPatchPath := "" + if config.Server.PatchPath != "" { + configPatchPath = config.Server.PatchPath + } else { + configPatchPath = "/opt/vasystem/patch" + } + if !util.DirExists(configPatchPath) { + os.Mkdir(configPatchPath, 0777) + } + filenameWithSuffix := path.Base(resp.Url) + ext := path.Ext(filenameWithSuffix) + gzFilePath := configPatchPath + "/" + resp.Md5 + ext + + ip := &InsProgress{ + Status: InsStatus_Downloading, + Progress: 0, + Size: resp.Size, + } + defer func() { + if util.FileExists(gzFilePath) { + os.Remove(gzFilePath) + } + }() + if !util.FileExists(gzFilePath) { + err := DownloadFile(gzFilePath, resp.Url, ip) + if err != nil { + logger.Debug("DownloadFile err:", err) + return err + } + rmd5, err := util.FileMd5(gzFilePath) + if err != nil { + logger.Error("FileMd5 err:", err) + return err + } + if rmd5 != resp.Md5 { + err = errors.New("涓嬭浇鐨勪緷璧栨枃浠舵牎楠宮d5澶辫触锛岃閲嶆柊涓嬭浇") + logger.Error(err) + return err + } + } + //瑙e帇瀹夎渚濊禆 + depPath := "/opt/toolkits/" + depName + if !util.DirExists(depPath) { + os.Mkdir(configPatchPath, os.ModePerm) + } + out, err := util.UnTarGzByCmd(gzFilePath, depPath) + logger.Info("UnTarGzByCmd depName:", depName, " err:", err, " out:", out) + if err != nil { + os.RemoveAll(depPath) + return err + } + + return nil +} diff --git a/appcenter-service/service/proc.go b/appcenter-service/service/proc.go new file mode 100644 index 0000000..d69d506 --- /dev/null +++ b/appcenter-service/service/proc.go @@ -0,0 +1,6 @@ +package service + + +const ( + ProcName = "appcenter-service" +) diff --git a/appcenter-service/service/sdkService.go b/appcenter-service/service/sdkService.go new file mode 100644 index 0000000..69825ec --- /dev/null +++ b/appcenter-service/service/sdkService.go @@ -0,0 +1,170 @@ +package service + +import ( + "basic.com/pubsub/protomsg.git" + "basic.com/valib/bhomeclient.git" + "basic.com/valib/licence.git" + "basic.com/valib/logger.git" + "encoding/json" + "errors" + "github.com/satori/go.uuid" + "time" + "vamicro/appcenter-service/models" + "vamicro/appcenter-service/vo" + "vamicro/config" + "vamicro/extend/util" +) + +type SdkService struct { + bk bhomeclient.Broker +} + +func NewSdkService(broker bhomeclient.Broker) *SdkService { + return &SdkService{ + bk: broker, + } +} + +type res struct { + Code int `json:"code"` + Success bool `json:"success"` + Msg string `json:"msg"` + Data interface{} `json:"data"` +} + +func GetLicenseFromShopCenter(sdkId string) (string, error) { + url := "http://" + util.GetShopUrl() + "/data/api-s/sdk/dev/license" + machineCode := licence.GetMachineCode() + logger.Debug("url:", url, "machineCode:", machineCode) + paramBody := map[string]interface{}{ + "devId": config.Server.AnalyServerId, + "sdkId": sdkId, + } + header := map[string]string{ + "Authorization": token, + } + respBody, err := util.DoPostRequest(url, util.CONTENT_TYPE_JSON, paramBody, nil, header, time.Second*2) + if err != nil { + logger.Debug("DoPostRequest err:", err) + return "", nil + } + var r res + if err = json.Unmarshal(respBody, &r); err != nil { + logger.Debug("unmarshal err:", err) + return "", nil + } + bts, _ := json.Marshal(r.Data) + var m map[string]interface{} + if err := json.Unmarshal(bts, &m); err != nil { + return "", err + } + if lce, ok := m["license"]; ok { + return lce.(string), nil + } + return "", errors.New("鏈幏鍙栧埌鎺堟潈淇℃伅") +} + +//瀹炴椂鐩戣鏈満绠楁硶鏄惁宸叉巿鏉� +func (sv SdkService) WatchLicense() { + for { + var sdkE models.Sdk + sdks, err := sdkE.FindAll("") + if err == nil && sdks != nil { + for _, s := range sdks { + if s.AuthState3rd == models.AuthState3rd_UnAuth || s.AuthState3rd == models.AuthState3rd_expired { + //鏌ョ湅鍟嗗煄涓绠楁硶鏄惁宸叉洿鏂版巿鏉冧俊鎭� + if lceStr, err := GetLicenseFromShopCenter(s.Id); err == nil { + sdkE.Update3rdLicense(s.Id, lceStr, models.AuthState3rd_Authed) + } + } + } + } + time.Sleep(10 * time.Second) + } +} + +func (sv SdkService) Register(argBody *vo.SdkRegisterVo) bool { + var err error + tx := models.GetDB().Begin() + defer func() { + if err != nil && tx != nil { + tx.Rollback() + } + }() + + var sdkE models.Sdk + rows, _ := sdkE.SelectById(argBody.Id) + registerSdk := argBody.Copy2Sdk() + if rows > 0 { + //update + if err = tx.Table(sdkE.TableName()).Save(®isterSdk).Error; err != nil { + return false + } + } else { + if err = tx.Table(sdkE.TableName()).Create(®isterSdk).Error; err != nil { + logger.Debug("register create sdk err:", err) + return false + } + } + //deal args + if err = tx.Exec("delete from sdk_arg where sdk_id=?", sdkE.Id).Error; err != nil { + logger.Debug("register del sdkarg err:", err) + return false + } + if argBody.Args != nil { + for _, argVo := range argBody.Args { + if argVo.Name == "" || argVo.Alias == "" || argVo.Type == "" { + err = errors.New("sdk arg error") + logger.Debug("register sdk err:", err) + return false + } + sdkArgE := models.SdkArgEntity{ + Id: uuid.NewV4().String(), + SdkId: argBody.Id, + Scope: argVo.Scope, + } + sdkArgE.SdkArg = argVo.Copy2SdkArg() + if sdkArgE.ArgType == "" { + sdkArgE.ArgType = "target" //濡傛灉涓虹┖锛岃涓烘槸鐩爣 + } + if err = tx.Table(sdkArgE.TableName()).Create(&sdkArgE).Error; err != nil { + logger.Debug("register sdk err:", err) + return false + } + + //澶勭悊绠楁硶鍙傛暟鏋氫妇鍊� + if err = tx.Exec("delete from dictionary where type=?", argVo.Alias).Error; err != nil { + logger.Debug("register sdk err:", err) + return false + } + if argVo.Dics != nil && len(argVo.Dics) > 0 { + for _, argValEle := range argVo.Dics { + argValDic := models.Dictionary{ + Id: uuid.NewV4().String(), + Value: argValEle.Value, + Name: argValEle.Name, + Type: argVo.Alias, + Sort: argValEle.Sort, + ParentId: argBody.Id, //灞炰簬鍝釜绠楁硶 + } + if err = tx.Table(argValDic.TableName()).Create(&argValDic).Error; err != nil { + logger.Debug("register sdk err:", err) + return false + } + } + } + } + } + tx.Commit() + sv.AddDbChangeMsg(protomsg.DbAction_Insert) + return true +} + +func (sv SdkService) AddDbChangeMsg(action protomsg.DbAction) { + pMsg := protomsg.DbChangeMessage{ + Table: protomsg.TableChanged_T_Sdk, + Action: action, + } + pb, _ := json.Marshal(pMsg) + sv.bk.Publish(ProcName, pb) +} diff --git a/appcenter-service/vo/sdk.go b/appcenter-service/vo/sdk.go new file mode 100644 index 0000000..27442f0 --- /dev/null +++ b/appcenter-service/vo/sdk.go @@ -0,0 +1,102 @@ +package vo + +import ( + "strings" + "time" + "vamicro/appcenter-service/models" +) + +type SdkVo struct { + models.Sdk + Args []models.SdkArg `json:"args"` //绠楁硶鍙傛暟 +} + +type SdkRegisterVo struct { + Id string `json:"id"` + SdkType string `json:"sdk_type"`//浜鸿劯妫�娴嬶細FaceDetect,浜鸿劯鎻愬彇锛欶aceExtract,浜鸿劯姣斿锛欶aceCompare,琛屼负锛歒olo + SdkName string `json:"sdk_name"` //绠楁硶鍚嶇О + Args []SdkRegisterArgVo `json:"args"` //绠楁硶鍙傛暟 + Icon string `json:"icon"` //绠楁硶鍥炬爣 + Url string `json:"url"` //绠楁硶涓嬭浇鍦板潃 + IconBlob string `json:"iconBlob"` //鍥剧墖 + IconBlob2 string `json:"iconBlob2"` //绗簩濂楀浘鐗� + Version string `json:"version"` //鐗堟湰鍙� + EnTrack bool `json:"enTrack"` + ArgDef string `json:"argDef"` + RuleSo string `json:"rule_so"` + BaseVersion string `json:"baseVersion"` +} + +type SdkRegisterArgVo struct { + Scope string `json:"scope"` + models.SdkArg + + Dics []SdkArgDic `json:"dics"` //濡傛灉姝ょ畻娉曞弬鏁版槸琚�夐」锛岄渶瑕佸皢鍙傛暟鏋氫妇鍊煎啓鍏ュ埌瀛楀吀琛ㄤ腑 +} + +type SdkArgDic struct { + Value string `json:"value"` + Name string `json:"name"` + Sort int `json:"sort"` +} + +func (sra *SdkRegisterArgVo) Copy2SdkArg() models.SdkArg { + return sra.SdkArg +} + +func (sv *SdkRegisterVo)Copy2Sdk() models.Sdk { + argDef := strings.Replace(sv.ArgDef, "\\u003c", "<", -1) + argDef = strings.Replace(argDef, "\\u003e", ">", -1) + argDef = strings.Replace(argDef, "\\u0026", "&", -1) + return models.Sdk{ + Id :sv.Id, + IpcId :"", + SdkType :sv.SdkType, + SdkName :sv.SdkName, + Icon :sv.Icon, + Url :sv.Url, + CreateTime :time.Now().Format("2006-01-02 15:04:05"), + CreateBy :"basic", + UpdateTime :time.Now().Format("2006-01-02 15:04:05"), + Enable :true, + DelFlag :0, + IconBlob: sv.IconBlob, + IconBlob2: sv.IconBlob2, + Version: sv.Version, + EnTrack: sv.EnTrack, + ArgDef: argDef, + RuleSo: sv.RuleSo, + BaseVersion: sv.BaseVersion, + } +} + +type SdkArgDefault struct { + SdkId string `json:"sdkId" binding:"required"` + DefArgs []ArgDefault `json:"defArgs" binding:"required"` +} + +type ArgDefault struct { + ArgType string `json:"arg_type" example:"鏍囩:label,鐩爣:target"` + Alias string `json:"alias" example:"鍙傛暟鍒悕,渚嬪锛歝onfidence"` + Name string `json:"name" example:"鍙傛暟鍚�,渚嬪:缃俊搴�"` + Type string `json:"type" example:"绫诲瀷,鍊�:value,閫夐」:option"` + Operators []OperatorKV `json:"operators"` + DefaultValue string `json:"default_value" example:"榛樿鍊�"` + Unit string `json:"unit" example:"鍗曚綅"` + Range string `json:"range" example:"鍙栧�艰寖鍥达紝渚嬪:[1,100]"` + Sort int `json:"sort"` + + Config ArgConfig `json:"config"` +} + +type OperatorKV struct { + Operator string `json:"operator"` + Name string `json:"name"` +} + +type ArgConfig struct { + IsShow bool `json:"isShow"` //鏄惁鍙 + IsConfigurable bool `json:"isConfigurable"` //鏄惁鍙厤 + IsOptional bool `json:"isOptional"` //鏄惁鍙�� + IsMulti bool `json:"isMulti"` //鏄惁澶氶�� +} -- Gitblit v1.8.0