mirror of
https://github.com/AdguardTeam/AdGuardHome.git
synced 2025-05-03 06:22:56 +03:00
Pull request: refactor-opts
Updates #2893. Squashed commit of the following: commit c7027abd1088e27569367f3450e9225ff605b43d Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Wed Oct 5 16:54:23 2022 +0300 home: imp docs commit 86a5b0aca916a7db608eba8263ecdc6ca79c8043 Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Wed Oct 5 16:50:44 2022 +0300 home: refactor opts more commit 74c5989d1edf8d007dec847f4aaa0d7a0d24dc38 Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Wed Oct 5 15:17:26 2022 +0300 home: refactor option parsing
This commit is contained in:
parent
f557339ca0
commit
2e0f6e5468
8 changed files with 515 additions and 414 deletions
internal/home
|
@ -97,9 +97,15 @@ var Context homeContext
|
|||
|
||||
// Main is the entry point
|
||||
func Main(clientBuildFS fs.FS) {
|
||||
// config can be specified, which reads options from there, but other command line flags have to override config values
|
||||
// therefore, we must do it manually instead of using a lib
|
||||
args := loadOptions()
|
||||
initCmdLineOpts()
|
||||
|
||||
// The configuration file path can be overridden, but other command-line
|
||||
// options have to override config values. Therefore, do it manually
|
||||
// instead of using package flag.
|
||||
//
|
||||
// TODO(a.garipov): The comment above is most likely false. Replace with
|
||||
// package flag.
|
||||
opts := loadCmdLineOpts()
|
||||
|
||||
Context.appSignalChannel = make(chan os.Signal)
|
||||
signal.Notify(Context.appSignalChannel, syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP, syscall.SIGQUIT)
|
||||
|
@ -120,26 +126,18 @@ func Main(clientBuildFS fs.FS) {
|
|||
}
|
||||
}()
|
||||
|
||||
if args.serviceControlAction != "" {
|
||||
handleServiceControlAction(args, clientBuildFS)
|
||||
if opts.serviceControlAction != "" {
|
||||
handleServiceControlAction(opts, clientBuildFS)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// run the protection
|
||||
run(args, clientBuildFS)
|
||||
run(opts, clientBuildFS)
|
||||
}
|
||||
|
||||
func setupContext(args options) {
|
||||
Context.runningAsService = args.runningAsService
|
||||
Context.disableUpdate = args.disableUpdate ||
|
||||
version.Channel() == version.ChannelDevelopment
|
||||
|
||||
Context.firstRun = detectFirstRun()
|
||||
if Context.firstRun {
|
||||
log.Info("This is the first time AdGuard Home is launched")
|
||||
checkPermissions()
|
||||
}
|
||||
func setupContext(opts options) {
|
||||
setupContextFlags(opts)
|
||||
|
||||
switch version.Channel() {
|
||||
case version.ChannelEdge, version.ChannelDevelopment:
|
||||
|
@ -174,13 +172,13 @@ func setupContext(args options) {
|
|||
os.Exit(1)
|
||||
}
|
||||
|
||||
if args.checkConfig {
|
||||
if opts.checkConfig {
|
||||
log.Info("configuration file is ok")
|
||||
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
if !args.noEtcHosts && config.Clients.Sources.HostsFile {
|
||||
if !opts.noEtcHosts && config.Clients.Sources.HostsFile {
|
||||
err = setupHostsContainer()
|
||||
fatalOnError(err)
|
||||
}
|
||||
|
@ -189,6 +187,24 @@ func setupContext(args options) {
|
|||
Context.mux = http.NewServeMux()
|
||||
}
|
||||
|
||||
// setupContextFlags sets global flags and prints their status to the log.
|
||||
func setupContextFlags(opts options) {
|
||||
Context.firstRun = detectFirstRun()
|
||||
if Context.firstRun {
|
||||
log.Info("This is the first time AdGuard Home is launched")
|
||||
checkPermissions()
|
||||
}
|
||||
|
||||
Context.runningAsService = opts.runningAsService
|
||||
// Don't print the runningAsService flag, since that has already been done
|
||||
// in [run].
|
||||
|
||||
Context.disableUpdate = opts.disableUpdate || version.Channel() == version.ChannelDevelopment
|
||||
if Context.disableUpdate {
|
||||
log.Info("AdGuard Home updates are disabled")
|
||||
}
|
||||
}
|
||||
|
||||
// logIfUnsupported logs a formatted warning if the error is one of the
|
||||
// unsupported errors and returns nil. If err is nil, logIfUnsupported returns
|
||||
// nil. Otherwise, it returns err.
|
||||
|
@ -270,7 +286,7 @@ func setupHostsContainer() (err error) {
|
|||
return nil
|
||||
}
|
||||
|
||||
func setupConfig(args options) (err error) {
|
||||
func setupConfig(opts options) (err error) {
|
||||
config.DNS.DnsfilterConf.EtcHosts = Context.etcHosts
|
||||
config.DNS.DnsfilterConf.ConfigModified = onConfigModified
|
||||
config.DNS.DnsfilterConf.HTTPRegister = httpRegister
|
||||
|
@ -312,9 +328,9 @@ func setupConfig(args options) (err error) {
|
|||
|
||||
Context.clients.Init(config.Clients.Persistent, Context.dhcpServer, Context.etcHosts, arpdb)
|
||||
|
||||
if args.bindPort != 0 {
|
||||
if opts.bindPort != 0 {
|
||||
tcpPorts := aghalg.UniqChecker[tcpPort]{}
|
||||
addPorts(tcpPorts, tcpPort(args.bindPort), tcpPort(config.BetaBindPort))
|
||||
addPorts(tcpPorts, tcpPort(opts.bindPort), tcpPort(config.BetaBindPort))
|
||||
|
||||
udpPorts := aghalg.UniqChecker[udpPort]{}
|
||||
addPorts(udpPorts, udpPort(config.DNS.Port))
|
||||
|
@ -336,23 +352,23 @@ func setupConfig(args options) (err error) {
|
|||
return fmt.Errorf("validating udp ports: %w", err)
|
||||
}
|
||||
|
||||
config.BindPort = args.bindPort
|
||||
config.BindPort = opts.bindPort
|
||||
}
|
||||
|
||||
// override bind host/port from the console
|
||||
if args.bindHost != nil {
|
||||
config.BindHost = args.bindHost
|
||||
if opts.bindHost != nil {
|
||||
config.BindHost = opts.bindHost
|
||||
}
|
||||
if len(args.pidFile) != 0 && writePIDFile(args.pidFile) {
|
||||
Context.pidFileName = args.pidFile
|
||||
if len(opts.pidFile) != 0 && writePIDFile(opts.pidFile) {
|
||||
Context.pidFileName = opts.pidFile
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func initWeb(args options, clientBuildFS fs.FS) (web *Web, err error) {
|
||||
func initWeb(opts options, clientBuildFS fs.FS) (web *Web, err error) {
|
||||
var clientFS, clientBetaFS fs.FS
|
||||
if args.localFrontend {
|
||||
if opts.localFrontend {
|
||||
log.Info("warning: using local frontend files")
|
||||
|
||||
clientFS = os.DirFS("build/static")
|
||||
|
@ -400,24 +416,24 @@ func fatalOnError(err error) {
|
|||
}
|
||||
|
||||
// run configures and starts AdGuard Home.
|
||||
func run(args options, clientBuildFS fs.FS) {
|
||||
func run(opts options, clientBuildFS fs.FS) {
|
||||
// configure config filename
|
||||
initConfigFilename(args)
|
||||
initConfigFilename(opts)
|
||||
|
||||
// configure working dir and config path
|
||||
initWorkingDir(args)
|
||||
initWorkingDir(opts)
|
||||
|
||||
// configure log level and output
|
||||
configureLogger(args)
|
||||
configureLogger(opts)
|
||||
|
||||
// Print the first message after logger is configured.
|
||||
log.Info(version.Full())
|
||||
log.Debug("current working directory is %s", Context.workDir)
|
||||
if args.runningAsService {
|
||||
if opts.runningAsService {
|
||||
log.Info("AdGuard Home is running as a service")
|
||||
}
|
||||
|
||||
setupContext(args)
|
||||
setupContext(opts)
|
||||
|
||||
err := configureOS(config)
|
||||
fatalOnError(err)
|
||||
|
@ -427,7 +443,7 @@ func run(args options, clientBuildFS fs.FS) {
|
|||
// but also avoid relying on automatic Go init() function
|
||||
filtering.InitModule()
|
||||
|
||||
err = setupConfig(args)
|
||||
err = setupConfig(opts)
|
||||
fatalOnError(err)
|
||||
|
||||
if !Context.firstRun {
|
||||
|
@ -456,7 +472,7 @@ func run(args options, clientBuildFS fs.FS) {
|
|||
}
|
||||
|
||||
sessFilename := filepath.Join(Context.getDataDir(), "sessions.db")
|
||||
GLMode = args.glinetMode
|
||||
GLMode = opts.glinetMode
|
||||
var rateLimiter *authRateLimiter
|
||||
if config.AuthAttempts > 0 && config.AuthBlockMin > 0 {
|
||||
rateLimiter = newAuthRateLimiter(
|
||||
|
@ -483,7 +499,7 @@ func run(args options, clientBuildFS fs.FS) {
|
|||
log.Fatalf("Can't initialize TLS module")
|
||||
}
|
||||
|
||||
Context.web, err = initWeb(args, clientBuildFS)
|
||||
Context.web, err = initWeb(opts, clientBuildFS)
|
||||
fatalOnError(err)
|
||||
|
||||
if !Context.firstRun {
|
||||
|
@ -575,10 +591,10 @@ func writePIDFile(fn string) bool {
|
|||
return true
|
||||
}
|
||||
|
||||
func initConfigFilename(args options) {
|
||||
func initConfigFilename(opts options) {
|
||||
// config file path can be overridden by command-line arguments:
|
||||
if args.configFilename != "" {
|
||||
Context.configFilename = args.configFilename
|
||||
if opts.confFilename != "" {
|
||||
Context.configFilename = opts.confFilename
|
||||
} else {
|
||||
// Default config file name
|
||||
Context.configFilename = "AdGuardHome.yaml"
|
||||
|
@ -587,15 +603,15 @@ func initConfigFilename(args options) {
|
|||
|
||||
// initWorkingDir initializes the workDir
|
||||
// if no command-line arguments specified, we use the directory where our binary file is located
|
||||
func initWorkingDir(args options) {
|
||||
func initWorkingDir(opts options) {
|
||||
execPath, err := os.Executable()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if args.workDir != "" {
|
||||
if opts.workDir != "" {
|
||||
// If there is a custom config file, use it's directory as our working dir
|
||||
Context.workDir = args.workDir
|
||||
Context.workDir = opts.workDir
|
||||
} else {
|
||||
Context.workDir = filepath.Dir(execPath)
|
||||
}
|
||||
|
@ -609,15 +625,15 @@ func initWorkingDir(args options) {
|
|||
}
|
||||
|
||||
// configureLogger configures logger level and output
|
||||
func configureLogger(args options) {
|
||||
func configureLogger(opts options) {
|
||||
ls := getLogSettings()
|
||||
|
||||
// command-line arguments can override config settings
|
||||
if args.verbose || config.Verbose {
|
||||
if opts.verbose || config.Verbose {
|
||||
ls.Verbose = true
|
||||
}
|
||||
if args.logFile != "" {
|
||||
ls.File = args.logFile
|
||||
if opts.logFile != "" {
|
||||
ls.File = opts.logFile
|
||||
} else if config.File != "" {
|
||||
ls.File = config.File
|
||||
}
|
||||
|
@ -638,7 +654,7 @@ func configureLogger(args options) {
|
|||
// happen pretty quickly.
|
||||
log.SetFlags(log.LstdFlags | log.Lmicroseconds)
|
||||
|
||||
if args.runningAsService && ls.File == "" && runtime.GOOS == "windows" {
|
||||
if opts.runningAsService && ls.File == "" && runtime.GOOS == "windows" {
|
||||
// When running as a Windows service, use eventlog by default if nothing
|
||||
// else is configured. Otherwise, we'll simply lose the log output.
|
||||
ls.File = configSyslog
|
||||
|
@ -728,25 +744,29 @@ func exitWithError() {
|
|||
os.Exit(64)
|
||||
}
|
||||
|
||||
// loadOptions reads command line arguments and initializes configuration
|
||||
func loadOptions() options {
|
||||
o, f, err := parse(os.Args[0], os.Args[1:])
|
||||
|
||||
// loadCmdLineOpts reads command line arguments and initializes configuration
|
||||
// from them. If there is an error or an effect, loadCmdLineOpts processes them
|
||||
// and exits.
|
||||
func loadCmdLineOpts() (opts options) {
|
||||
opts, eff, err := parseCmdOpts(os.Args[0], os.Args[1:])
|
||||
if err != nil {
|
||||
log.Error(err.Error())
|
||||
_ = printHelp(os.Args[0])
|
||||
printHelp(os.Args[0])
|
||||
|
||||
exitWithError()
|
||||
} else if f != nil {
|
||||
err = f()
|
||||
}
|
||||
|
||||
if eff != nil {
|
||||
err = eff()
|
||||
if err != nil {
|
||||
log.Error(err.Error())
|
||||
exitWithError()
|
||||
} else {
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
return o
|
||||
return opts
|
||||
}
|
||||
|
||||
// printWebAddrs prints addresses built from proto, addr, and an appropriate
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue