cli.go 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. // Copyright 2018 Frédéric Guillot. All rights reserved.
  2. // Use of this source code is governed by the Apache 2.0
  3. // license that can be found in the LICENSE file.
  4. package cli // import "miniflux.app/cli"
  5. import (
  6. "flag"
  7. "fmt"
  8. "miniflux.app/config"
  9. "miniflux.app/database"
  10. "miniflux.app/locale"
  11. "miniflux.app/logger"
  12. "miniflux.app/storage"
  13. "miniflux.app/ui/static"
  14. "miniflux.app/version"
  15. )
  16. const (
  17. flagInfoHelp = "Show application information"
  18. flagVersionHelp = "Show application version"
  19. flagMigrateHelp = "Run SQL migrations"
  20. flagFlushSessionsHelp = "Flush all sessions (disconnect users)"
  21. flagCreateAdminHelp = "Create admin user"
  22. flagResetPasswordHelp = "Reset user password"
  23. flagResetFeedErrorsHelp = "Clear all feed errors for all users"
  24. flagDebugModeHelp = "Show debug logs"
  25. flagConfigFileHelp = "Load configuration file"
  26. flagConfigDumpHelp = "Print parsed configuration values"
  27. flagHealthCheckHelp = `Perform a health check on the given endpoint (the value "auto" try to guess the health check endpoint).`
  28. )
  29. // Parse parses command line arguments.
  30. func Parse() {
  31. var (
  32. err error
  33. flagInfo bool
  34. flagVersion bool
  35. flagMigrate bool
  36. flagFlushSessions bool
  37. flagCreateAdmin bool
  38. flagResetPassword bool
  39. flagResetFeedErrors bool
  40. flagDebugMode bool
  41. flagConfigFile string
  42. flagConfigDump bool
  43. flagHealthCheck string
  44. )
  45. flag.BoolVar(&flagInfo, "info", false, flagInfoHelp)
  46. flag.BoolVar(&flagInfo, "i", false, flagInfoHelp)
  47. flag.BoolVar(&flagVersion, "version", false, flagVersionHelp)
  48. flag.BoolVar(&flagVersion, "v", false, flagVersionHelp)
  49. flag.BoolVar(&flagMigrate, "migrate", false, flagMigrateHelp)
  50. flag.BoolVar(&flagFlushSessions, "flush-sessions", false, flagFlushSessionsHelp)
  51. flag.BoolVar(&flagCreateAdmin, "create-admin", false, flagCreateAdminHelp)
  52. flag.BoolVar(&flagResetPassword, "reset-password", false, flagResetPasswordHelp)
  53. flag.BoolVar(&flagResetFeedErrors, "reset-feed-errors", false, flagResetFeedErrorsHelp)
  54. flag.BoolVar(&flagDebugMode, "debug", false, flagDebugModeHelp)
  55. flag.StringVar(&flagConfigFile, "config-file", "", flagConfigFileHelp)
  56. flag.StringVar(&flagConfigFile, "c", "", flagConfigFileHelp)
  57. flag.BoolVar(&flagConfigDump, "config-dump", false, flagConfigDumpHelp)
  58. flag.StringVar(&flagHealthCheck, "healthcheck", "", flagHealthCheckHelp)
  59. flag.Parse()
  60. cfg := config.NewParser()
  61. if flagConfigFile != "" {
  62. config.Opts, err = cfg.ParseFile(flagConfigFile)
  63. if err != nil {
  64. logger.Fatal("%v", err)
  65. }
  66. }
  67. config.Opts, err = cfg.ParseEnvironmentVariables()
  68. if err != nil {
  69. logger.Fatal("%v", err)
  70. }
  71. if flagConfigDump {
  72. fmt.Print(config.Opts)
  73. return
  74. }
  75. if config.Opts.LogDateTime() {
  76. logger.EnableDateTime()
  77. }
  78. if flagDebugMode || config.Opts.HasDebugMode() {
  79. logger.EnableDebug()
  80. }
  81. if flagHealthCheck != "" {
  82. doHealthCheck(flagHealthCheck)
  83. return
  84. }
  85. if flagInfo {
  86. info()
  87. return
  88. }
  89. if flagVersion {
  90. fmt.Println(version.Version)
  91. return
  92. }
  93. if config.Opts.IsDefaultDatabaseURL() {
  94. logger.Info("The default value for DATABASE_URL is used")
  95. }
  96. logger.Debug("Loading translations...")
  97. if err := locale.LoadCatalogMessages(); err != nil {
  98. logger.Fatal("Unable to load translations: %v", err)
  99. }
  100. logger.Debug("Loading static assets...")
  101. if err := static.CalculateBinaryFileChecksums(); err != nil {
  102. logger.Fatal("Unable to calculate binary files checksum: %v", err)
  103. }
  104. if err := static.GenerateStylesheetsBundles(); err != nil {
  105. logger.Fatal("Unable to generate Stylesheet bundles: %v", err)
  106. }
  107. if err := static.GenerateJavascriptBundles(); err != nil {
  108. logger.Fatal("Unable to generate Javascript bundles: %v", err)
  109. }
  110. db, err := database.NewConnectionPool(
  111. config.Opts.DatabaseURL(),
  112. config.Opts.DatabaseMinConns(),
  113. config.Opts.DatabaseMaxConns(),
  114. config.Opts.DatabaseConnectionLifetime(),
  115. )
  116. if err != nil {
  117. logger.Fatal("Unable to initialize database connection pool: %v", err)
  118. }
  119. defer db.Close()
  120. store := storage.NewStorage(db)
  121. if err := store.Ping(); err != nil {
  122. logger.Fatal("Unable to connect to the database: %v", err)
  123. }
  124. if flagMigrate {
  125. if err := database.Migrate(db); err != nil {
  126. logger.Fatal(`%v`, err)
  127. }
  128. return
  129. }
  130. if flagResetFeedErrors {
  131. store.ResetFeedErrors()
  132. return
  133. }
  134. if flagFlushSessions {
  135. flushSessions(store)
  136. return
  137. }
  138. if flagCreateAdmin {
  139. createAdmin(store)
  140. return
  141. }
  142. if flagResetPassword {
  143. resetPassword(store)
  144. return
  145. }
  146. // Run migrations and start the daemon.
  147. if config.Opts.RunMigrations() {
  148. if err := database.Migrate(db); err != nil {
  149. logger.Fatal(`%v`, err)
  150. }
  151. }
  152. if err := database.IsSchemaUpToDate(db); err != nil {
  153. logger.Fatal(`You must run the SQL migrations, %v`, err)
  154. }
  155. // Create admin user and start the daemon.
  156. if config.Opts.CreateAdmin() {
  157. createAdmin(store)
  158. }
  159. startDaemon(store)
  160. }