mirror of
https://github.com/acepanel/panel.git
synced 2026-02-05 00:39:32 +08:00
104 lines
2.5 KiB
Go
104 lines
2.5 KiB
Go
package data
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/spf13/cast"
|
|
|
|
"github.com/TheTNB/panel/internal/biz"
|
|
"github.com/TheTNB/panel/internal/http/request"
|
|
"github.com/TheTNB/panel/pkg/shell"
|
|
"github.com/TheTNB/panel/pkg/types"
|
|
)
|
|
|
|
type containerImageRepo struct {
|
|
cmd string
|
|
}
|
|
|
|
func NewContainerImageRepo(cmd ...string) biz.ContainerImageRepo {
|
|
if len(cmd) == 0 {
|
|
cmd = append(cmd, "docker")
|
|
}
|
|
return &containerImageRepo{
|
|
cmd: cmd[0],
|
|
}
|
|
}
|
|
|
|
// List 列出镜像
|
|
func (r *containerImageRepo) List() ([]types.ContainerImage, error) {
|
|
output, err := shell.ExecfWithTimeout(10*time.Second, "%s images -a --format json", r.cmd)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
lines := strings.Split(output, "\n")
|
|
|
|
var images []types.ContainerImage
|
|
for _, line := range lines {
|
|
if line == "" {
|
|
continue
|
|
}
|
|
|
|
var item struct {
|
|
ID string `json:"ID"`
|
|
Containers string `json:"Containers"`
|
|
Repository string `json:"Repository"`
|
|
Tag string `json:"Tag"`
|
|
Digest string `json:"Digest"`
|
|
CreatedAt string `json:"CreatedAt"`
|
|
Size string `json:"Size"`
|
|
SharedSize string `json:"SharedSize"`
|
|
VirtualSize string `json:"VirtualSize"`
|
|
}
|
|
if err = json.Unmarshal([]byte(line), &item); err != nil {
|
|
return nil, fmt.Errorf("unmarshal failed: %w", err)
|
|
}
|
|
|
|
createdAt, _ := time.Parse("2006-01-02 15:04:05 -0700 MST", item.CreatedAt)
|
|
images = append(images, types.ContainerImage{
|
|
ID: item.ID,
|
|
Containers: cast.ToInt64(item.Containers),
|
|
Tag: item.Tag,
|
|
CreatedAt: createdAt,
|
|
Size: item.Size,
|
|
})
|
|
}
|
|
|
|
return images, nil
|
|
}
|
|
|
|
// Pull 拉取镜像
|
|
func (r *containerImageRepo) Pull(req *request.ContainerImagePull) error {
|
|
var sb strings.Builder
|
|
|
|
if req.Auth {
|
|
sb.WriteString(fmt.Sprintf("%s login -u %s -p %s", r.cmd, req.Username, req.Password))
|
|
if _, err := shell.ExecfWithTimeout(1*time.Minute, sb.String()); err != nil {
|
|
return fmt.Errorf("login failed: %w", err)
|
|
}
|
|
sb.Reset()
|
|
}
|
|
|
|
sb.WriteString(fmt.Sprintf("%s pull %s", r.cmd, req.Name))
|
|
|
|
if _, err := shell.ExecfWithTimeout(20*time.Minute, sb.String()); err != nil { // nolint: govet
|
|
return fmt.Errorf("pull failed: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// Remove 删除镜像
|
|
func (r *containerImageRepo) Remove(id string) error {
|
|
_, err := shell.ExecfWithTimeout(30*time.Second, "%s rmi %s", r.cmd, id)
|
|
return err
|
|
}
|
|
|
|
// Prune 清理未使用的镜像
|
|
func (r *containerImageRepo) Prune() error {
|
|
_, err := shell.ExecfWithTimeout(30*time.Second, "%s image prune -f", r.cmd)
|
|
return err
|
|
}
|