mirror of https://github.com/bcicen/ctop.git
Compare commits
107 Commits
Author | SHA1 | Date |
---|---|---|
bradley | 59f00dd6aa | |
bradley | 06265407b2 | |
bradley | a08150ea9c | |
Alex Stelmachonak | 6bf41ea05f | |
Jeya Nishwanth | 3dff9970ad | |
William Diaz | 458ef62f80 | |
William Diaz | a821deb3b4 | |
Aurélien Lajoie | dacd3be920 | |
Bradley Cicenas | 222a7d77b2 | |
Bradley Cicenas | 9bc26c8296 | |
Bradley Cicenas | 5271cf6d90 | |
Bradley Cicenas | a8e1fb7246 | |
Bradley Cicenas | d60b215611 | |
Bradley Cicenas | 79242c7de5 | |
Bradley Cicenas | 6dcb62f172 | |
DasSkelett | 163060b3fa | |
Bradley Cicenas | acbf17a4fd | |
Bradley Cicenas | 021b1710a3 | |
Bradley Cicenas | 2d43cd146f | |
Bradley Cicenas | 11a1cb10f4 | |
Bradley Cicenas | f83e73d1ea | |
Bradley Cicenas | 1f91033beb | |
Bradley Cicenas | da09b95d29 | |
Florian Vahl | 350cb09338 | |
dependabot[bot] | d8542c894c | |
Bradley Cicenas | be23d85eda | |
bradley | 2047e3fa52 | |
dependabot[bot] | 4b653e71f6 | |
Bradley Cicenas | c145cf404a | |
bradley | 52f52a1163 | |
bradley | 94f1f3f558 | |
Quinten Peels | 3d5a1c0682 | |
neikei | 1c3577ad4e | |
Bradley Cicenas | b48a5cf2f9 | |
Bradley Cicenas | 9f8f38f9d7 | |
bradley | 2b898fb216 | |
Frol Kryuchkov | 99be3b979e | |
bradley | 29f9abf35c | |
bradley | 82e731e577 | |
Bradley Cicenas | a603c1b58c | |
Bradley Cicenas | 8f0c9f5048 | |
bradley | 15708224a7 | |
bradley | 442e70b8df | |
garsue | c58a609349 | |
garsue | 78b038e687 | |
Vadim-Valdis Yudaev | 2d937aca08 | |
Sergey Ponomarev | 77c9001ed1 | |
Sergey Ponomarev | d98ce102b1 | |
Sergey Ponomarev | cfa43f809e | |
bradley | 0094cba5ea | |
bradley | 537bb2adfa | |
Sergey Ponomarev | 8dce3ece2b | |
Sergey Ponomarev | dd92e85d45 | |
Sergey Ponomarev | 491cd85b4d | |
Sergey Ponomarev | 9545dfba31 | |
Sergey Ponomarev | cdcb8b6d99 | |
bradley | b562c923b3 | |
Sergey Ponomarev | f2c28c5fb0 | |
Sergey Ponomarev | ac76b2eac1 | |
bradley | b32f90fa4a | |
bradley | bec78c90b5 | |
Bradley Cicenas | 043f4bd3f3 | |
Sergey Ponomarev | c2401cb33a | |
Sergey Ponomarev | fa254c652c | |
Sergey Ponomarev | a59c7aab3c | |
Sergey Ponomarev | 4e44c9d5f7 | |
Sergey Ponomarev | 948e7cc9d0 | |
Sergey Ponomarev | 4850f817f3 | |
Sergey Ponomarev | 10c49018a6 | |
Sergey Ponomarev | 6c662d91fb | |
Sergey Ponomarev | b4a63f8c60 | |
Sergey Ponomarev | 4973bc83ff | |
Bradley Cicenas | 87d135909f | |
Sergey Ponomarev | 7632420ecc | |
Sergey Ponomarev | 4fbc998a41 | |
bradley | 117c3bc7b5 | |
bradley | b1171f6c3e | |
Sergey Ponomarev | 9a41252764 | |
Sergey Ponomarev | f377dcaee2 | |
Sergey Ponomarev | 65e9c6dff6 | |
Sergey Ponomarev | df0d8b7892 | |
bradley | 2792e72d18 | |
bradley | 68d6da5c61 | |
Sergey Ponomarev | 53a6b36bf5 | |
Sergey Ponomarev | 5ec02f760e | |
Sergey Ponomarev | 83a422933a | |
Sergey Ponomarev | 7679d4a7fd | |
Sergey Ponomarev | e34afceb5f | |
bradley | ddfff03c05 | |
Sergey Ponomarev | 29d90cfdd9 | |
Sergey Ponomarev | ba126e6e7c | |
Sergey Ponomarev | 009201ed0c | |
Sergey Ponomarev | 2c07cab59c | |
bradley | fd06992236 | |
Sergey Ponomarev | e64edbdc36 | |
Sergey Ponomarev | 4c280cee56 | |
Sergey Ponomarev | b65e970a83 | |
Sergey Ponomarev | 957cabba2d | |
Sergey Ponomarev | 5aacdc3772 | |
Bradley Cicenas | 99d9aeec98 | |
bradley | 44600fca45 | |
bradley | 9aaba5dfca | |
Bradley Cicenas | 0bd8efe800 | |
Sergey Ponomarev | 3a29c94833 | |
Sergey Ponomarev | a22d99fefb | |
Sergey Ponomarev | c984b270db | |
Vahe Mkrtchyan | 4a0e80ffdf |
|
@ -3,13 +3,13 @@ jobs:
|
|||
build:
|
||||
working_directory: ~/build
|
||||
docker:
|
||||
- image: circleci/golang:latest
|
||||
- image: cimg/go:1.18
|
||||
steps:
|
||||
- checkout
|
||||
- setup_remote_docker:
|
||||
version: 19.03.13
|
||||
version: 20.10.11
|
||||
- run: make image
|
||||
- deploy:
|
||||
- deploy:
|
||||
command: |
|
||||
if [[ "$CIRCLE_BRANCH" == "master" ]]; then
|
||||
docker tag ctop quay.io/vektorlab/ctop:latest
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
ctop
|
||||
.idea
|
||||
/vendor/
|
||||
/vendor/
|
||||
*.log
|
|
@ -1,4 +1,4 @@
|
|||
FROM quay.io/vektorcloud/go:1.13
|
||||
FROM quay.io/vektorcloud/go:1.18
|
||||
|
||||
RUN apk add --no-cache make
|
||||
|
||||
|
|
15
Makefile
15
Makefile
|
@ -12,11 +12,12 @@ build:
|
|||
|
||||
build-all:
|
||||
mkdir -p _build
|
||||
GOOS=darwin GOARCH=amd64 CGO_ENABLED=0 go build -tags release -ldflags $(LD_FLAGS) -o _build/ctop-$(VERSION)-darwin-amd64
|
||||
GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -tags release -ldflags $(LD_FLAGS) -o _build/ctop-$(VERSION)-linux-amd64
|
||||
GOOS=linux GOARCH=arm CGO_ENABLED=0 go build -tags release -ldflags $(LD_FLAGS) -o _build/ctop-$(VERSION)-linux-arm
|
||||
GOOS=linux GOARCH=arm64 CGO_ENABLED=0 go build -tags release -ldflags $(LD_FLAGS) -o _build/ctop-$(VERSION)-linux-arm64
|
||||
GOOS=windows GOARCH=amd64 CGO_ENABLED=0 go build -tags release -ldflags $(LD_FLAGS) -o _build/ctop-$(VERSION)-windows-amd64
|
||||
GOOS=darwin GOARCH=amd64 CGO_ENABLED=0 go build -tags release -ldflags $(LD_FLAGS) -o _build/ctop-$(VERSION)-darwin-amd64
|
||||
GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -tags release -ldflags $(LD_FLAGS) -o _build/ctop-$(VERSION)-linux-amd64
|
||||
GOOS=linux GOARCH=arm CGO_ENABLED=0 go build -tags release -ldflags $(LD_FLAGS) -o _build/ctop-$(VERSION)-linux-arm
|
||||
GOOS=linux GOARCH=arm64 CGO_ENABLED=0 go build -tags release -ldflags $(LD_FLAGS) -o _build/ctop-$(VERSION)-linux-arm64
|
||||
GOOS=linux GOARCH=ppc64le CGO_ENABLED=0 go build -tags release -ldflags $(LD_FLAGS) -o _build/ctop-$(VERSION)-linux-ppc64le
|
||||
GOOS=windows GOARCH=amd64 CGO_ENABLED=0 go build -tags release -ldflags $(LD_FLAGS) -o _build/ctop-$(VERSION)-windows-amd64
|
||||
cd _build; sha256sum * > sha256sums.txt
|
||||
|
||||
run-dev:
|
||||
|
@ -30,7 +31,7 @@ image:
|
|||
release:
|
||||
mkdir release
|
||||
cp _build/* release
|
||||
cd release; sha256sum --quiet --check sha256sums.txt
|
||||
gh release create $(VERSION) -d -t $(VERSION) *
|
||||
cd release; sha256sum --quiet --check sha256sums.txt && \
|
||||
gh release create v$(VERSION) -d -t v$(VERSION) *
|
||||
|
||||
.PHONY: build
|
||||
|
|
44
README.md
44
README.md
|
@ -2,7 +2,7 @@
|
|||
|
||||
#
|
||||
|
||||
![release][release] ![homebrew][homebrew]
|
||||
![release][release] ![homebrew][homebrew] ![macports][macports] ![scoop][scoop]
|
||||
|
||||
Top-like interface for container metrics
|
||||
|
||||
|
@ -21,20 +21,28 @@ Fetch the [latest release](https://github.com/bcicen/ctop/releases) for your pla
|
|||
|
||||
Maintained by a [third party](https://packages.azlux.fr/)
|
||||
```bash
|
||||
echo "deb http://packages.azlux.fr/debian/ buster main" | sudo tee /etc/apt/sources.list.d/azlux.list
|
||||
wget -qO - https://azlux.fr/repo.gpg.key | sudo apt-key add -
|
||||
sudo apt update
|
||||
sudo apt install docker-ctop
|
||||
sudo apt-get install ca-certificates curl gnupg lsb-release
|
||||
curl -fsSL https://azlux.fr/repo.gpg.key | sudo gpg --dearmor -o /usr/share/keyrings/azlux-archive-keyring.gpg
|
||||
echo \
|
||||
"deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/azlux-archive-keyring.gpg] http://packages.azlux.fr/debian \
|
||||
$(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/azlux.list >/dev/null
|
||||
sudo apt-get update
|
||||
sudo apt-get install docker-ctop
|
||||
```
|
||||
|
||||
#### Arch
|
||||
|
||||
`ctop` is available for Arch in the [AUR](https://aur.archlinux.org/packages/ctop-bin/)
|
||||
```bash
|
||||
sudo pacman -S ctop
|
||||
```
|
||||
|
||||
_`ctop` is also available for Arch in the [AUR](https://aur.archlinux.org/packages/ctop-bin/)_
|
||||
|
||||
|
||||
#### Linux (Generic)
|
||||
|
||||
```bash
|
||||
sudo wget https://github.com/bcicen/ctop/releases/download/v0.7.5/ctop-0.7.5-linux-amd64 -O /usr/local/bin/ctop
|
||||
sudo wget https://github.com/bcicen/ctop/releases/download/v0.7.7/ctop-0.7.7-linux-amd64 -O /usr/local/bin/ctop
|
||||
sudo chmod +x /usr/local/bin/ctop
|
||||
```
|
||||
|
||||
|
@ -45,10 +53,22 @@ brew install ctop
|
|||
```
|
||||
or
|
||||
```bash
|
||||
sudo curl -Lo /usr/local/bin/ctop https://github.com/bcicen/ctop/releases/download/v0.7.5/ctop-0.7.5-darwin-amd64
|
||||
sudo port install ctop
|
||||
```
|
||||
or
|
||||
```bash
|
||||
sudo curl -Lo /usr/local/bin/ctop https://github.com/bcicen/ctop/releases/download/v0.7.7/ctop-0.7.7-darwin-amd64
|
||||
sudo chmod +x /usr/local/bin/ctop
|
||||
```
|
||||
|
||||
#### Windows
|
||||
|
||||
`ctop` is available in [scoop](https://scoop.sh/):
|
||||
|
||||
```powershell
|
||||
scoop install ctop
|
||||
```
|
||||
|
||||
#### Docker
|
||||
|
||||
```bash
|
||||
|
@ -82,9 +102,7 @@ Option | Description
|
|||
`-i` | invert default colors
|
||||
`-r` | reverse container sort order
|
||||
`-s` | select initial container sort field
|
||||
`-scale-cpu` | show cpu as % of system total
|
||||
`-v` | output version information and exit
|
||||
`-shell` | exec shell to use (default: sh)
|
||||
|
||||
### Keybindings
|
||||
|
||||
|
@ -109,3 +127,9 @@ Option | Description
|
|||
[single_view]: _docs/single.md
|
||||
[release]: https://img.shields.io/github/release/bcicen/ctop.svg "ctop"
|
||||
[homebrew]: https://img.shields.io/homebrew/v/ctop.svg "ctop"
|
||||
[macports]: https://repology.org/badge/version-for-repo/macports/ctop.svg?header=macports "ctop"
|
||||
[scoop]: https://img.shields.io/scoop/v/ctop?bucket=main "ctop"
|
||||
|
||||
## Alternatives
|
||||
|
||||
See [Awesome Docker list](https://github.com/veggiemonk/awesome-docker/blob/master/README.md#terminal) for similar tools to work with Docker.
|
||||
|
|
|
@ -54,3 +54,18 @@ CTOP_DEBUG=1 CTOP_DEBUG_TCP=1 ./ctop
|
|||
```
|
||||
|
||||
A TCP listener for streaming log messages will be started on the default listen address(`0.0.0.0:9000`)
|
||||
|
||||
## Log to file
|
||||
|
||||
You can also log to a file by specifying `CTOP_DEBUG_FILE=/path/to/ctop.log` environment variable:
|
||||
```sh
|
||||
CTOP_DEBUG=1 CTOP_DEBUG_FILE=ctop.log ./ctop
|
||||
```
|
||||
|
||||
This is useful for GoLand to see logs right in debug panel:
|
||||
* Edit Run configuration
|
||||
* Go to Logs tab
|
||||
* Specify this log file in "Log file to be shown in console".
|
||||
Then during debugging you'll see the log tab in debug panel:
|
||||
|
||||
![Debug in GoLand](img/goland_debug.png)
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 143 KiB |
|
@ -6,46 +6,76 @@ import (
|
|||
|
||||
// defaults
|
||||
var defaultColumns = []Column{
|
||||
Column{
|
||||
{
|
||||
Name: "status",
|
||||
Label: "Status Indicator",
|
||||
Enabled: true,
|
||||
},
|
||||
Column{
|
||||
{
|
||||
Name: "name",
|
||||
Label: "Container Name",
|
||||
Enabled: true,
|
||||
},
|
||||
Column{
|
||||
{
|
||||
Name: "id",
|
||||
Label: "Container ID",
|
||||
Enabled: true,
|
||||
},
|
||||
Column{
|
||||
{
|
||||
Name: "image",
|
||||
Label: "Image name",
|
||||
Enabled: false,
|
||||
},
|
||||
{
|
||||
Name: "ports",
|
||||
Label: "Exposed ports",
|
||||
Enabled: false,
|
||||
},
|
||||
{
|
||||
Name: "IPs",
|
||||
Label: "Exposed IPs",
|
||||
Enabled: false,
|
||||
},
|
||||
{
|
||||
Name: "created",
|
||||
Label: "Date created",
|
||||
Enabled: false,
|
||||
},
|
||||
{
|
||||
Name: "cpu",
|
||||
Label: "CPU Usage",
|
||||
Enabled: true,
|
||||
},
|
||||
Column{
|
||||
{
|
||||
Name: "cpus",
|
||||
Label: "CPU Usage (% of system total)",
|
||||
Enabled: false,
|
||||
},
|
||||
{
|
||||
Name: "mem",
|
||||
Label: "Memory Usage",
|
||||
Enabled: true,
|
||||
},
|
||||
Column{
|
||||
{
|
||||
Name: "net",
|
||||
Label: "Network RX/TX",
|
||||
Enabled: true,
|
||||
},
|
||||
Column{
|
||||
{
|
||||
Name: "io",
|
||||
Label: "Disk IO Read/Write",
|
||||
Enabled: true,
|
||||
},
|
||||
Column{
|
||||
{
|
||||
Name: "pids",
|
||||
Label: "Container PID Count",
|
||||
Enabled: true,
|
||||
},
|
||||
Column{
|
||||
Name: "uptime",
|
||||
Label: "Running uptime duration",
|
||||
Enabled: true,
|
||||
},
|
||||
}
|
||||
|
||||
type Column struct {
|
||||
|
|
|
@ -3,6 +3,7 @@ package config
|
|||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
|
@ -66,7 +67,7 @@ func Read() error {
|
|||
for _, s := range strings.Split(colStr, ",") {
|
||||
s = strings.TrimSpace(s)
|
||||
if s != "" {
|
||||
colNames = append(colNames, strings.TrimSpace(s))
|
||||
colNames = append(colNames, s)
|
||||
}
|
||||
}
|
||||
SetColumns(colNames)
|
||||
|
@ -81,7 +82,7 @@ func Write() (path string, err error) {
|
|||
return path, err
|
||||
}
|
||||
|
||||
cfgdir := basedir(path)
|
||||
cfgdir := filepath.Dir(path)
|
||||
// create config dir if not exist
|
||||
if _, err := os.Stat(cfgdir); err != nil {
|
||||
err = os.MkdirAll(cfgdir, 0755)
|
||||
|
@ -141,8 +142,3 @@ func xdgSupport() bool {
|
|||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func basedir(path string) string {
|
||||
parts := strings.Split(path, "/")
|
||||
return strings.Join((parts[0 : len(parts)-1]), "/")
|
||||
}
|
||||
|
|
|
@ -12,14 +12,9 @@ var defaultParams = []*Param{
|
|||
Val: "state",
|
||||
Label: "Container Sort Field",
|
||||
},
|
||||
&Param{
|
||||
Key: "shell",
|
||||
Val: "sh",
|
||||
Label: "Shell",
|
||||
},
|
||||
&Param{
|
||||
Key: "columns",
|
||||
Val: "status,name,id,cpu,mem,net,io,pids",
|
||||
Val: "status,name,id,cpu,mem,net,io,pids,uptime",
|
||||
Label: "Enabled Columns",
|
||||
},
|
||||
}
|
||||
|
|
|
@ -22,11 +22,6 @@ var defaultSwitches = []*Switch{
|
|||
Val: true,
|
||||
Label: "Enable status header",
|
||||
},
|
||||
&Switch{
|
||||
Key: "scaleCpu",
|
||||
Val: false,
|
||||
Label: "Show CPU as %% of system total",
|
||||
},
|
||||
}
|
||||
|
||||
type Switch struct {
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package collector
|
||||
|
||||
import (
|
||||
"github.com/bcicen/ctop/config"
|
||||
"github.com/bcicen/ctop/models"
|
||||
api "github.com/fsouza/go-dockerclient"
|
||||
)
|
||||
|
@ -16,15 +15,13 @@ type Docker struct {
|
|||
done chan bool
|
||||
lastCpu float64
|
||||
lastSysCpu float64
|
||||
scaleCpu bool
|
||||
}
|
||||
|
||||
func NewDocker(client *api.Client, id string) *Docker {
|
||||
return &Docker{
|
||||
Metrics: models.Metrics{},
|
||||
id: id,
|
||||
client: client,
|
||||
scaleCpu: config.GetSwitchVal("scaleCpu"),
|
||||
Metrics: models.Metrics{},
|
||||
id: id,
|
||||
client: client,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -74,22 +71,23 @@ func (c *Docker) Logs() LogCollector {
|
|||
|
||||
// Stop collector
|
||||
func (c *Docker) Stop() {
|
||||
c.running = false
|
||||
c.done <- true
|
||||
}
|
||||
|
||||
func (c *Docker) ReadCPU(stats *api.Stats) {
|
||||
ncpus := float64(len(stats.CPUStats.CPUUsage.PercpuUsage))
|
||||
ncpus := uint8(stats.CPUStats.OnlineCPUs)
|
||||
if ncpus == 0 {
|
||||
ncpus = uint8(len(stats.CPUStats.CPUUsage.PercpuUsage))
|
||||
}
|
||||
total := float64(stats.CPUStats.CPUUsage.TotalUsage)
|
||||
system := float64(stats.CPUStats.SystemCPUUsage)
|
||||
|
||||
cpudiff := total - c.lastCpu
|
||||
syscpudiff := system - c.lastSysCpu
|
||||
|
||||
if c.scaleCpu {
|
||||
c.CPUUtil = round((cpudiff / syscpudiff * 100))
|
||||
} else {
|
||||
c.CPUUtil = round((cpudiff / syscpudiff * 100) * ncpus)
|
||||
}
|
||||
c.NCpus = ncpus
|
||||
c.CPUUtil = percent(cpudiff, syscpudiff)
|
||||
c.lastCpu = total
|
||||
c.lastSysCpu = system
|
||||
c.Pids = int(stats.PidsStats.Current)
|
||||
|
|
|
@ -47,9 +47,15 @@ func (l *DockerLogs) Stream() chan models.Log {
|
|||
go func() {
|
||||
scanner := bufio.NewScanner(r)
|
||||
for scanner.Scan() {
|
||||
parts := strings.Split(scanner.Text(), " ")
|
||||
ts := l.parseTime(parts[0])
|
||||
logCh <- models.Log{Timestamp: ts, Message: strings.Join(parts[1:], " ")}
|
||||
parts := strings.SplitN(scanner.Text(), " ", 2)
|
||||
if len(parts) == 0 {
|
||||
continue
|
||||
}
|
||||
if len(parts) < 2 {
|
||||
logCh <- models.Log{Timestamp: l.parseTime(""), Message: parts[0]}
|
||||
} else {
|
||||
logCh <- models.Log{Timestamp: l.parseTime(parts[0]), Message: parts[1]}
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
|
@ -74,12 +80,12 @@ func (l *DockerLogs) Stream() chan models.Log {
|
|||
func (l *DockerLogs) Stop() { l.done <- true }
|
||||
|
||||
func (l *DockerLogs) parseTime(s string) time.Time {
|
||||
ts, err := time.Parse("2006-01-02T15:04:05.000000000Z", s)
|
||||
ts, err := time.Parse(time.RFC3339Nano, s)
|
||||
if err == nil {
|
||||
return ts
|
||||
}
|
||||
|
||||
ts, err2 := time.Parse("2006-01-02T15:04:05.000000000Z", l.stripPfx(s))
|
||||
ts, err2 := time.Parse(time.RFC3339Nano, l.stripPfx(s))
|
||||
if err2 == nil {
|
||||
return ts
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//go:build !release
|
||||
// +build !release
|
||||
|
||||
package collector
|
||||
|
@ -38,6 +39,7 @@ func (c *Mock) Start() {
|
|||
}
|
||||
|
||||
func (c *Mock) Stop() {
|
||||
c.running = false
|
||||
c.done = true
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//go:build linux
|
||||
// +build linux
|
||||
|
||||
package collector
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//go:build linux
|
||||
// +build linux
|
||||
|
||||
package collector
|
||||
|
@ -9,7 +10,6 @@ import (
|
|||
"github.com/opencontainers/runc/libcontainer/cgroups"
|
||||
"github.com/opencontainers/runc/types"
|
||||
|
||||
"github.com/bcicen/ctop/config"
|
||||
"github.com/bcicen/ctop/models"
|
||||
)
|
||||
|
||||
|
@ -24,7 +24,6 @@ type Runc struct {
|
|||
interval int // collection interval, in seconds
|
||||
lastCpu float64
|
||||
lastSysCpu float64
|
||||
scaleCpu bool
|
||||
}
|
||||
|
||||
func NewRunc(libc libcontainer.Container) *Runc {
|
||||
|
@ -33,7 +32,6 @@ func NewRunc(libc libcontainer.Container) *Runc {
|
|||
id: libc.ID(),
|
||||
libc: libc,
|
||||
interval: 1,
|
||||
scaleCpu: config.GetSwitchVal("scaleCpu"),
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
@ -49,6 +47,7 @@ func (c *Runc) Start() {
|
|||
}
|
||||
|
||||
func (c *Runc) Stop() {
|
||||
c.running = false
|
||||
c.done = true
|
||||
}
|
||||
|
||||
|
@ -88,18 +87,15 @@ func (c *Runc) run() {
|
|||
|
||||
func (c *Runc) ReadCPU(stats *cgroups.Stats) {
|
||||
u := stats.CpuStats.CpuUsage
|
||||
ncpus := float64(len(u.PercpuUsage))
|
||||
ncpus := uint8(len(u.PercpuUsage))
|
||||
total := float64(u.TotalUsage)
|
||||
system := float64(getSysCPUUsage())
|
||||
|
||||
cpudiff := total - c.lastCpu
|
||||
syscpudiff := system - c.lastSysCpu
|
||||
|
||||
if c.scaleCpu {
|
||||
c.CPUUtil = round((cpudiff / syscpudiff * 100))
|
||||
} else {
|
||||
c.CPUUtil = round((cpudiff / syscpudiff * 100) * ncpus)
|
||||
}
|
||||
c.NCpus = ncpus
|
||||
c.CPUUtil = percent(cpudiff, syscpudiff)
|
||||
c.lastCpu = total
|
||||
c.lastSysCpu = system
|
||||
c.Pids = int(stats.PidsStats.Current)
|
||||
|
|
|
@ -4,6 +4,10 @@ import (
|
|||
"fmt"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/op/go-logging"
|
||||
"github.com/hako/durafmt"
|
||||
|
||||
"github.com/bcicen/ctop/connector/collector"
|
||||
"github.com/bcicen/ctop/connector/manager"
|
||||
|
@ -13,10 +17,25 @@ import (
|
|||
|
||||
func init() { enabled["docker"] = NewDocker }
|
||||
|
||||
var actionToStatus = map[string]string{
|
||||
"start": "running",
|
||||
"die": "exited",
|
||||
"stop": "exited",
|
||||
"pause": "paused",
|
||||
"unpause": "running",
|
||||
}
|
||||
|
||||
type StatusUpdate struct {
|
||||
Cid string
|
||||
Field string // "status" or "health"
|
||||
Status string
|
||||
}
|
||||
|
||||
type Docker struct {
|
||||
client *api.Client
|
||||
containers map[string]*container.Container
|
||||
needsRefresh chan string // container IDs requiring refresh
|
||||
statuses chan StatusUpdate
|
||||
closed chan struct{}
|
||||
lock sync.RWMutex
|
||||
}
|
||||
|
@ -31,6 +50,7 @@ func NewDocker() (Connector, error) {
|
|||
client: client,
|
||||
containers: make(map[string]*container.Container),
|
||||
needsRefresh: make(chan string, 60),
|
||||
statuses: make(chan StatusUpdate, 60),
|
||||
closed: make(chan struct{}),
|
||||
lock: sync.RWMutex{},
|
||||
}
|
||||
|
@ -48,6 +68,7 @@ func NewDocker() (Connector, error) {
|
|||
log.Debugf("docker-connector ServerVersion: %s", info.ServerVersion)
|
||||
|
||||
go cm.Loop()
|
||||
go cm.LoopStatuses()
|
||||
cm.refreshAll()
|
||||
go cm.watchEvents()
|
||||
return cm, nil
|
||||
|
@ -60,22 +81,43 @@ func (cm *Docker) Wait() struct{} { return <-cm.closed }
|
|||
func (cm *Docker) watchEvents() {
|
||||
log.Info("docker event listener starting")
|
||||
events := make(chan *api.APIEvents)
|
||||
cm.client.AddEventListener(events)
|
||||
opts := api.EventsOptions{Filters: map[string][]string{
|
||||
"type": {"container"},
|
||||
"event": {"create", "start", "health_status", "pause", "unpause", "stop", "die", "destroy"},
|
||||
},
|
||||
}
|
||||
cm.client.AddEventListenerWithOptions(opts, events)
|
||||
|
||||
for e := range events {
|
||||
if e.Type != "container" {
|
||||
continue
|
||||
}
|
||||
|
||||
actionName := strings.Split(e.Action, ":")[0]
|
||||
|
||||
actionName := e.Action
|
||||
switch actionName {
|
||||
case "start", "die", "pause", "unpause", "health_status":
|
||||
log.Debugf("handling docker event: action=%s id=%s", e.Action, e.ID)
|
||||
// most frequent event is a health checks
|
||||
case "health_status: healthy", "health_status: unhealthy":
|
||||
sepIdx := strings.Index(actionName, ": ")
|
||||
healthStatus := e.Action[sepIdx+2:]
|
||||
if log.IsEnabledFor(logging.DEBUG) {
|
||||
log.Debugf("handling docker event: action=health_status id=%s %s", e.ID, healthStatus)
|
||||
}
|
||||
cm.statuses <- StatusUpdate{e.ID, "health", healthStatus}
|
||||
case "create":
|
||||
if log.IsEnabledFor(logging.DEBUG) {
|
||||
log.Debugf("handling docker event: action=create id=%s", e.ID)
|
||||
}
|
||||
cm.needsRefresh <- e.ID
|
||||
case "destroy":
|
||||
log.Debugf("handling docker event: action=%s id=%s", e.Action, e.ID)
|
||||
if log.IsEnabledFor(logging.DEBUG) {
|
||||
log.Debugf("handling docker event: action=destroy id=%s", e.ID)
|
||||
}
|
||||
cm.delByID(e.ID)
|
||||
default:
|
||||
// check if this action changes status e.g. start -> running
|
||||
status := actionToStatus[actionName]
|
||||
if status != "" {
|
||||
if log.IsEnabledFor(logging.DEBUG) {
|
||||
log.Debugf("handling docker event: action=%s id=%s %s", actionName, e.ID, status)
|
||||
}
|
||||
cm.statuses <- StatusUpdate{e.ID, "status", status}
|
||||
}
|
||||
}
|
||||
}
|
||||
log.Info("docker event listener exited")
|
||||
|
@ -100,6 +142,23 @@ func portsFormat(ports map[api.Port][]api.PortBinding) string {
|
|||
return strings.Join(append(exposed, published...), "\n")
|
||||
}
|
||||
|
||||
func webPort(ports map[api.Port][]api.PortBinding) string {
|
||||
for _, v := range ports {
|
||||
if len(v) == 0 {
|
||||
continue
|
||||
}
|
||||
for _, binding := range v {
|
||||
publishedIp := binding.HostIP
|
||||
if publishedIp == "0.0.0.0" {
|
||||
publishedIp = "localhost"
|
||||
}
|
||||
publishedWebPort := fmt.Sprintf("%s:%s", publishedIp, binding.HostPort)
|
||||
return publishedWebPort
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func ipsFormat(networks map[string]api.ContainerNetwork) string {
|
||||
var ips []string
|
||||
|
||||
|
@ -112,9 +171,12 @@ func ipsFormat(networks map[string]api.ContainerNetwork) string {
|
|||
}
|
||||
|
||||
func (cm *Docker) refresh(c *container.Container) {
|
||||
insp := cm.inspect(c.Id)
|
||||
insp, found, failed := cm.inspect(c.Id)
|
||||
if failed {
|
||||
return
|
||||
}
|
||||
// remove container if no longer exists
|
||||
if insp == nil {
|
||||
if !found {
|
||||
cm.delByID(c.Id)
|
||||
return
|
||||
}
|
||||
|
@ -122,22 +184,37 @@ func (cm *Docker) refresh(c *container.Container) {
|
|||
c.SetMeta("image", insp.Config.Image)
|
||||
c.SetMeta("IPs", ipsFormat(insp.NetworkSettings.Networks))
|
||||
c.SetMeta("ports", portsFormat(insp.NetworkSettings.Ports))
|
||||
c.SetMeta("created", insp.Created.Format("Mon Jan 2 15:04:05 2006"))
|
||||
c.SetMeta("health", insp.State.Health.Status)
|
||||
for _, env := range insp.Config.Env {
|
||||
c.SetMeta("[ENV-VAR]", env)
|
||||
webPort := webPort(insp.NetworkSettings.Ports)
|
||||
if webPort != "" {
|
||||
c.SetMeta("Web Port", webPort)
|
||||
}
|
||||
c.SetMeta("created", insp.Created.Format("Mon Jan 02 15:04:05 2006"))
|
||||
c.SetMeta("uptime", calcUptime(insp))
|
||||
c.SetMeta("health", insp.State.Health.Status)
|
||||
c.SetMeta("[ENV-VAR]", strings.Join(insp.Config.Env, ";"))
|
||||
c.SetState(insp.State.Status)
|
||||
}
|
||||
|
||||
func (cm *Docker) inspect(id string) *api.Container {
|
||||
func (cm *Docker) inspect(id string) (insp *api.Container, found bool, failed bool) {
|
||||
c, err := cm.client.InspectContainer(id)
|
||||
if err != nil {
|
||||
if _, ok := err.(*api.NoSuchContainer); !ok {
|
||||
log.Errorf("%s (%T)", err.Error(), err)
|
||||
if _, notFound := err.(*api.NoSuchContainer); notFound {
|
||||
return c, false, false
|
||||
}
|
||||
// other error e.g. connection failed
|
||||
log.Errorf("%s (%T)", err.Error(), err)
|
||||
return c, false, true
|
||||
}
|
||||
return c
|
||||
return c, true, false
|
||||
}
|
||||
|
||||
func calcUptime(insp *api.Container) string {
|
||||
endTime := insp.State.FinishedAt
|
||||
if endTime.IsZero() || insp.State.Running {
|
||||
endTime = time.Now()
|
||||
}
|
||||
uptime := endTime.Sub(insp.State.StartedAt)
|
||||
return durafmt.Parse(uptime).LimitFirstN(1).String()
|
||||
}
|
||||
|
||||
// Mark all container IDs for refresh
|
||||
|
@ -169,6 +246,24 @@ func (cm *Docker) Loop() {
|
|||
}
|
||||
}
|
||||
|
||||
func (cm *Docker) LoopStatuses() {
|
||||
for {
|
||||
select {
|
||||
case statusUpdate := <-cm.statuses:
|
||||
c, _ := cm.Get(statusUpdate.Cid)
|
||||
if c != nil {
|
||||
if statusUpdate.Field == "health" {
|
||||
c.SetMeta("health", statusUpdate.Status)
|
||||
} else {
|
||||
c.SetState(statusUpdate.Status)
|
||||
}
|
||||
}
|
||||
case <-cm.closed:
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MustGet gets a single container, creating one anew if not existing
|
||||
func (cm *Docker) MustGet(id string) *container.Container {
|
||||
c, ok := cm.Get(id)
|
||||
|
@ -218,5 +313,5 @@ func (cm *Docker) All() (containers container.Containers) {
|
|||
|
||||
// use primary container name
|
||||
func shortName(name string) string {
|
||||
return strings.Replace(name, "/", "", 1)
|
||||
return strings.TrimPrefix(name, "/")
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//go:build !release
|
||||
// +build !release
|
||||
|
||||
package connector
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
//go:build linux
|
||||
// +build linux
|
||||
|
||||
package connector
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
@ -14,7 +15,6 @@ import (
|
|||
"github.com/bcicen/ctop/connector/manager"
|
||||
"github.com/bcicen/ctop/container"
|
||||
"github.com/opencontainers/runc/libcontainer"
|
||||
"github.com/opencontainers/runc/libcontainer/cgroups/systemd"
|
||||
)
|
||||
|
||||
func init() { enabled["runc"] = NewRunc }
|
||||
|
@ -65,7 +65,7 @@ func NewRunc() (Connector, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
factory, err := getFactory(opts)
|
||||
factory, err := libcontainer.New(opts.root)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -104,7 +104,7 @@ func (cm *Runc) GetLibc(id string) libcontainer.Container {
|
|||
libc, err := cm.factory.Load(id)
|
||||
if err != nil {
|
||||
// remove container if no longer exists
|
||||
if lerr, ok := err.(libcontainer.Error); ok && lerr.Code() == libcontainer.ContainerNotExists {
|
||||
if errors.Is(err, libcontainer.ErrNotExist) {
|
||||
cm.delByID(id)
|
||||
} else {
|
||||
log.Warningf("failed to read container: %s\n", err)
|
||||
|
@ -169,7 +169,7 @@ func (cm *Runc) refreshAll() {
|
|||
}
|
||||
|
||||
// queue all existing containers for refresh
|
||||
for id, _ := range cm.containers {
|
||||
for id := range cm.containers {
|
||||
cm.needsRefresh <- id
|
||||
}
|
||||
log.Debugf("queued %d containers for refresh", len(cm.containers))
|
||||
|
@ -243,15 +243,3 @@ func (cm *Runc) All() (containers container.Containers) {
|
|||
cm.lock.Unlock()
|
||||
return containers
|
||||
}
|
||||
|
||||
func getFactory(opts RuncOpts) (libcontainer.Factory, error) {
|
||||
cgroupManager := libcontainer.Cgroupfs
|
||||
if opts.systemdCgroups {
|
||||
if systemd.IsRunningSystemd() {
|
||||
cgroupManager = libcontainer.SystemdCgroups
|
||||
} else {
|
||||
return nil, fmt.Errorf("systemd cgroup enabled, but systemd support for managing cgroups is not available")
|
||||
}
|
||||
}
|
||||
return libcontainer.New(opts.root, cgroupManager)
|
||||
}
|
||||
|
|
|
@ -31,10 +31,14 @@ type Container struct {
|
|||
|
||||
func New(id string, collector collector.Collector, manager manager.Manager) *Container {
|
||||
widgets := compact.NewCompactRow()
|
||||
shortID := id
|
||||
if len(shortID) > 12 {
|
||||
shortID = shortID[0:12]
|
||||
}
|
||||
return &Container{
|
||||
Metrics: models.NewMetrics(),
|
||||
Id: id,
|
||||
Meta: models.NewMeta("id", id[:12]),
|
||||
Meta: models.NewMeta("id", shortID),
|
||||
Widgets: widgets,
|
||||
updater: widgets,
|
||||
collector: collector,
|
||||
|
|
|
@ -79,6 +79,15 @@ var Sorters = map[string]sortMethod{
|
|||
}
|
||||
return stateMap[c1state] > stateMap[c2state]
|
||||
},
|
||||
"uptime": func(c1, c2 *Container) bool {
|
||||
// Use secondary sort method if equal values
|
||||
c1Uptime := c1.GetMeta("uptime")
|
||||
c2Uptime := c2.GetMeta("uptime")
|
||||
if c1Uptime == c2Uptime {
|
||||
return nameSorter(c1, c2)
|
||||
}
|
||||
return c1Uptime > c2Uptime
|
||||
},
|
||||
}
|
||||
|
||||
func SortFields() (fields []string) {
|
||||
|
|
|
@ -9,14 +9,20 @@ import (
|
|||
|
||||
var (
|
||||
allCols = map[string]NewCompactColFn{
|
||||
"status": NewStatus,
|
||||
"name": NewNameCol,
|
||||
"id": NewCIDCol,
|
||||
"cpu": NewCPUCol,
|
||||
"mem": NewMemCol,
|
||||
"net": NewNetCol,
|
||||
"io": NewIOCol,
|
||||
"pids": NewPIDCol,
|
||||
"status": NewStatus,
|
||||
"name": NewNameCol,
|
||||
"id": NewCIDCol,
|
||||
"image": NewImageCol,
|
||||
"ports": NewPortsCol,
|
||||
"IPs": NewIpsCol,
|
||||
"created": NewCreatedCol,
|
||||
"cpu": NewCPUCol,
|
||||
"cpus": NewCpuScaledCol,
|
||||
"mem": NewMemCol,
|
||||
"net": NewNetCol,
|
||||
"io": NewIOCol,
|
||||
"pids": NewPIDCol,
|
||||
"uptime": NewUptimeCol,
|
||||
}
|
||||
)
|
||||
|
||||
|
|
|
@ -11,15 +11,23 @@ import (
|
|||
|
||||
type CPUCol struct {
|
||||
*GaugeCol
|
||||
scaleCpu bool
|
||||
}
|
||||
|
||||
func NewCPUCol() CompactCol {
|
||||
return &CPUCol{NewGaugeCol("CPU")}
|
||||
return &CPUCol{NewGaugeCol("CPU"), false}
|
||||
}
|
||||
|
||||
func NewCpuScaledCol() CompactCol {
|
||||
return &CPUCol{NewGaugeCol("CPUS"), true}
|
||||
}
|
||||
|
||||
func (w *CPUCol) SetMetrics(m models.Metrics) {
|
||||
val := m.CPUUtil
|
||||
w.BarColor = colorScale(val)
|
||||
if !w.scaleCpu {
|
||||
val = val * int(m.NCpus)
|
||||
}
|
||||
w.Label = fmt.Sprintf("%d%%", val)
|
||||
|
||||
if val > 100 {
|
||||
|
@ -92,11 +100,11 @@ func (w *GaugeCol) UnHighlight() {
|
|||
}
|
||||
|
||||
func colorScale(n int) ui.Attribute {
|
||||
if n > 70 {
|
||||
return ui.ThemeAttr("status.danger")
|
||||
if n <= 70 {
|
||||
return ui.ThemeAttr("status.ok")
|
||||
}
|
||||
if n > 30 {
|
||||
if n <= 90 {
|
||||
return ui.ThemeAttr("status.warn")
|
||||
}
|
||||
return ui.ThemeAttr("status.ok")
|
||||
return ui.ThemeAttr("status.danger")
|
||||
}
|
||||
|
|
|
@ -6,12 +6,6 @@ import (
|
|||
ui "github.com/gizak/termui"
|
||||
)
|
||||
|
||||
const (
|
||||
mark = "◉"
|
||||
healthMark = "✚"
|
||||
vBar = string('\u25AE') + string('\u25AE')
|
||||
)
|
||||
|
||||
// Status indicator
|
||||
type Status struct {
|
||||
*ui.Block
|
||||
|
@ -22,26 +16,18 @@ type Status struct {
|
|||
func NewStatus() CompactCol {
|
||||
s := &Status{
|
||||
Block: ui.NewBlock(),
|
||||
status: []ui.Cell{{Ch: ' '}},
|
||||
health: []ui.Cell{{Ch: ' '}},
|
||||
}
|
||||
s.Height = 1
|
||||
s.Border = false
|
||||
s.setState("")
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *Status) Buffer() ui.Buffer {
|
||||
buf := s.Block.Buffer()
|
||||
x := 0
|
||||
for _, c := range s.health {
|
||||
buf.Set(s.InnerX()+x, s.InnerY(), c)
|
||||
x += c.Width()
|
||||
}
|
||||
x += 1
|
||||
for _, c := range s.status {
|
||||
buf.Set(s.InnerX()+x, s.InnerY(), c)
|
||||
x += c.Width()
|
||||
}
|
||||
buf.Set(s.InnerX(), s.InnerY(), s.health[0])
|
||||
buf.Set(s.InnerX()+2, s.InnerY(), s.status[0])
|
||||
return buf
|
||||
}
|
||||
|
||||
|
@ -59,36 +45,48 @@ func (s *Status) Header() string { return "" }
|
|||
func (s *Status) FixedWidth() int { return 3 }
|
||||
|
||||
func (s *Status) setState(val string) {
|
||||
// defaults
|
||||
text := mark
|
||||
color := ui.ColorDefault
|
||||
var mark string
|
||||
|
||||
switch val {
|
||||
case "":
|
||||
return
|
||||
case "created":
|
||||
mark = "◉"
|
||||
case "running":
|
||||
mark = "▶"
|
||||
color = ui.ThemeAttr("status.ok")
|
||||
case "exited":
|
||||
mark = "⏹"
|
||||
color = ui.ThemeAttr("status.danger")
|
||||
case "paused":
|
||||
text = vBar
|
||||
mark = "⏸"
|
||||
default:
|
||||
mark = " "
|
||||
log.Warningf("unknown status string: \"%v\"", val)
|
||||
}
|
||||
|
||||
s.status = ui.TextCells(text, color, ui.ColorDefault)
|
||||
s.status = ui.TextCells(mark, color, ui.ColorDefault)
|
||||
}
|
||||
|
||||
func (s *Status) setHealth(val string) {
|
||||
color := ui.ColorDefault
|
||||
mark := healthMark
|
||||
var mark string
|
||||
|
||||
switch val {
|
||||
case "":
|
||||
return
|
||||
case "healthy":
|
||||
mark = "☼"
|
||||
color = ui.ThemeAttr("status.ok")
|
||||
case "unhealthy":
|
||||
mark = "⚠"
|
||||
color = ui.ThemeAttr("status.danger")
|
||||
case "starting":
|
||||
mark = "◌"
|
||||
color = ui.ThemeAttr("status.warn")
|
||||
default:
|
||||
mark = " "
|
||||
log.Warningf("unknown health state string: \"%v\"", val)
|
||||
}
|
||||
|
||||
|
|
|
@ -9,30 +9,44 @@ import (
|
|||
ui "github.com/gizak/termui"
|
||||
)
|
||||
|
||||
type NameCol struct {
|
||||
// Column that shows container's meta property i.e. name, id, image tc.
|
||||
type MetaCol struct {
|
||||
*TextCol
|
||||
metaName string
|
||||
}
|
||||
|
||||
func (w *MetaCol) SetMeta(m models.Meta) {
|
||||
w.setText(m.Get(w.metaName))
|
||||
}
|
||||
|
||||
func NewNameCol() CompactCol {
|
||||
return &NameCol{NewTextCol("NAME")}
|
||||
}
|
||||
|
||||
func (w *NameCol) SetMeta(m models.Meta) {
|
||||
w.setText(m.Get("name"))
|
||||
}
|
||||
|
||||
type CIDCol struct {
|
||||
*TextCol
|
||||
c := &MetaCol{NewTextCol("NAME"), "name"}
|
||||
c.fWidth = 30
|
||||
return c
|
||||
}
|
||||
|
||||
func NewCIDCol() CompactCol {
|
||||
c := &CIDCol{NewTextCol("CID")}
|
||||
c := &MetaCol{NewTextCol("CID"), "id"}
|
||||
c.fWidth = 12
|
||||
return c
|
||||
}
|
||||
|
||||
func (w *CIDCol) SetMeta(m models.Meta) {
|
||||
w.setText(m.Get("id"))
|
||||
func NewImageCol() CompactCol {
|
||||
return &MetaCol{NewTextCol("IMAGE"), "image"}
|
||||
}
|
||||
|
||||
func NewPortsCol() CompactCol {
|
||||
return &MetaCol{NewTextCol("PORTS"), "ports"}
|
||||
}
|
||||
|
||||
func NewIpsCol() CompactCol {
|
||||
return &MetaCol{NewTextCol("IPs"), "IPs"}
|
||||
}
|
||||
|
||||
func NewCreatedCol() CompactCol {
|
||||
c := &MetaCol{NewTextCol("CREATED"), "created"}
|
||||
c.fWidth = 19 // Year will be stripped e.g. "Thu Nov 26 07:44:03" without 2020 at end
|
||||
return c
|
||||
}
|
||||
|
||||
type NetCol struct {
|
||||
|
@ -75,6 +89,18 @@ func (w *PIDCol) SetMetrics(m models.Metrics) {
|
|||
w.setText(fmt.Sprintf("%d", m.Pids))
|
||||
}
|
||||
|
||||
type UptimeCol struct {
|
||||
*TextCol
|
||||
}
|
||||
|
||||
func NewUptimeCol() CompactCol {
|
||||
return &UptimeCol{NewTextCol("UPTIME")}
|
||||
}
|
||||
|
||||
func (w *UptimeCol) SetMeta(m models.Meta) {
|
||||
w.Text = m.Get("uptime")
|
||||
}
|
||||
|
||||
type TextCol struct {
|
||||
*ui.Par
|
||||
header string
|
||||
|
|
|
@ -20,10 +20,10 @@ func NewCpu() *Cpu {
|
|||
|
||||
// hack to force the default minY scale to 0
|
||||
tmpData := []float64{20}
|
||||
cpu.Data = tmpData
|
||||
cpu.Data["CPU"] = tmpData
|
||||
_ = cpu.Buffer()
|
||||
|
||||
cpu.Data = cpu.hist.Data
|
||||
cpu.Data["CPU"] = cpu.hist.Data
|
||||
return cpu
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
package single
|
||||
|
||||
import (
|
||||
ui "github.com/gizak/termui"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
ui "github.com/gizak/termui"
|
||||
)
|
||||
|
||||
var envPattern = regexp.MustCompile(`(?P<KEY>[^=]+)=(?P<VALUJE>.*)`)
|
||||
|
@ -23,14 +25,18 @@ func NewEnv() *Env {
|
|||
return i
|
||||
}
|
||||
|
||||
func (w *Env) Set(k, v string) {
|
||||
match := envPattern.FindStringSubmatch(v)
|
||||
key := match[1]
|
||||
value := match[2]
|
||||
w.data[key] = value
|
||||
|
||||
func (w *Env) Set(allEnvs string) {
|
||||
envs := strings.Split(allEnvs, ";")
|
||||
w.Rows = [][]string{}
|
||||
w.Rows = append(w.Rows, mkInfoRows(key, value)...)
|
||||
for _, env := range envs {
|
||||
match := envPattern.FindStringSubmatch(env)
|
||||
if len(match) == 3 {
|
||||
key := match[1]
|
||||
value := match[2]
|
||||
w.data[key] = value
|
||||
w.Rows = append(w.Rows, mkInfoRows(key, value)...)
|
||||
}
|
||||
}
|
||||
|
||||
w.Height = len(w.Rows) + 2
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ import (
|
|||
ui "github.com/gizak/termui"
|
||||
)
|
||||
|
||||
var displayInfo = []string{"id", "name", "image", "ports", "IPs", "state", "created", "health"}
|
||||
var displayInfo = []string{"id", "name", "image", "ports", "IPs", "state", "created", "uptime", "health"}
|
||||
|
||||
type Info struct {
|
||||
*ui.Table
|
||||
|
|
|
@ -55,7 +55,7 @@ func (e *Single) SetWidth(w int) { e.Width = w }
|
|||
func (e *Single) SetMeta(m models.Meta) {
|
||||
for k, v := range m {
|
||||
if k == "[ENV-VAR]" {
|
||||
e.Env.Set(k, v)
|
||||
e.Env.Set(v)
|
||||
} else {
|
||||
e.Info.Set(k, v)
|
||||
}
|
||||
|
|
4
debug.go
4
debug.go
|
@ -12,6 +12,10 @@ import (
|
|||
var mstats = &runtime.MemStats{}
|
||||
|
||||
func logEvent(e ui.Event) {
|
||||
// skip timer events e.g. /timer/1s
|
||||
if e.From == "timer" {
|
||||
return
|
||||
}
|
||||
var s string
|
||||
s += fmt.Sprintf("Type=%s", quote(e.Type))
|
||||
s += fmt.Sprintf(" Path=%s", quote(e.Path))
|
||||
|
|
59
go.mod
59
go.mod
|
@ -3,19 +3,62 @@ module github.com/bcicen/ctop
|
|||
require (
|
||||
github.com/BurntSushi/toml v0.3.1
|
||||
github.com/c9s/goprocinfo v0.0.0-20170609001544-b34328d6e0cd
|
||||
github.com/fsouza/go-dockerclient v1.6.6
|
||||
github.com/gizak/termui v2.3.0+incompatible
|
||||
github.com/fsouza/go-dockerclient v1.7.0
|
||||
github.com/gizak/termui v2.3.1-0.20180817033724-8d4faad06196+incompatible
|
||||
github.com/hako/durafmt v0.0.0-20210608085754-5c1018a4e16b // indirect
|
||||
github.com/jgautheron/codename-generator v0.0.0-20150829203204-16d037c7cc3c
|
||||
github.com/mattn/go-runewidth v0.0.0-20170201023540-14207d285c6c // indirect
|
||||
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 // indirect
|
||||
github.com/nsf/termbox-go v0.0.0-20180303152453-e2050e41c884
|
||||
github.com/mattn/go-runewidth v0.0.2
|
||||
github.com/nsf/termbox-go v0.0.0-20190121233118-02980233997d
|
||||
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d
|
||||
github.com/op/go-logging v0.0.0-20160211212156-b2cb9fa56473
|
||||
github.com/opencontainers/runc v1.0.0-rc92
|
||||
github.com/opencontainers/runc v1.1.0
|
||||
github.com/pkg/browser v0.0.0-20201207095918-0426ae3fba23
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/stretchr/testify v1.4.0
|
||||
)
|
||||
|
||||
replace github.com/gizak/termui => github.com/bcicen/termui v0.0.0-20180326052246-4eb80249d3f5
|
||||
require (
|
||||
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 // indirect
|
||||
github.com/Microsoft/go-winio v0.4.16 // indirect
|
||||
github.com/Microsoft/hcsshim v0.8.10 // indirect
|
||||
github.com/checkpoint-restore/go-criu/v5 v5.3.0 // indirect
|
||||
github.com/cilium/ebpf v0.7.0 // indirect
|
||||
github.com/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59 // indirect
|
||||
github.com/containerd/console v1.0.3 // indirect
|
||||
github.com/containerd/containerd v1.4.1 // indirect
|
||||
github.com/containerd/continuity v0.0.0-20200928162600-f2cc35102c2a // indirect
|
||||
github.com/coreos/go-systemd/v22 v22.3.2 // indirect
|
||||
github.com/cyphar/filepath-securejoin v0.2.3 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/docker/docker v20.10.0-beta1.0.20201113105859-b6bfff2a628f+incompatible // indirect
|
||||
github.com/docker/go-connections v0.4.0 // indirect
|
||||
github.com/docker/go-units v0.4.0 // indirect
|
||||
github.com/godbus/dbus/v5 v5.0.6 // indirect
|
||||
github.com/gogo/protobuf v1.3.1 // indirect
|
||||
github.com/hashicorp/golang-lru v0.5.1 // indirect
|
||||
github.com/maruel/panicparse v1.6.1 // indirect
|
||||
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 // indirect
|
||||
github.com/moby/sys/mount v0.2.0 // indirect
|
||||
github.com/moby/sys/mountinfo v0.5.0 // indirect
|
||||
github.com/moby/term v0.0.0-20201110203204-bea5bbe245bf // indirect
|
||||
github.com/morikuni/aec v1.0.0 // indirect
|
||||
github.com/mrunalp/fileutils v0.5.0 // indirect
|
||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||
github.com/opencontainers/image-spec v1.0.1 // indirect
|
||||
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417 // indirect
|
||||
github.com/opencontainers/selinux v1.10.0 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/seccomp/libseccomp-golang v0.9.2-0.20210429002308-3879420cc921 // indirect
|
||||
github.com/sirupsen/logrus v1.8.1 // indirect
|
||||
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 // indirect
|
||||
github.com/vishvananda/netlink v1.1.0 // indirect
|
||||
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df // indirect
|
||||
go.opencensus.io v0.22.0 // indirect
|
||||
golang.org/x/net v0.0.0-20201224014010-6772e930b67b // indirect
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58 // indirect
|
||||
golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c // indirect
|
||||
google.golang.org/protobuf v1.27.1 // indirect
|
||||
gopkg.in/yaml.v2 v2.2.8 // indirect
|
||||
)
|
||||
|
||||
go 1.15
|
||||
go 1.18
|
||||
|
|
250
go.sum
250
go.sum
|
@ -4,70 +4,63 @@ github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7O
|
|||
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
|
||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw=
|
||||
github.com/Microsoft/go-winio v0.4.15-0.20200113171025-3fe6c5262873 h1:93nQ7k53GjoMQ07HVP8g6Zj1fQZDDj7Xy2VkNNtvX8o=
|
||||
github.com/Microsoft/go-winio v0.4.15-0.20200113171025-3fe6c5262873/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw=
|
||||
github.com/Microsoft/hcsshim v0.8.9 h1:VrfodqvztU8YSOvygU+DN1BGaSGxmrNfqOv5oOuX2Bk=
|
||||
github.com/Microsoft/hcsshim v0.8.9/go.mod h1:5692vkUqntj1idxauYlpoINNKeqCiG6Sg38RRsjT5y8=
|
||||
github.com/bcicen/termui v0.0.0-20180326052246-4eb80249d3f5 h1:2pI3ZsoefWIi++8EqmANoC7Px/v2lRwnleVUcCuFgLg=
|
||||
github.com/bcicen/termui v0.0.0-20180326052246-4eb80249d3f5/go.mod h1:yIA9ITWZD1p4/DvCQ44xvhyVb9XEUlVnY1rzGSHwbiM=
|
||||
github.com/Microsoft/go-winio v0.4.15-0.20200908182639-5b44b70ab3ab/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw=
|
||||
github.com/Microsoft/go-winio v0.4.16 h1:FtSW/jqD+l4ba5iPBj9CODVtgfYAD8w2wS923g/cFDk=
|
||||
github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0=
|
||||
github.com/Microsoft/hcsshim v0.8.10 h1:k5wTrpnVU2/xv8ZuzGkbXVd3js5zJ8RnumPo5RxiIxU=
|
||||
github.com/Microsoft/hcsshim v0.8.10/go.mod h1:g5uw8EV2mAlzqe94tfNBNdr89fnbD/n3HV0OhsddkmM=
|
||||
github.com/c9s/goprocinfo v0.0.0-20170609001544-b34328d6e0cd h1:xqaBnULC8wEnQpRDXAsDgXkU/STqoluz1REOoegSfNU=
|
||||
github.com/c9s/goprocinfo v0.0.0-20170609001544-b34328d6e0cd/go.mod h1:uEyr4WpAH4hio6LFriaPkL938XnrvLpNPmQHBdrmbIE=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/checkpoint-restore/go-criu/v4 v4.1.0 h1:WW2B2uxx9KWF6bGlHqhm8Okiafwwx7Y2kcpn8lCpjgo=
|
||||
github.com/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw=
|
||||
github.com/cilium/ebpf v0.0.0-20200702112145-1c8d4c9ef775 h1:cHzBGGVew0ezFsq2grfy2RsB8hO/eNyBgOLHBCqfR1U=
|
||||
github.com/cilium/ebpf v0.0.0-20200702112145-1c8d4c9ef775/go.mod h1:7cR51M8ViRLIdUjrmSXlK9pkrsDlLHbO8jiB8X8JnOc=
|
||||
github.com/checkpoint-restore/go-criu/v5 v5.3.0 h1:wpFFOoomK3389ue2lAb0Boag6XPht5QYpipxmSNL4d8=
|
||||
github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E=
|
||||
github.com/cilium/ebpf v0.0.0-20200110133405-4032b1d8aae3/go.mod h1:MA5e5Lr8slmEg9bt0VpxxWqJlO4iwu3FBdHUzV7wQVg=
|
||||
github.com/cilium/ebpf v0.7.0 h1:1k/q3ATgxSXRdrmPfH8d7YK0GfqVsEKZAX9dQZvs56k=
|
||||
github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko=
|
||||
github.com/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59 h1:qWj4qVYZ95vLWwqyNJCQg7rDsG5wPdze0UaPolH7DUk=
|
||||
github.com/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59/go.mod h1:pA0z1pT8KYB3TCXK/ocprsh7MAkoW8bZVzPdih9snmM=
|
||||
github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw=
|
||||
github.com/containerd/console v1.0.0 h1:fU3UuQapBs+zLJu82NhR11Rif1ny2zfMMAyPJzSN5tQ=
|
||||
github.com/containerd/console v1.0.0/go.mod h1:8Pf4gM6VEbTNRIT26AyyU7hxdQU3MvAvxVI0sc00XBE=
|
||||
github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw=
|
||||
github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U=
|
||||
github.com/containerd/containerd v1.3.2/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
||||
github.com/containerd/containerd v1.3.4 h1:3o0smo5SKY7H6AJCmJhsnCjR2/V2T8VmiHt7seN2/kI=
|
||||
github.com/containerd/containerd v1.3.4/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
||||
github.com/containerd/containerd v1.4.1 h1:pASeJT3R3YyVn+94qEPk0SnU1OQ20Jd/T+SPKy9xehY=
|
||||
github.com/containerd/containerd v1.4.1/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
||||
github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
|
||||
github.com/containerd/continuity v0.0.0-20200413184840-d3ef23f19fbb h1:nXPkFq8X1a9ycY3GYQpFNxHh3j2JgY7zDZfq2EXMIzk=
|
||||
github.com/containerd/continuity v0.0.0-20200413184840-d3ef23f19fbb/go.mod h1:Dq467ZllaHgAtVp4p1xUQWBrFXR9s/wyoTpG8zOJGkY=
|
||||
github.com/containerd/continuity v0.0.0-20200928162600-f2cc35102c2a h1:jEIoR0aA5GogXZ8pP3DUzE+zrhaF6/1rYZy+7KkYEWM=
|
||||
github.com/containerd/continuity v0.0.0-20200928162600-f2cc35102c2a/go.mod h1:W0qIOTD7mp2He++YVq+kgfXezRYqzP1uDuMVH1bITDY=
|
||||
github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI=
|
||||
github.com/containerd/go-runc v0.0.0-20180907222934-5a6d9f37cfa3/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0=
|
||||
github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o=
|
||||
github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc=
|
||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e h1:Wf6HqHfScWJN9/ZjdUKyjop4mf3Qdd+1TvvltAvM3m8=
|
||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/go-systemd/v22 v22.1.0 h1:kq/SbG2BCKLkDKkjQf5OWwKWUKj1lgs3lFI4PxnR5lg=
|
||||
github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY=
|
||||
github.com/coreos/go-systemd/v22 v22.0.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk=
|
||||
github.com/coreos/go-systemd/v22 v22.3.2 h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzAJc1DzSI=
|
||||
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/creack/pty v1.1.9 h1:uDmaGzcdjhF4i/plgjmEsriH11Y0o7RKapEf/LDaM3w=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/cyphar/filepath-securejoin v0.2.2 h1:jCwT2GTP+PY5nBz3c/YL5PAIbusElVrPujOBSCj8xRg=
|
||||
github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw=
|
||||
github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/cyphar/filepath-securejoin v0.2.3 h1:YX6ebbZCZP7VkM3scTTokDgBL2TY741X51MTk3ycuNI=
|
||||
github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug=
|
||||
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||
github.com/docker/docker v17.12.0-ce-rc1.0.20200505174321-1655290016ac+incompatible h1:ZxJX4ZSNg1LORBsStUojbrLfkrE3Ut122XhzyZnN110=
|
||||
github.com/docker/docker v17.12.0-ce-rc1.0.20200505174321-1655290016ac+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/docker v20.10.0-beta1.0.20201113105859-b6bfff2a628f+incompatible h1:lwpV3629md5omgAKjxPWX17shI7vMRpE3nyb9WHn8pA=
|
||||
github.com/docker/docker v20.10.0-beta1.0.20201113105859-b6bfff2a628f+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
|
||||
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
||||
github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw=
|
||||
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsouza/go-dockerclient v1.6.6 h1:9e3xkBrVkPb81gzYq23i7iDUEd6sx2ooeJA/gnYU6R4=
|
||||
github.com/fsouza/go-dockerclient v1.6.6/go.mod h1:3/oRIWoe7uT6bwtAayj/EmJmepBjeL4pYvt7ZxC7Rnk=
|
||||
github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e h1:BWhy2j3IXJhjCbC68FptL43tDKIq8FladmaTs3Xs7Z8=
|
||||
github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4=
|
||||
github.com/godbus/dbus/v5 v5.0.3 h1:ZqHaoEF7TBzh4jzPmqVhE/5A1z9of6orkAe5uHoAeME=
|
||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/frankban/quicktest v1.11.3 h1:8sXhOn0uLys67V8EsXLc6eszDs8VXWxL3iRvebPhedY=
|
||||
github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k=
|
||||
github.com/fsouza/go-dockerclient v1.7.0 h1:Ie1/8pAnBHNyCbSIDnYKBdXUEobk4AeJhWZz7k6rWfc=
|
||||
github.com/fsouza/go-dockerclient v1.7.0/go.mod h1:Ny0LfP7OOsYu9nAi4339E4Ifor6nGBFO2M8lnd2nR+c=
|
||||
github.com/gizak/termui v2.3.1-0.20180817033724-8d4faad06196+incompatible h1:pUbrySwhNIu18YXjMTCt/Z3kr8eYQ8hRDs4BeR/crmA=
|
||||
github.com/gizak/termui v2.3.1-0.20180817033724-8d4faad06196+incompatible/go.mod h1:PkJoWUt/zacQKysNfQtcw1RW+eK2SxkieVBtl+4ovLA=
|
||||
github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE=
|
||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/godbus/dbus/v5 v5.0.6 h1:mkgN1ofwASrYnJ5W6U/BxG15eXXXjirgZc7CLqkcaro=
|
||||
github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls=
|
||||
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
|
@ -75,122 +68,111 @@ github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb
|
|||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
|
||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||
github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
|
||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.5.0 h1:LUVKkCeviFUMKqHa4tXIIij/lbhnMbP7Fn5wKdKkRh4=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM=
|
||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
||||
github.com/hako/durafmt v0.0.0-20210608085754-5c1018a4e16b h1:wDUNC2eKiL35DbLvsDhiblTUXHxcOPwQSCzi7xpQUN4=
|
||||
github.com/hako/durafmt v0.0.0-20210608085754-5c1018a4e16b/go.mod h1:VzxiSdG6j1pi7rwGm/xYI5RbtpBgM8sARDXlvEvxlu0=
|
||||
github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU=
|
||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/jgautheron/codename-generator v0.0.0-20150829203204-16d037c7cc3c h1:/hc+TxW4Q1v6aqNPHE5jiaNF2xEK0CzWTgo25RQhQ+U=
|
||||
github.com/jgautheron/codename-generator v0.0.0-20150829203204-16d037c7cc3c/go.mod h1:FJRkXmPrkHw0WDjB/LXMUhjWJ112Y6JUYnIVBOy8oH8=
|
||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/mattn/go-runewidth v0.0.0-20170201023540-14207d285c6c h1:eFzthqtg3W6Pihj3DMTXLAF4f+ge5r5Ie5g6HLIZAF0=
|
||||
github.com/mattn/go-runewidth v0.0.0-20170201023540-14207d285c6c/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/maruel/panicparse v1.6.1 h1:803MjBzGcUgE1vYgg3UMNq3G1oyYeKkMu3t6hBS97x0=
|
||||
github.com/maruel/panicparse v1.6.1/go.mod h1:uoxI4w9gJL6XahaYPMq/z9uadrdr1SyHuQwV2q80Mm0=
|
||||
github.com/maruel/panicparse/v2 v2.1.1/go.mod h1:AeTWdCE4lcq8OKsLb6cHSj1RWHVSnV9HBCk7sKLF4Jg=
|
||||
github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-runewidth v0.0.2 h1:UnlwIPBGaTZfPQ6T1IGzPI0EkYAQmT9fAEJ/poFC63o=
|
||||
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
|
||||
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 h1:DpOJ2HYzCv8LZP15IdmG+YdwD2luVPHITV96TkirNBM=
|
||||
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
|
||||
github.com/moby/sys/mount v0.1.0 h1:Ytx78EatgFKtrqZ0BvJ0UtJE472ZvawVmil6pIfuCCU=
|
||||
github.com/moby/sys/mount v0.1.0/go.mod h1:FVQFLDRWwyBjDTBNQXDlWnSFREqOo3OKX9aqhmeoo74=
|
||||
github.com/moby/sys/mountinfo v0.1.0/go.mod h1:w2t2Avltqx8vE7gX5l+QiBKxODu2TX0+Syr3h52Tw4o=
|
||||
github.com/moby/sys/mountinfo v0.1.3 h1:KIrhRO14+AkwKvG/g2yIpNMOUVZ02xNhOw8KY1WsLOI=
|
||||
github.com/moby/sys/mountinfo v0.1.3/go.mod h1:w2t2Avltqx8vE7gX5l+QiBKxODu2TX0+Syr3h52Tw4o=
|
||||
github.com/moby/term v0.0.0-20200429084858-129dac9f73f6 h1:3Y9aosU6S5Bo8GYH0s+t1ej4m30GuUKvQ3c9ZLqdL28=
|
||||
github.com/moby/term v0.0.0-20200429084858-129dac9f73f6/go.mod h1:or9wGItza1sRcM4Wd3dIv8DsFHYQuFsMHEdxUIlUxms=
|
||||
github.com/moby/sys/mount v0.2.0 h1:WhCW5B355jtxndN5ovugJlMFJawbUODuW8fSnEH6SSM=
|
||||
github.com/moby/sys/mount v0.2.0/go.mod h1:aAivFE2LB3W4bACsUXChRHQ0qKWsetY4Y9V7sxOougM=
|
||||
github.com/moby/sys/mountinfo v0.4.0/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A=
|
||||
github.com/moby/sys/mountinfo v0.5.0 h1:2Ks8/r6lopsxWi9m58nlwjaeSzUX9iiL1vj5qB/9ObI=
|
||||
github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU=
|
||||
github.com/moby/term v0.0.0-20201110203204-bea5bbe245bf h1:Un6PNx5oMK6CCwO3QTUyPiK2mtZnPrpDl5UnZ64eCkw=
|
||||
github.com/moby/term v0.0.0-20201110203204-bea5bbe245bf/go.mod h1:FBS0z0QWA44HXygs7VXDUOGoN/1TV3RuWkLO04am3wc=
|
||||
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
|
||||
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
|
||||
github.com/mrunalp/fileutils v0.0.0-20200520151820-abd8a0e76976 h1:aZQToFSLH8ejFeSkTc3r3L4dPImcj7Ib/KgmkQqbGGg=
|
||||
github.com/mrunalp/fileutils v0.0.0-20200520151820-abd8a0e76976/go.mod h1:x8F1gnqOkIEiO4rqoeEEEqQbo7HjGMTvyoq3gej4iT0=
|
||||
github.com/nsf/termbox-go v0.0.0-20180303152453-e2050e41c884 h1:fcs71SMqqDhUD+PbpIv9xf3EH9F9s6HfiLwr6jKm1VA=
|
||||
github.com/nsf/termbox-go v0.0.0-20180303152453-e2050e41c884/go.mod h1:IuKpRQcYE1Tfu+oAQqaLisqDeXgjyyltCfsaoYN18NQ=
|
||||
github.com/mrunalp/fileutils v0.5.0 h1:NKzVxiH7eSk+OQ4M+ZYW1K6h27RUV3MI6NUTsHhU6Z4=
|
||||
github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ=
|
||||
github.com/nsf/termbox-go v0.0.0-20190121233118-02980233997d h1:x3S6kxmy49zXVVyhcnrFqxvNVCBPb2KZ9hV2RBdS840=
|
||||
github.com/nsf/termbox-go v0.0.0-20190121233118-02980233997d/go.mod h1:IuKpRQcYE1Tfu+oAQqaLisqDeXgjyyltCfsaoYN18NQ=
|
||||
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d h1:VhgPp6v9qf9Agr/56bj7Y/xa04UccTW04VP0Qed4vnQ=
|
||||
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d/go.mod h1:YUTz3bUH2ZwIWBy3CJBeOBEugqcmXREj14T+iG/4k4U=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/op/go-logging v0.0.0-20160211212156-b2cb9fa56473 h1:J1QZwDXgZ4dJD2s19iqR9+U00OWM2kDzbf1O/fmvCWg=
|
||||
github.com/op/go-logging v0.0.0-20160211212156-b2cb9fa56473/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
|
||||
github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
||||
github.com/opencontainers/go-digest v1.0.0-rc1 h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2iki3E3Ii+WN7gQ=
|
||||
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
||||
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||
github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI=
|
||||
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
||||
github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
||||
github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
||||
github.com/opencontainers/runc v1.0.0-rc92 h1:+IczUKCRzDzFDnw99O/PAqrcBBCoRp9xN3cB1SYSNS4=
|
||||
github.com/opencontainers/runc v1.0.0-rc92/go.mod h1:X1zlU4p7wOlX4+WRCz+hvlRv8phdL7UqbYD+vQwNMmE=
|
||||
github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||
github.com/opencontainers/runtime-spec v1.0.3-0.20200728170252-4d89ac9fbff6 h1:NhsM2gc769rVWDqJvapK37r+7+CBXI8xHhnfnt8uQsg=
|
||||
github.com/opencontainers/runtime-spec v1.0.3-0.20200728170252-4d89ac9fbff6/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||
github.com/opencontainers/selinux v1.6.0 h1:+bIAS/Za3q5FTwWym4fTB0vObnfCf3G/NC7K6Jx62mY=
|
||||
github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqiriPsEqVhc+svHE=
|
||||
github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/opencontainers/runc v1.1.0 h1:O9+X96OcDjkmmZyfaG996kV7yq8HsoU2h1XRRQcefG8=
|
||||
github.com/opencontainers/runc v1.1.0/go.mod h1:Tj1hFw6eFWp/o33uxGf5yF2BX5yz2Z6iptFpuvbbKqc=
|
||||
github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417 h1:3snG66yBm59tKhhSPQrQ/0bCrv1LQbKt40LnUPiUxdc=
|
||||
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||
github.com/opencontainers/selinux v1.10.0 h1:rAiKF8hTcgLI3w0DHm6i0ylVVcOrlgR1kK99DRLDhyU=
|
||||
github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI=
|
||||
github.com/pkg/browser v0.0.0-20201207095918-0426ae3fba23 h1:dofHuld+js7eKSemxqTVIo8yRlpRw+H1SdpzZxWruBc=
|
||||
github.com/pkg/browser v0.0.0-20201207095918-0426ae3fba23/go.mod h1:N6UoU20jOqggOuDwUaBQpluzLNDqif3kq9z2wpdYEfQ=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/seccomp/libseccomp-golang v0.9.1 h1:NJjM5DNFOs0s3kYE1WUOr6G8V97sdt46rlXTMfXGWBo=
|
||||
github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
|
||||
github.com/seccomp/libseccomp-golang v0.9.2-0.20210429002308-3879420cc921 h1:58EBmR2dMNL2n/FnbQewK3D14nXr0V9CObDSvMJLq+Y=
|
||||
github.com/seccomp/libseccomp-golang v0.9.2-0.20210429002308-3879420cc921/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
|
||||
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I=
|
||||
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
||||
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
|
||||
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
||||
github.com/spf13/pflag v1.0.1-0.20171106142849-4c012f6dcd95/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2 h1:b6uOv7YOFK0TYG7HtkIgExQo+2RdLuwRft63jn2HWj8=
|
||||
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
||||
github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||
github.com/urfave/cli v1.22.1 h1:+mkCCcOFKPnCmVYVcURKps1Xe+3zP90gSYGNfRkjoIY=
|
||||
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 h1:kdXcSzyDtseVEc4yCz2qF8ZrQvIDBJLl4S1c3GCXmoI=
|
||||
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
||||
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||
github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||
github.com/vishvananda/netlink v1.1.0 h1:1iyaYNBLmP6L0220aDnYQpo1QEV4t4hJ+xEEhhJH8j0=
|
||||
github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
|
||||
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df h1:OviZH7qLw/7ZovXvuNyL3XQl8UFofeikI1NW1Gypu7k=
|
||||
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
|
||||
github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243 h1:R43TdZy32XXSXjJn7M/HhALJ9imq6ztLnChfYJpVDnM=
|
||||
github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
|
||||
go.opencensus.io v0.22.0 h1:C9hSCOW830chIVkdja34wa6Ky+IzWllkUinR+BtRZd4=
|
||||
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||
golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20200429183012-4b2356b1ed79 h1:IaQbIIB2X/Mp/DKctl6ROxz1KyMlKp4uyvL6+kQ7C88=
|
||||
golang.org/x/crypto v0.0.0-20200429183012-4b2356b1ed79/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
|
@ -200,10 +182,10 @@ golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73r
|
|||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9 h1:rjwSpXsdiK0dV8/Naq3kAw9ymfAeJIyd0upUIElB+lI=
|
||||
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20201224014010-6772e930b67b h1:iFwSg7t5GZmB/Q5TjiEAsdoLDrdJRC1RiF2WhuV29Qw=
|
||||
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
@ -212,25 +194,33 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEha
|
|||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190514135907-3a4b5fb9f71f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200120151820-655fe14d7479/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1 h1:sIky/MyNRSHTrdxfsiUSS4WIAMvInbeXljJz+jDjeYE=
|
||||
golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200724161237-0e2f3a69832c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200922070232-aee5d888a860/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c h1:DHcbWVXeY+0Y8HHKR+rbLwnoh2F4tNCY7rTiHJ30RmA=
|
||||
golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201113234701-d7a72108b828/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
|
@ -245,36 +235,22 @@ google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7
|
|||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2ElGhA4+qG2zF97qiUzTM+rQ0klBOcE=
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
||||
google.golang.org/grpc v1.29.1 h1:EC2SB8S04d2r73uptxphDSUG+kTKVgjRPF+N3xpxRB4=
|
||||
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||
google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM=
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ=
|
||||
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
|
||||
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
|
||||
gotest.tools/v3 v3.0.2 h1:kG1BFyqVHuQoVQiR1bWGnfz/fmHvvuiSPIV7rvl360E=
|
||||
gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
|
||||
gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0=
|
||||
gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
|
|
3
grid.go
3
grid.go
|
@ -162,6 +162,9 @@ func Display() bool {
|
|||
menu = ExecShell
|
||||
ui.StopLoop()
|
||||
})
|
||||
ui.Handle("/sys/kbd/w", func(ui.Event) {
|
||||
menu = OpenInBrowser()
|
||||
})
|
||||
ui.Handle("/sys/kbd/o", func(ui.Event) {
|
||||
menu = SingleView
|
||||
ui.StopLoop()
|
||||
|
|
|
@ -29,6 +29,7 @@ type statusMsg struct {
|
|||
type CTopLogger struct {
|
||||
*logging.Logger
|
||||
backend *logging.MemoryBackend
|
||||
logFile *os.File
|
||||
sLog []statusMsg
|
||||
}
|
||||
|
||||
|
@ -58,18 +59,37 @@ func Init() *CTopLogger {
|
|||
Log = &CTopLogger{
|
||||
logging.MustGetLogger("ctop"),
|
||||
logging.NewMemoryBackend(size),
|
||||
nil,
|
||||
[]statusMsg{},
|
||||
}
|
||||
|
||||
if debugMode() {
|
||||
debugMode := debugMode()
|
||||
if debugMode {
|
||||
level = logging.DEBUG
|
||||
StartServer()
|
||||
}
|
||||
|
||||
backendLvl := logging.AddModuleLevel(Log.backend)
|
||||
backendLvl.SetLevel(level, "")
|
||||
|
||||
logging.SetBackend(backendLvl)
|
||||
logFilePath := debugModeFile()
|
||||
if logFilePath == "" {
|
||||
logging.SetBackend(backendLvl)
|
||||
} else {
|
||||
logFile, err := os.OpenFile(logFilePath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0666)
|
||||
if err != nil {
|
||||
logging.SetBackend(backendLvl)
|
||||
Log.Error("Unable to create log file: %s", err.Error())
|
||||
} else {
|
||||
backendFile := logging.NewLogBackend(logFile, "", 0)
|
||||
backendFileLvl := logging.AddModuleLevel(backendFile)
|
||||
backendFileLvl.SetLevel(level, "")
|
||||
logging.SetBackend(backendLvl, backendFileLvl)
|
||||
Log.logFile = logFile
|
||||
}
|
||||
}
|
||||
|
||||
if debugMode {
|
||||
StartServer()
|
||||
}
|
||||
Log.Notice("logger initialized")
|
||||
}
|
||||
return Log
|
||||
|
@ -102,8 +122,12 @@ func (log *CTopLogger) tail() chan string {
|
|||
|
||||
func (log *CTopLogger) Exit() {
|
||||
exited = true
|
||||
if log.logFile != nil {
|
||||
_ = log.logFile.Close()
|
||||
}
|
||||
StopServer()
|
||||
}
|
||||
|
||||
func debugMode() bool { return os.Getenv("CTOP_DEBUG") == "1" }
|
||||
func debugModeTCP() bool { return os.Getenv("CTOP_DEBUG_TCP") == "1" }
|
||||
func debugMode() bool { return os.Getenv("CTOP_DEBUG") == "1" }
|
||||
func debugModeTCP() bool { return os.Getenv("CTOP_DEBUG_TCP") == "1" }
|
||||
func debugModeFile() string { return os.Getenv("CTOP_DEBUG_FILE") }
|
||||
|
|
10
main.go
10
main.go
|
@ -44,9 +44,7 @@ func main() {
|
|||
sortFieldFlag = flag.String("s", "", "select container sort field")
|
||||
reverseSortFlag = flag.Bool("r", false, "reverse container sort order")
|
||||
invertFlag = flag.Bool("i", false, "invert default colors")
|
||||
scaleCpu = flag.Bool("scale-cpu", false, "show cpu as % of system total")
|
||||
connectorFlag = flag.String("connector", "docker", "container connector to use")
|
||||
defaultShell = flag.String("shell", "sh", "exec shell to use")
|
||||
)
|
||||
flag.Parse()
|
||||
|
||||
|
@ -87,14 +85,6 @@ func main() {
|
|||
config.Toggle("sortReversed")
|
||||
}
|
||||
|
||||
if *scaleCpu {
|
||||
config.Toggle("scaleCpu")
|
||||
}
|
||||
|
||||
if *defaultShell != "" {
|
||||
config.Update("shell", *defaultShell)
|
||||
}
|
||||
|
||||
// init ui
|
||||
if *invertFlag {
|
||||
InvertColorMap()
|
||||
|
|
46
menus.go
46
menus.go
|
@ -10,6 +10,7 @@ import (
|
|||
"github.com/bcicen/ctop/widgets"
|
||||
"github.com/bcicen/ctop/widgets/menu"
|
||||
ui "github.com/gizak/termui"
|
||||
"github.com/pkg/browser"
|
||||
)
|
||||
|
||||
// MenuFn executes a menu window, returning the next menu or nil
|
||||
|
@ -27,6 +28,7 @@ var helpDialog = []menu.Item{
|
|||
{"[o] - open single view", ""},
|
||||
{"[l] - view container logs ([t] to toggle timestamp when open)", ""},
|
||||
{"[e] - exec shell", ""},
|
||||
{"[w] - open browser (first port is http)", ""},
|
||||
{"[c] - configure columns", ""},
|
||||
{"[S] - save current configuration to file", ""},
|
||||
{"[q] - exit ctop", ""},
|
||||
|
@ -130,7 +132,7 @@ func ColumnsMenu() MenuFn {
|
|||
m.Selectable = true
|
||||
m.SortItems = false
|
||||
m.BorderLabel = "Columns"
|
||||
//m.SubText = "Enabled Columns"
|
||||
m.SubText = "Re-order: <Page Up> / <Page Down>"
|
||||
|
||||
rebuild := func() {
|
||||
// get padding for right alignment of enabled status
|
||||
|
@ -221,6 +223,9 @@ func ContainerMenu() MenuFn {
|
|||
items = append(items, menu.Item{Val: "pause", Label: "[p] pause"})
|
||||
items = append(items, menu.Item{Val: "restart", Label: "[r] restart"})
|
||||
items = append(items, menu.Item{Val: "exec", Label: "[e] exec shell"})
|
||||
if c.Meta["Web Port"] != "" {
|
||||
items = append(items, menu.Item{Val: "browser", Label: "[w] open in browser"})
|
||||
}
|
||||
}
|
||||
if c.Meta["state"] == "exited" || c.Meta["state"] == "created" {
|
||||
items = append(items, menu.Item{Val: "start", Label: "[s] start"})
|
||||
|
@ -258,7 +263,7 @@ func ContainerMenu() MenuFn {
|
|||
ui.StopLoop()
|
||||
})
|
||||
}
|
||||
if c.Meta["state"] != "exited" || c.Meta["state"] != "created" {
|
||||
if c.Meta["state"] != "exited" && c.Meta["state"] != "created" {
|
||||
ui.Handle("/sys/kbd/p", func(ui.Event) {
|
||||
if c.Meta["state"] == "paused" {
|
||||
selected = "unpause"
|
||||
|
@ -277,6 +282,11 @@ func ContainerMenu() MenuFn {
|
|||
selected = "restart"
|
||||
ui.StopLoop()
|
||||
})
|
||||
if c.Meta["Web Port"] != "" {
|
||||
ui.Handle("/sys/kbd/w", func(ui.Event) {
|
||||
selected = "browser"
|
||||
})
|
||||
}
|
||||
}
|
||||
ui.Handle("/sys/kbd/R", func(ui.Event) {
|
||||
selected = "remove"
|
||||
|
@ -303,6 +313,8 @@ func ContainerMenu() MenuFn {
|
|||
nextMenu = LogMenu
|
||||
case "exec":
|
||||
nextMenu = ExecShell
|
||||
case "browser":
|
||||
nextMenu = OpenInBrowser
|
||||
case "start":
|
||||
nextMenu = Confirm(confirmTxt("start", c.GetMeta("name")), c.Start)
|
||||
case "stop":
|
||||
|
@ -358,15 +370,37 @@ func ExecShell() MenuFn {
|
|||
|
||||
ui.DefaultEvtStream.ResetHandlers()
|
||||
defer ui.DefaultEvtStream.ResetHandlers()
|
||||
|
||||
shell := config.Get("shell")
|
||||
if err := c.Exec([]string{shell.Val, "-c", "printf '\\e[0m\\e[?25h' && clear && " + shell.Val}); err != nil {
|
||||
log.Fatal(err)
|
||||
// Detect and execute default shell in container.
|
||||
// Execute Ash shell command: /bin/sh -c
|
||||
// Reset colors: printf '\e[0m\e[?25h'
|
||||
// Clear screen
|
||||
// Run default shell for the user. It's configured in /etc/passwd and looks like root:x:0:0:root:/root:/bin/bash:
|
||||
// 1. Get current user id: id -un
|
||||
// 2. Find user's line in /etc/passwd by grep
|
||||
// 3. Extract default user's shell by cutting seven's column separated by :
|
||||
// 4. Execute the shell path with eval
|
||||
if err := c.Exec([]string{"/bin/sh", "-c", "printf '\\e[0m\\e[?25h' && clear && eval `grep ^$(id -un): /etc/passwd | cut -d : -f 7-`"}); err != nil {
|
||||
log.StatusErr(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func OpenInBrowser() MenuFn {
|
||||
c := cursor.Selected()
|
||||
if c == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
webPort := c.Meta.Get("Web Port")
|
||||
if webPort == "" {
|
||||
return nil
|
||||
}
|
||||
link := "http://" + webPort + "/"
|
||||
browser.OpenURL(link)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Create a confirmation dialog with a given description string and
|
||||
// func to perform if confirmed
|
||||
func Confirm(txt string, fn func()) MenuFn {
|
||||
|
|
|
@ -31,6 +31,7 @@ func (m Meta) Get(k string) string {
|
|||
}
|
||||
|
||||
type Metrics struct {
|
||||
NCpus uint8
|
||||
CPUUtil int
|
||||
NetTx int64
|
||||
NetRx int64
|
||||
|
|
|
@ -2,6 +2,7 @@ package widgets
|
|||
|
||||
import (
|
||||
ui "github.com/gizak/termui"
|
||||
"github.com/mattn/go-runewidth"
|
||||
)
|
||||
|
||||
type ToggleText interface {
|
||||
|
@ -70,7 +71,7 @@ func (t *TextView) Buffer() ui.Buffer {
|
|||
for _, ch := range line {
|
||||
cell = ui.Cell{Ch: ch, Fg: t.TextFgColor, Bg: t.TextBgColor}
|
||||
buf.Set(x, y, cell)
|
||||
x++
|
||||
x = x + runewidth.RuneWidth(ch)
|
||||
}
|
||||
x = t.Block.X + t.padding[0]
|
||||
y++
|
||||
|
|
Loading…
Reference in New Issue