mirror of
https://github.com/bcicen/ctop.git
synced 2025-12-06 23:26:45 +08:00
Compare commits
69 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8f0c9f5048 | ||
|
|
15708224a7 | ||
|
|
442e70b8df | ||
|
|
c58a609349 | ||
|
|
78b038e687 | ||
|
|
2d937aca08 | ||
|
|
0094cba5ea | ||
|
|
537bb2adfa | ||
|
|
491cd85b4d | ||
|
|
9545dfba31 | ||
|
|
cdcb8b6d99 | ||
|
|
b562c923b3 | ||
|
|
f2c28c5fb0 | ||
|
|
ac76b2eac1 | ||
|
|
b32f90fa4a | ||
|
|
bec78c90b5 | ||
|
|
043f4bd3f3 | ||
|
|
c2401cb33a | ||
|
|
fa254c652c | ||
|
|
a59c7aab3c | ||
|
|
4e44c9d5f7 | ||
|
|
948e7cc9d0 | ||
|
|
6c662d91fb | ||
|
|
b4a63f8c60 | ||
|
|
87d135909f | ||
|
|
117c3bc7b5 | ||
|
|
b1171f6c3e | ||
|
|
9a41252764 | ||
|
|
f377dcaee2 | ||
|
|
65e9c6dff6 | ||
|
|
df0d8b7892 | ||
|
|
2792e72d18 | ||
|
|
68d6da5c61 | ||
|
|
53a6b36bf5 | ||
|
|
5ec02f760e | ||
|
|
83a422933a | ||
|
|
7679d4a7fd | ||
|
|
e34afceb5f | ||
|
|
ddfff03c05 | ||
|
|
29d90cfdd9 | ||
|
|
ba126e6e7c | ||
|
|
009201ed0c | ||
|
|
2c07cab59c | ||
|
|
fd06992236 | ||
|
|
e64edbdc36 | ||
|
|
4c280cee56 | ||
|
|
b65e970a83 | ||
|
|
957cabba2d | ||
|
|
5aacdc3772 | ||
|
|
99d9aeec98 | ||
|
|
44600fca45 | ||
|
|
9aaba5dfca | ||
|
|
0bd8efe800 | ||
|
|
3a29c94833 | ||
|
|
a22d99fefb | ||
|
|
c971d26d42 | ||
|
|
de380ff810 | ||
|
|
e7e2478468 | ||
|
|
42c80c2395 | ||
|
|
d22bbc3420 | ||
|
|
bdfb98265d | ||
|
|
af1908fb27 | ||
|
|
73a976c6fe | ||
|
|
2bcfc365f7 | ||
|
|
ecc7bf4081 | ||
|
|
68e4c32c1b | ||
|
|
a63f05b430 | ||
|
|
41c04fefa2 | ||
|
|
4a0e80ffdf |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1,3 +1,4 @@
|
|||||||
ctop
|
ctop
|
||||||
.idea
|
.idea
|
||||||
/vendor/
|
/vendor/
|
||||||
|
*.log
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
FROM quay.io/vektorcloud/go:1.13
|
FROM quay.io/vektorcloud/go:1.15
|
||||||
|
|
||||||
RUN apk add --no-cache make
|
RUN apk add --no-cache make
|
||||||
|
|
||||||
|
|||||||
6
Makefile
6
Makefile
@@ -29,10 +29,8 @@ image:
|
|||||||
|
|
||||||
release:
|
release:
|
||||||
mkdir release
|
mkdir release
|
||||||
go get github.com/progrium/gh-release/...
|
|
||||||
cp _build/* release
|
cp _build/* release
|
||||||
cd release; sha256sum --quiet --check sha256sums.txt
|
cd release; sha256sum --quiet --check sha256sums.txt && \
|
||||||
gh-release create bcicen/$(NAME) $(VERSION) \
|
gh release create $(VERSION) -d -t v$(VERSION) *
|
||||||
$(shell git rev-parse --abbrev-ref HEAD) $(VERSION)
|
|
||||||
|
|
||||||
.PHONY: build
|
.PHONY: build
|
||||||
|
|||||||
35
README.md
35
README.md
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#
|
#
|
||||||
|
|
||||||
![release][release] ![homebrew][homebrew]
|
![release][release] ![homebrew][homebrew] ![macports][macports]
|
||||||
|
|
||||||
Top-like interface for container metrics
|
Top-like interface for container metrics
|
||||||
|
|
||||||
@@ -17,10 +17,24 @@ as well as a [single container view][single_view] for inspecting a specific cont
|
|||||||
|
|
||||||
Fetch the [latest release](https://github.com/bcicen/ctop/releases) for your platform:
|
Fetch the [latest release](https://github.com/bcicen/ctop/releases) for your platform:
|
||||||
|
|
||||||
#### Linux
|
#### Debian/Ubuntu
|
||||||
|
|
||||||
|
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
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Arch
|
||||||
|
|
||||||
|
`ctop` is available for Arch in the [AUR](https://aur.archlinux.org/packages/ctop-bin/)
|
||||||
|
|
||||||
|
#### Linux (Generic)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo wget https://github.com/bcicen/ctop/releases/download/v0.7.4/ctop-0.7.4-linux-amd64 -O /usr/local/bin/ctop
|
sudo wget https://github.com/bcicen/ctop/releases/download/v0.7.6/ctop-0.7.6-linux-amd64 -O /usr/local/bin/ctop
|
||||||
sudo chmod +x /usr/local/bin/ctop
|
sudo chmod +x /usr/local/bin/ctop
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -31,7 +45,11 @@ brew install ctop
|
|||||||
```
|
```
|
||||||
or
|
or
|
||||||
```bash
|
```bash
|
||||||
sudo curl -Lo /usr/local/bin/ctop https://github.com/bcicen/ctop/releases/download/v0.7.4/ctop-0.7.4-darwin-amd64
|
sudo port install ctop
|
||||||
|
```
|
||||||
|
or
|
||||||
|
```bash
|
||||||
|
sudo curl -Lo /usr/local/bin/ctop https://github.com/bcicen/ctop/releases/download/v0.7.6/ctop-0.7.6-darwin-amd64
|
||||||
sudo chmod +x /usr/local/bin/ctop
|
sudo chmod +x /usr/local/bin/ctop
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -44,8 +62,6 @@ docker run --rm -ti \
|
|||||||
quay.io/vektorlab/ctop:latest
|
quay.io/vektorlab/ctop:latest
|
||||||
```
|
```
|
||||||
|
|
||||||
`ctop` is also available for Arch in the [AUR](https://aur.archlinux.org/packages/ctop-bin/)
|
|
||||||
|
|
||||||
## Building
|
## Building
|
||||||
|
|
||||||
Build steps can be found [here][build].
|
Build steps can be found [here][build].
|
||||||
@@ -70,9 +86,7 @@ Option | Description
|
|||||||
`-i` | invert default colors
|
`-i` | invert default colors
|
||||||
`-r` | reverse container sort order
|
`-r` | reverse container sort order
|
||||||
`-s` | select initial container sort field
|
`-s` | select initial container sort field
|
||||||
`-scale-cpu` | show cpu as % of system total
|
|
||||||
`-v` | output version information and exit
|
`-v` | output version information and exit
|
||||||
`-shell` | exec shell to use (default: sh)
|
|
||||||
|
|
||||||
### Keybindings
|
### Keybindings
|
||||||
|
|
||||||
@@ -97,3 +111,8 @@ Option | Description
|
|||||||
[single_view]: _docs/single.md
|
[single_view]: _docs/single.md
|
||||||
[release]: https://img.shields.io/github/release/bcicen/ctop.svg "ctop"
|
[release]: https://img.shields.io/github/release/bcicen/ctop.svg "ctop"
|
||||||
[homebrew]: https://img.shields.io/homebrew/v/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"
|
||||||
|
|
||||||
|
## 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`)
|
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:
|
||||||
|
|
||||||
|

|
||||||
|
|||||||
BIN
_docs/img/goland_debug.png
Normal file
BIN
_docs/img/goland_debug.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 143 KiB |
@@ -6,42 +6,67 @@ import (
|
|||||||
|
|
||||||
// defaults
|
// defaults
|
||||||
var defaultColumns = []Column{
|
var defaultColumns = []Column{
|
||||||
Column{
|
{
|
||||||
Name: "status",
|
Name: "status",
|
||||||
Label: "Status Indicator",
|
Label: "Status Indicator",
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
},
|
},
|
||||||
Column{
|
{
|
||||||
Name: "name",
|
Name: "name",
|
||||||
Label: "Container Name",
|
Label: "Container Name",
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
},
|
},
|
||||||
Column{
|
{
|
||||||
Name: "id",
|
Name: "id",
|
||||||
Label: "Container ID",
|
Label: "Container ID",
|
||||||
Enabled: true,
|
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",
|
Name: "cpu",
|
||||||
Label: "CPU Usage",
|
Label: "CPU Usage",
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
},
|
},
|
||||||
Column{
|
{
|
||||||
|
Name: "cpus",
|
||||||
|
Label: "CPU Usage (% of system total)",
|
||||||
|
Enabled: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
Name: "mem",
|
Name: "mem",
|
||||||
Label: "Memory Usage",
|
Label: "Memory Usage",
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
},
|
},
|
||||||
Column{
|
{
|
||||||
Name: "net",
|
Name: "net",
|
||||||
Label: "Network RX/TX",
|
Label: "Network RX/TX",
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
},
|
},
|
||||||
Column{
|
{
|
||||||
Name: "io",
|
Name: "io",
|
||||||
Label: "Disk IO Read/Write",
|
Label: "Disk IO Read/Write",
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
},
|
},
|
||||||
Column{
|
{
|
||||||
Name: "pids",
|
Name: "pids",
|
||||||
Label: "Container PID Count",
|
Label: "Container PID Count",
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package config
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@@ -66,7 +67,7 @@ func Read() error {
|
|||||||
for _, s := range strings.Split(colStr, ",") {
|
for _, s := range strings.Split(colStr, ",") {
|
||||||
s = strings.TrimSpace(s)
|
s = strings.TrimSpace(s)
|
||||||
if s != "" {
|
if s != "" {
|
||||||
colNames = append(colNames, strings.TrimSpace(s))
|
colNames = append(colNames, s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SetColumns(colNames)
|
SetColumns(colNames)
|
||||||
@@ -81,7 +82,7 @@ func Write() (path string, err error) {
|
|||||||
return path, err
|
return path, err
|
||||||
}
|
}
|
||||||
|
|
||||||
cfgdir := basedir(path)
|
cfgdir := filepath.Dir(path)
|
||||||
// create config dir if not exist
|
// create config dir if not exist
|
||||||
if _, err := os.Stat(cfgdir); err != nil {
|
if _, err := os.Stat(cfgdir); err != nil {
|
||||||
err = os.MkdirAll(cfgdir, 0755)
|
err = os.MkdirAll(cfgdir, 0755)
|
||||||
@@ -141,8 +142,3 @@ func xdgSupport() bool {
|
|||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func basedir(path string) string {
|
|
||||||
parts := strings.Split(path, "/")
|
|
||||||
return strings.Join((parts[0 : len(parts)-1]), "/")
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -12,11 +12,6 @@ var defaultParams = []*Param{
|
|||||||
Val: "state",
|
Val: "state",
|
||||||
Label: "Container Sort Field",
|
Label: "Container Sort Field",
|
||||||
},
|
},
|
||||||
&Param{
|
|
||||||
Key: "shell",
|
|
||||||
Val: "sh",
|
|
||||||
Label: "Shell",
|
|
||||||
},
|
|
||||||
&Param{
|
&Param{
|
||||||
Key: "columns",
|
Key: "columns",
|
||||||
Val: "status,name,id,cpu,mem,net,io,pids",
|
Val: "status,name,id,cpu,mem,net,io,pids",
|
||||||
|
|||||||
@@ -22,11 +22,6 @@ var defaultSwitches = []*Switch{
|
|||||||
Val: true,
|
Val: true,
|
||||||
Label: "Enable status header",
|
Label: "Enable status header",
|
||||||
},
|
},
|
||||||
&Switch{
|
|
||||||
Key: "scaleCpu",
|
|
||||||
Val: false,
|
|
||||||
Label: "Show CPU as %% of system total",
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type Switch struct {
|
type Switch struct {
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package collector
|
package collector
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/bcicen/ctop/config"
|
|
||||||
"github.com/bcicen/ctop/models"
|
"github.com/bcicen/ctop/models"
|
||||||
api "github.com/fsouza/go-dockerclient"
|
api "github.com/fsouza/go-dockerclient"
|
||||||
)
|
)
|
||||||
@@ -16,15 +15,13 @@ type Docker struct {
|
|||||||
done chan bool
|
done chan bool
|
||||||
lastCpu float64
|
lastCpu float64
|
||||||
lastSysCpu float64
|
lastSysCpu float64
|
||||||
scaleCpu bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDocker(client *api.Client, id string) *Docker {
|
func NewDocker(client *api.Client, id string) *Docker {
|
||||||
return &Docker{
|
return &Docker{
|
||||||
Metrics: models.Metrics{},
|
Metrics: models.Metrics{},
|
||||||
id: id,
|
id: id,
|
||||||
client: client,
|
client: client,
|
||||||
scaleCpu: config.GetSwitchVal("scaleCpu"),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,22 +71,20 @@ func (c *Docker) Logs() LogCollector {
|
|||||||
|
|
||||||
// Stop collector
|
// Stop collector
|
||||||
func (c *Docker) Stop() {
|
func (c *Docker) Stop() {
|
||||||
|
c.running = false
|
||||||
c.done <- true
|
c.done <- true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Docker) ReadCPU(stats *api.Stats) {
|
func (c *Docker) ReadCPU(stats *api.Stats) {
|
||||||
ncpus := float64(len(stats.CPUStats.CPUUsage.PercpuUsage))
|
ncpus := uint8(len(stats.CPUStats.CPUUsage.PercpuUsage))
|
||||||
total := float64(stats.CPUStats.CPUUsage.TotalUsage)
|
total := float64(stats.CPUStats.CPUUsage.TotalUsage)
|
||||||
system := float64(stats.CPUStats.SystemCPUUsage)
|
system := float64(stats.CPUStats.SystemCPUUsage)
|
||||||
|
|
||||||
cpudiff := total - c.lastCpu
|
cpudiff := total - c.lastCpu
|
||||||
syscpudiff := system - c.lastSysCpu
|
syscpudiff := system - c.lastSysCpu
|
||||||
|
|
||||||
if c.scaleCpu {
|
c.NCpus = ncpus
|
||||||
c.CPUUtil = round((cpudiff / syscpudiff * 100))
|
c.CPUUtil = percent(cpudiff, syscpudiff)
|
||||||
} else {
|
|
||||||
c.CPUUtil = round((cpudiff / syscpudiff * 100) * ncpus)
|
|
||||||
}
|
|
||||||
c.lastCpu = total
|
c.lastCpu = total
|
||||||
c.lastSysCpu = system
|
c.lastSysCpu = system
|
||||||
c.Pids = int(stats.PidsStats.Current)
|
c.Pids = int(stats.PidsStats.Current)
|
||||||
|
|||||||
@@ -47,9 +47,9 @@ func (l *DockerLogs) Stream() chan models.Log {
|
|||||||
go func() {
|
go func() {
|
||||||
scanner := bufio.NewScanner(r)
|
scanner := bufio.NewScanner(r)
|
||||||
for scanner.Scan() {
|
for scanner.Scan() {
|
||||||
parts := strings.Split(scanner.Text(), " ")
|
parts := strings.SplitN(scanner.Text(), " ", 2)
|
||||||
ts := l.parseTime(parts[0])
|
ts := l.parseTime(parts[0])
|
||||||
logCh <- models.Log{Timestamp: ts, Message: strings.Join(parts[1:], " ")}
|
logCh <- models.Log{Timestamp: ts, Message: parts[1]}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@@ -74,12 +74,12 @@ func (l *DockerLogs) Stream() chan models.Log {
|
|||||||
func (l *DockerLogs) Stop() { l.done <- true }
|
func (l *DockerLogs) Stop() { l.done <- true }
|
||||||
|
|
||||||
func (l *DockerLogs) parseTime(s string) time.Time {
|
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 {
|
if err == nil {
|
||||||
return ts
|
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 {
|
if err2 == nil {
|
||||||
return ts
|
return ts
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ func (c *Mock) Start() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Mock) Stop() {
|
func (c *Mock) Stop() {
|
||||||
|
c.running = false
|
||||||
c.done = true
|
c.done = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import (
|
|||||||
"github.com/opencontainers/runc/libcontainer/cgroups"
|
"github.com/opencontainers/runc/libcontainer/cgroups"
|
||||||
"github.com/opencontainers/runc/types"
|
"github.com/opencontainers/runc/types"
|
||||||
|
|
||||||
"github.com/bcicen/ctop/config"
|
|
||||||
"github.com/bcicen/ctop/models"
|
"github.com/bcicen/ctop/models"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -24,7 +23,6 @@ type Runc struct {
|
|||||||
interval int // collection interval, in seconds
|
interval int // collection interval, in seconds
|
||||||
lastCpu float64
|
lastCpu float64
|
||||||
lastSysCpu float64
|
lastSysCpu float64
|
||||||
scaleCpu bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewRunc(libc libcontainer.Container) *Runc {
|
func NewRunc(libc libcontainer.Container) *Runc {
|
||||||
@@ -33,7 +31,6 @@ func NewRunc(libc libcontainer.Container) *Runc {
|
|||||||
id: libc.ID(),
|
id: libc.ID(),
|
||||||
libc: libc,
|
libc: libc,
|
||||||
interval: 1,
|
interval: 1,
|
||||||
scaleCpu: config.GetSwitchVal("scaleCpu"),
|
|
||||||
}
|
}
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
@@ -49,6 +46,7 @@ func (c *Runc) Start() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Runc) Stop() {
|
func (c *Runc) Stop() {
|
||||||
|
c.running = false
|
||||||
c.done = true
|
c.done = true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,18 +86,15 @@ func (c *Runc) run() {
|
|||||||
|
|
||||||
func (c *Runc) ReadCPU(stats *cgroups.Stats) {
|
func (c *Runc) ReadCPU(stats *cgroups.Stats) {
|
||||||
u := stats.CpuStats.CpuUsage
|
u := stats.CpuStats.CpuUsage
|
||||||
ncpus := float64(len(u.PercpuUsage))
|
ncpus := uint8(len(u.PercpuUsage))
|
||||||
total := float64(u.TotalUsage)
|
total := float64(u.TotalUsage)
|
||||||
system := float64(getSysCPUUsage())
|
system := float64(getSysCPUUsage())
|
||||||
|
|
||||||
cpudiff := total - c.lastCpu
|
cpudiff := total - c.lastCpu
|
||||||
syscpudiff := system - c.lastSysCpu
|
syscpudiff := system - c.lastSysCpu
|
||||||
|
|
||||||
if c.scaleCpu {
|
c.NCpus = ncpus
|
||||||
c.CPUUtil = round((cpudiff / syscpudiff * 100))
|
c.CPUUtil = percent(cpudiff, syscpudiff)
|
||||||
} else {
|
|
||||||
c.CPUUtil = round((cpudiff / syscpudiff * 100) * ncpus)
|
|
||||||
}
|
|
||||||
c.lastCpu = total
|
c.lastCpu = total
|
||||||
c.lastSysCpu = system
|
c.lastSysCpu = system
|
||||||
c.Pids = int(stats.PidsStats.Current)
|
c.Pids = int(stats.PidsStats.Current)
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package connector
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/op/go-logging"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
@@ -13,10 +14,25 @@ import (
|
|||||||
|
|
||||||
func init() { enabled["docker"] = NewDocker }
|
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 {
|
type Docker struct {
|
||||||
client *api.Client
|
client *api.Client
|
||||||
containers map[string]*container.Container
|
containers map[string]*container.Container
|
||||||
needsRefresh chan string // container IDs requiring refresh
|
needsRefresh chan string // container IDs requiring refresh
|
||||||
|
statuses chan StatusUpdate
|
||||||
closed chan struct{}
|
closed chan struct{}
|
||||||
lock sync.RWMutex
|
lock sync.RWMutex
|
||||||
}
|
}
|
||||||
@@ -31,6 +47,7 @@ func NewDocker() (Connector, error) {
|
|||||||
client: client,
|
client: client,
|
||||||
containers: make(map[string]*container.Container),
|
containers: make(map[string]*container.Container),
|
||||||
needsRefresh: make(chan string, 60),
|
needsRefresh: make(chan string, 60),
|
||||||
|
statuses: make(chan StatusUpdate, 60),
|
||||||
closed: make(chan struct{}),
|
closed: make(chan struct{}),
|
||||||
lock: sync.RWMutex{},
|
lock: sync.RWMutex{},
|
||||||
}
|
}
|
||||||
@@ -48,6 +65,7 @@ func NewDocker() (Connector, error) {
|
|||||||
log.Debugf("docker-connector ServerVersion: %s", info.ServerVersion)
|
log.Debugf("docker-connector ServerVersion: %s", info.ServerVersion)
|
||||||
|
|
||||||
go cm.Loop()
|
go cm.Loop()
|
||||||
|
go cm.LoopStatuses()
|
||||||
cm.refreshAll()
|
cm.refreshAll()
|
||||||
go cm.watchEvents()
|
go cm.watchEvents()
|
||||||
return cm, nil
|
return cm, nil
|
||||||
@@ -67,15 +85,45 @@ func (cm *Docker) watchEvents() {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
actionName := strings.Split(e.Action, ":")[0]
|
actionName := e.Action
|
||||||
|
// fast skip all exec_* events: exec_create, exec_start, exec_die
|
||||||
|
if strings.HasPrefix(actionName, "exec_") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// Action may have additional param i.e. "health_status: healthy"
|
||||||
|
// We need to strip to have only action name
|
||||||
|
sepIdx := strings.Index(actionName, ": ")
|
||||||
|
if sepIdx != -1 {
|
||||||
|
actionName = actionName[:sepIdx]
|
||||||
|
}
|
||||||
|
|
||||||
switch actionName {
|
switch actionName {
|
||||||
case "start", "die", "pause", "unpause", "health_status":
|
// most frequent event is a health checks
|
||||||
log.Debugf("handling docker event: action=%s id=%s", e.Action, e.ID)
|
case "health_status":
|
||||||
|
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
|
cm.needsRefresh <- e.ID
|
||||||
case "destroy":
|
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)
|
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")
|
log.Info("docker event listener exited")
|
||||||
@@ -112,9 +160,12 @@ func ipsFormat(networks map[string]api.ContainerNetwork) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (cm *Docker) refresh(c *container.Container) {
|
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
|
// remove container if no longer exists
|
||||||
if insp == nil {
|
if !found {
|
||||||
cm.delByID(c.Id)
|
cm.delByID(c.Id)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -124,20 +175,21 @@ func (cm *Docker) refresh(c *container.Container) {
|
|||||||
c.SetMeta("ports", portsFormat(insp.NetworkSettings.Ports))
|
c.SetMeta("ports", portsFormat(insp.NetworkSettings.Ports))
|
||||||
c.SetMeta("created", insp.Created.Format("Mon Jan 2 15:04:05 2006"))
|
c.SetMeta("created", insp.Created.Format("Mon Jan 2 15:04:05 2006"))
|
||||||
c.SetMeta("health", insp.State.Health.Status)
|
c.SetMeta("health", insp.State.Health.Status)
|
||||||
for _, env := range insp.Config.Env {
|
c.SetMeta("[ENV-VAR]", strings.Join(insp.Config.Env, ";"))
|
||||||
c.SetMeta("[ENV-VAR]", env)
|
|
||||||
}
|
|
||||||
c.SetState(insp.State.Status)
|
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)
|
c, err := cm.client.InspectContainer(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if _, ok := err.(*api.NoSuchContainer); !ok {
|
if _, notFound := err.(*api.NoSuchContainer); notFound {
|
||||||
log.Errorf("%s (%T)", err.Error(), err)
|
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
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mark all container IDs for refresh
|
// Mark all container IDs for refresh
|
||||||
@@ -169,6 +221,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
|
// MustGet gets a single container, creating one anew if not existing
|
||||||
func (cm *Docker) MustGet(id string) *container.Container {
|
func (cm *Docker) MustGet(id string) *container.Container {
|
||||||
c, ok := cm.Get(id)
|
c, ok := cm.Get(id)
|
||||||
@@ -218,5 +288,5 @@ func (cm *Docker) All() (containers container.Containers) {
|
|||||||
|
|
||||||
// use primary container name
|
// use primary container name
|
||||||
func shortName(name string) string {
|
func shortName(name string) string {
|
||||||
return strings.Replace(name, "/", "", 1)
|
return strings.TrimPrefix(name, "/")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ func New(id string, collector collector.Collector, manager manager.Manager) *Con
|
|||||||
return &Container{
|
return &Container{
|
||||||
Metrics: models.NewMetrics(),
|
Metrics: models.NewMetrics(),
|
||||||
Id: id,
|
Id: id,
|
||||||
Meta: models.NewMeta("id", id),
|
Meta: models.NewMeta("id", id[:12]),
|
||||||
Widgets: widgets,
|
Widgets: widgets,
|
||||||
updater: widgets,
|
updater: widgets,
|
||||||
collector: collector,
|
collector: collector,
|
||||||
|
|||||||
@@ -9,14 +9,19 @@ import (
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
allCols = map[string]NewCompactColFn{
|
allCols = map[string]NewCompactColFn{
|
||||||
"status": NewStatus,
|
"status": NewStatus,
|
||||||
"name": NewNameCol,
|
"name": NewNameCol,
|
||||||
"id": NewCIDCol,
|
"id": NewCIDCol,
|
||||||
"cpu": NewCPUCol,
|
"image": NewImageCol,
|
||||||
"mem": NewMemCol,
|
"ports": NewPortsCol,
|
||||||
"net": NewNetCol,
|
"IPs": NewIpsCol,
|
||||||
"io": NewIOCol,
|
"created": NewCreatedCol,
|
||||||
"pids": NewPIDCol,
|
"cpu": NewCPUCol,
|
||||||
|
"cpus": NewCpuScaledCol,
|
||||||
|
"mem": NewMemCol,
|
||||||
|
"net": NewNetCol,
|
||||||
|
"io": NewIOCol,
|
||||||
|
"pids": NewPIDCol,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -11,15 +11,23 @@ import (
|
|||||||
|
|
||||||
type CPUCol struct {
|
type CPUCol struct {
|
||||||
*GaugeCol
|
*GaugeCol
|
||||||
|
scaleCpu bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewCPUCol() CompactCol {
|
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) {
|
func (w *CPUCol) SetMetrics(m models.Metrics) {
|
||||||
val := m.CPUUtil
|
val := m.CPUUtil
|
||||||
w.BarColor = colorScale(val)
|
w.BarColor = colorScale(val)
|
||||||
|
if !w.scaleCpu {
|
||||||
|
val = val * int(m.NCpus)
|
||||||
|
}
|
||||||
w.Label = fmt.Sprintf("%d%%", val)
|
w.Label = fmt.Sprintf("%d%%", val)
|
||||||
|
|
||||||
if val > 100 {
|
if val > 100 {
|
||||||
|
|||||||
@@ -9,35 +9,44 @@ import (
|
|||||||
ui "github.com/gizak/termui"
|
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
|
*TextCol
|
||||||
|
metaName string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *MetaCol) SetMeta(m models.Meta) {
|
||||||
|
w.setText(m.Get(w.metaName))
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewNameCol() CompactCol {
|
func NewNameCol() CompactCol {
|
||||||
return &NameCol{NewTextCol("NAME")}
|
c := &MetaCol{NewTextCol("NAME"), "name"}
|
||||||
}
|
c.fWidth = 30
|
||||||
|
return c
|
||||||
func (w *NameCol) SetMeta(m models.Meta) {
|
|
||||||
w.Text = m.Get("name")
|
|
||||||
// truncate container id
|
|
||||||
if len(w.Text) > 12 {
|
|
||||||
w.Text = w.Text[:12]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type CIDCol struct {
|
|
||||||
*TextCol
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewCIDCol() CompactCol {
|
func NewCIDCol() CompactCol {
|
||||||
return &CIDCol{NewTextCol("CID")}
|
c := &MetaCol{NewTextCol("CID"), "id"}
|
||||||
|
c.fWidth = 12
|
||||||
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *CIDCol) SetMeta(m models.Meta) {
|
func NewImageCol() CompactCol {
|
||||||
w.Text = m.Get("id")
|
return &MetaCol{NewTextCol("IMAGE"), "image"}
|
||||||
if len(w.Text) > 12 {
|
}
|
||||||
w.Text = w.Text[:12]
|
|
||||||
}
|
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 {
|
type NetCol struct {
|
||||||
@@ -50,7 +59,7 @@ func NewNetCol() CompactCol {
|
|||||||
|
|
||||||
func (w *NetCol) SetMetrics(m models.Metrics) {
|
func (w *NetCol) SetMetrics(m models.Metrics) {
|
||||||
label := fmt.Sprintf("%s / %s", cwidgets.ByteFormat64Short(m.NetRx), cwidgets.ByteFormat64Short(m.NetTx))
|
label := fmt.Sprintf("%s / %s", cwidgets.ByteFormat64Short(m.NetRx), cwidgets.ByteFormat64Short(m.NetTx))
|
||||||
w.Text = label
|
w.setText(label)
|
||||||
}
|
}
|
||||||
|
|
||||||
type IOCol struct {
|
type IOCol struct {
|
||||||
@@ -63,7 +72,7 @@ func NewIOCol() CompactCol {
|
|||||||
|
|
||||||
func (w *IOCol) SetMetrics(m models.Metrics) {
|
func (w *IOCol) SetMetrics(m models.Metrics) {
|
||||||
label := fmt.Sprintf("%s / %s", cwidgets.ByteFormat64Short(m.IOBytesRead), cwidgets.ByteFormat64Short(m.IOBytesWrite))
|
label := fmt.Sprintf("%s / %s", cwidgets.ByteFormat64Short(m.IOBytesRead), cwidgets.ByteFormat64Short(m.IOBytesWrite))
|
||||||
w.Text = label
|
w.setText(label)
|
||||||
}
|
}
|
||||||
|
|
||||||
type PIDCol struct {
|
type PIDCol struct {
|
||||||
@@ -77,7 +86,7 @@ func NewPIDCol() CompactCol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (w *PIDCol) SetMetrics(m models.Metrics) {
|
func (w *PIDCol) SetMetrics(m models.Metrics) {
|
||||||
w.Text = fmt.Sprintf("%d", m.Pids)
|
w.setText(fmt.Sprintf("%d", m.Pids))
|
||||||
}
|
}
|
||||||
|
|
||||||
type TextCol struct {
|
type TextCol struct {
|
||||||
@@ -91,7 +100,12 @@ func NewTextCol(header string) *TextCol {
|
|||||||
p.Border = false
|
p.Border = false
|
||||||
p.Height = 1
|
p.Height = 1
|
||||||
p.Width = 20
|
p.Width = 20
|
||||||
return &TextCol{p, header, 0}
|
|
||||||
|
return &TextCol{
|
||||||
|
Par: p,
|
||||||
|
header: header,
|
||||||
|
fWidth: 0,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *TextCol) Highlight() {
|
func (w *TextCol) Highlight() {
|
||||||
@@ -106,8 +120,16 @@ func (w *TextCol) UnHighlight() {
|
|||||||
w.TextBgColor = ui.ThemeAttr("par.text.bg")
|
w.TextBgColor = ui.ThemeAttr("par.text.bg")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *TextCol) Reset() { w.Text = "-" }
|
// TextCol implements CompactCol
|
||||||
|
func (w *TextCol) Reset() { w.setText("-") }
|
||||||
func (w *TextCol) SetMeta(models.Meta) {}
|
func (w *TextCol) SetMeta(models.Meta) {}
|
||||||
func (w *TextCol) SetMetrics(models.Metrics) {}
|
func (w *TextCol) SetMetrics(models.Metrics) {}
|
||||||
func (w *TextCol) Header() string { return w.header }
|
func (w *TextCol) Header() string { return w.header }
|
||||||
func (w *TextCol) FixedWidth() int { return w.fWidth }
|
func (w *TextCol) FixedWidth() int { return w.fWidth }
|
||||||
|
|
||||||
|
func (w *TextCol) setText(s string) {
|
||||||
|
if w.fWidth > 0 && len(s) > w.fWidth {
|
||||||
|
s = s[0:w.fWidth]
|
||||||
|
}
|
||||||
|
w.Text = s
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package single
|
|||||||
import (
|
import (
|
||||||
ui "github.com/gizak/termui"
|
ui "github.com/gizak/termui"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
var envPattern = regexp.MustCompile(`(?P<KEY>[^=]+)=(?P<VALUJE>.*)`)
|
var envPattern = regexp.MustCompile(`(?P<KEY>[^=]+)=(?P<VALUJE>.*)`)
|
||||||
@@ -23,14 +24,16 @@ func NewEnv() *Env {
|
|||||||
return i
|
return i
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Env) Set(k, v string) {
|
func (w *Env) Set(allEnvs string) {
|
||||||
match := envPattern.FindStringSubmatch(v)
|
envs := strings.Split(allEnvs, ";")
|
||||||
key := match[1]
|
|
||||||
value := match[2]
|
|
||||||
w.data[key] = value
|
|
||||||
|
|
||||||
w.Rows = [][]string{}
|
w.Rows = [][]string{}
|
||||||
w.Rows = append(w.Rows, mkInfoRows(key, value)...)
|
for _, env := range envs {
|
||||||
|
match := envPattern.FindStringSubmatch(env)
|
||||||
|
key := match[1]
|
||||||
|
value := match[2]
|
||||||
|
w.data[key] = value
|
||||||
|
w.Rows = append(w.Rows, mkInfoRows(key, value)...)
|
||||||
|
}
|
||||||
|
|
||||||
w.Height = len(w.Rows) + 2
|
w.Height = len(w.Rows) + 2
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,14 +13,13 @@ type Info struct {
|
|||||||
data map[string]string
|
data map[string]string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewInfo(id string) *Info {
|
func NewInfo() *Info {
|
||||||
p := ui.NewTable()
|
p := ui.NewTable()
|
||||||
p.Height = 4
|
p.Height = 4
|
||||||
p.Width = colWidth[0]
|
p.Width = colWidth[0]
|
||||||
p.FgColor = ui.ThemeAttr("par.text.fg")
|
p.FgColor = ui.ThemeAttr("par.text.fg")
|
||||||
p.Separator = false
|
p.Separator = false
|
||||||
i := &Info{p, make(map[string]string)}
|
i := &Info{p, make(map[string]string)}
|
||||||
i.Set("id", id)
|
|
||||||
return i
|
return i
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,12 +23,9 @@ type Single struct {
|
|||||||
Width int
|
Width int
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSingle(id string) *Single {
|
func NewSingle() *Single {
|
||||||
if len(id) > 12 {
|
|
||||||
id = id[:12]
|
|
||||||
}
|
|
||||||
return &Single{
|
return &Single{
|
||||||
Info: NewInfo(id),
|
Info: NewInfo(),
|
||||||
Net: NewNet(),
|
Net: NewNet(),
|
||||||
Cpu: NewCpu(),
|
Cpu: NewCpu(),
|
||||||
Mem: NewMem(),
|
Mem: NewMem(),
|
||||||
@@ -58,7 +55,7 @@ func (e *Single) SetWidth(w int) { e.Width = w }
|
|||||||
func (e *Single) SetMeta(m models.Meta) {
|
func (e *Single) SetMeta(m models.Meta) {
|
||||||
for k, v := range m {
|
for k, v := range m {
|
||||||
if k == "[ENV-VAR]" {
|
if k == "[ENV-VAR]" {
|
||||||
e.Env.Set(k, v)
|
e.Env.Set(v)
|
||||||
} else {
|
} else {
|
||||||
e.Info.Set(k, v)
|
e.Info.Set(k, v)
|
||||||
}
|
}
|
||||||
|
|||||||
4
debug.go
4
debug.go
@@ -12,6 +12,10 @@ import (
|
|||||||
var mstats = &runtime.MemStats{}
|
var mstats = &runtime.MemStats{}
|
||||||
|
|
||||||
func logEvent(e ui.Event) {
|
func logEvent(e ui.Event) {
|
||||||
|
// skip timer events e.g. /timer/1s
|
||||||
|
if e.From == "timer" {
|
||||||
|
return
|
||||||
|
}
|
||||||
var s string
|
var s string
|
||||||
s += fmt.Sprintf("Type=%s", quote(e.Type))
|
s += fmt.Sprintf("Type=%s", quote(e.Type))
|
||||||
s += fmt.Sprintf(" Path=%s", quote(e.Path))
|
s += fmt.Sprintf(" Path=%s", quote(e.Path))
|
||||||
|
|||||||
41
go.sum
41
go.sum
@@ -1,4 +1,6 @@
|
|||||||
|
bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898 h1:SC+c6A1qTFstO9qmB86mPV2IpYme/2ZoEQ0hrP+wo+Q=
|
||||||
bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8=
|
bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8=
|
||||||
|
cloud.google.com/go v0.26.0 h1:e0WKqKTd5BnrG8aKH3J3h+QvEIQtSUcf2n5UZ5ZgLtQ=
|
||||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||||
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8=
|
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8=
|
||||||
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
|
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
|
||||||
@@ -13,13 +15,17 @@ github.com/bcicen/termui v0.0.0-20180326052246-4eb80249d3f5 h1:2pI3ZsoefWIi++8Eq
|
|||||||
github.com/bcicen/termui v0.0.0-20180326052246-4eb80249d3f5/go.mod h1:yIA9ITWZD1p4/DvCQ44xvhyVb9XEUlVnY1rzGSHwbiM=
|
github.com/bcicen/termui v0.0.0-20180326052246-4eb80249d3f5/go.mod h1:yIA9ITWZD1p4/DvCQ44xvhyVb9XEUlVnY1rzGSHwbiM=
|
||||||
github.com/c9s/goprocinfo v0.0.0-20170609001544-b34328d6e0cd h1:xqaBnULC8wEnQpRDXAsDgXkU/STqoluz1REOoegSfNU=
|
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/c9s/goprocinfo v0.0.0-20170609001544-b34328d6e0cd/go.mod h1:uEyr4WpAH4hio6LFriaPkL938XnrvLpNPmQHBdrmbIE=
|
||||||
|
github.com/census-instrumentation/opencensus-proto v0.2.1 h1:glEXhBS5PSLLv4IXzLA5yPRVX4bilULVyxxbrfOtDAk=
|
||||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
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 h1:WW2B2uxx9KWF6bGlHqhm8Okiafwwx7Y2kcpn8lCpjgo=
|
||||||
github.com/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw=
|
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 h1:cHzBGGVew0ezFsq2grfy2RsB8hO/eNyBgOLHBCqfR1U=
|
||||||
github.com/cilium/ebpf v0.0.0-20200702112145-1c8d4c9ef775/go.mod h1:7cR51M8ViRLIdUjrmSXlK9pkrsDlLHbO8jiB8X8JnOc=
|
github.com/cilium/ebpf v0.0.0-20200702112145-1c8d4c9ef775/go.mod h1:7cR51M8ViRLIdUjrmSXlK9pkrsDlLHbO8jiB8X8JnOc=
|
||||||
|
github.com/client9/misspell v0.3.4 h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJI=
|
||||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||||
|
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f h1:WBZRG4aNOuI15bLRrCgN8fCq8E5Xuty6jGbmSNEvSsU=
|
||||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
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 h1:tSNMc+rJDfmYntojat8lljbt1mgKNpTxUZJsSzJ9Y1s=
|
||||||
github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko=
|
github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko=
|
||||||
github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw=
|
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 h1:fU3UuQapBs+zLJu82NhR11Rif1ny2zfMMAyPJzSN5tQ=
|
||||||
@@ -30,9 +36,13 @@ github.com/containerd/containerd v1.3.4/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMX
|
|||||||
github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
|
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 h1:nXPkFq8X1a9ycY3GYQpFNxHh3j2JgY7zDZfq2EXMIzk=
|
||||||
github.com/containerd/continuity v0.0.0-20200413184840-d3ef23f19fbb/go.mod h1:Dq467ZllaHgAtVp4p1xUQWBrFXR9s/wyoTpG8zOJGkY=
|
github.com/containerd/continuity v0.0.0-20200413184840-d3ef23f19fbb/go.mod h1:Dq467ZllaHgAtVp4p1xUQWBrFXR9s/wyoTpG8zOJGkY=
|
||||||
|
github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448 h1:PUD50EuOMkXVcpBIA/R95d56duJR9VxhwncsFbNnxW4=
|
||||||
github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI=
|
github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI=
|
||||||
|
github.com/containerd/go-runc v0.0.0-20180907222934-5a6d9f37cfa3 h1:esQOJREg8nw8aXj6uCN5dfW5cKUBiEJ/+nni1Q/D/sw=
|
||||||
github.com/containerd/go-runc v0.0.0-20180907222934-5a6d9f37cfa3/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0=
|
github.com/containerd/go-runc v0.0.0-20180907222934-5a6d9f37cfa3/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0=
|
||||||
|
github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de h1:dlfGmNcE3jDAecLqwKPMNX6nk2qh1c1Vg1/YTzpOOF4=
|
||||||
github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o=
|
github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o=
|
||||||
|
github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd h1:JNn81o/xG+8NEo3bC/vx9pbi/g2WI8mtP2/nXzu297Y=
|
||||||
github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc=
|
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 h1:Wf6HqHfScWJN9/ZjdUKyjop4mf3Qdd+1TvvltAvM3m8=
|
||||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||||
@@ -55,10 +65,14 @@ github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKoh
|
|||||||
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
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 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw=
|
||||||
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||||
|
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4 h1:qk/FSDDxo05wdJH28W+p5yivv7LuLYLRXPPD8KQCtZs=
|
||||||
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
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.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||||
|
github.com/envoyproxy/go-control-plane v0.9.4 h1:rEvIZUSZ3fx39WIi3JkQqQBitGwpELBIYWeBVh6wn+E=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||||
|
github.com/envoyproxy/protoc-gen-validate v0.1.0 h1:EQciDnbrYxy13PgWoY8AqoxGiPrpgBZ1R8UNe3ddc+A=
|
||||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||||
|
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
|
||||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
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 h1:9e3xkBrVkPb81gzYq23i7iDUEd6sx2ooeJA/gnYU6R4=
|
||||||
github.com/fsouza/go-dockerclient v1.6.6/go.mod h1:3/oRIWoe7uT6bwtAayj/EmJmepBjeL4pYvt7ZxC7Rnk=
|
github.com/fsouza/go-dockerclient v1.6.6/go.mod h1:3/oRIWoe7uT6bwtAayj/EmJmepBjeL4pYvt7ZxC7Rnk=
|
||||||
@@ -70,7 +84,9 @@ 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/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||||
github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls=
|
github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls=
|
||||||
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
|
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
|
||||||
|
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
|
||||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||||
|
github.com/golang/mock v1.1.1 h1:G5FRp8JnTd7RQH5kemVNlMeyXQAztQ3mOWV95KxsXH8=
|
||||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
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.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
@@ -91,20 +107,27 @@ 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.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 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.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
|
||||||
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
||||||
|
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/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||||
|
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
|
||||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||||
|
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
||||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
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 h1:/hc+TxW4Q1v6aqNPHE5jiaNF2xEK0CzWTgo25RQhQ+U=
|
||||||
github.com/jgautheron/codename-generator v0.0.0-20150829203204-16d037c7cc3c/go.mod h1:FJRkXmPrkHw0WDjB/LXMUhjWJ112Y6JUYnIVBOy8oH8=
|
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.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||||
|
github.com/kisielk/errcheck v1.2.0 h1:reN85Pxc5larApoH1keMBiu2GWtPqXQ1nc9gx+jOU+E=
|
||||||
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
|
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
|
||||||
|
github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg=
|
||||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
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.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.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3/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 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
|
github.com/kr/pty v1.1.1 h1:VkoXIwSboBpnk99O/KFauAEILuNHv5DVFKZMBN/gUgw=
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
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 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
@@ -128,7 +151,9 @@ github.com/nsf/termbox-go v0.0.0-20180303152453-e2050e41c884/go.mod h1:IuKpRQcYE
|
|||||||
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d h1:VhgPp6v9qf9Agr/56bj7Y/xa04UccTW04VP0Qed4vnQ=
|
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/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.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
|
github.com/onsi/ginkgo v1.10.1 h1:q/mM8GF/n0shIN8SaAZ0V+jnLPzen6WIVZdiwrRlMlo=
|
||||||
github.com/onsi/ginkgo v1.10.1/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 h1:XPnZz8VVBHjVsy1vzJmRwIcSwiUO+JFfrv/xGiigmME=
|
||||||
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
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 h1:J1QZwDXgZ4dJD2s19iqR9+U00OWM2kDzbf1O/fmvCWg=
|
||||||
github.com/op/go-logging v0.0.0-20160211212156-b2cb9fa56473/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
|
github.com/op/go-logging v0.0.0-20160211212156-b2cb9fa56473/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
|
||||||
@@ -152,7 +177,9 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
|||||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
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 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4 h1:gQz4mCbXsO+nc9n1hCxHcGA3Zx3Eo+UHZoInFGUIXNM=
|
||||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
|
github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7 h1:hhvfGDVThBnd4kYisSFmYuHYeUhglxcwag7FhVPH9zM=
|
||||||
github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
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 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
|
||||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
@@ -165,10 +192,13 @@ github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMB
|
|||||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
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 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I=
|
||||||
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
||||||
|
github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee h1:GQkkv3XSnxhAMjdq2wLfEnptEVr+2BNvmHizILHn+d4=
|
||||||
github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
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.1-0.20171106142849-4c012f6dcd95/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||||
|
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
|
||||||
github.com/spf13/pflag v1.0.3/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.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=
|
||||||
github.com/stretchr/objx v0.1.1/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 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
|
||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
@@ -185,15 +215,18 @@ github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df h1:OviZH7qLw/7Zo
|
|||||||
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
|
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 h1:R43TdZy32XXSXjJn7M/HhALJ9imq6ztLnChfYJpVDnM=
|
||||||
github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
|
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=
|
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-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 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
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 h1:IaQbIIB2X/Mp/DKctl6ROxz1KyMlKp4uyvL6+kQ7C88=
|
||||||
golang.org/x/crypto v0.0.0-20200429183012-4b2356b1ed79/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200429183012-4b2356b1ed79/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4 h1:c2HOrn5iMezYjSlGPncknSEr/8x5LELb/ilJbXi9DEA=
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
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-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||||
|
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3 h1:XQyxROzUlZH+WIQwySDgnISgOivlhjIEwaQaJEJrrN0=
|
||||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
@@ -204,6 +237,7 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
|
|||||||
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/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 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-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be h1:vEDujvNQGv4jgYKudGeI/+DAX4Jffq6hpD55MmoEvKs=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
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-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
@@ -237,10 +271,12 @@ golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGm
|
|||||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
|
golang.org/x/tools v0.0.0-20190624222133-a101b041ded4 h1:1mMox4TgefDwqluYCv677yNXwlfTkija4owZve/jr78=
|
||||||
golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||||
|
google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508=
|
||||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
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-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||||
@@ -261,12 +297,16 @@ google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miE
|
|||||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
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 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM=
|
||||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||||
|
gopkg.in/airbrake/gobrake.v2 v2.0.9 h1:7z2uVWwn7oVeeugY1DtlPAy5H+KYgB1KeKTnqjNatLo=
|
||||||
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
|
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
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 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
|
||||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||||
|
gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2 h1:OAj3g0cR6Dx/R07QgQe8wkA9RNjB2u4i700xBkIT4e0=
|
||||||
gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo=
|
gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo=
|
||||||
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
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.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.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
@@ -277,4 +317,5 @@ gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81
|
|||||||
gotest.tools/v3 v3.0.2 h1:kG1BFyqVHuQoVQiR1bWGnfz/fmHvvuiSPIV7rvl360E=
|
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.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
|
||||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc h1:/hemPrYIhOhy8zYrNj+069zDB68us2sMGsfkFJO0iZs=
|
||||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
|||||||
2
grid.go
2
grid.go
@@ -83,7 +83,7 @@ func SingleView() MenuFn {
|
|||||||
ui.DefaultEvtStream.ResetHandlers()
|
ui.DefaultEvtStream.ResetHandlers()
|
||||||
defer ui.DefaultEvtStream.ResetHandlers()
|
defer ui.DefaultEvtStream.ResetHandlers()
|
||||||
|
|
||||||
ex := single.NewSingle(c.Id)
|
ex := single.NewSingle()
|
||||||
c.SetUpdater(ex)
|
c.SetUpdater(ex)
|
||||||
|
|
||||||
ex.Align()
|
ex.Align()
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ type statusMsg struct {
|
|||||||
type CTopLogger struct {
|
type CTopLogger struct {
|
||||||
*logging.Logger
|
*logging.Logger
|
||||||
backend *logging.MemoryBackend
|
backend *logging.MemoryBackend
|
||||||
|
logFile *os.File
|
||||||
sLog []statusMsg
|
sLog []statusMsg
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,18 +59,37 @@ func Init() *CTopLogger {
|
|||||||
Log = &CTopLogger{
|
Log = &CTopLogger{
|
||||||
logging.MustGetLogger("ctop"),
|
logging.MustGetLogger("ctop"),
|
||||||
logging.NewMemoryBackend(size),
|
logging.NewMemoryBackend(size),
|
||||||
|
nil,
|
||||||
[]statusMsg{},
|
[]statusMsg{},
|
||||||
}
|
}
|
||||||
|
|
||||||
if debugMode() {
|
debugMode := debugMode()
|
||||||
|
if debugMode {
|
||||||
level = logging.DEBUG
|
level = logging.DEBUG
|
||||||
StartServer()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
backendLvl := logging.AddModuleLevel(Log.backend)
|
backendLvl := logging.AddModuleLevel(Log.backend)
|
||||||
backendLvl.SetLevel(level, "")
|
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")
|
Log.Notice("logger initialized")
|
||||||
}
|
}
|
||||||
return Log
|
return Log
|
||||||
@@ -102,8 +122,12 @@ func (log *CTopLogger) tail() chan string {
|
|||||||
|
|
||||||
func (log *CTopLogger) Exit() {
|
func (log *CTopLogger) Exit() {
|
||||||
exited = true
|
exited = true
|
||||||
|
if log.logFile != nil {
|
||||||
|
_ = log.logFile.Close()
|
||||||
|
}
|
||||||
StopServer()
|
StopServer()
|
||||||
}
|
}
|
||||||
|
|
||||||
func debugMode() bool { return os.Getenv("CTOP_DEBUG") == "1" }
|
func debugMode() bool { return os.Getenv("CTOP_DEBUG") == "1" }
|
||||||
func debugModeTCP() bool { return os.Getenv("CTOP_DEBUG_TCP") == "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")
|
sortFieldFlag = flag.String("s", "", "select container sort field")
|
||||||
reverseSortFlag = flag.Bool("r", false, "reverse container sort order")
|
reverseSortFlag = flag.Bool("r", false, "reverse container sort order")
|
||||||
invertFlag = flag.Bool("i", false, "invert default colors")
|
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")
|
connectorFlag = flag.String("connector", "docker", "container connector to use")
|
||||||
defaultShell = flag.String("shell", "sh", "exec shell to use")
|
|
||||||
)
|
)
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
@@ -87,14 +85,6 @@ func main() {
|
|||||||
config.Toggle("sortReversed")
|
config.Toggle("sortReversed")
|
||||||
}
|
}
|
||||||
|
|
||||||
if *scaleCpu {
|
|
||||||
config.Toggle("scaleCpu")
|
|
||||||
}
|
|
||||||
|
|
||||||
if *defaultShell != "" {
|
|
||||||
config.Update("shell", *defaultShell)
|
|
||||||
}
|
|
||||||
|
|
||||||
// init ui
|
// init ui
|
||||||
if *invertFlag {
|
if *invertFlag {
|
||||||
InvertColorMap()
|
InvertColorMap()
|
||||||
|
|||||||
19
menus.go
19
menus.go
@@ -130,7 +130,7 @@ func ColumnsMenu() MenuFn {
|
|||||||
m.Selectable = true
|
m.Selectable = true
|
||||||
m.SortItems = false
|
m.SortItems = false
|
||||||
m.BorderLabel = "Columns"
|
m.BorderLabel = "Columns"
|
||||||
//m.SubText = "Enabled Columns"
|
m.SubText = "Re-order: <Page Up> / <Page Down>"
|
||||||
|
|
||||||
rebuild := func() {
|
rebuild := func() {
|
||||||
// get padding for right alignment of enabled status
|
// get padding for right alignment of enabled status
|
||||||
@@ -258,7 +258,7 @@ func ContainerMenu() MenuFn {
|
|||||||
ui.StopLoop()
|
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) {
|
ui.Handle("/sys/kbd/p", func(ui.Event) {
|
||||||
if c.Meta["state"] == "paused" {
|
if c.Meta["state"] == "paused" {
|
||||||
selected = "unpause"
|
selected = "unpause"
|
||||||
@@ -358,10 +358,17 @@ func ExecShell() MenuFn {
|
|||||||
|
|
||||||
ui.DefaultEvtStream.ResetHandlers()
|
ui.DefaultEvtStream.ResetHandlers()
|
||||||
defer ui.DefaultEvtStream.ResetHandlers()
|
defer ui.DefaultEvtStream.ResetHandlers()
|
||||||
|
// Detect and execute default shell in container.
|
||||||
shell := config.Get("shell")
|
// Execute Ash shell command: /bin/sh -c
|
||||||
if err := c.Exec([]string{shell.Val, "-c", "printf '\\e[0m\\e[?25h' && clear && " + shell.Val}); err != nil {
|
// Reset colors: printf '\e[0m\e[?25h'
|
||||||
log.Fatal(err)
|
// 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
|
return nil
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ func (m Meta) Get(k string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Metrics struct {
|
type Metrics struct {
|
||||||
|
NCpus uint8
|
||||||
CPUUtil int
|
CPUUtil int
|
||||||
NetTx int64
|
NetTx int64
|
||||||
NetRx int64
|
NetRx int64
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package widgets
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
ui "github.com/gizak/termui"
|
ui "github.com/gizak/termui"
|
||||||
|
"github.com/mattn/go-runewidth"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ToggleText interface {
|
type ToggleText interface {
|
||||||
@@ -70,7 +71,7 @@ func (t *TextView) Buffer() ui.Buffer {
|
|||||||
for _, ch := range line {
|
for _, ch := range line {
|
||||||
cell = ui.Cell{Ch: ch, Fg: t.TextFgColor, Bg: t.TextBgColor}
|
cell = ui.Cell{Ch: ch, Fg: t.TextFgColor, Bg: t.TextBgColor}
|
||||||
buf.Set(x, y, cell)
|
buf.Set(x, y, cell)
|
||||||
x++
|
x = x + runewidth.RuneWidth(ch)
|
||||||
}
|
}
|
||||||
x = t.Block.X + t.padding[0]
|
x = t.Block.X + t.padding[0]
|
||||||
y++
|
y++
|
||||||
|
|||||||
Reference in New Issue
Block a user