summaryrefslogtreecommitdiff
path: root/internal/app/flags.go
diff options
context:
space:
mode:
authorBenjamin Chausse <benjamin@chausse.xyz>2025-02-03 01:12:45 -0500
committerBenjamin Chausse <benjamin@chausse.xyz>2025-02-03 01:12:45 -0500
commit5389e1a5d26fdbf2441fa5a1e101999e8449b9d1 (patch)
tree069cd37cb8e556c1ba3b47c3ea8576a1aa91ea2c /internal/app/flags.go
Batman
Diffstat (limited to 'internal/app/flags.go')
-rw-r--r--internal/app/flags.go127
1 files changed, 127 insertions, 0 deletions
diff --git a/internal/app/flags.go b/internal/app/flags.go
new file mode 100644
index 0000000..e96b8ef
--- /dev/null
+++ b/internal/app/flags.go
@@ -0,0 +1,127 @@
+package app
+
+import (
+ "context"
+ "fmt"
+ "log/slog"
+ "os"
+ "strings"
+
+ "github.com/ChausseBenjamin/rafta/internal/logging"
+ "github.com/ChausseBenjamin/rafta/internal/server"
+ "github.com/urfave/cli/v3"
+)
+
+const (
+ FlagListenPort = "port"
+ FlagLogLevel = "log-level"
+ FlagLogFormat = "log-format"
+ FlagLogOutput = "log-output"
+ FlagDBPath = "database"
+)
+
+func flags() []cli.Flag {
+ return []cli.Flag{
+ // Logging {{{
+ &cli.StringFlag{
+ Name: FlagLogFormat,
+ Aliases: []string{"f"},
+ Value: "plain",
+ Usage: "plain, json",
+ Sources: cli.EnvVars("LOG_FORMAT"),
+ Action: validateLogFormat,
+ },
+ &cli.StringFlag{
+ Name: FlagLogOutput,
+ Aliases: []string{"o"},
+ Value: "stdout",
+ Usage: "stdout, stderr, file",
+ Sources: cli.EnvVars("LOG_OUTPUT"),
+ Action: validateLogOutput,
+ },
+ &cli.StringFlag{
+ Name: FlagLogLevel,
+ Aliases: []string{"l"},
+ Value: "info",
+ Usage: "debug, info, warn, error",
+ Sources: cli.EnvVars("LOG_LEVEL"),
+ Action: validateLogLevel,
+ }, // }}}
+ // gRPC server {{{
+ &cli.IntFlag{
+ Name: FlagListenPort,
+ Aliases: []string{"p"},
+ Value: 1234,
+ Sources: cli.EnvVars("LISTEN_PORT"),
+ Action: validateListenPort,
+ }, // }}}
+ // Database {{{
+ &cli.StringFlag{
+ Name: FlagDBPath,
+ Aliases: []string{"d"},
+ Value: "store.db",
+ Usage: "database file",
+ Sources: cli.EnvVars("DATABASE_PATH"),
+ Action: validateDBPath,
+ }, // }}}
+ }
+}
+
+func validateLogOutput(ctx context.Context, cmd *cli.Command, s string) error {
+ switch {
+ case s == "stdout" || s == "stderr":
+ return nil
+ default:
+ // assume file
+ f, err := os.OpenFile(s, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
+ if err != nil {
+ slog.ErrorContext(
+ ctx,
+ fmt.Sprintf("Error creating/accessing provided log file %s", s),
+ )
+ return err
+ }
+ defer f.Close()
+ return nil
+ }
+}
+
+func validateLogLevel(ctx context.Context, cmd *cli.Command, s string) error {
+ for _, lvl := range []string{"deb", "inf", "warn", "err"} {
+ if strings.Contains(strings.ToLower(s), lvl) {
+ return nil
+ }
+ }
+ slog.ErrorContext(
+ ctx,
+ fmt.Sprintf("Unknown log level provided: %s", s),
+ )
+ return logging.ErrInvalidLevel
+}
+
+func validateLogFormat(ctx context.Context, cmd *cli.Command, s string) error {
+ s = strings.ToLower(s)
+ if s == "json" || s == "plain" {
+ return nil
+ }
+ return nil
+}
+
+func validateListenPort(ctx context.Context, cmd *cli.Command, p int64) error {
+ if p < 1024 || p > 65535 {
+ slog.ErrorContext(
+ ctx,
+ fmt.Sprintf("Out-of-bound port provided: %d", p),
+ )
+ return server.ErrOutOfBoundsPort
+ }
+ return nil
+}
+
+func validateDBPath(ctx context.Context, cmd *cli.Command, s string) error {
+ // TODO: Ensure the db file is writable.
+ // TODO: Ensure the db file is a valid sqlite3 db.
+ // TODO: Call db.Reset() if either of the above fail.
+ // TODO: Log the error/crash if the db file is not writable.
+ return nil
+}