mirror of
https://github.com/jesseduffield/lazydocker.git
synced 2026-07-25 08:31:03 +00:00
Merge pull request #7 from christophe-duc/feature/add_restart_pod
added restart functionality for pods
This commit is contained in:
commit
70a9e480de
8 changed files with 1042 additions and 879 deletions
1849
coverage.txt
1849
coverage.txt
File diff suppressed because it is too large
Load diff
|
|
@ -1,6 +1,8 @@
|
|||
package commands
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/sasha-s/go-deadlock"
|
||||
|
|
@ -32,6 +34,13 @@ func (p *Pod) State() string {
|
|||
return p.Summary.Status
|
||||
}
|
||||
|
||||
// Restart restarts the pod
|
||||
func (p *Pod) Restart() error {
|
||||
p.Log.Warn(fmt.Sprintf("restarting pod %s", p.Name))
|
||||
ctx := context.Background()
|
||||
return p.Runtime.RestartPod(ctx, p.ID, nil)
|
||||
}
|
||||
|
||||
// HasContainers returns true if the pod has non-infra containers.
|
||||
func (p *Pod) HasContainers() bool {
|
||||
return len(p.Containers) > 0
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ type ContainerRuntime interface {
|
|||
// Pod operations
|
||||
ListPods(ctx context.Context) ([]PodSummary, error)
|
||||
PodStats(ctx context.Context, id string, stream bool) (<-chan PodStatsEntry, <-chan error)
|
||||
RestartPod(ctx context.Context, id string, timeout *int) error
|
||||
|
||||
// Events streams container/image/volume/network events
|
||||
Events(ctx context.Context) (<-chan Event, <-chan error)
|
||||
|
|
|
|||
|
|
@ -375,7 +375,7 @@ func (r *LibpodRuntime) PodStats(ctx context.Context, id string, stream bool) (<
|
|||
}
|
||||
|
||||
// aggregatePodContainerStats collects and aggregates stats from all containers in a pod.
|
||||
func (r *LibpodRuntime) aggregatePodContainerStats(ctx context.Context, pod *libpod.Pod) (PodStatsEntry, error) {
|
||||
func (r *LibpodRuntime) aggregatePodContainerStats(_ context.Context, pod *libpod.Pod) (PodStatsEntry, error) {
|
||||
ctrs, err := pod.AllContainers()
|
||||
if err != nil {
|
||||
return PodStatsEntry{}, err
|
||||
|
|
@ -438,6 +438,16 @@ func (r *LibpodRuntime) aggregatePodContainerStats(ctx context.Context, pod *lib
|
|||
return entry, nil
|
||||
}
|
||||
|
||||
// RestartPod restarts a pod.
|
||||
func (r *LibpodRuntime) RestartPod(ctx context.Context, id string, timeout *int) error {
|
||||
pod, err := r.runtime.LookupPod(id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = pod.Restart(ctx)
|
||||
return err
|
||||
}
|
||||
|
||||
// Events streams container runtime events.
|
||||
// For libpod, we use a polling approach since direct event streaming requires more setup.
|
||||
func (r *LibpodRuntime) Events(ctx context.Context) (<-chan Event, <-chan error) {
|
||||
|
|
|
|||
|
|
@ -145,6 +145,10 @@ func (r *LibpodRuntime) PodStats(ctx context.Context, id string, stream bool) (<
|
|||
return statsChan, errChan
|
||||
}
|
||||
|
||||
func (r *LibpodRuntime) RestartPod(ctx context.Context, id string, timeout *int) error {
|
||||
return ErrLibpodNotAvailable
|
||||
}
|
||||
|
||||
// Events returns an error channel on non-Linux platforms.
|
||||
func (r *LibpodRuntime) Events(ctx context.Context) (<-chan Event, <-chan error) {
|
||||
eventsChan := make(chan Event)
|
||||
|
|
|
|||
|
|
@ -40,8 +40,9 @@ type MockRuntime struct {
|
|||
PruneNetworksFunc func(ctx context.Context) error
|
||||
|
||||
// Pod operation mocks
|
||||
ListPodsFunc func(ctx context.Context) ([]PodSummary, error)
|
||||
PodStatsFunc func(ctx context.Context, id string, stream bool) (<-chan PodStatsEntry, <-chan error)
|
||||
ListPodsFunc func(ctx context.Context) ([]PodSummary, error)
|
||||
PodStatsFunc func(ctx context.Context, id string, stream bool) (<-chan PodStatsEntry, <-chan error)
|
||||
RestartPodFunc func(ctx context.Context, id string, timeout *int) error
|
||||
|
||||
// Event mock
|
||||
EventsFunc func(ctx context.Context) (<-chan Event, <-chan error)
|
||||
|
|
@ -280,6 +281,14 @@ func (m *MockRuntime) PodStats(ctx context.Context, id string, stream bool) (<-c
|
|||
return statsCh, errCh
|
||||
}
|
||||
|
||||
func (m *MockRuntime) RestartPod(ctx context.Context, id string, timeout *int) error {
|
||||
m.recordCall("RestartPod", id, timeout)
|
||||
if m.RestartPodFunc != nil {
|
||||
return m.RestartPodFunc(ctx, id, timeout)
|
||||
}
|
||||
return ErrMockNotImplemented
|
||||
}
|
||||
|
||||
// Events
|
||||
|
||||
func (m *MockRuntime) Events(ctx context.Context) (<-chan Event, <-chan error) {
|
||||
|
|
|
|||
|
|
@ -340,6 +340,12 @@ func (r *SocketRuntime) PodStats(ctx context.Context, id string, stream bool) (<
|
|||
return statsChan, errChan
|
||||
}
|
||||
|
||||
// RestartPod restarts a pod.
|
||||
func (r *SocketRuntime) RestartPod(ctx context.Context, id string, timeout *int) error {
|
||||
_, err := pods.Restart(r.conn, id, nil)
|
||||
return err
|
||||
}
|
||||
|
||||
// aggregatePodStats combines stats from all containers in a pod into a single entry.
|
||||
func aggregatePodStats(reports []*types.PodStatsReport) PodStatsEntry {
|
||||
if len(reports) == 0 {
|
||||
|
|
@ -405,30 +411,30 @@ func aggregatePodStats(reports []*types.PodStatsReport) PodStatsEntry {
|
|||
func parsePercentage(s string) float64 {
|
||||
s = strings.TrimSuffix(strings.TrimSpace(s), "%")
|
||||
var val float64
|
||||
fmt.Sscanf(s, "%f", &val)
|
||||
_, _ = fmt.Sscanf(s, "%f", &val)
|
||||
return val
|
||||
}
|
||||
|
||||
// parseMemoryBytes parses memory usage string like "1000000 / 4000000" into usage and limit.
|
||||
func parseMemoryBytes(s string) (usage, limit uint64) {
|
||||
func parseMemoryBytes(s string) (uint64, uint64) {
|
||||
parts := strings.Split(s, "/")
|
||||
if len(parts) != 2 {
|
||||
return 0, 0
|
||||
}
|
||||
usage = parseByteValue(strings.TrimSpace(parts[0]))
|
||||
limit = parseByteValue(strings.TrimSpace(parts[1]))
|
||||
return
|
||||
usage := parseByteValue(strings.TrimSpace(parts[0]))
|
||||
limit := parseByteValue(strings.TrimSpace(parts[1]))
|
||||
return usage, limit
|
||||
}
|
||||
|
||||
// parseIOBytes parses I/O string like "1.5kB / 2.3kB" into input and output bytes.
|
||||
func parseIOBytes(s string) (input, output uint64) {
|
||||
func parseIOBytes(s string) (uint64, uint64) {
|
||||
parts := strings.Split(s, "/")
|
||||
if len(parts) != 2 {
|
||||
return 0, 0
|
||||
}
|
||||
input = parseByteValue(strings.TrimSpace(parts[0]))
|
||||
output = parseByteValue(strings.TrimSpace(parts[1]))
|
||||
return
|
||||
input := parseByteValue(strings.TrimSpace(parts[0]))
|
||||
output := parseByteValue(strings.TrimSpace(parts[1]))
|
||||
return input, output
|
||||
}
|
||||
|
||||
// parseByteValue parses a byte value string with optional unit (e.g., "1.5kB", "10MB", "1000000").
|
||||
|
|
@ -469,7 +475,7 @@ func parseByteValue(s string) uint64 {
|
|||
func parseUint(s string) uint64 {
|
||||
s = strings.TrimSpace(s)
|
||||
var val uint64
|
||||
fmt.Sscanf(s, "%d", &val)
|
||||
_, _ = fmt.Sscanf(s, "%d", &val)
|
||||
return val
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -568,7 +568,12 @@ func (gui *Gui) handleContainerRestart(g *gocui.Gui, v *gocui.View) error {
|
|||
}
|
||||
|
||||
if item.IsPod {
|
||||
return gui.createErrorPanel("Restart not yet supported for pods")
|
||||
return gui.WithWaitingStatus(gui.Tr.RestartingStatus, func() error {
|
||||
if err := item.Pod.Restart(); err != nil {
|
||||
return gui.createErrorPanel(err.Error())
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
ctr := item.Container
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue