package main import ( "context" "net/http" "forge.cadoles.com/Cadoles/daddy/internal/config" "forge.cadoles.com/Cadoles/daddy/internal/route" "github.com/go-chi/chi" "github.com/go-chi/chi/middleware" "gitlab.com/wpetit/goweb/middleware/container" "flag" "fmt" "log" "os" "github.com/pkg/errors" "gitlab.com/wpetit/goweb/logger" ) //nolint: gochecknoglobals var ( configFile = "" workdir = "" dumpConfig = false version = false migrate = "" ) // nolint: gochecknoglobals var ( GitRef = "unknown" ProjectVersion = "unknown" BuildDate = "unknown" ) //nolint: gochecknoinits func init() { flag.StringVar(&configFile, "config", configFile, "configuration file") flag.StringVar(&workdir, "workdir", workdir, "working directory") flag.BoolVar(&dumpConfig, "dump-config", dumpConfig, "dump configuration and exit") flag.BoolVar(&version, "version", version, "show version and exit") flag.StringVar(&migrate, "migrate", migrate, "migrate data schema version and exit, possible values: latest, down, up") } func main() { ctx := context.Background() flag.Parse() if version { fmt.Printf("%s (%s) - %s\n", ProjectVersion, GitRef, BuildDate) os.Exit(0) } // Switch to new working directory if defined if workdir != "" { if err := os.Chdir(workdir); err != nil { logger.Fatal( ctx, "could not change working directory", logger.E(err), logger.F("workdir", workdir), ) } } // Load configuration file if defined, use default configuration otherwise var conf *config.Config var err error if configFile != "" { conf, err = config.NewFromFile(configFile) if err != nil { log.Fatalf("%+v", errors.Wrapf(err, " '%s'", configFile)) logger.Fatal( ctx, "could not load config file", logger.E(err), logger.F("configFile", configFile), ) } } else { if dumpConfig { conf = config.NewDumpDefault() } else { conf = config.NewDefault() } } // Dump configuration if asked if dumpConfig { if err := config.Dump(conf, os.Stdout); err != nil { logger.Fatal( ctx, "could not dump config", logger.E(err), ) } os.Exit(0) } if err := config.WithEnvironment(conf); err != nil { logger.Fatal( ctx, "could not override config with environment", logger.E(err), ) } logger.Info( ctx, "starting", logger.F("gitRef", GitRef), logger.F("projectVersion", ProjectVersion), logger.F("buildDate", BuildDate), ) logger.Debug(ctx, "setting log format", logger.F("format", conf.Log.Format)) logger.SetFormat(conf.Log.Format) logger.Debug(ctx, "setting log level", logger.F("level", conf.Log.Level.String())) logger.SetLevel(conf.Log.Level) // Create service container ctn, err := getServiceContainer(ctx, conf) if err != nil { logger.Fatal( ctx, "could not create service container", logger.E(err), ) } ctx = container.WithContainer(ctx, ctn) if migrate != "" { if err := applyMigration(ctx, ctn); err != nil { logger.Fatal( ctx, "could not apply migration", logger.E(err), ) } os.Exit(0) } // Init commands and queries if err := initCommands(ctn); err != nil { logger.Fatal( ctx, "could not init commands", logger.E(err), ) } if err := initQueries(ctn); err != nil { logger.Fatal( ctx, "could not init queries", logger.E(err), ) } r := chi.NewRouter() // Define base middlewares r.Use(middleware.Logger) r.Use(middleware.Recoverer) // Expose service container on router r.Use(container.ServiceContainer(ctn)) // Define routes if err := route.Mount(r, conf); err != nil { logger.Fatal( ctx, "could not mount http routes", logger.E(err), ) } logger.Info(ctx, "listening", logger.F("address", conf.HTTP.Address)) if err := http.ListenAndServe(conf.HTTP.Address, r); err != nil { logger.Fatal( ctx, "could not listen", logger.E(err), logger.F("address", conf.HTTP.Address), ) } }