1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
|
package app
import (
"context"
"fmt"
"log/slog"
"os"
"strings"
"time"
"github.com/ChausseBenjamin/rafta/internal/logging"
"github.com/ChausseBenjamin/rafta/internal/pb"
"github.com/urfave/cli/v3"
)
const (
FlagListenPort = "port"
FlagLogLevel = "log-level"
FlagLogFormat = "log-format"
FlagLogOutput = "log-output"
FlagDBPath = "database"
FlagGraceTimeout = "grace-timeout"
)
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: 1157, // list in leetspeek :P
Sources: cli.EnvVars("LISTEN_PORT"),
Action: validateListenPort,
},
&cli.DurationFlag{
Name: FlagGraceTimeout,
Aliases: []string{"t"},
Value: 5 * time.Second,
Sources: cli.EnvVars("GRACEFUL_TIMEOUT"),
}, // }}}
// Database {{{
&cli.StringFlag{
Name: FlagDBPath,
Aliases: []string{"d"},
Value: "store.db",
Usage: "database file",
Sources: cli.EnvVars("DATABASE_PATH"),
}, // }}}
}
}
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 pb.ErrOutOfBoundsPort
}
return nil
}
|