-
-
Notifications
You must be signed in to change notification settings - Fork 112
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
84 additions
and
78 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,78 +1,103 @@ | ||
package data | ||
|
||
import ( | ||
"context" | ||
"encoding/base64" | ||
"encoding/json" | ||
"io" | ||
"fmt" | ||
"strings" | ||
"time" | ||
|
||
"github.com/docker/docker/api/types/filters" | ||
"github.com/docker/docker/api/types/image" | ||
"github.com/docker/docker/api/types/registry" | ||
"github.com/docker/docker/client" | ||
"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 { | ||
client *client.Client | ||
cmd string | ||
} | ||
|
||
func NewContainerImageRepo(sock ...string) biz.ContainerImageRepo { | ||
if len(sock) == 0 { | ||
sock = append(sock, "/run/podman/podman.sock") | ||
func NewContainerImageRepo(cmd ...string) biz.ContainerImageRepo { | ||
if len(cmd) == 0 { | ||
cmd = append(cmd, "docker") | ||
} | ||
cli, _ := client.NewClientWithOpts(client.WithHost("unix://"+sock[0]), client.WithAPIVersionNegotiation()) | ||
return &containerImageRepo{ | ||
client: cli, | ||
cmd: cmd[0], | ||
} | ||
} | ||
|
||
// List 列出镜像 | ||
func (r *containerImageRepo) List() ([]image.Summary, error) { | ||
return r.client.ImageList(context.Background(), image.ListOptions{ | ||
All: true, | ||
}) | ||
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 { | ||
options := image.PullOptions{} | ||
var sb strings.Builder | ||
|
||
if req.Auth { | ||
authConfig := registry.AuthConfig{ | ||
Username: req.Username, | ||
Password: req.Password, | ||
} | ||
encodedJSON, err := json.Marshal(authConfig) | ||
if err != nil { | ||
return err | ||
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) | ||
} | ||
authStr := base64.URLEncoding.EncodeToString(encodedJSON) | ||
options.RegistryAuth = authStr | ||
sb.Reset() | ||
} | ||
|
||
out, err := r.client.ImagePull(context.Background(), req.Name, options) | ||
if err != nil { | ||
return err | ||
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) | ||
} | ||
defer out.Close() | ||
|
||
_, err = io.Copy(io.Discard, out) | ||
return err | ||
return nil | ||
} | ||
|
||
// Remove 删除镜像 | ||
func (r *containerImageRepo) Remove(id string) error { | ||
_, err := r.client.ImageRemove(context.Background(), id, image.RemoveOptions{ | ||
Force: true, | ||
PruneChildren: true, | ||
}) | ||
_, err := shell.ExecfWithTimeout(30*time.Second, "%s rmi %s", r.cmd, id) | ||
return err | ||
} | ||
|
||
// Prune 清理未使用的镜像 | ||
func (r *containerImageRepo) Prune() error { | ||
_, err := r.client.ImagesPrune(context.Background(), filters.NewArgs()) | ||
_, err := shell.ExecfWithTimeout(30*time.Second, "%s image prune -f", r.cmd) | ||
return err | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package types | ||
|
||
import ( | ||
"time" | ||
) | ||
|
||
type ContainerImage struct { | ||
ID string `json:"id"` | ||
Containers int64 `json:"containers"` | ||
Tag string `json:"tag"` | ||
Size string `json:"size"` | ||
CreatedAt time.Time `json:"created_at"` | ||
} |