feat(devops): add Boot/Stop/Status methods
Manages dev VM lifecycle using LinuxKitManager. Supports fresh boot, status checking, graceful stop. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
cd7930af2a
commit
95017cdc8a
1 changed files with 127 additions and 0 deletions
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/host-uk/core/pkg/container"
|
"github.com/host-uk/core/pkg/container"
|
||||||
)
|
)
|
||||||
|
|
@ -87,3 +88,129 @@ func (d *DevOps) Install(ctx context.Context, progress func(downloaded, total in
|
||||||
func (d *DevOps) CheckUpdate(ctx context.Context) (current, latest string, hasUpdate bool, err error) {
|
func (d *DevOps) CheckUpdate(ctx context.Context) (current, latest string, hasUpdate bool, err error) {
|
||||||
return d.images.CheckUpdate(ctx)
|
return d.images.CheckUpdate(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BootOptions configures how to boot the dev environment.
|
||||||
|
type BootOptions struct {
|
||||||
|
Memory int // MB, default 4096
|
||||||
|
CPUs int // default 2
|
||||||
|
Name string // container name
|
||||||
|
Fresh bool // destroy existing and start fresh
|
||||||
|
}
|
||||||
|
|
||||||
|
// DefaultBootOptions returns sensible defaults.
|
||||||
|
func DefaultBootOptions() BootOptions {
|
||||||
|
return BootOptions{
|
||||||
|
Memory: 4096,
|
||||||
|
CPUs: 2,
|
||||||
|
Name: "core-dev",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Boot starts the dev environment.
|
||||||
|
func (d *DevOps) Boot(ctx context.Context, opts BootOptions) error {
|
||||||
|
if !d.images.IsInstalled() {
|
||||||
|
return fmt.Errorf("dev image not installed (run 'core dev install' first)")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if already running
|
||||||
|
if !opts.Fresh {
|
||||||
|
running, err := d.IsRunning(ctx)
|
||||||
|
if err == nil && running {
|
||||||
|
return fmt.Errorf("dev environment already running (use 'core dev stop' first or --fresh)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop existing if fresh
|
||||||
|
if opts.Fresh {
|
||||||
|
_ = d.Stop(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
imagePath, err := ImagePath()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build run options for LinuxKitManager
|
||||||
|
runOpts := container.RunOptions{
|
||||||
|
Name: opts.Name,
|
||||||
|
Memory: opts.Memory,
|
||||||
|
CPUs: opts.CPUs,
|
||||||
|
SSHPort: 2222,
|
||||||
|
Detach: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = d.container.Run(ctx, imagePath, runOpts)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop stops the dev environment.
|
||||||
|
func (d *DevOps) Stop(ctx context.Context) error {
|
||||||
|
c, err := d.findContainer(ctx, "core-dev")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if c == nil {
|
||||||
|
return fmt.Errorf("dev environment not found")
|
||||||
|
}
|
||||||
|
return d.container.Stop(ctx, c.ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsRunning checks if the dev environment is running.
|
||||||
|
func (d *DevOps) IsRunning(ctx context.Context) (bool, error) {
|
||||||
|
c, err := d.findContainer(ctx, "core-dev")
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
return c != nil && c.Status == container.StatusRunning, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// findContainer finds a container by name.
|
||||||
|
func (d *DevOps) findContainer(ctx context.Context, name string) (*container.Container, error) {
|
||||||
|
containers, err := d.container.List(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for _, c := range containers {
|
||||||
|
if c.Name == name {
|
||||||
|
return c, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DevStatus returns information about the dev environment.
|
||||||
|
type DevStatus struct {
|
||||||
|
Installed bool
|
||||||
|
Running bool
|
||||||
|
ImageVersion string
|
||||||
|
ContainerID string
|
||||||
|
Memory int
|
||||||
|
CPUs int
|
||||||
|
SSHPort int
|
||||||
|
Uptime time.Duration
|
||||||
|
}
|
||||||
|
|
||||||
|
// Status returns the current dev environment status.
|
||||||
|
func (d *DevOps) Status(ctx context.Context) (*DevStatus, error) {
|
||||||
|
status := &DevStatus{
|
||||||
|
Installed: d.images.IsInstalled(),
|
||||||
|
SSHPort: 2222,
|
||||||
|
}
|
||||||
|
|
||||||
|
if info, ok := d.images.manifest.Images[ImageName()]; ok {
|
||||||
|
status.ImageVersion = info.Version
|
||||||
|
}
|
||||||
|
|
||||||
|
c, _ := d.findContainer(ctx, "core-dev")
|
||||||
|
if c != nil {
|
||||||
|
status.Running = c.Status == container.StatusRunning
|
||||||
|
status.ContainerID = c.ID
|
||||||
|
status.Memory = c.Memory
|
||||||
|
status.CPUs = c.CPUs
|
||||||
|
if status.Running {
|
||||||
|
status.Uptime = time.Since(c.StartedAt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return status, nil
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue