mirror of
https://github.com/Control-D-Inc/ctrld.git
synced 2026-02-03 22:18:39 +00:00
This commit extends the documentation effort by adding detailed explanatory comments to key CLI components and core functionality throughout the cmd/ directory. The changes focus on explaining WHY certain logic is needed, not just WHAT the code does, improving code maintainability and helping developers understand complex business decisions. Key improvements: - Main entry points: Document CLI initialization, logging setup, and cache configuration with reasoning for design decisions - DNS proxy core: Explain DNS proxy constants, data structures, and core processing pipeline for handling DNS queries - Service management: Document service command structure, configuration patterns, and platform-specific service handling - Logging infrastructure: Explain log buffer management, level encoders, and log formatting decisions for different use cases - Metrics and monitoring: Document Prometheus metrics structure, HTTP endpoints, and conditional metric collection for performance - Network handling: Explain Linux-specific network interface filtering, virtual interface detection, and DNS configuration management - Hostname validation: Document RFC1123 compliance and DNS naming standards for system compatibility - Mobile integration: Explain HTTP retry logic, fallback mechanisms, and mobile platform integration patterns - Connection management: Document connection wrapper design to prevent log pollution during process lifecycle Technical details: - Added explanatory comments to 11 additional files in cmd/cli/ - Maintained consistent documentation style and format - Preserved all existing functionality while improving code clarity - Enhanced understanding of complex business logic and platform-specific behavior These comments help future developers understand the reasoning behind complex decisions, making the codebase more maintainable and reducing the risk of incorrect modifications during maintenance.
257 lines
8.1 KiB
Go
257 lines
8.1 KiB
Go
package cli
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"runtime"
|
|
|
|
"github.com/kardianos/service"
|
|
"github.com/spf13/cobra"
|
|
)
|
|
|
|
// filterEmptyStrings removes empty strings from a slice
|
|
// This is used to clean up command line arguments and configuration values
|
|
func filterEmptyStrings(slice []string) []string {
|
|
var result []string
|
|
for _, s := range slice {
|
|
if s != "" {
|
|
result = append(result, s)
|
|
}
|
|
}
|
|
return result
|
|
}
|
|
|
|
// ServiceCommand handles service-related operations
|
|
// This encapsulates all service management functionality for the CLI
|
|
type ServiceCommand struct {
|
|
serviceManager *ServiceManager
|
|
}
|
|
|
|
// initializeServiceManager creates a service manager with default configuration
|
|
// This sets up the basic service infrastructure needed for all service operations
|
|
func (sc *ServiceCommand) initializeServiceManager() (service.Service, *prog, error) {
|
|
svcConfig := sc.createServiceConfig()
|
|
return sc.initializeServiceManagerWithServiceConfig(svcConfig)
|
|
}
|
|
|
|
// initializeServiceManagerWithServiceConfig creates a service manager with the given configuration
|
|
// This allows for custom service configuration while maintaining the same initialization pattern
|
|
func (sc *ServiceCommand) initializeServiceManagerWithServiceConfig(svcConfig *service.Config) (service.Service, *prog, error) {
|
|
p := &prog{}
|
|
|
|
s, err := sc.newService(p, svcConfig)
|
|
if err != nil {
|
|
return nil, nil, fmt.Errorf("failed to create service: %w", err)
|
|
}
|
|
|
|
sc.serviceManager = &ServiceManager{prog: p, svc: s}
|
|
return s, p, nil
|
|
}
|
|
|
|
// newService creates a new service instance using the provided program and configuration.
|
|
// This abstracts the service creation process for different operating systems
|
|
func (sc *ServiceCommand) newService(p *prog, svcConfig *service.Config) (service.Service, error) {
|
|
s, err := newService(p, svcConfig)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to create service: %w", err)
|
|
}
|
|
return s, nil
|
|
}
|
|
|
|
// NewServiceCommand creates a new service command handler
|
|
// This provides a clean factory method for creating service command instances
|
|
func NewServiceCommand() *ServiceCommand {
|
|
return &ServiceCommand{}
|
|
}
|
|
|
|
// createServiceConfig creates a properly initialized service configuration
|
|
// This ensures consistent service naming and description across all platforms
|
|
func (sc *ServiceCommand) createServiceConfig() *service.Config {
|
|
return &service.Config{
|
|
Name: ctrldServiceName,
|
|
DisplayName: "Control-D Helper Service",
|
|
Description: "A highly configurable, multi-protocol DNS forwarding proxy",
|
|
Option: service.KeyValue{},
|
|
}
|
|
}
|
|
|
|
// InitServiceCmd creates the service command with proper logic and aliases
|
|
// This sets up all service-related subcommands with appropriate permissions and flags
|
|
func InitServiceCmd(rootCmd *cobra.Command) *cobra.Command {
|
|
// Create service command handlers
|
|
sc := NewServiceCommand()
|
|
|
|
startCmd, startCmdAlias := createStartCommands(sc)
|
|
rootCmd.AddCommand(startCmdAlias)
|
|
|
|
// 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,
|
|
}
|
|
stopCmd.Flags().StringVarP(&iface, "iface", "", "", `Reset DNS setting for iface, "auto" means the default interface gateway`)
|
|
stopCmd.Flags().Int64VarP(&deactivationPin, "pin", "", defaultDeactivationPin, `Pin code for stopping ctrld`)
|
|
_ = stopCmd.Flags().MarkHidden("pin")
|
|
|
|
// 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,
|
|
}
|
|
|
|
// 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,
|
|
}
|
|
uninstallCmd.Flags().StringVarP(&iface, "iface", "", "", `Reset DNS setting for iface, "auto" means the default interface gateway`)
|
|
uninstallCmd.Flags().Int64VarP(&deactivationPin, "pin", "", defaultDeactivationPin, `Pin code for stopping ctrld`)
|
|
_ = uninstallCmd.Flags().MarkHidden("pin")
|
|
uninstallCmd.Flags().BoolVarP(&cleanup, "cleanup", "", false, `Removing ctrld binary and config files`)
|
|
|
|
// Interfaces command - use the existing InitInterfacesCmd function
|
|
interfacesCmd := InitInterfacesCmd(rootCmd)
|
|
|
|
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(startCmd)
|
|
serviceCmd.AddCommand(stopCmd)
|
|
serviceCmd.AddCommand(restartCmd)
|
|
serviceCmd.AddCommand(reloadCmd)
|
|
serviceCmd.AddCommand(statusCmd)
|
|
serviceCmd.AddCommand(uninstallCmd)
|
|
serviceCmd.AddCommand(interfacesCmd)
|
|
|
|
rootCmd.AddCommand(serviceCmd)
|
|
|
|
return serviceCmd
|
|
}
|