refactor: 把 context 打通到数据库、对象存储与容器 API

上一轮打通 shell 路径时留下三处接口本身不带 ctx,导致底下的
context.Background() 无法消除。这三处 contextcheck 都不报(接口方法没有
ctx 形参,静态分析认为合理),属于 lint 发现不了的死角:

- pkg/db.Operator 的 17 个方法加 ctx,MySQL/Postgres/ClickHouse/SQLite/
  MongoDB/Elasticsearch 实现同步改。其中 Elasticsearch 的 resty 请求原先
  根本没挂 ctx,不只是传了 Background
- pkg/storage.Storage 的 6 个方法加 ctx,local/s3/sftp/webdav 四个实现与
  s3sdk 子包同步改;sftp 连接改用 net.Dialer.DialContext,连接阶段可取消
- internal/data/container*.go 的 moby client 调用,Container/Image/Network/
  Volume 四个 Repo 共 26 个方法加 ctx

非测试代码的 context.Background() 从 71 处降到 14 处,剩下的是应用根 ctx、
有意的独立超时,以及几个瞬时本机操作的叶子函数。双平台 lint 保持 0 issues。

新增 23 处 context.WithoutCancel,其中两处的理由值得记:

备份上传断开取消链,是因为 ClearStorageExpired 按 mtime 保留最新 N 份,
上传被取消留下的截断文件会被当成最新的有效备份,把真正完好的旧备份挤出
保留窗口——静默的数据丢失。而 Put 失败路径没有任何远端清理逻辑,本地侧
反而有(任务队列独享 TMPDIR + defer RemoveAll),两边不对称。

Postgres.UserDrop 是 REASSIGN OWNED → DROP OWNED → DROP USER 三步,中途
取消会留下丢了所有权却没被删掉的用户;MySQL 权限变更后的 FLUSH 被跳过则
新授权根本不生效。

ImagePull 经核实不需要断开:moby 的 LayerDownloadManager 把未完成的层写在
临时文件里并在取消时删除,层只有完整校验后才注册进 layer store,取消不会
留下悬空层。

顺带删掉 8 处 //nolint:contextcheck,它们当初就是因为 Operator 接口没有
ctx 才挂上的。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
耗子
2026-09-15 01:17:02 +08:00
co-authored by Claude Opus 5
parent 59f99cc8fc
commit e0588a1468
51 changed files with 892 additions and 677 deletions
+24 -22
View File
@@ -233,16 +233,18 @@ func (s *App) SetRootPassword(w http.ResponseWriter, r *http.Request) {
}
oldRootPassword, _ := s.settingRepo.Get(biz.SettingKeyMySQLRootPassword)
// 改密后还要写回面板设置,中途取消会让面板存的密码与实际不符
ctx := context.WithoutCancel(r.Context())
mysql, err := db.NewMySQL(r.Context(), "root", oldRootPassword, db.MySQLSocket(app.Root), "unix")
if err != nil {
// 尝试安全模式直接改密,中途取消会让面板存的密码与实际不符
if err = db.MySQLResetRootPassword(context.WithoutCancel(r.Context()), req.Password, app.Root); err != nil {
// 尝试安全模式直接改密
if err = db.MySQLResetRootPassword(ctx, req.Password, app.Root); err != nil {
service.Error(w, http.StatusInternalServerError, "%v", err)
return
}
} else {
defer mysql.Close()
if err = mysql.UserPassword("root", req.Password, "localhost"); err != nil {
if err = mysql.UserPassword(ctx, "root", req.Password, "localhost"); err != nil {
service.Error(w, http.StatusInternalServerError, "%v", err)
return
}
@@ -365,7 +367,7 @@ func (s *App) ProcessList(w http.ResponseWriter, r *http.Request) {
}
defer mysql.Close()
rows, err := mysql.Query(`
rows, err := mysql.Query(r.Context(), `
SELECT ID, coalesce(USER,''), coalesce(HOST,''), coalesce(DB,''), coalesce(COMMAND,''),
TIME, coalesce(STATE,''), coalesce(INFO,'')
FROM information_schema.PROCESSLIST WHERE ID != CONNECTION_ID() ORDER BY TIME DESC`)
@@ -408,7 +410,7 @@ func (s *App) KillProcess(w http.ResponseWriter, r *http.Request) {
defer mysql.Close()
// KILL 不支持预编译参数,id 已校验为正整数
if _, err = mysql.Exec(fmt.Sprintf(`KILL %d`, id)); err != nil {
if _, err = mysql.Exec(r.Context(), fmt.Sprintf(`KILL %d`, id)); err != nil {
service.Error(w, http.StatusInternalServerError, "%v", err)
return
}
@@ -425,7 +427,7 @@ func (s *App) TransactionList(w http.ResponseWriter, r *http.Request) {
}
defer mysql.Close()
rows, err := mysql.Query(`
rows, err := mysql.Query(r.Context(), `
SELECT trx_id, trx_mysql_thread_id, coalesce(trx_state,''), coalesce(trx_query,''),
timestampdiff(SECOND, trx_started, now()), trx_rows_locked, trx_rows_modified
FROM information_schema.INNODB_TRX ORDER BY trx_started`)
@@ -455,14 +457,14 @@ func (s *App) TransactionList(w http.ResponseWriter, r *http.Request) {
FROM performance_schema.data_lock_waits w
JOIN information_schema.innodb_trx r ON r.trx_id = w.REQUESTING_ENGINE_TRANSACTION_ID
JOIN information_schema.innodb_trx b ON b.trx_id = w.BLOCKING_ENGINE_TRANSACTION_ID`
if s.isMariaDB(mysql) {
if s.isMariaDB(r.Context(), mysql) {
lockSQL = `
SELECT r.trx_mysql_thread_id, coalesce(r.trx_query,''), b.trx_mysql_thread_id, coalesce(b.trx_query,'')
FROM information_schema.INNODB_LOCK_WAITS w
JOIN information_schema.INNODB_TRX r ON r.trx_id = w.requesting_trx_id
JOIN information_schema.INNODB_TRX b ON b.trx_id = w.blocking_trx_id`
}
if lockRows, lockErr := mysql.Query(lockSQL); lockErr == nil {
if lockRows, lockErr := mysql.Query(r.Context(), lockSQL); lockErr == nil {
defer func() { _ = lockRows.Close() }()
for lockRows.Next() {
var item LockWait
@@ -490,7 +492,7 @@ func (s *App) TopSQL(w http.ResponseWriter, r *http.Request) {
defer mysql.Close()
var enabled int
if err = mysql.QueryRow(`SELECT @@performance_schema`).Scan(&enabled); err != nil {
if err = mysql.QueryRow(r.Context(), `SELECT @@performance_schema`).Scan(&enabled); err != nil {
if strings.Contains(err.Error(), "Unknown system variable") {
service.Success(w, TopSQL{Supported: false, Items: []TopSQLItem{}})
return
@@ -506,7 +508,7 @@ func (s *App) TopSQL(w http.ResponseWriter, r *http.Request) {
return
}
rows, err := mysql.Query(`
rows, err := mysql.Query(r.Context(), `
SELECT coalesce(SCHEMA_NAME,''), COUNT_STAR, SUM_TIMER_WAIT DIV 1000000000,
round(AVG_TIMER_WAIT/1e9,2), SUM_ROWS_SENT, SUM_ROWS_EXAMINED, coalesce(DIGEST_TEXT,'')
FROM performance_schema.events_statements_summary_by_digest
@@ -544,7 +546,7 @@ func (s *App) EnableTopSQL(w http.ResponseWriter, r *http.Request) {
}
defer mysql.Close()
var enabled int
if err = mysql.QueryRow(`SELECT @@performance_schema`).Scan(&enabled); err != nil {
if err = mysql.QueryRow(r.Context(), `SELECT @@performance_schema`).Scan(&enabled); err != nil {
service.Error(w, http.StatusUnprocessableEntity, s.t.Get("performance_schema is not supported by this instance"))
return
}
@@ -575,7 +577,7 @@ func (s *App) ResetTopSQL(w http.ResponseWriter, r *http.Request) {
}
defer mysql.Close()
if _, err = mysql.Exec(`TRUNCATE TABLE performance_schema.events_statements_summary_by_digest`); err != nil {
if _, err = mysql.Exec(r.Context(), `TRUNCATE TABLE performance_schema.events_statements_summary_by_digest`); err != nil {
service.Error(w, http.StatusInternalServerError, "%v", err)
return
}
@@ -592,7 +594,7 @@ func (s *App) DatabaseList(w http.ResponseWriter, r *http.Request) {
}
defer mysql.Close()
rows, err := mysql.Query(`
rows, err := mysql.Query(r.Context(), `
SELECT SCHEMA_NAME FROM information_schema.SCHEMATA
WHERE SCHEMA_NAME NOT IN ('mysql','information_schema','performance_schema','sys')
ORDER BY SCHEMA_NAME`)
@@ -646,7 +648,7 @@ func (s *App) TableList(w http.ResponseWriter, r *http.Request) {
args = append(args, req.Database)
}
query += ` ORDER BY data_length + index_length DESC LIMIT 50`
rows, err := mysql.Query(query, args...)
rows, err := mysql.Query(r.Context(), query, args...)
if err != nil {
service.Error(w, http.StatusInternalServerError, "%v", err)
return
@@ -729,7 +731,7 @@ func (s *App) BinlogList(w http.ResponseWriter, r *http.Request) {
defer mysql.Close()
var enabled int
if err = mysql.QueryRow(`SELECT @@log_bin`).Scan(&enabled); err != nil {
if err = mysql.QueryRow(r.Context(), `SELECT @@log_bin`).Scan(&enabled); err != nil {
service.Error(w, http.StatusInternalServerError, "%v", err)
return
}
@@ -738,7 +740,7 @@ func (s *App) BinlogList(w http.ResponseWriter, r *http.Request) {
return
}
rows, err := mysql.Query(`SHOW BINARY LOGS`)
rows, err := mysql.Query(r.Context(), `SHOW BINARY LOGS`)
if err != nil {
service.Error(w, http.StatusInternalServerError, "%v", err)
return
@@ -778,7 +780,7 @@ func (s *App) PurgeBinlog(w http.ResponseWriter, r *http.Request) {
defer mysql.Close()
// 校验文件名存在于 binlog 列表,PURGE 不支持预编译参数
rows, err := mysql.Query(`SHOW BINARY LOGS`)
rows, err := mysql.Query(r.Context(), `SHOW BINARY LOGS`)
if err != nil {
service.Error(w, http.StatusInternalServerError, "%v", err)
return
@@ -793,7 +795,7 @@ func (s *App) PurgeBinlog(w http.ResponseWriter, r *http.Request) {
return
}
if _, err = mysql.Exec(fmt.Sprintf(`PURGE BINARY LOGS TO '%s'`, req.File)); err != nil {
if _, err = mysql.Exec(r.Context(), fmt.Sprintf(`PURGE BINARY LOGS TO '%s'`, req.File)); err != nil {
service.Error(w, http.StatusInternalServerError, "%v", err)
return
}
@@ -810,10 +812,10 @@ func (s *App) ReplicationStatus(w http.ResponseWriter, r *http.Request) {
}
defer mysql.Close()
rows, err := mysql.Query(`SHOW REPLICA STATUS`)
rows, err := mysql.Query(r.Context(), `SHOW REPLICA STATUS`)
if err != nil {
// 老版本 fallback
if rows, err = mysql.Query(`SHOW SLAVE STATUS`); err != nil {
if rows, err = mysql.Query(r.Context(), `SHOW SLAVE STATUS`); err != nil {
service.Error(w, http.StatusInternalServerError, "%v", err)
return
}
@@ -859,9 +861,9 @@ func (s *App) connect(ctx context.Context) (db.Operator, error) {
}
// isMariaDB 判断当前实例是否为 MariaDB
func (s *App) isMariaDB(op db.Operator) bool {
func (s *App) isMariaDB(ctx context.Context, op db.Operator) bool {
var version string
if err := op.QueryRow(`SELECT VERSION()`).Scan(&version); err != nil {
if err := op.QueryRow(ctx, `SELECT VERSION()`).Scan(&version); err != nil {
return false
}
return strings.Contains(strings.ToLower(version), "mariadb")
+18 -16
View File
@@ -234,16 +234,18 @@ func (s *App) SetPostgresPassword(w http.ResponseWriter, r *http.Request) {
oldPassword, _ := s.settingRepo.Get(biz.SettingKeyPostgresPassword)
port := db.PostgresPort(app.Root)
// 改完密码还要存进面板库,中途取消会让两边密码对不上
ctx := context.WithoutCancel(r.Context())
postgres, err := db.NewPostgres(r.Context(), "postgres", oldPassword, "127.0.0.1", port)
if err != nil {
// 直接修改密码,改完还要存进面板库,中途取消会让两边密码对不上
if _, err = shell.Execf(context.WithoutCancel(r.Context()), `su - postgres -c "psql -p %d -c \"ALTER USER postgres WITH PASSWORD '%s';\""`, port, req.Password); err != nil {
// 回退到直接修改密码
if _, err = shell.Execf(ctx, `su - postgres -c "psql -p %d -c \"ALTER USER postgres WITH PASSWORD '%s';\""`, port, req.Password); err != nil {
service.Error(w, http.StatusInternalServerError, s.t.Get("failed to set postgres password: %v", err))
return
}
} else {
defer postgres.Close()
if err = postgres.UserPassword("postgres", req.Password); err != nil {
if err = postgres.UserPassword(ctx, "postgres", req.Password); err != nil {
service.Error(w, http.StatusInternalServerError, s.t.Get("failed to set postgres password: %v", err))
return
}
@@ -453,7 +455,7 @@ func (s *App) EnableExtension(w http.ResponseWriter, r *http.Request) {
}
defer postgres.Close()
if _, err = postgres.Exec(fmt.Sprintf(`CREATE EXTENSION IF NOT EXISTS "%s"`, ext.ExtName)); err != nil {
if _, err = postgres.Exec(r.Context(), fmt.Sprintf(`CREATE EXTENSION IF NOT EXISTS "%s"`, ext.ExtName)); err != nil {
service.Error(w, http.StatusInternalServerError, s.t.Get("failed to enable extension: %v", err))
return
}
@@ -470,7 +472,7 @@ func (s *App) SessionList(w http.ResponseWriter, r *http.Request) {
}
defer postgres.Close()
rows, err := postgres.Query(`
rows, err := postgres.Query(r.Context(), `
SELECT a.pid, coalesce(a.datname,''), coalesce(a.usename,''), coalesce(a.client_addr::text,''),
coalesce(a.state,''), coalesce(a.wait_event_type,''), coalesce(a.wait_event,''),
coalesce(array_to_string(pg_blocking_pids(a.pid),','),''),
@@ -519,7 +521,7 @@ func (s *App) TerminateSession(w http.ResponseWriter, r *http.Request) {
}
defer postgres.Close()
if _, err = postgres.Exec(`SELECT pg_terminate_backend($1)`, pid); err != nil {
if _, err = postgres.Exec(r.Context(), `SELECT pg_terminate_backend($1)`, pid); err != nil {
service.Error(w, http.StatusInternalServerError, "%v", err)
return
}
@@ -536,7 +538,7 @@ func (s *App) TopSQL(w http.ResponseWriter, r *http.Request) {
}
defer postgres.Close()
rows, err := postgres.Query(`
rows, err := postgres.Query(r.Context(), `
SELECT coalesce(d.datname,''), s.calls, round(s.total_exec_time)::bigint,
round(s.mean_exec_time::numeric,2)::float8, s.rows,
coalesce(round(100.0*s.shared_blks_hit/nullif(s.shared_blks_hit+s.shared_blks_read,0),1),0)::float8,
@@ -606,7 +608,7 @@ func (s *App) EnableTopSQL(w http.ResponseWriter, r *http.Request) {
}
defer postgres.Close()
if _, err = postgres.Exec(`CREATE EXTENSION IF NOT EXISTS pg_stat_statements`); err != nil {
if _, err = postgres.Exec(r.Context(), `CREATE EXTENSION IF NOT EXISTS pg_stat_statements`); err != nil {
service.Error(w, http.StatusInternalServerError, "%v", err)
return
}
@@ -623,7 +625,7 @@ func (s *App) ResetTopSQL(w http.ResponseWriter, r *http.Request) {
}
defer postgres.Close()
if _, err = postgres.Exec(`SELECT pg_stat_statements_reset()`); err != nil {
if _, err = postgres.Exec(r.Context(), `SELECT pg_stat_statements_reset()`); err != nil {
service.Error(w, http.StatusInternalServerError, "%v", err)
return
}
@@ -640,7 +642,7 @@ func (s *App) DatabaseList(w http.ResponseWriter, r *http.Request) {
}
defer postgres.Close()
rows, err := postgres.Query(`SELECT datname FROM pg_database WHERE datallowconn ORDER BY datname`)
rows, err := postgres.Query(r.Context(), `SELECT datname FROM pg_database WHERE datallowconn ORDER BY datname`)
if err != nil {
service.Error(w, http.StatusInternalServerError, "%v", err)
return
@@ -679,7 +681,7 @@ func (s *App) BloatList(w http.ResponseWriter, r *http.Request) {
}
defer postgres.Close()
rows, err := postgres.Query(`
rows, err := postgres.Query(r.Context(), `
SELECT schemaname, relname, pg_size_pretty(pg_total_relation_size(relid)),
pg_total_relation_size(relid), n_live_tup, n_dead_tup,
coalesce(round(100.0*n_dead_tup/nullif(n_live_tup+n_dead_tup,0),1),0)::float8,
@@ -773,17 +775,17 @@ func (s *App) WalStatus(w http.ResponseWriter, r *http.Request) {
defer postgres.Close()
var wal Wal
if err = postgres.QueryRow(`SELECT pg_size_pretty(coalesce(sum(size),0)) FROM pg_ls_waldir()`).Scan(&wal.WalSize); err != nil {
if err = postgres.QueryRow(r.Context(), `SELECT pg_size_pretty(coalesce(sum(size),0)) FROM pg_ls_waldir()`).Scan(&wal.WalSize); err != nil {
service.Error(w, http.StatusInternalServerError, "%v", err)
return
}
if err = postgres.QueryRow(`SELECT archived_count, failed_count, coalesce(last_archived_wal,''), coalesce(last_failed_wal,'') FROM pg_stat_archiver`).Scan(
if err = postgres.QueryRow(r.Context(), `SELECT archived_count, failed_count, coalesce(last_archived_wal,''), coalesce(last_failed_wal,'') FROM pg_stat_archiver`).Scan(
&wal.Archiver.ArchivedCount, &wal.Archiver.FailedCount, &wal.Archiver.LastArchivedWal, &wal.Archiver.LastFailedWal); err != nil {
service.Error(w, http.StatusInternalServerError, "%v", err)
return
}
slotRows, err := postgres.Query(`SELECT slot_name, slot_type, active, coalesce(pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn)),'') FROM pg_replication_slots`)
slotRows, err := postgres.Query(r.Context(), `SELECT slot_name, slot_type, active, coalesce(pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn)),'') FROM pg_replication_slots`)
if err != nil {
service.Error(w, http.StatusInternalServerError, "%v", err)
return
@@ -803,7 +805,7 @@ func (s *App) WalStatus(w http.ResponseWriter, r *http.Request) {
return
}
replRows, err := postgres.Query(`SELECT coalesce(client_addr::text,''), coalesce(state,''), coalesce(sync_state,''), coalesce(pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), replay_lsn)),'') FROM pg_stat_replication`)
replRows, err := postgres.Query(r.Context(), `SELECT coalesce(client_addr::text,''), coalesce(state,''), coalesce(sync_state,''), coalesce(pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), replay_lsn)),'') FROM pg_stat_replication`)
if err != nil {
service.Error(w, http.StatusInternalServerError, "%v", err)
return
@@ -841,7 +843,7 @@ func (s *App) DropReplicationSlot(w http.ResponseWriter, r *http.Request) {
}
defer postgres.Close()
if _, err = postgres.Exec(`SELECT pg_drop_replication_slot($1)`, slot); err != nil {
if _, err = postgres.Exec(r.Context(), `SELECT pg_drop_replication_slot($1)`, slot); err != nil {
service.Error(w, http.StatusInternalServerError, "%v", err)
return
}
+1 -1
View File
@@ -488,7 +488,7 @@ func (uc *AlertUsecase) collect(ctx context.Context, rule *AlertRule, info types
}), nil
case AlertTypeContainer:
containers, err := uc.container.ListAll(containerSock(uc.setting))
containers, err := uc.container.ListAll(ctx, containerSock(uc.setting))
if err != nil {
return nil, err
}
+6 -6
View File
@@ -31,9 +31,9 @@ type BackupRepo interface {
Delete(ctx context.Context, typ BackupType, name string) error
Restore(ctx context.Context, typ BackupType, backup, target string) error
ClearExpired(path, prefix string, save uint) error
ClearStorageExpired(account uint, dir, prefix string, save uint) error
ClearStorageExpired(ctx context.Context, account uint, dir, prefix string, save uint) error
CutoffLog(ctx context.Context, path, target string) (string, error)
CutoffUpload(account uint, typ BackupType, name string, files []string) error
CutoffUpload(ctx context.Context, account uint, typ BackupType, name string, files []string) error
GetDefaultPath(typ BackupType) string
FixPanel(ctx context.Context) error
UpdatePanel(ctx context.Context, version, url, checksum string, progress func(string)) error
@@ -113,16 +113,16 @@ func (uc *BackupUsecase) ClearExpired(path, prefix string, save uint) error {
return uc.repo.ClearExpired(path, prefix, save)
}
func (uc *BackupUsecase) ClearStorageExpired(account uint, dir, prefix string, save uint) error {
return uc.repo.ClearStorageExpired(account, dir, prefix, save)
func (uc *BackupUsecase) ClearStorageExpired(ctx context.Context, account uint, dir, prefix string, save uint) error {
return uc.repo.ClearStorageExpired(ctx, account, dir, prefix, save)
}
func (uc *BackupUsecase) CutoffLog(ctx context.Context, path, target string) (string, error) {
return uc.repo.CutoffLog(ctx, path, target)
}
func (uc *BackupUsecase) CutoffUpload(account uint, typ BackupType, name string, files []string) error {
return uc.repo.CutoffUpload(account, typ, name, files)
func (uc *BackupUsecase) CutoffUpload(ctx context.Context, account uint, typ BackupType, name string, files []string) error {
return uc.repo.CutoffUpload(ctx, account, typ, name, files)
}
func (uc *BackupUsecase) GetDefaultPath(typ BackupType) string {
+45 -44
View File
@@ -1,6 +1,7 @@
package biz
import (
"context"
"slices"
"strings"
@@ -12,19 +13,19 @@ import (
)
type ContainerRepo interface {
ListAll(sock string) ([]types.Container, error)
Inspect(sock string, id string) (any, error)
Create(sock string, req *request.ContainerCreate) (string, error)
Remove(sock string, id string) error
Start(sock string, id string) error
Stop(sock string, id string) error
Restart(sock string, id string) error
Pause(sock string, id string) error
Unpause(sock string, id string) error
Kill(sock string, id string) error
Rename(sock string, id string, newName string) error
Logs(sock string, id string, tail int) (string, error)
Prune(sock string) error
ListAll(ctx context.Context, sock string) ([]types.Container, error)
Inspect(ctx context.Context, sock string, id string) (any, error)
Create(ctx context.Context, sock string, req *request.ContainerCreate) (string, error)
Remove(ctx context.Context, sock string, id string) error
Start(ctx context.Context, sock string, id string) error
Stop(ctx context.Context, sock string, id string) error
Restart(ctx context.Context, sock string, id string) error
Pause(ctx context.Context, sock string, id string) error
Unpause(ctx context.Context, sock string, id string) error
Kill(ctx context.Context, sock string, id string) error
Rename(ctx context.Context, sock string, id string, newName string) error
Logs(ctx context.Context, sock string, id string, tail int) (string, error)
Prune(ctx context.Context, sock string) error
}
type ContainerUsecase struct {
@@ -43,14 +44,14 @@ func NewContainerUsecase(t *gotext.Locale, containerRepo ContainerRepo, settingR
}
}
func (uc *ContainerUsecase) ListAll() ([]types.Container, error) {
func (uc *ContainerUsecase) ListAll(ctx context.Context) ([]types.Container, error) {
sock := containerSock(uc.setting)
return uc.repo.ListAll(sock)
return uc.repo.ListAll(ctx, sock)
}
func (uc *ContainerUsecase) ListByName(name string) ([]types.Container, error) {
func (uc *ContainerUsecase) ListByName(ctx context.Context, name string) ([]types.Container, error) {
sock := containerSock(uc.setting)
containers, err := uc.repo.ListAll(sock)
containers, err := uc.repo.ListAll(ctx, sock)
if err != nil {
return nil, err
}
@@ -62,14 +63,14 @@ func (uc *ContainerUsecase) ListByName(name string) ([]types.Container, error) {
return containers, nil
}
func (uc *ContainerUsecase) Inspect(id string) (any, error) {
func (uc *ContainerUsecase) Inspect(ctx context.Context, id string) (any, error) {
sock := containerSock(uc.setting)
return uc.repo.Inspect(sock, id)
return uc.repo.Inspect(ctx, sock, id)
}
func (uc *ContainerUsecase) Create(req *request.ContainerCreate) (string, error) {
func (uc *ContainerUsecase) Create(ctx context.Context, req *request.ContainerCreate) (string, error) {
sock := containerSock(uc.setting)
return uc.repo.Create(sock, req)
return uc.repo.Create(ctx, sock, req)
}
func (uc *ContainerUsecase) CreateBackground(req *request.ContainerCreate) error {
@@ -96,12 +97,12 @@ func (uc *ContainerUsecase) CreateBackground(req *request.ContainerCreate) error
}
// Update 删除旧容器后按新配置重建同名容器
func (uc *ContainerUsecase) Update(id string, req *request.ContainerCreate) (string, error) {
func (uc *ContainerUsecase) Update(ctx context.Context, id string, req *request.ContainerCreate) (string, error) {
sock := containerSock(uc.setting)
if err := uc.repo.Remove(sock, id); err != nil {
if err := uc.repo.Remove(ctx, sock, id); err != nil {
return "", err
}
return uc.repo.Create(sock, req)
return uc.repo.Create(ctx, sock, req)
}
func (uc *ContainerUsecase) UpdateBackground(id string, req *request.ContainerCreate) error {
@@ -131,52 +132,52 @@ func (uc *ContainerUsecase) UpdateBackground(id string, req *request.ContainerCr
return uc.task.Push(task)
}
func (uc *ContainerUsecase) Remove(id string) error {
func (uc *ContainerUsecase) Remove(ctx context.Context, id string) error {
sock := containerSock(uc.setting)
return uc.repo.Remove(sock, id)
return uc.repo.Remove(ctx, sock, id)
}
func (uc *ContainerUsecase) Start(id string) error {
func (uc *ContainerUsecase) Start(ctx context.Context, id string) error {
sock := containerSock(uc.setting)
return uc.repo.Start(sock, id)
return uc.repo.Start(ctx, sock, id)
}
func (uc *ContainerUsecase) Stop(id string) error {
func (uc *ContainerUsecase) Stop(ctx context.Context, id string) error {
sock := containerSock(uc.setting)
return uc.repo.Stop(sock, id)
return uc.repo.Stop(ctx, sock, id)
}
func (uc *ContainerUsecase) Restart(id string) error {
func (uc *ContainerUsecase) Restart(ctx context.Context, id string) error {
sock := containerSock(uc.setting)
return uc.repo.Restart(sock, id)
return uc.repo.Restart(ctx, sock, id)
}
func (uc *ContainerUsecase) Pause(id string) error {
func (uc *ContainerUsecase) Pause(ctx context.Context, id string) error {
sock := containerSock(uc.setting)
return uc.repo.Pause(sock, id)
return uc.repo.Pause(ctx, sock, id)
}
func (uc *ContainerUsecase) Unpause(id string) error {
func (uc *ContainerUsecase) Unpause(ctx context.Context, id string) error {
sock := containerSock(uc.setting)
return uc.repo.Unpause(sock, id)
return uc.repo.Unpause(ctx, sock, id)
}
func (uc *ContainerUsecase) Kill(id string) error {
func (uc *ContainerUsecase) Kill(ctx context.Context, id string) error {
sock := containerSock(uc.setting)
return uc.repo.Kill(sock, id)
return uc.repo.Kill(ctx, sock, id)
}
func (uc *ContainerUsecase) Rename(id string, newName string) error {
func (uc *ContainerUsecase) Rename(ctx context.Context, id string, newName string) error {
sock := containerSock(uc.setting)
return uc.repo.Rename(sock, id, newName)
return uc.repo.Rename(ctx, sock, id, newName)
}
func (uc *ContainerUsecase) Logs(id string, tail int) (string, error) {
func (uc *ContainerUsecase) Logs(ctx context.Context, id string, tail int) (string, error) {
sock := containerSock(uc.setting)
return uc.repo.Logs(sock, id, tail)
return uc.repo.Logs(ctx, sock, id, tail)
}
func (uc *ContainerUsecase) Prune() error {
func (uc *ContainerUsecase) Prune(ctx context.Context) error {
sock := containerSock(uc.setting)
return uc.repo.Prune(sock)
return uc.repo.Prune(ctx, sock)
}
+17 -15
View File
@@ -1,6 +1,8 @@
package biz
import (
"context"
"github.com/leonelquinteros/gotext"
"github.com/acepanel/panel/v3/internal/request"
@@ -9,11 +11,11 @@ import (
)
type ContainerImageRepo interface {
List(sock string) ([]types.ContainerImage, error)
Exist(sock string, name string) (bool, error)
Pull(sock string, req *request.ContainerImagePull) error
Remove(sock string, id string) error
Prune(sock string) error
List(ctx context.Context, sock string) ([]types.ContainerImage, error)
Exist(ctx context.Context, sock string, name string) (bool, error)
Pull(ctx context.Context, sock string, req *request.ContainerImagePull) error
Remove(ctx context.Context, sock string, id string) error
Prune(ctx context.Context, sock string) error
}
type ContainerImageUsecase struct {
@@ -32,19 +34,19 @@ func NewContainerImageUsecase(t *gotext.Locale, containerImageRepo ContainerImag
}
}
func (uc *ContainerImageUsecase) List() ([]types.ContainerImage, error) {
func (uc *ContainerImageUsecase) List(ctx context.Context) ([]types.ContainerImage, error) {
sock := containerSock(uc.setting)
return uc.repo.List(sock)
return uc.repo.List(ctx, sock)
}
func (uc *ContainerImageUsecase) Exist(name string) (bool, error) {
func (uc *ContainerImageUsecase) Exist(ctx context.Context, name string) (bool, error) {
sock := containerSock(uc.setting)
return uc.repo.Exist(sock, name)
return uc.repo.Exist(ctx, sock, name)
}
func (uc *ContainerImageUsecase) Pull(req *request.ContainerImagePull) error {
func (uc *ContainerImageUsecase) Pull(ctx context.Context, req *request.ContainerImagePull) error {
sock := containerSock(uc.setting)
return uc.repo.Pull(sock, req)
return uc.repo.Pull(ctx, sock, req)
}
func (uc *ContainerImageUsecase) PullBackground(req *request.ContainerImagePull) error {
@@ -63,12 +65,12 @@ func (uc *ContainerImageUsecase) PullBackground(req *request.ContainerImagePull)
return uc.task.Push(task)
}
func (uc *ContainerImageUsecase) Remove(id string) error {
func (uc *ContainerImageUsecase) Remove(ctx context.Context, id string) error {
sock := containerSock(uc.setting)
return uc.repo.Remove(sock, id)
return uc.repo.Remove(ctx, sock, id)
}
func (uc *ContainerImageUsecase) Prune() error {
func (uc *ContainerImageUsecase) Prune(ctx context.Context) error {
sock := containerSock(uc.setting)
return uc.repo.Prune(sock)
return uc.repo.Prune(ctx, sock)
}
+14 -12
View File
@@ -1,15 +1,17 @@
package biz
import (
"context"
"github.com/acepanel/panel/v3/internal/request"
"github.com/acepanel/panel/v3/pkg/types"
)
type ContainerNetworkRepo interface {
List(sock string) ([]types.ContainerNetwork, error)
Create(sock string, req *request.ContainerNetworkCreate) (string, error)
Remove(sock string, id string) error
Prune(sock string) error
List(ctx context.Context, sock string) ([]types.ContainerNetwork, error)
Create(ctx context.Context, sock string, req *request.ContainerNetworkCreate) (string, error)
Remove(ctx context.Context, sock string, id string) error
Prune(ctx context.Context, sock string) error
}
type ContainerNetworkUsecase struct {
@@ -21,22 +23,22 @@ func NewContainerNetworkUsecase(repo ContainerNetworkRepo, setting SettingRepo)
return &ContainerNetworkUsecase{repo: repo, setting: setting}
}
func (uc *ContainerNetworkUsecase) List() ([]types.ContainerNetwork, error) {
func (uc *ContainerNetworkUsecase) List(ctx context.Context) ([]types.ContainerNetwork, error) {
sock := containerSock(uc.setting)
return uc.repo.List(sock)
return uc.repo.List(ctx, sock)
}
func (uc *ContainerNetworkUsecase) Create(req *request.ContainerNetworkCreate) (string, error) {
func (uc *ContainerNetworkUsecase) Create(ctx context.Context, req *request.ContainerNetworkCreate) (string, error) {
sock := containerSock(uc.setting)
return uc.repo.Create(sock, req)
return uc.repo.Create(ctx, sock, req)
}
func (uc *ContainerNetworkUsecase) Remove(id string) error {
func (uc *ContainerNetworkUsecase) Remove(ctx context.Context, id string) error {
sock := containerSock(uc.setting)
return uc.repo.Remove(sock, id)
return uc.repo.Remove(ctx, sock, id)
}
func (uc *ContainerNetworkUsecase) Prune() error {
func (uc *ContainerNetworkUsecase) Prune(ctx context.Context) error {
sock := containerSock(uc.setting)
return uc.repo.Prune(sock)
return uc.repo.Prune(ctx, sock)
}
+14 -12
View File
@@ -1,15 +1,17 @@
package biz
import (
"context"
"github.com/acepanel/panel/v3/internal/request"
"github.com/acepanel/panel/v3/pkg/types"
)
type ContainerVolumeRepo interface {
List(sock string) ([]types.ContainerVolume, error)
Create(sock string, req *request.ContainerVolumeCreate) (string, error)
Remove(sock string, id string) error
Prune(sock string) error
List(ctx context.Context, sock string) ([]types.ContainerVolume, error)
Create(ctx context.Context, sock string, req *request.ContainerVolumeCreate) (string, error)
Remove(ctx context.Context, sock string, id string) error
Prune(ctx context.Context, sock string) error
}
type ContainerVolumeUsecase struct {
@@ -21,22 +23,22 @@ func NewContainerVolumeUsecase(repo ContainerVolumeRepo, setting SettingRepo) *C
return &ContainerVolumeUsecase{repo: repo, setting: setting}
}
func (uc *ContainerVolumeUsecase) List() ([]types.ContainerVolume, error) {
func (uc *ContainerVolumeUsecase) List(ctx context.Context) ([]types.ContainerVolume, error) {
sock := containerSock(uc.setting)
return uc.repo.List(sock)
return uc.repo.List(ctx, sock)
}
func (uc *ContainerVolumeUsecase) Create(req *request.ContainerVolumeCreate) (string, error) {
func (uc *ContainerVolumeUsecase) Create(ctx context.Context, req *request.ContainerVolumeCreate) (string, error) {
sock := containerSock(uc.setting)
return uc.repo.Create(sock, req)
return uc.repo.Create(ctx, sock, req)
}
func (uc *ContainerVolumeUsecase) Remove(id string) error {
func (uc *ContainerVolumeUsecase) Remove(ctx context.Context, id string) error {
sock := containerSock(uc.setting)
return uc.repo.Remove(sock, id)
return uc.repo.Remove(ctx, sock, id)
}
func (uc *ContainerVolumeUsecase) Prune() error {
func (uc *ContainerVolumeUsecase) Prune(ctx context.Context) error {
sock := containerSock(uc.setting)
return uc.repo.Prune(sock)
return uc.repo.Prune(ctx, sock)
}
+17 -14
View File
@@ -93,7 +93,7 @@ func (uc *DatabaseUsecase) Create(ctx context.Context, req *request.DatabaseCrea
return mongoErr
}
defer mongo.Close()
if mongoErr = mongo.DatabaseCreate(req.Name); mongoErr != nil { //nolint:contextcheck
if mongoErr = mongo.DatabaseCreate(ctx, req.Name); mongoErr != nil {
return mongoErr
}
uc.log.Info("database created", slog.String("type", OperationTypeDatabase), slog.Uint64("operator_id", operatorID(ctx)), slog.String("name", req.Name), slog.Uint64("server_id", uint64(req.ServerID)))
@@ -106,6 +106,9 @@ func (uc *DatabaseUsecase) Create(ctx context.Context, req *request.DatabaseCrea
}
defer operator.Close()
// 建用户 → 建库 → 授权是一个整体,中途取消会留下空库或没有权限的用户
ctx = context.WithoutCancel(ctx)
switch server.Type {
case DatabaseTypeMysql:
if req.CreateUser {
@@ -118,19 +121,19 @@ func (uc *DatabaseUsecase) Create(ctx context.Context, req *request.DatabaseCrea
return err
}
}
if err = operator.DatabaseCreate(req.Name); err != nil {
if err = operator.DatabaseCreate(ctx, req.Name); err != nil {
return err
}
if req.Username != "" {
// 授权已有用户时按其实际 host 授权,MySQL 8 起 GRANT 不再隐式创建用户
hosts := []string{req.Host}
if !req.CreateUser {
if hosts = uc.mysqlUserHosts(operator, req.Username); len(hosts) == 0 {
if hosts = uc.mysqlUserHosts(ctx, operator, req.Username); len(hosts) == 0 {
return errors.New(uc.t.Get("database user %s does not exist", req.Username))
}
}
for _, host := range hosts {
if err = operator.PrivilegesGrant(req.Username, req.Name, host); err != nil {
if err = operator.PrivilegesGrant(ctx, req.Username, req.Name, host); err != nil {
return err
}
}
@@ -146,11 +149,11 @@ func (uc *DatabaseUsecase) Create(ctx context.Context, req *request.DatabaseCrea
return err
}
}
if err = operator.DatabaseCreate(req.Name); err != nil {
if err = operator.DatabaseCreate(ctx, req.Name); err != nil {
return err
}
if req.Username != "" {
if err = operator.PrivilegesGrant(req.Username, req.Name); err != nil {
if err = operator.PrivilegesGrant(ctx, req.Username, req.Name); err != nil {
return err
}
}
@@ -158,7 +161,7 @@ func (uc *DatabaseUsecase) Create(ctx context.Context, req *request.DatabaseCrea
if !ok {
return errors.New(uc.t.Get("%s does not support database comment", server.Type))
}
if err = pg.DatabaseComment(req.Name, req.Comment); err != nil { //nolint:contextcheck
if err = pg.DatabaseComment(ctx, req.Name, req.Comment); err != nil {
return err
}
case DatabaseTypeClickHouse:
@@ -171,11 +174,11 @@ func (uc *DatabaseUsecase) Create(ctx context.Context, req *request.DatabaseCrea
return err
}
}
if err = operator.DatabaseCreate(req.Name); err != nil {
if err = operator.DatabaseCreate(ctx, req.Name); err != nil {
return err
}
if req.Username != "" {
if err = operator.PrivilegesGrant(req.Username, req.Name); err != nil {
if err = operator.PrivilegesGrant(ctx, req.Username, req.Name); err != nil {
return err
}
}
@@ -189,8 +192,8 @@ func (uc *DatabaseUsecase) Create(ctx context.Context, req *request.DatabaseCrea
}
// mysqlUserHosts 查询 MySQL 用户实际存在的 host 列表
func (uc *DatabaseUsecase) mysqlUserHosts(operator db.Operator, user string) []string {
rows, err := operator.Query("SELECT host FROM mysql.user WHERE user = ?", user)
func (uc *DatabaseUsecase) mysqlUserHosts(ctx context.Context, operator db.Operator, user string) []string {
rows, err := operator.Query(ctx, "SELECT host FROM mysql.user WHERE user = ?", user)
if err != nil {
return nil
}
@@ -219,7 +222,7 @@ func (uc *DatabaseUsecase) Delete(ctx context.Context, serverID uint, name strin
return mongoErr
}
defer mongo.Close()
if mongoErr = mongo.DatabaseDrop(name); mongoErr != nil { //nolint:contextcheck
if mongoErr = mongo.DatabaseDrop(ctx, name); mongoErr != nil {
return mongoErr
}
case DatabaseTypeSQLite:
@@ -230,7 +233,7 @@ func (uc *DatabaseUsecase) Delete(ctx context.Context, serverID uint, name strin
return opErr
}
defer operator.Close()
if opErr = operator.DatabaseDrop(name); opErr != nil {
if opErr = operator.DatabaseDrop(ctx, name); opErr != nil {
return opErr
}
}
@@ -258,7 +261,7 @@ func (uc *DatabaseUsecase) Comment(ctx context.Context, req *request.DatabaseCom
if !ok {
return errors.New(uc.t.Get("%s does not support database comment", server.Type))
}
return pg.DatabaseComment(req.Name, req.Comment) //nolint:contextcheck
return pg.DatabaseComment(ctx, req.Name, req.Comment)
default:
return errors.New(uc.t.Get("%s does not support database comment", server.Type))
}
+3 -3
View File
@@ -199,7 +199,7 @@ func (uc *DatabaseServerUsecase) Sync(ctx context.Context, id uint) error {
switch server.Type {
case DatabaseTypeMysql:
allUsers, err := operator.Users()
allUsers, err := operator.Users(ctx)
if err != nil {
return err
}
@@ -219,7 +219,7 @@ func (uc *DatabaseServerUsecase) Sync(ctx context.Context, id uint) error {
}
}
case DatabaseTypePostgresql:
allUsers, err := operator.Users()
allUsers, err := operator.Users(ctx)
if err != nil {
return err
}
@@ -238,7 +238,7 @@ func (uc *DatabaseServerUsecase) Sync(ctx context.Context, id uint) error {
}
}
case DatabaseTypeClickHouse:
allUsers, err := operator.Users()
allUsers, err := operator.Users(ctx)
if err != nil {
return err
}
+21 -11
View File
@@ -116,17 +116,20 @@ func (uc *DatabaseUserUsecase) Create(ctx context.Context, req *request.Database
}
defer operator.Close()
// 建用户 → 建库 → 授权 → 落库是一个整体,中途取消会留下没有权限的用户
ctx = context.WithoutCancel(ctx)
// 创建用户
if err = operator.UserCreate(req.Username, req.Password, req.Host); err != nil {
if err = operator.UserCreate(ctx, req.Username, req.Password, req.Host); err != nil {
return err
}
// 创建数据库并授权
for name := range slices.Values(req.Privileges) {
if err = operator.DatabaseCreate(name); err != nil {
if err = operator.DatabaseCreate(ctx, name); err != nil {
return err
}
if err = operator.PrivilegesGrant(req.Username, name, req.Host); err != nil {
if err = operator.PrivilegesGrant(ctx, req.Username, name, req.Host); err != nil {
return err
}
}
@@ -166,28 +169,31 @@ func (uc *DatabaseUserUsecase) Update(ctx context.Context, req *request.Database
}
defer operator.Close()
// 改密码 → 撤权 → 重新授权 → 落库是一个整体,中途取消会让面板记录与实际权限不一致
ctx = context.WithoutCancel(ctx)
// 更新密码
if req.Password != "" {
if err = operator.UserPassword(user.Username, req.Password, user.Host); err != nil {
if err = operator.UserPassword(ctx, user.Username, req.Password, user.Host); err != nil {
return err
}
user.Password = req.Password
}
// 撤销被移除的权限
currentPrivileges, _ := operator.UserPrivileges(user.Username, user.Host)
currentPrivileges, _ := operator.UserPrivileges(ctx, user.Username, user.Host)
for name := range slices.Values(currentPrivileges) {
if !slices.Contains(req.Privileges, name) {
_ = operator.PrivilegesRevoke(user.Username, name, user.Host)
_ = operator.PrivilegesRevoke(ctx, user.Username, name, user.Host)
}
}
// 创建数据库并授权
for name := range slices.Values(req.Privileges) {
if err = operator.DatabaseCreate(name); err != nil {
if err = operator.DatabaseCreate(ctx, name); err != nil {
return err
}
if err = operator.PrivilegesGrant(user.Username, name, user.Host); err != nil {
if err = operator.PrivilegesGrant(ctx, user.Username, name, user.Host); err != nil {
return err
}
}
@@ -218,7 +224,8 @@ func (uc *DatabaseUserUsecase) Delete(ctx context.Context, id uint) error {
}
defer operator.Close()
_ = operator.UserDrop(user.Username, user.Host)
// 取消会让面板记录已删而引擎里的用户残留
_ = operator.UserDrop(context.WithoutCancel(ctx), user.Username, user.Host)
if err = uc.repo.DeleteByID(id); err != nil {
return err
@@ -242,6 +249,9 @@ func (uc *DatabaseUserUsecase) DeleteByNames(ctx context.Context, serverID uint,
}
defer operator.Close()
// 取消会让面板记录已删而引擎里的用户残留
ctx = context.WithoutCancel(ctx)
switch server.Type {
case DatabaseTypeMysql:
users, err := uc.repo.ListByNames(serverID, names)
@@ -256,11 +266,11 @@ func (uc *DatabaseUserUsecase) DeleteByNames(ctx context.Context, serverID uint,
break
}
}
_ = operator.UserDrop(name, host)
_ = operator.UserDrop(ctx, name, host)
}
case DatabaseTypePostgresql, DatabaseTypeClickHouse:
for name := range slices.Values(names) {
_ = operator.UserDrop(name)
_ = operator.UserDrop(ctx, name)
}
default:
}
+25 -17
View File
@@ -353,7 +353,7 @@ func (r *backupRepo) CutoffLog(ctx context.Context, path, target string) (string
}
// CutoffUpload 将指定的切割日志文件上传到远程存储
func (r *backupRepo) CutoffUpload(account uint, typ biz.BackupType, name string, files []string) error {
func (r *backupRepo) CutoffUpload(ctx context.Context, account uint, typ biz.BackupType, name string, files []string) error {
backupStorage, err := r.GetStorage(account)
if err != nil {
return err
@@ -370,7 +370,7 @@ func (r *backupRepo) CutoffUpload(account uint, typ biz.BackupType, name string,
return err
}
remotePath := filepath.Join("cutoff", string(typ), name, filepath.Base(localPath))
if putErr := client.Put(remotePath, file); putErr != nil {
if putErr := r.upload(ctx, client, remotePath, file); putErr != nil {
_ = file.Close()
return putErr
}
@@ -434,7 +434,7 @@ func (r *backupRepo) ClearExpired(path, prefix string, save uint) error {
// dir 存储器内的目标目录,备份为 <类型>,切割日志为 cutoff/<类型>/<目标>
// prefix 目标文件前缀
// save 保存份数
func (r *backupRepo) ClearStorageExpired(storage uint, dir, prefix string, save uint) error {
func (r *backupRepo) ClearStorageExpired(ctx context.Context, storage uint, dir, prefix string, save uint) error {
backupStorage, err := r.GetStorage(storage)
if err != nil {
return err
@@ -445,7 +445,7 @@ func (r *backupRepo) ClearStorageExpired(storage uint, dir, prefix string, save
return err
}
files, err := client.List(dir)
files, err := client.List(ctx, dir)
if err != nil {
return err
}
@@ -457,7 +457,7 @@ func (r *backupRepo) ClearStorageExpired(storage uint, dir, prefix string, save
var filtered []fileInfo
for _, file := range files {
if strings.HasPrefix(file, prefix) && r.isBackupArchive(file) {
lastModified, modErr := client.LastModified(filepath.Join(dir, file))
lastModified, modErr := client.LastModified(ctx, filepath.Join(dir, file))
if modErr != nil {
continue
}
@@ -480,13 +480,15 @@ func (r *backupRepo) ClearStorageExpired(storage uint, dir, prefix string, save
}
// 切片保留 save 份,删除剩余
// 已判定过期的文件删到一半就停会留下无人认领的残留,这段不可取消
deleteCtx := context.WithoutCancel(ctx)
toDelete := filtered[save:]
for _, file := range toDelete {
filePath := filepath.Join(dir, file.name)
if app.IsCli {
fmt.Println(r.t.Get("|-Cleaning expired file: %s", filePath))
}
if err = client.Delete(filePath); err != nil {
if err = client.Delete(deleteCtx, filePath); err != nil {
return errors.New(r.t.Get("Cleanup failed: %v", err))
}
}
@@ -494,6 +496,12 @@ func (r *backupRepo) ClearStorageExpired(storage uint, dir, prefix string, save
return nil
}
// upload 上传备份文件到存储器
// 上传中途取消会在远端留下截断的文件,而过期清理只按前缀和后缀识别备份,会把它当成有效备份计入保留份数
func (r *backupRepo) upload(ctx context.Context, client storage.Storage, path string, content stdio.Reader) error {
return client.Put(context.WithoutCancel(ctx), path, content)
}
// getStorage 获取存储器
func (r *backupRepo) getStorage(backupStorage biz.BackupStorage) (storage.Storage, error) {
switch backupStorage.Type {
@@ -562,7 +570,7 @@ func (r *backupRepo) createWebsite(ctx context.Context, name string, storage sto
}
defer func(file *os.File) { _ = file.Close() }(file)
if err = storage.Put(filepath.Join(string(biz.BackupTypeWebsite), name), file); err != nil {
if err = r.upload(ctx, storage, filepath.Join(string(biz.BackupTypeWebsite), name), file); err != nil {
return err
}
@@ -584,7 +592,7 @@ func (r *backupRepo) createMySQL(ctx context.Context, name string, storage stora
return err
}
defer mysql.Close()
if exist, _ := mysql.DatabaseExists(target); !exist {
if exist, _ := mysql.DatabaseExists(ctx, target); !exist {
return errors.New(r.t.Get("database does not exist: %s", target))
}
@@ -602,7 +610,7 @@ func (r *backupRepo) createMySQL(ctx context.Context, name string, storage stora
// 导出数据库
var gtidMode string
dumpArgs := "--single-transaction --quick --routines --events --max-allowed-packet=1G"
if mysql.QueryRow(`SELECT @@gtid_mode`).Scan(&gtidMode) == nil {
if mysql.QueryRow(ctx, `SELECT @@gtid_mode`).Scan(&gtidMode) == nil {
dumpArgs += " --set-gtid-purged=OFF"
}
name += ".sql"
@@ -629,7 +637,7 @@ func (r *backupRepo) createMySQL(ctx context.Context, name string, storage stora
}
defer func(file *os.File) { _ = file.Close() }(file)
if err = storage.Put(filepath.Join(string(biz.BackupTypeMySQL), name), file); err != nil {
if err = r.upload(ctx, storage, filepath.Join(string(biz.BackupTypeMySQL), name), file); err != nil {
return err
}
@@ -652,7 +660,7 @@ func (r *backupRepo) createPostgres(ctx context.Context, name string, storage st
return err
}
defer postgres.Close()
if exist, _ := postgres.DatabaseExists(target); !exist {
if exist, _ := postgres.DatabaseExists(ctx, target); !exist {
return errors.New(r.t.Get("database does not exist: %s", target))
}
@@ -692,7 +700,7 @@ func (r *backupRepo) createPostgres(ctx context.Context, name string, storage st
}
defer func(file *os.File) { _ = file.Close() }(file)
if err = storage.Put(filepath.Join(string(biz.BackupTypePostgres), name), file); err != nil {
if err = r.upload(ctx, storage, filepath.Join(string(biz.BackupTypePostgres), name), file); err != nil {
return err
}
@@ -785,7 +793,7 @@ func (r *backupRepo) createClickHouse(ctx context.Context, name string, storage
}
defer func(file *os.File) { _ = file.Close() }(file)
if err = storage.Put(filepath.Join(string(biz.BackupTypeClickHouse), name), file); err != nil {
if err = r.upload(ctx, storage, filepath.Join(string(biz.BackupTypeClickHouse), name), file); err != nil {
return err
}
@@ -849,7 +857,7 @@ func (r *backupRepo) createPath(ctx context.Context, name string, storage storag
}
defer func(file *os.File) { _ = file.Close() }(file)
if err = storage.Put(filepath.Join(string(biz.BackupTypePath), name), file); err != nil {
if err = r.upload(ctx, storage, filepath.Join(string(biz.BackupTypePath), name), file); err != nil {
return err
}
@@ -969,7 +977,7 @@ func (r *backupRepo) restoreMySQL(ctx context.Context, backup, target string) er
return err
}
defer mysql.Close()
if exist, _ := mysql.DatabaseExists(target); !exist {
if exist, _ := mysql.DatabaseExists(ctx, target); !exist {
return errors.New(r.t.Get("database does not exist: %s", target))
}
@@ -1002,7 +1010,7 @@ func (r *backupRepo) restorePostgres(ctx context.Context, backup, target string)
return err
}
defer postgres.Close()
if exist, _ := postgres.DatabaseExists(target); !exist {
if exist, _ := postgres.DatabaseExists(ctx, target); !exist {
return errors.New(r.t.Get("database does not exist: %s", target))
}
@@ -1214,7 +1222,7 @@ func (r *backupRepo) createRedisLike(ctx context.Context, name string, storage s
}
defer func(file *os.File) { _ = file.Close() }(file)
if err = storage.Put(filepath.Join(kind, name), file); err != nil {
if err = r.upload(ctx, storage, filepath.Join(kind, name), file); err != nil {
return err
}
+31 -27
View File
@@ -29,14 +29,14 @@ func NewContainerRepo() biz.ContainerRepo {
}
// ListAll 列出所有容器
func (r *containerRepo) ListAll(sock string) ([]types.Container, error) {
func (r *containerRepo) ListAll(ctx context.Context, sock string) ([]types.Container, error) {
apiClient, err := getDockerClient(sock)
if err != nil {
return nil, err
}
defer func(apiClient *client.Client) { _ = apiClient.Close() }(apiClient)
resp, err := apiClient.ContainerList(context.Background(), client.ContainerListOptions{
resp, err := apiClient.ContainerList(ctx, client.ContainerListOptions{
All: true,
})
if err != nil {
@@ -114,14 +114,14 @@ func (r *containerRepo) ListAll(sock string) ([]types.Container, error) {
}
// Inspect 获取容器详细信息
func (r *containerRepo) Inspect(sock string, id string) (any, error) {
func (r *containerRepo) Inspect(ctx context.Context, sock string, id string) (any, error) {
apiClient, err := getDockerClient(sock)
if err != nil {
return nil, err
}
defer func(apiClient *client.Client) { _ = apiClient.Close() }(apiClient)
resp, err := apiClient.ContainerInspect(context.Background(), id, client.ContainerInspectOptions{})
resp, err := apiClient.ContainerInspect(ctx, id, client.ContainerInspectOptions{})
if err != nil {
return nil, err
}
@@ -130,14 +130,15 @@ func (r *containerRepo) Inspect(sock string, id string) (any, error) {
}
// Create 创建容器
func (r *containerRepo) Create(sock string, req *request.ContainerCreate) (string, error) {
func (r *containerRepo) Create(ctx context.Context, sock string, req *request.ContainerCreate) (string, error) {
apiClient, err := getDockerClient(sock)
if err != nil {
return "", err
}
defer func(apiClient *client.Client) { _ = apiClient.Close() }(apiClient)
ctx := context.Background()
// 创建后紧接着启动,中途取消会留下已创建未启动的容器
ctx = context.WithoutCancel(ctx)
// 获取镜像信息
image, err := apiClient.ImageInspect(ctx, req.Image)
@@ -295,109 +296,111 @@ func (r *containerRepo) Create(sock string, req *request.ContainerCreate) (strin
}
// Remove 移除容器
func (r *containerRepo) Remove(sock string, id string) error {
func (r *containerRepo) Remove(ctx context.Context, sock string, id string) error {
apiClient, err := getDockerClient(sock)
if err != nil {
return err
}
defer func(apiClient *client.Client) { _ = apiClient.Close() }(apiClient)
_, err = apiClient.ContainerRemove(context.Background(), id, client.ContainerRemoveOptions{
// 中途取消会把容器留在删除中的半状态
_, err = apiClient.ContainerRemove(context.WithoutCancel(ctx), id, client.ContainerRemoveOptions{
Force: true,
})
return err
}
// Start 启动容器
func (r *containerRepo) Start(sock string, id string) error {
func (r *containerRepo) Start(ctx context.Context, sock string, id string) error {
apiClient, err := getDockerClient(sock)
if err != nil {
return err
}
defer func(apiClient *client.Client) { _ = apiClient.Close() }(apiClient)
_, err = apiClient.ContainerStart(context.Background(), id, client.ContainerStartOptions{})
_, err = apiClient.ContainerStart(ctx, id, client.ContainerStartOptions{})
return err
}
// Stop 停止容器
func (r *containerRepo) Stop(sock string, id string) error {
func (r *containerRepo) Stop(ctx context.Context, sock string, id string) error {
apiClient, err := getDockerClient(sock)
if err != nil {
return err
}
defer func(apiClient *client.Client) { _ = apiClient.Close() }(apiClient)
_, err = apiClient.ContainerStop(context.Background(), id, client.ContainerStopOptions{})
_, err = apiClient.ContainerStop(ctx, id, client.ContainerStopOptions{})
return err
}
// Restart 重启容器
func (r *containerRepo) Restart(sock string, id string) error {
func (r *containerRepo) Restart(ctx context.Context, sock string, id string) error {
apiClient, err := getDockerClient(sock)
if err != nil {
return err
}
defer func(apiClient *client.Client) { _ = apiClient.Close() }(apiClient)
_, err = apiClient.ContainerRestart(context.Background(), id, client.ContainerRestartOptions{})
// 内部先停后启,中途取消会把容器留在停止状态
_, err = apiClient.ContainerRestart(context.WithoutCancel(ctx), id, client.ContainerRestartOptions{})
return err
}
// Pause 暂停容器
func (r *containerRepo) Pause(sock string, id string) error {
func (r *containerRepo) Pause(ctx context.Context, sock string, id string) error {
apiClient, err := getDockerClient(sock)
if err != nil {
return err
}
defer func(apiClient *client.Client) { _ = apiClient.Close() }(apiClient)
_, err = apiClient.ContainerPause(context.Background(), id, client.ContainerPauseOptions{})
_, err = apiClient.ContainerPause(ctx, id, client.ContainerPauseOptions{})
return err
}
// Unpause 恢复容器
func (r *containerRepo) Unpause(sock string, id string) error {
func (r *containerRepo) Unpause(ctx context.Context, sock string, id string) error {
apiClient, err := getDockerClient(sock)
if err != nil {
return err
}
defer func(apiClient *client.Client) { _ = apiClient.Close() }(apiClient)
_, err = apiClient.ContainerUnpause(context.Background(), id, client.ContainerUnpauseOptions{})
_, err = apiClient.ContainerUnpause(ctx, id, client.ContainerUnpauseOptions{})
return err
}
// Kill 杀死容器
func (r *containerRepo) Kill(sock string, id string) error {
func (r *containerRepo) Kill(ctx context.Context, sock string, id string) error {
apiClient, err := getDockerClient(sock)
if err != nil {
return err
}
defer func(apiClient *client.Client) { _ = apiClient.Close() }(apiClient)
_, err = apiClient.ContainerKill(context.Background(), id, client.ContainerKillOptions{
_, err = apiClient.ContainerKill(ctx, id, client.ContainerKillOptions{
Signal: "KILL",
})
return err
}
// Rename 重命名容器
func (r *containerRepo) Rename(sock string, id string, newName string) error {
func (r *containerRepo) Rename(ctx context.Context, sock string, id string, newName string) error {
apiClient, err := getDockerClient(sock)
if err != nil {
return err
}
defer func(apiClient *client.Client) { _ = apiClient.Close() }(apiClient)
_, err = apiClient.ContainerRename(context.Background(), id, client.ContainerRenameOptions{
_, err = apiClient.ContainerRename(ctx, id, client.ContainerRenameOptions{
NewName: newName,
})
return err
}
// Logs 查看容器末尾 tail 行日志
func (r *containerRepo) Logs(sock string, id string, tail int) (string, error) {
func (r *containerRepo) Logs(ctx context.Context, sock string, id string, tail int) (string, error) {
apiClient, err := getDockerClient(sock)
if err != nil {
return "", err
@@ -405,13 +408,13 @@ func (r *containerRepo) Logs(sock string, id string, tail int) (string, error) {
defer func(apiClient *client.Client) { _ = apiClient.Close() }(apiClient)
// 非 TTY 容器日志为多路复用流,需按 TTY 设置决定是否解复用
inspect, err := apiClient.ContainerInspect(context.Background(), id, client.ContainerInspectOptions{})
inspect, err := apiClient.ContainerInspect(ctx, id, client.ContainerInspectOptions{})
if err != nil {
return "", err
}
tty := inspect.Container.Config != nil && inspect.Container.Config.Tty
reader, err := apiClient.ContainerLogs(context.Background(), id, client.ContainerLogsOptions{
reader, err := apiClient.ContainerLogs(ctx, id, client.ContainerLogsOptions{
ShowStdout: true,
ShowStderr: true,
Tail: strconv.Itoa(tail),
@@ -430,14 +433,15 @@ func (r *containerRepo) Logs(sock string, id string, tail int) (string, error) {
}
// Prune 清理未使用的容器
func (r *containerRepo) Prune(sock string) error {
func (r *containerRepo) Prune(ctx context.Context, sock string) error {
apiClient, err := getDockerClient(sock)
if err != nil {
return err
}
defer func(apiClient *client.Client) { _ = apiClient.Close() }(apiClient)
_, err = apiClient.ContainerPrune(context.Background(), client.ContainerPruneOptions{
// 中途取消会留下清理到一半的状态
_, err = apiClient.ContainerPrune(context.WithoutCancel(ctx), client.ContainerPruneOptions{
Filters: make(client.Filters).Add("label", "created_by!=acepanel"),
})
return err
+13 -11
View File
@@ -27,14 +27,14 @@ func NewContainerImageRepo() biz.ContainerImageRepo {
}
// List 列出镜像
func (r *containerImageRepo) List(sock string) ([]types.ContainerImage, error) {
func (r *containerImageRepo) List(ctx context.Context, sock string) ([]types.ContainerImage, error) {
apiClient, err := getDockerClient(sock)
if err != nil {
return nil, err
}
defer func(apiClient *client.Client) { _ = apiClient.Close() }(apiClient)
resp, err := apiClient.ImageList(context.Background(), client.ImageListOptions{
resp, err := apiClient.ImageList(ctx, client.ImageListOptions{
All: true,
})
if err != nil {
@@ -61,14 +61,14 @@ func (r *containerImageRepo) List(sock string) ([]types.ContainerImage, error) {
}
// Exist 检查镜像是否存在
func (r *containerImageRepo) Exist(sock string, name string) (bool, error) {
func (r *containerImageRepo) Exist(ctx context.Context, sock string, name string) (bool, error) {
apiClient, err := getDockerClient(sock)
if err != nil {
return false, err
}
defer func(apiClient *client.Client) { _ = apiClient.Close() }(apiClient)
_, err = apiClient.ImageInspect(context.Background(), name)
_, err = apiClient.ImageInspect(ctx, name)
if err != nil {
if cerrdefs.IsNotFound(err) {
return false, nil
@@ -80,7 +80,7 @@ func (r *containerImageRepo) Exist(sock string, name string) (bool, error) {
}
// Pull 拉取镜像
func (r *containerImageRepo) Pull(sock string, req *request.ContainerImagePull) error {
func (r *containerImageRepo) Pull(ctx context.Context, sock string, req *request.ContainerImagePull) error {
apiClient, err := getDockerClient(sock)
if err != nil {
return err
@@ -101,24 +101,25 @@ func (r *containerImageRepo) Pull(sock string, req *request.ContainerImagePull)
options.RegistryAuth = authStr
}
out, err := apiClient.ImagePull(context.Background(), req.Name, options)
out, err := apiClient.ImagePull(ctx, req.Name, options)
if err != nil {
return err
}
defer func(out client.ImagePullResponse) { _ = out.Close() }(out)
return out.Wait(context.Background())
return out.Wait(ctx)
}
// Remove 删除镜像
func (r *containerImageRepo) Remove(sock string, id string) error {
func (r *containerImageRepo) Remove(ctx context.Context, sock string, id string) error {
apiClient, err := getDockerClient(sock)
if err != nil {
return err
}
defer func(apiClient *client.Client) { _ = apiClient.Close() }(apiClient)
_, err = apiClient.ImageRemove(context.Background(), id, client.ImageRemoveOptions{
// 级联删除父层,中途取消会留下删了一半的镜像链
_, err = apiClient.ImageRemove(context.WithoutCancel(ctx), id, client.ImageRemoveOptions{
Force: true,
PruneChildren: true,
})
@@ -126,14 +127,15 @@ func (r *containerImageRepo) Remove(sock string, id string) error {
}
// Prune 清理未使用的镜像
func (r *containerImageRepo) Prune(sock string) error {
func (r *containerImageRepo) Prune(ctx context.Context, sock string) error {
apiClient, err := getDockerClient(sock)
if err != nil {
return err
}
defer func(apiClient *client.Client) { _ = apiClient.Close() }(apiClient)
_, err = apiClient.ImagePrune(context.Background(), client.ImagePruneOptions{
// 中途取消会留下清理到一半的状态
_, err = apiClient.ImagePrune(context.WithoutCancel(ctx), client.ImagePruneOptions{
Filters: make(client.Filters).
Add("dangling", "false").
Add("label", "created_by!=acepanel"),
+11 -9
View File
@@ -23,14 +23,14 @@ func NewContainerNetworkRepo() biz.ContainerNetworkRepo {
}
// List 列出网络
func (r *containerNetworkRepo) List(sock string) ([]types.ContainerNetwork, error) {
func (r *containerNetworkRepo) List(ctx context.Context, sock string) ([]types.ContainerNetwork, error) {
apiClient, err := getDockerClient(sock)
if err != nil {
return nil, err
}
defer func(apiClient *client.Client) { _ = apiClient.Close() }(apiClient)
resp, err := apiClient.NetworkList(context.Background(), client.NetworkListOptions{})
resp, err := apiClient.NetworkList(ctx, client.NetworkListOptions{})
if err != nil {
return nil, err
}
@@ -74,7 +74,7 @@ func (r *containerNetworkRepo) List(sock string) ([]types.ContainerNetwork, erro
}
// Create 创建网络
func (r *containerNetworkRepo) Create(sock string, req *request.ContainerNetworkCreate) (string, error) {
func (r *containerNetworkRepo) Create(ctx context.Context, sock string, req *request.ContainerNetworkCreate) (string, error) {
apiClient, err := getDockerClient(sock)
if err != nil {
return "", err
@@ -140,7 +140,7 @@ func (r *containerNetworkRepo) Create(sock string, req *request.ContainerNetwork
}
}
resp, err := apiClient.NetworkCreate(context.Background(), req.Name, options)
resp, err := apiClient.NetworkCreate(ctx, req.Name, options)
if err != nil {
return "", err
}
@@ -149,7 +149,7 @@ func (r *containerNetworkRepo) Create(sock string, req *request.ContainerNetwork
}
// Remove 删除网络
func (r *containerNetworkRepo) Remove(sock string, id string) error {
func (r *containerNetworkRepo) Remove(ctx context.Context, sock string, id string) error {
apiClient, err := getDockerClient(sock)
if err != nil {
return err
@@ -157,7 +157,7 @@ func (r *containerNetworkRepo) Remove(sock string, id string) error {
defer func(apiClient *client.Client) { _ = apiClient.Close() }(apiClient)
// 拦截受保护网络的删除
info, err := apiClient.NetworkInspect(context.Background(), id, client.NetworkInspectOptions{})
info, err := apiClient.NetworkInspect(ctx, id, client.NetworkInspectOptions{})
if err != nil {
return err
}
@@ -165,19 +165,21 @@ func (r *containerNetworkRepo) Remove(sock string, id string) error {
return errors.New("cannot delete acepanel-network")
}
_, err = apiClient.NetworkRemove(context.Background(), id, client.NetworkRemoveOptions{})
// 中途取消会留下拆到一半的网络
_, err = apiClient.NetworkRemove(context.WithoutCancel(ctx), id, client.NetworkRemoveOptions{})
return err
}
// Prune 清理未使用的网络
func (r *containerNetworkRepo) Prune(sock string) error {
func (r *containerNetworkRepo) Prune(ctx context.Context, sock string) error {
apiClient, err := getDockerClient(sock)
if err != nil {
return err
}
defer func(apiClient *client.Client) { _ = apiClient.Close() }(apiClient)
_, err = apiClient.NetworkPrune(context.Background(), client.NetworkPruneOptions{
// 中途取消会留下清理到一半的状态
_, err = apiClient.NetworkPrune(context.WithoutCancel(ctx), client.NetworkPruneOptions{
Filters: make(client.Filters).Add("label", "created_by!=acepanel"),
})
return err
+10 -8
View File
@@ -21,14 +21,14 @@ func NewContainerVolumeRepo() biz.ContainerVolumeRepo {
}
// List 列出存储卷
func (r *containerVolumeRepo) List(sock string) ([]types.ContainerVolume, error) {
func (r *containerVolumeRepo) List(ctx context.Context, sock string) ([]types.ContainerVolume, error) {
apiClient, err := getDockerClient(sock)
if err != nil {
return nil, err
}
defer func(apiClient *client.Client) { _ = apiClient.Close() }(apiClient)
resp, err := apiClient.VolumeList(context.Background(), client.VolumeListOptions{})
resp, err := apiClient.VolumeList(ctx, client.VolumeListOptions{})
if err != nil {
return nil, err
}
@@ -63,14 +63,14 @@ func (r *containerVolumeRepo) List(sock string) ([]types.ContainerVolume, error)
}
// Create 创建存储卷
func (r *containerVolumeRepo) Create(sock string, req *request.ContainerVolumeCreate) (string, error) {
func (r *containerVolumeRepo) Create(ctx context.Context, sock string, req *request.ContainerVolumeCreate) (string, error) {
apiClient, err := getDockerClient(sock)
if err != nil {
return "", err
}
defer func(apiClient *client.Client) { _ = apiClient.Close() }(apiClient)
resp, err := apiClient.VolumeCreate(context.Background(), client.VolumeCreateOptions{
resp, err := apiClient.VolumeCreate(ctx, client.VolumeCreateOptions{
Name: req.Name,
Driver: req.Driver,
DriverOpts: types.KVToMap(req.Options),
@@ -84,28 +84,30 @@ func (r *containerVolumeRepo) Create(sock string, req *request.ContainerVolumeCr
}
// Remove 删除存储卷
func (r *containerVolumeRepo) Remove(sock string, id string) error {
func (r *containerVolumeRepo) Remove(ctx context.Context, sock string, id string) error {
apiClient, err := getDockerClient(sock)
if err != nil {
return err
}
defer func(apiClient *client.Client) { _ = apiClient.Close() }(apiClient)
_, err = apiClient.VolumeRemove(context.Background(), id, client.VolumeRemoveOptions{
// 中途取消会留下元数据已删但磁盘数据仍在的卷
_, err = apiClient.VolumeRemove(context.WithoutCancel(ctx), id, client.VolumeRemoveOptions{
Force: true,
})
return err
}
// Prune 清理未使用的存储卷
func (r *containerVolumeRepo) Prune(sock string) error {
func (r *containerVolumeRepo) Prune(ctx context.Context, sock string) error {
apiClient, err := getDockerClient(sock)
if err != nil {
return err
}
defer func(apiClient *client.Client) { _ = apiClient.Close() }(apiClient)
_, err = apiClient.VolumePrune(context.Background(), client.VolumePruneOptions{
// 中途取消会留下清理到一半的状态
_, err = apiClient.VolumePrune(context.WithoutCancel(ctx), client.VolumePruneOptions{
Filters: make(client.Filters).Add("label", "created_by!=acepanel"),
})
return err
+4 -4
View File
@@ -43,7 +43,7 @@ func (r *databaseRepo) DatabasesOf(ctx context.Context, server *biz.DatabaseServ
if err != nil {
return nil, err
}
if databases, err := mongo.Databases(); err == nil { //nolint:contextcheck
if databases, err := mongo.Databases(ctx); err == nil {
for item := range slices.Values(databases) {
database = append(database, &biz.Database{
Type: server.Type,
@@ -55,11 +55,11 @@ func (r *databaseRepo) DatabasesOf(ctx context.Context, server *biz.DatabaseServ
}
mongo.Close()
case biz.DatabaseTypeSQLite:
sqlite, err := db.NewSQLite(server.Host) //nolint:contextcheck
sqlite, err := db.NewSQLite(ctx, server.Host)
if err != nil {
return nil, err
}
if tables, err := sqlite.Tables(); err == nil { //nolint:contextcheck
if tables, err := sqlite.Tables(ctx); err == nil {
for table := range slices.Values(tables) {
database = append(database, &biz.Database{
Type: server.Type,
@@ -75,7 +75,7 @@ func (r *databaseRepo) DatabasesOf(ctx context.Context, server *biz.DatabaseServ
if err != nil {
return nil, err
}
if databases, err := operator.Databases(); err == nil {
if databases, err := operator.Databases(ctx); err == nil {
for item := range slices.Values(databases) {
database = append(database, &biz.Database{
Type: server.Type,
+8 -8
View File
@@ -35,7 +35,7 @@ func (r *databaseElasticsearchRepo) Indices(ctx context.Context, req *request.Da
}
defer client.Close()
return client.Indices()
return client.Indices(ctx)
}
func (r *databaseElasticsearchRepo) IndexCreate(ctx context.Context, req *request.DatabaseESIndexCreate) error {
@@ -45,7 +45,7 @@ func (r *databaseElasticsearchRepo) IndexCreate(ctx context.Context, req *reques
}
defer client.Close()
return client.IndexCreate(req.Name)
return client.IndexCreate(ctx, req.Name)
}
func (r *databaseElasticsearchRepo) IndexDelete(ctx context.Context, req *request.DatabaseESIndexDelete) error {
@@ -55,7 +55,7 @@ func (r *databaseElasticsearchRepo) IndexDelete(ctx context.Context, req *reques
}
defer client.Close()
return client.IndexDelete(req.Name)
return client.IndexDelete(ctx, req.Name)
}
func (r *databaseElasticsearchRepo) Data(ctx context.Context, req *request.DatabaseESData) ([]db.ESDocument, int64, error) {
@@ -65,7 +65,7 @@ func (r *databaseElasticsearchRepo) Data(ctx context.Context, req *request.Datab
}
defer client.Close()
return client.Search(req.Index, req.Search, int(req.Page), int(req.Limit))
return client.Search(ctx, req.Index, req.Search, int(req.Page), int(req.Limit))
}
func (r *databaseElasticsearchRepo) DocumentGet(ctx context.Context, req *request.DatabaseESDocumentGet) (*db.ESDocument, error) {
@@ -75,7 +75,7 @@ func (r *databaseElasticsearchRepo) DocumentGet(ctx context.Context, req *reques
}
defer client.Close()
return client.DocumentGet(req.Index, req.ID)
return client.DocumentGet(ctx, req.Index, req.ID)
}
func (r *databaseElasticsearchRepo) DocumentSet(ctx context.Context, req *request.DatabaseESDocumentSet) error {
@@ -86,9 +86,9 @@ func (r *databaseElasticsearchRepo) DocumentSet(ctx context.Context, req *reques
defer client.Close()
if req.ID == "" {
return client.DocumentCreate(req.Index, req.Body)
return client.DocumentCreate(ctx, req.Index, req.Body)
}
return client.DocumentUpdate(req.Index, req.ID, req.Body)
return client.DocumentUpdate(ctx, req.Index, req.ID, req.Body)
}
func (r *databaseElasticsearchRepo) DocumentDelete(ctx context.Context, req *request.DatabaseESDocumentDelete) error {
@@ -98,7 +98,7 @@ func (r *databaseElasticsearchRepo) DocumentDelete(ctx context.Context, req *req
}
defer client.Close()
return client.DocumentDelete(req.Index, req.ID)
return client.DocumentDelete(ctx, req.Index, req.ID)
}
// getClient 根据服务器 ID 创建 Elasticsearch 客户端
+1 -1
View File
@@ -146,7 +146,7 @@ func (r *databaseServerRepo) CheckServer(ctx context.Context, server *biz.Databa
return true
}
case biz.DatabaseTypeSQLite:
sqlite, err := db.NewSQLite(server.Host) //nolint:contextcheck
sqlite, err := db.NewSQLite(ctx, server.Host)
if err == nil {
sqlite.Close()
server.Status = biz.DatabaseServerStatusValid
+3 -3
View File
@@ -152,7 +152,7 @@ func (r *databaseUserRepo) fillUser(ctx context.Context, user *biz.DatabaseUser)
switch server.Type {
case biz.DatabaseTypeMysql:
privileges, _ := operator.UserPrivileges(user.Username, user.Host)
privileges, _ := operator.UserPrivileges(ctx, user.Username, user.Host)
user.Privileges = privileges
if mysql2, err := newMySQLOperator(ctx, user.Username, user.Password, server.Host, server.Port); err == nil {
mysql2.Close()
@@ -161,7 +161,7 @@ func (r *databaseUserRepo) fillUser(ctx context.Context, user *biz.DatabaseUser)
user.Status = biz.DatabaseUserStatusInvalid
}
case biz.DatabaseTypePostgresql:
privileges, _ := operator.UserPrivileges(user.Username)
privileges, _ := operator.UserPrivileges(ctx, user.Username)
user.Privileges = privileges
if postgres2, err := db.NewPostgres(ctx, user.Username, user.Password, server.Host, server.Port); err == nil {
postgres2.Close()
@@ -170,7 +170,7 @@ func (r *databaseUserRepo) fillUser(ctx context.Context, user *biz.DatabaseUser)
user.Status = biz.DatabaseUserStatusInvalid
}
case biz.DatabaseTypeClickHouse:
privileges, _ := operator.UserPrivileges(user.Username)
privileges, _ := operator.UserPrivileges(ctx, user.Username)
user.Privileges = privileges
if ch2, err := db.NewClickHouse(ctx, user.Username, user.Password, fmt.Sprintf("%s:%d", server.Host, server.Port)); err == nil {
ch2.Close()
+20 -8
View File
@@ -25,7 +25,7 @@ var _ biz.BackupRepo = &BackupRepo{}
// ClearExpiredFunc: func(path string, prefix string, save uint) error {
// panic("mock out the ClearExpired method")
// },
// ClearStorageExpiredFunc: func(account uint, dir string, prefix string, save uint) error {
// ClearStorageExpiredFunc: func(ctx context.Context, account uint, dir string, prefix string, save uint) error {
// panic("mock out the ClearStorageExpired method")
// },
// CreateFunc: func(ctx context.Context, typ biz.BackupType, target string, account uint) error {
@@ -37,7 +37,7 @@ var _ biz.BackupRepo = &BackupRepo{}
// CutoffLogFunc: func(ctx context.Context, path string, target string) (string, error) {
// panic("mock out the CutoffLog method")
// },
// CutoffUploadFunc: func(account uint, typ biz.BackupType, name string, files []string) error {
// CutoffUploadFunc: func(ctx context.Context, account uint, typ biz.BackupType, name string, files []string) error {
// panic("mock out the CutoffUpload method")
// },
// DeleteFunc: func(ctx context.Context, typ biz.BackupType, name string) error {
@@ -72,7 +72,7 @@ type BackupRepo struct {
ClearExpiredFunc func(path string, prefix string, save uint) error
// ClearStorageExpiredFunc mocks the ClearStorageExpired method.
ClearStorageExpiredFunc func(account uint, dir string, prefix string, save uint) error
ClearStorageExpiredFunc func(ctx context.Context, account uint, dir string, prefix string, save uint) error
// CreateFunc mocks the Create method.
CreateFunc func(ctx context.Context, typ biz.BackupType, target string, account uint) error
@@ -84,7 +84,7 @@ type BackupRepo struct {
CutoffLogFunc func(ctx context.Context, path string, target string) (string, error)
// CutoffUploadFunc mocks the CutoffUpload method.
CutoffUploadFunc func(account uint, typ biz.BackupType, name string, files []string) error
CutoffUploadFunc func(ctx context.Context, account uint, typ biz.BackupType, name string, files []string) error
// DeleteFunc mocks the Delete method.
DeleteFunc func(ctx context.Context, typ biz.BackupType, name string) error
@@ -120,6 +120,8 @@ type BackupRepo struct {
}
// ClearStorageExpired holds details about calls to the ClearStorageExpired method.
ClearStorageExpired []struct {
// Ctx is the ctx argument value.
Ctx context.Context
// Account is the account argument value.
Account uint
// Dir is the dir argument value.
@@ -156,6 +158,8 @@ type BackupRepo struct {
}
// CutoffUpload holds details about calls to the CutoffUpload method.
CutoffUpload []struct {
// Ctx is the ctx argument value.
Ctx context.Context
// Account is the account argument value.
Account uint
// Typ is the typ argument value.
@@ -275,16 +279,18 @@ func (mock *BackupRepo) ClearExpiredCalls() []struct {
}
// ClearStorageExpired calls ClearStorageExpiredFunc.
func (mock *BackupRepo) ClearStorageExpired(account uint, dir string, prefix string, save uint) error {
func (mock *BackupRepo) ClearStorageExpired(ctx context.Context, account uint, dir string, prefix string, save uint) error {
if mock.ClearStorageExpiredFunc == nil {
panic("BackupRepo.ClearStorageExpiredFunc: method is nil but BackupRepo.ClearStorageExpired was just called")
}
callInfo := struct {
Ctx context.Context
Account uint
Dir string
Prefix string
Save uint
}{
Ctx: ctx,
Account: account,
Dir: dir,
Prefix: prefix,
@@ -293,7 +299,7 @@ func (mock *BackupRepo) ClearStorageExpired(account uint, dir string, prefix str
mock.lockClearStorageExpired.Lock()
mock.calls.ClearStorageExpired = append(mock.calls.ClearStorageExpired, callInfo)
mock.lockClearStorageExpired.Unlock()
return mock.ClearStorageExpiredFunc(account, dir, prefix, save)
return mock.ClearStorageExpiredFunc(ctx, account, dir, prefix, save)
}
// ClearStorageExpiredCalls gets all the calls that were made to ClearStorageExpired.
@@ -301,12 +307,14 @@ func (mock *BackupRepo) ClearStorageExpired(account uint, dir string, prefix str
//
// len(mockedBackupRepo.ClearStorageExpiredCalls())
func (mock *BackupRepo) ClearStorageExpiredCalls() []struct {
Ctx context.Context
Account uint
Dir string
Prefix string
Save uint
} {
var calls []struct {
Ctx context.Context
Account uint
Dir string
Prefix string
@@ -435,16 +443,18 @@ func (mock *BackupRepo) CutoffLogCalls() []struct {
}
// CutoffUpload calls CutoffUploadFunc.
func (mock *BackupRepo) CutoffUpload(account uint, typ biz.BackupType, name string, files []string) error {
func (mock *BackupRepo) CutoffUpload(ctx context.Context, account uint, typ biz.BackupType, name string, files []string) error {
if mock.CutoffUploadFunc == nil {
panic("BackupRepo.CutoffUploadFunc: method is nil but BackupRepo.CutoffUpload was just called")
}
callInfo := struct {
Ctx context.Context
Account uint
Typ biz.BackupType
Name string
Files []string
}{
Ctx: ctx,
Account: account,
Typ: typ,
Name: name,
@@ -453,7 +463,7 @@ func (mock *BackupRepo) CutoffUpload(account uint, typ biz.BackupType, name stri
mock.lockCutoffUpload.Lock()
mock.calls.CutoffUpload = append(mock.calls.CutoffUpload, callInfo)
mock.lockCutoffUpload.Unlock()
return mock.CutoffUploadFunc(account, typ, name, files)
return mock.CutoffUploadFunc(ctx, account, typ, name, files)
}
// CutoffUploadCalls gets all the calls that were made to CutoffUpload.
@@ -461,12 +471,14 @@ func (mock *BackupRepo) CutoffUpload(account uint, typ biz.BackupType, name stri
//
// len(mockedBackupRepo.CutoffUploadCalls())
func (mock *BackupRepo) CutoffUploadCalls() []struct {
Ctx context.Context
Account uint
Typ biz.BackupType
Name string
Files []string
} {
var calls []struct {
Ctx context.Context
Account uint
Typ biz.BackupType
Name string
+51 -20
View File
@@ -5,6 +5,7 @@
package biz
import (
"context"
"sync"
"github.com/acepanel/panel/v3/internal/biz"
@@ -22,19 +23,19 @@ var _ biz.ContainerImageRepo = &ContainerImageRepo{}
//
// // make and configure a mocked biz.ContainerImageRepo
// mockedContainerImageRepo := &ContainerImageRepo{
// ExistFunc: func(sock string, name string) (bool, error) {
// ExistFunc: func(ctx context.Context, sock string, name string) (bool, error) {
// panic("mock out the Exist method")
// },
// ListFunc: func(sock string) ([]types.ContainerImage, error) {
// ListFunc: func(ctx context.Context, sock string) ([]types.ContainerImage, error) {
// panic("mock out the List method")
// },
// PruneFunc: func(sock string) error {
// PruneFunc: func(ctx context.Context, sock string) error {
// panic("mock out the Prune method")
// },
// PullFunc: func(sock string, req *request.ContainerImagePull) error {
// PullFunc: func(ctx context.Context, sock string, req *request.ContainerImagePull) error {
// panic("mock out the Pull method")
// },
// RemoveFunc: func(sock string, id string) error {
// RemoveFunc: func(ctx context.Context, sock string, id string) error {
// panic("mock out the Remove method")
// },
// }
@@ -45,24 +46,26 @@ var _ biz.ContainerImageRepo = &ContainerImageRepo{}
// }
type ContainerImageRepo struct {
// ExistFunc mocks the Exist method.
ExistFunc func(sock string, name string) (bool, error)
ExistFunc func(ctx context.Context, sock string, name string) (bool, error)
// ListFunc mocks the List method.
ListFunc func(sock string) ([]types.ContainerImage, error)
ListFunc func(ctx context.Context, sock string) ([]types.ContainerImage, error)
// PruneFunc mocks the Prune method.
PruneFunc func(sock string) error
PruneFunc func(ctx context.Context, sock string) error
// PullFunc mocks the Pull method.
PullFunc func(sock string, req *request.ContainerImagePull) error
PullFunc func(ctx context.Context, sock string, req *request.ContainerImagePull) error
// RemoveFunc mocks the Remove method.
RemoveFunc func(sock string, id string) error
RemoveFunc func(ctx context.Context, sock string, id string) error
// calls tracks calls to the methods.
calls struct {
// Exist holds details about calls to the Exist method.
Exist []struct {
// Ctx is the ctx argument value.
Ctx context.Context
// Sock is the sock argument value.
Sock string
// Name is the name argument value.
@@ -70,16 +73,22 @@ type ContainerImageRepo struct {
}
// List holds details about calls to the List method.
List []struct {
// Ctx is the ctx argument value.
Ctx context.Context
// Sock is the sock argument value.
Sock string
}
// Prune holds details about calls to the Prune method.
Prune []struct {
// Ctx is the ctx argument value.
Ctx context.Context
// Sock is the sock argument value.
Sock string
}
// Pull holds details about calls to the Pull method.
Pull []struct {
// Ctx is the ctx argument value.
Ctx context.Context
// Sock is the sock argument value.
Sock string
// Req is the req argument value.
@@ -87,6 +96,8 @@ type ContainerImageRepo struct {
}
// Remove holds details about calls to the Remove method.
Remove []struct {
// Ctx is the ctx argument value.
Ctx context.Context
// Sock is the sock argument value.
Sock string
// ID is the id argument value.
@@ -101,21 +112,23 @@ type ContainerImageRepo struct {
}
// Exist calls ExistFunc.
func (mock *ContainerImageRepo) Exist(sock string, name string) (bool, error) {
func (mock *ContainerImageRepo) Exist(ctx context.Context, sock string, name string) (bool, error) {
if mock.ExistFunc == nil {
panic("ContainerImageRepo.ExistFunc: method is nil but ContainerImageRepo.Exist was just called")
}
callInfo := struct {
Ctx context.Context
Sock string
Name string
}{
Ctx: ctx,
Sock: sock,
Name: name,
}
mock.lockExist.Lock()
mock.calls.Exist = append(mock.calls.Exist, callInfo)
mock.lockExist.Unlock()
return mock.ExistFunc(sock, name)
return mock.ExistFunc(ctx, sock, name)
}
// ExistCalls gets all the calls that were made to Exist.
@@ -123,10 +136,12 @@ func (mock *ContainerImageRepo) Exist(sock string, name string) (bool, error) {
//
// len(mockedContainerImageRepo.ExistCalls())
func (mock *ContainerImageRepo) ExistCalls() []struct {
Ctx context.Context
Sock string
Name string
} {
var calls []struct {
Ctx context.Context
Sock string
Name string
}
@@ -137,19 +152,21 @@ func (mock *ContainerImageRepo) ExistCalls() []struct {
}
// List calls ListFunc.
func (mock *ContainerImageRepo) List(sock string) ([]types.ContainerImage, error) {
func (mock *ContainerImageRepo) List(ctx context.Context, sock string) ([]types.ContainerImage, error) {
if mock.ListFunc == nil {
panic("ContainerImageRepo.ListFunc: method is nil but ContainerImageRepo.List was just called")
}
callInfo := struct {
Ctx context.Context
Sock string
}{
Ctx: ctx,
Sock: sock,
}
mock.lockList.Lock()
mock.calls.List = append(mock.calls.List, callInfo)
mock.lockList.Unlock()
return mock.ListFunc(sock)
return mock.ListFunc(ctx, sock)
}
// ListCalls gets all the calls that were made to List.
@@ -157,9 +174,11 @@ func (mock *ContainerImageRepo) List(sock string) ([]types.ContainerImage, error
//
// len(mockedContainerImageRepo.ListCalls())
func (mock *ContainerImageRepo) ListCalls() []struct {
Ctx context.Context
Sock string
} {
var calls []struct {
Ctx context.Context
Sock string
}
mock.lockList.RLock()
@@ -169,19 +188,21 @@ func (mock *ContainerImageRepo) ListCalls() []struct {
}
// Prune calls PruneFunc.
func (mock *ContainerImageRepo) Prune(sock string) error {
func (mock *ContainerImageRepo) Prune(ctx context.Context, sock string) error {
if mock.PruneFunc == nil {
panic("ContainerImageRepo.PruneFunc: method is nil but ContainerImageRepo.Prune was just called")
}
callInfo := struct {
Ctx context.Context
Sock string
}{
Ctx: ctx,
Sock: sock,
}
mock.lockPrune.Lock()
mock.calls.Prune = append(mock.calls.Prune, callInfo)
mock.lockPrune.Unlock()
return mock.PruneFunc(sock)
return mock.PruneFunc(ctx, sock)
}
// PruneCalls gets all the calls that were made to Prune.
@@ -189,9 +210,11 @@ func (mock *ContainerImageRepo) Prune(sock string) error {
//
// len(mockedContainerImageRepo.PruneCalls())
func (mock *ContainerImageRepo) PruneCalls() []struct {
Ctx context.Context
Sock string
} {
var calls []struct {
Ctx context.Context
Sock string
}
mock.lockPrune.RLock()
@@ -201,21 +224,23 @@ func (mock *ContainerImageRepo) PruneCalls() []struct {
}
// Pull calls PullFunc.
func (mock *ContainerImageRepo) Pull(sock string, req *request.ContainerImagePull) error {
func (mock *ContainerImageRepo) Pull(ctx context.Context, sock string, req *request.ContainerImagePull) error {
if mock.PullFunc == nil {
panic("ContainerImageRepo.PullFunc: method is nil but ContainerImageRepo.Pull was just called")
}
callInfo := struct {
Ctx context.Context
Sock string
Req *request.ContainerImagePull
}{
Ctx: ctx,
Sock: sock,
Req: req,
}
mock.lockPull.Lock()
mock.calls.Pull = append(mock.calls.Pull, callInfo)
mock.lockPull.Unlock()
return mock.PullFunc(sock, req)
return mock.PullFunc(ctx, sock, req)
}
// PullCalls gets all the calls that were made to Pull.
@@ -223,10 +248,12 @@ func (mock *ContainerImageRepo) Pull(sock string, req *request.ContainerImagePul
//
// len(mockedContainerImageRepo.PullCalls())
func (mock *ContainerImageRepo) PullCalls() []struct {
Ctx context.Context
Sock string
Req *request.ContainerImagePull
} {
var calls []struct {
Ctx context.Context
Sock string
Req *request.ContainerImagePull
}
@@ -237,21 +264,23 @@ func (mock *ContainerImageRepo) PullCalls() []struct {
}
// Remove calls RemoveFunc.
func (mock *ContainerImageRepo) Remove(sock string, id string) error {
func (mock *ContainerImageRepo) Remove(ctx context.Context, sock string, id string) error {
if mock.RemoveFunc == nil {
panic("ContainerImageRepo.RemoveFunc: method is nil but ContainerImageRepo.Remove was just called")
}
callInfo := struct {
Ctx context.Context
Sock string
ID string
}{
Ctx: ctx,
Sock: sock,
ID: id,
}
mock.lockRemove.Lock()
mock.calls.Remove = append(mock.calls.Remove, callInfo)
mock.lockRemove.Unlock()
return mock.RemoveFunc(sock, id)
return mock.RemoveFunc(ctx, sock, id)
}
// RemoveCalls gets all the calls that were made to Remove.
@@ -259,10 +288,12 @@ func (mock *ContainerImageRepo) Remove(sock string, id string) error {
//
// len(mockedContainerImageRepo.RemoveCalls())
func (mock *ContainerImageRepo) RemoveCalls() []struct {
Ctx context.Context
Sock string
ID string
} {
var calls []struct {
Ctx context.Context
Sock string
ID string
}
+41 -16
View File
@@ -5,6 +5,7 @@
package biz
import (
"context"
"sync"
"github.com/acepanel/panel/v3/internal/biz"
@@ -22,16 +23,16 @@ var _ biz.ContainerNetworkRepo = &ContainerNetworkRepo{}
//
// // make and configure a mocked biz.ContainerNetworkRepo
// mockedContainerNetworkRepo := &ContainerNetworkRepo{
// CreateFunc: func(sock string, req *request.ContainerNetworkCreate) (string, error) {
// CreateFunc: func(ctx context.Context, sock string, req *request.ContainerNetworkCreate) (string, error) {
// panic("mock out the Create method")
// },
// ListFunc: func(sock string) ([]types.ContainerNetwork, error) {
// ListFunc: func(ctx context.Context, sock string) ([]types.ContainerNetwork, error) {
// panic("mock out the List method")
// },
// PruneFunc: func(sock string) error {
// PruneFunc: func(ctx context.Context, sock string) error {
// panic("mock out the Prune method")
// },
// RemoveFunc: func(sock string, id string) error {
// RemoveFunc: func(ctx context.Context, sock string, id string) error {
// panic("mock out the Remove method")
// },
// }
@@ -42,21 +43,23 @@ var _ biz.ContainerNetworkRepo = &ContainerNetworkRepo{}
// }
type ContainerNetworkRepo struct {
// CreateFunc mocks the Create method.
CreateFunc func(sock string, req *request.ContainerNetworkCreate) (string, error)
CreateFunc func(ctx context.Context, sock string, req *request.ContainerNetworkCreate) (string, error)
// ListFunc mocks the List method.
ListFunc func(sock string) ([]types.ContainerNetwork, error)
ListFunc func(ctx context.Context, sock string) ([]types.ContainerNetwork, error)
// PruneFunc mocks the Prune method.
PruneFunc func(sock string) error
PruneFunc func(ctx context.Context, sock string) error
// RemoveFunc mocks the Remove method.
RemoveFunc func(sock string, id string) error
RemoveFunc func(ctx context.Context, sock string, id string) error
// calls tracks calls to the methods.
calls struct {
// Create holds details about calls to the Create method.
Create []struct {
// Ctx is the ctx argument value.
Ctx context.Context
// Sock is the sock argument value.
Sock string
// Req is the req argument value.
@@ -64,16 +67,22 @@ type ContainerNetworkRepo struct {
}
// List holds details about calls to the List method.
List []struct {
// Ctx is the ctx argument value.
Ctx context.Context
// Sock is the sock argument value.
Sock string
}
// Prune holds details about calls to the Prune method.
Prune []struct {
// Ctx is the ctx argument value.
Ctx context.Context
// Sock is the sock argument value.
Sock string
}
// Remove holds details about calls to the Remove method.
Remove []struct {
// Ctx is the ctx argument value.
Ctx context.Context
// Sock is the sock argument value.
Sock string
// ID is the id argument value.
@@ -87,21 +96,23 @@ type ContainerNetworkRepo struct {
}
// Create calls CreateFunc.
func (mock *ContainerNetworkRepo) Create(sock string, req *request.ContainerNetworkCreate) (string, error) {
func (mock *ContainerNetworkRepo) Create(ctx context.Context, sock string, req *request.ContainerNetworkCreate) (string, error) {
if mock.CreateFunc == nil {
panic("ContainerNetworkRepo.CreateFunc: method is nil but ContainerNetworkRepo.Create was just called")
}
callInfo := struct {
Ctx context.Context
Sock string
Req *request.ContainerNetworkCreate
}{
Ctx: ctx,
Sock: sock,
Req: req,
}
mock.lockCreate.Lock()
mock.calls.Create = append(mock.calls.Create, callInfo)
mock.lockCreate.Unlock()
return mock.CreateFunc(sock, req)
return mock.CreateFunc(ctx, sock, req)
}
// CreateCalls gets all the calls that were made to Create.
@@ -109,10 +120,12 @@ func (mock *ContainerNetworkRepo) Create(sock string, req *request.ContainerNetw
//
// len(mockedContainerNetworkRepo.CreateCalls())
func (mock *ContainerNetworkRepo) CreateCalls() []struct {
Ctx context.Context
Sock string
Req *request.ContainerNetworkCreate
} {
var calls []struct {
Ctx context.Context
Sock string
Req *request.ContainerNetworkCreate
}
@@ -123,19 +136,21 @@ func (mock *ContainerNetworkRepo) CreateCalls() []struct {
}
// List calls ListFunc.
func (mock *ContainerNetworkRepo) List(sock string) ([]types.ContainerNetwork, error) {
func (mock *ContainerNetworkRepo) List(ctx context.Context, sock string) ([]types.ContainerNetwork, error) {
if mock.ListFunc == nil {
panic("ContainerNetworkRepo.ListFunc: method is nil but ContainerNetworkRepo.List was just called")
}
callInfo := struct {
Ctx context.Context
Sock string
}{
Ctx: ctx,
Sock: sock,
}
mock.lockList.Lock()
mock.calls.List = append(mock.calls.List, callInfo)
mock.lockList.Unlock()
return mock.ListFunc(sock)
return mock.ListFunc(ctx, sock)
}
// ListCalls gets all the calls that were made to List.
@@ -143,9 +158,11 @@ func (mock *ContainerNetworkRepo) List(sock string) ([]types.ContainerNetwork, e
//
// len(mockedContainerNetworkRepo.ListCalls())
func (mock *ContainerNetworkRepo) ListCalls() []struct {
Ctx context.Context
Sock string
} {
var calls []struct {
Ctx context.Context
Sock string
}
mock.lockList.RLock()
@@ -155,19 +172,21 @@ func (mock *ContainerNetworkRepo) ListCalls() []struct {
}
// Prune calls PruneFunc.
func (mock *ContainerNetworkRepo) Prune(sock string) error {
func (mock *ContainerNetworkRepo) Prune(ctx context.Context, sock string) error {
if mock.PruneFunc == nil {
panic("ContainerNetworkRepo.PruneFunc: method is nil but ContainerNetworkRepo.Prune was just called")
}
callInfo := struct {
Ctx context.Context
Sock string
}{
Ctx: ctx,
Sock: sock,
}
mock.lockPrune.Lock()
mock.calls.Prune = append(mock.calls.Prune, callInfo)
mock.lockPrune.Unlock()
return mock.PruneFunc(sock)
return mock.PruneFunc(ctx, sock)
}
// PruneCalls gets all the calls that were made to Prune.
@@ -175,9 +194,11 @@ func (mock *ContainerNetworkRepo) Prune(sock string) error {
//
// len(mockedContainerNetworkRepo.PruneCalls())
func (mock *ContainerNetworkRepo) PruneCalls() []struct {
Ctx context.Context
Sock string
} {
var calls []struct {
Ctx context.Context
Sock string
}
mock.lockPrune.RLock()
@@ -187,21 +208,23 @@ func (mock *ContainerNetworkRepo) PruneCalls() []struct {
}
// Remove calls RemoveFunc.
func (mock *ContainerNetworkRepo) Remove(sock string, id string) error {
func (mock *ContainerNetworkRepo) Remove(ctx context.Context, sock string, id string) error {
if mock.RemoveFunc == nil {
panic("ContainerNetworkRepo.RemoveFunc: method is nil but ContainerNetworkRepo.Remove was just called")
}
callInfo := struct {
Ctx context.Context
Sock string
ID string
}{
Ctx: ctx,
Sock: sock,
ID: id,
}
mock.lockRemove.Lock()
mock.calls.Remove = append(mock.calls.Remove, callInfo)
mock.lockRemove.Unlock()
return mock.RemoveFunc(sock, id)
return mock.RemoveFunc(ctx, sock, id)
}
// RemoveCalls gets all the calls that were made to Remove.
@@ -209,10 +232,12 @@ func (mock *ContainerNetworkRepo) Remove(sock string, id string) error {
//
// len(mockedContainerNetworkRepo.RemoveCalls())
func (mock *ContainerNetworkRepo) RemoveCalls() []struct {
Ctx context.Context
Sock string
ID string
} {
var calls []struct {
Ctx context.Context
Sock string
ID string
}
+131 -52
View File
@@ -5,6 +5,7 @@
package biz
import (
"context"
"sync"
"github.com/acepanel/panel/v3/internal/biz"
@@ -22,43 +23,43 @@ var _ biz.ContainerRepo = &ContainerRepo{}
//
// // make and configure a mocked biz.ContainerRepo
// mockedContainerRepo := &ContainerRepo{
// CreateFunc: func(sock string, req *request.ContainerCreate) (string, error) {
// CreateFunc: func(ctx context.Context, sock string, req *request.ContainerCreate) (string, error) {
// panic("mock out the Create method")
// },
// InspectFunc: func(sock string, id string) (any, error) {
// InspectFunc: func(ctx context.Context, sock string, id string) (any, error) {
// panic("mock out the Inspect method")
// },
// KillFunc: func(sock string, id string) error {
// KillFunc: func(ctx context.Context, sock string, id string) error {
// panic("mock out the Kill method")
// },
// ListAllFunc: func(sock string) ([]types.Container, error) {
// ListAllFunc: func(ctx context.Context, sock string) ([]types.Container, error) {
// panic("mock out the ListAll method")
// },
// LogsFunc: func(sock string, id string, tail int) (string, error) {
// LogsFunc: func(ctx context.Context, sock string, id string, tail int) (string, error) {
// panic("mock out the Logs method")
// },
// PauseFunc: func(sock string, id string) error {
// PauseFunc: func(ctx context.Context, sock string, id string) error {
// panic("mock out the Pause method")
// },
// PruneFunc: func(sock string) error {
// PruneFunc: func(ctx context.Context, sock string) error {
// panic("mock out the Prune method")
// },
// RemoveFunc: func(sock string, id string) error {
// RemoveFunc: func(ctx context.Context, sock string, id string) error {
// panic("mock out the Remove method")
// },
// RenameFunc: func(sock string, id string, newName string) error {
// RenameFunc: func(ctx context.Context, sock string, id string, newName string) error {
// panic("mock out the Rename method")
// },
// RestartFunc: func(sock string, id string) error {
// RestartFunc: func(ctx context.Context, sock string, id string) error {
// panic("mock out the Restart method")
// },
// StartFunc: func(sock string, id string) error {
// StartFunc: func(ctx context.Context, sock string, id string) error {
// panic("mock out the Start method")
// },
// StopFunc: func(sock string, id string) error {
// StopFunc: func(ctx context.Context, sock string, id string) error {
// panic("mock out the Stop method")
// },
// UnpauseFunc: func(sock string, id string) error {
// UnpauseFunc: func(ctx context.Context, sock string, id string) error {
// panic("mock out the Unpause method")
// },
// }
@@ -69,48 +70,50 @@ var _ biz.ContainerRepo = &ContainerRepo{}
// }
type ContainerRepo struct {
// CreateFunc mocks the Create method.
CreateFunc func(sock string, req *request.ContainerCreate) (string, error)
CreateFunc func(ctx context.Context, sock string, req *request.ContainerCreate) (string, error)
// InspectFunc mocks the Inspect method.
InspectFunc func(sock string, id string) (any, error)
InspectFunc func(ctx context.Context, sock string, id string) (any, error)
// KillFunc mocks the Kill method.
KillFunc func(sock string, id string) error
KillFunc func(ctx context.Context, sock string, id string) error
// ListAllFunc mocks the ListAll method.
ListAllFunc func(sock string) ([]types.Container, error)
ListAllFunc func(ctx context.Context, sock string) ([]types.Container, error)
// LogsFunc mocks the Logs method.
LogsFunc func(sock string, id string, tail int) (string, error)
LogsFunc func(ctx context.Context, sock string, id string, tail int) (string, error)
// PauseFunc mocks the Pause method.
PauseFunc func(sock string, id string) error
PauseFunc func(ctx context.Context, sock string, id string) error
// PruneFunc mocks the Prune method.
PruneFunc func(sock string) error
PruneFunc func(ctx context.Context, sock string) error
// RemoveFunc mocks the Remove method.
RemoveFunc func(sock string, id string) error
RemoveFunc func(ctx context.Context, sock string, id string) error
// RenameFunc mocks the Rename method.
RenameFunc func(sock string, id string, newName string) error
RenameFunc func(ctx context.Context, sock string, id string, newName string) error
// RestartFunc mocks the Restart method.
RestartFunc func(sock string, id string) error
RestartFunc func(ctx context.Context, sock string, id string) error
// StartFunc mocks the Start method.
StartFunc func(sock string, id string) error
StartFunc func(ctx context.Context, sock string, id string) error
// StopFunc mocks the Stop method.
StopFunc func(sock string, id string) error
StopFunc func(ctx context.Context, sock string, id string) error
// UnpauseFunc mocks the Unpause method.
UnpauseFunc func(sock string, id string) error
UnpauseFunc func(ctx context.Context, sock string, id string) error
// calls tracks calls to the methods.
calls struct {
// Create holds details about calls to the Create method.
Create []struct {
// Ctx is the ctx argument value.
Ctx context.Context
// Sock is the sock argument value.
Sock string
// Req is the req argument value.
@@ -118,6 +121,8 @@ type ContainerRepo struct {
}
// Inspect holds details about calls to the Inspect method.
Inspect []struct {
// Ctx is the ctx argument value.
Ctx context.Context
// Sock is the sock argument value.
Sock string
// ID is the id argument value.
@@ -125,6 +130,8 @@ type ContainerRepo struct {
}
// Kill holds details about calls to the Kill method.
Kill []struct {
// Ctx is the ctx argument value.
Ctx context.Context
// Sock is the sock argument value.
Sock string
// ID is the id argument value.
@@ -132,11 +139,15 @@ type ContainerRepo struct {
}
// ListAll holds details about calls to the ListAll method.
ListAll []struct {
// Ctx is the ctx argument value.
Ctx context.Context
// Sock is the sock argument value.
Sock string
}
// Logs holds details about calls to the Logs method.
Logs []struct {
// Ctx is the ctx argument value.
Ctx context.Context
// Sock is the sock argument value.
Sock string
// ID is the id argument value.
@@ -146,6 +157,8 @@ type ContainerRepo struct {
}
// Pause holds details about calls to the Pause method.
Pause []struct {
// Ctx is the ctx argument value.
Ctx context.Context
// Sock is the sock argument value.
Sock string
// ID is the id argument value.
@@ -153,11 +166,15 @@ type ContainerRepo struct {
}
// Prune holds details about calls to the Prune method.
Prune []struct {
// Ctx is the ctx argument value.
Ctx context.Context
// Sock is the sock argument value.
Sock string
}
// Remove holds details about calls to the Remove method.
Remove []struct {
// Ctx is the ctx argument value.
Ctx context.Context
// Sock is the sock argument value.
Sock string
// ID is the id argument value.
@@ -165,6 +182,8 @@ type ContainerRepo struct {
}
// Rename holds details about calls to the Rename method.
Rename []struct {
// Ctx is the ctx argument value.
Ctx context.Context
// Sock is the sock argument value.
Sock string
// ID is the id argument value.
@@ -174,6 +193,8 @@ type ContainerRepo struct {
}
// Restart holds details about calls to the Restart method.
Restart []struct {
// Ctx is the ctx argument value.
Ctx context.Context
// Sock is the sock argument value.
Sock string
// ID is the id argument value.
@@ -181,6 +202,8 @@ type ContainerRepo struct {
}
// Start holds details about calls to the Start method.
Start []struct {
// Ctx is the ctx argument value.
Ctx context.Context
// Sock is the sock argument value.
Sock string
// ID is the id argument value.
@@ -188,6 +211,8 @@ type ContainerRepo struct {
}
// Stop holds details about calls to the Stop method.
Stop []struct {
// Ctx is the ctx argument value.
Ctx context.Context
// Sock is the sock argument value.
Sock string
// ID is the id argument value.
@@ -195,6 +220,8 @@ type ContainerRepo struct {
}
// Unpause holds details about calls to the Unpause method.
Unpause []struct {
// Ctx is the ctx argument value.
Ctx context.Context
// Sock is the sock argument value.
Sock string
// ID is the id argument value.
@@ -217,21 +244,23 @@ type ContainerRepo struct {
}
// Create calls CreateFunc.
func (mock *ContainerRepo) Create(sock string, req *request.ContainerCreate) (string, error) {
func (mock *ContainerRepo) Create(ctx context.Context, sock string, req *request.ContainerCreate) (string, error) {
if mock.CreateFunc == nil {
panic("ContainerRepo.CreateFunc: method is nil but ContainerRepo.Create was just called")
}
callInfo := struct {
Ctx context.Context
Sock string
Req *request.ContainerCreate
}{
Ctx: ctx,
Sock: sock,
Req: req,
}
mock.lockCreate.Lock()
mock.calls.Create = append(mock.calls.Create, callInfo)
mock.lockCreate.Unlock()
return mock.CreateFunc(sock, req)
return mock.CreateFunc(ctx, sock, req)
}
// CreateCalls gets all the calls that were made to Create.
@@ -239,10 +268,12 @@ func (mock *ContainerRepo) Create(sock string, req *request.ContainerCreate) (st
//
// len(mockedContainerRepo.CreateCalls())
func (mock *ContainerRepo) CreateCalls() []struct {
Ctx context.Context
Sock string
Req *request.ContainerCreate
} {
var calls []struct {
Ctx context.Context
Sock string
Req *request.ContainerCreate
}
@@ -253,21 +284,23 @@ func (mock *ContainerRepo) CreateCalls() []struct {
}
// Inspect calls InspectFunc.
func (mock *ContainerRepo) Inspect(sock string, id string) (any, error) {
func (mock *ContainerRepo) Inspect(ctx context.Context, sock string, id string) (any, error) {
if mock.InspectFunc == nil {
panic("ContainerRepo.InspectFunc: method is nil but ContainerRepo.Inspect was just called")
}
callInfo := struct {
Ctx context.Context
Sock string
ID string
}{
Ctx: ctx,
Sock: sock,
ID: id,
}
mock.lockInspect.Lock()
mock.calls.Inspect = append(mock.calls.Inspect, callInfo)
mock.lockInspect.Unlock()
return mock.InspectFunc(sock, id)
return mock.InspectFunc(ctx, sock, id)
}
// InspectCalls gets all the calls that were made to Inspect.
@@ -275,10 +308,12 @@ func (mock *ContainerRepo) Inspect(sock string, id string) (any, error) {
//
// len(mockedContainerRepo.InspectCalls())
func (mock *ContainerRepo) InspectCalls() []struct {
Ctx context.Context
Sock string
ID string
} {
var calls []struct {
Ctx context.Context
Sock string
ID string
}
@@ -289,21 +324,23 @@ func (mock *ContainerRepo) InspectCalls() []struct {
}
// Kill calls KillFunc.
func (mock *ContainerRepo) Kill(sock string, id string) error {
func (mock *ContainerRepo) Kill(ctx context.Context, sock string, id string) error {
if mock.KillFunc == nil {
panic("ContainerRepo.KillFunc: method is nil but ContainerRepo.Kill was just called")
}
callInfo := struct {
Ctx context.Context
Sock string
ID string
}{
Ctx: ctx,
Sock: sock,
ID: id,
}
mock.lockKill.Lock()
mock.calls.Kill = append(mock.calls.Kill, callInfo)
mock.lockKill.Unlock()
return mock.KillFunc(sock, id)
return mock.KillFunc(ctx, sock, id)
}
// KillCalls gets all the calls that were made to Kill.
@@ -311,10 +348,12 @@ func (mock *ContainerRepo) Kill(sock string, id string) error {
//
// len(mockedContainerRepo.KillCalls())
func (mock *ContainerRepo) KillCalls() []struct {
Ctx context.Context
Sock string
ID string
} {
var calls []struct {
Ctx context.Context
Sock string
ID string
}
@@ -325,19 +364,21 @@ func (mock *ContainerRepo) KillCalls() []struct {
}
// ListAll calls ListAllFunc.
func (mock *ContainerRepo) ListAll(sock string) ([]types.Container, error) {
func (mock *ContainerRepo) ListAll(ctx context.Context, sock string) ([]types.Container, error) {
if mock.ListAllFunc == nil {
panic("ContainerRepo.ListAllFunc: method is nil but ContainerRepo.ListAll was just called")
}
callInfo := struct {
Ctx context.Context
Sock string
}{
Ctx: ctx,
Sock: sock,
}
mock.lockListAll.Lock()
mock.calls.ListAll = append(mock.calls.ListAll, callInfo)
mock.lockListAll.Unlock()
return mock.ListAllFunc(sock)
return mock.ListAllFunc(ctx, sock)
}
// ListAllCalls gets all the calls that were made to ListAll.
@@ -345,9 +386,11 @@ func (mock *ContainerRepo) ListAll(sock string) ([]types.Container, error) {
//
// len(mockedContainerRepo.ListAllCalls())
func (mock *ContainerRepo) ListAllCalls() []struct {
Ctx context.Context
Sock string
} {
var calls []struct {
Ctx context.Context
Sock string
}
mock.lockListAll.RLock()
@@ -357,15 +400,17 @@ func (mock *ContainerRepo) ListAllCalls() []struct {
}
// Logs calls LogsFunc.
func (mock *ContainerRepo) Logs(sock string, id string, tail int) (string, error) {
func (mock *ContainerRepo) Logs(ctx context.Context, sock string, id string, tail int) (string, error) {
if mock.LogsFunc == nil {
panic("ContainerRepo.LogsFunc: method is nil but ContainerRepo.Logs was just called")
}
callInfo := struct {
Ctx context.Context
Sock string
ID string
Tail int
}{
Ctx: ctx,
Sock: sock,
ID: id,
Tail: tail,
@@ -373,7 +418,7 @@ func (mock *ContainerRepo) Logs(sock string, id string, tail int) (string, error
mock.lockLogs.Lock()
mock.calls.Logs = append(mock.calls.Logs, callInfo)
mock.lockLogs.Unlock()
return mock.LogsFunc(sock, id, tail)
return mock.LogsFunc(ctx, sock, id, tail)
}
// LogsCalls gets all the calls that were made to Logs.
@@ -381,11 +426,13 @@ func (mock *ContainerRepo) Logs(sock string, id string, tail int) (string, error
//
// len(mockedContainerRepo.LogsCalls())
func (mock *ContainerRepo) LogsCalls() []struct {
Ctx context.Context
Sock string
ID string
Tail int
} {
var calls []struct {
Ctx context.Context
Sock string
ID string
Tail int
@@ -397,21 +444,23 @@ func (mock *ContainerRepo) LogsCalls() []struct {
}
// Pause calls PauseFunc.
func (mock *ContainerRepo) Pause(sock string, id string) error {
func (mock *ContainerRepo) Pause(ctx context.Context, sock string, id string) error {
if mock.PauseFunc == nil {
panic("ContainerRepo.PauseFunc: method is nil but ContainerRepo.Pause was just called")
}
callInfo := struct {
Ctx context.Context
Sock string
ID string
}{
Ctx: ctx,
Sock: sock,
ID: id,
}
mock.lockPause.Lock()
mock.calls.Pause = append(mock.calls.Pause, callInfo)
mock.lockPause.Unlock()
return mock.PauseFunc(sock, id)
return mock.PauseFunc(ctx, sock, id)
}
// PauseCalls gets all the calls that were made to Pause.
@@ -419,10 +468,12 @@ func (mock *ContainerRepo) Pause(sock string, id string) error {
//
// len(mockedContainerRepo.PauseCalls())
func (mock *ContainerRepo) PauseCalls() []struct {
Ctx context.Context
Sock string
ID string
} {
var calls []struct {
Ctx context.Context
Sock string
ID string
}
@@ -433,19 +484,21 @@ func (mock *ContainerRepo) PauseCalls() []struct {
}
// Prune calls PruneFunc.
func (mock *ContainerRepo) Prune(sock string) error {
func (mock *ContainerRepo) Prune(ctx context.Context, sock string) error {
if mock.PruneFunc == nil {
panic("ContainerRepo.PruneFunc: method is nil but ContainerRepo.Prune was just called")
}
callInfo := struct {
Ctx context.Context
Sock string
}{
Ctx: ctx,
Sock: sock,
}
mock.lockPrune.Lock()
mock.calls.Prune = append(mock.calls.Prune, callInfo)
mock.lockPrune.Unlock()
return mock.PruneFunc(sock)
return mock.PruneFunc(ctx, sock)
}
// PruneCalls gets all the calls that were made to Prune.
@@ -453,9 +506,11 @@ func (mock *ContainerRepo) Prune(sock string) error {
//
// len(mockedContainerRepo.PruneCalls())
func (mock *ContainerRepo) PruneCalls() []struct {
Ctx context.Context
Sock string
} {
var calls []struct {
Ctx context.Context
Sock string
}
mock.lockPrune.RLock()
@@ -465,21 +520,23 @@ func (mock *ContainerRepo) PruneCalls() []struct {
}
// Remove calls RemoveFunc.
func (mock *ContainerRepo) Remove(sock string, id string) error {
func (mock *ContainerRepo) Remove(ctx context.Context, sock string, id string) error {
if mock.RemoveFunc == nil {
panic("ContainerRepo.RemoveFunc: method is nil but ContainerRepo.Remove was just called")
}
callInfo := struct {
Ctx context.Context
Sock string
ID string
}{
Ctx: ctx,
Sock: sock,
ID: id,
}
mock.lockRemove.Lock()
mock.calls.Remove = append(mock.calls.Remove, callInfo)
mock.lockRemove.Unlock()
return mock.RemoveFunc(sock, id)
return mock.RemoveFunc(ctx, sock, id)
}
// RemoveCalls gets all the calls that were made to Remove.
@@ -487,10 +544,12 @@ func (mock *ContainerRepo) Remove(sock string, id string) error {
//
// len(mockedContainerRepo.RemoveCalls())
func (mock *ContainerRepo) RemoveCalls() []struct {
Ctx context.Context
Sock string
ID string
} {
var calls []struct {
Ctx context.Context
Sock string
ID string
}
@@ -501,15 +560,17 @@ func (mock *ContainerRepo) RemoveCalls() []struct {
}
// Rename calls RenameFunc.
func (mock *ContainerRepo) Rename(sock string, id string, newName string) error {
func (mock *ContainerRepo) Rename(ctx context.Context, sock string, id string, newName string) error {
if mock.RenameFunc == nil {
panic("ContainerRepo.RenameFunc: method is nil but ContainerRepo.Rename was just called")
}
callInfo := struct {
Ctx context.Context
Sock string
ID string
NewName string
}{
Ctx: ctx,
Sock: sock,
ID: id,
NewName: newName,
@@ -517,7 +578,7 @@ func (mock *ContainerRepo) Rename(sock string, id string, newName string) error
mock.lockRename.Lock()
mock.calls.Rename = append(mock.calls.Rename, callInfo)
mock.lockRename.Unlock()
return mock.RenameFunc(sock, id, newName)
return mock.RenameFunc(ctx, sock, id, newName)
}
// RenameCalls gets all the calls that were made to Rename.
@@ -525,11 +586,13 @@ func (mock *ContainerRepo) Rename(sock string, id string, newName string) error
//
// len(mockedContainerRepo.RenameCalls())
func (mock *ContainerRepo) RenameCalls() []struct {
Ctx context.Context
Sock string
ID string
NewName string
} {
var calls []struct {
Ctx context.Context
Sock string
ID string
NewName string
@@ -541,21 +604,23 @@ func (mock *ContainerRepo) RenameCalls() []struct {
}
// Restart calls RestartFunc.
func (mock *ContainerRepo) Restart(sock string, id string) error {
func (mock *ContainerRepo) Restart(ctx context.Context, sock string, id string) error {
if mock.RestartFunc == nil {
panic("ContainerRepo.RestartFunc: method is nil but ContainerRepo.Restart was just called")
}
callInfo := struct {
Ctx context.Context
Sock string
ID string
}{
Ctx: ctx,
Sock: sock,
ID: id,
}
mock.lockRestart.Lock()
mock.calls.Restart = append(mock.calls.Restart, callInfo)
mock.lockRestart.Unlock()
return mock.RestartFunc(sock, id)
return mock.RestartFunc(ctx, sock, id)
}
// RestartCalls gets all the calls that were made to Restart.
@@ -563,10 +628,12 @@ func (mock *ContainerRepo) Restart(sock string, id string) error {
//
// len(mockedContainerRepo.RestartCalls())
func (mock *ContainerRepo) RestartCalls() []struct {
Ctx context.Context
Sock string
ID string
} {
var calls []struct {
Ctx context.Context
Sock string
ID string
}
@@ -577,21 +644,23 @@ func (mock *ContainerRepo) RestartCalls() []struct {
}
// Start calls StartFunc.
func (mock *ContainerRepo) Start(sock string, id string) error {
func (mock *ContainerRepo) Start(ctx context.Context, sock string, id string) error {
if mock.StartFunc == nil {
panic("ContainerRepo.StartFunc: method is nil but ContainerRepo.Start was just called")
}
callInfo := struct {
Ctx context.Context
Sock string
ID string
}{
Ctx: ctx,
Sock: sock,
ID: id,
}
mock.lockStart.Lock()
mock.calls.Start = append(mock.calls.Start, callInfo)
mock.lockStart.Unlock()
return mock.StartFunc(sock, id)
return mock.StartFunc(ctx, sock, id)
}
// StartCalls gets all the calls that were made to Start.
@@ -599,10 +668,12 @@ func (mock *ContainerRepo) Start(sock string, id string) error {
//
// len(mockedContainerRepo.StartCalls())
func (mock *ContainerRepo) StartCalls() []struct {
Ctx context.Context
Sock string
ID string
} {
var calls []struct {
Ctx context.Context
Sock string
ID string
}
@@ -613,21 +684,23 @@ func (mock *ContainerRepo) StartCalls() []struct {
}
// Stop calls StopFunc.
func (mock *ContainerRepo) Stop(sock string, id string) error {
func (mock *ContainerRepo) Stop(ctx context.Context, sock string, id string) error {
if mock.StopFunc == nil {
panic("ContainerRepo.StopFunc: method is nil but ContainerRepo.Stop was just called")
}
callInfo := struct {
Ctx context.Context
Sock string
ID string
}{
Ctx: ctx,
Sock: sock,
ID: id,
}
mock.lockStop.Lock()
mock.calls.Stop = append(mock.calls.Stop, callInfo)
mock.lockStop.Unlock()
return mock.StopFunc(sock, id)
return mock.StopFunc(ctx, sock, id)
}
// StopCalls gets all the calls that were made to Stop.
@@ -635,10 +708,12 @@ func (mock *ContainerRepo) Stop(sock string, id string) error {
//
// len(mockedContainerRepo.StopCalls())
func (mock *ContainerRepo) StopCalls() []struct {
Ctx context.Context
Sock string
ID string
} {
var calls []struct {
Ctx context.Context
Sock string
ID string
}
@@ -649,21 +724,23 @@ func (mock *ContainerRepo) StopCalls() []struct {
}
// Unpause calls UnpauseFunc.
func (mock *ContainerRepo) Unpause(sock string, id string) error {
func (mock *ContainerRepo) Unpause(ctx context.Context, sock string, id string) error {
if mock.UnpauseFunc == nil {
panic("ContainerRepo.UnpauseFunc: method is nil but ContainerRepo.Unpause was just called")
}
callInfo := struct {
Ctx context.Context
Sock string
ID string
}{
Ctx: ctx,
Sock: sock,
ID: id,
}
mock.lockUnpause.Lock()
mock.calls.Unpause = append(mock.calls.Unpause, callInfo)
mock.lockUnpause.Unlock()
return mock.UnpauseFunc(sock, id)
return mock.UnpauseFunc(ctx, sock, id)
}
// UnpauseCalls gets all the calls that were made to Unpause.
@@ -671,10 +748,12 @@ func (mock *ContainerRepo) Unpause(sock string, id string) error {
//
// len(mockedContainerRepo.UnpauseCalls())
func (mock *ContainerRepo) UnpauseCalls() []struct {
Ctx context.Context
Sock string
ID string
} {
var calls []struct {
Ctx context.Context
Sock string
ID string
}
+41 -16
View File
@@ -5,6 +5,7 @@
package biz
import (
"context"
"sync"
"github.com/acepanel/panel/v3/internal/biz"
@@ -22,16 +23,16 @@ var _ biz.ContainerVolumeRepo = &ContainerVolumeRepo{}
//
// // make and configure a mocked biz.ContainerVolumeRepo
// mockedContainerVolumeRepo := &ContainerVolumeRepo{
// CreateFunc: func(sock string, req *request.ContainerVolumeCreate) (string, error) {
// CreateFunc: func(ctx context.Context, sock string, req *request.ContainerVolumeCreate) (string, error) {
// panic("mock out the Create method")
// },
// ListFunc: func(sock string) ([]types.ContainerVolume, error) {
// ListFunc: func(ctx context.Context, sock string) ([]types.ContainerVolume, error) {
// panic("mock out the List method")
// },
// PruneFunc: func(sock string) error {
// PruneFunc: func(ctx context.Context, sock string) error {
// panic("mock out the Prune method")
// },
// RemoveFunc: func(sock string, id string) error {
// RemoveFunc: func(ctx context.Context, sock string, id string) error {
// panic("mock out the Remove method")
// },
// }
@@ -42,21 +43,23 @@ var _ biz.ContainerVolumeRepo = &ContainerVolumeRepo{}
// }
type ContainerVolumeRepo struct {
// CreateFunc mocks the Create method.
CreateFunc func(sock string, req *request.ContainerVolumeCreate) (string, error)
CreateFunc func(ctx context.Context, sock string, req *request.ContainerVolumeCreate) (string, error)
// ListFunc mocks the List method.
ListFunc func(sock string) ([]types.ContainerVolume, error)
ListFunc func(ctx context.Context, sock string) ([]types.ContainerVolume, error)
// PruneFunc mocks the Prune method.
PruneFunc func(sock string) error
PruneFunc func(ctx context.Context, sock string) error
// RemoveFunc mocks the Remove method.
RemoveFunc func(sock string, id string) error
RemoveFunc func(ctx context.Context, sock string, id string) error
// calls tracks calls to the methods.
calls struct {
// Create holds details about calls to the Create method.
Create []struct {
// Ctx is the ctx argument value.
Ctx context.Context
// Sock is the sock argument value.
Sock string
// Req is the req argument value.
@@ -64,16 +67,22 @@ type ContainerVolumeRepo struct {
}
// List holds details about calls to the List method.
List []struct {
// Ctx is the ctx argument value.
Ctx context.Context
// Sock is the sock argument value.
Sock string
}
// Prune holds details about calls to the Prune method.
Prune []struct {
// Ctx is the ctx argument value.
Ctx context.Context
// Sock is the sock argument value.
Sock string
}
// Remove holds details about calls to the Remove method.
Remove []struct {
// Ctx is the ctx argument value.
Ctx context.Context
// Sock is the sock argument value.
Sock string
// ID is the id argument value.
@@ -87,21 +96,23 @@ type ContainerVolumeRepo struct {
}
// Create calls CreateFunc.
func (mock *ContainerVolumeRepo) Create(sock string, req *request.ContainerVolumeCreate) (string, error) {
func (mock *ContainerVolumeRepo) Create(ctx context.Context, sock string, req *request.ContainerVolumeCreate) (string, error) {
if mock.CreateFunc == nil {
panic("ContainerVolumeRepo.CreateFunc: method is nil but ContainerVolumeRepo.Create was just called")
}
callInfo := struct {
Ctx context.Context
Sock string
Req *request.ContainerVolumeCreate
}{
Ctx: ctx,
Sock: sock,
Req: req,
}
mock.lockCreate.Lock()
mock.calls.Create = append(mock.calls.Create, callInfo)
mock.lockCreate.Unlock()
return mock.CreateFunc(sock, req)
return mock.CreateFunc(ctx, sock, req)
}
// CreateCalls gets all the calls that were made to Create.
@@ -109,10 +120,12 @@ func (mock *ContainerVolumeRepo) Create(sock string, req *request.ContainerVolum
//
// len(mockedContainerVolumeRepo.CreateCalls())
func (mock *ContainerVolumeRepo) CreateCalls() []struct {
Ctx context.Context
Sock string
Req *request.ContainerVolumeCreate
} {
var calls []struct {
Ctx context.Context
Sock string
Req *request.ContainerVolumeCreate
}
@@ -123,19 +136,21 @@ func (mock *ContainerVolumeRepo) CreateCalls() []struct {
}
// List calls ListFunc.
func (mock *ContainerVolumeRepo) List(sock string) ([]types.ContainerVolume, error) {
func (mock *ContainerVolumeRepo) List(ctx context.Context, sock string) ([]types.ContainerVolume, error) {
if mock.ListFunc == nil {
panic("ContainerVolumeRepo.ListFunc: method is nil but ContainerVolumeRepo.List was just called")
}
callInfo := struct {
Ctx context.Context
Sock string
}{
Ctx: ctx,
Sock: sock,
}
mock.lockList.Lock()
mock.calls.List = append(mock.calls.List, callInfo)
mock.lockList.Unlock()
return mock.ListFunc(sock)
return mock.ListFunc(ctx, sock)
}
// ListCalls gets all the calls that were made to List.
@@ -143,9 +158,11 @@ func (mock *ContainerVolumeRepo) List(sock string) ([]types.ContainerVolume, err
//
// len(mockedContainerVolumeRepo.ListCalls())
func (mock *ContainerVolumeRepo) ListCalls() []struct {
Ctx context.Context
Sock string
} {
var calls []struct {
Ctx context.Context
Sock string
}
mock.lockList.RLock()
@@ -155,19 +172,21 @@ func (mock *ContainerVolumeRepo) ListCalls() []struct {
}
// Prune calls PruneFunc.
func (mock *ContainerVolumeRepo) Prune(sock string) error {
func (mock *ContainerVolumeRepo) Prune(ctx context.Context, sock string) error {
if mock.PruneFunc == nil {
panic("ContainerVolumeRepo.PruneFunc: method is nil but ContainerVolumeRepo.Prune was just called")
}
callInfo := struct {
Ctx context.Context
Sock string
}{
Ctx: ctx,
Sock: sock,
}
mock.lockPrune.Lock()
mock.calls.Prune = append(mock.calls.Prune, callInfo)
mock.lockPrune.Unlock()
return mock.PruneFunc(sock)
return mock.PruneFunc(ctx, sock)
}
// PruneCalls gets all the calls that were made to Prune.
@@ -175,9 +194,11 @@ func (mock *ContainerVolumeRepo) Prune(sock string) error {
//
// len(mockedContainerVolumeRepo.PruneCalls())
func (mock *ContainerVolumeRepo) PruneCalls() []struct {
Ctx context.Context
Sock string
} {
var calls []struct {
Ctx context.Context
Sock string
}
mock.lockPrune.RLock()
@@ -187,21 +208,23 @@ func (mock *ContainerVolumeRepo) PruneCalls() []struct {
}
// Remove calls RemoveFunc.
func (mock *ContainerVolumeRepo) Remove(sock string, id string) error {
func (mock *ContainerVolumeRepo) Remove(ctx context.Context, sock string, id string) error {
if mock.RemoveFunc == nil {
panic("ContainerVolumeRepo.RemoveFunc: method is nil but ContainerVolumeRepo.Remove was just called")
}
callInfo := struct {
Ctx context.Context
Sock string
ID string
}{
Ctx: ctx,
Sock: sock,
ID: id,
}
mock.lockRemove.Lock()
mock.calls.Remove = append(mock.calls.Remove, callInfo)
mock.lockRemove.Unlock()
return mock.RemoveFunc(sock, id)
return mock.RemoveFunc(ctx, sock, id)
}
// RemoveCalls gets all the calls that were made to Remove.
@@ -209,10 +232,12 @@ func (mock *ContainerVolumeRepo) Remove(sock string, id string) error {
//
// len(mockedContainerVolumeRepo.RemoveCalls())
func (mock *ContainerVolumeRepo) RemoveCalls() []struct {
Ctx context.Context
Sock string
ID string
} {
var calls []struct {
Ctx context.Context
Sock string
ID string
}
+5 -4
View File
@@ -1,6 +1,7 @@
package service
import (
"context"
"errors"
"net/http"
@@ -51,7 +52,7 @@ func (s *BackupStorageService) Create(w http.ResponseWriter, r *http.Request) {
return
}
if err = s.validateStorage(req.Type, req.Info); err != nil {
if err = s.validateStorage(r.Context(), req.Type, req.Info); err != nil {
Error(w, http.StatusUnprocessableEntity, "%v", err)
return
}
@@ -72,7 +73,7 @@ func (s *BackupStorageService) Update(w http.ResponseWriter, r *http.Request) {
return
}
if err = s.validateStorage(req.Type, req.Info); err != nil {
if err = s.validateStorage(r.Context(), req.Type, req.Info); err != nil {
Error(w, http.StatusUnprocessableEntity, "%v", err)
return
}
@@ -117,7 +118,7 @@ func (s *BackupStorageService) Delete(w http.ResponseWriter, r *http.Request) {
}
// validateStorage 验证存储配置是否正确
func (s *BackupStorageService) validateStorage(accountType string, info types.BackupStorageInfo) error {
func (s *BackupStorageService) validateStorage(ctx context.Context, accountType string, info types.BackupStorageInfo) error {
var err error
var client storage.Storage
@@ -159,7 +160,7 @@ func (s *BackupStorageService) validateStorage(accountType string, info types.Ba
return nil
}
if _, err = client.List(""); err != nil {
if _, err = client.List(ctx, ""); err != nil {
return errors.New(s.t.Get("storage connection error: %v", err))
}
+4 -4
View File
@@ -1194,7 +1194,7 @@ func (s *CliService) BackupClear(ctx context.Context, cmd *cli.Command) error {
fmt.Println(s.t.Get("|-Keep count: %d", cmd.Uint("keep")))
if cmd.Uint("storage") != 0 {
if err := s.backupRepo.ClearStorageExpired(cmd.Uint("storage"), cmd.String("type"), cmd.String("file"), cmd.Uint("keep")); err != nil {
if err := s.backupRepo.ClearStorageExpired(ctx, cmd.Uint("storage"), cmd.String("type"), cmd.String("file"), cmd.Uint("keep")); err != nil {
return errors.New(s.t.Get("Cleaning failed: %v", err))
}
} else {
@@ -1250,7 +1250,7 @@ func (s *CliService) CutoffWebsite(ctx context.Context, cmd *cli.Command) error
// 上传到远程存储
if cmd.Uint("storage") != 0 {
if err = s.backupRepo.CutoffUpload(cmd.Uint("storage"), biz.BackupTypeWebsite, website.Name, files); err != nil {
if err = s.backupRepo.CutoffUpload(ctx, cmd.Uint("storage"), biz.BackupTypeWebsite, website.Name, files); err != nil {
return err
}
}
@@ -1289,7 +1289,7 @@ func (s *CliService) CutoffContainer(ctx context.Context, cmd *cli.Command) erro
// 上传到远程存储
if cmd.Uint("storage") != 0 {
if err = s.backupRepo.CutoffUpload(cmd.Uint("storage"), "container", name, []string{zipPath}); err != nil {
if err = s.backupRepo.CutoffUpload(ctx, cmd.Uint("storage"), "container", name, []string{zipPath}); err != nil {
return err
}
}
@@ -1337,7 +1337,7 @@ func (s *CliService) CutoffClear(ctx context.Context, cmd *cli.Command) error {
}
// 清理远程存储过期日志,切割日志上传在 cutoff/<类型>/<目标> 下
if storageID != 0 {
if err := s.backupRepo.ClearStorageExpired(storageID, filepath.Join("cutoff", typ, name), prefix, keep); err != nil {
if err := s.backupRepo.ClearStorageExpired(ctx, storageID, filepath.Join("cutoff", typ, name), prefix, keep); err != nil {
return err
}
}
+14 -14
View File
@@ -21,7 +21,7 @@ func NewContainerService(containerUsecase *biz.ContainerUsecase) *ContainerServi
}
func (s *ContainerService) List(w http.ResponseWriter, r *http.Request) {
containers, err := s.containerRepo.ListAll()
containers, err := s.containerRepo.ListAll(r.Context())
if err != nil {
Error(w, http.StatusInternalServerError, "%v", err)
}
@@ -35,7 +35,7 @@ func (s *ContainerService) List(w http.ResponseWriter, r *http.Request) {
}
func (s *ContainerService) Search(w http.ResponseWriter, r *http.Request) {
containers, err := s.containerRepo.ListByName(r.FormValue("name"))
containers, err := s.containerRepo.ListByName(r.Context(), r.FormValue("name"))
if err != nil {
Error(w, http.StatusInternalServerError, "%v", err)
return
@@ -48,7 +48,7 @@ func (s *ContainerService) Search(w http.ResponseWriter, r *http.Request) {
}
func (s *ContainerService) Inspect(w http.ResponseWriter, r *http.Request) {
data, err := s.containerRepo.Inspect(chi.URLParam(r, "id"))
data, err := s.containerRepo.Inspect(r.Context(), chi.URLParam(r, "id"))
if err != nil {
Error(w, http.StatusInternalServerError, "%v", err)
return
@@ -74,7 +74,7 @@ func (s *ContainerService) Update(w http.ResponseWriter, r *http.Request) {
return
}
id, err := s.containerRepo.Update(idParam, req)
id, err := s.containerRepo.Update(r.Context(), idParam, req)
if err != nil {
Error(w, http.StatusInternalServerError, "%v", err)
return
@@ -99,7 +99,7 @@ func (s *ContainerService) Create(w http.ResponseWriter, r *http.Request) {
return
}
id, err := s.containerRepo.Create(req)
id, err := s.containerRepo.Create(r.Context(), req)
if err != nil {
Error(w, http.StatusInternalServerError, "%v", err)
return
@@ -115,7 +115,7 @@ func (s *ContainerService) Remove(w http.ResponseWriter, r *http.Request) {
return
}
if err = s.containerRepo.Remove(req.ID); err != nil {
if err = s.containerRepo.Remove(r.Context(), req.ID); err != nil {
Error(w, http.StatusInternalServerError, "%v", err)
return
}
@@ -130,7 +130,7 @@ func (s *ContainerService) Start(w http.ResponseWriter, r *http.Request) {
return
}
if err = s.containerRepo.Start(req.ID); err != nil {
if err = s.containerRepo.Start(r.Context(), req.ID); err != nil {
Error(w, http.StatusInternalServerError, "%v", err)
return
}
@@ -145,7 +145,7 @@ func (s *ContainerService) Stop(w http.ResponseWriter, r *http.Request) {
return
}
if err = s.containerRepo.Stop(req.ID); err != nil {
if err = s.containerRepo.Stop(r.Context(), req.ID); err != nil {
Error(w, http.StatusInternalServerError, "%v", err)
return
}
@@ -160,7 +160,7 @@ func (s *ContainerService) Restart(w http.ResponseWriter, r *http.Request) {
return
}
if err = s.containerRepo.Restart(req.ID); err != nil {
if err = s.containerRepo.Restart(r.Context(), req.ID); err != nil {
Error(w, http.StatusInternalServerError, "%v", err)
return
}
@@ -175,7 +175,7 @@ func (s *ContainerService) Pause(w http.ResponseWriter, r *http.Request) {
return
}
if err = s.containerRepo.Pause(req.ID); err != nil {
if err = s.containerRepo.Pause(r.Context(), req.ID); err != nil {
Error(w, http.StatusInternalServerError, "%v", err)
return
}
@@ -190,7 +190,7 @@ func (s *ContainerService) Unpause(w http.ResponseWriter, r *http.Request) {
return
}
if err = s.containerRepo.Unpause(req.ID); err != nil {
if err = s.containerRepo.Unpause(r.Context(), req.ID); err != nil {
Error(w, http.StatusInternalServerError, "%v", err)
return
}
@@ -205,7 +205,7 @@ func (s *ContainerService) Kill(w http.ResponseWriter, r *http.Request) {
return
}
if err = s.containerRepo.Kill(req.ID); err != nil {
if err = s.containerRepo.Kill(r.Context(), req.ID); err != nil {
Error(w, http.StatusInternalServerError, "%v", err)
return
}
@@ -220,7 +220,7 @@ func (s *ContainerService) Rename(w http.ResponseWriter, r *http.Request) {
return
}
if err = s.containerRepo.Rename(req.ID, req.Name); err != nil {
if err = s.containerRepo.Rename(r.Context(), req.ID, req.Name); err != nil {
Error(w, http.StatusInternalServerError, "%v", err)
return
}
@@ -229,7 +229,7 @@ func (s *ContainerService) Rename(w http.ResponseWriter, r *http.Request) {
}
func (s *ContainerService) Prune(w http.ResponseWriter, r *http.Request) {
if err := s.containerRepo.Prune(); err != nil {
if err := s.containerRepo.Prune(r.Context()); err != nil {
Error(w, http.StatusInternalServerError, "%v", err)
return
}
+5 -5
View File
@@ -20,7 +20,7 @@ func NewContainerImageService(containerImageUsecase *biz.ContainerImageUsecase)
}
func (s *ContainerImageService) List(w http.ResponseWriter, r *http.Request) {
images, err := s.containerImageRepo.List()
images, err := s.containerImageRepo.List(r.Context())
if err != nil {
Error(w, http.StatusInternalServerError, "%v", err)
return
@@ -41,7 +41,7 @@ func (s *ContainerImageService) Exist(w http.ResponseWriter, r *http.Request) {
return
}
exist, err := s.containerImageRepo.Exist(req.Name)
exist, err := s.containerImageRepo.Exist(r.Context(), req.Name)
if err != nil {
Error(w, http.StatusInternalServerError, "%v", err)
return
@@ -66,7 +66,7 @@ func (s *ContainerImageService) Pull(w http.ResponseWriter, r *http.Request) {
return
}
if err = s.containerImageRepo.Pull(req); err != nil {
if err = s.containerImageRepo.Pull(r.Context(), req); err != nil {
Error(w, http.StatusInternalServerError, "%v", err)
return
}
@@ -81,7 +81,7 @@ func (s *ContainerImageService) Remove(w http.ResponseWriter, r *http.Request) {
return
}
if err = s.containerImageRepo.Remove(req.ID); err != nil {
if err = s.containerImageRepo.Remove(r.Context(), req.ID); err != nil {
Error(w, http.StatusInternalServerError, "%v", err)
return
}
@@ -90,7 +90,7 @@ func (s *ContainerImageService) Remove(w http.ResponseWriter, r *http.Request) {
}
func (s *ContainerImageService) Prune(w http.ResponseWriter, r *http.Request) {
if err := s.containerImageRepo.Prune(); err != nil {
if err := s.containerImageRepo.Prune(r.Context()); err != nil {
Error(w, http.StatusInternalServerError, "%v", err)
return
}
+4 -4
View File
@@ -20,7 +20,7 @@ func NewContainerNetworkService(containerNetworkUsecase *biz.ContainerNetworkUse
}
func (s *ContainerNetworkService) List(w http.ResponseWriter, r *http.Request) {
networks, err := s.containerNetworkRepo.List()
networks, err := s.containerNetworkRepo.List(r.Context())
if err != nil {
Error(w, http.StatusInternalServerError, "%v", err)
return
@@ -41,7 +41,7 @@ func (s *ContainerNetworkService) Create(w http.ResponseWriter, r *http.Request)
return
}
id, err := s.containerNetworkRepo.Create(req)
id, err := s.containerNetworkRepo.Create(r.Context(), req)
if err != nil {
Error(w, http.StatusInternalServerError, "%v", err)
return
@@ -57,7 +57,7 @@ func (s *ContainerNetworkService) Remove(w http.ResponseWriter, r *http.Request)
return
}
if err = s.containerNetworkRepo.Remove(req.ID); err != nil {
if err = s.containerNetworkRepo.Remove(r.Context(), req.ID); err != nil {
Error(w, http.StatusInternalServerError, "%v", err)
return
}
@@ -66,7 +66,7 @@ func (s *ContainerNetworkService) Remove(w http.ResponseWriter, r *http.Request)
}
func (s *ContainerNetworkService) Prune(w http.ResponseWriter, r *http.Request) {
if err := s.containerNetworkRepo.Prune(); err != nil {
if err := s.containerNetworkRepo.Prune(r.Context()); err != nil {
Error(w, http.StatusInternalServerError, "%v", err)
return
}
+4 -4
View File
@@ -20,7 +20,7 @@ func NewContainerVolumeService(containerVolumeUsecase *biz.ContainerVolumeUsecas
}
func (s *ContainerVolumeService) List(w http.ResponseWriter, r *http.Request) {
volumes, err := s.containerVolumeRepo.List()
volumes, err := s.containerVolumeRepo.List(r.Context())
if err != nil {
Error(w, http.StatusInternalServerError, "%v", err)
return
@@ -41,7 +41,7 @@ func (s *ContainerVolumeService) Create(w http.ResponseWriter, r *http.Request)
return
}
name, err := s.containerVolumeRepo.Create(req)
name, err := s.containerVolumeRepo.Create(r.Context(), req)
if err != nil {
Error(w, http.StatusInternalServerError, "%v", err)
return
@@ -57,7 +57,7 @@ func (s *ContainerVolumeService) Remove(w http.ResponseWriter, r *http.Request)
return
}
if err = s.containerVolumeRepo.Remove(req.ID); err != nil {
if err = s.containerVolumeRepo.Remove(r.Context(), req.ID); err != nil {
Error(w, http.StatusInternalServerError, "%v", err)
return
}
@@ -66,7 +66,7 @@ func (s *ContainerVolumeService) Remove(w http.ResponseWriter, r *http.Request)
}
func (s *ContainerVolumeService) Prune(w http.ResponseWriter, r *http.Request) {
if err := s.containerVolumeRepo.Prune(); err != nil {
if err := s.containerVolumeRepo.Prune(r.Context()); err != nil {
Error(w, http.StatusInternalServerError, "%v", err)
return
}
+3 -3
View File
@@ -144,7 +144,7 @@ func (s *FileService) Tail(w http.ResponseWriter, r *http.Request) {
}
if req.Container != "" {
s.tailContainer(w, req)
s.tailContainer(r.Context(), w, req)
return
}
@@ -1058,10 +1058,10 @@ func formatJournalLine(ts, hostname, ident, comm, pid, message string) string {
}
// tailContainer 反向读取容器末尾日志
func (s *FileService) tailContainer(w http.ResponseWriter, req *request.FileTail) {
func (s *FileService) tailContainer(ctx context.Context, w http.ResponseWriter, req *request.FileTail) {
// 容器日志只能整段拉取再切片,回溯深度由 Tail 顶部统一钳制
total := req.Offset + req.Limit
out, err := s.containerRepo.Logs(req.Container, total)
out, err := s.containerRepo.Logs(ctx, req.Container, total)
if err != nil {
Error(w, http.StatusInternalServerError, "%v", err)
return
+3 -3
View File
@@ -184,7 +184,7 @@ func (s *HomeService) CountInfo(w http.ResponseWriter, r *http.Request) {
mysql, err := db.NewMySQL(r.Context(), "root", rootPassword, db.MySQLSocket(app.Root), "unix")
if err == nil {
defer mysql.Close()
databases, err := mysql.Databases()
databases, err := mysql.Databases(r.Context())
if err == nil {
databaseCount += len(databases)
}
@@ -194,7 +194,7 @@ func (s *HomeService) CountInfo(w http.ResponseWriter, r *http.Request) {
if server, err := s.databaseServerRepo.GetByName(r.Context(), "local_postgresql"); err == nil {
if postgres, err := db.NewPostgres(r.Context(), server.Username, server.Password, server.Host, server.Port); err == nil {
defer postgres.Close()
if databases, err := postgres.Databases(); err == nil {
if databases, err := postgres.Databases(r.Context()); err == nil {
databaseCount += len(databases)
}
}
@@ -212,7 +212,7 @@ func (s *HomeService) CountInfo(w http.ResponseWriter, r *http.Request) {
}
containerCount := -1
containers, err := s.containerRepo.ListAll()
containers, err := s.containerRepo.ListAll(r.Context())
if err == nil {
containerCount = len(containers)
}
+4 -4
View File
@@ -63,7 +63,7 @@ func (s *ToolboxLogService) Scan(w http.ResponseWriter, r *http.Request) {
case "mysql":
items = s.scanMySQLLogs()
case "docker":
items = s.scanDockerLogs()
items = s.scanDockerLogs(r.Context())
case "system":
items = s.scanSystemLogs(r.Context())
default:
@@ -237,11 +237,11 @@ func (s *ToolboxLogService) scanMySQLLogs() []LogItem {
}
// scanDockerLogs 扫描 Docker/Podman 相关内容
func (s *ToolboxLogService) scanDockerLogs() []LogItem {
func (s *ToolboxLogService) scanDockerLogs(ctx context.Context) []LogItem {
items := make([]LogItem, 0)
// 未使用的容器镜像 (Docker)
images, err := s.containerImageRepo.List()
images, err := s.containerImageRepo.List(ctx)
if err == nil {
// 计算未使用的镜像
var unusedCount int
@@ -532,7 +532,7 @@ func (s *ToolboxLogService) cleanDockerLogs(ctx context.Context) int64 {
var cleaned int64
// 清理未使用的镜像 (Docker)
_ = s.containerImageRepo.Prune()
_ = s.containerImageRepo.Prune(ctx)
// 清理 Docker 容器日志
dockerLogPath := "/var/lib/docker/containers"
+33 -37
View File
@@ -32,7 +32,7 @@ func NewClickHouse(ctx context.Context, username, password, address string) (*Cl
}
// 测试连接
if err := ch.ping(ctx); err != nil {
if err := ch.Ping(ctx); err != nil {
_ = client.Close()
return nil, fmt.Errorf("connect to clickhouse failed: %w", err)
}
@@ -44,12 +44,7 @@ func (r *ClickHouse) Close() {
_ = r.client.Close()
}
func (r *ClickHouse) Ping() error {
return r.ping(context.Background())
}
// ping 带 context 的连通性检查,供构造时使用
func (r *ClickHouse) ping(ctx context.Context) error {
func (r *ClickHouse) Ping(ctx context.Context) error {
resp, err := r.client.R().
SetContext(ctx).
SetQueryParam("user", r.username).
@@ -66,45 +61,45 @@ func (r *ClickHouse) ping(ctx context.Context) error {
return nil
}
func (r *ClickHouse) Query(query string, args ...any) (*sql.Rows, error) {
func (r *ClickHouse) Query(ctx context.Context, query string, args ...any) (*sql.Rows, error) {
return nil, errors.New("clickhouse HTTP API does not support sql.Rows")
}
func (r *ClickHouse) QueryRow(query string, args ...any) *sql.Row {
func (r *ClickHouse) QueryRow(ctx context.Context, query string, args ...any) *sql.Row {
return nil
}
func (r *ClickHouse) Exec(query string, args ...any) (sql.Result, error) {
_, err := r.exec(query)
func (r *ClickHouse) Exec(ctx context.Context, query string, args ...any) (sql.Result, error) {
_, err := r.exec(ctx, query)
return nil, err
}
func (r *ClickHouse) Prepare(query string) (*sql.Stmt, error) {
func (r *ClickHouse) Prepare(ctx context.Context, query string) (*sql.Stmt, error) {
return nil, errors.New("clickhouse HTTP API does not support Prepare")
}
func (r *ClickHouse) DatabaseCreate(name string) error {
func (r *ClickHouse) DatabaseCreate(ctx context.Context, name string) error {
name = strings.ReplaceAll(name, "`", "``")
_, err := r.exec(fmt.Sprintf("CREATE DATABASE IF NOT EXISTS `%s`", name))
_, err := r.exec(ctx, fmt.Sprintf("CREATE DATABASE IF NOT EXISTS `%s`", name))
return err
}
func (r *ClickHouse) DatabaseDrop(name string) error {
func (r *ClickHouse) DatabaseDrop(ctx context.Context, name string) error {
name = strings.ReplaceAll(name, "`", "``")
_, err := r.exec(fmt.Sprintf("DROP DATABASE IF EXISTS `%s`", name))
_, err := r.exec(ctx, fmt.Sprintf("DROP DATABASE IF EXISTS `%s`", name))
return err
}
func (r *ClickHouse) DatabaseExists(name string) (bool, error) {
result, err := r.exec(fmt.Sprintf("SELECT count() FROM system.databases WHERE name = '%s'", name))
func (r *ClickHouse) DatabaseExists(ctx context.Context, name string) (bool, error) {
result, err := r.exec(ctx, fmt.Sprintf("SELECT count() FROM system.databases WHERE name = '%s'", name))
if err != nil {
return false, err
}
return strings.TrimSpace(result) != "0", nil
}
func (r *ClickHouse) DatabaseSize(name string) (int64, error) {
result, err := r.exec(fmt.Sprintf("SELECT COALESCE(sum(bytes_on_disk), 0) FROM system.parts WHERE database = '%s'", name))
func (r *ClickHouse) DatabaseSize(ctx context.Context, name string) (int64, error) {
result, err := r.exec(ctx, fmt.Sprintf("SELECT COALESCE(sum(bytes_on_disk), 0) FROM system.parts WHERE database = '%s'", name))
if err != nil {
return 0, err
}
@@ -115,27 +110,27 @@ func (r *ClickHouse) DatabaseSize(name string) (int64, error) {
return size, nil
}
func (r *ClickHouse) UserCreate(user, password string, host ...string) error {
func (r *ClickHouse) UserCreate(ctx context.Context, user, password string, host ...string) error {
user = strings.ReplaceAll(user, "`", "``")
_, err := r.exec(fmt.Sprintf("CREATE USER IF NOT EXISTS `%s` IDENTIFIED BY '%s'", user, password))
_, err := r.exec(ctx, fmt.Sprintf("CREATE USER IF NOT EXISTS `%s` IDENTIFIED BY '%s'", user, password))
return err
}
func (r *ClickHouse) UserDrop(user string, host ...string) error {
func (r *ClickHouse) UserDrop(ctx context.Context, user string, host ...string) error {
user = strings.ReplaceAll(user, "`", "``")
_, err := r.exec(fmt.Sprintf("DROP USER IF EXISTS `%s`", user))
_, err := r.exec(ctx, fmt.Sprintf("DROP USER IF EXISTS `%s`", user))
return err
}
func (r *ClickHouse) UserPassword(user, password string, host ...string) error {
func (r *ClickHouse) UserPassword(ctx context.Context, user, password string, host ...string) error {
user = strings.ReplaceAll(user, "`", "``")
_, err := r.exec(fmt.Sprintf("ALTER USER `%s` IDENTIFIED BY '%s'", user, password))
_, err := r.exec(ctx, fmt.Sprintf("ALTER USER `%s` IDENTIFIED BY '%s'", user, password))
return err
}
func (r *ClickHouse) UserPrivileges(user string, host ...string) ([]string, error) {
func (r *ClickHouse) UserPrivileges(ctx context.Context, user string, host ...string) ([]string, error) {
user = strings.ReplaceAll(user, "`", "``")
result, err := r.exec(fmt.Sprintf("SHOW GRANTS FOR `%s`", user))
result, err := r.exec(ctx, fmt.Sprintf("SHOW GRANTS FOR `%s`", user))
if err != nil {
return nil, err
}
@@ -161,22 +156,22 @@ func (r *ClickHouse) UserPrivileges(user string, host ...string) ([]string, erro
return databases, nil
}
func (r *ClickHouse) PrivilegesGrant(user, database string, host ...string) error {
func (r *ClickHouse) PrivilegesGrant(ctx context.Context, user, database string, host ...string) error {
user = strings.ReplaceAll(user, "`", "``")
database = strings.ReplaceAll(database, "`", "``")
_, err := r.exec(fmt.Sprintf("GRANT ALL ON `%s`.* TO `%s`", database, user))
_, err := r.exec(ctx, fmt.Sprintf("GRANT ALL ON `%s`.* TO `%s`", database, user))
return err
}
func (r *ClickHouse) PrivilegesRevoke(user, database string, host ...string) error {
func (r *ClickHouse) PrivilegesRevoke(ctx context.Context, user, database string, host ...string) error {
user = strings.ReplaceAll(user, "`", "``")
database = strings.ReplaceAll(database, "`", "``")
_, err := r.exec(fmt.Sprintf("REVOKE ALL ON `%s`.* FROM `%s`", database, user))
_, err := r.exec(ctx, fmt.Sprintf("REVOKE ALL ON `%s`.* FROM `%s`", database, user))
return err
}
func (r *ClickHouse) Users() ([]User, error) {
result, err := r.exec("SELECT name FROM system.users FORMAT TabSeparated")
func (r *ClickHouse) Users(ctx context.Context) ([]User, error) {
result, err := r.exec(ctx, "SELECT name FROM system.users FORMAT TabSeparated")
if err != nil {
return nil, err
}
@@ -193,8 +188,8 @@ func (r *ClickHouse) Users() ([]User, error) {
return users, nil
}
func (r *ClickHouse) Databases() ([]Database, error) {
result, err := r.exec("SELECT name FROM system.databases WHERE name NOT IN ('system', 'INFORMATION_SCHEMA', 'information_schema') FORMAT TabSeparated")
func (r *ClickHouse) Databases(ctx context.Context) ([]Database, error) {
result, err := r.exec(ctx, "SELECT name FROM system.databases WHERE name NOT IN ('system', 'INFORMATION_SCHEMA', 'information_schema') FORMAT TabSeparated")
if err != nil {
return nil, err
}
@@ -212,8 +207,9 @@ func (r *ClickHouse) Databases() ([]Database, error) {
}
// exec 通过 HTTP API 执行 SQL
func (r *ClickHouse) exec(query string) (string, error) {
func (r *ClickHouse) exec(ctx context.Context, query string) (string, error) {
resp, err := r.client.R().
SetContext(ctx).
SetQueryParam("user", r.username).
SetQueryParam("password", r.password).
SetBody(query).
+21 -18
View File
@@ -1,29 +1,32 @@
package db
import "database/sql"
import (
"context"
"database/sql"
)
type Operator interface {
Close()
Ping() error
Ping(ctx context.Context) error
Query(query string, args ...any) (*sql.Rows, error)
QueryRow(query string, args ...any) *sql.Row
Exec(query string, args ...any) (sql.Result, error)
Prepare(query string) (*sql.Stmt, error)
Query(ctx context.Context, query string, args ...any) (*sql.Rows, error)
QueryRow(ctx context.Context, query string, args ...any) *sql.Row
Exec(ctx context.Context, query string, args ...any) (sql.Result, error)
Prepare(ctx context.Context, query string) (*sql.Stmt, error)
DatabaseCreate(name string) error
DatabaseDrop(name string) error
DatabaseExists(name string) (bool, error)
DatabaseSize(name string) (int64, error)
DatabaseCreate(ctx context.Context, name string) error
DatabaseDrop(ctx context.Context, name string) error
DatabaseExists(ctx context.Context, name string) (bool, error)
DatabaseSize(ctx context.Context, name string) (int64, error)
UserCreate(user, password string, host ...string) error
UserDrop(user string, host ...string) error
UserPassword(user, password string, host ...string) error
UserPrivileges(user string, host ...string) ([]string, error)
UserCreate(ctx context.Context, user, password string, host ...string) error
UserDrop(ctx context.Context, user string, host ...string) error
UserPassword(ctx context.Context, user, password string, host ...string) error
UserPrivileges(ctx context.Context, user string, host ...string) ([]string, error)
PrivilegesGrant(user, database string, host ...string) error
PrivilegesRevoke(user, database string, host ...string) error
PrivilegesGrant(ctx context.Context, user, database string, host ...string) error
PrivilegesRevoke(ctx context.Context, user, database string, host ...string) error
Users() ([]User, error)
Databases() ([]Database, error)
Users(ctx context.Context) ([]User, error)
Databases(ctx context.Context) ([]Database, error)
}
+18 -18
View File
@@ -40,7 +40,7 @@ func NewElasticsearch(ctx context.Context, address, username, password string) (
}
es := &Elasticsearch{client: client}
if err := es.ping(ctx); err != nil {
if err := es.Ping(ctx); err != nil {
_ = client.Close()
return nil, fmt.Errorf("connect to elasticsearch failed: %w", err)
}
@@ -52,12 +52,7 @@ func (r *Elasticsearch) Close() {
_ = r.client.Close()
}
func (r *Elasticsearch) Ping() error {
return r.ping(context.Background())
}
// ping 带 context 的连通性检查,供构造时使用
func (r *Elasticsearch) ping(ctx context.Context) error {
func (r *Elasticsearch) Ping(ctx context.Context) error {
resp, err := r.client.R().SetContext(ctx).Get("/")
if err != nil {
return err
@@ -70,8 +65,8 @@ func (r *Elasticsearch) ping(ctx context.Context) error {
}
// Indices 获取所有索引
func (r *Elasticsearch) Indices() ([]ESIndex, error) {
resp, err := r.client.R().Get("/_cat/indices?format=json&h=index,health,status,docs.count,store.size")
func (r *Elasticsearch) Indices(ctx context.Context) ([]ESIndex, error) {
resp, err := r.client.R().SetContext(ctx).Get("/_cat/indices?format=json&h=index,health,status,docs.count,store.size")
if err != nil {
return nil, fmt.Errorf("failed to get indices: %w", err)
}
@@ -109,8 +104,9 @@ func (r *Elasticsearch) Indices() ([]ESIndex, error) {
}
// IndexCreate 创建索引
func (r *Elasticsearch) IndexCreate(name string) error {
func (r *Elasticsearch) IndexCreate(ctx context.Context, name string) error {
resp, err := r.client.R().
SetContext(ctx).
SetHeader("Content-Type", "application/json").
Put("/" + name)
if err != nil {
@@ -123,8 +119,8 @@ func (r *Elasticsearch) IndexCreate(name string) error {
}
// IndexDelete 删除索引
func (r *Elasticsearch) IndexDelete(name string) error {
resp, err := r.client.R().Delete("/" + name)
func (r *Elasticsearch) IndexDelete(ctx context.Context, name string) error {
resp, err := r.client.R().SetContext(ctx).Delete("/" + name)
if err != nil {
return fmt.Errorf("failed to delete index: %w", err)
}
@@ -135,7 +131,7 @@ func (r *Elasticsearch) IndexDelete(name string) error {
}
// Search 搜索文档
func (r *Elasticsearch) Search(index, query string, page, pageSize int) ([]ESDocument, int64, error) {
func (r *Elasticsearch) Search(ctx context.Context, index, query string, page, pageSize int) ([]ESDocument, int64, error) {
from := (page - 1) * pageSize
body := map[string]any{
"from": from,
@@ -150,6 +146,7 @@ func (r *Elasticsearch) Search(index, query string, page, pageSize int) ([]ESDoc
}
resp, err := r.client.R().
SetContext(ctx).
SetHeader("Content-Type", "application/json").
SetBody(body).
Post("/" + index + "/_search")
@@ -189,8 +186,8 @@ func (r *Elasticsearch) Search(index, query string, page, pageSize int) ([]ESDoc
}
// DocumentGet 获取文档
func (r *Elasticsearch) DocumentGet(index, id string) (*ESDocument, error) {
resp, err := r.client.R().Get("/" + index + "/_doc/" + id)
func (r *Elasticsearch) DocumentGet(ctx context.Context, index, id string) (*ESDocument, error) {
resp, err := r.client.R().SetContext(ctx).Get("/" + index + "/_doc/" + id)
if err != nil {
return nil, fmt.Errorf("failed to get document: %w", err)
}
@@ -215,8 +212,9 @@ func (r *Elasticsearch) DocumentGet(index, id string) (*ESDocument, error) {
}
// DocumentCreate 创建文档(自动生成 ID)
func (r *Elasticsearch) DocumentCreate(index, body string) error {
func (r *Elasticsearch) DocumentCreate(ctx context.Context, index, body string) error {
resp, err := r.client.R().
SetContext(ctx).
SetHeader("Content-Type", "application/json").
SetQueryParam("refresh", "true").
SetBody(body).
@@ -231,8 +229,9 @@ func (r *Elasticsearch) DocumentCreate(index, body string) error {
}
// DocumentUpdate 更新文档
func (r *Elasticsearch) DocumentUpdate(index, id, body string) error {
func (r *Elasticsearch) DocumentUpdate(ctx context.Context, index, id, body string) error {
resp, err := r.client.R().
SetContext(ctx).
SetHeader("Content-Type", "application/json").
SetQueryParam("refresh", "true").
SetBody(body).
@@ -247,8 +246,9 @@ func (r *Elasticsearch) DocumentUpdate(index, id, body string) error {
}
// DocumentDelete 删除文档
func (r *Elasticsearch) DocumentDelete(index, id string) error {
func (r *Elasticsearch) DocumentDelete(ctx context.Context, index, id string) error {
resp, err := r.client.R().
SetContext(ctx).
SetQueryParam("refresh", "true").
Delete("/" + index + "/_doc/" + id)
if err != nil {
+19 -29
View File
@@ -24,7 +24,7 @@ func NewMongoDB(ctx context.Context, username, password, address string) (*Mongo
address: address,
}
if err := m.ping(ctx); err != nil {
if err := m.Ping(ctx); err != nil {
return nil, fmt.Errorf("connect to mongodb failed: %w", err)
}
@@ -33,31 +33,26 @@ func NewMongoDB(ctx context.Context, username, password, address string) (*Mongo
func (r *MongoDB) Close() {}
func (r *MongoDB) Ping() error {
return r.ping(context.Background())
}
// ping 带 context 的连通性检查,供构造时使用
func (r *MongoDB) ping(ctx context.Context) error {
_, err := r.mongoshContext(ctx, `db.runCommand({ping:1})`)
func (r *MongoDB) Ping(ctx context.Context) error {
_, err := r.mongosh(ctx, `db.runCommand({ping:1})`)
return err
}
// DatabaseCreate 创建数据库(MongoDB 通过创建集合来显式创建数据库)
func (r *MongoDB) DatabaseCreate(name string) error {
_, err := r.mongosh(fmt.Sprintf(`db.getSiblingDB('%s').createCollection('_init')`, name))
func (r *MongoDB) DatabaseCreate(ctx context.Context, name string) error {
_, err := r.mongosh(ctx, fmt.Sprintf(`db.getSiblingDB('%s').createCollection('_init')`, name))
return err
}
// DatabaseDrop 删除数据库
func (r *MongoDB) DatabaseDrop(name string) error {
_, err := r.mongosh(fmt.Sprintf(`db.getSiblingDB('%s').dropDatabase()`, name))
func (r *MongoDB) DatabaseDrop(ctx context.Context, name string) error {
_, err := r.mongosh(ctx, fmt.Sprintf(`db.getSiblingDB('%s').dropDatabase()`, name))
return err
}
// Databases 获取数据库列表
func (r *MongoDB) Databases() ([]MongoDatabase, error) {
raw, err := r.mongosh(`JSON.stringify(db.adminCommand({listDatabases:1,nameOnly:false}))`)
func (r *MongoDB) Databases(ctx context.Context) ([]MongoDatabase, error) {
raw, err := r.mongosh(ctx, `JSON.stringify(db.adminCommand({listDatabases:1,nameOnly:false}))`)
if err != nil {
return nil, err
}
@@ -101,26 +96,26 @@ func mongoLongToInt64(v any) int64 {
}
// UserCreate 创建用户
func (r *MongoDB) UserCreate(user, password, database string) error {
_, err := r.mongosh(fmt.Sprintf(`db.getSiblingDB('%s').createUser({user:'%s',pwd:'%s',roles:[{role:'readWrite',db:'%s'}]})`, database, user, password, database))
func (r *MongoDB) UserCreate(ctx context.Context, user, password, database string) error {
_, err := r.mongosh(ctx, fmt.Sprintf(`db.getSiblingDB('%s').createUser({user:'%s',pwd:'%s',roles:[{role:'readWrite',db:'%s'}]})`, database, user, password, database))
return err
}
// UserDrop 删除用户
func (r *MongoDB) UserDrop(user, database string) error {
_, err := r.mongosh(fmt.Sprintf(`db.getSiblingDB('%s').dropUser('%s')`, database, user))
func (r *MongoDB) UserDrop(ctx context.Context, user, database string) error {
_, err := r.mongosh(ctx, fmt.Sprintf(`db.getSiblingDB('%s').dropUser('%s')`, database, user))
return err
}
// UserPassword 修改用户密码
func (r *MongoDB) UserPassword(user, password string) error {
_, err := r.mongosh(fmt.Sprintf(`db.getSiblingDB('admin').changeUserPassword('%s','%s')`, user, password))
func (r *MongoDB) UserPassword(ctx context.Context, user, password string) error {
_, err := r.mongosh(ctx, fmt.Sprintf(`db.getSiblingDB('admin').changeUserPassword('%s','%s')`, user, password))
return err
}
// Users 获取用户列表
func (r *MongoDB) Users() ([]MongoUser, error) {
raw, err := r.mongosh(`JSON.stringify(db.getSiblingDB('admin').system.users.find({},{user:1,db:1,roles:1}).toArray())`)
func (r *MongoDB) Users(ctx context.Context) ([]MongoUser, error) {
raw, err := r.mongosh(ctx, `JSON.stringify(db.getSiblingDB('admin').system.users.find({},{user:1,db:1,roles:1}).toArray())`)
if err != nil {
return nil, err
}
@@ -153,13 +148,8 @@ func (r *MongoDB) Users() ([]MongoUser, error) {
return users, nil
}
// mongosh 执行 mongosh 命令
func (r *MongoDB) mongosh(eval string) (string, error) {
return r.mongoshContext(context.Background(), eval)
}
// mongoshContext 执行 mongosh 命令,ctx 取消时终止进程
func (r *MongoDB) mongoshContext(ctx context.Context, eval string) (string, error) {
// mongosh 执行 mongosh 命令,ctx 取消时终止进程
func (r *MongoDB) mongosh(ctx context.Context, eval string) (string, error) {
// serverSelectionTimeoutMS 限制建连耗时,避免不可达地址长时间挂起
cmd := fmt.Sprintf(`mongosh --quiet --eval "%s" "mongodb://%s:%s@%s/admin?serverSelectionTimeoutMS=10000" 2>/dev/null`,
strings.ReplaceAll(eval, `"`, `\"`),
+47 -46
View File
@@ -44,42 +44,42 @@ func (r *MySQL) Close() {
_ = r.db.Close()
}
func (r *MySQL) Ping() error {
return r.db.PingContext(context.Background())
func (r *MySQL) Ping(ctx context.Context) error {
return r.db.PingContext(ctx)
}
func (r *MySQL) Query(query string, args ...any) (*sql.Rows, error) {
return r.db.QueryContext(context.Background(), query, args...)
func (r *MySQL) Query(ctx context.Context, query string, args ...any) (*sql.Rows, error) {
return r.db.QueryContext(ctx, query, args...)
}
func (r *MySQL) QueryRow(query string, args ...any) *sql.Row {
return r.db.QueryRowContext(context.Background(), query, args...)
func (r *MySQL) QueryRow(ctx context.Context, query string, args ...any) *sql.Row {
return r.db.QueryRowContext(ctx, query, args...)
}
func (r *MySQL) Exec(query string, args ...any) (sql.Result, error) {
return r.db.ExecContext(context.Background(), query, args...)
func (r *MySQL) Exec(ctx context.Context, query string, args ...any) (sql.Result, error) {
return r.db.ExecContext(ctx, query, args...)
}
func (r *MySQL) Prepare(query string) (*sql.Stmt, error) {
return r.db.PrepareContext(context.Background(), query)
func (r *MySQL) Prepare(ctx context.Context, query string) (*sql.Stmt, error) {
return r.db.PrepareContext(ctx, query)
}
func (r *MySQL) DatabaseCreate(name string) error {
func (r *MySQL) DatabaseCreate(ctx context.Context, name string) error {
name = strings.ReplaceAll(name, "`", "``")
_, err := r.Exec(fmt.Sprintf("CREATE DATABASE IF NOT EXISTS `%s`", name))
r.flushPrivileges()
_, err := r.Exec(ctx, fmt.Sprintf("CREATE DATABASE IF NOT EXISTS `%s`", name))
r.flushPrivileges(ctx)
return err
}
func (r *MySQL) DatabaseDrop(name string) error {
func (r *MySQL) DatabaseDrop(ctx context.Context, name string) error {
name = strings.ReplaceAll(name, "`", "``")
_, err := r.Exec(fmt.Sprintf("DROP DATABASE IF EXISTS `%s`", name))
r.flushPrivileges()
_, err := r.Exec(ctx, fmt.Sprintf("DROP DATABASE IF EXISTS `%s`", name))
r.flushPrivileges(ctx)
return err
}
func (r *MySQL) DatabaseExists(name string) (bool, error) {
rows, err := r.Query("SHOW DATABASES")
func (r *MySQL) DatabaseExists(ctx context.Context, name string) (bool, error) {
rows, err := r.Query(ctx, "SHOW DATABASES")
if err != nil {
return false, err
}
@@ -97,45 +97,45 @@ func (r *MySQL) DatabaseExists(name string) (bool, error) {
return false, rows.Err()
}
func (r *MySQL) DatabaseSize(name string) (int64, error) {
func (r *MySQL) DatabaseSize(ctx context.Context, name string) (int64, error) {
var size int64
err := r.QueryRow("SELECT COALESCE(SUM(data_length) + SUM(index_length), 0) FROM information_schema.tables WHERE table_schema = ?", name).Scan(&size)
err := r.QueryRow(ctx, "SELECT COALESCE(SUM(data_length) + SUM(index_length), 0) FROM information_schema.tables WHERE table_schema = ?", name).Scan(&size)
return size, err
}
func (r *MySQL) UserCreate(user, password string, host ...string) error {
func (r *MySQL) UserCreate(ctx context.Context, user, password string, host ...string) error {
if len(host) == 0 || host[0] == "" {
host = []string{"%"}
}
_, err := r.Exec(fmt.Sprintf("CREATE USER IF NOT EXISTS '%s'@'%s' IDENTIFIED BY '%s'", user, host[0], password))
r.flushPrivileges()
_, err := r.Exec(ctx, fmt.Sprintf("CREATE USER IF NOT EXISTS '%s'@'%s' IDENTIFIED BY '%s'", user, host[0], password))
r.flushPrivileges(ctx)
return err
}
func (r *MySQL) UserDrop(user string, host ...string) error {
func (r *MySQL) UserDrop(ctx context.Context, user string, host ...string) error {
if len(host) == 0 || host[0] == "" {
host = []string{"%"}
}
_, err := r.Exec(fmt.Sprintf("DROP USER IF EXISTS '%s'@'%s'", user, host[0]))
r.flushPrivileges()
_, err := r.Exec(ctx, fmt.Sprintf("DROP USER IF EXISTS '%s'@'%s'", user, host[0]))
r.flushPrivileges(ctx)
return err
}
func (r *MySQL) UserPassword(user, password string, host ...string) error {
func (r *MySQL) UserPassword(ctx context.Context, user, password string, host ...string) error {
if len(host) == 0 || host[0] == "" {
host = []string{"%"}
}
_, err := r.Exec(fmt.Sprintf("ALTER USER '%s'@'%s' IDENTIFIED BY '%s'", user, host[0], password))
r.flushPrivileges()
_, err := r.Exec(ctx, fmt.Sprintf("ALTER USER '%s'@'%s' IDENTIFIED BY '%s'", user, host[0], password))
r.flushPrivileges(ctx)
return err
}
func (r *MySQL) UserPrivileges(user string, host ...string) ([]string, error) {
func (r *MySQL) UserPrivileges(ctx context.Context, user string, host ...string) ([]string, error) {
if len(host) == 0 || host[0] == "" {
host = []string{"%"}
}
rows, err := r.Query(fmt.Sprintf("SHOW GRANTS FOR '%s'@'%s'", user, host[0]))
rows, err := r.Query(ctx, fmt.Sprintf("SHOW GRANTS FOR '%s'@'%s'", user, host[0]))
if err != nil {
return nil, err
}
@@ -167,28 +167,28 @@ func (r *MySQL) UserPrivileges(user string, host ...string) ([]string, error) {
return slices.Compact(databases), nil
}
func (r *MySQL) PrivilegesGrant(user, database string, host ...string) error {
func (r *MySQL) PrivilegesGrant(ctx context.Context, user, database string, host ...string) error {
if len(host) == 0 || host[0] == "" {
host = []string{"%"}
}
database = strings.ReplaceAll(database, "`", "``")
_, err := r.Exec(fmt.Sprintf("GRANT ALL PRIVILEGES ON `%s`.* TO '%s'@'%s'", database, user, host[0]))
r.flushPrivileges()
_, err := r.Exec(ctx, fmt.Sprintf("GRANT ALL PRIVILEGES ON `%s`.* TO '%s'@'%s'", database, user, host[0]))
r.flushPrivileges(ctx)
return err
}
func (r *MySQL) PrivilegesRevoke(user, database string, host ...string) error {
func (r *MySQL) PrivilegesRevoke(ctx context.Context, user, database string, host ...string) error {
if len(host) == 0 || host[0] == "" {
host = []string{"%"}
}
database = strings.ReplaceAll(database, "`", "``")
_, err := r.Exec(fmt.Sprintf("REVOKE ALL PRIVILEGES ON `%s`.* FROM '%s'@'%s'", database, user, host[0]))
r.flushPrivileges()
_, err := r.Exec(ctx, fmt.Sprintf("REVOKE ALL PRIVILEGES ON `%s`.* FROM '%s'@'%s'", database, user, host[0]))
r.flushPrivileges(ctx)
return err
}
func (r *MySQL) Users() ([]User, error) {
rows, err := r.Query("SELECT user, host FROM mysql.user")
func (r *MySQL) Users(ctx context.Context) ([]User, error) {
rows, err := r.Query(ctx, "SELECT user, host FROM mysql.user")
if err != nil {
return nil, err
}
@@ -200,7 +200,7 @@ func (r *MySQL) Users() ([]User, error) {
if err := rows.Scan(&user, &host); err != nil {
continue
}
grants, err := r.userGrants(user, host)
grants, err := r.userGrants(ctx, user, host)
if err != nil {
continue
}
@@ -215,7 +215,7 @@ func (r *MySQL) Users() ([]User, error) {
return users, rows.Err()
}
func (r *MySQL) Databases() ([]Database, error) {
func (r *MySQL) Databases(ctx context.Context) ([]Database, error) {
query := `
SELECT
SCHEMA_NAME,
@@ -225,7 +225,7 @@ func (r *MySQL) Databases() ([]Database, error) {
WHERE SCHEMA_NAME NOT IN ('information_schema', 'performance_schema', 'mysql', 'sys')
`
rows, err := r.Query(query)
rows, err := r.Query(ctx, query)
if err != nil {
return nil, err
}
@@ -247,8 +247,8 @@ func (r *MySQL) Databases() ([]Database, error) {
return databases, nil
}
func (r *MySQL) userGrants(user, host string) ([]string, error) {
rows, err := r.Query(fmt.Sprintf("SHOW GRANTS FOR '%s'@'%s'", user, host))
func (r *MySQL) userGrants(ctx context.Context, user, host string) ([]string, error) {
rows, err := r.Query(ctx, fmt.Sprintf("SHOW GRANTS FOR '%s'@'%s'", user, host))
if err != nil {
return nil, err
}
@@ -265,6 +265,7 @@ func (r *MySQL) userGrants(user, host string) ([]string, error) {
return grants, rows.Err()
}
func (r *MySQL) flushPrivileges() {
_, _ = r.Exec("FLUSH PRIVILEGES")
func (r *MySQL) flushPrivileges(ctx context.Context) {
// 权限变更后必须刷新,取消时跳过会让新用户或授权不生效
_, _ = r.Exec(context.WithoutCancel(ctx), "FLUSH PRIVILEGES")
}
+44 -40
View File
@@ -54,29 +54,29 @@ func (r *Postgres) Close() {
_ = r.db.Close()
}
func (r *Postgres) Ping() error {
return r.db.PingContext(context.Background())
func (r *Postgres) Ping(ctx context.Context) error {
return r.db.PingContext(ctx)
}
func (r *Postgres) Query(query string, args ...any) (*sql.Rows, error) {
return r.db.QueryContext(context.Background(), query, args...)
func (r *Postgres) Query(ctx context.Context, query string, args ...any) (*sql.Rows, error) {
return r.db.QueryContext(ctx, query, args...)
}
func (r *Postgres) QueryRow(query string, args ...any) *sql.Row {
return r.db.QueryRowContext(context.Background(), query, args...)
func (r *Postgres) QueryRow(ctx context.Context, query string, args ...any) *sql.Row {
return r.db.QueryRowContext(ctx, query, args...)
}
func (r *Postgres) Exec(query string, args ...any) (sql.Result, error) {
return r.db.ExecContext(context.Background(), query, args...)
func (r *Postgres) Exec(ctx context.Context, query string, args ...any) (sql.Result, error) {
return r.db.ExecContext(ctx, query, args...)
}
func (r *Postgres) Prepare(query string) (*sql.Stmt, error) {
return r.db.PrepareContext(context.Background(), query)
func (r *Postgres) Prepare(ctx context.Context, query string) (*sql.Stmt, error) {
return r.db.PrepareContext(ctx, query)
}
func (r *Postgres) DatabaseCreate(name string) error {
func (r *Postgres) DatabaseCreate(ctx context.Context, name string) error {
// postgres 不支持 CREATE DATABASE IF NOT EXISTS,但是为了保持与 MySQL 一致,先检查数据库是否存在
exist, err := r.DatabaseExists(name)
exist, err := r.DatabaseExists(ctx, name)
if err != nil {
return err
}
@@ -84,41 +84,41 @@ func (r *Postgres) DatabaseCreate(name string) error {
return nil
}
name = strings.ReplaceAll(name, `"`, `""`)
_, err = r.Exec(fmt.Sprintf(`CREATE DATABASE "%s"`, name))
_, err = r.Exec(ctx, fmt.Sprintf(`CREATE DATABASE "%s"`, name))
return err
}
func (r *Postgres) DatabaseDrop(name string) error {
func (r *Postgres) DatabaseDrop(ctx context.Context, name string) error {
name = strings.ReplaceAll(name, `"`, `""`)
_, err := r.Exec(fmt.Sprintf(`DROP DATABASE IF EXISTS "%s"`, name))
_, err := r.Exec(ctx, fmt.Sprintf(`DROP DATABASE IF EXISTS "%s"`, name))
return err
}
func (r *Postgres) DatabaseExists(name string) (bool, error) {
func (r *Postgres) DatabaseExists(ctx context.Context, name string) (bool, error) {
var count int
if err := r.QueryRow("SELECT COUNT(*) FROM pg_database WHERE datname = $1", name).Scan(&count); err != nil {
if err := r.QueryRow(ctx, "SELECT COUNT(*) FROM pg_database WHERE datname = $1", name).Scan(&count); err != nil {
return false, err
}
return count > 0, nil
}
func (r *Postgres) DatabaseSize(name string) (int64, error) {
func (r *Postgres) DatabaseSize(ctx context.Context, name string) (int64, error) {
var size int64
if err := r.QueryRow("SELECT pg_database_size($1)", name).Scan(&size); err != nil {
if err := r.QueryRow(ctx, "SELECT pg_database_size($1)", name).Scan(&size); err != nil {
return 0, err
}
return size, nil
}
func (r *Postgres) DatabaseComment(name, comment string) error {
func (r *Postgres) DatabaseComment(ctx context.Context, name, comment string) error {
name = strings.ReplaceAll(name, `"`, `""`)
_, err := r.Exec(fmt.Sprintf(`COMMENT ON DATABASE "%s" IS '%s'`, name, comment))
_, err := r.Exec(ctx, fmt.Sprintf(`COMMENT ON DATABASE "%s" IS '%s'`, name, comment))
return err
}
func (r *Postgres) UserCreate(user, password string, host ...string) error {
func (r *Postgres) UserCreate(ctx context.Context, user, password string, host ...string) error {
user = strings.ReplaceAll(user, `"`, `""`)
_, err := r.Exec(fmt.Sprintf(`CREATE USER "%s" WITH PASSWORD '%s'`, user, password))
_, err := r.Exec(ctx, fmt.Sprintf(`CREATE USER "%s" WITH PASSWORD '%s'`, user, password))
if err != nil {
return err
}
@@ -126,18 +126,20 @@ func (r *Postgres) UserCreate(user, password string, host ...string) error {
return nil
}
func (r *Postgres) UserDrop(user string, host ...string) error {
func (r *Postgres) UserDrop(ctx context.Context, user string, host ...string) error {
// PostgreSQL 中,如果用户拥有数据库对象或权限,直接 DROP USER 会失败
// 必须先转移所有权并撤销权限
// 三步是一个整体,中途取消会留下丢了所有权却没被删掉的用户
ctx = context.WithoutCancel(ctx)
user = strings.ReplaceAll(user, `"`, `""`)
username := strings.ReplaceAll(r.username, `"`, `""`)
if _, err := r.Exec(fmt.Sprintf(`REASSIGN OWNED BY "%s" TO "%s"`, user, username)); err != nil {
if _, err := r.Exec(ctx, fmt.Sprintf(`REASSIGN OWNED BY "%s" TO "%s"`, user, username)); err != nil {
return err
}
if _, err := r.Exec(fmt.Sprintf(`DROP OWNED BY "%s"`, user)); err != nil {
if _, err := r.Exec(ctx, fmt.Sprintf(`DROP OWNED BY "%s"`, user)); err != nil {
return err
}
_, err := r.Exec(fmt.Sprintf(`DROP USER IF EXISTS "%s"`, user))
_, err := r.Exec(ctx, fmt.Sprintf(`DROP USER IF EXISTS "%s"`, user))
if err != nil {
return err
}
@@ -145,13 +147,13 @@ func (r *Postgres) UserDrop(user string, host ...string) error {
return nil
}
func (r *Postgres) UserPassword(user, password string, host ...string) error {
func (r *Postgres) UserPassword(ctx context.Context, user, password string, host ...string) error {
user = strings.ReplaceAll(user, `"`, `""`)
_, err := r.Exec(fmt.Sprintf(`ALTER USER "%s" WITH PASSWORD '%s'`, user, password))
_, err := r.Exec(ctx, fmt.Sprintf(`ALTER USER "%s" WITH PASSWORD '%s'`, user, password))
return err
}
func (r *Postgres) UserPrivileges(user string, host ...string) ([]string, error) {
func (r *Postgres) UserPrivileges(ctx context.Context, user string, host ...string) ([]string, error) {
query := `
SELECT d.datname
FROM pg_catalog.pg_database d
@@ -162,7 +164,7 @@ func (r *Postgres) UserPrivileges(user string, host ...string) ([]string, error)
ORDER BY d.datname;
`
rows, err := r.Query(query, user)
rows, err := r.Query(ctx, query, user)
if err != nil {
return nil, err
}
@@ -185,27 +187,29 @@ func (r *Postgres) UserPrivileges(user string, host ...string) ([]string, error)
return databases, nil
}
func (r *Postgres) PrivilegesGrant(user, database string, host ...string) error {
func (r *Postgres) PrivilegesGrant(ctx context.Context, user, database string, host ...string) error {
// 改属主和授权是一个整体,中途取消会留下换了属主却没有权限的库
ctx = context.WithoutCancel(ctx)
user = strings.ReplaceAll(user, `"`, `""`)
database = strings.ReplaceAll(database, `"`, `""`)
if _, err := r.Exec(fmt.Sprintf(`ALTER DATABASE "%s" OWNER TO "%s"`, database, user)); err != nil {
if _, err := r.Exec(ctx, fmt.Sprintf(`ALTER DATABASE "%s" OWNER TO "%s"`, database, user)); err != nil {
return err
}
if _, err := r.Exec(fmt.Sprintf(`GRANT ALL PRIVILEGES ON DATABASE "%s" TO "%s"`, database, user)); err != nil {
if _, err := r.Exec(ctx, fmt.Sprintf(`GRANT ALL PRIVILEGES ON DATABASE "%s" TO "%s"`, database, user)); err != nil {
return err
}
return nil
}
func (r *Postgres) PrivilegesRevoke(user, database string, host ...string) error {
func (r *Postgres) PrivilegesRevoke(ctx context.Context, user, database string, host ...string) error {
user = strings.ReplaceAll(user, `"`, `""`)
database = strings.ReplaceAll(database, `"`, `""`)
_, err := r.Exec(fmt.Sprintf(`REVOKE ALL PRIVILEGES ON DATABASE "%s" FROM "%s"`, database, user))
_, err := r.Exec(ctx, fmt.Sprintf(`REVOKE ALL PRIVILEGES ON DATABASE "%s" FROM "%s"`, database, user))
return err
}
func (r *Postgres) Users() ([]User, error) {
func (r *Postgres) Users(ctx context.Context) ([]User, error) {
query := `
SELECT rolname,
rolsuper,
@@ -216,7 +220,7 @@ func (r *Postgres) Users() ([]User, error) {
FROM pg_roles
WHERE rolcanlogin = true;
`
rows, err := r.Query(query)
rows, err := r.Query(ctx, query)
if err != nil {
return nil, err
}
@@ -257,7 +261,7 @@ func (r *Postgres) Users() ([]User, error) {
return users, nil
}
func (r *Postgres) Databases() ([]Database, error) {
func (r *Postgres) Databases(ctx context.Context) ([]Database, error) {
query := `
SELECT
d.datname,
@@ -267,7 +271,7 @@ func (r *Postgres) Databases() ([]Database, error) {
FROM pg_catalog.pg_database d
WHERE datistemplate = false;
`
rows, err := r.Query(query)
rows, err := r.Query(ctx, query)
if err != nil {
return nil, err
}
+8 -8
View File
@@ -15,12 +15,12 @@ type SQLite struct {
}
// NewSQLite 打开 SQLite 数据库文件
func NewSQLite(path string) (*SQLite, error) {
func NewSQLite(ctx context.Context, path string) (*SQLite, error) {
db, err := sql.Open("sqlite", path)
if err != nil {
return nil, fmt.Errorf("open sqlite failed: %w", err)
}
if err = db.PingContext(context.Background()); err != nil {
if err = db.PingContext(ctx); err != nil {
return nil, fmt.Errorf("connect to sqlite failed: %w", err)
}
return &SQLite{db: db, path: path}, nil
@@ -30,13 +30,13 @@ func (r *SQLite) Close() {
_ = r.db.Close()
}
func (r *SQLite) Ping() error {
return r.db.PingContext(context.Background())
func (r *SQLite) Ping(ctx context.Context) error {
return r.db.PingContext(ctx)
}
// Tables 获取所有表
func (r *SQLite) Tables() ([]string, error) {
rows, err := r.db.QueryContext(context.Background(), "SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' ORDER BY name")
func (r *SQLite) Tables(ctx context.Context) ([]string, error) {
rows, err := r.db.QueryContext(ctx, "SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' ORDER BY name")
if err != nil {
return nil, err
}
@@ -64,8 +64,8 @@ type SQLiteColumn struct {
}
// TableInfo 获取表结构
func (r *SQLite) TableInfo(name string) ([]SQLiteColumn, error) {
rows, err := r.db.QueryContext(context.Background(), fmt.Sprintf("PRAGMA table_info('%s')", name))
func (r *SQLite) TableInfo(ctx context.Context, name string) ([]SQLiteColumn, error) {
rows, err := r.db.QueryContext(ctx, fmt.Sprintf("PRAGMA table_info('%s')", name))
if err != nil {
return nil, err
}
+10 -10
View File
@@ -30,7 +30,7 @@ func NewLocal(basePath string) (Storage, error) {
}
// Delete 删除文件
func (l *Local) Delete(files ...string) error {
func (l *Local) Delete(_ context.Context, files ...string) error {
for _, file := range files {
fullPath := l.fullPath(file)
if err := os.Remove(fullPath); err != nil && !os.IsNotExist(err) {
@@ -41,14 +41,14 @@ func (l *Local) Delete(files ...string) error {
}
// Exists 检查文件是否存在
func (l *Local) Exists(file string) bool {
func (l *Local) Exists(_ context.Context, file string) bool {
fullPath := l.fullPath(file)
_, err := os.Stat(fullPath)
return !os.IsNotExist(err)
}
// LastModified 获取文件最后修改时间
func (l *Local) LastModified(file string) (time.Time, error) {
func (l *Local) LastModified(_ context.Context, file string) (time.Time, error) {
fullPath := l.fullPath(file)
info, err := os.Stat(fullPath)
if err != nil {
@@ -58,7 +58,7 @@ func (l *Local) LastModified(file string) (time.Time, error) {
}
// List 列出目录下的所有文件
func (l *Local) List(path string) ([]string, error) {
func (l *Local) List(_ context.Context, path string) ([]string, error) {
fullPath := l.fullPath(path)
entries, err := os.ReadDir(fullPath)
if err != nil {
@@ -75,7 +75,7 @@ func (l *Local) List(path string) ([]string, error) {
}
// Put 写入文件内容
func (l *Local) Put(file string, content io.Reader) error {
func (l *Local) Put(ctx context.Context, file string, content io.Reader) error {
fullPath := l.fullPath(file)
// 确保目录存在
@@ -84,7 +84,7 @@ func (l *Local) Put(file string, content io.Reader) error {
}
// 预检查空间
if err := l.preCheckPath(filepath.Dir(fullPath)); err != nil {
if err := l.preCheckPath(ctx, filepath.Dir(fullPath)); err != nil {
return fmt.Errorf("pre check path failed: %w", err)
}
@@ -100,7 +100,7 @@ func (l *Local) Put(file string, content io.Reader) error {
}
// Size 获取文件大小
func (l *Local) Size(file string) (int64, error) {
func (l *Local) Size(_ context.Context, file string) (int64, error) {
fullPath := l.fullPath(file)
info, err := os.Stat(fullPath)
if err != nil {
@@ -120,12 +120,12 @@ func (l *Local) fullPath(path string) string {
return filepath.Join(l.basePath, path)
}
func (l *Local) preCheckPath(path string) error {
size, err := pkgio.SizeX(context.Background(), path)
func (l *Local) preCheckPath(ctx context.Context, path string) error {
size, err := pkgio.SizeX(ctx, path)
if err != nil {
return err
}
files, err := pkgio.CountX(context.Background(), path)
files, err := pkgio.CountX(ctx, path)
if err != nil {
return err
}
+13 -12
View File
@@ -1,6 +1,7 @@
package storage
import (
"context"
"fmt"
"io"
"strings"
@@ -55,25 +56,25 @@ func NewS3(cfg S3Config) Storage {
}
// Delete 删除文件
func (s *S3) Delete(files ...string) error {
func (s *S3) Delete(ctx context.Context, files ...string) error {
if len(files) == 0 {
return nil
}
keys := lo.Map(files, func(file string, _ int) string {
return s.getKey(file)
})
return s.client.Delete(keys...)
return s.client.Delete(ctx, keys...)
}
// Exists 检查文件是否存在
func (s *S3) Exists(file string) bool {
_, err := s.client.Stat(s.getKey(file))
func (s *S3) Exists(ctx context.Context, file string) bool {
_, err := s.client.Stat(ctx, s.getKey(file))
return err == nil
}
// LastModified 获取文件最后修改时间
func (s *S3) LastModified(file string) (time.Time, error) {
info, err := s.client.Stat(s.getKey(file))
func (s *S3) LastModified(ctx context.Context, file string) (time.Time, error) {
info, err := s.client.Stat(ctx, s.getKey(file))
if err != nil {
return time.Time{}, err
}
@@ -81,14 +82,14 @@ func (s *S3) LastModified(file string) (time.Time, error) {
}
// List 列出目录下的所有文件
func (s *S3) List(path string) ([]string, error) {
func (s *S3) List(ctx context.Context, path string) ([]string, error) {
prefix := s.getKey(path)
if prefix != "" && !strings.HasSuffix(prefix, "/") {
prefix += "/"
}
var files []string
for obj, err := range s.client.List(prefix, "/") {
for obj, err := range s.client.List(ctx, prefix, "/") {
if err != nil {
return nil, err
}
@@ -103,13 +104,13 @@ func (s *S3) List(path string) ([]string, error) {
}
// Put 写入文件内容
func (s *S3) Put(file string, content io.Reader) error {
return s.client.Put(s.getKey(file), content, "application/octet-stream")
func (s *S3) Put(ctx context.Context, file string, content io.Reader) error {
return s.client.Put(ctx, s.getKey(file), content, "application/octet-stream")
}
// Size 获取文件大小
func (s *S3) Size(file string) (int64, error) {
info, err := s.client.Stat(s.getKey(file))
func (s *S3) Size(ctx context.Context, file string) (int64, error) {
info, err := s.client.Stat(ctx, s.getKey(file))
if err != nil {
return 0, err
}
+3 -4
View File
@@ -22,11 +22,11 @@ type Object struct {
// List 返回一个自动翻页、产出 prefix 下所有对象的迭代器
// delimiter 非空(通常为 "/")时按目录层级分组
// 迭代中若出错,会以 (零值 Object, err) 产出一次随后结束
func (c *S3) List(prefix, delimiter string) iter.Seq2[Object, error] {
func (c *S3) List(ctx context.Context, prefix, delimiter string) iter.Seq2[Object, error] {
return func(yield func(Object, error) bool) {
token := ""
for {
page, err := c.listPage(prefix, delimiter, token)
page, err := c.listPage(ctx, prefix, delimiter, token)
if err != nil {
yield(Object{}, err)
return
@@ -50,7 +50,7 @@ type listPage struct {
nextToken string
}
func (c *S3) listPage(prefix, delimiter, token string) (listPage, error) {
func (c *S3) listPage(ctx context.Context, prefix, delimiter, token string) (listPage, error) {
query := url.Values{"list-type": {"2"}}
if prefix != "" {
query.Set("prefix", prefix)
@@ -62,7 +62,6 @@ func (c *S3) listPage(prefix, delimiter, token string) (listPage, error) {
query.Set("continuation-token", token)
}
ctx := context.Background()
req, err := http.NewRequestWithContext(ctx, http.MethodGet, c.base+"?"+query.Encode(), nil)
if err != nil {
return listPage{}, err
+4 -6
View File
@@ -24,8 +24,7 @@ type ObjectInfo struct {
}
// Stat 通过 HEAD 获取对象元数据;对象不存在时返回的错误可用 IsNotFound 判断
func (c *S3) Stat(key string) (ObjectInfo, error) {
ctx := context.Background()
func (c *S3) Stat(ctx context.Context, key string) (ObjectInfo, error) {
req, err := http.NewRequestWithContext(ctx, http.MethodHead, c.objectURL(key), nil)
if err != nil {
return ObjectInfo{}, err
@@ -58,16 +57,16 @@ func (c *S3) Stat(key string) (ObjectInfo, error) {
}
// Delete 删除一个或多个对象,自动按每批 1000 个分批请求
func (c *S3) Delete(keys ...string) error {
func (c *S3) Delete(ctx context.Context, keys ...string) error {
for batch := range slices.Chunk(keys, 1000) {
if err := c.deleteBatch(batch); err != nil {
if err := c.deleteBatch(ctx, batch); err != nil {
return err
}
}
return nil
}
func (c *S3) deleteBatch(keys []string) error {
func (c *S3) deleteBatch(ctx context.Context, keys []string) error {
type object struct {
Key string `xml:"Key"`
}
@@ -86,7 +85,6 @@ func (c *S3) deleteBatch(keys []string) error {
return err
}
ctx := context.Background()
req, err := http.NewRequestWithContext(ctx, http.MethodPost, c.base+"?delete", bytes.NewReader(body))
if err != nil {
return err
+1 -1
View File
@@ -29,7 +29,7 @@ func TestDoRetry(t *testing.T) {
defer srv.Close()
c := New(Config{Region: "us-east-1", Bucket: "b", Endpoint: srv.URL, PathStyle: true})
if err := c.putObject("k", []byte("hello"), "text/plain"); err != nil {
if err := c.putObject(t.Context(), "k", []byte("hello"), "text/plain"); err != nil {
t.Fatal(err)
}
+17 -19
View File
@@ -31,7 +31,7 @@ const (
)
// Put 上传一个对象:内容不足一个分片时走单次 PUT,否则流式分片上传
func (c *S3) Put(key string, body io.Reader, contentType string) error {
func (c *S3) Put(ctx context.Context, key string, body io.Reader, contentType string) error {
// 用动态 buffer 读取首块,避免小对象也分配整个 partSize
var first bytes.Buffer
n, err := io.CopyN(&first, body, c.partSize)
@@ -40,14 +40,13 @@ func (c *S3) Put(key string, body io.Reader, contentType string) error {
}
if n < c.partSize {
// 全部内容不足一个分片 → 单次 PUT(含空对象)
return c.putObject(key, first.Bytes(), contentType)
return c.putObject(ctx, key, first.Bytes(), contentType)
}
// 已读满一个分片,可能还有更多 → 流式分片上传
return c.uploadMultipart(key, first.Bytes(), body, contentType)
return c.uploadMultipart(ctx, key, first.Bytes(), body, contentType)
}
func (c *S3) putObject(key string, data []byte, contentType string) error {
ctx := context.Background()
func (c *S3) putObject(ctx context.Context, key string, data []byte, contentType string) error {
req, err := http.NewRequestWithContext(ctx, http.MethodPut, c.objectURL(key), bytes.NewReader(data))
if err != nil {
return err
@@ -67,19 +66,19 @@ type completedPart struct {
ETag string `xml:"ETag"`
}
func (c *S3) uploadMultipart(key string, first []byte, body io.Reader, contentType string) error {
uploadID, err := c.initiate(key, contentType)
func (c *S3) uploadMultipart(ctx context.Context, key string, first []byte, body io.Reader, contentType string) error {
uploadID, err := c.initiate(ctx, key, contentType)
if err != nil {
return err
}
parts, err := c.uploadParts(key, uploadID, first, body)
parts, err := c.uploadParts(ctx, key, uploadID, first, body)
if err != nil {
_ = c.abort(key, uploadID)
_ = c.abort(ctx, key, uploadID)
return err
}
if err := c.complete(key, uploadID, parts); err != nil {
_ = c.abort(key, uploadID)
if err := c.complete(ctx, key, uploadID, parts); err != nil {
_ = c.abort(ctx, key, uploadID)
return err
}
return nil
@@ -87,8 +86,8 @@ func (c *S3) uploadMultipart(key string, first []byte, body io.Reader, contentTy
// uploadParts 顺序读取、并发上传分片。errgroup 的并发上限会对读取形成背压,
// 因此常驻内存约为 concurrency × partSize,而非整个文件大小
func (c *S3) uploadParts(key, uploadID string, first []byte, body io.Reader) ([]completedPart, error) {
g, ctx := errgroup.WithContext(context.Background())
func (c *S3) uploadParts(ctx context.Context, key, uploadID string, first []byte, body io.Reader) ([]completedPart, error) {
g, ctx := errgroup.WithContext(ctx)
g.SetLimit(c.concurrency)
var mu sync.Mutex
@@ -166,8 +165,7 @@ func isRetryable(err error) bool {
return errors.As(err, &ne)
}
func (c *S3) initiate(key, contentType string) (string, error) {
ctx := context.Background()
func (c *S3) initiate(ctx context.Context, key, contentType string) (string, error) {
req, err := http.NewRequestWithContext(ctx, http.MethodPost, c.objectURL(key)+"?uploads", nil)
if err != nil {
return "", err
@@ -193,7 +191,7 @@ func (c *S3) initiate(key, contentType string) (string, error) {
return result.UploadID, nil
}
func (c *S3) complete(key, uploadID string, parts []completedPart) error {
func (c *S3) complete(ctx context.Context, key, uploadID string, parts []completedPart) error {
payload := struct {
XMLName xml.Name `xml:"CompleteMultipartUpload"`
XMLNS string `xml:"xmlns,attr"`
@@ -205,7 +203,6 @@ func (c *S3) complete(key, uploadID string, parts []completedPart) error {
return err
}
ctx := context.Background()
req, err := http.NewRequestWithContext(ctx, http.MethodPost, c.objectURL(key)+"?uploadId="+url.QueryEscape(uploadID), bytes.NewReader(body))
if err != nil {
return err
@@ -220,8 +217,9 @@ func (c *S3) complete(key, uploadID string, parts []completedPart) error {
return err
}
func (c *S3) abort(key, uploadID string) error {
ctx := context.Background()
// abort 清理未完成的分片上传,取消导致的失败也要清,否则残片会一直占用存储
func (c *S3) abort(ctx context.Context, key, uploadID string) error {
ctx = context.WithoutCancel(ctx)
req, err := http.NewRequestWithContext(ctx, http.MethodDelete, c.objectURL(key)+"?uploadId="+url.QueryEscape(uploadID), nil)
if err != nil {
return err
+2 -2
View File
@@ -54,7 +54,7 @@ func TestPut(t *testing.T) {
t.Run("small file uses single PUT", func(t *testing.T) {
data := bytes.Repeat([]byte("x"), 1024)
if err := c.Put("small.txt", bytes.NewReader(data), "text/plain"); err != nil {
if err := c.Put(t.Context(), "small.txt", bytes.NewReader(data), "text/plain"); err != nil {
t.Fatal(err)
}
if !bytes.Equal(simpleBody, data) {
@@ -76,7 +76,7 @@ func TestPut(t *testing.T) {
for i := range data {
data[i] = byte(i)
}
if err := c.Put("big.bin", bytes.NewReader(data), "application/octet-stream"); err != nil {
if err := c.Put(t.Context(), "big.bin", bytes.NewReader(data), "application/octet-stream"); err != nil {
t.Fatal(err)
}
if len(parts) != 3 {
+22 -14
View File
@@ -1,9 +1,11 @@
package storage
import (
"context"
"errors"
"fmt"
"io"
"net"
"os"
"path/filepath"
"strings"
@@ -45,7 +47,7 @@ func NewSFTP(config SFTPConfig) (Storage, error) {
}
// connect 建立 SFTP 连接,返回 client 和 cleanup 函数
func (s *SFTP) connect() (*sftp.Client, func(), error) {
func (s *SFTP) connect(ctx context.Context) (*sftp.Client, func(), error) {
var auth []ssh.AuthMethod
// 密码认证
if s.config.Password != "" {
@@ -68,10 +70,16 @@ func (s *SFTP) connect() (*sftp.Client, func(), error) {
}
addr := fmt.Sprintf("%s:%d", s.config.Host, s.config.Port)
sshClient, err := ssh.Dial("tcp", addr, clientConfig)
conn, err := (&net.Dialer{Timeout: s.config.Timeout}).DialContext(ctx, "tcp", addr)
if err != nil {
return nil, nil, fmt.Errorf("failed to connect to SSH server: %w", err)
}
sshConn, chans, reqs, err := ssh.NewClientConn(conn, addr, clientConfig)
if err != nil {
_ = conn.Close()
return nil, nil, fmt.Errorf("failed to connect to SSH server: %w", err)
}
sshClient := ssh.NewClient(sshConn, chans, reqs)
sftpClient, err := sftp.NewClient(sshClient)
if err != nil {
@@ -88,8 +96,8 @@ func (s *SFTP) connect() (*sftp.Client, func(), error) {
}
// Delete 删除文件
func (s *SFTP) Delete(files ...string) error {
client, cleanup, err := s.connect()
func (s *SFTP) Delete(ctx context.Context, files ...string) error {
client, cleanup, err := s.connect(ctx)
if err != nil {
return err
}
@@ -105,8 +113,8 @@ func (s *SFTP) Delete(files ...string) error {
}
// Exists 检查文件是否存在
func (s *SFTP) Exists(file string) bool {
client, cleanup, err := s.connect()
func (s *SFTP) Exists(ctx context.Context, file string) bool {
client, cleanup, err := s.connect(ctx)
if err != nil {
return false
}
@@ -118,8 +126,8 @@ func (s *SFTP) Exists(file string) bool {
}
// LastModified 获取文件最后修改时间
func (s *SFTP) LastModified(file string) (time.Time, error) {
client, cleanup, err := s.connect()
func (s *SFTP) LastModified(ctx context.Context, file string) (time.Time, error) {
client, cleanup, err := s.connect(ctx)
if err != nil {
return time.Time{}, err
}
@@ -135,8 +143,8 @@ func (s *SFTP) LastModified(file string) (time.Time, error) {
}
// List 列出目录下的所有文件
func (s *SFTP) List(path string) ([]string, error) {
client, cleanup, err := s.connect()
func (s *SFTP) List(ctx context.Context, path string) ([]string, error) {
client, cleanup, err := s.connect(ctx)
if err != nil {
return nil, err
}
@@ -163,8 +171,8 @@ func (s *SFTP) List(path string) ([]string, error) {
}
// Put 写入文件内容
func (s *SFTP) Put(file string, content io.Reader) error {
client, cleanup, err := s.connect()
func (s *SFTP) Put(ctx context.Context, file string, content io.Reader) error {
client, cleanup, err := s.connect(ctx)
if err != nil {
return err
}
@@ -194,8 +202,8 @@ func (s *SFTP) Put(file string, content io.Reader) error {
}
// Size 获取文件大小
func (s *SFTP) Size(file string) (int64, error) {
client, cleanup, err := s.connect()
func (s *SFTP) Size(ctx context.Context, file string) (int64, error) {
client, cleanup, err := s.connect(ctx)
if err != nil {
return 0, err
}
+7 -6
View File
@@ -1,21 +1,22 @@
package storage
import (
"context"
"io"
"time"
)
type Storage interface {
// Delete deletes the given file(s).
Delete(file ...string) error
Delete(ctx context.Context, file ...string) error
// Exists determines if a file exists.
Exists(file string) bool
Exists(ctx context.Context, file string) bool
// LastModified gets the file's last modified time.
LastModified(file string) (time.Time, error)
LastModified(ctx context.Context, file string) (time.Time, error)
// List lists all files (not directories) in the given path.
List(path string) ([]string, error)
List(ctx context.Context, path string) ([]string, error)
// Put writes the contents of a file.
Put(file string, content io.Reader) error
Put(ctx context.Context, file string, content io.Reader) error
// Size gets the file size of a given file.
Size(file string) (int64, error)
Size(ctx context.Context, file string) (int64, error)
}
+7 -6
View File
@@ -1,6 +1,7 @@
package storage
import (
"context"
"fmt"
"io"
"os"
@@ -53,7 +54,7 @@ func NewWebDav(config WebDavConfig) (Storage, error) {
}
// Delete 删除文件
func (w *WebDav) Delete(files ...string) error {
func (w *WebDav) Delete(_ context.Context, files ...string) error {
for _, file := range files {
remotePath := w.fullPath(file)
if err := w.client.Remove(remotePath); err != nil {
@@ -64,14 +65,14 @@ func (w *WebDav) Delete(files ...string) error {
}
// Exists 检查文件是否存在
func (w *WebDav) Exists(file string) bool {
func (w *WebDav) Exists(_ context.Context, file string) bool {
remotePath := w.fullPath(file)
_, err := w.client.Stat(remotePath)
return err == nil
}
// LastModified 获取文件最后修改时间
func (w *WebDav) LastModified(file string) (time.Time, error) {
func (w *WebDav) LastModified(_ context.Context, file string) (time.Time, error) {
remotePath := w.fullPath(file)
stat, err := w.client.Stat(remotePath)
if err != nil {
@@ -82,7 +83,7 @@ func (w *WebDav) LastModified(file string) (time.Time, error) {
}
// Put 写入文件内容
func (w *WebDav) Put(file string, content io.Reader) error {
func (w *WebDav) Put(_ context.Context, file string, content io.Reader) error {
remotePath := w.fullPath(file)
// 确保目录存在
@@ -101,7 +102,7 @@ func (w *WebDav) Put(file string, content io.Reader) error {
}
// Size 获取文件大小
func (w *WebDav) Size(file string) (int64, error) {
func (w *WebDav) Size(_ context.Context, file string) (int64, error) {
remotePath := w.fullPath(file)
stat, err := w.client.Stat(remotePath)
if err != nil {
@@ -112,7 +113,7 @@ func (w *WebDav) Size(file string) (int64, error) {
}
// List 列出目录下的所有文件
func (w *WebDav) List(path string) ([]string, error) {
func (w *WebDav) List(_ context.Context, path string) ([]string, error) {
remotePath := w.fullPath(path)
entries, err := w.client.ReadDir(remotePath)
if err != nil {