Files
mesh-host/internal/apply/stop.go
T

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
}