Compare commits
123 Commits
Author | SHA1 | Date |
---|---|---|
|
66fc1cc64f | |
|
04b6c47895 | |
|
fe095fd4b3 | |
|
a2eb9b4823 | |
|
d6ba7488b2 | |
|
58b4fbdc03 | |
|
7f9559b3ac | |
|
9ed811d204 | |
|
31dce751c8 | |
|
6e59fa69eb | |
|
cd74eeb550 | |
|
5e89744b23 | |
|
196004fe46 | |
|
b7e0b93adb | |
|
e3242f37c7 | |
|
897f8ddae1 | |
|
92b9653353 | |
|
a89d6d6ef0 | |
|
6cb9178d24 | |
|
5fc3515715 | |
|
5a9541f97f | |
|
785b690989 | |
|
5ab12464fb | |
|
0b65653d80 | |
|
6294d7d1ee | |
|
136c5f75df | |
|
b02ec6036f | |
|
ef10f184b1 | |
|
3eabf12196 | |
|
7f02a36e85 | |
|
164ca27d7f | |
|
2a7c6195b4 | |
|
70fd604f0f | |
|
c9527473cf | |
|
42293a3a71 | |
|
f902cdff07 | |
|
cd904893fc | |
|
eee4f642fa | |
|
6392f961a4 | |
|
fb76d52ae9 | |
|
05bdbdea9a | |
|
0c1dfb8b00 | |
|
ff9a2eeb41 | |
|
def31691ba | |
|
04b7a6151b | |
|
0f4d9385e6 | |
|
5424f11115 | |
|
ffda1a0afa | |
|
0a975ecdf8 | |
|
2326d5fc63 | |
|
4ffa4b95d9 | |
|
49b2994ff8 | |
|
b1464afd8c | |
|
cc8608c200 | |
|
4a10ca867d | |
|
8eb63a6d2b | |
|
1be2154e2b | |
|
9b2bb83815 | |
|
4c73f653d8 | |
|
0a04e82ebe | |
|
8999d0e2b7 | |
|
347ab777b4 | |
|
6c62f33576 | |
|
4049d7adaa | |
|
fe94712e4a | |
|
d62c79f787 | |
|
441fe2edec | |
|
66e7fff1a6 | |
|
f06e2ef927 | |
|
5302f66806 | |
|
e15d76a796 | |
|
a92cec5e42 | |
|
43fbc57357 | |
|
9be037d3c8 | |
|
53a43f86e6 | |
|
7bfc237682 | |
|
9312e8decd | |
|
5022beffa7 | |
|
0aeb2e552c | |
|
242982a2b1 | |
|
34a7797dd7 | |
|
cfd827afff | |
|
02ada9374d | |
|
bce001c25d | |
|
eed5fd9092 | |
|
84cc728081 | |
|
9e6388aac3 | |
|
47b1d1f37a | |
|
56a12860b9 | |
|
fc019f08d2 | |
|
177f06c46a | |
|
204d054c97 | |
|
d88a67af73 | |
|
59a9904e83 | |
|
8a850c7d04 | |
|
abb902f171 | |
|
b41b05a79c | |
|
8460ac4527 | |
|
db872518ff | |
|
3eebbbef0b | |
|
dee6b15b4e | |
|
44e38ae256 | |
|
87d8ab1552 | |
|
610cf9fcb6 | |
|
aa8a47710e | |
|
8d2bf0a874 | |
|
7c30fa9d32 | |
|
9a57aeb763 | |
|
a07daf871e | |
|
c7273f6649 | |
|
5314673185 | |
|
f13c817218 | |
|
958a2a447e | |
|
761e48fb43 | |
|
af4b22fa6a | |
|
edc139c27d | |
|
d8f0ffb364 | |
|
870cae0a60 | |
|
086842a209 | |
|
676ff6b10f | |
|
f1f1ff11f8 | |
|
679aa134e6 | |
|
0e8ff20e37 |
|
@ -9,7 +9,7 @@ jobs:
|
|||
steps:
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '>=1.22'
|
||||
go-version: '>=1.23'
|
||||
- uses: actions/checkout@v4
|
||||
- run: |
|
||||
go mod tidy
|
||||
|
@ -24,7 +24,7 @@ jobs:
|
|||
steps:
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '1.22'
|
||||
go-version: '1.23'
|
||||
- uses: actions/checkout@v4
|
||||
- run: |
|
||||
bash hack/install_dep.sh
|
||||
|
@ -59,7 +59,7 @@ jobs:
|
|||
steps:
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '>=1.22'
|
||||
go-version: '>=1.23'
|
||||
- uses: actions/checkout@v4
|
||||
- run: |
|
||||
make all
|
||||
|
|
|
@ -45,7 +45,7 @@ jobs:
|
|||
steps:
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '>=1.22'
|
||||
go-version: '>=1.23'
|
||||
- uses: actions/checkout@v4
|
||||
- run: |
|
||||
go mod tidy
|
||||
|
@ -60,7 +60,7 @@ jobs:
|
|||
steps:
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '1.22'
|
||||
go-version: '1.23'
|
||||
- uses: actions/checkout@v4
|
||||
- run: |
|
||||
bash hack/install_dep.sh
|
||||
|
@ -86,7 +86,7 @@ jobs:
|
|||
steps:
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '>=1.22'
|
||||
go-version: '>=1.23'
|
||||
- uses: actions/checkout@v4
|
||||
- run: |
|
||||
make all
|
||||
|
|
|
@ -9,16 +9,15 @@ linters:
|
|||
- varnamelen
|
||||
- gochecknoinits
|
||||
- wrapcheck
|
||||
- execinquery
|
||||
- funlen
|
||||
- depguard
|
||||
- nolintlint
|
||||
# generics disabled
|
||||
- wastedassign
|
||||
- rowserrcheck
|
||||
# deprecated
|
||||
- gomnd
|
||||
- gomoddirectives
|
||||
- exportloopref
|
||||
- tenv
|
||||
linters-settings:
|
||||
# typecheck:
|
||||
# enabled: false
|
||||
|
|
21
.packit.yaml
21
.packit.yaml
|
@ -12,15 +12,18 @@ jobs:
|
|||
- openssl-devel
|
||||
- rpkg
|
||||
targets:
|
||||
- fedora-latest-stable
|
||||
- fedora-development
|
||||
# Disabled until there is go 1.22.6 in centos stream
|
||||
#- epel-9-x86_64
|
||||
#- epel-9-aarch64
|
||||
#- centos-stream-9-x86_64
|
||||
#- centos-stream-9-aarch64
|
||||
#- centos-stream-10-x86_64
|
||||
#- centos-stream-10-aarch64
|
||||
- fedora-all-x86_64
|
||||
- fedora-all-aarch64
|
||||
- epel-9-x86_64
|
||||
- epel-9-aarch64
|
||||
# temporary disabled since epel10 running go v1.23.1 and we need 1.23.3
|
||||
# - epel-10-x86_64
|
||||
# - epel-10-aarch64
|
||||
- centos-stream-9-x86_64
|
||||
- centos-stream-9-aarch64
|
||||
# - centos-stream-10-x86_64
|
||||
# - centos-stream-10-aarch64
|
||||
|
||||
actions:
|
||||
post-upstream-clone:
|
||||
- "rpkg spec --outdir ./"
|
||||
|
|
2
Makefile
2
Makefile
|
@ -88,7 +88,7 @@ install.tools: .install.ginkgo .install.bats .install.pre-commit .install.codesp
|
|||
|
||||
.PHONY: .install.golangci-lint
|
||||
.install.golangci-lint:
|
||||
VERSION=1.61.0 ./hack/install_golangci.sh
|
||||
VERSION=1.64.4 ./hack/install_golangci.sh
|
||||
|
||||
.PHONY: .install.codespell
|
||||
.install.codespell:
|
||||
|
|
66
README.md
66
README.md
|
@ -1,66 +0,0 @@
|
|||
## podman-tui
|
||||
|
||||

|
||||

|
||||

|
||||
[](https://goreportcard.com/report/github.com/containers/podman-tui)
|
||||
[](https://codecov.io/gh/navidys/podman-tui)
|
||||
|
||||
Terminal user interface for Podman environment.
|
||||
|
||||

|
||||
|
||||
- [**Overview**](#overview)
|
||||
- [**Compatibility Matrix**](#compatibility-matrix)
|
||||
- [**Installation**](#installation)
|
||||
- [**PreRun Checks**](#prerun-checks)
|
||||
- [**Key Bindings**](#key-bindings)
|
||||
- [**Code of Conduct**](#code-of-conduct)
|
||||
- [**License**](#license)
|
||||
|
||||
## Overview
|
||||
|
||||
podman-tui is a terminal user interface for podman environment.
|
||||
It is using [podman go bindings](https://github.com/containers/podman/tree/main/pkg/bindings) to communicate with local or remote podman machine (through SSH).
|
||||
|
||||
## Compatibility matrix
|
||||
|
||||
| Terminal User Interface | Podman |
|
||||
| ----------- | ------ |
|
||||
| release-1.x | v5.x.y |
|
||||
| release-0.x | v4.x.y |
|
||||
|
||||
## Installation
|
||||
|
||||
Building from source (Linux, Windows and MacOS) or installing packaged versions are detailed in [install guide](install.md).
|
||||
|
||||
## PreRun Checks
|
||||
|
||||
* `podman.socket` service needs to be running on podman machine.
|
||||
The recommended way to start Podman system service in production mode is via systemd socket-activation:
|
||||
|
||||
```shell
|
||||
$ systemctl --user start podman.socket
|
||||
```
|
||||
|
||||
See [start podman system service](https://podman.io/blogs/2020/08/10/podman-go-bindings.html) for more details.
|
||||
|
||||
* If the SSH key has a passphrase, then you need to set and export `CONTAINER_PASSPHRASE=<password>` variable.
|
||||
```shell
|
||||
$ export CONTAINER_PASSPHRASE=keypass
|
||||
```
|
||||
|
||||
* podman-tui uses 256 colors terminal mode on `Nix` system and standard ANSI colors on `Windows` system (use "command prompt" application).
|
||||
|
||||
|
||||
## Key Bindings
|
||||
|
||||
Check [podman-tui docs](./docs/README.md) for keyboard mappings.
|
||||
|
||||
## Code of Conduct
|
||||
|
||||
This project is using the [Containers Community Code of Conduct](https://github.com/containers/common/blob/main/CODE-OF-CONDUCT.md)
|
||||
|
||||
## License
|
||||
|
||||
Licensed under the [Apache 2.0](LICENSE) license.
|
|
@ -1,9 +1,9 @@
|
|||
VAGRANTFILE_API_VERSION = "2"
|
||||
|
||||
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
|
||||
config.vm.hostname = "fedora40"
|
||||
config.vm.box = "fedora/40-cloud-base"
|
||||
config.vm.box_version = "40.20240414.0"
|
||||
config.vm.hostname = "fedora41"
|
||||
config.vm.box = "fedora/41-cloud-base"
|
||||
config.vm.box_version = "41-20241024.0"
|
||||
|
||||
config.vm.provision "shell", inline: "mkdir -p /home/vagrant/go"
|
||||
config.vm.synced_folder ".", "/home/vagrant/go/src/podman-tui",
|
||||
|
|
43
app/app.go
43
app/app.go
|
@ -39,7 +39,7 @@ type App struct {
|
|||
currentPage string
|
||||
needInitUI bool
|
||||
fastRefreshChan chan bool
|
||||
config *config.Config
|
||||
config config.Config
|
||||
}
|
||||
|
||||
// NewApp returns new app.
|
||||
|
@ -73,10 +73,10 @@ func NewApp(name string, version string) *App {
|
|||
app.secrets = secrets.NewSecrets()
|
||||
app.system = system.NewSystem()
|
||||
|
||||
app.system.SetConnectionListFunc(app.config.ServicesConnections)
|
||||
app.system.SetConnectionListFunc(app.config.RemoteConnections)
|
||||
app.system.SetConnectionSetDefaultFunc(func(name string) error {
|
||||
err := app.config.SetDefaultService(name)
|
||||
app.system.UpdateConnectionsData()
|
||||
err := app.config.SetDefaultConnection(name)
|
||||
app.system.UpdateData()
|
||||
|
||||
return err
|
||||
})
|
||||
|
@ -85,6 +85,10 @@ func NewApp(name string, version string) *App {
|
|||
app.system.SetConnectionDisconnectFunc(app.health.Disconnect)
|
||||
app.system.SetConnectionAddFunc(app.config.Add)
|
||||
app.system.SetConnectionRemoveFunc(app.config.Remove)
|
||||
app.system.SetAppFocusHandler(func() {
|
||||
app.Application.SetFocus(app.system)
|
||||
app.fastRefreshChan <- true
|
||||
})
|
||||
|
||||
app.help = help.NewHelp(name, version)
|
||||
|
||||
|
@ -96,6 +100,37 @@ func NewApp(name string, version string) *App {
|
|||
// its required for image build dialog.
|
||||
app.images.SetFastRefreshChannel(app.fastRefreshChan)
|
||||
|
||||
// set app set focus
|
||||
app.containers.SetAppFocusHandler(func() {
|
||||
app.Application.SetFocus(app.containers)
|
||||
app.fastRefreshChan <- true
|
||||
})
|
||||
|
||||
app.pods.SetAppFocusHandler(func() {
|
||||
app.Application.SetFocus(app.pods)
|
||||
app.fastRefreshChan <- true
|
||||
})
|
||||
|
||||
app.images.SetAppFocusHandler(func() {
|
||||
app.Application.SetFocus(app.images)
|
||||
app.fastRefreshChan <- true
|
||||
})
|
||||
|
||||
app.volumes.SetAppFocusHandler(func() {
|
||||
app.Application.SetFocus(app.volumes)
|
||||
app.fastRefreshChan <- true
|
||||
})
|
||||
|
||||
app.networks.SetAppFocusHandler(func() {
|
||||
app.Application.SetFocus(app.networks)
|
||||
app.fastRefreshChan <- true
|
||||
})
|
||||
|
||||
app.secrets.SetAppFocusHandler(func() {
|
||||
app.Application.SetFocus(app.secrets)
|
||||
app.fastRefreshChan <- true
|
||||
})
|
||||
|
||||
// menu items
|
||||
menuItems := [][]string{
|
||||
{utils.HelpScreenKey.Label(), app.help.GetTitle()},
|
||||
|
|
|
@ -13,7 +13,7 @@ func (app *App) initUI() {
|
|||
app.initInfoBar()
|
||||
}
|
||||
|
||||
app.system.UpdateConnectionsData()
|
||||
app.system.UpdateData()
|
||||
}
|
||||
|
||||
func (app *App) initInfoBar() {
|
||||
|
|
|
@ -71,7 +71,7 @@ func (app *App) refreshNotConnOK() {
|
|||
app.switchToScreen(app.system.GetTitle())
|
||||
}
|
||||
|
||||
app.system.UpdateConnectionsData()
|
||||
app.system.UpdateData()
|
||||
|
||||
app.needInitUI = true
|
||||
}
|
||||
|
|
|
@ -114,7 +114,7 @@ func (app *App) updatePageData(page string) {
|
|||
|
||||
switch page {
|
||||
case app.system.GetTitle():
|
||||
app.system.UpdateConnectionsData()
|
||||
app.system.UpdateData()
|
||||
case app.pods.GetTitle():
|
||||
app.pods.UpdateData()
|
||||
case app.containers.GetTitle():
|
||||
|
|
|
@ -7,7 +7,7 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
appVersion = "1.3.0"
|
||||
appVersion = "1.7.0-dev"
|
||||
)
|
||||
|
||||
// versionCmd represents the version command.
|
||||
|
|
133
config/add.go
133
config/add.go
|
@ -1,133 +0,0 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"net/url"
|
||||
"os"
|
||||
"regexp"
|
||||
|
||||
"github.com/containers/podman-tui/ui/utils"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
// Add adds new service connection.
|
||||
func (c *Config) Add(name string, uri string, identity string) error {
|
||||
log.Debug().Msgf("config: adding new service %s %s %s", name, uri, identity)
|
||||
|
||||
newService, err := validateNewService(name, uri, identity)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := c.add(name, newService); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := c.Write(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return c.reload()
|
||||
}
|
||||
|
||||
func (c *Config) add(name string, newService Service) error {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
for serviceName := range c.Services {
|
||||
if serviceName == name {
|
||||
return ErrDuplicatedServiceName
|
||||
}
|
||||
}
|
||||
|
||||
c.Services[name] = newService
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// most of codes are from:
|
||||
// https://github.com/containers/podman/blob/main/cmd/podman/system/connection/add.go.
|
||||
func validateNewService(name string, dest string, identity string) (Service, error) { //nolint:cyclop
|
||||
var (
|
||||
service Service
|
||||
serviceIdentity string
|
||||
)
|
||||
|
||||
if name == "" {
|
||||
return service, ErrEmptyServiceName
|
||||
}
|
||||
|
||||
if dest == "" {
|
||||
return service, ErrEmptyURIDestination
|
||||
}
|
||||
|
||||
if match, err := regexp.Match("^[A-Za-z][A-Za-z0-9+.-]*://", []byte(dest)); err != nil { //nolint:mirror
|
||||
return service, fmt.Errorf("%w invalid destition", err)
|
||||
} else if !match {
|
||||
dest = "ssh://" + dest
|
||||
}
|
||||
|
||||
uri, err := url.Parse(dest)
|
||||
if err != nil {
|
||||
return service, err
|
||||
}
|
||||
|
||||
switch uri.Scheme {
|
||||
case "ssh":
|
||||
if uri.User.Username() == "" {
|
||||
if uri.User, err = getUserInfo(uri); err != nil {
|
||||
return service, err
|
||||
}
|
||||
}
|
||||
|
||||
serviceIdentity, err = utils.ResolveHomeDir(identity)
|
||||
if err != nil {
|
||||
return service, err
|
||||
}
|
||||
|
||||
if identity == "" {
|
||||
return service, ErrEmptySSHIdentity
|
||||
}
|
||||
|
||||
if uri.Port() == "" {
|
||||
uri.Host = net.JoinHostPort(uri.Hostname(), "22")
|
||||
}
|
||||
|
||||
if uri.Path == "" || uri.Path == "/" {
|
||||
if uri.Path, err = getUDS(uri, serviceIdentity); err != nil {
|
||||
return service, err
|
||||
}
|
||||
}
|
||||
case "unix":
|
||||
if identity != "" {
|
||||
return service, fmt.Errorf("%w identity", ErrInvalidUnixSchemaOption)
|
||||
}
|
||||
|
||||
info, err := os.Stat(uri.Path)
|
||||
|
||||
switch {
|
||||
case errors.Is(err, os.ErrNotExist):
|
||||
log.Warn().Msgf("config: %q does not exists", uri.Path)
|
||||
case errors.Is(err, os.ErrPermission):
|
||||
log.Warn().Msgf("config: You do not have permission to read %q", uri.Path)
|
||||
case err != nil:
|
||||
return service, err
|
||||
case info.Mode()&os.ModeSocket == 0:
|
||||
return service, fmt.Errorf("%w %q", ErrFileNotUnixSocket, uri.Path)
|
||||
}
|
||||
case "tcp":
|
||||
if identity != "" {
|
||||
return service, fmt.Errorf("%w identity", ErrInvalidTCPSchemaOption)
|
||||
}
|
||||
default:
|
||||
return service, fmt.Errorf("%w %q", ErrInvalidURISchemaName, uri.Scheme)
|
||||
}
|
||||
|
||||
service.Identity = serviceIdentity
|
||||
service.URI = uri.String()
|
||||
service.Default = false
|
||||
|
||||
return service, nil
|
||||
}
|
123
config/config.go
123
config/config.go
|
@ -1,124 +1,43 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"sort"
|
||||
"sync"
|
||||
|
||||
"github.com/containers/podman-tui/config/pconfig"
|
||||
"github.com/containers/podman-tui/config/tconfig"
|
||||
"github.com/containers/podman-tui/pdcs/registry"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
const (
|
||||
// _configPath is the path to the podman-tui/podman-tui.conf
|
||||
// inside a given config directory.
|
||||
_configPath = "podman-tui/podman-tui.conf"
|
||||
// UserAppConfig holds the user podman-tui config path.
|
||||
UserAppConfig = ".config/" + _configPath
|
||||
)
|
||||
|
||||
var (
|
||||
ErrRemotePodmanUDSReport = errors.New("remote podman failed to report its UDS socket")
|
||||
ErrInvalidURISchemaName = errors.New("invalid schema name")
|
||||
ErrInvalidTCPSchemaOption = errors.New("invalid option for tcp")
|
||||
ErrInvalidUnixSchemaOption = errors.New("invalid option for unix")
|
||||
ErrFileNotUnixSocket = errors.New("not a unix domain socket")
|
||||
ErrEmptySSHIdentity = errors.New("empty identity field for SSH connection")
|
||||
ErrEmptyURIDestination = errors.New("empty URI destination")
|
||||
ErrEmptyServiceName = errors.New("empty service name")
|
||||
ErrDuplicatedServiceName = errors.New("duplicated service name")
|
||||
)
|
||||
|
||||
// Config contains configuration options for container tools.
|
||||
type Config struct {
|
||||
mu sync.Mutex
|
||||
// Services specify the service destination connections
|
||||
Services map[string]Service `toml:"services,omitempty"`
|
||||
type Config interface {
|
||||
RemoteConnections() []registry.Connection
|
||||
SetDefaultConnection(name string) error
|
||||
GetDefaultConnection() registry.Connection
|
||||
Add(name string, uri string, identity string) error
|
||||
Remove(name string) error
|
||||
}
|
||||
|
||||
// Service represents remote service destination.
|
||||
type Service struct {
|
||||
// URI, required. Example: ssh://root@example.com:22/run/podman/podman.sock
|
||||
URI string `toml:"uri"`
|
||||
func NewConfig() (Config, error) { //nolint:ireturn
|
||||
var cfg Config
|
||||
|
||||
// Identity file with ssh key, optional
|
||||
Identity string `toml:"identity,omitempty"`
|
||||
|
||||
// Default if its default service, optional
|
||||
Default bool `toml:"default,omitempty"`
|
||||
}
|
||||
|
||||
// NewConfig returns new config.
|
||||
func NewConfig() (*Config, error) {
|
||||
log.Debug().Msgf("config: new")
|
||||
|
||||
path, err := configPath()
|
||||
pconfig, err := pconfig.NewConfig()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
newConfig := &Config{}
|
||||
if _, err := os.Stat(path); err == nil {
|
||||
if err := newConfig.readConfigFromFile(path); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
premoteConns := pconfig.RemoteConnections()
|
||||
if len(premoteConns) > 0 {
|
||||
cfg = pconfig
|
||||
} else {
|
||||
if !os.IsNotExist(err) {
|
||||
tconfig, err := tconfig.NewConfig()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cfg = tconfig
|
||||
}
|
||||
|
||||
newConfig.addLocalHostIfEmptyConfig()
|
||||
|
||||
defaultConn := newConfig.getDefault()
|
||||
if defaultConn.URI != "" {
|
||||
defaultConn := cfg.GetDefaultConnection()
|
||||
if defaultConn.URI != "" && defaultConn.Name != "" {
|
||||
registry.SetConnection(defaultConn)
|
||||
}
|
||||
|
||||
return newConfig, nil
|
||||
}
|
||||
|
||||
func (c *Config) addLocalHostIfEmptyConfig() {
|
||||
if len(c.Services) > 0 {
|
||||
return
|
||||
}
|
||||
|
||||
c.Services = make(map[string]Service)
|
||||
c.Services["localhost"] = Service{
|
||||
URI: localNodeUnixSocket(),
|
||||
Default: true,
|
||||
}
|
||||
}
|
||||
|
||||
// ServicesConnections returns list of available connections.
|
||||
func (c *Config) ServicesConnections() []registry.Connection {
|
||||
conn := make([]registry.Connection, 0)
|
||||
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
for name, service := range c.Services {
|
||||
conn = append(conn, registry.Connection{
|
||||
Name: name,
|
||||
URI: service.URI,
|
||||
Identity: service.Identity,
|
||||
Default: service.Default,
|
||||
})
|
||||
}
|
||||
|
||||
sort.Sort(connectionListSortedName{conn})
|
||||
|
||||
return conn
|
||||
}
|
||||
|
||||
type connSort []registry.Connection
|
||||
|
||||
func (a connSort) Len() int { return len(a) }
|
||||
func (a connSort) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||
|
||||
type connectionListSortedName struct{ connSort }
|
||||
|
||||
func (a connectionListSortedName) Less(i, j int) bool {
|
||||
return a.connSort[i].Name < a.connSort[j].Name
|
||||
return cfg, nil
|
||||
}
|
||||
|
|
|
@ -1,56 +0,0 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"github.com/containers/podman-tui/pdcs/registry"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
// SetDefaultService sets default service name.
|
||||
func (c *Config) SetDefaultService(name string) error {
|
||||
log.Debug().Msgf("config: set %s as default service", name)
|
||||
|
||||
if err := c.setDef(name); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := c.Write(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return c.reload()
|
||||
}
|
||||
|
||||
func (c *Config) setDef(name string) error {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
for key := range c.Services {
|
||||
dest := c.Services[key]
|
||||
dest.Default = false
|
||||
|
||||
if key == name {
|
||||
dest.Default = true
|
||||
}
|
||||
|
||||
c.Services[key] = dest
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Config) getDefault() registry.Connection {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
for name, service := range c.Services {
|
||||
if service.Default {
|
||||
return registry.Connection{
|
||||
Name: name,
|
||||
Identity: service.Identity,
|
||||
URI: service.URI,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return registry.Connection{}
|
||||
}
|
|
@ -0,0 +1,132 @@
|
|||
package pconfig
|
||||
|
||||
import (
|
||||
"slices"
|
||||
"sort"
|
||||
|
||||
cconfig "github.com/containers/common/pkg/config"
|
||||
"github.com/containers/podman-tui/config/utils"
|
||||
"github.com/containers/podman-tui/pdcs/registry"
|
||||
"github.com/containers/podman/v5/pkg/domain/entities"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
podmanOptions *entities.PodmanConfig
|
||||
}
|
||||
|
||||
func NewConfig() (*Config, error) {
|
||||
log.Debug().Msg("config: loading podman remote connections")
|
||||
|
||||
newConfig := &Config{}
|
||||
|
||||
defaultConfig, err := cconfig.New(&cconfig.Options{
|
||||
SetDefault: true,
|
||||
Modules: nil,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
podmanOptions := entities.PodmanConfig{ContainersConf: &cconfig.Config{}, ContainersConfDefaultsRO: defaultConfig}
|
||||
newConfig.podmanOptions = &podmanOptions
|
||||
|
||||
return newConfig, nil
|
||||
}
|
||||
|
||||
func (c *Config) RemoteConnections() []registry.Connection {
|
||||
rconn := make([]registry.Connection, 0)
|
||||
|
||||
conns, err := c.podmanOptions.ContainersConfDefaultsRO.GetAllConnections()
|
||||
if err != nil {
|
||||
log.Err(err).Msgf("config: podman remote connection")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
log.Debug().Msgf("connections: %v", conns)
|
||||
|
||||
for _, conn := range conns {
|
||||
rconn = append(rconn, registry.Connection{
|
||||
Name: conn.Name,
|
||||
URI: conn.URI,
|
||||
Identity: conn.Identity,
|
||||
Default: conn.Default,
|
||||
})
|
||||
}
|
||||
|
||||
sort.Sort(utils.ConnectionListSortedName{rconn}) //nolint:govet
|
||||
|
||||
return rconn
|
||||
}
|
||||
|
||||
func (c *Config) Remove(name string) error {
|
||||
return cconfig.EditConnectionConfig(func(cfg *cconfig.ConnectionsFile) error {
|
||||
delete(cfg.Connection.Connections, name)
|
||||
|
||||
if cfg.Connection.Default == name {
|
||||
cfg.Connection.Default = ""
|
||||
}
|
||||
|
||||
// If there are existing farm, remove the deleted connection that might be part of a farm
|
||||
for k, v := range cfg.Farm.List {
|
||||
index := slices.Index(v, name)
|
||||
if index > -1 {
|
||||
cfg.Farm.List[k] = append(v[:index], v[index+1:]...)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (c *Config) Add(name string, uri string, identity string) error {
|
||||
connURI, err := utils.ValidateNewConnection(name, uri, identity)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dst := cconfig.Destination{
|
||||
URI: connURI,
|
||||
Identity: identity,
|
||||
}
|
||||
|
||||
return cconfig.EditConnectionConfig(func(cfg *cconfig.ConnectionsFile) error {
|
||||
if cfg.Connection.Connections == nil {
|
||||
cfg.Connection.Connections = map[string]cconfig.Destination{
|
||||
name: dst,
|
||||
}
|
||||
cfg.Connection.Default = name
|
||||
} else {
|
||||
cfg.Connection.Connections[name] = dst
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (c *Config) SetDefaultConnection(name string) error {
|
||||
return cconfig.EditConnectionConfig(func(cfg *cconfig.ConnectionsFile) error {
|
||||
if _, found := cfg.Connection.Connections[name]; !found {
|
||||
return utils.ErrConnectionNotFound
|
||||
}
|
||||
|
||||
cfg.Connection.Default = name
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (c *Config) GetDefaultConnection() registry.Connection {
|
||||
for _, conn := range c.RemoteConnections() {
|
||||
if conn.Default {
|
||||
return registry.Connection{
|
||||
Name: conn.Name,
|
||||
Identity: conn.Identity,
|
||||
URI: conn.URI,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return registry.Connection{}
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
package config
|
||||
|
||||
import "github.com/rs/zerolog/log"
|
||||
|
||||
// Remove removes a service from config.
|
||||
func (c *Config) Remove(name string) error {
|
||||
log.Debug().Msgf("config: remove service %q", name)
|
||||
|
||||
c.remove(name)
|
||||
|
||||
if err := c.Write(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return c.reload()
|
||||
}
|
||||
|
||||
func (c *Config) remove(name string) {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
for serviceName := range c.Services {
|
||||
if serviceName == name {
|
||||
delete(c.Services, name)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
package tconfig
|
||||
|
||||
import (
|
||||
"github.com/containers/podman-tui/config/utils"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
// Add adds a new remote connection.
|
||||
func (c *Config) Add(name string, uri string, identity string) error {
|
||||
log.Debug().Msgf("config: adding new remote connection %s %s %s", name, uri, identity)
|
||||
|
||||
connURI, err := utils.ValidateNewConnection(name, uri, identity)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
conn := RemoteConnection{
|
||||
URI: connURI,
|
||||
Identity: identity,
|
||||
Default: false,
|
||||
}
|
||||
|
||||
if err := c.add(name, conn); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := c.write(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return c.reload()
|
||||
}
|
||||
|
||||
func (c *Config) add(name string, conn RemoteConnection) error {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
for connName := range c.Connection.Connections {
|
||||
if connName == name {
|
||||
return ErrDuplicatedConnectionName
|
||||
}
|
||||
}
|
||||
|
||||
c.Connection.Connections[name] = conn
|
||||
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,103 @@
|
|||
package tconfig
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"sort"
|
||||
"sync"
|
||||
|
||||
"github.com/containers/podman-tui/config/utils"
|
||||
"github.com/containers/podman-tui/pdcs/registry"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
const (
|
||||
// _configPath is the path to the podman-tui/podman-tui.json
|
||||
// inside a given config directory.
|
||||
_configPath = "podman-tui/podman-tui.json"
|
||||
// UserAppConfig holds the user podman-tui config path.
|
||||
UserAppConfig = ".config/" + _configPath
|
||||
)
|
||||
|
||||
var ErrDuplicatedConnectionName = errors.New("duplicated connection name")
|
||||
|
||||
// Config contains configuration options for container tools.
|
||||
type Config struct {
|
||||
mu sync.Mutex
|
||||
Connection RemoteConnections
|
||||
}
|
||||
|
||||
type RemoteConnections struct {
|
||||
Connections map[string]RemoteConnection `json:"connections"`
|
||||
}
|
||||
|
||||
type RemoteConnection struct {
|
||||
// URI, required. Example: ssh://root@example.com:22/run/podman/podman.sock
|
||||
URI string `json:"uri"`
|
||||
|
||||
// Identity file with ssh key, optional
|
||||
Identity string `json:"identity,omitempty"`
|
||||
|
||||
// Default if its default connection, optional
|
||||
Default bool `json:"default,omitempty"`
|
||||
}
|
||||
|
||||
// NewConfig returns new config.
|
||||
func NewConfig() (*Config, error) {
|
||||
path, err := utils.ConfigPath()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
log.Debug().Msgf("config: loading from %q", path)
|
||||
|
||||
newConfig := &Config{}
|
||||
newConfig.Connection.Connections = make(map[string]RemoteConnection)
|
||||
|
||||
if _, err := os.Stat(path); err == nil {
|
||||
if err := newConfig.readConfigFromFile(path); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
if !os.IsNotExist(err) {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
newConfig.addLocalHostIfEmptyConfig()
|
||||
|
||||
return newConfig, nil
|
||||
}
|
||||
|
||||
func (c *Config) addLocalHostIfEmptyConfig() {
|
||||
if len(c.Connection.Connections) > 0 {
|
||||
return
|
||||
}
|
||||
|
||||
c.Connection.Connections = make(map[string]RemoteConnection)
|
||||
c.Connection.Connections["localhost"] = RemoteConnection{
|
||||
URI: utils.LocalNodeUnixSocket(),
|
||||
Default: true,
|
||||
}
|
||||
}
|
||||
|
||||
// RemoteConnections returns list of available connections.
|
||||
func (c *Config) RemoteConnections() []registry.Connection {
|
||||
rconn := make([]registry.Connection, 0)
|
||||
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
for name, conn := range c.Connection.Connections {
|
||||
rconn = append(rconn, registry.Connection{
|
||||
Name: name,
|
||||
URI: conn.URI,
|
||||
Identity: conn.Identity,
|
||||
Default: conn.Default,
|
||||
})
|
||||
}
|
||||
|
||||
sort.Sort(utils.ConnectionListSortedName{rconn}) //nolint:govet
|
||||
|
||||
return rconn
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
package tconfig
|
||||
|
||||
import (
|
||||
"github.com/containers/podman-tui/config/utils"
|
||||
"github.com/containers/podman-tui/pdcs/registry"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
// SetDefaultConnection sets default connection.
|
||||
func (c *Config) SetDefaultConnection(name string) error {
|
||||
log.Debug().Msgf("config: set %s as default connection", name)
|
||||
|
||||
if err := c.setDef(name); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := c.write(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return c.reload()
|
||||
}
|
||||
|
||||
func (c *Config) setDef(name string) error {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
for connName := range c.Connection.Connections {
|
||||
if connName == name {
|
||||
dest := c.Connection.Connections[connName]
|
||||
dest.Default = true
|
||||
c.Connection.Connections[connName] = dest
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
return utils.ErrConnectionNotFound
|
||||
}
|
||||
|
||||
func (c *Config) GetDefaultConnection() registry.Connection {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
for connName, conn := range c.Connection.Connections {
|
||||
if conn.Default {
|
||||
return registry.Connection{
|
||||
Name: connName,
|
||||
Identity: conn.Identity,
|
||||
URI: conn.URI,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return registry.Connection{}
|
||||
}
|
|
@ -1,10 +1,12 @@
|
|||
package config
|
||||
package tconfig
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"github.com/BurntSushi/toml"
|
||||
"github.com/containers/podman-tui/config/utils"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
|
@ -14,30 +16,23 @@ func (c *Config) readConfigFromFile(path string) error {
|
|||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
rawConfig, err := os.ReadFile(path)
|
||||
cfgFile, err := os.Open(path)
|
||||
if err != nil {
|
||||
return fmt.Errorf("config: %w open configuration %q", err, path)
|
||||
}
|
||||
|
||||
cfgData, err := io.ReadAll(cfgFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("config: %w read configuration %q", err, path)
|
||||
}
|
||||
|
||||
config := os.ExpandEnv(string(rawConfig))
|
||||
|
||||
meta, err := toml.Decode(config, c)
|
||||
if err != nil {
|
||||
return fmt.Errorf("config: %w decode configuration %q", err, path)
|
||||
}
|
||||
|
||||
keys := meta.Undecoded()
|
||||
if len(keys) > 0 {
|
||||
log.Debug().Msgf("config: failed to decode the keys %q from %q.", keys, path)
|
||||
}
|
||||
|
||||
return nil
|
||||
return json.Unmarshal(cfgData, &c.Connection)
|
||||
}
|
||||
|
||||
func (c *Config) reload() error {
|
||||
log.Debug().Msgf("config: reload configuration")
|
||||
|
||||
path, err := configPath()
|
||||
path, err := utils.ConfigPath()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
package tconfig
|
||||
|
||||
import "github.com/rs/zerolog/log"
|
||||
|
||||
// Remove removes a connection from config.
|
||||
func (c *Config) Remove(name string) error {
|
||||
log.Debug().Msgf("config: remove remote connection %q", name)
|
||||
|
||||
c.remove(name)
|
||||
|
||||
if err := c.write(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return c.reload()
|
||||
}
|
||||
|
||||
func (c *Config) remove(name string) {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
for connName := range c.Connection.Connections {
|
||||
if connName != name {
|
||||
delete(c.Connection.Connections, name)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,21 +1,23 @@
|
|||
package config
|
||||
package tconfig
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/BurntSushi/toml"
|
||||
"github.com/containers/podman-tui/config/utils"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
// Write writes config.
|
||||
func (c *Config) Write() error {
|
||||
func (c *Config) write() error {
|
||||
var err error
|
||||
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
path, err := configPath()
|
||||
path, err := utils.ConfigPath()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -33,7 +35,14 @@ func (c *Config) Write() error {
|
|||
|
||||
defer configFile.Close()
|
||||
|
||||
enc := toml.NewEncoder(configFile)
|
||||
jsonData, err := json.Marshal(c.Connection)
|
||||
if err != nil {
|
||||
return fmt.Errorf("config: configuration json marshal %w", err)
|
||||
}
|
||||
|
||||
return enc.Encode(c)
|
||||
if _, err := configFile.Write(jsonData); err != nil {
|
||||
return fmt.Errorf("config: %w write configuration %q", err, path)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
package utils
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/url"
|
||||
"os"
|
||||
"regexp"
|
||||
|
||||
"github.com/containers/podman-tui/ui/utils"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrInvalidURISchemaName = errors.New("invalid schema name")
|
||||
ErrInvalidTCPSchemaOption = errors.New("invalid option for tcp")
|
||||
ErrInvalidUnixSchemaOption = errors.New("invalid option for unix")
|
||||
ErrFileNotUnixSocket = errors.New("not a unix domain socket")
|
||||
ErrEmptySSHIdentity = errors.New("empty identity field for SSH connection")
|
||||
ErrEmptyURIDestination = errors.New("empty URI destination")
|
||||
ErrEmptyConnectionName = errors.New("empty connection name")
|
||||
ErrConnectionNotFound = errors.New("connection not found")
|
||||
)
|
||||
|
||||
func ValidateNewConnection(name string, dest string, identity string) (string, error) { //nolint:cyclop
|
||||
var connIdentity string
|
||||
|
||||
if name == "" {
|
||||
return "", ErrEmptyConnectionName
|
||||
}
|
||||
|
||||
if dest == "" {
|
||||
return "", ErrEmptyURIDestination
|
||||
}
|
||||
|
||||
if match, err := regexp.Match("^[A-Za-z][A-Za-z0-9+.-]*://", []byte(dest)); err != nil { //nolint:mirror
|
||||
return "", fmt.Errorf("%w invalid destition", err)
|
||||
} else if !match {
|
||||
dest = "ssh://" + dest
|
||||
}
|
||||
|
||||
uri, err := url.Parse(dest)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
switch uri.Scheme {
|
||||
case "ssh":
|
||||
if uri.User.Username() == "" {
|
||||
if uri.User, err = getUserInfo(uri); err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
connIdentity, err = utils.ResolveHomeDir(identity)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if identity == "" {
|
||||
return "", ErrEmptySSHIdentity
|
||||
}
|
||||
|
||||
if uri.Port() == "" {
|
||||
uri.Host = net.JoinHostPort(uri.Hostname(), "22")
|
||||
}
|
||||
|
||||
if uri.Path == "" || uri.Path == "/" {
|
||||
if uri.Path, err = getUDS(uri, connIdentity); err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
case "unix":
|
||||
if identity != "" {
|
||||
return "", fmt.Errorf("%w identity", ErrInvalidUnixSchemaOption)
|
||||
}
|
||||
|
||||
info, err := os.Stat(uri.Path)
|
||||
|
||||
switch {
|
||||
case errors.Is(err, os.ErrNotExist):
|
||||
log.Warn().Msgf("config: %q does not exists", uri.Path)
|
||||
case errors.Is(err, os.ErrPermission):
|
||||
log.Warn().Msgf("config: You do not have permission to read %q", uri.Path)
|
||||
case err != nil:
|
||||
return "", err
|
||||
case info.Mode()&os.ModeSocket == 0:
|
||||
return "", fmt.Errorf("%w %q", ErrFileNotUnixSocket, uri.Path)
|
||||
}
|
||||
case "tcp":
|
||||
if identity != "" {
|
||||
return "", fmt.Errorf("%w identity", ErrInvalidTCPSchemaOption)
|
||||
}
|
||||
default:
|
||||
return "", fmt.Errorf("%w %q", ErrInvalidURISchemaName, uri.Scheme)
|
||||
}
|
||||
|
||||
return uri.String(), nil
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package utils
|
||||
|
||||
import "github.com/containers/podman-tui/pdcs/registry"
|
||||
|
||||
type ConnSort []registry.Connection
|
||||
|
||||
func (a ConnSort) Len() int { return len(a) }
|
||||
func (a ConnSort) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||
|
||||
type ConnectionListSortedName struct{ ConnSort }
|
||||
|
||||
func (a ConnectionListSortedName) Less(i, j int) bool {
|
||||
return a.ConnSort[i].Name < a.ConnSort[j].Name
|
||||
}
|
|
@ -1,8 +1,9 @@
|
|||
package config
|
||||
package utils
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/url"
|
||||
|
@ -19,7 +20,17 @@ import (
|
|||
"golang.org/x/crypto/ssh/agent"
|
||||
)
|
||||
|
||||
func configPath() (string, error) {
|
||||
const (
|
||||
// _configPath is the path to the podman-tui/podman-tui.json
|
||||
// inside a given config directory.
|
||||
_configPath = "podman-tui/podman-tui.json"
|
||||
// UserAppConfig holds the user podman-tui config path.
|
||||
UserAppConfig = ".config/" + _configPath
|
||||
)
|
||||
|
||||
var ErrRemotePodmanUDSReport = errors.New("remote podman failed to report its UDS socket")
|
||||
|
||||
func ConfigPath() (string, error) {
|
||||
if configHome := os.Getenv("XDG_CONFIG_HOME"); configHome != "" {
|
||||
return filepath.Join(configHome, _configPath), nil
|
||||
}
|
||||
|
@ -32,8 +43,8 @@ func configPath() (string, error) {
|
|||
return filepath.Join(home, UserAppConfig), nil
|
||||
}
|
||||
|
||||
// localNodeUnixSocket return local node unix socket file.
|
||||
func localNodeUnixSocket() string {
|
||||
// LocalNodeUnixSocket return local node unix socket file.
|
||||
func LocalNodeUnixSocket() string {
|
||||
var (
|
||||
sockDir string
|
||||
socket string
|
||||
|
@ -48,7 +59,7 @@ func localNodeUnixSocket() string {
|
|||
sockDir = os.Getenv("XDG_RUNTIME_DIR")
|
||||
}
|
||||
|
||||
socket = "unix:" + sockDir + "/podman/podman.sock"
|
||||
socket = "unix:/" + sockDir + "/podman/podman.sock"
|
||||
|
||||
return socket
|
||||
}
|
|
@ -1,4 +1,57 @@
|
|||
# Documents
|
||||
## podman-tui
|
||||
|
||||

|
||||

|
||||

|
||||
[](https://goreportcard.com/report/github.com/containers/podman-tui)
|
||||
[](https://codecov.io/gh/navidys/podman-tui)
|
||||
|
||||
Terminal user interface for Podman environment.
|
||||
|
||||

|
||||
|
||||
- [**Overview**](#overview)
|
||||
- [**Compatibility Matrix**](#compatibility-matrix)
|
||||
- [**Installation**](#installation)
|
||||
- [**PreRun Checks**](#prerun-checks)
|
||||
- [**Key Bindings**](#key-bindings)
|
||||
- [**Code of Conduct**](#code-of-conduct)
|
||||
- [**License**](#license)
|
||||
|
||||
## Overview
|
||||
|
||||
podman-tui is a terminal user interface for podman environment.
|
||||
It is using [podman go bindings](https://github.com/containers/podman/tree/main/pkg/bindings) to communicate with local or remote podman machine (through SSH).
|
||||
|
||||
## Compatibility matrix
|
||||
|
||||
| Terminal User Interface | Podman |
|
||||
| ----------- | ------ |
|
||||
| release-1.x | v5.x.y |
|
||||
| release-0.x | v4.x.y |
|
||||
|
||||
## Installation
|
||||
|
||||
Building from source (Linux, Windows and MacOS) or installing packaged versions are detailed in [install guide](install.md).
|
||||
|
||||
## PreRun Checks
|
||||
|
||||
* `podman.socket` service needs to be running on podman machine.
|
||||
The recommended way to start Podman system service in production mode is via systemd socket-activation:
|
||||
|
||||
```shell
|
||||
$ systemctl --user start podman.socket
|
||||
```
|
||||
|
||||
See [start podman system service](https://podman.io/blogs/2020/08/10/podman-go-bindings.html) for more details.
|
||||
|
||||
* If the SSH key has a passphrase, then you need to set and export `CONTAINER_PASSPHRASE=<password>` variable.
|
||||
```shell
|
||||
$ export CONTAINER_PASSPHRASE=keypass
|
||||
```
|
||||
|
||||
* podman-tui uses 256 colors terminal mode on `Nix` system and standard ANSI colors on `Windows` system (use "command prompt" application).
|
||||
|
||||
|
||||
## Key Bindings
|
||||
|
||||
|
@ -27,3 +80,11 @@ podman-tui uses following keyboard keys for different actions:
|
|||
| Display images screen | F6 |
|
||||
| Display networks screen | F7 |
|
||||
| Display secrets screen | F8 |
|
||||
|
||||
## Code of Conduct
|
||||
|
||||
This project is using the [Containers Community Code of Conduct](https://github.com/containers/common/blob/main/CODE-OF-CONDUCT.md)
|
||||
|
||||
## License
|
||||
|
||||
Licensed under the [Apache 2.0](LICENSE) license.
|
||||
|
|
|
@ -112,22 +112,27 @@ $ podman run -it --name podman-tui-app \
|
|||
|
||||
## Configuration Files
|
||||
|
||||
### podman-tui.conf
|
||||
### podman-tui.json
|
||||
|
||||
~/.config/podman-tui/podman-tui.conf
|
||||
~/.config/podman-tui/podman-tui.json
|
||||
|
||||
podman-tui.conf is the configuration file which specifies local and remotes podman systems connections details.
|
||||
podman-tui.json is the configuration file which specifies local and remotes podman systems connections details.
|
||||
|
||||
```shell
|
||||
[services]
|
||||
|
||||
[services.fc36node01]
|
||||
uri = "ssh://navid@fc36node01:22/run/user/1000/podman/podman.sock"
|
||||
identity = "/home/navid/.ssh/id_ed25519"
|
||||
[services.fc36node02]
|
||||
uri = "ssh://navid@fc36node02:22/run/user/1000/podman/podman.sock"
|
||||
identity = "/home/navid/.ssh/id_ed25519"
|
||||
default = true
|
||||
[services.localhost]
|
||||
uri = "unix://run/user/1000/podman/podman.sock"
|
||||
{
|
||||
"connections": {
|
||||
"f42node01": {
|
||||
"uri": "ssh://navid@f42node01:22/run/user/1000/podman/podman.sock",
|
||||
"identity": "/home/navid/.ssh/id_ed25519"
|
||||
},
|
||||
"fc42node02": {
|
||||
"uri": "ssh://navid@f42node02:22/run/user/1000/podman/podman.sock",
|
||||
"identity": "/home/navid/.ssh/id_ed25519"
|
||||
},
|
||||
"localhost": {
|
||||
"uri": "unix://run/user/1000/podman/podman.sock",
|
||||
"default": true
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
155
go.mod
155
go.mod
|
@ -1,32 +1,32 @@
|
|||
module github.com/containers/podman-tui
|
||||
|
||||
go 1.22.6
|
||||
go 1.23.3
|
||||
|
||||
require (
|
||||
github.com/BurntSushi/toml v1.4.0
|
||||
github.com/containers/buildah v1.38.0
|
||||
github.com/containers/common v0.61.0
|
||||
github.com/containers/podman/v5 v5.3.1
|
||||
github.com/containers/storage v1.56.0
|
||||
github.com/containers/buildah v1.40.1
|
||||
github.com/containers/common v0.63.1
|
||||
github.com/containers/podman/v5 v5.5.1
|
||||
github.com/containers/storage v1.58.0
|
||||
github.com/distribution/reference v0.6.0
|
||||
github.com/docker/go-units v0.5.0
|
||||
github.com/gdamore/tcell/v2 v2.7.4
|
||||
github.com/gdamore/tcell/v2 v2.8.1
|
||||
github.com/hashicorp/go-multierror v1.1.1
|
||||
github.com/hinshun/vt10x v0.0.0-20220301184237-5011da428d02
|
||||
github.com/navidys/tvxwidgets v0.4.1
|
||||
github.com/onsi/ginkgo/v2 v2.21.0
|
||||
github.com/onsi/gomega v1.35.1
|
||||
github.com/onsi/ginkgo/v2 v2.23.4
|
||||
github.com/onsi/gomega v1.37.0
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/rivo/tview v0.0.0-20220307222120-9994674d60a8
|
||||
github.com/rs/zerolog v1.33.0
|
||||
github.com/rs/zerolog v1.34.0
|
||||
github.com/sirupsen/logrus v1.9.3
|
||||
github.com/spf13/cobra v1.8.1
|
||||
golang.org/x/crypto v0.29.0
|
||||
github.com/spf13/cobra v1.9.1
|
||||
golang.org/x/crypto v0.39.0
|
||||
)
|
||||
|
||||
require (
|
||||
dario.cat/mergo v1.0.1 // indirect
|
||||
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect
|
||||
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect
|
||||
github.com/BurntSushi/toml v1.5.0 // indirect
|
||||
github.com/Microsoft/go-winio v0.6.2 // indirect
|
||||
github.com/Microsoft/hcsshim v0.12.9 // indirect
|
||||
github.com/VividCortex/ewma v1.2.0 // indirect
|
||||
|
@ -34,50 +34,50 @@ require (
|
|||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
|
||||
github.com/blang/semver/v4 v4.0.0 // indirect
|
||||
github.com/chzyer/readline v1.5.1 // indirect
|
||||
github.com/containerd/cgroups/v3 v3.0.3 // indirect
|
||||
github.com/containerd/errdefs v0.3.0 // indirect
|
||||
github.com/containerd/cgroups/v3 v3.0.5 // indirect
|
||||
github.com/containerd/errdefs v1.0.0 // indirect
|
||||
github.com/containerd/errdefs/pkg v0.3.0 // indirect
|
||||
github.com/containerd/log v0.1.0 // indirect
|
||||
github.com/containerd/platforms v0.2.1 // indirect
|
||||
github.com/containerd/stargz-snapshotter/estargz v0.15.1 // indirect
|
||||
github.com/containerd/typeurl/v2 v2.2.0 // indirect
|
||||
github.com/containers/image/v5 v5.33.0 // indirect
|
||||
github.com/containerd/platforms v1.0.0-rc.1 // indirect
|
||||
github.com/containerd/stargz-snapshotter/estargz v0.16.3 // indirect
|
||||
github.com/containerd/typeurl/v2 v2.2.3 // indirect
|
||||
github.com/containers/image/v5 v5.35.0 // indirect
|
||||
github.com/containers/libtrust v0.0.0-20230121012942-c1716e8a8d01 // indirect
|
||||
github.com/containers/ocicrypt v1.2.0 // indirect
|
||||
github.com/containers/ocicrypt v1.2.1 // indirect
|
||||
github.com/containers/psgo v1.9.0 // indirect
|
||||
github.com/coreos/go-systemd/v22 v22.5.1-0.20231103132048-7d375ecc2b09 // indirect
|
||||
github.com/cyberphone/json-canonicalization v0.0.0-20231217050601-ba74d44ecf5f // indirect
|
||||
github.com/cyphar/filepath-securejoin v0.3.4 // indirect
|
||||
github.com/cyberphone/json-canonicalization v0.0.0-20241213102144-19d51d7fe467 // indirect
|
||||
github.com/cyphar/filepath-securejoin v0.4.1 // indirect
|
||||
github.com/disiqueira/gotree/v3 v3.0.2 // indirect
|
||||
github.com/docker/distribution v2.8.3+incompatible // indirect
|
||||
github.com/docker/docker v27.3.1+incompatible // indirect
|
||||
github.com/docker/docker-credential-helpers v0.8.2 // indirect
|
||||
github.com/docker/docker v28.1.1+incompatible // indirect
|
||||
github.com/docker/docker-credential-helpers v0.9.3 // indirect
|
||||
github.com/docker/go-connections v0.5.0 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/fsnotify/fsnotify v1.8.0 // indirect
|
||||
github.com/gdamore/encoding v1.0.0 // indirect
|
||||
github.com/go-jose/go-jose/v4 v4.0.4 // indirect
|
||||
github.com/fsnotify/fsnotify v1.9.0 // indirect
|
||||
github.com/gdamore/encoding v1.0.1 // indirect
|
||||
github.com/go-jose/go-jose/v4 v4.0.5 // indirect
|
||||
github.com/go-logr/logr v1.4.2 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/go-openapi/analysis v0.23.0 // indirect
|
||||
github.com/go-openapi/errors v0.22.0 // indirect
|
||||
github.com/go-openapi/errors v0.22.1 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.21.0 // indirect
|
||||
github.com/go-openapi/jsonreference v0.21.0 // indirect
|
||||
github.com/go-openapi/loads v0.22.0 // indirect
|
||||
github.com/go-openapi/runtime v0.28.0 // indirect
|
||||
github.com/go-openapi/spec v0.21.0 // indirect
|
||||
github.com/go-openapi/strfmt v0.23.0 // indirect
|
||||
github.com/go-openapi/swag v0.23.0 // indirect
|
||||
github.com/go-openapi/swag v0.23.1 // indirect
|
||||
github.com/go-openapi/validate v0.24.0 // indirect
|
||||
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
|
||||
github.com/godbus/dbus/v5 v5.1.1-0.20240921181615-a817f3cc4a9e // indirect
|
||||
github.com/godbus/dbus/v5 v5.1.1-0.20241109141217-c266b19b28e9 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
|
||||
github.com/golang/protobuf v1.5.4 // indirect
|
||||
github.com/google/go-cmp v0.6.0 // indirect
|
||||
github.com/google/go-containerregistry v0.20.2 // indirect
|
||||
github.com/google/go-cmp v0.7.0 // indirect
|
||||
github.com/google/go-containerregistry v0.20.3 // indirect
|
||||
github.com/google/go-intervals v0.0.2 // indirect
|
||||
github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db // indirect
|
||||
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/gorilla/mux v1.8.1 // indirect
|
||||
github.com/gorilla/schema v1.4.1 // indirect
|
||||
|
@ -87,76 +87,79 @@ require (
|
|||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/kevinburke/ssh_config v1.2.0 // indirect
|
||||
github.com/klauspost/compress v1.17.11 // indirect
|
||||
github.com/klauspost/compress v1.18.0 // indirect
|
||||
github.com/klauspost/pgzip v1.2.6 // indirect
|
||||
github.com/kr/fs v0.1.0 // indirect
|
||||
github.com/letsencrypt/boulder v0.0.0-20240620165639-de9c06129bec // indirect
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
|
||||
github.com/mailru/easyjson v0.7.7 // indirect
|
||||
github.com/mailru/easyjson v0.9.0 // indirect
|
||||
github.com/manifoldco/promptui v0.9.0 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.16 // indirect
|
||||
github.com/mattn/go-sqlite3 v1.14.24 // indirect
|
||||
github.com/mattn/go-sqlite3 v1.14.28 // indirect
|
||||
github.com/miekg/pkcs11 v1.1.1 // indirect
|
||||
github.com/mistifyio/go-zfs/v3 v3.0.1 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/moby/docker-image-spec v1.3.1 // indirect
|
||||
github.com/moby/sys/capability v0.3.0 // indirect
|
||||
github.com/moby/sys/capability v0.4.0 // indirect
|
||||
github.com/moby/sys/mountinfo v0.7.2 // indirect
|
||||
github.com/moby/sys/user v0.3.0 // indirect
|
||||
github.com/moby/term v0.5.0 // indirect
|
||||
github.com/moby/sys/user v0.4.0 // indirect
|
||||
github.com/moby/sys/userns v0.1.0 // indirect
|
||||
github.com/moby/term v0.5.2 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/morikuni/aec v1.0.0 // indirect
|
||||
github.com/nxadm/tail v1.4.11 // indirect
|
||||
github.com/oklog/ulid v1.3.1 // indirect
|
||||
github.com/opencontainers/cgroups v0.0.1 // indirect
|
||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||
github.com/opencontainers/image-spec v1.1.0 // indirect
|
||||
github.com/opencontainers/runc v1.2.1 // indirect
|
||||
github.com/opencontainers/runtime-spec v1.2.0 // indirect
|
||||
github.com/opencontainers/runtime-tools v0.9.1-0.20241001195557-6c9570a1678f // indirect
|
||||
github.com/opencontainers/selinux v1.11.1 // indirect
|
||||
github.com/opencontainers/image-spec v1.1.1 // indirect
|
||||
github.com/opencontainers/runc v1.2.6 // indirect
|
||||
github.com/opencontainers/runtime-spec v1.2.1 // indirect
|
||||
github.com/opencontainers/runtime-tools v0.9.1-0.20250303011046-260e151b8552 // indirect
|
||||
github.com/opencontainers/selinux v1.12.0 // indirect
|
||||
github.com/ostreedev/ostree-go v0.0.0-20210805093236-719684c64e4f // indirect
|
||||
github.com/pkg/sftp v1.13.7 // indirect
|
||||
github.com/proglottis/gpgme v0.1.3 // indirect
|
||||
github.com/pkg/sftp v1.13.9 // indirect
|
||||
github.com/proglottis/gpgme v0.1.4 // indirect
|
||||
github.com/rivo/uniseg v0.4.7 // indirect
|
||||
github.com/secure-systems-lab/go-securesystemslib v0.8.0 // indirect
|
||||
github.com/sigstore/fulcio v1.6.4 // indirect
|
||||
github.com/sigstore/rekor v1.3.6 // indirect
|
||||
github.com/sigstore/sigstore v1.8.9 // indirect
|
||||
github.com/skeema/knownhosts v1.3.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/secure-systems-lab/go-securesystemslib v0.9.0 // indirect
|
||||
github.com/sigstore/fulcio v1.6.6 // indirect
|
||||
github.com/sigstore/protobuf-specs v0.4.1 // indirect
|
||||
github.com/sigstore/rekor v1.3.10 // indirect
|
||||
github.com/sigstore/sigstore v1.9.3 // indirect
|
||||
github.com/skeema/knownhosts v1.3.1 // indirect
|
||||
github.com/smallstep/pkcs7 v0.1.1 // indirect
|
||||
github.com/spf13/pflag v1.0.6 // indirect
|
||||
github.com/stefanberger/go-pkcs11uri v0.0.0-20230803200340-78284954bff6 // indirect
|
||||
github.com/sylabs/sif/v2 v2.19.1 // indirect
|
||||
github.com/sylabs/sif/v2 v2.21.1 // indirect
|
||||
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 // indirect
|
||||
github.com/tchap/go-patricia/v2 v2.3.1 // indirect
|
||||
github.com/tchap/go-patricia/v2 v2.3.2 // indirect
|
||||
github.com/titanous/rocacheck v0.0.0-20171023193734-afe73141d399 // indirect
|
||||
github.com/ulikunitz/xz v0.5.12 // indirect
|
||||
github.com/vbatts/tar-split v0.11.6 // indirect
|
||||
github.com/vbauerster/mpb/v8 v8.8.3 // indirect
|
||||
github.com/vbatts/tar-split v0.12.1 // indirect
|
||||
github.com/vbauerster/mpb/v8 v8.9.3 // indirect
|
||||
go.mongodb.org/mongo-driver v1.14.0 // indirect
|
||||
go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352 // indirect
|
||||
go.opencensus.io v0.24.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 // indirect
|
||||
go.opentelemetry.io/otel v1.28.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.28.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.28.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c // indirect
|
||||
golang.org/x/net v0.30.0 // indirect
|
||||
golang.org/x/sync v0.9.0 // indirect
|
||||
golang.org/x/sys v0.27.0 // indirect
|
||||
golang.org/x/term v0.26.0 // indirect
|
||||
golang.org/x/text v0.20.0 // indirect
|
||||
golang.org/x/time v0.6.0 // indirect
|
||||
golang.org/x/tools v0.26.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect
|
||||
google.golang.org/grpc v1.67.0 // indirect
|
||||
google.golang.org/protobuf v1.35.1 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 // indirect
|
||||
go.opentelemetry.io/otel v1.34.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.34.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.34.0 // indirect
|
||||
go.uber.org/automaxprocs v1.6.0 // indirect
|
||||
golang.org/x/net v0.40.0 // indirect
|
||||
golang.org/x/sync v0.15.0 // indirect
|
||||
golang.org/x/sys v0.33.0 // indirect
|
||||
golang.org/x/term v0.32.0 // indirect
|
||||
golang.org/x/text v0.26.0 // indirect
|
||||
golang.org/x/time v0.11.0 // indirect
|
||||
golang.org/x/tools v0.33.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250313205543-e70fdf4c4cb4 // indirect
|
||||
google.golang.org/grpc v1.71.0 // indirect
|
||||
google.golang.org/protobuf v1.36.6 // indirect
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
sigs.k8s.io/yaml v1.4.0 // indirect
|
||||
tags.cncf.io/container-device-interface v0.8.0 // indirect
|
||||
tags.cncf.io/container-device-interface v1.0.1 // indirect
|
||||
)
|
||||
|
||||
replace github.com/opencontainers/runc => github.com/opencontainers/runc v1.1.1-0.20240131200429-02120488a4c0
|
||||
|
|
395
go.sum
395
go.sum
|
@ -3,11 +3,11 @@ dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s=
|
|||
dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
|
||||
github.com/14rcole/gopopulate v0.0.0-20180821133914-b175b219e774 h1:SCbEWT58NSt7d2mcFdvxC9uyrdcTfvBbPLThhkDmXzg=
|
||||
github.com/14rcole/gopopulate v0.0.0-20180821133914-b175b219e774/go.mod h1:6/0dYRLLXyJjbkIPeeGyoJ/eKOSI0eU6eTlCBYibgd0=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0=
|
||||
github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
||||
github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg=
|
||||
github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
||||
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
|
||||
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
|
||||
github.com/Microsoft/hcsshim v0.12.9 h1:2zJy5KA+l0loz1HzEGqyNnjd3fyZA31ZBCGKacp6lLg=
|
||||
|
@ -38,46 +38,46 @@ github.com/chzyer/test v1.0.0 h1:p3BQDXSxOhOG0P9z6/hGnII4LGiEPOYBhs8asl/fC04=
|
|||
github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8=
|
||||
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/v3 v3.0.3 h1:S5ByHZ/h9PMe5IOQoN7E+nMc2UcLEM/V48DGDJ9kip0=
|
||||
github.com/containerd/cgroups/v3 v3.0.3/go.mod h1:8HBe7V3aWGLFPd/k03swSIsGjZhHI2WzJmticMgVuz0=
|
||||
github.com/containerd/errdefs v0.3.0 h1:FSZgGOeK4yuT/+DnF07/Olde/q4KBoMsaamhXxIMDp4=
|
||||
github.com/containerd/errdefs v0.3.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M=
|
||||
github.com/containerd/cgroups/v3 v3.0.5 h1:44na7Ud+VwyE7LIoJ8JTNQOa549a8543BmzaJHo6Bzo=
|
||||
github.com/containerd/cgroups/v3 v3.0.5/go.mod h1:SA5DLYnXO8pTGYiAHXz94qvLQTKfVM5GEVisn4jpins=
|
||||
github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI=
|
||||
github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M=
|
||||
github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE=
|
||||
github.com/containerd/errdefs/pkg v0.3.0/go.mod h1:NJw6s9HwNuRhnjJhM7pylWwMyAkmCQvQ4GpJHEqRLVk=
|
||||
github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
|
||||
github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
|
||||
github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A=
|
||||
github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw=
|
||||
github.com/containerd/stargz-snapshotter/estargz v0.15.1 h1:eXJjw9RbkLFgioVaTG+G/ZW/0kEe2oEKCdS/ZxIyoCU=
|
||||
github.com/containerd/stargz-snapshotter/estargz v0.15.1/go.mod h1:gr2RNwukQ/S9Nv33Lt6UC7xEx58C+LHRdoqbEKjz1Kk=
|
||||
github.com/containerd/typeurl/v2 v2.2.0 h1:6NBDbQzr7I5LHgp34xAXYF5DOTQDn05X58lsPEmzLso=
|
||||
github.com/containerd/typeurl/v2 v2.2.0/go.mod h1:8XOOxnyatxSWuG8OfsZXVnAF4iZfedjS/8UHSPJnX4g=
|
||||
github.com/containers/buildah v1.38.0 h1:FmciZMwzhdcvtWj+8IE+61+lfTG2JfgrbZ2DUnEMnTE=
|
||||
github.com/containers/buildah v1.38.0/go.mod h1:tUsHC2bcgR5Q/R76qZUn7x0FRglqPFry2g5KhWfH4LI=
|
||||
github.com/containers/common v0.61.0 h1:j/84PTqZIKKYy42OEJsZmjZ4g4Kq2ERuC3tqp2yWdh4=
|
||||
github.com/containers/common v0.61.0/go.mod h1:NGRISq2vTFPSbhNqj6MLwyes4tWSlCnqbJg7R77B8xc=
|
||||
github.com/containers/image/v5 v5.33.0 h1:6oPEFwTurf7pDTGw7TghqGs8K0+OvPtY/UyzU0B2DfE=
|
||||
github.com/containers/image/v5 v5.33.0/go.mod h1:T7HpASmvnp2H1u4cyckMvCzLuYgpD18dSmabSw0AcHk=
|
||||
github.com/containerd/platforms v1.0.0-rc.1 h1:83KIq4yy1erSRgOVHNk1HYdPvzdJ5CnsWaRoJX4C41E=
|
||||
github.com/containerd/platforms v1.0.0-rc.1/go.mod h1:J71L7B+aiM5SdIEqmd9wp6THLVRzJGXfNuWCZCllLA4=
|
||||
github.com/containerd/stargz-snapshotter/estargz v0.16.3 h1:7evrXtoh1mSbGj/pfRccTampEyKpjpOnS3CyiV1Ebr8=
|
||||
github.com/containerd/stargz-snapshotter/estargz v0.16.3/go.mod h1:uyr4BfYfOj3G9WBVE8cOlQmXAbPN9VEQpBBeJIuOipU=
|
||||
github.com/containerd/typeurl/v2 v2.2.3 h1:yNA/94zxWdvYACdYO8zofhrTVuQY73fFU1y++dYSw40=
|
||||
github.com/containerd/typeurl/v2 v2.2.3/go.mod h1:95ljDnPfD3bAbDJRugOiShd/DlAAsxGtUBhJxIn7SCk=
|
||||
github.com/containers/buildah v1.40.1 h1:RW+Fbelwblzg1mJfKfyGZPS4Nbc5QtT866fJ9pYFtYo=
|
||||
github.com/containers/buildah v1.40.1/go.mod h1:1UCQBc3LZrT4u5R/u7igGgUQxeDlJmn/OyYDQ9mumFk=
|
||||
github.com/containers/common v0.63.1 h1:6g02gbW34PaRVH4Heb2Pk11x0SdbQ+8AfeKKeQGqYBE=
|
||||
github.com/containers/common v0.63.1/go.mod h1:+3GCotSqNdIqM3sPs152VvW7m5+Mg8Kk+PExT3G9hZw=
|
||||
github.com/containers/image/v5 v5.35.0 h1:T1OeyWp3GjObt47bchwD9cqiaAm/u4O4R9hIWdrdrP8=
|
||||
github.com/containers/image/v5 v5.35.0/go.mod h1:8vTsgb+1gKcBL7cnjyNOInhJQfTUQjJoO2WWkKDoebM=
|
||||
github.com/containers/libtrust v0.0.0-20230121012942-c1716e8a8d01 h1:Qzk5C6cYglewc+UyGf6lc8Mj2UaPTHy/iF2De0/77CA=
|
||||
github.com/containers/libtrust v0.0.0-20230121012942-c1716e8a8d01/go.mod h1:9rfv8iPl1ZP7aqh9YA68wnZv2NUDbXdcdPHVz0pFbPY=
|
||||
github.com/containers/ocicrypt v1.2.0 h1:X14EgRK3xNFvJEfI5O4Qn4T3E25ANudSOZz/sirVuPM=
|
||||
github.com/containers/ocicrypt v1.2.0/go.mod h1:ZNviigQajtdlxIZGibvblVuIFBKIuUI2M0QM12SD31U=
|
||||
github.com/containers/podman/v5 v5.3.1 h1:KuhrhsuLerfzklxZmCf40QA/DLtsuFJs+RTVUNmX8Ao=
|
||||
github.com/containers/podman/v5 v5.3.1/go.mod h1:xUbIlPCLXYMmjs1FHVtNbYWYlDONCFxzZK8MaHMcFlI=
|
||||
github.com/containers/ocicrypt v1.2.1 h1:0qIOTT9DoYwcKmxSt8QJt+VzMY18onl9jUXsxpVhSmM=
|
||||
github.com/containers/ocicrypt v1.2.1/go.mod h1:aD0AAqfMp0MtwqWgHM1bUwe1anx0VazI108CRrSKINQ=
|
||||
github.com/containers/podman/v5 v5.5.1 h1:nFqybTuKX6kLvnQ67hScE0/ihba5k+qHFArXdopnqlI=
|
||||
github.com/containers/podman/v5 v5.5.1/go.mod h1:mxncFv2XqD6ZlXZnBk4JpGmQfkx1+k7KyuBTy1d4Xfc=
|
||||
github.com/containers/psgo v1.9.0 h1:eJ74jzSaCHnWt26OlKZROSyUyRcGDf+gYBdXnxrMW4g=
|
||||
github.com/containers/psgo v1.9.0/go.mod h1:0YoluUm43Mz2UnBIh1P+6V6NWcbpTL5uRtXyOcH0B5A=
|
||||
github.com/containers/storage v1.56.0 h1:DZ9KSkj6M2tvj/4bBoaJu3QDHRl35BwsZ4kmLJS97ZI=
|
||||
github.com/containers/storage v1.56.0/go.mod h1:c6WKowcAlED/DkWGNuL9bvGYqIWCVy7isRMdCSKWNjk=
|
||||
github.com/containers/storage v1.58.0 h1:Q7SyyCCjqgT3wYNgRNIL8o/wUS92heIj2/cc8Sewvcc=
|
||||
github.com/containers/storage v1.58.0/go.mod h1:w7Jl6oG+OpeLGLzlLyOZPkmUso40kjpzgrHUk5tyBlo=
|
||||
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||
github.com/coreos/go-systemd/v22 v22.5.1-0.20231103132048-7d375ecc2b09 h1:OoRAFlvDGCUqDLampLQjk0yeeSGdF9zzst/3G9IkBbc=
|
||||
github.com/coreos/go-systemd/v22 v22.5.1-0.20231103132048-7d375ecc2b09/go.mod h1:m2r/smMKsKwgMSAoFKHaa68ImdCSNuKE1MxvQ64xuCQ=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
||||
github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
|
||||
github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
|
||||
github.com/cyberphone/json-canonicalization v0.0.0-20231217050601-ba74d44ecf5f h1:eHnXnuK47UlSTOQexbzxAZfekVz6i+LKRdj1CU5DPaM=
|
||||
github.com/cyberphone/json-canonicalization v0.0.0-20231217050601-ba74d44ecf5f/go.mod h1:uzvlm1mxhHkdfqitSA92i7Se+S9ksOn3a3qmv/kyOCw=
|
||||
github.com/cyphar/filepath-securejoin v0.3.4 h1:VBWugsJh2ZxJmLFSM06/0qzQyiQX2Qs0ViKrUAcqdZ8=
|
||||
github.com/cyphar/filepath-securejoin v0.3.4/go.mod h1:8s/MCNJREmFK0H02MF6Ihv1nakJe4L/w3WZLHNkvlYM=
|
||||
github.com/cyberphone/json-canonicalization v0.0.0-20241213102144-19d51d7fe467 h1:uX1JmpONuD549D73r6cgnxyUu18Zb7yHAy5AYU0Pm4Q=
|
||||
github.com/cyberphone/json-canonicalization v0.0.0-20241213102144-19d51d7fe467/go.mod h1:uzvlm1mxhHkdfqitSA92i7Se+S9ksOn3a3qmv/kyOCw=
|
||||
github.com/cyphar/filepath-securejoin v0.4.1 h1:JyxxyPEaktOD+GAnqIqTf9A8tHyAG22rowi7HkoSU1s=
|
||||
github.com/cyphar/filepath-securejoin v0.4.1/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||
|
@ -86,14 +86,14 @@ github.com/disiqueira/gotree/v3 v3.0.2 h1:ik5iuLQQoufZBNPY518dXhiO5056hyNBIK9lWh
|
|||
github.com/disiqueira/gotree/v3 v3.0.2/go.mod h1:ZuyjE4+mUQZlbpkI24AmruZKhg3VHEgPLDY8Qk+uUu8=
|
||||
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
|
||||
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
|
||||
github.com/docker/cli v27.3.1+incompatible h1:qEGdFBF3Xu6SCvCYhc7CzaQTlBmqDuzxPDpigSyeKQQ=
|
||||
github.com/docker/cli v27.3.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||
github.com/docker/cli v28.0.4+incompatible h1:pBJSJeNd9QeIWPjRcV91RVJihd/TXB77q1ef64XEu4A=
|
||||
github.com/docker/cli v28.0.4+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||
github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk=
|
||||
github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||
github.com/docker/docker v27.3.1+incompatible h1:KttF0XoteNTicmUtBO0L2tP+J7FGRFTjaEF4k6WdhfI=
|
||||
github.com/docker/docker v27.3.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/docker-credential-helpers v0.8.2 h1:bX3YxiGzFP5sOXWc3bTPEXdEaZSeVMrFgOr3T+zrFAo=
|
||||
github.com/docker/docker-credential-helpers v0.8.2/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M=
|
||||
github.com/docker/docker v28.1.1+incompatible h1:49M11BFLsVO1gxY9UX9p/zwkE/rswggs8AdFmXQw51I=
|
||||
github.com/docker/docker v28.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/docker-credential-helpers v0.9.3 h1:gAm/VtF9wgqJMoxzT3Gj5p4AqIjCBS4wrsOh9yRqcz8=
|
||||
github.com/docker/docker-credential-helpers v0.9.3/go.mod h1:x+4Gbw9aGmChi3qTLZj8Dfn0TD20M/fuWy0E5+WDeCo=
|
||||
github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c=
|
||||
github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc=
|
||||
github.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8=
|
||||
|
@ -107,15 +107,16 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7
|
|||
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
||||
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
|
||||
github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M=
|
||||
github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
||||
github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko=
|
||||
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
|
||||
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
||||
github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg=
|
||||
github.com/gdamore/encoding v1.0.1 h1:YzKZckdBL6jVt2Gc+5p82qhrGiqMdG/eNs6Wy0u3Uhw=
|
||||
github.com/gdamore/encoding v1.0.1/go.mod h1:0Z0cMFinngz9kS1QfMjCP8TY7em3bZYeeklsSDPivEo=
|
||||
github.com/gdamore/tcell/v2 v2.4.1-0.20210905002822-f057f0a857a1/go.mod h1:Az6Jt+M5idSED2YPGtwnfJV0kXohgdCBPmHGSYc1r04=
|
||||
github.com/gdamore/tcell/v2 v2.7.4 h1:sg6/UnTM9jGpZU+oFYAsDahfchWAFW8Xx2yFinNSAYU=
|
||||
github.com/gdamore/tcell/v2 v2.7.4/go.mod h1:dSXtXTSK0VsW1biw65DZLZ2NKr7j0qP/0J7ONmsraWg=
|
||||
github.com/go-jose/go-jose/v4 v4.0.4 h1:VsjPI33J0SB9vQM6PLmNjoHqMQNGPiZ0rHL7Ni7Q6/E=
|
||||
github.com/go-jose/go-jose/v4 v4.0.4/go.mod h1:NKb5HO1EZccyMpiZNbdUw/14tiXNyUJh188dfnMCAfc=
|
||||
github.com/gdamore/tcell/v2 v2.8.1 h1:KPNxyqclpWpWQlPLx6Xui1pMk8S+7+R37h3g07997NU=
|
||||
github.com/gdamore/tcell/v2 v2.8.1/go.mod h1:bj8ori1BG3OYMjmb3IklZVWfZUJ1UBQt9JXrOCOhGWw=
|
||||
github.com/go-jose/go-jose/v4 v4.0.5 h1:M6T8+mKZl/+fNNuFHvGIzDz7BTLQPIounk/b9dw3AaE=
|
||||
github.com/go-jose/go-jose/v4 v4.0.5/go.mod h1:s3P1lRrkT8igV8D9OjyL4WRyHvjB6a4JSllnOrmmBOA=
|
||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
|
||||
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
|
@ -123,8 +124,8 @@ github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
|||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||
github.com/go-openapi/analysis v0.23.0 h1:aGday7OWupfMs+LbmLZG4k0MYXIANxcuBTYUC03zFCU=
|
||||
github.com/go-openapi/analysis v0.23.0/go.mod h1:9mz9ZWaSlV8TvjQHLl2mUW2PbZtemkE8yA5v22ohupo=
|
||||
github.com/go-openapi/errors v0.22.0 h1:c4xY/OLxUBSTiepAg3j/MHuAv5mJhnf53LLMWFB+u/w=
|
||||
github.com/go-openapi/errors v0.22.0/go.mod h1:J3DmZScxCDufmIMsdOuDHxJbdOGC0xtUynjIx092vXE=
|
||||
github.com/go-openapi/errors v0.22.1 h1:kslMRRnK7NCb/CvR1q1VWuEQCEIsBGn5GgKD9e+HYhU=
|
||||
github.com/go-openapi/errors v0.22.1/go.mod h1:+n/5UdIqdVnLIJ6Q9Se8HNGUXYaY6CN8ImWzfi/Gzp0=
|
||||
github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ=
|
||||
github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY=
|
||||
github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ=
|
||||
|
@ -137,8 +138,8 @@ github.com/go-openapi/spec v0.21.0 h1:LTVzPc3p/RzRnkQqLRndbAzjY0d0BCL72A6j3CdL9Z
|
|||
github.com/go-openapi/spec v0.21.0/go.mod h1:78u6VdPw81XU44qEWGhtr982gJ5BWg2c0I5XwVMotYk=
|
||||
github.com/go-openapi/strfmt v0.23.0 h1:nlUS6BCqcnAk0pyhi9Y+kdDVZdZMHfEKQiS4HaMgO/c=
|
||||
github.com/go-openapi/strfmt v0.23.0/go.mod h1:NrtIpfKtWIygRkKVsxh7XQMDQW5HKQl6S5ik2elW+K4=
|
||||
github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE=
|
||||
github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=
|
||||
github.com/go-openapi/swag v0.23.1 h1:lpsStH0n2ittzTnbaSloVZLuB5+fvSY/+hnagBjSNZU=
|
||||
github.com/go-openapi/swag v0.23.1/go.mod h1:STZs8TbRvEQQKUA+JZNAm3EWlgaOBGpyFDqQnDHMef0=
|
||||
github.com/go-openapi/validate v0.24.0 h1:LdfDKwNbpB6Vn40xhTdNZAnfLECL81w+VX3BumrGD58=
|
||||
github.com/go-openapi/validate v0.24.0/go.mod h1:iyeX1sEufmv3nPbBdX3ieNviWnOZaJ1+zquzJEf2BAQ=
|
||||
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
|
||||
|
@ -147,14 +148,14 @@ github.com/go-test/deep v1.1.1 h1:0r/53hagsehfO4bzD2Pgr/+RgHqhmf+k1Bpse2cTu1U=
|
|||
github.com/go-test/deep v1.1.1/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
|
||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/godbus/dbus/v5 v5.1.1-0.20240921181615-a817f3cc4a9e h1:znsZ+BW06LsAtZwQvY/rgWQ3o1q0mnR4SG4q8HCP+3Q=
|
||||
github.com/godbus/dbus/v5 v5.1.1-0.20240921181615-a817f3cc4a9e/go.mod h1:nRJ+j259aT/CW6otoGCHPa1K/lNHLO+UGmW133FNj9s=
|
||||
github.com/godbus/dbus/v5 v5.1.1-0.20241109141217-c266b19b28e9 h1:Kzr9J0S0V2PRxiX6B6xw1kWjzsIyjLO2Ibi4fNTaYBM=
|
||||
github.com/godbus/dbus/v5 v5.1.1-0.20241109141217-c266b19b28e9/go.mod h1:3AAv2+hPq5rdnr5txxxRwiGjPXamgoIHgz9FPBfOp3c=
|
||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ=
|
||||
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw=
|
||||
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.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
|
@ -174,15 +175,16 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
|||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-containerregistry v0.20.2 h1:B1wPJ1SN/S7pB+ZAimcciVD+r+yV/l/DSArMxlbwseo=
|
||||
github.com/google/go-containerregistry v0.20.2/go.mod h1:z38EKdKh4h7IP2gSfUUqEvalZBqs6AoLeWfUy34nQC8=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/google/go-containerregistry v0.20.3 h1:oNx7IdTI936V8CQRveCjaxOiegWwvM7kqkbXTpyiovI=
|
||||
github.com/google/go-containerregistry v0.20.3/go.mod h1:w00pIgBRDVUDFM6bq+Qx8lwNWK+cxgCuX1vd3PIBDNI=
|
||||
github.com/google/go-intervals v0.0.2 h1:FGrVEiUnTRKR8yE04qzXYaJMtnIYqobR5QbblK3ixcM=
|
||||
github.com/google/go-intervals v0.0.2/go.mod h1:MkaR3LNRfeKLPmqgJYs4E66z5InYjmCjbbr4TQlcT6Y=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db h1:097atOisP2aRj7vFgYQBbFN4U4JNXUNYpxael3UzMyo=
|
||||
github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
|
||||
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 h1:BHT72Gu3keYf3ZEu2J0b1vyeLSOYI8bm5wbJM/8yDe8=
|
||||
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
|
@ -191,8 +193,8 @@ github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
|
|||
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
|
||||
github.com/gorilla/schema v1.4.1 h1:jUg5hUjCSDZpNGLuXQOgIWGdlgrIdYvgQ0wZtdK1M3E=
|
||||
github.com/gorilla/schema v1.4.1/go.mod h1:Dg5SSm5PV60mhF2NFaTV1xuYYj8tV8NOPRo4FggUMnM=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 h1:asbCHRVmodnJTuQ3qamDwqVOIjwqUPTYmYuemVOx+Ys=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0/go.mod h1:ggCgvZ2r7uOoQjOyu2Y1NhHmEPPzzuhWgcza5M1Ji1I=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1 h1:VNqngBF40hVlDloBruUehVYC3ArSgIyScOAyMRqBxRg=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1/go.mod h1:RBRO7fro65R6tjKzYgLAFo0t1QEXY1Dp+i/bvpRiqiQ=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
|
||||
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
|
@ -214,8 +216,8 @@ github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4
|
|||
github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
|
||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
|
||||
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
|
||||
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
|
||||
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
|
||||
github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU=
|
||||
github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
|
||||
github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8=
|
||||
|
@ -228,8 +230,8 @@ github.com/letsencrypt/boulder v0.0.0-20240620165639-de9c06129bec h1:2tTW6cDth2T
|
|||
github.com/letsencrypt/boulder v0.0.0-20240620165639-de9c06129bec/go.mod h1:TmwEoGCwIti7BCeJ9hescZgRtatxRE+A72pCoPfmcfk=
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
|
||||
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||
github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4=
|
||||
github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU=
|
||||
github.com/manifoldco/promptui v0.9.0 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYthEiA=
|
||||
github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg=
|
||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||
|
@ -239,11 +241,10 @@ github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D
|
|||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
|
||||
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/mattn/go-sqlite3 v1.14.24 h1:tpSp2G2KyMnnQu99ngJ47EIkWVmliIizyZBfPrBWDRM=
|
||||
github.com/mattn/go-sqlite3 v1.14.24/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||
github.com/mattn/go-sqlite3 v1.14.28 h1:ThEiQrnbtumT+QMknw63Befp/ce/nUPgBPMlRFEum7A=
|
||||
github.com/mattn/go-sqlite3 v1.14.28/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||
github.com/miekg/pkcs11 v1.1.1 h1:Ugu9pdy6vAYku5DEpVWVFPYnzV+bxB+iRdbuFSu7TvU=
|
||||
github.com/miekg/pkcs11 v1.1.1/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=
|
||||
github.com/mistifyio/go-zfs/v3 v3.0.1 h1:YaoXgBePoMA12+S1u/ddkv+QqxcfiZK4prI6HPnkFiU=
|
||||
|
@ -252,14 +253,20 @@ github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyua
|
|||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
|
||||
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
|
||||
github.com/moby/sys/capability v0.3.0 h1:kEP+y6te0gEXIaeQhIi0s7vKs/w0RPoH1qPa6jROcVg=
|
||||
github.com/moby/sys/capability v0.3.0/go.mod h1:4g9IK291rVkms3LKCDOoYlnV8xKwoDTpIrNEE35Wq0I=
|
||||
github.com/moby/sys/atomicwriter v0.1.0 h1:kw5D/EqkBwsBFi0ss9v1VG3wIkVhzGvLklJ+w3A14Sw=
|
||||
github.com/moby/sys/atomicwriter v0.1.0/go.mod h1:Ul8oqv2ZMNHOceF643P6FKPXeCmYtlQMvpizfsSoaWs=
|
||||
github.com/moby/sys/capability v0.4.0 h1:4D4mI6KlNtWMCM1Z/K0i7RV1FkX+DBDHKVJpCndZoHk=
|
||||
github.com/moby/sys/capability v0.4.0/go.mod h1:4g9IK291rVkms3LKCDOoYlnV8xKwoDTpIrNEE35Wq0I=
|
||||
github.com/moby/sys/mountinfo v0.7.2 h1:1shs6aH5s4o5H2zQLn796ADW1wMrIwHsyJ2v9KouLrg=
|
||||
github.com/moby/sys/mountinfo v0.7.2/go.mod h1:1YOa8w8Ih7uW0wALDUgT1dTTSBrZ+HiBLGws92L2RU4=
|
||||
github.com/moby/sys/user v0.3.0 h1:9ni5DlcW5an3SvRSx4MouotOygvzaXbaSrc/wGDFWPo=
|
||||
github.com/moby/sys/user v0.3.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs=
|
||||
github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
|
||||
github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
|
||||
github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU=
|
||||
github.com/moby/sys/sequential v0.6.0/go.mod h1:uyv8EUTrca5PnDsdMGXhZe6CCe8U/UiTWd+lL+7b/Ko=
|
||||
github.com/moby/sys/user v0.4.0 h1:jhcMKit7SA80hivmFJcbB1vqmw//wU61Zdui2eQXuMs=
|
||||
github.com/moby/sys/user v0.4.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs=
|
||||
github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g=
|
||||
github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28=
|
||||
github.com/moby/term v0.5.2 h1:6qk3FJAFDs6i/q3W/pQ97SX192qKfZgGjCQqfCJkgzQ=
|
||||
github.com/moby/term v0.5.2/go.mod h1:d3djjFCrjnB+fl8NJux+EJzu0msscUP+f8it8hPkFLc=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
|
@ -275,40 +282,44 @@ github.com/nxadm/tail v1.4.11 h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY=
|
|||
github.com/nxadm/tail v1.4.11/go.mod h1:OTaG3NK980DZzxbRq6lEuzgU+mug70nY11sMd4JXXHc=
|
||||
github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4=
|
||||
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
||||
github.com/onsi/ginkgo/v2 v2.21.0 h1:7rg/4f3rB88pb5obDgNZrNHrQ4e6WpjonchcpuBRnZM=
|
||||
github.com/onsi/ginkgo/v2 v2.21.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo=
|
||||
github.com/onsi/gomega v1.35.1 h1:Cwbd75ZBPxFSuZ6T+rN/WCb/gOc6YgFBXLlZLhC7Ds4=
|
||||
github.com/onsi/gomega v1.35.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog=
|
||||
github.com/onsi/ginkgo/v2 v2.23.4 h1:ktYTpKJAVZnDT4VjxSbiBenUjmlL/5QkBEocaWXiQus=
|
||||
github.com/onsi/ginkgo/v2 v2.23.4/go.mod h1:Bt66ApGPBFzHyR+JO10Zbt0Gsp4uWxu5mIOTusL46e8=
|
||||
github.com/onsi/gomega v1.37.0 h1:CdEG8g0S133B4OswTDC/5XPSzE1OeP29QOioj2PID2Y=
|
||||
github.com/onsi/gomega v1.37.0/go.mod h1:8D9+Txp43QWKhM24yyOBEdpkzN8FvJyAwecBgsU4KU0=
|
||||
github.com/opencontainers/cgroups v0.0.1 h1:MXjMkkFpKv6kpuirUa4USFBas573sSAY082B4CiHEVA=
|
||||
github.com/opencontainers/cgroups v0.0.1/go.mod h1:s8lktyhlGUqM7OSRL5P7eAW6Wb+kWPNvt4qvVfzA5vs=
|
||||
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.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug=
|
||||
github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM=
|
||||
github.com/opencontainers/runc v1.1.1-0.20240131200429-02120488a4c0 h1:NwSQ/5rex97Rum/xZOMjlDQbbZ8YJKOTihf9sxqHxtE=
|
||||
github.com/opencontainers/runc v1.1.1-0.20240131200429-02120488a4c0/go.mod h1:tBsQqk9ETVlXxzXjk2Xh/1VjxC/U3Gaq5ps/rC/cadE=
|
||||
github.com/opencontainers/runtime-spec v1.2.0 h1:z97+pHb3uELt/yiAWD691HNHQIF07bE7dzrbT927iTk=
|
||||
github.com/opencontainers/runtime-spec v1.2.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||
github.com/opencontainers/runtime-tools v0.9.1-0.20241001195557-6c9570a1678f h1:tGGVO3yF9p5s/mPi3kO1AdoUDK49z0dgQqV0jeT1kik=
|
||||
github.com/opencontainers/runtime-tools v0.9.1-0.20241001195557-6c9570a1678f/go.mod h1:oIH6VwKkaDOO+SIYZpdwrC/0wKYqrfO6E1sG1j3UVws=
|
||||
github.com/opencontainers/selinux v1.11.1 h1:nHFvthhM0qY8/m+vfhJylliSshm8G1jJ2jDMcgULaH8=
|
||||
github.com/opencontainers/selinux v1.11.1/go.mod h1:E5dMC3VPuVvVHDYmi78qvhJp8+M586T4DlDRYpFkyec=
|
||||
github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040=
|
||||
github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M=
|
||||
github.com/opencontainers/runc v1.2.6 h1:P7Hqg40bsMvQGCS4S7DJYhUZOISMLJOB2iGX5COWiPk=
|
||||
github.com/opencontainers/runc v1.2.6/go.mod h1:dOQeFo29xZKBNeRBI0B19mJtfHv68YgCTh1X+YphA+4=
|
||||
github.com/opencontainers/runtime-spec v1.2.1 h1:S4k4ryNgEpxW1dzyqffOmhI1BHYcjzU8lpJfSlR0xww=
|
||||
github.com/opencontainers/runtime-spec v1.2.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||
github.com/opencontainers/runtime-tools v0.9.1-0.20250303011046-260e151b8552 h1:CkXngT0nixZqQUPDVfwVs3GiuhfTqCMk0V+OoHpxIvA=
|
||||
github.com/opencontainers/runtime-tools v0.9.1-0.20250303011046-260e151b8552/go.mod h1:T487Kf80NeF2i0OyVXHiylg217e0buz8pQsa0T791RA=
|
||||
github.com/opencontainers/selinux v1.12.0 h1:6n5JV4Cf+4y0KNXW48TLj5DwfXpvWlxXplUkdTrmPb8=
|
||||
github.com/opencontainers/selinux v1.12.0/go.mod h1:BTPX+bjVbWGXw7ZZWUbdENt8w0htPSrlgOOysQaU62U=
|
||||
github.com/ostreedev/ostree-go v0.0.0-20210805093236-719684c64e4f h1:/UDgs8FGMqwnHagNDPGOlts35QkhAZ8by3DR7nMih7M=
|
||||
github.com/ostreedev/ostree-go v0.0.0-20210805093236-719684c64e4f/go.mod h1:J6OG6YJVEWopen4avK3VNQSnALmmjvniMmni/YFYAwc=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/sftp v1.13.7 h1:uv+I3nNJvlKZIQGSr8JVQLNHFU9YhhNpvC14Y6KgmSM=
|
||||
github.com/pkg/sftp v1.13.7/go.mod h1:KMKI0t3T6hfA+lTR/ssZdunHo+uwq7ghoN09/FSu3DY=
|
||||
github.com/pkg/sftp v1.13.9 h1:4NGkvGudBL7GteO3m6qnaQ4pC0Kvf0onSVc9gR3EWBw=
|
||||
github.com/pkg/sftp v1.13.9/go.mod h1:OBN7bVXdstkFFN/gdnHPUb5TE8eb8G1Rp9wCItqjkkA=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/proglottis/gpgme v0.1.3 h1:Crxx0oz4LKB3QXc5Ea0J19K/3ICfy3ftr5exgUK1AU0=
|
||||
github.com/proglottis/gpgme v0.1.3/go.mod h1:fPbW/EZ0LvwQtH8Hy7eixhp1eF3G39dtx7GUN+0Gmy0=
|
||||
github.com/prometheus/client_golang v1.20.2 h1:5ctymQzZlyOON1666svgwn3s6IKWgfbjsejTMiXIyjg=
|
||||
github.com/prometheus/client_golang v1.20.2/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
|
||||
github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g=
|
||||
github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U=
|
||||
github.com/proglottis/gpgme v0.1.4 h1:3nE7YNA70o2aLjcg63tXMOhPD7bplfE5CBdV+hLAm2M=
|
||||
github.com/proglottis/gpgme v0.1.4/go.mod h1:5LoXMgpE4bttgwwdv9bLs/vwqv3qV7F4glEEZ7mRKrM=
|
||||
github.com/prometheus/client_golang v1.21.1 h1:DOvXXTqVzvkIewV/CDPFdejpMCGeMcbGCQ8YOmu+Ibk=
|
||||
github.com/prometheus/client_golang v1.21.1/go.mod h1:U9NM32ykUErtVBxdvD3zfi+EuFkkaBvMb09mIfe0Zgg=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
|
||||
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
|
||||
github.com/prometheus/common v0.57.0 h1:Ro/rKjwdq9mZn1K5QPctzh+MA4Lp0BuYk5ZZEVhoNcY=
|
||||
github.com/prometheus/common v0.57.0/go.mod h1:7uRPFSUTbfZWsJ7MHY56sqt7hLQu3bxXHDnNhl8E9qI=
|
||||
github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io=
|
||||
github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I=
|
||||
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
|
||||
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
|
||||
github.com/rivo/tview v0.0.0-20220307222120-9994674d60a8 h1:xe+mmCnDN82KhC010l3NfYlA8ZbOuzbXAzSYBa6wbMc=
|
||||
|
@ -317,32 +328,38 @@ github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJ
|
|||
github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
||||
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
|
||||
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
|
||||
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
||||
github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8=
|
||||
github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss=
|
||||
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
|
||||
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
|
||||
github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0=
|
||||
github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY=
|
||||
github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 h1:PKK9DyHxif4LZo+uQSgXNqs0jj5+xZwwfKHgph2lxBw=
|
||||
github.com/santhosh-tekuri/jsonschema/v6 v6.0.1/go.mod h1:JXeL+ps8p7/KNMjDQk3TCwPpBy0wYklyWTfbkIzdIFU=
|
||||
github.com/sebdah/goldie/v2 v2.5.5 h1:rx1mwF95RxZ3/83sdS4Yp7t2C5TCokvWP4TBRbAyEWY=
|
||||
github.com/sebdah/goldie/v2 v2.5.5/go.mod h1:oZ9fp0+se1eapSRjfYbsV/0Hqhbuu3bJVvKI/NNtssI=
|
||||
github.com/secure-systems-lab/go-securesystemslib v0.8.0 h1:mr5An6X45Kb2nddcFlbmfHkLguCE9laoZCUzEEpIZXA=
|
||||
github.com/secure-systems-lab/go-securesystemslib v0.8.0/go.mod h1:UH2VZVuJfCYR8WgMlCU1uFsOUU+KeyrTWcSS73NBOzU=
|
||||
github.com/secure-systems-lab/go-securesystemslib v0.9.0 h1:rf1HIbL64nUpEIZnjLZ3mcNEL9NBPB0iuVjyxvq3LZc=
|
||||
github.com/secure-systems-lab/go-securesystemslib v0.9.0/go.mod h1:DVHKMcZ+V4/woA/peqr+L0joiRXbPpQ042GgJckkFgw=
|
||||
github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8=
|
||||
github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I=
|
||||
github.com/sigstore/fulcio v1.6.4 h1:d86obfxUAG3Y6CYwOx1pdwCZwKmROB6w6927pKOVIRY=
|
||||
github.com/sigstore/fulcio v1.6.4/go.mod h1:Y6bn3i3KGhXpaHsAtYP3Z4Np0+VzCo1fLv8Ci6mbPDs=
|
||||
github.com/sigstore/rekor v1.3.6 h1:QvpMMJVWAp69a3CHzdrLelqEqpTM3ByQRt5B5Kspbi8=
|
||||
github.com/sigstore/rekor v1.3.6/go.mod h1:JDTSNNMdQ/PxdsS49DJkJ+pRJCO/83nbR5p3aZQteXc=
|
||||
github.com/sigstore/sigstore v1.8.9 h1:NiUZIVWywgYuVTxXmRoTT4O4QAGiTEKup4N1wdxFadk=
|
||||
github.com/sigstore/sigstore v1.8.9/go.mod h1:d9ZAbNDs8JJfxJrYmulaTazU3Pwr8uLL9+mii4BNR3w=
|
||||
github.com/sigstore/fulcio v1.6.6 h1:XaMYX6TNT+8n7Npe8D94nyZ7/ERjEsNGFC+REdi/wzw=
|
||||
github.com/sigstore/fulcio v1.6.6/go.mod h1:BhQ22lwaebDgIxVBEYOOqLRcN5+xOV+C9bh/GUXRhOk=
|
||||
github.com/sigstore/protobuf-specs v0.4.1 h1:5SsMqZbdkcO/DNHudaxuCUEjj6x29tS2Xby1BxGU7Zc=
|
||||
github.com/sigstore/protobuf-specs v0.4.1/go.mod h1:+gXR+38nIa2oEupqDdzg4qSBT0Os+sP7oYv6alWewWc=
|
||||
github.com/sigstore/rekor v1.3.10 h1:/mSvRo4MZ/59ECIlARhyykAlQlkmeAQpvBPlmJtZOCU=
|
||||
github.com/sigstore/rekor v1.3.10/go.mod h1:JvryKJ40O0XA48MdzYUPu0y4fyvqt0C4iSY7ri9iu3A=
|
||||
github.com/sigstore/sigstore v1.9.3 h1:y2qlTj+vh+Or3ictKuR3JUFawZPdDxAjrWkeFhon0OQ=
|
||||
github.com/sigstore/sigstore v1.9.3/go.mod h1:VwYkiw0G0dRtwL25KSs04hCyVFF6CYMd/qvNeYrl7EQ=
|
||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/skeema/knownhosts v1.3.0 h1:AM+y0rI04VksttfwjkSTNQorvGqmwATnvnAHpSgc0LY=
|
||||
github.com/skeema/knownhosts v1.3.0/go.mod h1:sPINvnADmT/qYH1kfv+ePMmOBTH6Tbl7b5LvTDjFK7M=
|
||||
github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
|
||||
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/skeema/knownhosts v1.3.1 h1:X2osQ+RAjK76shCbvhHHHVl3ZlgDm8apHEHFqRjnBY8=
|
||||
github.com/skeema/knownhosts v1.3.1/go.mod h1:r7KTdC8l4uxWRyK2TpQZ/1o5HaSzh06ePQNxPwTcfiY=
|
||||
github.com/smallstep/pkcs7 v0.1.1 h1:x+rPdt2W088V9Vkjho4KtoggyktZJlMduZAtRHm68LU=
|
||||
github.com/smallstep/pkcs7 v0.1.1/go.mod h1:dL6j5AIz9GHjVEBTXtW+QliALcgM19RtXaTeyxI+AfA=
|
||||
github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo=
|
||||
github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0=
|
||||
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
|
||||
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/stefanberger/go-pkcs11uri v0.0.0-20230803200340-78284954bff6 h1:pnnLyeX7o/5aX8qUQ69P/mLojDqwda8hFOCBTmP/6hw=
|
||||
github.com/stefanberger/go-pkcs11uri v0.0.0-20230803200340-78284954bff6/go.mod h1:39R/xuhNgVhi+K0/zst4TLrJrVmbm6LVgl4A0+ZFS5M=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
|
@ -353,22 +370,22 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
|||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/sylabs/sif/v2 v2.19.1 h1:1eeMmFc8elqJe60ZiWwXgL3gMheb0IP4GmNZ4q0IEA0=
|
||||
github.com/sylabs/sif/v2 v2.19.1/go.mod h1:U1SUhvl8X1JIxAylC0DYz1fa/Xba6EMZD1dGPGBH83E=
|
||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/sylabs/sif/v2 v2.21.1 h1:GZ0b5//AFAqJEChd8wHV/uSKx/l1iuGYwjR8nx+4wPI=
|
||||
github.com/sylabs/sif/v2 v2.21.1/go.mod h1:YoqEGQnb5x/ItV653bawXHZJOXQaEWpGwHsSD3YePJI=
|
||||
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/tchap/go-patricia/v2 v2.3.1 h1:6rQp39lgIYZ+MHmdEq4xzuk1t7OdC35z/xm0BGhTkes=
|
||||
github.com/tchap/go-patricia/v2 v2.3.1/go.mod h1:VZRHKAb53DLaG+nA9EaYYiaEx6YztwDlLElMsnSHD4k=
|
||||
github.com/tchap/go-patricia/v2 v2.3.2 h1:xTHFutuitO2zqKAQ5rCROYgUb7Or/+IC3fts9/Yc7nM=
|
||||
github.com/tchap/go-patricia/v2 v2.3.2/go.mod h1:VZRHKAb53DLaG+nA9EaYYiaEx6YztwDlLElMsnSHD4k=
|
||||
github.com/titanous/rocacheck v0.0.0-20171023193734-afe73141d399 h1:e/5i7d4oYZ+C1wj2THlRK+oAhjeS/TRQwMfkIuet3w0=
|
||||
github.com/titanous/rocacheck v0.0.0-20171023193734-afe73141d399/go.mod h1:LdwHTNJT99C5fTAzDz0ud328OgXz+gierycbcIx2fRs=
|
||||
github.com/ulikunitz/xz v0.5.12 h1:37Nm15o69RwBkXM0J6A5OlE67RZTfzUxTj8fB3dfcsc=
|
||||
github.com/ulikunitz/xz v0.5.12/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
||||
github.com/vbatts/tar-split v0.11.6 h1:4SjTW5+PU11n6fZenf2IPoV8/tz3AaYHMWjf23envGs=
|
||||
github.com/vbatts/tar-split v0.11.6/go.mod h1:dqKNtesIOr2j2Qv3W/cHjnvk9I8+G7oAkFDFN6TCBEI=
|
||||
github.com/vbauerster/mpb/v8 v8.8.3 h1:dTOByGoqwaTJYPubhVz3lO5O6MK553XVgUo33LdnNsQ=
|
||||
github.com/vbauerster/mpb/v8 v8.8.3/go.mod h1:JfCCrtcMsJwP6ZwMn9e5LMnNyp3TVNpUWWkN+nd4EWk=
|
||||
github.com/vbatts/tar-split v0.12.1 h1:CqKoORW7BUWBe7UL/iqTVvkTBOF8UvOMKOIZykxnnbo=
|
||||
github.com/vbatts/tar-split v0.12.1/go.mod h1:eF6B6i6ftWQcDqEn3/iGFRFRo8cBIMSJVOpnNdfTMFA=
|
||||
github.com/vbauerster/mpb/v8 v8.9.3 h1:PnMeF+sMvYv9u23l6DO6Q3+Mdj408mjLRXIzmUmU2Z8=
|
||||
github.com/vbauerster/mpb/v8 v8.9.3/go.mod h1:hxS8Hz4C6ijnppDSIX6LjG8FYJSoPo9iIOcE53Zik0c=
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo=
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0=
|
||||
|
@ -380,36 +397,42 @@ github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9dec
|
|||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
go.mongodb.org/mongo-driver v1.14.0 h1:P98w8egYRjYe3XDjxhYJagTokP/H6HzlsnojRgZRd80=
|
||||
go.mongodb.org/mongo-driver v1.14.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c=
|
||||
go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352 h1:CCriYyAfq1Br1aIYettdHZTy8mBTIPo7We18TuO/bak=
|
||||
go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk=
|
||||
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
|
||||
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 h1:4K4tsIXefpVJtvA/8srF4V4y0akAoPHkIslgAkjixJA=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0/go.mod h1:jjdQuTGVsXV4vSs+CJ2qYDeDPf9yIJV23qlIzBm73Vg=
|
||||
go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo=
|
||||
go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.27.0 h1:R9DE4kQ4k+YtfLI2ULwX82VtNQ2J8yZmA7ZIF/D+7Mc=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.27.0/go.mod h1:OQFyQVrDlbe+R7xrEyDr/2Wr67Ol0hRUgsfA+V5A95s=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.21.0 h1:digkEZCJWobwBqMwC0cwCq8/wkkRy/OowZg5OArWZrM=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.21.0/go.mod h1:/OpE/y70qVkndM0TrxT4KBoN3RsFZP0QaofcfYrj76I=
|
||||
go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q=
|
||||
go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s=
|
||||
go.opentelemetry.io/otel/sdk v1.28.0 h1:b9d7hIry8yZsgtbmM0DKyPWMMUMlK9NEKuIG4aBqWyE=
|
||||
go.opentelemetry.io/otel/sdk v1.28.0/go.mod h1:oYj7ClPUA7Iw3m+r7GeEjz0qckQRJK2B8zjcZEfu7Pg=
|
||||
go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g=
|
||||
go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI=
|
||||
go.opentelemetry.io/proto/otlp v1.2.0 h1:pVeZGk7nXDC9O2hncA6nHldxEjm6LByfA2aN8IOkz94=
|
||||
go.opentelemetry.io/proto/otlp v1.2.0/go.mod h1:gGpR8txAl5M03pDhMC79G6SdqNV26naRm/KDsgaHD8A=
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
|
||||
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 h1:CV7UdSGJt/Ao6Gp4CXckLxVRRsRgDHoI8XjbL3PDl8s=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0/go.mod h1:FRmFuRJfag1IZ2dPkHnEoSFVgTVPUd2qf5Vi69hLb8I=
|
||||
go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY=
|
||||
go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.33.0 h1:Vh5HayB/0HHfOQA7Ctx69E/Y/DcQSMPpKANYVMQ7fBA=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.33.0/go.mod h1:cpgtDBaqD/6ok/UG0jT15/uKjAY8mRA53diogHBg3UI=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.33.0 h1:wpMfgF8E1rkrT1Z6meFh1NDtownE9Ii3n3X2GJYjsaU=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.33.0/go.mod h1:wAy0T/dUbs468uOlkT31xjvqQgEVXv58BRFWEgn5v/0=
|
||||
go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ=
|
||||
go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE=
|
||||
go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A=
|
||||
go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce1EK0Gyvahk=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.34.0/go.mod h1:jQ/r8Ze28zRKoNRdkjCZxfs6YvBTG1+YIqyFVFYec5w=
|
||||
go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k=
|
||||
go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE=
|
||||
go.opentelemetry.io/proto/otlp v1.4.0 h1:TA9WRvW6zMwP+Ssb6fLoUIuirti1gGbP28GcKG1jgeg=
|
||||
go.opentelemetry.io/proto/otlp v1.4.0/go.mod h1:PPBWZIP98o2ElSqI35IHfu7hIhSwvc5N38Jw8pXuGFY=
|
||||
go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs=
|
||||
go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
|
||||
golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ=
|
||||
golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg=
|
||||
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
|
||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
||||
golang.org/x/crypto v0.30.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
|
||||
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
|
||||
golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM=
|
||||
golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c h1:7dEasQXItcW1xKJ2+gg5VOiBnqWrJc+rq0DPKyvvdbY=
|
||||
golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c/go.mod h1:NQtJDoLvd6faHhE7m4T/1IY708gDefGGjR/iUW8yQQ8=
|
||||
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-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
|
@ -417,6 +440,9 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
|||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
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-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
|
@ -430,8 +456,11 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
|
|||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4=
|
||||
golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU=
|
||||
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
|
||||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
||||
golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
|
||||
golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
|
||||
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=
|
||||
|
@ -440,8 +469,12 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ
|
|||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ=
|
||||
golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
||||
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8=
|
||||
golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
|
@ -461,31 +494,40 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s=
|
||||
golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
|
||||
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
|
||||
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
|
||||
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
||||
golang.org/x/term v0.26.0 h1:WEQa6V3Gja/BhNxg540hBip/kkaYtRg3cxg4oXSw4AU=
|
||||
golang.org/x/term v0.26.0/go.mod h1:Si5m1o57C5nBNQo5z1iq+XDijt21BDBDp2bK0QI8e3E=
|
||||
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
|
||||
golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
|
||||
golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek=
|
||||
golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg=
|
||||
golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug=
|
||||
golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4=
|
||||
golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U=
|
||||
golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
|
||||
golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M=
|
||||
golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA=
|
||||
golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0=
|
||||
golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
|
@ -496,8 +538,10 @@ golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roY
|
|||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ=
|
||||
golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0=
|
||||
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
|
||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
|
||||
golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc=
|
||||
golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
@ -507,18 +551,17 @@ 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-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||
google.golang.org/genproto v0.0.0-20240823204242-4ba0660f739c h1:TYOEhrQMrNDTAd2rX9m+WgGr8Ku6YNuj1D7OX6rWSok=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 h1:wKguEg1hsxI2/L3hUYrpo1RVi48K+uTyzKqprwLXsb8=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb h1:p31xT4yrYrSM/G4Sn2+TNUkVhFCbG9y8itM2S6Th950=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:jbe3Bkdp+Dh2IrslsFCklNhweNTBgSYanP1UXhJDhKg=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250313205543-e70fdf4c4cb4 h1:iK2jbkWL86DXjEx0qiHcRE9dE4/Ahua5k6V8OWFb//c=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250313205543-e70fdf4c4cb4/go.mod h1:LuRYeWDFV6WOn90g357N17oMCaxpgCnbi/44qJvDn2I=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
||||
google.golang.org/grpc v1.67.0 h1:IdH9y6PF5MPSdAntIcpjQ+tXO41pcQsfZV2RxtQgVcw=
|
||||
google.golang.org/grpc v1.67.0/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA=
|
||||
google.golang.org/grpc v1.71.0 h1:kF77BGdPTQ4/JZWMlb9VpJ5pa25aqvVqogsxNHHdeBg=
|
||||
google.golang.org/grpc v1.71.0/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec=
|
||||
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=
|
||||
|
@ -528,8 +571,8 @@ google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2
|
|||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||
google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA=
|
||||
google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
|
||||
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
|
@ -538,13 +581,11 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWD
|
|||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
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.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU=
|
||||
gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU=
|
||||
gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q=
|
||||
gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA=
|
||||
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=
|
||||
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
|
||||
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
|
||||
tags.cncf.io/container-device-interface v0.8.0 h1:8bCFo/g9WODjWx3m6EYl3GfUG31eKJbaggyBDxEldRc=
|
||||
tags.cncf.io/container-device-interface v0.8.0/go.mod h1:Apb7N4VdILW0EVdEMRYXIDVRZfNJZ+kmEUss2kRRQ6Y=
|
||||
tags.cncf.io/container-device-interface v1.0.1 h1:KqQDr4vIlxwfYh0Ed/uJGVgX+CHAkahrgabg6Q8GYxc=
|
||||
tags.cncf.io/container-device-interface v1.0.1/go.mod h1:JojJIOeW3hNbcnOH2q0NrWNha/JuHoDZcmYxAZwb2i0=
|
||||
|
|
|
@ -23,11 +23,16 @@ var ErrInvalidCreateTimeout = errors.New("invalid container create timeout value
|
|||
// CreateOptions container create options.
|
||||
type CreateOptions struct {
|
||||
Name string
|
||||
Command string
|
||||
Labels []string
|
||||
Image string
|
||||
Remove bool
|
||||
Privileged bool
|
||||
Timeout string
|
||||
Interactive bool
|
||||
TTY bool
|
||||
Detach bool
|
||||
Secret []string
|
||||
WorkDir string
|
||||
EnvVars []string
|
||||
EnvFile []string
|
||||
|
@ -71,12 +76,39 @@ type CreateOptions struct {
|
|||
HealthStartupRetries string
|
||||
HealthStartupSuccess string
|
||||
HealthStartupTimeout string
|
||||
HealthLogDestination string
|
||||
HealthMaxLogSize string
|
||||
HealthMaxLogCount string
|
||||
Memory string
|
||||
MemoryReservation string
|
||||
MemorySwap string
|
||||
MemorySwappiness string
|
||||
CPUs string
|
||||
CPUShares string
|
||||
CPUPeriod string
|
||||
CPUQuota string
|
||||
CPURtPeriod string
|
||||
CPURtRuntime string
|
||||
CPUSetCPUs string
|
||||
CPUSetMems string
|
||||
SHMSize string
|
||||
SHMSizeSystemd string
|
||||
NamespaceCgroup string
|
||||
NamespacePid string
|
||||
NamespaceIpc string
|
||||
NamespaceUser string
|
||||
NamespaceUts string
|
||||
NamespaceUidmap string
|
||||
NamespaceSubuidName string
|
||||
NamespaceGidmap string
|
||||
NamespaceSubgidName string
|
||||
}
|
||||
|
||||
// Create creates a new container.
|
||||
func Create(opts CreateOptions) ([]string, error) { //nolint:cyclop,gocognit,gocyclo
|
||||
func Create(opts CreateOptions, run bool) ([]string, string, error) { //nolint:cyclop,gocognit,gocyclo,maintidx
|
||||
var (
|
||||
warningResponse []string
|
||||
containerID string
|
||||
createOptions entities.ContainerCreateOptions
|
||||
)
|
||||
|
||||
|
@ -85,7 +117,7 @@ func Create(opts CreateOptions) ([]string, error) { //nolint:cyclop,gocognit,goc
|
|||
|
||||
conn, err := registry.GetConnection()
|
||||
if err != nil {
|
||||
return warningResponse, err
|
||||
return warningResponse, containerID, err
|
||||
}
|
||||
|
||||
if len(opts.Labels) > 0 {
|
||||
|
@ -99,7 +131,7 @@ func Create(opts CreateOptions) ([]string, error) { //nolint:cyclop,gocognit,goc
|
|||
if opts.Timeout != "" {
|
||||
timeout, err := strconv.Atoi(opts.Timeout)
|
||||
if err != nil {
|
||||
return warningResponse, fmt.Errorf("%w: %s", ErrInvalidCreateTimeout, opts.Timeout)
|
||||
return warningResponse, containerID, fmt.Errorf("%w: %s", ErrInvalidCreateTimeout, opts.Timeout)
|
||||
}
|
||||
|
||||
createOptions.Timeout = uint(timeout) //nolint:gosec
|
||||
|
@ -115,7 +147,7 @@ func Create(opts CreateOptions) ([]string, error) { //nolint:cyclop,gocognit,goc
|
|||
|
||||
createOptions.Net, err = containerNetworkOptions(opts)
|
||||
if err != nil {
|
||||
return warningResponse, err
|
||||
return warningResponse, containerID, err
|
||||
}
|
||||
|
||||
if opts.Pod != "" {
|
||||
|
@ -211,31 +243,179 @@ func Create(opts CreateOptions) ([]string, error) { //nolint:cyclop,gocognit,goc
|
|||
createOptions.GroupEntry = opts.GroupEntry
|
||||
}
|
||||
|
||||
// add secrets
|
||||
if len(opts.Secret) > 0 {
|
||||
createOptions.Secrets = opts.Secret
|
||||
}
|
||||
|
||||
if run {
|
||||
createOptions.Interactive = opts.Interactive
|
||||
createOptions.TTY = opts.TTY
|
||||
}
|
||||
|
||||
// add healthcheck options
|
||||
if err := containerHealthOptions(&createOptions, opts); err != nil {
|
||||
return warningResponse, err
|
||||
return warningResponse, containerID, err
|
||||
}
|
||||
|
||||
// add resources
|
||||
if opts.Memory != "" {
|
||||
createOptions.Memory = opts.Memory
|
||||
}
|
||||
|
||||
if opts.MemoryReservation != "" {
|
||||
createOptions.MemoryReservation = opts.MemoryReservation
|
||||
}
|
||||
|
||||
if opts.MemorySwap != "" {
|
||||
createOptions.MemorySwap = opts.MemorySwap
|
||||
}
|
||||
|
||||
if opts.MemorySwappiness != "" {
|
||||
val, err := strconv.Atoi(opts.MemorySwappiness)
|
||||
if err != nil {
|
||||
return warningResponse, containerID, err
|
||||
}
|
||||
|
||||
createOptions.MemorySwappiness = int64(val)
|
||||
}
|
||||
|
||||
if opts.CPUs != "" {
|
||||
val, err := strconv.ParseFloat(opts.CPUs, 64)
|
||||
if err != nil {
|
||||
return warningResponse, containerID, err
|
||||
}
|
||||
|
||||
createOptions.CPUS = val
|
||||
}
|
||||
|
||||
if opts.CPUShares != "" {
|
||||
val, err := strconv.ParseUint(opts.CPUShares, 10, 64)
|
||||
if err != nil {
|
||||
return warningResponse, containerID, err
|
||||
}
|
||||
|
||||
createOptions.CPUShares = val
|
||||
}
|
||||
|
||||
if opts.CPUPeriod != "" {
|
||||
val, err := strconv.ParseUint(opts.CPUPeriod, 10, 64)
|
||||
if err != nil {
|
||||
return warningResponse, containerID, err
|
||||
}
|
||||
|
||||
createOptions.CPUPeriod = val
|
||||
}
|
||||
|
||||
if opts.CPURtPeriod != "" {
|
||||
val, err := strconv.ParseUint(opts.CPURtPeriod, 10, 64)
|
||||
if err != nil {
|
||||
return warningResponse, containerID, err
|
||||
}
|
||||
|
||||
createOptions.CPURTPeriod = val
|
||||
}
|
||||
|
||||
if opts.CPUQuota != "" {
|
||||
val, err := strconv.Atoi(opts.CPUQuota)
|
||||
if err != nil {
|
||||
return warningResponse, containerID, err
|
||||
}
|
||||
|
||||
createOptions.CPUQuota = int64(val)
|
||||
}
|
||||
|
||||
if opts.CPURtRuntime != "" {
|
||||
val, err := strconv.Atoi(opts.CPURtRuntime)
|
||||
if err != nil {
|
||||
return warningResponse, containerID, err
|
||||
}
|
||||
|
||||
createOptions.CPURTRuntime = int64(val)
|
||||
}
|
||||
|
||||
if opts.CPUSetCPUs != "" {
|
||||
createOptions.CPUSetCPUs = opts.CPUSetCPUs
|
||||
}
|
||||
|
||||
if opts.CPUSetMems != "" {
|
||||
createOptions.CPUSetMems = opts.CPUSetMems
|
||||
}
|
||||
|
||||
if opts.SHMSize != "" {
|
||||
createOptions.ShmSize = opts.SHMSize
|
||||
}
|
||||
|
||||
if opts.SHMSizeSystemd != "" {
|
||||
createOptions.ShmSizeSystemd = opts.SHMSizeSystemd
|
||||
}
|
||||
|
||||
// namespace options
|
||||
if opts.NamespaceCgroup != "" {
|
||||
createOptions.CgroupNS = opts.NamespaceCgroup
|
||||
}
|
||||
|
||||
if opts.NamespaceIpc != "" {
|
||||
createOptions.IPC = opts.NamespaceIpc
|
||||
}
|
||||
|
||||
if opts.NamespacePid != "" {
|
||||
createOptions.PID = opts.NamespacePid
|
||||
}
|
||||
|
||||
if opts.NamespaceUser != "" {
|
||||
createOptions.UserNS = opts.NamespaceUser
|
||||
}
|
||||
|
||||
if opts.NamespaceUts != "" {
|
||||
createOptions.UTS = opts.NamespaceUts
|
||||
}
|
||||
|
||||
if opts.NamespaceUidmap != "" {
|
||||
createOptions.UIDMap = []string{opts.NamespaceUidmap}
|
||||
}
|
||||
|
||||
if opts.NamespaceSubuidName != "" {
|
||||
createOptions.SubUIDName = opts.NamespaceSubuidName
|
||||
}
|
||||
|
||||
if opts.NamespaceGidmap != "" {
|
||||
createOptions.GIDMap = []string{opts.NamespaceGidmap}
|
||||
}
|
||||
|
||||
if opts.NamespaceSubgidName != "" {
|
||||
createOptions.SubGIDName = opts.NamespaceSubgidName
|
||||
}
|
||||
|
||||
// generate spec
|
||||
s := specgen.NewSpecGenerator(opts.Name, false)
|
||||
if err := specgenutil.FillOutSpecGen(s, &createOptions, nil); err != nil {
|
||||
return warningResponse, err
|
||||
return warningResponse, containerID, err
|
||||
}
|
||||
|
||||
// container image
|
||||
s.Image = opts.Image
|
||||
|
||||
// command
|
||||
cmd := strings.TrimSpace(opts.Command)
|
||||
if cmd != "" {
|
||||
s.Command = strings.Split(cmd, " ")
|
||||
}
|
||||
|
||||
// validate spec
|
||||
if err := s.Validate(); err != nil {
|
||||
return warningResponse, err
|
||||
return warningResponse, containerID, err
|
||||
}
|
||||
|
||||
response, err := containers.CreateWithSpec(conn, s, &containers.CreateOptions{})
|
||||
if err != nil {
|
||||
return warningResponse, err
|
||||
return warningResponse, containerID, err
|
||||
}
|
||||
|
||||
warningResponse = response.Warnings
|
||||
containerID = response.ID
|
||||
|
||||
return warningResponse, nil
|
||||
return warningResponse, containerID, nil
|
||||
}
|
||||
|
||||
func containerHealthOptions(createOptions *entities.ContainerCreateOptions, opts CreateOptions) error { //nolint:cyclop
|
||||
|
@ -246,6 +426,7 @@ func containerHealthOptions(createOptions *entities.ContainerCreateOptions, opts
|
|||
createOptions.HealthTimeout = define.DefaultHealthCheckTimeout
|
||||
createOptions.StartupHCTimeout = define.DefaultHealthCheckTimeout
|
||||
createOptions.HealthOnFailure = opts.HealthOnFailure
|
||||
createOptions.HealthLogDestination = opts.HealthLogDestination
|
||||
|
||||
if opts.HealthCmd == "" {
|
||||
createOptions.HealthCmd = "none"
|
||||
|
@ -255,6 +436,26 @@ func containerHealthOptions(createOptions *entities.ContainerCreateOptions, opts
|
|||
|
||||
createOptions.HealthCmd = opts.HealthCmd
|
||||
|
||||
if opts.HealthMaxLogCount != "" {
|
||||
logCount, err := strconv.ParseUint(opts.HealthMaxLogCount, 10, 32)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
logCountWd := uint(logCount)
|
||||
createOptions.HealthMaxLogCount = logCountWd
|
||||
}
|
||||
|
||||
if opts.HealthMaxLogSize != "" {
|
||||
logSize, err := strconv.ParseUint(opts.HealthMaxLogSize, 10, 32)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
logSizeWd := uint(logSize)
|
||||
createOptions.HealthMaxLogSize = logSizeWd
|
||||
}
|
||||
|
||||
if opts.HealthInterval != "" {
|
||||
createOptions.HealthInterval = opts.HealthInterval
|
||||
}
|
||||
|
|
|
@ -89,7 +89,7 @@ func ResizeExecTty(id string, height int, width int) {
|
|||
}
|
||||
}
|
||||
|
||||
// Exec returns the diff of the specified container ID.
|
||||
// Exec executes command in a given sessionOD.
|
||||
func Exec(sessionID string, opts ExecOption) { //nolint:cyclop
|
||||
log.Debug().Msgf("pdcs: podman container session (%s) exec %v", sessionID, opts)
|
||||
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
package containers
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/containers/podman-tui/pdcs/registry"
|
||||
"github.com/containers/podman/v5/pkg/bindings/containers"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
// RunInitAttach will init container for run and attach.
|
||||
func RunInitAttach(cntID string, stdin io.Reader, stdout io.Writer, attachReady chan bool, detachKey string) error {
|
||||
log.Debug().Msgf("pdcs: podman container run init attach %s", cntID)
|
||||
|
||||
conn, err := registry.GetConnection()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
attachOptions := new(containers.AttachOptions)
|
||||
attachOptions.WithDetachKeys(detachKey)
|
||||
|
||||
if err := containers.ContainerInit(conn, cntID, new(containers.InitOptions)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := containers.Attach(conn, cntID, stdin, stdout, stdout, attachReady, attachOptions); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -3,6 +3,7 @@ package pods
|
|||
import (
|
||||
"encoding/json"
|
||||
"net"
|
||||
"strconv"
|
||||
|
||||
"github.com/containers/common/libnetwork/types"
|
||||
"github.com/containers/common/pkg/config"
|
||||
|
@ -19,26 +20,42 @@ import (
|
|||
|
||||
// CreateOptions implements pods create spec options.
|
||||
type CreateOptions struct {
|
||||
Name string
|
||||
NoHost bool
|
||||
Labels map[string]string
|
||||
DNSServer []string
|
||||
DNSOptions []string
|
||||
DNSSearchDomain []string
|
||||
Infra bool
|
||||
InfraCommand string
|
||||
InfraImage string
|
||||
Hostname string
|
||||
IPAddress string
|
||||
MacAddress string
|
||||
AddHost []string
|
||||
Network string
|
||||
Publish []string
|
||||
SecurityOpts []string
|
||||
Name string
|
||||
NoHost bool
|
||||
Labels map[string]string
|
||||
DNSServer []string
|
||||
DNSOptions []string
|
||||
DNSSearchDomain []string
|
||||
Infra bool
|
||||
InfraCommand string
|
||||
InfraImage string
|
||||
Hostname string
|
||||
IPAddress string
|
||||
MacAddress string
|
||||
AddHost []string
|
||||
Network string
|
||||
Publish []string
|
||||
SecurityOpts []string
|
||||
Memory string
|
||||
MemorySwap string
|
||||
CPUs string
|
||||
CPUShares string
|
||||
CPUSetCPUs string
|
||||
CPUSetMems string
|
||||
ShmSize string
|
||||
ShmSizeSystemd string
|
||||
NamespaceShare []string
|
||||
NamespacePid string
|
||||
NamespaceUser string
|
||||
NamespaceUts string
|
||||
NamespaceUidmap string
|
||||
NamespaceSubuidName string
|
||||
NamespaceGidmap string
|
||||
NamespaceSubgidName string
|
||||
}
|
||||
|
||||
// Create creates a new pod.
|
||||
func Create(opts CreateOptions) error { //nolint:cyclop
|
||||
func Create(opts CreateOptions) error { //nolint:cyclop,gocognit,gocyclo
|
||||
log.Debug().Msgf("pdcs: podman pod create %v", opts)
|
||||
|
||||
var createOptions entities.PodCreateOptions
|
||||
|
@ -57,6 +74,88 @@ func Create(opts CreateOptions) error { //nolint:cyclop
|
|||
|
||||
createOptions.Name = opts.Name
|
||||
createOptions.Labels = opts.Labels
|
||||
createOptions.Infra = opts.Infra
|
||||
|
||||
// resources
|
||||
if opts.Memory != "" {
|
||||
infraOptions.Memory = opts.Memory
|
||||
}
|
||||
|
||||
if opts.MemorySwap != "" {
|
||||
infraOptions.MemorySwap = opts.MemorySwap
|
||||
}
|
||||
|
||||
if opts.CPUs != "" {
|
||||
val, err := strconv.ParseFloat(opts.CPUs, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
infraOptions.CPUS = val
|
||||
}
|
||||
|
||||
if opts.CPUShares != "" {
|
||||
val, err := strconv.ParseUint(opts.CPUShares, 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
infraOptions.CPUShares = val
|
||||
}
|
||||
|
||||
if opts.CPUSetCPUs != "" {
|
||||
infraOptions.CPUSetCPUs = opts.CPUSetCPUs
|
||||
}
|
||||
|
||||
if opts.CPUSetMems != "" {
|
||||
infraOptions.CPUSetMems = opts.CPUSetMems
|
||||
}
|
||||
|
||||
if opts.ShmSize != "" {
|
||||
infraOptions.ShmSize = opts.ShmSize
|
||||
}
|
||||
|
||||
if opts.ShmSizeSystemd != "" {
|
||||
infraOptions.ShmSizeSystemd = opts.ShmSizeSystemd
|
||||
}
|
||||
|
||||
// namespace
|
||||
if len(opts.NamespaceShare) > 0 {
|
||||
createOptions.Share = opts.NamespaceShare
|
||||
}
|
||||
|
||||
if opts.NamespacePid != "" {
|
||||
createOptions.Pid = opts.NamespacePid
|
||||
}
|
||||
|
||||
if opts.NamespaceUser != "" {
|
||||
userns, err := specgen.ParseUserNamespace(opts.NamespaceUser)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
createOptions.Userns = userns
|
||||
}
|
||||
|
||||
if opts.NamespaceUts != "" {
|
||||
createOptions.Uts = opts.NamespaceUts
|
||||
}
|
||||
|
||||
if opts.NamespaceUidmap != "" {
|
||||
infraOptions.UIDMap = []string{opts.NamespaceUidmap}
|
||||
}
|
||||
|
||||
if opts.NamespaceSubuidName != "" {
|
||||
infraOptions.SubUIDName = opts.NamespaceSubuidName
|
||||
}
|
||||
|
||||
if opts.NamespaceGidmap != "" {
|
||||
infraOptions.GIDMap = []string{opts.NamespaceGidmap}
|
||||
}
|
||||
|
||||
if opts.NamespaceSubgidName != "" {
|
||||
infraOptions.SubGIDName = opts.NamespaceSubgidName
|
||||
}
|
||||
|
||||
// network options
|
||||
podNetworkOptions, err := podNetworkOptions(opts)
|
||||
|
@ -64,8 +163,6 @@ func Create(opts CreateOptions) error { //nolint:cyclop
|
|||
return err
|
||||
}
|
||||
|
||||
createOptions.Infra = opts.Infra
|
||||
|
||||
if createOptions.Infra { //nolint:nestif
|
||||
if opts.InfraImage != "" {
|
||||
createOptions.InfraImage = opts.InfraImage
|
||||
|
|
|
@ -15,8 +15,8 @@
|
|||
%global git0 https://%{import_path}
|
||||
|
||||
Name: podman-tui
|
||||
Version: 1.3.0
|
||||
Release: 1%{?dist}
|
||||
Version: 1.7.0
|
||||
Release: dev.1%{?dist}
|
||||
Summary: Podman Terminal User Interface
|
||||
License: ASL 2.0
|
||||
URL: %{git0}
|
||||
|
@ -60,6 +60,58 @@ install -p ./bin/%{name} %{buildroot}%{_bindir}
|
|||
%{_bindir}/%{name}
|
||||
|
||||
%changelog
|
||||
* Wed May 28 2025 Navid Yaghoobi <navidys@fedoraproject.org> 1.7.0-dev-1
|
||||
|
||||
* Wed May 28 2025 Navid Yaghoobi <navidys@fedoraproject.org> 1.6.0-1
|
||||
- Added container create health log dest, max count and size options
|
||||
- Set default values for container create/run health log options
|
||||
- Fix bats test for network connect
|
||||
- Running golang-lint
|
||||
- Bump github.com/containers/podman/v5 from 5.4.2 to 5.5.0
|
||||
- Bump github.com/containers/buildah from 1.39.4 to 1.40.0
|
||||
- Bump github.com/containers/common from 0.62.3 to 0.63.0
|
||||
- Bump github.com/containers/storage from 1.57.2 to 1.58.0
|
||||
- Bump github.com/onsi/ginkgo/v2 from 2.22.2 to 2.23.4
|
||||
- Bump github.com/onsi/gomega from 1.36.2 to 1.37.0
|
||||
- Bump golang.org/x/net from 0.36.0 to 0.38.0
|
||||
- Bump golang.org/x/crypto from 0.36.0 to 0.38.0
|
||||
|
||||
* Sun Apr 06 2025 Navid Yaghoobi <navidys@fedoraproject.org> 1.5.0-1
|
||||
- Go update to v1.23.0 + Golangci-lint update to v1.64.4
|
||||
- UI input check trim spaces
|
||||
- New feature - pod create resource settings category
|
||||
- Fix Vagrantbox hostname
|
||||
- Fix view's dialogs focus issue
|
||||
- Exec and run vterm container ID and name display issue fix
|
||||
- Added bats tests for container run cmd
|
||||
- Vagrantfile box version update to fedora/41-cloud-base
|
||||
- UI dialog size adjustments
|
||||
- New feature - container create resource settings category
|
||||
- View sub dialog size adjustments
|
||||
- New feature - container run
|
||||
- Container exec terminal size change
|
||||
- Container create dialog secret option
|
||||
- Fix wrong function name
|
||||
- Bump github.com/containers/podman/v5 to 5.4.2
|
||||
- Bump github.com/rs/zerolog to 1.34.0
|
||||
- Bump github.com/containers/buildah to 1.39.4
|
||||
- Bump github.com/BurntSushi/toml to 1.5.0
|
||||
- Bump github.com/containers/common to 0.62.3
|
||||
- Bump github.com/containers/storage to 1.57.2
|
||||
- Bump golang.org/x/net to 0.36.0
|
||||
- Bump golang.org/x/crypto to 0.36.0
|
||||
|
||||
* Sat Mar 01 2025 Navid Yaghoobi <navidys@fedoraproject.org> 1.4.0-1
|
||||
- Bump github.com/containers/podman/v5 to v5.4.0
|
||||
- Bump github.com/containers/buildah to v1.39.1
|
||||
- Bump github.com/containers/common to v0.62.0
|
||||
- Bump github.com/containers/storage to v1.57.1
|
||||
- Bump golang.org/x/crypto to v0.33.0
|
||||
- Bump github.com/go-jose/go-jose/v4 to 4.0.5
|
||||
- Bump github.com/spf13/cobra to 1.9.1
|
||||
- Bugfix panic in system events
|
||||
- Docs update - merge README(s)
|
||||
|
||||
* Sun Dec 01 2024 Navid Yaghoobi <navidys@fedoraproject.org> 1.3.0-1
|
||||
- Bump github.com/containers/podman/v5 to v5.3.1
|
||||
- Bump github.com/containers/buildah to v1.38.0
|
||||
|
|
|
@ -39,28 +39,13 @@ func (engine *Engine) startEventStreamer() {
|
|||
engine.sysEvents.mu.Unlock()
|
||||
|
||||
go engine.eventReader()
|
||||
go engine.streamEvents()
|
||||
}
|
||||
|
||||
func (engine *Engine) streamEvents() {
|
||||
log.Debug().Msg("health check: pdcs event steamer started")
|
||||
|
||||
for {
|
||||
go func() {
|
||||
if err := sysinfo.Events(engine.sysEvents.eventChan, engine.sysEvents.eventCancelChan); err != nil {
|
||||
log.Error().Msgf("health check: pdcs event streamer %v", err)
|
||||
log.Error().Msgf("health check: event streamer %v", err)
|
||||
|
||||
engine.sysEvents.cancelChan <- true
|
||||
engine.sysEvents.mu.Lock()
|
||||
engine.sysEvents.status = false
|
||||
engine.sysEvents.mu.Unlock()
|
||||
log.Debug().Msgf("health check: pdcs event steamer cancel sent")
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
log.Debug().Msg("health check: pdcs event streamer stopped")
|
||||
|
||||
close(engine.sysEvents.eventCancelChan)
|
||||
}()
|
||||
}
|
||||
|
||||
func (engine *Engine) eventReader() {
|
||||
|
@ -70,6 +55,11 @@ func (engine *Engine) eventReader() {
|
|||
select {
|
||||
case <-engine.sysEvents.cancelChan:
|
||||
log.Debug().Msg("health check: event reader stopped")
|
||||
engine.sysEvents.eventCancelChan <- true
|
||||
|
||||
engine.sysEvents.mu.Lock()
|
||||
engine.sysEvents.status = false
|
||||
engine.sysEvents.mu.Unlock()
|
||||
|
||||
close(engine.sysEvents.cancelChan)
|
||||
registry.CancelContext()
|
||||
|
|
|
@ -68,6 +68,9 @@ func (engine *Engine) Disconnect() {
|
|||
}
|
||||
|
||||
log.Debug().Msgf("health: disconnect")
|
||||
|
||||
engine.sysEvents.cancelChan <- true
|
||||
|
||||
registry.SetConnectionStatus(registry.ConnectionStatusDisconnected)
|
||||
engine.conn.setStatus(registry.ConnectionStatusDisconnected, "")
|
||||
registry.UnsetConnection()
|
||||
|
|
|
@ -19,9 +19,9 @@ load helpers_tui
|
|||
podman_tui_set_view "images"
|
||||
podman_tui_select_image_cmd "pull"
|
||||
podman_tui_send_inputs "busybox" "Enter"
|
||||
sleep 8
|
||||
sleep $TEST_TIMEOUT_HIGH
|
||||
podman_tui_send_inputs "Down" "Enter"
|
||||
sleep 12
|
||||
sleep $TEST_TIMEOUT_HIGH
|
||||
|
||||
run_helper podman image ls busybox --format "{{ .Repository }}"
|
||||
assert "$output" =~ "docker.io/library/busybox" "expected image"
|
||||
|
@ -46,7 +46,7 @@ load helpers_tui
|
|||
podman_tui_send_inputs $TEST_IMAGE_SAVE_PATH "Tab"
|
||||
podman_tui_send_inputs "Space" "Tab" "Tab" "Tab" "Tab"
|
||||
podman_tui_send_inputs "Enter"
|
||||
sleep 6
|
||||
sleep $TEST_TIMEOUT_MEDIUM
|
||||
|
||||
run_helper ls ${TEST_IMAGE_SAVE_PATH} 2> /dev/null
|
||||
assert "$output" == "$TEST_IMAGE_SAVE_PATH" "expected $TEST_IMAGE_SAVE_PATH exists"
|
||||
|
@ -70,7 +70,7 @@ load helpers_tui
|
|||
podman_tui_send_inputs "Tab"
|
||||
podman_tui_send_inputs "localhost/${TEST_NAME}_image_imported:latest"
|
||||
podman_tui_send_inputs "Tab" "Tab" "Enter"
|
||||
sleep 6
|
||||
sleep $TEST_TIMEOUT_MEDIUM
|
||||
|
||||
run_helper podman image ls ${TEST_NAME}_image_imported --format "{{ .Repository }}:{{ .Tag }}"
|
||||
assert "$output" =~ "localhost/${TEST_NAME}_image_imported" "expected image"
|
||||
|
@ -96,7 +96,7 @@ load helpers_tui
|
|||
podman_tui_send_inputs ${TEST_IMAGE_BUILD_REPOSITORY}
|
||||
podman_tui_send_inputs "Tab" "Tab"
|
||||
podman_tui_send_inputs "Enter"
|
||||
sleep 8
|
||||
sleep $TEST_TIMEOUT_MEDIUM
|
||||
podman_tui_send_inputs "Tab" "Enter"
|
||||
|
||||
run_helper podman image ls ${TEST_IMAGE_BUILD_TAG} --format "{{ .Repository }}:{{ .Tag }}"
|
||||
|
@ -113,7 +113,7 @@ load helpers_tui
|
|||
podman_tui_set_view "images"
|
||||
podman_tui_select_item $image_index
|
||||
podman_tui_select_image_cmd "diff"
|
||||
sleep 2
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
podman_tui_send_inputs "Tab" "Enter"
|
||||
|
||||
run_helper grep -w 'A /var' $PODMAN_TUI_LOG
|
||||
|
@ -130,7 +130,7 @@ load helpers_tui
|
|||
podman_tui_set_view "images"
|
||||
podman_tui_select_item $image_index
|
||||
podman_tui_select_image_cmd "history"
|
||||
sleep 2
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
podman_tui_send_inputs "Tab" "Enter"
|
||||
|
||||
run_helper egrep -w "\[\[$image_id.*BusyBox.*" $PODMAN_TUI_LOG
|
||||
|
@ -148,7 +148,7 @@ load helpers_tui
|
|||
podman_tui_set_view "images"
|
||||
podman_tui_select_item $image_index
|
||||
podman_tui_select_image_cmd "inspect"
|
||||
sleep 2
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
podman_tui_send_inputs "Enter"
|
||||
|
||||
run_helper sed -n '/ "RepoTags": \[/, / \],/p' $PODMAN_TUI_LOG
|
||||
|
@ -165,7 +165,7 @@ load helpers_tui
|
|||
podman_tui_select_item $busyboxIndex
|
||||
podman_tui_select_image_cmd "tag"
|
||||
podman_tui_send_inputs "$TEST_IMAGE_TAG_NAME" "Tab" "Tab" "Enter"
|
||||
sleep 2
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
|
||||
run_helper podman image ls $TEST_IMAGE_TAG_NAME --format "{{ .Repository }}"
|
||||
assert "$output" =~ "$TEST_IMAGE_TAG_NAME" "expected tagged image $TEST_IMAGE_TAG_NAME"
|
||||
|
@ -180,10 +180,10 @@ load helpers_tui
|
|||
# press "Tab" 2 times and "Enter" to untag busybox image
|
||||
podman_tui_set_view "images"
|
||||
podman_tui_select_item $busybox_tagindex
|
||||
sleep 1
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
podman_tui_select_image_cmd "untag"
|
||||
podman_tui_send_inputs "Tab" "Tab" "Enter"
|
||||
sleep 2
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
|
||||
untagged_umage=$(podman image ls --format '{{ .Repository }}')
|
||||
assert "$untagged_umage" !~ "$TEST_IMAGE_TAG_NAME" "expected $TEST_IMAGE_TAG_NAME not to be in the list"
|
||||
|
@ -205,7 +205,7 @@ load helpers_tui
|
|||
podman_tui_select_item $untagged_image
|
||||
podman_tui_select_image_cmd "remove"
|
||||
podman_tui_send_inputs "Enter"
|
||||
sleep 2
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
podman_tui_send_inputs "Tab" "Enter"
|
||||
|
||||
# check if busybox image has been removed
|
||||
|
@ -222,7 +222,7 @@ load helpers_tui
|
|||
podman_tui_set_view "images"
|
||||
podman_tui_select_image_cmd "prune"
|
||||
podman_tui_send_inputs "Enter"
|
||||
sleep 2
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
|
||||
# check if busybox image has been removed
|
||||
run_helper podman image ls --format "{{ .Repository }}" --filter "reference=busybox"
|
||||
|
|
|
@ -16,9 +16,9 @@ load helpers_tui
|
|||
podman_tui_set_view "volumes"
|
||||
podman_tui_select_volume_cmd "create"
|
||||
podman_tui_send_inputs "$TEST_VOLUME_NAME" "Tab" "$TEST_LABEL" "Tab" "Tab" "Tab" "Tab" "Enter"
|
||||
sleep 1
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
podman_tui_send_inputs "Tab" "Enter"
|
||||
sleep 2
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
|
||||
run_helper podman volume ls --format "{{ .Name }}" --filter "name=${TEST_VOLUME_NAME}"
|
||||
assert "$output" == "$TEST_VOLUME_NAME" "expected $TEST_VOLUME_NAME to be in the list"
|
||||
|
@ -34,9 +34,9 @@ load helpers_tui
|
|||
podman_tui_set_view "volumes"
|
||||
podman_tui_select_item $vol_index
|
||||
podman_tui_select_volume_cmd "inspect"
|
||||
sleep 1
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
podman_tui_send_inputs "Enter"
|
||||
sleep 2
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
|
||||
run_helper sed -n '/ "Labels": {/, / },/p' ${PODMAN_TUI_LOG}
|
||||
assert "$output" =~ "\"$TEST_LABEL_NAME\": \"$TEST_LABEL_VALUE\"" "expected \"$TEST_LABEL_NAME\": \"$TEST_LABEL_VALUE\" in volume inspect"
|
||||
|
@ -52,7 +52,7 @@ load helpers_tui
|
|||
podman_tui_select_item $vol_index
|
||||
podman_tui_select_volume_cmd "remove"
|
||||
podman_tui_send_inputs "Enter"
|
||||
sleep 2
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
|
||||
run_helper podman volume ls --format "{{ .Name }}" --filter "name=${TEST_VOLUME_NAME}"
|
||||
assert "$output" == "" "expected $TEST_VOLUME_NAME removed"
|
||||
|
@ -68,7 +68,7 @@ load helpers_tui
|
|||
podman_tui_set_view "volumes"
|
||||
podman_tui_select_volume_cmd "prune"
|
||||
podman_tui_send_inputs "Enter"
|
||||
sleep 2
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
|
||||
run_helper podman volume ls --format "{{ .Name }}" --filter "name=${TEST_NETWORK_NAME}"
|
||||
assert "$output" =~ "" "expected at least $TEST_VOLUME_NAME image removal"
|
||||
|
|
|
@ -18,13 +18,13 @@ load helpers_tui
|
|||
|
||||
podman_tui_set_view "networks"
|
||||
podman_tui_select_network_cmd "connect"
|
||||
sleep 2
|
||||
podman_tui_send_inputs "Tab" "Tab"
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
podman_tui_send_inputs "Tab"
|
||||
podman_tui_send_inputs $TEST_NETWORK_CONNECT_ALIAS
|
||||
podman_tui_send_inputs "Tab" "Tab" "Tab" "Tab"
|
||||
podman_tui_send_inputs "Tab" "Enter"
|
||||
|
||||
sleep 2
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
|
||||
run_helper podman container inspect $TEST_CONTAINER_NAME --format "\"{{ .NetworkSettings.Networks.$TEST_NETWORK_CONNECT }}\""
|
||||
assert "$output" =~ "$TEST_NETWORK_CONNECT_ALIAS" "expected $TEST_NETWORK_CONNECT_ALIAS to be in the list of aliases"
|
||||
|
@ -39,8 +39,8 @@ load helpers_tui
|
|||
|
||||
podman_tui_set_view "networks"
|
||||
podman_tui_select_network_cmd "disconnect"
|
||||
sleep 2
|
||||
podman_tui_send_inputs "Tab" "Tab" "Tab" "Enter"
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
podman_tui_send_inputs "Tab" "Tab" "Enter"
|
||||
|
||||
run_helper podman container inspect $TEST_CONTAINER_NAME --format "{{ .NetworkSettings.Networks.$TEST_NETWORK_CONNECT }}"
|
||||
assert "$output" == "<no value>" "expected $TEST_NETWORK_CONNECT_ALIAS to be removed from container"
|
||||
|
@ -60,9 +60,9 @@ load helpers_tui
|
|||
podman_tui_send_inputs "Tab"
|
||||
podman_tui_send_inputs "$TEST_LABEL"
|
||||
podman_tui_send_inputs "Tab" "Tab" "Tab" "Tab" "Tab" "Enter"
|
||||
sleep 1
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
podman_tui_send_inputs "Tab" "Enter"
|
||||
sleep 2
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
run_helper podman network ls --format "{{ .Name }}" --filter "name=${TEST_NETWORK_NAME}$"
|
||||
assert "$output" == "$TEST_NETWORK_NAME" "expected $TEST_NETWORK_NAME to be in the list"
|
||||
}
|
||||
|
@ -77,9 +77,9 @@ load helpers_tui
|
|||
podman_tui_set_view "networks"
|
||||
podman_tui_select_item $net_index
|
||||
podman_tui_select_network_cmd "inspect"
|
||||
sleep 1
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
podman_tui_send_inputs "Enter"
|
||||
sleep 2
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
|
||||
run_helper sed -n '/ "labels": {/, / }/p' $PODMAN_TUI_LOG
|
||||
assert "$output" =~ "\"$TEST_LABEL_NAME\": \"$TEST_LABEL_VALUE\"" "expected \"$TEST_LABEL_NAME\": \"$TEST_LABEL_VALUE\" in network inspect"
|
||||
|
@ -95,7 +95,7 @@ load helpers_tui
|
|||
podman_tui_select_item $net_index
|
||||
podman_tui_select_network_cmd "remove"
|
||||
podman_tui_send_inputs "Enter"
|
||||
sleep 2
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
|
||||
run_helper podman network ls --format "{{ .Name }}" --filter "name=${TEST_NETWORK_NAME}$"
|
||||
assert "$output" == "" "expected $TEST_NETWORK_NAME removed"
|
||||
|
@ -111,7 +111,7 @@ load helpers_tui
|
|||
podman_tui_set_view "networks"
|
||||
podman_tui_select_network_cmd "prune"
|
||||
podman_tui_send_inputs "Enter"
|
||||
sleep 2
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
|
||||
run_helper podman network ls --format "{{ .Name }}" --filter "name=${TEST_NETWORK_NAME}$"
|
||||
assert "$output" == "" "expected at least $TEST_NETWORK_NAME network removal"
|
||||
|
|
|
@ -6,7 +6,38 @@
|
|||
load helpers
|
||||
load helpers_tui
|
||||
|
||||
@test "pod create" {
|
||||
@test "pod create (resource)" {
|
||||
podman pod rm -f $TEST_POD_NAME || echo done
|
||||
podman image pull pause:3.5 || echo done
|
||||
|
||||
podman_tui_set_view "pods"
|
||||
podman_tui_select_pod_cmd "create"
|
||||
podman_tui_send_inputs $TEST_POD_NAME "Tab" "Tab" "Tab" "Tab" "Tab"
|
||||
podman_tui_send_inputs "Down" "Down" "Down" "Down" "Down" "Tab"
|
||||
podman_tui_send_inputs $TEST_POD_MEMORY "Tab" $TEST_POD_SWAP
|
||||
podman_tui_send_inputs "Tab" "Tab" $TEST_POD_CPU_SHARES
|
||||
podman_tui_send_inputs "Tab" "Tab" $TEST_POD_CPUSET_MEM
|
||||
podman_tui_send_inputs "Tab" "Tab" "Tab" "Tab"
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
|
||||
podman_tui_send_inputs "Enter"
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
|
||||
run_helper podman pod ls --filter="name=${TEST_POD_NAME}$" --format "{{ .Status}}"
|
||||
assert $output =~ "Created" "expected $TEST_POD_NAME to be created"
|
||||
|
||||
pod_memory=$(podman pod inspect $TEST_POD_NAME --format "{{ json .MemoryLimit }}")
|
||||
pod_memory_swap=$(podman pod inspect $TEST_POD_NAME --format "{{ json .MemorySwap }}")
|
||||
pod_cpu_shares=$(podman pod inspect $TEST_POD_NAME --format "{{ json .CPUShares }}")
|
||||
pod_cpu_set_mems=$(podman pod inspect $TEST_POD_NAME --format "{{ json .CPUSetMems }}")
|
||||
|
||||
assert "$pod_memory" =~ "$TEST_POD_MEMORY" "expected pod memory to match: $TEST_POD_MEMORY"
|
||||
assert "$pod_memory_swap" =~ "$TEST_POD_SWAP" "expected pod memory swap to match: $TEST_POD_SWAP"
|
||||
assert "$pod_cpu_shares" =~ "$TEST_POD_CPU_SHARES" "expected pod cpu shares to match: $TEST_POD_CPU_SHARES"
|
||||
assert "$pod_cpu_set_mems" =~ "$TEST_POD_CPUSET_MEM" "expected pod cpu set mems to match: $TEST_POD_CPUSET_MEM"
|
||||
}
|
||||
|
||||
@test "pod create (networking, security)" {
|
||||
podman pod rm -f $TEST_POD_NAME || echo done
|
||||
podman network rm $TEST_POD_NETWORK_NAME || echo done
|
||||
podman image pull pause:3.5 || echo done
|
||||
|
@ -35,7 +66,7 @@ load helpers_tui
|
|||
podman_tui_send_inputs "Tab" "Tab" "Tab" "Tab" "Tab" "Space"
|
||||
podman_tui_send_inputs "Tab" "Tab"
|
||||
podman_tui_send_inputs "Enter"
|
||||
sleep 4
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
|
||||
run_helper podman pod ls --filter="name=${TEST_POD_NAME}$" --format "{{ .Status}}"
|
||||
assert $output =~ "Created" "expected $TEST_POD_NAME to be created"
|
||||
|
@ -54,7 +85,7 @@ load helpers_tui
|
|||
podman_tui_set_view "pods"
|
||||
podman_tui_select_item $pod_index
|
||||
podman_tui_select_pod_cmd "start"
|
||||
sleep 2
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
|
||||
run_helper podman pod ls --filter="name=${TEST_POD_NAME}$" --format "{{ .Status}}"
|
||||
assert $output =~ "Running" "expected $TEST_POD_NAME running"
|
||||
|
@ -69,7 +100,7 @@ load helpers_tui
|
|||
podman_tui_set_view "pods"
|
||||
podman_tui_select_item $pod_index
|
||||
podman_tui_select_pod_cmd "pause"
|
||||
sleep 2
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
|
||||
run_helper podman pod ls --filter="name=${TEST_POD_NAME}$" --format "{{ .Status}}"
|
||||
assert $output =~ "Paused" "expected $TEST_POD_NAME running"
|
||||
|
@ -84,7 +115,7 @@ load helpers_tui
|
|||
podman_tui_set_view "pods"
|
||||
podman_tui_select_item $pod_index
|
||||
podman_tui_select_pod_cmd "unpause"
|
||||
sleep 2
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
|
||||
run_helper podman pod ls --filter="name=${TEST_POD_NAME}$" --format "{{ .Status}}"
|
||||
assert $output =~ "Running" "expected $TEST_POD_NAME running"
|
||||
|
@ -99,7 +130,7 @@ load helpers_tui
|
|||
podman_tui_set_view "pods"
|
||||
podman_tui_select_item $pod_index
|
||||
podman_tui_select_pod_cmd "stop"
|
||||
sleep 2
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
|
||||
run_helper podman pod ls --filter="name=${TEST_POD_NAME}$" --format "{{ .Status}}"
|
||||
assert $output =~ "Exited" "expected $TEST_POD_NAME exited"
|
||||
|
@ -114,7 +145,7 @@ load helpers_tui
|
|||
podman_tui_set_view "pods"
|
||||
podman_tui_select_item $pod_index
|
||||
podman_tui_select_pod_cmd "restart"
|
||||
sleep 2
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
|
||||
run_helper podman pod ls --filter="name=${TEST_POD_NAME}$" --format "{{ .Status}}"
|
||||
assert $output =~ "Running" "expected $TEST_POD_NAME exited"
|
||||
|
@ -129,7 +160,7 @@ load helpers_tui
|
|||
podman_tui_set_view "pods"
|
||||
podman_tui_select_item $pod_index
|
||||
podman_tui_select_pod_cmd "kill"
|
||||
sleep 2
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
|
||||
run_helper podman pod ls --filter="name=${TEST_POD_NAME}$" --format "{{ .Status}}"
|
||||
assert $output =~ "Exited" "expected $TEST_POD_NAME exited"
|
||||
|
@ -145,7 +176,7 @@ load helpers_tui
|
|||
podman_tui_set_view "pods"
|
||||
podman_tui_select_item $pod_index
|
||||
podman_tui_select_pod_cmd "inspect"
|
||||
sleep 2
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
podman_tui_send_inputs "Enter"
|
||||
|
||||
run_helper sed -n '/ "Labels": {/, / },/p' $PODMAN_TUI_LOG
|
||||
|
@ -164,7 +195,7 @@ load helpers_tui
|
|||
podman_tui_select_pod_cmd "remove"
|
||||
podman_tui_send_inputs "Enter"
|
||||
podman_tui_send_inputs "Enter"
|
||||
sleep 2
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
|
||||
run_helper podman pod ls --format "{{ .Name }}" --filter "name=${TEST_POD_NAME}$"
|
||||
assert "$output" == "" "expected $TEST_POD_NAME pod removal"
|
||||
|
@ -174,7 +205,7 @@ load helpers_tui
|
|||
podman pod create --name $TEST_POD_NAME --label $TEST_LABEL || echo done
|
||||
podman pod start $TEST_POD_NAME || echo done
|
||||
podman pod stop $TEST_POD_NAME || echo done
|
||||
sleep 2
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
|
||||
# switch to pods view
|
||||
# select prune command from pod commands dialog
|
||||
|
@ -182,7 +213,7 @@ load helpers_tui
|
|||
podman_tui_set_view "pods"
|
||||
podman_tui_select_pod_cmd "prune"
|
||||
podman_tui_send_inputs "Enter"
|
||||
sleep 3
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
|
||||
run_helper podman pod ls --format "{{ .Name }}" --filter "name=${TEST_POD_NAME}$"
|
||||
assert "$output" == "" "expected at least $TEST_POD_NAME pod removal"
|
||||
|
|
|
@ -6,6 +6,39 @@
|
|||
load helpers
|
||||
load helpers_tui
|
||||
|
||||
@test "container run" {
|
||||
podman container rm -f $TEST_CONTAINER_NAME || echo done
|
||||
|
||||
buysbox_image=$(podman image ls --sort repository --format "{{ .Repository }}" --filter "reference=docker.io/library/busybox")
|
||||
if [ "${buysbox_image}" == "" ] ; then
|
||||
podman image pull docker.io/library/busybox
|
||||
fi
|
||||
|
||||
image_index=$(podman image ls --sort repository --noheading | nl -v 1 | grep 'busybox ' | awk '{print $1}')
|
||||
|
||||
podman_tui_set_view "containers"
|
||||
podman_tui_select_container_cmd "run"
|
||||
podman_tui_send_inputs $TEST_CONTAINER_NAME "Tab" "$TEST_CONTAINER_RUN_CMD" "Tab"
|
||||
podman_tui_send_inputs "Down"
|
||||
podman_tui_select_item $image_index
|
||||
podman_tui_send_inputs "Enter"
|
||||
podman_tui_send_inputs "Tab" "Tab" "Tab" "Tab" "Space"
|
||||
podman_tui_send_inputs "Tab" "Tab" "Space"
|
||||
podman_tui_send_inputs "Tab" "Space"
|
||||
podman_tui_send_inputs "Tab" "Space"
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
podman_tui_send_inputs "Tab" "Tab" "Tab" "Enter"
|
||||
sleep $TEST_TIMEOUT_HIGH
|
||||
|
||||
cnt_status=$(podman container inspect $TEST_CONTAINER_NAME --format "{{ json .State.Status }}")
|
||||
assert "$cnt_status" =~ "running" "expected container status to match: running"
|
||||
|
||||
podman container stop $TEST_CONTAINER_NAME
|
||||
|
||||
run_helper podman container ls --all --filter "name=${TEST_CONTAINER_NAME}$" --noheading
|
||||
assert "$output" == "" "expected $TEST_CONTAINER_NAME to be removed"
|
||||
}
|
||||
|
||||
@test "container create (privileged, timeout, remove)" {
|
||||
podman container rm -f $TEST_CONTAINER_NAME || echo done
|
||||
|
||||
|
@ -25,15 +58,15 @@ load helpers_tui
|
|||
# select image from dropdown widget
|
||||
# select privileged
|
||||
# set timeout to 10
|
||||
podman_tui_send_inputs $TEST_CONTAINER_NAME "Tab"
|
||||
podman_tui_send_inputs $TEST_CONTAINER_NAME "Tab" "Tab"
|
||||
podman_tui_send_inputs "Down"
|
||||
podman_tui_select_item $image_index
|
||||
podman_tui_send_inputs "Enter" "Tab" "Tab" "Tab"
|
||||
podman_tui_send_inputs "Space" "Tab" "Space" "Tab" "$TEST_CONTAINER_TIMEOUT"
|
||||
podman_tui_send_inputs "Tab" "Tab"
|
||||
sleep 2
|
||||
podman_tui_send_inputs "Tab" "Tab" "Tab"
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
podman_tui_send_inputs "Enter"
|
||||
sleep 3
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
|
||||
cnt_status=$(podman container inspect $TEST_CONTAINER_NAME --format "{{ json .State.Status }}")
|
||||
cnt_annotations=$(podman container inspect $TEST_CONTAINER_NAME --format "{{ json .Config.Annotations }}")
|
||||
|
@ -62,11 +95,11 @@ load helpers_tui
|
|||
|
||||
# fillout name field
|
||||
# select image from dropdown widget
|
||||
podman_tui_send_inputs $TEST_CONTAINER_NAME "Tab"
|
||||
podman_tui_send_inputs $TEST_CONTAINER_NAME "Tab" "Tab"
|
||||
podman_tui_send_inputs "Down"
|
||||
podman_tui_select_item $image_index
|
||||
podman_tui_send_inputs "Enter" "Tab" "Tab" "Tab" "Tab" "Tab" "Tab" "Tab" "Tab"
|
||||
sleep 2
|
||||
podman_tui_send_inputs "Enter" "Tab" "Tab" "Tab" "Tab" "Tab" "Tab" "Tab" "Tab" "Tab"
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
|
||||
# switch to environmen page
|
||||
podman_tui_send_inputs "Down" "Tab"
|
||||
|
@ -75,9 +108,9 @@ load helpers_tui
|
|||
podman_tui_send_inputs "Tab" "Tab" "Tab" "Tab" "Tab" "Tab"
|
||||
podman_tui_send_inputs "$TEST_CONTAINER_UMASK"
|
||||
podman_tui_send_inputs "Tab" "Tab"
|
||||
sleep 2
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
podman_tui_send_inputs "Enter"
|
||||
sleep 3
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
|
||||
cnt_workdir=$(podman container inspect $TEST_CONTAINER_NAME --format "{{ json .Config.WorkingDir }}")
|
||||
cnt_vars=$(podman container inspect $TEST_CONTAINER_NAME --format "{{ json .Config.Env }}")
|
||||
|
@ -89,6 +122,63 @@ load helpers_tui
|
|||
assert "$cnt_vars" =~ "$TEST_CONTAINER_ENV2" "expected container env to match: $TEST_CONTAINER_ENV2"
|
||||
}
|
||||
|
||||
@test "container create (resource page)" {
|
||||
podman container rm -f $TEST_CONTAINER_NAME || echo done
|
||||
|
||||
buysbox_image=$(podman image ls --sort repository --format "{{ .Repository }}" --filter "reference=docker.io/library/busybox")
|
||||
if [ "${buysbox_image}" == "" ] ; then
|
||||
podman image pull docker.io/library/busybox
|
||||
fi
|
||||
|
||||
image_index=$(podman image ls --sort repository --noheading | nl -v 1 | grep 'busybox ' | awk '{print $1}')
|
||||
|
||||
# switch to containers view
|
||||
# select create command from container commands dialog
|
||||
podman_tui_set_view "containers"
|
||||
podman_tui_select_container_cmd "create"
|
||||
|
||||
# fillout name field
|
||||
# select image from dropdown widget
|
||||
podman_tui_send_inputs $TEST_CONTAINER_NAME "Tab" "Tab"
|
||||
podman_tui_send_inputs "Down"
|
||||
podman_tui_select_item $image_index
|
||||
podman_tui_send_inputs "Enter" "Tab" "Tab" "Tab" "Tab" "Tab" "Tab" "Tab" "Tab" "Tab"
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
|
||||
# switch to environmen page
|
||||
podman_tui_send_inputs "Down" "Down" "Down" "Down" "Down" "Down" "Down" "Down" "Down" "Tab"
|
||||
podman_tui_send_inputs "$TEST_CONTAINER_MEMORY" "Tab" "$TEST_CONTAINER_MEMORY_RESERV" "Tab"
|
||||
podman_tui_send_inputs "$TEST_CONTAINER_MEMORY_SWAP" "Tab" "$TEST_CONTAINER_MEMORY_SWAPPINESS"
|
||||
podman_tui_send_inputs "Tab" "Tab" "$TEST_CONTAINER_CPU_SHARES"
|
||||
podman_tui_send_inputs "Tab" "$TEST_CONTAINER_CPU_PERIOD"
|
||||
podman_tui_send_inputs "Tab" "Tab" "$TEST_CONTAINER_CPU_QUOTA"
|
||||
podman_tui_send_inputs "Tab" "Tab" "Tab" "Tab"
|
||||
podman_tui_send_inputs "$TEST_CONTAINER_SHM_SIZE" "Tab"
|
||||
podman_tui_send_inputs "$TEST_CONTAINER_SHM_SIZE_SYSTYEMD"
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
podman_tui_send_inputs "Tab" "Tab"
|
||||
podman_tui_send_inputs "Enter"
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
|
||||
cnt_memory=$(podman container inspect $TEST_CONTAINER_NAME --format "{{ json .HostConfig.Memory }}")
|
||||
cnt_memory_reserv=$(podman container inspect $TEST_CONTAINER_NAME --format "{{ json .HostConfig.MemoryReservation }}")
|
||||
cnt_memory_swap=$(podman container inspect $TEST_CONTAINER_NAME --format "{{ json .HostConfig.MemorySwap }}")
|
||||
cnt_memory_swappiness=$(podman container inspect $TEST_CONTAINER_NAME --format "{{ json .HostConfig.MemorySwappiness }}")
|
||||
cnt_cpu_shares=$(podman container inspect $TEST_CONTAINER_NAME --format "{{ json .HostConfig.CpuShares }}")
|
||||
cnt_cpu_period=$(podman container inspect $TEST_CONTAINER_NAME --format "{{ json .HostConfig.CpuPeriod }}")
|
||||
cnt_cpu_quota=$(podman container inspect $TEST_CONTAINER_NAME --format "{{ json .HostConfig.CpuQuota }}")
|
||||
cnt_shm_size=$(podman container inspect $TEST_CONTAINER_NAME --format "{{ json .HostConfig.ShmSize }}")
|
||||
|
||||
assert "$cnt_memory" =~ "$TEST_CONTAINER_MEMORY" "expected container memory to match: $TEST_CONTAINER_MEMORY"
|
||||
assert "$cnt_memory_reserv" =~ "$TEST_CONTAINER_MEMORY_RESERV" "expected container memory reservation to match: $TEST_CONTAINER_MEMORY_RESERV"
|
||||
assert "$cnt_memory_swap" =~ "$TEST_CONTAINER_MEMORY_SWAP" "expected container memory swap to match: $TEST_CONTAINER_MEMORY_SWAP"
|
||||
assert "$cnt_memory_swappiness" =~ "$TEST_CONTAINER_MEMORY_SWAPPINESS" "expected container memory swappiness to match: $TEST_CONTAINER_MEMORY_SWAPPINESS"
|
||||
assert "$cnt_cpu_shares" =~ "$TEST_CONTAINER_CPU_SHARES" "expected container cpu shares to match: $TEST_CONTAINER_CPU_SHARES"
|
||||
assert "$cnt_cpu_period" =~ "$TEST_CONTAINER_CPU_PERIOD" "expected container cpu period to match: $TEST_CONTAINER_CPU_PERIOD"
|
||||
assert "$cnt_cpu_quota" =~ "$TEST_CONTAINER_CPU_QUOTA" "expected container cpu quota to match: $TEST_CONTAINER_CPU_QUOTA"
|
||||
assert "$cnt_shm_size" =~ "$TEST_CONTAINER_SHM_SIZE" "expected container shm size to match: $TEST_CONTAINER_SHM_SIZE"
|
||||
}
|
||||
|
||||
@test "container create (pod, network, volume, security options, health)" {
|
||||
httpd_image=$(podman image ls --sort repository --format "{{ .Repository }}" --filter "reference=docker.io/library/httpd")
|
||||
if [ "${httpd_image}" == "" ] ; then
|
||||
|
@ -106,7 +196,7 @@ load helpers_tui
|
|||
podman network create $TEST_CONTAINER_NETWORK_NAME || echo done
|
||||
podman volume create $TEST_CONTAINER_VOLUME_NAME || echo done
|
||||
podman pod create --name $TEST_CONTAINER_POD_NAME --network $TEST_CONTAINER_NETWORK_NAME --publish $TEST_CONTAINER_PORT || echo done
|
||||
sleep 2
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
|
||||
# get required pod, image, network and volume index for number of KeyDown stroke
|
||||
pod_index=$(podman pod ls --sort name --format "{{ .Name }}" | nl -v 1 | grep "$TEST_CONTAINER_POD_NAME" | awk '{print $1}')
|
||||
|
@ -123,32 +213,28 @@ load helpers_tui
|
|||
# select image from dropdown widget
|
||||
# select pod from dropdown widget
|
||||
# fillout label field
|
||||
podman_tui_send_inputs $TEST_CONTAINER_NAME "Tab"
|
||||
podman_tui_send_inputs $TEST_CONTAINER_NAME "Tab" "Tab"
|
||||
podman_tui_send_inputs "Down"
|
||||
podman_tui_select_item $image_index
|
||||
podman_tui_send_inputs "Enter" "Tab"
|
||||
podman_tui_send_inputs "Down"
|
||||
podman_tui_select_item $pod_index
|
||||
podman_tui_send_inputs "Enter" "Tab"
|
||||
podman_tui_send_inputs $TEST_LABEL "Tab" "Tab" "Tab" "Tab" "Tab"
|
||||
sleep 1
|
||||
podman_tui_send_inputs $TEST_LABEL "Tab" "Tab" "Tab" "Tab" "Tab" "Tab"
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
podman_tui_send_inputs "Tab"
|
||||
sleep 1
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
|
||||
# switch to "health check" create view
|
||||
podman_tui_send_inputs "Down" "Down" "Down" "Down" "Tab"
|
||||
podman_tui_send_inputs $TEST_CONTAINER_HEALTH_CMD "Tab" "Tab"
|
||||
podman_tui_send_inputs $TEST_CONTAINER_HEALTH_CMD "Tab" "Tab" "Tab" "Tab" "Tab"
|
||||
podman_tui_send_inputs "Enter" "Down" "Down" "Enter"
|
||||
podman_tui_send_inputs "Tab" "Tab" "Tab"
|
||||
podman_tui_send_inputs $TEST_CONTAINER_HEALTH_INTERVAL
|
||||
podman_tui_send_inputs "Tab" "Tab"
|
||||
podman_tui_send_inputs $TEST_CONTAINER_HEALTH_RETRIES
|
||||
podman_tui_send_inputs "Tab" "Tab"
|
||||
podman_tui_send_inputs $TEST_CONTAINER_HEALTH_TIMEOUT
|
||||
podman_tui_send_inputs "Tab" "Tab" "Tab"
|
||||
sleep 1
|
||||
podman_tui_send_inputs "Tab" "Tab" "Tab" "Tab"
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
podman_tui_send_inputs "Tab"
|
||||
sleep 1
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
|
||||
# switch to "security options" create view
|
||||
podman_tui_send_inputs "Down" "Down" "Down" "Tab"
|
||||
|
@ -161,11 +247,11 @@ load helpers_tui
|
|||
podman_tui_send_inputs "${TEST_CONTAINER_VOLUME_NAME}:${TEST_CONTAINER_VOLUME_MOUNT_POINT}:rw"
|
||||
podman_tui_send_inputs "Tab" "Tab"
|
||||
podman_tui_send_inputs "type=bind,src=${TEST_CONTAINER_MOUNT_SOURCE},dst=${TEST_CONTAINER_MOUNT_DEST}"
|
||||
sleep 1
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
|
||||
# go to "Create" button and press Enter
|
||||
podman_tui_send_inputs "Tab" "Tab" "Enter"
|
||||
sleep 2
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
|
||||
# get created container information
|
||||
container_information=$(podman container ls --all --pod --filter "name=${TEST_CONTAINER_NAME}$" --format \
|
||||
|
@ -222,7 +308,7 @@ load helpers_tui
|
|||
podman_tui_send_inputs Tab Tab Tab Tab
|
||||
podman_tui_send_inputs Tab Tab Tab Tab
|
||||
podman_tui_send_inputs Enter
|
||||
sleep 10
|
||||
sleep $TEST_TIMEOUT_HIGH
|
||||
run_helper podman image ls ${TEST_CONTAINER_COMMIT_IMAGE_NAME} --format "{{ .Repository }}"
|
||||
assert "$output" =~ "localhost/${TEST_CONTAINER_COMMIT_IMAGE_NAME}" "expected image"
|
||||
}
|
||||
|
@ -236,7 +322,7 @@ load helpers_tui
|
|||
podman_tui_set_view "containers"
|
||||
podman_tui_select_item $container_index
|
||||
podman_tui_select_container_cmd "start"
|
||||
sleep 2
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
|
||||
run_helper podman container ls --all --filter="name=${TEST_CONTAINER_NAME}$" --format "{{ .Status }}"
|
||||
assert "$output" =~ "Up" "expected $TEST_CONTAINER_NAME to be up"
|
||||
|
@ -265,7 +351,7 @@ load helpers_tui
|
|||
podman_tui_send_inputs "Tab" "Tab" "Tab" "Tab"
|
||||
podman_tui_send_inputs "Tab" "Tab" "Enter"
|
||||
|
||||
sleep 10
|
||||
sleep $TEST_TIMEOUT_HIGH
|
||||
|
||||
run_helper ls ~/${TEST_CONTAINER_CHECKPOINT_NAME}_dump.tar 2>/dev/null || echo -e '\c'
|
||||
assert "$output" == "/root/${TEST_CONTAINER_CHECKPOINT_NAME}_dump.tar" "expected tar file to be created"
|
||||
|
@ -288,7 +374,7 @@ load helpers_tui
|
|||
podman_tui_send_inputs "Tab" "Tab" "Tab" "Tab"
|
||||
podman_tui_send_inputs "Tab" "Tab" "Enter"
|
||||
|
||||
sleep 8
|
||||
sleep $TEST_TIMEOUT_HIGH
|
||||
run_helper podman container ls --all --format "{{ .Names }}"
|
||||
assert "$output" =~ "${TEST_CONTAINER_CHECKPOINT_NAME}_restore" "expected container to be restored"
|
||||
}
|
||||
|
@ -312,10 +398,10 @@ load helpers_tui
|
|||
podman_tui_send_inputs "Tab" "Space" "Tab"
|
||||
podman_tui_send_inputs "Tab" "Tab" "Tab" "Tab" "Tab" "Tab" "Tab" "Tab"
|
||||
podman_tui_send_inputs "Enter"
|
||||
sleep 1
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
podman_tui_send_inputs "echo Space test Space > Space a.txt" "Enter"
|
||||
podman_tui_send_inputs "Tab" "Enter"
|
||||
sleep 2
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
|
||||
run_helper podman container exec $TEST_CONTAINER_NAME cat a.txt
|
||||
|
||||
|
@ -331,7 +417,7 @@ load helpers_tui
|
|||
podman_tui_set_view "containers"
|
||||
podman_tui_select_item $container_index
|
||||
podman_tui_select_container_cmd "inspect"
|
||||
sleep 2
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
|
||||
run_helper sed -n '/ "Labels": {/, / },/p' $PODMAN_TUI_LOG
|
||||
|
||||
|
@ -347,7 +433,7 @@ load helpers_tui
|
|||
podman_tui_set_view "containers"
|
||||
podman_tui_select_item $container_index
|
||||
podman_tui_select_container_cmd "diff"
|
||||
sleep 6
|
||||
sleep $TEST_TIMEOUT_MEDIUM
|
||||
|
||||
run_helper grep -w "/etc" $PODMAN_TUI_LOG
|
||||
assert "$output" =~ '/etc' "expected '/etc' in the logs"
|
||||
|
@ -362,7 +448,7 @@ load helpers_tui
|
|||
podman_tui_set_view "containers"
|
||||
podman_tui_select_item $container_index
|
||||
podman_tui_select_container_cmd "top"
|
||||
sleep 2
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
|
||||
run_helper grep -w "USER PID PPID" $PODMAN_TUI_LOG
|
||||
assert "$output" =~ 'USER PID PPID' "expected 'USER PID PPID' in the logs"
|
||||
|
@ -377,7 +463,7 @@ load helpers_tui
|
|||
podman_tui_set_view "containers"
|
||||
podman_tui_select_item $container_index
|
||||
podman_tui_select_container_cmd "port"
|
||||
sleep 2
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
|
||||
container_ports=$(podman container ls --all --filter="name=${TEST_CONTAINER_NAME}$" --format "{{ .Ports }}")
|
||||
run_helper grep -w "$container_ports" $PODMAN_TUI_LOG
|
||||
|
@ -393,7 +479,7 @@ load helpers_tui
|
|||
podman_tui_set_view "containers"
|
||||
podman_tui_select_item $container_index
|
||||
podman_tui_select_container_cmd "pause"
|
||||
sleep 2
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
|
||||
run_helper podman container ls --all --filter="name=${TEST_CONTAINER_NAME}$" --format "{{ .Status }}"
|
||||
assert "$output" =~ "Paused" "expected $TEST_CONTAINER_NAME to be paused"
|
||||
|
@ -408,7 +494,7 @@ load helpers_tui
|
|||
podman_tui_set_view "containers"
|
||||
podman_tui_select_item $container_index
|
||||
podman_tui_select_container_cmd "unpause"
|
||||
sleep 2
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
|
||||
run_helper podman container ls --all --filter="name=${TEST_CONTAINER_NAME}$" --format "{{ .Status }}"
|
||||
assert "$output" =~ "Up" "expected $TEST_CONTAINER_NAME to be Up"
|
||||
|
@ -423,7 +509,7 @@ load helpers_tui
|
|||
podman_tui_set_view "containers"
|
||||
podman_tui_select_item $container_index
|
||||
podman_tui_select_container_cmd "stop"
|
||||
sleep 2
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
|
||||
run_helper podman container ls --all --filter="name=${TEST_CONTAINER_NAME}$" --format "{{ .Status }}"
|
||||
assert "$output" =~ "Exited" "expected $TEST_CONTAINER_NAME to be Up"
|
||||
|
@ -439,7 +525,7 @@ load helpers_tui
|
|||
podman_tui_set_view "containers"
|
||||
podman_tui_select_item $container_index
|
||||
podman_tui_select_container_cmd "kill"
|
||||
sleep 2
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
|
||||
run_helper podman container ls --all --filter="name=${TEST_CONTAINER_NAME}$" --format "{{ .Status }}"
|
||||
assert "$output" =~ "Exited" "expected $TEST_CONTAINER_NAME to be killed"
|
||||
|
@ -455,7 +541,7 @@ load helpers_tui
|
|||
podman_tui_select_item $container_index
|
||||
podman_tui_select_container_cmd "remove"
|
||||
podman_tui_send_inputs "Enter"
|
||||
sleep 2
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
|
||||
run_helper podman container ls --all --filter "name=${TEST_CONTAINER_NAME}$" --noheading
|
||||
assert "$output" == "" "expected $TEST_CONTAINER_NAME to be removed"
|
||||
|
@ -474,7 +560,7 @@ load helpers_tui
|
|||
podman_tui_select_container_cmd "rename"
|
||||
podman_tui_send_inputs ${TEST_CONTAINER_NAME}_renamed
|
||||
podman_tui_send_inputs "Tab" "Tab" "Enter"
|
||||
sleep 2
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
|
||||
run_helper podman container ls --all --filter "name=${TEST_CONTAINER_NAME}_renamed$" --format "{{ .Names }}"
|
||||
assert "$output" == "${TEST_CONTAINER_NAME}_renamed" "expected ${TEST_CONTAINER_NAME}_renamed to be in the list"
|
||||
|
@ -492,7 +578,7 @@ load helpers_tui
|
|||
podman_tui_select_item $container_index
|
||||
podman_tui_select_container_cmd "prune"
|
||||
podman_tui_send_inputs "Enter"
|
||||
sleep 10
|
||||
sleep $TEST_TIMEOUT_MEDIUM
|
||||
|
||||
run_helper podman container ls --all --filter "name=${TEST_CONTAINER_NAME}$" --noheading
|
||||
assert "$output" == "" "expected $TEST_CONTAINER_NAME to be removed"
|
||||
|
|
|
@ -18,11 +18,10 @@ load helpers_tui
|
|||
podman_tui_send_inputs "Tab"
|
||||
podman_tui_send_inputs $TEST_SYSTEM_CONN_URI
|
||||
podman_tui_send_inputs "Tab" "Tab" "Tab" "Enter"
|
||||
sleep 1
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
|
||||
run_helper tail -2 $PODMAN_TUI_CONFIG_FILE
|
||||
assert "$output" =~ "[services.${TEST_SYSTEM_CONN_NAME}]" "expected [services.${TEST_SYSTEM_CONN_NAME}] in ${PODMAN_TUI_CONFIG_FILE}"
|
||||
assert "$output" =~ "uri = \"unix://run/podman/podman.sock\"" "expected ${TEST_SYSTEM_CONN_URI} in ${PODMAN_TUI_CONFIG_FILE}"
|
||||
run_helper jq ".connections.${TEST_SYSTEM_CONN_NAME}.uri" ${PODMAN_TUI_CONFIG_FILE}
|
||||
assert "$output" == "\"$TEST_SYSTEM_CONN_URI\"" "expected ${TEST_SYSTEM_CONN_URI} in ${PODMAN_TUI_CONFIG_FILE}"
|
||||
}
|
||||
|
||||
@test "system set default" {
|
||||
|
@ -32,12 +31,13 @@ load helpers_tui
|
|||
podman_tui_set_view "system"
|
||||
podman_tui_select_item 1
|
||||
podman_tui_select_system_cmd "default"
|
||||
sleep 1
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
|
||||
run_helper tail -3 $PODMAN_TUI_CONFIG_FILE
|
||||
assert "$output" =~ "[services.${TEST_SYSTEM_CONN_NAME}]" "expected [services.${TEST_SYSTEM_CONN_NAME}] in ${PODMAN_TUI_CONFIG_FILE}"
|
||||
assert "$output" =~ "uri = \"unix://run/podman/podman.sock\"" "expected ${TEST_SYSTEM_CONN_URI} in ${PODMAN_TUI_CONFIG_FILE}"
|
||||
assert "$output" =~ "default = true" "expected 'default = true' in ${PODMAN_TUI_CONFIG_FILE}"
|
||||
run_helper jq ".connections.${TEST_SYSTEN_CONN_LOCAL}.uri" ${PODMAN_TUI_CONFIG_FILE}
|
||||
assert "$output" == "\"$TEST_SYSTEM_CONN_URI\"" "expected ${TEST_SYSTEM_CONN_URI} in ${PODMAN_TUI_CONFIG_FILE}"
|
||||
|
||||
run_helper jq ".connections.${TEST_SYSTEN_CONN_LOCAL}.default" ${PODMAN_TUI_CONFIG_FILE}
|
||||
assert "$output" == "true" "expected 'default = true' in ${PODMAN_TUI_CONFIG_FILE}"
|
||||
}
|
||||
|
||||
@test "system remove" {
|
||||
|
@ -49,10 +49,10 @@ load helpers_tui
|
|||
podman_tui_select_item 1
|
||||
podman_tui_select_system_cmd "remove"
|
||||
podman_tui_send_inputs "Enter"
|
||||
sleep 1
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
|
||||
run_helper tail -3 $PODMAN_TUI_CONFIG_FILE
|
||||
assert "$output" !~ "services.${TEST_SYSTEM_CONN_NAME}" "expected [services.${TEST_SYSTEM_CONN_NAME}] not in ${PODMAN_TUI_CONFIG_FILE}"
|
||||
run_helper jq ".connections.${TEST_SYSTEN_CONN_LOCAL}" ${PODMAN_TUI_CONFIG_FILE}
|
||||
assert "$output" == "null" "expected ${TEST_SYSTEN_CONN_LOCAL} connection to be removed from in ${PODMAN_TUI_CONFIG_FILE}"
|
||||
}
|
||||
|
||||
@test "system disconnect" {
|
||||
|
@ -60,7 +60,7 @@ load helpers_tui
|
|||
# select "disconnect" command
|
||||
podman_tui_set_view "system"
|
||||
podman_tui_select_system_cmd "disconnect"
|
||||
sleep 2
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
|
||||
run_helper tmux capture-pane -pS 0 -E 0
|
||||
assert "$output" =~ "DISCONNECTED" "expected DISCONNECTED connection status"
|
||||
|
@ -74,13 +74,13 @@ load helpers_tui
|
|||
# select "disconnect" command
|
||||
podman_tui_set_view "system"
|
||||
podman_tui_select_system_cmd "disconnect"
|
||||
sleep 2
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
run_helper tmux capture-pane -pS 0 -E 0
|
||||
assert "$output" =~ "DISCONNECTED" "expected DISCONNECTED connection status"
|
||||
|
||||
# select "connect" command
|
||||
podman_tui_select_system_cmd "connect"
|
||||
sleep 3
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
run_helper tmux capture-pane -pS 0 -E 0
|
||||
assert "$output" =~ "STATUS_OK" "expected STATUS_OK connection status"
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ PODMAN_TUI=${PODMAN_TUI:-./bin/podman-tui}
|
|||
PODMAN_TUI_DEBUG="$PODMAN_TUI -d"
|
||||
PODMAN_TUI_LOG="podman-tui.log"
|
||||
PODMAN_TUI_CONFIG_DIR="/root/.config/podman-tui"
|
||||
PODMAN_TUI_CONFIG_FILE="${PODMAN_TUI_CONFIG_DIR}/podman-tui.conf"
|
||||
PODMAN_TUI_CONFIG_FILE="${PODMAN_TUI_CONFIG_DIR}/podman-tui.json"
|
||||
TMUX_SESSION="podman_tui_test"
|
||||
|
||||
|
||||
|
@ -13,12 +13,7 @@ function setup() {
|
|||
# setup config file
|
||||
[ ! -d "${PODMAN_TUI_CONFIG_DIR}" ] && mkdir -p ${PODMAN_TUI_CONFIG_DIR}
|
||||
cat > ${PODMAN_TUI_CONFIG_FILE} << EOF
|
||||
[services]
|
||||
[services.localhost]
|
||||
uri = "unix://run/podman/podman.sock"
|
||||
default = true
|
||||
[services.localhost_test]
|
||||
uri = "unix://run/podman/podman.sock"
|
||||
{"connections":{"localhost":{"uri":"unix://run/podman/podman.sock","default":true},"localhost_test":{"uri":"unix://run/podman/podman.sock"}}}
|
||||
EOF
|
||||
|
||||
# start podman socket
|
||||
|
|
|
@ -11,9 +11,9 @@ TEST_POD_NETWORK_NAME="${TEST_NAME}_pod01_net"
|
|||
TEST_CONTAINER_NAME="${TEST_NAME}_cnt01"
|
||||
TEST_CONTAINER_CHECKPOINT_NAME="${TEST_NAME}_checkpoint"
|
||||
TEST_CONTAINER_HEALTH_CMD="date"
|
||||
TEST_CONTAINER_HEALTH_INTERVAL="60s"
|
||||
TEST_CONTAINER_HEALTH_TIMEOUT="60s"
|
||||
TEST_CONTAINER_HEALTH_RETRIES="6"
|
||||
TEST_CONTAINER_HEALTH_INTERVAL="30s"
|
||||
TEST_CONTAINER_HEALTH_TIMEOUT="30s"
|
||||
TEST_CONTAINER_HEALTH_RETRIES="3"
|
||||
TEST_CONTAINER_HEALTH_ONFAILURE="restart"
|
||||
TEST_CONTAINER_POD_NAME="${TEST_NAME}_cnt01_pod"
|
||||
TEST_CONTAINER_NETWORK_NAME="${TEST_NAME}_cnt01_net"
|
||||
|
@ -28,15 +28,33 @@ TEST_CONTAINER_WORKDIR="/${TEST_NAME}_workdir"
|
|||
TEST_CONTAINER_ENV1="key1=value1"
|
||||
TEST_CONTAINER_ENV2="key2=value2"
|
||||
TEST_CONTAINER_UMASK="0777"
|
||||
TEST_CONTAINER_RUN_CMD="/bin/sh"
|
||||
TEST_LABEL_NAME="test"
|
||||
TEST_LABEL_VALUE="$TEST_NAME"
|
||||
TEST_LABEL="${TEST_LABEL_NAME}=${TEST_LABEL_VALUE}"
|
||||
TEST_SYSTEN_CONN_LOCAL="localhost_test"
|
||||
TEST_SYSTEM_CONN_NAME="localhost_test_tui"
|
||||
TEST_SYSTEM_CONN_URI="unix://run/podman/podman.sock"
|
||||
TEST_IMAGE_BUILD_CONTEXT_DIR="$(realpath .)/test/testdata/"
|
||||
TEST_IMAGE_BUILD_TAG="${TEST_NAME}_image:latest"
|
||||
TEST_IMAGE_BUILD_REPOSITORY="localhost"
|
||||
TEST_IMAGE_SAVE_PATH="/tmp/${TEST_NAME}_image_save.tar"
|
||||
TEST_CONTAINER_MEMORY=100
|
||||
TEST_CONTAINER_MEMORY_RESERV=80
|
||||
TEST_CONTAINER_MEMORY_SWAP=150
|
||||
TEST_CONTAINER_MEMORY_SWAPPINESS=50
|
||||
TEST_CONTAINER_CPU_SHARES=10
|
||||
TEST_CONTAINER_CPU_PERIOD=20
|
||||
TEST_CONTAINER_CPU_QUOTA=10
|
||||
TEST_CONTAINER_SHM_SIZE=120
|
||||
TEST_CONTAINER_SHM_SIZE_SYSTYEMD=150
|
||||
TEST_POD_MEMORY=20
|
||||
TEST_POD_SWAP=30
|
||||
TEST_POD_CPUSET_MEM=40
|
||||
TEST_POD_CPU_SHARES=50
|
||||
TEST_TIMEOUT_HIGH=15
|
||||
TEST_TIMEOUT_MEDIUM=10
|
||||
TEST_TIMEOUT_LOW=5
|
||||
|
||||
################
|
||||
# podman_tui_set_view # switches to different podman-tui views
|
||||
|
@ -237,16 +255,18 @@ function podman_tui_select_container_cmd() {
|
|||
menu_index=14;;
|
||||
"remove")
|
||||
menu_index=15;;
|
||||
"start")
|
||||
"run")
|
||||
menu_index=16;;
|
||||
"stat")
|
||||
"start")
|
||||
menu_index=17;;
|
||||
"stop")
|
||||
"stat")
|
||||
menu_index=18;;
|
||||
"top")
|
||||
"stop")
|
||||
menu_index=19;;
|
||||
"unpause")
|
||||
"top")
|
||||
menu_index=20;;
|
||||
"unpause")
|
||||
menu_index=21;;
|
||||
esac
|
||||
|
||||
podman_tui_select_menu $menu_index
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -16,7 +16,7 @@ var _ = Describe("container create", Ordered, func() {
|
|||
|
||||
BeforeAll(func() {
|
||||
createDialogApp = tview.NewApplication()
|
||||
createDialog = NewContainerCreateDialog()
|
||||
createDialog = NewContainerCreateDialog(ContainerCreateOnlyDialogMode)
|
||||
createDialogScreen = tcell.NewSimulationScreen("UTF-8")
|
||||
err := createDialogScreen.Init()
|
||||
if err != nil {
|
||||
|
@ -52,7 +52,7 @@ var _ = Describe("container create", Ordered, func() {
|
|||
createDialogApp.Draw()
|
||||
Expect(createDialog.dropdownHasFocus()).To(Equal(true))
|
||||
|
||||
createDialog.focusElement = createcontainerPodFieldFocis
|
||||
createDialog.focusElement = createcontainerPodFieldFocus
|
||||
createDialogApp.SetFocus(createDialog)
|
||||
createDialogApp.Draw()
|
||||
Expect(createDialog.dropdownHasFocus()).To(Equal(true))
|
||||
|
@ -89,7 +89,7 @@ var _ = Describe("container create", Ordered, func() {
|
|||
createFunc := func() {
|
||||
createAction = createWants
|
||||
}
|
||||
createDialog.SetCreateFunc(createFunc)
|
||||
createDialog.SetHandlerFunc(createFunc)
|
||||
createDialog.focusElement = createContainerFormFocus
|
||||
createDialogApp.SetFocus(createDialog)
|
||||
createDialogApp.Draw()
|
||||
|
@ -210,6 +210,11 @@ var _ = Describe("container create", Ordered, func() {
|
|||
|
||||
It("setContainerInfoPageNextFocus", func() {
|
||||
createDialog.focusElement = createContainerNameFieldFocus
|
||||
createDialogApp.SetFocus(createDialog)
|
||||
createDialogApp.Draw()
|
||||
createDialog.setContainerInfoPageNextFocus()
|
||||
Expect(createDialog.focusElement).To(Equal(createContainerCommandFieldFocus))
|
||||
|
||||
createDialogApp.SetFocus(createDialog)
|
||||
createDialogApp.Draw()
|
||||
createDialog.setContainerInfoPageNextFocus()
|
||||
|
@ -218,7 +223,7 @@ var _ = Describe("container create", Ordered, func() {
|
|||
createDialogApp.SetFocus(createDialog)
|
||||
createDialogApp.Draw()
|
||||
createDialog.setContainerInfoPageNextFocus()
|
||||
Expect(createDialog.focusElement).To(Equal(createcontainerPodFieldFocis))
|
||||
Expect(createDialog.focusElement).To(Equal(createcontainerPodFieldFocus))
|
||||
|
||||
createDialogApp.SetFocus(createDialog)
|
||||
createDialogApp.Draw()
|
||||
|
@ -240,6 +245,11 @@ var _ = Describe("container create", Ordered, func() {
|
|||
createDialog.setContainerInfoPageNextFocus()
|
||||
Expect(createDialog.focusElement).To(Equal(createContainerTimeoutFieldFocus))
|
||||
|
||||
createDialogApp.SetFocus(createDialog)
|
||||
createDialogApp.Draw()
|
||||
createDialog.setContainerInfoPageNextFocus()
|
||||
Expect(createDialog.focusElement).To(Equal(createContainerSecretFieldFocus))
|
||||
|
||||
createDialogApp.SetFocus(createDialog)
|
||||
createDialogApp.Draw()
|
||||
createDialog.setContainerInfoPageNextFocus()
|
||||
|
@ -289,6 +299,74 @@ var _ = Describe("container create", Ordered, func() {
|
|||
Expect(createDialog.focusElement).To(Equal(createContainerFormFocus))
|
||||
})
|
||||
|
||||
It("setResourceSettingsPageNextFocus", func() {
|
||||
createDialog.focusElement = createContainerMemoryFieldFocus
|
||||
createDialogApp.SetFocus(createDialog)
|
||||
createDialogApp.Draw()
|
||||
createDialog.setResourceSettingsPageNextFocus()
|
||||
Expect(createDialog.focusElement).To(Equal(createContainerMemoryReservatoinFieldFocus))
|
||||
|
||||
createDialogApp.SetFocus(createDialog)
|
||||
createDialogApp.Draw()
|
||||
createDialog.setResourceSettingsPageNextFocus()
|
||||
Expect(createDialog.focusElement).To(Equal(createContainerMemorySwapFieldFocus))
|
||||
|
||||
createDialogApp.SetFocus(createDialog)
|
||||
createDialogApp.Draw()
|
||||
createDialog.setResourceSettingsPageNextFocus()
|
||||
Expect(createDialog.focusElement).To(Equal(createcontainerMemorySwappinessFieldFocus))
|
||||
|
||||
createDialogApp.SetFocus(createDialog)
|
||||
createDialogApp.Draw()
|
||||
createDialog.setResourceSettingsPageNextFocus()
|
||||
Expect(createDialog.focusElement).To(Equal(createContainerCPUsFieldFocus))
|
||||
|
||||
createDialogApp.SetFocus(createDialog)
|
||||
createDialogApp.Draw()
|
||||
createDialog.setResourceSettingsPageNextFocus()
|
||||
Expect(createDialog.focusElement).To(Equal(createContainerCPUSharesFieldFocus))
|
||||
|
||||
createDialogApp.SetFocus(createDialog)
|
||||
createDialogApp.Draw()
|
||||
createDialog.setResourceSettingsPageNextFocus()
|
||||
Expect(createDialog.focusElement).To(Equal(createContainerCPUPeriodFieldFocus))
|
||||
|
||||
createDialogApp.SetFocus(createDialog)
|
||||
createDialogApp.Draw()
|
||||
createDialog.setResourceSettingsPageNextFocus()
|
||||
Expect(createDialog.focusElement).To(Equal(createContainerCPURtPeriodFieldFocus))
|
||||
|
||||
createDialogApp.SetFocus(createDialog)
|
||||
createDialogApp.Draw()
|
||||
createDialog.setResourceSettingsPageNextFocus()
|
||||
Expect(createDialog.focusElement).To(Equal(createContainerCPUQuotaFieldFocus))
|
||||
|
||||
createDialogApp.SetFocus(createDialog)
|
||||
createDialogApp.Draw()
|
||||
createDialog.setResourceSettingsPageNextFocus()
|
||||
Expect(createDialog.focusElement).To(Equal(createContainerCPURtRuntimeFeildFocus))
|
||||
|
||||
createDialogApp.SetFocus(createDialog)
|
||||
createDialogApp.Draw()
|
||||
createDialog.setResourceSettingsPageNextFocus()
|
||||
Expect(createDialog.focusElement).To(Equal(createContainerCPUSetCPUsFieldFocus))
|
||||
|
||||
createDialogApp.SetFocus(createDialog)
|
||||
createDialogApp.Draw()
|
||||
createDialog.setResourceSettingsPageNextFocus()
|
||||
Expect(createDialog.focusElement).To(Equal(createContainerCPUSetMemsFieldFocus))
|
||||
|
||||
createDialogApp.SetFocus(createDialog)
|
||||
createDialogApp.Draw()
|
||||
createDialog.setResourceSettingsPageNextFocus()
|
||||
Expect(createDialog.focusElement).To(Equal(createContainerShmSizeFieldFocus))
|
||||
|
||||
createDialogApp.SetFocus(createDialog)
|
||||
createDialogApp.Draw()
|
||||
createDialog.setResourceSettingsPageNextFocus()
|
||||
Expect(createDialog.focusElement).To(Equal(createContainerShmSizeSystemdFieldFocus))
|
||||
})
|
||||
|
||||
It("hide", func() {
|
||||
createDialog.Hide()
|
||||
Expect(createDialog.IsDisplay()).To(Equal(false))
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/containers/podman-tui/pdcs/containers"
|
||||
"github.com/containers/podman-tui/ui/dialogs"
|
||||
|
@ -55,6 +56,8 @@ type VtermDialog struct { //nolint:revive
|
|||
init bool
|
||||
ttyWidth int
|
||||
ttyHeight int
|
||||
alreadyDetached bool
|
||||
alreadyDetachedLock sync.Mutex
|
||||
cancelHandler func()
|
||||
fastRefreshHandler func()
|
||||
}
|
||||
|
@ -74,7 +77,8 @@ func NewVtermDialog() *VtermDialog {
|
|||
tcell.KeyCtrlP, tcell.KeyCtrlQ, tcell.KeyCtrlP,
|
||||
},
|
||||
},
|
||||
display: false,
|
||||
display: false,
|
||||
alreadyDetached: false,
|
||||
}
|
||||
|
||||
dialog.initLayoutUI()
|
||||
|
@ -118,7 +122,7 @@ func (d *VtermDialog) initLayoutUI() {
|
|||
layout.SetBackgroundColor(bgColor)
|
||||
layout.SetBorder(false)
|
||||
layout.AddItem(d.containerInfo, 1, 0, true)
|
||||
layout.AddItem(utils.EmptyBoxSpace(bgColor), 1, 0, true)
|
||||
// layout.AddItem(utils.EmptyBoxSpace(bgColor), 1, 0, true)
|
||||
layout.AddItem(d.termScreen, 0, 1, true)
|
||||
|
||||
termLayout.SetBackgroundColor(bgColor)
|
||||
|
@ -132,7 +136,7 @@ func (d *VtermDialog) initLayoutUI() {
|
|||
d.layout.SetBorder(true)
|
||||
d.layout.SetBorderColor(borderColor)
|
||||
d.layout.SetBackgroundColor(bgColor)
|
||||
d.layout.SetTitle("CONTAINER TERMINAL")
|
||||
// d.layout.SetTitle("CONTAINER TERMINAL")
|
||||
|
||||
d.layout.AddItem(termLayout, 0, 1, true)
|
||||
d.layout.AddItem(d.form, dialogs.DialogFormHeight, 0, true)
|
||||
|
@ -200,9 +204,29 @@ func (d *VtermDialog) Display() {
|
|||
go d.startVTBuffer()
|
||||
}
|
||||
|
||||
d.SetAlreadyDetach(false)
|
||||
d.display = true
|
||||
}
|
||||
|
||||
func (d *VtermDialog) SetAlreadyDetach(detached bool) {
|
||||
d.alreadyDetachedLock.Lock()
|
||||
defer d.alreadyDetachedLock.Unlock()
|
||||
|
||||
d.alreadyDetached = detached
|
||||
}
|
||||
|
||||
func (d *VtermDialog) IsAlreadyDetach() bool {
|
||||
var alreadyDetached bool
|
||||
|
||||
d.alreadyDetachedLock.Lock()
|
||||
|
||||
alreadyDetached = d.alreadyDetached
|
||||
|
||||
d.alreadyDetachedLock.Unlock()
|
||||
|
||||
return alreadyDetached
|
||||
}
|
||||
|
||||
// IsDisplay returns true if primitive is shown onto the screen.
|
||||
func (d *VtermDialog) IsDisplay() bool {
|
||||
return d.display
|
||||
|
@ -220,7 +244,9 @@ func (d *VtermDialog) Hide() {
|
|||
|
||||
d.sessionMode = sessionModeNone
|
||||
|
||||
d.sendDetachToSession()
|
||||
if !d.IsAlreadyDetach() {
|
||||
d.sendDetachToSession()
|
||||
}
|
||||
|
||||
if d.sessionMode == sessionModeExec {
|
||||
d.execSessionStdout.Close()
|
||||
|
@ -294,7 +320,9 @@ func (d *VtermDialog) InputHandler() func(event *tcell.EventKey, setFocus func(p
|
|||
if handler := d.termScreen.InputHandler(); handler != nil {
|
||||
handler(event, setFocus)
|
||||
|
||||
d.writeToSession(event)
|
||||
if !d.IsAlreadyDetach() {
|
||||
d.writeToSession(event)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -391,8 +419,12 @@ func (d *VtermDialog) SetCancelFunc(handler func()) *VtermDialog {
|
|||
// SetContainerInfo sets container's ID and NAME to the terminal header.
|
||||
func (d *VtermDialog) SetContainerInfo(id string, name string) {
|
||||
d.containerID = id
|
||||
containerInfo := id[0:12]
|
||||
|
||||
if name != "" {
|
||||
containerInfo = fmt.Sprintf("%s (%s)", containerInfo, name)
|
||||
}
|
||||
|
||||
containerInfo := fmt.Sprintf("%12s (%s)", id, name)
|
||||
d.containerInfo.SetText(containerInfo)
|
||||
}
|
||||
|
||||
|
@ -404,7 +436,7 @@ func (d *VtermDialog) SetSessionID(id string) {
|
|||
id = id[0:utils.IDLength]
|
||||
}
|
||||
|
||||
sessionIDLabel := fmt.Sprintf("SESSION (%s)", id)
|
||||
sessionIDLabel := fmt.Sprintf("TERMINAL SESSION (%s)", id)
|
||||
d.termScreen.SetTitle(sessionIDLabel)
|
||||
}
|
||||
|
||||
|
|
|
@ -46,6 +46,8 @@ func (cnt *Containers) runCommand(cmd string) { //nolint:cyclop
|
|||
cnt.port()
|
||||
case "rm":
|
||||
cnt.rm()
|
||||
case "run":
|
||||
cnt.runDialog.Display()
|
||||
case "start":
|
||||
cnt.start()
|
||||
case "stats":
|
||||
|
@ -90,6 +92,7 @@ func (cnt *Containers) attach() {
|
|||
|
||||
cnt.progressDialog.Hide()
|
||||
cnt.displayError(title, err)
|
||||
cnt.appFocusHandler()
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -101,6 +104,7 @@ func (cnt *Containers) attach() {
|
|||
cnt.progressDialog.Hide()
|
||||
cnt.terminalDialog.SetContainerInfo(cntID, cntName)
|
||||
cnt.terminalDialog.Display()
|
||||
cnt.appFocusHandler()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -128,6 +132,7 @@ func (cnt *Containers) preHealthcheck() {
|
|||
title := fmt.Sprintf("CONTAINER (%s) HEALTHCHECK ERROR", cntID)
|
||||
|
||||
cnt.displayError(title, err)
|
||||
cnt.appFocusHandler()
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -137,6 +142,7 @@ func (cnt *Containers) preHealthcheck() {
|
|||
cnt.messageDialog.SetTitle("podman container healthcheck")
|
||||
cnt.messageDialog.SetText(dialogs.MessageContainerInfo, headerLabel, report)
|
||||
cnt.messageDialog.Display()
|
||||
cnt.appFocusHandler()
|
||||
}
|
||||
|
||||
go cntHealthCheck()
|
||||
|
@ -205,6 +211,7 @@ func (cnt *Containers) restore() {
|
|||
|
||||
cnt.progressDialog.Hide()
|
||||
cnt.displayError(title, err)
|
||||
cnt.appFocusHandler()
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -215,6 +222,7 @@ func (cnt *Containers) restore() {
|
|||
cnt.messageDialog.SetTitle("podman container restore")
|
||||
cnt.messageDialog.SetText(dialogs.MessageContainerInfo, headerLabel, report)
|
||||
cnt.messageDialog.Display()
|
||||
cnt.appFocusHandler()
|
||||
}
|
||||
|
||||
go restore()
|
||||
|
@ -246,6 +254,7 @@ func (cnt *Containers) checkpoint() {
|
|||
|
||||
cnt.progressDialog.Hide()
|
||||
cnt.displayError(title, err)
|
||||
cnt.appFocusHandler()
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -256,6 +265,7 @@ func (cnt *Containers) checkpoint() {
|
|||
cnt.messageDialog.SetTitle("podman container checkpoint")
|
||||
cnt.messageDialog.SetText(dialogs.MessageContainerInfo, headerLabel, report)
|
||||
cnt.messageDialog.Display()
|
||||
cnt.appFocusHandler()
|
||||
}
|
||||
|
||||
go checkpoint()
|
||||
|
@ -289,6 +299,7 @@ func (cnt *Containers) commit() {
|
|||
title := fmt.Sprintf("CONTAINER (%s) COMMIT ERROR", cnt.selectedID)
|
||||
|
||||
cnt.displayError(title, err)
|
||||
cnt.appFocusHandler()
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -299,6 +310,7 @@ func (cnt *Containers) commit() {
|
|||
cnt.messageDialog.SetTitle("podman container commit")
|
||||
cnt.messageDialog.SetText(dialogs.MessageContainerInfo, headerLabel, response)
|
||||
cnt.messageDialog.Display()
|
||||
cnt.appFocusHandler()
|
||||
}
|
||||
|
||||
go cntCommit()
|
||||
|
@ -386,6 +398,7 @@ func (cnt *Containers) exec() {
|
|||
prepareAndExec := func() {
|
||||
cnt.terminalDialog.SetSessionID(execSessionID)
|
||||
containers.Exec(execSessionID, execOpts)
|
||||
cnt.terminalDialog.SetAlreadyDetach(true)
|
||||
}
|
||||
|
||||
go prepareAndExec()
|
||||
|
@ -393,9 +406,147 @@ func (cnt *Containers) exec() {
|
|||
cnt.terminalDialog.Display()
|
||||
}
|
||||
|
||||
func (cnt *Containers) run() {
|
||||
runOpts := cnt.runDialog.ContainerCreateOptions()
|
||||
if runOpts.Image == "" {
|
||||
cnt.displayError("CONTAINER RUN ERROR", errEmptyContainerImageName)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
cnt.progressDialog.SetTitle("container run in progress")
|
||||
cnt.progressDialog.Display()
|
||||
|
||||
if runOpts.Detach {
|
||||
cnt.runDetach(runOpts)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
cnt.runAttach(runOpts)
|
||||
}
|
||||
|
||||
func (cnt *Containers) runDetach(runOpts containers.CreateOptions) {
|
||||
go func() {
|
||||
warnings, cntID, err := containers.Create(runOpts, true)
|
||||
if err != nil {
|
||||
cnt.progressDialog.Hide()
|
||||
cnt.displayError("CONTAINER RUN ERROR", err)
|
||||
cnt.appFocusHandler()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if len(warnings) > 0 {
|
||||
cnt.progressDialog.Hide()
|
||||
|
||||
headerLabel := fmt.Sprintf("%s (%s)", "", runOpts.Name)
|
||||
|
||||
cnt.messageDialog.SetTitle("CONTAINER RUN WARNINGS")
|
||||
cnt.messageDialog.SetText(dialogs.MessageContainerInfo, headerLabel, strings.Join(warnings, "\n"))
|
||||
cnt.messageDialog.Display()
|
||||
cnt.appFocusHandler()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if err := containers.Start(cntID); err != nil {
|
||||
cnt.progressDialog.Hide()
|
||||
cnt.displayError("CONTAINER RUN ERROR", err)
|
||||
cnt.appFocusHandler()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
cnt.progressDialog.Hide()
|
||||
}()
|
||||
}
|
||||
|
||||
func (cnt *Containers) runAttach(runOpts containers.CreateOptions) {
|
||||
runStatusChan := make(chan bool)
|
||||
attachReady := make(chan bool)
|
||||
runIDChan := make(chan string)
|
||||
stdin, stdout := cnt.terminalDialog.InitAttachChannels()
|
||||
detachKeys := cnt.terminalDialog.DetachKeys()
|
||||
|
||||
run := func() {
|
||||
warnings, cntID, err := containers.Create(runOpts, true)
|
||||
if err != nil {
|
||||
runStatusChan <- false
|
||||
|
||||
cnt.displayError("CONTAINER RUN ERROR", err)
|
||||
cnt.appFocusHandler()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if len(warnings) > 0 {
|
||||
runStatusChan <- false
|
||||
|
||||
headerLabel := fmt.Sprintf("%s (%s)", "", runOpts.Name)
|
||||
|
||||
cnt.messageDialog.SetTitle("CONTAINER RUN WARNINGS")
|
||||
cnt.messageDialog.SetText(dialogs.MessageContainerInfo, headerLabel, strings.Join(warnings, "\n"))
|
||||
cnt.messageDialog.Display()
|
||||
cnt.appFocusHandler()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
runIDChan <- cntID
|
||||
|
||||
err = containers.RunInitAttach(cntID, stdin, stdout, attachReady, detachKeys)
|
||||
if err != nil {
|
||||
attachReady <- false
|
||||
|
||||
cnt.displayError("CONTAINER RUN ERROR", err)
|
||||
cnt.appFocusHandler()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
runStatusChan <- true
|
||||
}
|
||||
|
||||
waitForAttach := func() {
|
||||
cntID := ""
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-runStatusChan:
|
||||
cnt.terminalDialog.SetAlreadyDetach(true)
|
||||
cnt.progressDialog.Hide()
|
||||
|
||||
return
|
||||
|
||||
case id := <-runIDChan:
|
||||
cntID = id
|
||||
case isReady := <-attachReady:
|
||||
cnt.progressDialog.Hide()
|
||||
|
||||
if isReady {
|
||||
if err := containers.Start(cntID); err != nil {
|
||||
cnt.displayError("CONTAINER RUN ERROR", err)
|
||||
cnt.appFocusHandler()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
cnt.terminalDialog.SetContainerInfo(cntID, "")
|
||||
cnt.terminalDialog.Display()
|
||||
cnt.appFocusHandler()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
go waitForAttach()
|
||||
go run()
|
||||
}
|
||||
|
||||
func (cnt *Containers) create() {
|
||||
createOpts := cnt.createDialog.ContainerCreateOptions()
|
||||
if createOpts.Name == "" || createOpts.Image == "" {
|
||||
if createOpts.Image == "" {
|
||||
cnt.displayError("CONTAINER CREATE ERROR", errEmptyContainerImageName)
|
||||
|
||||
return
|
||||
|
@ -405,12 +556,13 @@ func (cnt *Containers) create() {
|
|||
cnt.progressDialog.Display()
|
||||
|
||||
create := func() {
|
||||
warnings, err := containers.Create(createOpts)
|
||||
warnings, _, err := containers.Create(createOpts, false)
|
||||
|
||||
cnt.progressDialog.Hide()
|
||||
|
||||
if err != nil {
|
||||
cnt.displayError("CONTAINER CREATE ERROR", err)
|
||||
cnt.appFocusHandler()
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -421,6 +573,7 @@ func (cnt *Containers) create() {
|
|||
cnt.messageDialog.SetTitle("CONTAINER CREATE WARNINGS")
|
||||
cnt.messageDialog.SetText(dialogs.MessageContainerInfo, headerLabel, strings.Join(warnings, "\n"))
|
||||
cnt.messageDialog.Display()
|
||||
cnt.appFocusHandler()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -446,7 +599,7 @@ func (cnt *Containers) diff() {
|
|||
|
||||
cnt.messageDialog.SetTitle("podman container diff")
|
||||
cnt.messageDialog.SetText(dialogs.MessageContainerInfo, headerLabel, strings.Join(data, "\n"))
|
||||
cnt.messageDialog.Display()
|
||||
cnt.messageDialog.DisplayFullSize()
|
||||
}
|
||||
|
||||
func (cnt *Containers) inspect() {
|
||||
|
@ -468,7 +621,7 @@ func (cnt *Containers) inspect() {
|
|||
|
||||
cnt.messageDialog.SetTitle("podman container inspect")
|
||||
cnt.messageDialog.SetText(dialogs.MessageContainerInfo, headerLabel, data)
|
||||
cnt.messageDialog.Display()
|
||||
cnt.messageDialog.DisplayFullSize()
|
||||
}
|
||||
|
||||
func (cnt *Containers) kill() {
|
||||
|
@ -489,6 +642,7 @@ func (cnt *Containers) kill() {
|
|||
if err != nil {
|
||||
title := fmt.Sprintf("CONTAINER (%s) KILL ERROR", cnt.selectedID)
|
||||
cnt.displayError(title, err)
|
||||
cnt.appFocusHandler()
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -517,6 +671,7 @@ func (cnt *Containers) logs() {
|
|||
title := fmt.Sprintf("CONTAINER (%s) DISPLAY LOG ERROR", cntID)
|
||||
|
||||
cnt.displayError(title, err)
|
||||
cnt.appFocusHandler()
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -530,7 +685,8 @@ func (cnt *Containers) logs() {
|
|||
cnt.messageDialog.SetTitle("podman container logs")
|
||||
cnt.messageDialog.SetText(dialogs.MessageContainerInfo, headerLabel, cntLogs)
|
||||
cnt.messageDialog.TextScrollToEnd()
|
||||
cnt.messageDialog.Display()
|
||||
cnt.messageDialog.DisplayFullSize()
|
||||
cnt.appFocusHandler()
|
||||
}
|
||||
|
||||
go getLogs()
|
||||
|
@ -554,6 +710,7 @@ func (cnt *Containers) pause() {
|
|||
if err != nil {
|
||||
title := fmt.Sprintf("CONTAINER (%s) PAUSE ERROR", cnt.selectedID)
|
||||
cnt.displayError(title, err)
|
||||
cnt.appFocusHandler()
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -605,6 +762,7 @@ func (cnt *Containers) prune() {
|
|||
|
||||
if err != nil {
|
||||
cnt.displayError("CONTAINER PRUNE ERROR", err)
|
||||
cnt.appFocusHandler()
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -657,6 +815,7 @@ func (cnt *Containers) renameContainer(id string, newName string) {
|
|||
if err != nil {
|
||||
title := fmt.Sprintf("CONTAINER (%s) RENAME ERROR", cnt.selectedID)
|
||||
cnt.displayError(title, err)
|
||||
cnt.appFocusHandler()
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -700,6 +859,7 @@ func (cnt *Containers) remove() {
|
|||
title := fmt.Sprintf("CONTAINER (%s) REMOVE ERROR", cnt.selectedID)
|
||||
|
||||
cnt.displayError(title, err)
|
||||
cnt.appFocusHandler()
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -708,6 +868,7 @@ func (cnt *Containers) remove() {
|
|||
title := fmt.Sprintf("CONTAINER (%s) REMOVE ERROR", cnt.selectedID)
|
||||
|
||||
cnt.displayError(title, fmt.Errorf("%v", errData)) //nolint:goerr113
|
||||
cnt.appFocusHandler()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -733,6 +894,7 @@ func (cnt *Containers) start() {
|
|||
title := fmt.Sprintf("CONTAINER (%s) START ERROR", cnt.selectedID)
|
||||
|
||||
cnt.displayError(title, err)
|
||||
cnt.appFocusHandler()
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -759,6 +921,7 @@ func (cnt *Containers) stop() {
|
|||
title := fmt.Sprintf("CONTAINER (%s) STOP ERROR", cnt.selectedID)
|
||||
|
||||
cnt.displayError(title, err)
|
||||
cnt.appFocusHandler()
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -808,6 +971,7 @@ func (cnt *Containers) unpause() {
|
|||
title := fmt.Sprintf("CONTAINER (%s) UNPAUSE ERROR", cnt.selectedID)
|
||||
|
||||
cnt.displayError(title, err)
|
||||
cnt.appFocusHandler()
|
||||
|
||||
return
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ var (
|
|||
errNoContainerStart = errors.New("there is no container to start")
|
||||
errNoContainerStop = errors.New("there is no container to stop")
|
||||
errNoContainerTop = errors.New("there is no container to display top")
|
||||
errEmptyContainerImageName = errors.New("empty container name or image name")
|
||||
errEmptyContainerImageName = errors.New("empty container image name")
|
||||
)
|
||||
|
||||
// Containers implements the containers page primitive.
|
||||
|
@ -60,6 +60,7 @@ type Containers struct {
|
|||
progressDialog *dialogs.ProgressDialog
|
||||
topDialog *dialogs.TopDialog
|
||||
createDialog *cntdialogs.ContainerCreateDialog
|
||||
runDialog *cntdialogs.ContainerCreateDialog
|
||||
execDialog *cntdialogs.ContainerExecDialog
|
||||
terminalDialog *vterm.VtermDialog
|
||||
statsDialog *cntdialogs.ContainerStatsDialog
|
||||
|
@ -71,6 +72,7 @@ type Containers struct {
|
|||
selectedName string
|
||||
confirmData string
|
||||
fastRefreshChan chan bool
|
||||
appFocusHandler func()
|
||||
}
|
||||
|
||||
type containerListReport struct {
|
||||
|
@ -90,7 +92,8 @@ func NewContainers() *Containers {
|
|||
progressDialog: dialogs.NewProgressDialog(),
|
||||
confirmDialog: dialogs.NewConfirmDialog(),
|
||||
topDialog: dialogs.NewTopDialog(),
|
||||
createDialog: cntdialogs.NewContainerCreateDialog(),
|
||||
createDialog: cntdialogs.NewContainerCreateDialog(cntdialogs.ContainerCreateOnlyDialogMode),
|
||||
runDialog: cntdialogs.NewContainerCreateDialog(cntdialogs.ContainerCreateAndRunDialogMode),
|
||||
execDialog: cntdialogs.NewContainerExecDialog(),
|
||||
terminalDialog: vterm.NewVtermDialog(),
|
||||
statsDialog: cntdialogs.NewContainerStatsDialog(),
|
||||
|
@ -117,6 +120,7 @@ func NewContainers() *Containers {
|
|||
{"rename", "rename the selected container"},
|
||||
{"restore", "restores a container from a checkpoint"},
|
||||
{"rm", "remove the selected container"},
|
||||
{"run", "runs a command in a new container from the given image"},
|
||||
{"start", "start the selected containers"},
|
||||
{"stats", "display container resource usage statistics"},
|
||||
{"stop", "stop the selected containers"},
|
||||
|
@ -180,11 +184,21 @@ func NewContainers() *Containers {
|
|||
containers.createDialog.Hide()
|
||||
})
|
||||
|
||||
containers.createDialog.SetCreateFunc(func() {
|
||||
containers.createDialog.SetHandlerFunc(func() {
|
||||
containers.createDialog.Hide()
|
||||
containers.create()
|
||||
})
|
||||
|
||||
// set run dialog functions
|
||||
containers.runDialog.SetCancelFunc(func() {
|
||||
containers.runDialog.Hide()
|
||||
})
|
||||
|
||||
containers.runDialog.SetHandlerFunc(func() {
|
||||
containers.runDialog.Hide()
|
||||
containers.run()
|
||||
})
|
||||
|
||||
// set exec dialog functions
|
||||
containers.execDialog.SetCancelFunc(containers.execDialog.Hide)
|
||||
containers.execDialog.SetExecFunc(containers.exec)
|
||||
|
@ -213,6 +227,11 @@ func NewContainers() *Containers {
|
|||
return containers
|
||||
}
|
||||
|
||||
// SetAppFocusHandler sets application focus handler.
|
||||
func (cnt *Containers) SetAppFocusHandler(handler func()) {
|
||||
cnt.appFocusHandler = handler
|
||||
}
|
||||
|
||||
// GetTitle returns primitive title.
|
||||
func (cnt *Containers) GetTitle() string {
|
||||
return cnt.title
|
||||
|
@ -248,11 +267,11 @@ func (cnt *Containers) HasFocus() bool { //nolint:cyclop
|
|||
return true
|
||||
}
|
||||
|
||||
if cnt.Box.HasFocus() || cnt.terminalDialog.HasFocus() {
|
||||
if cnt.runDialog.HasFocus() || cnt.terminalDialog.HasFocus() {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
return cnt.Box.HasFocus()
|
||||
}
|
||||
|
||||
// SubDialogHasFocus returns whether or not sub dialog primitive has focus.
|
||||
|
@ -285,7 +304,7 @@ func (cnt *Containers) SubDialogHasFocus() bool { //nolint:cyclop
|
|||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
return cnt.runDialog.HasFocus()
|
||||
}
|
||||
|
||||
// Focus is called when this primitive receives focus.
|
||||
|
@ -339,6 +358,13 @@ func (cnt *Containers) Focus(delegate func(p tview.Primitive)) { //nolint:cyclop
|
|||
return
|
||||
}
|
||||
|
||||
// run dialog
|
||||
if cnt.runDialog.IsDisplay() {
|
||||
delegate(cnt.runDialog)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// exec dialog
|
||||
if cnt.execDialog.IsDisplay() {
|
||||
delegate(cnt.execDialog)
|
||||
|
@ -440,6 +466,10 @@ func (cnt *Containers) HideAllDialogs() { //nolint:cyclop
|
|||
cnt.createDialog.Hide()
|
||||
}
|
||||
|
||||
if cnt.runDialog.IsDisplay() {
|
||||
cnt.runDialog.Hide()
|
||||
}
|
||||
|
||||
if cnt.execDialog.IsDisplay() {
|
||||
cnt.execDialog.Hide()
|
||||
}
|
||||
|
|
|
@ -26,14 +26,16 @@ func (cnt *Containers) UpdateData() {
|
|||
}
|
||||
|
||||
cnt.containersList.mu.Lock()
|
||||
defer cnt.containersList.mu.Unlock()
|
||||
|
||||
cnt.containersList.report = cntList
|
||||
cnt.containersList.mu.Unlock()
|
||||
}
|
||||
|
||||
func (cnt *Containers) getData() []entities.ListContainer {
|
||||
cnt.containersList.mu.Lock()
|
||||
defer cnt.containersList.mu.Unlock()
|
||||
|
||||
data := cnt.containersList.report
|
||||
cnt.containersList.mu.Unlock()
|
||||
|
||||
return data
|
||||
}
|
||||
|
@ -41,8 +43,9 @@ func (cnt *Containers) getData() []entities.ListContainer {
|
|||
// ClearData clears table data.
|
||||
func (cnt *Containers) ClearData() {
|
||||
cnt.containersList.mu.Lock()
|
||||
defer cnt.containersList.mu.Unlock()
|
||||
|
||||
cnt.containersList.report = nil
|
||||
cnt.containersList.mu.Unlock()
|
||||
cnt.table.Clear()
|
||||
|
||||
expand := 1
|
||||
|
|
|
@ -6,17 +6,17 @@ import (
|
|||
|
||||
// Draw draws this primitive onto the screen.
|
||||
func (cnt *Containers) Draw(screen tcell.Screen) { //nolint:cyclop
|
||||
cnt.refresh()
|
||||
cnt.Box.DrawForSubclass(screen, cnt)
|
||||
cnt.Box.SetBorder(false)
|
||||
|
||||
x, y, width, height := cnt.GetInnerRect()
|
||||
cntViewX, cntViewY, cntViewW, cntViewH := cnt.GetInnerRect()
|
||||
|
||||
cnt.table.SetRect(x, y, width, height)
|
||||
cnt.refresh(cntViewW)
|
||||
cnt.table.SetRect(cntViewX, cntViewY, cntViewW, cntViewH)
|
||||
cnt.table.SetBorder(true)
|
||||
cnt.table.Draw(screen)
|
||||
|
||||
x, y, width, height = cnt.table.GetInnerRect()
|
||||
x, y, width, height := cnt.table.GetInnerRect()
|
||||
|
||||
// error dialog
|
||||
if cnt.errorDialog.IsDisplay() {
|
||||
|
@ -49,9 +49,23 @@ func (cnt *Containers) Draw(screen tcell.Screen) { //nolint:cyclop
|
|||
|
||||
return
|
||||
}
|
||||
|
||||
// run dialog
|
||||
if cnt.runDialog.IsDisplay() {
|
||||
cnt.runDialog.SetRect(x, y, width, height)
|
||||
cnt.runDialog.Draw(screen)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// message dialog
|
||||
if cnt.messageDialog.IsDisplay() {
|
||||
cnt.messageDialog.SetRect(x, y, width, height+1)
|
||||
if cnt.messageDialog.IsDisplayFullSize() {
|
||||
cnt.messageDialog.SetRect(cntViewX, cntViewY, cntViewW, cntViewH)
|
||||
} else {
|
||||
cnt.messageDialog.SetRect(x, y, width, height+1)
|
||||
}
|
||||
|
||||
cnt.messageDialog.Draw(screen)
|
||||
|
||||
return
|
||||
|
@ -121,7 +135,7 @@ func (cnt *Containers) Draw(screen tcell.Screen) { //nolint:cyclop
|
|||
|
||||
// terminal dialog
|
||||
if cnt.terminalDialog.IsDisplay() {
|
||||
cnt.terminalDialog.SetRect(x, y, width, height)
|
||||
cnt.terminalDialog.SetRect(cntViewX, cntViewY, cntViewW, cntViewH)
|
||||
cnt.terminalDialog.Draw(screen)
|
||||
|
||||
return
|
||||
|
|
|
@ -44,6 +44,13 @@ func (cnt *Containers) InputHandler() func(event *tcell.EventKey, setFocus func(
|
|||
}
|
||||
}
|
||||
|
||||
// run dialog handler
|
||||
if cnt.runDialog.HasFocus() {
|
||||
if runDialogHandler := cnt.runDialog.InputHandler(); runDialogHandler != nil {
|
||||
runDialogHandler(event, setFocus)
|
||||
}
|
||||
}
|
||||
|
||||
// exec dialog handler
|
||||
if cnt.execDialog.HasFocus() {
|
||||
if execDialogHandler := cnt.execDialog.InputHandler(); execDialogHandler != nil {
|
||||
|
|
|
@ -12,7 +12,9 @@ import (
|
|||
"github.com/rivo/tview"
|
||||
)
|
||||
|
||||
func (cnt *Containers) refresh() {
|
||||
func (cnt *Containers) refresh(maxWidth int) {
|
||||
imageColMaxWidth := maxWidth / 5 //nolint:mnd
|
||||
|
||||
cnt.table.Clear()
|
||||
|
||||
expand := 1
|
||||
|
@ -72,6 +74,7 @@ func (cnt *Containers) refresh() {
|
|||
// image name column
|
||||
cnt.table.SetCell(rowIndex, viewContainersImageColIndex,
|
||||
tview.NewTableCell(cntImage).
|
||||
SetMaxWidth(imageColMaxWidth).
|
||||
SetTextColor(cellTextColor).
|
||||
SetExpansion(expand).
|
||||
SetAlign(alignment))
|
||||
|
|
|
@ -134,9 +134,9 @@ func (d *ConfirmDialog) setRect() {
|
|||
|
||||
if d.width > DialogMinWidth {
|
||||
if messageWidth < DialogMinWidth {
|
||||
d.width = DialogMinWidth + 2 //nolint:mnd
|
||||
d.width = DialogMinWidth + 4 //nolint:mnd
|
||||
} else if messageWidth < d.width {
|
||||
d.width = messageWidth + 2 //nolint:mnd
|
||||
d.width = messageWidth + 6 //nolint:mnd
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -13,13 +13,14 @@ import (
|
|||
// MessageDialog is a simaple message dialog primitive.
|
||||
type MessageDialog struct {
|
||||
*tview.Box
|
||||
layout *tview.Flex
|
||||
infoType *tview.InputField
|
||||
textview *tview.TextView
|
||||
form *tview.Form
|
||||
display bool
|
||||
message string
|
||||
cancelHandler func()
|
||||
layout *tview.Flex
|
||||
infoType *tview.InputField
|
||||
textview *tview.TextView
|
||||
form *tview.Form
|
||||
display bool
|
||||
displayFullSize bool
|
||||
message string
|
||||
cancelHandler func()
|
||||
}
|
||||
|
||||
type messageInfo int
|
||||
|
@ -38,10 +39,11 @@ const (
|
|||
// NewMessageDialog returns new message dialog primitive.
|
||||
func NewMessageDialog(text string) *MessageDialog {
|
||||
dialog := &MessageDialog{
|
||||
Box: tview.NewBox(),
|
||||
infoType: tview.NewInputField(),
|
||||
display: false,
|
||||
message: text,
|
||||
Box: tview.NewBox(),
|
||||
infoType: tview.NewInputField(),
|
||||
display: false,
|
||||
displayFullSize: false,
|
||||
message: text,
|
||||
}
|
||||
|
||||
dialog.infoType.SetBackgroundColor(style.DialogBgColor)
|
||||
|
@ -65,7 +67,6 @@ func NewMessageDialog(text string) *MessageDialog {
|
|||
tlayout.AddItem(utils.EmptyBoxSpace(style.DialogBgColor), 1, 0, false)
|
||||
tlayout.AddItem(tview.NewFlex().SetDirection(tview.FlexRow).
|
||||
AddItem(dialog.infoType, 1, 0, false).
|
||||
AddItem(utils.EmptyBoxSpace(style.DialogBgColor), 1, 0, false).
|
||||
AddItem(dialog.textview, 0, 1, true),
|
||||
0, 1, true)
|
||||
tlayout.AddItem(utils.EmptyBoxSpace(style.DialogBgColor), 1, 0, false)
|
||||
|
@ -78,7 +79,6 @@ func NewMessageDialog(text string) *MessageDialog {
|
|||
dialog.form.SetButtonBackgroundColor(style.ButtonBgColor)
|
||||
|
||||
dialog.layout = tview.NewFlex().SetDirection(tview.FlexRow)
|
||||
dialog.layout.AddItem(utils.EmptyBoxSpace(style.DialogBgColor), 1, 0, true)
|
||||
dialog.layout.AddItem(tlayout, 0, 1, true)
|
||||
dialog.layout.AddItem(dialog.form, DialogFormHeight, 0, true)
|
||||
dialog.layout.SetBorder(true)
|
||||
|
@ -91,6 +91,13 @@ func NewMessageDialog(text string) *MessageDialog {
|
|||
// Display displays this primitive.
|
||||
func (d *MessageDialog) Display() {
|
||||
d.display = true
|
||||
d.displayFullSize = false
|
||||
}
|
||||
|
||||
// DisplayFullSize displays this primitive in full size.
|
||||
func (d *MessageDialog) DisplayFullSize() {
|
||||
d.display = true
|
||||
d.displayFullSize = true
|
||||
}
|
||||
|
||||
// IsDisplay returns true if primitive is shown.
|
||||
|
@ -98,6 +105,11 @@ func (d *MessageDialog) IsDisplay() bool {
|
|||
return d.display
|
||||
}
|
||||
|
||||
// IsDisplayFullSize returns true if primitive is shown in full size.
|
||||
func (d *MessageDialog) IsDisplayFullSize() bool {
|
||||
return d.displayFullSize
|
||||
}
|
||||
|
||||
// Hide stops displaying this primitive.
|
||||
func (d *MessageDialog) Hide() {
|
||||
d.message = ""
|
||||
|
@ -169,6 +181,17 @@ func (d *MessageDialog) HasFocus() bool {
|
|||
|
||||
// SetRect set rects for this primitive.
|
||||
func (d *MessageDialog) SetRect(x, y, width, height int) {
|
||||
if d.displayFullSize {
|
||||
dX := x + 1
|
||||
dY := y + 1
|
||||
dWidth := width - 2 //nolint:mnd
|
||||
dHeight := height - 2 //nolint:mnd
|
||||
|
||||
d.Box.SetRect(dX, dY, dWidth, dHeight)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
messageHeight := 0
|
||||
if d.message != "" {
|
||||
messageHeight = len(strings.Split(d.message, "\n")) + 3 //nolint:mnd
|
||||
|
@ -182,8 +205,8 @@ func (d *MessageDialog) SetRect(x, y, width, height int) {
|
|||
}
|
||||
|
||||
dWidth := width - (2 * DialogPadding) //nolint:mnd
|
||||
if messageWidth+4 < dWidth {
|
||||
dWidth = messageWidth + 4 //nolint:mnd
|
||||
if messageWidth+6 < dWidth {
|
||||
dWidth = messageWidth + 6 //nolint:mnd
|
||||
}
|
||||
|
||||
if DialogMinWidth < width && dWidth < DialogMinWidth {
|
||||
|
@ -193,7 +216,7 @@ func (d *MessageDialog) SetRect(x, y, width, height int) {
|
|||
emptySpace := (width - dWidth) / 2 //nolint:mnd
|
||||
dX := x + emptySpace
|
||||
|
||||
dHeight := messageHeight + DialogFormHeight + DialogPadding + 1
|
||||
dHeight := messageHeight + DialogFormHeight + DialogPadding
|
||||
if dHeight > height {
|
||||
dHeight = height - DialogPadding - 1
|
||||
}
|
||||
|
|
|
@ -62,9 +62,9 @@ var _ = Describe("message dialog", Ordered, func() {
|
|||
height := 20
|
||||
// wants
|
||||
wWants := 40
|
||||
hWants := 11
|
||||
xWants := 5 // 0 + (50-40)/2
|
||||
yWants := 4 // 0 + (20-8)/2 - 2
|
||||
hWants := 10
|
||||
xWants := 5
|
||||
yWants := 5
|
||||
|
||||
messageDialog.SetRect(x, y, width, height)
|
||||
x1, y1, w1, h1 := messageDialog.Box.GetRect()
|
||||
|
|
|
@ -77,6 +77,7 @@ func (img *Images) build() {
|
|||
|
||||
if err != nil {
|
||||
img.displayError("IMAGE BUILD ERROR", err)
|
||||
img.appFocusHandler()
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -84,6 +85,7 @@ func (img *Images) build() {
|
|||
img.messageDialog.SetTitle("podman image build")
|
||||
img.messageDialog.SetText(dialogs.MessageImageInfo, report, "")
|
||||
img.messageDialog.Display()
|
||||
img.appFocusHandler()
|
||||
}
|
||||
|
||||
go buildFunc()
|
||||
|
@ -108,7 +110,9 @@ func (img *Images) diff() {
|
|||
|
||||
if err != nil {
|
||||
title := fmt.Sprintf("IMAGE (%s) DIFF ERROR", imageID)
|
||||
|
||||
img.displayError(title, err)
|
||||
img.appFocusHandler()
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -117,7 +121,8 @@ func (img *Images) diff() {
|
|||
|
||||
img.messageDialog.SetTitle("podman image diff")
|
||||
img.messageDialog.SetText(dialogs.MessageImageInfo, headerLabel, strings.Join(data, "\n"))
|
||||
img.messageDialog.Display()
|
||||
img.messageDialog.DisplayFullSize()
|
||||
img.appFocusHandler()
|
||||
}
|
||||
|
||||
go diff()
|
||||
|
@ -160,6 +165,7 @@ func (img *Images) imageImport() {
|
|||
|
||||
if err != nil {
|
||||
img.displayError("IMAGE IMPORT ERROR", err)
|
||||
img.appFocusHandler()
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -167,6 +173,7 @@ func (img *Images) imageImport() {
|
|||
img.messageDialog.SetTitle("podman image import")
|
||||
img.messageDialog.SetText(dialogs.MessageImageInfo, newImageID, "")
|
||||
img.messageDialog.Display()
|
||||
img.appFocusHandler()
|
||||
}
|
||||
|
||||
go importFunc()
|
||||
|
@ -192,7 +199,7 @@ func (img *Images) inspect() {
|
|||
|
||||
img.messageDialog.SetTitle("podman image inspect")
|
||||
img.messageDialog.SetText(dialogs.MessageImageInfo, headerLabel, data)
|
||||
img.messageDialog.Display()
|
||||
img.messageDialog.DisplayFullSize()
|
||||
}
|
||||
|
||||
func (img *Images) cprune() {
|
||||
|
@ -213,6 +220,7 @@ func (img *Images) prune() {
|
|||
|
||||
if err != nil {
|
||||
img.displayError("IMAGE PRUNE ERROR", err)
|
||||
img.appFocusHandler()
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -243,7 +251,9 @@ func (img *Images) push() {
|
|||
if err := images.Push(img.selectedID, pushOptions); err != nil {
|
||||
img.progressDialog.Hide()
|
||||
title := fmt.Sprintf("IMAGE (%s) PUSH ERROR", img.selectedID)
|
||||
|
||||
img.displayError(title, err)
|
||||
img.appFocusHandler()
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -285,13 +295,16 @@ func (img *Images) remove() {
|
|||
|
||||
if err != nil {
|
||||
title := fmt.Sprintf("IMAGE (%s) REMOVE ERROR", imageID)
|
||||
|
||||
img.displayError(title, err)
|
||||
img.appFocusHandler()
|
||||
} else {
|
||||
headerLabel := fmt.Sprintf("%12s (%s)", imageID, imageName)
|
||||
|
||||
img.messageDialog.SetTitle("podman image remove")
|
||||
img.messageDialog.SetText(dialogs.MessageImageInfo, headerLabel, strings.Join(data, "\n"))
|
||||
img.messageDialog.Display()
|
||||
img.appFocusHandler()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -330,7 +343,9 @@ func (img *Images) save() {
|
|||
|
||||
if err != nil {
|
||||
title := fmt.Sprintf("IMAGE (%s) SAVE ERROR", img.selectedID)
|
||||
|
||||
img.displayError(title, err)
|
||||
img.appFocusHandler()
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -348,7 +363,9 @@ func (img *Images) search(term string) {
|
|||
result, err := images.Search(term)
|
||||
if err != nil {
|
||||
title := fmt.Sprintf("IMAGE (%s) SEARCH ERROR", img.selectedID)
|
||||
|
||||
img.displayError(title, err)
|
||||
img.appFocusHandler()
|
||||
}
|
||||
|
||||
img.searchDialog.UpdateResults(result)
|
||||
|
@ -423,7 +440,9 @@ func (img *Images) tree() {
|
|||
tree, err := images.Tree(imageID)
|
||||
if err != nil {
|
||||
title := fmt.Sprintf("IMAGE (%s) TREE ERROR", imageID)
|
||||
|
||||
img.displayError(title, err)
|
||||
img.appFocusHandler()
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -434,6 +453,7 @@ func (img *Images) tree() {
|
|||
img.messageDialog.SetTitle("podman image tree")
|
||||
img.messageDialog.SetText(dialogs.MessageImageInfo, headerLabel, tree)
|
||||
img.messageDialog.Display()
|
||||
img.appFocusHandler()
|
||||
}
|
||||
|
||||
img.progressDialog.SetTitle("image tree in progress")
|
||||
|
@ -459,7 +479,9 @@ func (img *Images) pull(image string) {
|
|||
err := images.Pull(name)
|
||||
if err != nil {
|
||||
title := fmt.Sprintf("IMAGE (%s) PULL ERROR", img.selectedID)
|
||||
|
||||
img.displayError(title, err)
|
||||
img.appFocusHandler()
|
||||
}
|
||||
|
||||
img.progressDialog.Hide()
|
||||
|
|
|
@ -22,14 +22,16 @@ func (img *Images) UpdateData() {
|
|||
}
|
||||
|
||||
img.imagesList.mu.Lock()
|
||||
defer img.imagesList.mu.Unlock()
|
||||
|
||||
img.imagesList.report = images
|
||||
img.imagesList.mu.Unlock()
|
||||
}
|
||||
|
||||
func (img *Images) getData() []images.ImageListReporter {
|
||||
img.imagesList.mu.Lock()
|
||||
defer img.imagesList.mu.Unlock()
|
||||
|
||||
data := img.imagesList.report
|
||||
img.imagesList.mu.Unlock()
|
||||
|
||||
return data
|
||||
}
|
||||
|
@ -37,8 +39,10 @@ func (img *Images) getData() []images.ImageListReporter {
|
|||
// ClearData clears table data.
|
||||
func (img *Images) ClearData() {
|
||||
img.imagesList.mu.Lock()
|
||||
defer img.imagesList.mu.Unlock()
|
||||
|
||||
img.imagesList.report = nil
|
||||
img.imagesList.mu.Unlock()
|
||||
|
||||
img.table.Clear()
|
||||
|
||||
expand := 1
|
||||
|
|
|
@ -6,17 +6,17 @@ import (
|
|||
|
||||
// Draw draws this primitive onto the screen.
|
||||
func (img *Images) Draw(screen tcell.Screen) { //nolint:cyclop
|
||||
img.refresh()
|
||||
img.Box.DrawForSubclass(screen, img)
|
||||
img.Box.SetBorder(false)
|
||||
|
||||
x, y, width, height := img.GetInnerRect()
|
||||
imagewViewX, imagewViewY, imagewViewW, imagewViewH := img.GetInnerRect()
|
||||
|
||||
img.table.SetRect(x, y, width, height)
|
||||
img.refresh(imagewViewW)
|
||||
img.table.SetRect(imagewViewX, imagewViewY, imagewViewW, imagewViewH)
|
||||
img.table.SetBorder(true)
|
||||
|
||||
img.table.Draw(screen)
|
||||
x, y, width, height = img.table.GetInnerRect()
|
||||
x, y, width, height := img.table.GetInnerRect()
|
||||
|
||||
// error dialog
|
||||
if img.errorDialog.IsDisplay() {
|
||||
|
@ -44,7 +44,12 @@ func (img *Images) Draw(screen tcell.Screen) { //nolint:cyclop
|
|||
|
||||
// message dialog
|
||||
if img.messageDialog.IsDisplay() {
|
||||
img.messageDialog.SetRect(x, y, width, height+1)
|
||||
if img.messageDialog.IsDisplayFullSize() {
|
||||
img.messageDialog.SetRect(imagewViewX, imagewViewY, imagewViewW, imagewViewH)
|
||||
} else {
|
||||
img.messageDialog.SetRect(x, y, width, height+1)
|
||||
}
|
||||
|
||||
img.messageDialog.Draw(screen)
|
||||
|
||||
return
|
||||
|
@ -60,7 +65,7 @@ func (img *Images) Draw(screen tcell.Screen) { //nolint:cyclop
|
|||
|
||||
// search dialog
|
||||
if img.searchDialog.IsDisplay() {
|
||||
img.searchDialog.SetRect(x, y, width, height)
|
||||
img.searchDialog.SetRect(imagewViewX, imagewViewY, imagewViewW, imagewViewH)
|
||||
img.searchDialog.Draw(screen)
|
||||
}
|
||||
|
||||
|
@ -72,7 +77,7 @@ func (img *Images) Draw(screen tcell.Screen) { //nolint:cyclop
|
|||
|
||||
// history dialog
|
||||
if img.historyDialog.IsDisplay() {
|
||||
img.historyDialog.SetRect(x, y, width, height)
|
||||
img.historyDialog.SetRect(imagewViewX, imagewViewY, imagewViewW, imagewViewH)
|
||||
img.historyDialog.Draw(screen)
|
||||
|
||||
return
|
||||
|
|
|
@ -58,6 +58,7 @@ type Images struct {
|
|||
selectedName string
|
||||
confirmData string
|
||||
fastRefreshChan chan bool
|
||||
appFocusHandler func()
|
||||
}
|
||||
|
||||
type imageListReport struct {
|
||||
|
@ -207,6 +208,11 @@ func NewImages() *Images {
|
|||
return images
|
||||
}
|
||||
|
||||
// SetAppFocusHandler sets application focus handler.
|
||||
func (img *Images) SetAppFocusHandler(handler func()) {
|
||||
img.appFocusHandler = handler
|
||||
}
|
||||
|
||||
// GetTitle returns primitive title.
|
||||
func (img *Images) GetTitle() string {
|
||||
return img.title
|
||||
|
|
|
@ -1246,7 +1246,7 @@ func (d *ImageBuildDialog) ImageBuildOptions() (images.ImageBuildOptions, error)
|
|||
|
||||
// basic info page
|
||||
// Containerfiles
|
||||
for _, cntFile := range strings.Split(d.containerFilePath.GetText(), " ") {
|
||||
for _, cntFile := range strings.Split(strings.TrimSpace(d.containerFilePath.GetText()), " ") {
|
||||
if cntFile != "" {
|
||||
cFile, err := utils.ResolveHomeDir(cntFile)
|
||||
if err != nil {
|
||||
|
@ -1262,14 +1262,14 @@ func (d *ImageBuildDialog) ImageBuildOptions() (images.ImageBuildOptions, error)
|
|||
BuildOptions: entities.BuildOptions{},
|
||||
}
|
||||
|
||||
dir, err := utils.ResolveHomeDir(d.contextDirectoryPath.GetText())
|
||||
dir, err := utils.ResolveHomeDir(strings.TrimSpace(d.contextDirectoryPath.GetText()))
|
||||
if err != nil {
|
||||
return images.ImageBuildOptions{}, fmt.Errorf("cannot resolve home directory %w", err)
|
||||
}
|
||||
|
||||
opts.BuildOptions.ContextDirectory = dir
|
||||
opts.BuildOptions.AdditionalTags = append(opts.BuildOptions.AdditionalTags, d.tagField.GetText())
|
||||
opts.BuildOptions.Registry = d.registryField.GetText()
|
||||
opts.BuildOptions.AdditionalTags = append(opts.BuildOptions.AdditionalTags, strings.TrimSpace(d.tagField.GetText()))
|
||||
opts.BuildOptions.Registry = strings.TrimSpace(d.registryField.GetText())
|
||||
|
||||
_, pullOption := d.pullPolicyField.GetCurrentOption()
|
||||
switch pullOption {
|
||||
|
|
|
@ -146,23 +146,15 @@ func (d *ImageHistoryDialog) InputHandler() func(event *tcell.EventKey, setFocus
|
|||
|
||||
// SetRect set rects for this primitive.
|
||||
func (d *ImageHistoryDialog) SetRect(x, y, width, height int) {
|
||||
dX := x + dialogs.DialogPadding
|
||||
dWidth := width - (2 * dialogs.DialogPadding) //nolint:mnd
|
||||
dHeight := len(d.results) + dialogs.DialogFormHeight + 5 //nolint:mnd
|
||||
|
||||
if dHeight > height {
|
||||
dHeight = height
|
||||
}
|
||||
|
||||
tableHeight := dHeight - dialogs.DialogFormHeight - 2 //nolint:mnd
|
||||
|
||||
hs := ((height - dHeight) / 2) //nolint:mnd
|
||||
dY := y + hs
|
||||
dX := x + 1
|
||||
dY := y + 1
|
||||
dWidth := width - 2 //nolint:mnd
|
||||
dHeight := height - 2 //nolint:mnd
|
||||
|
||||
d.Box.SetRect(dX, dY, dWidth, dHeight)
|
||||
|
||||
// set table height size
|
||||
d.layout.ResizeItem(d.table, tableHeight, 0)
|
||||
d.layout.ResizeItem(d.table, dHeight, 0)
|
||||
cWidth := d.getCreatedByWidth()
|
||||
|
||||
for i := range d.table.GetRowCount() {
|
||||
|
|
|
@ -319,7 +319,7 @@ func (d *ImageImportDialog) ImageImportOptions() (images.ImageImportOptions, err
|
|||
|
||||
commit = strings.TrimSpace(d.commitMessage.GetText())
|
||||
reference = strings.TrimSpace(d.reference.GetText())
|
||||
change = strings.Split(d.change.GetText(), " ")
|
||||
change = strings.Split(strings.TrimSpace(d.change.GetText()), " ")
|
||||
|
||||
opts := images.ImageImportOptions{
|
||||
Change: change,
|
||||
|
|
|
@ -413,7 +413,7 @@ func (d *ImageSearchDialog) SetPullFunc(handler func()) *ImageSearchDialog {
|
|||
|
||||
// GetSearchText returns search input field text.
|
||||
func (d *ImageSearchDialog) GetSearchText() string {
|
||||
return d.input.GetText()
|
||||
return strings.TrimSpace(d.input.GetText())
|
||||
}
|
||||
|
||||
// GetSelectedItem returns selected image name from search result table.
|
||||
|
|
|
@ -10,7 +10,7 @@ import (
|
|||
"github.com/rivo/tview"
|
||||
)
|
||||
|
||||
func (img *Images) refresh() {
|
||||
func (img *Images) refresh(_ int) {
|
||||
img.table.Clear()
|
||||
|
||||
expand := 1
|
||||
|
|
|
@ -50,6 +50,7 @@ func (nets *Networks) cconnect() {
|
|||
if err != nil {
|
||||
nets.progressDialog.Hide()
|
||||
nets.displayError("NETWORK CONNECT ERROR", err)
|
||||
nets.appFocusHandler()
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -60,6 +61,7 @@ func (nets *Networks) cconnect() {
|
|||
nets.connectDialog.SetContainers(cntListReport)
|
||||
nets.progressDialog.Hide()
|
||||
nets.connectDialog.Display()
|
||||
nets.appFocusHandler()
|
||||
}
|
||||
|
||||
go initData()
|
||||
|
@ -76,6 +78,7 @@ func (nets *Networks) connect() {
|
|||
if err := networks.Connect(connectOptions); err != nil {
|
||||
nets.progressDialog.Hide()
|
||||
nets.displayError("NETWORK CONNECT ERROR", err)
|
||||
nets.appFocusHandler()
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -101,6 +104,7 @@ func (nets *Networks) cdisconnect() {
|
|||
if err != nil {
|
||||
nets.progressDialog.Hide()
|
||||
nets.displayError("NETWORK DISCONNECT ERROR", err)
|
||||
nets.appFocusHandler()
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -111,6 +115,7 @@ func (nets *Networks) cdisconnect() {
|
|||
nets.disconnectDialog.SetContainers(cntListReport)
|
||||
nets.progressDialog.Hide()
|
||||
nets.disconnectDialog.Display()
|
||||
nets.appFocusHandler()
|
||||
}
|
||||
|
||||
go initData()
|
||||
|
@ -127,6 +132,7 @@ func (nets *Networks) disconnect() {
|
|||
if err := networks.Disconnect(networkName, containerID); err != nil {
|
||||
nets.progressDialog.Hide()
|
||||
nets.displayError("NETWORK DISCONNECT ERROR", err)
|
||||
nets.appFocusHandler()
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -170,7 +176,7 @@ func (nets *Networks) inspect() {
|
|||
|
||||
nets.messageDialog.SetTitle("podman network inspect")
|
||||
nets.messageDialog.SetText(dialogs.MessageNetworkInfo, headerLabel, data)
|
||||
nets.messageDialog.Display()
|
||||
nets.messageDialog.DisplayFullSize()
|
||||
}
|
||||
|
||||
func (nets *Networks) cprune() {
|
||||
|
@ -190,6 +196,7 @@ func (nets *Networks) prune() {
|
|||
if err := networks.Prune(); err != nil {
|
||||
nets.progressDialog.Hide()
|
||||
nets.displayError("NETWORK PRUNE ERROR", err)
|
||||
nets.appFocusHandler()
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -233,7 +240,9 @@ func (nets *Networks) remove() {
|
|||
|
||||
if err != nil {
|
||||
title := fmt.Sprintf("NETWORK (%s) REMOVE ERROR", nets.selectedID)
|
||||
|
||||
nets.displayError(title, err)
|
||||
nets.appFocusHandler()
|
||||
|
||||
return
|
||||
}
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
package networks
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/containers/podman-tui/pdcs/networks"
|
||||
"github.com/containers/podman-tui/ui/style"
|
||||
"github.com/rivo/tview"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
// UpdateData retrieves networks list data.
|
||||
func (nets *Networks) UpdateData() {
|
||||
netList, err := networks.List()
|
||||
if err != nil {
|
||||
log.Error().Msgf("view: networks update %v", err)
|
||||
nets.errorDialog.SetText(fmt.Sprintf("%v", err))
|
||||
nets.errorDialog.Display()
|
||||
}
|
||||
|
||||
nets.networkList.mu.Lock()
|
||||
defer nets.networkList.mu.Unlock()
|
||||
|
||||
nets.networkList.report = netList
|
||||
}
|
||||
|
||||
func (nets *Networks) getData() [][]string {
|
||||
nets.networkList.mu.Lock()
|
||||
defer nets.networkList.mu.Unlock()
|
||||
|
||||
data := nets.networkList.report
|
||||
|
||||
return data
|
||||
}
|
||||
|
||||
// ClearData clears table data.
|
||||
func (nets *Networks) ClearData() {
|
||||
nets.networkList.mu.Lock()
|
||||
defer nets.networkList.mu.Unlock()
|
||||
|
||||
nets.networkList.report = nil
|
||||
|
||||
nets.table.Clear()
|
||||
|
||||
expand := 1
|
||||
fgColor := style.PageHeaderFgColor
|
||||
bgColor := style.PageHeaderBgColor
|
||||
|
||||
for i := range nets.headers {
|
||||
nets.table.SetCell(0, i,
|
||||
tview.NewTableCell(fmt.Sprintf("[::b]%s", strings.ToUpper(nets.headers[i]))). //nolint:perfsprint
|
||||
SetExpansion(expand).
|
||||
SetBackgroundColor(bgColor).
|
||||
SetTextColor(fgColor).
|
||||
SetAlign(tview.AlignLeft).
|
||||
SetSelectable(false))
|
||||
}
|
||||
|
||||
nets.table.SetTitle(fmt.Sprintf("[::b]%s[0]", strings.ToUpper(nets.title)))
|
||||
}
|
|
@ -9,14 +9,15 @@ func (nets *Networks) Draw(screen tcell.Screen) {
|
|||
nets.Box.DrawForSubclass(screen, nets)
|
||||
nets.Box.SetBorder(false)
|
||||
|
||||
x, y, width, height := nets.GetInnerRect()
|
||||
netViewX, netViewY, netViewW, netViewH := nets.GetInnerRect()
|
||||
|
||||
nets.table.SetRect(x, y, width, height)
|
||||
nets.table.SetRect(netViewX, netViewY, netViewW, netViewH)
|
||||
nets.refresh(netViewW)
|
||||
nets.table.SetBorder(true)
|
||||
|
||||
nets.table.Draw(screen)
|
||||
|
||||
x, y, width, height = nets.table.GetInnerRect()
|
||||
x, y, width, height := nets.table.GetInnerRect()
|
||||
|
||||
// error dialog
|
||||
if nets.errorDialog.IsDisplay() {
|
||||
|
@ -60,7 +61,12 @@ func (nets *Networks) Draw(screen tcell.Screen) {
|
|||
|
||||
// message dialog
|
||||
if nets.messageDialog.IsDisplay() {
|
||||
nets.messageDialog.SetRect(x, y, width, height+1)
|
||||
if nets.messageDialog.IsDisplayFullSize() {
|
||||
nets.messageDialog.SetRect(netViewX, netViewY, netViewW, netViewH)
|
||||
} else {
|
||||
nets.messageDialog.SetRect(x, y, width, height+1)
|
||||
}
|
||||
|
||||
nets.messageDialog.Draw(screen)
|
||||
|
||||
return
|
||||
|
|
|
@ -393,10 +393,10 @@ func (d *NetworkConnectDialog) GetConnectOptions() networks.NetworkConnect {
|
|||
container := strings.Split(selectedCnt, " ")[0]
|
||||
connectOptions.Container = container
|
||||
connectOptions.Network = d.networkName
|
||||
connectOptions.IPv4 = d.ipv4.GetText()
|
||||
connectOptions.IPv6 = d.ipv6.GetText()
|
||||
connectOptions.MacAddress = d.macAddr.GetText()
|
||||
connectOptions.Aliases = strings.Split(d.aliases.GetText(), " ")
|
||||
connectOptions.IPv4 = strings.TrimSpace(d.ipv4.GetText())
|
||||
connectOptions.IPv6 = strings.TrimSpace(d.ipv6.GetText())
|
||||
connectOptions.MacAddress = strings.TrimSpace(d.macAddr.GetText())
|
||||
connectOptions.Aliases = strings.Split(strings.TrimSpace(d.aliases.GetText()), " ")
|
||||
|
||||
return connectOptions
|
||||
}
|
||||
|
|
|
@ -636,10 +636,10 @@ func (d *NetworkCreateDialog) NetworkCreateOptions() networks.CreateOptions { //
|
|||
}
|
||||
|
||||
opts := networks.CreateOptions{
|
||||
Name: d.networkNameField.GetText(),
|
||||
Name: strings.TrimSpace(d.networkNameField.GetText()),
|
||||
Labels: labels,
|
||||
Internal: d.networkInternalCheckBox.IsChecked(),
|
||||
Drivers: d.networkDriverField.GetText(),
|
||||
Drivers: strings.TrimSpace(d.networkDriverField.GetText()),
|
||||
DriversOptions: options,
|
||||
IPv6: d.networkIpv6CheckBox.IsChecked(),
|
||||
Gateways: gateways,
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/containers/podman-tui/ui/dialogs"
|
||||
"github.com/containers/podman-tui/ui/networks/netdialogs"
|
||||
|
@ -38,8 +39,15 @@ type Networks struct {
|
|||
createDialog *netdialogs.NetworkCreateDialog
|
||||
connectDialog *netdialogs.NetworkConnectDialog
|
||||
disconnectDialog *netdialogs.NetworkDisconnectDialog
|
||||
networkList networkListReport
|
||||
selectedID string
|
||||
confirmData string
|
||||
appFocusHandler func()
|
||||
}
|
||||
|
||||
type networkListReport struct {
|
||||
mu sync.Mutex
|
||||
report [][]string
|
||||
}
|
||||
|
||||
// NewNetworks returns nets page view.
|
||||
|
@ -138,6 +146,11 @@ func NewNetworks() *Networks {
|
|||
return nets
|
||||
}
|
||||
|
||||
// SetAppFocusHandler sets application focus handler.
|
||||
func (nets *Networks) SetAppFocusHandler(handler func()) {
|
||||
nets.appFocusHandler = handler
|
||||
}
|
||||
|
||||
// GetTitle returns primitive title.
|
||||
func (nets *Networks) GetTitle() string {
|
||||
return nets.title
|
||||
|
|
|
@ -4,21 +4,11 @@ import (
|
|||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/containers/podman-tui/pdcs/networks"
|
||||
"github.com/containers/podman-tui/ui/style"
|
||||
"github.com/rivo/tview"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
// UpdateData retrieves networks list data.
|
||||
func (nets *Networks) UpdateData() {
|
||||
netList, err := networks.List()
|
||||
if err != nil {
|
||||
log.Error().Msgf("view: networks update %v", err)
|
||||
nets.errorDialog.SetText(fmt.Sprintf("%v", err))
|
||||
nets.errorDialog.Display()
|
||||
}
|
||||
|
||||
func (nets *Networks) refresh(_ int) {
|
||||
nets.table.Clear()
|
||||
|
||||
expand := 1
|
||||
|
@ -35,6 +25,7 @@ func (nets *Networks) UpdateData() {
|
|||
}
|
||||
|
||||
rowIndex := 1
|
||||
netList := nets.getData()
|
||||
|
||||
nets.table.SetTitle(fmt.Sprintf("[::b]%s[%d]", strings.ToUpper(nets.title), len(netList)))
|
||||
|
||||
|
@ -64,24 +55,3 @@ func (nets *Networks) UpdateData() {
|
|||
rowIndex++
|
||||
}
|
||||
}
|
||||
|
||||
// ClearData clears table data.
|
||||
func (nets *Networks) ClearData() {
|
||||
nets.table.Clear()
|
||||
|
||||
expand := 1
|
||||
fgColor := style.PageHeaderFgColor
|
||||
bgColor := style.PageHeaderBgColor
|
||||
|
||||
for i := range nets.headers {
|
||||
nets.table.SetCell(0, i,
|
||||
tview.NewTableCell(fmt.Sprintf("[::b]%s", strings.ToUpper(nets.headers[i]))). //nolint:perfsprint
|
||||
SetExpansion(expand).
|
||||
SetBackgroundColor(bgColor).
|
||||
SetTextColor(fgColor).
|
||||
SetAlign(tview.AlignLeft).
|
||||
SetSelectable(false))
|
||||
}
|
||||
|
||||
nets.table.SetTitle(fmt.Sprintf("[::b]%s[0]", strings.ToUpper(nets.title)))
|
||||
}
|
||||
|
|
|
@ -75,6 +75,7 @@ func (p *Pods) create() {
|
|||
|
||||
if err != nil {
|
||||
p.displayError("POD CREATE ERROR", err)
|
||||
p.appFocusHandler()
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -104,7 +105,7 @@ func (p *Pods) inspect() {
|
|||
|
||||
p.messageDialog.SetTitle("podman pod inspect")
|
||||
p.messageDialog.SetText(dialogs.MessagePodInfo, headerLabel, data)
|
||||
p.messageDialog.Display()
|
||||
p.messageDialog.DisplayFullSize()
|
||||
}
|
||||
|
||||
func (p *Pods) kill() {
|
||||
|
@ -126,6 +127,7 @@ func (p *Pods) kill() {
|
|||
title := fmt.Sprintf("POD (%s) KILL ERROR", p.selectedID)
|
||||
|
||||
p.displayError(title, err)
|
||||
p.appFocusHandler()
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -153,6 +155,7 @@ func (p *Pods) pause() {
|
|||
title := fmt.Sprintf("POD (%s) PAUSE ERROR", p.selectedID)
|
||||
|
||||
p.displayError(title, err)
|
||||
p.appFocusHandler()
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -172,6 +175,7 @@ func (p *Pods) prune() {
|
|||
|
||||
if err != nil {
|
||||
p.displayError("PODS PRUNE ERROR", err)
|
||||
p.appFocusHandler()
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -180,6 +184,7 @@ func (p *Pods) prune() {
|
|||
errMessages := fmt.Errorf("%w %v", errPodPrune, errData)
|
||||
|
||||
p.displayError("PODS PRUNE ERROR", errMessages)
|
||||
p.appFocusHandler()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -203,7 +208,9 @@ func (p *Pods) restart() {
|
|||
|
||||
if err != nil {
|
||||
title := fmt.Sprintf("POD (%s) RESTART ERROR", p.selectedID)
|
||||
|
||||
p.displayError(title, err)
|
||||
p.appFocusHandler()
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -244,14 +251,18 @@ func (p *Pods) remove() {
|
|||
|
||||
if err != nil {
|
||||
title := fmt.Sprintf("POD (%s) REMOVE ERROR", p.selectedID)
|
||||
|
||||
p.displayError(title, err)
|
||||
p.appFocusHandler()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if len(errData) > 0 {
|
||||
title := fmt.Sprintf("POD (%s) REMOVE ERROR", p.selectedID)
|
||||
|
||||
p.displayError(title, fmt.Errorf("%w %v", errPodRemove, errData))
|
||||
p.appFocusHandler()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -275,7 +286,9 @@ func (p *Pods) start() {
|
|||
|
||||
if err != nil {
|
||||
title := fmt.Sprintf("POD (%s) START ERROR", p.selectedID)
|
||||
|
||||
p.displayError(title, err)
|
||||
p.appFocusHandler()
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -301,7 +314,9 @@ func (p *Pods) stop() {
|
|||
|
||||
if err != nil {
|
||||
title := fmt.Sprintf("POD (%s) STOP ERROR", p.selectedID)
|
||||
|
||||
p.displayError(title, err)
|
||||
p.appFocusHandler()
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -347,7 +362,9 @@ func (p *Pods) unpause() {
|
|||
|
||||
if err != nil {
|
||||
title := fmt.Sprintf("POD (%s) UNPAUSE ERROR", p.selectedID)
|
||||
|
||||
p.displayError(title, err)
|
||||
p.appFocusHandler()
|
||||
|
||||
return
|
||||
}
|
||||
|
|
|
@ -23,14 +23,16 @@ func (pods *Pods) UpdateData() {
|
|||
}
|
||||
|
||||
pods.podsList.mu.Lock()
|
||||
defer pods.podsList.mu.Unlock()
|
||||
|
||||
pods.podsList.report = podList
|
||||
pods.podsList.mu.Unlock()
|
||||
}
|
||||
|
||||
func (pods *Pods) getData() []*entities.ListPodsReport {
|
||||
pods.podsList.mu.Lock()
|
||||
defer pods.podsList.mu.Unlock()
|
||||
|
||||
data := pods.podsList.report
|
||||
pods.podsList.mu.Unlock()
|
||||
|
||||
return data
|
||||
}
|
||||
|
@ -38,8 +40,10 @@ func (pods *Pods) getData() []*entities.ListPodsReport {
|
|||
// ClearData clears table data.
|
||||
func (pods *Pods) ClearData() { //nolint:stylecheck
|
||||
pods.podsList.mu.Lock()
|
||||
defer pods.podsList.mu.Unlock()
|
||||
|
||||
pods.podsList.report = nil
|
||||
pods.podsList.mu.Unlock()
|
||||
|
||||
pods.table.Clear()
|
||||
|
||||
expand := 1
|
||||
|
|
|
@ -6,18 +6,18 @@ import (
|
|||
|
||||
// Draw draws this primitive onto the screen.
|
||||
func (pods *Pods) Draw(screen tcell.Screen) {
|
||||
pods.refresh()
|
||||
pods.Box.DrawForSubclass(screen, pods)
|
||||
pods.Box.SetBorder(false)
|
||||
|
||||
x, y, width, height := pods.GetInnerRect()
|
||||
podViewX, podViewY, podViewW, podViewH := pods.GetInnerRect()
|
||||
|
||||
pods.table.SetRect(x, y, width, height)
|
||||
pods.refresh(podViewW)
|
||||
pods.table.SetRect(podViewX, podViewY, podViewW, podViewH)
|
||||
pods.table.SetBorder(true)
|
||||
|
||||
pods.table.Draw(screen)
|
||||
|
||||
x, y, width, height = pods.table.GetInnerRect()
|
||||
x, y, width, height := pods.table.GetInnerRect()
|
||||
|
||||
// error dialog
|
||||
if pods.errorDialog.IsDisplay() {
|
||||
|
@ -53,7 +53,12 @@ func (pods *Pods) Draw(screen tcell.Screen) {
|
|||
|
||||
// message dialog
|
||||
if pods.messageDialog.IsDisplay() {
|
||||
pods.messageDialog.SetRect(x, y, width, height+1)
|
||||
if pods.messageDialog.IsDisplayFullSize() {
|
||||
pods.messageDialog.SetRect(podViewX, podViewY, podViewW, podViewH)
|
||||
} else {
|
||||
pods.messageDialog.SetRect(x, y, width, height+1)
|
||||
}
|
||||
|
||||
pods.messageDialog.Draw(screen)
|
||||
|
||||
return
|
||||
|
@ -75,7 +80,7 @@ func (pods *Pods) Draw(screen tcell.Screen) {
|
|||
|
||||
// stats dialogs
|
||||
if pods.statsDialog.IsDisplay() {
|
||||
pods.statsDialog.SetRect(x, y, width, height)
|
||||
pods.statsDialog.SetRect(podViewX, podViewY, podViewW, podViewH)
|
||||
pods.statsDialog.Draw(screen)
|
||||
|
||||
return
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -297,10 +297,10 @@ func (d *PodStatsDialog) Draw(screen tcell.Screen) {
|
|||
|
||||
// SetRect set rects for this primitive.
|
||||
func (d *PodStatsDialog) SetRect(x, y, width, height int) {
|
||||
dX := x + dialogs.DialogPadding
|
||||
dY := y + dialogs.DialogPadding - 1
|
||||
dWidth := width - (2 * dialogs.DialogPadding) //nolint:mnd
|
||||
dHeight := height - (2 * (dialogs.DialogPadding - 1)) //nolint:mnd
|
||||
dX := x + 1
|
||||
dY := y + 1
|
||||
dWidth := width - 2 //nolint:mnd
|
||||
dHeight := height - 2 //nolint:mnd
|
||||
|
||||
d.Box.SetRect(dX, dY, dWidth, dHeight)
|
||||
}
|
||||
|
|
|
@ -40,20 +40,21 @@ var (
|
|||
// Pods implemnents the pods page primitive.
|
||||
type Pods struct {
|
||||
*tview.Box
|
||||
title string
|
||||
headers []string
|
||||
table *tview.Table
|
||||
errorDialog *dialogs.ErrorDialog
|
||||
progressDialog *dialogs.ProgressDialog
|
||||
confirmDialog *dialogs.ConfirmDialog
|
||||
cmdDialog *dialogs.CommandDialog
|
||||
messageDialog *dialogs.MessageDialog
|
||||
topDialog *dialogs.TopDialog
|
||||
createDialog *poddialogs.PodCreateDialog
|
||||
statsDialog *poddialogs.PodStatsDialog
|
||||
podsList podsListReport
|
||||
selectedID string
|
||||
confirmData string
|
||||
title string
|
||||
headers []string
|
||||
table *tview.Table
|
||||
errorDialog *dialogs.ErrorDialog
|
||||
progressDialog *dialogs.ProgressDialog
|
||||
confirmDialog *dialogs.ConfirmDialog
|
||||
cmdDialog *dialogs.CommandDialog
|
||||
messageDialog *dialogs.MessageDialog
|
||||
topDialog *dialogs.TopDialog
|
||||
createDialog *poddialogs.PodCreateDialog
|
||||
statsDialog *poddialogs.PodStatsDialog
|
||||
podsList podsListReport
|
||||
selectedID string
|
||||
confirmData string
|
||||
appFocusHandler func()
|
||||
}
|
||||
|
||||
type podsListReport struct {
|
||||
|
@ -164,6 +165,11 @@ func NewPods() *Pods {
|
|||
return pods
|
||||
}
|
||||
|
||||
// SetAppFocusHandler sets application focus handler.
|
||||
func (pods *Pods) SetAppFocusHandler(handler func()) {
|
||||
pods.appFocusHandler = handler
|
||||
}
|
||||
|
||||
// GetTitle returns primitive title.
|
||||
func (pods *Pods) GetTitle() string {
|
||||
return pods.title
|
||||
|
|
|
@ -12,7 +12,7 @@ import (
|
|||
"github.com/rivo/tview"
|
||||
)
|
||||
|
||||
func (pods *Pods) refresh() {
|
||||
func (pods *Pods) refresh(_ int) {
|
||||
pods.table.Clear()
|
||||
|
||||
expand := 1
|
||||
|
|
|
@ -72,7 +72,7 @@ func (s *Secrets) inspect() {
|
|||
|
||||
s.messageDialog.SetTitle("podman secret inspect")
|
||||
s.messageDialog.SetText(dialogs.MessageSecretInfo, headerLabel, data)
|
||||
s.messageDialog.Display()
|
||||
s.messageDialog.DisplayFullSize()
|
||||
}
|
||||
|
||||
func (s *Secrets) rm() {
|
||||
|
@ -114,6 +114,7 @@ func (s *Secrets) remove() {
|
|||
if err != nil {
|
||||
title := fmt.Sprintf("SECRET (%s) REMOVE ERROR", secID)
|
||||
s.displayError(title, err)
|
||||
s.appFocusHandler()
|
||||
|
||||
return
|
||||
}
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
package secrets
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/containers/podman-tui/pdcs/secrets"
|
||||
"github.com/containers/podman-tui/ui/style"
|
||||
"github.com/containers/podman/v5/pkg/domain/entities/types"
|
||||
"github.com/rivo/tview"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
// UpdateData retrieves secrets list data.
|
||||
func (s *Secrets) UpdateData() {
|
||||
secResponse, err := secrets.List()
|
||||
if err != nil {
|
||||
log.Error().Msgf("view: secrets update %v", err)
|
||||
|
||||
s.errorDialog.SetText(fmt.Sprintf("%v", err))
|
||||
s.errorDialog.Display()
|
||||
}
|
||||
|
||||
s.secretList.mu.Lock()
|
||||
defer s.secretList.mu.Unlock()
|
||||
|
||||
s.secretList.report = secResponse
|
||||
}
|
||||
|
||||
func (s *Secrets) getData() []*types.SecretInfoReport {
|
||||
s.secretList.mu.Lock()
|
||||
defer s.secretList.mu.Unlock()
|
||||
|
||||
data := s.secretList.report
|
||||
|
||||
return data
|
||||
}
|
||||
|
||||
// ClearData clears table data.
|
||||
func (s *Secrets) ClearData() {
|
||||
s.secretList.mu.Lock()
|
||||
defer s.secretList.mu.Unlock()
|
||||
|
||||
s.secretList.report = nil
|
||||
|
||||
s.table.Clear()
|
||||
|
||||
expand := 1
|
||||
|
||||
for i := range s.headers {
|
||||
s.table.SetCell(0, i,
|
||||
tview.NewTableCell(fmt.Sprintf("[::b]%s", strings.ToUpper(s.headers[i]))). //nolint:perfsprint
|
||||
SetExpansion(expand).
|
||||
SetBackgroundColor(style.PageHeaderBgColor).
|
||||
SetTextColor(style.PageHeaderFgColor).
|
||||
SetAlign(tview.AlignLeft).
|
||||
SetSelectable(false))
|
||||
}
|
||||
|
||||
s.table.SetTitle(fmt.Sprintf("[::b]%s[0]", strings.ToUpper(s.title)))
|
||||
}
|
|
@ -7,13 +7,14 @@ func (s *Secrets) Draw(screen tcell.Screen) {
|
|||
s.Box.DrawForSubclass(screen, s)
|
||||
s.Box.SetBorder(false)
|
||||
|
||||
x, y, width, height := s.GetInnerRect()
|
||||
secretViewX, secretViewY, secretViewW, secretViewH := s.GetInnerRect()
|
||||
|
||||
s.table.SetRect(x, y, width, height)
|
||||
s.table.SetRect(secretViewX, secretViewY, secretViewW, secretViewH)
|
||||
s.refresh(secretViewW)
|
||||
s.table.SetBorder(true)
|
||||
s.table.Draw(screen)
|
||||
|
||||
x, y, width, height = s.table.GetInnerRect()
|
||||
x, y, width, height := s.table.GetInnerRect()
|
||||
|
||||
// error dialog
|
||||
if s.errorDialog.IsDisplay() {
|
||||
|
@ -31,7 +32,12 @@ func (s *Secrets) Draw(screen tcell.Screen) {
|
|||
|
||||
// message dialog
|
||||
if s.messageDialog.IsDisplay() {
|
||||
s.messageDialog.SetRect(x, y, width, height+1)
|
||||
if s.messageDialog.IsDisplayFullSize() {
|
||||
s.messageDialog.SetRect(secretViewX, secretViewY, secretViewW, secretViewH)
|
||||
} else {
|
||||
s.messageDialog.SetRect(x, y, width, height+1)
|
||||
}
|
||||
|
||||
s.messageDialog.Draw(screen)
|
||||
|
||||
return
|
||||
|
|
|
@ -5,23 +5,12 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/containers/podman-tui/pdcs/secrets"
|
||||
"github.com/containers/podman-tui/ui/style"
|
||||
"github.com/docker/go-units"
|
||||
"github.com/rivo/tview"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
// UpdateData retrieves secrets list data.
|
||||
func (s *Secrets) UpdateData() {
|
||||
secResponse, err := secrets.List()
|
||||
if err != nil {
|
||||
log.Error().Msgf("view: secrets update %v", err)
|
||||
|
||||
s.errorDialog.SetText(fmt.Sprintf("%v", err))
|
||||
s.errorDialog.Display()
|
||||
}
|
||||
|
||||
func (s *Secrets) refresh(_ int) {
|
||||
s.table.Clear()
|
||||
|
||||
expand := 1
|
||||
|
@ -38,6 +27,7 @@ func (s *Secrets) UpdateData() {
|
|||
}
|
||||
|
||||
rowIndex := 1
|
||||
secResponse := s.getData()
|
||||
|
||||
s.table.SetTitle(fmt.Sprintf("[::b]%s[%d]", strings.ToUpper(s.title), len(secResponse)))
|
||||
|
||||
|
@ -81,22 +71,3 @@ func (s *Secrets) UpdateData() {
|
|||
rowIndex++
|
||||
}
|
||||
}
|
||||
|
||||
// ClearData clears table data.
|
||||
func (s *Secrets) ClearData() {
|
||||
s.table.Clear()
|
||||
|
||||
expand := 1
|
||||
|
||||
for i := range s.headers {
|
||||
s.table.SetCell(0, i,
|
||||
tview.NewTableCell(fmt.Sprintf("[::b]%s", strings.ToUpper(s.headers[i]))). //nolint:perfsprint
|
||||
SetExpansion(expand).
|
||||
SetBackgroundColor(style.PageHeaderBgColor).
|
||||
SetTextColor(style.PageHeaderFgColor).
|
||||
SetAlign(tview.AlignLeft).
|
||||
SetSelectable(false))
|
||||
}
|
||||
|
||||
s.table.SetTitle(fmt.Sprintf("[::b]%s[0]", strings.ToUpper(s.title)))
|
||||
}
|
||||
|
|
|
@ -4,10 +4,12 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/containers/podman-tui/ui/dialogs"
|
||||
"github.com/containers/podman-tui/ui/secrets/secdialogs"
|
||||
"github.com/containers/podman-tui/ui/style"
|
||||
"github.com/containers/podman/v5/pkg/domain/entities/types"
|
||||
"github.com/rivo/tview"
|
||||
)
|
||||
|
||||
|
@ -29,15 +31,22 @@ var (
|
|||
// Secrets implements the secrets page primitive.
|
||||
type Secrets struct {
|
||||
*tview.Box
|
||||
title string
|
||||
headers []string
|
||||
table *tview.Table
|
||||
cmdDialog *dialogs.CommandDialog
|
||||
messageDialog *dialogs.MessageDialog
|
||||
errorDialog *dialogs.ErrorDialog
|
||||
progressDialog *dialogs.ProgressDialog
|
||||
confirmDialog *dialogs.ConfirmDialog
|
||||
createDialog *secdialogs.SecretCreateDialog
|
||||
title string
|
||||
headers []string
|
||||
table *tview.Table
|
||||
cmdDialog *dialogs.CommandDialog
|
||||
messageDialog *dialogs.MessageDialog
|
||||
errorDialog *dialogs.ErrorDialog
|
||||
progressDialog *dialogs.ProgressDialog
|
||||
confirmDialog *dialogs.ConfirmDialog
|
||||
createDialog *secdialogs.SecretCreateDialog
|
||||
secretList secretListReport
|
||||
appFocusHandler func()
|
||||
}
|
||||
|
||||
type secretListReport struct {
|
||||
mu sync.Mutex
|
||||
report []*types.SecretInfoReport
|
||||
}
|
||||
|
||||
// NewSecrets returns secrets page view.
|
||||
|
@ -108,6 +117,11 @@ func NewSecrets() *Secrets {
|
|||
return secrets
|
||||
}
|
||||
|
||||
// SetAppFocusHandler sets application focus handler.
|
||||
func (s *Secrets) SetAppFocusHandler(handler func()) {
|
||||
s.appFocusHandler = handler
|
||||
}
|
||||
|
||||
// GetTitle returns primitive title.
|
||||
func (s *Secrets) GetTitle() string {
|
||||
return s.title
|
||||
|
|
|
@ -50,10 +50,11 @@ func (sys *System) addConnection() {
|
|||
go func() {
|
||||
err := sys.connectionAddFunc(name, uri, identity)
|
||||
sys.progressDialog.Hide()
|
||||
sys.UpdateConnectionsData()
|
||||
sys.UpdateData()
|
||||
|
||||
if err != nil {
|
||||
sys.displayError("ADD NEW CONNECTION ERROR", err)
|
||||
sys.appFocusHandler()
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -75,13 +76,13 @@ func (sys *System) connect() {
|
|||
|
||||
sys.eventDialog.SetText("")
|
||||
sys.connectionConnectFunc(dest)
|
||||
sys.UpdateConnectionsData()
|
||||
sys.UpdateData()
|
||||
}
|
||||
|
||||
func (sys *System) disconnect() {
|
||||
sys.connectionDisconnectFunc()
|
||||
sys.eventDialog.SetText("")
|
||||
sys.UpdateConnectionsData()
|
||||
sys.UpdateData()
|
||||
}
|
||||
|
||||
func (sys *System) df() {
|
||||
|
@ -99,6 +100,7 @@ func (sys *System) df() {
|
|||
|
||||
if err != nil {
|
||||
sys.displayError("SYSTEM DISK USAGE ERROR", err)
|
||||
sys.appFocusHandler()
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -107,6 +109,7 @@ func (sys *System) df() {
|
|||
sys.dfDialog.SetServiceName(connName)
|
||||
sys.dfDialog.UpdateDiskSummary(response)
|
||||
sys.dfDialog.Display()
|
||||
sys.appFocusHandler()
|
||||
}
|
||||
|
||||
go diskUsage()
|
||||
|
@ -138,7 +141,7 @@ func (sys *System) info() {
|
|||
|
||||
sys.messageDialog.SetTitle("SYSTEM INFORMATION")
|
||||
sys.messageDialog.SetText(dialogs.MessageSystemInfo, connName, data)
|
||||
sys.messageDialog.Display()
|
||||
sys.messageDialog.DisplayFullSize()
|
||||
}
|
||||
|
||||
func (sys *System) cprune() {
|
||||
|
@ -168,6 +171,7 @@ func (sys *System) prune() {
|
|||
|
||||
if err != nil {
|
||||
sys.displayError("SYSTEM PRUNE ERROR", err)
|
||||
sys.appFocusHandler()
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -175,6 +179,7 @@ func (sys *System) prune() {
|
|||
sys.messageDialog.SetTitle("PODMAN SYSTEM PRUNE")
|
||||
sys.messageDialog.SetText(dialogs.MessageSystemInfo, registry.ConnectionName(), report)
|
||||
sys.messageDialog.Display()
|
||||
sys.appFocusHandler()
|
||||
}
|
||||
|
||||
go prune()
|
||||
|
@ -219,11 +224,12 @@ func (sys *System) remove() {
|
|||
|
||||
if err != nil {
|
||||
sys.displayError("SYSTEM CONNECTION REMOVE ERROR", err)
|
||||
sys.appFocusHandler()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
sys.UpdateConnectionsData()
|
||||
sys.UpdateData()
|
||||
}()
|
||||
}
|
||||
|
||||
|
@ -234,6 +240,7 @@ func (sys *System) setDefault() {
|
|||
|
||||
if err := sys.connectionSetDefaultFunc(selectedItem.name); err != nil {
|
||||
sys.displayError("SYSTEM CONNECTION SET DEFAULT ERROR", err)
|
||||
sys.appFocusHandler()
|
||||
|
||||
return
|
||||
}
|
||||
|
|
|
@ -7,12 +7,16 @@ import (
|
|||
"github.com/containers/podman-tui/ui/style"
|
||||
)
|
||||
|
||||
// UpdateConnectionsData retrieves connections list data.
|
||||
func (sys *System) UpdateConnectionsData() {
|
||||
// UpdateData retrieves connections list data.
|
||||
func (sys *System) UpdateData() {
|
||||
destinations := sys.connectionListFunc()
|
||||
|
||||
sys.connectionList.mu.Lock()
|
||||
|
||||
sys.connectionList.report = destinations
|
||||
|
||||
sys.connectionList.mu.Unlock()
|
||||
|
||||
sys.udpateConnectionDataStatus()
|
||||
}
|
||||
|
||||
|
@ -34,8 +38,9 @@ func (sys *System) udpateConnectionDataStatus() {
|
|||
|
||||
func (sys *System) getConnectionsData() []registry.Connection {
|
||||
sys.connectionList.mu.Lock()
|
||||
defer sys.connectionList.mu.Unlock()
|
||||
|
||||
destReport := sys.connectionList.report
|
||||
sys.connectionList.mu.Unlock()
|
||||
|
||||
return destReport
|
||||
}
|
||||
|
|
|
@ -5,16 +5,16 @@ import (
|
|||
)
|
||||
|
||||
// Draw draws this primitive onto the screen.
|
||||
func (sys *System) Draw(screen tcell.Screen) {
|
||||
sys.refresh()
|
||||
func (sys *System) Draw(screen tcell.Screen) { //nolint:cyclop
|
||||
sys.Box.DrawForSubclass(screen, sys)
|
||||
|
||||
x, y, width, height := sys.GetInnerRect()
|
||||
sysViewX, sysViewY, sysViewW, sysViewH := sys.GetInnerRect()
|
||||
|
||||
sys.connTable.SetRect(x, y, width, height)
|
||||
sys.connTable.SetRect(sysViewX, sysViewY, sysViewW, sysViewH)
|
||||
sys.refresh(sysViewW)
|
||||
sys.connTable.Draw(screen)
|
||||
|
||||
x, y, width, height = sys.connTable.GetInnerRect()
|
||||
x, y, width, height := sys.connTable.GetInnerRect()
|
||||
|
||||
// error dialog
|
||||
if sys.errorDialog.IsDisplay() {
|
||||
|
@ -50,7 +50,12 @@ func (sys *System) Draw(screen tcell.Screen) {
|
|||
|
||||
// message dialog
|
||||
if sys.messageDialog.IsDisplay() {
|
||||
sys.messageDialog.SetRect(x, y, width, height)
|
||||
if sys.messageDialog.IsDisplayFullSize() {
|
||||
sys.messageDialog.SetRect(sysViewX, sysViewY, sysViewW, sysViewH)
|
||||
} else {
|
||||
sys.messageDialog.SetRect(x, y, width, height)
|
||||
}
|
||||
|
||||
sys.messageDialog.Draw(screen)
|
||||
|
||||
return
|
||||
|
@ -82,7 +87,7 @@ func (sys *System) Draw(screen tcell.Screen) {
|
|||
|
||||
// event dialog
|
||||
if sys.eventDialog.IsDisplay() {
|
||||
sys.eventDialog.SetRect(x, y, width, height)
|
||||
sys.eventDialog.SetRect(sysViewX, sysViewY, sysViewW, sysViewH)
|
||||
sys.eventDialog.Draw(screen)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ import (
|
|||
"github.com/rivo/tview"
|
||||
)
|
||||
|
||||
func (sys *System) refresh() {
|
||||
func (sys *System) refresh(_ int) {
|
||||
connections := sys.getConnectionsData()
|
||||
sys.connTable.Clear()
|
||||
sys.updateConnTableTitle(len(connections))
|
||||
|
|
|
@ -74,9 +74,7 @@ func NewDfDialog() *DfDialog {
|
|||
|
||||
tableLayout.AddItem(utils.EmptyBoxSpace(style.DialogBgColor), 1, 0, true)
|
||||
tableLayout.AddItem(tview.NewFlex().SetDirection(tview.FlexRow).
|
||||
AddItem(utils.EmptyBoxSpace(style.DialogBgColor), 1, 0, false).
|
||||
AddItem(dialog.serviceName, 1, 0, false).
|
||||
AddItem(utils.EmptyBoxSpace(style.DialogBgColor), 1, 0, false).
|
||||
AddItem(dialog.table, 0, 1, true), 0, 1, true)
|
||||
tableLayout.AddItem(utils.EmptyBoxSpace(style.DialogBgColor), 1, 0, true)
|
||||
|
||||
|
|
|
@ -69,10 +69,8 @@ func NewEventDialog() *EventsDialog {
|
|||
tlayout.AddItem(utils.EmptyBoxSpace(style.DialogBgColor), 1, 0, false)
|
||||
|
||||
tlayout.AddItem(tview.NewFlex().SetDirection(tview.FlexRow).
|
||||
AddItem(utils.EmptyBoxSpace(style.DialogBgColor), 1, 0, false).
|
||||
AddItem(tview.NewFlex().SetDirection(tview.FlexRow).
|
||||
AddItem(eventsDialog.serviceName, 1, 0, false).
|
||||
AddItem(utils.EmptyBoxSpace(style.DialogBgColor), 1, 0, false).
|
||||
AddItem(eventsDialog.textview, 0, 1, true),
|
||||
0, 1, true), 0, 1, true)
|
||||
|
||||
|
@ -163,19 +161,10 @@ func (d *EventsDialog) HasFocus() bool {
|
|||
|
||||
// SetRect set rects for this primitive.
|
||||
func (d *EventsDialog) SetRect(x, y, width, height int) {
|
||||
dWidth := width - (2 * dialogs.DialogPadding) //nolint:mnd
|
||||
if dWidth < 0 {
|
||||
dWidth = 0
|
||||
}
|
||||
|
||||
dX := x + dialogs.DialogPadding
|
||||
|
||||
dHeight := height - (2 * dialogs.DialogPadding) //nolint:mnd
|
||||
if dHeight < 0 {
|
||||
dHeight = 0
|
||||
}
|
||||
|
||||
dY := y + dialogs.DialogPadding
|
||||
dX := x + 1
|
||||
dY := y + 1
|
||||
dWidth := width - 2 //nolint:mnd
|
||||
dHeight := height - 2 //nolint:mnd
|
||||
|
||||
d.Box.SetRect(dX, dY, dWidth, dHeight)
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@ type System struct {
|
|||
connectionSetDefaultFunc func(string) error
|
||||
connectionConnectFunc func(registry.Connection)
|
||||
connectionDisconnectFunc func()
|
||||
appFocusHandler func()
|
||||
}
|
||||
|
||||
type connectionListReport struct {
|
||||
|
@ -147,7 +148,7 @@ func NewSystem() *System {
|
|||
sys.connPrgDialog.Hide()
|
||||
registry.UnsetConnection()
|
||||
sys.eventDialog.SetText("")
|
||||
sys.UpdateConnectionsData()
|
||||
sys.UpdateData()
|
||||
})
|
||||
|
||||
// set connection create dialog functions
|
||||
|
@ -159,6 +160,11 @@ func NewSystem() *System {
|
|||
return sys
|
||||
}
|
||||
|
||||
// SetAppFocusHandler sets application focus handler.
|
||||
func (sys *System) SetAppFocusHandler(handler func()) {
|
||||
sys.appFocusHandler = handler
|
||||
}
|
||||
|
||||
// GetTitle returns primitive title.
|
||||
func (sys *System) GetTitle() string {
|
||||
return sys.title
|
||||
|
|
|
@ -88,6 +88,7 @@ func (vols *Volumes) prune() {
|
|||
errorTitle := "volume prune error"
|
||||
if err != nil {
|
||||
vols.displayError(errorTitle, err)
|
||||
vols.appFocusHandler()
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -95,6 +96,7 @@ func (vols *Volumes) prune() {
|
|||
if len(errData) > 0 {
|
||||
pruneError := errors.New(strings.Join(errData, "\n")) //nolint:goerr113
|
||||
vols.displayError(errorTitle, pruneError)
|
||||
vols.appFocusHandler()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -141,6 +143,7 @@ func (vols *Volumes) remove() {
|
|||
if err != nil {
|
||||
title := fmt.Sprintf("volume (%s) remove error", volID)
|
||||
vols.displayError(title, err)
|
||||
vols.appFocusHandler()
|
||||
|
||||
return
|
||||
}
|
||||
|
|
|
@ -23,14 +23,16 @@ func (vols *Volumes) UpdateData() {
|
|||
}
|
||||
|
||||
vols.volumeList.mu.Lock()
|
||||
defer vols.volumeList.mu.Unlock()
|
||||
|
||||
vols.volumeList.report = volList
|
||||
vols.volumeList.mu.Unlock()
|
||||
}
|
||||
|
||||
func (vols *Volumes) getData() []*entities.VolumeListReport {
|
||||
vols.volumeList.mu.Lock()
|
||||
defer vols.volumeList.mu.Unlock()
|
||||
|
||||
data := vols.volumeList.report
|
||||
vols.volumeList.mu.Unlock()
|
||||
|
||||
return data
|
||||
}
|
||||
|
@ -38,8 +40,9 @@ func (vols *Volumes) getData() []*entities.VolumeListReport {
|
|||
// ClearData clears table data.
|
||||
func (vols *Volumes) ClearData() {
|
||||
vols.volumeList.mu.Lock()
|
||||
defer vols.volumeList.mu.Unlock()
|
||||
|
||||
vols.volumeList.report = nil
|
||||
vols.volumeList.mu.Unlock()
|
||||
|
||||
vols.table.Clear()
|
||||
|
||||
|
|
|
@ -6,12 +6,12 @@ import (
|
|||
|
||||
// Draw draws this primitive onto the screen.
|
||||
func (vols *Volumes) Draw(screen tcell.Screen) {
|
||||
vols.refresh()
|
||||
vols.Box.DrawForSubclass(screen, vols)
|
||||
vols.Box.SetBorder(false)
|
||||
|
||||
x, y, width, height := vols.GetInnerRect()
|
||||
|
||||
vols.refresh(width)
|
||||
vols.table.SetRect(x, y, width, height)
|
||||
vols.table.SetBorder(true)
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ const (
|
|||
volsTableMountPointColIndex
|
||||
)
|
||||
|
||||
func (vols *Volumes) refresh() {
|
||||
func (vols *Volumes) refresh(_ int) {
|
||||
vols.table.Clear()
|
||||
|
||||
expand := 1
|
||||
|
|
|
@ -16,17 +16,18 @@ import (
|
|||
// Volumes implemnents the volumes page primitive.
|
||||
type Volumes struct {
|
||||
*tview.Box
|
||||
title string
|
||||
headers []string
|
||||
table *tview.Table
|
||||
errorDialog *dialogs.ErrorDialog
|
||||
progressDialog *dialogs.ProgressDialog
|
||||
confirmDialog *dialogs.ConfirmDialog
|
||||
cmdDialog *dialogs.CommandDialog
|
||||
messageDialog *dialogs.MessageDialog
|
||||
createDialog *voldialogs.VolumeCreateDialog
|
||||
volumeList volListReport
|
||||
confirmData string
|
||||
title string
|
||||
headers []string
|
||||
table *tview.Table
|
||||
errorDialog *dialogs.ErrorDialog
|
||||
progressDialog *dialogs.ProgressDialog
|
||||
confirmDialog *dialogs.ConfirmDialog
|
||||
cmdDialog *dialogs.CommandDialog
|
||||
messageDialog *dialogs.MessageDialog
|
||||
createDialog *voldialogs.VolumeCreateDialog
|
||||
volumeList volListReport
|
||||
confirmData string
|
||||
appFocusHandler func()
|
||||
}
|
||||
|
||||
type volListReport struct {
|
||||
|
@ -123,6 +124,11 @@ func (vols *Volumes) initUI() {
|
|||
})
|
||||
}
|
||||
|
||||
// SetAppFocusHandler sets application focus handler.
|
||||
func (vols *Volumes) SetAppFocusHandler(handler func()) {
|
||||
vols.appFocusHandler = handler
|
||||
}
|
||||
|
||||
// GetTitle returns primitive title.
|
||||
func (vols *Volumes) GetTitle() string {
|
||||
return vols.title
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue