Compare commits

...

107 Commits

Author SHA1 Message Date
bradley 59f00dd6aa
Merge pull request #296 from utix/patch-1
Fix running icon
2022-08-01 06:32:57 -05:00
bradley 06265407b2
Merge pull request #306 from jnishwanth/patch-1
updated README.md
2022-08-01 06:24:33 -05:00
bradley a08150ea9c
Merge pull request #303 from wdiazux/master
Fix apt-key is deprecated
2022-08-01 06:23:25 -05:00
Alex Stelmachonak 6bf41ea05f
Add Windows-specific intructions and badge for scoop (#295) 2022-08-01 07:21:06 -04:00
Jeya Nishwanth 3dff9970ad
updated README.md
`ctop` has been added to the arch community repository. Hence can be installed without the AUR now!
2022-06-12 03:07:41 +05:30
William Diaz 458ef62f80 Required packages to set up the repository 2022-05-21 23:06:07 -06:00
William Diaz a821deb3b4 Fix apt-key is deprecated 2022-05-21 22:48:46 -06:00
Aurélien Lajoie dacd3be920
Fix running icon
Use ▶ for running status
2022-04-26 19:10:52 +02:00
Bradley Cicenas 222a7d77b2 Squashed commit of the following:
commit 9968c504a5
Author: Florian Vahl <florian@flova.de>
Date:   Tue Feb 1 00:37:31 2022 +0100

    Fix formating (Spaces -> Tabs)

commit 6b8840647e
Author: Florian <florian@flova.de>
Date:   Tue Feb 1 00:27:44 2022 +0100

    Use better duration formating

commit 815dc6ec84
Author: Florian <florian@flova.de>
Date:   Tue Feb 1 00:27:04 2022 +0100

    Fix date formating in 'created' col

commit 05b17798f8
Author: Florian <florian@flova.de>
Date:   Tue Feb 1 00:26:08 2022 +0100

    Add fix from #275 for uptime of running containers
2022-03-30 14:13:10 -04:00
Bradley Cicenas 9bc26c8296 update dockerfile base image -> go1.18 2022-03-24 08:14:39 -04:00
Bradley Cicenas 5271cf6d90
update go.mod go1.17 -> go1.18 2022-03-24 11:53:43 +00:00
Bradley Cicenas a8e1fb7246
update circleci image to go1.18 2022-03-23 17:50:10 +00:00
Bradley Cicenas d60b215611
go mod tidy 2022-03-23 17:47:39 +00:00
Bradley Cicenas 79242c7de5 update go.mod 1.15 -> 1.17 2022-03-23 13:47:16 -04:00
Bradley Cicenas 6dcb62f172 remove termui fork dependency 2022-03-23 13:46:53 -04:00
DasSkelett 163060b3fa
Update runc to 1.1.0 to get newer x/sys and fix Go 1.18 build (#292)
* Update runc to 1.1.0 to get newer x/sys

...to fix building on Darwin with Go 1.18.

This required some code changes as opencontainers unfortunately introduced breaking changes in a minor revision.
However, those changes were to simpify the libcontainer factory initialization.

* Switch CircleCI image to cimg/go, update remote Docker version to 20.10
2022-03-23 13:46:40 -04:00
Bradley Cicenas acbf17a4fd
prevent index out of range panic on empty value env strings 2022-03-23 17:06:47 +00:00
Bradley Cicenas 021b1710a3
update readme 2022-03-22 13:45:12 +00:00
Bradley Cicenas 2d43cd146f
update readme version 2022-03-22 12:51:01 +00:00
Bradley Cicenas 11a1cb10f4
v0.7.7 2022-03-22 12:00:27 +00:00
Bradley Cicenas f83e73d1ea Merge branch 'dependabot/go_modules/github.com/opencontainers/runc-1.0.3' 2022-01-06 17:13:56 -05:00
Bradley Cicenas 1f91033beb Merge branch 'master' into dependabot/go_modules/github.com/opencontainers/runc-1.0.3 2022-01-06 17:13:20 -05:00
Bradley Cicenas da09b95d29
prevent panic on container IDs < 12 chars 2022-01-06 22:12:35 +00:00
Florian Vahl 350cb09338
Fix cpu count estimation (#281)
* Fix query for the number of cpu cores.

* Fix formating

* Fix formating again...
2021-12-29 11:56:22 -05:00
dependabot[bot] d8542c894c
Bump github.com/opencontainers/runc from 1.0.0-rc95 to 1.0.3
Bumps [github.com/opencontainers/runc](https://github.com/opencontainers/runc) from 1.0.0-rc95 to 1.0.3.
- [Release notes](https://github.com/opencontainers/runc/releases)
- [Commits](https://github.com/opencontainers/runc/compare/v1.0.0-rc95...v1.0.3)

---
updated-dependencies:
- dependency-name: github.com/opencontainers/runc
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-12-08 01:45:57 +00:00
Bradley Cicenas be23d85eda Merge remote-tracking branch 'stokito/browser' 2021-10-24 10:40:43 -04:00
bradley 2047e3fa52
Merge pull request #272 from bcicen/dependabot/go_modules/github.com/opencontainers/runc-1.0.0-rc95
Bump github.com/opencontainers/runc from 1.0.0-rc93 to 1.0.0-rc95
2021-10-24 10:35:37 -04:00
dependabot[bot] 4b653e71f6
Bump github.com/opencontainers/runc from 1.0.0-rc93 to 1.0.0-rc95
Bumps [github.com/opencontainers/runc](https://github.com/opencontainers/runc) from 1.0.0-rc93 to 1.0.0-rc95.
- [Release notes](https://github.com/opencontainers/runc/releases)
- [Commits](https://github.com/opencontainers/runc/compare/v1.0.0-rc93...v1.0.0-rc95)

---
updated-dependencies:
- dependency-name: github.com/opencontainers/runc
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-07-27 17:42:05 +00:00
Bradley Cicenas c145cf404a
match release tag to title 2021-07-01 19:32:32 +00:00
bradley 52f52a1163
Merge pull request #268 from neikei/patch-1
Added support for ppc64le
2021-06-13 10:25:11 -04:00
bradley 94f1f3f558
Merge pull request #269 from Quintenps/master
Update README.md (Fixed release download url)
2021-06-13 10:23:07 -04:00
Quinten Peels 3d5a1c0682
Update README.md
Fixed release download url in readme
2021-06-13 16:07:58 +02:00
neikei 1c3577ad4e
Added support for ppc64le 2021-06-13 15:12:27 +02:00
Bradley Cicenas b48a5cf2f9
go mod tidy 2021-06-11 18:07:31 +00:00
Bradley Cicenas 9f8f38f9d7 Merge remote-tracking branch 'remotes/stokito/events_filter' 2021-06-11 14:04:53 -04:00
bradley 2b898fb216
Merge pull request #267 from frol-kr/bugfix/issue-254-crushes-when-container-logs-opened
#254-handling-with-wrong-log-format
2021-06-11 13:46:42 -04:00
Frol Kryuchkov 99be3b979e #254-handling-with-wrong-log-format 2021-06-11 17:22:34 +03:00
bradley 29f9abf35c
Merge pull request #236 from stokito/status_unicode
Use more clear status marks
2021-06-10 22:06:40 -04:00
bradley 82e731e577
Merge pull request #239 from stokito/cpu_color
CPU upper: > 70% yellow/warn and > 90% is red/danger
2021-06-10 22:04:54 -04:00
Bradley Cicenas a603c1b58c Merge remote-tracking branch 'remotes/stokito/uptime' 2021-06-10 22:01:45 -04:00
Bradley Cicenas 8f0c9f5048
v0.7.6 2021-06-11 01:23:43 +00:00
bradley 15708224a7
Merge pull request #262 from judaew/patch-1
Add install variant via MacPorts
2021-06-10 21:19:16 -04:00
bradley 442e70b8df
Merge pull request #264 from garsue/use-runewidth-to-increment-textview-x
Use go-runewidth to increment x in TextView
2021-06-10 21:18:33 -04:00
garsue c58a609349 Update go.sum 2021-05-29 22:01:26 +09:00
garsue 78b038e687 Use runewidth to increment x in TextView 2021-05-29 19:48:02 +09:00
Vadim-Valdis Yudaev 2d937aca08 Add install variant via MacPorts 2021-05-20 17:09:14 +03:00
Sergey Ponomarev 77c9001ed1 optimize health_status event handling 2021-02-04 09:37:44 +02:00
Sergey Ponomarev d98ce102b1 Filter events 2021-02-04 09:22:57 +02:00
Sergey Ponomarev cfa43f809e Update go-dockerclient and opencontainers/runc
The go-dockerclient v1.7.0 now has an ability to specify events filter. But it's dependencies are also updated.
One of those dependencies is mountinfo and the same dependency is used by opencontainers/runc.
The problem is that mountinfo changed it's API and if we just update dockerclient then build is broken.
So we have to update both opencontainers/runc and go-dockerclient
2021-02-04 08:59:06 +02:00
bradley 0094cba5ea
Merge pull request #244 from stokito/fix_243
#243 Fix bug: show ENV variables
2020-12-14 12:29:25 -05:00
bradley 537bb2adfa
Merge pull request #247 from stokito/more_columns
More columns
2020-12-14 12:25:17 -05:00
Sergey Ponomarev 8dce3ece2b Open in browser: show menu item only if web port is published 2020-12-12 21:50:08 +02:00
Sergey Ponomarev dd92e85d45 Open in browser
Most containers expose some http port. We can open it in browser.
For simplicity we can just open first container's published port.
We'll determine the ip:port on container creation and store to meta "Web Port".
To open browser on any platform was added a new dependency github.com/pkg/browser which is very small
2020-12-12 21:21:53 +02:00
Sergey Ponomarev 491cd85b4d Additional columns 2020-12-11 21:58:37 +02:00
Sergey Ponomarev 9545dfba31 Extract MetaCol 2020-12-11 20:59:35 +02:00
Sergey Ponomarev cdcb8b6d99 columns.go: remove redundant type 2020-12-11 20:32:22 +02:00
bradley b562c923b3
Merge pull request #242 from stokito/awesome
Add Alternatives section
2020-12-09 16:10:09 -05:00
Sergey Ponomarev f2c28c5fb0 #243 Fix bug: show ENV variables
Previously only last env variable is shown
2020-12-09 23:06:14 +02:00
Sergey Ponomarev ac76b2eac1 Add Alternatives section
This may help users to find more specific tool than ctop
2020-11-30 17:25:40 +02:00
bradley b32f90fa4a
Merge pull request #240 from stokito/name_width
#128 Set column Name to fixed width 30
2020-11-29 09:19:07 -05:00
bradley bec78c90b5
Merge pull request #238 from stokito/leftovers
Use standard Go functions
2020-11-29 09:06:13 -05:00
Bradley Cicenas 043f4bd3f3
update dockerfile to go 1.15 2020-11-28 20:30:02 +00:00
Sergey Ponomarev c2401cb33a #128 Set column Name to fixed width 30 2020-11-27 23:12:16 +02:00
Sergey Ponomarev fa254c652c Columns settings: add hint for re-order columns 2020-11-27 22:34:55 +02:00
Sergey Ponomarev a59c7aab3c Fix: enable pause [p] only for running or paused container 2020-11-27 22:28:58 +02:00
Sergey Ponomarev 4e44c9d5f7 file.go use filepath.Dir() 2020-11-26 12:08:55 +02:00
Sergey Ponomarev 948e7cc9d0 docker_logs.go use SplitN(2) 2020-11-26 12:08:36 +02:00
Sergey Ponomarev 4850f817f3 status.go: use more clear status marks 2020-11-25 22:29:10 +02:00
Sergey Ponomarev 10c49018a6 status.go: make logic more explicit 2020-11-25 22:21:19 +02:00
Sergey Ponomarev 6c662d91fb docker.go shortName() use TrimPrefix() 2020-11-25 19:17:07 +02:00
Sergey Ponomarev b4a63f8c60 docker_logs.go: use time.RFC3339Nano constant 2020-11-24 22:19:29 +02:00
Sergey Ponomarev 4973bc83ff cpu color: make threshold upper: > 70% warn and > 90% is danger 2020-11-24 00:51:09 +02:00
Bradley Cicenas 87d135909f rename cpus column 2020-11-23 17:48:56 -05:00
Sergey Ponomarev 7632420ecc cpu color: check lower values first
this is simpler to understand and faster for usual containers
2020-11-24 00:22:25 +02:00
Sergey Ponomarev 4fbc998a41 status.go: simplify Buffer()
s.health and s.status are always have only one element with a single char length
2020-11-23 15:23:07 +02:00
bradley 117c3bc7b5
Merge pull request #234 from stokito/refresh
docker connector: refresh() delete container only if it not found but keep on failures
2020-11-22 19:00:31 -05:00
bradley b1171f6c3e
Merge pull request #235 from stokito/cpu_scale
#207 Replace scaleCpu option with dedicated column CPU Scaled
2020-11-21 12:19:43 -05:00
Sergey Ponomarev 9a41252764 #207 CPU unscaled column changes color according to system total usage
If container uses two cores then CPU column will be always red even if we have dozens of other free cores and CPUS is 1%
2020-11-20 23:24:13 +02:00
Sergey Ponomarev f377dcaee2 #207 Replace scaleCpu option with dedicated column CPU Scaled
The new column is disabled by default.
2020-11-20 23:08:19 +02:00
Sergey Ponomarev 65e9c6dff6 docker connector: refresh() delete container only if it not found but keep on failures
If inspect() call was failed due to connection problems then container will be removed anyway as like ot wasn't found.
This is probably almost never happens in real life but still some missed logic bug
2020-11-20 19:44:09 +02:00
Sergey Ponomarev df0d8b7892 #187 "created" action is handled separately in watchEvents() 2020-11-20 19:26:02 +02:00
bradley 2792e72d18
Merge pull request #233 from stokito/exec_shell
Exec shell config
2020-11-20 11:22:59 -05:00
bradley 68d6da5c61
Merge pull request #231 from stokito/log_file
Log to file
2020-11-20 08:30:13 -05:00
Sergey Ponomarev 53a6b36bf5 exec shell: detect default shell
Instead of using configured shell (e.g. bash) we can autodetect default container user's shell and execute it.
This is much safer because not all containers may have installed shell that is configured in ctop.
2020-11-20 10:42:52 +02:00
Sergey Ponomarev 5ec02f760e exec shell: remove shell config or option
The option is never worked and can't properly work because almost all containers anyway using Ash/Dash from /bin/sh
2020-11-20 10:39:28 +02:00
Sergey Ponomarev 83a422933a exec shell: on error show a status message instead of fatal exit 2020-11-20 10:33:44 +02:00
Sergey Ponomarev 7679d4a7fd exec shell: fix shell config
Currently each time when ctop started it overwrites "shell" config with default value of program argument.
This means that in fact default shell config is never worked at all.
2020-11-20 10:31:00 +02:00
Sergey Ponomarev e34afceb5f logging: log to file
New env var CTOP_DEBUG_FILE to specify a path to log file
2020-11-19 20:11:46 +02:00
bradley ddfff03c05
Merge pull request #229 from stokito/events
Improve docker events handling
2020-11-19 11:27:09 -05:00
Sergey Ponomarev 29d90cfdd9 logging: start server after log is configured
Without this "logging server started" is written to stderr
2020-11-19 11:21:27 +02:00
Sergey Ponomarev ba126e6e7c events handling: early skipping of extremely frequent exec_* events
The exec_create, exec_start, exec_die and other events are generated by health checks
2020-11-18 23:04:29 +02:00
Sergey Ponomarev 009201ed0c actionToStatus: catch more generic die instead of kill 2020-11-18 23:04:29 +02:00
Sergey Ponomarev 2c07cab59c logging: skip timer events e.g. /timer/1s
Each second we receive the timer event which makes little sense but log is bloated with the event.
To make logs more readable we can disable logging of this event
2020-11-18 23:04:29 +02:00
bradley fd06992236
Merge pull request #230 from stokito/skip_timer_logging
logging: skip timer events e.g. /timer/1s
2020-11-18 09:40:33 -05:00
Sergey Ponomarev e64edbdc36 logging: skip timer events e.g. /timer/1s
Each second we receive the timer event which makes little sense but log is bloated with the event.
To make logs more readable we can disable logging of this event
2020-11-18 11:25:20 +02:00
Sergey Ponomarev 4c280cee56 Improve docker events handling: separate channel for status updates
Instead of calling a heavy inspect api call we can easily changing status just by knowing an action.
Let's do this in a separate channel decouple UI update from basic event loop.
2020-11-17 22:00:03 +02:00
Sergey Ponomarev b65e970a83 Improve docker events handling
Firstly check health updates because it will be a lot of them especially when a container is unstable.
Clearly handle create event to create a container even if it wasn't started.
Instead of die event handle more precise events like oom, kill and only then trigger refresh.
Lookup the state from a map.
2020-11-17 21:50:25 +02:00
Sergey Ponomarev 957cabba2d docker.go: watchEvents() optimize actionName extraction
Split(e.Action, ":") creates and array but we can avoid this.
2020-11-17 12:06:34 +02:00
Sergey Ponomarev 5aacdc3772 docker.go: logging of events
Add log.IsEnabledFor(logging.DEBUG) guard to avoid unnecessary memory allocations. Debug level is usually disabled.
Inline "destroy"
2020-11-17 11:42:45 +02:00
Bradley Cicenas 99d9aeec98
set running = false when mock,runc collectors stopped 2020-11-13 21:43:11 +00:00
bradley 44600fca45
Merge pull request #201 from vcmkrtchyan/master
Fix freeze when container is started/stopped multiple times
2020-11-13 16:42:16 -05:00
bradley 9aaba5dfca
Merge pull request #223 from stokito/trim
file.go: remove duplicated trim
2020-11-13 15:40:01 -05:00
Bradley Cicenas 0bd8efe800
fix makefile release 2020-11-13 20:35:40 +00:00
Sergey Ponomarev 3a29c94833 Use percent() function to calc CPU usage 2020-11-13 11:02:14 +02:00
Sergey Ponomarev a22d99fefb file.go: remove duplicated trim
The s var was already trimmed on line 67
2020-11-12 21:23:18 +02:00
Sergey Ponomarev c984b270db #135 Add uptime column 2020-10-26 16:32:51 +02:00
Vahe Mkrtchyan 4a0e80ffdf Fix freeze when container is started/stopped multiple times 2020-07-23 15:23:19 +04:00
39 changed files with 619 additions and 342 deletions

View File

@ -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

3
.gitignore vendored
View File

@ -1,3 +1,4 @@
ctop
.idea
/vendor/
/vendor/
*.log

View File

@ -1,4 +1,4 @@
FROM quay.io/vektorcloud/go:1.13
FROM quay.io/vektorcloud/go:1.18
RUN apk add --no-cache make

View File

@ -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

View File

@ -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.

View File

@ -1 +1 @@
0.7.5
0.7.7

View File

@ -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)

BIN
_docs/img/goland_debug.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 143 KiB

View File

@ -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 {

View File

@ -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]), "/")
}

View File

@ -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",
},
}

View File

@ -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 {

View File

@ -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)

View File

@ -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
}

View File

@ -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
}

View File

@ -1,3 +1,4 @@
//go:build linux
// +build linux
package collector

View File

@ -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)

View File

@ -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, "/")
}

View File

@ -1,3 +1,4 @@
//go:build !release
// +build !release
package connector

View File

@ -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)
}

View File

@ -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,

View File

@ -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) {

View File

@ -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,
}
)

View File

@ -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")
}

View File

@ -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)
}

View File

@ -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

View File

@ -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
}

View File

@ -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
}

View File

@ -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

View File

@ -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)
}

View File

@ -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
View File

@ -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
View File

@ -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=

View File

@ -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()

View File

@ -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
View File

@ -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()

View File

@ -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 {

View File

@ -31,6 +31,7 @@ func (m Meta) Get(k string) string {
}
type Metrics struct {
NCpus uint8
CPUUtil int
NetTx int64
NetRx int64

View File

@ -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++