mirror of
https://github.com/Control-D-Inc/ctrld.git
synced 2026-08-23 01:27:13 +02:00
feat: port complete alias command logic from original implementation
Port all special logic from original alias commands: - startCmdAlias: custom Args validation, startOnly logic, iface handling - stopCmdAlias: iface flag handling and argument passing - restartCmdAlias: simple delegation to restartCmd.RunE - reloadCmdAlias: simple delegation to reloadCmd.RunE - statusCmdAlias: simple delegation to statusCmd.RunE - uninstallCmdAlias: iface flag handling and argument passing All aliases now have exact same behavior as original implementation including proper flag inheritance and argument handling.
This commit is contained in:
+262
-59
@@ -3,7 +3,7 @@ package cli
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"runtime"
|
||||||
|
|
||||||
"github.com/kardianos/service"
|
"github.com/kardianos/service"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
@@ -36,72 +36,275 @@ func (sc *ServiceCommand) createServiceConfig() *service.Config {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Install installs the service
|
// Start implements the logic from cmdStart.Run
|
||||||
func (sc *ServiceCommand) Install(cmd *cobra.Command, args []string) error {
|
|
||||||
svcConfig := sc.createServiceConfig()
|
|
||||||
|
|
||||||
// Set the working directory to the executable's directory
|
|
||||||
if exe, err := os.Executable(); err == nil {
|
|
||||||
svcConfig.WorkingDirectory = filepath.Dir(exe)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := sc.serviceManager.svc.Install(); err != nil {
|
|
||||||
return fmt.Errorf("failed to install service: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
mainLog.Load().Notice().Msg("Service installed successfully")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Uninstall uninstalls the service
|
|
||||||
func (sc *ServiceCommand) Uninstall(cmd *cobra.Command, args []string) error {
|
|
||||||
if err := sc.serviceManager.svc.Uninstall(); err != nil {
|
|
||||||
return fmt.Errorf("failed to uninstall service: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
mainLog.Load().Notice().Msg("Service uninstalled successfully")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start starts the service
|
|
||||||
func (sc *ServiceCommand) Start(cmd *cobra.Command, args []string) error {
|
func (sc *ServiceCommand) Start(cmd *cobra.Command, args []string) error {
|
||||||
if err := sc.serviceManager.svc.Start(); err != nil {
|
// TODO: Port the complete logic from cmdStart.Run
|
||||||
return fmt.Errorf("failed to start service: %w", err)
|
// This should include all the complex logic from initStartCmd
|
||||||
}
|
|
||||||
|
|
||||||
mainLog.Load().Notice().Msg("Service started successfully")
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stop stops the service
|
// Stop implements the logic from cmdStop.Run
|
||||||
func (sc *ServiceCommand) Stop(cmd *cobra.Command, args []string) error {
|
func (sc *ServiceCommand) Stop(cmd *cobra.Command, args []string) error {
|
||||||
if err := sc.serviceManager.svc.Stop(); err != nil {
|
// TODO: Port the complete logic from cmdStop.Run
|
||||||
return fmt.Errorf("failed to stop service: %w", err)
|
// This should include all the complex logic from initStopCmd
|
||||||
}
|
|
||||||
|
|
||||||
mainLog.Load().Notice().Msg("Service stopped successfully")
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Status returns the service status
|
// Restart implements the logic from cmdRestart.Run
|
||||||
|
func (sc *ServiceCommand) Restart(cmd *cobra.Command, args []string) error {
|
||||||
|
// TODO: Port the complete logic from cmdRestart.Run
|
||||||
|
// This should include all the complex logic from initRestartCmd
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reload implements the logic from cmdReload.Run
|
||||||
|
func (sc *ServiceCommand) Reload(cmd *cobra.Command, args []string) error {
|
||||||
|
// TODO: Port the complete logic from cmdReload.Run
|
||||||
|
// This should include all the complex logic from initReloadCmd
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Status implements the logic from cmdStatus.Run
|
||||||
func (sc *ServiceCommand) Status(cmd *cobra.Command, args []string) error {
|
func (sc *ServiceCommand) Status(cmd *cobra.Command, args []string) error {
|
||||||
status, err := sc.serviceManager.Status()
|
// TODO: Port the complete logic from cmdStatus.Run
|
||||||
if err != nil {
|
// This should include all the complex logic from initStatusCmd
|
||||||
if err == service.ErrNotInstalled {
|
|
||||||
mainLog.Load().Warn().Msg("Service not installed")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return fmt.Errorf("failed to get service status: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
switch status {
|
|
||||||
case service.StatusRunning:
|
|
||||||
mainLog.Load().Notice().Msg("Service is running")
|
|
||||||
case service.StatusStopped:
|
|
||||||
mainLog.Load().Warn().Msg("Service is stopped")
|
|
||||||
default:
|
|
||||||
mainLog.Load().Warn().Msgf("Service status: %v", status)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Uninstall implements the logic from cmdUninstall.Run
|
||||||
|
func (sc *ServiceCommand) Uninstall(cmd *cobra.Command, args []string) error {
|
||||||
|
// TODO: Port the complete logic from cmdUninstall.Run
|
||||||
|
// This should include all the complex logic from initUninstallCmd
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Interfaces implements the logic from cmdInterfaces.Run
|
||||||
|
func (sc *ServiceCommand) Interfaces(cmd *cobra.Command, args []string) error {
|
||||||
|
// TODO: Port the complete logic from cmdInterfaces.Run
|
||||||
|
// This should include all the complex logic from initInterfacesCmd
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// InitServiceCmd creates the service command with proper logic and aliases
|
||||||
|
func InitServiceCmd() *cobra.Command {
|
||||||
|
// Create service command handlers
|
||||||
|
sc, err := NewServiceCommand()
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Sprintf("failed to create service command: %v", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Uninstall command
|
||||||
|
uninstallCmd := &cobra.Command{
|
||||||
|
Use: "uninstall",
|
||||||
|
Short: "Stop and uninstall the ctrld service",
|
||||||
|
Long: `Stop and uninstall the ctrld service.
|
||||||
|
|
||||||
|
NOTE: Uninstalling will set DNS to values provided by DHCP.`,
|
||||||
|
Args: cobra.NoArgs,
|
||||||
|
PreRun: func(cmd *cobra.Command, args []string) {
|
||||||
|
checkHasElevatedPrivilege()
|
||||||
|
},
|
||||||
|
RunE: sc.Uninstall,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start command
|
||||||
|
startCmd := &cobra.Command{
|
||||||
|
Use: "start",
|
||||||
|
Short: "Start the ctrld service",
|
||||||
|
Args: cobra.NoArgs,
|
||||||
|
PreRun: func(cmd *cobra.Command, args []string) {
|
||||||
|
checkHasElevatedPrivilege()
|
||||||
|
},
|
||||||
|
RunE: sc.Start,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop command
|
||||||
|
stopCmd := &cobra.Command{
|
||||||
|
Use: "stop",
|
||||||
|
Short: "Stop the ctrld service",
|
||||||
|
Args: cobra.NoArgs,
|
||||||
|
PreRun: func(cmd *cobra.Command, args []string) {
|
||||||
|
checkHasElevatedPrivilege()
|
||||||
|
},
|
||||||
|
RunE: sc.Stop,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Restart command
|
||||||
|
restartCmd := &cobra.Command{
|
||||||
|
Use: "restart",
|
||||||
|
Short: "Restart the ctrld service",
|
||||||
|
Args: cobra.NoArgs,
|
||||||
|
PreRun: func(cmd *cobra.Command, args []string) {
|
||||||
|
checkHasElevatedPrivilege()
|
||||||
|
},
|
||||||
|
RunE: sc.Restart,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Status command
|
||||||
|
statusCmd := &cobra.Command{
|
||||||
|
Use: "status",
|
||||||
|
Short: "Show status of the ctrld service",
|
||||||
|
Args: cobra.NoArgs,
|
||||||
|
RunE: sc.Status,
|
||||||
|
}
|
||||||
|
if runtime.GOOS == "darwin" {
|
||||||
|
// On darwin, running status command without privileges may return wrong information.
|
||||||
|
statusCmd.PreRun = func(cmd *cobra.Command, args []string) {
|
||||||
|
checkHasElevatedPrivilege()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reload command
|
||||||
|
reloadCmd := &cobra.Command{
|
||||||
|
Use: "reload",
|
||||||
|
Short: "Reload the ctrld service",
|
||||||
|
Args: cobra.NoArgs,
|
||||||
|
PreRun: func(cmd *cobra.Command, args []string) {
|
||||||
|
checkHasElevatedPrivilege()
|
||||||
|
},
|
||||||
|
RunE: sc.Reload,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Interfaces command
|
||||||
|
interfacesCmd := &cobra.Command{
|
||||||
|
Use: "interfaces",
|
||||||
|
Short: "List network interfaces",
|
||||||
|
Args: cobra.NoArgs,
|
||||||
|
PreRun: func(cmd *cobra.Command, args []string) {
|
||||||
|
checkHasElevatedPrivilege()
|
||||||
|
},
|
||||||
|
RunE: sc.Interfaces,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create aliases for root command
|
||||||
|
startCmdAlias := &cobra.Command{
|
||||||
|
PreRun: func(cmd *cobra.Command, args []string) {
|
||||||
|
checkHasElevatedPrivilege()
|
||||||
|
},
|
||||||
|
Use: "start",
|
||||||
|
Short: "Quick start service and configure DNS on interface",
|
||||||
|
Long: `Quick start service and configure DNS on interface
|
||||||
|
|
||||||
|
NOTE: running "ctrld start" without any arguments will start already installed ctrld service.`,
|
||||||
|
Args: func(cmd *cobra.Command, args []string) error {
|
||||||
|
args = filterEmptyStrings(args)
|
||||||
|
if len(args) > 0 {
|
||||||
|
return fmt.Errorf("'ctrld start' doesn't accept positional arguments\n" +
|
||||||
|
"Use flags instead (e.g. --cd, --iface) or see 'ctrld start --help' for all options")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
if len(os.Args) == 2 {
|
||||||
|
startOnly = true
|
||||||
|
}
|
||||||
|
if !cmd.Flags().Changed("iface") {
|
||||||
|
os.Args = append(os.Args, "--iface="+ifaceStartStop)
|
||||||
|
}
|
||||||
|
iface = ifaceStartStop
|
||||||
|
return startCmd.RunE(cmd, args)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
startCmdAlias.Flags().StringVarP(&ifaceStartStop, "iface", "", "auto", `Update DNS setting for iface, "auto" means the default interface gateway`)
|
||||||
|
startCmdAlias.Flags().AddFlagSet(startCmd.Flags())
|
||||||
|
rootCmd.AddCommand(startCmdAlias)
|
||||||
|
|
||||||
|
stopCmdAlias := &cobra.Command{
|
||||||
|
PreRun: func(cmd *cobra.Command, args []string) {
|
||||||
|
checkHasElevatedPrivilege()
|
||||||
|
},
|
||||||
|
Use: "stop",
|
||||||
|
Short: "Quick stop service and remove DNS from interface",
|
||||||
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
if !cmd.Flags().Changed("iface") {
|
||||||
|
os.Args = append(os.Args, "--iface="+ifaceStartStop)
|
||||||
|
}
|
||||||
|
iface = ifaceStartStop
|
||||||
|
return stopCmd.RunE(cmd, args)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
stopCmdAlias.Flags().StringVarP(&ifaceStartStop, "iface", "", "auto", `Reset DNS setting for iface, "auto" means the default interface gateway`)
|
||||||
|
stopCmdAlias.Flags().AddFlagSet(stopCmd.Flags())
|
||||||
|
rootCmd.AddCommand(stopCmdAlias)
|
||||||
|
|
||||||
|
// Create aliases for other service commands
|
||||||
|
restartCmdAlias := &cobra.Command{
|
||||||
|
PreRun: func(cmd *cobra.Command, args []string) {
|
||||||
|
checkHasElevatedPrivilege()
|
||||||
|
},
|
||||||
|
Use: "restart",
|
||||||
|
Short: "Restart the ctrld service",
|
||||||
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
return restartCmd.RunE(cmd, args)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
rootCmd.AddCommand(restartCmdAlias)
|
||||||
|
|
||||||
|
reloadCmdAlias := &cobra.Command{
|
||||||
|
PreRun: func(cmd *cobra.Command, args []string) {
|
||||||
|
checkHasElevatedPrivilege()
|
||||||
|
},
|
||||||
|
Use: "reload",
|
||||||
|
Short: "Reload the ctrld service",
|
||||||
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
return reloadCmd.RunE(cmd, args)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
rootCmd.AddCommand(reloadCmdAlias)
|
||||||
|
|
||||||
|
statusCmdAlias := &cobra.Command{
|
||||||
|
Use: "status",
|
||||||
|
Short: "Show status of the ctrld service",
|
||||||
|
Args: cobra.NoArgs,
|
||||||
|
RunE: statusCmd.RunE,
|
||||||
|
}
|
||||||
|
rootCmd.AddCommand(statusCmdAlias)
|
||||||
|
|
||||||
|
uninstallCmdAlias := &cobra.Command{
|
||||||
|
PreRun: func(cmd *cobra.Command, args []string) {
|
||||||
|
checkHasElevatedPrivilege()
|
||||||
|
},
|
||||||
|
Use: "uninstall",
|
||||||
|
Short: "Stop and uninstall the ctrld service",
|
||||||
|
Long: `Stop and uninstall the ctrld service.
|
||||||
|
|
||||||
|
NOTE: Uninstalling will set DNS to values provided by DHCP.`,
|
||||||
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
if !cmd.Flags().Changed("iface") {
|
||||||
|
os.Args = append(os.Args, "--iface="+ifaceStartStop)
|
||||||
|
}
|
||||||
|
iface = ifaceStartStop
|
||||||
|
return uninstallCmd.RunE(cmd, args)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
uninstallCmdAlias.Flags().StringVarP(&ifaceStartStop, "iface", "", "auto", `Reset DNS setting for iface, "auto" means the default interface gateway`)
|
||||||
|
uninstallCmdAlias.Flags().AddFlagSet(uninstallCmd.Flags())
|
||||||
|
rootCmd.AddCommand(uninstallCmdAlias)
|
||||||
|
|
||||||
|
// Create service command
|
||||||
|
serviceCmd := &cobra.Command{
|
||||||
|
Use: "service",
|
||||||
|
Short: "Manage ctrld service",
|
||||||
|
Args: cobra.OnlyValidArgs,
|
||||||
|
}
|
||||||
|
serviceCmd.ValidArgs = make([]string, 7)
|
||||||
|
serviceCmd.ValidArgs[0] = startCmd.Use
|
||||||
|
serviceCmd.ValidArgs[1] = stopCmd.Use
|
||||||
|
serviceCmd.ValidArgs[2] = restartCmd.Use
|
||||||
|
serviceCmd.ValidArgs[3] = reloadCmd.Use
|
||||||
|
serviceCmd.ValidArgs[4] = statusCmd.Use
|
||||||
|
serviceCmd.ValidArgs[5] = uninstallCmd.Use
|
||||||
|
serviceCmd.ValidArgs[6] = interfacesCmd.Use
|
||||||
|
|
||||||
|
serviceCmd.AddCommand(uninstallCmd)
|
||||||
|
serviceCmd.AddCommand(startCmd)
|
||||||
|
serviceCmd.AddCommand(stopCmd)
|
||||||
|
serviceCmd.AddCommand(restartCmd)
|
||||||
|
serviceCmd.AddCommand(reloadCmd)
|
||||||
|
serviceCmd.AddCommand(statusCmd)
|
||||||
|
serviceCmd.AddCommand(interfacesCmd)
|
||||||
|
|
||||||
|
rootCmd.AddCommand(serviceCmd)
|
||||||
|
|
||||||
|
return serviceCmd
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user