package cmd import ( "errors" "fmt" "io" "os" "github.com/spf13/cobra" "github.com/warkanum/unitdore/config" "github.com/warkanum/unitdore/initsys" ) var ( updateOrder int updateEnable bool updateDisable bool ) var updateCmd = &cobra.Command{ Use: "update ", Short: "Update a unit's config and recreate its service file", Args: cobra.ExactArgs(1), RunE: runUpdate, } func init() { updateCmd.Flags().IntVar(&updateOrder, "order", 0, "set startup order") updateCmd.Flags().BoolVar(&updateEnable, "enable", false, "enable the unit") updateCmd.Flags().BoolVar(&updateDisable, "disable", false, "disable the unit") rootCmd.AddCommand(updateCmd) } func runUpdate(cmd *cobra.Command, args []string) error { if updateEnable && updateDisable { return errors.New("--enable and --disable are mutually exclusive") } cfg, err := config.Load(configPath) if err != nil { return err } ini, err := initsys.New(cfg) if err != nil { return err } var order *int if cmd.Flags().Changed("order") { order = &updateOrder } return applyUpdate(cfg, ini, args[0], order, updateEnable, updateDisable, configPath, os.Stdout) } // applyUpdate changes a unit's config, saves it and brings the installed // service file in line: re-created if enabled, stopped and removed if disabled. func applyUpdate(cfg *config.Config, ini initsys.Init, name string, order *int, enable, disable bool, path string, w io.Writer) error { u := cfg.FindUnit(name) if u == nil { return fmt.Errorf("unit %q not found", name) } if order != nil { u.Order = *order fmt.Fprintf(w, " order → %d\n", u.Order) } if enable { u.Enabled = true u.DisabledReason = "" fmt.Fprintf(w, " enabled\n") } if disable { u.Enabled = false fmt.Fprintf(w, " disabled\n") } if err := cfg.ResolveOrder(); err != nil { return err } if err := cfg.Save(path); err != nil { return err } prefix, suffix := cfg.Prefix, cfg.Suffix // The target is stopped and removed if now disabled if ini.IsInstalled(*u, prefix, suffix) && !u.Enabled { svcPath, _ := ini.UnitPath(*u, prefix, suffix) if err := ini.Disable(*u, prefix, suffix); err != nil { return fmt.Errorf("disabling unit: %w", err) } if err := ini.Uninstall(*u, prefix, suffix); err != nil { return fmt.Errorf("removing service file: %w", err) } fmt.Fprintf(w, " ✓ service stopped and removed: %s\n", svcPath) } // Order and enabled state change the After=/delay of other units too, so // every installed, enabled unit is regenerated for i := range cfg.Units { o := cfg.Units[i] if !o.Enabled || !ini.IsInstalled(o, prefix, suffix) { continue } if err := ini.Install(o, prefix, suffix); err != nil { return fmt.Errorf("recreating service file for %s: %w", o.Name, err) } svcPath, _ := ini.UnitPath(o, prefix, suffix) fmt.Fprintf(w, " ✓ service file recreated: %s\n", svcPath) } return nil }