Compare commits
No commits in common. "main" and "v1.7.0" have entirely different histories.
|
@ -18,7 +18,7 @@ jobs:
|
|||
runs-on: 'ubuntu-latest'
|
||||
steps:
|
||||
- name: Check out the repo
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v5
|
||||
|
|
|
@ -10,7 +10,7 @@ jobs:
|
|||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '>=1.23'
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v4
|
||||
- run: |
|
||||
go mod tidy
|
||||
go mod vendor
|
||||
|
@ -25,7 +25,7 @@ jobs:
|
|||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '1.23'
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v4
|
||||
- run: |
|
||||
bash hack/install_dep.sh
|
||||
make .install.golangci-lint
|
||||
|
@ -36,7 +36,7 @@ jobs:
|
|||
container:
|
||||
image: fedora:latest
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v4
|
||||
- run: |
|
||||
# Preparing and running unit tests #
|
||||
dnf -y install git-core golang glibc-static git-core wget gcc make
|
||||
|
@ -60,6 +60,6 @@ jobs:
|
|||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '>=1.23'
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v4
|
||||
- run: |
|
||||
make all
|
||||
|
|
|
@ -6,7 +6,7 @@ jobs:
|
|||
pre-commit:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v5
|
||||
- uses: pre-commit/action@v3.0.1
|
||||
|
||||
|
@ -34,7 +34,7 @@ jobs:
|
|||
codespell:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v4
|
||||
- uses: codespell-project/actions-codespell@master
|
||||
with:
|
||||
check_filenames: true
|
||||
|
@ -46,7 +46,7 @@ jobs:
|
|||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '>=1.23'
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v4
|
||||
- run: |
|
||||
go mod tidy
|
||||
go mod vendor
|
||||
|
@ -61,7 +61,7 @@ jobs:
|
|||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '1.23'
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v4
|
||||
- run: |
|
||||
bash hack/install_dep.sh
|
||||
make .install.golangci-lint
|
||||
|
@ -72,7 +72,7 @@ jobs:
|
|||
container:
|
||||
image: fedora:latest
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v4
|
||||
- run: |
|
||||
# Preparing and running unit tests #
|
||||
dnf -y install git-core golang glibc-static git-core wget gcc make
|
||||
|
@ -87,7 +87,7 @@ jobs:
|
|||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '>=1.23'
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v4
|
||||
- run: |
|
||||
make all
|
||||
|
||||
|
|
|
@ -1,40 +1,33 @@
|
|||
version: "2"
|
||||
run:
|
||||
modules-download-mode: readonly
|
||||
|
||||
formatters:
|
||||
enable:
|
||||
- gofmt
|
||||
- goimports
|
||||
exclusions:
|
||||
generated: disable
|
||||
|
||||
timeout: 10m
|
||||
deadline: 5m
|
||||
linters:
|
||||
default: all
|
||||
enable-all: true
|
||||
disable:
|
||||
- gochecknoinits
|
||||
- gochecknoglobals
|
||||
- exhaustruct
|
||||
- varnamelen
|
||||
- gochecknoinits
|
||||
- wrapcheck
|
||||
- funlen
|
||||
- depguard
|
||||
- wrapcheck
|
||||
- wsl
|
||||
settings:
|
||||
errcheck:
|
||||
check-blank: false
|
||||
exclude-functions:
|
||||
- fmt:.*
|
||||
nolintlint:
|
||||
require-specific: true
|
||||
revive:
|
||||
rules:
|
||||
- name: package-comments
|
||||
disabled: true
|
||||
exclusions:
|
||||
paths:
|
||||
- test/
|
||||
- ".*_test.go"
|
||||
- nolintlint
|
||||
# generics disabled
|
||||
- wastedassign
|
||||
- rowserrcheck
|
||||
# deprecated
|
||||
- gomoddirectives
|
||||
- tenv
|
||||
linters-settings:
|
||||
# typecheck:
|
||||
# enabled: false
|
||||
errcheck:
|
||||
check-blank: false
|
||||
exclude-functions:
|
||||
- fmt:.*
|
||||
nolintlint:
|
||||
require-specific: true
|
||||
|
||||
issues:
|
||||
max-issues-per-linter: 0
|
||||
max-same-issues: 0
|
||||
exclude-files:
|
||||
- ".*_test.go"
|
||||
|
|
|
@ -16,12 +16,13 @@ jobs:
|
|||
- fedora-all-aarch64
|
||||
- epel-9-x86_64
|
||||
- epel-9-aarch64
|
||||
- epel-10-x86_64
|
||||
- epel-10-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
|
||||
# - centos-stream-10-x86_64
|
||||
# - centos-stream-10-aarch64
|
||||
|
||||
actions:
|
||||
post-upstream-clone:
|
||||
|
|
3
Makefile
3
Makefile
|
@ -88,7 +88,7 @@ install.tools: .install.ginkgo .install.bats .install.pre-commit .install.codesp
|
|||
|
||||
.PHONY: .install.golangci-lint
|
||||
.install.golangci-lint:
|
||||
VERSION=2.3.1 ./hack/install_golangci.sh
|
||||
VERSION=1.64.4 ./hack/install_golangci.sh
|
||||
|
||||
.PHONY: .install.codespell
|
||||
.install.codespell:
|
||||
|
@ -112,7 +112,6 @@ test-unit: ## Run unit tests
|
|||
--coverprofile coverprofile \
|
||||
--output-dir ${COVERAGE_PATH} \
|
||||
--succinct
|
||||
|
||||
$(GO) tool cover -html=${COVERAGE_PATH}/coverprofile -o ${COVERAGE_PATH}/coverage.html
|
||||
$(GO) tool cover -func=${COVERAGE_PATH}/coverprofile > ${COVERAGE_PATH}/functions
|
||||
cat ${COVERAGE_PATH}/functions | sed -n 's/\(total:\).*\([0-9][0-9].[0-9]\)/\1 \2/p'
|
||||
|
|
25
app/app.go
25
app/app.go
|
@ -24,7 +24,6 @@ import (
|
|||
// App represents main application struct.
|
||||
type App struct {
|
||||
*tview.Application
|
||||
|
||||
infoBar *infobar.InfoBar
|
||||
pages *tview.Pages
|
||||
pods *pods.Pods
|
||||
|
@ -87,8 +86,7 @@ func NewApp(name string, version string) *App {
|
|||
app.system.SetConnectionAddFunc(app.config.Add)
|
||||
app.system.SetConnectionRemoveFunc(app.config.Remove)
|
||||
app.system.SetAppFocusHandler(func() {
|
||||
app.SetFocus(app.system)
|
||||
|
||||
app.Application.SetFocus(app.system)
|
||||
app.fastRefreshChan <- true
|
||||
})
|
||||
|
||||
|
@ -104,38 +102,32 @@ func NewApp(name string, version string) *App {
|
|||
|
||||
// set app set focus
|
||||
app.containers.SetAppFocusHandler(func() {
|
||||
app.SetFocus(app.containers)
|
||||
|
||||
app.Application.SetFocus(app.containers)
|
||||
app.fastRefreshChan <- true
|
||||
})
|
||||
|
||||
app.pods.SetAppFocusHandler(func() {
|
||||
app.SetFocus(app.pods)
|
||||
|
||||
app.Application.SetFocus(app.pods)
|
||||
app.fastRefreshChan <- true
|
||||
})
|
||||
|
||||
app.images.SetAppFocusHandler(func() {
|
||||
app.SetFocus(app.images)
|
||||
|
||||
app.Application.SetFocus(app.images)
|
||||
app.fastRefreshChan <- true
|
||||
})
|
||||
|
||||
app.volumes.SetAppFocusHandler(func() {
|
||||
app.SetFocus(app.volumes)
|
||||
|
||||
app.Application.SetFocus(app.volumes)
|
||||
app.fastRefreshChan <- true
|
||||
})
|
||||
|
||||
app.networks.SetAppFocusHandler(func() {
|
||||
app.SetFocus(app.networks)
|
||||
|
||||
app.Application.SetFocus(app.networks)
|
||||
app.fastRefreshChan <- true
|
||||
})
|
||||
|
||||
app.secrets.SetAppFocusHandler(func() {
|
||||
app.SetFocus(app.secrets)
|
||||
|
||||
app.Application.SetFocus(app.secrets)
|
||||
app.fastRefreshChan <- true
|
||||
})
|
||||
|
||||
|
@ -280,8 +272,7 @@ func (app *App) Run() error { //nolint:cyclop
|
|||
// start fast refresh loop
|
||||
go app.fastRefresh()
|
||||
|
||||
err := app.SetRoot(flex, true).SetFocus(app.system).EnableMouse(false).Run()
|
||||
if err != nil {
|
||||
if err := app.SetRoot(flex, true).SetFocus(app.system).EnableMouse(false).Run(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,6 @@ import (
|
|||
|
||||
"github.com/containers/podman-tui/ui/style"
|
||||
"github.com/rivo/tview"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
func newMenu(menuItems [][]string) *tview.TextView {
|
||||
|
@ -28,10 +27,7 @@ func newMenu(menuItems [][]string) *tview.TextView {
|
|||
menuList = append(menuList, key+item)
|
||||
}
|
||||
|
||||
_, err := fmt.Fprintf(menu, "%s", strings.Join(menuList, " "))
|
||||
if err != nil {
|
||||
log.Warn().Msgf("failed to create new menu: %s", err.Error())
|
||||
}
|
||||
fmt.Fprintf(menu, "%s", strings.Join(menuList, " "))
|
||||
|
||||
return menu
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ func (app *App) refresh() {
|
|||
|
||||
app.initInfoBar()
|
||||
app.infoBar.UpdateConnStatus(connStatus)
|
||||
app.Draw()
|
||||
app.Application.Draw()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -97,7 +97,7 @@ func (app *App) fastRefresh() {
|
|||
for {
|
||||
refresh := <-app.fastRefreshChan
|
||||
if refresh {
|
||||
app.Draw()
|
||||
app.Application.Draw()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -88,21 +88,21 @@ func (app *App) switchToNextScreen() {
|
|||
func (app *App) setPageFocus(page string) {
|
||||
switch page {
|
||||
case app.help.GetTitle():
|
||||
app.SetFocus(app.help)
|
||||
app.Application.SetFocus(app.help)
|
||||
case app.system.GetTitle():
|
||||
app.SetFocus(app.system)
|
||||
app.Application.SetFocus(app.system)
|
||||
case app.pods.GetTitle():
|
||||
app.SetFocus(app.pods)
|
||||
app.Application.SetFocus(app.pods)
|
||||
case app.containers.GetTitle():
|
||||
app.SetFocus(app.containers)
|
||||
app.Application.SetFocus(app.containers)
|
||||
case app.networks.GetTitle():
|
||||
app.SetFocus(app.networks)
|
||||
app.Application.SetFocus(app.networks)
|
||||
case app.images.GetTitle():
|
||||
app.SetFocus(app.images)
|
||||
app.Application.SetFocus(app.images)
|
||||
case app.volumes.GetTitle():
|
||||
app.SetFocus(app.volumes)
|
||||
app.Application.SetFocus(app.volumes)
|
||||
case app.secrets.GetTitle():
|
||||
app.SetFocus(app.secrets)
|
||||
app.Application.SetFocus(app.secrets)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
17
cmd/root.go
17
cmd/root.go
|
@ -29,7 +29,7 @@ func Execute() {
|
|||
cobra.CheckErr(rootCmd.Execute())
|
||||
}
|
||||
|
||||
func run(cmd *cobra.Command, args []string) error { //nolint:cyclop
|
||||
func run(cmd *cobra.Command, args []string) error { //nolint:cyclop,revive
|
||||
var (
|
||||
logOutput = io.Discard
|
||||
runLog = fmt.Sprintf("starting %s version %s", appName, appVersion)
|
||||
|
@ -54,12 +54,12 @@ func run(cmd *cobra.Command, args []string) error { //nolint:cyclop
|
|||
return err
|
||||
}
|
||||
|
||||
logFD, err := os.OpenFile(logfile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, os.ModePerm) //nolint:gosec
|
||||
logFD, err := os.OpenFile(logfile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, os.ModePerm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer logFD.Close() //nolint:errcheck
|
||||
defer logFD.Close()
|
||||
|
||||
logOutput = logFD
|
||||
}
|
||||
|
@ -95,11 +95,9 @@ func run(cmd *cobra.Command, args []string) error { //nolint:cyclop
|
|||
}
|
||||
|
||||
app := app.NewApp(appName, appVersion)
|
||||
|
||||
err = app.Run()
|
||||
if err != nil {
|
||||
if err := app.Run(); err != nil {
|
||||
if setSSHIdentityPassphrase {
|
||||
os.Unsetenv("CONTAINER_PASSPHRASE") //nolint:errcheck
|
||||
os.Unsetenv("CONTAINER_PASSPHRASE")
|
||||
}
|
||||
|
||||
return err
|
||||
|
@ -108,10 +106,7 @@ func run(cmd *cobra.Command, args []string) error { //nolint:cyclop
|
|||
// unset CONTAINER_PASSPHRASE environment variable if we have set it
|
||||
// after application exits
|
||||
if setSSHIdentityPassphrase {
|
||||
err := os.Unsetenv("CONTAINER_PASSPHRASE")
|
||||
if err != nil {
|
||||
log.Error().Msgf("failed to unset env var CONTAINER_PASSPHRASE: %s", err.Error())
|
||||
}
|
||||
os.Unsetenv("CONTAINER_PASSPHRASE")
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
@ -7,7 +7,7 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
appVersion = "1.8.0-dev"
|
||||
appVersion = "1.7.0"
|
||||
)
|
||||
|
||||
// versionCmd represents the version command.
|
||||
|
@ -15,7 +15,7 @@ var versionCmd = &cobra.Command{
|
|||
Use: "version",
|
||||
Short: fmt.Sprintf("Display %s version and exit.\n", appName),
|
||||
Long: fmt.Sprintf("Display %s version and exit.\n", appName),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
Run: func(cmd *cobra.Command, args []string) { //nolint:revive
|
||||
fmt.Printf("%s v%s\n", appName, appVersion) //nolint:forbidigo
|
||||
},
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package pconfig
|
|||
|
||||
import (
|
||||
"slices"
|
||||
"sort"
|
||||
|
||||
cconfig "github.com/containers/common/pkg/config"
|
||||
"github.com/containers/podman-tui/config/utils"
|
||||
|
@ -54,6 +55,8 @@ func (c *Config) RemoteConnections() []registry.Connection {
|
|||
})
|
||||
}
|
||||
|
||||
sort.Sort(utils.ConnectionListSortedName{rconn}) //nolint:govet
|
||||
|
||||
return rconn
|
||||
}
|
||||
|
||||
|
|
|
@ -20,13 +20,11 @@ func (c *Config) Add(name string, uri string, identity string) error {
|
|||
Default: false,
|
||||
}
|
||||
|
||||
err = c.add(name, conn)
|
||||
if err != nil {
|
||||
if err := c.add(name, conn); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = c.write()
|
||||
if err != nil {
|
||||
if err := c.write(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ package tconfig
|
|||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"sort"
|
||||
"sync"
|
||||
|
||||
"github.com/containers/podman-tui/config/utils"
|
||||
|
@ -53,14 +54,14 @@ func NewConfig() (*Config, error) {
|
|||
newConfig := &Config{}
|
||||
newConfig.Connection.Connections = make(map[string]RemoteConnection)
|
||||
|
||||
_, err = os.Stat(path)
|
||||
if err == nil {
|
||||
err := newConfig.readConfigFromFile(path)
|
||||
if err != nil {
|
||||
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
|
||||
}
|
||||
} else if !os.IsNotExist(err) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
newConfig.addLocalHostIfEmptyConfig()
|
||||
|
@ -68,6 +69,18 @@ func NewConfig() (*Config, error) {
|
|||
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)
|
||||
|
@ -84,17 +97,7 @@ func (c *Config) RemoteConnections() []registry.Connection {
|
|||
})
|
||||
}
|
||||
|
||||
sort.Sort(utils.ConnectionListSortedName{rconn}) //nolint:govet
|
||||
|
||||
return rconn
|
||||
}
|
||||
|
||||
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,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,36 +10,17 @@ import (
|
|||
func (c *Config) SetDefaultConnection(name string) error {
|
||||
log.Debug().Msgf("config: set %s as default connection", name)
|
||||
|
||||
err := c.setDef(name)
|
||||
if err != nil {
|
||||
if err := c.setDef(name); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = c.write()
|
||||
if err != nil {
|
||||
if err := c.write(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return c.reload()
|
||||
}
|
||||
|
||||
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{}
|
||||
}
|
||||
|
||||
func (c *Config) setDef(name string) error {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
@ -56,3 +37,20 @@ func (c *Config) setDef(name string) error {
|
|||
|
||||
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{}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ func (c *Config) readConfigFromFile(path string) error {
|
|||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
cfgFile, err := os.Open(path) //nolint:gosec
|
||||
cfgFile, err := os.Open(path)
|
||||
if err != nil {
|
||||
return fmt.Errorf("config: %w open configuration %q", err, path)
|
||||
}
|
||||
|
@ -37,8 +37,7 @@ func (c *Config) reload() error {
|
|||
return err
|
||||
}
|
||||
|
||||
err = c.readConfigFromFile(path)
|
||||
if err != nil {
|
||||
if err := c.readConfigFromFile(path); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
|
@ -8,8 +8,7 @@ func (c *Config) Remove(name string) error {
|
|||
|
||||
c.remove(name)
|
||||
|
||||
err := c.write()
|
||||
if err != nil {
|
||||
if err := c.write(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
|
@ -24,30 +24,23 @@ func (c *Config) write() error {
|
|||
|
||||
log.Debug().Msgf("config: write configuration file %q", path)
|
||||
|
||||
err = os.MkdirAll(filepath.Dir(path), 0o750) //nolint:mnd
|
||||
if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil { //nolint:mnd
|
||||
return err
|
||||
}
|
||||
|
||||
configFile, err := os.OpenFile(path, os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0o640) //nolint:mnd
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
configFile, err := os.OpenFile(path, os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0o600) //nolint:mnd,gosec
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer func() {
|
||||
err := configFile.Close()
|
||||
if err != nil {
|
||||
log.Error().Msgf("failed to close config file after write: %s", err.Error())
|
||||
}
|
||||
}()
|
||||
defer configFile.Close()
|
||||
|
||||
jsonData, err := json.Marshal(c.Connection)
|
||||
if err != nil {
|
||||
return fmt.Errorf("config: configuration json marshal %w", err)
|
||||
}
|
||||
|
||||
_, err = configFile.Write(jsonData)
|
||||
if err != nil {
|
||||
if _, err := configFile.Write(jsonData); err != nil {
|
||||
return fmt.Errorf("config: %w write configuration %q", err, path)
|
||||
}
|
||||
|
||||
|
|
|
@ -34,8 +34,7 @@ func ValidateNewConnection(name string, dest string, identity string) (string, e
|
|||
return "", ErrEmptyURIDestination
|
||||
}
|
||||
|
||||
match, err := regexp.Match("^[A-Za-z][A-Za-z0-9+.-]*://", []byte(dest)) //nolint:mirror
|
||||
if err != nil {
|
||||
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
|
||||
|
@ -49,8 +48,7 @@ func ValidateNewConnection(name string, dest string, identity string) (string, e
|
|||
switch uri.Scheme {
|
||||
case "ssh":
|
||||
if uri.User.Username() == "" {
|
||||
uri.User, err = getUserInfo(uri)
|
||||
if err != nil {
|
||||
if uri.User, err = getUserInfo(uri); err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
@ -69,8 +67,7 @@ func ValidateNewConnection(name string, dest string, identity string) (string, e
|
|||
}
|
||||
|
||||
if uri.Path == "" || uri.Path == "/" {
|
||||
uri.Path, err = getUDS(uri, connIdentity)
|
||||
if err != nil {
|
||||
if uri.Path, err = getUDS(uri, connIdentity); err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -91,7 +91,7 @@ func getUserInfo(uri *url.URL) (*url.Userinfo, error) {
|
|||
}
|
||||
|
||||
// most of the codes are from https://github.com/containers/podman/blob/main/cmd/podman/system/connection/add.go.
|
||||
func getUDS(uri *url.URL, iden string) (string, error) { //nolint:cyclop
|
||||
func getUDS(uri *url.URL, iden string) (string, error) {
|
||||
cfg, err := validateAndConfigure(uri, iden)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("%w failed to validate", err)
|
||||
|
@ -102,24 +102,14 @@ func getUDS(uri *url.URL, iden string) (string, error) { //nolint:cyclop
|
|||
return "", fmt.Errorf("%w failed to connect", err)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
err := dial.Close()
|
||||
if err != nil {
|
||||
log.Error().Msgf("failed to close SSH tcp connection: %s", err.Error())
|
||||
}
|
||||
}()
|
||||
defer dial.Close()
|
||||
|
||||
session, err := dial.NewSession()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("%w failed to create new ssh session on %q", err, uri.Host)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
err := session.Close()
|
||||
if err != nil {
|
||||
log.Error().Msgf("failed to close SSH session: %s", err.Error())
|
||||
}
|
||||
}()
|
||||
defer session.Close()
|
||||
|
||||
// Override podman binary for testing etc
|
||||
podman := "podman"
|
||||
|
@ -133,9 +123,7 @@ func getUDS(uri *url.URL, iden string) (string, error) { //nolint:cyclop
|
|||
}
|
||||
|
||||
var info define.Info
|
||||
|
||||
err = json.Unmarshal(infoJSON, &info)
|
||||
if err != nil {
|
||||
if err := json.Unmarshal(infoJSON, &info); err != nil {
|
||||
return "", fmt.Errorf("%w failed to parse 'podman info' results", err)
|
||||
}
|
||||
|
||||
|
@ -179,7 +167,7 @@ func validateAndConfigure(uri *url.URL, iden string) (*ssh.ClientConfig, error)
|
|||
if sock, found := os.LookupEnv("SSH_AUTH_SOCK"); found {
|
||||
log.Debug().Msgf("config: Found SSH_AUTH_SOCK %q, ssh-agent signer enabled", sock)
|
||||
|
||||
c, err := net.Dial("unix", sock) //nolint:noctx
|
||||
c, err := net.Dial("unix", sock)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -245,12 +233,7 @@ func execRemoteCommand(dial *ssh.Client, run string) ([]byte, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
defer func() {
|
||||
err := sess.Close()
|
||||
if err != nil {
|
||||
log.Error().Msgf("failed to close exec session: %s", err.Error())
|
||||
}
|
||||
}()
|
||||
defer sess.Close()
|
||||
|
||||
var (
|
||||
buffer bytes.Buffer
|
||||
|
@ -260,8 +243,7 @@ func execRemoteCommand(dial *ssh.Client, run string) ([]byte, error) {
|
|||
sess.Stdout = &buffer // output from client funneled into buffer
|
||||
sess.Stderr = &bufferErr // err form client funneled into buffer
|
||||
|
||||
err = sess.Run(run)
|
||||
if err != nil { // run the command on the ssh client
|
||||
if err := sess.Run(run); err != nil { // run the command on the ssh client
|
||||
return nil, fmt.Errorf("%w %s", err, bufferErr.String())
|
||||
}
|
||||
|
||||
|
|
80
go.mod
80
go.mod
|
@ -3,34 +3,35 @@ module github.com/containers/podman-tui
|
|||
go 1.23.3
|
||||
|
||||
require (
|
||||
github.com/containers/buildah v1.41.3
|
||||
github.com/containers/common v0.64.1
|
||||
github.com/containers/podman/v5 v5.6.0
|
||||
github.com/containers/storage v1.59.1
|
||||
github.com/containers/buildah v1.40.1
|
||||
github.com/containers/common v0.63.1
|
||||
github.com/containers/podman/v5 v5.5.2
|
||||
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.9.0
|
||||
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.23.4
|
||||
github.com/onsi/gomega v1.38.0
|
||||
github.com/onsi/gomega v1.37.0
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/rivo/tview v0.42.0
|
||||
github.com/rivo/tview v0.0.0-20220307222120-9994674d60a8
|
||||
github.com/rs/zerolog v1.34.0
|
||||
github.com/sirupsen/logrus v1.9.3
|
||||
github.com/spf13/cobra v1.9.1
|
||||
golang.org/x/crypto v0.41.0
|
||||
golang.org/x/crypto v0.40.0
|
||||
)
|
||||
|
||||
require (
|
||||
dario.cat/mergo v1.0.2 // indirect
|
||||
dario.cat/mergo v1.0.1 // 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.13.0 // indirect
|
||||
github.com/Microsoft/hcsshim v0.12.9 // indirect
|
||||
github.com/VividCortex/ewma v1.2.0 // indirect
|
||||
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d // indirect
|
||||
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.5 // indirect
|
||||
|
@ -40,7 +41,7 @@ require (
|
|||
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.36.1 // 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.1 // indirect
|
||||
github.com/containers/psgo v1.9.0 // indirect
|
||||
|
@ -49,15 +50,25 @@ require (
|
|||
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 v28.3.2+incompatible // 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.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.3 // 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.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.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.20241109141217-c266b19b28e9 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
|
@ -73,6 +84,7 @@ require (
|
|||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/jinzhu/copier v0.4.0 // indirect
|
||||
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.18.0 // indirect
|
||||
|
@ -80,6 +92,7 @@ require (
|
|||
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.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
|
||||
|
@ -87,6 +100,7 @@ require (
|
|||
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.4.0 // indirect
|
||||
github.com/moby/sys/mountinfo v0.7.2 // indirect
|
||||
|
@ -97,51 +111,55 @@ require (
|
|||
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/opencontainers/cgroups v0.0.4 // 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.1 // indirect
|
||||
github.com/opencontainers/runc v1.3.0 // 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.20250523060157-0ea5ed0382a2 // 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.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.9.0 // indirect
|
||||
github.com/sigstore/fulcio v1.6.6 // indirect
|
||||
github.com/sigstore/protobuf-specs v0.4.1 // indirect
|
||||
github.com/sigstore/sigstore v1.9.5 // 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.21.1 // indirect
|
||||
github.com/tchap/go-patricia/v2 v2.3.3 // indirect
|
||||
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 // 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.12.1 // indirect
|
||||
github.com/vbauerster/mpb/v8 v8.10.2 // indirect
|
||||
github.com/vbauerster/mpb/v8 v8.9.3 // indirect
|
||||
go.mongodb.org/mongo-driver v1.14.0 // indirect
|
||||
go.opencensus.io v0.24.0 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 // indirect
|
||||
go.opentelemetry.io/otel v1.35.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.35.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.35.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
|
||||
go.yaml.in/yaml/v2 v2.4.2 // indirect
|
||||
golang.org/x/net v0.42.0 // indirect
|
||||
golang.org/x/net v0.41.0 // indirect
|
||||
golang.org/x/sync v0.16.0 // indirect
|
||||
golang.org/x/sys v0.35.0 // indirect
|
||||
golang.org/x/term v0.34.0 // indirect
|
||||
golang.org/x/text v0.28.0 // indirect
|
||||
golang.org/x/sys v0.34.0 // indirect
|
||||
golang.org/x/term v0.33.0 // indirect
|
||||
golang.org/x/text v0.27.0 // indirect
|
||||
golang.org/x/time v0.11.0 // indirect
|
||||
golang.org/x/tools v0.35.0 // indirect
|
||||
golang.org/x/tools v0.34.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.72.2 // 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.5.0 // indirect
|
||||
sigs.k8s.io/yaml v1.4.0 // indirect
|
||||
tags.cncf.io/container-device-interface v1.0.1 // indirect
|
||||
)
|
||||
|
|
211
go.sum
211
go.sum
|
@ -1,6 +1,8 @@
|
|||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8=
|
||||
dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA=
|
||||
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-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=
|
||||
|
@ -8,12 +10,14 @@ 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.13.0 h1:/BcXOiS6Qi7N9XqUcv27vkIuVOkBEcWstd2pMlWSeaA=
|
||||
github.com/Microsoft/hcsshim v0.13.0/go.mod h1:9KWJ/8DgU+QzYGupX4tzMhRQE8h6w90lH6HAaclpEok=
|
||||
github.com/Microsoft/hcsshim v0.12.9 h1:2zJy5KA+l0loz1HzEGqyNnjd3fyZA31ZBCGKacp6lLg=
|
||||
github.com/Microsoft/hcsshim v0.12.9/go.mod h1:fJ0gkFAna6ukt0bLdKB8djt4XIJhF/vEPuoIWYVvZ8Y=
|
||||
github.com/VividCortex/ewma v1.2.0 h1:f58SaIzcDXrSy3kWaHNvuJgJ3Nmz59Zji6XoJR/q1ow=
|
||||
github.com/VividCortex/ewma v1.2.0/go.mod h1:nz4BbCtbLyFDeC9SUHbtcT5644juEuWfUAUnGx7j5l4=
|
||||
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8=
|
||||
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d/go.mod h1:asat636LX7Bqt5lYEZ27JNDcqxfjdBQuJ/MM4CN/Lzo=
|
||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so=
|
||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
|
||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
|
||||
|
@ -48,22 +52,22 @@ github.com/containerd/stargz-snapshotter/estargz v0.16.3 h1:7evrXtoh1mSbGj/pfRcc
|
|||
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.41.3 h1:L6wyRXGR+Cejx+/LMsEryi1JmuwbAICZEje+tQ7ihMs=
|
||||
github.com/containers/buildah v1.41.3/go.mod h1:vVIYC6f5gbPNfhprdMZh9lkOJzzM7lta0romUtBFSw0=
|
||||
github.com/containers/common v0.64.1 h1:E8vSiL+B84/UCsyVSb70GoxY9cu+0bseLujm4EKF6GE=
|
||||
github.com/containers/common v0.64.1/go.mod h1:CtfQNHoCAZqWeXMwdShcsxmMJSeGRgKKMqAwRKmWrHE=
|
||||
github.com/containers/image/v5 v5.36.1 h1:6zpXBqR59UcAzoKpa/By5XekeqFV+htWYfr65+Cgjqo=
|
||||
github.com/containers/image/v5 v5.36.1/go.mod h1:b4GMKH2z/5t6/09utbse2ZiLK/c72GuGLFdp7K69eA4=
|
||||
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.1 h1:0qIOTT9DoYwcKmxSt8QJt+VzMY18onl9jUXsxpVhSmM=
|
||||
github.com/containers/ocicrypt v1.2.1/go.mod h1:aD0AAqfMp0MtwqWgHM1bUwe1anx0VazI108CRrSKINQ=
|
||||
github.com/containers/podman/v5 v5.6.0 h1:tBs3B4RJHeCJsYPK90DkQYSCupa0vau/8JmBNH/Kz9k=
|
||||
github.com/containers/podman/v5 v5.6.0/go.mod h1:Qxcq3VrAbVqdw7C5MPtGoGxTNpfnJFACL5+flxNgf/Y=
|
||||
github.com/containers/podman/v5 v5.5.2 h1:H9C6hRs+Aa9g5x/wApHoVqT0fxFr0DH0tgs1h1/ktHc=
|
||||
github.com/containers/podman/v5 v5.5.2/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.59.1 h1:11Zu68MXsEQGBBd+GadPrHPpWeqjKS8hJDGiAHgIqDs=
|
||||
github.com/containers/storage v1.59.1/go.mod h1:KoAYHnAjP3/cTsRS+mmWZGkufSY2GACiKQ4V3ZLQnR0=
|
||||
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=
|
||||
|
@ -82,12 +86,12 @@ 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 v28.3.2+incompatible h1:mOt9fcLE7zaACbxW1GeS65RI67wIJrTnqS3hP2huFsY=
|
||||
github.com/docker/cli v28.3.2+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 v28.3.2+incompatible h1:wn66NJ6pWB1vBZIilP8G3qQPqHy5XymfYn5vsqeA5oA=
|
||||
github.com/docker/docker v28.3.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
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=
|
||||
|
@ -105,17 +109,39 @@ github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSw
|
|||
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
|
||||
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.9.0 h1:N6t+eqK7/xwtRPwxzs1PXeRWnm0H9l02CrgJ7DLn1ys=
|
||||
github.com/gdamore/tcell/v2 v2.9.0/go.mod h1:8/ZoqM9rxzYphT9tH/9LnunhV9oPBqwS8WHGYm5nrmo=
|
||||
github.com/gdamore/tcell/v2 v2.4.1-0.20210905002822-f057f0a857a1/go.mod h1:Az6Jt+M5idSED2YPGtwnfJV0kXohgdCBPmHGSYc1r04=
|
||||
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.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
||||
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
|
||||
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
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.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=
|
||||
github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4=
|
||||
github.com/go-openapi/loads v0.22.0 h1:ECPGd4jX1U6NApCGG1We+uEozOAvXvJSF4nnwHZ8Aco=
|
||||
github.com/go-openapi/loads v0.22.0/go.mod h1:yLsaTCS92mnSAZX5WWoxszLj0u+Ojl+Zs5Stn1oF+rs=
|
||||
github.com/go-openapi/runtime v0.28.0 h1:gpPPmWSNGo214l6n8hzdXYhPuJcGtziTOgUpvsFWGIQ=
|
||||
github.com/go-openapi/runtime v0.28.0/go.mod h1:QN7OzcS+XuYmkQLw05akXk0jRH/eZ3kb18+1KwW9gyc=
|
||||
github.com/go-openapi/spec v0.21.0 h1:LTVzPc3p/RzRnkQqLRndbAzjY0d0BCL72A6j3CdL9ZY=
|
||||
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.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=
|
||||
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
|
||||
github.com/go-test/deep v1.1.1 h1:0r/53hagsehfO4bzD2Pgr/+RgHqhmf+k1Bpse2cTu1U=
|
||||
|
@ -148,6 +174,7 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
|
|||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
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/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
|
@ -181,6 +208,8 @@ github.com/jinzhu/copier v0.4.0 h1:w3ciUoD19shMCRargcpm0cm91ytaBhDvuRpz1ODO/U8=
|
|||
github.com/jinzhu/copier v0.4.0/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg=
|
||||
github.com/jmhodges/clock v1.2.0 h1:eq4kys+NI0PLngzaHEe7AmPT90XMGIEySD1JfV1PDIs=
|
||||
github.com/jmhodges/clock v1.2.0/go.mod h1:qKjhA7x7u/lQpPB1XAqX1b1lCI/w3/fNuYpI/ZjLynI=
|
||||
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
||||
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4=
|
||||
|
@ -201,6 +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.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=
|
||||
|
@ -209,6 +240,7 @@ github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/
|
|||
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
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.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
|
||||
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/mattn/go-sqlite3 v1.14.28 h1:ThEiQrnbtumT+QMknw63Befp/ce/nUPgBPMlRFEum7A=
|
||||
|
@ -217,6 +249,8 @@ 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=
|
||||
github.com/mistifyio/go-zfs/v3 v3.0.1/go.mod h1:CzVgeB0RvF2EGzQnytKVvVSDwmKJXxkOTUGbNrTja/k=
|
||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||
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/atomicwriter v0.1.0 h1:kw5D/EqkBwsBFi0ss9v1VG3wIkVhzGvLklJ+w3A14Sw=
|
||||
|
@ -246,24 +280,28 @@ github.com/navidys/tvxwidgets v0.4.1 h1:abITHN2R0AN1G5XYBDCeTBfR+E1FRsDKN5j1FKI8
|
|||
github.com/navidys/tvxwidgets v0.4.1/go.mod h1:VJRhOCt9q4cuqN1UebaWRAc0MG4pmpHMBWL3tRSoqdI=
|
||||
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.23.4 h1:ktYTpKJAVZnDT4VjxSbiBenUjmlL/5QkBEocaWXiQus=
|
||||
github.com/onsi/ginkgo/v2 v2.23.4/go.mod h1:Bt66ApGPBFzHyR+JO10Zbt0Gsp4uWxu5mIOTusL46e8=
|
||||
github.com/onsi/gomega v1.38.0 h1:c/WX+w8SLAinvuKKQFh77WEucCnPk4j2OTUr7lt7BeY=
|
||||
github.com/onsi/gomega v1.38.0/go.mod h1:OcXcwId0b9QsE7Y49u+BTrL4IdKOBOKnD6VQNTJEB6o=
|
||||
github.com/opencontainers/cgroups v0.0.4 h1:XVj8P/IHVms/j+7eh8ggdkTLAxjz84ZzuFyGoE28DR4=
|
||||
github.com/opencontainers/cgroups v0.0.4/go.mod h1:s8lktyhlGUqM7OSRL5P7eAW6Wb+kWPNvt4qvVfzA5vs=
|
||||
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.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040=
|
||||
github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M=
|
||||
github.com/opencontainers/runc v1.3.0 h1:cvP7xbEvD0QQAs0nZKLzkVog2OPZhI/V2w3WmTmUSXI=
|
||||
github.com/opencontainers/runc v1.3.0/go.mod h1:9wbWt42gV+KRxKRVVugNP6D5+PQciRbenB4fLVsqGPs=
|
||||
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.20250523060157-0ea5ed0382a2 h1:2xZEHOdeQBV6PW8ZtimN863bIOl7OCW/X10K0cnxKeA=
|
||||
github.com/opencontainers/runtime-tools v0.9.1-0.20250523060157-0ea5ed0382a2/go.mod h1:MXdPzqAA8pHC58USHqNCSjyLnRQ6D+NjbpP+02Z1U/0=
|
||||
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.9 h1:4NGkvGudBL7GteO3m6qnaQ4pC0Kvf0onSVc9gR3EWBw=
|
||||
|
@ -275,18 +313,19 @@ github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4
|
|||
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.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q=
|
||||
github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0=
|
||||
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.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
|
||||
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
|
||||
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.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.42.0 h1:b/ftp+RxtDsHSaynXTbJb+/n/BxDEi+W3UfF5jILK6c=
|
||||
github.com/rivo/tview v0.42.0/go.mod h1:cSfIYfhpSGCjp3r/ECJb+GKS7cGJnqV8vfjQPwoXyfY=
|
||||
github.com/rivo/tview v0.0.0-20220307222120-9994674d60a8 h1:xe+mmCnDN82KhC010l3NfYlA8ZbOuzbXAzSYBa6wbMc=
|
||||
github.com/rivo/tview v0.0.0-20220307222120-9994674d60a8/go.mod h1:WIfMkQNY+oq/mWwtsjOYHIZBuwthioY2srOmljJkTnk=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
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.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
|
||||
|
@ -295,8 +334,8 @@ 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.2 h1:KRzFb2m7YtdldCEkzs6KqmJw4nqEVZGK7IN2kJkjTuQ=
|
||||
github.com/santhosh-tekuri/jsonschema/v6 v6.0.2/go.mod h1:JXeL+ps8p7/KNMjDQk3TCwPpBy0wYklyWTfbkIzdIFU=
|
||||
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.9.0 h1:rf1HIbL64nUpEIZnjLZ3mcNEL9NBPB0iuVjyxvq3LZc=
|
||||
|
@ -307,8 +346,10 @@ 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/sigstore v1.9.5 h1:Wm1LT9yF4LhQdEMy5A2JeGRHTrAWGjT3ubE5JUSrGVU=
|
||||
github.com/sigstore/sigstore v1.9.5/go.mod h1:VtxgvGqCmEZN9X2zhFSOkfXxvKUjpy8RpUW39oCtoII=
|
||||
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.1 h1:X2osQ+RAjK76shCbvhHHHVl3ZlgDm8apHEHFqRjnBY8=
|
||||
|
@ -333,16 +374,18 @@ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOf
|
|||
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/tchap/go-patricia/v2 v2.3.3 h1:xfNEsODumaEcCcY3gI0hYPZ/PcpVv5ju6RMAhgwZDDc=
|
||||
github.com/tchap/go-patricia/v2 v2.3.3/go.mod h1:VZRHKAb53DLaG+nA9EaYYiaEx6YztwDlLElMsnSHD4k=
|
||||
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.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.12.1 h1:CqKoORW7BUWBe7UL/iqTVvkTBOF8UvOMKOIZykxnnbo=
|
||||
github.com/vbatts/tar-split v0.12.1/go.mod h1:eF6B6i6ftWQcDqEn3/iGFRFRo8cBIMSJVOpnNdfTMFA=
|
||||
github.com/vbauerster/mpb/v8 v8.10.2 h1:2uBykSHAYHekE11YvJhKxYmLATKHAGorZwFlyNw4hHM=
|
||||
github.com/vbauerster/mpb/v8 v8.10.2/go.mod h1:+Ja4P92E3/CorSZgfDtK46D7AVbDqmBQRTmyTqPElo0=
|
||||
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=
|
||||
|
@ -352,34 +395,32 @@ github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQ
|
|||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
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.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
|
||||
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
|
||||
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.60.0 h1:sbiXRNDSWJOTobXh5HyQKjq6wUC5tNybqjIqDpAY4CU=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0/go.mod h1:69uWxva0WgAA/4bu2Yy70SLDBwZXuQ6PbBpbsa5iZrQ=
|
||||
go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ=
|
||||
go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.32.0 h1:IJFEoHiytixx8cMiVAO+GmHR6Frwu+u5Ur8njpFO6Ac=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.32.0/go.mod h1:3rHrKNtLIoS0oZwkY2vxi+oJcwFRWdtUyRII+so45p8=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0 h1:xJ2qHD0C1BeYVTLLR9sX12+Qb95kfeD/byKj6Ky1pXg=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0/go.mod h1:u5BF1xyjstDowA1R5QAO9JHzqK+ublenEW/dyqTjBVk=
|
||||
go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M=
|
||||
go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE=
|
||||
go.opentelemetry.io/otel/sdk v1.35.0 h1:iPctf8iprVySXSKJffSS79eOjl9pvxV9ZqOWT0QejKY=
|
||||
go.opentelemetry.io/otel/sdk v1.35.0/go.mod h1:+ga1bZliga3DxJ3CQGg3updiaAJoNECOgJREo9KHGQg=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.35.0 h1:1RriWBmCKgkeHEhM7a2uMjMUfP7MsOF5JpUCaEqEI9o=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.35.0/go.mod h1:is6XYCUMpcKi+ZsOvfluY5YstFnhW0BidkR+gL+qN+w=
|
||||
go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs=
|
||||
go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc=
|
||||
go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0=
|
||||
go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8=
|
||||
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=
|
||||
go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI=
|
||||
go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU=
|
||||
go.yaml.in/yaml/v3 v3.0.3 h1:bXOww4E/J3f66rav3pX3m8w6jDE4knZjGOw8b5Y6iNE=
|
||||
go.yaml.in/yaml/v3 v3.0.3/go.mod h1:tBHosrYAkRZjRAOREWbDnBXUf08JOwYq++0QNwQiWzI=
|
||||
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=
|
||||
|
@ -389,8 +430,8 @@ golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDf
|
|||
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.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4=
|
||||
golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc=
|
||||
golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM=
|
||||
golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
|
@ -418,8 +459,8 @@ golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
|||
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.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs=
|
||||
golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8=
|
||||
golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw=
|
||||
golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA=
|
||||
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,6 +481,7 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h
|
|||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210309074719-68d13333faf2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
|
@ -455,10 +497,13 @@ golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|||
golang.org/x/sys v0.17.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.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
|
||||
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
|
||||
golang.org/x/sys v0.34.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=
|
||||
|
@ -466,10 +511,12 @@ 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.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
|
||||
golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
|
||||
golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4=
|
||||
golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw=
|
||||
golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek=
|
||||
golang.org/x/term v0.33.0 h1:NuFncQrRcaRvVmgRkvM3j/F00gWIAlcmlB8ACEKmGIg=
|
||||
golang.org/x/term v0.33.0/go.mod h1:s18+ql9tYWp1IfpV9DmCtQDDSRBUjKaw9M1eAv5UeF0=
|
||||
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=
|
||||
|
@ -477,8 +524,8 @@ 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.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.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
|
||||
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
|
||||
golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4=
|
||||
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=
|
||||
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=
|
||||
|
@ -493,8 +540,8 @@ 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.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.35.0 h1:mBffYraMEf7aa0sB+NuKnuCy8qI/9Bughn8dC2Gu5r0=
|
||||
golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw=
|
||||
golang.org/x/tools v0.34.0 h1:qIpSLOxeCYGg9TrcJokLBG4KFA6d795g0xkBkiESGlo=
|
||||
golang.org/x/tools v0.34.0/go.mod h1:pAP9OwEaY1CAW3HOmg3hLZC5Z0CCmzjAF2UQMSqNARg=
|
||||
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=
|
||||
|
@ -513,8 +560,8 @@ google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyac
|
|||
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.72.2 h1:TdbGzwb82ty4OusHWepvFWGLgIbNo1/SUynEN0ssqv8=
|
||||
google.golang.org/grpc v1.72.2/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM=
|
||||
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=
|
||||
|
@ -538,7 +585,7 @@ 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.5.0 h1:M10b2U7aEUY6hRtU870n2VTPgR5RZiL/I6Lcc2F4NUQ=
|
||||
sigs.k8s.io/yaml v1.5.0/go.mod h1:wZs27Rbxoai4C0f8/9urLZtZtF3avA3gKvGyPdDqTO4=
|
||||
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 v1.0.1 h1:KqQDr4vIlxwfYh0Ed/uJGVgX+CHAkahrgabg6Q8GYxc=
|
||||
tags.cncf.io/container-device-interface v1.0.1/go.mod h1:JojJIOeW3hNbcnOH2q0NrWNha/JuHoDZcmYxAZwb2i0=
|
||||
|
|
|
@ -254,8 +254,7 @@ func Create(opts CreateOptions, run bool) ([]string, string, error) { //nolint:c
|
|||
}
|
||||
|
||||
// add healthcheck options
|
||||
err = containerHealthOptions(&createOptions, opts)
|
||||
if err != nil {
|
||||
if err := containerHealthOptions(&createOptions, opts); err != nil {
|
||||
return warningResponse, containerID, err
|
||||
}
|
||||
|
||||
|
@ -390,9 +389,7 @@ func Create(opts CreateOptions, run bool) ([]string, string, error) { //nolint:c
|
|||
|
||||
// generate spec
|
||||
s := specgen.NewSpecGenerator(opts.Name, false)
|
||||
|
||||
err = specgenutil.FillOutSpecGen(s, &createOptions, nil)
|
||||
if err != nil {
|
||||
if err := specgenutil.FillOutSpecGen(s, &createOptions, nil); err != nil {
|
||||
return warningResponse, containerID, err
|
||||
}
|
||||
|
||||
|
@ -406,8 +403,7 @@ func Create(opts CreateOptions, run bool) ([]string, string, error) { //nolint:c
|
|||
}
|
||||
|
||||
// validate spec
|
||||
err = s.Validate()
|
||||
if err != nil {
|
||||
if err := s.Validate(); err != nil {
|
||||
return warningResponse, containerID, err
|
||||
}
|
||||
|
||||
|
|
|
@ -95,8 +95,7 @@ func Exec(sessionID string, opts ExecOption) { //nolint:cyclop
|
|||
|
||||
conn, err := registry.GetConnection()
|
||||
if err != nil {
|
||||
_, err := opts.OutputStream.Write([]byte(fmt.Sprintf("%v", err))) //nolint:staticcheck
|
||||
if err != nil {
|
||||
if _, err := opts.OutputStream.Write([]byte(fmt.Sprintf("%v", err))); err != nil {
|
||||
log.Error().Msgf("%v", err)
|
||||
}
|
||||
|
||||
|
@ -117,12 +116,10 @@ func Exec(sessionID string, opts ExecOption) { //nolint:cyclop
|
|||
execStartAttachOpts.InputStream = opts.InputStream
|
||||
}
|
||||
|
||||
err := containers.ExecStartAndAttach(conn, sessionID, execStartAttachOpts)
|
||||
if err != nil {
|
||||
if err := containers.ExecStartAndAttach(conn, sessionID, execStartAttachOpts); err != nil {
|
||||
log.Error().Msgf("pdcs: podman session (%s) exec error %v", sessionID, err)
|
||||
|
||||
_, err := opts.OutputStream.Write([]byte(fmt.Sprintf("%v", err))) //nolint:staticcheck
|
||||
if err != nil {
|
||||
if _, err := opts.OutputStream.Write([]byte(fmt.Sprintf("%v", err))); err != nil {
|
||||
log.Error().Msgf("%v", err)
|
||||
}
|
||||
}
|
||||
|
@ -132,12 +129,10 @@ func Exec(sessionID string, opts ExecOption) { //nolint:cyclop
|
|||
return
|
||||
}
|
||||
|
||||
err = containers.ExecStart(conn, sessionID, &containers.ExecStartOptions{})
|
||||
if err != nil {
|
||||
if err := containers.ExecStart(conn, sessionID, &containers.ExecStartOptions{}); err != nil {
|
||||
log.Error().Msgf("pdcs: podman session (%s) exec error %v", sessionID, err)
|
||||
|
||||
_, err := opts.OutputStream.Write([]byte(fmt.Sprintf("%v", err))) //nolint:staticcheck
|
||||
if err != nil {
|
||||
if _, err := opts.OutputStream.Write([]byte(fmt.Sprintf("%v", err))); err != nil {
|
||||
log.Error().Msgf("%v", err)
|
||||
}
|
||||
|
||||
|
@ -146,23 +141,19 @@ func Exec(sessionID string, opts ExecOption) { //nolint:cyclop
|
|||
|
||||
log.Debug().Msgf("pdcs: podman session (%s) exec finished successfully", sessionID)
|
||||
|
||||
_, err = opts.OutputStream.Write([]byte(fmt.Sprintf("session_id ...... : %s\r\n", sessionID))) //nolint:staticcheck
|
||||
if err != nil {
|
||||
if _, err := opts.OutputStream.Write([]byte(fmt.Sprintf("session_id ...... : %s\r\n", sessionID))); err != nil {
|
||||
log.Error().Msgf("%v", err)
|
||||
}
|
||||
|
||||
_, err = opts.OutputStream.Write([]byte(fmt.Sprintf("exec_mode ...... : %s\r\n", "detached"))) //nolint:staticcheck
|
||||
if err != nil {
|
||||
if _, err := opts.OutputStream.Write([]byte(fmt.Sprintf("exec_mode ...... : %s\r\n", "detached"))); err != nil {
|
||||
log.Error().Msgf("%v", err)
|
||||
}
|
||||
|
||||
_, err = opts.OutputStream.Write([]byte(fmt.Sprintf("exec_command .... : %s\r\n", strings.Join(opts.Cmd, " ")))) //nolint:staticcheck,lll
|
||||
if err != nil {
|
||||
if _, err := opts.OutputStream.Write([]byte(fmt.Sprintf("exec_command .... : %s\r\n", strings.Join(opts.Cmd, " ")))); err != nil { //nolint:lll
|
||||
log.Error().Msgf("%v", err)
|
||||
}
|
||||
|
||||
_, err = opts.OutputStream.Write([]byte(fmt.Sprintf("exec_status ..... : %s\r\n", "OK"))) //nolint:staticcheck
|
||||
if err != nil {
|
||||
if _, err := opts.OutputStream.Write([]byte(fmt.Sprintf("exec_status ..... : %s\r\n", "OK"))); err != nil {
|
||||
log.Error().Msgf("%v", err)
|
||||
}
|
||||
}
|
||||
|
@ -173,7 +164,7 @@ func genExecCreateConfig(opts ExecOption) (*handlers.ExecCreateConfig, error) {
|
|||
createCfg := &handlers.ExecCreateConfig{}
|
||||
createCfg.Cmd = opts.Cmd
|
||||
createCfg.Tty = opts.Tty
|
||||
createCfg.Detach = opts.Detach //nolint:staticcheck
|
||||
createCfg.Detach = opts.Detach
|
||||
createCfg.WorkingDir = opts.WorkDir
|
||||
createCfg.User = opts.User
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package containers
|
||||
|
||||
import (
|
||||
"sort"
|
||||
|
||||
"github.com/containers/podman-tui/pdcs/registry"
|
||||
"github.com/containers/podman/v5/pkg/bindings/containers"
|
||||
"github.com/containers/podman/v5/pkg/domain/entities"
|
||||
|
@ -21,7 +23,20 @@ func List() ([]entities.ListContainer, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
sort.Sort(containerListSortedName{response})
|
||||
|
||||
log.Debug().Msgf("pdcs: %v", response)
|
||||
|
||||
return response, nil
|
||||
}
|
||||
|
||||
type lprSort []entities.ListContainer
|
||||
|
||||
func (a lprSort) Len() int { return len(a) }
|
||||
func (a lprSort) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||
|
||||
type containerListSortedName struct{ lprSort }
|
||||
|
||||
func (a containerListSortedName) Less(i, j int) bool {
|
||||
return a.lprSort[i].Names[0] < a.lprSort[j].Names[0]
|
||||
}
|
||||
|
|
|
@ -44,7 +44,6 @@ func Logs(id string) ([]string, error) {
|
|||
if err != nil {
|
||||
return logs, err
|
||||
}
|
||||
|
||||
done <- true
|
||||
// logs = append(logs, <-logout)
|
||||
// logs = append(logs, <-logerr)
|
||||
|
|
|
@ -43,9 +43,9 @@ type conReporter struct {
|
|||
}
|
||||
|
||||
func (con conReporter) ports() string {
|
||||
if len(con.Ports) < 1 {
|
||||
if len(con.ListContainer.Ports) < 1 {
|
||||
return ""
|
||||
}
|
||||
|
||||
return utils.PortsToString(con.Ports)
|
||||
return utils.PortsToString(con.ListContainer.Ports)
|
||||
}
|
||||
|
|
|
@ -20,13 +20,11 @@ func RunInitAttach(cntID string, stdin io.Reader, stdout io.Writer, attachReady
|
|||
attachOptions := new(containers.AttachOptions)
|
||||
attachOptions.WithDetachKeys(detachKey)
|
||||
|
||||
err = containers.ContainerInit(conn, cntID, new(containers.InitOptions))
|
||||
if err != nil {
|
||||
if err := containers.ContainerInit(conn, cntID, new(containers.InitOptions)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = containers.Attach(conn, cntID, stdin, stdout, stdout, attachReady, attachOptions)
|
||||
if err != nil {
|
||||
if err := containers.Attach(conn, cntID, stdin, stdout, stdout, attachReady, attachOptions); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
|
@ -40,12 +40,7 @@ func Import(opts ImageImportOptions) (string, error) {
|
|||
return "", err
|
||||
}
|
||||
|
||||
defer func() {
|
||||
err := tarFile.Close()
|
||||
if err != nil {
|
||||
log.Error().Msgf("failed to close tar file: %s", err.Error())
|
||||
}
|
||||
}()
|
||||
defer tarFile.Close()
|
||||
|
||||
reader = bufio.NewReader(tarFile)
|
||||
}
|
||||
|
|
|
@ -2,10 +2,11 @@ package images
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
|
||||
"github.com/containers/podman-tui/pdcs/registry"
|
||||
"github.com/containers/podman/v5/pkg/bindings/images"
|
||||
"github.com/containers/podman/v5/pkg/domain/entities/types"
|
||||
"github.com/containers/podman/v5/pkg/domain/entities"
|
||||
"github.com/distribution/reference"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/rs/zerolog/log"
|
||||
|
@ -29,7 +30,7 @@ func List() ([]ImageListReporter, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
imgs, err := imageListReporter(response)
|
||||
imgs, err := sortImages(response)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -41,13 +42,12 @@ func List() ([]ImageListReporter, error) {
|
|||
|
||||
// ImageListReporter image list report.
|
||||
type ImageListReporter struct {
|
||||
types.ImageSummary
|
||||
|
||||
Repository string `json:"repository,omitempty"`
|
||||
Tag string `json:"tag,omitempty"`
|
||||
entities.ImageSummary
|
||||
}
|
||||
|
||||
func imageListReporter(imageS []*types.ImageSummary) ([]ImageListReporter, error) {
|
||||
func sortImages(imageS []*entities.ImageSummary) ([]ImageListReporter, error) {
|
||||
imgs := make([]ImageListReporter, 0, len(imageS))
|
||||
|
||||
var err error
|
||||
|
@ -88,9 +88,17 @@ func imageListReporter(imageS []*types.ImageSummary) ([]ImageListReporter, error
|
|||
}
|
||||
}
|
||||
|
||||
sort.Slice(imgs, sortFunc(imgs))
|
||||
|
||||
return imgs, err
|
||||
}
|
||||
|
||||
func sortFunc(data []ImageListReporter) func(i, j int) bool {
|
||||
return func(i, j int) bool {
|
||||
return data[i].Repository < data[j].Repository
|
||||
}
|
||||
}
|
||||
|
||||
func tokenRepoTag(ref string) (string, string, error) {
|
||||
tagRef := fmt.Sprintf("%s:%s", noneTag, noneTag)
|
||||
if ref == tagRef {
|
||||
|
|
|
@ -44,13 +44,7 @@ func Save(imageID string, opts ImageSaveOptions) error { //nolint:cyclop
|
|||
|
||||
return err
|
||||
}
|
||||
|
||||
defer func() {
|
||||
err := outputFile.Close()
|
||||
if err != nil {
|
||||
log.Error().Msgf("failed to close image save output file: %s", err.Error())
|
||||
}
|
||||
}()
|
||||
defer outputFile.Close()
|
||||
|
||||
cancelChan := make(chan bool, 1)
|
||||
writerChan := make(chan []byte, 1024) //nolint:mnd
|
||||
|
@ -68,8 +62,7 @@ func Save(imageID string, opts ImageSaveOptions) error { //nolint:cyclop
|
|||
|
||||
return
|
||||
case data := <-writerChan:
|
||||
_, err := outputFile.Write(data)
|
||||
if err != nil {
|
||||
if _, err := outputFile.Write(data); err != nil {
|
||||
outputErrors = append(outputErrors, err)
|
||||
}
|
||||
}
|
||||
|
@ -84,7 +77,6 @@ func Save(imageID string, opts ImageSaveOptions) error { //nolint:cyclop
|
|||
saveOpts.WithOciAcceptUncompressedLayers(opts.OciAcceptUncompressedLayers)
|
||||
|
||||
err = images.Export(conn, []string{imageID}, outputWriter, &saveOpts)
|
||||
|
||||
cancelChan <- true
|
||||
|
||||
if err != nil {
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package networks
|
||||
|
||||
import (
|
||||
"sort"
|
||||
|
||||
"github.com/containers/common/libnetwork/types"
|
||||
"github.com/containers/podman-tui/pdcs/registry"
|
||||
"github.com/containers/podman/v5/pkg/bindings/network"
|
||||
|
@ -8,10 +10,10 @@ import (
|
|||
)
|
||||
|
||||
// List returns list of podman networks.
|
||||
func List() ([]types.Network, error) {
|
||||
func List() ([][]string, error) {
|
||||
log.Debug().Msg("pdcs: podman network ls")
|
||||
|
||||
report := make([]types.Network, 0)
|
||||
report := make([][]string, 0)
|
||||
|
||||
conn, err := registry.GetConnection()
|
||||
if err != nil {
|
||||
|
@ -23,7 +25,26 @@ func List() ([]types.Network, error) {
|
|||
return report, err
|
||||
}
|
||||
|
||||
log.Debug().Msgf("pdcs: %v", response)
|
||||
sort.Sort(netListSortedName{response})
|
||||
|
||||
return response, nil
|
||||
for _, item := range response {
|
||||
report = append(report, []string{
|
||||
item.ID,
|
||||
item.Name,
|
||||
item.Driver,
|
||||
})
|
||||
}
|
||||
|
||||
log.Debug().Msgf("pdcs: %v", report)
|
||||
|
||||
return report, nil
|
||||
}
|
||||
|
||||
type lprSort []types.Network
|
||||
|
||||
func (a lprSort) Len() int { return len(a) }
|
||||
func (a lprSort) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||
|
||||
type netListSortedName struct{ lprSort }
|
||||
|
||||
func (a netListSortedName) Less(i, j int) bool { return a.lprSort[i].Name < a.lprSort[j].Name }
|
||||
|
|
|
@ -224,8 +224,7 @@ func Create(opts CreateOptions) error { //nolint:cyclop,gocognit,gocyclo
|
|||
}
|
||||
|
||||
// validate spec
|
||||
err = podSpec.Validate()
|
||||
if err != nil {
|
||||
if err := podSpec.Validate(); err != nil {
|
||||
errList = append(errList, err)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package pods
|
||||
|
||||
import (
|
||||
"sort"
|
||||
|
||||
"github.com/containers/podman-tui/pdcs/registry"
|
||||
"github.com/containers/podman/v5/pkg/bindings/pods"
|
||||
"github.com/containers/podman/v5/pkg/domain/entities"
|
||||
|
@ -21,7 +23,18 @@ func List() ([]*entities.ListPodsReport, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
sort.Sort(podPsSortedName{response})
|
||||
|
||||
log.Debug().Msgf("pdcs: %v", response)
|
||||
|
||||
return response, nil
|
||||
}
|
||||
|
||||
type lprSort []*entities.ListPodsReport
|
||||
|
||||
func (a lprSort) Len() int { return len(a) }
|
||||
func (a lprSort) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||
|
||||
type podPsSortedName struct{ lprSort }
|
||||
|
||||
func (a podPsSortedName) Less(i, j int) bool { return a.lprSort[i].Name < a.lprSort[j].Name }
|
||||
|
|
|
@ -54,7 +54,6 @@ func sortStats(podSReport []*entities.PodStatsReport, sortBy int) []StatReporter
|
|||
|
||||
for _, item := range podSReport {
|
||||
var reporterItem StatReporter
|
||||
|
||||
reporterItem.Pod = item.Pod
|
||||
reporterItem.CID = item.CID
|
||||
reporterItem.Name = item.Name
|
||||
|
|
|
@ -49,17 +49,14 @@ func SetConnectionStatus(status ConnStatus) {
|
|||
|
||||
pdcsRegistry.mu.Lock()
|
||||
defer pdcsRegistry.mu.Unlock()
|
||||
|
||||
pdcsRegistry.connection.Status = status
|
||||
}
|
||||
|
||||
// SetConnection sets registry connection.
|
||||
func SetConnection(connection Connection) {
|
||||
log.Debug().Msgf("pdcs: registry set connection %v", connection)
|
||||
|
||||
pdcsRegistry.mu.Lock()
|
||||
defer pdcsRegistry.mu.Unlock()
|
||||
|
||||
pdcsRegistry.connection = connection
|
||||
pdcsRegistry.connectionIsSet = true
|
||||
}
|
||||
|
|
|
@ -77,13 +77,7 @@ func Create(opts *SecretCreateOptions) error { //nolint:cyclop
|
|||
return err
|
||||
}
|
||||
|
||||
defer func() {
|
||||
err := file.Close()
|
||||
if err != nil {
|
||||
log.Error().Msgf("failed to close secret file input: %s", err.Error())
|
||||
}
|
||||
}()
|
||||
|
||||
defer file.Close()
|
||||
reader = file
|
||||
}
|
||||
|
||||
|
@ -96,8 +90,7 @@ func Create(opts *SecretCreateOptions) error { //nolint:cyclop
|
|||
return err
|
||||
}
|
||||
|
||||
_, err = secrets.Create(conn, reader, createOpts)
|
||||
if err != nil {
|
||||
if _, err := secrets.Create(conn, reader, createOpts); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package volumes
|
||||
|
||||
import (
|
||||
"sort"
|
||||
|
||||
"github.com/containers/podman-tui/pdcs/registry"
|
||||
"github.com/containers/podman/v5/pkg/bindings/volumes"
|
||||
"github.com/containers/podman/v5/pkg/domain/entities"
|
||||
|
@ -21,7 +23,17 @@ func List() ([]*entities.VolumeListReport, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
sort.Sort(volumeListSortedName{response})
|
||||
log.Debug().Msgf("pdcs: %v", response)
|
||||
|
||||
return response, nil
|
||||
}
|
||||
|
||||
type lprSort []*entities.VolumeListReport
|
||||
|
||||
func (a lprSort) Len() int { return len(a) }
|
||||
func (a lprSort) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||
|
||||
type volumeListSortedName struct{ lprSort }
|
||||
|
||||
func (a volumeListSortedName) Less(i, j int) bool { return a.lprSort[i].Name < a.lprSort[j].Name }
|
||||
|
|
|
@ -15,8 +15,8 @@
|
|||
%global git0 https://%{import_path}
|
||||
|
||||
Name: podman-tui
|
||||
Version: 1.8.0
|
||||
Release: dev.1%{?dist}
|
||||
Version: 1.7.0
|
||||
Release: 1%{?dist}
|
||||
Summary: Podman Terminal User Interface
|
||||
License: ASL 2.0
|
||||
URL: %{git0}
|
||||
|
@ -60,8 +60,6 @@ install -p ./bin/%{name} %{buildroot}%{_bindir}
|
|||
%{_bindir}/%{name}
|
||||
|
||||
%changelog
|
||||
* Fri Jul 11 2025 Navid Yaghoobi <navidys@fedoraproject.org> 1.8.0-dev-1
|
||||
|
||||
* Fri Jul 11 2025 Navid Yaghoobi <navidys@fedoraproject.org> 1.7.0-1
|
||||
- Bump golang.org/x/crypto from 0.39.0 to 0.40.0
|
||||
- Remove unused BUILDTAGS
|
||||
|
|
|
@ -15,10 +15,9 @@ type apiConn struct {
|
|||
|
||||
// ConnStatus returns connection status.
|
||||
func (conn *apiConn) ConnStatus() (registry.ConnStatus, string) {
|
||||
var (
|
||||
status registry.ConnStatus
|
||||
message string
|
||||
)
|
||||
var status registry.ConnStatus
|
||||
|
||||
message := ""
|
||||
|
||||
conn.mu.Lock()
|
||||
status = conn.connStaus
|
||||
|
|
|
@ -40,8 +40,7 @@ func (engine *Engine) startEventStreamer() {
|
|||
|
||||
go engine.eventReader()
|
||||
go func() {
|
||||
err := sysinfo.Events(engine.sysEvents.eventChan, engine.sysEvents.eventCancelChan)
|
||||
if err != nil {
|
||||
if err := sysinfo.Events(engine.sysEvents.eventChan, engine.sysEvents.eventCancelChan); err != nil {
|
||||
log.Error().Msgf("health check: event streamer %v", err)
|
||||
|
||||
engine.sysEvents.cancelChan <- true
|
||||
|
@ -56,7 +55,6 @@ 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()
|
||||
|
@ -96,10 +94,10 @@ func (engine *Engine) GetEventMessages() []string {
|
|||
|
||||
// HasNewEvent returns true if there is new event added to event buffer.
|
||||
func (engine *Engine) HasNewEvent() bool {
|
||||
hasEvent := false
|
||||
|
||||
engine.sysEvents.mu.Lock()
|
||||
|
||||
hasEvent := engine.sysEvents.hasNewEvent
|
||||
|
||||
hasEvent = engine.sysEvents.hasNewEvent
|
||||
engine.sysEvents.mu.Unlock()
|
||||
|
||||
return hasEvent
|
||||
|
@ -107,7 +105,6 @@ func (engine *Engine) HasNewEvent() bool {
|
|||
|
||||
func (engine *Engine) addEventMessage(msg string) {
|
||||
engine.sysEvents.mu.Lock()
|
||||
|
||||
if len(engine.sysEvents.messageBuffer) == engine.sysEvents.messageBufferSize {
|
||||
// empty first 10 entries
|
||||
engine.sysEvents.messageBuffer = engine.sysEvents.messageBuffer[20:]
|
||||
|
|
|
@ -29,6 +29,7 @@ load helpers_tui
|
|||
|
||||
@test "image save" {
|
||||
podman image pull docker.io/library/busybox || echo done
|
||||
image_index=$(podman image ls --sort repository --noheading | nl -v 0 | grep 'busybox ' | awk '{print $1}')
|
||||
[ -f "${TEST_IMAGE_SAVE_PATH}" ] && /bin/rm -rf $TEST_IMAGE_SAVE_PATH
|
||||
|
||||
# switch to images view
|
||||
|
@ -39,7 +40,7 @@ load helpers_tui
|
|||
# go to save button and press enter
|
||||
|
||||
podman_tui_set_view "images"
|
||||
podman_tui_select_item 0
|
||||
podman_tui_select_item $image_index
|
||||
podman_tui_select_image_cmd "save"
|
||||
|
||||
podman_tui_send_inputs $TEST_IMAGE_SAVE_PATH "Tab"
|
||||
|
@ -103,12 +104,14 @@ load helpers_tui
|
|||
}
|
||||
|
||||
@test "image diff" {
|
||||
image_index=$(podman image ls --sort repository --noheading | nl -v 0 | grep 'busybox ' | awk '{print $1}')
|
||||
|
||||
# switch to images view
|
||||
# select busybox image from list
|
||||
# select diff command from image commands dialog
|
||||
# close busybox image diff result message dialog
|
||||
podman_tui_set_view "images"
|
||||
podman_tui_select_item 2
|
||||
podman_tui_select_item $image_index
|
||||
podman_tui_select_image_cmd "diff"
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
podman_tui_send_inputs "Tab" "Enter"
|
||||
|
@ -118,12 +121,14 @@ load helpers_tui
|
|||
}
|
||||
|
||||
@test "image history" {
|
||||
image_index=$(podman image ls --sort repository --noheading | nl -v 0 | grep 'busybox ' | awk '{print $1}')
|
||||
image_id=$(podman image ls --sort repository --filter "reference=docker.io/library/busybox" --format "{{ .ID }}")
|
||||
# switch to images view
|
||||
# select busybox image from list
|
||||
# select history command from image commands dialog
|
||||
# close busybox image history result message dialog
|
||||
podman_tui_set_view "images"
|
||||
podman_tui_select_item 2
|
||||
podman_tui_select_item $image_index
|
||||
podman_tui_select_image_cmd "history"
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
podman_tui_send_inputs "Tab" "Enter"
|
||||
|
@ -133,6 +138,7 @@ load helpers_tui
|
|||
}
|
||||
|
||||
@test "image inspect" {
|
||||
image_index=$(podman image ls --sort repository --noheading | nl -v 0 | grep 'busybox ' | awk '{print $1}')
|
||||
image_id=$(podman image ls --sort repository --noheading | nl -v 0 | grep 'busybox ' | awk '{print $4}')
|
||||
|
||||
# switch to images view
|
||||
|
@ -140,7 +146,7 @@ load helpers_tui
|
|||
# select inspect command from image commands dialog
|
||||
# close busybox image inspect result message dialog
|
||||
podman_tui_set_view "images"
|
||||
podman_tui_select_item 2
|
||||
podman_tui_select_item $image_index
|
||||
podman_tui_select_image_cmd "inspect"
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
podman_tui_send_inputs "Enter"
|
||||
|
@ -150,11 +156,13 @@ load helpers_tui
|
|||
}
|
||||
|
||||
@test "image tag" {
|
||||
busybox_index=$(podman image ls --sort repository --noheading | nl -v 0 | grep 'busybox ' | awk '{print $1}')
|
||||
|
||||
# switch to images view
|
||||
# select busybox image from list
|
||||
# select tag command from image commands dialog
|
||||
podman_tui_set_view "images"
|
||||
podman_tui_select_item 2
|
||||
podman_tui_select_item $busyboxIndex
|
||||
podman_tui_select_image_cmd "tag"
|
||||
podman_tui_send_inputs "$TEST_IMAGE_TAG_NAME" "Tab" "Tab" "Enter"
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
|
@ -164,12 +172,14 @@ load helpers_tui
|
|||
}
|
||||
|
||||
@test "image untag" {
|
||||
busybox_tagindex=$(podman image ls --sort repository --noheading | nl -v 0 | grep "$TEST_IMAGE_TAG_NAME " | awk '{print $1}')
|
||||
|
||||
# switch to images view
|
||||
# select busybox image from list
|
||||
# select untag command from image commands dialog
|
||||
# press "Tab" 2 times and "Enter" to untag busybox image
|
||||
podman_tui_set_view "images"
|
||||
podman_tui_select_item 2
|
||||
podman_tui_select_item $busybox_tagindex
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
podman_tui_select_image_cmd "untag"
|
||||
podman_tui_send_inputs "Tab" "Tab" "Enter"
|
||||
|
@ -183,6 +193,7 @@ load helpers_tui
|
|||
@test "image remove" {
|
||||
run_helper podman image ls --format "'{{ .Repository }}'"
|
||||
before="$output"
|
||||
untagged_image=$(podman image ls --sort repository --noheading | nl -v 0 | grep '<none> ' | awk '{print $1}')
|
||||
|
||||
# switch to images view
|
||||
# select <none> image from list
|
||||
|
@ -191,7 +202,7 @@ load helpers_tui
|
|||
# wait for image removal operation
|
||||
# close image removal result message dialog
|
||||
podman_tui_set_view "images"
|
||||
podman_tui_select_item 2
|
||||
podman_tui_select_item $untagged_image
|
||||
podman_tui_select_image_cmd "remove"
|
||||
podman_tui_send_inputs "Enter"
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
|
|
|
@ -25,12 +25,14 @@ load helpers_tui
|
|||
}
|
||||
|
||||
@test "volume inspect" {
|
||||
vol_index=$(podman volume ls -q | nl -v 0 | grep "$TEST_VOLUME_NAME" | awk '{print $1}')
|
||||
|
||||
# switch to volumes view
|
||||
# select test volume from list
|
||||
# select inspect command from volume commands dialog
|
||||
# close volume inspect result message dialog
|
||||
podman_tui_set_view "volumes"
|
||||
podman_tui_select_item 0
|
||||
podman_tui_select_item $vol_index
|
||||
podman_tui_select_volume_cmd "inspect"
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
podman_tui_send_inputs "Enter"
|
||||
|
@ -41,11 +43,13 @@ load helpers_tui
|
|||
}
|
||||
|
||||
@test "volume remove" {
|
||||
vol_index=$(podman volume ls -q | nl -v 0 | grep "$TEST_VOLUME_NAME" | awk '{print $1}')
|
||||
|
||||
# switch to volumes view
|
||||
# select test volume from list
|
||||
# select remove command from volume commands dialog
|
||||
podman_tui_set_view "volumes"
|
||||
podman_tui_select_item 0
|
||||
podman_tui_select_item $vol_index
|
||||
podman_tui_select_volume_cmd "remove"
|
||||
podman_tui_send_inputs "Enter"
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
|
|
|
@ -17,7 +17,6 @@ load helpers_tui
|
|||
# select connect button
|
||||
|
||||
podman_tui_set_view "networks"
|
||||
podman_tui_select_item 1
|
||||
podman_tui_select_network_cmd "connect"
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
podman_tui_send_inputs "Tab"
|
||||
|
@ -39,7 +38,6 @@ load helpers_tui
|
|||
# select disconnect button
|
||||
|
||||
podman_tui_set_view "networks"
|
||||
podman_tui_select_item 1
|
||||
podman_tui_select_network_cmd "disconnect"
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
podman_tui_send_inputs "Tab" "Tab" "Enter"
|
||||
|
@ -70,12 +68,14 @@ load helpers_tui
|
|||
}
|
||||
|
||||
@test "network inspect" {
|
||||
net_index=$(podman network ls -q | nl -v 0 | grep "$TEST_NETWORK_NAME" | awk '{print $1}')
|
||||
|
||||
# switch to networks view
|
||||
# select test network from list
|
||||
# select inspect command from network commands dialog
|
||||
# close network inspect result message dialog
|
||||
podman_tui_set_view "networks"
|
||||
podman_tui_select_item 1
|
||||
podman_tui_select_item $net_index
|
||||
podman_tui_select_network_cmd "inspect"
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
podman_tui_send_inputs "Enter"
|
||||
|
@ -86,11 +86,13 @@ load helpers_tui
|
|||
}
|
||||
|
||||
@test "network remove" {
|
||||
net_index=$(podman network ls -q | nl -v 0 | grep "$TEST_NETWORK_NAME" | awk '{print $1}')
|
||||
|
||||
# switch to networks view
|
||||
# select test network from list
|
||||
# select remove command from network commands dialog
|
||||
podman_tui_set_view "networks"
|
||||
podman_tui_select_item 1
|
||||
podman_tui_select_item $net_index
|
||||
podman_tui_select_network_cmd "remove"
|
||||
podman_tui_send_inputs "Enter"
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
|
|
|
@ -43,6 +43,7 @@ load helpers_tui
|
|||
podman image pull pause:3.5 || echo done
|
||||
podman network create $TEST_POD_NETWORK_NAME || echo done
|
||||
|
||||
net_index=$(podman network ls -q | nl -v 1 | grep "$TEST_POD_NETWORK_NAME" | awk '{print $1}')
|
||||
# switch to pods view
|
||||
# select create command from pod commands dialog
|
||||
# fillout name field
|
||||
|
@ -58,7 +59,7 @@ load helpers_tui
|
|||
podman_tui_send_inputs $TEST_POD_NAME "Tab" "Tab" $TEST_LABEL
|
||||
podman_tui_send_inputs "Tab" "Tab" "Tab" "Down" "Down" "Down" "Tab"
|
||||
podman_tui_send_inputs "Tab" "Tab" "Tab" "Tab" "Down"
|
||||
podman_tui_select_item 1
|
||||
podman_tui_select_item $net_index
|
||||
podman_tui_send_inputs "Enter"
|
||||
podman_tui_send_inputs "Tab" "Tab" "Tab" "Tab" "Down" "Tab"
|
||||
podman_tui_send_inputs "disable"
|
||||
|
@ -76,11 +77,13 @@ load helpers_tui
|
|||
}
|
||||
|
||||
@test "pod start" {
|
||||
pod_index=$(podman pod ls --sort name --format "{{ .Name }}" | nl -v 0 | grep "$TEST_POD_NAME" | awk '{print $1}')
|
||||
|
||||
# switch to pods view
|
||||
# select test pod from list
|
||||
# select start command from pod commands dialog
|
||||
podman_tui_set_view "pods"
|
||||
podman_tui_select_item 0
|
||||
podman_tui_select_item $pod_index
|
||||
podman_tui_select_pod_cmd "start"
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
|
||||
|
@ -89,11 +92,13 @@ load helpers_tui
|
|||
}
|
||||
|
||||
@test "pod pause" {
|
||||
pod_index=$(podman pod ls --sort name --format "{{ .Name }}" | nl -v 0 | grep "$TEST_POD_NAME" | awk '{print $1}')
|
||||
|
||||
# switch to pods view
|
||||
# select test pod from list
|
||||
# select pause command from pod commands dialog
|
||||
podman_tui_set_view "pods"
|
||||
podman_tui_select_item 0
|
||||
podman_tui_select_item $pod_index
|
||||
podman_tui_select_pod_cmd "pause"
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
|
||||
|
@ -102,11 +107,13 @@ load helpers_tui
|
|||
}
|
||||
|
||||
@test "pod unpause" {
|
||||
pod_index=$(podman pod ls --sort name --format "{{ .Name }}" | nl -v 0 | grep "$TEST_POD_NAME" | awk '{print $1}')
|
||||
|
||||
# switch to pods view
|
||||
# select test pod from list
|
||||
# select unpause command from pod commands dialog
|
||||
podman_tui_set_view "pods"
|
||||
podman_tui_select_item 0
|
||||
podman_tui_select_item $pod_index
|
||||
podman_tui_select_pod_cmd "unpause"
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
|
||||
|
@ -115,11 +122,13 @@ load helpers_tui
|
|||
}
|
||||
|
||||
@test "pod stop" {
|
||||
pod_index=$(podman pod ls --sort name --format "{{ .Name }}" | nl -v 0 | grep "$TEST_POD_NAME" | awk '{print $1}')
|
||||
|
||||
# switch to pods view
|
||||
# select test pod from list
|
||||
# select stop command from pod commands dialog
|
||||
podman_tui_set_view "pods"
|
||||
podman_tui_select_item 0
|
||||
podman_tui_select_item $pod_index
|
||||
podman_tui_select_pod_cmd "stop"
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
|
||||
|
@ -128,11 +137,13 @@ load helpers_tui
|
|||
}
|
||||
|
||||
@test "pod restart" {
|
||||
pod_index=$(podman pod ls --sort name --format "{{ .Name }}" | nl -v 0 | grep "$TEST_POD_NAME" | awk '{print $1}')
|
||||
|
||||
# switch to pods view
|
||||
# select test pod from list
|
||||
# select restart command from pod commands dialog
|
||||
podman_tui_set_view "pods"
|
||||
podman_tui_select_item 0
|
||||
podman_tui_select_item $pod_index
|
||||
podman_tui_select_pod_cmd "restart"
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
|
||||
|
@ -141,11 +152,13 @@ load helpers_tui
|
|||
}
|
||||
|
||||
@test "pod kill" {
|
||||
pod_index=$(podman pod ls --sort name --format "{{ .Name }}" | nl -v 0 | grep "$TEST_POD_NAME" | awk '{print $1}')
|
||||
|
||||
# switch to pods view
|
||||
# select test pod from list
|
||||
# select kill command from pod commands dialog
|
||||
podman_tui_set_view "pods"
|
||||
podman_tui_select_item 0
|
||||
podman_tui_select_item $pod_index
|
||||
podman_tui_select_pod_cmd "kill"
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
|
||||
|
@ -154,12 +167,14 @@ load helpers_tui
|
|||
}
|
||||
|
||||
@test "pod inspect" {
|
||||
pod_index=$(podman pod ls --sort name --format "{{ .Name }}" | nl -v 0 | grep "$TEST_POD_NAME" | awk '{print $1}')
|
||||
|
||||
# switch to pods view
|
||||
# select test pod from list
|
||||
# select inspect command from pod commands dialog
|
||||
# close pod inspect result message dialog
|
||||
podman_tui_set_view "pods"
|
||||
podman_tui_select_item 0
|
||||
podman_tui_select_item $pod_index
|
||||
podman_tui_select_pod_cmd "inspect"
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
podman_tui_send_inputs "Enter"
|
||||
|
@ -169,12 +184,14 @@ load helpers_tui
|
|||
}
|
||||
|
||||
@test "pod remove" {
|
||||
pod_index=$(podman pod ls --sort name --format "{{ .Name }}" | nl -v 0 | grep "$TEST_POD_NAME" | awk '{print $1}')
|
||||
|
||||
# switch to pods view
|
||||
# select test pod from list
|
||||
# select remove command from pod commands dialog
|
||||
# confirm the operation on warnings dialog
|
||||
podman_tui_set_view "pods"
|
||||
podman_tui_select_item 0
|
||||
podman_tui_select_item $pod_index
|
||||
podman_tui_select_pod_cmd "remove"
|
||||
podman_tui_send_inputs "Enter"
|
||||
podman_tui_send_inputs "Enter"
|
||||
|
|
|
@ -14,11 +14,13 @@ load helpers_tui
|
|||
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 1
|
||||
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"
|
||||
|
@ -45,6 +47,8 @@ load helpers_tui
|
|||
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"
|
||||
|
@ -56,7 +60,7 @@ load helpers_tui
|
|||
# set timeout to 10
|
||||
podman_tui_send_inputs $TEST_CONTAINER_NAME "Tab" "Tab"
|
||||
podman_tui_send_inputs "Down"
|
||||
podman_tui_select_item 1
|
||||
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" "Tab"
|
||||
|
@ -74,7 +78,7 @@ load helpers_tui
|
|||
assert "$cnt_timeout" =~ "$TEST_CONTAINER_TIMEOUT" "expected container config timeout to match: $TEST_CONTAINER_TIMEOUT"
|
||||
}
|
||||
|
||||
@test "container create (environment)" {
|
||||
@test "container create (environment 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")
|
||||
|
@ -82,6 +86,8 @@ load helpers_tui
|
|||
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"
|
||||
|
@ -91,7 +97,7 @@ load helpers_tui
|
|||
# select image from dropdown widget
|
||||
podman_tui_send_inputs $TEST_CONTAINER_NAME "Tab" "Tab"
|
||||
podman_tui_send_inputs "Down"
|
||||
podman_tui_select_item 1
|
||||
podman_tui_select_item $image_index
|
||||
podman_tui_send_inputs "Enter" "Tab" "Tab" "Tab" "Tab" "Tab" "Tab" "Tab" "Tab" "Tab"
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
|
||||
|
@ -116,7 +122,7 @@ load helpers_tui
|
|||
assert "$cnt_vars" =~ "$TEST_CONTAINER_ENV2" "expected container env to match: $TEST_CONTAINER_ENV2"
|
||||
}
|
||||
|
||||
@test "container create (resource)" {
|
||||
@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")
|
||||
|
@ -124,6 +130,8 @@ load helpers_tui
|
|||
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"
|
||||
|
@ -133,7 +141,7 @@ load helpers_tui
|
|||
# select image from dropdown widget
|
||||
podman_tui_send_inputs $TEST_CONTAINER_NAME "Tab" "Tab"
|
||||
podman_tui_send_inputs "Down"
|
||||
podman_tui_select_item 1
|
||||
podman_tui_select_item $image_index
|
||||
podman_tui_send_inputs "Enter" "Tab" "Tab" "Tab" "Tab" "Tab" "Tab" "Tab" "Tab" "Tab"
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
|
||||
|
@ -190,6 +198,12 @@ load helpers_tui
|
|||
podman pod create --name $TEST_CONTAINER_POD_NAME --network $TEST_CONTAINER_NETWORK_NAME --publish $TEST_CONTAINER_PORT || echo done
|
||||
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}')
|
||||
image_index=$(podman image ls --sort repository --noheading | nl -v 1 | grep 'httpd ' | awk '{print $1}')
|
||||
net_index=$(podman network ls -q | nl -v 1 | grep "$TEST_CONTAINER_NETWORK_NAME" | awk '{print $1}')
|
||||
|
||||
|
||||
# switch to containers view
|
||||
# select create command from container commands dialog
|
||||
podman_tui_set_view "containers"
|
||||
|
@ -201,10 +215,10 @@ load helpers_tui
|
|||
# fillout label field
|
||||
podman_tui_send_inputs $TEST_CONTAINER_NAME "Tab" "Tab"
|
||||
podman_tui_send_inputs "Down"
|
||||
podman_tui_select_item 2
|
||||
podman_tui_select_item $image_index
|
||||
podman_tui_send_inputs "Enter" "Tab"
|
||||
podman_tui_send_inputs "Down"
|
||||
podman_tui_select_item 1
|
||||
podman_tui_select_item $pod_index
|
||||
podman_tui_send_inputs "Enter" "Tab"
|
||||
podman_tui_send_inputs $TEST_LABEL "Tab" "Tab" "Tab" "Tab" "Tab" "Tab"
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
|
@ -279,13 +293,15 @@ load helpers_tui
|
|||
}
|
||||
|
||||
@test "container commit" {
|
||||
container_index=$(podman container ls --all --format "{{ .Names }}" | sort | nl -v 0 | grep "$TEST_CONTAINER_NAME" | awk '{print $1}')
|
||||
|
||||
# switch to containers view
|
||||
# select container from the list
|
||||
# select commit command from container commands dialog
|
||||
# fillout image input field
|
||||
# go to commit button and press enter
|
||||
podman_tui_set_view "containers"
|
||||
podman_tui_select_item 0
|
||||
podman_tui_select_item $container_index
|
||||
podman_tui_select_container_cmd "commit"
|
||||
|
||||
podman_tui_send_inputs $TEST_CONTAINER_COMMIT_IMAGE_NAME
|
||||
|
@ -298,11 +314,13 @@ load helpers_tui
|
|||
}
|
||||
|
||||
@test "container start" {
|
||||
container_index=$(podman container ls --all --format "{{ .Names }}" | sort | nl -v 0 | grep "$TEST_CONTAINER_NAME" | awk '{print $1}')
|
||||
|
||||
# switch to containers view
|
||||
# select test container from list
|
||||
# select start command from container commands dialog
|
||||
podman_tui_set_view "containers"
|
||||
podman_tui_select_item 0
|
||||
podman_tui_select_item $container_index
|
||||
podman_tui_select_container_cmd "start"
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
|
||||
|
@ -314,6 +332,9 @@ load helpers_tui
|
|||
@test "container checkpoint" {
|
||||
podman container create --name ${TEST_CONTAINER_CHECKPOINT_NAME} docker.io/library/httpd
|
||||
podman container start ${TEST_CONTAINER_CHECKPOINT_NAME}
|
||||
|
||||
container_index=$(podman container ls --all --format "{{ .Names }}" | sort | nl -v 0 | grep "$TEST_CONTAINER_CHECKPOINT_NAME" | awk '{print $1}')
|
||||
|
||||
# switch to containers view
|
||||
# select test container from list
|
||||
# select checkpoint command from container commands dialog
|
||||
|
@ -321,7 +342,7 @@ load helpers_tui
|
|||
# go to checkpoint button and Enter
|
||||
|
||||
podman_tui_set_view "containers"
|
||||
podman_tui_select_item 0
|
||||
podman_tui_select_item $container_index
|
||||
podman_tui_select_container_cmd "checkpoint"
|
||||
|
||||
podman_tui_send_inputs "Tab"
|
||||
|
@ -359,6 +380,8 @@ load helpers_tui
|
|||
}
|
||||
|
||||
@test "container exec" {
|
||||
container_index=$(podman container ls --all --format "{{ .Names }}" | sort | nl -v 0 | grep "$TEST_CONTAINER_NAME" | awk '{print $1}')
|
||||
|
||||
# switch to containers view
|
||||
# select test container from list
|
||||
# select exec command from container commands dialog
|
||||
|
@ -369,7 +392,7 @@ load helpers_tui
|
|||
# type "echo test > a.txt"
|
||||
# go to Close button and Enter
|
||||
podman_tui_set_view "containers"
|
||||
podman_tui_select_item 2
|
||||
podman_tui_select_item $container_index
|
||||
podman_tui_select_container_cmd "exec"
|
||||
podman_tui_send_inputs "/bin/bash"
|
||||
podman_tui_send_inputs "Tab" "Space" "Tab"
|
||||
|
@ -386,11 +409,13 @@ load helpers_tui
|
|||
}
|
||||
|
||||
@test "container inspect" {
|
||||
container_index=$(podman container ls --all --format "{{ .Names }}" | sort | nl -v 0 | grep "$TEST_CONTAINER_NAME" | awk '{print $1}')
|
||||
|
||||
# switch to containers view
|
||||
# select test container from list
|
||||
# select inspect command from container commands dialog
|
||||
podman_tui_set_view "containers"
|
||||
podman_tui_select_item 2
|
||||
podman_tui_select_item $container_index
|
||||
podman_tui_select_container_cmd "inspect"
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
|
||||
|
@ -400,11 +425,13 @@ load helpers_tui
|
|||
}
|
||||
|
||||
@test "container diff" {
|
||||
container_index=$(podman container ls --all --format "{{ .Names }}" | sort | nl -v 0 | grep "$TEST_CONTAINER_NAME" | awk '{print $1}')
|
||||
|
||||
# switch to containers view
|
||||
# select test container from list
|
||||
# select diff command from container commands dialog
|
||||
podman_tui_set_view "containers"
|
||||
podman_tui_select_item 2
|
||||
podman_tui_select_item $container_index
|
||||
podman_tui_select_container_cmd "diff"
|
||||
sleep $TEST_TIMEOUT_MEDIUM
|
||||
|
||||
|
@ -413,11 +440,13 @@ load helpers_tui
|
|||
}
|
||||
|
||||
@test "container top" {
|
||||
container_index=$(podman container ls --all --format "{{ .Names }}" | sort | nl -v 0 | grep "$TEST_CONTAINER_NAME" | awk '{print $1}')
|
||||
|
||||
# switch to containers view
|
||||
# select test container from list
|
||||
# select top command from container commands dialog
|
||||
podman_tui_set_view "containers"
|
||||
podman_tui_select_item 2
|
||||
podman_tui_select_item $container_index
|
||||
podman_tui_select_container_cmd "top"
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
|
||||
|
@ -426,11 +455,13 @@ load helpers_tui
|
|||
}
|
||||
|
||||
@test "container port" {
|
||||
container_index=$(podman container ls --all --format "{{ .Names }}" | sort | nl -v 0 | grep "$TEST_CONTAINER_NAME" | awk '{print $1}')
|
||||
|
||||
# switch to containers view
|
||||
# select test container from list
|
||||
# select port command from container commands dialog
|
||||
podman_tui_set_view "containers"
|
||||
podman_tui_select_item 2
|
||||
podman_tui_select_item $container_index
|
||||
podman_tui_select_container_cmd "port"
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
|
||||
|
@ -440,11 +471,13 @@ load helpers_tui
|
|||
}
|
||||
|
||||
@test "container pause" {
|
||||
container_index=$(podman container ls --all --format "{{ .Names }}" | sort | nl -v 0 | grep "$TEST_CONTAINER_NAME" | awk '{print $1}')
|
||||
|
||||
# switch to containers view
|
||||
# select test container from list
|
||||
# select pause command from container commands dialog
|
||||
podman_tui_set_view "containers"
|
||||
podman_tui_select_item 2
|
||||
podman_tui_select_item $container_index
|
||||
podman_tui_select_container_cmd "pause"
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
|
||||
|
@ -453,11 +486,13 @@ load helpers_tui
|
|||
}
|
||||
|
||||
@test "container unpause" {
|
||||
container_index=$(podman container ls --all --format "{{ .Names }}" | sort | nl -v 0 | grep "$TEST_CONTAINER_NAME" | awk '{print $1}')
|
||||
|
||||
# switch to containers view
|
||||
# select test container from list
|
||||
# select unpause command from container commands dialog
|
||||
podman_tui_set_view "containers"
|
||||
podman_tui_select_item 2
|
||||
podman_tui_select_item $container_index
|
||||
podman_tui_select_container_cmd "unpause"
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
|
||||
|
@ -466,11 +501,13 @@ load helpers_tui
|
|||
}
|
||||
|
||||
@test "container stop" {
|
||||
container_index=$(podman container ls --all --format "{{ .Names }}" | sort | nl -v 0 | grep "$TEST_CONTAINER_NAME" | awk '{print $1}')
|
||||
|
||||
# switch to containers view
|
||||
# select test container from list
|
||||
# select stop command from container commands dialog
|
||||
podman_tui_set_view "containers"
|
||||
podman_tui_select_item 2
|
||||
podman_tui_select_item $container_index
|
||||
podman_tui_select_container_cmd "stop"
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
|
||||
|
@ -480,11 +517,13 @@ load helpers_tui
|
|||
|
||||
@test "container kill" {
|
||||
podman container start $TEST_CONTAINER_NAME || echo done
|
||||
container_index=$(podman container ls --all --format "{{ .Names }}" | sort | nl -v 0 | grep "$TEST_CONTAINER_NAME" | awk '{print $1}')
|
||||
|
||||
# switch to containers view
|
||||
# select test container from list
|
||||
# select kill command from container commands dialog
|
||||
podman_tui_set_view "containers"
|
||||
podman_tui_select_item 2
|
||||
podman_tui_select_item $container_index
|
||||
podman_tui_select_container_cmd "kill"
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
|
||||
|
@ -493,11 +532,13 @@ load helpers_tui
|
|||
}
|
||||
|
||||
@test "container remove" {
|
||||
container_index=$(podman container ls --all --format "{{ .Names }}" | sort | nl -v 0 | grep "$TEST_CONTAINER_NAME" | awk '{print $1}')
|
||||
|
||||
# switch to containers view
|
||||
# select test container from list
|
||||
# select remove command from container commands dialog
|
||||
podman_tui_set_view "containers"
|
||||
podman_tui_select_item 2
|
||||
podman_tui_select_item $container_index
|
||||
podman_tui_select_container_cmd "remove"
|
||||
podman_tui_send_inputs "Enter"
|
||||
sleep $TEST_TIMEOUT_LOW
|
||||
|
@ -507,14 +548,15 @@ load helpers_tui
|
|||
}
|
||||
|
||||
@test "container rename" {
|
||||
podman container rm $TEST_CONTAINER_NAME || echo done
|
||||
|
||||
podman container create --name $TEST_CONTAINER_NAME httpd
|
||||
container_index=$(podman container ls --all --format "{{ .Names }}" | sort | nl -v 0 | grep "$TEST_CONTAINER_NAME" | awk '{print $1}')
|
||||
|
||||
# switch to containers view
|
||||
# select test container from list
|
||||
# select rename command from container commands dialog
|
||||
podman_tui_set_view "containers"
|
||||
podman_tui_select_item 0
|
||||
podman_tui_select_item $container_index
|
||||
podman_tui_select_container_cmd "rename"
|
||||
podman_tui_send_inputs ${TEST_CONTAINER_NAME}_renamed
|
||||
podman_tui_send_inputs "Tab" "Tab" "Enter"
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
TEST_IMAGE_TAG_NAME="podman_tui_busybox_tag01"
|
||||
TEST_NAME="ptui_test"
|
||||
TEST_VOLUME_NAME="${TEST_NAME}_vol01"
|
||||
TEST_NETWORK_NAME="zz_${TEST_NAME}_net01"
|
||||
TEST_NETWORK_CONNECT="zz_${TEST_NAME}_net0_connect"
|
||||
TEST_NETWORK_CONNECT_ALIAS="zz_${TEST_NAME}_net0_connect_alias"
|
||||
TEST_NETWORK_NAME="${TEST_NAME}_net01"
|
||||
TEST_NETWORK_CONNECT="net_connect_${TEST_NAME}"
|
||||
TEST_NETWORK_CONNECT_ALIAS="net_connect_alias"
|
||||
TEST_POD_NAME="${TEST_NAME}_pod01"
|
||||
TEST_POD_NETWORK_NAME="${TEST_NAME}_pod01_net"
|
||||
TEST_CONTAINER_NAME="${TEST_NAME}_cnt01"
|
||||
|
@ -15,7 +15,7 @@ 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_POD_NAME}"
|
||||
TEST_CONTAINER_POD_NAME="${TEST_NAME}_cnt01_pod"
|
||||
TEST_CONTAINER_NETWORK_NAME="${TEST_NAME}_cnt01_net"
|
||||
TEST_CONTAINER_VOLUME_NAME="${TEST_NAME}_cnt01_vol"
|
||||
TEST_CONTAINER_VOLUME_MOUNT_POINT="/data_mount01"
|
||||
|
|
|
@ -35,7 +35,6 @@ const (
|
|||
// ContainerCheckpointDialog implements container checkpoint dialog primitive.
|
||||
type ContainerCheckpointDialog struct {
|
||||
*tview.Box
|
||||
|
||||
layout *tview.Flex
|
||||
containerInfo *tview.InputField
|
||||
createImage *tview.InputField
|
||||
|
@ -83,7 +82,7 @@ func NewContainerCheckpointDialog() *ContainerCheckpointDialog {
|
|||
|
||||
// containerInfo
|
||||
dialog.containerInfo.SetBackgroundColor(style.DialogBgColor)
|
||||
dialog.containerInfo.SetLabel(fmt.Sprintf("[::b]%s:", utils.ContainerIDLabel))
|
||||
dialog.containerInfo.SetLabel("[::b]CONTAINER ID:")
|
||||
dialog.containerInfo.SetLabelWidth(labelWidth)
|
||||
dialog.containerInfo.SetFieldBackgroundColor(style.DialogBgColor)
|
||||
dialog.containerInfo.SetLabelStyle(tcell.StyleDefault.
|
||||
|
@ -454,9 +453,9 @@ func (d *ContainerCheckpointDialog) Draw(screen tcell.Screen) {
|
|||
return
|
||||
}
|
||||
|
||||
d.DrawForSubclass(screen, d)
|
||||
d.Box.DrawForSubclass(screen, d)
|
||||
|
||||
x, y, width, height := d.GetInnerRect()
|
||||
x, y, width, height := d.Box.GetInnerRect()
|
||||
|
||||
d.layout.SetRect(x, y, width, height)
|
||||
d.layout.Draw(screen)
|
||||
|
@ -482,6 +481,31 @@ func (d *ContainerCheckpointDialog) SetCancelFunc(handler func()) *ContainerChec
|
|||
return d
|
||||
}
|
||||
|
||||
func (d *ContainerCheckpointDialog) setFocusElement() { //nolint:cyclop
|
||||
switch d.focusElement {
|
||||
case cntCheckpointImageFocus:
|
||||
d.focusElement = cntCheckpointExportFocus
|
||||
case cntCheckpointExportFocus:
|
||||
d.focusElement = cntCheckpointFileLockFocus
|
||||
case cntCheckpointFileLockFocus:
|
||||
d.focusElement = cntCheckpointIgnoreRootFsFocus
|
||||
case cntCheckpointIgnoreRootFsFocus:
|
||||
d.focusElement = cntCheckpointTCPEstablishedFocus
|
||||
case cntCheckpointTCPEstablishedFocus:
|
||||
d.focusElement = cntCheckpointPreCheckpointFocus
|
||||
case cntCheckpointPreCheckpointFocus:
|
||||
d.focusElement = cntCheckpointPrintStatsFocus
|
||||
case cntCheckpointPrintStatsFocus:
|
||||
d.focusElement = cntCheckpointKeepFocus
|
||||
case cntCheckpointKeepFocus:
|
||||
d.focusElement = cntCheckpointLeaveRunningFocus
|
||||
case cntCheckpointLeaveRunningFocus:
|
||||
d.focusElement = cntCheckpointWithPreviousFocus
|
||||
case cntCheckpointWithPreviousFocus:
|
||||
d.focusElement = cntCheckpointFormFocus
|
||||
}
|
||||
}
|
||||
|
||||
// SetContainerInfo sets selected container ID and name information.
|
||||
func (d *ContainerCheckpointDialog) SetContainerInfo(id string, name string) {
|
||||
d.containerID = id
|
||||
|
@ -514,28 +538,3 @@ func (d *ContainerCheckpointDialog) GetCheckpointOptions() containers.CntCheckPo
|
|||
|
||||
return opts
|
||||
}
|
||||
|
||||
func (d *ContainerCheckpointDialog) setFocusElement() { //nolint:cyclop
|
||||
switch d.focusElement {
|
||||
case cntCheckpointImageFocus:
|
||||
d.focusElement = cntCheckpointExportFocus
|
||||
case cntCheckpointExportFocus:
|
||||
d.focusElement = cntCheckpointFileLockFocus
|
||||
case cntCheckpointFileLockFocus:
|
||||
d.focusElement = cntCheckpointIgnoreRootFsFocus
|
||||
case cntCheckpointIgnoreRootFsFocus:
|
||||
d.focusElement = cntCheckpointTCPEstablishedFocus
|
||||
case cntCheckpointTCPEstablishedFocus:
|
||||
d.focusElement = cntCheckpointPreCheckpointFocus
|
||||
case cntCheckpointPreCheckpointFocus:
|
||||
d.focusElement = cntCheckpointPrintStatsFocus
|
||||
case cntCheckpointPrintStatsFocus:
|
||||
d.focusElement = cntCheckpointKeepFocus
|
||||
case cntCheckpointKeepFocus:
|
||||
d.focusElement = cntCheckpointLeaveRunningFocus
|
||||
case cntCheckpointLeaveRunningFocus:
|
||||
d.focusElement = cntCheckpointWithPreviousFocus
|
||||
case cntCheckpointWithPreviousFocus:
|
||||
d.focusElement = cntCheckpointFormFocus
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,7 +33,6 @@ const (
|
|||
// ContainerCommitDialog represents container commit dialog primitive.
|
||||
type ContainerCommitDialog struct {
|
||||
*tview.Box
|
||||
|
||||
layout *tview.Flex
|
||||
cntInfo *tview.InputField
|
||||
image *tview.InputField
|
||||
|
@ -72,9 +71,11 @@ func NewContainerCommitDialog() *ContainerCommitDialog {
|
|||
labelWidth := 9
|
||||
|
||||
// container info input field
|
||||
cntInfoLabel := "CONTAINER ID:" //nolint:goconst
|
||||
|
||||
dialog.cntInfo.SetBackgroundColor(style.DialogBgColor)
|
||||
dialog.cntInfo.SetLabel("[::b]" + utils.ContainerIDLabel)
|
||||
dialog.cntInfo.SetLabelWidth(len(utils.ContainerIDLabel) + 1)
|
||||
dialog.cntInfo.SetLabel("[::b]" + cntInfoLabel)
|
||||
dialog.cntInfo.SetLabelWidth(len(cntInfoLabel) + 1)
|
||||
dialog.cntInfo.SetFieldBackgroundColor(style.DialogBgColor)
|
||||
dialog.cntInfo.SetLabelStyle(tcell.StyleDefault.
|
||||
Background(style.DialogBorderColor).
|
||||
|
@ -365,6 +366,25 @@ func (d *ContainerCommitDialog) InputHandler() func(event *tcell.EventKey, setFo
|
|||
})
|
||||
}
|
||||
|
||||
func (d *ContainerCommitDialog) setFocusElement() {
|
||||
switch d.focusElement {
|
||||
case cntCommitImageFocus:
|
||||
d.focusElement = cntCommitAuthorFocus
|
||||
case cntCommitAuthorFocus:
|
||||
d.focusElement = cntCommitChangeFocus
|
||||
case cntCommitChangeFocus:
|
||||
d.focusElement = cntCommitFormatFocus
|
||||
case cntCommitFormatFocus:
|
||||
d.focusElement = cntCommitSquashFocus
|
||||
case cntCommitSquashFocus:
|
||||
d.focusElement = cntCommitPauseFocus
|
||||
case cntCommitPauseFocus:
|
||||
d.focusElement = cntCommitMessageFocus
|
||||
case cntCommitMessageFocus:
|
||||
d.focusElement = cntCommitFormFocus
|
||||
}
|
||||
}
|
||||
|
||||
// SetRect set rects for this primitive.
|
||||
func (d *ContainerCommitDialog) SetRect(x, y, width, height int) {
|
||||
if width > cntCommitDialogMaxWidth {
|
||||
|
@ -388,9 +408,9 @@ func (d *ContainerCommitDialog) Draw(screen tcell.Screen) {
|
|||
return
|
||||
}
|
||||
|
||||
d.DrawForSubclass(screen, d)
|
||||
d.Box.DrawForSubclass(screen, d)
|
||||
|
||||
x, y, width, height := d.GetInnerRect()
|
||||
x, y, width, height := d.Box.GetInnerRect()
|
||||
|
||||
d.layout.SetRect(x, y, width, height)
|
||||
d.layout.Draw(screen)
|
||||
|
@ -445,22 +465,3 @@ func (d *ContainerCommitDialog) GetContainerCommitOptions() containers.CntCommit
|
|||
|
||||
return opts
|
||||
}
|
||||
|
||||
func (d *ContainerCommitDialog) setFocusElement() {
|
||||
switch d.focusElement {
|
||||
case cntCommitImageFocus:
|
||||
d.focusElement = cntCommitAuthorFocus
|
||||
case cntCommitAuthorFocus:
|
||||
d.focusElement = cntCommitChangeFocus
|
||||
case cntCommitChangeFocus:
|
||||
d.focusElement = cntCommitFormatFocus
|
||||
case cntCommitFormatFocus:
|
||||
d.focusElement = cntCommitSquashFocus
|
||||
case cntCommitSquashFocus:
|
||||
d.focusElement = cntCommitPauseFocus
|
||||
case cntCommitPauseFocus:
|
||||
d.focusElement = cntCommitMessageFocus
|
||||
case cntCommitMessageFocus:
|
||||
d.focusElement = cntCommitFormFocus
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -90,8 +90,6 @@ var _ = Describe("container create", Ordered, func() {
|
|||
createAction = createWants
|
||||
}
|
||||
createDialog.SetHandlerFunc(createFunc)
|
||||
createDialog.Hide()
|
||||
createDialog.Display()
|
||||
createDialog.focusElement = createContainerFormFocus
|
||||
createDialogApp.SetFocus(createDialog)
|
||||
createDialogApp.Draw()
|
||||
|
|
|
@ -36,7 +36,6 @@ const (
|
|||
// ContainerExecDialog represents container exec dialog primitive.
|
||||
type ContainerExecDialog struct {
|
||||
*tview.Box
|
||||
|
||||
layout *tview.Flex
|
||||
cntInfo *tview.InputField
|
||||
command *tview.InputField
|
||||
|
@ -78,9 +77,11 @@ func NewContainerExecDialog() *ContainerExecDialog {
|
|||
inputFieldBgColor := style.InputFieldBgColor
|
||||
|
||||
// label (container ID and Name)
|
||||
cntInfoLabel := "CONTAINER ID:"
|
||||
|
||||
dialog.cntInfo.SetBackgroundColor(style.DialogBgColor)
|
||||
dialog.cntInfo.SetLabel("[::b]" + utils.ContainerIDLabel)
|
||||
dialog.cntInfo.SetLabelWidth(len(utils.ContainerIDLabel) + 1)
|
||||
dialog.cntInfo.SetLabel("[::b]" + cntInfoLabel)
|
||||
dialog.cntInfo.SetLabelWidth(len(cntInfoLabel) + 1)
|
||||
dialog.cntInfo.SetFieldBackgroundColor(style.DialogBgColor)
|
||||
dialog.cntInfo.SetLabelStyle(tcell.StyleDefault.
|
||||
Background(style.DialogBorderColor).
|
||||
|
@ -605,9 +606,9 @@ func (d *ContainerExecDialog) Draw(screen tcell.Screen) {
|
|||
return
|
||||
}
|
||||
|
||||
d.DrawForSubclass(screen, d)
|
||||
d.Box.DrawForSubclass(screen, d)
|
||||
|
||||
x, y, width, height := d.GetInnerRect()
|
||||
x, y, width, height := d.Box.GetInnerRect()
|
||||
|
||||
d.layout.SetRect(x, y, width, height)
|
||||
|
||||
|
|
|
@ -48,7 +48,6 @@ const (
|
|||
// ContainerRestoreDialog implements container restore dialog primitive.
|
||||
type ContainerRestoreDialog struct {
|
||||
*tview.Box
|
||||
|
||||
layout *tview.Flex
|
||||
containers *tview.DropDown
|
||||
pods *tview.DropDown
|
||||
|
@ -435,9 +434,9 @@ func (d *ContainerRestoreDialog) Draw(screen tcell.Screen) {
|
|||
return
|
||||
}
|
||||
|
||||
d.DrawForSubclass(screen, d)
|
||||
d.Box.DrawForSubclass(screen, d)
|
||||
|
||||
x, y, width, height := d.GetInnerRect()
|
||||
x, y, width, height := d.Box.GetInnerRect()
|
||||
|
||||
d.layout.SetRect(x, y, width, height)
|
||||
d.layout.Draw(screen)
|
||||
|
@ -463,6 +462,36 @@ func (d *ContainerRestoreDialog) SetCancelFunc(handler func()) *ContainerRestore
|
|||
return d
|
||||
}
|
||||
|
||||
func (d *ContainerRestoreDialog) setFocusElement() {
|
||||
if d.focusElement < cntRestoreFormFocus {
|
||||
d.focusElement++
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
d.focusElement = cntRestoreContainersFocus
|
||||
}
|
||||
|
||||
func (d *ContainerRestoreDialog) getInnerPrimitives() []tview.Primitive {
|
||||
// the item sort is important to be same as focus element number
|
||||
return []tview.Primitive{
|
||||
d.containers,
|
||||
d.pods,
|
||||
d.name,
|
||||
d.publishPorts,
|
||||
d.importArchive,
|
||||
d.keep,
|
||||
d.ignoreStaticIP,
|
||||
d.ignoreStaticMAC,
|
||||
d.fileLocks,
|
||||
d.printStats,
|
||||
d.tcpEstablished,
|
||||
d.ignoreVolumes,
|
||||
d.ignoreRootFS,
|
||||
d.form,
|
||||
}
|
||||
}
|
||||
|
||||
// SetContainers sets containers dropdown options.
|
||||
func (d *ContainerRestoreDialog) SetContainers(cnts [][]string) {
|
||||
emptyOptions := fmt.Sprintf("%*s", cntRestoreDialogSingleFieldWidth, " ")
|
||||
|
@ -527,33 +556,3 @@ func (d *ContainerRestoreDialog) GetRestoreOptions() containers.CntRestoreOption
|
|||
|
||||
return opts
|
||||
}
|
||||
|
||||
func (d *ContainerRestoreDialog) setFocusElement() {
|
||||
if d.focusElement < cntRestoreFormFocus {
|
||||
d.focusElement++
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
d.focusElement = cntRestoreContainersFocus
|
||||
}
|
||||
|
||||
func (d *ContainerRestoreDialog) getInnerPrimitives() []tview.Primitive {
|
||||
// the item sort is important to be same as focus element number
|
||||
return []tview.Primitive{
|
||||
d.containers,
|
||||
d.pods,
|
||||
d.name,
|
||||
d.publishPorts,
|
||||
d.importArchive,
|
||||
d.keep,
|
||||
d.ignoreStaticIP,
|
||||
d.ignoreStaticMAC,
|
||||
d.fileLocks,
|
||||
d.printStats,
|
||||
d.tcpEstablished,
|
||||
d.ignoreVolumes,
|
||||
d.ignoreRootFS,
|
||||
d.form,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,6 @@ import (
|
|||
// ContainerStatsDialog implements the containers stats dialog primitive.
|
||||
type ContainerStatsDialog struct {
|
||||
*tview.Box
|
||||
|
||||
layout *tview.Flex
|
||||
form *tview.Form
|
||||
table *tview.Table
|
||||
|
@ -49,9 +48,11 @@ func NewContainerStatsDialog() *ContainerStatsDialog {
|
|||
statsDialog.initTableUI()
|
||||
|
||||
// container info text view
|
||||
cntInfoLabel := "CONTAINER ID:"
|
||||
|
||||
statsDialog.containerInfo.SetBackgroundColor(style.DialogBgColor)
|
||||
statsDialog.containerInfo.SetLabel("[::b]" + utils.ContainerIDLabel)
|
||||
statsDialog.containerInfo.SetLabelWidth(len(utils.ContainerIDLabel) + 1)
|
||||
statsDialog.containerInfo.SetLabel("[::b]" + cntInfoLabel)
|
||||
statsDialog.containerInfo.SetLabelWidth(len(cntInfoLabel) + 1)
|
||||
statsDialog.containerInfo.SetFieldBackgroundColor(style.DialogBgColor)
|
||||
statsDialog.containerInfo.SetLabelStyle(tcell.StyleDefault.
|
||||
Background(style.DialogBorderColor).
|
||||
|
@ -120,9 +121,7 @@ func (d *ContainerStatsDialog) Hide() {
|
|||
d.setContainerBlockOutput(0)
|
||||
d.setContainerNetInput(0)
|
||||
d.setContainerNetOutput(0)
|
||||
|
||||
d.mu.Lock()
|
||||
|
||||
defer d.mu.Unlock()
|
||||
|
||||
*d.statsStream = false
|
||||
|
@ -169,8 +168,8 @@ func (d *ContainerStatsDialog) Draw(screen tcell.Screen) {
|
|||
return
|
||||
}
|
||||
|
||||
d.DrawForSubclass(screen, d)
|
||||
x, y, width, height := d.GetInnerRect()
|
||||
d.Box.DrawForSubclass(screen, d)
|
||||
x, y, width, height := d.Box.GetInnerRect()
|
||||
d.layout.SetRect(x, y, width, height)
|
||||
d.layout.Draw(screen)
|
||||
}
|
||||
|
|
|
@ -49,9 +49,7 @@ func (w *writer) Write(b []byte) (int, error) {
|
|||
}
|
||||
|
||||
buf := make([]byte, len(b))
|
||||
|
||||
copy(buf, b)
|
||||
|
||||
w.ch <- buf
|
||||
|
||||
return len(b), nil
|
||||
|
|
|
@ -32,9 +32,8 @@ const (
|
|||
|
||||
// VtermDialog implements virtual terminal that can be used during
|
||||
// exec, attach, run activity.
|
||||
type VtermDialog struct {
|
||||
type VtermDialog struct { //nolint:revive
|
||||
*tview.Box
|
||||
|
||||
layout *tview.Flex
|
||||
form *tview.Form
|
||||
containerInfo *tview.InputField
|
||||
|
@ -87,6 +86,73 @@ func NewVtermDialog() *VtermDialog {
|
|||
return dialog
|
||||
}
|
||||
|
||||
func (d *VtermDialog) initLayoutUI() {
|
||||
bgColor := style.DialogBgColor
|
||||
borderColor := style.DialogBorderColor
|
||||
terminalBgColor := style.TerminalBgColor
|
||||
terminalBorderColor := style.TerminalBorderColor
|
||||
|
||||
// container information field
|
||||
// label
|
||||
cntInfoLabel := "CONTAINER ID:"
|
||||
|
||||
d.containerInfo.SetBackgroundColor(bgColor)
|
||||
d.containerInfo.SetLabel("[::b]" + cntInfoLabel)
|
||||
d.containerInfo.SetLabelWidth(len(cntInfoLabel) + 1)
|
||||
d.containerInfo.SetFieldBackgroundColor(bgColor)
|
||||
d.containerInfo.SetLabelStyle(tcell.StyleDefault.
|
||||
Background(borderColor).
|
||||
Foreground(style.DialogFgColor))
|
||||
|
||||
// form fields
|
||||
d.form.AddButton("Cancel", nil).
|
||||
SetButtonsAlign(tview.AlignRight)
|
||||
d.form.SetBackgroundColor(bgColor)
|
||||
d.form.SetButtonBackgroundColor(style.ButtonBgColor)
|
||||
|
||||
// terminal screen
|
||||
d.termScreen.SetBackgroundColor(terminalBgColor)
|
||||
d.termScreen.SetBorder(true)
|
||||
d.termScreen.SetBorderColor(terminalBorderColor)
|
||||
|
||||
// layout setup
|
||||
layout := tview.NewFlex().SetDirection(tview.FlexRow)
|
||||
termLayout := tview.NewFlex().SetDirection(tview.FlexColumn)
|
||||
|
||||
layout.SetBackgroundColor(bgColor)
|
||||
layout.SetBorder(false)
|
||||
layout.AddItem(d.containerInfo, 1, 0, true)
|
||||
// layout.AddItem(utils.EmptyBoxSpace(bgColor), 1, 0, true)
|
||||
layout.AddItem(d.termScreen, 0, 1, true)
|
||||
|
||||
termLayout.SetBackgroundColor(bgColor)
|
||||
termLayout.SetBorder(false)
|
||||
termLayout.AddItem(utils.EmptyBoxSpace(bgColor), 1, 0, false)
|
||||
termLayout.AddItem(layout, 0, 1, false)
|
||||
termLayout.AddItem(utils.EmptyBoxSpace(bgColor), 1, 0, false)
|
||||
|
||||
// main layout
|
||||
d.layout.SetDirection(tview.FlexRow)
|
||||
d.layout.SetBorder(true)
|
||||
d.layout.SetBorderColor(borderColor)
|
||||
d.layout.SetBackgroundColor(bgColor)
|
||||
// d.layout.SetTitle("CONTAINER TERMINAL")
|
||||
|
||||
d.layout.AddItem(termLayout, 0, 1, true)
|
||||
d.layout.AddItem(d.form, dialogs.DialogFormHeight, 0, true)
|
||||
}
|
||||
|
||||
func (d *VtermDialog) initChannelsCommon() {
|
||||
d.sessionOutputDoneChan = make(chan bool, 2) //nolint:mnd
|
||||
d.vtTerminal = vt10x.New()
|
||||
sessionStdinPipeIn, sessionStdinPipeOut := io.Pipe()
|
||||
d.sessionStdin = bufio.NewReader(sessionStdinPipeIn)
|
||||
d.sessionStdinWriter = bufio.NewWriter(sessionStdinPipeOut)
|
||||
|
||||
d.vtTermPipeReader, d.vtTermPipeWriter = io.Pipe()
|
||||
d.vtTermBuffer = bufio.NewReader(d.vtTermPipeReader)
|
||||
}
|
||||
|
||||
// InitChannels will init buffers and channels for attach.
|
||||
func (d *VtermDialog) InitAttachChannels() (io.Reader, io.Writer) {
|
||||
log.Debug().Msg("view: container terminal dialog init channels (attach)")
|
||||
|
@ -128,10 +194,9 @@ func (d *VtermDialog) Display() {
|
|||
return
|
||||
}
|
||||
|
||||
switch d.sessionMode {
|
||||
case sessionModeAttach:
|
||||
if d.sessionMode == sessionModeAttach {
|
||||
go d.sessionOutputStreamer()
|
||||
case sessionModeExec:
|
||||
} else if d.sessionMode == sessionModeExec {
|
||||
go d.execSessionOutputStreamer()
|
||||
}
|
||||
|
||||
|
@ -184,21 +249,11 @@ func (d *VtermDialog) Hide() {
|
|||
}
|
||||
|
||||
if d.sessionMode == sessionModeExec {
|
||||
err := d.execSessionStdout.Close()
|
||||
if err != nil {
|
||||
log.Error().Msgf("failed to close vterm exec stdout session: %s", err.Error())
|
||||
}
|
||||
d.execSessionStdout.Close()
|
||||
}
|
||||
|
||||
err := d.vtTermPipeReader.Close()
|
||||
if err != nil {
|
||||
log.Error().Msgf("failed to close vterm pipe reader: %s", err.Error())
|
||||
}
|
||||
|
||||
err = d.vtTermPipeWriter.Close()
|
||||
if err != nil {
|
||||
log.Error().Msgf("failed to close vterm pipe writer: %s", err.Error())
|
||||
}
|
||||
d.vtTermPipeReader.Close()
|
||||
d.vtTermPipeWriter.Close()
|
||||
}
|
||||
|
||||
// HasFocus returns true if terminal dialog has focus.
|
||||
|
@ -299,8 +354,8 @@ func (d *VtermDialog) Draw(screen tcell.Screen) {
|
|||
return
|
||||
}
|
||||
|
||||
d.DrawForSubclass(screen, d)
|
||||
x, y, width, height := d.GetInnerRect()
|
||||
d.Box.DrawForSubclass(screen, d)
|
||||
x, y, width, height := d.Box.GetInnerRect()
|
||||
d.layout.SetRect(x, y, width, height)
|
||||
d.layout.Draw(screen)
|
||||
|
||||
|
@ -335,6 +390,23 @@ func (d *VtermDialog) Draw(screen tcell.Screen) {
|
|||
}
|
||||
}
|
||||
|
||||
func (d *VtermDialog) setTTYSize(width int, height int) {
|
||||
if width < 0 || height < 0 {
|
||||
return
|
||||
}
|
||||
|
||||
d.ttyWidth = width
|
||||
d.ttyHeight = height
|
||||
|
||||
d.vtTerminal.Resize(width, height)
|
||||
|
||||
if d.sessionMode == sessionModeAttach {
|
||||
go containers.ResizeContainerTTY(d.containerID, width, height) //nolint:errcheck
|
||||
} else if d.sessionMode == sessionModeExec {
|
||||
go containers.ResizeExecTty(d.sessionID, d.ttyHeight, d.ttyWidth)
|
||||
}
|
||||
}
|
||||
|
||||
// SetCancelFunc sets form close button selected function.
|
||||
func (d *VtermDialog) SetCancelFunc(handler func()) *VtermDialog {
|
||||
d.cancelHandler = handler
|
||||
|
@ -382,31 +454,28 @@ func (d *VtermDialog) SetFastRefreshHandler(handler func()) {
|
|||
func (d *VtermDialog) writeToSession(event *tcell.EventKey) {
|
||||
switch event.Key() { //nolint:exhaustive
|
||||
case tcell.KeyUp:
|
||||
d.writeToStdinSessionWriter(rune(27)) //nolint:mnd
|
||||
d.writeToStdinSessionWriter(rune(91)) //nolint:mnd
|
||||
d.writeToStdinSessionWriter(rune(65)) //nolint:mnd
|
||||
d.sessionStdinWriter.WriteRune(rune(27)) //nolint:errcheck,mnd
|
||||
d.sessionStdinWriter.WriteRune(rune(91)) //nolint:errcheck,mnd
|
||||
d.sessionStdinWriter.WriteRune(rune(65)) //nolint:errcheck,mnd
|
||||
case tcell.KeyDown:
|
||||
d.writeToStdinSessionWriter(rune(27)) //nolint:mnd
|
||||
d.writeToStdinSessionWriter(rune(91)) //nolint:mnd
|
||||
d.writeToStdinSessionWriter(rune(66)) //nolint:mnd
|
||||
d.sessionStdinWriter.WriteRune(rune(27)) //nolint:errcheck,mnd
|
||||
d.sessionStdinWriter.WriteRune(rune(91)) //nolint:errcheck,mnd
|
||||
d.sessionStdinWriter.WriteRune(rune(66)) //nolint:errcheck,mnd
|
||||
case tcell.KeyRight:
|
||||
d.writeToStdinSessionWriter(rune(27)) //nolint:mnd
|
||||
d.writeToStdinSessionWriter(rune(91)) //nolint:mnd
|
||||
d.writeToStdinSessionWriter(rune(67)) //nolint:mnd
|
||||
d.sessionStdinWriter.WriteRune(rune(27)) //nolint:errcheck,mnd
|
||||
d.sessionStdinWriter.WriteRune(rune(91)) //nolint:errcheck,mnd
|
||||
d.sessionStdinWriter.WriteRune(rune(67)) //nolint:errcheck,mnd
|
||||
case tcell.KeyLeft:
|
||||
d.writeToStdinSessionWriter(rune(27)) //nolint:mnd
|
||||
d.writeToStdinSessionWriter(rune(91)) //nolint:mnd
|
||||
d.writeToStdinSessionWriter(rune(68)) //nolint:mnd
|
||||
d.sessionStdinWriter.WriteRune(rune(27)) //nolint:errcheck,mnd
|
||||
d.sessionStdinWriter.WriteRune(rune(91)) //nolint:errcheck,mnd
|
||||
d.sessionStdinWriter.WriteRune(rune(68)) //nolint:errcheck,mnd
|
||||
case tcell.KeyEsc:
|
||||
d.writeToStdinSessionWriter(rune(27)) //nolint:mnd
|
||||
d.sessionStdinWriter.WriteRune(rune(27)) //nolint:errcheck,mnd
|
||||
default:
|
||||
d.writeToStdinSessionWriter(event.Rune())
|
||||
d.sessionStdinWriter.WriteRune(event.Rune()) //nolint:errcheck
|
||||
}
|
||||
|
||||
err := d.sessionStdinWriter.Flush()
|
||||
if err != nil {
|
||||
log.Error().Msgf("failed to flush vterm stdin writer session: %s", err.Error())
|
||||
}
|
||||
d.sessionStdinWriter.Flush()
|
||||
}
|
||||
|
||||
func (d *VtermDialog) sendDetachToSession() {
|
||||
|
@ -415,13 +484,10 @@ func (d *VtermDialog) sendDetachToSession() {
|
|||
keys := d.detachKeys.keys()
|
||||
|
||||
for i := range keys {
|
||||
d.writeToStdinSessionWriter(rune(keys[i]))
|
||||
d.sessionStdinWriter.WriteRune(rune(keys[i])) //nolint:errcheck
|
||||
}
|
||||
|
||||
err := d.sessionStdinWriter.Flush()
|
||||
if err != nil {
|
||||
log.Error().Msgf("failed to flush vterm stdin writer session: %s", err.Error())
|
||||
}
|
||||
d.sessionStdinWriter.Flush()
|
||||
}
|
||||
|
||||
// vtContent returns current content and cursor location of vt10x terminal.
|
||||
|
@ -464,11 +530,7 @@ func (d *VtermDialog) execSessionOutputStreamer() {
|
|||
|
||||
return
|
||||
case data := <-d.execSessionStdout.Chan():
|
||||
_, err := d.vtTermPipeWriter.Write(data)
|
||||
if err != nil {
|
||||
log.Error().Msgf("failed to write %s to vterm pipe writer: %s", data, err.Error())
|
||||
}
|
||||
|
||||
d.vtTermPipeWriter.Write(data) //nolint:errcheck
|
||||
d.fastRefreshHandler()
|
||||
}
|
||||
}
|
||||
|
@ -487,11 +549,7 @@ func (d *VtermDialog) sessionOutputStreamer() {
|
|||
dataString := string(data)
|
||||
dataString = strings.ReplaceAll(dataString, "\n", "\r\n")
|
||||
|
||||
_, err := d.vtTermPipeWriter.Write([]byte(dataString))
|
||||
if err != nil {
|
||||
log.Error().Msgf("failed to write %s to vterm pipe writer: %s", []byte(dataString), err.Error())
|
||||
}
|
||||
|
||||
d.vtTermPipeWriter.Write([]byte(dataString)) //nolint:errcheck
|
||||
d.fastRefreshHandler()
|
||||
}
|
||||
}
|
||||
|
@ -509,93 +567,3 @@ func (dkey termDetachKeys) string() string {
|
|||
func (dkey termDetachKeys) keys() []tcell.Key {
|
||||
return dkey.tcellKeys
|
||||
}
|
||||
|
||||
func (d *VtermDialog) initLayoutUI() {
|
||||
bgColor := style.DialogBgColor
|
||||
borderColor := style.DialogBorderColor
|
||||
terminalBgColor := style.TerminalBgColor
|
||||
terminalBorderColor := style.TerminalBorderColor
|
||||
|
||||
// container information field
|
||||
// label
|
||||
d.containerInfo.SetBackgroundColor(bgColor)
|
||||
d.containerInfo.SetLabel("[::b]" + utils.ContainerIDLabel)
|
||||
d.containerInfo.SetLabelWidth(len(utils.ContainerIDLabel) + 1)
|
||||
d.containerInfo.SetFieldBackgroundColor(bgColor)
|
||||
d.containerInfo.SetLabelStyle(tcell.StyleDefault.
|
||||
Background(borderColor).
|
||||
Foreground(style.DialogFgColor))
|
||||
|
||||
// form fields
|
||||
d.form.AddButton("Cancel", nil).
|
||||
SetButtonsAlign(tview.AlignRight)
|
||||
d.form.SetBackgroundColor(bgColor)
|
||||
d.form.SetButtonBackgroundColor(style.ButtonBgColor)
|
||||
|
||||
// terminal screen
|
||||
d.termScreen.SetBackgroundColor(terminalBgColor)
|
||||
d.termScreen.SetBorder(true)
|
||||
d.termScreen.SetBorderColor(terminalBorderColor)
|
||||
|
||||
// layout setup
|
||||
layout := tview.NewFlex().SetDirection(tview.FlexRow)
|
||||
termLayout := tview.NewFlex().SetDirection(tview.FlexColumn)
|
||||
|
||||
layout.SetBackgroundColor(bgColor)
|
||||
layout.SetBorder(false)
|
||||
layout.AddItem(d.containerInfo, 1, 0, true)
|
||||
// layout.AddItem(utils.EmptyBoxSpace(bgColor), 1, 0, true)
|
||||
layout.AddItem(d.termScreen, 0, 1, true)
|
||||
|
||||
termLayout.SetBackgroundColor(bgColor)
|
||||
termLayout.SetBorder(false)
|
||||
termLayout.AddItem(utils.EmptyBoxSpace(bgColor), 1, 0, false)
|
||||
termLayout.AddItem(layout, 0, 1, false)
|
||||
termLayout.AddItem(utils.EmptyBoxSpace(bgColor), 1, 0, false)
|
||||
|
||||
// main layout
|
||||
d.layout.SetDirection(tview.FlexRow)
|
||||
d.layout.SetBorder(true)
|
||||
d.layout.SetBorderColor(borderColor)
|
||||
d.layout.SetBackgroundColor(bgColor)
|
||||
// d.layout.SetTitle("CONTAINER TERMINAL")
|
||||
|
||||
d.layout.AddItem(termLayout, 0, 1, true)
|
||||
d.layout.AddItem(d.form, dialogs.DialogFormHeight, 0, true)
|
||||
}
|
||||
|
||||
func (d *VtermDialog) initChannelsCommon() {
|
||||
d.sessionOutputDoneChan = make(chan bool, 2) //nolint:mnd
|
||||
d.vtTerminal = vt10x.New()
|
||||
sessionStdinPipeIn, sessionStdinPipeOut := io.Pipe()
|
||||
d.sessionStdin = bufio.NewReader(sessionStdinPipeIn)
|
||||
d.sessionStdinWriter = bufio.NewWriter(sessionStdinPipeOut)
|
||||
|
||||
d.vtTermPipeReader, d.vtTermPipeWriter = io.Pipe()
|
||||
d.vtTermBuffer = bufio.NewReader(d.vtTermPipeReader)
|
||||
}
|
||||
|
||||
func (d *VtermDialog) setTTYSize(width int, height int) {
|
||||
if width < 0 || height < 0 {
|
||||
return
|
||||
}
|
||||
|
||||
d.ttyWidth = width
|
||||
d.ttyHeight = height
|
||||
|
||||
d.vtTerminal.Resize(width, height)
|
||||
|
||||
switch d.sessionMode {
|
||||
case sessionModeAttach:
|
||||
go containers.ResizeContainerTTY(d.containerID, width, height) //nolint:errcheck
|
||||
case sessionModeExec:
|
||||
go containers.ResizeExecTty(d.sessionID, d.ttyHeight, d.ttyWidth)
|
||||
}
|
||||
}
|
||||
|
||||
func (d *VtermDialog) writeToStdinSessionWriter(val rune) {
|
||||
_, err := d.sessionStdinWriter.WriteRune(val)
|
||||
if err != nil {
|
||||
log.Error().Msgf("failed to write value %d to vterm session writer rune: %s", val, err.Error())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,6 @@ import (
|
|||
"github.com/containers/podman-tui/pdcs/pods"
|
||||
"github.com/containers/podman-tui/ui/dialogs"
|
||||
"github.com/containers/podman-tui/ui/style"
|
||||
"github.com/containers/podman-tui/ui/utils"
|
||||
bcontainers "github.com/containers/podman/v5/pkg/bindings/containers"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
@ -37,7 +36,7 @@ func (cnt *Containers) runCommand(cmd string) { //nolint:cyclop
|
|||
cnt.logs()
|
||||
case "pause":
|
||||
cnt.pause()
|
||||
case utils.PruneCommandLabel:
|
||||
case "prune": //nolint:goconst
|
||||
cnt.cprune()
|
||||
case "rename":
|
||||
cnt.rename()
|
||||
|
@ -334,7 +333,7 @@ func (cnt *Containers) stats() {
|
|||
}
|
||||
|
||||
if cntStatus != "running" {
|
||||
cnt.displayError("", fmt.Errorf("container (%s) status improper", cntID)) //nolint:err113
|
||||
cnt.displayError("", fmt.Errorf("container (%s) status improper", cntID)) //nolint:goerr113
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -451,8 +450,7 @@ func (cnt *Containers) runDetach(runOpts containers.CreateOptions) {
|
|||
return
|
||||
}
|
||||
|
||||
err = containers.Start(cntID)
|
||||
if err != nil {
|
||||
if err := containers.Start(cntID); err != nil {
|
||||
cnt.progressDialog.Hide()
|
||||
cnt.displayError("CONTAINER RUN ERROR", err)
|
||||
cnt.appFocusHandler()
|
||||
|
@ -527,8 +525,7 @@ func (cnt *Containers) runAttach(runOpts containers.CreateOptions) {
|
|||
cnt.progressDialog.Hide()
|
||||
|
||||
if isReady {
|
||||
err := containers.Start(cntID)
|
||||
if err != nil {
|
||||
if err := containers.Start(cntID); err != nil {
|
||||
cnt.displayError("CONTAINER RUN ERROR", err)
|
||||
cnt.appFocusHandler()
|
||||
|
||||
|
@ -771,7 +768,7 @@ func (cnt *Containers) prune() {
|
|||
}
|
||||
|
||||
if len(errData) > 0 {
|
||||
cnt.displayError("CONTAINER PRUNE ERROR", fmt.Errorf("%v", errData)) //nolint:err113
|
||||
cnt.displayError("CONTAINER PRUNE ERROR", fmt.Errorf("%v", errData)) //nolint:goerr113
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -790,8 +787,8 @@ func (cnt *Containers) rename() {
|
|||
fgColor := style.GetColorHex(style.DialogFgColor)
|
||||
bgColor := fmt.Sprintf("#%x", style.DialogBorderColor.Hex())
|
||||
containerInfo := fmt.Sprintf("%s (%s)", cnt.selectedID, cnt.selectedName)
|
||||
description := fmt.Sprintf("[%s:%s:b]%s[:-:-] %s",
|
||||
fgColor, bgColor, utils.ContainerIDLabel, containerInfo)
|
||||
description := fmt.Sprintf("[%s:%s:b]CONTAINER ID:[:-:-] %s",
|
||||
fgColor, bgColor, containerInfo)
|
||||
|
||||
cnt.cmdInputDialog.SetDescription(description)
|
||||
cnt.cmdInputDialog.SetSelectButtonLabel("rename")
|
||||
|
@ -841,7 +838,7 @@ func (cnt *Containers) rm() {
|
|||
cnt.confirmData = "rm"
|
||||
bgColor := style.GetColorHex(style.DialogBorderColor)
|
||||
fgColor := style.GetColorHex(style.DialogFgColor)
|
||||
containerItem := fmt.Sprintf("[%s:%s:b]%s[:-:-] %s(%s)", fgColor, bgColor, utils.ContainerIDLabel, cntID, cntName)
|
||||
containerItem := fmt.Sprintf("[%s:%s:b]CONTAINER ID:[:-:-] %s(%s)", fgColor, bgColor, cntID, cntName)
|
||||
description := fmt.Sprintf("%s\n\nAre you sure you want to remove the selected container ?", //nolint:perfsprint
|
||||
containerItem)
|
||||
|
||||
|
@ -870,7 +867,7 @@ func (cnt *Containers) remove() {
|
|||
if len(errData) > 0 {
|
||||
title := fmt.Sprintf("CONTAINER (%s) REMOVE ERROR", cnt.selectedID)
|
||||
|
||||
cnt.displayError(title, fmt.Errorf("%v", errData)) //nolint:err113
|
||||
cnt.displayError(title, fmt.Errorf("%v", errData)) //nolint:goerr113
|
||||
cnt.appFocusHandler()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,6 @@ import (
|
|||
"github.com/containers/podman-tui/ui/containers/cntdialogs/vterm"
|
||||
"github.com/containers/podman-tui/ui/dialogs"
|
||||
"github.com/containers/podman-tui/ui/style"
|
||||
"github.com/containers/podman-tui/ui/utils"
|
||||
"github.com/containers/podman/v5/pkg/domain/entities"
|
||||
"github.com/rivo/tview"
|
||||
)
|
||||
|
@ -50,7 +49,6 @@ var (
|
|||
// Containers implements the containers page primitive.
|
||||
type Containers struct {
|
||||
*tview.Box
|
||||
|
||||
title string
|
||||
headers []string
|
||||
table *tview.Table
|
||||
|
@ -60,16 +58,15 @@ type Containers struct {
|
|||
confirmDialog *dialogs.ConfirmDialog
|
||||
messageDialog *dialogs.MessageDialog
|
||||
progressDialog *dialogs.ProgressDialog
|
||||
sortDialog *dialogs.SortDialog
|
||||
topDialog *dialogs.TopDialog
|
||||
createDialog *cntdialogs.ContainerCreateDialog
|
||||
runDialog *cntdialogs.ContainerCreateDialog
|
||||
execDialog *cntdialogs.ContainerExecDialog
|
||||
terminalDialog *vterm.VtermDialog
|
||||
statsDialog *cntdialogs.ContainerStatsDialog
|
||||
commitDialog *cntdialogs.ContainerCommitDialog
|
||||
checkpointDialog *cntdialogs.ContainerCheckpointDialog
|
||||
restoreDialog *cntdialogs.ContainerRestoreDialog
|
||||
terminalDialog *vterm.VtermDialog
|
||||
containersList containerListReport
|
||||
selectedID string
|
||||
selectedName string
|
||||
|
@ -79,10 +76,8 @@ type Containers struct {
|
|||
}
|
||||
|
||||
type containerListReport struct {
|
||||
mu sync.Mutex
|
||||
report []entities.ListContainer
|
||||
sortBy string
|
||||
ascending bool
|
||||
mu sync.Mutex
|
||||
report []entities.ListContainer
|
||||
}
|
||||
|
||||
// NewContainers returns containers page view.
|
||||
|
@ -97,18 +92,15 @@ func NewContainers() *Containers {
|
|||
progressDialog: dialogs.NewProgressDialog(),
|
||||
confirmDialog: dialogs.NewConfirmDialog(),
|
||||
topDialog: dialogs.NewTopDialog(),
|
||||
sortDialog: dialogs.NewSortDialog([]string{"name", "pod", "image", "created", "status"}, 3), //nolint:mnd
|
||||
createDialog: cntdialogs.NewContainerCreateDialog(cntdialogs.ContainerCreateOnlyDialogMode),
|
||||
runDialog: cntdialogs.NewContainerCreateDialog(cntdialogs.ContainerCreateAndRunDialogMode),
|
||||
execDialog: cntdialogs.NewContainerExecDialog(),
|
||||
terminalDialog: vterm.NewVtermDialog(),
|
||||
statsDialog: cntdialogs.NewContainerStatsDialog(),
|
||||
commitDialog: cntdialogs.NewContainerCommitDialog(),
|
||||
checkpointDialog: cntdialogs.NewContainerCheckpointDialog(),
|
||||
restoreDialog: cntdialogs.NewContainerRestoreDialog(),
|
||||
terminalDialog: vterm.NewVtermDialog(),
|
||||
containersList: containerListReport{sortBy: "created", ascending: true},
|
||||
}
|
||||
|
||||
containers.topDialog.SetTitle("podman container top")
|
||||
|
||||
containers.cmdDialog = dialogs.NewCommandDialog([][]string{
|
||||
|
@ -178,7 +170,7 @@ func NewContainers() *Containers {
|
|||
containers.confirmDialog.Hide()
|
||||
|
||||
switch containers.confirmData {
|
||||
case utils.PruneCommandLabel:
|
||||
case "prune":
|
||||
containers.prune()
|
||||
case "rm":
|
||||
containers.remove()
|
||||
|
@ -232,10 +224,6 @@ func NewContainers() *Containers {
|
|||
containers.restoreDialog.SetRestoreFunc(containers.restore)
|
||||
containers.restoreDialog.SetCancelFunc(containers.restoreDialog.Hide)
|
||||
|
||||
// set sort dialog functions
|
||||
containers.sortDialog.SetSelectFunc(containers.SortView)
|
||||
containers.sortDialog.SetCancelFunc(containers.sortDialog.Hide)
|
||||
|
||||
return containers
|
||||
}
|
||||
|
||||
|
@ -283,11 +271,7 @@ func (cnt *Containers) HasFocus() bool { //nolint:cyclop
|
|||
return true
|
||||
}
|
||||
|
||||
if cnt.sortDialog.HasFocus() || cnt.Box.HasFocus() {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
return cnt.Box.HasFocus()
|
||||
}
|
||||
|
||||
// SubDialogHasFocus returns whether or not sub dialog primitive has focus.
|
||||
|
@ -320,11 +304,7 @@ func (cnt *Containers) SubDialogHasFocus() bool { //nolint:cyclop
|
|||
return true
|
||||
}
|
||||
|
||||
if cnt.sortDialog.HasFocus() || cnt.runDialog.HasFocus() {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
return cnt.runDialog.HasFocus()
|
||||
}
|
||||
|
||||
// Focus is called when this primitive receives focus.
|
||||
|
@ -427,14 +407,24 @@ func (cnt *Containers) Focus(delegate func(p tview.Primitive)) { //nolint:cyclop
|
|||
return
|
||||
}
|
||||
|
||||
// sort dialog
|
||||
if cnt.sortDialog.IsDisplay() {
|
||||
delegate(cnt.sortDialog)
|
||||
delegate(cnt.table)
|
||||
}
|
||||
|
||||
return
|
||||
func (cnt *Containers) getSelectedItem() (string, string) {
|
||||
var (
|
||||
cntID string
|
||||
cntName string
|
||||
)
|
||||
|
||||
if cnt.table.GetRowCount() <= 1 {
|
||||
return cntID, cntName
|
||||
}
|
||||
|
||||
delegate(cnt.table)
|
||||
row, _ := cnt.table.GetSelection()
|
||||
cntID = cnt.table.GetCell(row, viewContainersIDColIndex).Text
|
||||
cntName = cnt.table.GetCell(row, viewContainersNamesColIndex).Text
|
||||
|
||||
return cntID, cntName
|
||||
}
|
||||
|
||||
// SetFastRefreshChannel sets channel for fastRefresh func.
|
||||
|
@ -503,25 +493,4 @@ func (cnt *Containers) HideAllDialogs() { //nolint:cyclop
|
|||
if cnt.terminalDialog.IsDisplay() {
|
||||
cnt.terminalDialog.Hide()
|
||||
}
|
||||
|
||||
if cnt.sortDialog.IsDisplay() {
|
||||
cnt.sortDialog.Hide()
|
||||
}
|
||||
}
|
||||
|
||||
func (cnt *Containers) getSelectedItem() (string, string) {
|
||||
var (
|
||||
cntID string
|
||||
cntName string
|
||||
)
|
||||
|
||||
if cnt.table.GetRowCount() <= 1 {
|
||||
return cntID, cntName
|
||||
}
|
||||
|
||||
row, _ := cnt.table.GetSelection()
|
||||
cntID = cnt.table.GetCell(row, viewContainersIDColIndex).Text
|
||||
cntName = cnt.table.GetCell(row, viewContainersNamesColIndex).Text
|
||||
|
||||
return cntID, cntName
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@ package containers
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
|
@ -15,18 +14,6 @@ import (
|
|||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
// SortView sorts data view called from sort dialog.
|
||||
func (cnt *Containers) SortView(option string, ascending bool) {
|
||||
log.Debug().Msgf("view: containers sort by %s", option)
|
||||
|
||||
cnt.containersList.mu.Lock()
|
||||
defer cnt.containersList.mu.Unlock()
|
||||
|
||||
cnt.containersList.sortBy = option
|
||||
cnt.containersList.ascending = ascending
|
||||
sort.Sort(containerListSorted{cnt.containersList.report, option, ascending})
|
||||
}
|
||||
|
||||
// UpdateData retrieves containers list data.
|
||||
func (cnt *Containers) UpdateData() {
|
||||
cntList, err := containers.List()
|
||||
|
@ -41,8 +28,6 @@ func (cnt *Containers) UpdateData() {
|
|||
cnt.containersList.mu.Lock()
|
||||
defer cnt.containersList.mu.Unlock()
|
||||
|
||||
sort.Sort(containerListSorted{cntList, cnt.containersList.sortBy, cnt.containersList.ascending})
|
||||
|
||||
cnt.containersList.report = cntList
|
||||
}
|
||||
|
||||
|
@ -91,7 +76,7 @@ func (con conReporter) names() string {
|
|||
func (con conReporter) state() string {
|
||||
var state string
|
||||
|
||||
switch con.State {
|
||||
switch con.ListContainer.State {
|
||||
case "running":
|
||||
t := units.HumanDuration(time.Since(time.Unix(con.StartedAt, 0)))
|
||||
state = "Up " + t + " ago"
|
||||
|
@ -101,14 +86,14 @@ func (con conReporter) state() string {
|
|||
t := units.HumanDuration(time.Since(time.Unix(con.ExitedAt, 0)))
|
||||
state = fmt.Sprintf("Exited (%d) %s ago", con.ExitCode, t)
|
||||
default:
|
||||
state = con.State
|
||||
state = con.ListContainer.State
|
||||
}
|
||||
|
||||
return state
|
||||
}
|
||||
|
||||
func (con conReporter) status() string {
|
||||
hc := con.Status
|
||||
hc := con.ListContainer.Status
|
||||
if hc != "" {
|
||||
return con.state() + " (" + hc + ")"
|
||||
}
|
||||
|
@ -117,56 +102,9 @@ func (con conReporter) status() string {
|
|||
}
|
||||
|
||||
func (con conReporter) ports() string {
|
||||
if len(con.Ports) < 1 {
|
||||
if len(con.ListContainer.Ports) < 1 {
|
||||
return ""
|
||||
}
|
||||
|
||||
return putils.PortsToString(con.Ports)
|
||||
}
|
||||
|
||||
type lprSort []entities.ListContainer
|
||||
|
||||
func (a lprSort) Len() int { return len(a) }
|
||||
func (a lprSort) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||
|
||||
type containerListSorted struct {
|
||||
lprSort
|
||||
|
||||
option string
|
||||
ascending bool
|
||||
}
|
||||
|
||||
func (a containerListSorted) Less(i, j int) bool {
|
||||
switch a.option {
|
||||
case "pod":
|
||||
if a.ascending {
|
||||
return a.lprSort[i].Pod < a.lprSort[j].Pod
|
||||
}
|
||||
|
||||
return a.lprSort[i].Pod > a.lprSort[j].Pod
|
||||
case "image":
|
||||
if a.ascending {
|
||||
return a.lprSort[i].Image < a.lprSort[j].Image
|
||||
}
|
||||
|
||||
return a.lprSort[i].Image > a.lprSort[j].Image
|
||||
case "status":
|
||||
if a.ascending {
|
||||
return a.lprSort[i].State < a.lprSort[j].State
|
||||
}
|
||||
|
||||
return a.lprSort[i].State > a.lprSort[j].State
|
||||
case "created":
|
||||
if a.ascending {
|
||||
return a.lprSort[i].Created.After(a.lprSort[j].Created)
|
||||
}
|
||||
|
||||
return a.lprSort[i].Created.Before(a.lprSort[j].Created)
|
||||
}
|
||||
|
||||
if a.ascending {
|
||||
return a.lprSort[i].Names[0] < a.lprSort[j].Names[0]
|
||||
}
|
||||
|
||||
return a.lprSort[i].Names[0] > a.lprSort[j].Names[0]
|
||||
return putils.PortsToString(con.ListContainer.Ports)
|
||||
}
|
||||
|
|
|
@ -6,8 +6,8 @@ import (
|
|||
|
||||
// Draw draws this primitive onto the screen.
|
||||
func (cnt *Containers) Draw(screen tcell.Screen) { //nolint:cyclop
|
||||
cnt.DrawForSubclass(screen, cnt)
|
||||
cnt.SetBorder(false)
|
||||
cnt.Box.DrawForSubclass(screen, cnt)
|
||||
cnt.Box.SetBorder(false)
|
||||
|
||||
cntViewX, cntViewY, cntViewW, cntViewH := cnt.GetInnerRect()
|
||||
|
||||
|
@ -140,12 +140,4 @@ func (cnt *Containers) Draw(screen tcell.Screen) { //nolint:cyclop
|
|||
|
||||
return
|
||||
}
|
||||
|
||||
// sort dialog
|
||||
if cnt.sortDialog.IsDisplay() {
|
||||
cnt.sortDialog.SetRect(cntViewX, cntViewY, cntViewW, cntViewH)
|
||||
cnt.sortDialog.Draw(screen)
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
|
|
|
@ -107,13 +107,6 @@ func (cnt *Containers) InputHandler() func(event *tcell.EventKey, setFocus func(
|
|||
}
|
||||
}
|
||||
|
||||
// container sort dialog handler
|
||||
if cnt.sortDialog.HasFocus() {
|
||||
if cntSortDialogHandler := cnt.sortDialog.InputHandler(); cntSortDialogHandler != nil {
|
||||
cntSortDialogHandler(event, setFocus)
|
||||
}
|
||||
}
|
||||
|
||||
// container terminal dialog handler
|
||||
if cnt.terminalDialog.HasFocus() {
|
||||
if cntTerminalDialogHandler := cnt.terminalDialog.InputHandler(); cntTerminalDialogHandler != nil {
|
||||
|
@ -124,7 +117,6 @@ func (cnt *Containers) InputHandler() func(event *tcell.EventKey, setFocus func(
|
|||
// table handlers
|
||||
if cnt.table.HasFocus() { //nolint:nestif
|
||||
cnt.selectedID, cnt.selectedName = cnt.getSelectedItem()
|
||||
// display command menu
|
||||
if event.Rune() == utils.CommandMenuKey.Rune() {
|
||||
if cnt.cmdDialog.GetCommandCount() <= 1 {
|
||||
return
|
||||
|
@ -136,14 +128,6 @@ func (cnt *Containers) InputHandler() func(event *tcell.EventKey, setFocus func(
|
|||
return
|
||||
}
|
||||
|
||||
// display sort menu
|
||||
if event.Rune() == utils.SortMenuKey.Rune() {
|
||||
cnt.sortDialog.Display()
|
||||
setFocus(cnt)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if event.Key() == utils.DeleteKey.EventKey() {
|
||||
cnt.rm()
|
||||
setFocus(cnt)
|
||||
|
|
|
@ -30,7 +30,6 @@ func (cnt *Containers) refresh(maxWidth int) {
|
|||
SetSelectable(false))
|
||||
}
|
||||
|
||||
currentSelectedRow, _ := cnt.table.GetSelection()
|
||||
rowIndex := 1
|
||||
cntList := cnt.getData()
|
||||
|
||||
|
@ -117,11 +116,4 @@ func (cnt *Containers) refresh(maxWidth int) {
|
|||
|
||||
rowIndex++
|
||||
}
|
||||
|
||||
if currentSelectedRow > len(cntList) {
|
||||
currentSelectedRow--
|
||||
if currentSelectedRow >= 0 {
|
||||
cnt.table.Select(currentSelectedRow, -1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,6 @@ const (
|
|||
// CommandDialog is a commands list dialog.
|
||||
type CommandDialog struct {
|
||||
*tview.Box
|
||||
|
||||
layout *tview.Flex
|
||||
table *tview.Table
|
||||
form *tview.Form
|
||||
|
@ -38,12 +37,6 @@ type CommandDialog struct {
|
|||
|
||||
// NewCommandDialog returns a command list primitive.
|
||||
func NewCommandDialog(options [][]string) *CommandDialog {
|
||||
var cmdWidth int
|
||||
|
||||
// command table items
|
||||
col1Width := 0
|
||||
col2Width := 0
|
||||
|
||||
form := tview.NewForm().
|
||||
AddButton("Cancel", nil).
|
||||
SetButtonsAlign(tview.AlignRight)
|
||||
|
@ -54,6 +47,7 @@ func NewCommandDialog(options [][]string) *CommandDialog {
|
|||
cmdsTable := tview.NewTable()
|
||||
cmdsTable.SetBackgroundColor(style.DialogBgColor)
|
||||
|
||||
cmdWidth := 0
|
||||
// command table header
|
||||
cmdsTable.SetCell(0, 0,
|
||||
tview.NewTableCell(fmt.Sprintf("[%s::b]COMMAND", style.GetColorHex(style.TableHeaderFgColor))).
|
||||
|
@ -71,6 +65,10 @@ func NewCommandDialog(options [][]string) *CommandDialog {
|
|||
SetAlign(tview.AlignCenter).
|
||||
SetSelectable(false))
|
||||
|
||||
// command table items
|
||||
col1Width := 0
|
||||
col2Width := 0
|
||||
|
||||
for i := range options {
|
||||
cmdsTable.SetCell(i+1, 0,
|
||||
tview.NewTableCell(options[i][0]).
|
||||
|
@ -275,7 +273,7 @@ func (cmd *CommandDialog) SetRect(x, y, width, height int) {
|
|||
|
||||
cmd.Box.SetRect(x+ws, dy, bWidth, bHeight)
|
||||
|
||||
x, y, width, height = cmd.GetInnerRect()
|
||||
x, y, width, height = cmd.Box.GetInnerRect()
|
||||
|
||||
cmd.layout.SetRect(x, y, width, height)
|
||||
}
|
||||
|
@ -286,7 +284,7 @@ func (cmd *CommandDialog) Draw(screen tcell.Screen) {
|
|||
return
|
||||
}
|
||||
|
||||
cmd.DrawForSubclass(screen, cmd)
|
||||
cmd.Box.DrawForSubclass(screen, cmd)
|
||||
cmd.layout.Draw(screen)
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,6 @@ import (
|
|||
// ConfirmDialog is a simple confirmation dialog primitive.
|
||||
type ConfirmDialog struct {
|
||||
*tview.Box
|
||||
|
||||
layout *tview.Flex
|
||||
textview *tview.TextView
|
||||
form *tview.Form
|
||||
|
@ -113,56 +112,6 @@ func (d *ConfirmDialog) SetRect(x, y, width, height int) {
|
|||
d.setRect()
|
||||
}
|
||||
|
||||
// Draw draws this primitive onto the screen.
|
||||
func (d *ConfirmDialog) Draw(screen tcell.Screen) {
|
||||
if !d.display {
|
||||
return
|
||||
}
|
||||
|
||||
d.DrawForSubclass(screen, d)
|
||||
|
||||
x, y, width, height := d.GetInnerRect()
|
||||
d.layout.SetRect(x, y, width, height)
|
||||
d.layout.Draw(screen)
|
||||
}
|
||||
|
||||
// InputHandler returns input handler function for this primitive.
|
||||
func (d *ConfirmDialog) InputHandler() func(event *tcell.EventKey, setFocus func(p tview.Primitive)) {
|
||||
return d.WrapInputHandler(func(event *tcell.EventKey, setFocus func(p tview.Primitive)) {
|
||||
log.Debug().Msgf("confirm dialog: event %v received", event)
|
||||
|
||||
if event.Key() == tcell.KeyEsc {
|
||||
d.cancelHandler()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if formHandler := d.form.InputHandler(); formHandler != nil {
|
||||
formHandler(event, setFocus)
|
||||
|
||||
return
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// SetCancelFunc sets form cancel button selected function.
|
||||
func (d *ConfirmDialog) SetCancelFunc(handler func()) *ConfirmDialog {
|
||||
d.cancelHandler = handler
|
||||
cancelButton := d.form.GetButton(d.form.GetButtonCount() - 2) //nolint:mnd
|
||||
cancelButton.SetSelectedFunc(handler)
|
||||
|
||||
return d
|
||||
}
|
||||
|
||||
// SetSelectedFunc sets form select button selected function.
|
||||
func (d *ConfirmDialog) SetSelectedFunc(handler func()) *ConfirmDialog {
|
||||
d.selectHandler = handler
|
||||
enterButton := d.form.GetButton(d.form.GetButtonCount() - 1)
|
||||
enterButton.SetSelectedFunc(handler)
|
||||
|
||||
return d
|
||||
}
|
||||
|
||||
func (d *ConfirmDialog) setRect() {
|
||||
maxHeight := d.height
|
||||
maxWidth := d.width
|
||||
|
@ -207,3 +156,53 @@ func (d *ConfirmDialog) setRect() {
|
|||
|
||||
d.Box.SetRect(d.x, d.y, d.width, d.height)
|
||||
}
|
||||
|
||||
// Draw draws this primitive onto the screen.
|
||||
func (d *ConfirmDialog) Draw(screen tcell.Screen) {
|
||||
if !d.display {
|
||||
return
|
||||
}
|
||||
|
||||
d.Box.DrawForSubclass(screen, d)
|
||||
|
||||
x, y, width, height := d.Box.GetInnerRect()
|
||||
d.layout.SetRect(x, y, width, height)
|
||||
d.layout.Draw(screen)
|
||||
}
|
||||
|
||||
// InputHandler returns input handler function for this primitive.
|
||||
func (d *ConfirmDialog) InputHandler() func(event *tcell.EventKey, setFocus func(p tview.Primitive)) {
|
||||
return d.WrapInputHandler(func(event *tcell.EventKey, setFocus func(p tview.Primitive)) {
|
||||
log.Debug().Msgf("confirm dialog: event %v received", event)
|
||||
|
||||
if event.Key() == tcell.KeyEsc {
|
||||
d.cancelHandler()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if formHandler := d.form.InputHandler(); formHandler != nil {
|
||||
formHandler(event, setFocus)
|
||||
|
||||
return
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// SetCancelFunc sets form cancel button selected function.
|
||||
func (d *ConfirmDialog) SetCancelFunc(handler func()) *ConfirmDialog {
|
||||
d.cancelHandler = handler
|
||||
cancelButton := d.form.GetButton(d.form.GetButtonCount() - 2) //nolint:mnd
|
||||
cancelButton.SetSelectedFunc(handler)
|
||||
|
||||
return d
|
||||
}
|
||||
|
||||
// SetSelectedFunc sets form select button selected function.
|
||||
func (d *ConfirmDialog) SetSelectedFunc(handler func()) *ConfirmDialog {
|
||||
d.selectHandler = handler
|
||||
enterButton := d.form.GetButton(d.form.GetButtonCount() - 1)
|
||||
enterButton.SetSelectedFunc(handler)
|
||||
|
||||
return d
|
||||
}
|
||||
|
|
|
@ -12,7 +12,6 @@ import (
|
|||
// ErrorDialog is an error dialog primitive.
|
||||
type ErrorDialog struct {
|
||||
*tview.Box
|
||||
|
||||
modal *tview.Modal
|
||||
title string
|
||||
message string
|
||||
|
@ -30,7 +29,7 @@ func NewErrorDialog() *ErrorDialog {
|
|||
|
||||
dialog.modal.SetButtonBackgroundColor(style.ErrorDialogButtonBgColor)
|
||||
|
||||
dialog.modal.SetDoneFunc(func(buttonIndex int, buttonLabel string) {
|
||||
dialog.modal.SetDoneFunc(func(buttonIndex int, buttonLabel string) { //nolint:revive
|
||||
dialog.Hide()
|
||||
})
|
||||
|
||||
|
@ -117,7 +116,7 @@ func (d *ErrorDialog) Draw(screen tcell.Screen) {
|
|||
|
||||
// SetDoneFunc sets modal done function.
|
||||
func (d *ErrorDialog) SetDoneFunc(handler func()) *ErrorDialog {
|
||||
d.modal.SetDoneFunc(func(buttonIndex int, buttonLabel string) {
|
||||
d.modal.SetDoneFunc(func(buttonIndex int, buttonLabel string) { //nolint:revive
|
||||
handler()
|
||||
})
|
||||
|
||||
|
|
|
@ -23,7 +23,6 @@ const (
|
|||
// SimpleInputDialog is an input dialog primitive.
|
||||
type SimpleInputDialog struct {
|
||||
*tview.Box
|
||||
|
||||
height int
|
||||
layout *tview.Flex
|
||||
textview *tview.TextView
|
||||
|
@ -96,16 +95,44 @@ func (d *SimpleInputDialog) Hide() {
|
|||
d.display = false
|
||||
}
|
||||
|
||||
func (d *SimpleInputDialog) setLayout(haveDesc bool) {
|
||||
d.layout.Clear()
|
||||
|
||||
descHeight := siDescHeight
|
||||
|
||||
if !haveDesc {
|
||||
descHeight = 1
|
||||
d.height = siDialogHeight - 3 //nolint:mnd
|
||||
} else {
|
||||
d.height = siDialogHeight
|
||||
}
|
||||
|
||||
d.layout.AddItem(
|
||||
tview.NewFlex().SetDirection(tview.FlexColumn).
|
||||
AddItem(utils.EmptyBoxSpace(style.DialogBgColor), 1, 0, false).
|
||||
AddItem(d.textview, 0, 1, false).
|
||||
AddItem(utils.EmptyBoxSpace(style.DialogBgColor), 1, 0, false),
|
||||
descHeight, 0, true)
|
||||
|
||||
d.layout.AddItem(tview.NewFlex().SetDirection(tview.FlexColumn).
|
||||
AddItem(utils.EmptyBoxSpace(style.DialogBgColor), 1, 0, false).
|
||||
AddItem(d.input, 0, 1, false).
|
||||
AddItem(utils.EmptyBoxSpace(style.DialogBgColor), 1, 0, false),
|
||||
1, 0, true)
|
||||
|
||||
d.layout.AddItem(d.form, DialogFormHeight, 0, true)
|
||||
d.layout.SetBorder(true)
|
||||
d.layout.SetBorderColor(style.DialogBorderColor)
|
||||
d.layout.SetBackgroundColor(style.DialogBgColor)
|
||||
}
|
||||
|
||||
// SetDescription sets dialogs description.
|
||||
func (d *SimpleInputDialog) SetDescription(text string) {
|
||||
d.textview.Clear()
|
||||
|
||||
haveDesc := true
|
||||
|
||||
_, err := fmt.Fprintf(d.textview, "\n%s", text)
|
||||
if err != nil {
|
||||
log.Error().Msgf("failed to write to ui text view: %s", err.Error())
|
||||
}
|
||||
fmt.Fprintf(d.textview, "\n%s", text)
|
||||
|
||||
if len(text) == 0 {
|
||||
haveDesc = false
|
||||
|
@ -266,8 +293,8 @@ func (d *SimpleInputDialog) Draw(screen tcell.Screen) {
|
|||
return
|
||||
}
|
||||
|
||||
d.DrawForSubclass(screen, d)
|
||||
x, y, width, height := d.GetInnerRect()
|
||||
d.Box.DrawForSubclass(screen, d)
|
||||
x, y, width, height := d.Box.GetInnerRect()
|
||||
d.layout.SetRect(x, y, width, height)
|
||||
d.layout.Draw(screen)
|
||||
}
|
||||
|
@ -289,34 +316,3 @@ func (d *SimpleInputDialog) SetCancelFunc(handler func()) *SimpleInputDialog {
|
|||
|
||||
return d
|
||||
}
|
||||
|
||||
func (d *SimpleInputDialog) setLayout(haveDesc bool) {
|
||||
d.layout.Clear()
|
||||
|
||||
descHeight := siDescHeight
|
||||
|
||||
if !haveDesc {
|
||||
descHeight = 1
|
||||
d.height = siDialogHeight - 3 //nolint:mnd
|
||||
} else {
|
||||
d.height = siDialogHeight
|
||||
}
|
||||
|
||||
d.layout.AddItem(
|
||||
tview.NewFlex().SetDirection(tview.FlexColumn).
|
||||
AddItem(utils.EmptyBoxSpace(style.DialogBgColor), 1, 0, false).
|
||||
AddItem(d.textview, 0, 1, false).
|
||||
AddItem(utils.EmptyBoxSpace(style.DialogBgColor), 1, 0, false),
|
||||
descHeight, 0, true)
|
||||
|
||||
d.layout.AddItem(tview.NewFlex().SetDirection(tview.FlexColumn).
|
||||
AddItem(utils.EmptyBoxSpace(style.DialogBgColor), 1, 0, false).
|
||||
AddItem(d.input, 0, 1, false).
|
||||
AddItem(utils.EmptyBoxSpace(style.DialogBgColor), 1, 0, false),
|
||||
1, 0, true)
|
||||
|
||||
d.layout.AddItem(d.form, DialogFormHeight, 0, true)
|
||||
d.layout.SetBorder(true)
|
||||
d.layout.SetBorderColor(style.DialogBorderColor)
|
||||
d.layout.SetBackgroundColor(style.DialogBgColor)
|
||||
}
|
||||
|
|
|
@ -13,7 +13,6 @@ import (
|
|||
// MessageDialog is a simaple message dialog primitive.
|
||||
type MessageDialog struct {
|
||||
*tview.Box
|
||||
|
||||
layout *tview.Flex
|
||||
infoType *tview.InputField
|
||||
textview *tview.TextView
|
||||
|
@ -133,7 +132,7 @@ func (d *MessageDialog) SetText(headerType messageInfo, headerMessage string, me
|
|||
case MessagePodInfo:
|
||||
msgTypeLabel = "POD ID:"
|
||||
case MessageContainerInfo:
|
||||
msgTypeLabel = utils.ContainerIDLabel
|
||||
msgTypeLabel = "CONTAINER ID:"
|
||||
case MessageVolumeInfo:
|
||||
msgTypeLabel = "VOLUME NAME:"
|
||||
case MessageImageInfo:
|
||||
|
@ -237,8 +236,8 @@ func (d *MessageDialog) Draw(screen tcell.Screen) {
|
|||
return
|
||||
}
|
||||
|
||||
d.DrawForSubclass(screen, d)
|
||||
x, y, width, height := d.GetInnerRect()
|
||||
d.Box.DrawForSubclass(screen, d)
|
||||
x, y, width, height := d.Box.GetInnerRect()
|
||||
d.layout.SetRect(x, y, width, height)
|
||||
d.layout.Draw(screen)
|
||||
}
|
||||
|
|
|
@ -17,7 +17,6 @@ const (
|
|||
// ProgressDialog represents progress bar permitive.
|
||||
type ProgressDialog struct {
|
||||
*tview.Box
|
||||
|
||||
x int
|
||||
y int
|
||||
width int
|
||||
|
@ -47,8 +46,8 @@ func (d *ProgressDialog) Draw(screen tcell.Screen) {
|
|||
return
|
||||
}
|
||||
|
||||
d.DrawForSubclass(screen, d)
|
||||
x, y, width, _ := d.GetInnerRect()
|
||||
d.Box.DrawForSubclass(screen, d)
|
||||
x, y, width, _ := d.Box.GetInnerRect()
|
||||
tickStr := d.tickStr(width)
|
||||
tview.Print(screen, tickStr, x, y, width, tview.AlignLeft, tcell.ColorYellow)
|
||||
}
|
||||
|
@ -91,7 +90,7 @@ func (d *ProgressDialog) IsDisplay() bool {
|
|||
}
|
||||
|
||||
// Focus is called when this primitive receives focus.
|
||||
func (d *ProgressDialog) Focus(delegate func(p tview.Primitive)) {}
|
||||
func (d *ProgressDialog) Focus(delegate func(p tview.Primitive)) {} //nolint:revive
|
||||
|
||||
// HasFocus returns whether or not this primitive has focus.
|
||||
func (d *ProgressDialog) HasFocus() bool {
|
||||
|
@ -100,16 +99,12 @@ func (d *ProgressDialog) HasFocus() bool {
|
|||
|
||||
// InputHandler returns input handler function for this primitive.
|
||||
func (d *ProgressDialog) InputHandler() func(event *tcell.EventKey, setFocus func(p tview.Primitive)) {
|
||||
return d.WrapInputHandler(func(event *tcell.EventKey, setFocus func(p tview.Primitive)) {
|
||||
return d.WrapInputHandler(func(event *tcell.EventKey, setFocus func(p tview.Primitive)) { //nolint:revive
|
||||
log.Debug().Msgf("progress dialog: event %v received", event)
|
||||
})
|
||||
}
|
||||
|
||||
func (d *ProgressDialog) tickStr(maxCount int) string {
|
||||
prgStr := prgCell + prgCell + prgCell + prgCell
|
||||
prgHeadStr := ""
|
||||
hWidth := 0
|
||||
prgEndStr := ""
|
||||
barColor := style.GetColorHex(style.PrgBarColor)
|
||||
counter := d.counterValue
|
||||
|
||||
|
@ -119,11 +114,18 @@ func (d *ProgressDialog) tickStr(maxCount int) string {
|
|||
d.counterValue = 0
|
||||
}
|
||||
|
||||
prgHeadStr := ""
|
||||
hWidth := 0
|
||||
prgEndStr := ""
|
||||
prgStr := ""
|
||||
|
||||
for range d.counterValue {
|
||||
prgHeadStr += fmt.Sprintf("[black::]%s", prgCell) //nolint:perfsprint
|
||||
hWidth++
|
||||
}
|
||||
|
||||
prgStr = prgCell + prgCell + prgCell + prgCell
|
||||
|
||||
for range maxCount + hWidth + 4 {
|
||||
prgEndStr += fmt.Sprintf("[black::]%s", prgCell) //nolint:perfsprint
|
||||
}
|
||||
|
|
|
@ -1,262 +0,0 @@
|
|||
package dialogs
|
||||
|
||||
import (
|
||||
"github.com/containers/podman-tui/ui/style"
|
||||
"github.com/containers/podman-tui/ui/utils"
|
||||
"github.com/gdamore/tcell/v2"
|
||||
"github.com/rivo/tview"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
const (
|
||||
sortDialogMaxWidth = 30
|
||||
sortDialogMaxHeight = 8
|
||||
)
|
||||
|
||||
const (
|
||||
sortDialogOptionsFocus = 0 + iota
|
||||
sortDialogOrderFocus
|
||||
sortDialogFormFocus
|
||||
)
|
||||
|
||||
type SortDialog struct {
|
||||
*tview.Box
|
||||
|
||||
layout *tview.Flex
|
||||
sortBy *tview.DropDown
|
||||
sortOrder *tview.DropDown
|
||||
form *tview.Form
|
||||
display bool
|
||||
selectHandler func()
|
||||
cancelHandler func()
|
||||
focusElement int
|
||||
}
|
||||
|
||||
func NewSortDialog(options []string, defaultOption int) *SortDialog {
|
||||
sd := SortDialog{
|
||||
Box: tview.NewBox(),
|
||||
form: tview.NewForm(),
|
||||
layout: tview.NewFlex(),
|
||||
focusElement: sortDialogOptionsFocus,
|
||||
}
|
||||
|
||||
sortOrder := "Sort order:"
|
||||
sd.sortOrder = tview.NewDropDown()
|
||||
sd.sortOrder.SetLabel(sortOrder)
|
||||
sd.sortOrder.SetLabelWidth(len(sortOrder) + 1)
|
||||
sd.sortOrder.SetTitleAlign(tview.AlignRight)
|
||||
sd.sortOrder.SetLabelColor(style.DialogFgColor)
|
||||
sd.sortOrder.SetBackgroundColor(style.DialogBgColor)
|
||||
sd.sortOrder.SetOptions([]string{"ascending", "descending"}, nil)
|
||||
sd.sortOrder.SetListStyles(style.DropDownUnselected, style.DropDownSelected)
|
||||
sd.sortOrder.SetFieldBackgroundColor(style.InputFieldBgColor)
|
||||
sd.sortOrder.SetFieldWidth(0)
|
||||
sd.sortOrder.SetCurrentOption(0)
|
||||
|
||||
sd.sortBy = tview.NewDropDown()
|
||||
sd.sortBy.SetLabel("Sort by:")
|
||||
sd.sortBy.SetLabelWidth(len(sortOrder) + 1)
|
||||
sd.sortBy.SetTitleAlign(tview.AlignRight)
|
||||
sd.sortBy.SetLabelColor(style.DialogFgColor)
|
||||
sd.sortBy.SetBackgroundColor(style.DialogBgColor)
|
||||
sd.sortBy.SetOptions(options, nil)
|
||||
sd.sortBy.SetListStyles(style.DropDownUnselected, style.DropDownSelected)
|
||||
sd.sortBy.SetFieldBackgroundColor(style.InputFieldBgColor)
|
||||
sd.sortBy.SetFieldWidth(0)
|
||||
|
||||
if len(options) > 0 {
|
||||
sd.sortBy.SetCurrentOption(defaultOption)
|
||||
}
|
||||
|
||||
// form
|
||||
sd.form.AddButton("Cancel", nil)
|
||||
sd.form.AddButton(" Sort ", nil)
|
||||
sd.form.SetButtonsAlign(tview.AlignRight)
|
||||
sd.form.SetBackgroundColor(style.DialogBgColor)
|
||||
sd.form.SetButtonBackgroundColor(style.ButtonBgColor)
|
||||
|
||||
// main layout
|
||||
sd.layout.SetDirection(tview.FlexRow)
|
||||
sd.layout.SetBackgroundColor(style.DialogBgColor)
|
||||
sd.layout.SetBorder(true)
|
||||
sd.layout.SetBorderColor(style.DialogBorderColor)
|
||||
sd.layout.AddItem(sd.sortBy, 0, 1, true)
|
||||
sd.layout.AddItem(utils.EmptyBoxSpace(style.DialogBgColor), 0, 1, false)
|
||||
sd.layout.AddItem(sd.sortOrder, 0, 1, true)
|
||||
sd.layout.AddItem(sd.form, DialogFormHeight, 0, true)
|
||||
|
||||
return &sd
|
||||
}
|
||||
|
||||
// Display displays this primitive.
|
||||
func (d *SortDialog) Display() {
|
||||
d.display = true
|
||||
}
|
||||
|
||||
// IsDisplay returns true if primitive is shown.
|
||||
func (d *SortDialog) IsDisplay() bool {
|
||||
return d.display
|
||||
}
|
||||
|
||||
// Hide stops displaying this primitive.
|
||||
func (d *SortDialog) Hide() {
|
||||
d.display = false
|
||||
d.focusElement = sortDialogOptionsFocus
|
||||
d.form.SetFocus(0)
|
||||
}
|
||||
|
||||
// HasFocus returns whether or not this primitive has focus.
|
||||
func (d *SortDialog) HasFocus() bool {
|
||||
if d.sortBy.HasFocus() || d.sortOrder.HasFocus() {
|
||||
return true
|
||||
}
|
||||
|
||||
if d.form.HasFocus() || d.layout.HasFocus() {
|
||||
return true
|
||||
}
|
||||
|
||||
return d.Box.HasFocus()
|
||||
}
|
||||
|
||||
// Focus is called when this primitive receives focus.
|
||||
func (d *SortDialog) Focus(delegate func(p tview.Primitive)) {
|
||||
switch d.focusElement {
|
||||
case sortDialogOptionsFocus:
|
||||
delegate(d.sortBy)
|
||||
case sortDialogOrderFocus:
|
||||
delegate(d.sortOrder)
|
||||
case sortDialogFormFocus:
|
||||
sortButton := d.form.GetButton(1)
|
||||
sortButton.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
|
||||
if event.Key() == tcell.KeyTab {
|
||||
d.focusElement = sortDialogOptionsFocus
|
||||
|
||||
d.Focus(delegate)
|
||||
d.form.SetFocus(0)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
if event.Key() == tcell.KeyEnter {
|
||||
d.selectHandler()
|
||||
}
|
||||
|
||||
return event
|
||||
})
|
||||
|
||||
delegate(d.form)
|
||||
}
|
||||
}
|
||||
|
||||
// InputHandler returns input handler function for this primitive.
|
||||
func (d *SortDialog) InputHandler() func(event *tcell.EventKey, setFocus func(p tview.Primitive)) { //nolint:cyclop
|
||||
return d.WrapInputHandler(func(event *tcell.EventKey, setFocus func(p tview.Primitive)) {
|
||||
log.Debug().Msgf("sort dialog dialog: event %v received", event)
|
||||
|
||||
if event.Key() == utils.SwitchFocusKey.Key {
|
||||
switch d.focusElement {
|
||||
case sortDialogOptionsFocus:
|
||||
d.focusElement = sortDialogOrderFocus
|
||||
case sortDialogOrderFocus:
|
||||
d.focusElement = sortDialogFormFocus
|
||||
}
|
||||
}
|
||||
|
||||
// dropdown widgets shall handle events before "Esc" key handler
|
||||
if d.sortBy.HasFocus() {
|
||||
event = utils.ParseKeyEventKey(event)
|
||||
if sortByHandler := d.sortBy.InputHandler(); sortByHandler != nil {
|
||||
sortByHandler(event, setFocus)
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if d.sortOrder.HasFocus() {
|
||||
event = utils.ParseKeyEventKey(event)
|
||||
if sortOrderHandler := d.sortOrder.InputHandler(); sortOrderHandler != nil {
|
||||
sortOrderHandler(event, setFocus)
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if d.form.HasFocus() {
|
||||
if event.Key() == tcell.KeyEsc {
|
||||
d.cancelHandler()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if formHandler := d.form.InputHandler(); formHandler != nil {
|
||||
formHandler(event, setFocus)
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// SetRect set rects for this primitive.
|
||||
func (d *SortDialog) SetRect(x, y, width, height int) {
|
||||
if width > sortDialogMaxWidth {
|
||||
emptySpace := (width - sortDialogMaxWidth) / 2 //nolint:mnd
|
||||
x += emptySpace
|
||||
width = sortDialogMaxWidth
|
||||
}
|
||||
|
||||
if height > sortDialogMaxHeight {
|
||||
emptySpace := (height - sortDialogMaxHeight) / 2 //nolint:mnd
|
||||
y += emptySpace
|
||||
height = sortDialogMaxHeight
|
||||
}
|
||||
|
||||
d.Box.SetRect(x, y, width, height)
|
||||
}
|
||||
|
||||
// Draw draws this primitive onto the screen.
|
||||
func (d *SortDialog) Draw(screen tcell.Screen) {
|
||||
if !d.display {
|
||||
return
|
||||
}
|
||||
|
||||
d.DrawForSubclass(screen, d)
|
||||
|
||||
x, y, width, height := d.GetInnerRect()
|
||||
|
||||
d.layout.SetRect(x, y, width, height)
|
||||
d.layout.Draw(screen)
|
||||
}
|
||||
|
||||
// SetSelectFunc sets form sort button selected function.
|
||||
func (d *SortDialog) SetSelectFunc(handler func(string, bool)) *SortDialog {
|
||||
selectHandler := func() {
|
||||
if d.sortBy.GetOptionCount() > 0 {
|
||||
_, sortOpt := d.sortBy.GetCurrentOption()
|
||||
_, order := d.sortOrder.GetCurrentOption()
|
||||
ascending := true
|
||||
|
||||
if order == "descending" {
|
||||
ascending = false
|
||||
}
|
||||
|
||||
handler(sortOpt, ascending)
|
||||
}
|
||||
|
||||
d.Hide()
|
||||
}
|
||||
|
||||
d.selectHandler = selectHandler
|
||||
|
||||
return d
|
||||
}
|
||||
|
||||
// SetCancelFunc sets form cancel button selected function.
|
||||
func (d *SortDialog) SetCancelFunc(handler func()) *SortDialog {
|
||||
d.cancelHandler = handler
|
||||
cancelButton := d.form.GetButton(d.form.GetButtonCount() - 2) //nolint:mnd
|
||||
|
||||
cancelButton.SetSelectedFunc(handler)
|
||||
|
||||
return d
|
||||
}
|
|
@ -25,7 +25,6 @@ const (
|
|||
// TopDialog is a simple dialog with pod/container top result table.
|
||||
type TopDialog struct {
|
||||
*tview.Box
|
||||
|
||||
layout *tview.Flex
|
||||
table *tview.Table
|
||||
info *tview.InputField
|
||||
|
@ -175,8 +174,8 @@ func (d *TopDialog) Draw(screen tcell.Screen) {
|
|||
return
|
||||
}
|
||||
|
||||
d.DrawForSubclass(screen, d)
|
||||
x, y, width, height := d.GetInnerRect()
|
||||
d.Box.DrawForSubclass(screen, d)
|
||||
x, y, width, height := d.Box.GetInnerRect()
|
||||
d.layout.SetRect(x, y, width, height)
|
||||
d.layout.Draw(screen)
|
||||
}
|
||||
|
@ -188,9 +187,28 @@ func (d *TopDialog) SetCancelFunc(handler func()) *TopDialog {
|
|||
return d
|
||||
}
|
||||
|
||||
func (d *TopDialog) initTable() {
|
||||
bgColor := style.TableHeaderBgColor
|
||||
fgColor := style.TableHeaderFgColor
|
||||
|
||||
d.table.Clear()
|
||||
d.table.SetFixed(1, 1)
|
||||
d.table.SetSelectable(true, false)
|
||||
|
||||
for i := range d.tableHeaders {
|
||||
d.table.SetCell(0, i,
|
||||
tview.NewTableCell(fmt.Sprintf("[%s::b]%s", style.GetColorHex(fgColor), strings.ToUpper(d.tableHeaders[i]))).
|
||||
SetExpansion(0).
|
||||
SetBackgroundColor(bgColor).
|
||||
SetTextColor(fgColor).
|
||||
SetAlign(tview.AlignLeft).
|
||||
SetSelectable(false))
|
||||
}
|
||||
}
|
||||
|
||||
// UpdateResults updates result table.
|
||||
func (d *TopDialog) UpdateResults(infoType topInfo, id string, name string, data [][]string) {
|
||||
headerInfo := utils.ContainerIDLabel
|
||||
headerInfo := "CONTAINER ID:"
|
||||
if infoType == TopPodInfo {
|
||||
headerInfo = "POD ID:"
|
||||
}
|
||||
|
@ -279,25 +297,6 @@ func (d *TopDialog) UpdateResults(infoType topInfo, id string, name string, data
|
|||
}
|
||||
}
|
||||
|
||||
func (d *TopDialog) initTable() {
|
||||
bgColor := style.TableHeaderBgColor
|
||||
fgColor := style.TableHeaderFgColor
|
||||
|
||||
d.table.Clear()
|
||||
d.table.SetFixed(1, 1)
|
||||
d.table.SetSelectable(true, false)
|
||||
|
||||
for i := range d.tableHeaders {
|
||||
d.table.SetCell(0, i,
|
||||
tview.NewTableCell(fmt.Sprintf("[%s::b]%s", style.GetColorHex(fgColor), strings.ToUpper(d.tableHeaders[i]))).
|
||||
SetExpansion(0).
|
||||
SetBackgroundColor(bgColor).
|
||||
SetTextColor(fgColor).
|
||||
SetAlign(tview.AlignLeft).
|
||||
SetSelectable(false))
|
||||
}
|
||||
}
|
||||
|
||||
func (d *TopDialog) getCommandWidth() int {
|
||||
var (
|
||||
commandWidth int
|
||||
|
|
|
@ -12,7 +12,6 @@ import (
|
|||
// Help is a help primitive dialog.
|
||||
type Help struct {
|
||||
*tview.Box
|
||||
|
||||
title string
|
||||
layout *tview.Flex
|
||||
}
|
||||
|
@ -44,8 +43,8 @@ func NewHelp(appName string, appVersion string) *Help {
|
|||
SetTextAlign(tview.AlignLeft)
|
||||
appinfo.SetBackgroundColor(bgColor)
|
||||
|
||||
licenseInfo := "released under the Apache License 2.0."
|
||||
appInfoText := fmt.Sprintf("%s %s - %s", appName, appVersion, licenseInfo)
|
||||
licenseInfo := "Released under the Apache License 2.0."
|
||||
appInfoText := fmt.Sprintf("%s %s - (C) 2022 podman-tui dev team.\n%s", appName, appVersion, licenseInfo)
|
||||
|
||||
appinfo.SetText(appInfoText)
|
||||
appinfo.SetTextColor(headerColor)
|
||||
|
@ -55,7 +54,7 @@ func NewHelp(appName string, appVersion string) *Help {
|
|||
rowIndex := 0
|
||||
colIndex := 0
|
||||
needInit := true
|
||||
maxRowIndex := len(utils.UIKeysBindings) / 2 //nolint:mnd
|
||||
maxRowIndex := len(utils.UIKeysBindings)/2 + 1 //nolint:mnd
|
||||
|
||||
for i := range utils.UIKeysBindings {
|
||||
if i >= maxRowIndex {
|
||||
|
@ -83,7 +82,7 @@ func NewHelp(appName string, appVersion string) *Help {
|
|||
|
||||
// appinfo and appkeys layout
|
||||
mlayout := tview.NewFlex().SetDirection(tview.FlexRow)
|
||||
mlayout.AddItem(appinfo, 1, 0, false)
|
||||
mlayout.AddItem(appinfo, 2, 0, false) //nolint:mnd
|
||||
mlayout.AddItem(utils.EmptyBoxSpace(bgColor), 1, 0, false)
|
||||
mlayout.AddItem(keyinfo, 0, 1, false)
|
||||
mlayout.AddItem(utils.EmptyBoxSpace(bgColor), 1, 0, false)
|
||||
|
@ -117,12 +116,12 @@ func (help *Help) Focus(delegate func(p tview.Primitive)) {
|
|||
|
||||
// Draw draws this primitive onto the screen.
|
||||
func (help *Help) Draw(screen tcell.Screen) {
|
||||
x, y, width, height := help.GetInnerRect()
|
||||
x, y, width, height := help.Box.GetInnerRect()
|
||||
if height <= 3 { //nolint:mnd
|
||||
return
|
||||
}
|
||||
|
||||
help.DrawForSubclass(screen, help)
|
||||
help.Box.DrawForSubclass(screen, help)
|
||||
help.layout.SetRect(x, y, width, height)
|
||||
help.layout.Draw(screen)
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@ import (
|
|||
"github.com/containers/podman-tui/pdcs/images"
|
||||
"github.com/containers/podman-tui/ui/dialogs"
|
||||
"github.com/containers/podman-tui/ui/style"
|
||||
"github.com/containers/podman-tui/ui/utils"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
|
@ -23,7 +22,7 @@ func (img *Images) runCommand(cmd string) { //nolint:cyclop
|
|||
img.importDialog.Display()
|
||||
case "inspect":
|
||||
img.inspect()
|
||||
case utils.PruneCommandLabel:
|
||||
case "prune": //nolint:goconst
|
||||
img.cprune()
|
||||
case "push":
|
||||
img.cpush()
|
||||
|
@ -140,8 +139,6 @@ func (img *Images) history() {
|
|||
if err != nil {
|
||||
title := fmt.Sprintf("IMAGE (%s) HISTORY ERROR", img.selectedID)
|
||||
img.displayError(title, err)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
img.historyDialog.SetImageInfo(img.selectedID, img.selectedName)
|
||||
|
@ -223,9 +220,10 @@ func (img *Images) prune() {
|
|||
|
||||
if err != nil {
|
||||
img.displayError("IMAGE PRUNE ERROR", err)
|
||||
}
|
||||
img.appFocusHandler()
|
||||
|
||||
img.appFocusHandler()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
go prune()
|
||||
|
@ -250,17 +248,17 @@ func (img *Images) push() {
|
|||
img.progressDialog.Display()
|
||||
|
||||
push := func() {
|
||||
err := images.Push(img.selectedID, pushOptions)
|
||||
|
||||
img.progressDialog.Hide()
|
||||
|
||||
if err != nil {
|
||||
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
|
||||
}
|
||||
|
||||
img.appFocusHandler()
|
||||
img.progressDialog.Hide()
|
||||
}
|
||||
|
||||
go push()
|
||||
|
@ -347,9 +345,10 @@ func (img *Images) save() {
|
|||
title := fmt.Sprintf("IMAGE (%s) SAVE ERROR", img.selectedID)
|
||||
|
||||
img.displayError(title, err)
|
||||
}
|
||||
img.appFocusHandler()
|
||||
|
||||
img.appFocusHandler()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
go saveFunc()
|
||||
|
@ -362,17 +361,15 @@ func (img *Images) search(term string) {
|
|||
|
||||
search := func(term string) {
|
||||
result, err := images.Search(term)
|
||||
|
||||
img.progressDialog.Hide()
|
||||
|
||||
if err != nil {
|
||||
title := fmt.Sprintf("IMAGE (%s) SEARCH ERROR", img.selectedID)
|
||||
|
||||
img.displayError(title, err)
|
||||
img.appFocusHandler()
|
||||
}
|
||||
|
||||
img.searchDialog.UpdateResults(result)
|
||||
img.appFocusHandler()
|
||||
img.progressDialog.Hide()
|
||||
}
|
||||
|
||||
go search(term)
|
||||
|
@ -405,8 +402,7 @@ func (img *Images) ctag() {
|
|||
}
|
||||
|
||||
func (img *Images) tag(tag string) {
|
||||
err := images.Tag(img.selectedID, tag)
|
||||
if err != nil {
|
||||
if err := images.Tag(img.selectedID, tag); err != nil {
|
||||
title := fmt.Sprintf("IMAGE (%s) TAG ERROR", img.selectedID)
|
||||
img.displayError(title, err)
|
||||
}
|
||||
|
@ -467,8 +463,7 @@ func (img *Images) tree() {
|
|||
}
|
||||
|
||||
func (img *Images) untag(id string) {
|
||||
err := images.Untag(id)
|
||||
if err != nil {
|
||||
if err := images.Untag(id); err != nil {
|
||||
title := fmt.Sprintf("IMAGE (%s) UNTAG ERROR", img.selectedID)
|
||||
|
||||
img.displayError(title, err)
|
||||
|
@ -482,15 +477,14 @@ func (img *Images) pull(image string) {
|
|||
|
||||
pull := func(name string) {
|
||||
err := images.Pull(name)
|
||||
|
||||
img.progressDialog.Hide()
|
||||
|
||||
if err != nil {
|
||||
title := fmt.Sprintf("IMAGE (%s) PULL ERROR", img.selectedID)
|
||||
|
||||
img.displayError(title, err)
|
||||
img.appFocusHandler()
|
||||
}
|
||||
|
||||
img.progressDialog.Hide()
|
||||
}
|
||||
|
||||
go pull(image)
|
||||
|
|
|
@ -2,9 +2,7 @@ package images
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/containers/podman-tui/pdcs/images"
|
||||
"github.com/containers/podman-tui/ui/style"
|
||||
|
@ -12,19 +10,6 @@ import (
|
|||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
// SortView sorts data view called from sort dialog.
|
||||
func (img *Images) SortView(option string, ascending bool) {
|
||||
log.Debug().Msgf("view: images sort by %s", option)
|
||||
|
||||
img.imagesList.mu.Lock()
|
||||
defer img.imagesList.mu.Unlock()
|
||||
|
||||
img.imagesList.sortBy = option
|
||||
img.imagesList.ascending = ascending
|
||||
|
||||
sort.Sort(imgListSorted{img.imagesList.report, option, ascending})
|
||||
}
|
||||
|
||||
// UpdateData retrieves images list data.
|
||||
func (img *Images) UpdateData() {
|
||||
images, err := images.List()
|
||||
|
@ -39,8 +24,6 @@ func (img *Images) UpdateData() {
|
|||
img.imagesList.mu.Lock()
|
||||
defer img.imagesList.mu.Unlock()
|
||||
|
||||
sort.Sort(imgListSorted{images, img.imagesList.sortBy, img.imagesList.ascending})
|
||||
|
||||
img.imagesList.report = images
|
||||
}
|
||||
|
||||
|
@ -78,41 +61,3 @@ func (img *Images) ClearData() {
|
|||
|
||||
img.table.SetTitle(fmt.Sprintf("[::b]%s[0]", strings.ToUpper(img.title)))
|
||||
}
|
||||
|
||||
type lprSort []images.ImageListReporter
|
||||
|
||||
func (a lprSort) Len() int { return len(a) }
|
||||
func (a lprSort) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||
|
||||
type imgListSorted struct {
|
||||
lprSort
|
||||
|
||||
option string
|
||||
ascending bool
|
||||
}
|
||||
|
||||
func (a imgListSorted) Less(i, j int) bool {
|
||||
switch a.option {
|
||||
case "size":
|
||||
if a.ascending {
|
||||
return a.lprSort[i].Size < a.lprSort[j].Size
|
||||
}
|
||||
|
||||
return a.lprSort[i].Size > a.lprSort[j].Size
|
||||
case "created":
|
||||
icreated := time.Unix(a.lprSort[i].Created, 0).UTC()
|
||||
jcreated := time.Unix(a.lprSort[j].Created, 0).UTC()
|
||||
|
||||
if a.ascending {
|
||||
return icreated.After(jcreated)
|
||||
}
|
||||
|
||||
return icreated.Before(jcreated)
|
||||
}
|
||||
|
||||
if a.ascending {
|
||||
return a.lprSort[i].Repository < a.lprSort[j].Repository
|
||||
}
|
||||
|
||||
return a.lprSort[i].Repository > a.lprSort[j].Repository
|
||||
}
|
||||
|
|
|
@ -5,9 +5,9 @@ import (
|
|||
)
|
||||
|
||||
// Draw draws this primitive onto the screen.
|
||||
func (img *Images) Draw(screen tcell.Screen) {
|
||||
img.DrawForSubclass(screen, img)
|
||||
img.SetBorder(false)
|
||||
func (img *Images) Draw(screen tcell.Screen) { //nolint:cyclop
|
||||
img.Box.DrawForSubclass(screen, img)
|
||||
img.Box.SetBorder(false)
|
||||
|
||||
imagewViewX, imagewViewY, imagewViewW, imagewViewH := img.GetInnerRect()
|
||||
|
||||
|
@ -18,21 +18,108 @@ func (img *Images) Draw(screen tcell.Screen) {
|
|||
img.table.Draw(screen)
|
||||
x, y, width, height := img.table.GetInnerRect()
|
||||
|
||||
for _, dialog := range img.getInnerDialogs() {
|
||||
if dialog.IsDisplay() {
|
||||
dialog.SetRect(x, y, width, height)
|
||||
dialog.Draw(screen)
|
||||
// error dialog
|
||||
if img.errorDialog.IsDisplay() {
|
||||
img.errorDialog.SetRect(x, y, width, height)
|
||||
img.errorDialog.Draw(screen)
|
||||
|
||||
break
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
for _, dialog := range img.getInnerTopDialogs() {
|
||||
if dialog.IsDisplay() {
|
||||
dialog.SetRect(x, y, width, height)
|
||||
dialog.Draw(screen)
|
||||
// command dialog
|
||||
if img.cmdDialog.IsDisplay() {
|
||||
img.cmdDialog.SetRect(x, y, width, height)
|
||||
img.cmdDialog.Draw(screen)
|
||||
|
||||
break
|
||||
return
|
||||
}
|
||||
|
||||
// command input dialog
|
||||
if img.cmdInputDialog.IsDisplay() {
|
||||
img.cmdInputDialog.SetRect(x, y, width, height)
|
||||
img.cmdInputDialog.Draw(screen)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// message dialog
|
||||
if img.messageDialog.IsDisplay() {
|
||||
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
|
||||
}
|
||||
|
||||
// confirm dialog
|
||||
if img.confirmDialog.IsDisplay() {
|
||||
img.confirmDialog.SetRect(x, y, width, height)
|
||||
img.confirmDialog.Draw(screen)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// search dialog
|
||||
if img.searchDialog.IsDisplay() {
|
||||
img.searchDialog.SetRect(imagewViewX, imagewViewY, imagewViewW, imagewViewH)
|
||||
img.searchDialog.Draw(screen)
|
||||
}
|
||||
|
||||
// progress dialog
|
||||
if img.progressDialog.IsDisplay() {
|
||||
img.progressDialog.SetRect(x, y, width, height)
|
||||
img.progressDialog.Draw(screen)
|
||||
}
|
||||
|
||||
// history dialog
|
||||
if img.historyDialog.IsDisplay() {
|
||||
img.historyDialog.SetRect(imagewViewX, imagewViewY, imagewViewW, imagewViewH)
|
||||
img.historyDialog.Draw(screen)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// build dialog
|
||||
if img.buildDialog.IsDisplay() {
|
||||
img.buildDialog.SetRect(x, y, width, height)
|
||||
img.buildDialog.Draw(screen)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// build progress dialog
|
||||
if img.buildPrgDialog.IsDisplay() {
|
||||
img.buildPrgDialog.SetRect(x, y, width, height)
|
||||
img.buildPrgDialog.Draw(screen)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// save dialog
|
||||
if img.saveDialog.IsDisplay() {
|
||||
img.saveDialog.SetRect(x, y, width, height)
|
||||
img.saveDialog.Draw(screen)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// import dialog
|
||||
if img.importDialog.IsDisplay() {
|
||||
img.importDialog.SetRect(x, y, width, height)
|
||||
img.importDialog.Draw(screen)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// push dialog
|
||||
if img.pushDialog.IsDisplay() {
|
||||
img.pushDialog.SetRect(x, y, width, height)
|
||||
img.pushDialog.Draw(screen)
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,6 @@ import (
|
|||
"github.com/containers/podman-tui/ui/dialogs"
|
||||
"github.com/containers/podman-tui/ui/images/imgdialogs"
|
||||
"github.com/containers/podman-tui/ui/style"
|
||||
"github.com/containers/podman-tui/ui/utils"
|
||||
"github.com/rivo/tview"
|
||||
)
|
||||
|
||||
|
@ -38,22 +37,20 @@ var (
|
|||
// Images implements the images primitive.
|
||||
type Images struct {
|
||||
*tview.Box
|
||||
|
||||
title string
|
||||
headers []string
|
||||
table *tview.Table
|
||||
errorDialog *dialogs.ErrorDialog
|
||||
progressDialog *dialogs.ProgressDialog
|
||||
cmdDialog *dialogs.CommandDialog
|
||||
cmdInputDialog *dialogs.SimpleInputDialog
|
||||
messageDialog *dialogs.MessageDialog
|
||||
confirmDialog *dialogs.ConfirmDialog
|
||||
sortDialog *dialogs.SortDialog
|
||||
searchDialog *imgdialogs.ImageSearchDialog
|
||||
historyDialog *imgdialogs.ImageHistoryDialog
|
||||
importDialog *imgdialogs.ImageImportDialog
|
||||
buildDialog *imgdialogs.ImageBuildDialog
|
||||
buildPrgDialog *imgdialogs.ImageBuildProgressDialog
|
||||
progressDialog *dialogs.ProgressDialog
|
||||
saveDialog *imgdialogs.ImageSaveDialog
|
||||
pushDialog *imgdialogs.ImagePushDialog
|
||||
imagesList imageListReport
|
||||
|
@ -65,10 +62,8 @@ type Images struct {
|
|||
}
|
||||
|
||||
type imageListReport struct {
|
||||
mu sync.Mutex
|
||||
report []images.ImageListReporter
|
||||
sortBy string
|
||||
ascending bool
|
||||
mu sync.Mutex
|
||||
report []images.ImageListReporter
|
||||
}
|
||||
|
||||
// NewImages returns images page view.
|
||||
|
@ -78,11 +73,9 @@ func NewImages() *Images {
|
|||
title: "images",
|
||||
headers: []string{"repository", "tag", "image id", "created at", "size"},
|
||||
errorDialog: dialogs.NewErrorDialog(),
|
||||
progressDialog: dialogs.NewProgressDialog(),
|
||||
cmdInputDialog: dialogs.NewSimpleInputDialog(""),
|
||||
messageDialog: dialogs.NewMessageDialog(""),
|
||||
confirmDialog: dialogs.NewConfirmDialog(),
|
||||
sortDialog: dialogs.NewSortDialog([]string{"repository", "created", "size"}, 1),
|
||||
searchDialog: imgdialogs.NewImageSearchDialog(),
|
||||
historyDialog: imgdialogs.NewImageHistoryDialog(),
|
||||
importDialog: imgdialogs.NewImageImportDialog(),
|
||||
|
@ -90,7 +83,7 @@ func NewImages() *Images {
|
|||
buildPrgDialog: imgdialogs.NewImageBuildProgressDialog(),
|
||||
saveDialog: imgdialogs.NewImageSaveDialog(),
|
||||
pushDialog: imgdialogs.NewImagePushDialog(),
|
||||
imagesList: imageListReport{sortBy: "created", ascending: true},
|
||||
progressDialog: dialogs.NewProgressDialog(),
|
||||
}
|
||||
|
||||
images.cmdDialog = dialogs.NewCommandDialog([][]string{
|
||||
|
@ -158,7 +151,7 @@ func NewImages() *Images {
|
|||
images.confirmDialog.Hide()
|
||||
|
||||
switch images.confirmData {
|
||||
case utils.PruneCommandLabel:
|
||||
case "prune":
|
||||
images.prune()
|
||||
case "rm":
|
||||
images.remove()
|
||||
|
@ -212,10 +205,6 @@ func NewImages() *Images {
|
|||
images.pushDialog.SetPushFunc(images.push)
|
||||
images.pushDialog.SetCancelFunc(images.pushDialog.Hide)
|
||||
|
||||
// set sort dialog functions
|
||||
images.sortDialog.SetSelectFunc(images.SortView)
|
||||
images.sortDialog.SetCancelFunc(images.sortDialog.Hide)
|
||||
|
||||
return images
|
||||
}
|
||||
|
||||
|
@ -230,89 +219,155 @@ func (img *Images) GetTitle() string {
|
|||
}
|
||||
|
||||
// HasFocus returns whether or not this primitive has focus.
|
||||
func (img *Images) HasFocus() bool {
|
||||
if img.SubDialogHasFocus() {
|
||||
func (img *Images) HasFocus() bool { //nolint:cyclop
|
||||
if img.table.HasFocus() || img.messageDialog.HasFocus() {
|
||||
return true
|
||||
}
|
||||
|
||||
if img.table.HasFocus() || img.Box.HasFocus() {
|
||||
if img.cmdDialog.HasFocus() || img.cmdInputDialog.HasFocus() {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
if img.confirmDialog.HasFocus() || img.errorDialog.HasFocus() {
|
||||
return true
|
||||
}
|
||||
|
||||
if img.searchDialog.HasFocus() || img.progressDialog.HasFocus() {
|
||||
return true
|
||||
}
|
||||
|
||||
if img.historyDialog.HasFocus() || img.buildDialog.HasFocus() {
|
||||
return true
|
||||
}
|
||||
|
||||
if img.buildPrgDialog.HasFocus() || img.saveDialog.HasFocus() {
|
||||
return true
|
||||
}
|
||||
|
||||
if img.importDialog.HasFocus() || img.pushDialog.HasFocus() {
|
||||
return true
|
||||
}
|
||||
|
||||
return img.Box.HasFocus()
|
||||
}
|
||||
|
||||
// SubDialogHasFocus returns whether or not sub dialog primitive has focus.
|
||||
func (img *Images) SubDialogHasFocus() bool {
|
||||
for _, dialog := range img.getInnerDialogs() {
|
||||
if dialog.HasFocus() {
|
||||
return true
|
||||
}
|
||||
func (img *Images) SubDialogHasFocus() bool { //nolint:cyclop
|
||||
if img.historyDialog.HasFocus() || img.messageDialog.HasFocus() {
|
||||
return true
|
||||
}
|
||||
|
||||
for _, dialog := range img.getInnerTopDialogs() {
|
||||
if dialog.HasFocus() {
|
||||
return true
|
||||
}
|
||||
if img.cmdDialog.HasFocus() || img.cmdInputDialog.HasFocus() {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
if img.confirmDialog.HasFocus() || img.errorDialog.HasFocus() {
|
||||
return true
|
||||
}
|
||||
|
||||
if img.searchDialog.HasFocus() || img.progressDialog.HasFocus() {
|
||||
return true
|
||||
}
|
||||
|
||||
if img.buildDialog.HasFocus() || img.buildPrgDialog.HasFocus() {
|
||||
return true
|
||||
}
|
||||
|
||||
if img.saveDialog.HasFocus() || img.importDialog.HasFocus() {
|
||||
return true
|
||||
}
|
||||
|
||||
return img.pushDialog.HasFocus()
|
||||
}
|
||||
|
||||
// Focus is called when this primitive receives focus.
|
||||
func (img *Images) Focus(delegate func(p tview.Primitive)) {
|
||||
// since error and confirm dialog can get focus on top of other dialogs
|
||||
func (img *Images) Focus(delegate func(p tview.Primitive)) { //nolint:cyclop
|
||||
// error dialog
|
||||
if img.errorDialog.IsDisplay() {
|
||||
delegate(img.errorDialog)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// command dialog
|
||||
if img.cmdDialog.IsDisplay() {
|
||||
delegate(img.cmdDialog)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// command input dialog
|
||||
if img.cmdInputDialog.IsDisplay() {
|
||||
delegate(img.cmdInputDialog)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// message dialog
|
||||
if img.messageDialog.IsDisplay() {
|
||||
delegate(img.messageDialog)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// confirm dialog
|
||||
if img.confirmDialog.IsDisplay() {
|
||||
delegate(img.confirmDialog)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
for _, dialog := range img.getInnerDialogs() {
|
||||
if dialog.IsDisplay() {
|
||||
delegate(dialog)
|
||||
// search dialog
|
||||
if img.searchDialog.IsDisplay() {
|
||||
delegate(img.searchDialog)
|
||||
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
for _, dialog := range img.getInnerTopDialogs() {
|
||||
if dialog.IsDisplay() {
|
||||
delegate(dialog)
|
||||
// history dialog
|
||||
if img.historyDialog.IsDisplay() {
|
||||
delegate(img.historyDialog)
|
||||
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// build dialog
|
||||
if img.buildDialog.IsDisplay() {
|
||||
delegate(img.buildDialog)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// build progress dialog
|
||||
if img.buildPrgDialog.IsDisplay() {
|
||||
delegate(img.buildPrgDialog)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// save dialog
|
||||
if img.saveDialog.IsDisplay() {
|
||||
delegate(img.saveDialog)
|
||||
|
||||
return
|
||||
}
|
||||
// import dialog
|
||||
if img.importDialog.IsDisplay() {
|
||||
delegate(img.importDialog)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// push dialog
|
||||
if img.pushDialog.IsDisplay() {
|
||||
delegate(img.pushDialog)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
delegate(img.table)
|
||||
}
|
||||
|
||||
// HideAllDialogs hides all sub dialogs.
|
||||
func (img *Images) HideAllDialogs() {
|
||||
for _, dialog := range img.getInnerDialogs() {
|
||||
if dialog.IsDisplay() {
|
||||
dialog.Hide()
|
||||
}
|
||||
}
|
||||
|
||||
for _, dialog := range img.getInnerTopDialogs() {
|
||||
if dialog.IsDisplay() {
|
||||
dialog.Hide()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SetFastRefreshChannel sets channel for fastRefresh func.
|
||||
func (img *Images) SetFastRefreshChannel(refresh chan bool) {
|
||||
img.fastRefreshChan = refresh
|
||||
}
|
||||
|
||||
func (img *Images) getSelectedItem() (string, string) {
|
||||
if img.table.GetRowCount() <= 1 {
|
||||
return "", ""
|
||||
|
@ -327,30 +382,62 @@ func (img *Images) getSelectedItem() (string, string) {
|
|||
return imageID, imageName
|
||||
}
|
||||
|
||||
func (img *Images) getInnerDialogs() []utils.UIDialog {
|
||||
dialogs := []utils.UIDialog{
|
||||
img.cmdDialog,
|
||||
img.cmdInputDialog,
|
||||
img.messageDialog,
|
||||
img.searchDialog,
|
||||
img.historyDialog,
|
||||
img.importDialog,
|
||||
img.buildDialog,
|
||||
img.buildPrgDialog,
|
||||
img.saveDialog,
|
||||
img.pushDialog,
|
||||
img.sortDialog,
|
||||
// HideAllDialogs hides all sub dialogs.
|
||||
func (img *Images) HideAllDialogs() { //nolint:cyclop
|
||||
if img.errorDialog.IsDisplay() {
|
||||
img.errorDialog.Hide()
|
||||
}
|
||||
|
||||
return dialogs
|
||||
}
|
||||
|
||||
func (img *Images) getInnerTopDialogs() []utils.UIDialog {
|
||||
dialogs := []utils.UIDialog{
|
||||
img.errorDialog,
|
||||
img.progressDialog,
|
||||
img.confirmDialog,
|
||||
if img.progressDialog.IsDisplay() {
|
||||
img.progressDialog.Hide()
|
||||
}
|
||||
|
||||
return dialogs
|
||||
if img.cmdDialog.IsDisplay() {
|
||||
img.cmdDialog.Hide()
|
||||
}
|
||||
|
||||
if img.cmdInputDialog.IsDisplay() {
|
||||
img.cmdInputDialog.Hide()
|
||||
}
|
||||
|
||||
if img.messageDialog.IsDisplay() {
|
||||
img.messageDialog.Hide()
|
||||
}
|
||||
|
||||
if img.searchDialog.IsDisplay() {
|
||||
img.searchDialog.Hide()
|
||||
}
|
||||
|
||||
if img.confirmDialog.IsDisplay() {
|
||||
img.confirmDialog.Hide()
|
||||
}
|
||||
|
||||
if img.historyDialog.IsDisplay() {
|
||||
img.historyDialog.Hide()
|
||||
}
|
||||
|
||||
if img.buildDialog.IsDisplay() {
|
||||
img.buildDialog.Hide()
|
||||
}
|
||||
|
||||
if img.buildPrgDialog.IsDisplay() {
|
||||
img.buildPrgDialog.Hide()
|
||||
}
|
||||
|
||||
if img.saveDialog.IsDisplay() {
|
||||
img.saveDialog.Hide()
|
||||
}
|
||||
|
||||
if img.importDialog.IsDisplay() {
|
||||
img.importDialog.Hide()
|
||||
}
|
||||
|
||||
if img.pushDialog.IsDisplay() {
|
||||
img.pushDialog.Hide()
|
||||
}
|
||||
}
|
||||
|
||||
// SetFastRefreshChannel sets channel for fastRefresh func.
|
||||
func (img *Images) SetFastRefreshChannel(refresh chan bool) {
|
||||
img.fastRefreshChan = refresh
|
||||
}
|
||||
|
|
|
@ -71,7 +71,6 @@ const (
|
|||
// ImageBuildDialog represents image build dialog primitive.
|
||||
type ImageBuildDialog struct {
|
||||
*tview.Box
|
||||
|
||||
layout *tview.Flex
|
||||
form *tview.Form
|
||||
categoryLabels []string
|
||||
|
@ -491,6 +490,117 @@ func NewImageBuildDialog() *ImageBuildDialog { //nolint:maintidx
|
|||
return buildDialog
|
||||
}
|
||||
|
||||
func (d *ImageBuildDialog) setupLayout() {
|
||||
bgColor := style.DialogBgColor
|
||||
// basic info page
|
||||
d.basicInfoPage.SetDirection(tview.FlexRow)
|
||||
d.basicInfoPage.AddItem(d.contextDirectoryPath, 1, 0, true)
|
||||
d.basicInfoPage.AddItem(utils.EmptyBoxSpace(bgColor), 1, 0, true)
|
||||
d.basicInfoPage.AddItem(d.containerFilePath, 1, 0, true)
|
||||
d.basicInfoPage.AddItem(utils.EmptyBoxSpace(bgColor), 1, 0, true)
|
||||
d.basicInfoPage.AddItem(d.pullPolicyField, 1, 0, true)
|
||||
d.basicInfoPage.AddItem(utils.EmptyBoxSpace(bgColor), 1, 0, true)
|
||||
d.basicInfoPage.AddItem(d.tagField, 1, 0, true)
|
||||
d.basicInfoPage.AddItem(utils.EmptyBoxSpace(bgColor), 1, 0, true)
|
||||
d.basicInfoPage.AddItem(d.registryField, 1, 0, true)
|
||||
d.basicInfoPage.SetBackgroundColor(bgColor)
|
||||
|
||||
// layers setup page
|
||||
secondRowLayout := tview.NewFlex().SetDirection(tview.FlexColumn)
|
||||
secondRowLayout.SetBackgroundColor(bgColor)
|
||||
secondRowLayout.AddItem(d.formatField, 0, 2, true) //nolint:mnd
|
||||
secondRowLayout.AddItem(d.SquashField, 0, 1, true)
|
||||
secondRowLayout.AddItem(d.layersField, 0, 1, true)
|
||||
secondRowLayout.AddItem(d.noCacheField, 0, 1, true)
|
||||
|
||||
cntRmRowLayout := tview.NewFlex().SetDirection(tview.FlexColumn)
|
||||
cntRmRowLayout.SetBackgroundColor(bgColor)
|
||||
cntRmRowLayout.AddItem(d.forceRemoveCntField, 0, 1, true)
|
||||
cntRmRowLayout.AddItem(d.removeCntField, 0, 2, true) //nolint:mnd
|
||||
|
||||
// build setup page
|
||||
d.buildInfoPage.SetDirection(tview.FlexRow)
|
||||
d.buildInfoPage.AddItem(d.buildArgsField, 1, 0, true)
|
||||
d.buildInfoPage.AddItem(utils.EmptyBoxSpace(bgColor), 1, 0, true)
|
||||
d.buildInfoPage.AddItem(secondRowLayout, 1, 0, true)
|
||||
d.buildInfoPage.AddItem(utils.EmptyBoxSpace(bgColor), 1, 0, true)
|
||||
d.buildInfoPage.AddItem(d.labelsField, 1, 0, true)
|
||||
d.buildInfoPage.AddItem(utils.EmptyBoxSpace(bgColor), 1, 0, true)
|
||||
d.buildInfoPage.AddItem(d.annotationsField, 1, 0, true)
|
||||
d.buildInfoPage.AddItem(utils.EmptyBoxSpace(bgColor), 1, 0, true)
|
||||
d.buildInfoPage.AddItem(cntRmRowLayout, 1, 0, true)
|
||||
d.buildInfoPage.SetBackgroundColor(bgColor)
|
||||
|
||||
// security options page
|
||||
d.securityOptsPage.SetDirection(tview.FlexRow)
|
||||
d.securityOptsPage.AddItem(d.selinuxLabelField, 1, 0, true)
|
||||
d.securityOptsPage.AddItem(utils.EmptyBoxSpace(bgColor), 1, 0, true)
|
||||
d.securityOptsPage.AddItem(d.apparmorProfileField, 1, 0, true)
|
||||
d.securityOptsPage.AddItem(utils.EmptyBoxSpace(bgColor), 1, 0, true)
|
||||
d.securityOptsPage.AddItem(d.seccompProfilePathField, 1, 0, true)
|
||||
|
||||
// networking setup page
|
||||
netFirstRow := tview.NewFlex().SetDirection(tview.FlexColumn)
|
||||
netFirstRow.SetBackgroundColor(bgColor)
|
||||
netFirstRow.AddItem(d.networkField, 0, 1, true)
|
||||
netFirstRow.AddItem(d.httpProxyField, 0, 1, true)
|
||||
d.networkingPage.SetDirection(tview.FlexRow)
|
||||
d.networkingPage.AddItem(netFirstRow, 1, 0, true)
|
||||
d.networkingPage.AddItem(utils.EmptyBoxSpace(bgColor), 1, 0, true)
|
||||
d.networkingPage.AddItem(d.addHostField, 1, 0, true)
|
||||
d.networkingPage.AddItem(utils.EmptyBoxSpace(bgColor), 1, 0, true)
|
||||
d.networkingPage.AddItem(d.dnsServersField, 1, 0, true)
|
||||
d.networkingPage.AddItem(utils.EmptyBoxSpace(bgColor), 1, 0, true)
|
||||
d.networkingPage.AddItem(d.dnsOptionsField, 1, 0, true)
|
||||
d.networkingPage.AddItem(utils.EmptyBoxSpace(bgColor), 1, 0, true)
|
||||
d.networkingPage.AddItem(d.dnsSearchField, 1, 0, true)
|
||||
d.networkingPage.SetBackgroundColor(bgColor)
|
||||
|
||||
// capability page
|
||||
d.capabilityPage.SetDirection(tview.FlexRow)
|
||||
d.capabilityPage.AddItem(d.addCapabilityField, 1, 0, true)
|
||||
d.capabilityPage.AddItem(utils.EmptyBoxSpace(bgColor), 1, 0, true)
|
||||
d.capabilityPage.AddItem(d.removeCapabilityField, 1, 0, true)
|
||||
|
||||
// cpu and memory page
|
||||
cpuSetRow := tview.NewFlex().SetDirection(tview.FlexColumn)
|
||||
cpuSetRow.AddItem(d.cpuSetCpusField, 0, 1, true)
|
||||
cpuSetRow.AddItem(d.cpuSetMemsField, 0, 1, true)
|
||||
|
||||
// memory and swap
|
||||
memSwapRow := tview.NewFlex().SetDirection(tview.FlexColumn)
|
||||
memSwapRow.AddItem(d.memoryField, 0, 1, true)
|
||||
memSwapRow.AddItem(d.memorySwapField, 0, 1, true)
|
||||
|
||||
d.cpuMemoryPage.SetDirection(tview.FlexRow)
|
||||
d.cpuMemoryPage.AddItem(d.cpuPeriodField, 0, 1, true)
|
||||
d.cpuMemoryPage.AddItem(utils.EmptyBoxSpace(bgColor), 0, 1, true)
|
||||
d.cpuMemoryPage.AddItem(d.cpuQuataField, 0, 1, true)
|
||||
d.cpuMemoryPage.AddItem(utils.EmptyBoxSpace(bgColor), 0, 1, true)
|
||||
d.cpuMemoryPage.AddItem(d.cpuSharesField, 0, 1, true)
|
||||
d.cpuMemoryPage.AddItem(utils.EmptyBoxSpace(bgColor), 0, 1, true)
|
||||
d.cpuMemoryPage.AddItem(cpuSetRow, 0, 1, true)
|
||||
d.cpuMemoryPage.AddItem(utils.EmptyBoxSpace(bgColor), 0, 1, true)
|
||||
d.cpuMemoryPage.AddItem(memSwapRow, 0, 1, true)
|
||||
|
||||
// adding category pages
|
||||
d.categoryPages.AddPage(d.categoryLabels[buildDialogBasicInfoPageIndex], d.basicInfoPage, true, true)
|
||||
d.categoryPages.AddPage(d.categoryLabels[buildDialogBuildInfoPageIndex], d.buildInfoPage, true, true)
|
||||
d.categoryPages.AddPage(d.categoryLabels[buildDialogCapabilityPageIndex], d.capabilityPage, true, true)
|
||||
d.categoryPages.AddPage(d.categoryLabels[buildDialogCPUMemoryPageIndex], d.cpuMemoryPage, true, true)
|
||||
d.categoryPages.AddPage(d.categoryLabels[buildDialogNetworkingPageIndex], d.networkingPage, true, true)
|
||||
d.categoryPages.AddPage(d.categoryLabels[buildDialogSecurityOptsPageIndex], d.securityOptsPage, true, true)
|
||||
|
||||
// add it to layout.
|
||||
_, layoutWidth := utils.AlignStringListWidth(d.categoryLabels)
|
||||
layout := tview.NewFlex().SetDirection(tview.FlexColumn)
|
||||
layout.AddItem(d.categories, layoutWidth+6, 0, true) //nolint:mnd
|
||||
layout.AddItem(d.categoryPages, 0, 1, true)
|
||||
layout.SetBackgroundColor(bgColor)
|
||||
|
||||
d.layout.AddItem(layout, 0, 1, true)
|
||||
}
|
||||
|
||||
// Display displays this primitive.
|
||||
func (d *ImageBuildDialog) Display() {
|
||||
d.focusElement = buildDialogContextDirectoryPathFieldFocus
|
||||
|
@ -645,7 +755,7 @@ func (d *ImageBuildDialog) InputHandler() func(event *tcell.EventKey, setFocus f
|
|||
log.Debug().Msgf("image build dialog: event %v received", event)
|
||||
|
||||
if event.Key() == utils.CloseDialogKey.Key {
|
||||
if !d.pullPolicyField.HasFocus() && !d.networkField.HasFocus() && !d.formatField.HasFocus() {
|
||||
if !(d.pullPolicyField.HasFocus() || d.networkField.HasFocus() || d.formatField.HasFocus()) {
|
||||
d.cancelHandler()
|
||||
|
||||
return
|
||||
|
@ -811,8 +921,8 @@ func (d *ImageBuildDialog) Draw(screen tcell.Screen) {
|
|||
return
|
||||
}
|
||||
|
||||
d.DrawForSubclass(screen, d)
|
||||
x, y, width, height := d.GetInnerRect()
|
||||
d.Box.DrawForSubclass(screen, d)
|
||||
x, y, width, height := d.Box.GetInnerRect()
|
||||
d.layout.SetRect(x, y, width, height)
|
||||
d.layout.Draw(screen)
|
||||
}
|
||||
|
@ -835,352 +945,6 @@ func (d *ImageBuildDialog) SetBuildFunc(handler func()) *ImageBuildDialog {
|
|||
return d
|
||||
}
|
||||
|
||||
// ImageBuildOptions returns image build options.
|
||||
func (d *ImageBuildDialog) ImageBuildOptions() (images.ImageBuildOptions, error) { //nolint:gocognit,gocyclo,cyclop,maintidx,lll
|
||||
var (
|
||||
memoryLimit int64
|
||||
memorySwap int64
|
||||
cpuPeriod uint64
|
||||
cpuQuota int64
|
||||
cpuShares uint64
|
||||
cpuSetCpus string
|
||||
cpuSetMems string
|
||||
containerFiles []string
|
||||
dnsServers []string
|
||||
dnsOptions []string
|
||||
dnsSearchDomains []string
|
||||
addHost []string
|
||||
labelOpts []string
|
||||
apparmorProfile string
|
||||
seccompProfilePath string
|
||||
)
|
||||
|
||||
// basic info page
|
||||
// Containerfiles
|
||||
for _, cntFile := range strings.Split(strings.TrimSpace(d.containerFilePath.GetText()), " ") {
|
||||
if cntFile != "" {
|
||||
cFile, err := utils.ResolveHomeDir(cntFile)
|
||||
if err != nil {
|
||||
return images.ImageBuildOptions{}, err
|
||||
}
|
||||
|
||||
containerFiles = append(containerFiles, cFile)
|
||||
}
|
||||
}
|
||||
|
||||
opts := images.ImageBuildOptions{
|
||||
ContainerFiles: containerFiles,
|
||||
BuildOptions: entities.BuildOptions{},
|
||||
}
|
||||
|
||||
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, strings.TrimSpace(d.tagField.GetText()))
|
||||
opts.BuildOptions.Registry = strings.TrimSpace(d.registryField.GetText())
|
||||
|
||||
_, pullOption := d.pullPolicyField.GetCurrentOption()
|
||||
switch pullOption {
|
||||
case "missing":
|
||||
opts.BuildOptions.PullPolicy = define.PullIfMissing
|
||||
case "always":
|
||||
opts.BuildOptions.PullPolicy = define.PullAlways
|
||||
case "ifnewer":
|
||||
opts.BuildOptions.PullPolicy = define.PullIfNewer
|
||||
case "never":
|
||||
opts.BuildOptions.PullPolicy = define.PullNever
|
||||
}
|
||||
|
||||
_, format := d.formatField.GetCurrentOption()
|
||||
switch format {
|
||||
case "oci":
|
||||
opts.BuildOptions.OutputFormat = define.OCIv1ImageManifest
|
||||
case "docker":
|
||||
opts.BuildOptions.OutputFormat = define.Dockerv2ImageManifest
|
||||
}
|
||||
|
||||
// build settings
|
||||
opts.BuildOptions.Squash = d.SquashField.IsChecked()
|
||||
opts.BuildOptions.Layers = d.layersField.IsChecked()
|
||||
opts.BuildOptions.NoCache = d.noCacheField.IsChecked()
|
||||
opts.BuildOptions.RemoveIntermediateCtrs = d.removeCntField.IsChecked()
|
||||
opts.BuildOptions.ForceRmIntermediateCtrs = d.forceRemoveCntField.IsChecked()
|
||||
|
||||
labels := strings.TrimSpace(d.labelsField.GetText())
|
||||
if labels != "" {
|
||||
opts.BuildOptions.Labels = strings.Split(labels, " ")
|
||||
}
|
||||
|
||||
annotations := strings.TrimSpace(d.annotationsField.GetText())
|
||||
if annotations != "" {
|
||||
opts.BuildOptions.Annotations = strings.Split(annotations, " ")
|
||||
}
|
||||
|
||||
// capability pages
|
||||
addCap := strings.TrimSpace(d.addCapabilityField.GetText())
|
||||
if addCap != "" {
|
||||
opts.BuildOptions.AddCapabilities = strings.Split(addCap, " ")
|
||||
}
|
||||
|
||||
removeCap := strings.TrimSpace(d.removeCapabilityField.GetText())
|
||||
if removeCap != "" {
|
||||
opts.BuildOptions.DropCapabilities = strings.Split(removeCap, " ")
|
||||
}
|
||||
|
||||
// cpu and memory page
|
||||
opts.BuildOptions.CommonBuildOpts = &define.CommonBuildOptions{}
|
||||
|
||||
cpuPeriodVal := d.cpuPeriodField.GetText()
|
||||
if cpuPeriodVal != "" {
|
||||
period, err := strconv.Atoi(cpuPeriodVal)
|
||||
if err != nil {
|
||||
return images.ImageBuildOptions{}, fmt.Errorf("invalid CPU period value %q %w", cpuPeriodVal, err)
|
||||
}
|
||||
|
||||
cpuPeriod = uint64(period) //nolint:gosec
|
||||
}
|
||||
|
||||
cpuQuotaVal := d.cpuQuataField.GetText()
|
||||
if cpuQuotaVal != "" {
|
||||
quota, err := strconv.Atoi(cpuQuotaVal)
|
||||
if err != nil {
|
||||
return images.ImageBuildOptions{}, fmt.Errorf("invalid CPU quota value %q %w", cpuQuotaVal, err)
|
||||
}
|
||||
|
||||
cpuQuota = int64(quota)
|
||||
}
|
||||
|
||||
cpuSharesVal := d.cpuSharesField.GetText()
|
||||
if cpuSharesVal != "" {
|
||||
shares, err := strconv.Atoi(cpuSharesVal)
|
||||
if err != nil {
|
||||
return images.ImageBuildOptions{}, fmt.Errorf("invalid CPU quota value %q %w", cpuSharesVal, err)
|
||||
}
|
||||
|
||||
cpuShares = uint64(shares) //nolint:gosec
|
||||
}
|
||||
|
||||
cpuSetCpusVal := d.cpuSetCpusField.GetText()
|
||||
if cpuSetCpusVal != "" {
|
||||
cpuSetCpus = cpuSetCpusVal
|
||||
}
|
||||
|
||||
cpuSetMemsVal := d.cpuSetMemsField.GetText()
|
||||
if cpuSetMemsVal != "" {
|
||||
cpuSetMems = cpuSetMemsVal
|
||||
}
|
||||
|
||||
memoryVal := d.memoryField.GetText()
|
||||
if memoryVal != "" {
|
||||
memory, err := strconv.Atoi(memoryVal)
|
||||
if err != nil {
|
||||
return images.ImageBuildOptions{}, fmt.Errorf("invalid memory value %q %w", memoryVal, err)
|
||||
}
|
||||
|
||||
memoryLimit = int64(memory)
|
||||
}
|
||||
|
||||
memorySwapVal := d.memorySwapField.GetText()
|
||||
if memorySwapVal != "" {
|
||||
swap, err := strconv.Atoi(memorySwapVal)
|
||||
if err != nil {
|
||||
return images.ImageBuildOptions{}, fmt.Errorf("invalid memory swap value %q %w", memorySwapVal, err)
|
||||
}
|
||||
|
||||
memorySwap = int64(swap)
|
||||
}
|
||||
|
||||
// networking page
|
||||
// network policy
|
||||
_, configureNetwork := d.networkField.GetCurrentOption()
|
||||
switch configureNetwork {
|
||||
case "NetworkDefault":
|
||||
opts.BuildOptions.ConfigureNetwork = define.NetworkDefault
|
||||
case "NetworkDisabled":
|
||||
opts.BuildOptions.ConfigureNetwork = define.NetworkDisabled
|
||||
case "NetworkEnabled":
|
||||
opts.BuildOptions.ConfigureNetwork = define.NetworkEnabled
|
||||
}
|
||||
// add hosts
|
||||
hosts := strings.TrimSpace(d.addHostField.GetText())
|
||||
if hosts != "" {
|
||||
addHost = strings.Split(hosts, " ")
|
||||
}
|
||||
|
||||
// dns page
|
||||
dnsServersList := strings.TrimSpace(d.dnsServersField.GetText())
|
||||
for _, dns := range strings.Split(dnsServersList, " ") {
|
||||
if dns != "" {
|
||||
dnsServers = append(dnsServers, dns)
|
||||
}
|
||||
}
|
||||
|
||||
for _, do := range strings.Split(d.dnsOptionsField.GetText(), " ") {
|
||||
if do != "" {
|
||||
dnsOptions = append(dnsOptions, do)
|
||||
}
|
||||
}
|
||||
|
||||
for _, ds := range strings.Split(d.dnsSearchField.GetText(), " ") {
|
||||
if ds != "" {
|
||||
dnsSearchDomains = append(dnsSearchDomains, ds)
|
||||
}
|
||||
}
|
||||
|
||||
// security options page
|
||||
for _, selinuxLabel := range strings.Split(d.selinuxLabelField.GetText(), " ") {
|
||||
if selinuxLabel != "" {
|
||||
labelOpts = append(labelOpts, selinuxLabel)
|
||||
}
|
||||
}
|
||||
|
||||
apparmor := strings.TrimSpace(d.apparmorProfileField.GetText())
|
||||
if apparmor != "" {
|
||||
apparmorProfile = apparmor
|
||||
}
|
||||
|
||||
seccomp := strings.TrimSpace(d.seccompProfilePathField.GetText())
|
||||
if seccomp != "" {
|
||||
seccompProfilePath = seccomp
|
||||
}
|
||||
|
||||
commonOpts := &define.CommonBuildOptions{
|
||||
AddHost: addHost,
|
||||
HTTPProxy: d.httpProxyField.IsChecked(),
|
||||
CPUPeriod: cpuPeriod,
|
||||
CPUQuota: cpuQuota,
|
||||
CPUSetCPUs: cpuSetCpus,
|
||||
CPUSetMems: cpuSetMems,
|
||||
CPUShares: cpuShares,
|
||||
DNSServers: dnsServers,
|
||||
DNSOptions: dnsOptions,
|
||||
DNSSearch: dnsSearchDomains,
|
||||
Memory: memoryLimit,
|
||||
MemorySwap: memorySwap,
|
||||
LabelOpts: labelOpts,
|
||||
ApparmorProfile: apparmorProfile,
|
||||
SeccompProfilePath: seccompProfilePath,
|
||||
}
|
||||
|
||||
opts.BuildOptions.CommonBuildOpts = commonOpts
|
||||
|
||||
return opts, nil
|
||||
}
|
||||
|
||||
func (d *ImageBuildDialog) setupLayout() {
|
||||
bgColor := style.DialogBgColor
|
||||
// basic info page
|
||||
d.basicInfoPage.SetDirection(tview.FlexRow)
|
||||
d.basicInfoPage.AddItem(d.contextDirectoryPath, 1, 0, true)
|
||||
d.basicInfoPage.AddItem(utils.EmptyBoxSpace(bgColor), 1, 0, true)
|
||||
d.basicInfoPage.AddItem(d.containerFilePath, 1, 0, true)
|
||||
d.basicInfoPage.AddItem(utils.EmptyBoxSpace(bgColor), 1, 0, true)
|
||||
d.basicInfoPage.AddItem(d.pullPolicyField, 1, 0, true)
|
||||
d.basicInfoPage.AddItem(utils.EmptyBoxSpace(bgColor), 1, 0, true)
|
||||
d.basicInfoPage.AddItem(d.tagField, 1, 0, true)
|
||||
d.basicInfoPage.AddItem(utils.EmptyBoxSpace(bgColor), 1, 0, true)
|
||||
d.basicInfoPage.AddItem(d.registryField, 1, 0, true)
|
||||
d.basicInfoPage.SetBackgroundColor(bgColor)
|
||||
|
||||
// layers setup page
|
||||
secondRowLayout := tview.NewFlex().SetDirection(tview.FlexColumn)
|
||||
secondRowLayout.SetBackgroundColor(bgColor)
|
||||
secondRowLayout.AddItem(d.formatField, 0, 2, true) //nolint:mnd
|
||||
secondRowLayout.AddItem(d.SquashField, 0, 1, true)
|
||||
secondRowLayout.AddItem(d.layersField, 0, 1, true)
|
||||
secondRowLayout.AddItem(d.noCacheField, 0, 1, true)
|
||||
|
||||
cntRmRowLayout := tview.NewFlex().SetDirection(tview.FlexColumn)
|
||||
cntRmRowLayout.SetBackgroundColor(bgColor)
|
||||
cntRmRowLayout.AddItem(d.forceRemoveCntField, 0, 1, true)
|
||||
cntRmRowLayout.AddItem(d.removeCntField, 0, 2, true) //nolint:mnd
|
||||
|
||||
// build setup page
|
||||
d.buildInfoPage.SetDirection(tview.FlexRow)
|
||||
d.buildInfoPage.AddItem(d.buildArgsField, 1, 0, true)
|
||||
d.buildInfoPage.AddItem(utils.EmptyBoxSpace(bgColor), 1, 0, true)
|
||||
d.buildInfoPage.AddItem(secondRowLayout, 1, 0, true)
|
||||
d.buildInfoPage.AddItem(utils.EmptyBoxSpace(bgColor), 1, 0, true)
|
||||
d.buildInfoPage.AddItem(d.labelsField, 1, 0, true)
|
||||
d.buildInfoPage.AddItem(utils.EmptyBoxSpace(bgColor), 1, 0, true)
|
||||
d.buildInfoPage.AddItem(d.annotationsField, 1, 0, true)
|
||||
d.buildInfoPage.AddItem(utils.EmptyBoxSpace(bgColor), 1, 0, true)
|
||||
d.buildInfoPage.AddItem(cntRmRowLayout, 1, 0, true)
|
||||
d.buildInfoPage.SetBackgroundColor(bgColor)
|
||||
|
||||
// security options page
|
||||
d.securityOptsPage.SetDirection(tview.FlexRow)
|
||||
d.securityOptsPage.AddItem(d.selinuxLabelField, 1, 0, true)
|
||||
d.securityOptsPage.AddItem(utils.EmptyBoxSpace(bgColor), 1, 0, true)
|
||||
d.securityOptsPage.AddItem(d.apparmorProfileField, 1, 0, true)
|
||||
d.securityOptsPage.AddItem(utils.EmptyBoxSpace(bgColor), 1, 0, true)
|
||||
d.securityOptsPage.AddItem(d.seccompProfilePathField, 1, 0, true)
|
||||
|
||||
// networking setup page
|
||||
netFirstRow := tview.NewFlex().SetDirection(tview.FlexColumn)
|
||||
netFirstRow.SetBackgroundColor(bgColor)
|
||||
netFirstRow.AddItem(d.networkField, 0, 1, true)
|
||||
netFirstRow.AddItem(d.httpProxyField, 0, 1, true)
|
||||
d.networkingPage.SetDirection(tview.FlexRow)
|
||||
d.networkingPage.AddItem(netFirstRow, 1, 0, true)
|
||||
d.networkingPage.AddItem(utils.EmptyBoxSpace(bgColor), 1, 0, true)
|
||||
d.networkingPage.AddItem(d.addHostField, 1, 0, true)
|
||||
d.networkingPage.AddItem(utils.EmptyBoxSpace(bgColor), 1, 0, true)
|
||||
d.networkingPage.AddItem(d.dnsServersField, 1, 0, true)
|
||||
d.networkingPage.AddItem(utils.EmptyBoxSpace(bgColor), 1, 0, true)
|
||||
d.networkingPage.AddItem(d.dnsOptionsField, 1, 0, true)
|
||||
d.networkingPage.AddItem(utils.EmptyBoxSpace(bgColor), 1, 0, true)
|
||||
d.networkingPage.AddItem(d.dnsSearchField, 1, 0, true)
|
||||
d.networkingPage.SetBackgroundColor(bgColor)
|
||||
|
||||
// capability page
|
||||
d.capabilityPage.SetDirection(tview.FlexRow)
|
||||
d.capabilityPage.AddItem(d.addCapabilityField, 1, 0, true)
|
||||
d.capabilityPage.AddItem(utils.EmptyBoxSpace(bgColor), 1, 0, true)
|
||||
d.capabilityPage.AddItem(d.removeCapabilityField, 1, 0, true)
|
||||
|
||||
// cpu and memory page
|
||||
cpuSetRow := tview.NewFlex().SetDirection(tview.FlexColumn)
|
||||
cpuSetRow.AddItem(d.cpuSetCpusField, 0, 1, true)
|
||||
cpuSetRow.AddItem(d.cpuSetMemsField, 0, 1, true)
|
||||
|
||||
// memory and swap
|
||||
memSwapRow := tview.NewFlex().SetDirection(tview.FlexColumn)
|
||||
memSwapRow.AddItem(d.memoryField, 0, 1, true)
|
||||
memSwapRow.AddItem(d.memorySwapField, 0, 1, true)
|
||||
|
||||
d.cpuMemoryPage.SetDirection(tview.FlexRow)
|
||||
d.cpuMemoryPage.AddItem(d.cpuPeriodField, 0, 1, true)
|
||||
d.cpuMemoryPage.AddItem(utils.EmptyBoxSpace(bgColor), 0, 1, true)
|
||||
d.cpuMemoryPage.AddItem(d.cpuQuataField, 0, 1, true)
|
||||
d.cpuMemoryPage.AddItem(utils.EmptyBoxSpace(bgColor), 0, 1, true)
|
||||
d.cpuMemoryPage.AddItem(d.cpuSharesField, 0, 1, true)
|
||||
d.cpuMemoryPage.AddItem(utils.EmptyBoxSpace(bgColor), 0, 1, true)
|
||||
d.cpuMemoryPage.AddItem(cpuSetRow, 0, 1, true)
|
||||
d.cpuMemoryPage.AddItem(utils.EmptyBoxSpace(bgColor), 0, 1, true)
|
||||
d.cpuMemoryPage.AddItem(memSwapRow, 0, 1, true)
|
||||
|
||||
// adding category pages
|
||||
d.categoryPages.AddPage(d.categoryLabels[buildDialogBasicInfoPageIndex], d.basicInfoPage, true, true)
|
||||
d.categoryPages.AddPage(d.categoryLabels[buildDialogBuildInfoPageIndex], d.buildInfoPage, true, true)
|
||||
d.categoryPages.AddPage(d.categoryLabels[buildDialogCapabilityPageIndex], d.capabilityPage, true, true)
|
||||
d.categoryPages.AddPage(d.categoryLabels[buildDialogCPUMemoryPageIndex], d.cpuMemoryPage, true, true)
|
||||
d.categoryPages.AddPage(d.categoryLabels[buildDialogNetworkingPageIndex], d.networkingPage, true, true)
|
||||
d.categoryPages.AddPage(d.categoryLabels[buildDialogSecurityOptsPageIndex], d.securityOptsPage, true, true)
|
||||
|
||||
// add it to layout.
|
||||
_, layoutWidth := utils.AlignStringListWidth(d.categoryLabels)
|
||||
layout := tview.NewFlex().SetDirection(tview.FlexColumn)
|
||||
layout.AddItem(d.categories, layoutWidth+6, 0, true) //nolint:mnd
|
||||
layout.AddItem(d.categoryPages, 0, 1, true)
|
||||
layout.SetBackgroundColor(bgColor)
|
||||
|
||||
d.layout.AddItem(layout, 0, 1, true)
|
||||
}
|
||||
|
||||
func (d *ImageBuildDialog) initData() {
|
||||
d.setActiveCategory(0)
|
||||
|
||||
|
@ -1459,3 +1223,238 @@ func (d *ImageBuildDialog) setSecurityOptionsPageNextFocus() {
|
|||
|
||||
d.focusElement = buildDialogFormFocus
|
||||
}
|
||||
|
||||
// ImageBuildOptions returns image build options.
|
||||
func (d *ImageBuildDialog) ImageBuildOptions() (images.ImageBuildOptions, error) { //nolint:gocognit,gocyclo,cyclop,maintidx,lll
|
||||
var (
|
||||
memoryLimit int64
|
||||
memorySwap int64
|
||||
cpuPeriod uint64
|
||||
cpuQuota int64
|
||||
cpuShares uint64
|
||||
cpuSetCpus string
|
||||
cpuSetMems string
|
||||
containerFiles []string
|
||||
dnsServers []string
|
||||
dnsOptions []string
|
||||
dnsSearchDomains []string
|
||||
addHost []string
|
||||
labelOpts []string
|
||||
apparmorProfile string
|
||||
seccompProfilePath string
|
||||
)
|
||||
|
||||
// basic info page
|
||||
// Containerfiles
|
||||
for _, cntFile := range strings.Split(strings.TrimSpace(d.containerFilePath.GetText()), " ") {
|
||||
if cntFile != "" {
|
||||
cFile, err := utils.ResolveHomeDir(cntFile)
|
||||
if err != nil {
|
||||
return images.ImageBuildOptions{}, err
|
||||
}
|
||||
|
||||
containerFiles = append(containerFiles, cFile)
|
||||
}
|
||||
}
|
||||
|
||||
opts := images.ImageBuildOptions{
|
||||
ContainerFiles: containerFiles,
|
||||
BuildOptions: entities.BuildOptions{},
|
||||
}
|
||||
|
||||
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, strings.TrimSpace(d.tagField.GetText()))
|
||||
opts.BuildOptions.Registry = strings.TrimSpace(d.registryField.GetText())
|
||||
|
||||
_, pullOption := d.pullPolicyField.GetCurrentOption()
|
||||
switch pullOption {
|
||||
case "missing":
|
||||
opts.BuildOptions.PullPolicy = define.PullIfMissing
|
||||
case "always":
|
||||
opts.BuildOptions.PullPolicy = define.PullAlways
|
||||
case "ifnewer":
|
||||
opts.BuildOptions.PullPolicy = define.PullIfNewer
|
||||
case "never":
|
||||
opts.BuildOptions.PullPolicy = define.PullNever
|
||||
}
|
||||
|
||||
_, format := d.formatField.GetCurrentOption()
|
||||
switch format {
|
||||
case "oci":
|
||||
opts.BuildOptions.OutputFormat = define.OCIv1ImageManifest
|
||||
case "docker":
|
||||
opts.BuildOptions.OutputFormat = define.Dockerv2ImageManifest
|
||||
}
|
||||
|
||||
// build settings
|
||||
opts.BuildOptions.Squash = d.SquashField.IsChecked()
|
||||
opts.BuildOptions.Layers = d.layersField.IsChecked()
|
||||
opts.BuildOptions.NoCache = d.noCacheField.IsChecked()
|
||||
opts.BuildOptions.RemoveIntermediateCtrs = d.removeCntField.IsChecked()
|
||||
opts.BuildOptions.ForceRmIntermediateCtrs = d.forceRemoveCntField.IsChecked()
|
||||
|
||||
labels := strings.TrimSpace(d.labelsField.GetText())
|
||||
if labels != "" {
|
||||
opts.BuildOptions.Labels = strings.Split(labels, " ")
|
||||
}
|
||||
|
||||
annotations := strings.TrimSpace(d.annotationsField.GetText())
|
||||
if annotations != "" {
|
||||
opts.BuildOptions.Annotations = strings.Split(annotations, " ")
|
||||
}
|
||||
|
||||
// capability pages
|
||||
addCap := strings.TrimSpace(d.addCapabilityField.GetText())
|
||||
if addCap != "" {
|
||||
opts.BuildOptions.AddCapabilities = strings.Split(addCap, " ")
|
||||
}
|
||||
|
||||
removeCap := strings.TrimSpace(d.removeCapabilityField.GetText())
|
||||
if removeCap != "" {
|
||||
opts.BuildOptions.DropCapabilities = strings.Split(removeCap, " ")
|
||||
}
|
||||
|
||||
// cpu and memory page
|
||||
opts.BuildOptions.CommonBuildOpts = &define.CommonBuildOptions{}
|
||||
|
||||
cpuPeriodVal := d.cpuPeriodField.GetText()
|
||||
if cpuPeriodVal != "" {
|
||||
period, err := strconv.Atoi(cpuPeriodVal)
|
||||
if err != nil {
|
||||
return images.ImageBuildOptions{}, fmt.Errorf("invalid CPU period value %q %w", cpuPeriodVal, err)
|
||||
}
|
||||
|
||||
cpuPeriod = uint64(period) //nolint:gosec
|
||||
}
|
||||
|
||||
cpuQuotaVal := d.cpuQuataField.GetText()
|
||||
if cpuQuotaVal != "" {
|
||||
quota, err := strconv.Atoi(cpuQuotaVal)
|
||||
if err != nil {
|
||||
return images.ImageBuildOptions{}, fmt.Errorf("invalid CPU quota value %q %w", cpuQuotaVal, err)
|
||||
}
|
||||
|
||||
cpuQuota = int64(quota)
|
||||
}
|
||||
|
||||
cpuSharesVal := d.cpuSharesField.GetText()
|
||||
if cpuSharesVal != "" {
|
||||
shares, err := strconv.Atoi(cpuSharesVal)
|
||||
if err != nil {
|
||||
return images.ImageBuildOptions{}, fmt.Errorf("invalid CPU quota value %q %w", cpuSharesVal, err)
|
||||
}
|
||||
|
||||
cpuShares = uint64(shares) //nolint:gosec
|
||||
}
|
||||
|
||||
cpuSetCpusVal := d.cpuSetCpusField.GetText()
|
||||
if cpuSetCpusVal != "" {
|
||||
cpuSetCpus = cpuSetCpusVal
|
||||
}
|
||||
|
||||
cpuSetMemsVal := d.cpuSetMemsField.GetText()
|
||||
if cpuSetMemsVal != "" {
|
||||
cpuSetMems = cpuSetMemsVal
|
||||
}
|
||||
|
||||
memoryVal := d.memoryField.GetText()
|
||||
if memoryVal != "" {
|
||||
memory, err := strconv.Atoi(memoryVal)
|
||||
if err != nil {
|
||||
return images.ImageBuildOptions{}, fmt.Errorf("invalid memory value %q %w", memoryVal, err)
|
||||
}
|
||||
|
||||
memoryLimit = int64(memory)
|
||||
}
|
||||
|
||||
memorySwapVal := d.memorySwapField.GetText()
|
||||
if memorySwapVal != "" {
|
||||
swap, err := strconv.Atoi(memorySwapVal)
|
||||
if err != nil {
|
||||
return images.ImageBuildOptions{}, fmt.Errorf("invalid memory swap value %q %w", memorySwapVal, err)
|
||||
}
|
||||
|
||||
memorySwap = int64(swap)
|
||||
}
|
||||
|
||||
// networking page
|
||||
// network policy
|
||||
_, configureNetwork := d.networkField.GetCurrentOption()
|
||||
switch configureNetwork {
|
||||
case "NetworkDefault":
|
||||
opts.BuildOptions.ConfigureNetwork = define.NetworkDefault
|
||||
case "NetworkDisabled":
|
||||
opts.BuildOptions.ConfigureNetwork = define.NetworkDisabled
|
||||
case "NetworkEnabled":
|
||||
opts.BuildOptions.ConfigureNetwork = define.NetworkEnabled
|
||||
}
|
||||
// add hosts
|
||||
hosts := strings.TrimSpace(d.addHostField.GetText())
|
||||
if hosts != "" {
|
||||
addHost = strings.Split(hosts, " ")
|
||||
}
|
||||
|
||||
// dns page
|
||||
dnsServersList := strings.TrimSpace(d.dnsServersField.GetText())
|
||||
for _, dns := range strings.Split(dnsServersList, " ") {
|
||||
if dns != "" {
|
||||
dnsServers = append(dnsServers, dns)
|
||||
}
|
||||
}
|
||||
|
||||
for _, do := range strings.Split(d.dnsOptionsField.GetText(), " ") {
|
||||
if do != "" {
|
||||
dnsOptions = append(dnsOptions, do)
|
||||
}
|
||||
}
|
||||
|
||||
for _, ds := range strings.Split(d.dnsSearchField.GetText(), " ") {
|
||||
if ds != "" {
|
||||
dnsSearchDomains = append(dnsSearchDomains, ds)
|
||||
}
|
||||
}
|
||||
|
||||
// security options page
|
||||
for _, selinuxLabel := range strings.Split(d.selinuxLabelField.GetText(), " ") {
|
||||
if selinuxLabel != "" {
|
||||
labelOpts = append(labelOpts, selinuxLabel)
|
||||
}
|
||||
}
|
||||
|
||||
apparmor := strings.TrimSpace(d.apparmorProfileField.GetText())
|
||||
if apparmor != "" {
|
||||
apparmorProfile = apparmor
|
||||
}
|
||||
|
||||
seccomp := strings.TrimSpace(d.seccompProfilePathField.GetText())
|
||||
if seccomp != "" {
|
||||
seccompProfilePath = seccomp
|
||||
}
|
||||
|
||||
commonOpts := &define.CommonBuildOptions{
|
||||
AddHost: addHost,
|
||||
HTTPProxy: d.httpProxyField.IsChecked(),
|
||||
CPUPeriod: cpuPeriod,
|
||||
CPUQuota: cpuQuota,
|
||||
CPUSetCPUs: cpuSetCpus,
|
||||
CPUSetMems: cpuSetMems,
|
||||
CPUShares: cpuShares,
|
||||
DNSServers: dnsServers,
|
||||
DNSOptions: dnsOptions,
|
||||
DNSSearch: dnsSearchDomains,
|
||||
Memory: memoryLimit,
|
||||
MemorySwap: memorySwap,
|
||||
LabelOpts: labelOpts,
|
||||
ApparmorProfile: apparmorProfile,
|
||||
SeccompProfilePath: seccompProfilePath,
|
||||
}
|
||||
|
||||
opts.BuildOptions.CommonBuildOpts = commonOpts
|
||||
|
||||
return opts, nil
|
||||
}
|
||||
|
|
|
@ -21,7 +21,6 @@ const (
|
|||
// ImageBuildProgressDialog implements build progress dialog primitive.
|
||||
type ImageBuildProgressDialog struct {
|
||||
*tview.Box
|
||||
|
||||
layout *tview.Flex
|
||||
output *tview.TextView
|
||||
progressBar *tvxwidgets.ActivityModeGauge
|
||||
|
@ -93,9 +92,7 @@ func (d *ImageBuildProgressDialog) IsDisplay() bool {
|
|||
func (d *ImageBuildProgressDialog) Hide() {
|
||||
d.display = false
|
||||
d.cancelChan <- true
|
||||
|
||||
close(d.writerChan)
|
||||
|
||||
d.output.SetText("")
|
||||
d.progressBar.Reset()
|
||||
}
|
||||
|
@ -116,7 +113,7 @@ func (d *ImageBuildProgressDialog) Focus(delegate func(p tview.Primitive)) {
|
|||
|
||||
// InputHandler returns input handler function for this primitive.
|
||||
func (d *ImageBuildProgressDialog) InputHandler() func(event *tcell.EventKey, setFocus func(p tview.Primitive)) {
|
||||
return d.WrapInputHandler(func(event *tcell.EventKey, setFocus func(p tview.Primitive)) {
|
||||
return d.WrapInputHandler(func(event *tcell.EventKey, setFocus func(p tview.Primitive)) { //nolint:revive
|
||||
log.Debug().Msgf("image build progress dialog: event %v received", event)
|
||||
})
|
||||
}
|
||||
|
@ -144,23 +141,12 @@ func (d *ImageBuildProgressDialog) Draw(screen tcell.Screen) {
|
|||
return
|
||||
}
|
||||
|
||||
d.DrawForSubclass(screen, d)
|
||||
x, y, width, height := d.GetInnerRect()
|
||||
d.Box.DrawForSubclass(screen, d)
|
||||
x, y, width, height := d.Box.GetInnerRect()
|
||||
d.layout.SetRect(x, y, width, height)
|
||||
d.layout.Draw(screen)
|
||||
}
|
||||
|
||||
// LogWriter returns output log writer.
|
||||
func (d *ImageBuildProgressDialog) LogWriter() channel.WriteCloser { //nolint:ireturn
|
||||
return channel.NewWriter(d.writerChan)
|
||||
}
|
||||
|
||||
// SetFastRefreshHandler sets fast refresh handler
|
||||
// fast refresh is used to print image build output as fast as possible.
|
||||
func (d *ImageBuildProgressDialog) SetFastRefreshHandler(handler func()) {
|
||||
d.fastRefreshHandler = handler
|
||||
}
|
||||
|
||||
func (d *ImageBuildProgressDialog) outputReaderLoop() {
|
||||
tick := time.NewTicker(utils.RefreshInterval)
|
||||
|
||||
|
@ -178,14 +164,20 @@ func (d *ImageBuildProgressDialog) outputReaderLoop() {
|
|||
return
|
||||
case data := <-d.writerChan:
|
||||
d.mu.Lock()
|
||||
|
||||
_, err := d.output.Write(data)
|
||||
if err != nil {
|
||||
log.Error().Msgf("failed to write data to output: %s", err.Error())
|
||||
}
|
||||
|
||||
d.output.Write(data) //nolint:errcheck
|
||||
d.mu.Unlock()
|
||||
d.fastRefreshHandler()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// LogWriter returns output log writer.
|
||||
func (d *ImageBuildProgressDialog) LogWriter() channel.WriteCloser { //nolint:ireturn
|
||||
return channel.NewWriter(d.writerChan)
|
||||
}
|
||||
|
||||
// SetFastRefreshHandler sets fast refresh handler
|
||||
// fast refresh is used to print image build output as fast as possible.
|
||||
func (d *ImageBuildProgressDialog) SetFastRefreshHandler(handler func()) {
|
||||
d.fastRefreshHandler = handler
|
||||
}
|
||||
|
|
|
@ -27,7 +27,6 @@ const (
|
|||
// ImageHistoryDialog represents image history dialog primitive.
|
||||
type ImageHistoryDialog struct {
|
||||
*tview.Box
|
||||
|
||||
layout *tview.Flex
|
||||
imageInfo *tview.InputField
|
||||
table *tview.Table
|
||||
|
@ -171,8 +170,8 @@ func (d *ImageHistoryDialog) Draw(screen tcell.Screen) {
|
|||
return
|
||||
}
|
||||
|
||||
d.DrawForSubclass(screen, d)
|
||||
x, y, width, height := d.GetInnerRect()
|
||||
d.Box.DrawForSubclass(screen, d)
|
||||
x, y, width, height := d.Box.GetInnerRect()
|
||||
d.layout.SetRect(x, y, width, height)
|
||||
d.layout.Draw(screen)
|
||||
}
|
||||
|
@ -186,6 +185,25 @@ func (d *ImageHistoryDialog) SetCancelFunc(handler func()) *ImageHistoryDialog {
|
|||
return d
|
||||
}
|
||||
|
||||
func (d *ImageHistoryDialog) initTable() {
|
||||
bgColor := style.TableHeaderBgColor
|
||||
fgColor := style.TableHeaderFgColor
|
||||
|
||||
d.table.Clear()
|
||||
d.table.SetFixed(1, 1)
|
||||
d.table.SetSelectable(true, false)
|
||||
|
||||
for i := range d.tableHeaders {
|
||||
d.table.SetCell(0, i,
|
||||
tview.NewTableCell(fmt.Sprintf("[%s::b]%s", style.GetColorHex(fgColor), strings.ToUpper(d.tableHeaders[i]))).
|
||||
SetExpansion(1).
|
||||
SetBackgroundColor(bgColor).
|
||||
SetTextColor(fgColor).
|
||||
SetAlign(tview.AlignLeft).
|
||||
SetSelectable(false))
|
||||
}
|
||||
}
|
||||
|
||||
// UpdateResults updates result table.
|
||||
func (d *ImageHistoryDialog) UpdateResults(data [][]string) {
|
||||
d.results = data
|
||||
|
@ -293,22 +311,3 @@ func (d *ImageHistoryDialog) getCreatedByWidth() int {
|
|||
|
||||
return createdByWidth
|
||||
}
|
||||
|
||||
func (d *ImageHistoryDialog) initTable() {
|
||||
bgColor := style.TableHeaderBgColor
|
||||
fgColor := style.TableHeaderFgColor
|
||||
|
||||
d.table.Clear()
|
||||
d.table.SetFixed(1, 1)
|
||||
d.table.SetSelectable(true, false)
|
||||
|
||||
for i := range d.tableHeaders {
|
||||
d.table.SetCell(0, i,
|
||||
tview.NewTableCell(fmt.Sprintf("[%s::b]%s", style.GetColorHex(fgColor), strings.ToUpper(d.tableHeaders[i]))).
|
||||
SetExpansion(1).
|
||||
SetBackgroundColor(bgColor).
|
||||
SetTextColor(fgColor).
|
||||
SetAlign(tview.AlignLeft).
|
||||
SetSelectable(false))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,7 +32,6 @@ const (
|
|||
// ImageImportDialog represents image import dialog primitive.
|
||||
type ImageImportDialog struct {
|
||||
*tview.Box
|
||||
|
||||
layout *tview.Flex
|
||||
path *tview.InputField
|
||||
change *tview.InputField
|
||||
|
@ -272,12 +271,25 @@ func (d *ImageImportDialog) Draw(screen tcell.Screen) {
|
|||
return
|
||||
}
|
||||
|
||||
d.DrawForSubclass(screen, d)
|
||||
x, y, width, height := d.GetInnerRect()
|
||||
d.Box.DrawForSubclass(screen, d)
|
||||
x, y, width, height := d.Box.GetInnerRect()
|
||||
d.layout.SetRect(x, y, width, height)
|
||||
d.layout.Draw(screen)
|
||||
}
|
||||
|
||||
func (d *ImageImportDialog) setFocusElement() {
|
||||
switch d.focusElement {
|
||||
case imageImportPathFocus:
|
||||
d.focusElement = imageImportChangeFocus
|
||||
case imageImportChangeFocus:
|
||||
d.focusElement = imageImportCommitMessageFocus
|
||||
case imageImportCommitMessageFocus:
|
||||
d.focusElement = imageImportReferenceFocus
|
||||
case imageImportReferenceFocus:
|
||||
d.focusElement = imageImportFormFocus
|
||||
}
|
||||
}
|
||||
|
||||
// SetImportFunc sets form import button selected function.
|
||||
func (d *ImageImportDialog) SetImportFunc(handler func()) *ImageImportDialog {
|
||||
d.importHandler = handler
|
||||
|
@ -326,8 +338,8 @@ func (d *ImageImportDialog) ImageImportOptions() (images.ImageImportOptions, err
|
|||
}
|
||||
|
||||
errFileName := utils.ValidateFileName(path)
|
||||
|
||||
errURL := utils.ValidURL(path)
|
||||
|
||||
if errURL == nil {
|
||||
opts.URL = true
|
||||
}
|
||||
|
@ -340,16 +352,3 @@ func (d *ImageImportDialog) ImageImportOptions() (images.ImageImportOptions, err
|
|||
|
||||
return opts, nil
|
||||
}
|
||||
|
||||
func (d *ImageImportDialog) setFocusElement() {
|
||||
switch d.focusElement {
|
||||
case imageImportPathFocus:
|
||||
d.focusElement = imageImportChangeFocus
|
||||
case imageImportChangeFocus:
|
||||
d.focusElement = imageImportCommitMessageFocus
|
||||
case imageImportCommitMessageFocus:
|
||||
d.focusElement = imageImportReferenceFocus
|
||||
case imageImportReferenceFocus:
|
||||
d.focusElement = imageImportFormFocus
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,7 +32,6 @@ const (
|
|||
// ImagePushDialog represents image push dialog primitive.
|
||||
type ImagePushDialog struct {
|
||||
*tview.Box
|
||||
|
||||
layout *tview.Flex
|
||||
imageInfo *tview.InputField
|
||||
destination *tview.InputField
|
||||
|
@ -246,6 +245,12 @@ func (d *ImagePushDialog) HasFocus() bool { //nolint:cyclop
|
|||
return d.Box.HasFocus()
|
||||
}
|
||||
|
||||
// dropdownHasFocus returns true if image push dialog dropdown primitives.
|
||||
// has focus.
|
||||
func (d *ImagePushDialog) dropdownHasFocus() bool {
|
||||
return d.format.HasFocus()
|
||||
}
|
||||
|
||||
// Focus is called when this primitive receives focus.
|
||||
func (d *ImagePushDialog) Focus(delegate func(p tview.Primitive)) {
|
||||
switch d.focusElement {
|
||||
|
@ -363,6 +368,25 @@ func (d *ImagePushDialog) InputHandler() func(event *tcell.EventKey, setFocus fu
|
|||
})
|
||||
}
|
||||
|
||||
func (d *ImagePushDialog) setFocusElement() {
|
||||
switch d.focusElement {
|
||||
case imagePushDesitnationFocus:
|
||||
d.focusElement = imagePushCompressFocus
|
||||
case imagePushCompressFocus:
|
||||
d.focusElement = imagePushFormatFocus
|
||||
case imagePushFormatFocus:
|
||||
d.focusElement = imagePushSkipTLSVerifyFocus
|
||||
case imagePushSkipTLSVerifyFocus:
|
||||
d.focusElement = imagePushUsernameFocus
|
||||
case imagePushUsernameFocus:
|
||||
d.focusElement = imagePushPasswordFocus
|
||||
case imagePushPasswordFocus:
|
||||
d.focusElement = imagePushAuthFileFocus
|
||||
case imagePushAuthFileFocus:
|
||||
d.focusElement = imagePushFormFocus
|
||||
}
|
||||
}
|
||||
|
||||
// SetRect set rects for this primitive.
|
||||
func (d *ImagePushDialog) SetRect(x, y, width, height int) {
|
||||
if width > imagePushDialogMaxWidth {
|
||||
|
@ -386,8 +410,8 @@ func (d *ImagePushDialog) Draw(screen tcell.Screen) {
|
|||
return
|
||||
}
|
||||
|
||||
d.DrawForSubclass(screen, d)
|
||||
x, y, width, height := d.GetInnerRect()
|
||||
d.Box.DrawForSubclass(screen, d)
|
||||
x, y, width, height := d.Box.GetInnerRect()
|
||||
|
||||
d.layout.SetRect(x, y, width, height)
|
||||
d.layout.Draw(screen)
|
||||
|
@ -433,28 +457,3 @@ func (d *ImagePushDialog) GetImagePushOptions() images.ImagePushOptions {
|
|||
|
||||
return opts
|
||||
}
|
||||
|
||||
// dropdownHasFocus returns true if image push dialog dropdown primitives.
|
||||
// has focus.
|
||||
func (d *ImagePushDialog) dropdownHasFocus() bool {
|
||||
return d.format.HasFocus()
|
||||
}
|
||||
|
||||
func (d *ImagePushDialog) setFocusElement() {
|
||||
switch d.focusElement {
|
||||
case imagePushDesitnationFocus:
|
||||
d.focusElement = imagePushCompressFocus
|
||||
case imagePushCompressFocus:
|
||||
d.focusElement = imagePushFormatFocus
|
||||
case imagePushFormatFocus:
|
||||
d.focusElement = imagePushSkipTLSVerifyFocus
|
||||
case imagePushSkipTLSVerifyFocus:
|
||||
d.focusElement = imagePushUsernameFocus
|
||||
case imagePushUsernameFocus:
|
||||
d.focusElement = imagePushPasswordFocus
|
||||
case imagePushPasswordFocus:
|
||||
d.focusElement = imagePushAuthFileFocus
|
||||
case imagePushAuthFileFocus:
|
||||
d.focusElement = imagePushFormFocus
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,7 +33,6 @@ const (
|
|||
// ImageSaveDialog represents image save dialog primitive.
|
||||
type ImageSaveDialog struct {
|
||||
*tview.Box
|
||||
|
||||
layout *tview.Flex
|
||||
imageInfo *tview.InputField
|
||||
output *tview.InputField
|
||||
|
@ -308,12 +307,25 @@ func (d *ImageSaveDialog) Draw(screen tcell.Screen) {
|
|||
return
|
||||
}
|
||||
|
||||
d.DrawForSubclass(screen, d)
|
||||
x, y, width, height := d.GetInnerRect()
|
||||
d.Box.DrawForSubclass(screen, d)
|
||||
x, y, width, height := d.Box.GetInnerRect()
|
||||
d.layout.SetRect(x, y, width, height)
|
||||
d.layout.Draw(screen)
|
||||
}
|
||||
|
||||
func (d *ImageSaveDialog) setFocusElement() {
|
||||
switch d.focusElement {
|
||||
case imageSaveOutputFocus:
|
||||
d.focusElement = imageSaveCompressFocus
|
||||
case imageSaveCompressFocus:
|
||||
d.focusElement = imageSaveAcceptUncompressedFocus
|
||||
case imageSaveAcceptUncompressedFocus:
|
||||
d.focusElement = imageSaveFormatFocus
|
||||
case imageSaveFormatFocus:
|
||||
d.focusElement = imageSaveFormFocus
|
||||
}
|
||||
}
|
||||
|
||||
// SetSaveFunc sets form save button selected function.
|
||||
func (d *ImageSaveDialog) SetSaveFunc(handler func()) *ImageSaveDialog {
|
||||
d.saveHandler = handler
|
||||
|
@ -372,16 +384,3 @@ func (d *ImageSaveDialog) ImageSaveOptions() (images.ImageSaveOptions, error) {
|
|||
|
||||
return opts, nil
|
||||
}
|
||||
|
||||
func (d *ImageSaveDialog) setFocusElement() {
|
||||
switch d.focusElement {
|
||||
case imageSaveOutputFocus:
|
||||
d.focusElement = imageSaveCompressFocus
|
||||
case imageSaveCompressFocus:
|
||||
d.focusElement = imageSaveAcceptUncompressedFocus
|
||||
case imageSaveAcceptUncompressedFocus:
|
||||
d.focusElement = imageSaveFormatFocus
|
||||
case imageSaveFormatFocus:
|
||||
d.focusElement = imageSaveFormFocus
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,7 +45,6 @@ const (
|
|||
// ImageSearchDialog represents image search dialogs.
|
||||
type ImageSearchDialog struct {
|
||||
*tview.Box
|
||||
|
||||
layout *tview.Flex
|
||||
searchLayout *tview.Flex
|
||||
input *tview.InputField
|
||||
|
@ -127,6 +126,62 @@ func NewImageSearchDialog() *ImageSearchDialog {
|
|||
return dialog
|
||||
}
|
||||
|
||||
func (d *ImageSearchDialog) initTable() {
|
||||
bgColor := style.TableHeaderBgColor
|
||||
fgColor := style.TableHeaderFgColor
|
||||
|
||||
d.searchResult.Clear()
|
||||
d.searchResult.SetCell(0, searchResultIndexColIndex,
|
||||
tview.NewTableCell(fmt.Sprintf("[%s::b]INDEX", style.GetColorHex(fgColor))).
|
||||
SetExpansion(1).
|
||||
SetBackgroundColor(bgColor).
|
||||
SetTextColor(fgColor).
|
||||
SetAlign(tview.AlignLeft).
|
||||
SetSelectable(false))
|
||||
|
||||
d.searchResult.SetCell(0, searchResultNameColIndex,
|
||||
tview.NewTableCell(fmt.Sprintf("[%s::b]NAME", style.GetColorHex(fgColor))).
|
||||
SetExpansion(1).
|
||||
SetBackgroundColor(bgColor).
|
||||
SetTextColor(fgColor).
|
||||
SetAlign(tview.AlignLeft).
|
||||
SetSelectable(false))
|
||||
|
||||
d.searchResult.SetCell(0, searchResultStarsColIndex,
|
||||
tview.NewTableCell(fmt.Sprintf("[%s::b]STARS", style.GetColorHex(fgColor))).
|
||||
SetExpansion(1).
|
||||
SetBackgroundColor(bgColor).
|
||||
SetTextColor(fgColor).
|
||||
SetAlign(tview.AlignCenter).
|
||||
SetSelectable(false))
|
||||
|
||||
d.searchResult.SetCell(0, searchResultOfficialColIndex,
|
||||
tview.NewTableCell(fmt.Sprintf("[%s::b]OFFICIAL", style.GetColorHex(fgColor))).
|
||||
SetExpansion(1).
|
||||
SetBackgroundColor(bgColor).
|
||||
SetTextColor(fgColor).
|
||||
SetAlign(tview.AlignCenter).
|
||||
SetSelectable(false))
|
||||
d.searchResult.SetCell(0, searchResultAutomatedColIndex,
|
||||
tview.NewTableCell(fmt.Sprintf("[%s::b]AUTOMATED", style.GetColorHex(fgColor))).
|
||||
SetExpansion(1).
|
||||
SetBackgroundColor(bgColor).
|
||||
SetTextColor(fgColor).
|
||||
SetAlign(tview.AlignCenter).
|
||||
SetSelectable(false))
|
||||
|
||||
d.searchResult.SetCell(0, searchResultDescColIndex,
|
||||
tview.NewTableCell(fmt.Sprintf("[%s::b]DESCRIPTION", style.GetColorHex(fgColor))).
|
||||
SetExpansion(1).
|
||||
SetBackgroundColor(bgColor).
|
||||
SetTextColor(fgColor).
|
||||
SetAlign(tview.AlignCenter).
|
||||
SetSelectable(false))
|
||||
|
||||
d.searchResult.SetFixed(1, 1)
|
||||
d.searchResult.SetSelectable(true, false)
|
||||
}
|
||||
|
||||
// Display displays this primitive.
|
||||
func (d *ImageSearchDialog) Display() {
|
||||
d.display = true
|
||||
|
@ -278,9 +333,9 @@ func (d *ImageSearchDialog) Draw(screen tcell.Screen) {
|
|||
}
|
||||
|
||||
bgColor := style.DialogBgColor
|
||||
d.SetBackgroundColor(bgColor)
|
||||
d.DrawForSubclass(screen, d)
|
||||
x, y, width, height := d.GetInnerRect()
|
||||
d.Box.SetBackgroundColor(bgColor)
|
||||
d.Box.DrawForSubclass(screen, d)
|
||||
x, y, width, height := d.Box.GetInnerRect()
|
||||
d.layout.SetRect(x, y, width, height)
|
||||
d.layout.SetBorder(true)
|
||||
d.layout.SetBackgroundColor(bgColor)
|
||||
|
@ -450,59 +505,3 @@ func (d *ImageSearchDialog) UpdateResults(data [][]string) {
|
|||
d.searchResult.ScrollToBeginning()
|
||||
}
|
||||
}
|
||||
|
||||
func (d *ImageSearchDialog) initTable() {
|
||||
bgColor := style.TableHeaderBgColor
|
||||
fgColor := style.TableHeaderFgColor
|
||||
|
||||
d.searchResult.Clear()
|
||||
d.searchResult.SetCell(0, searchResultIndexColIndex,
|
||||
tview.NewTableCell(fmt.Sprintf("[%s::b]INDEX", style.GetColorHex(fgColor))).
|
||||
SetExpansion(1).
|
||||
SetBackgroundColor(bgColor).
|
||||
SetTextColor(fgColor).
|
||||
SetAlign(tview.AlignLeft).
|
||||
SetSelectable(false))
|
||||
|
||||
d.searchResult.SetCell(0, searchResultNameColIndex,
|
||||
tview.NewTableCell(fmt.Sprintf("[%s::b]NAME", style.GetColorHex(fgColor))).
|
||||
SetExpansion(1).
|
||||
SetBackgroundColor(bgColor).
|
||||
SetTextColor(fgColor).
|
||||
SetAlign(tview.AlignLeft).
|
||||
SetSelectable(false))
|
||||
|
||||
d.searchResult.SetCell(0, searchResultStarsColIndex,
|
||||
tview.NewTableCell(fmt.Sprintf("[%s::b]STARS", style.GetColorHex(fgColor))).
|
||||
SetExpansion(1).
|
||||
SetBackgroundColor(bgColor).
|
||||
SetTextColor(fgColor).
|
||||
SetAlign(tview.AlignCenter).
|
||||
SetSelectable(false))
|
||||
|
||||
d.searchResult.SetCell(0, searchResultOfficialColIndex,
|
||||
tview.NewTableCell(fmt.Sprintf("[%s::b]OFFICIAL", style.GetColorHex(fgColor))).
|
||||
SetExpansion(1).
|
||||
SetBackgroundColor(bgColor).
|
||||
SetTextColor(fgColor).
|
||||
SetAlign(tview.AlignCenter).
|
||||
SetSelectable(false))
|
||||
d.searchResult.SetCell(0, searchResultAutomatedColIndex,
|
||||
tview.NewTableCell(fmt.Sprintf("[%s::b]AUTOMATED", style.GetColorHex(fgColor))).
|
||||
SetExpansion(1).
|
||||
SetBackgroundColor(bgColor).
|
||||
SetTextColor(fgColor).
|
||||
SetAlign(tview.AlignCenter).
|
||||
SetSelectable(false))
|
||||
|
||||
d.searchResult.SetCell(0, searchResultDescColIndex,
|
||||
tview.NewTableCell(fmt.Sprintf("[%s::b]DESCRIPTION", style.GetColorHex(fgColor))).
|
||||
SetExpansion(1).
|
||||
SetBackgroundColor(bgColor).
|
||||
SetTextColor(fgColor).
|
||||
SetAlign(tview.AlignCenter).
|
||||
SetSelectable(false))
|
||||
|
||||
d.searchResult.SetFixed(1, 1)
|
||||
d.searchResult.SetSelectable(true, false)
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ import (
|
|||
)
|
||||
|
||||
// InputHandler returns the handler for this primitive.
|
||||
func (img *Images) InputHandler() func(event *tcell.EventKey, setFocus func(p tview.Primitive)) { //nolint:gocognit,cyclop,lll
|
||||
func (img *Images) InputHandler() func(event *tcell.EventKey, setFocus func(p tview.Primitive)) { //nolint:gocognit,gocyclo,lll,cyclop
|
||||
return img.WrapInputHandler(func(event *tcell.EventKey, setFocus func(p tview.Primitive)) {
|
||||
log.Debug().Msgf("view: images event %v received", event)
|
||||
|
||||
|
@ -16,19 +16,88 @@ func (img *Images) InputHandler() func(event *tcell.EventKey, setFocus func(p tv
|
|||
return
|
||||
}
|
||||
|
||||
for _, dialog := range img.getInnerTopDialogs() {
|
||||
if dialog.HasFocus() {
|
||||
if handler := dialog.InputHandler(); handler != nil {
|
||||
handler(event, setFocus)
|
||||
}
|
||||
// error dialog handler
|
||||
if img.errorDialog.HasFocus() || img.errorDialog.IsDisplay() {
|
||||
if errorDialogHandler := img.errorDialog.InputHandler(); errorDialogHandler != nil {
|
||||
errorDialogHandler(event, setFocus)
|
||||
setFocus(img.errorDialog)
|
||||
}
|
||||
}
|
||||
|
||||
for _, dialog := range img.getInnerDialogs() {
|
||||
if dialog.HasFocus() {
|
||||
if handler := dialog.InputHandler(); handler != nil {
|
||||
handler(event, setFocus)
|
||||
}
|
||||
// message dialog handler
|
||||
if img.messageDialog.HasFocus() || img.messageDialog.IsDisplay() {
|
||||
if messageDialogHandler := img.messageDialog.InputHandler(); messageDialogHandler != nil {
|
||||
messageDialogHandler(event, setFocus)
|
||||
setFocus(img.messageDialog)
|
||||
}
|
||||
}
|
||||
|
||||
// command dialog handler
|
||||
if img.cmdDialog.HasFocus() {
|
||||
if cmdHandler := img.cmdDialog.InputHandler(); cmdHandler != nil {
|
||||
cmdHandler(event, setFocus)
|
||||
}
|
||||
}
|
||||
// input dialog handler
|
||||
if img.cmdInputDialog.HasFocus() {
|
||||
if cmdInputHandler := img.cmdInputDialog.InputHandler(); cmdInputHandler != nil {
|
||||
cmdInputHandler(event, setFocus)
|
||||
}
|
||||
}
|
||||
|
||||
// confirm dialog handler
|
||||
if img.confirmDialog.HasFocus() {
|
||||
if confirmDialogHandler := img.confirmDialog.InputHandler(); confirmDialogHandler != nil {
|
||||
confirmDialogHandler(event, setFocus)
|
||||
}
|
||||
}
|
||||
|
||||
// search dialog handler
|
||||
if img.searchDialog.HasFocus() {
|
||||
if searchDialogHandler := img.searchDialog.InputHandler(); searchDialogHandler != nil {
|
||||
searchDialogHandler(event, setFocus)
|
||||
}
|
||||
}
|
||||
|
||||
// history dialog handler
|
||||
if img.historyDialog.HasFocus() {
|
||||
if historyDialogHandler := img.historyDialog.InputHandler(); historyDialogHandler != nil {
|
||||
historyDialogHandler(event, setFocus)
|
||||
}
|
||||
}
|
||||
|
||||
// build dialog handler
|
||||
if img.buildDialog.HasFocus() {
|
||||
if buildDialogHandler := img.buildDialog.InputHandler(); buildDialogHandler != nil {
|
||||
buildDialogHandler(event, setFocus)
|
||||
}
|
||||
}
|
||||
|
||||
// build progress dialog handler
|
||||
if img.buildPrgDialog.HasFocus() {
|
||||
if buildPrgDialogHandler := img.buildPrgDialog.InputHandler(); buildPrgDialogHandler != nil {
|
||||
buildPrgDialogHandler(event, setFocus)
|
||||
}
|
||||
}
|
||||
|
||||
// save dialog handler
|
||||
if img.saveDialog.HasFocus() {
|
||||
if saveDialogHandler := img.saveDialog.InputHandler(); saveDialogHandler != nil {
|
||||
saveDialogHandler(event, setFocus)
|
||||
}
|
||||
}
|
||||
|
||||
// import dialog handler
|
||||
if img.importDialog.HasFocus() {
|
||||
if importDialogHandler := img.importDialog.InputHandler(); importDialogHandler != nil {
|
||||
importDialogHandler(event, setFocus)
|
||||
}
|
||||
}
|
||||
|
||||
// push dialog handler
|
||||
if img.pushDialog.HasFocus() {
|
||||
if pushDialogHandler := img.pushDialog.InputHandler(); pushDialogHandler != nil {
|
||||
pushDialogHandler(event, setFocus)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -46,14 +115,6 @@ func (img *Images) InputHandler() func(event *tcell.EventKey, setFocus func(p tv
|
|||
return
|
||||
}
|
||||
|
||||
// display sort menu
|
||||
if event.Rune() == utils.SortMenuKey.Rune() {
|
||||
img.sortDialog.Display()
|
||||
setFocus(img)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if event.Key() == utils.DeleteKey.EventKey() {
|
||||
img.rm()
|
||||
setFocus(img)
|
||||
|
|
|
@ -26,7 +26,6 @@ func (img *Images) refresh(_ int) {
|
|||
SetSelectable(false))
|
||||
}
|
||||
|
||||
currentSelectedRow, _ := img.table.GetSelection()
|
||||
rowIndex := 1
|
||||
images := img.getData()
|
||||
|
||||
|
@ -77,11 +76,4 @@ func (img *Images) refresh(_ int) {
|
|||
|
||||
rowIndex++
|
||||
}
|
||||
|
||||
if currentSelectedRow > len(images) {
|
||||
currentSelectedRow--
|
||||
if currentSelectedRow >= 0 {
|
||||
img.table.Select(currentSelectedRow, -1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,7 +29,6 @@ const (
|
|||
// InfoBar implements the info bar primitive.
|
||||
type InfoBar struct {
|
||||
*tview.Box
|
||||
|
||||
table *tview.Table
|
||||
title string
|
||||
connStatus registry.ConnStatus
|
||||
|
@ -164,9 +163,8 @@ func (info *InfoBar) UpdateSystemUsageInfo(memUsage float64, swapUsage float64)
|
|||
|
||||
// UpdateConnStatus updates connection status value.
|
||||
func (info *InfoBar) UpdateConnStatus(status registry.ConnStatus) {
|
||||
var connStatus string
|
||||
|
||||
info.connStatus = status
|
||||
connStatus := ""
|
||||
|
||||
switch info.connStatus {
|
||||
case registry.ConnectionStatusConnected:
|
||||
|
@ -182,8 +180,8 @@ func (info *InfoBar) UpdateConnStatus(status registry.ConnStatus) {
|
|||
|
||||
// Draw draws this primitive onto the screen.
|
||||
func (info *InfoBar) Draw(screen tcell.Screen) {
|
||||
info.DrawForSubclass(screen, info)
|
||||
info.SetBorder(false)
|
||||
info.Box.DrawForSubclass(screen, info)
|
||||
info.Box.SetBorder(false)
|
||||
|
||||
x, y, width, height := info.GetInnerRect()
|
||||
|
||||
|
|
|
@ -8,7 +8,6 @@ import (
|
|||
"github.com/containers/podman-tui/pdcs/networks"
|
||||
"github.com/containers/podman-tui/ui/dialogs"
|
||||
"github.com/containers/podman-tui/ui/style"
|
||||
"github.com/containers/podman-tui/ui/utils"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
|
@ -22,7 +21,7 @@ func (nets *Networks) runCommand(cmd string) {
|
|||
nets.cdisconnect()
|
||||
case "inspect":
|
||||
nets.inspect()
|
||||
case utils.PruneCommandLabel:
|
||||
case "prune": //nolint:goconst
|
||||
nets.cprune()
|
||||
case "rm":
|
||||
nets.rm()
|
||||
|
@ -76,15 +75,15 @@ func (nets *Networks) connect() {
|
|||
nets.progressDialog.SetTitle("podman network connect")
|
||||
nets.progressDialog.Display()
|
||||
|
||||
err := networks.Connect(connectOptions)
|
||||
|
||||
nets.progressDialog.Hide()
|
||||
|
||||
if err != nil {
|
||||
if err := networks.Connect(connectOptions); err != nil {
|
||||
nets.progressDialog.Hide()
|
||||
nets.displayError("NETWORK CONNECT ERROR", err)
|
||||
nets.appFocusHandler()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
nets.appFocusHandler()
|
||||
nets.progressDialog.Hide()
|
||||
}
|
||||
|
||||
go connect()
|
||||
|
@ -102,10 +101,8 @@ func (nets *Networks) cdisconnect() {
|
|||
nets.progressDialog.Display()
|
||||
|
||||
cntListReport, err := containers.List()
|
||||
|
||||
nets.progressDialog.Hide()
|
||||
|
||||
if err != nil {
|
||||
nets.progressDialog.Hide()
|
||||
nets.displayError("NETWORK DISCONNECT ERROR", err)
|
||||
nets.appFocusHandler()
|
||||
|
||||
|
@ -116,6 +113,7 @@ func (nets *Networks) cdisconnect() {
|
|||
|
||||
nets.disconnectDialog.SetNetworkInfo(netID, netName)
|
||||
nets.disconnectDialog.SetContainers(cntListReport)
|
||||
nets.progressDialog.Hide()
|
||||
nets.disconnectDialog.Display()
|
||||
nets.appFocusHandler()
|
||||
}
|
||||
|
@ -131,15 +129,15 @@ func (nets *Networks) disconnect() {
|
|||
nets.progressDialog.SetTitle("podman network disconnect")
|
||||
nets.progressDialog.Display()
|
||||
|
||||
err := networks.Disconnect(networkName, containerID)
|
||||
|
||||
nets.progressDialog.Hide()
|
||||
|
||||
if err != nil {
|
||||
if err := networks.Disconnect(networkName, containerID); err != nil {
|
||||
nets.progressDialog.Hide()
|
||||
nets.displayError("NETWORK DISCONNECT ERROR", err)
|
||||
nets.appFocusHandler()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
nets.appFocusHandler()
|
||||
nets.progressDialog.Hide()
|
||||
}
|
||||
|
||||
go disconnect()
|
||||
|
@ -184,7 +182,7 @@ func (nets *Networks) inspect() {
|
|||
func (nets *Networks) cprune() {
|
||||
nets.confirmDialog.SetTitle("podman network prune")
|
||||
|
||||
nets.confirmData = utils.PruneCommandLabel
|
||||
nets.confirmData = "prune"
|
||||
|
||||
nets.confirmDialog.SetText("Are you sure you want to remove all un used network ?")
|
||||
nets.confirmDialog.Display()
|
||||
|
@ -195,16 +193,16 @@ func (nets *Networks) prune() {
|
|||
nets.progressDialog.Display()
|
||||
|
||||
prune := func() {
|
||||
err := networks.Prune()
|
||||
|
||||
nets.progressDialog.Hide()
|
||||
|
||||
if err != nil {
|
||||
if err := networks.Prune(); err != nil {
|
||||
nets.progressDialog.Hide()
|
||||
nets.displayError("NETWORK PRUNE ERROR", err)
|
||||
nets.appFocusHandler()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
nets.appFocusHandler()
|
||||
nets.UpdateData()
|
||||
nets.progressDialog.Hide()
|
||||
}
|
||||
|
||||
go prune()
|
||||
|
@ -244,9 +242,11 @@ func (nets *Networks) remove() {
|
|||
title := fmt.Sprintf("NETWORK (%s) REMOVE ERROR", nets.selectedID)
|
||||
|
||||
nets.displayError(title, err)
|
||||
nets.appFocusHandler()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
nets.appFocusHandler()
|
||||
nets.UpdateData()
|
||||
}
|
||||
|
||||
|
|
|
@ -2,29 +2,14 @@ package networks
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/containers/common/libnetwork/types"
|
||||
"github.com/containers/podman-tui/pdcs/networks"
|
||||
"github.com/containers/podman-tui/ui/style"
|
||||
"github.com/rivo/tview"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
// SortView sorts data view called from sort dialog.
|
||||
func (nets *Networks) SortView(option string, ascending bool) {
|
||||
log.Debug().Msgf("view: networks sort by %s", option)
|
||||
|
||||
nets.networkList.mu.Lock()
|
||||
defer nets.networkList.mu.Unlock()
|
||||
|
||||
nets.networkList.sortBy = option
|
||||
nets.networkList.ascending = ascending
|
||||
|
||||
sort.Sort(netsListSorted{nets.networkList.report, option, ascending})
|
||||
}
|
||||
|
||||
// UpdateData retrieves networks list data.
|
||||
func (nets *Networks) UpdateData() {
|
||||
netList, err := networks.List()
|
||||
|
@ -37,12 +22,10 @@ func (nets *Networks) UpdateData() {
|
|||
nets.networkList.mu.Lock()
|
||||
defer nets.networkList.mu.Unlock()
|
||||
|
||||
sort.Sort(netsListSorted{netList, nets.networkList.sortBy, nets.networkList.ascending})
|
||||
|
||||
nets.networkList.report = netList
|
||||
}
|
||||
|
||||
func (nets *Networks) getData() []types.Network {
|
||||
func (nets *Networks) getData() [][]string {
|
||||
nets.networkList.mu.Lock()
|
||||
defer nets.networkList.mu.Unlock()
|
||||
|
||||
|
@ -76,31 +59,3 @@ func (nets *Networks) ClearData() {
|
|||
|
||||
nets.table.SetTitle(fmt.Sprintf("[::b]%s[0]", strings.ToUpper(nets.title)))
|
||||
}
|
||||
|
||||
type lprSort []types.Network
|
||||
|
||||
func (a lprSort) Len() int { return len(a) }
|
||||
func (a lprSort) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||
|
||||
type netsListSorted struct {
|
||||
lprSort
|
||||
|
||||
option string
|
||||
ascending bool
|
||||
}
|
||||
|
||||
func (a netsListSorted) Less(i, j int) bool {
|
||||
if a.option == "driver" {
|
||||
if a.ascending {
|
||||
return a.lprSort[i].Driver < a.lprSort[j].Driver
|
||||
}
|
||||
|
||||
return a.lprSort[i].Driver > a.lprSort[j].Driver
|
||||
}
|
||||
|
||||
if a.ascending {
|
||||
return a.lprSort[i].Name < a.lprSort[j].Name
|
||||
}
|
||||
|
||||
return a.lprSort[i].Name > a.lprSort[j].Name
|
||||
}
|
||||
|
|
|
@ -6,8 +6,8 @@ import (
|
|||
|
||||
// Draw draws this primitive onto the screen.
|
||||
func (nets *Networks) Draw(screen tcell.Screen) {
|
||||
nets.DrawForSubclass(screen, nets)
|
||||
nets.SetBorder(false)
|
||||
nets.Box.DrawForSubclass(screen, nets)
|
||||
nets.Box.SetBorder(false)
|
||||
|
||||
netViewX, netViewY, netViewW, netViewH := nets.GetInnerRect()
|
||||
|
||||
|
@ -19,12 +19,70 @@ func (nets *Networks) Draw(screen tcell.Screen) {
|
|||
|
||||
x, y, width, height := nets.table.GetInnerRect()
|
||||
|
||||
for _, dialog := range nets.getInnerDialogs() {
|
||||
if dialog.IsDisplay() {
|
||||
dialog.SetRect(x, y, width, height)
|
||||
dialog.Draw(screen)
|
||||
// error dialog
|
||||
if nets.errorDialog.IsDisplay() {
|
||||
nets.errorDialog.SetRect(x, y, width, height)
|
||||
nets.errorDialog.Draw(screen)
|
||||
|
||||
return
|
||||
return
|
||||
}
|
||||
|
||||
// command dialog
|
||||
if nets.cmdDialog.IsDisplay() {
|
||||
nets.cmdDialog.SetRect(x, y, width, height)
|
||||
nets.cmdDialog.Draw(screen)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// create dialog
|
||||
if nets.createDialog.IsDisplay() {
|
||||
nets.createDialog.SetRect(x, y, width, height)
|
||||
nets.createDialog.Draw(screen)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// connect dialog
|
||||
if nets.connectDialog.IsDisplay() {
|
||||
nets.connectDialog.SetRect(x, y, width, height)
|
||||
nets.connectDialog.Draw(screen)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// disconnect dialog
|
||||
if nets.disconnectDialog.IsDisplay() {
|
||||
nets.disconnectDialog.SetRect(x, y, width, height)
|
||||
nets.disconnectDialog.Draw(screen)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// message dialog
|
||||
if nets.messageDialog.IsDisplay() {
|
||||
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
|
||||
}
|
||||
|
||||
// confirm dialog
|
||||
if nets.confirmDialog.IsDisplay() {
|
||||
nets.confirmDialog.SetRect(x, y, width, height)
|
||||
nets.confirmDialog.Draw(screen)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// progress dialog
|
||||
if nets.progressDialog.IsDisplay() {
|
||||
nets.progressDialog.SetRect(x, y, width, height)
|
||||
nets.progressDialog.Draw(screen)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ import (
|
|||
)
|
||||
|
||||
// InputHandler returns the handler for this primitive.
|
||||
func (nets *Networks) InputHandler() func(event *tcell.EventKey, setFocus func(p tview.Primitive)) { //nolint:cyclop
|
||||
func (nets *Networks) InputHandler() func(event *tcell.EventKey, setFocus func(p tview.Primitive)) { //nolint:gocognit,lll,cyclop
|
||||
return nets.WrapInputHandler(func(event *tcell.EventKey, setFocus func(p tview.Primitive)) {
|
||||
log.Debug().Msgf("view: networks event %v received", event)
|
||||
|
||||
|
@ -16,11 +16,52 @@ func (nets *Networks) InputHandler() func(event *tcell.EventKey, setFocus func(p
|
|||
return
|
||||
}
|
||||
|
||||
for _, dialog := range nets.getInnerDialogs() {
|
||||
if dialog.HasFocus() {
|
||||
if dialogHandler := dialog.InputHandler(); dialogHandler != nil {
|
||||
dialogHandler(event, setFocus)
|
||||
}
|
||||
// error dialog handler
|
||||
if nets.errorDialog.HasFocus() {
|
||||
if errorDialogHandler := nets.errorDialog.InputHandler(); errorDialogHandler != nil {
|
||||
errorDialogHandler(event, setFocus)
|
||||
}
|
||||
}
|
||||
|
||||
// message dialog handler
|
||||
if nets.messageDialog.HasFocus() {
|
||||
if messageDialogHandler := nets.messageDialog.InputHandler(); messageDialogHandler != nil {
|
||||
messageDialogHandler(event, setFocus)
|
||||
}
|
||||
}
|
||||
|
||||
// create dialog handler
|
||||
if nets.createDialog.HasFocus() {
|
||||
if createDialogHandler := nets.createDialog.InputHandler(); createDialogHandler != nil {
|
||||
createDialogHandler(event, setFocus)
|
||||
}
|
||||
}
|
||||
|
||||
// connect dialog handler
|
||||
if nets.connectDialog.HasFocus() {
|
||||
if connectDialogHandler := nets.connectDialog.InputHandler(); connectDialogHandler != nil {
|
||||
connectDialogHandler(event, setFocus)
|
||||
}
|
||||
}
|
||||
|
||||
// disconnect dialog handler
|
||||
if nets.disconnectDialog.HasFocus() {
|
||||
if disconnectDialogHandler := nets.disconnectDialog.InputHandler(); disconnectDialogHandler != nil {
|
||||
disconnectDialogHandler(event, setFocus)
|
||||
}
|
||||
}
|
||||
|
||||
// confirm dialog handler
|
||||
if nets.confirmDialog.HasFocus() {
|
||||
if confirmDialogHandler := nets.confirmDialog.InputHandler(); confirmDialogHandler != nil {
|
||||
confirmDialogHandler(event, setFocus)
|
||||
}
|
||||
}
|
||||
|
||||
// command dialog handler
|
||||
if nets.cmdDialog.HasFocus() {
|
||||
if cmdHandler := nets.cmdDialog.InputHandler(); cmdHandler != nil {
|
||||
cmdHandler(event, setFocus)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -38,14 +79,6 @@ func (nets *Networks) InputHandler() func(event *tcell.EventKey, setFocus func(p
|
|||
return
|
||||
}
|
||||
|
||||
// display sort menu
|
||||
if event.Rune() == utils.SortMenuKey.Rune() {
|
||||
nets.sortDialog.Display()
|
||||
setFocus(nets)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if event.Key() == utils.DeleteKey.EventKey() {
|
||||
nets.rm()
|
||||
setFocus(nets)
|
||||
|
|
|
@ -32,7 +32,6 @@ const (
|
|||
// NetworkConnectDialog implements network connect dialog primitive.
|
||||
type NetworkConnectDialog struct {
|
||||
*tview.Box
|
||||
|
||||
layout *tview.Flex
|
||||
network *tview.InputField
|
||||
container *tview.DropDown
|
||||
|
@ -323,9 +322,9 @@ func (d *NetworkConnectDialog) Draw(screen tcell.Screen) {
|
|||
return
|
||||
}
|
||||
|
||||
d.DrawForSubclass(screen, d)
|
||||
d.Box.DrawForSubclass(screen, d)
|
||||
|
||||
x, y, width, height := d.GetInnerRect()
|
||||
x, y, width, height := d.Box.GetInnerRect()
|
||||
|
||||
d.layout.SetRect(x, y, width, height)
|
||||
d.layout.Draw(screen)
|
||||
|
@ -351,6 +350,21 @@ func (d *NetworkConnectDialog) SetCancelFunc(handler func()) *NetworkConnectDial
|
|||
return d
|
||||
}
|
||||
|
||||
func (d *NetworkConnectDialog) setFocusElement() {
|
||||
switch d.focusElement {
|
||||
case netConnectContainerFocus:
|
||||
d.focusElement = netConnectAliasesFocus
|
||||
case netConnectAliasesFocus:
|
||||
d.focusElement = netConnectAliasesIPv4Focus
|
||||
case netConnectAliasesIPv4Focus:
|
||||
d.focusElement = netConnectAliasesIPv6Focus
|
||||
case netConnectAliasesIPv6Focus:
|
||||
d.focusElement = netConnectMacAddrFocus
|
||||
case netConnectMacAddrFocus:
|
||||
d.focusElement = netConnectFormFocus
|
||||
}
|
||||
}
|
||||
|
||||
// SetNetworkInfo sets selected network name in connect dialog.
|
||||
func (d *NetworkConnectDialog) SetNetworkInfo(id, name string) {
|
||||
d.networkName = name
|
||||
|
@ -386,18 +400,3 @@ func (d *NetworkConnectDialog) GetConnectOptions() networks.NetworkConnect {
|
|||
|
||||
return connectOptions
|
||||
}
|
||||
|
||||
func (d *NetworkConnectDialog) setFocusElement() {
|
||||
switch d.focusElement {
|
||||
case netConnectContainerFocus:
|
||||
d.focusElement = netConnectAliasesFocus
|
||||
case netConnectAliasesFocus:
|
||||
d.focusElement = netConnectAliasesIPv4Focus
|
||||
case netConnectAliasesIPv4Focus:
|
||||
d.focusElement = netConnectAliasesIPv6Focus
|
||||
case netConnectAliasesIPv6Focus:
|
||||
d.focusElement = netConnectMacAddrFocus
|
||||
case netConnectMacAddrFocus:
|
||||
d.focusElement = netConnectFormFocus
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,7 +42,6 @@ const (
|
|||
// NetworkCreateDialog implements network create dialog.
|
||||
type NetworkCreateDialog struct {
|
||||
*tview.Box
|
||||
|
||||
layout *tview.Flex
|
||||
categoryLabels []string
|
||||
categories *tview.TextView
|
||||
|
@ -205,6 +204,49 @@ func NewNetworkCreateDialog() *NetworkCreateDialog {
|
|||
return &netDialog
|
||||
}
|
||||
|
||||
func (d *NetworkCreateDialog) setupLayout() {
|
||||
bgColor := style.DialogBgColor
|
||||
|
||||
// basic info page
|
||||
d.basicInfoPage.SetDirection(tview.FlexRow)
|
||||
d.basicInfoPage.AddItem(d.networkNameField, 1, 0, true)
|
||||
d.basicInfoPage.AddItem(utils.EmptyBoxSpace(bgColor), 1, 0, true)
|
||||
d.basicInfoPage.AddItem(d.networkLabelsField, 1, 0, true)
|
||||
d.basicInfoPage.AddItem(utils.EmptyBoxSpace(bgColor), 1, 0, true)
|
||||
d.basicInfoPage.AddItem(d.networkInternalCheckBox, 1, 0, true)
|
||||
d.basicInfoPage.AddItem(utils.EmptyBoxSpace(bgColor), 1, 0, true)
|
||||
d.basicInfoPage.AddItem(d.networkDriverField, 1, 0, true)
|
||||
d.basicInfoPage.AddItem(utils.EmptyBoxSpace(bgColor), 1, 0, true)
|
||||
d.basicInfoPage.AddItem(d.networkDriverOptionsField, 1, 0, true)
|
||||
d.basicInfoPage.SetBackgroundColor(bgColor)
|
||||
|
||||
// ip settings page
|
||||
d.ipSettingsPage.SetDirection(tview.FlexRow)
|
||||
d.ipSettingsPage.AddItem(d.networkIpv6CheckBox, 1, 0, true)
|
||||
d.ipSettingsPage.AddItem(utils.EmptyBoxSpace(bgColor), 1, 0, true)
|
||||
d.ipSettingsPage.AddItem(d.networkGatewayField, 1, 0, true)
|
||||
d.ipSettingsPage.AddItem(utils.EmptyBoxSpace(bgColor), 1, 0, true)
|
||||
d.ipSettingsPage.AddItem(d.networkIPRangeField, 1, 0, true)
|
||||
d.ipSettingsPage.AddItem(utils.EmptyBoxSpace(bgColor), 1, 0, true)
|
||||
d.ipSettingsPage.AddItem(d.networkSubnetField, 1, 0, true)
|
||||
d.ipSettingsPage.AddItem(utils.EmptyBoxSpace(bgColor), 1, 0, true)
|
||||
d.ipSettingsPage.AddItem(d.networkDisableDNSCheckBox, 1, 0, true)
|
||||
d.ipSettingsPage.SetBackgroundColor(bgColor)
|
||||
|
||||
// adding category pages
|
||||
d.categoryPages.AddPage(d.categoryLabels[basicInfoPageIndex], d.basicInfoPage, true, true)
|
||||
d.categoryPages.AddPage(d.categoryLabels[ipSettingsPageIndex], d.ipSettingsPage, true, true)
|
||||
|
||||
// add it to layout.
|
||||
_, layoutWidth := utils.AlignStringListWidth(d.categoryLabels)
|
||||
layout := tview.NewFlex().SetDirection(tview.FlexColumn)
|
||||
layout.AddItem(d.categories, layoutWidth+6, 0, true) //nolint:mnd
|
||||
layout.AddItem(d.categoryPages, 0, 1, true)
|
||||
layout.SetBackgroundColor(bgColor)
|
||||
|
||||
d.layout.AddItem(layout, 0, 1, true)
|
||||
}
|
||||
|
||||
// Display displays this primitive.
|
||||
func (d *NetworkCreateDialog) Display() {
|
||||
d.display = true
|
||||
|
@ -392,8 +434,8 @@ func (d *NetworkCreateDialog) Draw(screen tcell.Screen) {
|
|||
return
|
||||
}
|
||||
|
||||
d.DrawForSubclass(screen, d)
|
||||
x, y, width, height := d.GetInnerRect()
|
||||
d.Box.DrawForSubclass(screen, d)
|
||||
x, y, width, height := d.Box.GetInnerRect()
|
||||
|
||||
d.layout.SetRect(x, y, width, height)
|
||||
d.layout.Draw(screen)
|
||||
|
@ -419,115 +461,6 @@ func (d *NetworkCreateDialog) SetCreateFunc(handler func()) *NetworkCreateDialog
|
|||
return d
|
||||
}
|
||||
|
||||
// NetworkCreateOptions returns new network options.
|
||||
func (d *NetworkCreateDialog) NetworkCreateOptions() networks.CreateOptions { //nolint:cyclop
|
||||
var (
|
||||
labels = make(map[string]string)
|
||||
options = make(map[string]string)
|
||||
subnets []string
|
||||
gateways []string
|
||||
ipranges []string
|
||||
)
|
||||
|
||||
for _, label := range strings.Split(d.networkLabelsField.GetText(), " ") {
|
||||
if label != "" {
|
||||
split := strings.Split(label, "=")
|
||||
if len(split) == 2 { //nolint:mnd
|
||||
key := split[0]
|
||||
value := split[1]
|
||||
|
||||
if key != "" && value != "" {
|
||||
labels[key] = value
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, option := range strings.Split(d.networkDriverOptionsField.GetText(), " ") {
|
||||
if option != "" {
|
||||
split := strings.Split(option, "=")
|
||||
if len(split) == 2 { //nolint:mnd
|
||||
key := split[0]
|
||||
value := split[1]
|
||||
|
||||
if key != "" && value != "" {
|
||||
options[key] = value
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if strings.Trim(d.networkGatewayField.GetText(), " ") != "" {
|
||||
gateways = strings.Split(d.networkGatewayField.GetText(), " ")
|
||||
}
|
||||
|
||||
if strings.Trim(d.networkSubnetField.GetText(), " ") != "" {
|
||||
subnets = strings.Split(d.networkSubnetField.GetText(), " ")
|
||||
}
|
||||
|
||||
if strings.Trim(d.networkIPRangeField.GetText(), " ") != "" {
|
||||
ipranges = strings.Split(d.networkIPRangeField.GetText(), " ")
|
||||
}
|
||||
|
||||
opts := networks.CreateOptions{
|
||||
Name: strings.TrimSpace(d.networkNameField.GetText()),
|
||||
Labels: labels,
|
||||
Internal: d.networkInternalCheckBox.IsChecked(),
|
||||
Drivers: strings.TrimSpace(d.networkDriverField.GetText()),
|
||||
DriversOptions: options,
|
||||
IPv6: d.networkIpv6CheckBox.IsChecked(),
|
||||
Gateways: gateways,
|
||||
Subnets: subnets,
|
||||
IPRanges: ipranges,
|
||||
DisableDNS: d.networkDisableDNSCheckBox.IsChecked(),
|
||||
}
|
||||
|
||||
return opts
|
||||
}
|
||||
|
||||
func (d *NetworkCreateDialog) setupLayout() {
|
||||
bgColor := style.DialogBgColor
|
||||
|
||||
// basic info page
|
||||
d.basicInfoPage.SetDirection(tview.FlexRow)
|
||||
d.basicInfoPage.AddItem(d.networkNameField, 1, 0, true)
|
||||
d.basicInfoPage.AddItem(utils.EmptyBoxSpace(bgColor), 1, 0, true)
|
||||
d.basicInfoPage.AddItem(d.networkLabelsField, 1, 0, true)
|
||||
d.basicInfoPage.AddItem(utils.EmptyBoxSpace(bgColor), 1, 0, true)
|
||||
d.basicInfoPage.AddItem(d.networkInternalCheckBox, 1, 0, true)
|
||||
d.basicInfoPage.AddItem(utils.EmptyBoxSpace(bgColor), 1, 0, true)
|
||||
d.basicInfoPage.AddItem(d.networkDriverField, 1, 0, true)
|
||||
d.basicInfoPage.AddItem(utils.EmptyBoxSpace(bgColor), 1, 0, true)
|
||||
d.basicInfoPage.AddItem(d.networkDriverOptionsField, 1, 0, true)
|
||||
d.basicInfoPage.SetBackgroundColor(bgColor)
|
||||
|
||||
// ip settings page
|
||||
d.ipSettingsPage.SetDirection(tview.FlexRow)
|
||||
d.ipSettingsPage.AddItem(d.networkIpv6CheckBox, 1, 0, true)
|
||||
d.ipSettingsPage.AddItem(utils.EmptyBoxSpace(bgColor), 1, 0, true)
|
||||
d.ipSettingsPage.AddItem(d.networkGatewayField, 1, 0, true)
|
||||
d.ipSettingsPage.AddItem(utils.EmptyBoxSpace(bgColor), 1, 0, true)
|
||||
d.ipSettingsPage.AddItem(d.networkIPRangeField, 1, 0, true)
|
||||
d.ipSettingsPage.AddItem(utils.EmptyBoxSpace(bgColor), 1, 0, true)
|
||||
d.ipSettingsPage.AddItem(d.networkSubnetField, 1, 0, true)
|
||||
d.ipSettingsPage.AddItem(utils.EmptyBoxSpace(bgColor), 1, 0, true)
|
||||
d.ipSettingsPage.AddItem(d.networkDisableDNSCheckBox, 1, 0, true)
|
||||
d.ipSettingsPage.SetBackgroundColor(bgColor)
|
||||
|
||||
// adding category pages
|
||||
d.categoryPages.AddPage(d.categoryLabels[basicInfoPageIndex], d.basicInfoPage, true, true)
|
||||
d.categoryPages.AddPage(d.categoryLabels[ipSettingsPageIndex], d.ipSettingsPage, true, true)
|
||||
|
||||
// add it to layout.
|
||||
_, layoutWidth := utils.AlignStringListWidth(d.categoryLabels)
|
||||
layout := tview.NewFlex().SetDirection(tview.FlexColumn)
|
||||
layout.AddItem(d.categories, layoutWidth+6, 0, true) //nolint:mnd
|
||||
layout.AddItem(d.categoryPages, 0, 1, true)
|
||||
layout.SetBackgroundColor(bgColor)
|
||||
|
||||
d.layout.AddItem(layout, 0, 1, true)
|
||||
}
|
||||
|
||||
func (d *NetworkCreateDialog) setActiveCategory(index int) {
|
||||
fgColor := style.DialogFgColor
|
||||
bgColor := style.ButtonBgColor
|
||||
|
@ -651,3 +584,69 @@ func (d *NetworkCreateDialog) setIPSettingsPageNextFocus() {
|
|||
|
||||
d.focusElement = formFocus
|
||||
}
|
||||
|
||||
// NetworkCreateOptions returns new network options.
|
||||
func (d *NetworkCreateDialog) NetworkCreateOptions() networks.CreateOptions { //nolint:cyclop
|
||||
var (
|
||||
labels = make(map[string]string)
|
||||
options = make(map[string]string)
|
||||
subnets []string
|
||||
gateways []string
|
||||
ipranges []string
|
||||
)
|
||||
|
||||
for _, label := range strings.Split(d.networkLabelsField.GetText(), " ") {
|
||||
if label != "" {
|
||||
split := strings.Split(label, "=")
|
||||
if len(split) == 2 { //nolint:mnd
|
||||
key := split[0]
|
||||
value := split[1]
|
||||
|
||||
if key != "" && value != "" {
|
||||
labels[key] = value
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, option := range strings.Split(d.networkDriverOptionsField.GetText(), " ") {
|
||||
if option != "" {
|
||||
split := strings.Split(option, "=")
|
||||
if len(split) == 2 { //nolint:mnd
|
||||
key := split[0]
|
||||
value := split[1]
|
||||
|
||||
if key != "" && value != "" {
|
||||
options[key] = value
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if strings.Trim(d.networkGatewayField.GetText(), " ") != "" {
|
||||
gateways = strings.Split(d.networkGatewayField.GetText(), " ")
|
||||
}
|
||||
|
||||
if strings.Trim(d.networkSubnetField.GetText(), " ") != "" {
|
||||
subnets = strings.Split(d.networkSubnetField.GetText(), " ")
|
||||
}
|
||||
|
||||
if strings.Trim(d.networkIPRangeField.GetText(), " ") != "" {
|
||||
ipranges = strings.Split(d.networkIPRangeField.GetText(), " ")
|
||||
}
|
||||
|
||||
opts := networks.CreateOptions{
|
||||
Name: strings.TrimSpace(d.networkNameField.GetText()),
|
||||
Labels: labels,
|
||||
Internal: d.networkInternalCheckBox.IsChecked(),
|
||||
Drivers: strings.TrimSpace(d.networkDriverField.GetText()),
|
||||
DriversOptions: options,
|
||||
IPv6: d.networkIpv6CheckBox.IsChecked(),
|
||||
Gateways: gateways,
|
||||
Subnets: subnets,
|
||||
IPRanges: ipranges,
|
||||
DisableDNS: d.networkDisableDNSCheckBox.IsChecked(),
|
||||
}
|
||||
|
||||
return opts
|
||||
}
|
||||
|
|
|
@ -26,7 +26,6 @@ const (
|
|||
// NetworkDisconnectDialog implements network disconnect dialog primitive.
|
||||
type NetworkDisconnectDialog struct {
|
||||
*tview.Box
|
||||
|
||||
layout *tview.Flex
|
||||
network *tview.InputField
|
||||
container *tview.DropDown
|
||||
|
@ -225,9 +224,9 @@ func (d *NetworkDisconnectDialog) Draw(screen tcell.Screen) {
|
|||
return
|
||||
}
|
||||
|
||||
d.DrawForSubclass(screen, d)
|
||||
d.Box.DrawForSubclass(screen, d)
|
||||
|
||||
x, y, width, height := d.GetInnerRect()
|
||||
x, y, width, height := d.Box.GetInnerRect()
|
||||
|
||||
d.layout.SetRect(x, y, width, height)
|
||||
d.layout.Draw(screen)
|
||||
|
@ -265,6 +264,12 @@ func (d *NetworkDisconnectDialog) SetContainers(cntList []entities.ListContainer
|
|||
d.container.SetOptions(containers, nil)
|
||||
}
|
||||
|
||||
func (d *NetworkDisconnectDialog) setFocusElement() {
|
||||
if d.focusElement == netDisconnectContainerFocus {
|
||||
d.focusElement = netConnectFormFocus
|
||||
}
|
||||
}
|
||||
|
||||
// SetNetworkInfo sets selected network name in disconnect dialog.
|
||||
func (d *NetworkDisconnectDialog) SetNetworkInfo(id string, name string) {
|
||||
d.networkName = name
|
||||
|
@ -280,9 +285,3 @@ func (d *NetworkDisconnectDialog) GetDisconnectOptions() (string, string) {
|
|||
|
||||
return d.networkName, container
|
||||
}
|
||||
|
||||
func (d *NetworkDisconnectDialog) setFocusElement() {
|
||||
if d.focusElement == netDisconnectContainerFocus {
|
||||
d.focusElement = netConnectFormFocus
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,11 +6,9 @@ import (
|
|||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/containers/common/libnetwork/types"
|
||||
"github.com/containers/podman-tui/ui/dialogs"
|
||||
"github.com/containers/podman-tui/ui/networks/netdialogs"
|
||||
"github.com/containers/podman-tui/ui/style"
|
||||
"github.com/containers/podman-tui/ui/utils"
|
||||
"github.com/rivo/tview"
|
||||
)
|
||||
|
||||
|
@ -30,7 +28,6 @@ var (
|
|||
// Networks implemnents the Networks page primitive.
|
||||
type Networks struct {
|
||||
*tview.Box
|
||||
|
||||
title string
|
||||
headers []string
|
||||
table *tview.Table
|
||||
|
@ -39,7 +36,6 @@ type Networks struct {
|
|||
confirmDialog *dialogs.ConfirmDialog
|
||||
cmdDialog *dialogs.CommandDialog
|
||||
messageDialog *dialogs.MessageDialog
|
||||
sortDialog *dialogs.SortDialog
|
||||
createDialog *netdialogs.NetworkCreateDialog
|
||||
connectDialog *netdialogs.NetworkConnectDialog
|
||||
disconnectDialog *netdialogs.NetworkDisconnectDialog
|
||||
|
@ -50,10 +46,8 @@ type Networks struct {
|
|||
}
|
||||
|
||||
type networkListReport struct {
|
||||
mu sync.Mutex
|
||||
report []types.Network
|
||||
sortBy string
|
||||
ascending bool
|
||||
mu sync.Mutex
|
||||
report [][]string
|
||||
}
|
||||
|
||||
// NewNetworks returns nets page view.
|
||||
|
@ -66,11 +60,9 @@ func NewNetworks() *Networks {
|
|||
progressDialog: dialogs.NewProgressDialog(),
|
||||
confirmDialog: dialogs.NewConfirmDialog(),
|
||||
messageDialog: dialogs.NewMessageDialog(""),
|
||||
sortDialog: dialogs.NewSortDialog([]string{"name", "driver"}, 0),
|
||||
createDialog: netdialogs.NewNetworkCreateDialog(),
|
||||
connectDialog: netdialogs.NewNetworkConnectDialog(),
|
||||
disconnectDialog: netdialogs.NewNetworkDisconnectDialog(),
|
||||
networkList: networkListReport{sortBy: "name", ascending: true},
|
||||
}
|
||||
|
||||
nets.cmdDialog = dialogs.NewCommandDialog([][]string{
|
||||
|
@ -122,7 +114,7 @@ func NewNetworks() *Networks {
|
|||
nets.confirmDialog.Hide()
|
||||
|
||||
switch nets.confirmData {
|
||||
case utils.PruneCommandLabel:
|
||||
case "prune":
|
||||
nets.prune()
|
||||
case "rm":
|
||||
nets.remove()
|
||||
|
@ -151,10 +143,6 @@ func NewNetworks() *Networks {
|
|||
nets.disconnectDialog.SetCancelFunc(nets.disconnectDialog.Hide)
|
||||
nets.disconnectDialog.SetDisconnectFunc(nets.disconnect)
|
||||
|
||||
// set sort dialog functions
|
||||
nets.sortDialog.SetCancelFunc(nets.sortDialog.Hide)
|
||||
nets.sortDialog.SetSelectFunc(nets.SortView)
|
||||
|
||||
return nets
|
||||
}
|
||||
|
||||
|
@ -169,12 +157,24 @@ func (nets *Networks) GetTitle() string {
|
|||
}
|
||||
|
||||
// HasFocus returns whether or not this primitive has focus.
|
||||
func (nets *Networks) HasFocus() bool {
|
||||
if nets.SubDialogHasFocus() {
|
||||
func (nets *Networks) HasFocus() bool { //nolint:cyclop
|
||||
if nets.table.HasFocus() || nets.errorDialog.HasFocus() {
|
||||
return true
|
||||
}
|
||||
|
||||
if nets.table.HasFocus() || nets.Box.HasFocus() {
|
||||
if nets.cmdDialog.HasFocus() || nets.messageDialog.IsDisplay() {
|
||||
return true
|
||||
}
|
||||
|
||||
if nets.progressDialog.HasFocus() || nets.confirmDialog.IsDisplay() {
|
||||
return true
|
||||
}
|
||||
|
||||
if nets.createDialog.HasFocus() || nets.connectDialog.HasFocus() {
|
||||
return true
|
||||
}
|
||||
|
||||
if nets.disconnectDialog.HasFocus() || nets.Box.HasFocus() {
|
||||
return true
|
||||
}
|
||||
|
||||
|
@ -183,10 +183,20 @@ func (nets *Networks) HasFocus() bool {
|
|||
|
||||
// SubDialogHasFocus returns whether or not sub dialog primitive has focus.
|
||||
func (nets *Networks) SubDialogHasFocus() bool {
|
||||
for _, dialog := range nets.getInnerDialogs() {
|
||||
if dialog.HasFocus() {
|
||||
return true
|
||||
}
|
||||
if nets.createDialog.HasFocus() || nets.errorDialog.HasFocus() {
|
||||
return true
|
||||
}
|
||||
|
||||
if nets.cmdDialog.HasFocus() || nets.messageDialog.IsDisplay() {
|
||||
return true
|
||||
}
|
||||
|
||||
if nets.progressDialog.HasFocus() || nets.confirmDialog.IsDisplay() {
|
||||
return true
|
||||
}
|
||||
|
||||
if nets.connectDialog.HasFocus() || nets.disconnectDialog.HasFocus() {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
|
@ -194,38 +204,58 @@ func (nets *Networks) SubDialogHasFocus() bool {
|
|||
|
||||
// Focus is called when this primitive receives focus.
|
||||
func (nets *Networks) Focus(delegate func(p tview.Primitive)) {
|
||||
// error dialog
|
||||
if nets.errorDialog.IsDisplay() {
|
||||
delegate(nets.errorDialog)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// command dialog
|
||||
if nets.cmdDialog.IsDisplay() {
|
||||
delegate(nets.cmdDialog)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// message dialog
|
||||
if nets.messageDialog.IsDisplay() {
|
||||
delegate(nets.messageDialog)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// confirm dialog
|
||||
if nets.confirmDialog.IsDisplay() {
|
||||
delegate(nets.confirmDialog)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
for _, dialog := range nets.getInnerDialogs() {
|
||||
if dialog.IsDisplay() {
|
||||
delegate(dialog)
|
||||
// create dialog
|
||||
if nets.createDialog.IsDisplay() {
|
||||
delegate(nets.createDialog)
|
||||
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// connect dialog
|
||||
if nets.connectDialog.IsDisplay() {
|
||||
delegate(nets.connectDialog)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// disconnect dialog
|
||||
if nets.disconnectDialog.IsDisplay() {
|
||||
delegate(nets.disconnectDialog)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
delegate(nets.table)
|
||||
}
|
||||
|
||||
// HideAllDialogs hides all sub dialogs.
|
||||
func (nets *Networks) HideAllDialogs() {
|
||||
for _, dialog := range nets.getInnerDialogs() {
|
||||
if dialog.IsDisplay() {
|
||||
dialog.Hide()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (nets *Networks) getSelectedItem() (string, string) {
|
||||
if nets.table.GetRowCount() <= 1 {
|
||||
return "", ""
|
||||
|
@ -238,18 +268,37 @@ func (nets *Networks) getSelectedItem() (string, string) {
|
|||
return netID, netName
|
||||
}
|
||||
|
||||
func (nets *Networks) getInnerDialogs() []utils.UIDialog {
|
||||
dialogs := []utils.UIDialog{
|
||||
nets.errorDialog,
|
||||
nets.progressDialog,
|
||||
nets.confirmDialog,
|
||||
nets.cmdDialog,
|
||||
nets.messageDialog,
|
||||
nets.connectDialog,
|
||||
nets.createDialog,
|
||||
nets.disconnectDialog,
|
||||
nets.sortDialog,
|
||||
// HideAllDialogs hides all sub dialogs.
|
||||
func (nets *Networks) HideAllDialogs() {
|
||||
if nets.errorDialog.IsDisplay() {
|
||||
nets.errorDialog.Hide()
|
||||
}
|
||||
|
||||
return dialogs
|
||||
if nets.progressDialog.IsDisplay() {
|
||||
nets.progressDialog.Hide()
|
||||
}
|
||||
|
||||
if nets.confirmDialog.IsDisplay() {
|
||||
nets.confirmDialog.Hide()
|
||||
}
|
||||
|
||||
if nets.cmdDialog.IsDisplay() {
|
||||
nets.cmdDialog.Hide()
|
||||
}
|
||||
|
||||
if nets.messageDialog.IsDisplay() {
|
||||
nets.messageDialog.Hide()
|
||||
}
|
||||
|
||||
if nets.createDialog.IsDisplay() {
|
||||
nets.createDialog.Hide()
|
||||
}
|
||||
|
||||
if nets.connectDialog.IsDisplay() {
|
||||
nets.connectDialog.Hide()
|
||||
}
|
||||
|
||||
if nets.disconnectDialog.IsDisplay() {
|
||||
nets.disconnectDialog.Hide()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,38 +24,34 @@ func (nets *Networks) refresh(_ int) {
|
|||
SetSelectable(false))
|
||||
}
|
||||
|
||||
currentSelectedRow, _ := nets.table.GetSelection()
|
||||
rowIndex := 1
|
||||
netList := nets.getData()
|
||||
|
||||
nets.table.SetTitle(fmt.Sprintf("[::b]%s[%d]", strings.ToUpper(nets.title), len(netList)))
|
||||
|
||||
for _, net := range netList {
|
||||
for i := range netList {
|
||||
netID := netList[i][0]
|
||||
netName := netList[i][1]
|
||||
netDriver := netList[i][2]
|
||||
|
||||
// name column
|
||||
nets.table.SetCell(rowIndex, viewNetworkNameColIndex,
|
||||
tview.NewTableCell(net.ID[:12]).
|
||||
tview.NewTableCell(netID[:12]).
|
||||
SetExpansion(expand).
|
||||
SetAlign(alignment))
|
||||
|
||||
// version column
|
||||
nets.table.SetCell(rowIndex, viewNetworkVersionColIndex,
|
||||
tview.NewTableCell(net.Name).
|
||||
tview.NewTableCell(netName).
|
||||
SetExpansion(expand).
|
||||
SetAlign(alignment))
|
||||
|
||||
// plugins at column
|
||||
nets.table.SetCell(rowIndex, viewNetworkPluginColIndex,
|
||||
tview.NewTableCell(net.Driver).
|
||||
tview.NewTableCell(netDriver).
|
||||
SetExpansion(expand).
|
||||
SetAlign(alignment))
|
||||
|
||||
rowIndex++
|
||||
}
|
||||
|
||||
if currentSelectedRow > len(netList) {
|
||||
currentSelectedRow--
|
||||
if currentSelectedRow >= 0 {
|
||||
nets.table.Select(currentSelectedRow, -1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@ import (
|
|||
ppods "github.com/containers/podman-tui/pdcs/pods"
|
||||
"github.com/containers/podman-tui/ui/dialogs"
|
||||
"github.com/containers/podman-tui/ui/style"
|
||||
"github.com/containers/podman-tui/ui/utils"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
|
@ -21,9 +20,9 @@ func (p *Pods) runCommand(cmd string) { //nolint:cyclop
|
|||
p.kill()
|
||||
case "pause":
|
||||
p.pause()
|
||||
case utils.PruneCommandLabel:
|
||||
case "prune": //nolint:goconst
|
||||
p.confirmDialog.SetTitle("podman pod prune")
|
||||
p.confirmData = utils.PruneCommandLabel
|
||||
p.confirmData = "prune"
|
||||
p.confirmDialog.SetText("Are you sure you want to remove all stopped pods ?")
|
||||
p.confirmDialog.Display()
|
||||
case "restart":
|
||||
|
|
|
@ -2,8 +2,6 @@ package pods
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
ppods "github.com/containers/podman-tui/pdcs/pods"
|
||||
|
@ -13,18 +11,6 @@ import (
|
|||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
// SortView sorts data view called from sort dialog.
|
||||
func (pods *Pods) SortView(option string, ascending bool) {
|
||||
log.Debug().Msgf("view: pods sort by %s", option)
|
||||
|
||||
pods.podsList.mu.Lock()
|
||||
defer pods.podsList.mu.Unlock()
|
||||
|
||||
pods.podsList.sortBy = option
|
||||
pods.podsList.ascending = ascending
|
||||
sort.Sort(containerListSorted{pods.podsList.report, option, ascending})
|
||||
}
|
||||
|
||||
// UpdateData retrieves pods list data.
|
||||
func (pods *Pods) UpdateData() {
|
||||
podList, err := ppods.List()
|
||||
|
@ -39,7 +25,6 @@ func (pods *Pods) UpdateData() {
|
|||
pods.podsList.mu.Lock()
|
||||
defer pods.podsList.mu.Unlock()
|
||||
|
||||
sort.Sort(containerListSorted{podList, pods.podsList.sortBy, pods.podsList.ascending})
|
||||
pods.podsList.report = podList
|
||||
}
|
||||
|
||||
|
@ -53,7 +38,7 @@ func (pods *Pods) getData() []*entities.ListPodsReport {
|
|||
}
|
||||
|
||||
// ClearData clears table data.
|
||||
func (pods *Pods) ClearData() {
|
||||
func (pods *Pods) ClearData() { //nolint:stylecheck
|
||||
pods.podsList.mu.Lock()
|
||||
defer pods.podsList.mu.Unlock()
|
||||
|
||||
|
@ -77,47 +62,3 @@ func (pods *Pods) ClearData() {
|
|||
|
||||
pods.table.SetTitle(fmt.Sprintf("[::b]%s[0]", strings.ToUpper(pods.title)))
|
||||
}
|
||||
|
||||
type lprSort []*entities.ListPodsReport
|
||||
|
||||
func (a lprSort) Len() int { return len(a) }
|
||||
func (a lprSort) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||
|
||||
type containerListSorted struct {
|
||||
lprSort
|
||||
|
||||
option string
|
||||
ascending bool
|
||||
}
|
||||
|
||||
func (a containerListSorted) Less(i, j int) bool {
|
||||
switch a.option {
|
||||
case "# of containers":
|
||||
iNumOfCnt := strconv.Itoa(len(a.lprSort[i].Containers))
|
||||
jNumOfCnt := strconv.Itoa(len(a.lprSort[j].Containers))
|
||||
|
||||
if a.ascending {
|
||||
return iNumOfCnt < jNumOfCnt
|
||||
}
|
||||
|
||||
return iNumOfCnt > jNumOfCnt
|
||||
case "status":
|
||||
if a.ascending {
|
||||
return a.lprSort[i].Status < a.lprSort[j].Status
|
||||
}
|
||||
|
||||
return a.lprSort[i].Status > a.lprSort[j].Status
|
||||
case "created":
|
||||
if a.ascending {
|
||||
return a.lprSort[i].Created.After(a.lprSort[j].Created)
|
||||
}
|
||||
|
||||
return a.lprSort[i].Created.Before(a.lprSort[j].Created)
|
||||
}
|
||||
|
||||
if a.ascending {
|
||||
return a.lprSort[i].Name < a.lprSort[j].Name
|
||||
}
|
||||
|
||||
return a.lprSort[i].Name > a.lprSort[j].Name
|
||||
}
|
||||
|
|
|
@ -5,9 +5,9 @@ import (
|
|||
)
|
||||
|
||||
// Draw draws this primitive onto the screen.
|
||||
func (pods *Pods) Draw(screen tcell.Screen) { //nolint:cyclop
|
||||
pods.DrawForSubclass(screen, pods)
|
||||
pods.SetBorder(false)
|
||||
func (pods *Pods) Draw(screen tcell.Screen) {
|
||||
pods.Box.DrawForSubclass(screen, pods)
|
||||
pods.Box.SetBorder(false)
|
||||
|
||||
podViewX, podViewY, podViewW, podViewH := pods.GetInnerRect()
|
||||
|
||||
|
@ -78,19 +78,11 @@ func (pods *Pods) Draw(screen tcell.Screen) { //nolint:cyclop
|
|||
return
|
||||
}
|
||||
|
||||
// stats dialog
|
||||
// stats dialogs
|
||||
if pods.statsDialog.IsDisplay() {
|
||||
pods.statsDialog.SetRect(podViewX, podViewY, podViewW, podViewH)
|
||||
pods.statsDialog.Draw(screen)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// sort dialog
|
||||
if pods.sortDialog.IsDisplay() {
|
||||
pods.sortDialog.SetRect(podViewX, podViewY, podViewW, podViewH)
|
||||
pods.sortDialog.Draw(screen)
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
|
|
|
@ -65,13 +65,6 @@ func (pods *Pods) InputHandler() func(event *tcell.EventKey, setFocus func(p tvi
|
|||
}
|
||||
}
|
||||
|
||||
// pod sort dialog handler
|
||||
if pods.sortDialog.HasFocus() {
|
||||
if podsSortDialogHandler := pods.sortDialog.InputHandler(); podsSortDialogHandler != nil {
|
||||
podsSortDialogHandler(event, setFocus)
|
||||
}
|
||||
}
|
||||
|
||||
// table handlers
|
||||
if pods.table.HasFocus() { //nolint:nestif
|
||||
pods.selectedID, _ = pods.getSelectedItem()
|
||||
|
@ -86,14 +79,6 @@ func (pods *Pods) InputHandler() func(event *tcell.EventKey, setFocus func(p tvi
|
|||
return
|
||||
}
|
||||
|
||||
// display sort menu
|
||||
if event.Rune() == utils.SortMenuKey.Rune() {
|
||||
pods.sortDialog.Display()
|
||||
setFocus(pods)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if event.Key() == utils.DeleteKey.EventKey() {
|
||||
pods.rm()
|
||||
setFocus(pods)
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue