Explorar o código

move app domain to its own module (0.4.x) (#689)

Tiger Wang %!s(int64=2) %!d(string=hai) anos
pai
achega
536eac788d
Modificáronse 51 ficheiros con 319 adicións e 5538 borrados
  1. 0 89
      common/notify.go
  2. 0 29
      common/notify_test.go
  3. 0 78
      common/share.go
  4. 0 14
      common/share_test.go
  5. 2 16
      go.mod
  6. 8 454
      go.sum
  7. 10 14
      main.go
  8. 0 128
      model/app.go
  9. 0 23
      model/category.go
  10. 0 24
      model/docker.go
  11. 0 133
      model/manifest.go
  12. 0 21
      model/notify/application.go
  13. 1 5
      model/sys_common.go
  14. 5 8
      pkg/config/init.go
  15. 0 3
      pkg/docker/emum.go
  16. 0 402
      pkg/docker/helper.go
  17. 0 11
      pkg/docker/volumes.go
  18. 0 10
      pkg/docker/volumes_test.go
  19. 6 7
      pkg/sqlite/db.go
  20. 0 26
      pkg/utils/env_helper/env.go
  21. 23 27
      pkg/utils/httper/httper.go
  22. 0 92
      pkg/utils/loger/log.go
  23. 0 68
      pkg/utils/port/port.go
  24. 0 18
      pkg/utils/port/port_test.go
  25. 0 24
      pkg/utils/random/random.go
  26. 0 10
      pkg/utils/random/random_test.go
  27. 5 5
      route/init.go
  28. 2 4
      route/periodical.go
  29. 2 63
      route/route.go
  30. 3 5
      route/socket.go
  31. 0 355
      route/v1/app.go
  32. 0 1267
      route/v1/docker.go
  33. 12 25
      route/v1/file.go
  34. 56 0
      route/v1/notify.go
  35. 0 23
      route/v1/notiry.go
  36. 96 0
      route/v1/ssh.go
  37. 40 41
      route/v1/system.go
  38. 0 480
      service/app.go
  39. 1 247
      service/casa.go
  40. 0 962
      service/docker.go
  41. 0 24
      service/docker_base/common.go
  42. 0 9
      service/docker_base/model.go
  43. 0 93
      service/docker_base/mysql.go
  44. 0 50
      service/docker_test.go
  45. 4 6
      service/file.go
  46. 0 78
      service/model/o_container.go
  47. 7 23
      service/model/o_rely.go
  48. 18 15
      service/notify.go
  49. 8 20
      service/service.go
  50. 9 8
      service/system.go
  51. 1 1
      types/system.go

+ 0 - 89
common/notify.go

@@ -1,89 +0,0 @@
-package common
-
-import (
-	"bytes"
-	"encoding/json"
-	"errors"
-	"fmt"
-	"net/http"
-	"os"
-	"path/filepath"
-	"strings"
-)
-
-const (
-	CasaOSURLFilename = "casaos.url"
-	APICasaOSNotify   = "/v1/notify"
-)
-
-type NotifyService interface {
-	SendNotify(path string, message map[string]interface{}) error
-	SendSystemStatusNotify(message map[string]interface{}) error
-}
-type notifyService struct {
-	address string
-}
-
-func (n *notifyService) SendNotify(path string, message map[string]interface{}) error {
-
-	url := strings.TrimSuffix(n.address, "/") + APICasaOSNotify + "/" + path
-	body, err := json.Marshal(message)
-	if err != nil {
-		return err
-	}
-	response, err := http.Post(url, "application/json", bytes.NewBuffer(body))
-	if err != nil {
-		return err
-	}
-
-	if response.StatusCode != http.StatusOK {
-		return errors.New("failed to send notify (status code: " + fmt.Sprint(response.StatusCode) + ")")
-	}
-	return nil
-
-}
-
-// disk: "sys_disk":{"size":56866869248,"avail":5855485952,"health":true,"used":48099700736}
-// usb:   "sys_usb":[{"name": "sdc","size": 7747397632,"model": "DataTraveler_2.0","avail": 7714418688,"children": null}]
-func (n *notifyService) SendSystemStatusNotify(message map[string]interface{}) error {
-
-	url := strings.TrimSuffix(n.address, "/") + APICasaOSNotify + "/system_status"
-	fmt.Println(url)
-	body, err := json.Marshal(message)
-	if err != nil {
-		return err
-	}
-	response, err := http.Post(url, "application/json", bytes.NewBuffer(body))
-	if err != nil {
-		return err
-	}
-
-	if response.StatusCode != http.StatusOK {
-		return errors.New("failed to send notify (status code: " + fmt.Sprint(response.StatusCode) + ")")
-	}
-	return nil
-
-}
-func NewNotifyService(runtimePath string) (NotifyService, error) {
-	casaosAddressFile := filepath.Join(runtimePath, CasaOSURLFilename)
-
-	buf, err := os.ReadFile(casaosAddressFile)
-	if err != nil {
-		return nil, err
-	}
-
-	address := string(buf)
-
-	response, err := http.Get(address + "/ping")
-	if err != nil {
-		return nil, err
-	}
-
-	if response.StatusCode != 200 {
-		return nil, errors.New("failed to ping casaos service")
-	}
-
-	return &notifyService{
-		address: address,
-	}, nil
-}

+ 0 - 29
common/notify_test.go

@@ -1,29 +0,0 @@
-package common
-
-import "testing"
-
-func TestSendNotify(t *testing.T) {
-	notify, err := NewNotifyService("/var/run/casaos")
-	if err != nil {
-		t.Fatal(err)
-	}
-	err = notify.SendNotify("test", map[string]interface{}{
-		"test": "test",
-	})
-	if err != nil {
-		t.Fatal(err)
-	}
-}
-
-func TestSendSystemStatusNotify(t *testing.T) {
-	notify, err := NewNotifyService("/var/run/casaos")
-	if err != nil {
-		t.Fatal(err)
-	}
-	err = notify.SendSystemStatusNotify(map[string]interface{}{
-		"sys_usb": `[{"name": "sdc","size": 7747397632,"model": "DataTraveler_2.0","avail": 7714418688,"children": null}]`,
-	})
-	if err != nil {
-		t.Fatal(err)
-	}
-}

+ 0 - 78
common/share.go

@@ -1,78 +0,0 @@
-package common
-
-import (
-	"bytes"
-	"encoding/json"
-	"errors"
-	"fmt"
-	"net/http"
-	"os"
-	"path/filepath"
-	"strings"
-)
-
-const (
-	APICasaOSShare = "/v1/samba/shares"
-)
-
-type ShareService interface {
-	DeleteShare(id string) error
-}
-type shareService struct {
-	address string
-}
-
-func (n *shareService) DeleteShare(id string) error {
-	url := strings.TrimSuffix(n.address, "/") + APICasaOSShare + "/" + id
-	fmt.Println(url)
-	message := "{}"
-	body, err := json.Marshal(message)
-	if err != nil {
-		return err
-	}
-
-	client := &http.Client{}
-
-	// Create request
-	req, err := http.NewRequest("DELETE", url, bytes.NewBuffer(body))
-	if err != nil {
-		return err
-	}
-
-	// Fetch Request
-	response, err := client.Do(req)
-	if err != nil {
-		return err
-	}
-	defer response.Body.Close()
-
-	if response.StatusCode != http.StatusOK {
-		return errors.New("failed to send share (status code: " + fmt.Sprint(response.StatusCode) + ")")
-	}
-	return nil
-
-}
-
-func NewShareService(runtimePath string) (ShareService, error) {
-	casaosAddressFile := filepath.Join(runtimePath, CasaOSURLFilename)
-
-	buf, err := os.ReadFile(casaosAddressFile)
-	if err != nil {
-		return nil, err
-	}
-
-	address := string(buf)
-
-	response, err := http.Get(address + "/ping")
-	if err != nil {
-		return nil, err
-	}
-
-	if response.StatusCode != 200 {
-		return nil, errors.New("failed to ping casaos service")
-	}
-
-	return &shareService{
-		address: address,
-	}, nil
-}

+ 0 - 14
common/share_test.go

@@ -1,14 +0,0 @@
-package common
-
-import "testing"
-
-func TestDeleteShare(t *testing.T) {
-	share, err := NewShareService("/var/run/casaos")
-	if err != nil {
-		t.Fatal(err)
-	}
-	err = share.DeleteShare("1")
-	if err != nil {
-		t.Fatal(err)
-	}
-}

+ 2 - 16
go.mod

@@ -4,18 +4,13 @@ go 1.16
 
 require (
 	github.com/Curtis-Milo/nat-type-identifier-go v0.0.0-20220215191915-18d42168c63d
-	github.com/IceWhaleTech/CasaOS-Common v0.3.7-5
+	github.com/IceWhaleTech/CasaOS-Common v0.4.0-alpha1
 	github.com/IceWhaleTech/CasaOS-Gateway v0.3.6
-	github.com/Microsoft/go-winio v0.5.0 // indirect
 	github.com/ambelovsky/go-structs v1.1.0 // indirect
 	github.com/ambelovsky/gosf v0.0.0-20201109201340-237aea4d6109
 	github.com/ambelovsky/gosf-socketio v0.0.0-20201109193639-add9d32f8b19 // indirect
-	github.com/containerd/containerd v1.5.7 // indirect
 	github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e
 	github.com/disintegration/imaging v1.6.2
-	github.com/docker/distribution v2.8.0+incompatible // indirect
-	github.com/docker/docker v20.10.7+incompatible
-	github.com/docker/go-connections v0.4.0
 	github.com/dsoprea/go-exif/v3 v3.0.0-20210625224831-a6301f85c82b
 	github.com/dsoprea/go-logging v0.0.0-20200710184922-b02d349568dd // indirect
 	github.com/gin-contrib/gzip v0.0.6
@@ -25,21 +20,14 @@ require (
 	github.com/gomodule/redigo v1.8.5
 	github.com/google/go-github/v36 v36.0.0
 	github.com/googollee/go-socket.io v1.6.2
-	github.com/gorilla/mux v1.8.0 // indirect
-	github.com/gorilla/websocket v1.4.2
+	github.com/gorilla/websocket v1.5.0
 	github.com/hirochachacha/go-smb2 v1.1.0
-	github.com/jinzhu/copier v0.3.2
 	github.com/lucas-clemente/quic-go v0.25.0
 	github.com/mholt/archiver/v3 v3.5.1
-	github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect
-	github.com/morikuni/aec v1.0.0 // indirect
-	github.com/opencontainers/image-spec v1.0.2 // indirect
 	github.com/patrickmn/go-cache v2.1.0+incompatible
-	github.com/pkg/errors v0.9.1
 	github.com/robfig/cron v1.2.0
 	github.com/satori/go.uuid v1.2.0
 	github.com/shirou/gopsutil/v3 v3.22.7
-	github.com/sirupsen/logrus v1.8.1
 	github.com/smartystreets/assertions v1.2.0 // indirect
 	github.com/smartystreets/goconvey v1.6.4 // indirect
 	github.com/stretchr/testify v1.8.0
@@ -48,9 +36,7 @@ require (
 	golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4
 	golang.org/x/mod v0.5.0 // indirect
 	golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5
-	golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect
 	golang.org/x/tools v0.1.7 // indirect
-	gopkg.in/natefinch/lumberjack.v2 v2.0.0
 	gorm.io/driver/sqlite v1.2.6
 	gorm.io/gorm v1.22.5
 )

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 8 - 454
go.sum


+ 10 - 14
main.go

@@ -9,12 +9,12 @@ import (
 	"time"
 
 	"github.com/IceWhaleTech/CasaOS-Common/model"
+	"github.com/IceWhaleTech/CasaOS-Common/utils/logger"
 	"github.com/IceWhaleTech/CasaOS/model/notify"
 	"github.com/IceWhaleTech/CasaOS/pkg/cache"
 	"github.com/IceWhaleTech/CasaOS/pkg/config"
 	"github.com/IceWhaleTech/CasaOS/pkg/sqlite"
 	"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
-	"github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
 	"github.com/IceWhaleTech/CasaOS/route"
 	"github.com/IceWhaleTech/CasaOS/service"
 	"github.com/IceWhaleTech/CasaOS/types"
@@ -43,7 +43,7 @@ func init() {
 	}
 	config.InitSetup(*configFlag)
 
-	loger.LogInit()
+	logger.LogInit(config.AppInfo.LogPath, config.AppInfo.LogSaveName, config.AppInfo.LogFileExt)
 	if len(*dbFlag) == 0 {
 		*dbFlag = config.AppInfo.DBPath + "/db"
 	}
@@ -55,14 +55,9 @@ func init() {
 
 	service.Cache = cache.Init()
 
-	service.GetToken()
 	service.GetCPUThermalZone()
 
-	service.NewVersionApp = make(map[string]string)
 	route.InitFunction()
-
-	// go service.LoopFriend()
-	// go service.MyService.App().CheckNewImage()
 }
 
 // @title casaOS API
@@ -111,7 +106,7 @@ func main() {
 	if err != nil {
 		panic(err)
 	}
-	routers := []string{"sys", "apps", "container", "app-categories", "port", "file", "folder", "batch", "image", "samba", "notify"}
+	routers := []string{"sys", "port", "file", "folder", "batch", "image", "samba", "notify"}
 	for _, v := range routers {
 		err = service.MyService.Gateway().CreateRoute(&model.Route{
 			Path:   "/v1/" + v,
@@ -138,20 +133,19 @@ func main() {
 	}()
 
 	urlFilePath := filepath.Join(config.CommonInfo.RuntimePath, "casaos.url")
-	err = file.CreateFileAndWriteContent(urlFilePath, "http://"+listener.Addr().String())
-	if err != nil {
-		loger.Error("Management service is listening...",
+	if err := file.CreateFileAndWriteContent(urlFilePath, "http://"+listener.Addr().String()); err != nil {
+		logger.Error("error when creating address file", zap.Error(err),
 			zap.Any("address", listener.Addr().String()),
 			zap.Any("filepath", urlFilePath),
 		)
 	}
 
 	if supported, err := daemon.SdNotify(false, daemon.SdNotifyReady); err != nil {
-		loger.Error("Failed to notify systemd that casaos main service is ready", zap.Any("error", err))
+		logger.Error("Failed to notify systemd that casaos main service is ready", zap.Any("error", err))
 	} else if supported {
-		loger.Info("Notified systemd that casaos main service is ready")
+		logger.Info("Notified systemd that casaos main service is ready")
 	} else {
-		loger.Info("This process is not running as a systemd service.")
+		logger.Info("This process is not running as a systemd service.")
 	}
 
 	s := &http.Server{
@@ -159,6 +153,8 @@ func main() {
 		ReadHeaderTimeout: 5 * time.Second, // fix G112: Potential slowloris attack (see https://github.com/securego/gosec)
 	}
 
+	logger.Info("CasaOS main service is listening...", zap.Any("address", listener.Addr().String()))
+
 	err = s.Serve(listener) // not using http.serve() to fix G114: Use of net/http serve function that has no support for setting timeouts (see https://github.com/securego/gosec)
 	if err != nil {
 		panic(err)

+ 0 - 128
model/app.go

@@ -1,128 +0,0 @@
-package model
-
-import (
-	"database/sql/driver"
-	"encoding/json"
-	"time"
-)
-
-type ServerAppListCollection struct {
-	List      []ServerAppList `json:"list"`
-	Recommend []ServerAppList `json:"recommend"`
-	Community []ServerAppList `json:"community"`
-	Version   string          `json:"version"`
-}
-
-// @tiger - 对于用于出参的数据结构,静态信息(例如 title)和
-//          动态信息(例如 state、query_count)应该划分到不同的数据结构中
-//
-//          这样的好处是
-//          1 - 多次获取动态信息时可以减少出参复杂度,因为静态信息只获取一次就好
-//          2 - 在未来的迭代中,可以降低维护成本(所有字段都展开放在一个层级维护成本略高)
-//
-//          另外,一些针对性字段,例如 Docker 相关的,可以用 map 来保存。
-//          这样在未来增加多态 App,例如 Snap,不需要维护多个结构,或者一个结构保存不必要的字段
-type ServerAppList struct {
-	Id             uint      `gorm:"column:id;primary_key" json:"id"`
-	Title          string    `json:"title"`
-	Description    string    `json:"description"`
-	Tagline        string    `json:"tagline"`
-	Tags           Strings   `gorm:"type:json" json:"tags"`
-	Icon           string    `json:"icon"`
-	ScreenshotLink Strings   `gorm:"type:json" json:"screenshot_link"`
-	Category       string    `json:"category"`
-	CategoryId     int       `json:"category_id"`
-	CategoryFont   string    `json:"category_font"`
-	PortMap        string    `json:"port_map"`
-	ImageVersion   string    `json:"image_version"`
-	Tip            string    `json:"tip"`
-	Envs           EnvArray  `json:"envs"`
-	Ports          PortArray `json:"ports"`
-	Volumes        PathArray `json:"volumes"`
-	Devices        PathArray `json:"devices"`
-	NetworkModel   string    `json:"network_model"`
-	Image          string    `json:"image"`
-	Index          string    `json:"index"`
-	CreatedAt      time.Time `json:"created_at"`
-	UpdatedAt      time.Time `json:"updated_at"`
-	State          int       `json:"state"`
-	Author         string    `json:"author"`
-	MinMemory      int       `json:"min_memory"`
-	MinDisk        int       `json:"min_disk"`
-	MaxMemory      uint64    `json:"max_memory"`
-	Thumbnail      string    `json:"thumbnail"`
-	Healthy        string    `json:"healthy"`
-	Plugins        Strings   `json:"plugins"`
-	Origin         string    `json:"origin"`
-	Type           int       `json:"type"`
-	QueryCount     int       `json:"query_count"`
-	Developer      string    `json:"developer"`
-	HostName       string    `json:"host_name"`
-	Privileged     bool      `json:"privileged"`
-	CapAdd         Strings   `json:"cap_add"`
-	Cmd            Strings   `json:"cmd"`
-}
-
-type Ports struct {
-	ContainerPort uint   `json:"container_port"`
-	CommendPort   int    `json:"commend_port"`
-	Desc          string `json:"desc"`
-	Type          int    `json:"type"` //  1:必选 2:可选 3:默认值不必显示 4:系统处理  5:container内容也可编辑
-}
-
-type Volume struct {
-	ContainerPath string `json:"container_path"`
-	Path          string `json:"path"`
-	Desc          string `json:"desc"`
-	Type          int    `json:"type"` //  1:必选 2:可选 3:默认值不必显示 4:系统处理   5:container内容也可编辑
-}
-
-type Envs struct {
-	Name  string `json:"name"`
-	Value string `json:"value"`
-	Desc  string `json:"desc"`
-	Type  int    `json:"type"` //  1:必选 2:可选 3:默认值不必显示 4:系统处理 5:container内容也可编辑
-}
-
-type Devices struct {
-	ContainerPath string `json:"container_path"`
-	Path          string `json:"path"`
-	Desc          string `json:"desc"`
-	Type          int    `json:"type"` //  1:必选 2:可选 3:默认值不必显示 4:系统处理 5:container内容也可编辑
-}
-
-type configures struct {
-	TcpPorts []Ports   `json:"tcp_ports"`
-	UdpPorts []Ports   `json:"udp_ports"`
-	Envs     []Envs    `json:"envs"`
-	Volumes  []Volume  `json:"volumes"`
-	Devices  []Devices `json:"devices"`
-}
-
-/****************使gorm支持[]string结构*******************/
-type Strings []string
-
-func (c Strings) Value() (driver.Value, error) {
-	b, err := json.Marshal(c)
-	return string(b), err
-}
-
-func (c *Strings) Scan(input interface{}) error {
-	return json.Unmarshal(input.([]byte), c)
-}
-
-/****************使gorm支持[]string结构*******************/
-
-/****************使gorm支持[]string结构*******************/
-type MapStrings []map[string]string
-
-func (c MapStrings) Value() (driver.Value, error) {
-	b, err := json.Marshal(c)
-	return string(b), err
-}
-
-func (c *MapStrings) Scan(input interface{}) error {
-	return json.Unmarshal(input.([]byte), c)
-}
-
-/****************使gorm支持[]string结构*******************/

+ 0 - 23
model/category.go

@@ -1,23 +0,0 @@
-/*
- * @Author: link a624669980@163.com
- * @Date: 2022-05-16 17:37:08
- * @LastEditors: LinkLeong
- * @LastEditTime: 2022-07-13 10:46:38
- * @FilePath: /CasaOS/model/category.go
- * @Description:
- */
-package model
-
-type ServerCategoryList struct {
-	Version string         `json:"version"`
-	Item    []CategoryList `json:"item"`
-}
-type CategoryList struct {
-	Id uint `gorm:"column:id;primary_key" json:"id"`
-	//CreatedAt time.Time `json:"created_at"`
-	//
-	//UpdatedAt time.Time `json:"updated_at"`
-	Font  string `json:"font"` // @tiger - 如果这个和前端有关,应该不属于后端的出参范围,而是前端去界定
-	Name  string `json:"name"`
-	Count uint   `json:"count"` // @tiger - count 属于动态信息,应该单独放在一个出参结构中(原因见另外一个关于 静态/动态 出参的注释)
-}

+ 0 - 24
model/docker.go

@@ -1,24 +0,0 @@
-/*
- * @Author: LinkLeong link@icewhale.com
- * @Date: 2021-12-08 18:10:25
- * @LastEditors: LinkLeong
- * @LastEditTime: 2022-07-13 10:49:16
- * @FilePath: /CasaOS/model/docker.go
- * @Description:
- * @Website: https://www.casaos.io
- * Copyright (c) 2022 by icewhale, All Rights Reserved.
- */
-package model
-
-type DockerStatsModel struct {
-	Icon     string      `json:"icon"`
-	Title    string      `json:"title"`
-	Data     interface{} `json:"data"`
-	Previous interface{} `json:"previous"`
-}
-
-// reference - https://docs.docker.com/engine/reference/commandline/dockerd/#daemon-configuration-file
-type DockerDaemonConfigurationModel struct {
-	// e.g. `/var/lib/docker`
-	Root string `json:"data-root,omitempty"`
-}

+ 0 - 133
model/manifest.go

@@ -1,133 +0,0 @@
-package model
-
-import (
-	"database/sql/driver"
-	"encoding/json"
-)
-
-type TcpPorts struct {
-	Desc          string `json:"desc"`
-	ContainerPort int    `json:"container_port"`
-}
-type UdpPorts struct {
-	Desc          string `json:"desc"`
-	ContainerPort int    `json:"container_port"`
-}
-
-/*******************使用gorm支持json************************************/
-
-type PortMap struct {
-	ContainerPort string `json:"container"`
-	CommendPort   string `json:"host"`
-	Protocol      string `json:"protocol"`
-	Desc          string `json:"desc"`
-	Type          int    `json:"type"`
-}
-
-type PortArray []PortMap
-
-// Value 实现方法
-func (p PortArray) Value() (driver.Value, error) {
-	return json.Marshal(p)
-}
-
-// Scan 实现方法
-func (p *PortArray) Scan(input interface{}) error {
-	return json.Unmarshal(input.([]byte), p)
-}
-
-/************************************************************************/
-
-/*******************使用gorm支持json************************************/
-
-type Env struct {
-	Name  string `json:"container"`
-	Value string `json:"host"`
-	Desc  string `json:"desc"`
-	Type  int    `json:"type"`
-}
-
-type JSON json.RawMessage
-
-type EnvArray []Env
-
-// Value 实现方法
-func (p EnvArray) Value() (driver.Value, error) {
-	return json.Marshal(p)
-	//return .MarshalJSON()
-}
-
-// Scan 实现方法
-func (p *EnvArray) Scan(input interface{}) error {
-	return json.Unmarshal(input.([]byte), p)
-}
-
-/************************************************************************/
-
-/*******************使用gorm支持json************************************/
-
-type PathMap struct {
-	ContainerPath string `json:"container"`
-	Path          string `json:"host"`
-	Type          int    `json:"type"`
-	Desc          string `json:"desc"`
-}
-
-type PathArray []PathMap
-
-// Value 实现方法
-func (p PathArray) Value() (driver.Value, error) {
-	return json.Marshal(p)
-}
-
-// Scan 实现方法
-func (p *PathArray) Scan(input interface{}) error {
-	return json.Unmarshal(input.([]byte), p)
-}
-
-/************************************************************************/
-
-//type PostData struct {
-//	Envs       EnvArrey  `json:"envs,omitempty"`
-//	Udp        PortArrey `json:"udp_ports"`
-//	Tcp        PortArrey `json:"tcp_ports"`
-//	Volumes    PathArrey `json:"volumes"`
-//	Devices    PathArrey `json:"devices"`
-//	Port       string    `json:"port,omitempty"`
-//	PortMap    string    `json:"port_map"`
-//	CpuShares  int64     `json:"cpu_shares,omitempty"`
-//	Memory     int64     `json:"memory,omitempty"`
-//	Restart    string    `json:"restart,omitempty"`
-//	EnableUPNP bool      `json:"enable_upnp"`
-//	Label      string    `json:"label"`
-//	Position   bool      `json:"position"`
-//}
-
-type CustomizationPostData struct {
-	ContainerName string    `json:"container_name"`
-	CustomId      string    `json:"custom_id"`
-	Origin        string    `json:"origin"`
-	NetworkModel  string    `json:"network_model"`
-	Index         string    `json:"index"`
-	Icon          string    `json:"icon"`
-	Image         string    `json:"image"`
-	Envs          EnvArray  `json:"envs"`
-	Ports         PortArray `json:"ports"`
-	Volumes       PathArray `json:"volumes"`
-	Devices       PathArray `json:"devices"`
-	//Port         string    `json:"port,omitempty"`
-	PortMap     string   `json:"port_map"`
-	CpuShares   int64    `json:"cpu_shares"`
-	Memory      int64    `json:"memory"`
-	Restart     string   `json:"restart"`
-	EnableUPNP  bool     `json:"enable_upnp"`
-	Label       string   `json:"label"`
-	Description string   `json:"description"`
-	Position    bool     `json:"position"`
-	HostName    string   `json:"host_name"`
-	Privileged  bool     `json:"privileged"`
-	CapAdd      []string `json:"cap_add"`
-	Cmd         []string `json:"cmd"`
-	Protocol    string   `json:"protocol"`
-	Host        string   `json:"host"`
-}

+ 0 - 21
model/notify/application.go

@@ -1,21 +0,0 @@
-/*
- * @Author: LinkLeong link@icewhale.com
- * @Date: 2022-05-27 15:01:58
- * @LastEditors: LinkLeong
- * @LastEditTime: 2022-05-31 14:51:21
- * @FilePath: /CasaOS/model/notify/application.go
- * @Description:
- * @Website: https://www.casaos.io
- * Copyright (c) 2022 by icewhale, All Rights Reserved.
- */
-package notify
-
-type Application struct {
-	Name     string `json:"name"`
-	State    string `json:"state"`
-	Type     string `json:"type"`
-	Icon     string `json:"icon"`
-	Message  string `json:"message"`
-	Finished bool   `json:"finished"`
-	Success  bool   `json:"success"`
-}

+ 1 - 5
model/sys_common.go

@@ -14,7 +14,7 @@ import "time"
 
 // 系统配置
 type SysInfoModel struct {
-	Name string //系统名称
+	Name string // 系统名称
 }
 
 // 服务配置
@@ -66,10 +66,6 @@ type SystemConfig struct {
 	ConfigPath string `json:"config_path"`
 }
 
-type CasaOSGlobalVariables struct {
-	AppChange bool
-}
-
 type FileSetting struct {
 	ShareDir    []string `json:"share_dir" delim:"|"`
 	DownloadDir string   `json:"download_dir"`

+ 5 - 8
pkg/config/init.go

@@ -31,23 +31,20 @@ var AppInfo = &model.APPModel{}
 
 var CommonInfo = &model.CommonModel{}
 
-//var RedisInfo = &model.RedisModel{}
+// var RedisInfo = &model.RedisModel{}
 
 // server相关
 var ServerInfo = &model.ServerModel{}
 
 var SystemConfigInfo = &model.SystemConfig{}
 
-var CasaOSGlobalVariables = &model.CasaOSGlobalVariables{}
-
 var FileSettingInfo = &model.FileSetting{}
 
 var Cfg *ini.File
 
 // 初始化设置,获取系统的部分信息。
 func InitSetup(config string) {
-
-	var configDir = USERCONFIGURL
+	configDir := USERCONFIGURL
 	if len(config) > 0 {
 		configDir = config
 	}
@@ -55,7 +52,7 @@ func InitSetup(config string) {
 		configDir = "./conf/conf.conf"
 	}
 	var err error
-	//读取文件
+	// 读取文件
 	Cfg, err = ini.Load(configDir)
 	if err != nil {
 		Cfg, err = ini.Load("/etc/casaos.conf")
@@ -68,7 +65,7 @@ func InitSetup(config string) {
 		}
 	}
 	mapTo("app", AppInfo)
-	//mapTo("redis", RedisInfo)
+	// mapTo("redis", RedisInfo)
 	mapTo("server", ServerInfo)
 	mapTo("system", SystemConfigInfo)
 	mapTo("file", FileSettingInfo)
@@ -91,7 +88,6 @@ func InitSetup(config string) {
 	}
 	Cfg.SaveTo(configDir)
 	//	AppInfo.ProjectPath = getCurrentDirectory() //os.Getwd()
-
 }
 
 // 映射
@@ -111,6 +107,7 @@ func getCurrentAbPathByCaller() string {
 	}
 	return abPath
 }
+
 func getCurrentDirectory() string {
 	dir, err := filepath.Abs(filepath.Dir(os.Args[0]))
 	if err != nil {

+ 0 - 3
pkg/docker/emum.go

@@ -1,3 +0,0 @@
-package docker
-
-const NETWORKNAME = "oasis"

+ 0 - 402
pkg/docker/helper.go

@@ -1,402 +0,0 @@
-package docker
-
-import (
-	"bytes"
-	json2 "encoding/json"
-	"fmt"
-	"io"
-	"regexp"
-	"sync"
-	"time"
-
-	"github.com/gorilla/websocket"
-	"github.com/sirupsen/logrus"
-	"golang.org/x/crypto/ssh"
-)
-
-func NewSshClient(user, password string, port string) (*ssh.Client, error) {
-	// connet to ssh
-	// addr = fmt.Sprintf("%s:%d", host, port)
-
-	config := &ssh.ClientConfig{
-		Timeout:         time.Second * 5,
-		User:            user,
-		HostKeyCallback: ssh.InsecureIgnoreHostKey(),
-		// HostKeyCallback: ,
-		// HostKeyCallback: hostKeyCallBackFunc(h.Host),
-	}
-	// if h.Type == "password" {
-	config.Auth = []ssh.AuthMethod{ssh.Password(password)}
-	//} else {
-	//	config.Auth = []ssh.AuthMethod{publicKeyAuthFunc(h.Key)}
-	//}
-	addr := fmt.Sprintf("%s:%s", "127.0.0.1", port)
-	c, err := ssh.Dial("tcp", addr, config)
-	if err != nil {
-		return nil, err
-	}
-	return c, nil
-}
-
-// setup ssh shell session
-// set Session and StdinPipe here,
-// and the Session.Stdout and Session.Sdterr are also set.
-func NewSshConn(cols, rows int, sshClient *ssh.Client) (*SshConn, error) {
-	sshSession, err := sshClient.NewSession()
-	if err != nil {
-		return nil, err
-	}
-
-	stdinP, err := sshSession.StdinPipe()
-	if err != nil {
-		return nil, err
-	}
-	comboWriter := new(wsBufferWriter)
-
-	sshSession.Stdout = comboWriter
-	sshSession.Stderr = comboWriter
-
-	modes := ssh.TerminalModes{
-		ssh.ECHO:          1,     // disable echo
-		ssh.TTY_OP_ISPEED: 14400, // input speed = 14.4kbaud
-		ssh.TTY_OP_OSPEED: 14400, // output speed = 14.4kbaud
-	}
-	// Request pseudo terminal
-	if err := sshSession.RequestPty("xterm", rows, cols, modes); err != nil {
-		return nil, err
-	}
-	// Start remote shell
-	if err := sshSession.Shell(); err != nil {
-		return nil, err
-	}
-	return &SshConn{StdinPipe: stdinP, ComboOutput: comboWriter, Session: sshSession}, nil
-}
-
-type SshConn struct {
-	// calling Write() to write data into ssh server
-	StdinPipe io.WriteCloser
-	// Write() be called to receive data from ssh server
-	ComboOutput *wsBufferWriter
-	Session     *ssh.Session
-}
-type wsBufferWriter struct {
-	buffer bytes.Buffer
-	mu     sync.Mutex
-}
-
-func (w *wsBufferWriter) Write(p []byte) (int, error) {
-	w.mu.Lock()
-	defer w.mu.Unlock()
-	return w.buffer.Write(p)
-}
-
-func (s *SshConn) Close() {
-	if s.Session != nil {
-		s.Session.Close()
-	}
-}
-
-const (
-	wsMsgCmd    = "cmd"
-	wsMsgResize = "resize"
-)
-
-// ReceiveWsMsg  receive websocket msg do some handling then write into ssh.session.stdin
-func ReceiveWsMsgUser(wsConn *websocket.Conn, logBuff *bytes.Buffer) string {
-	// tells other go routine quit
-	username := ""
-	for {
-
-		// read websocket msg
-		_, wsData, err := wsConn.ReadMessage()
-		if err != nil {
-			return ""
-		}
-
-		msgObj := wsMsg{}
-		if err := json2.Unmarshal(wsData, &msgObj); err != nil {
-			msgObj.Type = "cmd"
-			msgObj.Cmd = string(wsData)
-		}
-		//if err := json.Unmarshal(wsData, &msgObj); err != nil {
-		//	logrus.WithError(err).WithField("wsData", string(wsData)).Error("unmarshal websocket message failed")
-		//}
-		switch msgObj.Type {
-		case wsMsgCmd:
-			// handle xterm.js stdin
-			// decodeBytes, err := base64.StdEncoding.DecodeString(msgObj.Cmd)
-			decodeBytes := []byte(msgObj.Cmd)
-			if msgObj.Cmd == "\u007f" {
-				if len(username) == 0 {
-					continue
-				}
-				wsConn.WriteMessage(websocket.TextMessage, []byte("\b\x1b[K"))
-				username = username[:len(username)-1]
-				continue
-			}
-			if msgObj.Cmd == "\r" {
-				return username
-			}
-			username += msgObj.Cmd
-
-			if err := wsConn.WriteMessage(websocket.TextMessage, decodeBytes); err != nil {
-				logrus.WithError(err).Error("ws cmd bytes write to ssh.stdin pipe failed")
-			}
-			// write input cmd to log buffer
-			if _, err := logBuff.Write(decodeBytes); err != nil {
-				logrus.WithError(err).Error("write received cmd into log buffer failed")
-			}
-		}
-
-	}
-}
-
-func ReceiveWsMsgPassword(wsConn *websocket.Conn, logBuff *bytes.Buffer) string {
-	// tells other go routine quit
-	password := ""
-	for {
-
-		// read websocket msg
-		_, wsData, err := wsConn.ReadMessage()
-		if err != nil {
-			logrus.WithError(err).Error("reading webSocket message failed")
-			return ""
-		}
-
-		msgObj := wsMsg{}
-		if err := json2.Unmarshal(wsData, &msgObj); err != nil {
-			msgObj.Type = "cmd"
-			msgObj.Cmd = string(wsData)
-		}
-		//if err := json.Unmarshal(wsData, &msgObj); err != nil {
-		//	logrus.WithError(err).WithField("wsData", string(wsData)).Error("unmarshal websocket message failed")
-		//}
-		switch msgObj.Type {
-		case wsMsgCmd:
-			// handle xterm.js stdin
-			// decodeBytes, err := base64.StdEncoding.DecodeString(msgObj.Cmd)
-			if msgObj.Cmd == "\r" {
-				return password
-			}
-
-			if msgObj.Cmd == "\u007f" {
-				if len(password) == 0 {
-					continue
-				}
-				password = password[:len(password)-1]
-				continue
-			}
-			password += msgObj.Cmd
-		}
-
-	}
-}
-
-// ReceiveWsMsg  receive websocket msg do some handling then write into ssh.session.stdin
-func (ssConn *SshConn) ReceiveWsMsg(wsConn *websocket.Conn, logBuff *bytes.Buffer, exitCh chan bool) {
-	// tells other go routine quit
-	defer setQuit(exitCh)
-	for {
-		select {
-		case <-exitCh:
-			return
-		default:
-			// read websocket msg
-			_, wsData, err := wsConn.ReadMessage()
-			if err != nil {
-				logrus.WithError(err).Error("reading webSocket message failed")
-				return
-			}
-			//unmashal bytes into struct
-			//msgObj := wsMsg{
-			//	Type: "cmd",
-			//	Cmd:  "",
-			//	Rows: 50,
-			//	Cols: 180,
-			//}
-			msgObj := wsMsg{}
-			if err := json2.Unmarshal(wsData, &msgObj); err != nil {
-				msgObj.Type = "cmd"
-				msgObj.Cmd = string(wsData)
-			}
-			//if err := json.Unmarshal(wsData, &msgObj); err != nil {
-			//	logrus.WithError(err).WithField("wsData", string(wsData)).Error("unmarshal websocket message failed")
-			//}
-			switch msgObj.Type {
-
-			case wsMsgResize:
-				// handle xterm.js size change
-				if msgObj.Cols > 0 && msgObj.Rows > 0 {
-					if err := ssConn.Session.WindowChange(msgObj.Rows, msgObj.Cols); err != nil {
-						logrus.WithError(err).Error("ssh pty change windows size failed")
-					}
-				}
-			case wsMsgCmd:
-				// handle xterm.js stdin
-				// decodeBytes, err := base64.StdEncoding.DecodeString(msgObj.Cmd)
-				decodeBytes := []byte(msgObj.Cmd)
-				if err != nil {
-					logrus.WithError(err).Error("websock cmd string base64 decoding failed")
-				}
-				if _, err := ssConn.StdinPipe.Write(decodeBytes); err != nil {
-					logrus.WithError(err).Error("ws cmd bytes write to ssh.stdin pipe failed")
-				}
-				// write input cmd to log buffer
-				if _, err := logBuff.Write(decodeBytes); err != nil {
-					logrus.WithError(err).Error("write received cmd into log buffer failed")
-				}
-			}
-		}
-	}
-}
-
-func (ssConn *SshConn) SendComboOutput(wsConn *websocket.Conn, exitCh chan bool) {
-	// tells other go routine quit
-	// defer setQuit(exitCh)
-
-	// every 120ms write combine output bytes into websocket response
-	tick := time.NewTicker(time.Millisecond * time.Duration(120))
-	// for range time.Tick(120 * time.Millisecond){}
-	defer tick.Stop()
-	for {
-		select {
-		case <-tick.C:
-			// write combine output bytes into websocket response
-			if err := flushComboOutput(ssConn.ComboOutput, wsConn); err != nil {
-				logrus.WithError(err).Error("ssh sending combo output to webSocket failed")
-				return
-			}
-		case <-exitCh:
-			return
-		}
-	}
-}
-
-func flushComboOutput(w *wsBufferWriter, wsConn *websocket.Conn) error {
-	if w.buffer.Len() != 0 {
-		err := wsConn.WriteMessage(websocket.TextMessage, w.buffer.Bytes())
-		if err != nil {
-			return err
-		}
-		w.buffer.Reset()
-	}
-	return nil
-}
-
-// ReceiveWsMsg  receive websocket msg do some handling then write into ssh.session.stdin
-func (ssConn *SshConn) Login(wsConn *websocket.Conn, logBuff *bytes.Buffer, exitCh chan bool) {
-	// tells other go routine quit
-	defer setQuit(exitCh)
-	for {
-		select {
-		case <-exitCh:
-			return
-		default:
-			// read websocket msg
-			_, wsData, err := wsConn.ReadMessage()
-			if err != nil {
-				logrus.WithError(err).Error("reading webSocket message failed")
-				return
-			}
-			//unmashal bytes into struct
-			//msgObj := wsMsg{
-			//	Type: "cmd",
-			//	Cmd:  "",
-			//	Rows: 50,
-			//	Cols: 180,
-			//}
-			msgObj := wsMsg{}
-			if err := json2.Unmarshal(wsData, &msgObj); err != nil {
-				msgObj.Type = "cmd"
-				msgObj.Cmd = string(wsData)
-			}
-			//if err := json.Unmarshal(wsData, &msgObj); err != nil {
-			//	logrus.WithError(err).WithField("wsData", string(wsData)).Error("unmarshal websocket message failed")
-			//}
-			switch msgObj.Type {
-
-			case wsMsgResize:
-				// handle xterm.js size change
-				if msgObj.Cols > 0 && msgObj.Rows > 0 {
-					if err := ssConn.Session.WindowChange(msgObj.Rows, msgObj.Cols); err != nil {
-						logrus.WithError(err).Error("ssh pty change windows size failed")
-					}
-				}
-			case wsMsgCmd:
-				// handle xterm.js stdin
-				// decodeBytes, err := base64.StdEncoding.DecodeString(msgObj.Cmd)
-				decodeBytes := []byte(msgObj.Cmd)
-				if err != nil {
-					logrus.WithError(err).Error("websock cmd string base64 decoding failed")
-				}
-				if _, err := ssConn.StdinPipe.Write(decodeBytes); err != nil {
-					logrus.WithError(err).Error("ws cmd bytes write to ssh.stdin pipe failed")
-				}
-				// write input cmd to log buffer
-				if _, err := logBuff.Write(decodeBytes); err != nil {
-					logrus.WithError(err).Error("write received cmd into log buffer failed")
-				}
-			}
-		}
-	}
-}
-
-func (ssConn *SshConn) SessionWait(quitChan chan bool) {
-	if err := ssConn.Session.Wait(); err != nil {
-		logrus.WithError(err).Error("ssh session wait failed")
-		setQuit(quitChan)
-	}
-}
-
-func setQuit(ch chan bool) {
-	ch <- true
-}
-
-type wsMsg struct {
-	Type string `json:"type"`
-	Cmd  string `json:"cmd"`
-	Cols int    `json:"cols"`
-	Rows int    `json:"rows"`
-}
-
-// 将终端的输出转发到前端
-func WsWriterCopy(reader io.Reader, writer *websocket.Conn) {
-	buf := make([]byte, 8192)
-	reg1 := regexp.MustCompile(`stty rows \d+ && stty cols \d+ `)
-	for {
-		nr, err := reader.Read(buf)
-		if nr > 0 {
-			result1 := reg1.FindIndex(buf[0:nr])
-			if len(result1) > 0 {
-				fmt.Println(result1)
-			} else {
-				err := writer.WriteMessage(websocket.BinaryMessage, buf[0:nr])
-				if err != nil {
-					return
-				}
-			}
-
-		}
-		if err != nil {
-			return
-		}
-	}
-}
-
-// 将前端的输入转发到终端
-func WsReaderCopy(reader *websocket.Conn, writer io.Writer) {
-	for {
-		messageType, p, err := reader.ReadMessage()
-		if err != nil {
-			return
-		}
-		if messageType == websocket.TextMessage {
-			msgObj := wsMsg{}
-			if err = json2.Unmarshal(p, &msgObj); err != nil {
-				writer.Write(p)
-			} else if msgObj.Type == wsMsgResize {
-				// writer.Write([]byte("stty rows " + strconv.Itoa(msgObj.Rows) + " && stty cols " + strconv.Itoa(msgObj.Cols) + " \r"))
-			}
-		}
-	}
-}

+ 0 - 11
pkg/docker/volumes.go

@@ -1,11 +0,0 @@
-package docker
-
-import "strings"
-
-func GetDir(id, envName string) string {
-
-	if strings.Contains(envName, "$AppID") && len(id) > 0 {
-		return strings.ReplaceAll(envName, "$AppID", id)
-	}
-	return envName
-}

+ 0 - 10
pkg/docker/volumes_test.go

@@ -1,10 +0,0 @@
-package docker
-
-import (
-	"fmt"
-	"testing"
-)
-
-func TestGetDir(t *testing.T) {
-	fmt.Println(GetDir("", "config"))
-}

+ 6 - 7
pkg/sqlite/db.go

@@ -13,8 +13,8 @@ package sqlite
 import (
 	"time"
 
+	"github.com/IceWhaleTech/CasaOS-Common/utils/logger"
 	"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
-	"github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
 	model2 "github.com/IceWhaleTech/CasaOS/service/model"
 	"go.uber.org/zap"
 	"gorm.io/driver/sqlite"
@@ -28,8 +28,8 @@ func GetDb(dbPath string) *gorm.DB {
 		return gdb
 	}
 	// Refer https://github.com/go-sql-driver/mysql#dsn-data-source-name
-	//dsn := fmt.Sprintf("%v:%v@tcp(%v:%v)/%v?charset=utf8mb4&parseTime=True&loc=Local", m.User, m.PWD, m.IP, m.Port, m.DBName)
-	//db, err := gorm.Open(mysql2.Open(dsn), &gorm.Config{})
+	// dsn := fmt.Sprintf("%v:%v@tcp(%v:%v)/%v?charset=utf8mb4&parseTime=True&loc=Local", m.User, m.PWD, m.IP, m.Port, m.DBName)
+	// db, err := gorm.Open(mysql2.Open(dsn), &gorm.Config{})
 	file.IsNotExistMkDir(dbPath)
 	db, err := gorm.Open(sqlite.Open(dbPath+"/casaOS.db"), &gorm.Config{})
 	c, _ := db.DB()
@@ -37,19 +37,18 @@ func GetDb(dbPath string) *gorm.DB {
 	c.SetMaxOpenConns(100)
 	c.SetConnMaxIdleTime(time.Second * 1000)
 	if err != nil {
-		loger.Error("sqlite connect error", zap.Any("db connect error", err))
+		logger.Error("sqlite connect error", zap.Any("db connect error", err))
 		panic("sqlite connect error")
-		return nil
 	}
 	gdb = db
 
-	err = db.AutoMigrate(&model2.AppNotify{}, &model2.AppListDBModel{}, model2.SharesDBModel{}, model2.ConnectionsDBModel{})
+	err = db.AutoMigrate(&model2.AppNotify{}, model2.SharesDBModel{}, model2.ConnectionsDBModel{})
 	db.Exec("DROP TABLE IF EXISTS o_application")
 	db.Exec("DROP TABLE IF EXISTS o_friend")
 	db.Exec("DROP TABLE IF EXISTS o_person_download")
 	db.Exec("DROP TABLE IF EXISTS o_person_down_record")
 	if err != nil {
-		loger.Error("check or create db error", zap.Any("error", err))
+		logger.Error("check or create db error", zap.Any("error", err))
 	}
 	return db
 }

+ 0 - 26
pkg/utils/env_helper/env.go

@@ -1,26 +0,0 @@
-package env_helper
-
-import "strings"
-
-func ReplaceDefaultENV(key, tz string) string {
-	temp := ""
-	switch key {
-	case "$DefaultPassword":
-		temp = "casaos"
-	case "$DefaultUserName":
-		temp = "admin"
-
-	case "$PUID":
-		temp = "1000"
-	case "$PGID":
-		temp = "1000"
-	case "$TZ":
-		temp = tz
-	}
-	return temp
-}
-
-//replace env default setting
-func ReplaceStringDefaultENV(str string) string {
-	return strings.ReplaceAll(strings.ReplaceAll(str, "$DefaultPassword", ReplaceDefaultENV("$DefaultPassword", "")), "$DefaultUserName", ReplaceDefaultENV("$DefaultUserName", ""))
-}

+ 23 - 27
pkg/utils/httper/httper.go

@@ -12,9 +12,9 @@ import (
 	"github.com/tidwall/gjson"
 )
 
-//发送GET请求
-//url:请求地址
-//response:请求返回的内容
+// 发送GET请求
+// url:请求地址
+// response:请求返回的内容
 func Get(url string, head map[string]string) (response string) {
 	client := &http.Client{Timeout: 30 * time.Second}
 	req, err := http.NewRequest("GET", url, nil)
@@ -28,10 +28,10 @@ func Get(url string, head map[string]string) (response string) {
 	resp, err := client.Do(req)
 	if err != nil {
 		fmt.Println(err)
-		//需要错误日志的处理
-		//loger.Error(error)
+		// 需要错误日志的处理
+		// logger.Error(error)
 		return ""
-		//panic(error)
+		// panic(error)
 	}
 	defer resp.Body.Close()
 	var buffer [512]byte
@@ -42,7 +42,7 @@ func Get(url string, head map[string]string) (response string) {
 		if err != nil && err == io.EOF {
 			break
 		} else if err != nil {
-			//loger.Error(err)
+			// logger.Error(err)
 			return ""
 			//	panic(err)
 		}
@@ -51,22 +51,21 @@ func Get(url string, head map[string]string) (response string) {
 	return
 }
 
-//发送GET请求
-//url:请求地址
-//response:请求返回的内容
+// 发送GET请求
+// url:请求地址
+// response:请求返回的内容
 func PersonGet(url string) (response string) {
 	client := &http.Client{Timeout: 5 * time.Second}
 	req, err := http.NewRequest("GET", url, nil)
-
 	if err != nil {
 		return ""
 	}
 	resp, err := client.Do(req)
 	if err != nil {
-		//需要错误日志的处理
-		//loger.Error(error)
+		// 需要错误日志的处理
+		// logger.Error(error)
 		return ""
-		//panic(error)
+		// panic(error)
 	}
 	defer resp.Body.Close()
 	var buffer [512]byte
@@ -77,7 +76,7 @@ func PersonGet(url string) (response string) {
 		if err != nil && err == io.EOF {
 			break
 		} else if err != nil {
-			//loger.Error(err)
+			// logger.Error(err)
 			return ""
 			//	panic(err)
 		}
@@ -86,11 +85,10 @@ func PersonGet(url string) (response string) {
 	return
 }
 
-//发送POST请求
-//url:请求地址,data:POST请求提交的数据,contentType:请求体格式,如:application/json
-//content:请求放回的内容
+// 发送POST请求
+// url:请求地址,data:POST请求提交的数据,contentType:请求体格式,如:application/json
+// content:请求放回的内容
 func Post(url string, data []byte, contentType string, head map[string]string) (content string) {
-
 	req, err := http.NewRequest("POST", url, bytes.NewBuffer(data))
 	req.Header.Add("content-type", contentType)
 	for k, v := range head {
@@ -113,9 +111,9 @@ func Post(url string, data []byte, contentType string, head map[string]string) (
 	return
 }
 
-//发送POST请求
-//url:请求地址,data:POST请求提交的数据,contentType:请求体格式,如:application/json
-//content:请求放回的内容
+// 发送POST请求
+// url:请求地址,data:POST请求提交的数据,contentType:请求体格式,如:application/json
+// content:请求放回的内容
 func ZeroTierGet(url string, head map[string]string) (content string, code int) {
 	req, err := http.NewRequest(http.MethodGet, url, nil)
 	for k, v := range head {
@@ -138,11 +136,10 @@ func ZeroTierGet(url string, head map[string]string) (content string, code int)
 	return
 }
 
-//发送GET请求
-//url:请求地址
-//response:请求返回的内容
+// 发送GET请求
+// url:请求地址
+// response:请求返回的内容
 func OasisGet(url string) (response string) {
-
 	head := make(map[string]string)
 
 	t := make(chan string)
@@ -155,5 +152,4 @@ func OasisGet(url string) (response string) {
 	head["Authorization"] = <-t
 
 	return Get(url, head)
-
 }

+ 0 - 92
pkg/utils/loger/log.go

@@ -1,92 +0,0 @@
-/*
- * @Author: LinkLeong link@icewhale.com
- * @Date: 2022-06-02 15:09:38
- * @LastEditors: LinkLeong
- * @LastEditTime: 2022-06-27 15:47:49
- * @FilePath: /CasaOS/pkg/utils/loger/log.go
- * @Description:
- * @Website: https://www.casaos.io
- * Copyright (c) 2022 by icewhale, All Rights Reserved.
- */
-package loger
-
-import (
-	"fmt"
-	"os"
-	"path"
-	"path/filepath"
-	"runtime"
-
-	"github.com/IceWhaleTech/CasaOS/pkg/config"
-	"go.uber.org/zap"
-	"go.uber.org/zap/zapcore"
-	"gopkg.in/natefinch/lumberjack.v2"
-)
-
-var loggers *zap.Logger
-
-func getFileLogWriter() (writeSyncer zapcore.WriteSyncer) {
-	// 使用 lumberjack 实现 log rotate
-	lumberJackLogger := &lumberjack.Logger{
-		Filename: filepath.Join(config.AppInfo.LogPath, fmt.Sprintf("%s.%s",
-			config.AppInfo.LogSaveName,
-			config.AppInfo.LogFileExt,
-		)),
-		MaxSize:    10,
-		MaxBackups: 60,
-		MaxAge:     1,
-		Compress:   true,
-	}
-
-	return zapcore.AddSync(lumberJackLogger)
-}
-
-func LogInit() {
-	encoderConfig := zap.NewProductionEncoderConfig()
-	encoderConfig.EncodeTime = zapcore.EpochTimeEncoder
-	encoder := zapcore.NewJSONEncoder(encoderConfig)
-	fileWriteSyncer := getFileLogWriter()
-	core := zapcore.NewTee(
-		zapcore.NewCore(encoder, zapcore.AddSync(os.Stdout), zapcore.InfoLevel),
-		zapcore.NewCore(encoder, fileWriteSyncer, zapcore.InfoLevel),
-	)
-	loggers = zap.New(core)
-
-}
-
-func Info(message string, fields ...zap.Field) {
-	callerFields := getCallerInfoForLog()
-	fields = append(fields, callerFields...)
-	loggers.Info(message, fields...)
-}
-
-func Debug(message string, fields ...zap.Field) {
-	callerFields := getCallerInfoForLog()
-	fields = append(fields, callerFields...)
-	loggers.Debug(message, fields...)
-}
-
-func Error(message string, fields ...zap.Field) {
-	callerFields := getCallerInfoForLog()
-	fields = append(fields, callerFields...)
-	loggers.Error(message, fields...)
-}
-
-func Warn(message string, fields ...zap.Field) {
-	callerFields := getCallerInfoForLog()
-	fields = append(fields, callerFields...)
-	loggers.Warn(message, fields...)
-}
-
-func getCallerInfoForLog() (callerFields []zap.Field) {
-
-	pc, file, line, ok := runtime.Caller(2) // 回溯两层,拿到写日志的调用方的函数信息
-	if !ok {
-		return
-	}
-	funcName := runtime.FuncForPC(pc).Name()
-	funcName = path.Base(funcName) //Base函数返回路径的最后一个元素,只保留函数名
-
-	callerFields = append(callerFields, zap.String("func", funcName), zap.String("file", file), zap.Int("line", line))
-	return
-}

+ 0 - 68
pkg/utils/port/port.go

@@ -1,68 +0,0 @@
-package port
-
-import (
-	"fmt"
-	"net"
-)
-
-// 获取可用端口
-func GetAvailablePort(t string) (int, error) {
-	address := fmt.Sprintf("%s:0", "0.0.0.0")
-	if t == "udp" {
-		add, err := net.ResolveUDPAddr(t, address)
-		if err != nil {
-			return 0, err
-		}
-
-		listener, err := net.ListenUDP(t, add)
-		if err != nil {
-			return 0, err
-		}
-
-		defer listener.Close()
-		return listener.LocalAddr().(*net.UDPAddr).Port, nil
-	} else {
-		add, err := net.ResolveTCPAddr(t, address)
-		if err != nil {
-			return 0, err
-		}
-
-		listener, err := net.ListenTCP(t, add)
-		if err != nil {
-			return 0, err
-		}
-
-		defer listener.Close()
-		return listener.Addr().(*net.TCPAddr).Port, nil
-	}
-
-}
-
-// 判断端口是否可以(未被占用)
-// param t tcp/udp
-func IsPortAvailable(port int, t string) bool {
-	address := fmt.Sprintf("%s:%d", "0.0.0.0", port)
-	if t == "udp" {
-		sadd, err := net.ResolveUDPAddr("udp", address)
-		uc, err := net.ListenUDP("udp", sadd)
-
-		if err != nil {
-			fmt.Println(err.Error())
-			return false
-		} else {
-			defer uc.Close()
-			return true
-		}
-
-	} else {
-		listener, err := net.Listen(t, address)
-
-		if err != nil {
-			//log.Infof("port %s is taken: %s", address, err)
-			return false
-		}
-		defer listener.Close()
-		return true
-	}
-
-}

+ 0 - 18
pkg/utils/port/port_test.go

@@ -1,18 +0,0 @@
-package port
-
-import (
-	"fmt"
-	"testing"
-)
-
-func TestPortAvailable(t *testing.T) {
-	//	fmt.Println(PortAvailable())
-	//fmt.Println(IsPortAvailable(6881,"tcp"))
-	p, _ := GetAvailablePort("udp")
-	fmt.Println("udp", p)
-	fmt.Println(IsPortAvailable(p, "udp"))
-
-	t1, _ := GetAvailablePort("tcp")
-	fmt.Println("tcp", t1)
-	fmt.Println(IsPortAvailable(t1, "tcp"))
-}

+ 0 - 24
pkg/utils/random/random.go

@@ -1,24 +0,0 @@
-package random
-
-import (
-	"math/rand"
-	"time"
-)
-
-func RandomString(n int, onlyLetter bool) string {
-
-	var letters []rune
-
-	if onlyLetter {
-		letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
-	} else {
-		letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
-	}
-
-	b := make([]rune, n)
-	rand.Seed(time.Now().UnixNano())
-	for i := range b {
-		b[i] = letters[rand.Intn(len(letters))]
-	}
-	return string(b)
-}

+ 0 - 10
pkg/utils/random/random_test.go

@@ -1,10 +0,0 @@
-package random
-
-import (
-	"fmt"
-	"testing"
-)
-
-func TestRandomString(t *testing.T) {
-	fmt.Println(RandomString(6, true))
-}

+ 5 - 5
route/init.go

@@ -17,12 +17,12 @@ import (
 	"strings"
 	"time"
 
+	"github.com/IceWhaleTech/CasaOS-Common/utils/logger"
 	"github.com/IceWhaleTech/CasaOS/model"
 	"github.com/IceWhaleTech/CasaOS/pkg/config"
 	"github.com/IceWhaleTech/CasaOS/pkg/samba"
 	"github.com/IceWhaleTech/CasaOS/pkg/utils/encryption"
 	"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
-	"github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
 	"github.com/IceWhaleTech/CasaOS/service"
 	"github.com/IceWhaleTech/CasaOS/types"
 	"go.uber.org/zap"
@@ -38,7 +38,7 @@ func InitInfo() {
 	if file.Exists(config.AppInfo.DBPath + "/baseinfo.conf") {
 		err := json.Unmarshal(file.ReadFullFile(config.AppInfo.DBPath+"/baseinfo.conf"), &mb)
 		if err != nil {
-			loger.Error("baseinfo.conf", zap.String("error", err.Error()))
+			logger.Error("baseinfo.conf", zap.String("error", err.Error()))
 		}
 	}
 	if file.Exists("/etc/CHANNEL") {
@@ -47,14 +47,14 @@ func InitInfo() {
 	}
 	mac, err := service.MyService.System().GetMacAddress()
 	if err != nil {
-		loger.Error("GetMacAddress", zap.String("error", err.Error()))
+		logger.Error("GetMacAddress", zap.String("error", err.Error()))
 	}
 	mb.Hash = encryption.GetMD5ByStr(mac)
 	mb.Version = types.CURRENTVERSION
 	os.Remove(config.AppInfo.DBPath + "/baseinfo.conf")
 	by, err := json.Marshal(mb)
 	if err != nil {
-		loger.Error("init info err", zap.Any("err", err))
+		logger.Error("init info err", zap.Any("err", err))
 		return
 	}
 	file.WriteToFullPath(by, config.AppInfo.DBPath+"/baseinfo.conf", 0o666)
@@ -68,7 +68,7 @@ func InitNetworkMount() {
 		directories, err := samba.GetSambaSharesList(connection.Host, connection.Port, connection.Username, connection.Password)
 		if err != nil {
 			service.MyService.Connections().DeleteConnection(fmt.Sprint(connection.ID))
-			loger.Error("mount samba err", zap.Any("err", err), zap.Any("info", connection))
+			logger.Error("mount samba err", zap.Any("err", err), zap.Any("info", connection))
 			continue
 		}
 		baseHostPath := "/mnt/" + connection.Host

+ 2 - 4
route/periodical.go

@@ -54,7 +54,6 @@ func SendMemBySocket() {
 }
 
 func SendAllHardwareStatusBySocket() {
-
 	netList := service.MyService.System().GetNetInfo()
 	newNet := []model.IOCountersStat{}
 	nets := service.MyService.System().GetNet(true)
@@ -91,7 +90,6 @@ func SendAllHardwareStatusBySocket() {
 	memInfo := service.MyService.System().GetMemInfo()
 
 	service.MyService.Notify().SendAllHardwareStatusBySocket(memInfo, cpuData, newNet)
-
 }
 
 // func MonitoryUSB() {
@@ -99,7 +97,7 @@ func SendAllHardwareStatusBySocket() {
 
 // 	conn := new(netlink.UEventConn)
 // 	if err := conn.Connect(netlink.UdevEvent); err != nil {
-// 		loger.Error("udev err", zap.Any("Unable to connect to Netlink Kobject UEvent socket", err))
+// 		logger.Error("udev err", zap.Any("Unable to connect to Netlink Kobject UEvent socket", err))
 // 	}
 // 	defer conn.Close()
 
@@ -124,7 +122,7 @@ func SendAllHardwareStatusBySocket() {
 // 				continue
 // 			}
 // 		case err := <-errors:
-// 			loger.Error("udev err", zap.Any("err", err))
+// 			logger.Error("udev err", zap.Any("err", err))
 // 		}
 // 	}
 

+ 2 - 63
route/route.go

@@ -58,68 +58,6 @@ func InitRouter() *gin.Engine {
 
 	v1Group.Use(jwt.ExceptLocalhost())
 	{
-		// v1UsersGroup := v1Group.Group("/users")
-		// v1UsersGroup.Use()
-		// {
-		// 	v1UsersGroup.GET("/current", v1.GetUserInfo)
-		// 	v1UsersGroup.PUT("/current", v1.PutUserInfo)
-		// 	v1UsersGroup.PUT("/current/password", v1.PutUserPassword)
-
-		// 	v1UsersGroup.GET("/current/custom/:key", v1.GetUserCustomConf)
-		// 	v1UsersGroup.POST("/current/custom/:key", v1.PostUserCustomConf)
-		// 	v1UsersGroup.DELETE("/current/custom/:key", v1.DeleteUserCustomConf)
-
-		// 	v1UsersGroup.POST("/current/image/:key", v1.PostUserUploadImage)
-		// 	v1UsersGroup.PUT("/current/image/:key", v1.PutUserImage)
-		// 	//v1UserGroup.POST("/file/image/:key", v1.PostUserFileImage)
-		// 	v1UsersGroup.DELETE("/current/image", v1.DeleteUserImage)
-
-		// 	//v1UserGroup.PUT("/avatar", v1.PutUserAvatar)
-		// 	//v1UserGroup.GET("/avatar", v1.GetUserAvatar)
-		// 	v1UsersGroup.DELETE("/:id", v1.DeleteUser)
-		// 	v1UsersGroup.GET("/:username", v1.GetUserInfoByUsername)
-		// 	v1UsersGroup.DELETE("", v1.DeleteUserAll)
-		// }
-
-		v1AppsGroup := v1Group.Group("/apps")
-		v1AppsGroup.Use()
-		{
-			v1AppsGroup.GET("", v1.AppList) // list
-			v1AppsGroup.GET("/:id", v1.AppInfo)
-		}
-		v1ContainerGroup := v1Group.Group("/container")
-		v1ContainerGroup.Use()
-		{
-
-			v1ContainerGroup.GET("", v1.MyAppList) ///my/list
-			v1ContainerGroup.GET("/usage", v1.AppUsageList)
-			v1ContainerGroup.GET("/:id", v1.ContainerUpdateInfo)    ///update/:id/info
-			v1ContainerGroup.GET("/:id/logs", v1.ContainerLog)      // /app/logs/:id
-			v1ContainerGroup.GET("/networks", v1.GetDockerNetworks) // app/install/config
-
-			v1ContainerGroup.GET("/:id/state", v1.GetContainerState) // app/state/:id ?state=install_progress
-			// there are problems, temporarily do not deal with
-			v1ContainerGroup.GET("/:id/terminal", v1.DockerTerminal) // app/terminal/:id
-			v1ContainerGroup.POST("", v1.InstallApp)                 // app/install
-			// v1ContainerGroup.GET("/:id", v1.ContainerInfo) // /app/info/:id
-
-			v1ContainerGroup.PUT("/:id", v1.UpdateSetting) ///update/:id/setting
-
-			v1ContainerGroup.PUT("/:id/state", v1.ChangAppState) // /app/state/:id
-			v1ContainerGroup.DELETE("/:id", v1.UnInstallApp)     // app/uninstall/:id
-			// Not used
-			v1ContainerGroup.PUT("/:id/latest", v1.PutAppUpdate)
-			// Not used
-			v1ContainerGroup.POST("/share", v1.ShareAppFile)
-			v1ContainerGroup.GET("/info", v1.GetDockerDaemonConfiguration)
-			v1ContainerGroup.PUT("/info", v1.PutDockerDaemonConfiguration)
-
-		}
-		v1AppCategoriesGroup := v1Group.Group("/app-categories")
-		v1AppCategoriesGroup.Use()
-		{
-			v1AppCategoriesGroup.GET("", v1.CategoryList)
-		}
 
 		v1SysGroup := v1Group.Group("/sys")
 		v1SysGroup.Use()
@@ -148,7 +86,6 @@ func InitRouter() *gin.Engine {
 
 			v1SysGroup.GET("/server-info", nil)
 			v1SysGroup.PUT("/server-info", nil)
-			v1SysGroup.GET("/apps-state", v1.GetSystemAppsStatus)
 			// v1SysGroup.GET("/port", v1.GetCasaOSPort)
 			// v1SysGroup.PUT("/port", v1.PutCasaOSPort)
 			v1SysGroup.GET("/proxy", v1.GetSystemProxy)
@@ -222,6 +159,8 @@ func InitRouter() *gin.Engine {
 			v1NotifyGroup.POST("/:path", v1.PostNotifyMessage)
 			// merge to system
 			v1NotifyGroup.POST("/system_status", v1.PostSystemStatusNotify)
+			v1NotifyGroup.POST("/install_app", v1.PostInstallAppNotify)
+			v1NotifyGroup.POST("/uninstall_app", v1.PostUninstallAppNotify)
 		}
 	}
 	return r

+ 3 - 5
route/socket.go

@@ -14,15 +14,14 @@ import (
 	"strconv"
 	"time"
 
+	"github.com/IceWhaleTech/CasaOS-Common/utils/port"
 	"github.com/IceWhaleTech/CasaOS/model/notify"
 	"github.com/IceWhaleTech/CasaOS/pkg/config"
-	"github.com/IceWhaleTech/CasaOS/pkg/utils/port"
 	"github.com/IceWhaleTech/CasaOS/service"
 	f "github.com/ambelovsky/gosf"
 )
 
 func SocketInit(msg chan notify.Message) {
-
 	// set socket port
 	socketPort := 0
 	if len(config.ServerInfo.SocketPort) == 0 {
@@ -51,10 +50,9 @@ func SocketInit(msg chan notify.Message) {
 			f.Broadcast("", v.Path, &v.Msg)
 			time.Sleep(time.Millisecond * 100)
 		}
-
 	}(msg)
 
 	f.Startup(map[string]interface{}{
-		"port": socketPort})
-
+		"port": socketPort,
+	})
 }

+ 0 - 355
route/v1/app.go

@@ -1,355 +0,0 @@
-package v1
-
-import (
-	"encoding/json"
-	"io/ioutil"
-	"net/http"
-	"path/filepath"
-	"strconv"
-
-	"github.com/IceWhaleTech/CasaOS/model"
-	"github.com/IceWhaleTech/CasaOS/pkg/utils/command"
-	"github.com/IceWhaleTech/CasaOS/pkg/utils/common_err"
-	"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
-
-	port2 "github.com/IceWhaleTech/CasaOS/pkg/utils/port"
-	"github.com/IceWhaleTech/CasaOS/service"
-	"github.com/gin-gonic/gin"
-)
-
-const (
-	dockerRootDirFilePath             = "/var/lib/casaos/docker_root"
-	dockerDaemonConfigurationFilePath = "/etc/docker/daemon.json"
-)
-
-// @Summary 获取远程列表
-// @Produce  application/json
-// @Accept application/json
-// @Tags app
-// @Param index query int false "页码"
-// @Param size query int false "每页数量"
-// @Param  category_id query int false "分类id"
-// @Param  type query string false "rank,new"
-// @Param  key query string false "search key"
-// @Security ApiKeyAuth
-// @Success 200 {string} string "ok"
-// @Router /app/list [get]
-func AppList(c *gin.Context) {
-	// service.MyService.Docker().DockerContainerCommit("test2")
-
-	index := c.DefaultQuery("index", "1")
-	size := c.DefaultQuery("size", "10000")
-	t := c.DefaultQuery("type", "rank")
-	categoryId := c.DefaultQuery("category_id", "0")
-	key := c.DefaultQuery("key", "")
-	if len(index) == 0 || len(size) == 0 || len(t) == 0 || len(categoryId) == 0 {
-		c.JSON(common_err.CLIENT_ERROR, &model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
-		return
-	}
-	collection, err := service.MyService.Casa().GetServerList(index, size, t, categoryId, key)
-	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
-	}
-	// for i := 0; i < len(recommend); i++ {
-	// 	ct, _ := service.MyService.Docker().DockerListByImage(recommend[i].Image, recommend[i].ImageVersion)
-	// 	if ct != nil {
-	// 		recommend[i].State = ct.State
-	// 	}
-	// }
-	// for i := 0; i < len(list); i++ {
-	// 	ct, _ := service.MyService.Docker().DockerListByImage(list[i].Image, list[i].ImageVersion)
-	// 	if ct != nil {
-	// 		list[i].State = ct.State
-	// 	}
-	// }
-	// for i := 0; i < len(community); i++ {
-	// 	ct, _ := service.MyService.Docker().DockerListByImage(community[i].Image, community[i].ImageVersion)
-	// 	if ct != nil {
-	// 		community[i].State = ct.State
-	// 	}
-	// }
-	data := make(map[string]interface{}, 3)
-	data["recommend"] = collection.Recommend
-	data["list"] = collection.List
-	data["community"] = collection.Community
-
-	c.JSON(common_err.SUCCESS, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
-}
-
-// @Summary 获取一个可用端口
-// @Produce  application/json
-// @Accept application/json
-// @Tags app
-// @Param  type query string true "端口类型 udp/tcp"
-// @Security ApiKeyAuth
-// @Success 200 {string} string "ok"
-// @Router /app/getport [get]
-func GetPort(c *gin.Context) {
-	t := c.DefaultQuery("type", "tcp")
-	var p int
-	ok := true
-	for ok {
-		p, _ = port2.GetAvailablePort(t)
-		ok = !port2.IsPortAvailable(p, t)
-	}
-	// @tiger 这里最好封装成 {'port': ...} 的形式,来体现出参的上下文
-	c.JSON(common_err.SUCCESS, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: p})
-}
-
-// @Summary 检查端口是否可用
-// @Produce  application/json
-// @Accept application/json
-// @Tags app
-// @Param  port path int true "端口号"
-// @Param  type query string true "端口类型 udp/tcp"
-// @Security ApiKeyAuth
-// @Success 200 {string} string "ok"
-// @Router /app/check/{port} [get]
-func PortCheck(c *gin.Context) {
-	p, _ := strconv.Atoi(c.Param("port"))
-	t := c.DefaultQuery("type", "tcp")
-	c.JSON(common_err.SUCCESS, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: port2.IsPortAvailable(p, t)})
-}
-
-// @Summary 我的应用列表
-// @Produce  application/json
-// @Accept application/json
-// @Tags app
-// @Security ApiKeyAuth
-// @Param  index query int false "index"
-// @Param  size query int false "size"
-// @Param  position query bool false "是否是首页应用"
-// @Success 200 {string} string "ok"
-// @Router /app/my/list [get]
-func MyAppList(c *gin.Context) {
-	index, _ := strconv.Atoi(c.DefaultQuery("index", "1"))
-	size, _ := strconv.Atoi(c.DefaultQuery("size", "0"))
-	position, _ := strconv.ParseBool(c.DefaultQuery("position", "true"))
-	list, unTranslation := service.MyService.App().GetMyList(index, size, position)
-	data := make(map[string]interface{}, 2)
-	data["casaos_apps"] = list
-	data["local_apps"] = unTranslation
-
-	c.JSON(common_err.SUCCESS, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
-}
-
-// @Summary my app hardware usage list
-// @Produce  application/json
-// @Accept application/json
-// @Tags app
-// @Security ApiKeyAuth
-// @Success 200 {string} string "ok"
-// @Router /app/usage [get]
-func AppUsageList(c *gin.Context) {
-	list := service.MyService.App().GetHardwareUsage()
-	c.JSON(common_err.SUCCESS, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: list})
-	// c.JSON(common_err.SUCCESS, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: nil})
-}
-
-// @Summary 应用详情
-// @Produce  application/json
-// @Accept application/json
-// @Tags app
-// @Param  id path int true "id"
-// @Security ApiKeyAuth
-// @Success 200 {string} string "ok"
-// @Router /app/appinfo/{id} [get]
-func AppInfo(c *gin.Context) {
-	id := c.Param("id")
-	language := c.GetHeader("Language")
-	info, err := service.MyService.Casa().GetServerAppInfo(id, "", language)
-	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 info.NetworkModel != "host" {
-		for i := 0; i < len(info.Ports); i++ {
-			if p, _ := strconv.Atoi(info.Ports[i].ContainerPort); port2.IsPortAvailable(p, info.Ports[i].Protocol) {
-				info.Ports[i].CommendPort = strconv.Itoa(p)
-			} else {
-				if info.Ports[i].Protocol == "tcp" {
-					if p, err := port2.GetAvailablePort("tcp"); err == nil {
-						info.Ports[i].CommendPort = strconv.Itoa(p)
-					}
-				} else if info.Ports[i].Protocol == "upd" {
-					if p, err := port2.GetAvailablePort("udp"); err == nil {
-						info.Ports[i].CommendPort = strconv.Itoa(p)
-					}
-				}
-			}
-
-			if info.Ports[i].Type == 0 {
-				info.PortMap = info.Ports[i].CommendPort
-			}
-		}
-	} else {
-		for i := 0; i < len(info.Ports); i++ {
-			if info.Ports[i].Type == 0 {
-				info.PortMap = info.Ports[i].ContainerPort
-				break
-			}
-		}
-	}
-
-	for i := 0; i < len(info.Devices); i++ {
-		if !file.CheckNotExist(info.Devices[i].ContainerPath) {
-			info.Devices[i].Path = info.Devices[i].ContainerPath
-		}
-	}
-	// if len(info.Tip) > 0 {
-	// 	info.Tip = env_helper.ReplaceStringDefaultENV(info.Tip)
-	// }
-
-	// portOrder := func(c1, c2 *model.Ports) bool {
-	// 	return c1.Type < c2.Type
-	// }
-
-	// envOrder := func(c1, c2 *model.Envs) bool {
-	// 	return c1.Type < c2.Type
-	// }
-
-	// volOrder := func(c1, c2 *model.Volume) bool {
-	// 	return c1.Type < c2.Type
-	// }
-
-	// devOrder := func(c1, c2 *model.Devices) bool {
-	// 	return c1.Type < c2.Type
-	// }
-
-	// sort
-	// if info.NetworkModel != "host" {
-	// 	sort.PortsSort(portOrder).Sort(info.Configures.TcpPorts)
-	// 	sort.PortsSort(portOrder).Sort(info.Configures.UdpPorts)
-	// }
-
-	// sort.EnvSort(envOrder).Sort(info.Envs)
-	// sort.VolSort(volOrder).Sort(info.Volumes.([]model.PathMap))
-	// sort.DevSort(devOrder).Sort(info.Devices)
-	info.Image += ":" + info.ImageVersion
-	info.MaxMemory = (service.MyService.System().GetMemInfo()["total"]).(uint64) >> 20
-
-	c.JSON(common_err.SUCCESS, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: info})
-}
-
-// @Summary 获取远程分类列表
-// @Produce  application/json
-// @Accept application/json
-// @Tags app
-// @Security ApiKeyAuth
-// @Success 200 {string} string "ok"
-// @Router /app/category [get]
-func CategoryList(c *gin.Context) {
-	list, err := service.MyService.Casa().GetServerCategoryList()
-	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
-	}
-	var count uint = 0
-	for _, category := range list {
-		count += category.Count
-	}
-
-	rear := append([]model.CategoryList{}, list[0:]...)
-	list = append(list[:0], model.CategoryList{Count: count, Name: "All", Font: "apps"})
-	list = append(list, rear...)
-	c.JSON(common_err.SUCCESS, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: list})
-}
-
-// @Summary 分享该应用配置
-// @Produce  application/json
-// @Accept application/json
-// @Tags app
-// @Security ApiKeyAuth
-// @Success 200 {string} string "ok"
-// @Router /app/share [post]
-func ShareAppFile(c *gin.Context) {
-	str, _ := ioutil.ReadAll(c.Request.Body)
-	content := service.MyService.Casa().ShareAppFile(str)
-	c.JSON(common_err.SUCCESS, json.RawMessage(content))
-}
-
-func GetDockerDaemonConfiguration(c *gin.Context) {
-	// info, err := service.MyService.Docker().GetDockerInfo()
-	// 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
-	// }
-	data := make(map[string]interface{})
-
-	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})
-			return
-		}
-	}
-	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) {
-	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 := 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
-	}
-
-	dockerConfig := model.DockerDaemonConfigurationModel{}
-	if file.Exists(dockerDaemonConfigurationFilePath) {
-		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})
-			return
-		}
-	}
-
-	dockerRootDir := value.(string)
-	if dockerRootDir == "/" {
-		dockerConfig.Root = "" // omitempty - empty string will not be serialized
-	} else {
-		if !file.Exists(dockerRootDir) {
-			c.JSON(http.StatusBadRequest, &model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.DIR_NOT_EXISTS), Data: common_err.GetMsg(common_err.DIR_NOT_EXISTS)})
-			return
-		}
-
-		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})
-			return
-		}
-	}
-
-	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
-		}
-	}
-
-	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: request})
-}

+ 0 - 1267
route/v1/docker.go

@@ -1,1267 +0,0 @@
-package v1
-
-import (
-	"bytes"
-	json2 "encoding/json"
-	"net/http"
-	"os/exec"
-	"path/filepath"
-	"strconv"
-	"strings"
-	"time"
-
-	"github.com/IceWhaleTech/CasaOS/model"
-	"github.com/IceWhaleTech/CasaOS/model/notify"
-	"github.com/IceWhaleTech/CasaOS/pkg/config"
-	"github.com/IceWhaleTech/CasaOS/pkg/docker"
-	"github.com/IceWhaleTech/CasaOS/pkg/utils/common_err"
-	"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
-	"github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
-	port2 "github.com/IceWhaleTech/CasaOS/pkg/utils/port"
-	"github.com/IceWhaleTech/CasaOS/pkg/utils/random"
-	"github.com/IceWhaleTech/CasaOS/service"
-	"github.com/IceWhaleTech/CasaOS/service/docker_base"
-	model2 "github.com/IceWhaleTech/CasaOS/service/model"
-	"github.com/IceWhaleTech/CasaOS/types"
-	"github.com/gin-gonic/gin"
-	"github.com/gorilla/websocket"
-	"github.com/jinzhu/copier"
-	uuid "github.com/satori/go.uuid"
-	"go.uber.org/zap"
-	"golang.org/x/crypto/ssh"
-)
-
-var upgrader = websocket.Upgrader{
-	ReadBufferSize:   1024,
-	WriteBufferSize:  1024,
-	CheckOrigin:      func(r *http.Request) bool { return true },
-	HandshakeTimeout: time.Duration(time.Second * 5),
-}
-
-// 打开docker的terminal
-func DockerTerminal(c *gin.Context) {
-	col := c.DefaultQuery("cols", "100")
-	row := c.DefaultQuery("rows", "30")
-	conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
-	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
-	}
-	defer conn.Close()
-	container := c.Param("id")
-	hr, err := service.Exec(container, row, col)
-	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
-	}
-	// 关闭I/O流
-	defer hr.Close()
-	// 退出进程
-	defer func() {
-		hr.Conn.Write([]byte("exit\r"))
-	}()
-	go func() {
-		docker.WsWriterCopy(hr.Conn, conn)
-	}()
-	docker.WsReaderCopy(conn, hr.Conn)
-}
-
-func PostSshLogin(c *gin.Context) {
-	j := make(map[string]string)
-	c.ShouldBind(&j)
-	userName := j["username"]
-	password := j["password"]
-	port := j["port"]
-	if userName == "" || password == "" || port == "" {
-		c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS), Data: "Username or password or port is empty"})
-		return
-	}
-	_, err := docker.NewSshClient(userName, password, port)
-	if err != nil {
-		c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.CLIENT_ERROR), Data: "Please check if the username and port are correct, and make sure that ssh server is installed."})
-		loger.Error("connect ssh error", zap.Any("error", err))
-		return
-	}
-	c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
-}
-
-func WsSsh(c *gin.Context) {
-	_, e := exec.LookPath("ssh")
-	if e != nil {
-		c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: "ssh server not found"})
-		return
-	}
-
-	userName := c.Query("username")
-	password := c.Query("password")
-	port := c.Query("port")
-	wsConn, _ := upgrader.Upgrade(c.Writer, c.Request, nil)
-	var logBuff = new(bytes.Buffer)
-
-	quitChan := make(chan bool, 3)
-	// user := ""
-	// password := ""
-	var login int = 1
-	cols, _ := strconv.Atoi(c.DefaultQuery("cols", "200"))
-	rows, _ := strconv.Atoi(c.DefaultQuery("rows", "32"))
-	var client *ssh.Client
-	for login != 0 {
-
-		var err error
-		if userName == "" || password == "" || port == "" {
-			wsConn.WriteMessage(websocket.TextMessage, []byte("username or password or port is empty"))
-		}
-		// wsConn.WriteMessage(websocket.TextMessage, []byte("login:"))
-		// user = docker.ReceiveWsMsgUser(wsConn, logBuff)
-		// wsConn.WriteMessage(websocket.TextMessage, []byte("\r\n\x1b[0m"))
-		// wsConn.WriteMessage(websocket.TextMessage, []byte("password:"))
-		// password = docker.ReceiveWsMsgPassword(wsConn, logBuff)
-		// wsConn.WriteMessage(websocket.TextMessage, []byte("\r\n\x1b[0m"))
-		client, err = docker.NewSshClient(userName, password, port)
-
-		if err != nil && client == nil {
-			wsConn.WriteMessage(websocket.TextMessage, []byte(err.Error()))
-			wsConn.WriteMessage(websocket.TextMessage, []byte("\r\n\x1b[0m"))
-		} else {
-			login = 0
-		}
-
-	}
-	if client != nil {
-		defer client.Close()
-	}
-
-	ssConn, _ := docker.NewSshConn(cols, rows, client)
-	defer ssConn.Close()
-
-	go ssConn.ReceiveWsMsg(wsConn, logBuff, quitChan)
-	go ssConn.SendComboOutput(wsConn, quitChan)
-	go ssConn.SessionWait(quitChan)
-
-	<-quitChan
-
-}
-
-// @Summary 安装app(该接口需要post json数据)
-// @Produce  application/json
-// @Accept application/json
-// @Tags app
-// @Param  id path int true "id"
-// @Param  port formData int true "主端口"
-// @Param  tcp formData string false "tcp端口"
-// @Param  udp formData string false "udp端口"
-// @Param  env formData string false "环境变量"
-// @Security ApiKeyAuth
-// @Success 200 {string} string "ok"
-// @Router /app/install [post]
-func InstallApp(c *gin.Context) {
-	var appInfo model.ServerAppList
-	m := model.CustomizationPostData{}
-	c.ShouldBind(&m)
-
-	const CUSTOM = "custom"
-	var dockerImage string
-	var dockerImageVersion string
-
-	//check app name is exist
-	if len(m.Protocol) == 0 {
-		m.Protocol = "http"
-	}
-	m.ContainerName = strings.Replace(m.Label, " ", "_", -1)
-	if m.Origin != CUSTOM {
-		oldName := m.ContainerName
-		oldLabel := m.Label
-		for i := 0; true; i++ {
-			if i != 0 {
-				m.ContainerName = oldName + "-" + strconv.Itoa(i)
-				m.Label = oldLabel + "-" + strconv.Itoa(i)
-			}
-			if _, err := service.MyService.Docker().DockerListByName(m.ContainerName); err != nil {
-				break
-			}
-		}
-	} else {
-		if _, err := service.MyService.Docker().DockerListByName(m.ContainerName); err == nil {
-			c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.ERROR_APP_NAME_EXIST, Message: common_err.GetMsg(common_err.ERROR_APP_NAME_EXIST)})
-			return
-		}
-
-	}
-
-	//check port
-	if len(m.PortMap) > 0 && m.PortMap != "0" {
-		//c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
-		portMap, _ := strconv.Atoi(m.PortMap)
-		if !port2.IsPortAvailable(portMap, "tcp") {
-			c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: "Duplicate port:" + m.PortMap})
-			return
-		}
-	}
-	//if len(m.Port) == 0 || m.Port == "0" {
-	//	m.Port = m.PortMap
-	//}
-
-	imageArr := strings.Split(m.Image, ":")
-	if len(imageArr) == 2 {
-		dockerImage = imageArr[0]
-		dockerImageVersion = imageArr[1]
-	} else {
-		dockerImage = m.Image
-		dockerImageVersion = "latest"
-	}
-	m.Image = dockerImage + ":" + dockerImageVersion
-	for _, u := range m.Ports {
-
-		if u.Protocol == "udp" {
-			t, _ := strconv.Atoi(u.CommendPort)
-			if !port2.IsPortAvailable(t, "udp") {
-				c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: "Duplicate port:" + u.CommendPort})
-				return
-			}
-		} else if u.Protocol == "tcp" {
-
-			te, _ := strconv.Atoi(u.CommendPort)
-			if !port2.IsPortAvailable(te, "tcp") {
-				c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: "Duplicate port:" + u.CommendPort})
-				return
-			}
-		} else if u.Protocol == "both" {
-			t, _ := strconv.Atoi(u.CommendPort)
-			if !port2.IsPortAvailable(t, "udp") {
-				c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: "Duplicate port:" + u.CommendPort})
-				return
-			}
-			te, _ := strconv.Atoi(u.CommendPort)
-			if !port2.IsPortAvailable(te, "tcp") {
-				c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: "Duplicate port:" + u.CommendPort})
-				return
-			}
-		}
-	}
-	if m.Origin == CUSTOM {
-		for _, device := range m.Devices {
-			if file.CheckNotExist(device.Path) {
-				c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.DEVICE_NOT_EXIST, Message: device.Path + "," + common_err.GetMsg(common_err.DEVICE_NOT_EXIST)})
-				return
-			}
-
-		}
-	} else {
-		dev := []model.PathMap{}
-		for _, device := range dev {
-			if !file.CheckNotExist(device.Path) {
-				dev = append(dev, device)
-			}
-		}
-		m.Devices = dev
-	}
-
-	//restart := c.PostForm("restart") //always 总是重启,   unless-stopped 除非用户手动停止容器,否则总是重新启动,    on-failure:仅当容器退出代码非零时重新启动
-	//if len(restart) > 0 {
-	//
-	//}
-	//
-	//privileged := c.PostForm("privileged") //是否处于特权模式
-	//if len(privileged) > 0 {
-	//
-	//}
-	id := uuid.NewV4().String()
-	m.CustomId = id
-	var relyMap = make(map[string]string)
-	go func() {
-		// installLog := model2.AppNotify{}
-		// installLog.State = 0
-		// installLog.CustomId = m.Label
-		// installLog.Message = "installing rely"
-		// installLog.Class = types.NOTIFY_APP
-		// installLog.Type = types.NOTIFY_TYPE_UNIMPORTANT
-		// installLog.CreatedAt = strconv.FormatInt(time.Now().Unix(), 10)
-		// installLog.UpdatedAt = strconv.FormatInt(time.Now().Unix(), 10)
-		// installLog.Id = uuid.NewV4().String()
-		// service.MyService.Notify().AddLog(installLog)
-		if m.Origin != CUSTOM {
-			for _, plugin := range appInfo.Plugins {
-				if plugin == "mysql" {
-					mid := uuid.NewV4().String()
-					mc := docker_base.MysqlConfig{}
-					mc.DataBasePassword = random.RandomString(6, false)
-					mc.DataBaseDB = appInfo.Title
-					mc.DataBaseUser = "root"
-					mc.DataBasePort = "3306"
-					mysqlContainerId, err := docker_base.MysqlCreate(mc, mid, m.CpuShares, m.Memory)
-					if len(mysqlContainerId) > 0 && err == nil {
-
-						mc.DataBaseHost = mid
-
-						m.Envs = docker_base.MysqlFilter(mc, m.Envs)
-
-						rely := model2.RelyDBModel{}
-						rely.Type = types.RELY_TYPE_MYSQL
-						rely.ContainerId = mysqlContainerId
-						rely.CustomId = mid
-						rely.ContainerCustomId = m.Label
-						var mysqlConfig model2.MysqlConfigs
-
-						//结构体转换
-						copier.Copy(&mysqlConfig, &mc)
-						rely.Config = mysqlConfig
-						service.MyService.Rely().Create(rely)
-
-						relyMap["mysql"] = mid
-
-					} else {
-						docker_base.MysqlDelete(mysqlContainerId)
-						// installLog.State = 0
-						// installLog.Message = err.Error()
-						// service.MyService.Notify().UpdateLog(installLog)
-					}
-				}
-			}
-		}
-
-		// step:下载镜像
-		err := service.MyService.Docker().DockerPullImage(dockerImage+":"+dockerImageVersion, m.Icon, m.Label)
-		if err != nil {
-			notify := notify.Application{}
-			notify.Icon = m.Icon
-			notify.Name = m.Label
-			notify.State = "PULLING"
-			notify.Type = "INSTALL"
-			notify.Success = false
-			notify.Finished = false
-			notify.Message = err.Error()
-			service.MyService.Notify().SendInstallAppBySocket(notify)
-			return
-		}
-
-		for !service.MyService.Docker().IsExistImage(m.Image) {
-			time.Sleep(time.Second)
-		}
-
-		_, err = service.MyService.Docker().DockerContainerCreate(m, "")
-		if err != nil {
-			//service.MyService.Redis().Set(id, "{\"id\"\""+id+"\",\"state\":false,\"message\":\""+err.Error()+"\",\"speed\":80}", 100)
-			notify := notify.Application{}
-			notify.Icon = m.Icon
-			notify.Name = m.Label
-			notify.State = "STARTING"
-			notify.Type = "INSTALL"
-			notify.Success = false
-			notify.Finished = false
-			notify.Message = err.Error()
-			service.MyService.Notify().SendInstallAppBySocket(notify)
-			return
-		} else {
-			notify := notify.Application{}
-			notify.Icon = m.Icon
-			notify.Name = m.Label
-			notify.State = "STARTING"
-			notify.Type = "INSTALL"
-			notify.Success = true
-			notify.Finished = false
-			service.MyService.Notify().SendInstallAppBySocket(notify)
-		}
-
-		//		echo -e "hellow\nworld" >>
-
-		//step:启动容器
-		err = service.MyService.Docker().DockerContainerStart(m.ContainerName)
-		if err != nil {
-			//service.MyService.Redis().Set(id, "{\"id\"\""+id+"\",\"state\":false,\"message\":\""+err.Error()+"\",\"speed\":90}", 100)
-			notify := notify.Application{}
-			notify.Icon = m.Icon
-			notify.Name = m.Label
-			notify.State = "STARTING"
-			notify.Type = "INSTALL"
-			notify.Success = false
-			notify.Finished = false
-			notify.Message = err.Error()
-			service.MyService.Notify().SendInstallAppBySocket(notify)
-			return
-		} else {
-			// if m.Origin != CUSTOM {
-			// 	installLog.Message = "setting upnp"
-			// } else {
-			// 	installLog.Message = "nearing completion"
-			// }
-			// service.MyService.Notify().UpdateLog(installLog)
-		}
-
-		//step: 启动成功     检查容器状态确认启动成功
-		container, err := service.MyService.Docker().DockerContainerInfo(m.ContainerName)
-		if err != nil && container.ContainerJSONBase.State.Running {
-			notify := notify.Application{}
-			notify.Icon = m.Icon
-			notify.Name = m.Label
-			notify.State = "INSTALLED"
-			notify.Type = "INSTALL"
-			notify.Success = false
-			notify.Finished = true
-			notify.Message = err.Error()
-			service.MyService.Notify().SendInstallAppBySocket(notify)
-			return
-		} else {
-			notify := notify.Application{}
-			notify.Icon = m.Icon
-			notify.Name = m.Label
-			notify.State = "INSTALLED"
-			notify.Type = "INSTALL"
-			notify.Success = true
-			notify.Finished = true
-			service.MyService.Notify().SendInstallAppBySocket(notify)
-		}
-
-		// if m.Origin != "custom" {
-		// 	for i := 0; i < len(m.Volumes); i++ {
-		// 		m.Volumes[i].Path = docker.GetDir(id, m.Volumes[i].Path)
-		// 	}
-		// }
-		//service.MyService.App().SaveContainer(md)
-		config.CasaOSGlobalVariables.AppChange = true
-
-	}()
-
-	c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: m.Label})
-
-}
-
-//// @Summary 自定义安装app(该接口需要post json数据)
-//// @Produce  application/json
-//// @Accept application/json
-//// @Tags app
-//// @Param  id path int true "id"
-//// @Param  port formData int true "主端口"
-//// @Param  tcp formData string false "tcp端口"
-//// @Param  udp formData string false "udp端口"
-//// @Param  env formData string false "环境变量"
-//// @Security ApiKeyAuth
-//// @Success 200 {string} string "ok"
-//// @Router /app/install/{id} [post]
-//func CustomInstallApp(c *gin.Context) {
-//	//appId := c.Param("id")
-//	//	appInfo := service.MyService.App().GetServerAppInfo(appId)
-//
-//	m := model.CustomizationPostData{}
-//	c.ShouldBind(&m)
-//	//检查端口
-//	if len(m.PortMap) == 0 || m.PortMap == "0" {
-//		c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
-//		return
-//	}
-//	if len(m.Port) == 0 || m.Port == "0" {
-//		m.Port = m.PortMap
-//	}
-//
-//	portMap, _ := strconv.Atoi(m.PortMap)
-//	if !port2.IsPortAvailable(portMap, "tcp") {
-//		c.JSON(http.StatusOK, model.Result{Success: common_err.ERROR, Message: "Duplicate port:" + m.PortMap})
-//		return
-//	}
-//
-//	for _, u := range m.Udp {
-//		t, _ := strconv.Atoi(u.CommendPort)
-//		if !port2.IsPortAvailable(t, "udp") {
-//			c.JSON(http.StatusOK, model.Result{Success: common_err.ERROR, Message: "Duplicate port:" + u.CommendPort})
-//			return
-//		}
-//	}
-//
-//	for _, t := range m.Tcp {
-//		te, _ := strconv.Atoi(t.CommendPort)
-//		if !port2.IsPortAvailable(te, "tcp") {
-//			c.JSON(http.StatusOK, model.Result{Success: common_err.ERROR, Message: "Duplicate port:" + t.CommendPort})
-//			return
-//		}
-//	}
-//
-//	//restart := c.PostForm("restart") //always 总是重启,   unless-stopped 除非用户手动停止容器,否则总是重新启动,    on-failure:仅当容器退出代码非零时重新启动
-//	//if len(restart) > 0 {
-//	//
-//	//}
-//	//
-//	//privileged := c.PostForm("privileged") //是否处于特权模式
-//	//if len(privileged) > 0 {
-//	//
-//	//}
-//
-//	err := service.MyService.Docker().DockerPullImage(m.Image)
-//	if err != nil {
-//		c.JSON(http.StatusOK, model.Result{Success: common_err.PULL_IMAGE_ERROR, Message: common_err.GetMsg(common_err.PULL_IMAGE_ERROR)})
-//	}
-//
-//	id := uuid.NewV4().String()
-//
-//	var relyMap = make(map[string]string)
-//	go func() {
-//		installLog := model2.AppNotify{}
-//		installLog.CustomId = id
-//		installLog.State = 0
-//		installLog.Message = "installing rely"
-//		installLog.Speed = 30
-//		installLog.CreatedAt = time.Now()
-//		installLog.UpdatedAt = time.Now()
-//		service.MyService.Notify().AddLog(installLog)
-//
-//		for !service.MyService.Docker().IsExistImage(m.Image) {
-//			time.Sleep(time.Second)
-//		}
-//
-//		installLog.Speed = 50
-//		installLog.Message = "pulling"
-//		service.MyService.Notify().UpdateLog(installLog)
-//		// step:下载镜像
-//
-//		var cpd model.PostData
-//		copier.Copy(&cpd, &m)
-//		//step:创建容器
-//		containerId, err := service.MyService.Docker().DockerContainerCreate(m.Image, id, cpd, m.NetworkModel, m.Image, "custom")
-//		installLog.ContainerId = containerId
-//		if err != nil {
-//			//service.MyService.Redis().Set(id, "{\"id\"\""+id+"\",\"state\":false,\"message\":\""+err.Error()+"\",\"speed\":80}", 100)
-//			installLog.State = 0
-//			installLog.Speed = 80
-//			installLog.Message = err.Error()
-//			service.MyService.Notify().UpdateLog(installLog)
-//			return
-//		} else {
-//			//service.MyService.Redis().Set(id, "{\"id\":\""+id+"\",\"state\":true,\"message\":\"starting\",\"speed\":80}", 100)
-//			installLog.Speed = 80
-//			installLog.Message = "starting"
-//			service.MyService.Notify().UpdateLog(installLog)
-//		}
-//
-//		//step:启动容器
-//		err = service.MyService.Docker().DockerContainerStart(id)
-//		if err != nil {
-//			//service.MyService.Redis().Set(id, "{\"id\"\""+id+"\",\"state\":false,\"message\":\""+err.Error()+"\",\"speed\":90}", 100)
-//			installLog.State = 0
-//			installLog.Speed = 90
-//			installLog.Message = err.Error()
-//			service.MyService.Notify().UpdateLog(installLog)
-//			return
-//		} else {
-//			//service.MyService.Redis().Set(id, "{\"id\":\""+id+"\",\"state\":true,\"message\":\"setting upnp\",\"speed\":90}", 100)
-//			installLog.Speed = 90
-//			installLog.Message = "setting upnp"
-//			service.MyService.Notify().UpdateLog(installLog)
-//		}
-//
-//		//step: 启动成功     检查容器状态确认启动成功
-//		containerStatus, err := service.MyService.Docker().DockerContainerInfo(id)
-//		if err != nil && containerStatus.ContainerJSONBase.State.Running {
-//			//service.MyService.Redis().Set(id, "{\"id\"\""+id+"\",\"state\":false,\"message\":\""+err.Error()+"\",\"speed\":100}", 100)
-//			installLog.State = 0
-//			installLog.Speed = 100
-//			installLog.Message = err.Error()
-//			service.MyService.Notify().UpdateLog(installLog)
-//			return
-//		} else {
-//			//service.MyService.Redis().Set(id, "{\"id\":\""+id+"\",\"state\":true,\"message\":\"installed\",\"speed\":100}", 100)
-//			installLog.Speed = 100
-//			installLog.Message = "installed"
-//			service.MyService.Notify().UpdateLog(installLog)
-//		}
-//
-//		rely := model.MapStrings{}
-//
-//		copier.Copy(&rely, &relyMap)
-//
-//		//step: 保存数据到数据库
-//		md := model2.AppListDBModel{
-//			CustomId: id,
-//			Title:    m.Label,
-//			//			ScreenshotLink: []string,
-//			Slogan:      "",
-//			Description: m.Description,
-//			//			Tags:           ,
-//			Icon:        m.Icon,
-//			Version:     m.Image,
-//			ContainerId: containerId,
-//			Image:       m.Image,
-//			Index:       "",
-//			Port:        m.Port,
-//			PortMap:     m.PortMap,
-//			Label:       m.Label,
-//			EnableUPNP:  m.EnableUPNP,
-//			UdpPorts:    m.Udp,
-//			TcpPorts:    m.Tcp,
-//			Envs:        m.Envs,
-//			Volumes:     m.Volumes,
-//			Position:    m.Position,
-//			NetModel:    m.NetworkModel,
-//			Restart:     m.Restart,
-//			CpuShares:   m.CpuShares,
-//			Memory:      m.Memory,
-//			Devices:     m.Devices,
-//			Rely:        rely,
-//			Origin:      "custom",
-//		}
-//		if m.NetworkModel == "host" {
-//			m.PortMap = m.Port
-//		}
-//		service.MyService.App().SaveContainer(md)
-//
-//	}()
-//
-//	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: id})
-//
-//}
-
-// @Summary 卸载app
-// @Produce  application/json
-// @Accept multipart/form-data
-// @Tags app
-// @Param  id path string true "容器id"
-// @Security ApiKeyAuth
-// @Success 200 {string} string "ok"
-// @Router /app/uninstall/{id} [delete]
-func UnInstallApp(c *gin.Context) {
-	appId := c.Param("id")
-
-	if len(appId) == 0 {
-		c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
-		return
-	}
-
-	j := make(map[string]string)
-	c.ShouldBind(&j)
-	isDelete := j["delete_config_folder"]
-
-	//info := service.MyService.App().GetUninstallInfo(appId)
-
-	info, err := service.MyService.Docker().DockerContainerInfo(appId)
-	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
-	}
-
-	//step:停止容器
-	err = service.MyService.Docker().DockerContainerStop(appId)
-	if err != nil {
-		c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.UNINSTALL_APP_ERROR, Message: common_err.GetMsg(common_err.UNINSTALL_APP_ERROR), Data: err.Error()})
-		return
-	}
-
-	err = service.MyService.Docker().DockerContainerRemove(appId, false)
-	if err != nil {
-		c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.UNINSTALL_APP_ERROR, Message: common_err.GetMsg(common_err.UNINSTALL_APP_ERROR), Data: err.Error()})
-		return
-	}
-
-	// step:remove image
-	service.MyService.Docker().DockerImageRemove(info.Config.Image)
-
-	if info.Config.Labels["origin"] != "custom" && len(isDelete) > 0 {
-		//step: 删除文件夹
-		for _, v := range info.Mounts {
-			if strings.Contains(v.Source, info.Name) {
-				path := filepath.Join(strings.Split(v.Source, info.Name)[0], info.Name)
-				service.MyService.App().DelAppConfigDir(path)
-			}
-		}
-
-		//step: 删除install log
-		//service.MyService.Notify().DelLog(appId)
-
-		//	for k, v := range info.Rely {
-		//
-		//		if k == "mysql" {
-		//			docker_base.MysqlDelete(v)
-		//			service.MyService.Rely().Delete(v)
-		//		}
-		//	}
-
-		//if info.EnableUPNP {
-		//	upnp, err := upnp2.Gateway()
-		//	if err == nil {
-		//		for _, p := range info.Ports {
-		//			if p.Protocol == "udp" {
-		//				upnp.CtrlUrl = upnp2.GetCtrlUrl(upnp.GatewayHost, upnp.DeviceDescUrl)
-		//				upnp.LocalHost = ip_helper2.GetLoclIp()
-		//				tComment, _ := strconv.Atoi(p.CommendPort)
-		//				upnp.DelPortMapping(tComment, "UDP")
-		//				time.Sleep(time.Millisecond * 200)
-		//			} else if p.Protocol == "tcp" {
-		//				upnp.CtrlUrl = upnp2.GetCtrlUrl(upnp.GatewayHost, upnp.DeviceDescUrl)
-		//				upnp.LocalHost = ip_helper2.GetLoclIp()
-		//				tComment, _ := strconv.Atoi(p.CommendPort)
-		//				upnp.DelPortMapping(tComment, "TCP")
-		//				time.Sleep(time.Millisecond * 200)
-		//			} else if p.Protocol == "both" {
-		//				upnp.CtrlUrl = upnp2.GetCtrlUrl(upnp.GatewayHost, upnp.DeviceDescUrl)
-		//				upnp.LocalHost = ip_helper2.GetLoclIp()
-		//				tComment, _ := strconv.Atoi(p.CommendPort)
-		//				upnp.DelPortMapping(tComment, "UDP")
-		//
-		//				upnp.DelPortMapping(tComment, "TCP")
-		//				time.Sleep(time.Millisecond * 200)
-		//			}
-		//		}
-		//	}
-		//}
-	}
-	config.CasaOSGlobalVariables.AppChange = true
-	notify := notify.Application{}
-	notify.Icon = info.Config.Labels["icon"]
-	notify.Name = strings.ReplaceAll(info.Name, "/", "")
-	notify.State = "FINISHED"
-	notify.Type = "UNINSTALL"
-	notify.Success = true
-	notify.Finished = true
-	service.MyService.Notify().SendUninstallAppBySocket(notify)
-	c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
-
-}
-
-// @Summary 修改app状态
-// @Produce  application/json
-// @Accept multipart/form-data
-// @Tags app
-// @Param  id path string true "appid"
-// @Param  state query string false "是否停止 start stop restart"
-// @Security ApiKeyAuth
-// @Success 200 {string} string "ok"
-// @Router /app/state/{id} [put]
-func ChangAppState(c *gin.Context) {
-	appId := c.Param("id")
-	js := make(map[string]string)
-	c.ShouldBind(&js)
-	state := js["state"]
-	if len(appId) == 0 || len(state) == 0 {
-		c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
-		return
-	}
-	var err error
-	if state == "start" {
-		err = service.MyService.Docker().DockerContainerStart(appId)
-	} else if state == "restart" {
-		service.MyService.Docker().DockerContainerStop(appId)
-		err = service.MyService.Docker().DockerContainerStart(appId)
-	} else {
-		err = service.MyService.Docker().DockerContainerStop(appId)
-	}
-
-	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
-	}
-	info, err := service.MyService.App().GetContainerInfo(appId)
-	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
-	}
-
-	// @tiger - 用 {'state': ...} 来体现出参上下文
-	c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: info.State})
-}
-
-// @Summary 查看容器日志
-// @Produce  application/json
-// @Accept application/json
-// @Tags app
-// @Param  id path string true "appid"
-// @Security ApiKeyAuth
-// @Success 200 {string} string "ok"
-// @Router /app/logs/{id} [get]
-func ContainerLog(c *gin.Context) {
-	appId := c.Param("id")
-	log, _ := service.MyService.Docker().DockerContainerLog(appId)
-	c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: string(log)})
-}
-
-// @Summary 获取容器状态
-// @Produce  application/json
-// @Accept application/json
-// @Tags app
-// @Param  id path string true "容器id"
-// @Param  type query string false "type=1"
-// @Security ApiKeyAuth
-// @Success 200 {string} string "ok"
-// @Router /app/state/{id} [get]
-func GetContainerState(c *gin.Context) {
-	id := c.Param("id")
-	//t := c.DefaultQuery("type", "0")
-	containerInfo, e := service.MyService.App().GetSimpleContainerInfo(id)
-	if e != nil {
-		c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: e.Error()})
-		return
-	}
-
-	var data = make(map[string]interface{})
-
-	data["state"] = containerInfo.State
-
-	// if t == "1" {
-	// 	appInfo := service.MyService.App().GetAppDBInfo(id)
-	// 	data["app"] = appInfo
-	// }
-
-	c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
-}
-
-// @Summary 更新设置
-// @Produce  application/json
-// @Accept multipart/form-data
-// @Tags app
-// @Param  id path string true "容器id"
-// @Param  shares formData string false "cpu权重"
-// @Param  mem formData string false "内存大小MB"
-// @Param  restart formData string false "重启策略"
-// @Param  label formData string false "应用名称"
-// @Param  position formData bool true "是否放到首页"
-// @Security ApiKeyAuth
-// @Success 200 {string} string "ok"
-// @Router /app/update/{id}/setting [put]
-func UpdateSetting(c *gin.Context) {
-	id := c.Param("id")
-	const CUSTOM = "custom"
-	m := model.CustomizationPostData{}
-	c.ShouldBind(&m)
-
-	if len(id) == 0 {
-		c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
-		return
-	}
-	//var cpd model.CustomizationPostData
-
-	//copier.Copy(&cpd, &m)
-
-	//appInfo := service.MyService.App().GetAppDBInfo(id)
-	//info, err := service.MyService.Docker().DockerContainerInfo(id)
-
-	// //check app name is exist
-	// if _, err := service.MyService.Docker().DockerListByName(m.Label); err == nil {
-	// 	c.JSON(http.StatusOK, model.Result{Success: common_err.ERROR_APP_NAME_EXIST, Message: common_err.GetMsg(common_err.ERROR_APP_NAME_EXIST)})
-	// 	return
-	// }
-	service.MyService.Docker().DockerContainerStop(id)
-	portMap, _ := strconv.Atoi(m.PortMap)
-	if !port2.IsPortAvailable(portMap, "tcp") {
-		service.MyService.Docker().DockerContainerStart(id)
-		c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: "Duplicate port:" + m.PortMap})
-		return
-	}
-
-	for _, u := range m.Ports {
-
-		if u.Protocol == "udp" {
-			t, _ := strconv.Atoi(u.CommendPort)
-			if !port2.IsPortAvailable(t, "udp") {
-				service.MyService.Docker().DockerContainerStart(id)
-				c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: "Duplicate port:" + u.CommendPort})
-				return
-			}
-		} else if u.Protocol == "tcp" {
-			te, _ := strconv.Atoi(u.CommendPort)
-			if !port2.IsPortAvailable(te, "tcp") {
-				service.MyService.Docker().DockerContainerStart(id)
-				c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: "Duplicate port:" + u.CommendPort})
-				return
-			}
-		} else if u.Protocol == "both" {
-			t, _ := strconv.Atoi(u.CommendPort)
-			if !port2.IsPortAvailable(t, "udp") {
-				service.MyService.Docker().DockerContainerStart(id)
-				c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: "Duplicate port:" + u.CommendPort})
-				return
-			}
-
-			te, _ := strconv.Atoi(u.CommendPort)
-			if !port2.IsPortAvailable(te, "tcp") {
-				service.MyService.Docker().DockerContainerStart(id)
-				c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: "Duplicate port:" + u.CommendPort})
-				return
-			}
-		}
-
-	}
-	service.MyService.Docker().DockerContainerUpdateName(id, id)
-	//service.MyService.Docker().DockerContainerRemove(id, true)
-
-	containerId, err := service.MyService.Docker().DockerContainerCreate(m, id)
-	if err != nil {
-		service.MyService.Docker().DockerContainerUpdateName(m.ContainerName, id)
-		service.MyService.Docker().DockerContainerStart(id)
-		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
-	}
-	//		echo -e "hellow\nworld" >>
-
-	//step:启动容器
-	err = service.MyService.Docker().DockerContainerStart(containerId)
-
-	if err != nil {
-		c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR)})
-		return
-	}
-	service.MyService.Docker().DockerContainerRemove(id, true)
-	//更新upnp
-	if m.Origin != CUSTOM {
-		//if appInfo.EnableUPNP != appInfo.EnableUPNP {
-		//	if appInfo.EnableUPNP {
-		//		upnp, err := upnp2.Gateway()
-		//		if err == nil {
-		//
-		//			for _, p := range appInfo.Ports {
-		//				if p.Protocol == "udp" {
-		//					upnp.CtrlUrl = upnp2.GetCtrlUrl(upnp.GatewayHost, upnp.DeviceDescUrl)
-		//					upnp.LocalHost = ip_helper2.GetLoclIp()
-		//					tComment, _ := strconv.Atoi(p.CommendPort)
-		//					upnp.AddPortMapping(tComment, tComment, "UDP")
-		//					time.Sleep(time.Millisecond * 200)
-		//				} else if p.Protocol == "tcp" {
-		//					upnp.CtrlUrl = upnp2.GetCtrlUrl(upnp.GatewayHost, upnp.DeviceDescUrl)
-		//					upnp.LocalHost = ip_helper2.GetLoclIp()
-		//					tComment, _ := strconv.Atoi(p.CommendPort)
-		//					upnp.AddPortMapping(tComment, tComment, "TCP")
-		//					time.Sleep(time.Millisecond * 200)
-		//				} else if p.Protocol == "both" {
-		//					upnp.CtrlUrl = upnp2.GetCtrlUrl(upnp.GatewayHost, upnp.DeviceDescUrl)
-		//					upnp.LocalHost = ip_helper2.GetLoclIp()
-		//					tComment, _ := strconv.Atoi(p.CommendPort)
-		//					upnp.AddPortMapping(tComment, tComment, "UDP")
-		//					time.Sleep(time.Millisecond * 200)
-		//
-		//					upnp.AddPortMapping(tComment, tComment, "TCP")
-		//					time.Sleep(time.Millisecond * 200)
-		//				}
-		//			}
-		//		}
-		//	} else {
-		//		upnp, err := upnp2.Gateway()
-		//		if err == nil {
-		//			for _, p := range appInfo.Ports {
-		//				if p.Protocol == "udp" {
-		//
-		//					upnp.CtrlUrl = upnp2.GetCtrlUrl(upnp.GatewayHost, upnp.DeviceDescUrl)
-		//					upnp.LocalHost = ip_helper2.GetLoclIp()
-		//					tComment, _ := strconv.Atoi(p.CommendPort)
-		//					upnp.DelPortMapping(tComment, "UDP")
-		//					time.Sleep(time.Millisecond * 200)
-		//				} else if p.Protocol == "tcp" {
-		//					upnp.CtrlUrl = upnp2.GetCtrlUrl(upnp.GatewayHost, upnp.DeviceDescUrl)
-		//					upnp.LocalHost = ip_helper2.GetLoclIp()
-		//					tComment, _ := strconv.Atoi(p.CommendPort)
-		//					upnp.DelPortMapping(tComment, "TCP")
-		//					time.Sleep(time.Millisecond * 200)
-		//				} else if p.Protocol == "both" {
-		//					upnp.CtrlUrl = upnp2.GetCtrlUrl(upnp.GatewayHost, upnp.DeviceDescUrl)
-		//					upnp.LocalHost = ip_helper2.GetLoclIp()
-		//					tComment, _ := strconv.Atoi(p.CommendPort)
-		//					upnp.DelPortMapping(tComment, "UDP")
-		//					time.Sleep(time.Millisecond * 200)
-		//
-		//					upnp.DelPortMapping(tComment, "TCP")
-		//					time.Sleep(time.Millisecond * 200)
-		//				}
-		//			}
-		//		}
-		//	}
-		//}
-	}
-
-	//service.MyService.App().UpdateApp(appInfo)
-
-	c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
-}
-
-// @Summary update app version
-// @Produce  application/json
-// @Accept multipart/form-data
-// @Tags app
-// @Param  id path string true "容器id"
-// @Security ApiKeyAuth
-// @Success 200 {string} string "ok"
-// @Router /app/update/{id} [put]
-func PutAppUpdate(c *gin.Context) {
-	id := c.Param("id")
-
-	if len(id) == 0 {
-		c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
-		return
-	}
-
-	inspect, err := service.MyService.Docker().DockerContainerInfo(id)
-	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
-
-	}
-	imageLatest := strings.Split(inspect.Config.Image, ":")[0] + ":latest"
-	err = service.MyService.Docker().DockerPullImage(imageLatest, "", "")
-	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
-
-	}
-	service.MyService.Docker().DockerContainerStop(id)
-	service.MyService.Docker().DockerContainerUpdateName(id, id)
-	//service.MyService.Docker().DockerContainerRemove(id, true)
-	inspect.Image = imageLatest
-	inspect.Config.Image = imageLatest
-	containerId, err := service.MyService.Docker().DockerContainerCopyCreate(inspect)
-	if err != nil {
-		service.MyService.Docker().DockerContainerUpdateName(inspect.Name, id)
-		service.MyService.Docker().DockerContainerStart(id)
-		c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR)})
-		return
-	}
-
-	//step:启动容器
-	err = service.MyService.Docker().DockerContainerStart(containerId)
-
-	if err != nil {
-		c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR)})
-		return
-	}
-	service.MyService.Docker().DockerContainerRemove(id, true)
-	delete(service.NewVersionApp, id)
-
-	c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
-}
-
-// @Summary 获取容器详情
-// @Produce  application/json
-// @Accept application/json
-// @Tags app
-// @Param  id path string true "appid"
-// @Security ApiKeyAuth
-// @Success 200 {string} string "ok"
-// @Router /app/info/{id} [get]
-func ContainerInfo(c *gin.Context) {
-	appId := c.Param("id")
-
-	// @tiger - 作为最佳实践,不应该直接把数据库的信息返回,来避免未来数据库结构上的迭代带来的新字段
-	appInfo := service.MyService.App().GetAppDBInfo(appId)
-	containerInfo, _ := service.MyService.Docker().DockerContainerStats(appId)
-	var cpuModel = "arm"
-	if cpu := service.MyService.System().GetCpuInfo(); len(cpu) > 0 {
-		if strings.Count(strings.ToLower(strings.TrimSpace(cpu[0].ModelName)), "intel") > 0 {
-			cpuModel = "intel"
-		} else if strings.Count(strings.ToLower(strings.TrimSpace(cpu[0].ModelName)), "amd") > 0 {
-			cpuModel = "amd"
-		}
-	}
-
-	info, err := service.MyService.Docker().DockerContainerInfo(appId)
-	if err != nil {
-		//todo 需要自定义错误
-		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
-	}
-	con := struct {
-		Status    string `json:"status"`
-		StartedAt string `json:"started_at"`
-		CPUShares int64  `json:"cpu_shares"`
-		Memory    int64  `json:"total_memory"`   // @tiger - 改成 total_memory,方便以后增加 free_memory 之类的字段
-		Restart   string `json:"restart_policy"` // @tiger - 改成 restart_policy?
-	}{Status: info.State.Status, StartedAt: info.State.StartedAt, CPUShares: info.HostConfig.CPUShares, Memory: info.HostConfig.Memory >> 20, Restart: info.HostConfig.RestartPolicy.Name}
-	data := make(map[string]interface{}, 5)
-	data["app"] = appInfo                                             // @tiget - 最佳实践是,返回 appid,然后具体的 app 信息由前端另行获取
-	data["cpu"] = cpuModel                                            // @tiger - 改成 arch
-	data["memory"] = service.MyService.System().GetMemInfo()["total"] // @tiger - 改成 total_memory,方便以后增加 free_memory 之类的字段
-	data["container"] = json2.RawMessage(containerInfo)
-	data["info"] = con
-	c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
-}
-
-func GetDockerNetworks(c *gin.Context) {
-	networks := service.MyService.Docker().DockerNetworkModelList()
-	list := []map[string]string{}
-	for _, network := range networks {
-		if network.Driver != "null" {
-			list = append(list, map[string]string{"name": network.Name, "driver": network.Driver, "id": network.ID})
-		}
-	}
-	c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: list})
-}
-
-// @Summary 获取依赖数据
-// @Produce  application/json
-// @Accept application/json
-// @Tags app
-// @Param  id path string true "rely id"
-// @Security ApiKeyAuth
-// @Success 200 {string} string "ok"
-// @Router /app/rely/{id}/info [get]
-func ContainerRelyInfo(c *gin.Context) {
-	id := c.Param("id")
-	appInfo := service.MyService.Rely().GetInfo(id)
-	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: appInfo})
-}
-
-// @Produce  application/json
-// @Accept application/json
-// @Tags app
-// @Param  id path string true "appid"
-// @Security ApiKeyAuth
-// @Success 200 {string} string "ok"
-// @Router /app/update/{id}/info [get]
-func ContainerUpdateInfo(c *gin.Context) {
-	appId := c.Param("id")
-	//appInfo := service.MyService.App().GetAppDBInfo(appId)
-	info, err := service.MyService.Docker().DockerContainerInfo(appId)
-	if err != nil {
-
-		c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: err.Error()})
-		return
-	}
-	var port model.PortArray
-	// json2.Unmarshal([]byte(appInfo.Ports), &port)
-
-	for k, v := range info.HostConfig.PortBindings {
-		temp := model.PortMap{
-			CommendPort:   v[0].HostPort,
-			ContainerPort: k.Port(),
-
-			Protocol: k.Proto(),
-		}
-		port = append(port, temp)
-	}
-
-	var envs model.EnvArray
-	// json2.Unmarshal([]byte(appInfo.Envs), &envs)
-
-	showENV := info.Config.Labels["show_env"]
-	showENVList := strings.Split(showENV, ",")
-	showENVMap := make(map[string]string)
-	if len(showENVList) > 0 && showENVList[0] != "" {
-		for _, name := range showENVList {
-			showENVMap[name] = "1"
-		}
-	}
-	for _, v := range info.Config.Env {
-		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],
-					Value: strings.Split(v, "=")[1],
-				}
-				envs = append(envs, temp)
-			}
-		} else {
-			temp := model.Env{
-				Name:  strings.Split(v, "=")[0],
-				Value: strings.Split(v, "=")[1],
-			}
-			envs = append(envs, temp)
-		}
-
-	}
-
-	var vol model.PathArray
-	// json2.Unmarshal([]byte(appInfo.Volumes), &vol)
-
-	for i := 0; i < len(info.Mounts); i++ {
-		temp := model.PathMap{
-			Path:          strings.ReplaceAll(info.Mounts[i].Source, "$AppID", info.Name),
-			ContainerPath: info.Mounts[i].Destination,
-		}
-		vol = append(vol, temp)
-	}
-	var driver model.PathArray
-
-	//volumesStr, _ := json2.Marshal(m.Volumes)
-	//devicesStr, _ := json2.Marshal(m.Devices)
-	for _, v := range info.HostConfig.Resources.Devices {
-		temp := model.PathMap{
-			Path:          v.PathOnHost,
-			ContainerPath: v.PathInContainer,
-		}
-		driver = append(driver, temp)
-	}
-
-	m := model.CustomizationPostData{}
-	m.Icon = info.Config.Labels["icon"]
-	m.Ports = port
-	m.Image = info.Config.Image
-	m.Origin = info.Config.Labels["origin"]
-	if len(m.Origin) == 0 {
-		m.Origin = "local"
-	}
-	m.NetworkModel = string(info.HostConfig.NetworkMode)
-	m.Description = info.Config.Labels["desc"]
-	m.ContainerName = strings.ReplaceAll(info.Name, "/", "")
-	m.PortMap = info.Config.Labels["web"]
-	m.Devices = driver
-	m.Envs = envs
-	m.Memory = info.HostConfig.Memory >> 20
-	m.CpuShares = info.HostConfig.CPUShares
-	m.Volumes = vol //appInfo.Volumes
-	m.Restart = info.HostConfig.RestartPolicy.Name
-	m.EnableUPNP = false
-	m.Index = info.Config.Labels["index"]
-	m.Position = false
-	m.CustomId = info.Config.Labels["custom_id"]
-	m.Host = info.Config.Labels["host"]
-	if len(m.CustomId) == 0 {
-		m.CustomId = uuid.NewV4().String()
-	}
-	m.CapAdd = info.HostConfig.CapAdd
-	m.Cmd = info.Config.Cmd
-	m.HostName = info.Config.Hostname
-	m.Privileged = info.HostConfig.Privileged
-	name := info.Config.Labels["name"]
-	if len(name) == 0 {
-		name = strings.ReplaceAll(info.Name, "/", "")
-	}
-	m.Label = name
-
-	m.Protocol = info.Config.Labels["protocol"]
-	if m.Protocol == "" {
-		m.Protocol = "http"
-	}
-
-	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: m})
-}
-
-////准备安装(暂时不需要)
-//func ReadyInstall(c *gin.Context) {
-//	_, tcp, udp := service.MyService.GetManifestJsonByRepo()
-//	data := make(map[string]interface{}, 2)
-//	if t := gjson.Parse(tcp).Array(); len(t) > 0 {
-//		//tcpList := []model.TcpPorts{}
-//		//e := json2.Unmarshal([]byte(tcp), tcpList)
-//		//if e!=nil {
-//		//	return
-//		//}
-//		//for _, port := range tcpList {
-//		//	if port.ContainerPort>0&&port.ExtranetPort {
-//		//
-//		//	}
-//		//}
-//		var inarr []interface{}
-//		for _, result := range t {
-//
-//			var p int
-//			ok := true
-//			for ok {
-//				p, _ = port.GetAvailablePort()
-//				ok = !port.IsPortAvailable(p)
-//			}
-//			pm := model.PortMap{gjson.Get(result.Raw, "container_port").Int(), p}
-//			inarr = append(inarr, pm)
-//		}
-//		data["tcp"] = inarr
-//	}
-//	if u := gjson.Parse(udp).Array(); len(u) > 0 {
-//		//udpList := []model.UdpPorts{}
-//		//e := json2.Unmarshal([]byte(udp), udpList)
-//		//if e != nil {
-//		//	return
-//		//}
-//		var inarr []model.PortMap
-//		for _, result := range u {
-//			var p int
-//			ok := true
-//			for ok {
-//				p, _ = port.GetAvailablePort()
-//				ok = !port.IsPortAvailable(p)
-//			}
-//			pm := model.PortMap{gjson.Get(result.Raw, "container_port").Int(), p}
-//			inarr = append(inarr, pm)
-//		}
-//		data["udp"] = inarr
-//	}
-//	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
-//}

+ 12 - 25
route/v1/file.go

@@ -15,10 +15,10 @@ import (
 	"strings"
 	"sync"
 
+	"github.com/IceWhaleTech/CasaOS-Common/utils/logger"
 	"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"
@@ -222,19 +222,6 @@ func DirPath(c *gin.Context) {
 	for _, v := range shares {
 		sharesMap[v.Path] = fmt.Sprint(v.ID)
 	}
-	if path == "/DATA/AppData" {
-		list := service.MyService.Docker().DockerContainerList()
-		apps := make(map[string]string, len(list))
-		for _, v := range list {
-			apps[strings.ReplaceAll(v.Names[0], "/", "")] = strings.ReplaceAll(v.Names[0], "/", "")
-		}
-		for i := 0; i < len(info); i++ {
-			if v, ok := apps[info[i].Name]; ok {
-				info[i].Label = v
-				info[i].Type = "application"
-			}
-		}
-	}
 
 	for i := 0; i < len(info); i++ {
 		if v, ok := sharesMap[info[i].Path]; ok {
@@ -403,7 +390,7 @@ func PostFileUpload(c *gin.Context) {
 	hash := file.GetHashByContent([]byte(fileName))
 
 	if len(path) == 0 {
-		loger.Error("path should not be empty")
+		logger.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
 	}
@@ -413,7 +400,7 @@ func PostFileUpload(c *gin.Context) {
 		dirPath = strings.TrimSuffix(relative, fileName)
 		tempDir += dirPath
 		if err := file.MkDir(path + "/" + dirPath); err != nil {
-			loger.Error("error when trying to create `"+path+"/"+dirPath+"`", zap.Error(err))
+			logger.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
 		}
@@ -423,7 +410,7 @@ func PostFileUpload(c *gin.Context) {
 
 	if !file.CheckNotExist(tempDir + chunkNumber) {
 		if err := file.RMDir(tempDir + chunkNumber); err != nil {
-			loger.Error("error when trying to remove existing `"+tempDir+chunkNumber+"`", zap.Error(err))
+			logger.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
 		}
@@ -431,14 +418,14 @@ func PostFileUpload(c *gin.Context) {
 
 	if totalChunks > 1 {
 		if err := file.IsNotExistMkDir(tempDir); err != nil {
-			loger.Error("error when trying to create `"+tempDir+"`", zap.Error(err))
+			logger.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))
+			logger.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
 		}
@@ -446,27 +433,27 @@ func PostFileUpload(c *gin.Context) {
 		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))
+			logger.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))
+			logger.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))
+				logger.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))
+				logger.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
 			}
@@ -474,7 +461,7 @@ func PostFileUpload(c *gin.Context) {
 	} else {
 		out, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE, 0o644)
 		if err != nil {
-			loger.Error("error when trying to open `"+path+"` for creation", zap.Error(err))
+			logger.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
 		}
@@ -482,7 +469,7 @@ func PostFileUpload(c *gin.Context) {
 		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))
+			logger.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
 		}

+ 56 - 0
route/v1/notify.go

@@ -0,0 +1,56 @@
+package v1
+
+import (
+	"net/http"
+
+	"github.com/IceWhaleTech/CasaOS-Common/model/notify"
+	"github.com/IceWhaleTech/CasaOS/model"
+	"github.com/IceWhaleTech/CasaOS/pkg/utils/common_err"
+	"github.com/IceWhaleTech/CasaOS/service"
+	"github.com/gin-gonic/gin"
+)
+
+func PostNotifyMessage(c *gin.Context) {
+	path := c.Param("path")
+	message := make(map[string]interface{})
+	if err := c.ShouldBind(&message); err != nil {
+		c.JSON(http.StatusBadRequest, model.Result{Success: common_err.INVALID_PARAMS, Message: err.Error()})
+		return
+	}
+
+	service.MyService.Notify().SendNotify(path, message)
+	c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
+}
+
+func PostSystemStatusNotify(c *gin.Context) {
+	message := make(map[string]interface{})
+	if err := c.ShouldBind(&message); err != nil {
+		c.JSON(http.StatusBadRequest, model.Result{Success: common_err.INVALID_PARAMS, Message: err.Error()})
+		return
+	}
+
+	service.MyService.Notify().SettingSystemTempData(message)
+	c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
+}
+
+func PostInstallAppNotify(c *gin.Context) {
+	app := notify.Application{}
+	if err := c.ShouldBind(&app); err != nil {
+		c.JSON(http.StatusBadRequest, model.Result{Success: common_err.INVALID_PARAMS, Message: err.Error()})
+		return
+	}
+
+	service.MyService.Notify().SendInstallAppBySocket(app)
+	c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
+}
+
+func PostUninstallAppNotify(c *gin.Context) {
+	app := notify.Application{}
+	if err := c.ShouldBind(&app); err != nil {
+		c.JSON(http.StatusBadRequest, model.Result{Success: common_err.INVALID_PARAMS, Message: err.Error()})
+		return
+	}
+
+	service.MyService.Notify().SendUninstallAppBySocket(app)
+	c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
+}

+ 0 - 23
route/v1/notiry.go

@@ -1,23 +0,0 @@
-package v1
-
-import (
-	"github.com/IceWhaleTech/CasaOS/model"
-	"github.com/IceWhaleTech/CasaOS/pkg/utils/common_err"
-	"github.com/IceWhaleTech/CasaOS/service"
-	"github.com/gin-gonic/gin"
-)
-
-func PostNotifyMessage(c *gin.Context) {
-	path := c.Param("path")
-	message := make(map[string]interface{})
-	c.ShouldBind(&message)
-	service.MyService.Notify().SendNotify(path, message)
-	c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
-}
-
-func PostSystemStatusNotify(c *gin.Context) {
-	message := make(map[string]interface{})
-	c.ShouldBind(&message)
-	service.MyService.Notify().SettingSystemTempData(message)
-	c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
-}

+ 96 - 0
route/v1/ssh.go

@@ -0,0 +1,96 @@
+package v1
+
+import (
+	"bytes"
+	"net/http"
+	"os/exec"
+	"strconv"
+	"time"
+
+	"github.com/IceWhaleTech/CasaOS-Common/utils/common_err"
+	"github.com/IceWhaleTech/CasaOS-Common/utils/logger"
+	sshHelper "github.com/IceWhaleTech/CasaOS-Common/utils/ssh"
+
+	"github.com/gin-gonic/gin"
+	"github.com/gorilla/websocket"
+	"go.uber.org/zap"
+	"golang.org/x/crypto/ssh"
+
+	modelCommon "github.com/IceWhaleTech/CasaOS-Common/model"
+)
+
+var upgrader = websocket.Upgrader{
+	ReadBufferSize:   1024,
+	WriteBufferSize:  1024,
+	CheckOrigin:      func(r *http.Request) bool { return true },
+	HandshakeTimeout: time.Duration(time.Second * 5),
+}
+
+func PostSshLogin(c *gin.Context) {
+	j := make(map[string]string)
+	c.ShouldBind(&j)
+	userName := j["username"]
+	password := j["password"]
+	port := j["port"]
+	if userName == "" || password == "" || port == "" {
+		c.JSON(common_err.CLIENT_ERROR, modelCommon.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS), Data: "Username or password or port is empty"})
+		return
+	}
+	_, err := sshHelper.NewSshClient(userName, password, port)
+	if err != nil {
+		c.JSON(common_err.CLIENT_ERROR, modelCommon.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.CLIENT_ERROR), Data: "Please check if the username and port are correct, and make sure that ssh server is installed."})
+		logger.Error("connect ssh error", zap.Any("error", err))
+		return
+	}
+	c.JSON(common_err.SUCCESS, modelCommon.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
+}
+
+func WsSsh(c *gin.Context) {
+	_, e := exec.LookPath("ssh")
+	if e != nil {
+		c.JSON(common_err.SERVICE_ERROR, modelCommon.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: "ssh server not found"})
+		return
+	}
+
+	userName := c.Query("username")
+	password := c.Query("password")
+	port := c.Query("port")
+	wsConn, _ := upgrader.Upgrade(c.Writer, c.Request, nil)
+	logBuff := new(bytes.Buffer)
+
+	quitChan := make(chan bool, 3)
+	// user := ""
+	// password := ""
+	var login int = 1
+	cols, _ := strconv.Atoi(c.DefaultQuery("cols", "200"))
+	rows, _ := strconv.Atoi(c.DefaultQuery("rows", "32"))
+	var client *ssh.Client
+	for login != 0 {
+
+		var err error
+		if userName == "" || password == "" || port == "" {
+			wsConn.WriteMessage(websocket.TextMessage, []byte("username or password or port is empty"))
+		}
+		client, err = sshHelper.NewSshClient(userName, password, port)
+
+		if err != nil && client == nil {
+			wsConn.WriteMessage(websocket.TextMessage, []byte(err.Error()))
+			wsConn.WriteMessage(websocket.TextMessage, []byte("\r\n\x1b[0m"))
+		} else {
+			login = 0
+		}
+
+	}
+	if client != nil {
+		defer client.Close()
+	}
+
+	ssConn, _ := sshHelper.NewSshConn(cols, rows, client)
+	defer ssConn.Close()
+
+	go ssConn.ReceiveWsMsg(wsConn, logBuff, quitChan)
+	go ssConn.SendComboOutput(wsConn, quitChan)
+	go ssConn.SessionWait(quitChan)
+
+	<-quitChan
+}

+ 40 - 41
route/v1/system.go

@@ -13,10 +13,10 @@ import (
 	"unsafe"
 
 	http2 "github.com/IceWhaleTech/CasaOS-Common/utils/http"
+	"github.com/IceWhaleTech/CasaOS-Common/utils/port"
 	"github.com/IceWhaleTech/CasaOS/model"
 	"github.com/IceWhaleTech/CasaOS/pkg/config"
 	"github.com/IceWhaleTech/CasaOS/pkg/utils/common_err"
-	port2 "github.com/IceWhaleTech/CasaOS/pkg/utils/port"
 	"github.com/IceWhaleTech/CasaOS/pkg/utils/version"
 	"github.com/IceWhaleTech/CasaOS/service"
 	model2 "github.com/IceWhaleTech/CasaOS/service/model"
@@ -127,7 +127,7 @@ func PutCasaOSPort(c *gin.Context) {
 	json := make(map[string]string)
 	c.ShouldBind(&json)
 	portStr := json["port"]
-	port, err := strconv.Atoi(portStr)
+	portNumber, err := strconv.Atoi(portStr)
 	if err != nil {
 		c.JSON(common_err.SERVICE_ERROR,
 			model.Result{
@@ -137,7 +137,7 @@ func PutCasaOSPort(c *gin.Context) {
 		return
 	}
 
-	isAvailable := port2.IsPortAvailable(port, "tcp")
+	isAvailable := port.IsPortAvailable(portNumber, "tcp")
 	if !isAvailable {
 		c.JSON(common_err.SERVICE_ERROR,
 			model.Result{
@@ -146,7 +146,7 @@ func PutCasaOSPort(c *gin.Context) {
 			})
 		return
 	}
-	service.MyService.System().UpSystemPort(strconv.Itoa(port))
+	service.MyService.System().UpSystemPort(strconv.Itoa(portNumber))
 	c.JSON(common_err.SUCCESS,
 		model.Result{
 			Success: common_err.SUCCESS,
@@ -165,40 +165,6 @@ func PostKillCasaOS(c *gin.Context) {
 	os.Exit(0)
 }
 
-func GetSystemAppsStatus(c *gin.Context) {
-	systemAppList := service.MyService.App().GetSystemAppList()
-	appList := []model2.MyAppList{}
-	for _, v := range systemAppList {
-		name := strings.ReplaceAll(v.Names[0], "/", "")
-		if len(v.Labels["name"]) > 0 {
-			name = v.Labels["name"]
-		}
-		appList = append(appList, model2.MyAppList{
-			Name:     name,
-			Icon:     v.Labels["icon"],
-			State:    v.State,
-			CustomId: v.Labels["custom_id"],
-			Id:       v.ID,
-			Port:     v.Labels["web"],
-			Index:    v.Labels["index"],
-			// Order:      m.Labels["order"],
-			Image:  v.Image,
-			Latest: false,
-			// Type:   m.Labels["origin"],
-			// Slogan: m.Slogan,
-			// Rely:     m.Rely,
-			Host:     v.Labels["host"],
-			Protocol: v.Labels["protocol"],
-		})
-	}
-	c.JSON(common_err.SUCCESS,
-		model.Result{
-			Success: common_err.SUCCESS,
-			Message: common_err.GetMsg(common_err.SUCCESS),
-			Data:    appList,
-		})
-}
-
 // @Summary get system hardware info
 // @Produce  application/json
 // @Accept application/json
@@ -228,7 +194,7 @@ func GetSystemUtilization(c *gin.Context) {
 	data := make(map[string]interface{})
 	cpu := service.MyService.System().GetCpuPercent()
 	num := service.MyService.System().GetCpuCoreNum()
-	var cpuModel = "arm"
+	cpuModel := "arm"
 	if cpu := service.MyService.System().GetCpuInfo(); len(cpu) > 0 {
 		if strings.Count(strings.ToLower(strings.TrimSpace(cpu[0].ModelName)), "intel") > 0 {
 			cpuModel = "intel"
@@ -375,13 +341,46 @@ func PutSystemState(c *gin.Context) {
 			time.Sleep(30 * time.Second)
 			service.MyService.System().SystemShutdown()
 		}()
-
 	} else if state == "restart" {
 		go func() {
 			time.Sleep(30 * time.Second)
 			service.MyService.System().SystemReboot()
 		}()
-
 	}
 	c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: "The operation will be executed after 30 seconds"})
 }
+
+// @Summary 获取一个可用端口
+// @Produce  application/json
+// @Accept application/json
+// @Tags app
+// @Param  type query string true "端口类型 udp/tcp"
+// @Security ApiKeyAuth
+// @Success 200 {string} string "ok"
+// @Router /app/getport [get]
+func GetPort(c *gin.Context) {
+	t := c.DefaultQuery("type", "tcp")
+	var p int
+	ok := true
+	for ok {
+		p, _ = port.GetAvailablePort(t)
+		ok = !port.IsPortAvailable(p, t)
+	}
+	// @tiger 这里最好封装成 {'port': ...} 的形式,来体现出参的上下文
+	c.JSON(common_err.SUCCESS, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: p})
+}
+
+// @Summary 检查端口是否可用
+// @Produce  application/json
+// @Accept application/json
+// @Tags app
+// @Param  port path int true "端口号"
+// @Param  type query string true "端口类型 udp/tcp"
+// @Security ApiKeyAuth
+// @Success 200 {string} string "ok"
+// @Router /app/check/{port} [get]
+func PortCheck(c *gin.Context) {
+	p, _ := strconv.Atoi(c.Param("port"))
+	t := c.DefaultQuery("type", "tcp")
+	c.JSON(common_err.SUCCESS, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: port.IsPortAvailable(p, t)})
+}

+ 0 - 480
service/app.go

@@ -1,480 +0,0 @@
-package service
-
-import (
-	"context"
-	"encoding/json"
-	"fmt"
-	"io"
-	"io/ioutil"
-	"runtime"
-	"strings"
-	"sync"
-	"time"
-
-	"github.com/IceWhaleTech/CasaOS/model"
-	"github.com/IceWhaleTech/CasaOS/pkg/config"
-	"github.com/IceWhaleTech/CasaOS/pkg/utils/command"
-	"github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
-	model2 "github.com/IceWhaleTech/CasaOS/service/model"
-	"github.com/docker/docker/api/types"
-	"github.com/docker/docker/api/types/filters"
-	client2 "github.com/docker/docker/client"
-	"github.com/pkg/errors"
-	uuid "github.com/satori/go.uuid"
-	"go.uber.org/zap"
-	"gorm.io/gorm"
-)
-
-type AppService interface {
-	GetMyList(index, size int, position bool) (*[]model2.MyAppList, *[]model2.MyAppList)
-	SaveContainer(m model2.AppListDBModel)
-	GetUninstallInfo(id string) model2.AppListDBModel
-	DeleteApp(id string)
-	GetContainerInfo(id string) (types.Container, error)
-	GetAppDBInfo(id string) model2.AppListDBModel
-	UpdateApp(m model2.AppListDBModel)
-	GetSimpleContainerInfo(id string) (types.Container, error)
-	DelAppConfigDir(path string)
-	GetSystemAppList() []types.Container
-	GetHardwareUsageStream()
-	GetHardwareUsage() []model.DockerStatsModel
-	GetAppStats(id string) string
-	GetAllDBApps() []model2.AppListDBModel
-	ImportApplications(casaApp bool)
-	CheckNewImage()
-}
-
-type appStruct struct {
-	db *gorm.DB
-}
-
-func (a *appStruct) CheckNewImage() {
-	list := MyService.Docker().DockerContainerList()
-	for _, v := range list {
-		inspect, err := MyService.Docker().DockerImageInfo(strings.Split(v.Image, ":")[0])
-		if err != nil {
-			NewVersionApp[v.ID] = inspect.ID
-			continue
-		}
-		if inspect.ID == v.ImageID {
-			delete(NewVersionApp, v.ID)
-			continue
-		}
-		NewVersionApp[v.ID] = inspect.ID
-	}
-
-}
-func (a *appStruct) ImportApplications(casaApp bool) {
-	if casaApp {
-		list := MyService.App().GetAllDBApps()
-		for _, app := range list {
-			info, err := MyService.Docker().DockerContainerInfo(app.CustomId)
-			if err != nil {
-				MyService.App().DeleteApp(app.CustomId)
-				continue
-			}
-			//info.NetworkSettings
-			info.Config.Labels["casaos"] = "casaos"
-			info.Config.Labels["web"] = app.PortMap
-			info.Config.Labels["icon"] = app.Icon
-			info.Config.Labels["desc"] = app.Description
-			info.Config.Labels["index"] = app.Index
-			info.Config.Labels["custom_id"] = app.CustomId
-			info.Name = app.Title
-			container_id, err := MyService.Docker().DockerContainerCopyCreate(info)
-			if err != nil {
-				fmt.Println(err)
-				continue
-			}
-			MyService.App().DeleteApp(app.CustomId)
-			MyService.Docker().DockerContainerStop(app.CustomId)
-			MyService.Docker().DockerContainerRemove(app.CustomId, false)
-			MyService.Docker().DockerContainerStart(container_id)
-
-		}
-	} else {
-		list := MyService.Docker().DockerContainerList()
-		for _, app := range list {
-			info, err := MyService.Docker().DockerContainerInfo(app.ID)
-			if err != nil || info.Config.Labels["casaos"] == "casaos" {
-				continue
-			}
-			info.Config.Labels["casaos"] = "casaos"
-			info.Config.Labels["web"] = ""
-			info.Config.Labels["icon"] = ""
-			info.Config.Labels["desc"] = ""
-			info.Config.Labels["index"] = ""
-			info.Config.Labels["custom_id"] = uuid.NewV4().String()
-
-			_, err = MyService.Docker().DockerContainerCopyCreate(info)
-			if err != nil {
-				continue
-			}
-
-		}
-	}
-
-	// allcontainer := MyService.Docker().DockerContainerList()
-	// for _, app := range allcontainer {
-	// 	info, err := MyService.Docker().DockerContainerInfo(app.ID)
-	// 	if err != nil {
-	// 		continue
-	// 	}
-	// 	MyService.Docker().DockerContainerStop(app.ID)
-	// 	MyService.Docker().DockerContainerRemove(app.ID, false)
-	// 	//info.NetworkSettings
-	// 	info.Config.Labels["custom_id"] = uuid.NewV4().String()
-	// 	container_id, err := MyService.Docker().DockerContainerCopyCreate(info)
-	// 	if err != nil {
-	// 		fmt.Println(err)
-	// 		continue
-	// 	}
-	// 	MyService.Docker().DockerContainerStart(container_id)
-	//}
-}
-
-//获取我的应用列表
-func (a *appStruct) GetMyList(index, size int, position bool) (*[]model2.MyAppList, *[]model2.MyAppList) {
-	cli, err := client2.NewClientWithOpts(client2.FromEnv, client2.WithTimeout(time.Second*5))
-	if err != nil {
-		loger.Error("Failed to init client", zap.Any("err", err))
-	}
-	defer cli.Close()
-	// fts := filters.NewArgs()
-	// fts.Add("label", "casaos=casaos")
-	//fts.Add("label", "casaos")
-	//fts.Add("casaos", "casaos")
-	containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{All: true})
-	if err != nil {
-		loger.Error("Failed to get container_list", zap.Any("err", err))
-	}
-	//获取本地数据库应用
-
-	unTranslation := []model2.MyAppList{}
-
-	list := []model2.MyAppList{}
-
-	for _, m := range containers {
-		if m.Labels["casaos"] == "casaos" {
-
-			_, newVersion := NewVersionApp[m.ID]
-			name := strings.ReplaceAll(m.Names[0], "/", "")
-			icon := m.Labels["icon"]
-			if len(m.Labels["name"]) > 0 {
-				name = m.Labels["name"]
-			}
-			if m.Labels["origin"] == "system" {
-				name = strings.Split(m.Image, ":")[0]
-				if len(strings.Split(name, "/")) > 1 {
-					icon = "https://icon.casaos.io/main/all/" + strings.Split(name, "/")[1] + ".png"
-				}
-			}
-
-			list = append(list, model2.MyAppList{
-				Name:     name,
-				Icon:     icon,
-				State:    m.State,
-				CustomId: m.Labels["custom_id"],
-				Id:       m.ID,
-				Port:     m.Labels["web"],
-				Index:    m.Labels["index"],
-				//Order:      m.Labels["order"],
-				Image:  m.Image,
-				Latest: newVersion,
-				//Type:   m.Labels["origin"],
-				//Slogan: m.Slogan,
-				//Rely:     m.Rely,
-				Host:     m.Labels["host"],
-				Protocol: m.Labels["protocol"],
-			})
-		} else {
-			unTranslation = append(unTranslation, model2.MyAppList{
-				Name:     strings.ReplaceAll(m.Names[0], "/", ""),
-				Icon:     "",
-				State:    m.State,
-				CustomId: m.ID,
-				Id:       m.ID,
-				Port:     "",
-				Latest:   false,
-				Host:     "",
-				Protocol: "",
-				Image:    m.Image,
-			})
-		}
-	}
-
-	//lMap := make(map[string]interface{})
-	// for _, dbModel := range lm {
-	// 	if position {
-	// 		if dbModel.Position {
-	// 			lMap[dbModel.ContainerId] = dbModel
-	// 		}
-	// 	} else {
-	// 		lMap[dbModel.ContainerId] = dbModel
-	// 	}
-	// }
-	// for _, container := range containers {
-
-	// 	if lMap[container.ID] != nil && container.Labels["origin"] != "system" {
-	// 		m := lMap[container.ID].(model2.AppListDBModel)
-	// 		if len(m.Label) == 0 {
-	// 			m.Label = m.Title
-	// 		}
-
-	// 		// info, err := cli.ContainerInspect(context.Background(), container.ID)
-	// 		// var tm string
-	// 		// if err != nil {
-	// 		// 	tm = time.Now().String()
-	// 		// } else {
-	// 		// 	tm = info.State.StartedAt
-	// 		//}
-	// 		list = append(list, model2.MyAppList{
-	// 			Name:     m.Label,
-	// 			Icon:     m.Icon,
-	// 			State:    container.State,
-	// 			CustomId: strings.ReplaceAll(container.Names[0], "/", ""),
-	// 			Port:     m.PortMap,
-	// 			Index:    m.Index,
-	// 			//UpTime:   tm,
-	// 			Image:  m.Image,
-	// 			Slogan: m.Slogan,
-	// 			//Rely:     m.Rely,
-	// 		})
-	// 	}
-
-	// }
-
-	return &list, &unTranslation
-
-}
-
-//system application list
-func (a *appStruct) GetSystemAppList() []types.Container {
-	//获取docker应用
-	cli, err := client2.NewClientWithOpts(client2.FromEnv)
-	if err != nil {
-		loger.Error("Failed to init client", zap.Any("err", err))
-	}
-	defer cli.Close()
-	fts := filters.NewArgs()
-	fts.Add("label", "origin=system")
-	containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{All: true, Filters: fts})
-	if err != nil {
-		loger.Error("Failed to get container_list", zap.Any("err", err))
-	}
-
-	//获取本地数据库应用
-
-	// var lm []model2.AppListDBModel
-	// a.db.Table(model2.CONTAINERTABLENAME).Select("title,icon,port_map,`index`,container_id,position,label,slogan,image,volumes").Find(&lm)
-
-	//list := []model2.MyAppList{}
-	//lMap := make(map[string]interface{})
-	// for _, dbModel := range lm {
-	// 	lMap[dbModel.ContainerId] = dbModel
-	// }
-
-	return containers
-
-}
-func (a *appStruct) GetAllDBApps() []model2.AppListDBModel {
-	var lm []model2.AppListDBModel
-	a.db.Table(model2.CONTAINERTABLENAME).Select("custom_id,title,icon,container_id,label,slogan,image,port_map").Find(&lm)
-	return lm
-}
-
-//获取我的应用列表
-func (a *appStruct) GetContainerInfo(id string) (types.Container, error) {
-	//获取docker应用
-	cli, err := client2.NewClientWithOpts(client2.FromEnv)
-	if err != nil {
-		loger.Error("Failed to init client", zap.Any("err", err))
-	}
-	filters := filters.NewArgs()
-	filters.Add("id", id)
-	containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{All: true, Filters: filters})
-	if err != nil {
-		loger.Error("Failed to get container_list", zap.Any("err", err))
-	}
-
-	if len(containers) > 0 {
-		return containers[0], nil
-	}
-	return types.Container{}, nil
-
-}
-
-func (a *appStruct) GetSimpleContainerInfo(id string) (types.Container, error) {
-	//获取docker应用
-	cli, err := client2.NewClientWithOpts(client2.FromEnv)
-	if err != nil {
-		return types.Container{}, err
-	}
-	defer cli.Close()
-	filters := filters.NewArgs()
-	filters.Add("id", id)
-	containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{All: true, Filters: filters})
-	if err != nil {
-		return types.Container{}, err
-	}
-
-	if len(containers) > 0 {
-		return containers[0], nil
-	}
-	return types.Container{}, errors.New("container not existent")
-}
-
-//获取我的应用列表
-func (a *appStruct) GetAppDBInfo(id string) model2.AppListDBModel {
-	var m model2.AppListDBModel
-	a.db.Table(model2.CONTAINERTABLENAME).Where("custom_id = ?", id).First(&m)
-	return m
-}
-
-//根据容器id获取镜像名称
-func (a *appStruct) GetUninstallInfo(id string) model2.AppListDBModel {
-	var m model2.AppListDBModel
-	a.db.Table(model2.CONTAINERTABLENAME).Select("image,version,enable_upnp,ports,envs,volumes,origin").Where("custom_id = ?", id).First(&m)
-	return m
-}
-
-//创建容器成功后保存容器
-func (a *appStruct) SaveContainer(m model2.AppListDBModel) {
-	a.db.Table(model2.CONTAINERTABLENAME).Create(&m)
-}
-
-func (a *appStruct) UpdateApp(m model2.AppListDBModel) {
-	a.db.Table(model2.CONTAINERTABLENAME).Save(&m)
-}
-
-func (a *appStruct) DelAppConfigDir(path string) {
-	command.OnlyExec("source " + config.AppInfo.ShellPath + "/helper.sh ;DelAppConfigDir " + path)
-}
-
-func (a *appStruct) DeleteApp(id string) {
-	a.db.Table(model2.CONTAINERTABLENAME).Where("custom_id = ?", id).Delete(&model2.AppListDBModel{})
-}
-
-var dataStats sync.Map
-
-var isFinish bool = false
-
-func (a *appStruct) GetAppStats(id string) string {
-	cli, err := client2.NewClientWithOpts(client2.FromEnv)
-	if err != nil {
-		return ""
-	}
-	defer cli.Close()
-	con, err := cli.ContainerStats(context.Background(), id, false)
-	if err != nil {
-		return err.Error()
-	}
-	defer con.Body.Close()
-	c, _ := ioutil.ReadAll(con.Body)
-	return string(c)
-}
-
-func (a *appStruct) GetHardwareUsage() []model.DockerStatsModel {
-
-	stream := true
-	for !isFinish {
-		if stream {
-			stream = false
-			go func() {
-				a.GetHardwareUsageStream()
-			}()
-		}
-		runtime.Gosched()
-	}
-	list := []model.DockerStatsModel{}
-
-	dataStats.Range(func(key, value interface{}) bool {
-		list = append(list, value.(model.DockerStatsModel))
-		return true
-	})
-	return list
-
-}
-
-func (a *appStruct) GetHardwareUsageStream() {
-
-	cli, err := client2.NewClientWithOpts(client2.FromEnv)
-	if err != nil {
-		return
-	}
-	defer cli.Close()
-
-	ctx := context.Background()
-	ctx, cancel := context.WithCancel(ctx)
-
-	fts := filters.NewArgs()
-	fts.Add("label", "casaos=casaos")
-	//fts.Add("status", "running")
-	containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{All: true, Filters: fts})
-	if err != nil {
-		loger.Error("Failed to get container_list", zap.Any("err", err))
-	}
-	for i := 0; i < 100; i++ {
-		if i%10 == 0 {
-			containers, err = cli.ContainerList(context.Background(), types.ContainerListOptions{All: true, Filters: fts})
-			if err != nil {
-				loger.Error("Failed to get container_list", zap.Any("err", err))
-				continue
-			}
-		}
-		if config.CasaOSGlobalVariables.AppChange {
-			config.CasaOSGlobalVariables.AppChange = false
-			dataStats.Range(func(key, value interface{}) bool {
-				dataStats.Delete(key)
-				return true
-			})
-		}
-
-		var temp sync.Map
-		var wg sync.WaitGroup
-		for _, v := range containers {
-			if v.State != "running" {
-				continue
-			}
-			wg.Add(1)
-			go func(v types.Container, i int) {
-				defer wg.Done()
-				stats, err := cli.ContainerStatsOneShot(ctx, v.ID)
-				if err != nil {
-					return
-				}
-				decode := json.NewDecoder(stats.Body)
-				var data interface{}
-				if err := decode.Decode(&data); err == io.EOF {
-					return
-				}
-				m, _ := dataStats.Load(v.ID)
-				dockerStats := model.DockerStatsModel{}
-				if m != nil {
-					dockerStats.Previous = m.(model.DockerStatsModel).Data
-				}
-				dockerStats.Data = data
-				dockerStats.Icon = v.Labels["icon"]
-				dockerStats.Title = strings.ReplaceAll(v.Names[0], "/", "")
-
-				// @tiger - 不建议直接把依赖的数据结构封装返回。
-				//          如果依赖的数据结构有变化,应该在这里适配或者保存,这样更加对客户端负责
-				temp.Store(v.ID, dockerStats)
-				if i == 99 {
-					stats.Body.Close()
-				}
-			}(v, i)
-		}
-		wg.Wait()
-		dataStats = temp
-		isFinish = true
-
-		time.Sleep(time.Second * 1)
-	}
-	isFinish = false
-	cancel()
-}
-
-func NewAppService(db *gorm.DB) AppService {
-	return &appStruct{db: db}
-}

+ 1 - 247
service/casa.go

@@ -1,266 +1,20 @@
 package service
 
 import (
-	"encoding/json"
 	json2 "encoding/json"
-	"fmt"
-	"sort"
-	"strconv"
 	"time"
 
 	"github.com/IceWhaleTech/CasaOS/model"
 	"github.com/IceWhaleTech/CasaOS/pkg/config"
-	"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
 	"github.com/IceWhaleTech/CasaOS/pkg/utils/httper"
-	httper2 "github.com/IceWhaleTech/CasaOS/pkg/utils/httper"
-	"github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
-	"github.com/pkg/errors"
 	"github.com/tidwall/gjson"
-	"go.uber.org/zap"
 )
 
 type CasaService interface {
-	GetServerList(index, size, tp, categoryId, key string) (model.ServerAppListCollection, error)
-	GetServerCategoryList() (list []model.CategoryList, err error)
-	GetServerAppInfo(id, t string, language string) (model.ServerAppList, error)
-	ShareAppFile(body []byte) string
 	GetCasaosVersion() model.Version
-	AsyncGetServerList() (collection model.ServerAppListCollection, err error)
-	AsyncGetServerCategoryList() ([]model.CategoryList, error)
 }
 
-type casaService struct {
-}
-
-func (o *casaService) ShareAppFile(body []byte) string {
-	head := make(map[string]string)
-
-	head["Authorization"] = GetToken()
-
-	content := httper2.Post(config.ServerInfo.ServerApi+"/v1/community/add", body, "application/json", head)
-	return content
-}
-
-func (o *casaService) GetServerList(index, size, tp, categoryId, key string) (model.ServerAppListCollection, error) {
-
-	keyName := fmt.Sprintf("list_%s_%s_%s_%s_%s", index, size, tp, categoryId, "en")
-	collection := model.ServerAppListCollection{}
-	if result, ok := Cache.Get(keyName); ok {
-		res, ok := result.(string)
-		if ok {
-			json2.Unmarshal([]byte(res), &collection)
-			return collection, nil
-		}
-	}
-
-	collectionStr := file.ReadFullFile(config.AppInfo.DBPath + "/app_list.json")
-
-	err := json2.Unmarshal(collectionStr, &collection)
-	if err != nil {
-		loger.Error("marshal error", zap.Any("err", err), zap.Any("content", string(collectionStr)))
-		collection, err = o.AsyncGetServerList()
-		if err != nil {
-			return collection, err
-		}
-	}
-
-	go o.AsyncGetServerList()
-
-	if categoryId != "0" {
-		categoryInt, _ := strconv.Atoi(categoryId)
-		nList := []model.ServerAppList{}
-		for _, v := range collection.List {
-			if v.CategoryId == categoryInt {
-				nList = append(nList, v)
-			}
-		}
-		collection.List = nList
-		nCommunity := []model.ServerAppList{}
-		for _, v := range collection.Community {
-			if v.CategoryId == categoryInt {
-				nCommunity = append(nCommunity, v)
-			}
-		}
-		collection.Community = nCommunity
-	}
-	if tp != "name" {
-		if tp == "new" {
-			sort.Slice(collection.List, func(i, j int) bool {
-				return collection.List[i].CreatedAt.After(collection.List[j].CreatedAt)
-			})
-			sort.Slice(collection.Community, func(i, j int) bool {
-				return collection.Community[i].CreatedAt.After(collection.Community[j].CreatedAt)
-			})
-		} else if tp == "rank" {
-			sort.Slice(collection.List, func(i, j int) bool {
-				return collection.List[i].QueryCount > collection.List[j].QueryCount
-			})
-			sort.Slice(collection.Community, func(i, j int) bool {
-				return collection.Community[i].QueryCount > collection.Community[j].QueryCount
-			})
-		}
-	}
-	sizeInt, _ := strconv.Atoi(size)
-
-	if index != "1" {
-		indexInt, _ := strconv.Atoi(index)
-		collection.List = collection.List[(indexInt-1)*sizeInt : indexInt*sizeInt]
-		collection.Community = collection.Community[(indexInt-1)*sizeInt : indexInt*sizeInt]
-	} else {
-		if len(collection.List) > sizeInt {
-			collection.List = collection.List[:sizeInt]
-		}
-		if len(collection.Community) > sizeInt {
-			collection.Community = collection.Community[:sizeInt]
-		}
-	}
-
-	if len(collection.List) > 0 {
-		by, _ := json.Marshal(collection)
-		Cache.Set(keyName, string(by), time.Minute*10)
-	}
-
-	return collection, nil
-
-}
-
-func (o *casaService) AsyncGetServerList() (collection model.ServerAppListCollection, err error) {
-
-	results := file.ReadFullFile(config.AppInfo.DBPath + "/app_list.json")
-	errr := json2.Unmarshal(results, &collection)
-	if errr != nil {
-		loger.Error("marshal error", zap.Any("err", err), zap.Any("content", string(results)))
-	}
-
-	head := make(map[string]string)
-
-	head["Authorization"] = GetToken()
-
-	listS := httper2.Get(config.ServerInfo.ServerApi+"/v2/app/newlist?index=1&size=1000&rank=name&category_id=0&key=&language=en", head)
-	listModel := []model.ServerAppList{}
-	communityModel := []model.ServerAppList{}
-	recommendModel := []model.ServerAppList{}
-	err = json2.Unmarshal([]byte(gjson.Get(listS, "data.list").String()), &listModel)
-	json2.Unmarshal([]byte(gjson.Get(listS, "data.recommend").String()), &recommendModel)
-	json2.Unmarshal([]byte(gjson.Get(listS, "data.community").String()), &communityModel)
-
-	if len(listModel) > 0 {
-		collection.Community = communityModel
-		collection.List = listModel
-		collection.Recommend = recommendModel
-		collection.Version = o.GetCasaosVersion().Version
-		var by []byte
-		by, err = json.Marshal(collection)
-		if err != nil {
-			loger.Error("marshal error", zap.Any("err", err))
-		}
-		file.WriteToPath(by, config.AppInfo.DBPath, "app_list.json")
-	}
-	return
-}
-
-// func (o *casaService) GetServerCategoryList() (list []model.ServerCategoryList) {
-
-// 	keyName := fmt.Sprintf("category_list")
-// 	if result, ok := Cache.Get(keyName); ok {
-// 		res, ok := result.(string)
-// 		if ok {
-// 			json2.Unmarshal([]byte(gjson.Get(res, "data").String()), &list)
-// 			return list
-// 		}
-// 	}
-
-// 	head := make(map[string]string)
-// 	head["Authorization"] = GetToken()
-
-// 	listS := httper2.Get(config.ServerInfo.ServerApi+"/v2/app/category", head)
-
-// 	json2.Unmarshal([]byte(gjson.Get(listS, "data").String()), &list)
-// 	if len(list) > 0 {
-// 		Cache.Set(keyName, listS, time.Hour*24)
-// 	}
-// 	return list
-// }
-
-func (o *casaService) GetServerCategoryList() (list []model.CategoryList, err error) {
-	category := model.ServerCategoryList{}
-	results := file.ReadFullFile(config.AppInfo.DBPath + "/app_category.json")
-	err = json2.Unmarshal(results, &category)
-	if err != nil {
-		loger.Error("marshal error", zap.Any("err", err), zap.Any("content", string(results)))
-		return o.AsyncGetServerCategoryList()
-	}
-	go o.AsyncGetServerCategoryList()
-	return category.Item, err
-}
-
-func (o *casaService) AsyncGetServerCategoryList() ([]model.CategoryList, error) {
-	list := model.ServerCategoryList{}
-	results := file.ReadFullFile(config.AppInfo.DBPath + "/app_category.json")
-	err := json2.Unmarshal(results, &list)
-	if err != nil {
-		loger.Error("marshal error", zap.Any("err", err), zap.Any("content", string(results)))
-	}
-	item := []model.CategoryList{}
-	head := make(map[string]string)
-	head["Authorization"] = GetToken()
-	listS := httper2.Get(config.ServerInfo.ServerApi+"/v2/app/category", head)
-	if len(listS) == 0 {
-		return item, errors.New("server error")
-	}
-	json2.Unmarshal([]byte(gjson.Get(listS, "data").String()), &item)
-	if len(item) > 0 {
-		list.Version = o.GetCasaosVersion().Version
-		list.Item = item
-		by, err := json.Marshal(list)
-		if err != nil {
-			loger.Error("marshal error", zap.Any("err", err))
-		}
-		file.WriteToPath(by, config.AppInfo.DBPath, "app_category.json")
-	}
-	return item, nil
-}
-
-func (o *casaService) GetServerAppInfo(id, t string, language string) (model.ServerAppList, error) {
-
-	head := make(map[string]string)
-
-	head["Authorization"] = GetToken()
-	infoS := httper2.Get(config.ServerInfo.ServerApi+"/v2/app/info/"+id+"?t="+t+"&language="+language, head)
-
-	info := model.ServerAppList{}
-	if infoS == "" {
-		return info, errors.New("server error")
-	}
-	err := json2.Unmarshal([]byte(gjson.Get(infoS, "data").String()), &info)
-	if err != nil {
-		fmt.Println(infoS)
-		return info, err
-	}
-
-	return info, nil
-}
-func GetToken() string {
-	t := make(chan string)
-	keyName := "casa_token"
-
-	var auth string
-	if result, ok := Cache.Get(keyName); ok {
-		auth, ok = result.(string)
-		if ok {
-
-			return auth
-		}
-	}
-	go func() {
-		str := httper2.Get(config.ServerInfo.ServerApi+"/token", nil)
-		t <- gjson.Get(str, "data").String()
-	}()
-	auth = <-t
-
-	Cache.SetDefault(keyName, auth)
-	return auth
-}
+type casaService struct{}
 
 /**
  * @description: get remote version

+ 0 - 962
service/docker.go

@@ -1,962 +0,0 @@
-package service
-
-import (
-	"bytes"
-	"context"
-	"encoding/base64"
-	"encoding/binary"
-	json2 "encoding/json"
-	"fmt"
-
-	"github.com/IceWhaleTech/CasaOS/model/notify"
-	"github.com/pkg/errors"
-	"go.uber.org/zap"
-
-	"github.com/IceWhaleTech/CasaOS/model"
-	"github.com/IceWhaleTech/CasaOS/pkg/docker"
-	command2 "github.com/IceWhaleTech/CasaOS/pkg/utils/command"
-	"github.com/IceWhaleTech/CasaOS/pkg/utils/env_helper"
-	"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
-	"github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
-
-	//"github.com/containerd/containerd/oci"
-	"io"
-	"io/ioutil"
-	"log"
-	"os"
-	"strconv"
-	"strings"
-	"time"
-
-	"github.com/docker/docker/api/types"
-	"github.com/docker/docker/api/types/container"
-	"github.com/docker/docker/api/types/filters"
-	"github.com/docker/docker/api/types/mount"
-	"github.com/docker/docker/api/types/network"
-	client2 "github.com/docker/docker/client"
-	"github.com/docker/go-connections/nat"
-)
-
-type DockerService interface {
-	DockerPullImage(imageName string, icon, name string) error
-	IsExistImage(imageName string) bool
-	DockerContainerCreate(m model.CustomizationPostData, id string) (containerId string, err error)
-	DockerContainerCopyCreate(info *types.ContainerJSON) (containerId string, err error)
-	DockerContainerStart(name string) error
-	DockerContainerStats(name string) (string, error)
-	DockerListByName(name string) (*types.Container, error)
-	DockerListByImage(image, version string) (*types.Container, error)
-	DockerContainerInfo(name string) (*types.ContainerJSON, error)
-	DockerImageRemove(name string) error
-	DockerContainerRemove(name string, update bool) error
-	DockerContainerStop(id string) error
-	DockerContainerUpdateName(name, id string) (err error)
-	DockerContainerUpdate(m model.CustomizationPostData, id string) (err error)
-	DockerContainerLog(name string) ([]byte, error)
-	DockerContainerCommit(name string)
-	DockerContainerList() []types.Container
-	DockerNetworkModelList() []types.NetworkResource
-	DockerImageInfo(image string) (types.ImageInspect, error)
-	GetNetWorkNameByNetWorkID(id string) (string, error)
-	ContainerExecShell(container_id string) string
-	GetDockerInfo() (types.Info, error)
-}
-
-type dockerService struct {
-	rootDir string
-}
-
-func (ds *dockerService) DockerContainerList() []types.Container {
-	cli, err := client2.NewClientWithOpts(client2.FromEnv, client2.WithTimeout(time.Second*5))
-	if err != nil {
-		return nil
-	}
-	defer cli.Close()
-	containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{All: true})
-	if err != nil {
-		return containers
-	}
-	return containers
-}
-
-func (ds *dockerService) ContainerExecShell(container_id string) string {
-	cli, _ := client2.NewClientWithOpts(client2.FromEnv)
-	exec, err := cli.ContainerExecCreate(context.Background(), container_id, types.ExecConfig{
-		User: "1000:1000",
-		Cmd:  []string{"echo -e \"hellow\nworld\" >> /a.txt"},
-	})
-	if err != nil {
-		os.Exit(5)
-	}
-	err = cli.ContainerExecStart(context.Background(), exec.ID, types.ExecStartCheck{})
-	if err != nil {
-		fmt.Println("exec script error ", err)
-	}
-	return exec.ID
-}
-
-// 创建默认网络
-func DockerNetwork() {
-
-	cli, _ := client2.NewClientWithOpts(client2.FromEnv)
-	defer cli.Close()
-	d, _ := cli.NetworkList(context.Background(), types.NetworkListOptions{})
-
-	for _, resource := range d {
-		if resource.Name == docker.NETWORKNAME {
-			return
-		}
-	}
-	cli.NetworkCreate(context.Background(), docker.NETWORKNAME, types.NetworkCreate{})
-}
-
-// 根据网络id获取网络名
-func (ds *dockerService) GetNetWorkNameByNetWorkID(id string) (string, error) {
-	cli, _ := client2.NewClientWithOpts(client2.FromEnv)
-	defer cli.Close()
-	filter := filters.NewArgs()
-	filter.Add("id", id)
-	d, err := cli.NetworkList(context.Background(), types.NetworkListOptions{Filters: filter})
-	if err == nil && len(d) > 0 {
-		return d[0].Name, nil
-	}
-	return "", err
-}
-
-// 拉取镜像
-func DockerPull() {
-
-	cli, _ := client2.NewClientWithOpts(client2.FromEnv)
-	defer cli.Close()
-
-	authConfig := types.AuthConfig{}
-	encodedJSON, err := json2.Marshal(authConfig)
-	fmt.Println(err)
-
-	authStr := base64.URLEncoding.EncodeToString(encodedJSON)
-	reader, err := cli.ImagePull(context.Background(), "swr.cn-north-4.myhuaweicloud.com/root/swr-demo-2048:latest", types.ImagePullOptions{RegistryAuth: authStr})
-
-	buf := new(bytes.Buffer)
-	buf.ReadFrom(reader)
-	fmt.Println(buf.String())
-
-}
-
-// 拉取镜像
-func DockerEx() {
-
-	cli, _ := client2.NewClientWithOpts(client2.FromEnv)
-	defer cli.Close()
-
-	importResponse, err := cli.ImageImport(context.Background(), types.ImageImportSource{
-		Source:     strings.NewReader("source"),
-		SourceName: "image_source",
-	}, "repository_name:imported", types.ImageImportOptions{
-		Tag:     "imported",
-		Message: "A message",
-		Changes: []string{"change1", "change2"},
-	})
-
-	response, err := ioutil.ReadAll(importResponse)
-	if err != nil {
-		fmt.Println(err)
-	}
-	importResponse.Close()
-	println(string(response))
-	if string(response) != "response" {
-		fmt.Printf("expected response to contain 'response', got %s", string(response))
-	}
-}
-
-//func DockerContainerSize() {
-//	cli, err := client2.NewClientWithOpts(client2.FromEnv)
-//	//but := bytes.Buffer{}
-//	d, err := cli.ContainerExecCreate(context.Background(), "c3adcef92bae648890941ac00e6c4024d7f2959c2e629f0b581d6a19d77b5eda")
-//	fmt.Println(d)
-//	st, _ := ioutil.ReadAll(d.Body)
-//	fmt.Println(string(st))
-//	if err != nil {
-//		fmt.Print(err)
-//	}
-//
-//}
-
-func (ds *dockerService) DockerImageInfo(image string) (types.ImageInspect, error) {
-	cli, err := client2.NewClientWithOpts(client2.FromEnv)
-	if err != nil {
-		return types.ImageInspect{}, err
-	}
-	inspect, _, err := cli.ImageInspectWithRaw(context.Background(), image)
-	if err != nil {
-		return inspect, err
-	}
-	return inspect, nil
-}
-
-func MsqlExec(container string) error {
-	cli, err := client2.NewClientWithOpts(client2.FromEnv)
-	ctx := context.Background()
-	// 执行/bin/bash命令
-	ir, err := cli.ContainerExecCreate(ctx, container, types.ExecConfig{
-		AttachStdin:  false,
-		AttachStdout: true,
-		AttachStderr: true,
-		Cmd:          []string{"date"},
-		Tty:          true,
-		Env:          []string{"aaa=ddd"},
-	})
-	err = cli.ContainerExecStart(ctx, ir.ID, types.ExecStartCheck{})
-
-	fmt.Println(err)
-
-	return err
-}
-
-func Exec(container, row, col string) (hr types.HijackedResponse, err error) {
-	cli, err := client2.NewClientWithOpts(client2.FromEnv)
-	ctx := context.Background()
-	// 执行/bin/bash命令
-	ir, err := cli.ContainerExecCreate(ctx, container, types.ExecConfig{
-		AttachStdin:  true,
-		AttachStdout: true,
-		AttachStderr: true,
-		Env:          []string{"COLUMNS=" + col, "LINES=" + row},
-		Cmd:          []string{"/bin/bash"},
-		Tty:          true,
-	})
-	if err != nil {
-		return
-	}
-	// 附加到上面创建的/bin/bash进程中
-	hr, err = cli.ContainerExecAttach(ctx, ir.ID, types.ExecStartCheck{Detach: false, Tty: true})
-	if err != nil {
-		return
-	}
-	return
-}
-
-func DockerLog() {
-	//cli, err := client2.NewClientWithOpts(client2.FromEnv)
-	//ctx := context.Background()
-	//ir, err := cli.ContainerLogs(ctx, "79c6fa382c330b9149e2d28d24f4d2c231cdb8cfc0710c2d268ccee13c5b24f8", types.ContainerLogsOptions{})
-	//str, err := ioutil.ReadAll(ir)
-	//fmt.Println(string(str))
-	//fmt.Println(err)
-
-	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
-	defer cancel()
-
-	client, _ := client2.NewClientWithOpts(client2.FromEnv)
-	reader, err := client.ContainerLogs(ctx, "79c6fa382c330b9149e2d28d24f4d2c231cdb8cfc0710c2d268ccee13c5b24f8", types.ContainerLogsOptions{})
-	if err != nil {
-		log.Fatal(err)
-	}
-	_, err = io.Copy(os.Stdout, reader)
-	if err != nil && err != io.EOF {
-		log.Fatal(err)
-	}
-}
-
-func DockerLogs() {
-	cli, err := client2.NewClientWithOpts(client2.FromEnv)
-	i, err := cli.ContainerLogs(context.Background(), "79c6fa382c330b9149e2d28d24f4d2c231cdb8cfc0710c2d268ccee13c5b24f8", types.ContainerLogsOptions{
-		ShowStderr: true,
-		ShowStdout: true,
-		Timestamps: false,
-		Follow:     true,
-		Tail:       "40",
-	})
-	if err != nil {
-		log.Fatal(err)
-	}
-	defer i.Close()
-
-	hdr := make([]byte, 8)
-	for {
-		_, err := i.Read(hdr)
-		if err != nil {
-			log.Fatal(err)
-		}
-		var w io.Writer
-		switch hdr[0] {
-		case 1:
-			w = os.Stdout
-		default:
-			w = os.Stderr
-		}
-		count := binary.BigEndian.Uint32(hdr[4:])
-		dat := make([]byte, count)
-		_, err = i.Read(dat)
-		fmt.Fprint(w, string(dat))
-	}
-}
-
-//正式内容
-
-// 检查镜像是否存在
-func (ds *dockerService) IsExistImage(imageName string) bool {
-	cli, err := client2.NewClientWithOpts(client2.FromEnv)
-	if err != nil {
-		return false
-	}
-	defer cli.Close()
-	filter := filters.NewArgs()
-	filter.Add("reference", imageName)
-
-	list, err := cli.ImageList(context.Background(), types.ImageListOptions{Filters: filter})
-
-	if err == nil && len(list) > 0 {
-		return true
-	}
-
-	return false
-}
-
-// 安装镜像
-func (ds *dockerService) DockerPullImage(imageName string, icon, name string) error {
-	cli, err := client2.NewClientWithOpts(client2.FromEnv)
-	if err != nil {
-		return err
-	}
-	defer cli.Close()
-	out, err := cli.ImagePull(context.Background(), imageName, types.ImagePullOptions{})
-	if err != nil {
-		return err
-	}
-	defer out.Close()
-	if err != nil {
-
-		return err
-	}
-	//io.Copy()
-	buf := make([]byte, 2048*4)
-	for {
-		n, err := out.Read(buf)
-		if err != nil {
-			if err != io.EOF {
-				fmt.Println("read error:", err)
-			}
-			break
-		}
-		if len(icon) > 0 && len(name) > 0 {
-			notify := notify.Application{}
-			notify.Icon = icon
-			notify.Name = name
-			notify.State = "PULLING"
-			notify.Type = "INSTALL"
-			notify.Finished = false
-			notify.Success = true
-			notify.Message = string(buf[:n])
-			MyService.Notify().SendInstallAppBySocket(notify)
-		}
-
-	}
-	return err
-}
-func (ds *dockerService) DockerContainerCopyCreate(info *types.ContainerJSON) (containerId string, err error) {
-	cli, err := client2.NewClientWithOpts(client2.FromEnv)
-	if err != nil {
-		return "", err
-	}
-	defer cli.Close()
-	container, err := cli.ContainerCreate(context.Background(), info.Config, info.HostConfig, &network.NetworkingConfig{info.NetworkSettings.Networks}, nil, info.Name)
-	if err != nil {
-		return "", err
-	}
-	return container.ID, err
-}
-
-// param imageName 镜像名称
-// param containerDbId 数据库的id
-// param port 容器内部主端口
-// param mapPort 容器主端口映射到外部的端口
-// param tcp 容器其他tcp端口
-// param udp 容器其他udp端口
-func (ds *dockerService) DockerContainerCreate(m model.CustomizationPostData, id string) (containerId string, err error) {
-	if len(m.NetworkModel) == 0 {
-		m.NetworkModel = "bridge"
-	}
-
-	cli, err := client2.NewClientWithOpts(client2.FromEnv)
-	if err != nil {
-		return "", err
-	}
-
-	defer cli.Close()
-	ports := make(nat.PortSet)
-	portMaps := make(nat.PortMap)
-	//	ports[nat.Port(fmt.Sprint(m.PortMap)+"/tcp")] = struct{}{}
-	//	if net != "host" {
-	//		portMaps[nat.Port(fmt.Sprint(m.Port)+"/tcp")] = []nat.PortBinding{{HostIP: "", HostPort: m.PortMap}}
-	//	}
-	//port := ""
-	for _, portMap := range m.Ports {
-		// if portMap.CommendPort == m.PortMap && portMap.Protocol == "tcp" || portMap.Protocol == "both" {
-		// 	port = portMap.ContainerPort
-		// }
-		if portMap.Protocol == "tcp" {
-
-			tContainer, _ := strconv.Atoi(portMap.ContainerPort)
-			if tContainer > 0 {
-				ports[nat.Port(portMap.ContainerPort+"/tcp")] = struct{}{}
-				if m.NetworkModel != "host" {
-					portMaps[nat.Port(portMap.ContainerPort+"/tcp")] = []nat.PortBinding{{HostPort: portMap.CommendPort}}
-				}
-			}
-		} else if portMap.Protocol == "both" {
-
-			tContainer, _ := strconv.Atoi(portMap.ContainerPort)
-			if tContainer > 0 {
-				ports[nat.Port(portMap.ContainerPort+"/tcp")] = struct{}{}
-				if m.NetworkModel != "host" {
-					portMaps[nat.Port(portMap.ContainerPort+"/tcp")] = []nat.PortBinding{{HostPort: portMap.CommendPort}}
-				}
-			}
-
-			uContainer, _ := strconv.Atoi(portMap.ContainerPort)
-			if uContainer > 0 {
-				ports[nat.Port(portMap.ContainerPort+"/udp")] = struct{}{}
-				if m.NetworkModel != "host" {
-					portMaps[nat.Port(portMap.ContainerPort+"/udp")] = []nat.PortBinding{{HostPort: portMap.CommendPort}}
-				}
-			}
-
-		} else {
-			uContainer, _ := strconv.Atoi(portMap.ContainerPort)
-			if uContainer > 0 {
-				ports[nat.Port(portMap.ContainerPort+"/udp")] = struct{}{}
-				if m.NetworkModel != "host" {
-					portMaps[nat.Port(portMap.ContainerPort+"/udp")] = []nat.PortBinding{{HostPort: portMap.CommendPort}}
-				}
-			}
-		}
-
-	}
-
-	var envArr []string
-	var showENV []string
-	showENV = append(showENV, "casaos")
-	for _, e := range m.Envs {
-		showENV = append(showENV, e.Name)
-		if strings.HasPrefix(e.Value, "$") {
-			envArr = append(envArr, e.Name+"="+env_helper.ReplaceDefaultENV(e.Value, MyService.System().GetTimeZone()))
-			continue
-		}
-		if len(e.Value) > 0 {
-			if e.Value == "port_map" {
-				envArr = append(envArr, e.Name+"="+m.PortMap)
-				continue
-			}
-			envArr = append(envArr, e.Name+"="+e.Value)
-		}
-	}
-
-	res := container.Resources{}
-	if m.CpuShares > 0 {
-		res.CPUShares = m.CpuShares
-	}
-	if m.Memory > 0 {
-		res.Memory = m.Memory << 20
-	}
-	for _, p := range m.Devices {
-		if len(p.Path) > 0 {
-			res.Devices = append(res.Devices, container.DeviceMapping{PathOnHost: p.Path, PathInContainer: p.ContainerPath, CgroupPermissions: "rwm"})
-		}
-	}
-	hostConfingBind := []string{}
-	// volumes bind
-	volumes := []mount.Mount{}
-	for _, v := range m.Volumes {
-		path := v.Path
-		if len(path) == 0 {
-			path = docker.GetDir(m.Label, v.Path)
-			if len(path) == 0 {
-				continue
-			}
-		}
-		path = strings.ReplaceAll(path, "$AppID", m.Label)
-		//reg1 := regexp.MustCompile(`([^<>/\\\|:""\*\?]+\.\w+$)`)
-		//result1 := reg1.FindAllStringSubmatch(path, -1)
-		//if len(result1) == 0 {
-		err = file.IsNotExistMkDir(path)
-		if err != nil {
-			loger.Error("Failed to create a folder", zap.Any("err", err))
-			continue
-		}
-		//}
-		//  else {
-		// 	err = file.IsNotExistCreateFile(path)
-		// 	if err != nil {
-		// 		ds.log.Error("mkdir error", err)
-		// 		continue
-		// 	}
-		// }
-
-		volumes = append(volumes, mount.Mount{
-			Type:   mount.TypeBind,
-			Source: path,
-			Target: v.ContainerPath,
-		})
-
-		hostConfingBind = append(hostConfingBind, v.Path+":"+v.ContainerPath)
-	}
-
-	rp := container.RestartPolicy{}
-
-	if len(m.Restart) > 0 {
-		rp.Name = m.Restart
-	}
-	// healthTest := []string{}
-	// if len(port) > 0 {
-	// 	healthTest = []string{"CMD-SHELL", "curl -f http://localhost:" + port + m.Index + " || exit 1"}
-	// }
-
-	// health := &container.HealthConfig{
-	// 	Test:        healthTest,
-	// 	StartPeriod: 0,
-	// 	Retries:     1000,
-	// }
-	// fmt.Print(health)
-	if len(m.HostName) == 0 {
-		m.HostName = m.Label
-	}
-
-	info, err := cli.ContainerInspect(context.Background(), id)
-	hostConfig := &container.HostConfig{}
-	config := &container.Config{}
-	config.Labels = map[string]string{}
-	if err == nil {
-		// info.HostConfig = &container.HostConfig{}
-		// info.Config = &container.Config{}
-		// info.NetworkSettings = &types.NetworkSettings{}
-		hostConfig = info.HostConfig
-		config = info.Config
-		if config.Labels["casaos"] == "casaos" {
-			config.Cmd = m.Cmd
-			config.Image = m.Image
-			config.Env = envArr
-			config.Hostname = m.HostName
-			config.ExposedPorts = ports
-		}
-	} else {
-		config.Cmd = m.Cmd
-		config.Image = m.Image
-		config.Env = envArr
-		config.Hostname = m.HostName
-		config.ExposedPorts = ports
-	}
-
-	config.Labels["origin"] = m.Origin
-	config.Labels["casaos"] = "casaos"
-	config.Labels["web"] = m.PortMap
-	config.Labels["icon"] = m.Icon
-	config.Labels["desc"] = m.Description
-	config.Labels["index"] = m.Index
-	config.Labels["custom_id"] = m.CustomId
-	config.Labels["show_env"] = strings.Join(showENV, ",")
-	config.Labels["protocol"] = m.Protocol
-	config.Labels["host"] = m.Host
-	config.Labels["name"] = m.Label
-	//container, err := cli.ContainerCreate(context.Background(), info.Config, info.HostConfig, &network.NetworkingConfig{info.NetworkSettings.Networks}, nil, info.Name)
-
-	hostConfig.Mounts = volumes
-	hostConfig.Binds = []string{}
-	hostConfig.Privileged = m.Privileged
-	hostConfig.CapAdd = m.CapAdd
-	hostConfig.NetworkMode = container.NetworkMode(m.NetworkModel)
-	hostConfig.RestartPolicy = rp
-	hostConfig.Resources = res
-	//hostConfig := &container.HostConfig{Resources: res, Mounts: volumes, RestartPolicy: rp, NetworkMode: , Privileged: m.Privileged, CapAdd: m.CapAdd}
-	//if net != "host" {
-
-	hostConfig.PortBindings = portMaps
-	//}
-	containerDb, err := cli.ContainerCreate(context.Background(),
-		config,
-		hostConfig,
-		&network.NetworkingConfig{EndpointsConfig: map[string]*network.EndpointSettings{m.NetworkModel: {NetworkID: "", Aliases: []string{}}}},
-		nil,
-		m.ContainerName)
-	if err != nil {
-		return "", err
-	}
-	return containerDb.ID, err
-}
-
-// 删除容器
-func (ds *dockerService) DockerContainerRemove(name string, update bool) error {
-	cli, err := client2.NewClientWithOpts(client2.FromEnv)
-	if err != nil {
-		return err
-	}
-	defer cli.Close()
-	err = cli.ContainerRemove(context.Background(), name, types.ContainerRemoveOptions{})
-
-	//路径处理
-	if !update {
-		path := docker.GetDir(name, "/config")
-		if !file.CheckNotExist(path) {
-			file.RMDir(path)
-		}
-	}
-
-	if err != nil {
-		return err
-	}
-
-	return err
-}
-
-// 删除镜像
-func (ds *dockerService) DockerImageRemove(name string) error {
-	cli, err := client2.NewClientWithOpts(client2.FromEnv)
-	if err != nil {
-		return err
-	}
-	defer cli.Close()
-	imageList, err := cli.ImageList(context.Background(), types.ImageListOptions{})
-
-	imageId := ""
-
-Loop:
-	for _, ig := range imageList {
-		for _, i := range ig.RepoTags {
-			if i == name {
-				imageId = ig.ID
-				break Loop
-			}
-		}
-	}
-	_, err = cli.ImageRemove(context.Background(), imageId, types.ImageRemoveOptions{})
-	return err
-}
-
-func DockerImageRemove(name string) error {
-	cli, err := client2.NewClientWithOpts(client2.FromEnv)
-	if err != nil {
-		return err
-	}
-	defer cli.Close()
-	imageList, err := cli.ImageList(context.Background(), types.ImageListOptions{})
-	imageId := ""
-
-Loop:
-	for _, ig := range imageList {
-		fmt.Println(ig.RepoDigests)
-		fmt.Println(ig.Containers)
-		for _, i := range ig.RepoTags {
-			if i == name {
-				imageId = ig.ID
-				break Loop
-			}
-		}
-	}
-	_, err = cli.ImageRemove(context.Background(), imageId, types.ImageRemoveOptions{})
-	return err
-}
-
-// 停止镜像
-func (ds *dockerService) DockerContainerStop(id string) error {
-	cli, err := client2.NewClientWithOpts(client2.FromEnv)
-	if err != nil {
-		return err
-	}
-	defer cli.Close()
-	err = cli.ContainerStop(context.Background(), id, nil)
-	return err
-}
-
-// 启动容器
-func (ds *dockerService) DockerContainerStart(name string) error {
-	cli, err := client2.NewClientWithOpts(client2.FromEnv)
-	if err != nil {
-		return err
-	}
-	defer cli.Close()
-	err = cli.ContainerStart(context.Background(), name, types.ContainerStartOptions{})
-	return err
-}
-
-// 查看日志
-func (ds *dockerService) DockerContainerLog(name string) ([]byte, error) {
-	cli, err := client2.NewClientWithOpts(client2.FromEnv)
-	if err != nil {
-		return []byte(""), err
-	}
-	defer cli.Close()
-	//body, err := cli.ContainerAttach(context.Background(), name, types.ContainerAttachOptions{Logs: true, Stream: false, Stdin: false, Stdout: false, Stderr: false})
-	body, err := cli.ContainerLogs(context.Background(), name, types.ContainerLogsOptions{ShowStdout: true, ShowStderr: true})
-
-	if err != nil {
-		return []byte(""), err
-	}
-
-	defer body.Close()
-	content, err := ioutil.ReadAll(body)
-	//content, err := ioutil.ReadAll(body)
-	if err != nil {
-		return []byte(""), err
-	}
-	return content, nil
-}
-
-func DockerContainerStats1() error {
-	cli, err := client2.NewClientWithOpts(client2.FromEnv)
-	if err != nil {
-		return err
-	}
-	defer cli.Close()
-	dss, err := cli.ContainerStats(context.Background(), "dockermysql", false)
-	if err != nil {
-		return err
-	}
-	defer dss.Body.Close()
-	sts, err := ioutil.ReadAll(dss.Body)
-	if err != nil {
-		return err
-	}
-	fmt.Println(string(sts))
-	return nil
-}
-
-// 获取容器状态
-func (ds *dockerService) DockerContainerStats(name string) (string, error) {
-	cli, err := client2.NewClientWithOpts(client2.FromEnv)
-	if err != nil {
-		return "", err
-	}
-	defer cli.Close()
-	dss, err := cli.ContainerStats(context.Background(), name, false)
-	if err != nil {
-		return "", err
-	}
-	defer dss.Body.Close()
-	sts, err := ioutil.ReadAll(dss.Body)
-	if err != nil {
-		return "", err
-	}
-	return string(sts), nil
-}
-
-// 备份容器
-func (ds *dockerService) DockerContainerCommit(name string) {
-	cli, err := client2.NewClientWithOpts(client2.FromEnv)
-	if err != nil {
-		fmt.Println(err)
-	}
-	defer cli.Close()
-	d, err := cli.ContainerInspect(context.Background(), name)
-	dss, err := cli.ContainerCommit(context.Background(), name, types.ContainerCommitOptions{Reference: "test", Config: d.Config})
-	if err != nil {
-		fmt.Println(err)
-	}
-	fmt.Println(dss)
-}
-
-func (ds *dockerService) DockerListByName(name string) (*types.Container, error) {
-	cli, _ := client2.NewClientWithOpts(client2.FromEnv)
-	defer cli.Close()
-	filter := filters.NewArgs()
-	filter.Add("name", name)
-	containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{Filters: filter})
-	if err != nil {
-		return &types.Container{}, err
-	}
-	if len(containers) == 0 {
-		return &types.Container{}, errors.New("not found")
-	}
-	return &containers[0], nil
-}
-
-func (ds *dockerService) DockerListByImage(image, version string) (*types.Container, error) {
-	cli, _ := client2.NewClientWithOpts(client2.FromEnv)
-	defer cli.Close()
-	filter := filters.NewArgs()
-	filter.Add("ancestor", image+":"+version)
-	containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{Filters: filter})
-	if err != nil {
-		return nil, err
-	}
-	if len(containers) == 0 {
-		return nil, nil
-	}
-	return &containers[0], nil
-}
-
-// 获取容器详情
-func (ds *dockerService) DockerContainerInfo(name string) (*types.ContainerJSON, error) {
-
-	cli, err := client2.NewClientWithOpts(client2.FromEnv)
-	if err != nil {
-		return &types.ContainerJSON{}, err
-	}
-	defer cli.Close()
-	d, err := cli.ContainerInspect(context.Background(), name)
-	if err != nil {
-		return &types.ContainerJSON{}, err
-	}
-	return &d, nil
-}
-
-// 更新容器
-// param shares cpu优先级
-// param containerDbId 数据库的id
-// param port 容器内部主端口
-// param mapPort 容器主端口映射到外部的端口
-// param tcp 容器其他tcp端口
-// param udp 容器其他udp端口
-func (ds *dockerService) DockerContainerUpdate(m model.CustomizationPostData, id string) (err error) {
-	cli, err := client2.NewClientWithOpts(client2.FromEnv)
-	if err != nil {
-		return err
-	}
-	defer cli.Close()
-	//重启策略
-	rp := container.RestartPolicy{
-		Name:              "",
-		MaximumRetryCount: 0,
-	}
-	if len(m.Restart) > 0 {
-		rp.Name = m.Restart
-	}
-	res := container.Resources{}
-
-	if m.Memory > 0 {
-		res.Memory = m.Memory * 1024 * 1024
-		res.MemorySwap = -1
-	}
-	if m.CpuShares > 0 {
-		res.CPUShares = m.CpuShares
-	}
-	for _, p := range m.Devices {
-		res.Devices = append(res.Devices, container.DeviceMapping{PathOnHost: p.Path, PathInContainer: p.ContainerPath, CgroupPermissions: "rwm"})
-	}
-	_, err = cli.ContainerUpdate(context.Background(), id, container.UpdateConfig{RestartPolicy: rp, Resources: res})
-	if err != nil {
-		return err
-	}
-
-	return
-}
-
-// 更新容器名称
-// param name 容器名称
-// param id 老的容器名称
-func (ds *dockerService) DockerContainerUpdateName(name, id string) (err error) {
-	cli, err := client2.NewClientWithOpts(client2.FromEnv)
-	if err != nil {
-		return err
-	}
-	defer cli.Close()
-
-	err = cli.ContainerRename(context.Background(), id, name)
-	if err != nil {
-		return err
-	}
-	return
-}
-
-// 获取网络列表
-func (ds *dockerService) DockerNetworkModelList() []types.NetworkResource {
-
-	cli, _ := client2.NewClientWithOpts(client2.FromEnv)
-	defer cli.Close()
-	networks, _ := cli.NetworkList(context.Background(), types.NetworkListOptions{})
-	return networks
-}
-func NewDockerService() DockerService {
-	return &dockerService{rootDir: command2.ExecResultStr(`source ./shell/helper.sh ;GetDockerRootDir`)}
-}
-
-func (ds *dockerService) GetDockerInfo() (types.Info, error) {
-	cli, err := client2.NewClientWithOpts(client2.FromEnv)
-	if err != nil {
-		return types.Info{}, err
-	}
-	defer cli.Close()
-
-	return cli.Info(context.Background())
-
-}
-
-//   ---------------------------------------test------------------------------------
-//func ServiceCreate() {
-//	cli, err := client2.NewClientWithOpts(client2.FromEnv)
-//	r, err := cli.ServiceCreate(context.Background(), swarm.ServiceSpec{}, types.ServiceCreateOptions{})
-//	if err != nil {
-//		fmt.Println("error", err)
-//	}
-//
-//
-//}
-
-// func Containerd() {
-// 	// create a new client connected to the default socket path for containerd
-// 	cli, err := containerd.New("/run/containerd/containerd.sock")
-// 	if err != nil {
-// 		fmt.Println("111")
-// 		fmt.Println(err)
-// 	}
-// 	defer cli.Close()
-
-// 	// create a new context with an "example" namespace
-// 	ctx := namespaces.WithNamespace(context.Background(), "default")
-
-// 	// pull the redis image from DockerHub
-// 	image, err := cli.Pull(ctx, "docker.io/library/busybox:latest", containerd.WithPullUnpack)
-// 	if err != nil {
-// 		fmt.Println("222")
-// 		fmt.Println(err)
-// 	}
-
-// 	// create a container
-// 	container, err := cli.NewContainer(
-// 		ctx,
-// 		"test1",
-// 		containerd.WithImage(image),
-// 		containerd.WithNewSnapshot("redis-server-snapshot1", image),
-// 		containerd.WithNewSpec(oci.WithImageConfig(image)),
-// 	)
-
-// 	if err != nil {
-// 		fmt.Println(err)
-// 	}
-// 	defer container.Delete(ctx, containerd.WithSnapshotCleanup)
-
-// 	// create a task from the container
-// 	task, err := container.NewTask(ctx, cio.NewCreator(cio.WithStdio))
-// 	if err != nil {
-// 		fmt.Println(err)
-// 	}
-// 	defer task.Delete(ctx)
-
-// 	// make sure we wait before calling start
-// 	exitStatusC, err := task.Wait(ctx)
-// 	if err != nil {
-// 		fmt.Println(err)
-// 	}
-
-// 	// call start on the task to execute the redis server
-// 	if err = task.Start(ctx); err != nil {
-// 		fmt.Println(err)
-// 	}
-
-// 	fmt.Println("执行完成等待")
-// 	// sleep for a lil bit to see the logs
-// 	time.Sleep(3 * time.Second)
-
-// 	// kill the process and get the exit status
-// 	if err = task.Kill(ctx, syscall.SIGTERM); err != nil {
-// 		fmt.Println(err)
-// 	}
-
-// 	// wait for the process to fully exit and print out the exit status
-
-// 	status := <-exitStatusC
-// 	code, _, err := status.Result()
-// 	if err != nil {
-// 		fmt.Println(err)
-// 	}
-// 	fmt.Printf("redis-server exited with status: %d\n", code)
-
-// }

+ 0 - 24
service/docker_base/common.go

@@ -1,24 +0,0 @@
-package docker_base
-
-import "github.com/IceWhaleTech/CasaOS/model"
-
-//过滤mysql关键字
-func MysqlFilter(c MysqlConfig, envs model.EnvArray) model.EnvArray {
-	for i := 0; i < len(envs); i++ {
-		switch envs[i].Value {
-		case "$MYSQL_HOST":
-			envs[i].Value = c.DataBaseHost
-		case "$MYSQL_PORT":
-			envs[i].Value = c.DataBasePort
-		case "$MYSQL_USERNAME":
-			envs[i].Value = c.DataBaseUser
-		case "$MYSQL_PASSWORD":
-			envs[i].Value = c.DataBasePassword
-		case "$MYSQL_DBNAME":
-			envs[i].Value = c.DataBaseDB
-		case "$MYSQL_HOST_AND_PORT":
-			envs[i].Value = c.DataBaseHost + ":" + c.DataBasePort
-		}
-	}
-	return envs
-}

+ 0 - 9
service/docker_base/model.go

@@ -1,9 +0,0 @@
-package docker_base
-
-type MysqlConfig struct {
-	DataBaseHost     string `json:"database_host"`
-	DataBasePort     string `json:"database_port"`
-	DataBaseUser     string `json:"database_user"`
-	DataBasePassword string `json:"data_base_password"`
-	DataBaseDB       string `json:"data_base_db"`
-}

+ 0 - 93
service/docker_base/mysql.go

@@ -1,93 +0,0 @@
-package docker_base
-
-import (
-	"context"
-	"github.com/docker/docker/api/types"
-	"github.com/docker/docker/api/types/container"
-	"github.com/docker/docker/api/types/filters"
-	"github.com/docker/docker/api/types/network"
-	client2 "github.com/docker/docker/client"
-	"time"
-)
-
-//创建一个mysql数据库
-func MysqlCreate(mysqlConfig MysqlConfig, dbId string, cpuShares int64, memory int64) (string, error) {
-	const imageName = "mysql"
-	const imageVersion = "8"
-	const imageNet = "oasis"
-
-	cli, err := client2.NewClientWithOpts(client2.FromEnv)
-	if err != nil {
-		return "", err
-	}
-	defer cli.Close()
-	_, err = cli.ImagePull(context.Background(), imageName+":"+imageVersion, types.ImagePullOptions{})
-
-	isExist := true
-	//检查到镜像才继续
-	for isExist {
-		filter := filters.NewArgs()
-		filter.Add("before", imageName+":"+imageVersion)
-		list, e := cli.ImageList(context.Background(), types.ImageListOptions{Filters: filter})
-		if e == nil && len(list) > 0 {
-			isExist = false
-		}
-		time.Sleep(time.Second)
-	}
-
-	var envArr = []string{"MYSQL_ROOT_PASSWORD=" + mysqlConfig.DataBasePassword, "MYSQL_DATABASE=" + mysqlConfig.DataBaseDB}
-
-	res := container.Resources{}
-	if cpuShares > 0 {
-		res.CPUShares = cpuShares
-	}
-	if memory > 0 {
-		res.Memory = memory << 20
-	}
-
-	rp := container.RestartPolicy{}
-
-	rp.Name = "always"
-
-	config := &container.Config{
-		Image:  imageName,
-		Labels: map[string]string{"version": imageVersion, "author": "official"},
-		Env:    envArr,
-	}
-	hostConfig := &container.HostConfig{Resources: res, RestartPolicy: rp, NetworkMode: container.NetworkMode(imageNet)}
-
-	containerCreate, err := cli.ContainerCreate(context.Background(),
-		config,
-		hostConfig,
-		&network.NetworkingConfig{EndpointsConfig: map[string]*network.EndpointSettings{imageNet: {NetworkID: ""}}},
-		nil,
-		dbId)
-
-	containerId := containerCreate.ID
-
-	//启动容器
-	err = cli.ContainerStart(context.Background(), dbId, types.ContainerStartOptions{})
-	if err != nil {
-		return containerId, err
-	}
-
-	return containerId, nil
-
-}
-
-func MysqlDelete(dbId string) error {
-
-	cli, err := client2.NewClientWithOpts(client2.FromEnv)
-	if err != nil {
-		return err
-	}
-	defer cli.Close()
-	err = cli.ContainerStop(context.Background(), dbId, nil)
-	if err != nil {
-		return err
-	}
-
-	err = cli.ContainerRemove(context.Background(), dbId, types.ContainerRemoveOptions{})
-	return err
-
-}

+ 0 - 50
service/docker_test.go

@@ -1,50 +0,0 @@
-package service
-
-import (
-	"fmt"
-	"testing"
-)
-
-//func TestDockerImageInfo(t *testing.T) {
-//	//DockerImageInfo()
-//
-//	address, err := net.ResolveTCPAddr("tcp", fmt.Sprintf("%s:0", "0.0.0.0"))
-//	if err != nil {
-//		fmt.Println(0, err)
-//	}
-//
-//	listener, err := net.ListenTCP("tcp", address)
-//	if err != nil {
-//		fmt.Println(0, err)
-//	}
-//
-//	defer listener.Close()
-//	fmt.Println(listener.Addr().(*net.TCPAddr).Port, nil)
-//
-//}
-
-//func TestDockerNetwork(t *testing.T) {
-//	DockerNetwork()
-//}
-//
-//func TestDockerPull(t *testing.T) {
-//	DockerPull()
-//}
-//
-//func TestDockerLog(t *testing.T) {
-//	DockerLog()
-//}
-//func TestDockerLogs(t *testing.T) {
-//	DockerLogs()
-//}
-
-func TestDockerContainerStats(t *testing.T) {
-	fmt.Println(DockerContainerStats1())
-}
-
-//func TestDockerImageRemove(t *testing.T) {
-//	host, domain, tld := gotld.GetSubdomain("aaa.liru-05.top", 1)
-//	fmt.Println(host)
-//	fmt.Println(domain)
-//	fmt.Println(tld)
-//}

+ 4 - 6
service/file.go

@@ -19,9 +19,9 @@ import (
 	"sync"
 	"time"
 
+	"github.com/IceWhaleTech/CasaOS-Common/utils/logger"
 	"github.com/IceWhaleTech/CasaOS/model"
 	"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
-	"github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
 	"go.uber.org/zap"
 )
 
@@ -78,8 +78,8 @@ func (w *writer) Write(p []byte) (n int, err error) {
 		return w.w.Write(p)
 	}
 }
-func FileOperate(k string) {
 
+func FileOperate(k string) {
 	list, ok := FileQueue.Load(k)
 	if !ok {
 		return
@@ -103,10 +103,10 @@ func FileOperate(k string) {
 			}
 			err := os.Rename(v.From, temp.To+"/"+lastPath)
 			if err != nil {
-				loger.Error("file move error", zap.Any("err", err))
+				logger.Error("file move error", zap.Any("err", err))
 				err = file.MoveFile(v.From, temp.To+"/"+lastPath)
 				if err != nil {
-					loger.Error("MoveFile error", zap.Any("err", err))
+					logger.Error("MoveFile error", zap.Any("err", err))
 					continue
 				}
 
@@ -152,7 +152,6 @@ func CheckFileStatus() {
 			}
 			temp := item.(model.FileOperate)
 			for i := 0; i < len(temp.Item); i++ {
-
 				if !temp.Item[i].Finished {
 					size, err := file.GetFileOrDirSize(temp.To + "/" + filepath.Base(temp.Item[i].From))
 					if err != nil {
@@ -166,7 +165,6 @@ func CheckFileStatus() {
 				} else {
 					total += temp.Item[i].ProcessedSize
 				}
-
 			}
 			temp.ProcessedSize = total
 			FileQueue.Store(v, temp)

+ 0 - 78
service/model/o_container.go

@@ -1,78 +0,0 @@
-/*
- * @Author: LinkLeong link@icewhale.com
- * @Date: 2022-05-13 18:15:46
- * @LastEditors: LinkLeong
- * @LastEditTime: 2022-07-13 10:56:34
- * @FilePath: /CasaOS/service/model/o_container.go
- * @Description:
- * @Website: https://www.casaos.io
- * Copyright (c) 2022 by icewhale, All Rights Reserved.
- */
-package model
-
-const CONTAINERTABLENAME = "o_container"
-
-//Soon to be removed
-type AppListDBModel struct {
-	CustomId string `gorm:"column:custom_id;primary_key" json:"custom_id"`
-	Title    string `json:"title"`
-	//	ScreenshotLink model.Strings `gorm:"type:json" json:"screenshot_link,omitempty"`
-	ScreenshotLink string `json:"screenshot_link"`
-	Slogan         string `json:"slogan"`
-	Description    string `json:"description"`
-	//Tags           model.Strings `gorm:"type:json" json:"tags"`
-	Tags        string `json:"tags"`
-	Icon        string `json:"icon"`
-	Version     string `json:"version"`
-	ContainerId string `json:"container_id,omitempty"`
-	Image       string `json:"image,omitempty"`
-	Index       string `json:"index"`
-	CreatedAt   string `gorm:"<-:create;autoCreateTime" json:"created_at"`
-	UpdatedAt   string `gorm:"<-:create;<-:update;autoUpdateTime" json:"updated_at"`
-	//Port           string           `json:"port,omitempty"`
-	PortMap    string `json:"port_map"`
-	Label      string `json:"label"`
-	EnableUPNP bool   `json:"enable_upnp"`
-	Envs       string `json:"envs"`
-	Ports      string `json:"ports"`
-	Volumes    string `json:"volumes"`
-	Devices    string `json:"devices"`
-	//Envs      []model.Env      `json:"envs"`
-	//Ports     []model.PortMap  `gorm:"type:json" json:"ports"`
-	//Volumes   []model.PathMap  `gorm:"type:json" json:"volumes"`
-	//Devices   []model.PathMap  `gorm:"type:json" json:"device"`
-	Position  bool   `json:"position"`
-	NetModel  string `json:"net_model"`
-	CpuShares int64  `json:"cpu_shares"`
-	Memory    int64  `json:"memory"`
-	Restart   string `json:"restart"`
-	//Rely      model.MapStrings `gorm:"type:json" json:"rely"` //[{"mysql":"id"},{"mysql":"id"}]
-	Origin     string `json:"origin"`
-	HostName   string `json:"host_name"`
-	Privileged bool   `json:"privileged"`
-	CapAdd     string `json:"cap_add"`
-	Cmd        string `gorm:"type:json" json:"cmd"`
-}
-
-func (p *AppListDBModel) TableName() string {
-	return "o_container"
-}
-
-type MyAppList struct {
-	Id       string `json:"id"`
-	Name     string `json:"name"`
-	Icon     string `json:"icon"`
-	State    string `json:"state"`
-	CustomId string `gorm:"column:custom_id;primary_key" json:"custom_id"`
-	Index    string `json:"index"`
-	//Order    string `json:"order"`
-	Port   string `json:"port"`
-	Slogan string `json:"slogan"`
-	Type   string `json:"type"`
-	//Rely       model.MapStrings `json:"rely"` //[{"mysql":"id"},{"mysql":"id"}]
-	Image    string `json:"image"`
-	Volumes  string `json:"volumes"`
-	Latest   bool   `json:"latest"`
-	Host     string `json:"host"`
-	Protocol string `json:"protocol"`
-}

+ 7 - 23
service/model/o_rely.go

@@ -1,33 +1,17 @@
 package model
 
 import (
-	"database/sql/driver"
-	"encoding/json"
-	"github.com/IceWhaleTech/CasaOS/service/docker_base"
 	"time"
 )
 
 type RelyDBModel struct {
-	Id                uint         `gorm:"column:id;primary_key" json:"id"`
-	CustomId          string       ` json:"custom_id"`
-	ContainerCustomId string       `json:"container_custom_id"`
-	Config            MysqlConfigs `json:"config"`
-	ContainerId       string       `json:"container_id,omitempty"`
-	Type              int          `json:"type"` //目前暂未使用
-	CreatedAt         time.Time    `gorm:"<-:create" json:"created_at"`
-	UpdatedAt         time.Time    `gorm:"<-:create;<-:update" json:"updated_at"`
-}
-
-/****************使gorm支持[]string结构*******************/
-type MysqlConfigs docker_base.MysqlConfig
-
-func (c MysqlConfigs) Value() (driver.Value, error) {
-	b, err := json.Marshal(c)
-	return string(b), err
-}
-
-func (c *MysqlConfigs) Scan(input interface{}) error {
-	return json.Unmarshal(input.([]byte), c)
+	Id                uint      `gorm:"column:id;primary_key" json:"id"`
+	CustomId          string    ` json:"custom_id"`
+	ContainerCustomId string    `json:"container_custom_id"`
+	ContainerId       string    `json:"container_id,omitempty"`
+	Type              int       `json:"type"` // 目前暂未使用
+	CreatedAt         time.Time `gorm:"<-:create" json:"created_at"`
+	UpdatedAt         time.Time `gorm:"<-:create;<-:update" json:"updated_at"`
 }
 
 /****************使gorm支持[]string结构*******************/

+ 18 - 15
service/notify.go

@@ -5,6 +5,7 @@ import (
 	"fmt"
 	"time"
 
+	notifyCommon "github.com/IceWhaleTech/CasaOS-Common/model/notify"
 	model2 "github.com/IceWhaleTech/CasaOS/model"
 	"github.com/IceWhaleTech/CasaOS/model/notify"
 	"github.com/IceWhaleTech/CasaOS/service/model"
@@ -15,24 +16,26 @@ import (
 	"gorm.io/gorm"
 )
 
-var NotifyMsg chan notify.Message
-var ClientCount int = 0
+var (
+	NotifyMsg   chan notify.Message
+	ClientCount int
+)
 
 type NotifyServer interface {
 	GetLog(id string) model.AppNotify
 	AddLog(log model.AppNotify)
 	UpdateLog(log model.AppNotify)
-	UpdateLogByCustomId(log model.AppNotify)
+	UpdateLogByCustomID(log model.AppNotify)
 	DelLog(id string)
 	GetList(c int) (list []model.AppNotify)
 	MarkRead(id string, state int)
 	//	SendText(m model.AppNotify)
-	SendUninstallAppBySocket(app notify.Application)
+	SendUninstallAppBySocket(app notifyCommon.Application)
 	SendNetInfoBySocket(netList []model2.IOCountersStat)
 	SendCPUInfoBySocket(cpu map[string]interface{})
 	SendMemInfoBySocket(mem map[string]interface{})
 	SendFileOperateNotify(nowSend bool)
-	SendInstallAppBySocket(app notify.Application)
+	SendInstallAppBySocket(app notifyCommon.Application)
 	SendAllHardwareStatusBySocket(mem map[string]interface{}, cpu map[string]interface{}, netList []model2.IOCountersStat)
 	SendStorageBySocket(message notify.StorageMessage)
 	SendNotify(path string, message map[string]interface{})
@@ -62,7 +65,6 @@ func (i *notifyServer) SendNotify(path string, message map[string]interface{}) {
 	notify.Msg = msg
 
 	NotifyMsg <- notify
-
 }
 
 func (i *notifyServer) SendStorageBySocket(message notify.StorageMessage) {
@@ -80,8 +82,8 @@ func (i *notifyServer) SendStorageBySocket(message notify.StorageMessage) {
 
 	NotifyMsg <- notify
 }
-func (i *notifyServer) SendAllHardwareStatusBySocket(mem map[string]interface{}, cpu map[string]interface{}, netList []model2.IOCountersStat) {
 
+func (i *notifyServer) SendAllHardwareStatusBySocket(mem map[string]interface{}, cpu map[string]interface{}, netList []model2.IOCountersStat) {
 	body := make(map[string]interface{})
 
 	body["sys_mem"] = mem
@@ -104,12 +106,10 @@ func (i *notifyServer) SendAllHardwareStatusBySocket(mem map[string]interface{},
 	notify.Msg = msg
 
 	NotifyMsg <- notify
-
 }
 
 // Send periodic broadcast messages
 func (i *notifyServer) SendFileOperateNotify(nowSend bool) {
-
 	if nowSend {
 
 		len := 0
@@ -259,7 +259,6 @@ func (i *notifyServer) SendFileOperateNotify(nowSend bool) {
 			time.Sleep(time.Second * 3)
 		}
 	}
-
 }
 
 func (i *notifyServer) SendMemInfoBySocket(mem map[string]interface{}) {
@@ -278,7 +277,7 @@ func (i *notifyServer) SendMemInfoBySocket(mem map[string]interface{}) {
 	NotifyMsg <- notify
 }
 
-func (i *notifyServer) SendInstallAppBySocket(app notify.Application) {
+func (i *notifyServer) SendInstallAppBySocket(app notifyCommon.Application) {
 	body := make(map[string]interface{})
 	body["data"] = app
 
@@ -309,6 +308,7 @@ func (i *notifyServer) SendCPUInfoBySocket(cpu map[string]interface{}) {
 
 	NotifyMsg <- notify
 }
+
 func (i *notifyServer) SendNetInfoBySocket(netList []model2.IOCountersStat) {
 	body := make(map[string]interface{})
 	body["data"] = netList
@@ -325,7 +325,7 @@ func (i *notifyServer) SendNetInfoBySocket(netList []model2.IOCountersStat) {
 	NotifyMsg <- notify
 }
 
-func (i *notifyServer) SendUninstallAppBySocket(app notify.Application) {
+func (i *notifyServer) SendUninstallAppBySocket(app notifyCommon.Application) {
 	body := make(map[string]interface{})
 	body["data"] = app
 
@@ -358,17 +358,20 @@ func (i *notifyServer) AddLog(log model.AppNotify) {
 func (i *notifyServer) UpdateLog(log model.AppNotify) {
 	i.db.Save(&log)
 }
-func (i *notifyServer) UpdateLogByCustomId(log model.AppNotify) {
+
+func (i *notifyServer) UpdateLogByCustomID(log model.AppNotify) {
 	if len(log.CustomId) == 0 {
 		return
 	}
 	i.db.Model(&model.AppNotify{}).Select("*").Where("custom_id = ? ", log.CustomId).Updates(log)
 }
+
 func (i *notifyServer) GetLog(id string) model.AppNotify {
 	var log model.AppNotify
 	i.db.Where("custom_id = ? ", id).First(&log)
 	return log
 }
+
 func (i *notifyServer) MarkRead(id string, state int) {
 	if id == "0" {
 		i.db.Model(&model.AppNotify{}).Where("1 = ?", 1).Update("state", state)
@@ -376,6 +379,7 @@ func (i *notifyServer) MarkRead(id string, state int) {
 	}
 	i.db.Model(&model.AppNotify{}).Where("id = ? ", id).Update("state", state)
 }
+
 func (i *notifyServer) DelLog(id string) {
 	var log model.AppNotify
 	i.db.Where("custom_id = ?", id).Delete(&log)
@@ -444,10 +448,9 @@ func SendMeg() {
 
 // }
 func (i *notifyServer) GetSystemTempMap() map[string]interface{} {
-
 	return i.SystemTempMap
-
 }
+
 func NewNotifyService(db *gorm.DB) NotifyServer {
 	return &notifyServer{db: db, SystemTempMap: make(map[string]interface{})}
 }

+ 8 - 20
service/service.go

@@ -21,14 +21,13 @@ var Cache *cache.Cache
 
 var MyService Repository
 
-var WebSocketConns []*websocket.Conn
-var NewVersionApp map[string]string
-var SocketRun bool
+var (
+	WebSocketConns []*websocket.Conn
+	SocketRun      bool
+)
 
 type Repository interface {
-	App() AppService
-	//User() UserService
-	Docker() DockerService
+	// User() UserService
 	Casa() CasaService
 	Notify() NotifyServer
 	Rely() RelyService
@@ -39,7 +38,6 @@ type Repository interface {
 }
 
 func NewService(db *gorm.DB, RuntimePath string) Repository {
-
 	gatewayManagement, err := external.NewManagementService(RuntimePath)
 	if err != nil && len(RuntimePath) > 0 {
 		panic(err)
@@ -47,8 +45,6 @@ func NewService(db *gorm.DB, RuntimePath string) Repository {
 
 	return &store{
 		gateway:     gatewayManagement,
-		app:         NewAppService(db),
-		docker:      NewDockerService(),
 		casa:        NewCasaService(),
 		notify:      NewNotifyService(db),
 		rely:        NewRelyService(db),
@@ -60,8 +56,6 @@ func NewService(db *gorm.DB, RuntimePath string) Repository {
 
 type store struct {
 	db          *gorm.DB
-	app         AppService
-	docker      DockerService
 	casa        CasaService
 	notify      NotifyServer
 	rely        RelyService
@@ -74,9 +68,11 @@ type store struct {
 func (c *store) Gateway() external.ManagementService {
 	return c.gateway
 }
+
 func (s *store) Connections() ConnectionsService {
 	return s.connections
 }
+
 func (s *store) Shares() SharesService {
 	return s.shares
 }
@@ -88,19 +84,11 @@ func (c *store) Rely() RelyService {
 func (c *store) System() SystemService {
 	return c.system
 }
-func (c *store) Notify() NotifyServer {
 
+func (c *store) Notify() NotifyServer {
 	return c.notify
 }
 
-func (c *store) App() AppService {
-	return c.app
-}
-
-func (c *store) Docker() DockerService {
-	return c.docker
-}
-
 func (c *store) Casa() CasaService {
 	return c.casa
 }

+ 9 - 8
service/system.go

@@ -12,12 +12,12 @@ import (
 	"strings"
 	"time"
 
+	"github.com/IceWhaleTech/CasaOS-Common/utils/logger"
 	"github.com/IceWhaleTech/CasaOS/model"
 	"github.com/IceWhaleTech/CasaOS/pkg/config"
 	command2 "github.com/IceWhaleTech/CasaOS/pkg/utils/command"
 	"github.com/IceWhaleTech/CasaOS/pkg/utils/common_err"
 	"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
-	"github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
 	"github.com/shirou/gopsutil/v3/cpu"
 	"github.com/shirou/gopsutil/v3/disk"
 	"github.com/shirou/gopsutil/v3/host"
@@ -66,6 +66,7 @@ func (c *systemService) GetMacAddress() (string, error) {
 	inter := interfaces[0]
 	return inter.HardwareAddr, nil
 }
+
 func (c *systemService) MkdirAll(path string) (int, error) {
 	_, err := os.Stat(path)
 	if err == nil {
@@ -227,15 +228,15 @@ func (s *systemService) UpdateSystemVersion(version string) {
 		os.Remove(config.AppInfo.LogPath + "/upgrade.log")
 	}
 	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/LinkLeong/casaos-alpha/main/update.sh | bash")
 	if len(config.ServerInfo.UpdateUrl) > 0 {
 		go command2.OnlyExec("curl -fsSL " + config.ServerInfo.UpdateUrl + " | bash")
 	} else {
 		go command2.OnlyExec("curl -fsSL https://get.casaos.io/update | 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))
+	// s.log.Error(config.AppInfo.ProjectPath + "/shell/tool.sh -r " + version)
+	// s.log.Error(command2.ExecResultStr(config.AppInfo.ProjectPath + "/shell/tool.sh -r " + version))
 }
 
 func (s *systemService) UpdateAssist() {
@@ -328,17 +329,17 @@ func GetCPUThermalZone() string {
 			name = strings.TrimSuffix(string(file.ReadFullFile(path+"/type")), "\n")
 			for _, s := range cpu_types {
 				if strings.HasPrefix(name, s) {
-					loger.Info(fmt.Sprintf("CPU thermal zone found: %s, path: %s.", name, path))
+					logger.Info(fmt.Sprintf("CPU thermal zone found: %s, path: %s.", name, path))
 					Cache.SetDefault(keyName, path)
 					return path
 				}
 			}
 		} else {
-			if len(name) > 0 { //proves at least one zone
-				loger.Warn("CPU thermal zone not matched. Default to thermal_zone0.")
+			if len(name) > 0 { // proves at least one zone
+				logger.Info("CPU thermal zone not matched. Default to thermal_zone0.")
 				path = stub + "0"
 			} else {
-				loger.Error("No CPU thermal zones found. CPU temp will not be displayed.")
+				logger.Error("No CPU thermal zones found. CPU temp will not be displayed.")
 				path = ""
 			}
 			break

+ 1 - 1
types/system.go

@@ -19,6 +19,6 @@
  */
 package types
 
-const CURRENTVERSION = "0.3.8"
+const CURRENTVERSION = "0.4.0"
 
 const BODY = " "

Algúns arquivos non se mostraron porque demasiados arquivos cambiaron neste cambio