mirror of
https://github.com/jesseduffield/lazydocker.git
synced 2026-07-25 08:31:03 +00:00
completed phase 5
This commit is contained in:
parent
b24ed8cc71
commit
38f28b1209
20 changed files with 158 additions and 151 deletions
|
|
@ -65,23 +65,23 @@ logs:
|
|||
since: '60m' # set to '' to show all logs
|
||||
tail: '' # set to 200 to show last 200 lines of logs
|
||||
commandTemplates:
|
||||
dockerCompose: docker compose # Determines the Docker Compose command to run, referred to as .DockerCompose in commandTemplates
|
||||
restartService: '{{ .DockerCompose }} restart {{ .Service.Name }}'
|
||||
up: '{{ .DockerCompose }} up -d'
|
||||
down: '{{ .DockerCompose }} down'
|
||||
downWithVolumes: '{{ .DockerCompose }} down --volumes'
|
||||
upService: '{{ .DockerCompose }} up -d {{ .Service.Name }}'
|
||||
startService: '{{ .DockerCompose }} start {{ .Service.Name }}'
|
||||
stopService: '{{ .DockerCompose }} stop {{ .Service.Name }}'
|
||||
serviceLogs: '{{ .DockerCompose }} logs --since=60m --follow {{ .Service.Name }}'
|
||||
viewServiceLogs: '{{ .DockerCompose }} logs --follow {{ .Service.Name }}'
|
||||
rebuildService: '{{ .DockerCompose }} up -d --build {{ .Service.Name }}'
|
||||
recreateService: '{{ .DockerCompose }} up -d --force-recreate {{ .Service.Name }}'
|
||||
allLogs: '{{ .DockerCompose }} logs --tail=300 --follow'
|
||||
viewAlLogs: '{{ .DockerCompose }} logs'
|
||||
dockerComposeConfig: '{{ .DockerCompose }} config'
|
||||
checkDockerComposeConfig: '{{ .DockerCompose }} config --quiet'
|
||||
serviceTop: '{{ .DockerCompose }} top {{ .Service.Name }}'
|
||||
podmanCompose: podman-compose # Determines the compose command to run, referred to as .PodmanCompose in commandTemplates
|
||||
restartService: '{{ .PodmanCompose }} restart {{ .Service.Name }}'
|
||||
up: '{{ .PodmanCompose }} up -d'
|
||||
down: '{{ .PodmanCompose }} down'
|
||||
downWithVolumes: '{{ .PodmanCompose }} down --volumes'
|
||||
upService: '{{ .PodmanCompose }} up -d {{ .Service.Name }}'
|
||||
startService: '{{ .PodmanCompose }} start {{ .Service.Name }}'
|
||||
stopService: '{{ .PodmanCompose }} stop {{ .Service.Name }}'
|
||||
serviceLogs: '{{ .PodmanCompose }} logs --since=60m --follow {{ .Service.Name }}'
|
||||
viewServiceLogs: '{{ .PodmanCompose }} logs --follow {{ .Service.Name }}'
|
||||
rebuildService: '{{ .PodmanCompose }} up -d --build {{ .Service.Name }}'
|
||||
recreateService: '{{ .PodmanCompose }} up -d --force-recreate {{ .Service.Name }}'
|
||||
allLogs: '{{ .PodmanCompose }} logs --tail=300 --follow'
|
||||
viewAlLogs: '{{ .PodmanCompose }} logs'
|
||||
composeConfig: '{{ .PodmanCompose }} config'
|
||||
checkComposeConfig: '{{ .PodmanCompose }} config --quiet'
|
||||
serviceTop: '{{ .PodmanCompose }} top {{ .Service.Name }}'
|
||||
oS:
|
||||
openCommand: open {{filename}}
|
||||
openLinkCommand: open {{link}}
|
||||
|
|
@ -124,12 +124,12 @@ customCommands:
|
|||
containers:
|
||||
- name: bash
|
||||
attach: true
|
||||
command: 'docker exec -it {{ .Container.ID }} bash'
|
||||
command: 'podman exec -it {{ .Container.ID }} bash'
|
||||
serviceNames: []
|
||||
```
|
||||
|
||||
You may use the following go templates (such as `{{ .Container.ID }}` above) in your commands:
|
||||
- `{{ .DockerCompose }}`: the docker compose command (default: `docker-compose`)
|
||||
- `{{ .PodmanCompose }}`: the compose command (default: `podman-compose`)
|
||||
- [`{{ .Container }}`](https://pkg.go.dev/github.com/christophe-duc/lazypodman@v0.20.0/pkg/commands#Container) and its fields. For example: `{{ .Container.Container.ImageID }}`
|
||||
- [`{{ .Service }}`](https://pkg.go.dev/github.com/christophe-duc/lazypodman@v0.20.0/pkg/commands#Service) and its fields. For example: `{{ .Service.Name }}`
|
||||
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ type PodmanCommand struct {
|
|||
Tr *i18n.TranslationSet
|
||||
Config *config.AppConfig
|
||||
Runtime ContainerRuntime
|
||||
InDockerComposeProject bool
|
||||
InComposeProject bool
|
||||
ErrorChan chan error
|
||||
ContainerMutex deadlock.Mutex
|
||||
ServiceMutex deadlock.Mutex
|
||||
|
|
@ -49,7 +49,7 @@ type LimitedPodmanCommand interface {
|
|||
// CommandObject is what we pass to our template resolvers when we are running a custom command.
|
||||
// We do not guarantee that all fields will be populated: just the ones that make sense for the current context
|
||||
type CommandObject struct {
|
||||
DockerCompose string
|
||||
PodmanCompose string
|
||||
Service *Service
|
||||
Container *Container
|
||||
Image *Image
|
||||
|
|
@ -59,7 +59,7 @@ type CommandObject struct {
|
|||
|
||||
// NewCommandObject takes a command object and returns a default command object with the passed command object merged in
|
||||
func (c *PodmanCommand) NewCommandObject(obj CommandObject) CommandObject {
|
||||
defaultObj := CommandObject{DockerCompose: c.Config.UserConfig.CommandTemplates.DockerCompose}
|
||||
defaultObj := CommandObject{PodmanCompose: c.Config.UserConfig.CommandTemplates.PodmanCompose}
|
||||
_ = mergo.Merge(&defaultObj, obj)
|
||||
return defaultObj
|
||||
}
|
||||
|
|
@ -112,23 +112,23 @@ func NewPodmanCommand(log *logrus.Entry, osCommand *OSCommand, tr *i18n.Translat
|
|||
Log: log,
|
||||
OSCommand: osCommand,
|
||||
Tr: tr,
|
||||
Config: config,
|
||||
Runtime: runtime,
|
||||
ErrorChan: errorChan,
|
||||
InDockerComposeProject: true,
|
||||
Closers: closers,
|
||||
Config: config,
|
||||
Runtime: runtime,
|
||||
ErrorChan: errorChan,
|
||||
InComposeProject: true,
|
||||
Closers: closers,
|
||||
}
|
||||
|
||||
podmanCommand.setComposeCommand(config)
|
||||
|
||||
err = osCommand.RunCommand(
|
||||
utils.ApplyTemplate(
|
||||
config.UserConfig.CommandTemplates.CheckDockerComposeConfig,
|
||||
config.UserConfig.CommandTemplates.CheckComposeConfig,
|
||||
podmanCommand.NewCommandObject(CommandObject{}),
|
||||
),
|
||||
)
|
||||
if err != nil {
|
||||
podmanCommand.InDockerComposeProject = false
|
||||
podmanCommand.InComposeProject = false
|
||||
log.Warn(err.Error())
|
||||
}
|
||||
|
||||
|
|
@ -138,31 +138,31 @@ func NewPodmanCommand(log *logrus.Entry, osCommand *OSCommand, tr *i18n.Translat
|
|||
// setComposeCommand detects and sets the appropriate compose command
|
||||
func (c *PodmanCommand) setComposeCommand(config *config.AppConfig) {
|
||||
// If user has explicitly set a compose command, respect it
|
||||
if config.UserConfig.CommandTemplates.DockerCompose != "docker compose" &&
|
||||
config.UserConfig.CommandTemplates.DockerCompose != "" {
|
||||
if config.UserConfig.CommandTemplates.PodmanCompose != "podman-compose" &&
|
||||
config.UserConfig.CommandTemplates.PodmanCompose != "" {
|
||||
return
|
||||
}
|
||||
|
||||
// Try podman-compose first
|
||||
if err := c.OSCommand.RunCommand("podman-compose version"); err == nil {
|
||||
config.UserConfig.CommandTemplates.DockerCompose = "podman-compose"
|
||||
config.UserConfig.CommandTemplates.PodmanCompose = "podman-compose"
|
||||
return
|
||||
}
|
||||
|
||||
// Try podman compose (built-in, if available)
|
||||
if err := c.OSCommand.RunCommand("podman compose version"); err == nil {
|
||||
config.UserConfig.CommandTemplates.DockerCompose = "podman compose"
|
||||
config.UserConfig.CommandTemplates.PodmanCompose = "podman compose"
|
||||
return
|
||||
}
|
||||
|
||||
// Fall back to docker-compose for compatibility
|
||||
if err := c.OSCommand.RunCommand("docker-compose version"); err == nil {
|
||||
config.UserConfig.CommandTemplates.DockerCompose = "docker-compose"
|
||||
config.UserConfig.CommandTemplates.PodmanCompose = "docker-compose"
|
||||
return
|
||||
}
|
||||
|
||||
// Default to podman-compose
|
||||
config.UserConfig.CommandTemplates.DockerCompose = "podman-compose"
|
||||
config.UserConfig.CommandTemplates.PodmanCompose = "podman-compose"
|
||||
}
|
||||
|
||||
func (c *PodmanCommand) Close() error {
|
||||
|
|
@ -448,11 +448,11 @@ func (c *PodmanCommand) GetContainers(existingContainers []*Container) ([]*Conta
|
|||
|
||||
// GetServices gets services
|
||||
func (c *PodmanCommand) GetServices() ([]*Service, error) {
|
||||
if !c.InDockerComposeProject {
|
||||
if !c.InComposeProject {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
composeCommand := c.Config.UserConfig.CommandTemplates.DockerCompose
|
||||
composeCommand := c.Config.UserConfig.CommandTemplates.PodmanCompose
|
||||
output, err := c.OSCommand.RunCommandWithOutput(fmt.Sprintf("%s config --services", composeCommand))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
@ -520,11 +520,11 @@ func (c *PodmanCommand) ViewAllLogs() (*exec.Cmd, error) {
|
|||
return cmd, nil
|
||||
}
|
||||
|
||||
// DockerComposeConfig returns the result of 'compose config'
|
||||
func (c *PodmanCommand) DockerComposeConfig() string {
|
||||
// ComposeConfig returns the result of 'compose config'
|
||||
func (c *PodmanCommand) ComposeConfig() string {
|
||||
output, err := c.OSCommand.RunCommandWithOutput(
|
||||
utils.ApplyTemplate(
|
||||
c.OSCommand.Config.UserConfig.CommandTemplates.DockerComposeConfig,
|
||||
c.OSCommand.Config.UserConfig.CommandTemplates.ComposeConfig,
|
||||
c.NewCommandObject(CommandObject{}),
|
||||
),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -42,26 +42,33 @@ func NewSSHHandler(oSCommand CmdKiller) *SSHHandler {
|
|||
}
|
||||
}
|
||||
|
||||
// HandleSSHDockerHost overrides the DOCKER_HOST environment variable
|
||||
// to point towards a local unix socket tunneled over SSH to the specified ssh host.
|
||||
// HandleSSHDockerHost overrides the CONTAINER_HOST (or DOCKER_HOST for compatibility)
|
||||
// environment variable to point towards a local unix socket tunneled over SSH.
|
||||
func (self *SSHHandler) HandleSSHDockerHost() (io.Closer, error) {
|
||||
const key = "DOCKER_HOST"
|
||||
// Check CONTAINER_HOST first (Podman standard), then DOCKER_HOST for compatibility
|
||||
key := "CONTAINER_HOST"
|
||||
hostValue := self.getenv(key)
|
||||
if hostValue == "" {
|
||||
key = "DOCKER_HOST"
|
||||
hostValue = self.getenv(key)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
u, err := url.Parse(self.getenv(key))
|
||||
u, err := url.Parse(hostValue)
|
||||
if err != nil {
|
||||
// if no or an invalid docker host is specified, continue nominally
|
||||
// if no or an invalid container host is specified, continue nominally
|
||||
return noopCloser{}, nil
|
||||
}
|
||||
|
||||
// if the docker host scheme is "ssh", forward the docker socket before creating the client
|
||||
// if the container host scheme is "ssh", forward the socket before creating the client
|
||||
if u.Scheme == "ssh" {
|
||||
tunnel, err := self.createDockerHostTunnel(ctx, u.Host)
|
||||
if err != nil {
|
||||
return noopCloser{}, fmt.Errorf("tunnel ssh docker host: %w", err)
|
||||
return noopCloser{}, fmt.Errorf("tunnel ssh container host: %w", err)
|
||||
}
|
||||
err = self.setenv(key, tunnel.socketPath)
|
||||
if err != nil {
|
||||
return noopCloser{}, fmt.Errorf("override DOCKER_HOST to tunneled socket: %w", err)
|
||||
return noopCloser{}, fmt.Errorf("override %s to tunneled socket: %w", key, err)
|
||||
}
|
||||
|
||||
return tunnel, nil
|
||||
|
|
@ -90,15 +97,15 @@ func (self *SSHHandler) createDockerHostTunnel(ctx context.Context, remoteHost s
|
|||
if err != nil {
|
||||
return nil, fmt.Errorf("create ssh tunnel tmp file: %w", err)
|
||||
}
|
||||
localSocket := path.Join(socketDir, "dockerhost.sock")
|
||||
localSocket := path.Join(socketDir, "podman.sock")
|
||||
|
||||
cmd, err := self.tunnelSSH(ctx, remoteHost, localSocket)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("tunnel docker host over ssh: %w", err)
|
||||
return nil, fmt.Errorf("tunnel container host over ssh: %w", err)
|
||||
}
|
||||
|
||||
// set a reasonable timeout, then wait for the socket to dial successfully
|
||||
// before attempting to create a new docker client
|
||||
// before attempting to create a new container client
|
||||
const socketTunnelTimeout = 8 * time.Second
|
||||
ctx, cancel := context.WithTimeout(ctx, socketTunnelTimeout)
|
||||
defer cancel()
|
||||
|
|
@ -108,7 +115,7 @@ func (self *SSHHandler) createDockerHostTunnel(ctx context.Context, remoteHost s
|
|||
return nil, fmt.Errorf("ssh tunneled socket never became available: %w", err)
|
||||
}
|
||||
|
||||
// construct the new DOCKER_HOST url with the proper scheme
|
||||
// construct the new CONTAINER_HOST url with the proper scheme
|
||||
newDockerHostURL := url.URL{Scheme: "unix", Path: localSocket}
|
||||
return &tunneledDockerHost{
|
||||
socketPath: newDockerHostURL.String(),
|
||||
|
|
@ -149,7 +156,7 @@ func (self *SSHHandler) tryDial(ctx context.Context, socketPath string) error {
|
|||
}
|
||||
|
||||
func (self *SSHHandler) tunnelSSH(ctx context.Context, host, localSocket string) (*exec.Cmd, error) {
|
||||
cmd := exec.CommandContext(ctx, "ssh", "-L", localSocket+":/var/run/docker.sock", host, "-N")
|
||||
cmd := exec.CommandContext(ctx, "ssh", "-L", localSocket+":/run/podman/podman.sock", host, "-N")
|
||||
self.oSCommand.PrepareForChildren(cmd)
|
||||
err := self.startCmd(cmd)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ type UserConfig struct {
|
|||
|
||||
// CustomCommands determines what shows up in your custom commands menu when
|
||||
// you press 'c'. You can use go templates to access three items on the
|
||||
// struct: the DockerCompose command (defaulted to 'docker-compose'), the
|
||||
// struct: the DockerCompose command (defaulted to 'podman-compose'), the
|
||||
// Service if present, and the Container if present. The struct types for
|
||||
// those are found in the commands package
|
||||
CustomCommands CustomCommands `yaml:"customCommands,omitempty"`
|
||||
|
|
@ -166,14 +166,15 @@ type CommandTemplatesConfig struct {
|
|||
// downs and removes volumes
|
||||
DownWithVolumes string `yaml:"downWithVolumes,omitempty"`
|
||||
|
||||
// DockerCompose is for your docker-compose command. You may want to combine a
|
||||
// few different docker-compose.yml files together, in which case you can set
|
||||
// this to "docker compose -f foo/docker-compose.yml -f
|
||||
// bah/docker-compose.yml". The reason that the other docker-compose command
|
||||
// templates all start with {{ .DockerCompose }} is so that they can make use
|
||||
// PodmanCompose is for your compose command. You may want to combine a
|
||||
// few different compose.yml files together, in which case you can set
|
||||
// this to "podman-compose -f foo/docker-compose.yml -f
|
||||
// bah/docker-compose.yml". The reason that the other compose command
|
||||
// templates all start with {{ .PodmanCompose }} is so that they can make use
|
||||
// of whatever you've set in this value rather than you having to copy and
|
||||
// paste it to all the other commands
|
||||
DockerCompose string `yaml:"dockerCompose,omitempty"`
|
||||
// paste it to all the other commands. Auto-detected in order: podman-compose,
|
||||
// podman compose, docker-compose.
|
||||
PodmanCompose string `yaml:"podmanCompose,omitempty"`
|
||||
|
||||
// StopService is the command for stopping a service
|
||||
StopService string `yaml:"stopService,omitempty"`
|
||||
|
|
@ -191,7 +192,7 @@ type CommandTemplatesConfig struct {
|
|||
ViewServiceLogs string `yaml:"viewServiceLogs,omitempty"`
|
||||
|
||||
// RebuildService is the command for rebuilding a service. Defaults to
|
||||
// something along the lines of `{{ .DockerCompose }} up --build {{
|
||||
// something along the lines of `{{ .PodmanCompose }} up --build {{
|
||||
// .Service.Name }}`
|
||||
RebuildService string `yaml:"rebuildService,omitempty"`
|
||||
|
||||
|
|
@ -207,16 +208,16 @@ type CommandTemplatesConfig struct {
|
|||
// ViewAllLogs is the command we use when you want to see all logs in a subprocess with no filtering
|
||||
ViewAllLogs string `yaml:"viewAlLogs,omitempty"`
|
||||
|
||||
// DockerComposeConfig is the command for viewing the config of your docker
|
||||
// compose. It basically prints out the yaml from your docker-compose.yml
|
||||
// ComposeConfig is the command for viewing the config of your compose
|
||||
// project. It basically prints out the yaml from your docker-compose.yml
|
||||
// file(s)
|
||||
DockerComposeConfig string `yaml:"dockerComposeConfig,omitempty"`
|
||||
ComposeConfig string `yaml:"composeConfig,omitempty"`
|
||||
|
||||
// CheckDockerComposeConfig is what we use to check whether we are in a
|
||||
// docker-compose context. If the command returns an error then we clearly
|
||||
// aren't in a docker-compose config and we then just hide the services panel
|
||||
// CheckComposeConfig is what we use to check whether we are in a
|
||||
// compose context. If the command returns an error then we clearly
|
||||
// aren't in a compose config and we then just hide the services panel
|
||||
// and only show containers
|
||||
CheckDockerComposeConfig string `yaml:"checkDockerComposeConfig,omitempty"`
|
||||
CheckComposeConfig string `yaml:"checkComposeConfig,omitempty"`
|
||||
|
||||
// ServiceTop is the command for viewing the processes under a given service
|
||||
ServiceTop string `yaml:"serviceTop,omitempty"`
|
||||
|
|
@ -326,7 +327,7 @@ type CustomCommand struct {
|
|||
Shell bool `yaml:"shell"`
|
||||
|
||||
// Command is the command we want to run. We can use the go templates here as
|
||||
// well. One example might be `{{ .DockerCompose }} exec {{ .Service.Name }}
|
||||
// well. One example might be `{{ .PodmanCompose }} exec {{ .Service.Name }}
|
||||
// /bin/sh`
|
||||
Command string `yaml:"command"`
|
||||
|
||||
|
|
@ -385,23 +386,23 @@ func GetDefaultConfig() UserConfig {
|
|||
Tail: "",
|
||||
},
|
||||
CommandTemplates: CommandTemplatesConfig{
|
||||
DockerCompose: "docker compose",
|
||||
RestartService: "{{ .DockerCompose }} restart {{ .Service.Name }}",
|
||||
StartService: "{{ .DockerCompose }} start {{ .Service.Name }}",
|
||||
Up: "{{ .DockerCompose }} up -d",
|
||||
Down: "{{ .DockerCompose }} down",
|
||||
DownWithVolumes: "{{ .DockerCompose }} down --volumes",
|
||||
UpService: "{{ .DockerCompose }} up -d {{ .Service.Name }}",
|
||||
RebuildService: "{{ .DockerCompose }} up -d --build {{ .Service.Name }}",
|
||||
RecreateService: "{{ .DockerCompose }} up -d --force-recreate {{ .Service.Name }}",
|
||||
StopService: "{{ .DockerCompose }} stop {{ .Service.Name }}",
|
||||
ServiceLogs: "{{ .DockerCompose }} logs --since=60m --follow {{ .Service.Name }}",
|
||||
ViewServiceLogs: "{{ .DockerCompose }} logs --follow {{ .Service.Name }}",
|
||||
AllLogs: "{{ .DockerCompose }} logs --tail=300 --follow",
|
||||
ViewAllLogs: "{{ .DockerCompose }} logs",
|
||||
DockerComposeConfig: "{{ .DockerCompose }} config",
|
||||
CheckDockerComposeConfig: "{{ .DockerCompose }} config --quiet",
|
||||
ServiceTop: "{{ .DockerCompose }} top {{ .Service.Name }}",
|
||||
PodmanCompose: "podman-compose",
|
||||
RestartService: "{{ .PodmanCompose }} restart {{ .Service.Name }}",
|
||||
StartService: "{{ .PodmanCompose }} start {{ .Service.Name }}",
|
||||
Up: "{{ .PodmanCompose }} up -d",
|
||||
Down: "{{ .PodmanCompose }} down",
|
||||
DownWithVolumes: "{{ .PodmanCompose }} down --volumes",
|
||||
UpService: "{{ .PodmanCompose }} up -d {{ .Service.Name }}",
|
||||
RebuildService: "{{ .PodmanCompose }} up -d --build {{ .Service.Name }}",
|
||||
RecreateService: "{{ .PodmanCompose }} up -d --force-recreate {{ .Service.Name }}",
|
||||
StopService: "{{ .PodmanCompose }} stop {{ .Service.Name }}",
|
||||
ServiceLogs: "{{ .PodmanCompose }} logs --since=60m --follow {{ .Service.Name }}",
|
||||
ViewServiceLogs: "{{ .PodmanCompose }} logs --follow {{ .Service.Name }}",
|
||||
AllLogs: "{{ .PodmanCompose }} logs --tail=300 --follow",
|
||||
ViewAllLogs: "{{ .PodmanCompose }} logs",
|
||||
ComposeConfig: "{{ .PodmanCompose }} config",
|
||||
CheckComposeConfig: "{{ .PodmanCompose }} config --quiet",
|
||||
ServiceTop: "{{ .PodmanCompose }} top {{ .Service.Name }}",
|
||||
},
|
||||
CustomCommands: CustomCommands{
|
||||
Containers: []CustomCommand{},
|
||||
|
|
@ -413,42 +414,42 @@ func GetDefaultConfig() UserConfig {
|
|||
Services: []CustomCommand{
|
||||
{
|
||||
Name: "up",
|
||||
Command: "{{ .DockerCompose }} up -d",
|
||||
Command: "{{ .PodmanCompose }} up -d",
|
||||
},
|
||||
{
|
||||
Name: "up (attached)",
|
||||
Command: "{{ .DockerCompose }} up",
|
||||
Command: "{{ .PodmanCompose }} up",
|
||||
Attach: true,
|
||||
},
|
||||
{
|
||||
Name: "stop",
|
||||
Command: "{{ .DockerCompose }} stop",
|
||||
Command: "{{ .PodmanCompose }} stop",
|
||||
},
|
||||
{
|
||||
Name: "pull",
|
||||
Command: "{{ .DockerCompose }} pull",
|
||||
Command: "{{ .PodmanCompose }} pull",
|
||||
Attach: true,
|
||||
},
|
||||
{
|
||||
Name: "build",
|
||||
Command: "{{ .DockerCompose }} build --parallel --force-rm",
|
||||
Command: "{{ .PodmanCompose }} build --parallel --force-rm",
|
||||
Attach: true,
|
||||
},
|
||||
{
|
||||
Name: "down",
|
||||
Command: "{{ .DockerCompose }} down",
|
||||
Command: "{{ .PodmanCompose }} down",
|
||||
},
|
||||
{
|
||||
Name: "down with volumes",
|
||||
Command: "{{ .DockerCompose }} down --volumes",
|
||||
Command: "{{ .PodmanCompose }} down --volumes",
|
||||
},
|
||||
{
|
||||
Name: "down with images",
|
||||
Command: "{{ .DockerCompose }} down --rmi all",
|
||||
Command: "{{ .PodmanCompose }} down --rmi all",
|
||||
},
|
||||
{
|
||||
Name: "down with volumes and images",
|
||||
Command: "{{ .DockerCompose }} down --volumes --rmi all",
|
||||
Command: "{{ .PodmanCompose }} down --volumes --rmi all",
|
||||
},
|
||||
},
|
||||
Containers: []CustomCommand{},
|
||||
|
|
@ -502,9 +503,9 @@ func NewAppConfig(name, version, commit, date string, buildSource string, debugg
|
|||
return nil, err
|
||||
}
|
||||
|
||||
// Pass compose files as individual -f flags to docker compose
|
||||
// Pass compose files as individual -f flags to compose command
|
||||
if len(composeFiles) > 0 {
|
||||
userConfig.CommandTemplates.DockerCompose += " -f " + strings.Join(composeFiles, " -f ")
|
||||
userConfig.CommandTemplates.PodmanCompose += " -f " + strings.Join(composeFiles, " -f ")
|
||||
}
|
||||
|
||||
appConfig := &AppConfig{
|
||||
|
|
|
|||
|
|
@ -7,43 +7,43 @@ import (
|
|||
"github.com/jesseduffield/yaml"
|
||||
)
|
||||
|
||||
func TestDockerComposeCommandNoFiles(t *testing.T) {
|
||||
func TestPodmanComposeCommandNoFiles(t *testing.T) {
|
||||
composeFiles := []string{}
|
||||
conf, err := NewAppConfig("name", "version", "commit", "date", "buildSource", false, composeFiles, "projectDir")
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected error: %s", err)
|
||||
}
|
||||
|
||||
actual := conf.UserConfig.CommandTemplates.DockerCompose
|
||||
expected := "docker compose"
|
||||
actual := conf.UserConfig.CommandTemplates.PodmanCompose
|
||||
expected := "podman-compose"
|
||||
if actual != expected {
|
||||
t.Fatalf("Expected %s but got %s", expected, actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDockerComposeCommandSingleFile(t *testing.T) {
|
||||
func TestPodmanComposeCommandSingleFile(t *testing.T) {
|
||||
composeFiles := []string{"one.yml"}
|
||||
conf, err := NewAppConfig("name", "version", "commit", "date", "buildSource", false, composeFiles, "projectDir")
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected error: %s", err)
|
||||
}
|
||||
|
||||
actual := conf.UserConfig.CommandTemplates.DockerCompose
|
||||
expected := "docker compose -f one.yml"
|
||||
actual := conf.UserConfig.CommandTemplates.PodmanCompose
|
||||
expected := "podman-compose -f one.yml"
|
||||
if actual != expected {
|
||||
t.Fatalf("Expected %s but got %s", expected, actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDockerComposeCommandMultipleFiles(t *testing.T) {
|
||||
func TestPodmanComposeCommandMultipleFiles(t *testing.T) {
|
||||
composeFiles := []string{"one.yml", "two.yml", "three.yml"}
|
||||
conf, err := NewAppConfig("name", "version", "commit", "date", "buildSource", false, composeFiles, "projectDir")
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected error: %s", err)
|
||||
}
|
||||
|
||||
actual := conf.UserConfig.CommandTemplates.DockerCompose
|
||||
expected := "docker compose -f one.yml -f two.yml -f three.yml"
|
||||
actual := conf.UserConfig.CommandTemplates.PodmanCompose
|
||||
expected := "podman-compose -f one.yml -f two.yml -f three.yml"
|
||||
if actual != expected {
|
||||
t.Fatalf("Expected %s but got %s", expected, actual)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -282,7 +282,7 @@ func (gui *Gui) refreshContainersAndServices() error {
|
|||
}
|
||||
|
||||
func (gui *Gui) renderContainersAndServices() error {
|
||||
if gui.PodmanCommand.InDockerComposeProject {
|
||||
if gui.PodmanCommand.InComposeProject {
|
||||
if err := gui.Panels.Services.RerenderList(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -449,7 +449,7 @@ func (gui *Gui) containerExecShell(container *commands.Container) error {
|
|||
})
|
||||
|
||||
// TODO: use SDK
|
||||
resolvedCommand := utils.ApplyTemplate("docker exec -it {{ .Container.ID }} /bin/sh -c 'eval $(grep ^$(id -un): /etc/passwd | cut -d : -f 7-)'", commandObject)
|
||||
resolvedCommand := utils.ApplyTemplate("podman exec -it {{ .Container.ID }} /bin/sh -c 'eval $(grep ^$(id -un): /etc/passwd | cut -d : -f 7-)'", commandObject)
|
||||
// attach and return the subprocess error
|
||||
cmd := gui.OSCommand.ExecutableFromString(resolvedCommand)
|
||||
return gui.runSubprocess(cmd)
|
||||
|
|
|
|||
|
|
@ -445,7 +445,7 @@ func (gui *Gui) ShouldRefresh(key string) bool {
|
|||
}
|
||||
|
||||
func (gui *Gui) initiallyFocusedViewName() string {
|
||||
if gui.PodmanCommand.InDockerComposeProject {
|
||||
if gui.PodmanCommand.InComposeProject {
|
||||
return "services"
|
||||
}
|
||||
return "containers"
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ func (gui *Gui) getProjectPanel() *panels.SideListPanel[*commands.Project] {
|
|||
return &panels.SideListPanel[*commands.Project]{
|
||||
ContextState: &panels.ContextState[*commands.Project]{
|
||||
GetMainTabs: func() []panels.MainTab[*commands.Project] {
|
||||
if gui.PodmanCommand.InDockerComposeProject {
|
||||
if gui.PodmanCommand.InComposeProject {
|
||||
return []panels.MainTab[*commands.Project]{
|
||||
{
|
||||
Key: "logs",
|
||||
|
|
@ -32,8 +32,8 @@ func (gui *Gui) getProjectPanel() *panels.SideListPanel[*commands.Project] {
|
|||
},
|
||||
{
|
||||
Key: "config",
|
||||
Title: gui.Tr.DockerComposeConfigTitle,
|
||||
Render: gui.renderDockerComposeConfig,
|
||||
Title: gui.Tr.ComposeConfigTitle,
|
||||
Render: gui.renderComposeConfig,
|
||||
},
|
||||
{
|
||||
Key: "credits",
|
||||
|
|
@ -79,7 +79,7 @@ func (gui *Gui) refreshProject() error {
|
|||
|
||||
func (gui *Gui) getProjectName() string {
|
||||
projectName := path.Base(gui.Config.ProjectDir)
|
||||
if gui.PodmanCommand.InDockerComposeProject {
|
||||
if gui.PodmanCommand.InComposeProject {
|
||||
for _, service := range gui.Panels.Services.List.GetAllItems() {
|
||||
container := service.Container
|
||||
if container != nil && container.DetailsLoaded() {
|
||||
|
|
@ -144,9 +144,9 @@ func (gui *Gui) renderAllLogs(_project *commands.Project) tasks.TaskFunc {
|
|||
})
|
||||
}
|
||||
|
||||
func (gui *Gui) renderDockerComposeConfig(_project *commands.Project) tasks.TaskFunc {
|
||||
func (gui *Gui) renderComposeConfig(_project *commands.Project) tasks.TaskFunc {
|
||||
return gui.NewSimpleRenderStringTask(func() string {
|
||||
return utils.ColoredYamlString(gui.PodmanCommand.DockerComposeConfig())
|
||||
return utils.ColoredYamlString(gui.PodmanCommand.ComposeConfig())
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ func (gui *Gui) getServicesPanel() *panels.SideListPanel[*commands.Service] {
|
|||
return presentation.GetServiceDisplayStrings(&gui.Config.UserConfig.Gui, service)
|
||||
},
|
||||
Hide: func() bool {
|
||||
return !gui.PodmanCommand.InDockerComposeProject
|
||||
return !gui.PodmanCommand.InComposeProject
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
@ -148,7 +148,7 @@ func (gui *Gui) handleServiceRemoveMenu(g *gocui.Gui, v *gocui.View) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
composeCommand := gui.Config.UserConfig.CommandTemplates.DockerCompose
|
||||
composeCommand := gui.Config.UserConfig.CommandTemplates.PodmanCompose
|
||||
|
||||
options := []*commandOption{
|
||||
{
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ import (
|
|||
"sort"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/christophe-duc/lazypodman/pkg/commands"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
|
@ -14,28 +13,28 @@ func sampleContainers() []*commands.Container {
|
|||
{
|
||||
ID: "1",
|
||||
Name: "1",
|
||||
Container: container.Summary{
|
||||
Summary: commands.ContainerSummary{
|
||||
State: "exited",
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "2",
|
||||
Name: "2",
|
||||
Container: container.Summary{
|
||||
Summary: commands.ContainerSummary{
|
||||
State: "running",
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "3",
|
||||
Name: "3",
|
||||
Container: container.Summary{
|
||||
Summary: commands.ContainerSummary{
|
||||
State: "running",
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "4",
|
||||
Name: "4",
|
||||
Container: container.Summary{
|
||||
Summary: commands.ContainerSummary{
|
||||
State: "created",
|
||||
},
|
||||
},
|
||||
|
|
@ -47,28 +46,28 @@ func expectedPerStatusContainers() []*commands.Container {
|
|||
{
|
||||
ID: "2",
|
||||
Name: "2",
|
||||
Container: container.Summary{
|
||||
Summary: commands.ContainerSummary{
|
||||
State: "running",
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "3",
|
||||
Name: "3",
|
||||
Container: container.Summary{
|
||||
Summary: commands.ContainerSummary{
|
||||
State: "running",
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "1",
|
||||
Name: "1",
|
||||
Container: container.Summary{
|
||||
Summary: commands.ContainerSummary{
|
||||
State: "exited",
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "4",
|
||||
Name: "4",
|
||||
Container: container.Summary{
|
||||
Summary: commands.ContainerSummary{
|
||||
State: "created",
|
||||
},
|
||||
},
|
||||
|
|
@ -80,28 +79,28 @@ func expectedLegacySortedContainers() []*commands.Container {
|
|||
{
|
||||
ID: "1",
|
||||
Name: "1",
|
||||
Container: container.Summary{
|
||||
Summary: commands.ContainerSummary{
|
||||
State: "exited",
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "2",
|
||||
Name: "2",
|
||||
Container: container.Summary{
|
||||
Summary: commands.ContainerSummary{
|
||||
State: "running",
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "3",
|
||||
Name: "3",
|
||||
Container: container.Summary{
|
||||
Summary: commands.ContainerSummary{
|
||||
State: "running",
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "4",
|
||||
Name: "4",
|
||||
Container: container.Summary{
|
||||
Summary: commands.ContainerSummary{
|
||||
State: "created",
|
||||
},
|
||||
},
|
||||
|
|
@ -110,8 +109,8 @@ func expectedLegacySortedContainers() []*commands.Container {
|
|||
|
||||
func assertEqualContainers(t *testing.T, left *commands.Container, right *commands.Container) {
|
||||
t.Helper()
|
||||
assert.Equal(t, left.Container.State, right.Container.State)
|
||||
assert.Equal(t, left.Container.ID, right.Container.ID)
|
||||
assert.Equal(t, left.Summary.State, right.Summary.State)
|
||||
assert.Equal(t, left.Summary.ID, right.Summary.ID)
|
||||
assert.Equal(t, left.Name, right.Name)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -128,7 +128,7 @@ func (gui *Gui) createAllViews() error {
|
|||
|
||||
gui.Views.Containers.Highlight = true
|
||||
gui.Views.Containers.SelBgColor = selectedLineBgColor
|
||||
if gui.Config.UserConfig.Gui.ShowAllContainers || !gui.PodmanCommand.InDockerComposeProject {
|
||||
if gui.Config.UserConfig.Gui.ShowAllContainers || !gui.PodmanCommand.InComposeProject {
|
||||
gui.Views.Containers.Title = gui.Tr.ContainersTitle
|
||||
} else {
|
||||
gui.Views.Containers.Title = gui.Tr.StandaloneContainersTitle
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ func chineseSet() TranslationSet {
|
|||
LogsTitle: "日志",
|
||||
ConfigTitle: "配置",
|
||||
EnvTitle: "环境变量",
|
||||
DockerComposeConfigTitle: "Docker-Compose配置",
|
||||
ComposeConfigTitle: "Compose配置",
|
||||
TopTitle: "系统资源管理",
|
||||
StatsTitle: "统计信息",
|
||||
CreditsTitle: "关于我们",
|
||||
|
|
@ -113,7 +113,7 @@ func chineseSet() TranslationSet {
|
|||
NoServices: "没有服务",
|
||||
|
||||
ConfirmQuit: "您确定要退出吗?",
|
||||
ConfirmUpProject: "您确定要“up”的docker compose项目吗?",
|
||||
ConfirmUpProject: "您确定要启动您的compose项目吗?",
|
||||
MustForceToRemoveContainer: "您无法删除正在运行的容器,除非您强制执行。您想强制执行吗?",
|
||||
NotEnoughSpace: "空间不足,无法渲染面板",
|
||||
ConfirmPruneImages: "您确定要删除所有未使用的镜像吗?",
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ func dutchSet() TranslationSet {
|
|||
LogsTitle: "Logs",
|
||||
ConfigTitle: "Config",
|
||||
EnvTitle: "Env",
|
||||
DockerComposeConfigTitle: "Docker-Compose Configuratie",
|
||||
ComposeConfigTitle: "Compose Configuratie",
|
||||
TopTitle: "Top",
|
||||
StatsTitle: "Stats",
|
||||
CreditsTitle: "Over",
|
||||
|
|
|
|||
|
|
@ -110,10 +110,10 @@ type TranslationSet struct {
|
|||
OpenInBrowser string
|
||||
SortContainersByState string
|
||||
|
||||
LogsTitle string
|
||||
ConfigTitle string
|
||||
EnvTitle string
|
||||
DockerComposeConfigTitle string
|
||||
LogsTitle string
|
||||
ConfigTitle string
|
||||
EnvTitle string
|
||||
ComposeConfigTitle string
|
||||
StatsTitle string
|
||||
CreditsTitle string
|
||||
ContainerConfigTitle string
|
||||
|
|
@ -232,7 +232,7 @@ func englishSet() TranslationSet {
|
|||
LogsTitle: "Logs",
|
||||
ConfigTitle: "Config",
|
||||
EnvTitle: "Env",
|
||||
DockerComposeConfigTitle: "Docker-Compose Config",
|
||||
ComposeConfigTitle: "Compose Config",
|
||||
TopTitle: "Top",
|
||||
StatsTitle: "Stats",
|
||||
CreditsTitle: "About",
|
||||
|
|
@ -250,7 +250,7 @@ func englishSet() TranslationSet {
|
|||
NoServices: "No services",
|
||||
|
||||
ConfirmQuit: "Are you sure you want to quit?",
|
||||
ConfirmUpProject: "Are you sure you want to 'up' your docker compose project?",
|
||||
ConfirmUpProject: "Are you sure you want to 'up' your compose project?",
|
||||
MustForceToRemoveContainer: "You cannot remove a running container unless you force it. Do you want to force it?",
|
||||
NotEnoughSpace: "Not enough space to render panels",
|
||||
ConfirmPruneImages: "Are you sure you want to prune all unused images?",
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ func frenchSet() TranslationSet {
|
|||
LogsTitle: "Journaux",
|
||||
ConfigTitle: "Config",
|
||||
EnvTitle: "Env",
|
||||
DockerComposeConfigTitle: "Config Docker-Compose",
|
||||
ComposeConfigTitle: "Config Compose",
|
||||
TopTitle: "Top",
|
||||
StatsTitle: "Statistiques",
|
||||
CreditsTitle: "À propos",
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ func germanSet() TranslationSet {
|
|||
LogsTitle: "Protokoll",
|
||||
ConfigTitle: "Konfiguration",
|
||||
EnvTitle: "Env",
|
||||
DockerComposeConfigTitle: "Docker-Compose Konfiguration",
|
||||
ComposeConfigTitle: "Compose Konfiguration",
|
||||
TopTitle: "Top",
|
||||
StatsTitle: "Statistiken",
|
||||
CreditsTitle: "Über Uns",
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ func polishSet() TranslationSet {
|
|||
LogsTitle: "Logi",
|
||||
ConfigTitle: "Konfiguracja",
|
||||
EnvTitle: "Env",
|
||||
DockerComposeConfigTitle: "Konfiguracja docker-compose",
|
||||
ComposeConfigTitle: "Konfiguracja compose",
|
||||
TopTitle: "Top",
|
||||
StatsTitle: "Staty",
|
||||
CreditsTitle: "O",
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ func portugueseSet() TranslationSet {
|
|||
LogsTitle: "Registros",
|
||||
ConfigTitle: "Config",
|
||||
EnvTitle: "Env",
|
||||
DockerComposeConfigTitle: "Docker-Compose Config",
|
||||
ComposeConfigTitle: "Compose Config",
|
||||
TopTitle: "Topo",
|
||||
StatsTitle: "Estatísticas",
|
||||
CreditsTitle: "Sobre",
|
||||
|
|
@ -113,7 +113,7 @@ func portugueseSet() TranslationSet {
|
|||
NoServices: "Sem serviços",
|
||||
|
||||
ConfirmQuit: "Tem certeza que deseja sair?",
|
||||
ConfirmUpProject: "Tem certeza que deseja 'iniciar' seu projeto docker compose?",
|
||||
ConfirmUpProject: "Tem certeza que deseja 'iniciar' seu projeto compose?",
|
||||
MustForceToRemoveContainer: "Você não pode remover um contêiner em execução a menos que o force. Deseja forçar?",
|
||||
NotEnoughSpace: "Sem espaço suficiente para renderizar os painéis",
|
||||
ConfirmPruneImages: "Tem certeza que deseja eliminar todas as imagens não utilizadas?",
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ func spanishSet() TranslationSet {
|
|||
LogsTitle: "Logs",
|
||||
ConfigTitle: "Configuración",
|
||||
EnvTitle: "Variables de entorno",
|
||||
DockerComposeConfigTitle: "Docker-Compose Config",
|
||||
ComposeConfigTitle: "Compose Config",
|
||||
TopTitle: "Top",
|
||||
StatsTitle: "Estadísticas",
|
||||
CreditsTitle: "Acerca",
|
||||
|
|
@ -108,7 +108,7 @@ func spanishSet() TranslationSet {
|
|||
NoServices: "Sin servicios",
|
||||
|
||||
ConfirmQuit: "¿Realmente quieres salir?",
|
||||
ConfirmUpProject: "¿Realmente quieres levantar tu proyecto docker compose?",
|
||||
ConfirmUpProject: "¿Realmente quieres levantar tu proyecto compose?",
|
||||
MustForceToRemoveContainer: "No puedes borrar un contenedor en ejecución a menos de que lo fuerces, ¿quieres hacerlo?",
|
||||
NotEnoughSpace: "No hay suficiente espacio para renderizar los paneles",
|
||||
ConfirmPruneImages: "¿Realmente quieres limpiar todas tus imágenes?",
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ func turkishSet() TranslationSet {
|
|||
LogsTitle: "Kayitlar",
|
||||
ConfigTitle: "Ayarlar",
|
||||
EnvTitle: "Env",
|
||||
DockerComposeConfigTitle: "Docker-Compose Ayar",
|
||||
ComposeConfigTitle: "Compose Ayar",
|
||||
TopTitle: "Top",
|
||||
StatsTitle: "Durumlar",
|
||||
CreditsTitle: "Hakkinda",
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue