mirror of
https://github.com/jesseduffield/lazydocker.git
synced 2026-07-24 08:01:03 +00:00
more progress
This commit is contained in:
parent
d3ea878fc4
commit
e5ccc673d9
3 changed files with 222 additions and 13 deletions
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
"github.com/docker/docker/client"
|
"github.com/docker/docker/client"
|
||||||
|
|
@ -26,6 +27,199 @@ type Container struct {
|
||||||
OSCommand *OSCommand
|
OSCommand *OSCommand
|
||||||
Log *logrus.Entry
|
Log *logrus.Entry
|
||||||
Stats ContainerCliStat
|
Stats ContainerCliStat
|
||||||
|
Details Details
|
||||||
|
}
|
||||||
|
|
||||||
|
type Details struct {
|
||||||
|
ID string `json:"Id"`
|
||||||
|
Created time.Time `json:"Created"`
|
||||||
|
Path string `json:"Path"`
|
||||||
|
Args []string `json:"Args"`
|
||||||
|
State struct {
|
||||||
|
Status string `json:"Status"`
|
||||||
|
Running bool `json:"Running"`
|
||||||
|
Paused bool `json:"Paused"`
|
||||||
|
Restarting bool `json:"Restarting"`
|
||||||
|
OOMKilled bool `json:"OOMKilled"`
|
||||||
|
Dead bool `json:"Dead"`
|
||||||
|
Pid int `json:"Pid"`
|
||||||
|
ExitCode int `json:"ExitCode"`
|
||||||
|
Error string `json:"Error"`
|
||||||
|
StartedAt time.Time `json:"StartedAt"`
|
||||||
|
FinishedAt time.Time `json:"FinishedAt"`
|
||||||
|
} `json:"State"`
|
||||||
|
Image string `json:"Image"`
|
||||||
|
ResolvConfPath string `json:"ResolvConfPath"`
|
||||||
|
HostnamePath string `json:"HostnamePath"`
|
||||||
|
HostsPath string `json:"HostsPath"`
|
||||||
|
LogPath string `json:"LogPath"`
|
||||||
|
Name string `json:"Name"`
|
||||||
|
RestartCount int `json:"RestartCount"`
|
||||||
|
Driver string `json:"Driver"`
|
||||||
|
Platform string `json:"Platform"`
|
||||||
|
MountLabel string `json:"MountLabel"`
|
||||||
|
ProcessLabel string `json:"ProcessLabel"`
|
||||||
|
AppArmorProfile string `json:"AppArmorProfile"`
|
||||||
|
ExecIDs interface{} `json:"ExecIDs"`
|
||||||
|
HostConfig struct {
|
||||||
|
Binds []string `json:"Binds"`
|
||||||
|
ContainerIDFile string `json:"ContainerIDFile"`
|
||||||
|
LogConfig struct {
|
||||||
|
Type string `json:"Type"`
|
||||||
|
Config struct {
|
||||||
|
} `json:"Config"`
|
||||||
|
} `json:"LogConfig"`
|
||||||
|
NetworkMode string `json:"NetworkMode"`
|
||||||
|
PortBindings struct {
|
||||||
|
} `json:"PortBindings"`
|
||||||
|
RestartPolicy struct {
|
||||||
|
Name string `json:"Name"`
|
||||||
|
MaximumRetryCount int `json:"MaximumRetryCount"`
|
||||||
|
} `json:"RestartPolicy"`
|
||||||
|
AutoRemove bool `json:"AutoRemove"`
|
||||||
|
VolumeDriver string `json:"VolumeDriver"`
|
||||||
|
VolumesFrom []interface{} `json:"VolumesFrom"`
|
||||||
|
CapAdd interface{} `json:"CapAdd"`
|
||||||
|
CapDrop interface{} `json:"CapDrop"`
|
||||||
|
DNS interface{} `json:"Dns"`
|
||||||
|
DNSOptions interface{} `json:"DnsOptions"`
|
||||||
|
DNSSearch interface{} `json:"DnsSearch"`
|
||||||
|
ExtraHosts interface{} `json:"ExtraHosts"`
|
||||||
|
GroupAdd interface{} `json:"GroupAdd"`
|
||||||
|
IpcMode string `json:"IpcMode"`
|
||||||
|
Cgroup string `json:"Cgroup"`
|
||||||
|
Links interface{} `json:"Links"`
|
||||||
|
OomScoreAdj int `json:"OomScoreAdj"`
|
||||||
|
PidMode string `json:"PidMode"`
|
||||||
|
Privileged bool `json:"Privileged"`
|
||||||
|
PublishAllPorts bool `json:"PublishAllPorts"`
|
||||||
|
ReadonlyRootfs bool `json:"ReadonlyRootfs"`
|
||||||
|
SecurityOpt interface{} `json:"SecurityOpt"`
|
||||||
|
UTSMode string `json:"UTSMode"`
|
||||||
|
UsernsMode string `json:"UsernsMode"`
|
||||||
|
ShmSize int `json:"ShmSize"`
|
||||||
|
Runtime string `json:"Runtime"`
|
||||||
|
ConsoleSize []int `json:"ConsoleSize"`
|
||||||
|
Isolation string `json:"Isolation"`
|
||||||
|
CPUShares int `json:"CpuShares"`
|
||||||
|
Memory int `json:"Memory"`
|
||||||
|
NanoCpus int `json:"NanoCpus"`
|
||||||
|
CgroupParent string `json:"CgroupParent"`
|
||||||
|
BlkioWeight int `json:"BlkioWeight"`
|
||||||
|
BlkioWeightDevice interface{} `json:"BlkioWeightDevice"`
|
||||||
|
BlkioDeviceReadBps interface{} `json:"BlkioDeviceReadBps"`
|
||||||
|
BlkioDeviceWriteBps interface{} `json:"BlkioDeviceWriteBps"`
|
||||||
|
BlkioDeviceReadIOps interface{} `json:"BlkioDeviceReadIOps"`
|
||||||
|
BlkioDeviceWriteIOps interface{} `json:"BlkioDeviceWriteIOps"`
|
||||||
|
CPUPeriod int `json:"CpuPeriod"`
|
||||||
|
CPUQuota int `json:"CpuQuota"`
|
||||||
|
CPURealtimePeriod int `json:"CpuRealtimePeriod"`
|
||||||
|
CPURealtimeRuntime int `json:"CpuRealtimeRuntime"`
|
||||||
|
CpusetCpus string `json:"CpusetCpus"`
|
||||||
|
CpusetMems string `json:"CpusetMems"`
|
||||||
|
Devices interface{} `json:"Devices"`
|
||||||
|
DeviceCgroupRules interface{} `json:"DeviceCgroupRules"`
|
||||||
|
DiskQuota int `json:"DiskQuota"`
|
||||||
|
KernelMemory int `json:"KernelMemory"`
|
||||||
|
MemoryReservation int `json:"MemoryReservation"`
|
||||||
|
MemorySwap int `json:"MemorySwap"`
|
||||||
|
MemorySwappiness interface{} `json:"MemorySwappiness"`
|
||||||
|
OomKillDisable bool `json:"OomKillDisable"`
|
||||||
|
PidsLimit int `json:"PidsLimit"`
|
||||||
|
Ulimits interface{} `json:"Ulimits"`
|
||||||
|
CPUCount int `json:"CpuCount"`
|
||||||
|
CPUPercent int `json:"CpuPercent"`
|
||||||
|
IOMaximumIOps int `json:"IOMaximumIOps"`
|
||||||
|
IOMaximumBandwidth int `json:"IOMaximumBandwidth"`
|
||||||
|
MaskedPaths []string `json:"MaskedPaths"`
|
||||||
|
ReadonlyPaths []string `json:"ReadonlyPaths"`
|
||||||
|
} `json:"HostConfig"`
|
||||||
|
GraphDriver struct {
|
||||||
|
Data struct {
|
||||||
|
LowerDir string `json:"LowerDir"`
|
||||||
|
MergedDir string `json:"MergedDir"`
|
||||||
|
UpperDir string `json:"UpperDir"`
|
||||||
|
WorkDir string `json:"WorkDir"`
|
||||||
|
} `json:"Data"`
|
||||||
|
Name string `json:"Name"`
|
||||||
|
} `json:"GraphDriver"`
|
||||||
|
Mounts []struct {
|
||||||
|
Type string `json:"Type"`
|
||||||
|
Name string `json:"Name,omitempty"`
|
||||||
|
Source string `json:"Source"`
|
||||||
|
Destination string `json:"Destination"`
|
||||||
|
Driver string `json:"Driver,omitempty"`
|
||||||
|
Mode string `json:"Mode"`
|
||||||
|
RW bool `json:"RW"`
|
||||||
|
Propagation string `json:"Propagation"`
|
||||||
|
} `json:"Mounts"`
|
||||||
|
Config struct {
|
||||||
|
Hostname string `json:"Hostname"`
|
||||||
|
Domainname string `json:"Domainname"`
|
||||||
|
User string `json:"User"`
|
||||||
|
AttachStdin bool `json:"AttachStdin"`
|
||||||
|
AttachStdout bool `json:"AttachStdout"`
|
||||||
|
AttachStderr bool `json:"AttachStderr"`
|
||||||
|
Tty bool `json:"Tty"`
|
||||||
|
OpenStdin bool `json:"OpenStdin"`
|
||||||
|
StdinOnce bool `json:"StdinOnce"`
|
||||||
|
Env []string `json:"Env"`
|
||||||
|
Cmd []string `json:"Cmd"`
|
||||||
|
Image string `json:"Image"`
|
||||||
|
Volumes struct {
|
||||||
|
APIBundle struct {
|
||||||
|
} `json:"/api-bundle"`
|
||||||
|
App struct {
|
||||||
|
} `json:"/app"`
|
||||||
|
} `json:"Volumes"`
|
||||||
|
WorkingDir string `json:"WorkingDir"`
|
||||||
|
Entrypoint interface{} `json:"Entrypoint"`
|
||||||
|
OnBuild interface{} `json:"OnBuild"`
|
||||||
|
Labels struct {
|
||||||
|
ComDockerComposeOneoff string `json:"com.docker.compose.oneoff"`
|
||||||
|
ComDockerComposeProject string `json:"com.docker.compose.project"`
|
||||||
|
ComDockerComposeService string `json:"com.docker.compose.service"`
|
||||||
|
ComDockerComposeSlug string `json:"com.docker.compose.slug"`
|
||||||
|
ComDockerComposeVersion string `json:"com.docker.compose.version"`
|
||||||
|
} `json:"Labels"`
|
||||||
|
} `json:"Config"`
|
||||||
|
NetworkSettings struct {
|
||||||
|
Bridge string `json:"Bridge"`
|
||||||
|
SandboxID string `json:"SandboxID"`
|
||||||
|
HairpinMode bool `json:"HairpinMode"`
|
||||||
|
LinkLocalIPv6Address string `json:"LinkLocalIPv6Address"`
|
||||||
|
LinkLocalIPv6PrefixLen int `json:"LinkLocalIPv6PrefixLen"`
|
||||||
|
Ports struct {
|
||||||
|
} `json:"Ports"`
|
||||||
|
SandboxKey string `json:"SandboxKey"`
|
||||||
|
SecondaryIPAddresses interface{} `json:"SecondaryIPAddresses"`
|
||||||
|
SecondaryIPv6Addresses interface{} `json:"SecondaryIPv6Addresses"`
|
||||||
|
EndpointID string `json:"EndpointID"`
|
||||||
|
Gateway string `json:"Gateway"`
|
||||||
|
GlobalIPv6Address string `json:"GlobalIPv6Address"`
|
||||||
|
GlobalIPv6PrefixLen int `json:"GlobalIPv6PrefixLen"`
|
||||||
|
IPAddress string `json:"IPAddress"`
|
||||||
|
IPPrefixLen int `json:"IPPrefixLen"`
|
||||||
|
IPv6Gateway string `json:"IPv6Gateway"`
|
||||||
|
MacAddress string `json:"MacAddress"`
|
||||||
|
Networks struct {
|
||||||
|
ApdevDefault struct {
|
||||||
|
IPAMConfig interface{} `json:"IPAMConfig"`
|
||||||
|
Links interface{} `json:"Links"`
|
||||||
|
Aliases []string `json:"Aliases"`
|
||||||
|
NetworkID string `json:"NetworkID"`
|
||||||
|
EndpointID string `json:"EndpointID"`
|
||||||
|
Gateway string `json:"Gateway"`
|
||||||
|
IPAddress string `json:"IPAddress"`
|
||||||
|
IPPrefixLen int `json:"IPPrefixLen"`
|
||||||
|
IPv6Gateway string `json:"IPv6Gateway"`
|
||||||
|
GlobalIPv6Address string `json:"GlobalIPv6Address"`
|
||||||
|
GlobalIPv6PrefixLen int `json:"GlobalIPv6PrefixLen"`
|
||||||
|
MacAddress string `json:"MacAddress"`
|
||||||
|
DriverOpts interface{} `json:"DriverOpts"`
|
||||||
|
} `json:"apdev_default"`
|
||||||
|
} `json:"Networks"`
|
||||||
|
} `json:"NetworkSettings"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ContainerCliStat is a stat object returned by the CLI docker stat command
|
// ContainerCliStat is a stat object returned by the CLI docker stat command
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,11 @@ func (c *DockerCommand) GetContainers() ([]*Container, error) {
|
||||||
|
|
||||||
ownContainers := make([]*Container, len(containers))
|
ownContainers := make([]*Container, len(containers))
|
||||||
|
|
||||||
|
ids := []string{}
|
||||||
|
|
||||||
for i, container := range containers {
|
for i, container := range containers {
|
||||||
|
ids = append(ids, container.ID)
|
||||||
|
|
||||||
ownContainers[i] = &Container{
|
ownContainers[i] = &Container{
|
||||||
ID: container.ID,
|
ID: container.ID,
|
||||||
Name: strings.TrimLeft(container.Names[0], "/"),
|
Name: strings.TrimLeft(container.Names[0], "/"),
|
||||||
|
|
@ -95,6 +99,21 @@ func (c *DockerCommand) GetContainers() ([]*Container, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cmd := c.OSCommand.RunCustomCommand("docker inspect " + strings.Join(ids, " "))
|
||||||
|
output, err := cmd.CombinedOutput()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var details []*Details
|
||||||
|
if err := json.Unmarshal(output, &details); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, container := range ownContainers {
|
||||||
|
container.Details = *details[i]
|
||||||
|
}
|
||||||
|
|
||||||
// ownContainers, err = c.UpdateContainerStats(ownContainers)
|
// ownContainers, err = c.UpdateContainerStats(ownContainers)
|
||||||
// if err != nil {
|
// if err != nil {
|
||||||
// return nil, err
|
// return nil, err
|
||||||
|
|
|
||||||
|
|
@ -174,13 +174,18 @@ func (gui *Gui) renderContainerLogs(mainView *gocui.View, container *commands.Co
|
||||||
mainView.Autoscroll = true
|
mainView.Autoscroll = true
|
||||||
mainView.Title = "Logs"
|
mainView.Title = "Logs"
|
||||||
|
|
||||||
|
if container.Details.Config.AttachStdin {
|
||||||
|
logs, err := gui.OSCommand.RunCommandWithOutput("docker logs --since=60m " + container.ID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return gui.renderString(gui.g, "main", logs)
|
||||||
|
}
|
||||||
|
|
||||||
var cmd *exec.Cmd
|
var cmd *exec.Cmd
|
||||||
cmd = gui.OSCommand.RunCustomCommand("docker logs --since=60m --timestamps --follow " + container.ID)
|
cmd = gui.OSCommand.RunCustomCommand("docker logs --since=60m --timestamps --follow " + container.ID)
|
||||||
|
|
||||||
r, err := cmd.StdoutPipe()
|
cmd.Stdout = mainView
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
gui.State.MainProcessChan <- struct{}{}
|
gui.State.MainProcessChan <- struct{}{}
|
||||||
|
|
@ -192,15 +197,6 @@ func (gui *Gui) renderContainerLogs(mainView *gocui.View, container *commands.Co
|
||||||
cmd.Process.Kill()
|
cmd.Process.Kill()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
go func() {
|
|
||||||
for {
|
|
||||||
s := bufio.NewScanner(r)
|
|
||||||
s.Split(bufio.ScanLines)
|
|
||||||
for s.Scan() {
|
|
||||||
mainView.Write(append(s.Bytes(), '\n'))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
cmd.Wait()
|
cmd.Wait()
|
||||||
gui.State.MainProcessMutex.Unlock()
|
gui.State.MainProcessMutex.Unlock()
|
||||||
}()
|
}()
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue