Compare commits

...

8 Commits

Author SHA1 Message Date
link
f020c1162d Fixing bugs
Resolve application installation path errors
2021-11-09 18:57:50 +08:00
link
37130966cf update ui 2021-11-04 16:03:33 +08:00
link
a6ceee7bc0 update ui 2021-11-03 19:05:41 +08:00
link
a5fee0ee97 New App Store
Add App Store for installation
Fix favicon display in dark mode
2021-11-03 17:07:46 +08:00
link
cad7af13af Update UI 2021-10-29 19:35:51 +08:00
link
2ed372b3cd Update system.go 2021-10-29 18:39:07 +08:00
link
8bca76b78b Add new features
add casaOS logs
add application  terminal
add application  logs
2021-10-29 18:37:27 +08:00
link
4939fe10aa update disk display
add casaos logs api
update ui
2021-10-27 19:03:59 +08:00
38 changed files with 793 additions and 274 deletions

2
UI

Submodule UI updated: 574be529e2...741aadb011

2
go.mod
View File

@@ -15,7 +15,6 @@ require (
github.com/forease/gotld v0.0.0-20190808124948-c50ff635576b github.com/forease/gotld v0.0.0-20190808124948-c50ff635576b
github.com/gin-contrib/gzip v0.0.2 // indirect github.com/gin-contrib/gzip v0.0.2 // indirect
github.com/gin-gonic/gin v1.7.2 github.com/gin-gonic/gin v1.7.2
github.com/gliderlabs/ssh v0.3.3
github.com/go-ini/ini v1.62.0 github.com/go-ini/ini v1.62.0
github.com/go-ole/go-ole v1.2.5 // indirect github.com/go-ole/go-ole v1.2.5 // indirect
github.com/go-openapi/spec v0.20.4 // indirect github.com/go-openapi/spec v0.20.4 // indirect
@@ -37,6 +36,7 @@ require (
github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect
github.com/morikuni/aec v1.0.0 // indirect github.com/morikuni/aec v1.0.0 // indirect
github.com/opencontainers/selinux v1.8.5 // indirect github.com/opencontainers/selinux v1.8.5 // indirect
github.com/patrickmn/go-cache v2.1.0+incompatible
github.com/pkg/errors v0.9.1 github.com/pkg/errors v0.9.1
github.com/prestonTao/upnp v0.0.0-20150206124352-f4370df5e109 github.com/prestonTao/upnp v0.0.0-20150206124352-f4370df5e109
github.com/prometheus/procfs v0.7.3 // indirect github.com/prometheus/procfs v0.7.3 // indirect

7
go.sum
View File

@@ -94,8 +94,6 @@ github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRF
github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0= github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0=
github.com/andybalholm/cascadia v1.1.0 h1:BuuO6sSfQNFRu1LppgbD25Hr2vLYW25JvxHs5zzsLTo= github.com/andybalholm/cascadia v1.1.0 h1:BuuO6sSfQNFRu1LppgbD25Hr2vLYW25JvxHs5zzsLTo=
github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y= github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
@@ -313,8 +311,6 @@ github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/
github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
github.com/gin-gonic/gin v1.7.2 h1:Tg03T9yM2xa8j6I3Z3oqLaQRSmKvxPd6g/2HJ6zICFA= github.com/gin-gonic/gin v1.7.2 h1:Tg03T9yM2xa8j6I3Z3oqLaQRSmKvxPd6g/2HJ6zICFA=
github.com/gin-gonic/gin v1.7.2/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY= github.com/gin-gonic/gin v1.7.2/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY=
github.com/gliderlabs/ssh v0.3.3 h1:mBQ8NiOgDkINJrZtoizkC3nDNYgSaWtxyem6S2XHBtA=
github.com/gliderlabs/ssh v0.3.3/go.mod h1:ZSS+CUoKHDrqVakTfTWUlKSr9MtMFkC4UvtQKD7O914=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
@@ -632,6 +628,8 @@ github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3
github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8= github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8=
github.com/opencontainers/selinux v1.8.5 h1:OkT6bMHOQ1JQQO4ihjQ49sj0+wciDcjziSVTRn8VeTA= github.com/opencontainers/selinux v1.8.5 h1:OkT6bMHOQ1JQQO4ihjQ49sj0+wciDcjziSVTRn8VeTA=
github.com/opencontainers/selinux v1.8.5/go.mod h1:HTvjPFoGMbpQsG886e3lQwnsRWtE4TC1OF3OUvG9FAo= github.com/opencontainers/selinux v1.8.5/go.mod h1:HTvjPFoGMbpQsG886e3lQwnsRWtE4TC1OF3OUvG9FAo=
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc=
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
@@ -825,7 +823,6 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ= golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ=
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=

View File

@@ -6,11 +6,13 @@ import (
"net/http" "net/http"
"time" "time"
"github.com/IceWhaleTech/CasaOS/pkg/cache"
"github.com/IceWhaleTech/CasaOS/pkg/config" "github.com/IceWhaleTech/CasaOS/pkg/config"
"github.com/IceWhaleTech/CasaOS/pkg/sqlite" "github.com/IceWhaleTech/CasaOS/pkg/sqlite"
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger" loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
"github.com/IceWhaleTech/CasaOS/route" "github.com/IceWhaleTech/CasaOS/route"
"github.com/IceWhaleTech/CasaOS/service" "github.com/IceWhaleTech/CasaOS/service"
"github.com/robfig/cron" "github.com/robfig/cron"
"gorm.io/gorm" "gorm.io/gorm"
) )
@@ -29,6 +31,8 @@ func init() {
sqliteDB = sqlite.GetDb(config.AppInfo.ProjectPath) sqliteDB = sqlite.GetDb(config.AppInfo.ProjectPath)
//gredis.GetRedisConn(config.RedisInfo), //gredis.GetRedisConn(config.RedisInfo),
service.MyService = service.NewService(sqliteDB, loger2.NewOLoger()) service.MyService = service.NewService(sqliteDB, loger2.NewOLoger())
service.Cache = cache.Init()
route.InitFunction()
} }
// @title casaOS API // @title casaOS API

View File

@@ -7,32 +7,35 @@ import (
) )
type ServerAppList struct { type ServerAppList struct {
Id uint `gorm:"column:id;primary_key" json:"id"` Id uint `gorm:"column:id;primary_key" json:"id"`
Title string `json:"title"` Title string `json:"title"`
Description string `json:"description"` Description string `json:"description"`
Tagline string `json:"tagline"` Tagline string `json:"tagline"`
Tags Strings `gorm:"type:json" json:"tags"` Tags Strings `gorm:"type:json" json:"tags"`
Icon string `json:"icon"` Icon string `json:"icon"`
ScreenshotLink Strings `gorm:"type:json" json:"screenshot_link"` ScreenshotLink Strings `gorm:"type:json" json:"screenshot_link"`
Category string `json:"category"` Category string `json:"category"`
TcpPort uint `json:"tcp_port"` PortMap string `json:"port_map"`
PortMap uint `json:"port_map"` ImageVersion string `json:"image_version"`
ImageVersion string `json:"image_version"` Tip string `json:"tip"`
Tip string `json:"tip"` Envs EnvArray `json:"envs"`
Configures configures `gorm:"type:json" json:"configures"` Ports PortArray `json:"ports"`
NetworkModel string `json:"network_mode"` Volumes PathArray `json:"volumes"`
Image string `json:"image"` Devices PathArray `json:"devices"`
Index string `json:"index"` NetworkModel string `json:"network_model"`
CreatedAt time.Time `json:"created_at"` Image string `json:"image"`
UpdatedAt time.Time `json:"updated_at"` Index string `json:"index"`
State string `json:"state"` CreatedAt time.Time `json:"created_at"`
Author string `json:"author"` UpdatedAt time.Time `json:"updated_at"`
MinMemory int `json:"min_memory"` State string `json:"state"`
MinDisk int `json:"min_disk"` Author string `json:"author"`
MaxMemory uint64 `json:"max_memory"` MinMemory int `json:"min_memory"`
Thumbnail string `json:"thumbnail"` MinDisk int `json:"min_disk"`
Healthy string `json:"healthy"` MaxMemory uint64 `json:"max_memory"`
Plugins Strings `json:"plugins"` Thumbnail string `json:"thumbnail"`
Healthy string `json:"healthy"`
Plugins Strings `json:"plugins"`
Origin string `json:"origin"`
} }
type Ports struct { type Ports struct {

View File

@@ -17,20 +17,22 @@ type UdpPorts struct {
/*******************使用gorm支持json************************************/ /*******************使用gorm支持json************************************/
type PortMap struct { type PortMap struct {
ContainerPort string `json:"container,omitempty"` ContainerPort string `json:"container"`
CommendPort string `json:"host,omitempty"` CommendPort string `json:"host"`
Protocol string `json:"protocol"` Protocol string `json:"protocol"`
Desc string `json:"desc"`
Type int `json:"type"`
} }
type PortArrey []PortMap type PortArray []PortMap
// Value 实现方法 // Value 实现方法
func (p PortArrey) Value() (driver.Value, error) { func (p PortArray) Value() (driver.Value, error) {
return json.Marshal(p) return json.Marshal(p)
} }
// Scan 实现方法 // Scan 实现方法
func (p *PortArrey) Scan(input interface{}) error { func (p *PortArray) Scan(input interface{}) error {
return json.Unmarshal(input.([]byte), p) return json.Unmarshal(input.([]byte), p)
} }
@@ -41,20 +43,22 @@ func (p *PortArrey) Scan(input interface{}) error {
type Env struct { type Env struct {
Name string `json:"container"` Name string `json:"container"`
Value string `json:"host"` Value string `json:"host"`
Desc string `json:"desc"`
Type int `json:"type"`
} }
type JSON json.RawMessage type JSON json.RawMessage
type EnvArrey []Env type EnvArray []Env
// Value 实现方法 // Value 实现方法
func (p EnvArrey) Value() (driver.Value, error) { func (p EnvArray) Value() (driver.Value, error) {
return json.Marshal(p) return json.Marshal(p)
//return .MarshalJSON() //return .MarshalJSON()
} }
// Scan 实现方法 // Scan 实现方法
func (p *EnvArrey) Scan(input interface{}) error { func (p *EnvArray) Scan(input interface{}) error {
return json.Unmarshal(input.([]byte), p) return json.Unmarshal(input.([]byte), p)
} }
@@ -65,17 +69,19 @@ func (p *EnvArrey) Scan(input interface{}) error {
type PathMap struct { type PathMap struct {
ContainerPath string `json:"container"` ContainerPath string `json:"container"`
Path string `json:"host"` Path string `json:"host"`
Type int `json:"type"`
Desc string `json:"desc"`
} }
type PathArrey []PathMap type PathArray []PathMap
// Value 实现方法 // Value 实现方法
func (p PathArrey) Value() (driver.Value, error) { func (p PathArray) Value() (driver.Value, error) {
return json.Marshal(p) return json.Marshal(p)
} }
// Scan 实现方法 // Scan 实现方法
func (p *PathArrey) Scan(input interface{}) error { func (p *PathArray) Scan(input interface{}) error {
return json.Unmarshal(input.([]byte), p) return json.Unmarshal(input.([]byte), p)
} }
@@ -103,10 +109,10 @@ type CustomizationPostData struct {
Index string `json:"index"` Index string `json:"index"`
Icon string `json:"icon"` Icon string `json:"icon"`
Image string `json:"image"` Image string `json:"image"`
Envs EnvArrey `json:"envs"` Envs EnvArray `json:"envs"`
Ports PortArrey `json:"ports"` Ports PortArray `json:"ports"`
Volumes PathArrey `json:"volumes"` Volumes PathArray `json:"volumes"`
Devices PathArrey `json:"devices"` Devices PathArray `json:"devices"`
//Port string `json:"port,omitempty"` //Port string `json:"port,omitempty"`
PortMap string `json:"port_map"` PortMap string `json:"port_map"`
CpuShares int64 `json:"cpu_shares"` CpuShares int64 `json:"cpu_shares"`

View File

@@ -64,4 +64,6 @@ type SystemConfig struct {
ConfigStr string `json:"config_str"` ConfigStr string `json:"config_str"`
WidgetList string `json:"widget_list"` WidgetList string `json:"widget_list"`
ConfigPath string `json:"config_path"` ConfigPath string `json:"config_path"`
SyncPort string `json:"sync_port"`
SyncKey string `json:"sync_key"`
} }

8
model/system_app/sync.go Normal file
View File

@@ -0,0 +1,8 @@
package system_app
import "encoding/xml"
type SyncConfig struct {
XMLName xml.Name `xml:"configuration"`
Key string `xml:"gui>apikey"`
}

11
pkg/cache/cache.go vendored Normal file
View File

@@ -0,0 +1,11 @@
package cache
import (
"time"
"github.com/patrickmn/go-cache"
)
func Init() *cache.Cache {
return cache.New(5*time.Minute, 60*time.Second)
}

View File

@@ -1,10 +1,29 @@
package docker package docker
import "strings"
func GetDir(id, envName string) string { func GetDir(id, envName string) string {
var path string var path string
switch envName {
case "/config": if len(id) == 0 {
path = "/oasis/app_data/" + id + "/" id = "$AppID"
}
switch {
case strings.Contains(strings.ToLower(envName), "config") || strings.Contains(strings.ToLower(envName), "photoprism/storage") || strings.Contains(strings.ToLower(envName), "config"):
path = "/DATA/AppData/" + id + "/"
case strings.Contains(strings.ToLower(envName), "movie"):
path = "/DATA/Media/Movies/"
case strings.Contains(strings.ToLower(envName), "music"):
path = "/DATA/Media/Music/"
case strings.Contains(strings.ToLower(envName), "photoprism/originals"):
path = "/DATA/Gallery"
case strings.Contains(strings.ToLower(envName), "download"):
path = "/DATA/Downloads/"
case strings.Contains(strings.ToLower(envName), "photo") || strings.Contains(strings.ToLower(envName), "pictures"):
path = "/DATA/Downloads/"
case strings.ToLower(envName) == "/srv":
path = "/DATA/"
default: default:
//path = "/media" //path = "/media"
} }

View File

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

View File

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

View File

@@ -50,6 +50,7 @@ func MkDir(src string) error {
if err != nil { if err != nil {
return err return err
} }
os.Chmod(src, 0777)
return nil return nil
} }
@@ -145,3 +146,16 @@ func IsNotExistCreateFile(src string) error {
return nil return nil
} }
func ReadFullFile(path string) []byte {
file, err := os.Open(path)
if err != nil {
return []byte("")
}
defer file.Close()
content, err := ioutil.ReadAll(file)
if err != nil {
return []byte("")
}
return content
}

View File

@@ -3,12 +3,13 @@ package httper
import ( import (
"bytes" "bytes"
"encoding/json" "encoding/json"
"github.com/IceWhaleTech/CasaOS/pkg/config"
"github.com/tidwall/gjson"
"io" "io"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"time" "time"
"github.com/IceWhaleTech/CasaOS/pkg/config"
"github.com/tidwall/gjson"
) )
//发送GET请求 //发送GET请求

View File

@@ -47,6 +47,7 @@ func IsPortAvailable(port int, t string) bool {
uc, err := net.ListenUDP("udp", sadd) uc, err := net.ListenUDP("udp", sadd)
if err != nil { if err != nil {
fmt.Println(err.Error())
return false return false
} else { } else {
defer uc.Close() defer uc.Close()

View File

@@ -1,8 +1,9 @@
package sort package sort
import ( import (
"github.com/IceWhaleTech/CasaOS/model"
"sort" "sort"
"github.com/IceWhaleTech/CasaOS/model"
) )
// 数据集类型, 与上一篇排序文章(多字段单独排序)比较, less字段的数据类型不再是 func(p1, p2 *Change) bool // 数据集类型, 与上一篇排序文章(多字段单独排序)比较, less字段的数据类型不再是 func(p1, p2 *Change) bool

188
route/init.go Normal file
View File

@@ -0,0 +1,188 @@
package route
import (
"encoding/json"
"encoding/xml"
"strconv"
"time"
"github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/model/system_app"
"github.com/IceWhaleTech/CasaOS/pkg/config"
"github.com/IceWhaleTech/CasaOS/pkg/docker"
"github.com/IceWhaleTech/CasaOS/pkg/utils/env_helper"
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
"github.com/IceWhaleTech/CasaOS/pkg/utils/port"
"github.com/IceWhaleTech/CasaOS/service"
model2 "github.com/IceWhaleTech/CasaOS/service/model"
uuid "github.com/satori/go.uuid"
)
func InitFunction() {
go checkSystemApp()
}
var syncIsExistence = false
func installSyncthing(appId string) {
var appInfo model.ServerAppList
m := model.CustomizationPostData{}
var dockerImage string
var dockerImageVersion string
appInfo = service.MyService.OAPI().GetServerAppInfo(appId)
dockerImage = appInfo.Image
if len(appInfo.ImageVersion) == 0 {
dockerImageVersion = "latest"
}
if appInfo.NetworkModel != "host" {
for i := 0; i < len(appInfo.Ports); i++ {
if p, _ := strconv.Atoi(appInfo.Ports[i].ContainerPort); port.IsPortAvailable(p, appInfo.Ports[i].Protocol) {
appInfo.Ports[i].CommendPort = strconv.Itoa(p)
} else {
if appInfo.Ports[i].Protocol == "tcp" {
if p, err := port.GetAvailablePort("tcp"); err == nil {
appInfo.Ports[i].CommendPort = strconv.Itoa(p)
}
} else if appInfo.Ports[i].Protocol == "upd" {
if p, err := port.GetAvailablePort("udp"); err == nil {
appInfo.Ports[i].CommendPort = strconv.Itoa(p)
}
}
}
if appInfo.Ports[i].Type == 0 {
appInfo.PortMap = appInfo.Ports[i].CommendPort
}
}
}
for i := 0; i < len(appInfo.Devices); i++ {
if !file.CheckNotExist(appInfo.Devices[i].ContainerPath) {
appInfo.Devices[i].Path = appInfo.Devices[i].ContainerPath
}
}
if len(appInfo.Tip) > 0 {
appInfo.Tip = env_helper.ReplaceStringDefaultENV(appInfo.Tip)
}
for i := 0; i < len(appInfo.Volumes); i++ {
appInfo.Volumes[i].Path = docker.GetDir("", appInfo.Volumes[i].ContainerPath)
}
appInfo.MaxMemory = service.MyService.ZiMa().GetMemInfo().Total >> 20
id := uuid.NewV4().String()
installLog := model2.AppNotify{}
// step下载镜像
err := service.MyService.Docker().DockerPullImage(dockerImage+":"+dockerImageVersion, installLog)
if err != nil {
//pull image error
return
}
for !service.MyService.Docker().IsExistImage(dockerImage + ":" + dockerImageVersion) {
time.Sleep(time.Second)
}
m.CpuShares = 50
m.Envs = appInfo.Envs
m.Memory = int64(appInfo.MaxMemory)
m.Origin = "system"
m.PortMap = appInfo.PortMap
m.Ports = appInfo.Ports
m.Restart = ""
m.Volumes = appInfo.Volumes
containerId, err := service.MyService.Docker().DockerContainerCreate(dockerImage+":"+dockerImageVersion, id, m, appInfo.NetworkModel)
if err != nil {
// create container error
return
}
//stepstart container
err = service.MyService.Docker().DockerContainerStart(id)
if err != nil {
//start container error
return
}
portsStr, _ := json.Marshal(appInfo.Ports)
envsStr, _ := json.Marshal(appInfo.Envs)
volumesStr, _ := json.Marshal(appInfo.Volumes)
devicesStr, _ := json.Marshal(appInfo.Devices)
//step: 保存数据到数据库
md := model2.AppListDBModel{
CustomId: id,
Title: appInfo.Title,
//ScreenshotLink: appInfo.ScreenshotLink,
Slogan: appInfo.Tagline,
Description: appInfo.Description,
//Tags: appInfo.Tags,
Icon: appInfo.Icon,
Version: dockerImageVersion,
ContainerId: containerId,
Image: dockerImage,
Index: appInfo.Index,
PortMap: appInfo.PortMap,
Label: appInfo.Title,
EnableUPNP: false,
Ports: string(portsStr),
Envs: string(envsStr),
Volumes: string(volumesStr),
Position: true,
NetModel: appInfo.NetworkModel,
Restart: m.Restart,
CpuShares: 50,
Memory: int64(appInfo.MaxMemory),
Devices: string(devicesStr),
Origin: m.Origin,
CreatedAt: strconv.FormatInt(time.Now().Unix(), 10),
UpdatedAt: strconv.FormatInt(time.Now().Unix(), 10),
}
service.MyService.App().SaveContainer(md)
checkSystemApp()
}
// check if the system application is installed
func checkSystemApp() {
list := service.MyService.App().GetSystemAppList()
for _, v := range *list {
if v.Image == "linuxserver/syncthing" {
syncIsExistence = true
if config.SystemConfigInfo.SyncPort != v.Port {
config.SystemConfigInfo.SyncPort = v.Port
}
var paths []model.PathMap
json.Unmarshal([]byte(v.Volumes), &paths)
path := ""
for _, i := range paths {
if i.ContainerPath == "/config" {
path = docker.GetDir(v.CustomId, i.ContainerPath) + "config.xml"
for i := 0; i < 10; i++ {
if file.CheckNotExist(path) {
time.Sleep(1 * time.Second)
} else {
break
}
}
break
}
}
content := file.ReadFullFile(path)
syncConfig := &system_app.SyncConfig{}
xml.Unmarshal(content, &syncConfig)
config.SystemConfigInfo.SyncKey = syncConfig.Key
}
}
if !syncIsExistence {
installSyncthing("44")
}
}

View File

@@ -37,6 +37,7 @@ func InitRouter() *gin.Engine {
r.POST("/v1/user/setusernamepwd", v1.Set_Name_Pwd) r.POST("/v1/user/setusernamepwd", v1.Set_Name_Pwd)
//get user info //get user info
r.GET("/v1/user/info", v1.UserInfo) r.GET("/v1/user/info", v1.UserInfo)
v1Group := r.Group("/v1") v1Group := r.Group("/v1")
v1Group.Use(jwt2.JWT(swagHandler)) v1Group.Use(jwt2.JWT(swagHandler))
@@ -265,6 +266,7 @@ func InitRouter() *gin.Engine {
{ {
v1SearchGroup.GET("/search", v1.GetSearchList) v1SearchGroup.GET("/search", v1.GetSearchList)
} }
v1Group.GET("/sync/*url", v1.SyncToSyncthing)
} }
return r return r
} }

View File

@@ -1,15 +1,17 @@
package v1 package v1
import ( import (
"net/http"
"strconv"
"github.com/IceWhaleTech/CasaOS/model" "github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/docker"
"github.com/IceWhaleTech/CasaOS/pkg/utils/env_helper"
"github.com/IceWhaleTech/CasaOS/pkg/utils/file" "github.com/IceWhaleTech/CasaOS/pkg/utils/file"
oasis_err2 "github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err" oasis_err2 "github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
port2 "github.com/IceWhaleTech/CasaOS/pkg/utils/port" port2 "github.com/IceWhaleTech/CasaOS/pkg/utils/port"
"github.com/IceWhaleTech/CasaOS/pkg/utils/sort"
"github.com/IceWhaleTech/CasaOS/service" "github.com/IceWhaleTech/CasaOS/service"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"net/http"
"strconv"
) )
// @Summary 获取远程列表 // @Summary 获取远程列表
@@ -110,51 +112,66 @@ func MyAppList(c *gin.Context) {
func AppInfo(c *gin.Context) { func AppInfo(c *gin.Context) {
id := c.Param("id") id := c.Param("id")
info := service.MyService.App().GetServerAppInfo(id) info := service.MyService.OAPI().GetServerAppInfo(id)
if info.NetworkModel != "host" { if info.NetworkModel != "host" {
port, _ := port2.GetAvailablePort("tcp") for i := 0; i < len(info.Ports); i++ {
info.PortMap = uint(port) if p, _ := strconv.Atoi(info.Ports[i].ContainerPort); port2.IsPortAvailable(p, info.Ports[i].Protocol) {
for i := 0; i < len(info.Configures.TcpPorts); i++ { info.Ports[i].CommendPort = strconv.Itoa(p)
info.Configures.TcpPorts[i].CommendPort, _ = port2.GetAvailablePort("tcp") } else {
} if info.Ports[i].Protocol == "tcp" {
for i := 0; i < len(info.Configures.UdpPorts); i++ { if p, err := port2.GetAvailablePort("tcp"); err == nil {
info.Configures.UdpPorts[i].CommendPort, _ = port2.GetAvailablePort("udp") info.Ports[i].CommendPort = strconv.Itoa(p)
} }
} else { } else if info.Ports[i].Protocol == "upd" {
info.PortMap = info.TcpPort if p, err := port2.GetAvailablePort("udp"); err == nil {
} info.Ports[i].CommendPort = strconv.Itoa(p)
}
}
}
for i := 0; i < len(info.Configures.Devices); i++ { if info.Ports[i].Type == 0 {
if !file.CheckNotExist(info.Configures.Devices[i].ContainerPath) { info.PortMap = info.Ports[i].CommendPort
info.Configures.Devices[i].Path = info.Configures.Devices[i].ContainerPath }
} }
} }
portOrder := func(c1, c2 *model.Ports) bool { for i := 0; i < len(info.Devices); i++ {
return c1.Type < c2.Type 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)
} }
envOrder := func(c1, c2 *model.Envs) bool { for i := 0; i < len(info.Volumes); i++ {
return c1.Type < c2.Type info.Volumes[i].Path = docker.GetDir("", info.Volumes[i].ContainerPath)
} }
// portOrder := func(c1, c2 *model.Ports) bool {
// return c1.Type < c2.Type
// }
volOrder := func(c1, c2 *model.Volume) bool { // envOrder := func(c1, c2 *model.Envs) bool {
return c1.Type < c2.Type // return c1.Type < c2.Type
} // }
devOrder := func(c1, c2 *model.Devices) bool { // volOrder := func(c1, c2 *model.Volume) bool {
return c1.Type < c2.Type // return c1.Type < c2.Type
} // }
// devOrder := func(c1, c2 *model.Devices) bool {
// return c1.Type < c2.Type
// }
//sort //sort
if info.NetworkModel != "host" { // if info.NetworkModel != "host" {
sort.PortsSort(portOrder).Sort(info.Configures.TcpPorts) // sort.PortsSort(portOrder).Sort(info.Configures.TcpPorts)
sort.PortsSort(portOrder).Sort(info.Configures.UdpPorts) // sort.PortsSort(portOrder).Sort(info.Configures.UdpPorts)
} // }
sort.EnvSort(envOrder).Sort(info.Configures.Envs) // sort.EnvSort(envOrder).Sort(info.Envs)
sort.VolSort(volOrder).Sort(info.Configures.Volumes) // sort.VolSort(volOrder).Sort(info.Volumes.([]model.PathMap))
sort.DevSort(devOrder).Sort(info.Configures.Devices) // sort.DevSort(devOrder).Sort(info.Devices)
info.MaxMemory = service.MyService.ZiMa().GetMemInfo().Total >> 20 info.MaxMemory = service.MyService.ZiMa().GetMemInfo().Total >> 20

View File

@@ -25,6 +25,7 @@ import (
"github.com/gorilla/websocket" "github.com/gorilla/websocket"
"github.com/jinzhu/copier" "github.com/jinzhu/copier"
uuid "github.com/satori/go.uuid" uuid "github.com/satori/go.uuid"
"github.com/tidwall/gjson"
"golang.org/x/crypto/ssh" "golang.org/x/crypto/ssh"
) )
@@ -172,7 +173,7 @@ func InstallApp(c *gin.Context) {
dockerImageVersion = "latest" dockerImageVersion = "latest"
} }
if m.Origin != "custom" { if m.Origin != "custom" {
appInfo = service.MyService.App().GetServerAppInfo(appId) appInfo = service.MyService.OAPI().GetServerAppInfo(appId)
} else { } else {
@@ -238,10 +239,9 @@ func InstallApp(c *gin.Context) {
var relyMap = make(map[string]string) var relyMap = make(map[string]string)
go func() { go func() {
installLog := model2.AppNotify{} installLog := model2.AppNotify{}
installLog.CustomId = id
installLog.State = 0 installLog.State = 0
installLog.CustomId = id
installLog.Message = "installing rely" installLog.Message = "installing rely"
installLog.Speed = 10
installLog.Type = types.NOTIFY_TYPE_UNIMPORTANT installLog.Type = types.NOTIFY_TYPE_UNIMPORTANT
installLog.CreatedAt = strconv.FormatInt(time.Now().Unix(), 10) installLog.CreatedAt = strconv.FormatInt(time.Now().Unix(), 10)
installLog.UpdatedAt = strconv.FormatInt(time.Now().Unix(), 10) installLog.UpdatedAt = strconv.FormatInt(time.Now().Unix(), 10)
@@ -279,16 +279,13 @@ func InstallApp(c *gin.Context) {
} else { } else {
docker_base.MysqlDelete(mysqlContainerId) docker_base.MysqlDelete(mysqlContainerId)
installLog.State = 0 installLog.State = 0
installLog.Speed = 30
installLog.Message = err.Error() installLog.Message = err.Error()
service.MyService.Notify().UpdateLog(installLog) service.MyService.Notify().UpdateLog(installLog)
} }
} }
} }
} }
installLog.Speed = 50
installLog.Message = "pulling" installLog.Message = "pulling"
service.MyService.Notify().UpdateLog(installLog) service.MyService.Notify().UpdateLog(installLog)
@@ -296,7 +293,6 @@ func InstallApp(c *gin.Context) {
err := service.MyService.Docker().DockerPullImage(dockerImage+":"+dockerImageVersion, installLog) err := service.MyService.Docker().DockerPullImage(dockerImage+":"+dockerImageVersion, installLog)
if err != nil { if err != nil {
installLog.State = 0 installLog.State = 0
installLog.Speed = 70
installLog.Message = err.Error() installLog.Message = err.Error()
installLog.Type = types.NOTIFY_TYPE_ERROR installLog.Type = types.NOTIFY_TYPE_ERROR
service.MyService.Notify().UpdateLog(installLog) service.MyService.Notify().UpdateLog(installLog)
@@ -323,35 +319,34 @@ func InstallApp(c *gin.Context) {
// return // return
// } // }
containerId, err := service.MyService.Docker().DockerContainerCreate(dockerImage+":"+dockerImageVersion, id, m, appInfo.NetworkModel) containerId, err := service.MyService.Docker().DockerContainerCreate(dockerImage+":"+dockerImageVersion, id, m, appInfo.NetworkModel)
installLog.ContainerId = containerId installLog.Name = appInfo.Title
installLog.Icon = appInfo.Icon
if err != nil { if err != nil {
//service.MyService.Redis().Set(id, "{\"id\"\""+id+"\",\"state\":false,\"message\":\""+err.Error()+"\",\"speed\":80}", 100) //service.MyService.Redis().Set(id, "{\"id\"\""+id+"\",\"state\":false,\"message\":\""+err.Error()+"\",\"speed\":80}", 100)
installLog.State = 0 installLog.State = 0
installLog.Speed = 80
installLog.Type = types.NOTIFY_TYPE_ERROR installLog.Type = types.NOTIFY_TYPE_ERROR
installLog.Message = err.Error() installLog.Message = err.Error()
service.MyService.Notify().UpdateLog(installLog) service.MyService.Notify().UpdateLog(installLog)
return return
} else { } else {
//service.MyService.Redis().Set(id, "{\"id\":\""+id+"\",\"state\":true,\"message\":\"starting\",\"speed\":80}", 100) //service.MyService.Redis().Set(id, "{\"id\":\""+id+"\",\"state\":true,\"message\":\"starting\",\"speed\":80}", 100)
installLog.Speed = 80
installLog.Message = "starting" installLog.Message = "starting"
service.MyService.Notify().UpdateLog(installLog) service.MyService.Notify().UpdateLog(installLog)
} }
// echo -e "hellow\nworld" >>
//step启动容器 //step启动容器
err = service.MyService.Docker().DockerContainerStart(id) err = service.MyService.Docker().DockerContainerStart(id)
if err != nil { if err != nil {
//service.MyService.Redis().Set(id, "{\"id\"\""+id+"\",\"state\":false,\"message\":\""+err.Error()+"\",\"speed\":90}", 100) //service.MyService.Redis().Set(id, "{\"id\"\""+id+"\",\"state\":false,\"message\":\""+err.Error()+"\",\"speed\":90}", 100)
installLog.State = 0 installLog.State = 0
installLog.Type = types.NOTIFY_TYPE_ERROR installLog.Type = types.NOTIFY_TYPE_ERROR
installLog.Speed = 90
installLog.Message = err.Error() installLog.Message = err.Error()
service.MyService.Notify().UpdateLog(installLog) service.MyService.Notify().UpdateLog(installLog)
return return
} else { } else {
//service.MyService.Redis().Set(id, "{\"id\":\""+id+"\",\"state\":true,\"message\":\"setting upnp\",\"speed\":90}", 100) //service.MyService.Redis().Set(id, "{\"id\":\""+id+"\",\"state\":true,\"message\":\"setting upnp\",\"speed\":90}", 100)
installLog.Speed = 90
if m.Origin != CUSTOM { if m.Origin != CUSTOM {
installLog.Message = "setting upnp" installLog.Message = "setting upnp"
} else { } else {
@@ -396,13 +391,11 @@ func InstallApp(c *gin.Context) {
if err != nil { if err != nil {
//service.MyService.Redis().Set(id, "{\"id\"\""+id+"\",\"state\":false,\"message\":\""+err.Error()+"\",\"speed\":95}", 100) //service.MyService.Redis().Set(id, "{\"id\"\""+id+"\",\"state\":false,\"message\":\""+err.Error()+"\",\"speed\":95}", 100)
installLog.State = 0 installLog.State = 0
installLog.Speed = 95
installLog.Type = types.NOTIFY_TYPE_ERROR installLog.Type = types.NOTIFY_TYPE_ERROR
installLog.Message = err.Error() installLog.Message = err.Error()
service.MyService.Notify().UpdateLog(installLog) service.MyService.Notify().UpdateLog(installLog)
} else { } else {
//service.MyService.Redis().Set(id, "{\"id\":\""+id+"\",\"state\":true,\"message\":\"checking\",\"speed\":95}", 100) //service.MyService.Redis().Set(id, "{\"id\":\""+id+"\",\"state\":true,\"message\":\"checking\",\"speed\":95}", 100)
installLog.Speed = 95
installLog.Message = "checking" installLog.Message = "checking"
service.MyService.Notify().UpdateLog(installLog) service.MyService.Notify().UpdateLog(installLog)
} }
@@ -414,14 +407,12 @@ func InstallApp(c *gin.Context) {
if err != nil && container.ContainerJSONBase.State.Running { if err != nil && container.ContainerJSONBase.State.Running {
//service.MyService.Redis().Set(id, "{\"id\"\""+id+"\",\"state\":false,\"message\":\""+err.Error()+"\",\"speed\":100}", 100) //service.MyService.Redis().Set(id, "{\"id\"\""+id+"\",\"state\":false,\"message\":\""+err.Error()+"\",\"speed\":100}", 100)
installLog.State = 0 installLog.State = 0
installLog.Speed = 100
installLog.Type = types.NOTIFY_TYPE_ERROR installLog.Type = types.NOTIFY_TYPE_ERROR
installLog.Message = err.Error() installLog.Message = err.Error()
service.MyService.Notify().UpdateLog(installLog) service.MyService.Notify().UpdateLog(installLog)
return return
} else { } else {
//service.MyService.Redis().Set(id, "{\"id\":\""+id+"\",\"state\":true,\"message\":\"installed\",\"speed\":100}", 100) //service.MyService.Redis().Set(id, "{\"id\":\""+id+"\",\"state\":true,\"message\":\"installed\",\"speed\":100}", 100)
installLog.Speed = 100
installLog.Message = "installed" installLog.Message = "installed"
service.MyService.Notify().UpdateLog(installLog) service.MyService.Notify().UpdateLog(installLog)
} }
@@ -697,7 +688,11 @@ func UnInstallApp(c *gin.Context) {
if info.Origin != "custom" { if info.Origin != "custom" {
//step: 删除文件夹 //step: 删除文件夹
service.MyService.App().DelAppConfigDir(appId) vol := gjson.Get(info.Volumes, "#.host")
for _, v := range vol.Array() {
service.MyService.App().DelAppConfigDir(appId, v.String())
}
//step: 删除install log //step: 删除install log
service.MyService.Notify().DelLog(appId) service.MyService.Notify().DelLog(appId)
@@ -802,7 +797,6 @@ func ContainerLog(c *gin.Context) {
func GetInstallSpeed(c *gin.Context) { func GetInstallSpeed(c *gin.Context) {
id := c.Param("id") id := c.Param("id")
b := service.MyService.Notify().GetLog(id) b := service.MyService.Notify().GetLog(id)
b.Id = b.CustomId
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: b}) c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: b})
} }
@@ -1132,16 +1126,20 @@ func ContainerUpdateInfo(c *gin.Context) {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: err.Error()}) c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: err.Error()})
return return
} }
var port model.PortArrey var port model.PortArray
json2.Unmarshal([]byte(appInfo.Ports), &port) json2.Unmarshal([]byte(appInfo.Ports), &port)
var envs model.EnvArrey var envs model.EnvArray
json2.Unmarshal([]byte(appInfo.Envs), &envs) json2.Unmarshal([]byte(appInfo.Envs), &envs)
var vol model.PathArrey var vol model.PathArray
json2.Unmarshal([]byte(appInfo.Volumes), &vol) json2.Unmarshal([]byte(appInfo.Volumes), &vol)
var dir model.PathArrey for i := 0; i < len(vol); i++ {
vol[i].Path = strings.ReplaceAll(vol[i].Path, "$AppID", appId)
}
var dir model.PathArray
json2.Unmarshal([]byte(appInfo.Devices), &dir) json2.Unmarshal([]byte(appInfo.Devices), &dir)
//volumesStr, _ := json2.Marshal(m.Volumes) //volumesStr, _ := json2.Marshal(m.Volumes)

22
route/v1/sync.go Normal file
View File

@@ -0,0 +1,22 @@
package v1
import (
"net/http/httputil"
"net/url"
"github.com/IceWhaleTech/CasaOS/pkg/config"
"github.com/gin-gonic/gin"
)
func SyncToSyncthing(c *gin.Context) {
u := c.Param("url")
target := "http://127.0.0.1:" + config.SystemConfigInfo.SyncPort
remote, err := url.Parse(target)
if err != nil {
return
}
proxy := httputil.NewSingleHostReverseProxy(remote)
c.Request.Header.Add("X-API-Key", config.SystemConfigInfo.SyncKey)
c.Request.URL.Path = u
proxy.ServeHTTP(c.Writer, c.Request)
}

View File

@@ -28,13 +28,12 @@ func CheckVersion(c *gin.Context) {
need, version := version.IsNeedUpdate() need, version := version.IsNeedUpdate()
if need { if need {
installLog := model2.AppNotify{} installLog := model2.AppNotify{}
installLog.CustomId = ""
installLog.State = 0 installLog.State = 0
installLog.Message = "New version " + version.Version + " is ready, ready to upgrade" installLog.Message = "New version " + version.Version + " is ready, ready to upgrade"
installLog.Speed = 100
installLog.Type = types.NOTIFY_TYPE_NEED_CONFIRM installLog.Type = types.NOTIFY_TYPE_NEED_CONFIRM
installLog.CreatedAt = strconv.FormatInt(time.Now().Unix(), 10) installLog.CreatedAt = strconv.FormatInt(time.Now().Unix(), 10)
installLog.UpdatedAt = strconv.FormatInt(time.Now().Unix(), 10) installLog.UpdatedAt = strconv.FormatInt(time.Now().Unix(), 10)
installLog.Name = "CasaOS System"
service.MyService.Notify().AddLog(installLog) service.MyService.Notify().AddLog(installLog)
} }
data := make(map[string]interface{}, 1) data := make(map[string]interface{}, 1)
@@ -69,7 +68,6 @@ func GetSystemConfig(c *gin.Context) {
// @Produce application/json // @Produce application/json
// @Accept application/json // @Accept application/json
// @Tags sys // @Tags sys
// @Param file query line false "get the number of log lines"
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Success 200 {string} string "ok" // @Success 200 {string} string "ok"
// @Router /sys/error/logs [get] // @Router /sys/error/logs [get]

View File

@@ -2,35 +2,32 @@ package service
import ( import (
"context" "context"
json2 "encoding/json" "strings"
"github.com/IceWhaleTech/CasaOS/model" "time"
"github.com/IceWhaleTech/CasaOS/pkg/config" "github.com/IceWhaleTech/CasaOS/pkg/config"
"github.com/IceWhaleTech/CasaOS/pkg/docker" "github.com/IceWhaleTech/CasaOS/pkg/docker"
"github.com/IceWhaleTech/CasaOS/pkg/utils/command" "github.com/IceWhaleTech/CasaOS/pkg/utils/command"
httper2 "github.com/IceWhaleTech/CasaOS/pkg/utils/httper"
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger" loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
model2 "github.com/IceWhaleTech/CasaOS/service/model" model2 "github.com/IceWhaleTech/CasaOS/service/model"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/filters" "github.com/docker/docker/api/types/filters"
client2 "github.com/docker/docker/client" client2 "github.com/docker/docker/client"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/tidwall/gjson"
"gorm.io/gorm" "gorm.io/gorm"
"strings"
"time"
) )
type AppService interface { type AppService interface {
GetMyList(index, size int, position bool) *[]model2.MyAppList GetMyList(index, size int, position bool) *[]model2.MyAppList
SaveContainer(m model2.AppListDBModel) SaveContainer(m model2.AppListDBModel)
GetServerAppInfo(id string) model.ServerAppList
GetUninstallInfo(id string) model2.AppListDBModel GetUninstallInfo(id string) model2.AppListDBModel
RemoveContainerById(id string) RemoveContainerById(id string)
GetContainerInfo(name string) (types.Container, error) GetContainerInfo(name string) (types.Container, error)
GetAppDBInfo(id string) model2.AppListDBModel GetAppDBInfo(id string) model2.AppListDBModel
UpdateApp(m model2.AppListDBModel) UpdateApp(m model2.AppListDBModel)
GetSimpleContainerInfo(name string) (types.Container, error) GetSimpleContainerInfo(name string) (types.Container, error)
DelAppConfigDir(id string) DelAppConfigDir(id, path string)
GetSystemAppList() *[]model2.MyAppList
} }
type appStruct struct { type appStruct struct {
@@ -56,7 +53,7 @@ func (a *appStruct) GetMyList(index, size int, position bool) *[]model2.MyAppLis
//获取本地数据库应用 //获取本地数据库应用
var lm []model2.AppListDBModel var lm []model2.AppListDBModel
a.db.Table(model2.CONTAINERTABLENAME).Select("title,icon,port_map,`index`,container_id,position,label,slogan").Find(&lm) a.db.Table(model2.CONTAINERTABLENAME).Select("title,icon,port_map,`index`,container_id,position,label,slogan,image").Find(&lm)
list := []model2.MyAppList{} list := []model2.MyAppList{}
lMap := make(map[string]interface{}) lMap := make(map[string]interface{})
@@ -69,6 +66,67 @@ func (a *appStruct) GetMyList(index, size int, position bool) *[]model2.MyAppLis
lMap[dbModel.ContainerId] = dbModel lMap[dbModel.ContainerId] = dbModel
} }
} }
for _, container := range containers {
if lMap[container.ID] != nil && container.Labels["origin"] != "system" {
var m model2.AppListDBModel
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
}
//system application list
func (a *appStruct) GetSystemAppList() *[]model2.MyAppList {
//获取docker应用
cli, err := client2.NewClientWithOpts(client2.FromEnv)
if err != nil {
a.log.Error("初始化client失败", "app.getmylist", "line:36", 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 {
a.log.Error("获取docker容器失败", "app.getmylist", "line:42", 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
}
for _, container := range containers { for _, container := range containers {
if lMap[container.ID] != nil { if lMap[container.ID] != nil {
@@ -93,7 +151,9 @@ func (a *appStruct) GetMyList(index, size int, position bool) *[]model2.MyAppLis
Port: m.PortMap, Port: m.PortMap,
Index: m.Index, Index: m.Index,
UpTime: tm, UpTime: tm,
Image: m.Image,
Slogan: m.Slogan, Slogan: m.Slogan,
Volumes: m.Volumes,
//Rely: m.Rely, //Rely: m.Rely,
}) })
} }
@@ -155,27 +215,6 @@ func (a *appStruct) GetUninstallInfo(id string) model2.AppListDBModel {
return m return m
} }
func (a *appStruct) GetServerAppInfo(id string) model.ServerAppList {
head := make(map[string]string)
t := make(chan string)
go func() {
str := httper2.Get(config.ServerInfo.ServerApi+"/token", nil)
t <- gjson.Get(str, "data").String()
}()
head["Authorization"] = <-t
infoS := httper2.Get(config.ServerInfo.ServerApi+"/v1/app/info/"+id, head)
info := model.ServerAppList{}
json2.Unmarshal([]byte(gjson.Get(infoS, "data").String()), &info)
return info
}
//创建容器成功后保存容器 //创建容器成功后保存容器
func (a *appStruct) SaveContainer(m model2.AppListDBModel) { func (a *appStruct) SaveContainer(m model2.AppListDBModel) {
a.db.Table(model2.CONTAINERTABLENAME).Create(&m) a.db.Table(model2.CONTAINERTABLENAME).Create(&m)
@@ -185,14 +224,20 @@ func (a *appStruct) UpdateApp(m model2.AppListDBModel) {
a.db.Table(model2.CONTAINERTABLENAME).Save(&m) a.db.Table(model2.CONTAINERTABLENAME).Save(&m)
} }
func (a *appStruct) DelAppConfigDir(id string) { func (a *appStruct) DelAppConfigDir(id, path string) {
command.OnlyExec("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;DelAppConfigDir " + docker.GetDir(id, "/config")) command.OnlyExec("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;DelAppConfigDir " + docker.GetDir(id, path))
} }
func (a *appStruct) RemoveContainerById(id string) { func (a *appStruct) RemoveContainerById(id string) {
a.db.Table(model2.CONTAINERTABLENAME).Where("custom_id = ?", id).Delete(&model2.AppListDBModel{}) a.db.Table(model2.CONTAINERTABLENAME).Where("custom_id = ?", id).Delete(&model2.AppListDBModel{})
} }
// init install
func Init() {
}
func NewAppService(db *gorm.DB, logger loger2.OLog) AppService { func NewAppService(db *gorm.DB, logger loger2.OLog) AppService {
Init()
return &appStruct{db: db, log: logger} return &appStruct{db: db, log: logger}
} }

View File

@@ -2,34 +2,29 @@ package service
import ( import (
json2 "encoding/json" json2 "encoding/json"
"strconv"
"github.com/IceWhaleTech/CasaOS/model" "github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/config" "github.com/IceWhaleTech/CasaOS/pkg/config"
httper2 "github.com/IceWhaleTech/CasaOS/pkg/utils/httper" httper2 "github.com/IceWhaleTech/CasaOS/pkg/utils/httper"
model2 "github.com/IceWhaleTech/CasaOS/service/model" model2 "github.com/IceWhaleTech/CasaOS/service/model"
"github.com/tidwall/gjson" "github.com/tidwall/gjson"
"strconv"
) )
type OasisService interface { type CasaService interface {
GetServerList(index, size, tp, categoryId, key string) ([]model.ServerAppList, int64) GetServerList(index, size, tp, categoryId, key string) ([]model.ServerAppList, int64)
GetServerCategoryList() []model.ServerCategoryList GetServerCategoryList() []model.ServerCategoryList
GetTaskList(size int) []model2.TaskDBModel GetTaskList(size int) []model2.TaskDBModel
GetServerAppInfo(id string) model.ServerAppList
} }
type oasisService struct { type casaService struct {
} }
func (o *oasisService) GetTaskList(size int) []model2.TaskDBModel { func (o *casaService) GetTaskList(size int) []model2.TaskDBModel {
head := make(map[string]string) head := make(map[string]string)
t := make(chan string) head["Authorization"] = GetToken()
go func() {
str := httper2.Get(config.ServerInfo.ServerApi+"/token", nil)
t <- gjson.Get(str, "data").String()
}()
head["Authorization"] = <-t
listS := httper2.Get(config.ServerInfo.ServerApi+"/v1/task/list/"+strconv.Itoa(size), head) listS := httper2.Get(config.ServerInfo.ServerApi+"/v1/task/list/"+strconv.Itoa(size), head)
@@ -39,18 +34,11 @@ func (o *oasisService) GetTaskList(size int) []model2.TaskDBModel {
return list return list
} }
func (o *oasisService) GetServerList(index, size, tp, categoryId, key string) ([]model.ServerAppList, int64) { func (o *casaService) GetServerList(index, size, tp, categoryId, key string) ([]model.ServerAppList, int64) {
head := make(map[string]string) head := make(map[string]string)
t := make(chan string) head["Authorization"] = GetToken()
go func() {
str := httper2.Get(config.ServerInfo.ServerApi+"/token", nil)
t <- gjson.Get(str, "data").String()
}()
head["Authorization"] = <-t
listS := httper2.Get(config.ServerInfo.ServerApi+"/v1/app/list?index="+index+"&size="+size+"&type="+tp+"&category_id="+categoryId+"&key="+key, head) listS := httper2.Get(config.ServerInfo.ServerApi+"/v1/app/list?index="+index+"&size="+size+"&type="+tp+"&category_id="+categoryId+"&key="+key, head)
@@ -62,18 +50,10 @@ func (o *oasisService) GetServerList(index, size, tp, categoryId, key string) ([
return list, count return list, count
} }
func (o *oasisService) GetServerCategoryList() []model.ServerCategoryList { func (o *casaService) GetServerCategoryList() []model.ServerCategoryList {
head := make(map[string]string) head := make(map[string]string)
head["Authorization"] = GetToken()
t := make(chan string)
go func() {
str := httper2.Get(config.ServerInfo.ServerApi+"/token", nil)
t <- gjson.Get(str, "data").String()
}()
head["Authorization"] = <-t
listS := httper2.Get(config.ServerInfo.ServerApi+"/v1/app/category", head) listS := httper2.Get(config.ServerInfo.ServerApi+"/v1/app/category", head)
@@ -83,7 +63,42 @@ func (o *oasisService) GetServerCategoryList() []model.ServerCategoryList {
return list return list
} }
func (o *casaService) GetServerAppInfo(id string) model.ServerAppList {
func NewOasisService() OasisService { head := make(map[string]string)
return &oasisService{}
head["Authorization"] = GetToken()
infoS := httper2.Get(config.ServerInfo.ServerApi+"/v1/app/info/"+id, head)
info := model.ServerAppList{}
json2.Unmarshal([]byte(gjson.Get(infoS, "data").String()), &info)
return info
}
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
}
func NewOasisService() CasaService {
return &casaService{}
} }

View File

@@ -3,14 +3,15 @@ package service
import ( import (
json2 "encoding/json" json2 "encoding/json"
"fmt" "fmt"
"strconv"
"strings"
"github.com/IceWhaleTech/CasaOS/model" "github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/config" "github.com/IceWhaleTech/CasaOS/pkg/config"
command2 "github.com/IceWhaleTech/CasaOS/pkg/utils/command" command2 "github.com/IceWhaleTech/CasaOS/pkg/utils/command"
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger" loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
"github.com/shirou/gopsutil/v3/disk" "github.com/shirou/gopsutil/v3/disk"
"github.com/tidwall/gjson" "github.com/tidwall/gjson"
"strconv"
"strings"
) )
type DiskService interface { type DiskService interface {

View File

@@ -7,6 +7,7 @@ import (
"encoding/binary" "encoding/binary"
json2 "encoding/json" json2 "encoding/json"
"fmt" "fmt"
"reflect"
"regexp" "regexp"
"syscall" "syscall"
@@ -20,6 +21,7 @@ import (
"github.com/IceWhaleTech/CasaOS/model" "github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/docker" "github.com/IceWhaleTech/CasaOS/pkg/docker"
command2 "github.com/IceWhaleTech/CasaOS/pkg/utils/command" 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/file"
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger" loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
@@ -60,6 +62,7 @@ type DockerService interface {
DockerNetworkModelList() []types.NetworkResource DockerNetworkModelList() []types.NetworkResource
DockerImageInfo(image string) DockerImageInfo(image string)
GetNetWorkNameByNetWorkID(id string) (string, error) GetNetWorkNameByNetWorkID(id string) (string, error)
ContainerExecShell(container_id string) string
} }
type dockerService struct { type dockerService struct {
@@ -67,15 +70,20 @@ type dockerService struct {
log loger2.OLog log loger2.OLog
} }
func DockerPs() { func (ds *dockerService) ContainerExecShell(container_id string) string {
cli, _ := client2.NewClientWithOpts(client2.FromEnv) cli, _ := client2.NewClientWithOpts(client2.FromEnv)
containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{}) exec, err := cli.ContainerExecCreate(context.Background(), container_id, types.ExecConfig{
User: "1000:1000",
Cmd: []string{"echo -e \"hellow\nworld\" >> /a.txt"},
})
if err != nil { if err != nil {
os.Exit(5) os.Exit(5)
} }
for _, container := range containers { err = cli.ContainerExecStart(context.Background(), exec.ID, types.ExecStartCheck{})
fmt.Printf("%s %s\n", container.ID[:10], container.Image) if err != nil {
fmt.Println("exec script error ", err)
} }
return exec.ID
} }
//创建默认网络 //创建默认网络
@@ -325,11 +333,13 @@ func (ds *dockerService) DockerPullImage(imageName string, m model2.AppNotify) e
} }
break break
} }
m.Type = types2.NOTIFY_TYPE_INSTALL_LOG if !reflect.DeepEqual(m, model2.AppNotify{}) {
m.State = 0 m.Type = types2.NOTIFY_TYPE_INSTALL_LOG
m.Speed = 70 m.State = 0
m.Message = string(buf[:n]) m.Message = string(buf[:n])
MyService.Notify().UpdateLog(m) MyService.Notify().UpdateLog(m)
}
} }
return err return err
} }
@@ -402,6 +412,10 @@ func (ds *dockerService) DockerContainerCreate(imageName string, containerDbId s
var envArr []string var envArr []string
for _, e := range m.Envs { for _, e := range m.Envs {
if strings.HasPrefix(e.Value, "$") {
envArr = append(envArr, e.Name+"="+env_helper.ReplaceDefaultENV(e.Value))
continue
}
if len(e.Value) > 0 { if len(e.Value) > 0 {
if e.Value == "port_map" { if e.Value == "port_map" {
envArr = append(envArr, e.Name+"="+m.PortMap) envArr = append(envArr, e.Name+"="+m.PortMap)
@@ -434,6 +448,7 @@ func (ds *dockerService) DockerContainerCreate(imageName string, containerDbId s
continue continue
} }
} }
path = strings.ReplaceAll(path, "$AppID", containerDbId)
reg1 := regexp.MustCompile(`([^<>/\\\|:""\*\?]+\.\w+$)`) reg1 := regexp.MustCompile(`([^<>/\\\|:""\*\?]+\.\w+$)`)
result1 := reg1.FindAllStringSubmatch(path, -1) result1 := reg1.FindAllStringSubmatch(path, -1)
if len(result1) == 0 { if len(result1) == 0 {
@@ -476,11 +491,12 @@ func (ds *dockerService) DockerContainerCreate(imageName string, containerDbId s
StartPeriod: 0, StartPeriod: 0,
Retries: 1000, Retries: 1000,
} }
fmt.Print(health)
config := &container.Config{ config := &container.Config{
Image: imageName, Image: imageName,
Labels: map[string]string{"origin": m.Origin, m.Origin: m.Origin}, Labels: map[string]string{"origin": m.Origin, m.Origin: m.Origin},
Env: envArr, Env: envArr,
Healthcheck: health, // Healthcheck: health,
} }
hostConfig := &container.HostConfig{Resources: res, Mounts: volumes, RestartPolicy: rp, NetworkMode: container.NetworkMode(net)} hostConfig := &container.HostConfig{Resources: res, Mounts: volumes, RestartPolicy: rp, NetworkMode: container.NetworkMode(net)}
//if net != "host" { //if net != "host" {
@@ -817,7 +833,6 @@ func Containerd() {
) )
if err != nil { if err != nil {
fmt.Println("333")
fmt.Println(err) fmt.Println(err)
} }
defer container.Delete(ctx, containerd.WithSnapshotCleanup) defer container.Delete(ctx, containerd.WithSnapshotCleanup)
@@ -825,7 +840,6 @@ func Containerd() {
// create a task from the container // create a task from the container
task, err := container.NewTask(ctx, cio.NewCreator(cio.WithStdio)) task, err := container.NewTask(ctx, cio.NewCreator(cio.WithStdio))
if err != nil { if err != nil {
fmt.Println("444")
fmt.Println(err) fmt.Println(err)
} }
defer task.Delete(ctx) defer task.Delete(ctx)
@@ -838,7 +852,6 @@ func Containerd() {
// call start on the task to execute the redis server // call start on the task to execute the redis server
if err = task.Start(ctx); err != nil { if err = task.Start(ctx); err != nil {
fmt.Println("555")
fmt.Println(err) fmt.Println(err)
} }
@@ -848,7 +861,6 @@ func Containerd() {
// kill the process and get the exit status // kill the process and get the exit status
if err = task.Kill(ctx, syscall.SIGTERM); err != nil { if err = task.Kill(ctx, syscall.SIGTERM); err != nil {
fmt.Println("666")
fmt.Println(err) fmt.Println(err)
} }
@@ -857,7 +869,6 @@ func Containerd() {
status := <-exitStatusC status := <-exitStatusC
code, _, err := status.Result() code, _, err := status.Result()
if err != nil { if err != nil {
fmt.Println("777")
fmt.Println(err) fmt.Println(err)
} }
fmt.Printf("redis-server exited with status: %d\n", code) fmt.Printf("redis-server exited with status: %d\n", code)

View File

@@ -3,7 +3,7 @@ package docker_base
import "github.com/IceWhaleTech/CasaOS/model" import "github.com/IceWhaleTech/CasaOS/model"
//过滤mysql关键字 //过滤mysql关键字
func MysqlFilter(c MysqlConfig, envs model.EnvArrey) model.EnvArrey { func MysqlFilter(c MysqlConfig, envs model.EnvArray) model.EnvArray {
for i := 0; i < len(envs); i++ { for i := 0; i < len(envs); i++ {
switch envs[i].Value { switch envs[i].Value {
case "$MYSQL_HOST": case "$MYSQL_HOST":

View File

@@ -61,4 +61,6 @@ type MyAppList struct {
UpTime string `json:"up_time"` UpTime string `json:"up_time"`
Slogan string `json:"slogan"` Slogan string `json:"slogan"`
Rely model.MapStrings `json:"rely"` //[{"mysql":"id"},{"mysql":"id"}] Rely model.MapStrings `json:"rely"` //[{"mysql":"id"},{"mysql":"id"}]
Image string `json:"image"`
Volumes string `json:"volumes"`
} }

View File

@@ -1,15 +1,15 @@
package model package model
type AppNotify struct { type AppNotify struct {
CustomId string `gorm:"column:custom_id;primary_key" json:"custom_id"` State int `json:"state"` //0:一直在变动的未读消息 1:未读 2:已读
ContainerId string `json:"container_id,omitempty"` Message string `json:"message"`
State int `json:"state"` //0:一直在变动的未读消息 1:未读 2:已读 CreatedAt string `json:"created_at"`
Message string `json:"message"` UpdatedAt string `json:"updated_at"`
CreatedAt string `gorm:"<-:create;autoCreateTime" json:"created_at"` Id string `json:"id"`
UpdatedAt string `gorm:"<-:create;<-:update;autoUpdateTime" json:"updated_at"` Type int `json:"type"` // 1:显示即为已读 2:info 3:warning 4:error 5:success
Speed int `json:"speed"` Icon string `json:"icon"`
Id string `gorm:"-" json:"id"` Name string `json:"name"`
Type int `json:"type"` // 1:显示即为已读 2:必须手动点掉 3:error CustomId string `gorm:"column:custom_id;primary_key" json:"custom_id"`
} }
func (p *AppNotify) TableName() string { func (p *AppNotify) TableName() string {

View File

@@ -2,9 +2,12 @@ package service
import ( import (
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger" loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
"github.com/patrickmn/go-cache"
"gorm.io/gorm" "gorm.io/gorm"
) )
var Cache *cache.Cache
var MyService Repository var MyService Repository
type Repository interface { type Repository interface {
@@ -15,7 +18,7 @@ type Repository interface {
//Redis() RedisService //Redis() RedisService
ZeroTier() ZeroTierService ZeroTier() ZeroTierService
ZiMa() ZiMaService ZiMa() ZiMaService
OAPI() OasisService OAPI() CasaService
Disk() DiskService Disk() DiskService
Notify() NotifyServer Notify() NotifyServer
ShareDirectory() ShareDirService ShareDirectory() ShareDirService
@@ -27,6 +30,7 @@ type Repository interface {
} }
func NewService(db *gorm.DB, log loger2.OLog) Repository { func NewService(db *gorm.DB, log loger2.OLog) Repository {
return &store{ return &store{
app: NewAppService(db, log), app: NewAppService(db, log),
ddns: NewDDNSService(db, log), ddns: NewDDNSService(db, log),
@@ -55,7 +59,7 @@ type store struct {
docker DockerService docker DockerService
zerotier ZeroTierService zerotier ZeroTierService
zima ZiMaService zima ZiMaService
oapi OasisService oapi CasaService
disk DiskService disk DiskService
notify NotifyServer notify NotifyServer
shareDirectory ShareDirService shareDirectory ShareDirService
@@ -102,7 +106,7 @@ func (c *store) ZeroTier() ZeroTierService {
func (c *store) ZiMa() ZiMaService { func (c *store) ZiMa() ZiMaService {
return c.zima return c.zima
} }
func (c *store) OAPI() OasisService { func (c *store) OAPI() CasaService {
return c.oapi return c.oapi
} }

View File

@@ -1,14 +1,11 @@
package service package service
import ( import (
"bufio" "io/ioutil"
"fmt"
"io"
"os" "os"
"github.com/IceWhaleTech/CasaOS/pkg/config" "github.com/IceWhaleTech/CasaOS/pkg/config"
command2 "github.com/IceWhaleTech/CasaOS/pkg/utils/command" command2 "github.com/IceWhaleTech/CasaOS/pkg/utils/command"
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
"github.com/IceWhaleTech/CasaOS/pkg/utils/loger" "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
) )
@@ -40,38 +37,20 @@ func (s *systemService) UpSystemConfig(str string, widget string) {
config.Cfg.Section("system").Key("WidgetList").SetValue(widget) config.Cfg.Section("system").Key("WidgetList").SetValue(widget)
config.SystemConfigInfo.WidgetList = widget config.SystemConfigInfo.WidgetList = widget
} }
config.Cfg.SaveTo("conf/conf.ini") config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
} }
func (s *systemService) GetCasaOSLogs(lineNumber int) string { func (s *systemService) GetCasaOSLogs(lineNumber int) string {
file, err := os.Open(s.log.Path())
reader, err := file.NewReadLineFromEnd(s.log.Path())
if err != nil { if err != nil {
return "" return err.Error()
}
defer reader.Close()
test, err := reader.ReadLine()
fmt.Println(err)
fmt.Println(test)
return string(test)
file, _ := os.Open(s.log.Path())
fileScanner := bufio.NewReader(file)
lineNumber = 5
lineCount := 1
var r string
for i := lineCount; i < lineNumber; i++ {
line, _, err := fileScanner.ReadLine()
r += string(line)
if err == io.EOF {
return r
}
// 如下是某些业务逻辑操作
// 如下代码打印每次读取的文件行内容
} }
defer file.Close() defer file.Close()
return r content, err := ioutil.ReadAll(file)
if err != nil {
return err.Error()
}
return string(content)
} }
func NewSystemService(log loger.OLog) SystemService { func NewSystemService(log loger.OLog) SystemService {

View File

@@ -1,4 +1,4 @@
package types package types
const CURRENTVERSION = "0.1.8" const CURRENTVERSION = "0.1.10"
const BODY = "<li>Add terminal</li><li>Improve single user management function</li><li>Experience optimization</li>" const BODY = "<li>Add App Store for installation</li><li>add casaOS logs</li><li>add application terminal</li><li>add application logs</li>"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

14
web/favicon.svg Normal file
View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 25.2.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
<style type="text/css">
.st0{fill:none;stroke:#363636;stroke-width:2;stroke-linejoin:round;stroke-miterlimit:2;}
@media ( prefers-color-scheme: dark ) {
.st0{fill:none;stroke:#FFFFFF;stroke-width:2;stroke-linejoin:round;stroke-miterlimit:2;}
}
</style>
<path class="st0" d="M12,22c5.5,0,10-4.5,10-10S17.5,2,12,2S2,6.5,2,12S6.5,22,12,22z"/>
<path class="st0" d="M12,22c3.9,0,7-3.1,7-7s-3.1-7-7-7s-7,3.1-7,7S8.1,22,12,22z"/>
<path class="st0" d="M12,22c2.2,0,4-1.8,4-4s-1.8-4-4-4s-4,1.8-4,4S9.8,22,12,22z"/>
</svg>

After

Width:  |  Height:  |  Size: 863 B

View File

@@ -11,18 +11,14 @@
} }
</script> </script>
<link rel="apple-touch-icon" sizes="180x180" href="/ui/img/icon/apple-touch-icon.png"> <link rel="apple-touch-icon" sizes="180x180" href="/ui/img/icon/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/ui/img/icon/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/ui/img/icon/favicon-16x16.png">
<link rel="manifest" href="/ui/site.webmanifest"> <link rel="manifest" href="/ui/site.webmanifest">
<link rel="mask-icon" href="/ui/img/icon/safari-pinned-tab.svg" color="#5bbad5">
<meta name="msapplication-TileColor" content="#da532c"> <meta name="msapplication-TileColor" content="#da532c">
<meta name="theme-color" content="#ffffff"> <meta name="theme-color" content="#ffffff">
<link rel="icon" href="/ui/favicon.ico"> <link rel="icon" href="/ui/favicon.svg" type="image/svg+xml">
<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/@mdi/font@6.2.95/css/materialdesignicons.min.css"> <link rel="stylesheet" href="//cdn.jsdelivr.net/npm/@mdi/font@6.2.95/css/materialdesignicons.min.css">
<title> <title>
CasaOS CasaOS
</title> </title>
<link href="/ui/js/0.js" rel="prefetch"><link href="/ui/js/1.js" rel="prefetch"><link href="/ui/js/2.js" rel="prefetch"><link href="/ui/js/3.js" rel="prefetch"><link href="/ui/js/4.js" rel="prefetch"><link href="/ui/js/app.js" rel="preload" as="script"><link href="/ui/js/chunk-vendors.js" rel="preload" as="script"></head> <link href="/ui/js/0.js" rel="prefetch"><link href="/ui/js/1.js" rel="prefetch"><link href="/ui/js/2.js" rel="prefetch"><link href="/ui/js/3.js" rel="prefetch"><link href="/ui/js/4.js" rel="prefetch"><link href="/ui/js/app.js" rel="preload" as="script"><link href="/ui/js/chunk-vendors.js" rel="preload" as="script"></head>
<body> <body>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -2,5 +2,5 @@ package web
import "embed" import "embed"
//go:embed index.html favicon.ico img js browserconfig.xml site.webmanifest //go:embed index.html favicon.svg img js browserconfig.xml site.webmanifest
var Static embed.FS var Static embed.FS