swirl/biz/container.go
2021-12-17 20:13:58 +08:00

201 lines
5.9 KiB
Go

package biz
import (
"context"
"time"
"github.com/cuigh/auxo/data"
"github.com/cuigh/auxo/net/web"
"github.com/cuigh/swirl/docker"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/mount"
)
type ContainerBiz interface {
Search(node, name, status string, pageIndex, pageSize int) ([]*Container, int, error)
Find(node, id string) (container *Container, raw string, err error)
Delete(node, id string, user web.User) (err error)
FetchLogs(node, id string, lines int, timestamps bool) (stdout, stderr string, err error)
ExecCreate(node, id string, cmd string) (resp types.IDResponse, err error)
ExecAttach(node, id string) (resp types.HijackedResponse, err error)
ExecStart(node, id string) error
}
func NewContainer(d *docker.Docker) ContainerBiz {
return &containerBiz{d: d}
}
type containerBiz struct {
d *docker.Docker
}
func (b *containerBiz) Find(node, id string) (c *Container, raw string, err error) {
var (
cj types.ContainerJSON
r []byte
)
if cj, r, err = b.d.ContainerInspect(context.TODO(), node, id); err == nil {
raw, err = indentJSON(r)
}
if err == nil {
c = newContainerDetail(&cj)
}
return
}
func (b *containerBiz) Search(node, name, status string, pageIndex, pageSize int) (containers []*Container, total int, err error) {
list, total, err := b.d.ContainerList(context.TODO(), node, name, status, pageIndex, pageSize)
if err != nil {
return nil, 0, err
}
containers = make([]*Container, len(list))
for i, nr := range list {
containers[i] = newContainerSummary(&nr)
}
return containers, total, nil
}
func (b *containerBiz) Delete(node, id string, user web.User) (err error) {
err = b.d.ContainerRemove(context.TODO(), node, id)
//if err == nil {
// Event.CreateContainer(model.EventActionDelete, id, user)
//}
return
}
func (b *containerBiz) ExecCreate(node, id, cmd string) (resp types.IDResponse, err error) {
return b.d.ContainerExecCreate(context.TODO(), node, id, cmd)
}
func (b *containerBiz) ExecAttach(node, id string) (resp types.HijackedResponse, err error) {
return b.d.ContainerExecAttach(context.TODO(), node, id)
}
func (b *containerBiz) ExecStart(node, id string) error {
return b.d.ContainerExecStart(context.TODO(), node, id)
}
func (b *containerBiz) FetchLogs(node, id string, lines int, timestamps bool) (string, string, error) {
stdout, stderr, err := b.d.ContainerLogs(context.TODO(), node, id, lines, timestamps)
if err != nil {
return "", "", err
}
return stdout.String(), stderr.String(), nil
}
type Container struct {
ID string `json:"id"`
Name string `json:"name"`
Image string `json:"image,omitempty"`
Command string `json:"command,omitempty"`
CreatedAt string `json:"createdAt"`
Ports []*ContainerPort `json:"ports,omitempty"`
SizeRw int64 `json:"sizeRw"`
SizeRootFs int64 `json:"sizeRootFs"`
Labels data.Options `json:"labels"`
State string `json:"state"`
Status string `json:"status"`
NetworkMode string `json:"networkMode"`
Mounts []*ContainerMount `json:"mounts"`
PID int `json:"pid,omitempty"`
StartedAt string `json:"startedAt,omitempty"`
}
type ContainerPort struct {
IP string `json:"ip,omitempty"`
PrivatePort uint16 `json:"privatePort,omitempty"`
PublicPort uint16 `json:"publicPort,omitempty"`
Type string `json:"type,omitempty"`
}
type ContainerMount struct {
Type mount.Type `json:"type,omitempty"`
Name string `json:"name,omitempty"`
Source string `json:"source,omitempty"`
Destination string `json:"destination,omitempty"`
Driver string `json:"driver,omitempty"`
Mode string `json:"mode,omitempty"`
RW bool `json:"rw,omitempty"`
Propagation mount.Propagation `json:"propagation,omitempty"`
}
func newContainerMount(m types.MountPoint) *ContainerMount {
return &ContainerMount{
Type: m.Type,
Name: m.Name,
Source: m.Source,
Destination: m.Destination,
Driver: m.Driver,
Mode: m.Mode,
RW: m.RW,
Propagation: m.Propagation,
}
}
func newContainerSummary(c *types.Container) *Container {
container := &Container{
ID: c.ID,
Name: c.Names[0],
Image: normalizeImage(c.Image),
Command: c.Command,
CreatedAt: formatTime(time.Unix(c.Created, 0)),
SizeRw: c.SizeRw,
SizeRootFs: c.SizeRootFs,
Labels: mapToOptions(c.Labels),
State: c.State,
Status: c.Status,
NetworkMode: c.HostConfig.NetworkMode,
}
for _, p := range c.Ports {
container.Ports = append(container.Ports, &ContainerPort{
IP: p.IP,
PrivatePort: p.PrivatePort,
PublicPort: p.PublicPort,
Type: p.Type,
})
}
for _, m := range c.Mounts {
container.Mounts = append(container.Mounts, newContainerMount(m))
}
return container
}
func newContainerDetail(c *types.ContainerJSON) *Container {
created, _ := time.Parse(time.RFC3339Nano, c.Created)
startedAt, _ := time.Parse(time.RFC3339Nano, c.State.StartedAt)
container := &Container{
ID: c.ID,
Name: c.Name,
Image: c.Image,
//Command: c.Command,
CreatedAt: formatTime(created),
Labels: mapToOptions(c.Config.Labels),
State: c.State.Status,
//Status: c.Status,
NetworkMode: string(c.HostConfig.NetworkMode),
PID: c.State.Pid,
StartedAt: formatTime(startedAt),
}
if c.SizeRw != nil {
container.SizeRw = *c.SizeRw
}
if c.SizeRootFs != nil {
container.SizeRootFs = *c.SizeRootFs
}
//for _, p := range c.Ports {
// container.Ports = append(container.Ports, &ContainerPort{
// IP: p.IP,
// PrivatePort: p.PrivatePort,
// PublicPort: p.PublicPort,
// Type: p.Type,
// })
//}
for _, m := range c.Mounts {
container.Mounts = append(container.Mounts, newContainerMount(m))
}
return container
}