diff --git a/build/scripts/migration/script.d/03-migrate-casaos.sh b/build/scripts/migration/script.d/03-migrate-casaos.sh index a48c437..719ff60 100644 --- a/build/scripts/migration/script.d/03-migrate-casaos.sh +++ b/build/scripts/migration/script.d/03-migrate-casaos.sh @@ -60,8 +60,6 @@ BUILD_PATH=$(dirname "${BASH_SOURCE[0]}")/../../.. SOURCE_ROOT=${BUILD_PATH}/sysroot APP_NAME="casaos" -APP_NAME_FORMAL="CasaOS" -#APP_NAME_FORMAL="casaos-alpha" # check if migration is needed SOURCE_BIN_PATH=${SOURCE_ROOT}/usr/bin @@ -85,45 +83,6 @@ if [ "${NEED_MIGRATION}" = "false" ]; then exit 0 fi -MIGRATION_SERVICE_DIR=${1} - -if [ -z "${MIGRATION_SERVICE_DIR}" ]; then - MIGRATION_SERVICE_DIR=${BUILD_PATH}/scripts/migration/service.d/${APP_NAME} -fi -MIGRATION_LIST_FILE=${MIGRATION_SERVICE_DIR}/migration.list -MIGRATION_PATH=() - -CURRENT_VERSION_FOUND="false" - -# a VERSION_PAIR looks like "v0.3.5 v0.3.6-alpha2" -# -# - "v0.3.5" is the current version installed on this host -# - "v0.3.6-alpha2" is the version of the migration tool from GitHub -while read -r VERSION_PAIR; do - if [ -z "${VERSION_PAIR}" ]; then - continue - fi - - # obtain "v0.3.5" from "v0.3.5 v0.3.6-alpha2" - VER1=$(echo "${VERSION_PAIR}" | cut -d' ' -f1) - - # obtain "v0.3.6-alpha2" from "v0.3.5 v0.3.6-alpha2" - VER2=$(echo "${VERSION_PAIR}" | cut -d' ' -f2) - - if [ "${CURRENT_VERSION}" = "${VER1// /}" ] || [ "${CURRENT_VERSION}" = "LEGACY_WITHOUT_VERSION" ]; then - CURRENT_VERSION_FOUND="true" - fi - - if [ "${CURRENT_VERSION_FOUND}" = "true" ]; then - MIGRATION_PATH+=("${VER2// /}") - fi -done < "${MIGRATION_LIST_FILE}" - -if [ ${#MIGRATION_PATH[@]} -eq 0 ]; then - __warning "No migration path found from ${CURRENT_VERSION} to ${SOURCE_VERSION}" - exit 0 -fi - ARCH="unknown" case $(uname -m) in @@ -141,22 +100,59 @@ case $(uname -m) in ;; esac +__info "ARCH: ${ARCH}" + +MIGRATION_SERVICE_DIR=${1} + +if [ -z "${MIGRATION_SERVICE_DIR}" ]; then + MIGRATION_SERVICE_DIR=${BUILD_PATH}/scripts/migration/service.d/${APP_NAME} +fi +MIGRATION_LIST_FILE=${MIGRATION_SERVICE_DIR}/migration.list +MIGRATION_PATH=() + +CURRENT_VERSION_FOUND="false" + +# a VERSION_PAIR looks like "v0.3.5 " +# +# - "v0.3.5" is the current version installed on this host +# - "" is the url of the migration tool +while read -r VERSION_PAIR; do + if [ -z "${VERSION_PAIR}" ]; then + continue + fi + + # obtain "v0.3.5" from "v0.3.5 v0.3.6-alpha2" + VER1=$(echo "${VERSION_PAIR}" | cut -d' ' -f1) + + # obtain "" from "v0.3.5 " + URL=$(eval echo "${VERSION_PAIR}" | cut -d' ' -f2) + + if [ "${CURRENT_VERSION}" = "${VER1// /}" ] || [ "${CURRENT_VERSION}" = "LEGACY_WITHOUT_VERSION" ]; then + CURRENT_VERSION_FOUND="true" + fi + + if [ "${CURRENT_VERSION_FOUND}" = "true" ]; then + MIGRATION_PATH+=("${URL// /}") + fi +done < "${MIGRATION_LIST_FILE}" + +if [ ${#MIGRATION_PATH[@]} -eq 0 ]; then + __warning "No migration path found from ${CURRENT_VERSION} to ${SOURCE_VERSION}" + exit 0 +fi + pushd "${MIGRATION_SERVICE_DIR}" -{ for VER2 in "${MIGRATION_PATH[@]}"; do - - - MIGRATION_TOOL_FILE=linux-"${ARCH}"-"${APP_NAME}"-migration-tool-"${VER2}".tar.gz +{ for URL in "${MIGRATION_PATH[@]}"; do + MIGRATION_TOOL_FILE=$(basename "${URL}") if [ -f "${MIGRATION_TOOL_FILE}" ]; then __info "Migration tool ${MIGRATION_TOOL_FILE} exists. Skip downloading." continue fi - # MIGRATION_TOOL_URL=http://192.168.2.197:8000/v1/package/migration?type=release&name="${APP_NAME_FORMAL}"&version=${VER2}&arch=${ARCH} - MIGRATION_TOOL_URL=https://github.com/IceWhaleTech/"${APP_NAME_FORMAL}"/releases/download/"${VER2}"/linux-"${ARCH}"-"${APP_NAME}"-migration-tool-"${VER2}".tar.gz - echo "Dowloading ${MIGRATION_TOOL_URL}..." - curl -sL -O "${MIGRATION_TOOL_URL}" + __info "Dowloading ${URL}..." + curl -fsSL -o "${MIGRATION_TOOL_FILE}" -O "${URL}" done } || { popd @@ -164,8 +160,8 @@ pushd "${MIGRATION_SERVICE_DIR}" } { - for VER2 in "${MIGRATION_PATH[@]}"; do - MIGRATION_TOOL_FILE=linux-"${ARCH}"-"${APP_NAME}"-migration-tool-"${VER2}".tar.gz + for URL in "${MIGRATION_PATH[@]}"; do + MIGRATION_TOOL_FILE=$(basename "${URL}") __info "Extracting ${MIGRATION_TOOL_FILE}..." tar zxvf "${MIGRATION_TOOL_FILE}" || __error "Failed to extract ${MIGRATION_TOOL_FILE}" diff --git a/build/scripts/migration/service.d/casaos/migration.list b/build/scripts/migration/service.d/casaos/migration.list index d3ce03f..c780280 100644 --- a/build/scripts/migration/service.d/casaos/migration.list +++ b/build/scripts/migration/service.d/casaos/migration.list @@ -1,4 +1,3 @@ -LEGACY_WITHOUT_VERSION v0.3.6 -v0.3.5 v0.3.6 -v0.3.5.1 v0.3.6 -v0.3.6 v0.3.7 +LEGACY_WITHOUT_VERSION https://github.com/IceWhaleTech/CasaOS/releases/download/v0.3.6/linux-${ARCH}-casaos-migration-tool-v0.3.6.tar.gz +v0.3.5 https://github.com/IceWhaleTech/CasaOS/releases/download/v0.3.6/linux-${ARCH}-casaos-migration-tool-v0.3.6.tar.gz +v0.3.5.1 https://github.com/IceWhaleTech/CasaOS/releases/download/v0.3.6/linux-${ARCH}-casaos-migration-tool-v0.3.6.tar.gz diff --git a/build/scripts/setup/service.d/casaos/debian/setup-casaos.sh b/build/scripts/setup/service.d/casaos/debian/setup-casaos.sh index e083373..50c8d91 100644 --- a/build/scripts/setup/service.d/casaos/debian/setup-casaos.sh +++ b/build/scripts/setup/service.d/casaos/debian/setup-casaos.sh @@ -31,15 +31,10 @@ if [ ! -f "${CONF_FILE}" ]; then cp -v "${CONF_FILE_SAMPLE}" "${CONF_FILE}" fi -if systemctl is-active "${APP_NAME}.service" &>/dev/null ;then - echo "server started" -else - # enable and start service - systemctl daemon-reload +rm -rf /etc/systemd/system/casaos.service # remove old service file - echo "Enabling service..." - systemctl enable --force --no-ask-password "${APP_NAME}.service" +systemctl daemon-reload - #echo "Starting service..." - #systemctl start --force --no-ask-password "${APP_NAME}.service" -fi \ No newline at end of file +# enable service (without starting) +echo "Enabling service..." +systemctl enable --force --no-ask-password "${APP_NAME}.service" diff --git a/build/sysroot/usr/share/casaos/shell/update.sh b/build/sysroot/usr/share/casaos/shell/update.sh index fdae5ca..c01abb4 100644 --- a/build/sysroot/usr/share/casaos/shell/update.sh +++ b/build/sysroot/usr/share/casaos/shell/update.sh @@ -9,4 +9,4 @@ ### -curl -fsSL https://raw.githubusercontent.com/LinkLeong/casaos-alpha/main/new.update.sh | bash \ No newline at end of file +curl -fsSL https://raw.githubusercontent.com/IceWhaleTech/get/main/update.sh | bash diff --git a/cmd/migration-tool/main.go b/cmd/migration-tool/main.go index 93b065d..d28663c0 100644 --- a/cmd/migration-tool/main.go +++ b/cmd/migration-tool/main.go @@ -83,8 +83,7 @@ func main() { } migrationTools := []interfaces.MigrationTool{ - NewMigrationToolFor_035(), - NewMigrationToolFor_036(), + // nothing to migrate from last version } var selectedMigrationTool interfaces.MigrationTool @@ -115,8 +114,7 @@ func main() { panic(err) } - selectedMigrationTool.PostMigrate() - _logger.Info("casaos migration ok") - // panic(err) - + if err := selectedMigrationTool.PostMigrate(); err != nil { + _logger.Error("Migration succeeded, but post-migration failed: %s", err) + } } diff --git a/cmd/migration-tool/migration-034-035.go b/cmd/migration-tool/migration-034-035.go deleted file mode 100644 index 3dfed60..0000000 --- a/cmd/migration-tool/migration-034-035.go +++ /dev/null @@ -1,182 +0,0 @@ -/* - * @Author: LinkLeong link@icewhale.org - * @Date: 2022-08-24 17:36:00 - * @LastEditors: LinkLeong - * @LastEditTime: 2022-09-05 11:24:27 - * @FilePath: /CasaOS/cmd/migration-tool/migration-034-035.go - * @Description: - * @Website: https://www.casaos.io - * Copyright (c) 2022 by icewhale, All Rights Reserved. - */ -package main - -import ( - "io" - "io/ioutil" - "os" - "path" - "strings" - - interfaces "github.com/IceWhaleTech/CasaOS-Common" - "github.com/IceWhaleTech/CasaOS-Common/utils/version" - "github.com/IceWhaleTech/CasaOS/pkg/config" - "github.com/IceWhaleTech/CasaOS/pkg/utils/command" - "github.com/IceWhaleTech/CasaOS/pkg/utils/file" - "github.com/IceWhaleTech/CasaOS/service" -) - -type migrationTool036 struct{} - -func (u *migrationTool036) IsMigrationNeeded() (bool, error) { - - majorVersion, minorVersion, patchVersion, err := version.DetectLegacyVersion() - if err != nil { - if err == version.ErrLegacyVersionNotFound { - return false, nil - } - - return false, err - } - - if majorVersion > 0 { - return false, nil - } - - if minorVersion > 3 { - return false, nil - } - - if minorVersion == 3 && patchVersion > 5 { - return false, nil - } - - _logger.Info("Migration is needed for a CasaOS version 0.3.5 and older...") - return true, nil - -} - -func (u *migrationTool036) PreMigrate() error { - - return nil -} - -func (u *migrationTool036) Migrate() error { - - if service.MyService.System().GetSysInfo().KernelArch == "aarch64" && config.ServerInfo.USBAutoMount != "True" && strings.Contains(service.MyService.System().GetDeviceTree(), "Raspberry Pi") { - service.MyService.System().UpdateUSBAutoMount("False") - service.MyService.System().ExecUSBAutoMountShell("False") - } - newAPIUrl := "https://api.casaos.io/casaos-api" - if config.ServerInfo.ServerApi == "https://api.casaos.zimaboard.com" { - config.ServerInfo.ServerApi = newAPIUrl - config.Cfg.Section("server").Key("ServerApi").SetValue(newAPIUrl) - config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath) - } - command.OnlyExec("curl -fsSL https://raw.githubusercontent.com/IceWhaleTech/get/main/assist.sh | bash") - if !file.CheckNotExist("/casaOS") { - command.OnlyExec("source /casaOS/server/shell/update.sh ;") - command.OnlyExec("source " + config.AppInfo.ShellPath + "/delete-old-service.sh ;") - } - - service.MyService.App().ImportApplications(true) - - src := "/casaOS/server/conf/conf.ini" - if file.Exists(src) { - dst := "/etc/casaos/casaos.conf" - source, err := os.Open(src) - if err != nil { - return err - } - defer source.Close() - - destination, err := os.Create(dst) - if err != nil { - return err - } - defer destination.Close() - _, err = io.Copy(destination, source) - if err != nil { - return err - } - - } - - if file.Exists("/casaOS/server/db") { - var fds []os.FileInfo - var err error - to := "/var/lib/casaos/db" - file.IsNotExistMkDir(to) - from := "/casaOS/server/db" - if fds, err = ioutil.ReadDir(from); err != nil { - return err - } - - for _, fd := range fds { - srcfp := path.Join(from, fd.Name()) - dstfp := path.Join(to, fd.Name()) - source, err := os.Open(srcfp) - if err != nil { - return err - } - defer source.Close() - - destination, err := os.Create(dstfp) - if err != nil { - return err - } - defer destination.Close() - _, err = io.Copy(destination, source) - if err != nil { - return err - } - } - - } - - if file.Exists("/casaOS/server/conf") { - var fds []os.FileInfo - var err error - to := "/var/lib/casaos/conf" - file.IsNotExistMkDir(to) - from := "/casaOS/server/conf" - if fds, err = ioutil.ReadDir(from); err != nil { - return err - } - - for _, fd := range fds { - fExt := path.Ext(fd.Name()) - if fExt != ".json" { - continue - } - srcfp := path.Join(from, fd.Name()) - dstfp := path.Join(to, fd.Name()) - source, err := os.Open(srcfp) - if err != nil { - return err - } - defer source.Close() - - destination, err := os.Create(dstfp) - if err != nil { - return err - } - defer destination.Close() - _, err = io.Copy(destination, source) - if err != nil { - return err - } - } - - } - - _logger.Info("update done") - return nil -} - -func (u *migrationTool036) PostMigrate() error { - return nil -} - -func NewMigrationToolFor_035() interfaces.MigrationTool { - return &migrationTool{} -} diff --git a/middleware/gin.go b/middleware/gin.go deleted file mode 100644 index a9b07b6..0000000 --- a/middleware/gin.go +++ /dev/null @@ -1,64 +0,0 @@ -/* - * @Author: LinkLeong link@icewhale.com - * @Date: 2021-10-08 10:29:08 - * @LastEditors: LinkLeong - * @LastEditTime: 2022-07-22 11:06:07 - * @FilePath: /CasaOS/middleware/gin.go - * @Description: - * @Website: https://www.casaos.io - * Copyright (c) 2022 by icewhale, All Rights Reserved. - */ -package middleware - -import ( - "fmt" - "net/http" - "runtime/debug" - "strings" - - "github.com/IceWhaleTech/CasaOS/pkg/utils/loger" - "github.com/gin-gonic/gin" - "go.uber.org/zap" -) - -func Cors() gin.HandlerFunc { - return func(c *gin.Context) { - method := c.Request.Method - - c.Header("Access-Control-Allow-Origin", "*") - c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE,UPDATE") - // 允许跨域设置可以返回其他子段,可以自定义字段 - c.Header("Access-Control-Allow-Headers", "Authorization, Content-Length, X-CSRF-Token, Token,session,Language,Content-Type,Access-Control-Allow-Origin,Access-Control-Allow-Headers,Access-Control-Allow-Methods,Connection,Host,Origin,Referer,User-Agent,X-Requested-With") - // 允许浏览器(客户端)可以解析的头部 (重要) - c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers") - // c.Writer.Header().Set("Access-Control-Allow-Headers", "Accept, Authorization, Content-Type, Content-Length, X-CSRF-Token, Token, session, Origin, Host, Connection, Accept-Encoding, Accept-Language, X-Requested-With") - // 设置缓存时间 - c.Header("Access-Control-Max-Age", "172800") - c.Header("Access-Control-Allow-Credentials", "true") - c.Set("Content-Type", "application/json") - //} - - // 允许类型校验 - if method == "OPTIONS" { - c.JSON(http.StatusOK, "ok!") - } - - defer func() { - if err := recover(); err != nil { - fmt.Println(err) - debug.PrintStack() - } - }() - - c.Next() - } -} - -func WriteLog() gin.HandlerFunc { - return func(c *gin.Context) { - if !strings.Contains(c.Request.URL.String(), "password") { - loger.Info("request:", zap.Any("path", c.Request.URL.String()), zap.Any("param", c.Params), zap.Any("query", c.Request.URL.Query()), zap.Any("method", c.Request.Method)) - c.Next() - } - } -} diff --git a/pkg/utils/file/file.go b/pkg/utils/file/file.go index e7fed65..1fd9de2 100644 --- a/pkg/utils/file/file.go +++ b/pkg/utils/file/file.go @@ -362,21 +362,27 @@ func WriteToFullPath(data []byte, fullPath string, perm fs.FileMode) error { func SpliceFiles(dir, path string, length int, startPoint int) error { fullPath := path - IsNotExistCreateFile(fullPath) + if err := IsNotExistCreateFile(fullPath); err != nil { + return err + } file, _ := os.OpenFile(fullPath, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0o666, ) + defer file.Close() + bufferedWriter := bufio.NewWriter(file) + + // todo: here should have a goroutine to remove each partial file after it is read, to save disk space + for i := 0; i < length+startPoint; i++ { data, err := ioutil.ReadFile(dir + "/" + strconv.Itoa(i+startPoint)) if err != nil { return err } - _, err = bufferedWriter.Write(data) - if err != nil { + if _, err := bufferedWriter.Write(data); err != nil { // recommend to use https://github.com/iceber/iouring-go for faster write return err } } diff --git a/route/route.go b/route/route.go index 8b254f8..a876849 100644 --- a/route/route.go +++ b/route/route.go @@ -1,8 +1,10 @@ package route import ( + "os" + + "github.com/IceWhaleTech/CasaOS-Common/middleware" "github.com/IceWhaleTech/CasaOS-Common/utils/jwt" - "github.com/IceWhaleTech/CasaOS/middleware" "github.com/IceWhaleTech/CasaOS/pkg/config" v1 "github.com/IceWhaleTech/CasaOS/route/v1" @@ -11,12 +13,22 @@ import ( ) func InitRouter() *gin.Engine { - r := gin.Default() + ginMode := gin.ReleaseMode + if config.ServerInfo.RunMode != "" { + ginMode = config.ServerInfo.RunMode + } + if os.Getenv(gin.EnvGinMode) != "" { + ginMode = os.Getenv(gin.EnvGinMode) + } + gin.SetMode(ginMode) + r := gin.New() + r.Use(gin.Recovery()) r.Use(middleware.Cors()) - r.Use(middleware.WriteLog()) r.Use(gzip.Gzip(gzip.DefaultCompression)) - gin.SetMode(config.ServerInfo.RunMode) + if ginMode != gin.ReleaseMode { + r.Use(middleware.WriteLog()) + } // r.StaticFS("/ui", http.FS(web.Static)) // r.GET("/", WebUIHome) diff --git a/route/v1/app.go b/route/v1/app.go index dec60ef..8e39347 100644 --- a/route/v1/app.go +++ b/route/v1/app.go @@ -18,6 +18,7 @@ import ( ) const ( + dockerRootDirFilePath = "/var/lib/casaos/docker_root" dockerDaemonConfigurationFilePath = "/etc/docker/daemon.json" ) @@ -274,36 +275,27 @@ func GetDockerDaemonConfiguration(c *gin.Context) { // c.JSON(common_err.SERVICE_ERROR, &model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()}) // return // } - dockerConfig := model.DockerDaemonConfigurationModel{} - data := make(map[string]interface{}, 1) - data["docker_root_dir"] = "" + data := make(map[string]interface{}) - // TODO read dockerRootDir from /etc/casaos/casaos.conf - if file.Exists(dockerDaemonConfigurationFilePath) { - byteResult := file.ReadFullFile(dockerDaemonConfigurationFilePath) - err := json.Unmarshal(byteResult, &dockerConfig) + if file.Exists(dockerRootDirFilePath) { + buf := file.ReadFullFile(dockerRootDirFilePath) + err := json.Unmarshal(buf, &data) if err != nil { - c.JSON(common_err.CLIENT_ERROR, &model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.INVALID_PARAMS), Data: err.Error()}) + c.JSON(common_err.CLIENT_ERROR, &model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.INVALID_PARAMS), Data: err}) return } - - if dockerConfig.Root != "" { - data["docker_root_dir"] = dockerConfig.Root - } else { - data["docker_root_dir"] = "/var/lib/docker" - } } c.JSON(common_err.SUCCESS, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data}) } func PutDockerDaemonConfiguration(c *gin.Context) { - js := make(map[string]interface{}) - if err := c.BindJSON(&js); err != nil { - c.JSON(http.StatusBadRequest, &model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.INVALID_PARAMS), Data: err.Error()}) + request := make(map[string]interface{}) + if err := c.BindJSON(&request); err != nil { + c.JSON(http.StatusBadRequest, &model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.INVALID_PARAMS), Data: err}) return } - value, ok := js["docker_root_dir"] + value, ok := request["docker_root_dir"] if !ok { c.JSON(http.StatusBadRequest, &model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.INVALID_PARAMS), Data: "`docker_root_dir` should not empty"}) return @@ -314,7 +306,7 @@ func PutDockerDaemonConfiguration(c *gin.Context) { byteResult := file.ReadFullFile(dockerDaemonConfigurationFilePath) err := json.Unmarshal(byteResult, &dockerConfig) if err != nil { - c.JSON(http.StatusInternalServerError, &model.Result{Success: common_err.SERVICE_ERROR, Message: "error when trying to deserialize " + dockerDaemonConfigurationFilePath, Data: err.Error()}) + c.JSON(http.StatusInternalServerError, &model.Result{Success: common_err.SERVICE_ERROR, Message: "error when trying to deserialize " + dockerDaemonConfigurationFilePath, Data: err}) return } } @@ -331,26 +323,33 @@ func PutDockerDaemonConfiguration(c *gin.Context) { dockerConfig.Root = filepath.Join(dockerRootDir, "docker") if err := file.IsNotExistMkDir(dockerConfig.Root); err != nil { - c.JSON(http.StatusInternalServerError, &model.Result{Success: common_err.SERVICE_ERROR, Message: "error when trying to create " + dockerConfig.Root, Data: err.Error()}) + c.JSON(http.StatusInternalServerError, &model.Result{Success: common_err.SERVICE_ERROR, Message: "error when trying to create " + dockerConfig.Root, Data: err}) return } } - byteMode, err := json.Marshal(dockerConfig) - if err != nil { + if buf, err := json.Marshal(request); err != nil { + c.JSON(http.StatusBadRequest, &model.Result{Success: common_err.CLIENT_ERROR, Message: "error when trying to serialize docker root json", Data: err}) + return + } else { + if err := file.WriteToFullPath(buf, dockerRootDirFilePath, 0o644); err != nil { + c.JSON(http.StatusInternalServerError, &model.Result{Success: common_err.SERVICE_ERROR, Message: "error when trying to write " + dockerRootDirFilePath, Data: err}) + return + } + } + + if buf, err := json.Marshal(dockerConfig); err != nil { c.JSON(http.StatusBadRequest, &model.Result{Success: common_err.CLIENT_ERROR, Message: "error when trying to serialize docker config", Data: dockerConfig}) return + } else { + if err := file.WriteToFullPath(buf, dockerDaemonConfigurationFilePath, 0o644); err != nil { + c.JSON(http.StatusInternalServerError, &model.Result{Success: common_err.SERVICE_ERROR, Message: "error when trying to write to " + dockerDaemonConfigurationFilePath, Data: err}) + return + } } - if err := file.WriteToFullPath(byteMode, dockerDaemonConfigurationFilePath, 0o644); err != nil { - c.JSON(http.StatusInternalServerError, &model.Result{Success: common_err.SERVICE_ERROR, Message: "error when trying to write to " + dockerDaemonConfigurationFilePath, Data: err.Error()}) - return - } - - // TODO also write dockerRootDir to /etc/casaos/casaos.conf - println(command.ExecResultStr("systemctl daemon-reload")) println(command.ExecResultStr("systemctl restart docker")) - c.JSON(http.StatusOK, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: js}) + c.JSON(http.StatusOK, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: request}) } diff --git a/route/v1/docker.go b/route/v1/docker.go index 60d33a3..4b7d4a4 100644 --- a/route/v1/docker.go +++ b/route/v1/docker.go @@ -1126,7 +1126,7 @@ func ContainerUpdateInfo(c *gin.Context) { } } for _, v := range info.Config.Env { - if len(showENVList) > 0 { + if len(showENVList) > 0 && info.Config.Labels["origin"] != "local" { if _, ok := showENVMap[strings.Split(v, "=")[0]]; ok { temp := model.Env{ Name: strings.Split(v, "=")[0], diff --git a/route/v1/file.go b/route/v1/file.go index 396074d..2b1fd11 100644 --- a/route/v1/file.go +++ b/route/v1/file.go @@ -18,9 +18,11 @@ import ( "github.com/IceWhaleTech/CasaOS/model" "github.com/IceWhaleTech/CasaOS/pkg/utils/common_err" "github.com/IceWhaleTech/CasaOS/pkg/utils/file" + "github.com/IceWhaleTech/CasaOS/pkg/utils/loger" "github.com/IceWhaleTech/CasaOS/service" "github.com/gin-gonic/gin" uuid "github.com/satori/go.uuid" + "go.uber.org/zap" ) // @Summary 读取文件 @@ -47,7 +49,7 @@ func GetFilerContent(c *gin.Context) { }) return } - //文件读取任务是将文件内容读取到内存中。 + // 文件读取任务是将文件内容读取到内存中。 info, err := ioutil.ReadFile(filePath) if err != nil { c.JSON(common_err.SERVICE_ERROR, model.Result{ @@ -83,7 +85,6 @@ func GetLocalFile(c *gin.Context) { return } c.File(path) - return } // @Summary download @@ -96,7 +97,6 @@ func GetLocalFile(c *gin.Context) { // @Success 200 {string} string "ok" // @Router /file/download [get] func GetDownloadFile(c *gin.Context) { - t := c.Query("format") files := c.Query("files") @@ -135,11 +135,11 @@ func GetDownloadFile(c *gin.Context) { } if !info.IsDir() { - //打开文件 + // 打开文件 fileTmp, _ := os.Open(filePath) defer fileTmp.Close() - //获取文件的名称 + // 获取文件的名称 fileName := path.Base(filePath) c.Header("Content-Disposition", "attachment; filename*=utf-8''"+url2.PathEscape(fileName)) c.File(filePath) @@ -179,7 +179,6 @@ func GetDownloadFile(c *gin.Context) { log.Printf("Failed to archive %s: %v", fname, err) } } - } func GetDownloadSingleFile(c *gin.Context) { @@ -202,7 +201,7 @@ func GetDownloadSingleFile(c *gin.Context) { defer fileTmp.Close() fileName := path.Base(filePath) - //c.Header("Content-Disposition", "inline") + // c.Header("Content-Disposition", "inline") c.Header("Content-Disposition", "attachment; filename*=utf-8''"+url2.PathEscape(fileName)) c.File(filePath) } @@ -248,7 +247,7 @@ func DirPath(c *gin.Context) { info[i].Extensions = ex } } - //Hide the files or folders in operation + // Hide the files or folders in operation fileQueue := make(map[string]string) if len(service.OpStrArr) > 0 { for _, v := range service.OpStrArr { @@ -361,7 +360,6 @@ func PostCreateFile(c *gin.Context) { // @Success 200 {string} string "ok" // @Router /file/upload [get] func GetFileUpload(c *gin.Context) { - relative := c.Query("relativePath") fileName := c.Query("filename") chunkNumber := c.Query("chunkNumber") @@ -405,7 +403,8 @@ func PostFileUpload(c *gin.Context) { hash := file.GetHashByContent([]byte(fileName)) if len(path) == 0 { - c.JSON(common_err.INVALID_PARAMS, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)}) + loger.Error("path should not be empty") + c.JSON(http.StatusBadRequest, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)}) return } tempDir := filepath.Join(path, ".temp", hash+strconv.Itoa(totalChunks)) + "/" @@ -413,47 +412,82 @@ func PostFileUpload(c *gin.Context) { if fileName != relative { dirPath = strings.TrimSuffix(relative, fileName) tempDir += dirPath - file.MkDir(path + "/" + dirPath) + if err := file.MkDir(path + "/" + dirPath); err != nil { + loger.Error("error when trying to create `"+path+"/"+dirPath+"`", zap.Error(err)) + c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()}) + return + } } path += "/" + relative if !file.CheckNotExist(tempDir + chunkNumber) { - file.RMDir(tempDir + chunkNumber) + if err := file.RMDir(tempDir + chunkNumber); err != nil { + loger.Error("error when trying to remove existing `"+tempDir+chunkNumber+"`", zap.Error(err)) + c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()}) + return + } } if totalChunks > 1 { - file.IsNotExistMkDir(tempDir) - - out, _ := os.OpenFile(tempDir+chunkNumber, os.O_WRONLY|os.O_CREATE, 0644) - defer out.Close() - _, err := io.Copy(out, f) - if err != nil { - c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()}) + if err := file.IsNotExistMkDir(tempDir); err != nil { + loger.Error("error when trying to create `"+tempDir+"`", zap.Error(err)) + c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()}) return } + + out, err := os.OpenFile(tempDir+chunkNumber, os.O_WRONLY|os.O_CREATE, 0o644) + if err != nil { + loger.Error("error when trying to open `"+tempDir+chunkNumber+"` for creation", zap.Error(err)) + c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()}) + return + } + + defer out.Close() + + if _, err := io.Copy(out, f); err != nil { // recommend to use https://github.com/iceber/iouring-go for faster copy + loger.Error("error when trying to write to `"+tempDir+chunkNumber+"`", zap.Error(err)) + c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()}) + return + } + + fileNum, err := ioutil.ReadDir(tempDir) + if err != nil { + loger.Error("error when trying to read number of files under `"+tempDir+"`", zap.Error(err)) + c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()}) + return + } + + if totalChunks == len(fileNum) { + if err := file.SpliceFiles(tempDir, path, totalChunks, 1); err != nil { + loger.Error("error when trying to splice files under `"+tempDir+"`", zap.Error(err)) + c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()}) + return + } + + if err := file.RMDir(tempDir); err != nil { + loger.Error("error when trying to remove `"+tempDir+"`", zap.Error(err)) + c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()}) + return + } + } } else { - out, _ := os.OpenFile(path, os.O_WRONLY|os.O_CREATE, 0644) - defer out.Close() - _, err := io.Copy(out, f) + out, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE, 0o644) if err != nil { - c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()}) + loger.Error("error when trying to open `"+path+"` for creation", zap.Error(err)) + c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()}) return } - c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)}) - return - } - fileNum, err := ioutil.ReadDir(tempDir) - if err != nil { - c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()}) - return - } - if totalChunks == len(fileNum) { - file.SpliceFiles(tempDir, path, totalChunks, 1) - file.RMDir(tempDir) - } - c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)}) + defer out.Close() + + if _, err := io.Copy(out, f); err != nil { // recommend to use https://github.com/iceber/iouring-go for faster copy + loger.Error("error when trying to write to `"+path+"`", zap.Error(err)) + c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()}) + return + } + } + c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)}) } // @Summary copy or move file @@ -465,7 +499,6 @@ func PostFileUpload(c *gin.Context) { // @Success 200 {string} string "ok" // @Router /file/operate [post] func PostOperateFileOrDir(c *gin.Context) { - list := model.FileOperate{} c.ShouldBind(&list) @@ -515,7 +548,6 @@ func PostOperateFileOrDir(c *gin.Context) { // @Success 200 {string} string "ok" // @Router /file/delete [delete] func DeleteFile(c *gin.Context) { - paths := []string{} c.ShouldBind(&paths) if len(paths) == 0 { @@ -547,7 +579,6 @@ func DeleteFile(c *gin.Context) { // @Success 200 {string} string "ok" // @Router /file/update [put] func PutFileContent(c *gin.Context) { - fi := model.FileUpdate{} c.ShouldBind(&fi) @@ -557,7 +588,7 @@ func PutFileContent(c *gin.Context) { c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.FILE_ALREADY_EXISTS, Message: common_err.GetMsg(common_err.FILE_ALREADY_EXISTS)}) return } - //err := os.Remove(path) + // err := os.Remove(path) err := os.RemoveAll(fi.FilePath) if err != nil { c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.FILE_DELETE_ERROR, Message: common_err.GetMsg(common_err.FILE_DELETE_ERROR), Data: err}) diff --git a/service/system.go b/service/system.go index c6ed444..8717e4c 100644 --- a/service/system.go +++ b/service/system.go @@ -221,7 +221,7 @@ func (s *systemService) UpdateSystemVersion(version string) { } file.CreateFile(config.AppInfo.LogPath + "/upgrade.log") //go command2.OnlyExec("curl -fsSL https://raw.githubusercontent.com/LinkLeong/casaos-alpha/main/update.sh | bash") - go command2.OnlyExec("curl -fsSL https://raw.githubusercontent.com/IceWhaleTech/get/main/update.sh | sudo bash") + go command2.OnlyExec("curl -fsSL https://raw.githubusercontent.com/IceWhaleTech/get/main/update.sh | bash") //s.log.Error(config.AppInfo.ProjectPath + "/shell/tool.sh -r " + version) //s.log.Error(command2.ExecResultStr(config.AppInfo.ProjectPath + "/shell/tool.sh -r " + version)) }