- install/uninstall/start/stop/enable take <name> or --all; *all kept as shortcuts - add enable (enable at boot + start); startall no longer enables - order/delay resolved by config.ResolveOrder and written into systemd, OpenRC and runit service files (After=/sleep), so they apply at boot - install --all stops and disables units before removing their files - update regenerates all installed, enabled units and removes disabled ones - edit creates the config dir; docs and man page updated - tests: fake Init for cmd, ResolveOrder, backend ordering output
71 lines
1.9 KiB
Go
71 lines
1.9 KiB
Go
package cmd
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"github.com/spf13/cobra"
|
|
"io"
|
|
|
|
"github.com/warkanum/unitdore/config"
|
|
"github.com/warkanum/unitdore/initsys"
|
|
"github.com/warkanum/unitdore/sysuser"
|
|
)
|
|
|
|
// runtimeLabel is the RUNTIME column value for list/status.
|
|
func runtimeLabel(u config.Unit) string {
|
|
if u.IsStack() {
|
|
return u.Runtime + " (stack)"
|
|
}
|
|
return u.Runtime
|
|
}
|
|
|
|
// lingerHint prints, once per user, how to make user units start at boot.
|
|
func lingerHint(w io.Writer, ini initsys.Init, seen map[string]bool, u config.Unit) {
|
|
if !ini.SupportsLinger() || u.User == "" || seen[u.User] || sysuser.LingerEnabled(u.User) {
|
|
return
|
|
}
|
|
seen[u.User] = true
|
|
fmt.Fprintf(w, " ! linger not enabled for %s — user units won't start at boot: sudo loginctl enable-linger %s\n", u.User, u.User)
|
|
}
|
|
|
|
// nameOrAll requires exactly one unit name, or none when --all is set.
|
|
func nameOrAll(all *bool) cobra.PositionalArgs {
|
|
return func(cmd *cobra.Command, args []string) error {
|
|
if *all {
|
|
if len(args) != 0 {
|
|
return errors.New("--all takes no unit name")
|
|
}
|
|
return nil
|
|
}
|
|
if len(args) != 1 {
|
|
return errors.New("requires a unit name, or --all")
|
|
}
|
|
return nil
|
|
}
|
|
}
|
|
|
|
// installedUnit finds a unit by name and checks that its service file exists.
|
|
func installedUnit(cfg *config.Config, ini initsys.Init, name string) (*config.Unit, error) {
|
|
u := cfg.FindUnit(name)
|
|
if u == nil {
|
|
return nil, fmt.Errorf("unit %q not found", name)
|
|
}
|
|
if !ini.IsInstalled(*u, cfg.Prefix, cfg.Suffix) {
|
|
return nil, fmt.Errorf("%s is not installed — run 'unitdore install %s' first", name, name)
|
|
}
|
|
return u, nil
|
|
}
|
|
|
|
// loadInit loads the config and selects the init backend.
|
|
func loadInit() (*config.Config, initsys.Init, error) {
|
|
cfg, err := config.Load(configPath)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
ini, err := initsys.New(cfg)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
return cfg, ini, nil
|
|
}
|