Skip to content

Commit 42eb923

Browse files
author
ismael FALL
committed
feat: implement moul/climan
Signed-off-by: ismael FALL <ismael.fall@epitech.eu>
1 parent a82b084 commit 42eb923

File tree

3 files changed

+153
-147
lines changed

3 files changed

+153
-147
lines changed

go/cmd/yolo/main.go

Lines changed: 35 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package main
33
import (
44
"context"
55
"flag"
6+
"fmt"
67
"log"
78
"math/rand"
89
"net/http"
@@ -13,6 +14,7 @@ import (
1314
"berty.tech/yolo/v2/go/pkg/bintray"
1415
"go.uber.org/zap"
1516
"golang.org/x/oauth2"
17+
"moul.io/climan"
1618
"moul.io/hcfilters"
1719
"moul.io/zapconfig"
1820

@@ -26,18 +28,22 @@ import (
2628
circleci "github.com/jszwedko/go-circleci"
2729
"github.com/peterbourgon/diskv"
2830
ff "github.com/peterbourgon/ff/v3"
29-
"github.com/peterbourgon/ff/v3/ffcli"
3031
)
3132

32-
var (
33-
verbose bool
34-
logFormat string
35-
dbStorePath string
36-
withPreloading bool
37-
)
33+
type flagsBuilder func(fs *flag.FlagSet)
34+
35+
type GlobalOptions struct {
36+
verbose bool
37+
logFormat string
38+
dbStorePath string
39+
40+
server server
41+
}
42+
43+
var optsGlobal = &GlobalOptions{}
3844

3945
func main() {
40-
err := yolo(os.Args)
46+
err := yolo(os.Args[1:])
4147
if err != nil {
4248
log.Fatalf("err: %+v", err)
4349
os.Exit(1)
@@ -49,25 +55,33 @@ func yolo(args []string) error {
4955
rootFlagSet := flag.NewFlagSet("yolo", flag.ExitOnError)
5056
rand.Seed(time.Now().UnixNano())
5157
rootFlagSet.SetOutput(os.Stderr)
52-
rootFlagSet.BoolVar(&verbose, "v", false, "increase log verbosity")
53-
rootFlagSet.StringVar(&logFormat, "log-format", "console", strings.Join(zapconfig.AvailablePresets, ", "))
54-
55-
root := &ffcli.Command{
56-
ShortUsage: `server [flags] <subcommand>`,
57-
FlagSet: rootFlagSet,
58-
Subcommands: []*ffcli.Command{
59-
serverCommand(),
60-
dumpObjectsCommand(),
61-
infoCommand(),
62-
treeCommand(),
58+
59+
commonFlagsBuilder := func(fs *flag.FlagSet) {
60+
fs.BoolVar(&optsGlobal.verbose, "v", false, "increase log verbosity")
61+
fs.StringVar(&optsGlobal.logFormat, "log-format", "console", strings.Join(zapconfig.AvailablePresets, ", "))
62+
fs.StringVar(&optsGlobal.dbStorePath, "db-path", ":memory:", "DB Store path")
63+
}
64+
65+
root := &climan.Command{
66+
ShortUsage: `server [flags] <subcommand>`,
67+
FlagSetBuilder: commonFlagsBuilder,
68+
Subcommands: []*climan.Command{
69+
serverCommand(commonFlagsBuilder),
70+
dumpObjectsCommand(commonFlagsBuilder),
71+
infoCommand(commonFlagsBuilder),
72+
treeCommand(commonFlagsBuilder),
6373
},
64-
Options: []ff.Option{ff.WithEnvVarNoPrefix()},
74+
FFOptions: []ff.Option{ff.WithEnvVarNoPrefix()},
6575
Exec: func(_ context.Context, _ []string) error {
6676
return flag.ErrHelp
6777
},
6878
}
6979

70-
return root.ParseAndRun(context.Background(), os.Args[1:])
80+
if err := root.Parse(args); err != nil {
81+
return fmt.Errorf("parse error: %w", err)
82+
}
83+
84+
return root.Run(context.Background())
7185
}
7286

7387
func bintrayClientFromArgs(username, token string, logger *zap.Logger) (*bintray.Client, error) {

go/cmd/yolo/server.go

Lines changed: 96 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -10,87 +10,89 @@ import (
1010

1111
"berty.tech/yolo/v2/go/pkg/bintray"
1212
"berty.tech/yolo/v2/go/pkg/yolosvc"
13+
"moul.io/climan"
1314

1415
"github.com/buildkite/go-buildkite/buildkite"
1516
"github.com/jszwedko/go-circleci"
1617
"github.com/oklog/run"
1718
"github.com/peterbourgon/ff/v3"
18-
"github.com/peterbourgon/ff/v3/ffcli"
1919
"github.com/tevino/abool"
2020
)
2121

22-
func serverCommand() *ffcli.Command {
23-
fs := flag.NewFlagSet("server", flag.ExitOnError)
24-
25-
var (
26-
devMode bool
27-
withCache bool
28-
maxBuilds int
29-
buildkiteToken string
30-
githubToken string
31-
githubRepos string
32-
bintrayUsername string
33-
bintrayToken string
34-
artifactsCachePath string
35-
circleciToken string
36-
grpcBind string
37-
httpBind string
38-
corsAllowedOrigins string
39-
requestTimeout time.Duration
40-
shutdownTimeout time.Duration
41-
basicAuth string
42-
authSalt string
43-
httpCachePath string
44-
realm string
45-
once bool
46-
iosPrivkeyPath string
47-
iosProvPath string
48-
iosPrivkeyPass string
49-
)
50-
51-
fs.BoolVar(&devMode, "dev-mode", false, "enable insecure helpers")
52-
fs.BoolVar(&withCache, "with-cache", false, "enable API caching")
53-
fs.StringVar(&buildkiteToken, "buildkite-token", "", "BuildKite API Token")
54-
fs.StringVar(&bintrayUsername, "bintray-username", "", "Bintray username")
55-
fs.StringVar(&bintrayToken, "bintray-token", "", "Bintray API Token")
56-
fs.StringVar(&circleciToken, "circleci-token", "", "CircleCI API Token")
57-
fs.StringVar(&githubToken, "github-token", "", "GitHub API Token")
58-
fs.StringVar(&githubRepos, "github-repos", "berty/berty", "GitHub repositories to watch")
59-
fs.StringVar(&dbStorePath, "db-path", ":memory:", "DB Store path")
60-
fs.StringVar(&artifactsCachePath, "artifacts-cache-path", "", "Artifacts caching path")
61-
fs.IntVar(&maxBuilds, "max-builds", 100, "maximum builds to fetch from external services (pagination)")
62-
fs.StringVar(&httpBind, "http-bind", ":8000", "HTTP bind address")
63-
fs.StringVar(&grpcBind, "grpc-bind", ":9000", "gRPC bind address")
64-
fs.StringVar(&corsAllowedOrigins, "cors-allowed-origins", "", "CORS allowed origins (*.domain.tld)")
65-
fs.DurationVar(&requestTimeout, "request-timeout", 5*time.Second, "request timeout")
66-
fs.DurationVar(&shutdownTimeout, "shutdown-timeout", 6*time.Second, "server shutdown timeout")
67-
fs.StringVar(&basicAuth, "basic-auth-password", "", "if set, enables basic authentication")
68-
fs.StringVar(&realm, "realm", "Yolo", "authentication Realm")
69-
fs.StringVar(&authSalt, "auth-salt", "", "salt used to generate authentication tokens at the end of the URLs")
70-
fs.StringVar(&httpCachePath, "http-cache-path", "", "if set, will cache http client requests")
71-
fs.BoolVar(&once, "once", false, "just run workers once")
72-
fs.StringVar(&iosPrivkeyPath, "ios-privkey", "", "iOS signing: path to private key or p12 file (PEM or DER format)")
73-
fs.StringVar(&iosProvPath, "ios-prov", "", "iOS signing: path to mobile provisioning profile")
74-
fs.StringVar(&iosPrivkeyPass, "ios-pass", "", "iOS signing: password for private key or p12 file")
75-
76-
return &ffcli.Command{
22+
type server struct {
23+
devMode bool
24+
withCache bool
25+
maxBuilds int
26+
buildkiteToken string
27+
githubToken string
28+
githubRepos string
29+
bintrayUsername string
30+
bintrayToken string
31+
artifactsCachePath string
32+
circleciToken string
33+
grpcBind string
34+
httpBind string
35+
corsAllowedOrigins string
36+
requestTimeout time.Duration
37+
shutdownTimeout time.Duration
38+
basicAuth string
39+
authSalt string
40+
httpCachePath string
41+
realm string
42+
once bool
43+
iosPrivkeyPath string
44+
iosProvPath string
45+
iosPrivkeyPass string
46+
}
47+
48+
func (s server) parse(fs *flag.FlagSet) {
49+
fs.BoolVar(&optsGlobal.server.devMode, "dev-mode", false, "enable insecure helpers")
50+
fs.BoolVar(&optsGlobal.server.withCache, "with-cache", false, "enable API caching")
51+
fs.StringVar(&optsGlobal.server.buildkiteToken, "buildkite-token", "", "BuildKite API Token")
52+
fs.StringVar(&optsGlobal.server.bintrayUsername, "bintray-username", "", "Bintray username")
53+
fs.StringVar(&optsGlobal.server.bintrayToken, "bintray-token", "", "Bintray API Token")
54+
fs.StringVar(&optsGlobal.server.circleciToken, "circleci-token", "", "CircleCI API Token")
55+
fs.StringVar(&optsGlobal.server.githubToken, "github-token", "", "GitHub API Token")
56+
fs.StringVar(&optsGlobal.server.githubRepos, "github-repos", "berty/berty", "GitHub repositories to watch")
57+
fs.StringVar(&optsGlobal.server.artifactsCachePath, "artifacts-cache-path", "", "Artifacts caching path")
58+
fs.IntVar(&optsGlobal.server.maxBuilds, "max-builds", 100, "maximum builds to fetch from external services (pagination)")
59+
fs.StringVar(&optsGlobal.server.httpBind, "http-bind", ":8000", "HTTP bind address")
60+
fs.StringVar(&optsGlobal.server.grpcBind, "grpc-bind", ":9000", "gRPC bind address")
61+
fs.StringVar(&optsGlobal.server.corsAllowedOrigins, "cors-allowed-origins", "", "CORS allowed origins (*.domain.tld)")
62+
fs.DurationVar(&optsGlobal.server.requestTimeout, "request-timeout", 5*time.Second, "request timeout")
63+
fs.DurationVar(&optsGlobal.server.shutdownTimeout, "shutdown-timeout", 6*time.Second, "server shutdown timeout")
64+
fs.StringVar(&optsGlobal.server.basicAuth, "basic-auth-password", "", "if set, enables basic authentication")
65+
fs.StringVar(&optsGlobal.server.realm, "realm", "Yolo", "authentication realm")
66+
fs.StringVar(&optsGlobal.server.authSalt, "auth-salt", "", "salt used to generate authentication tokens at the end of the URLs")
67+
fs.StringVar(&optsGlobal.server.httpCachePath, "http-cache-path", "", "if set, will cache http client requests")
68+
fs.BoolVar(&optsGlobal.server.once, "once", false, "just run workers once")
69+
fs.StringVar(&optsGlobal.server.iosPrivkeyPath, "ios-privkey", "", "iOS signing: path to private key or p12 file (PEM or DER format)")
70+
fs.StringVar(&optsGlobal.server.iosProvPath, "ios-prov", "", "iOS signing: path to mobile provisioning profile")
71+
fs.StringVar(&optsGlobal.server.iosPrivkeyPass, "ios-pass", "", "iOS signing: password for private key or p12 file")
72+
}
73+
74+
func serverCommand(commonFlagsBuilder flagsBuilder) *climan.Command {
75+
return &climan.Command{
7776
Name: `server`,
7877
ShortHelp: `Start a Yolo Server`,
79-
FlagSet: fs,
80-
Options: []ff.Option{ff.WithEnvVarNoPrefix()},
78+
FFOptions: []ff.Option{ff.WithEnvVarNoPrefix()},
79+
FlagSetBuilder: func(fs *flag.FlagSet) {
80+
commonFlagsBuilder(fs)
81+
optsGlobal.server.parse(fs)
82+
},
8183
Exec: func(ctx context.Context, _ []string) error {
82-
logger, err := loggerFromArgs(verbose, logFormat)
84+
logger, err := loggerFromArgs(optsGlobal.verbose, optsGlobal.logFormat)
8385
if err != nil {
8486
return err
8587
}
8688
ctx, cancel := context.WithCancel(ctx)
8789
defer cancel()
8890

89-
roundTripper, rtCloser := roundTripperFromArgs(ctx, httpCachePath, logger)
91+
roundTripper, rtCloser := roundTripperFromArgs(ctx, optsGlobal.server.httpCachePath, logger)
9092
defer rtCloser()
9193
http.DefaultTransport = roundTripper
9294

93-
db, err := dbFromArgs(dbStorePath, logger)
95+
db, err := dbFromArgs(optsGlobal.dbStorePath, logger)
9496
if err != nil {
9597
return err
9698
}
@@ -103,37 +105,37 @@ func serverCommand() *ffcli.Command {
103105

104106
// service conns
105107
var bkc *buildkite.Client
106-
if buildkiteToken != "" {
107-
bkc, err = buildkiteClientFromArgs(buildkiteToken)
108+
if optsGlobal.server.buildkiteToken != "" {
109+
bkc, err = buildkiteClientFromArgs(optsGlobal.server.buildkiteToken)
108110
if err != nil {
109111
return err
110112
}
111113
}
112114
var ccc *circleci.Client
113-
if circleciToken != "" {
114-
ccc, err = circleciClientFromArgs(circleciToken)
115+
if optsGlobal.server.circleciToken != "" {
116+
ccc, err = circleciClientFromArgs(optsGlobal.server.circleciToken)
115117
if err != nil {
116118
return err
117119
}
118120
}
119121
var btc *bintray.Client
120-
if bintrayToken != "" && bintrayUsername != "" {
121-
btc, err = bintrayClientFromArgs(bintrayUsername, bintrayToken, logger)
122+
if optsGlobal.server.bintrayToken != "" && optsGlobal.server.bintrayUsername != "" {
123+
btc, err = bintrayClientFromArgs(optsGlobal.server.bintrayUsername, optsGlobal.server.bintrayToken, logger)
122124
if err != nil {
123125
return err
124126
}
125127
}
126-
ghc, err := githubClientFromArgs(githubToken)
128+
ghc, err := githubClientFromArgs(optsGlobal.server.githubToken)
127129
if err != nil {
128130
return err
129131
}
130132

131-
if devMode {
133+
if optsGlobal.server.devMode {
132134
logger.Warn("--dev-mode: insecure helpers are enabled")
133135
}
134136

135-
if artifactsCachePath != "" {
136-
if err := os.MkdirAll(artifactsCachePath, 0o755); err != nil {
137+
if optsGlobal.server.artifactsCachePath != "" {
138+
if err := os.MkdirAll(optsGlobal.server.artifactsCachePath, 0o755); err != nil {
137139
return err
138140
}
139141
}
@@ -145,52 +147,52 @@ func serverCommand() *ffcli.Command {
145147
CircleciClient: ccc,
146148
BintrayClient: btc,
147149
GithubClient: ghc,
148-
AuthSalt: authSalt,
149-
DevMode: devMode,
150-
ArtifactsCachePath: artifactsCachePath,
151-
IOSPrivkeyPath: iosPrivkeyPath,
152-
IOSProvPath: iosProvPath,
153-
IOSPrivkeyPass: iosPrivkeyPass,
150+
AuthSalt: optsGlobal.server.authSalt,
151+
DevMode: optsGlobal.server.devMode,
152+
ArtifactsCachePath: optsGlobal.server.artifactsCachePath,
153+
IOSPrivkeyPath: optsGlobal.server.iosPrivkeyPath,
154+
IOSProvPath: optsGlobal.server.iosProvPath,
155+
IOSPrivkeyPass: optsGlobal.server.iosPrivkeyPass,
154156
})
155157
if err != nil {
156158
return err
157159
}
158160

159161
// service workers
160162
if bkc != nil {
161-
opts := yolosvc.BuildkiteWorkerOpts{Logger: logger, MaxBuilds: maxBuilds, ClearCache: cc, Once: once}
163+
opts := yolosvc.BuildkiteWorkerOpts{Logger: logger, MaxBuilds: optsGlobal.server.maxBuilds, ClearCache: cc, Once: optsGlobal.server.once}
162164
gr.Add(func() error { return svc.BuildkiteWorker(ctx, opts) }, func(_ error) { cancel() })
163165
}
164166
if ccc != nil {
165-
opts := yolosvc.CircleciWorkerOpts{Logger: logger, MaxBuilds: maxBuilds, ClearCache: cc, Once: once}
167+
opts := yolosvc.CircleciWorkerOpts{Logger: logger, MaxBuilds: optsGlobal.server.maxBuilds, ClearCache: cc, Once: optsGlobal.server.once}
166168
gr.Add(func() error { return svc.CircleciWorker(ctx, opts) }, func(_ error) { cancel() })
167169
}
168170
if btc != nil {
169-
opts := yolosvc.BintrayWorkerOpts{Logger: logger, ClearCache: cc, Once: once}
171+
opts := yolosvc.BintrayWorkerOpts{Logger: logger, ClearCache: cc, Once: optsGlobal.server.once}
170172
gr.Add(func() error { return svc.BintrayWorker(ctx, opts) }, func(_ error) { cancel() })
171173
}
172-
if !once { // disable pkgman when running with --once
173-
opts := yolosvc.PkgmanWorkerOpts{Logger: logger, ClearCache: cc, Once: once}
174+
if !optsGlobal.server.once { // disable pkgman when running with --once
175+
opts := yolosvc.PkgmanWorkerOpts{Logger: logger, ClearCache: cc, Once: optsGlobal.server.once}
174176
gr.Add(func() error { return svc.PkgmanWorker(ctx, opts) }, func(_ error) { cancel() })
175177
}
176-
if githubToken != "" {
177-
opts := yolosvc.GithubWorkerOpts{Logger: logger, MaxBuilds: maxBuilds, ClearCache: cc, Once: once, ReposFilter: githubRepos, Token: githubToken}
178+
if optsGlobal.server.githubToken != "" {
179+
opts := yolosvc.GithubWorkerOpts{Logger: logger, MaxBuilds: optsGlobal.server.maxBuilds, ClearCache: cc, Once: optsGlobal.server.once, ReposFilter: optsGlobal.server.githubRepos, Token: optsGlobal.server.githubToken}
178180
gr.Add(func() error { return svc.GitHubWorker(ctx, opts) }, func(_ error) { cancel() })
179181
}
180182

181183
// server/API
182184
server, err := yolosvc.NewServer(ctx, svc, yolosvc.ServerOpts{
183185
Logger: logger,
184-
GRPCBind: grpcBind,
185-
HTTPBind: httpBind,
186-
RequestTimeout: requestTimeout,
187-
ShutdownTimeout: shutdownTimeout,
188-
CORSAllowedOrigins: corsAllowedOrigins,
189-
BasicAuth: basicAuth,
190-
Realm: realm,
191-
AuthSalt: authSalt,
192-
DevMode: devMode,
193-
WithCache: withCache,
186+
GRPCBind: optsGlobal.server.grpcBind,
187+
HTTPBind: optsGlobal.server.httpBind,
188+
RequestTimeout: optsGlobal.server.requestTimeout,
189+
ShutdownTimeout: optsGlobal.server.shutdownTimeout,
190+
CORSAllowedOrigins: optsGlobal.server.corsAllowedOrigins,
191+
BasicAuth: optsGlobal.server.basicAuth,
192+
Realm: optsGlobal.server.realm,
193+
AuthSalt: optsGlobal.server.authSalt,
194+
DevMode: optsGlobal.server.devMode,
195+
WithCache: optsGlobal.server.withCache,
194196
ClearCache: cc,
195197
})
196198
if err != nil {

0 commit comments

Comments
 (0)