Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -182,8 +182,8 @@ func (c colimaApp) Stop(force bool) error {
// the order for stop is:
// container stop -> vm stop

// stop container runtimes if not a forceful shutdown
if c.guest.Running(ctx) && !force {
// stop container runtimes
if c.guest.Running(ctx) {
containers, err := c.currentContainerEnvironments(ctx)
if err != nil {
log.Warnln(fmt.Errorf("error retrieving runtimes: %w", err))
Expand All @@ -196,7 +196,7 @@ func (c colimaApp) Stop(force bool) error {
log := log.WithField("context", cont.Name())
log.Println("stopping ...")

if err := cont.Stop(ctx); err != nil {
if err := cont.Stop(ctx, force); err != nil {
// failure to stop a container runtime is not fatal
// it is only meant for graceful shutdown.
// the VM will shut down anyways.
Expand Down
2 changes: 1 addition & 1 deletion cmd/kubernetes.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ var kubernetesStopCmd = &cobra.Command{
return fmt.Errorf("%s is not enabled", kubernetes.Name)
}

return k.Stop(ctx)
return k.Stop(ctx, false)
},
}

Expand Down
3 changes: 2 additions & 1 deletion environment/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ type Container interface {
// Start starts the container runtime.
Start(ctx context.Context) error
// Stop stops the container runtime.
Stop(ctx context.Context) error
// If force is true, the runtime is killed immediately without graceful shutdown.
Stop(ctx context.Context, force bool) error
// Teardown tears down/uninstall the container runtime.
Teardown(ctx context.Context) error
// Update the container runtime.
Expand Down
17 changes: 10 additions & 7 deletions environment/container/containerd/containerd.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/abiosoft/colima/cli"
"github.com/abiosoft/colima/config"
"github.com/abiosoft/colima/environment"
"github.com/abiosoft/colima/environment/guest/systemctl"
)

// Name is container runtime name
Expand Down Expand Up @@ -45,6 +46,7 @@ func newRuntime(host environment.HostActions, guest environment.GuestActions) en
return &containerdRuntime{
host: host,
guest: guest,
systemctl: systemctl.New(guest),
CommandChain: cli.New(Name),
}
}
Expand All @@ -56,8 +58,9 @@ func init() {
var _ environment.Container = (*containerdRuntime)(nil)

type containerdRuntime struct {
host environment.HostActions
guest environment.GuestActions
host environment.HostActions
guest environment.GuestActions
systemctl systemctl.Systemctl
cli.CommandChain
}

Expand Down Expand Up @@ -85,7 +88,7 @@ func (c containerdRuntime) Start(ctx context.Context) error {
a := c.Init(ctx)

a.Add(func() error {
return c.guest.Run("sudo", "service", "containerd", "restart")
return c.systemctl.Restart("containerd.service")
})

// service startup takes few seconds, retry at most 10 times before giving up.
Expand All @@ -94,20 +97,20 @@ func (c containerdRuntime) Start(ctx context.Context) error {
})

a.Add(func() error {
return c.guest.Run("sudo", "service", "buildkit", "start")
return c.systemctl.Start("buildkit.service")
})

return a.Exec()
}

func (c containerdRuntime) Running(ctx context.Context) bool {
return c.guest.RunQuiet("service", "containerd", "status") == nil
return c.systemctl.Active("containerd.service")
}

func (c containerdRuntime) Stop(ctx context.Context) error {
func (c containerdRuntime) Stop(ctx context.Context, force bool) error {
a := c.Init(ctx)
a.Add(func() error {
return c.guest.Run("sudo", "service", "containerd", "stop")
return c.systemctl.Stop("containerd.service", force)
})
return a.Exec()
}
Expand Down
2 changes: 1 addition & 1 deletion environment/container/docker/containerd.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ func (d dockerRuntime) provisionContainerd(ctx context.Context) error {

a.Add(func() error {
// restart containerd service
return d.guest.Run("sudo", "service", "containerd", "restart")
return d.systemctl.Restart("containerd.service")
})

return a.Exec()
Expand Down
4 changes: 2 additions & 2 deletions environment/container/docker/daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,10 +119,10 @@ func (d dockerRuntime) addHostGateway(conf map[string]any) error {
}

func (d dockerRuntime) reloadAndRestartSystemdService() error {
if err := d.guest.Run("sudo", "systemctl", "daemon-reload"); err != nil {
if err := d.systemctl.DaemonReload(); err != nil {
return fmt.Errorf("error reloading systemd daemon: %w", err)
}
if err := d.guest.Run("sudo", "systemctl", "restart", "docker"); err != nil {
if err := d.systemctl.Restart("docker.service"); err != nil {
return fmt.Errorf("error restarting docker: %w", err)
}
return nil
Expand Down
15 changes: 9 additions & 6 deletions environment/container/docker/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/abiosoft/colima/cli"
"github.com/abiosoft/colima/config"
"github.com/abiosoft/colima/environment"
"github.com/abiosoft/colima/environment/guest/systemctl"
"github.com/abiosoft/colima/util"
"github.com/abiosoft/colima/util/debutil"
)
Expand All @@ -23,8 +24,9 @@ func init() {
}

type dockerRuntime struct {
host environment.HostActions
guest environment.GuestActions
host environment.HostActions
guest environment.GuestActions
systemctl systemctl.Systemctl
cli.CommandChain
}

Expand All @@ -33,6 +35,7 @@ func newRuntime(host environment.HostActions, guest environment.GuestActions) en
return &dockerRuntime{
host: host,
guest: guest,
systemctl: systemctl.New(guest),
CommandChain: cli.New(Name),
}
}
Expand Down Expand Up @@ -80,7 +83,7 @@ func (d dockerRuntime) Start(ctx context.Context) error {
a := d.Init(ctx)

a.Retry("", time.Second, 60, func(int) error {
return d.guest.RunQuiet("sudo", "systemctl", "start", "docker.service")
return d.systemctl.Start("docker.service")
})

// service startup takes few seconds, retry for a minute before giving up.
Expand All @@ -102,17 +105,17 @@ func (d dockerRuntime) Start(ctx context.Context) error {
}

func (d dockerRuntime) Running(ctx context.Context) bool {
return d.guest.RunQuiet("service", "docker", "status") == nil
return d.systemctl.Active("docker.service")
}

func (d dockerRuntime) Stop(ctx context.Context) error {
func (d dockerRuntime) Stop(ctx context.Context, force bool) error {
a := d.Init(ctx)

a.Add(func() error {
if !d.Running(ctx) {
return nil
}
return d.guest.Run("sudo", "systemctl", "stop", "docker.service")
return d.systemctl.Stop("docker.service", force)
})

// clear docker context settings
Expand Down
17 changes: 10 additions & 7 deletions environment/container/incus/incus.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/abiosoft/colima/cli"
"github.com/abiosoft/colima/config"
"github.com/abiosoft/colima/environment"
"github.com/abiosoft/colima/environment/guest/systemctl"
"github.com/abiosoft/colima/environment/vm/lima/limautil"
"github.com/abiosoft/colima/util"
"github.com/abiosoft/colima/util/debutil"
Expand All @@ -23,6 +24,7 @@ func newRuntime(host environment.HostActions, guest environment.GuestActions) en
return &incusRuntime{
host: host,
guest: guest,
systemctl: systemctl.New(guest),
CommandChain: cli.New(Name),
}
}
Expand Down Expand Up @@ -51,8 +53,9 @@ func init() {
var _ environment.Container = (*incusRuntime)(nil)

type incusRuntime struct {
host environment.HostActions
guest environment.GuestActions
host environment.HostActions
guest environment.GuestActions
systemctl systemctl.Systemctl
cli.CommandChain
}

Expand Down Expand Up @@ -134,7 +137,7 @@ func (c *incusRuntime) Provision(ctx context.Context) error {

// Running implements environment.Container.
func (c *incusRuntime) Running(ctx context.Context) bool {
return c.guest.RunQuiet("service", "incus", "status") == nil
return c.systemctl.Active("incus.service")
}

// Start implements environment.Container.
Expand All @@ -148,13 +151,13 @@ func (c *incusRuntime) Start(ctx context.Context) error {

if c.poolImported() {
a.Add(func() error {
return c.guest.RunQuiet("sudo", "systemctl", "start", "incus.service")
return c.systemctl.Start("incus.service")
})
} else {
// pool not yet imported
// restart incus to import pool
a.Add(func() error {
return c.guest.RunQuiet("sudo", "systemctl", "restart", "incus.service")
return c.systemctl.Restart("incus.service")
})
}

Expand Down Expand Up @@ -201,7 +204,7 @@ func (c *incusRuntime) Start(ctx context.Context) error {
}

// Stop implements environment.Container.
func (c *incusRuntime) Stop(ctx context.Context) error {
func (c *incusRuntime) Stop(ctx context.Context, force bool) error {
a := c.Init(ctx)

a.Add(func() error {
Expand All @@ -210,7 +213,7 @@ func (c *incusRuntime) Stop(ctx context.Context) error {
})

a.Add(func() error {
return c.guest.RunQuiet("sudo", "incus", "admin", "shutdown")
return c.systemctl.Stop("incus.service", force)
})

a.Add(c.unsetRemote)
Expand Down
15 changes: 10 additions & 5 deletions environment/container/kubernetes/kubernetes.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/abiosoft/colima/environment"
"github.com/abiosoft/colima/environment/container/containerd"
"github.com/abiosoft/colima/environment/container/docker"
"github.com/abiosoft/colima/environment/guest/systemctl"
)

// Name is container runtime name
Expand All @@ -27,6 +28,7 @@ func newRuntime(host environment.HostActions, guest environment.GuestActions) en
return &kubernetesRuntime{
host: host,
guest: guest,
systemctl: systemctl.New(guest),
CommandChain: cli.New(Name),
}
}
Expand All @@ -38,8 +40,9 @@ func init() {
var _ environment.Container = (*kubernetesRuntime)(nil)

type kubernetesRuntime struct {
host environment.HostActions
guest environment.GuestActions
host environment.HostActions
guest environment.GuestActions
systemctl systemctl.Systemctl
cli.CommandChain
}

Expand Down Expand Up @@ -152,7 +155,7 @@ func (c kubernetesRuntime) Start(ctx context.Context) error {
}

a.Add(func() error {
return c.guest.Run("sudo", "service", "k3s", "start")
return c.systemctl.Start("k3s.service")
})
a.Retry("", time.Second*2, 10, func(int) error {
return c.guest.RunQuiet("kubectl", "cluster-info")
Expand All @@ -165,15 +168,17 @@ func (c kubernetesRuntime) Start(ctx context.Context) error {
return c.provisionKubeconfig(ctx)
}

func (c kubernetesRuntime) Stop(ctx context.Context) error {
func (c kubernetesRuntime) Stop(ctx context.Context, force bool) error {
a := c.Init(ctx)
a.Add(func() error {
return c.guest.Run("k3s-killall.sh")
})

// k3s is buggy with external containerd for now
// cleanup is manual
a.Add(c.stopAllContainers)
if !force {
a.Add(c.stopAllContainers)
}

return a.Exec()
}
Expand Down
52 changes: 52 additions & 0 deletions environment/guest/systemctl/systemctl.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package systemctl

import "github.com/abiosoft/colima/environment"

// Runner is the subset of environment.GuestActions that Systemctl requires.
// Using a narrow interface makes Systemctl easier to test and more loosely coupled.
type Runner interface {
Run(args ...string) error
RunQuiet(args ...string) error
}

// compile-time check: environment.GuestActions satisfies runner.
var _ Runner = (environment.GuestActions)(nil)

// Systemctl provides a typed wrapper for running systemctl commands in the guest VM.
type Systemctl struct {
runner Runner
}

// New creates a new Systemctl instance backed by the given guest.
func New(guest Runner) Systemctl {
return Systemctl{runner: guest}
}

// Start starts a systemd service.
func (s Systemctl) Start(service string) error {
return s.runner.Run("sudo", "systemctl", "start", service)
}

// Restart restarts a systemd service.
func (s Systemctl) Restart(service string) error {
return s.runner.Run("sudo", "systemctl", "restart", service)
}

// Stop stops a systemd service. If force is true, it is killed immediately without graceful shutdown.
func (s Systemctl) Stop(service string, force bool) error {
verb := "stop"
if force {
verb = "kill"
}
return s.runner.Run("sudo", "systemctl", verb, service)
}

// Active returns whether a systemd service is currently active.
func (s Systemctl) Active(service string) bool {
return s.runner.RunQuiet("systemctl", "is-active", service) == nil
}

// DaemonReload reloads the systemd manager configuration.
func (s Systemctl) DaemonReload() error {
return s.runner.Run("sudo", "systemctl", "daemon-reload")
}
Loading