2
0
mirror of https://github.com/acepanel/panel.git synced 2026-02-04 03:07:20 +08:00

refactor: 重构应用加载器

This commit is contained in:
耗子
2025-01-02 21:11:06 +08:00
parent 4beb040b3d
commit 4f5961d7f7
18 changed files with 346 additions and 150 deletions

View File

@@ -6,6 +6,7 @@ import (
"github.com/google/wire"
"github.com/tnb-labs/panel/internal/app"
"github.com/tnb-labs/panel/internal/apps"
"github.com/tnb-labs/panel/internal/bootstrap"
"github.com/tnb-labs/panel/internal/data"
"github.com/tnb-labs/panel/internal/route"
@@ -14,5 +15,5 @@ import (
// initCli init command line.
func initCli() (*app.Cli, error) {
panic(wire.Build(bootstrap.ProviderSet, route.ProviderSet, service.ProviderSet, data.ProviderSet, app.NewCli))
panic(wire.Build(bootstrap.ProviderSet, route.ProviderSet, service.ProviderSet, data.ProviderSet, apps.ProviderSet, app.NewCli))
}

View File

@@ -8,6 +8,29 @@ package main
import (
"github.com/tnb-labs/panel/internal/app"
"github.com/tnb-labs/panel/internal/apps/benchmark"
"github.com/tnb-labs/panel/internal/apps/docker"
"github.com/tnb-labs/panel/internal/apps/fail2ban"
"github.com/tnb-labs/panel/internal/apps/frp"
"github.com/tnb-labs/panel/internal/apps/gitea"
"github.com/tnb-labs/panel/internal/apps/memcached"
"github.com/tnb-labs/panel/internal/apps/mysql"
"github.com/tnb-labs/panel/internal/apps/nginx"
"github.com/tnb-labs/panel/internal/apps/php74"
"github.com/tnb-labs/panel/internal/apps/php80"
"github.com/tnb-labs/panel/internal/apps/php81"
"github.com/tnb-labs/panel/internal/apps/php82"
"github.com/tnb-labs/panel/internal/apps/php83"
"github.com/tnb-labs/panel/internal/apps/php84"
"github.com/tnb-labs/panel/internal/apps/phpmyadmin"
"github.com/tnb-labs/panel/internal/apps/podman"
"github.com/tnb-labs/panel/internal/apps/postgresql"
"github.com/tnb-labs/panel/internal/apps/pureftpd"
"github.com/tnb-labs/panel/internal/apps/redis"
"github.com/tnb-labs/panel/internal/apps/rsync"
"github.com/tnb-labs/panel/internal/apps/s3fs"
"github.com/tnb-labs/panel/internal/apps/supervisor"
"github.com/tnb-labs/panel/internal/apps/toolbox"
"github.com/tnb-labs/panel/internal/bootstrap"
"github.com/tnb-labs/panel/internal/data"
"github.com/tnb-labs/panel/internal/route"
@@ -48,6 +71,30 @@ func initCli() (*app.Cli, error) {
cli := route.NewCli(cliService)
command := bootstrap.NewCli(cli)
gormigrate := bootstrap.NewMigrate(db)
appCli := app.NewCli(command, gormigrate)
benchmarkApp := benchmark.NewApp()
dockerApp := docker.NewApp()
fail2banApp := fail2ban.NewApp(websiteRepo)
frpApp := frp.NewApp()
giteaApp := gitea.NewApp()
memcachedApp := memcached.NewApp()
mysqlApp := mysql.NewApp(settingRepo)
nginxApp := nginx.NewApp()
php74App := php74.NewApp(taskRepo)
php80App := php80.NewApp(taskRepo)
php81App := php81.NewApp(taskRepo)
php82App := php82.NewApp(taskRepo)
php83App := php83.NewApp(taskRepo)
php84App := php84.NewApp(taskRepo)
phpmyadminApp := phpmyadmin.NewApp()
podmanApp := podman.NewApp()
postgresqlApp := postgresql.NewApp()
pureftpdApp := pureftpd.NewApp()
redisApp := redis.NewApp()
rsyncApp := rsync.NewApp()
s3fsApp := s3fs.NewApp(settingRepo)
supervisorApp := supervisor.NewApp()
toolboxApp := toolbox.NewApp()
loader := bootstrap.NewLoader(benchmarkApp, dockerApp, fail2banApp, frpApp, giteaApp, memcachedApp, mysqlApp, nginxApp, php74App, php80App, php81App, php82App, php83App, php84App, phpmyadminApp, podmanApp, postgresqlApp, pureftpdApp, redisApp, rsyncApp, s3fsApp, supervisorApp, toolboxApp)
appCli := app.NewCli(command, gormigrate, loader)
return appCli, nil
}

View File

@@ -8,7 +8,6 @@ package main
import (
"github.com/tnb-labs/panel/internal/app"
"github.com/tnb-labs/panel/internal/apps"
"github.com/tnb-labs/panel/internal/apps/benchmark"
"github.com/tnb-labs/panel/internal/apps/docker"
"github.com/tnb-labs/panel/internal/apps/fail2ban"
@@ -17,7 +16,12 @@ import (
"github.com/tnb-labs/panel/internal/apps/memcached"
"github.com/tnb-labs/panel/internal/apps/mysql"
"github.com/tnb-labs/panel/internal/apps/nginx"
"github.com/tnb-labs/panel/internal/apps/php"
"github.com/tnb-labs/panel/internal/apps/php74"
"github.com/tnb-labs/panel/internal/apps/php80"
"github.com/tnb-labs/panel/internal/apps/php81"
"github.com/tnb-labs/panel/internal/apps/php82"
"github.com/tnb-labs/panel/internal/apps/php83"
"github.com/tnb-labs/panel/internal/apps/php84"
"github.com/tnb-labs/panel/internal/apps/phpmyadmin"
"github.com/tnb-labs/panel/internal/apps/podman"
"github.com/tnb-labs/panel/internal/apps/postgresql"
@@ -112,7 +116,12 @@ func initWeb() (*app.Web, error) {
memcachedApp := memcached.NewApp()
mysqlApp := mysql.NewApp(settingRepo)
nginxApp := nginx.NewApp()
phpApp := php.NewApp(taskRepo)
php74App := php74.NewApp(taskRepo)
php80App := php80.NewApp(taskRepo)
php81App := php81.NewApp(taskRepo)
php82App := php82.NewApp(taskRepo)
php83App := php83.NewApp(taskRepo)
php84App := php84.NewApp(taskRepo)
phpmyadminApp := phpmyadmin.NewApp()
podmanApp := podman.NewApp()
postgresqlApp := postgresql.NewApp()
@@ -122,7 +131,7 @@ func initWeb() (*app.Web, error) {
s3fsApp := s3fs.NewApp(settingRepo)
supervisorApp := supervisor.NewApp()
toolboxApp := toolbox.NewApp()
loader := apps.NewLoader(benchmarkApp, dockerApp, fail2banApp, frpApp, giteaApp, memcachedApp, mysqlApp, nginxApp, phpApp, phpmyadminApp, podmanApp, postgresqlApp, pureftpdApp, redisApp, rsyncApp, s3fsApp, supervisorApp, toolboxApp)
loader := bootstrap.NewLoader(benchmarkApp, dockerApp, fail2banApp, frpApp, giteaApp, memcachedApp, mysqlApp, nginxApp, php74App, php80App, php81App, php82App, php83App, php84App, phpmyadminApp, podmanApp, postgresqlApp, pureftpdApp, redisApp, rsyncApp, s3fsApp, supervisorApp, toolboxApp)
http := route.NewHttp(userService, dashboardService, taskService, websiteService, databaseService, databaseServerService, databaseUserService, backupService, certService, certDNSService, certAccountService, appService, cronService, processService, safeService, firewallService, sshService, containerService, containerNetworkService, containerImageService, containerVolumeService, fileService, monitorService, settingService, systemctlService, loader)
wsService := service.NewWsService(koanf, sshRepo)
ws := route.NewWs(wsService)

View File

@@ -7,6 +7,8 @@ import (
"github.com/go-gormigrate/gormigrate/v2"
"github.com/urfave/cli/v3"
"github.com/tnb-labs/panel/pkg/apploader"
)
type Cli struct {
@@ -14,7 +16,7 @@ type Cli struct {
migrator *gormigrate.Gormigrate
}
func NewCli(cmd *cli.Command, migrator *gormigrate.Gormigrate) *Cli {
func NewCli(cmd *cli.Command, migrator *gormigrate.Gormigrate, _ *apploader.Loader) *Cli {
IsCli = true
return &Cli{
cmd: cmd,

View File

@@ -11,11 +11,11 @@ const (
// 面板全局变量
var (
Key string
Root string
Locale string
IsCli bool
Status = StatusNormal
Key string // 密钥
Root string // 根目录
Locale string // 语言
IsCli bool // 是否命令行
Status = StatusNormal // 面板状态
)
// 自动注入

View File

@@ -1,11 +1,6 @@
package apps
import (
"reflect"
"slices"
"strings"
"github.com/go-chi/chi/v5"
"github.com/google/wire"
"github.com/tnb-labs/panel/internal/apps/benchmark"
@@ -16,7 +11,12 @@ import (
"github.com/tnb-labs/panel/internal/apps/memcached"
"github.com/tnb-labs/panel/internal/apps/mysql"
"github.com/tnb-labs/panel/internal/apps/nginx"
"github.com/tnb-labs/panel/internal/apps/php"
"github.com/tnb-labs/panel/internal/apps/php74"
"github.com/tnb-labs/panel/internal/apps/php80"
"github.com/tnb-labs/panel/internal/apps/php81"
"github.com/tnb-labs/panel/internal/apps/php82"
"github.com/tnb-labs/panel/internal/apps/php83"
"github.com/tnb-labs/panel/internal/apps/php84"
"github.com/tnb-labs/panel/internal/apps/phpmyadmin"
"github.com/tnb-labs/panel/internal/apps/podman"
"github.com/tnb-labs/panel/internal/apps/postgresql"
@@ -29,7 +29,6 @@ import (
)
var ProviderSet = wire.NewSet(
NewLoader,
benchmark.NewApp,
docker.NewApp,
fail2ban.NewApp,
@@ -38,7 +37,12 @@ var ProviderSet = wire.NewSet(
memcached.NewApp,
mysql.NewApp,
nginx.NewApp,
php.NewApp,
php74.NewApp,
php80.NewApp,
php81.NewApp,
php82.NewApp,
php83.NewApp,
php84.NewApp,
phpmyadmin.NewApp,
podman.NewApp,
postgresql.NewApp,
@@ -49,122 +53,3 @@ var ProviderSet = wire.NewSet(
supervisor.NewApp,
toolbox.NewApp,
)
var slugs []string
type Loader struct {
benchmark *benchmark.App
docker *docker.App
fail2ban *fail2ban.App
frp *frp.App
gitea *gitea.App
memcached *memcached.App
mysql *mysql.App
nginx *nginx.App
php *php.App
phpmyadmin *phpmyadmin.App
podman *podman.App
postgresql *postgresql.App
pureftpd *pureftpd.App
redis *redis.App
rsync *rsync.App
s3fs *s3fs.App
supervisor *supervisor.App
toolbox *toolbox.App
}
func NewLoader(
benchmark *benchmark.App,
docker *docker.App,
fail2ban *fail2ban.App,
frp *frp.App,
gitea *gitea.App,
memcached *memcached.App,
mysql *mysql.App,
nginx *nginx.App,
php *php.App,
phpmyadmin *phpmyadmin.App,
podman *podman.App,
postgresql *postgresql.App,
pureftpd *pureftpd.App,
redis *redis.App,
rsync *rsync.App,
s3fs *s3fs.App,
supervisor *supervisor.App,
toolbox *toolbox.App,
) *Loader {
loader := &Loader{
benchmark: benchmark,
docker: docker,
fail2ban: fail2ban,
frp: frp,
gitea: gitea,
memcached: memcached,
mysql: mysql,
nginx: nginx,
php: php,
phpmyadmin: phpmyadmin,
podman: podman,
postgresql: postgresql,
pureftpd: pureftpd,
redis: redis,
rsync: rsync,
s3fs: s3fs,
supervisor: supervisor,
toolbox: toolbox,
}
loader.initSlugs()
return loader
}
func (r *Loader) Register(mux chi.Router) {
mux.Route("/benchmark", r.benchmark.Route)
mux.Route("/docker", r.docker.Route)
mux.Route("/fail2ban", r.fail2ban.Route)
mux.Route("/frp", r.frp.Route)
mux.Route("/gitea", r.gitea.Route)
mux.Route("/memcached", r.memcached.Route)
mux.Route("/mysql", r.mysql.Route)
mux.Route("/nginx", r.nginx.Route)
mux.Route("/php74", r.php.Route(74))
mux.Route("/php80", r.php.Route(80))
mux.Route("/php81", r.php.Route(81))
mux.Route("/php82", r.php.Route(82))
mux.Route("/php83", r.php.Route(83))
mux.Route("/php84", r.php.Route(84))
mux.Route("/phpmyadmin", r.phpmyadmin.Route)
mux.Route("/podman", r.podman.Route)
mux.Route("/postgresql", r.postgresql.Route)
mux.Route("/pureftpd", r.pureftpd.Route)
mux.Route("/redis", r.redis.Route)
mux.Route("/rsync", r.rsync.Route)
mux.Route("/s3fs", r.s3fs.Route)
mux.Route("/supervisor", r.supervisor.Route)
mux.Route("/toolbox", r.toolbox.Route)
}
func (r *Loader) initSlugs() []string {
if len(slugs) == 0 {
v := reflect.Indirect(reflect.ValueOf(r))
for i := 0; i < v.NumField(); i++ {
field := v.Field(i)
slug := strings.ToLower(v.Type().Field(i).Name)
if !field.IsNil() {
slugs = append(slugs, slug)
}
}
// 处理php
slugs = slices.DeleteFunc(slugs, func(slug string) bool {
return slug == "php"
})
slugs = append(slugs, "php74", "php80", "php81", "php82", "php83", "php84")
}
return slugs
}
func Slugs() []string {
return slugs
}

View File

@@ -0,0 +1,22 @@
package php74
import (
"github.com/go-chi/chi/v5"
"github.com/tnb-labs/panel/internal/apps/php"
"github.com/tnb-labs/panel/internal/biz"
)
type App struct {
php *php.App
}
func NewApp(task biz.TaskRepo) *App {
return &App{
php: php.NewApp(task),
}
}
func (s *App) Route(r chi.Router) {
s.php.Route(74)(r)
}

View File

@@ -0,0 +1,22 @@
package php80
import (
"github.com/go-chi/chi/v5"
"github.com/tnb-labs/panel/internal/apps/php"
"github.com/tnb-labs/panel/internal/biz"
)
type App struct {
php *php.App
}
func NewApp(task biz.TaskRepo) *App {
return &App{
php: php.NewApp(task),
}
}
func (s *App) Route(r chi.Router) {
s.php.Route(80)(r)
}

View File

@@ -0,0 +1,22 @@
package php81
import (
"github.com/go-chi/chi/v5"
"github.com/tnb-labs/panel/internal/apps/php"
"github.com/tnb-labs/panel/internal/biz"
)
type App struct {
php *php.App
}
func NewApp(task biz.TaskRepo) *App {
return &App{
php: php.NewApp(task),
}
}
func (s *App) Route(r chi.Router) {
s.php.Route(81)(r)
}

View File

@@ -0,0 +1,22 @@
package php82
import (
"github.com/go-chi/chi/v5"
"github.com/tnb-labs/panel/internal/apps/php"
"github.com/tnb-labs/panel/internal/biz"
)
type App struct {
php *php.App
}
func NewApp(task biz.TaskRepo) *App {
return &App{
php: php.NewApp(task),
}
}
func (s *App) Route(r chi.Router) {
s.php.Route(82)(r)
}

View File

@@ -0,0 +1,22 @@
package php83
import (
"github.com/go-chi/chi/v5"
"github.com/tnb-labs/panel/internal/apps/php"
"github.com/tnb-labs/panel/internal/biz"
)
type App struct {
php *php.App
}
func NewApp(task biz.TaskRepo) *App {
return &App{
php: php.NewApp(task),
}
}
func (s *App) Route(r chi.Router) {
s.php.Route(83)(r)
}

View File

@@ -0,0 +1,22 @@
package php84
import (
"github.com/go-chi/chi/v5"
"github.com/tnb-labs/panel/internal/apps/php"
"github.com/tnb-labs/panel/internal/biz"
)
type App struct {
php *php.App
}
func NewApp(task biz.TaskRepo) *App {
return &App{
php: php.NewApp(task),
}
}
func (s *App) Route(r chi.Router) {
s.php.Route(84)(r)
}

View File

@@ -0,0 +1,58 @@
package bootstrap
import (
"github.com/tnb-labs/panel/internal/apps/benchmark"
"github.com/tnb-labs/panel/internal/apps/docker"
"github.com/tnb-labs/panel/internal/apps/fail2ban"
"github.com/tnb-labs/panel/internal/apps/frp"
"github.com/tnb-labs/panel/internal/apps/gitea"
"github.com/tnb-labs/panel/internal/apps/memcached"
"github.com/tnb-labs/panel/internal/apps/mysql"
"github.com/tnb-labs/panel/internal/apps/nginx"
"github.com/tnb-labs/panel/internal/apps/php74"
"github.com/tnb-labs/panel/internal/apps/php80"
"github.com/tnb-labs/panel/internal/apps/php81"
"github.com/tnb-labs/panel/internal/apps/php82"
"github.com/tnb-labs/panel/internal/apps/php83"
"github.com/tnb-labs/panel/internal/apps/php84"
"github.com/tnb-labs/panel/internal/apps/phpmyadmin"
"github.com/tnb-labs/panel/internal/apps/podman"
"github.com/tnb-labs/panel/internal/apps/postgresql"
"github.com/tnb-labs/panel/internal/apps/pureftpd"
"github.com/tnb-labs/panel/internal/apps/redis"
"github.com/tnb-labs/panel/internal/apps/rsync"
"github.com/tnb-labs/panel/internal/apps/s3fs"
"github.com/tnb-labs/panel/internal/apps/supervisor"
"github.com/tnb-labs/panel/internal/apps/toolbox"
"github.com/tnb-labs/panel/pkg/apploader"
)
func NewLoader(
benchmark *benchmark.App,
docker *docker.App,
fail2ban *fail2ban.App,
frp *frp.App,
gitea *gitea.App,
memcached *memcached.App,
mysql *mysql.App,
nginx *nginx.App,
php74 *php74.App,
php80 *php80.App,
php81 *php81.App,
php82 *php82.App,
php83 *php83.App,
php84 *php84.App,
phpmyadmin *phpmyadmin.App,
podman *podman.App,
postgresql *postgresql.App,
pureftpd *pureftpd.App,
redis *redis.App,
rsync *rsync.App,
s3fs *s3fs.App,
supervisor *supervisor.App,
toolbox *toolbox.App,
) *apploader.Loader {
loader := new(apploader.Loader)
loader.Add(benchmark, docker, fail2ban, frp, gitea, memcached, mysql, nginx, php74, php80, php81, php82, php83, php84, phpmyadmin, podman, postgresql, pureftpd, redis, rsync, s3fs, supervisor, toolbox)
return loader
}

View File

@@ -3,4 +3,4 @@ package bootstrap
import "github.com/google/wire"
// ProviderSet is bootstrap providers.
var ProviderSet = wire.NewSet(NewConf, NewLog, NewCli, NewValidator, NewRouter, NewHttp, NewDB, NewMigrate, NewSession, NewCron, NewQueue)
var ProviderSet = wire.NewSet(NewConf, NewLog, NewCli, NewValidator, NewRouter, NewHttp, NewDB, NewMigrate, NewLoader, NewSession, NewCron, NewQueue)

View File

@@ -8,9 +8,9 @@ import (
"gorm.io/gorm"
"github.com/tnb-labs/panel/internal/app"
"github.com/tnb-labs/panel/internal/apps"
"github.com/tnb-labs/panel/internal/biz"
"github.com/tnb-labs/panel/pkg/api"
"github.com/tnb-labs/panel/pkg/apploader"
)
type cacheRepo struct {
@@ -57,8 +57,8 @@ func (r *cacheRepo) UpdateApps() error {
}
// 去除本地不存在的应用
*remote = slices.Clip(slices.DeleteFunc(*remote, func(app *api.App) bool {
return !slices.Contains(apps.Slugs(), app.Slug)
*remote = slices.Clip(slices.DeleteFunc(*remote, func(item *api.App) bool {
return !slices.Contains(apploader.Slugs(), item.Slug)
}))
encoded, err := json.Marshal(remote)

View File

@@ -8,10 +8,10 @@ import (
"github.com/go-chi/chi/v5"
"github.com/tnb-labs/panel/internal/apps"
"github.com/tnb-labs/panel/internal/embed"
"github.com/tnb-labs/panel/internal/http/middleware"
"github.com/tnb-labs/panel/internal/service"
"github.com/tnb-labs/panel/pkg/apploader"
)
type Http struct {
@@ -40,7 +40,7 @@ type Http struct {
monitor *service.MonitorService
setting *service.SettingService
systemctl *service.SystemctlService
apps *apps.Loader
apps *apploader.Loader
}
func NewHttp(
@@ -69,7 +69,7 @@ func NewHttp(
monitor *service.MonitorService,
setting *service.SettingService,
systemctl *service.SystemctlService,
apps *apps.Loader,
apps *apploader.Loader,
) *Http {
return &Http{
user: user,

View File

@@ -0,0 +1,63 @@
package apploader
import (
"reflect"
"slices"
"strings"
"sync"
"github.com/go-chi/chi/v5"
"github.com/tnb-labs/panel/pkg/types"
)
var apps sync.Map
type Loader struct{}
func (r *Loader) Add(app ...types.App) {
for item := range slices.Values(app) {
slug := getSlug(item)
apps.Store(slug, item)
}
}
func (r *Loader) Register(mux chi.Router) {
/*for slug, item := range r.Apps {
mux.Route("/"+slug, item.Route)
}*/
apps.Range(func(key, value any) bool {
app := value.(types.App)
mux.Route("/"+key.(string), app.Route)
return true
})
}
func Slugs() []string {
var slugs []string
apps.Range(func(key, value any) bool {
slugs = append(slugs, key.(string))
return true
})
return slugs
}
func getSlug(app types.App) string {
if app == nil {
return ""
}
t := reflect.TypeOf(app)
if t.Kind() == reflect.Ptr {
t = t.Elem()
}
pkgPath := t.PkgPath()
if pkgPath == "" {
return ""
}
parts := strings.Split(pkgPath, "/")
return parts[len(parts)-1]
}

View File

@@ -2,10 +2,9 @@ package types
import "github.com/go-chi/chi/v5"
// App 应用元数据结构
type App struct {
Slug string `json:"slug"` // 应用标识
Route func(r chi.Router) `json:"-"` // 路由
// App 应用接口
type App interface {
Route(r chi.Router)
}
// AppCenter 应用中心结构