package main import ( "context" "errors" "fmt" "log/slog" "os" "github.com/spf13/pflag" "github.com/spf13/viper" "github.com/openmeterio/openmeter/app/config" "github.com/openmeterio/openmeter/pkg/log" ) func main() { defer log.PanicLogger(log.WithExit) v, flags := viper.NewWithOptions(viper.WithDecodeHook(config.DecodeHook())), pflag.NewFlagSet("OpenMeter", pflag.ExitOnError) ctx := context.Background() config.SetViperDefaults(v, flags) flags.String("config", "", "Configuration file") flags.Bool("version", false, "Show version information") flags.Bool("validate", false, "Validate configuration and exit") _ = flags.Parse(os.Args[1:]) if v, _ := flags.GetBool("version"); v { fmt.Printf("%s version %s (%s) built on %s\n", "Open Meter", version, revision, revisionDate) os.Exit(0) } if c, _ := flags.GetString("config"); c != "" { v.SetConfigFile(c) } err := v.ReadInConfig() if err != nil && !errors.As(err, &viper.ConfigFileNotFoundError{}) { panic(err) } var conf config.Configuration err = v.Unmarshal(&conf) if err != nil { panic(err) } err = conf.Validate() if err != nil { println("configuration error:") println(err.Error()) os.Exit(1) } if v, _ := flags.GetBool("validate"); v { os.Exit(0) } app, cleanup, err := initializeApplication(ctx, conf) if err != nil { slog.Error("failed to initialize application", "error", err) // Call cleanup function is may not set yet if cleanup != nil { cleanup() } os.Exit(1) } defer cleanup() app.SetGlobals() logger := app.Logger // Migrate database if err := app.Migrate(ctx); err != nil { logger.Error("failed to initialize database", "error", err) os.Exit(1) } _, err = app.LedgerAccountResolver.EnsureBusinessAccounts(ctx, app.NamespaceManager.GetDefaultNamespace()) if err != nil { logger.Error("failed to provision ledger business accounts", "error", err) os.Exit(1) } // Provision sandbox app err = app.AppRegistry.SandboxProvisioner(ctx, app.NamespaceManager.GetDefaultNamespace()) if err != nil { logger.Error("failed to provision sandbox app", "error", err) os.Exit(1) } app.Run() }