Builds: design 47 G §297, A-98 Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
70 lines
2.3 KiB
Go
70 lines
2.3 KiB
Go
package apply
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"sort"
|
|
"strings"
|
|
|
|
"git.novox.be/novox/mesh-sdk/go/declaration"
|
|
"github.com/novox/mesh-host/internal/store"
|
|
"github.com/novox/mesh-host/internal/system"
|
|
)
|
|
|
|
// StopModule stops the units and containers the node's record holds for a module and removes nothing: no unit, file,
|
|
// container, data or record, so what the module kept survives and a later Apply starts the build it is given (design 47
|
|
// G A-98, §297). Units come first, a timer before the service it starts, then containers; a unit the mesh never held
|
|
// (Stateless) is left as it is. It answers what it stopped, and the first failure.
|
|
func StopModule(ctx context.Context, sys system.System, known store.State, module string, run Runner) ([]string, error) {
|
|
var timers, services, containers []store.Applied
|
|
for _, r := range known.Resources {
|
|
if store.OwnerOf(r, declaration.ModuleGuess) != module {
|
|
continue
|
|
}
|
|
switch r.Type {
|
|
case string(declaration.TypeService):
|
|
if r.Stateless {
|
|
continue
|
|
}
|
|
if strings.HasSuffix(r.Target, ".timer") {
|
|
timers = append(timers, r)
|
|
} else {
|
|
services = append(services, r)
|
|
}
|
|
case string(declaration.TypeContainer):
|
|
containers = append(containers, r)
|
|
}
|
|
}
|
|
var stopped []string
|
|
for _, r := range append(timers, services...) {
|
|
manager := managerFor(r.Scope, r.User, run)
|
|
if state, err := sys.ServiceState(ctx, manager, r.Target); err != nil {
|
|
if strings.Contains(err.Error(), "does not exist on this machine") {
|
|
continue
|
|
}
|
|
return stopped, fmt.Errorf("stopping %s of %s: %w", r.Target, module, err)
|
|
} else if state == "stopped" {
|
|
continue
|
|
}
|
|
if err := sys.SetServiceState(ctx, manager, r.Target, "stopped"); err != nil {
|
|
return stopped, fmt.Errorf("stopping %s of %s: %w", r.Target, module, err)
|
|
}
|
|
stopped = append(stopped, r.Target)
|
|
}
|
|
if len(containers) == 0 {
|
|
return stopped, nil
|
|
}
|
|
cri, err := containerRuntime(ctx, run)
|
|
if err != nil {
|
|
return stopped, err
|
|
}
|
|
sort.Slice(containers, func(i, j int) bool { return containers[i].Target < containers[j].Target })
|
|
for _, r := range containers {
|
|
if _, err := run(ctx, cri, "stop", r.Target); err != nil {
|
|
return stopped, fmt.Errorf("stopping the container %s of %s: %w", r.Target, module, err)
|
|
}
|
|
stopped = append(stopped, r.Target)
|
|
}
|
|
return stopped, nil
|
|
}
|