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 }