2
0
mirror of https://github.com/acepanel/panel.git synced 2026-02-04 05:31:44 +08:00

feat: 优化s3fs挂载获取

This commit is contained in:
2025-05-15 09:08:03 +08:00
parent 71f518c6f9
commit 867c14349e
5 changed files with 77 additions and 69 deletions

View File

@@ -99,7 +99,7 @@ func initCli() (*app.Cli, error) {
pureftpdApp := pureftpd.NewApp(locale)
redisApp := redis.NewApp(locale)
rsyncApp := rsync.NewApp(locale)
s3fsApp := s3fs.NewApp(locale, settingRepo)
s3fsApp := s3fs.NewApp(locale)
supervisorApp := supervisor.NewApp(locale)
toolboxApp := toolbox.NewApp(locale)
loader := bootstrap.NewLoader(benchmarkApp, codeserverApp, dockerApp, fail2banApp, frpApp, giteaApp, memcachedApp, minioApp, mysqlApp, nginxApp, php74App, php80App, php81App, php82App, php83App, php84App, phpmyadminApp, podmanApp, postgresqlApp, pureftpdApp, redisApp, rsyncApp, s3fsApp, supervisorApp, toolboxApp)

View File

@@ -140,7 +140,7 @@ func initWeb() (*app.Web, error) {
pureftpdApp := pureftpd.NewApp(locale)
redisApp := redis.NewApp(locale)
rsyncApp := rsync.NewApp(locale)
s3fsApp := s3fs.NewApp(locale, settingRepo)
s3fsApp := s3fs.NewApp(locale)
supervisorApp := supervisor.NewApp(locale)
toolboxApp := toolbox.NewApp(locale)
loader := bootstrap.NewLoader(benchmarkApp, codeserverApp, dockerApp, fail2banApp, frpApp, giteaApp, memcachedApp, minioApp, mysqlApp, nginxApp, php74App, php80App, php81App, php82App, php83App, php84App, phpmyadminApp, podmanApp, postgresqlApp, pureftpdApp, redisApp, rsyncApp, s3fsApp, supervisorApp, toolboxApp)

View File

@@ -1,9 +1,9 @@
package s3fs
import (
"encoding/json"
"net/http"
"os"
"regexp"
"strings"
"time"
@@ -12,21 +12,18 @@ import (
"github.com/leonelquinteros/gotext"
"github.com/spf13/cast"
"github.com/tnb-labs/panel/internal/biz"
"github.com/tnb-labs/panel/internal/service"
"github.com/tnb-labs/panel/pkg/io"
"github.com/tnb-labs/panel/pkg/shell"
)
type App struct {
t *gotext.Locale
settingRepo biz.SettingRepo
t *gotext.Locale
}
func NewApp(t *gotext.Locale, setting biz.SettingRepo) *App {
func NewApp(t *gotext.Locale) *App {
return &App{
t: t,
settingRepo: setting,
t: t,
}
}
@@ -38,19 +35,13 @@ func (s *App) Route(r chi.Router) {
// List 所有 S3fs 挂载
func (s *App) List(w http.ResponseWriter, r *http.Request) {
var s3fsList []Mount
list, err := s.settingRepo.Get("s3fs", "[]")
list, err := s.mounts()
if err != nil {
service.Error(w, http.StatusInternalServerError, s.t.Get("failed to get s3fs list: %v", err))
return
}
if err = json.Unmarshal([]byte(list), &s3fsList); err != nil {
service.Error(w, http.StatusInternalServerError, s.t.Get("failed to get s3fs list: %v", err))
return
}
paged, total := service.Paginate(r, s3fsList)
paged, total := service.Paginate(r, list)
service.Success(w, chix.M{
"total": total,
@@ -84,18 +75,13 @@ func (s *App) Create(w http.ResponseWriter, r *http.Request) {
return
}
var s3fsList []Mount
list, err := s.settingRepo.Get("s3fs", "[]")
list, err := s.mounts()
if err != nil {
service.Error(w, http.StatusInternalServerError, s.t.Get("failed to get s3fs list: %v", err))
return
}
if err = json.Unmarshal([]byte(list), &s3fsList); err != nil {
service.Error(w, http.StatusInternalServerError, s.t.Get("failed to get s3fs list: %v", err))
return
}
for _, item := range s3fsList {
for _, item := range list {
if item.Path == req.Path {
service.Error(w, http.StatusUnprocessableEntity, s.t.Get("mount path already exists"))
return
@@ -123,23 +109,6 @@ func (s *App) Create(w http.ResponseWriter, r *http.Request) {
return
}
s3fsList = append(s3fsList, Mount{
ID: id,
Path: req.Path,
Bucket: req.Bucket,
Url: req.URL,
})
encoded, err := json.Marshal(s3fsList)
if err != nil {
service.Error(w, http.StatusInternalServerError, s.t.Get("failed to add s3fs mount: %v", err))
return
}
if err = s.settingRepo.Set("s3fs", string(encoded)); err != nil {
service.Error(w, http.StatusInternalServerError, s.t.Get("failed to add s3fs mount: %v", err))
return
}
service.Success(w, nil)
}
@@ -151,19 +120,14 @@ func (s *App) Delete(w http.ResponseWriter, r *http.Request) {
return
}
var s3fsList []Mount
list, err := s.settingRepo.Get("s3fs", "[]")
list, err := s.mounts()
if err != nil {
service.Error(w, http.StatusInternalServerError, s.t.Get("failed to get s3fs list: %v", err))
return
}
if err = json.Unmarshal([]byte(list), &s3fsList); err != nil {
service.Error(w, http.StatusInternalServerError, s.t.Get("failed to get s3fs list: %v", err))
return
}
var mount Mount
for _, item := range s3fsList {
for _, item := range list {
if item.ID == req.ID {
mount = item
break
@@ -174,7 +138,7 @@ func (s *App) Delete(w http.ResponseWriter, r *http.Request) {
return
}
if _, err = shell.Execf(`fusermount -uz '%s'`, mount.Path); err != nil {
if _, err = shell.Execf(`fusermount -uzq '%s'`, mount.Path); err != nil {
service.Error(w, http.StatusInternalServerError, "%v", err)
return
}
@@ -195,21 +159,57 @@ func (s *App) Delete(w http.ResponseWriter, r *http.Request) {
return
}
var newS3fsList []Mount
for _, item := range s3fsList {
if item.ID != mount.ID {
newS3fsList = append(newS3fsList, item)
}
}
encoded, err := json.Marshal(newS3fsList)
if err != nil {
service.Error(w, http.StatusInternalServerError, s.t.Get("failed to delete s3fs mount: %v", err))
return
}
if err = s.settingRepo.Set("s3fs", string(encoded)); err != nil {
service.Error(w, http.StatusInternalServerError, s.t.Get("failed to delete s3fs mount: %v", err))
return
}
service.Success(w, nil)
}
func (s *App) mounts() ([]Mount, error) {
re := regexp.MustCompile(`^s3fs#(.*?)\s+(.*?)\s+fuse.*?url=(.*?),passwd_file=/etc/passwd-s3fs-(.*?)\s+`)
fstab, err := os.ReadFile("/etc/fstab")
if err != nil {
return nil, err
}
lines := strings.Split(string(fstab), "\n")
var mounts []Mount
ids, err := shell.Exec("find /etc -maxdepth 1 -name 'passwd-s3fs-*'")
if err != nil {
return nil, err
}
for _, id := range strings.Split(ids, "\n") {
if id == "" {
continue
}
id = strings.TrimPrefix(id, "/etc/passwd-s3fs-")
id = strings.TrimSuffix(id, "\n")
id = strings.TrimSpace(id)
if id == "" {
continue
}
mount := Mount{
ID: cast.ToInt64(id),
}
for _, line := range lines {
if line == "" {
continue
}
if strings.Contains(line, id) {
matches := re.FindStringSubmatch(line)
if len(matches) == 5 {
mount.Bucket = matches[1]
mount.Path = matches[2]
mount.URL = matches[3]
break
}
}
}
if mount.ID == 0 || mount.Path == "" || mount.Bucket == "" || mount.URL == "" {
continue
}
mounts = append(mounts, mount)
}
return mounts, nil
}

View File

@@ -4,5 +4,5 @@ type Mount struct {
ID int64 `json:"id"`
Path string `json:"path"`
Bucket string `json:"bucket"`
Url string `json:"url"`
URL string `json:"url"`
}

View File

@@ -7,13 +7,21 @@ package service
import (
"net/http"
"github.com/leonelquinteros/gotext"
"github.com/tnb-labs/panel/internal/biz"
)
type FileService struct{}
type FileService struct {
t *gotext.Locale
taskRepo biz.TaskRepo
}
func NewFileService(_ biz.TaskRepo) *FileService {
return &FileService{}
func NewFileService(t *gotext.Locale, task biz.TaskRepo) *FileService {
return &FileService{
t: t,
taskRepo: task,
}
}
func (s *FileService) Create(w http.ResponseWriter, r *http.Request) {}