Skip to content

Commit

Permalink
feat: implement moul/climan
Browse files Browse the repository at this point in the history
Signed-off-by: ismael FALL <[email protected]>
  • Loading branch information
Doozers committed Sep 15, 2022
1 parent a82b084 commit 42eb923
Show file tree
Hide file tree
Showing 3 changed files with 153 additions and 147 deletions.
56 changes: 35 additions & 21 deletions go/cmd/yolo/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package main
import (
"context"
"flag"
"fmt"
"log"
"math/rand"
"net/http"
Expand All @@ -13,6 +14,7 @@ import (
"berty.tech/yolo/v2/go/pkg/bintray"
"go.uber.org/zap"
"golang.org/x/oauth2"
"moul.io/climan"
"moul.io/hcfilters"
"moul.io/zapconfig"

Expand All @@ -26,18 +28,22 @@ import (
circleci "github.com/jszwedko/go-circleci"
"github.com/peterbourgon/diskv"
ff "github.com/peterbourgon/ff/v3"
"github.com/peterbourgon/ff/v3/ffcli"
)

var (
verbose bool
logFormat string
dbStorePath string
withPreloading bool
)
type flagsBuilder func(fs *flag.FlagSet)

type GlobalOptions struct {
verbose bool
logFormat string
dbStorePath string

server server
}

var optsGlobal = &GlobalOptions{}

func main() {
err := yolo(os.Args)
err := yolo(os.Args[1:])
if err != nil {
log.Fatalf("err: %+v", err)
os.Exit(1)
Expand All @@ -49,25 +55,33 @@ func yolo(args []string) error {
rootFlagSet := flag.NewFlagSet("yolo", flag.ExitOnError)
rand.Seed(time.Now().UnixNano())
rootFlagSet.SetOutput(os.Stderr)
rootFlagSet.BoolVar(&verbose, "v", false, "increase log verbosity")
rootFlagSet.StringVar(&logFormat, "log-format", "console", strings.Join(zapconfig.AvailablePresets, ", "))

root := &ffcli.Command{
ShortUsage: `server [flags] <subcommand>`,
FlagSet: rootFlagSet,
Subcommands: []*ffcli.Command{
serverCommand(),
dumpObjectsCommand(),
infoCommand(),
treeCommand(),

commonFlagsBuilder := func(fs *flag.FlagSet) {
fs.BoolVar(&optsGlobal.verbose, "v", false, "increase log verbosity")
fs.StringVar(&optsGlobal.logFormat, "log-format", "console", strings.Join(zapconfig.AvailablePresets, ", "))
fs.StringVar(&optsGlobal.dbStorePath, "db-path", ":memory:", "DB Store path")
}

root := &climan.Command{
ShortUsage: `server [flags] <subcommand>`,
FlagSetBuilder: commonFlagsBuilder,
Subcommands: []*climan.Command{
serverCommand(commonFlagsBuilder),
dumpObjectsCommand(commonFlagsBuilder),
infoCommand(commonFlagsBuilder),
treeCommand(commonFlagsBuilder),
},
Options: []ff.Option{ff.WithEnvVarNoPrefix()},
FFOptions: []ff.Option{ff.WithEnvVarNoPrefix()},
Exec: func(_ context.Context, _ []string) error {
return flag.ErrHelp
},
}

return root.ParseAndRun(context.Background(), os.Args[1:])
if err := root.Parse(args); err != nil {
return fmt.Errorf("parse error: %w", err)
}

return root.Run(context.Background())
}

func bintrayClientFromArgs(username, token string, logger *zap.Logger) (*bintray.Client, error) {
Expand Down
190 changes: 96 additions & 94 deletions go/cmd/yolo/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,87 +10,89 @@ import (

"berty.tech/yolo/v2/go/pkg/bintray"
"berty.tech/yolo/v2/go/pkg/yolosvc"
"moul.io/climan"

"github.com/buildkite/go-buildkite/buildkite"
"github.com/jszwedko/go-circleci"
"github.com/oklog/run"
"github.com/peterbourgon/ff/v3"
"github.com/peterbourgon/ff/v3/ffcli"
"github.com/tevino/abool"
)

func serverCommand() *ffcli.Command {
fs := flag.NewFlagSet("server", flag.ExitOnError)

var (
devMode bool
withCache bool
maxBuilds int
buildkiteToken string
githubToken string
githubRepos string
bintrayUsername string
bintrayToken string
artifactsCachePath string
circleciToken string
grpcBind string
httpBind string
corsAllowedOrigins string
requestTimeout time.Duration
shutdownTimeout time.Duration
basicAuth string
authSalt string
httpCachePath string
realm string
once bool
iosPrivkeyPath string
iosProvPath string
iosPrivkeyPass string
)

fs.BoolVar(&devMode, "dev-mode", false, "enable insecure helpers")
fs.BoolVar(&withCache, "with-cache", false, "enable API caching")
fs.StringVar(&buildkiteToken, "buildkite-token", "", "BuildKite API Token")
fs.StringVar(&bintrayUsername, "bintray-username", "", "Bintray username")
fs.StringVar(&bintrayToken, "bintray-token", "", "Bintray API Token")
fs.StringVar(&circleciToken, "circleci-token", "", "CircleCI API Token")
fs.StringVar(&githubToken, "github-token", "", "GitHub API Token")
fs.StringVar(&githubRepos, "github-repos", "berty/berty", "GitHub repositories to watch")
fs.StringVar(&dbStorePath, "db-path", ":memory:", "DB Store path")
fs.StringVar(&artifactsCachePath, "artifacts-cache-path", "", "Artifacts caching path")
fs.IntVar(&maxBuilds, "max-builds", 100, "maximum builds to fetch from external services (pagination)")
fs.StringVar(&httpBind, "http-bind", ":8000", "HTTP bind address")
fs.StringVar(&grpcBind, "grpc-bind", ":9000", "gRPC bind address")
fs.StringVar(&corsAllowedOrigins, "cors-allowed-origins", "", "CORS allowed origins (*.domain.tld)")
fs.DurationVar(&requestTimeout, "request-timeout", 5*time.Second, "request timeout")
fs.DurationVar(&shutdownTimeout, "shutdown-timeout", 6*time.Second, "server shutdown timeout")
fs.StringVar(&basicAuth, "basic-auth-password", "", "if set, enables basic authentication")
fs.StringVar(&realm, "realm", "Yolo", "authentication Realm")
fs.StringVar(&authSalt, "auth-salt", "", "salt used to generate authentication tokens at the end of the URLs")
fs.StringVar(&httpCachePath, "http-cache-path", "", "if set, will cache http client requests")
fs.BoolVar(&once, "once", false, "just run workers once")
fs.StringVar(&iosPrivkeyPath, "ios-privkey", "", "iOS signing: path to private key or p12 file (PEM or DER format)")
fs.StringVar(&iosProvPath, "ios-prov", "", "iOS signing: path to mobile provisioning profile")
fs.StringVar(&iosPrivkeyPass, "ios-pass", "", "iOS signing: password for private key or p12 file")

return &ffcli.Command{
type server struct {
devMode bool
withCache bool
maxBuilds int
buildkiteToken string
githubToken string
githubRepos string
bintrayUsername string
bintrayToken string
artifactsCachePath string
circleciToken string
grpcBind string
httpBind string
corsAllowedOrigins string
requestTimeout time.Duration
shutdownTimeout time.Duration
basicAuth string
authSalt string
httpCachePath string
realm string
once bool
iosPrivkeyPath string
iosProvPath string
iosPrivkeyPass string
}

func (s server) parse(fs *flag.FlagSet) {
fs.BoolVar(&optsGlobal.server.devMode, "dev-mode", false, "enable insecure helpers")
fs.BoolVar(&optsGlobal.server.withCache, "with-cache", false, "enable API caching")
fs.StringVar(&optsGlobal.server.buildkiteToken, "buildkite-token", "", "BuildKite API Token")
fs.StringVar(&optsGlobal.server.bintrayUsername, "bintray-username", "", "Bintray username")
fs.StringVar(&optsGlobal.server.bintrayToken, "bintray-token", "", "Bintray API Token")
fs.StringVar(&optsGlobal.server.circleciToken, "circleci-token", "", "CircleCI API Token")
fs.StringVar(&optsGlobal.server.githubToken, "github-token", "", "GitHub API Token")
fs.StringVar(&optsGlobal.server.githubRepos, "github-repos", "berty/berty", "GitHub repositories to watch")
fs.StringVar(&optsGlobal.server.artifactsCachePath, "artifacts-cache-path", "", "Artifacts caching path")
fs.IntVar(&optsGlobal.server.maxBuilds, "max-builds", 100, "maximum builds to fetch from external services (pagination)")
fs.StringVar(&optsGlobal.server.httpBind, "http-bind", ":8000", "HTTP bind address")
fs.StringVar(&optsGlobal.server.grpcBind, "grpc-bind", ":9000", "gRPC bind address")
fs.StringVar(&optsGlobal.server.corsAllowedOrigins, "cors-allowed-origins", "", "CORS allowed origins (*.domain.tld)")
fs.DurationVar(&optsGlobal.server.requestTimeout, "request-timeout", 5*time.Second, "request timeout")
fs.DurationVar(&optsGlobal.server.shutdownTimeout, "shutdown-timeout", 6*time.Second, "server shutdown timeout")
fs.StringVar(&optsGlobal.server.basicAuth, "basic-auth-password", "", "if set, enables basic authentication")
fs.StringVar(&optsGlobal.server.realm, "realm", "Yolo", "authentication realm")
fs.StringVar(&optsGlobal.server.authSalt, "auth-salt", "", "salt used to generate authentication tokens at the end of the URLs")
fs.StringVar(&optsGlobal.server.httpCachePath, "http-cache-path", "", "if set, will cache http client requests")
fs.BoolVar(&optsGlobal.server.once, "once", false, "just run workers once")
fs.StringVar(&optsGlobal.server.iosPrivkeyPath, "ios-privkey", "", "iOS signing: path to private key or p12 file (PEM or DER format)")
fs.StringVar(&optsGlobal.server.iosProvPath, "ios-prov", "", "iOS signing: path to mobile provisioning profile")
fs.StringVar(&optsGlobal.server.iosPrivkeyPass, "ios-pass", "", "iOS signing: password for private key or p12 file")
}

func serverCommand(commonFlagsBuilder flagsBuilder) *climan.Command {
return &climan.Command{
Name: `server`,
ShortHelp: `Start a Yolo Server`,
FlagSet: fs,
Options: []ff.Option{ff.WithEnvVarNoPrefix()},
FFOptions: []ff.Option{ff.WithEnvVarNoPrefix()},
FlagSetBuilder: func(fs *flag.FlagSet) {
commonFlagsBuilder(fs)
optsGlobal.server.parse(fs)
},
Exec: func(ctx context.Context, _ []string) error {
logger, err := loggerFromArgs(verbose, logFormat)
logger, err := loggerFromArgs(optsGlobal.verbose, optsGlobal.logFormat)
if err != nil {
return err
}
ctx, cancel := context.WithCancel(ctx)
defer cancel()

roundTripper, rtCloser := roundTripperFromArgs(ctx, httpCachePath, logger)
roundTripper, rtCloser := roundTripperFromArgs(ctx, optsGlobal.server.httpCachePath, logger)
defer rtCloser()
http.DefaultTransport = roundTripper

db, err := dbFromArgs(dbStorePath, logger)
db, err := dbFromArgs(optsGlobal.dbStorePath, logger)
if err != nil {
return err
}
Expand All @@ -103,37 +105,37 @@ func serverCommand() *ffcli.Command {

// service conns
var bkc *buildkite.Client
if buildkiteToken != "" {
bkc, err = buildkiteClientFromArgs(buildkiteToken)
if optsGlobal.server.buildkiteToken != "" {
bkc, err = buildkiteClientFromArgs(optsGlobal.server.buildkiteToken)
if err != nil {
return err
}
}
var ccc *circleci.Client
if circleciToken != "" {
ccc, err = circleciClientFromArgs(circleciToken)
if optsGlobal.server.circleciToken != "" {
ccc, err = circleciClientFromArgs(optsGlobal.server.circleciToken)
if err != nil {
return err
}
}
var btc *bintray.Client
if bintrayToken != "" && bintrayUsername != "" {
btc, err = bintrayClientFromArgs(bintrayUsername, bintrayToken, logger)
if optsGlobal.server.bintrayToken != "" && optsGlobal.server.bintrayUsername != "" {
btc, err = bintrayClientFromArgs(optsGlobal.server.bintrayUsername, optsGlobal.server.bintrayToken, logger)
if err != nil {
return err
}
}
ghc, err := githubClientFromArgs(githubToken)
ghc, err := githubClientFromArgs(optsGlobal.server.githubToken)
if err != nil {
return err
}

if devMode {
if optsGlobal.server.devMode {
logger.Warn("--dev-mode: insecure helpers are enabled")
}

if artifactsCachePath != "" {
if err := os.MkdirAll(artifactsCachePath, 0o755); err != nil {
if optsGlobal.server.artifactsCachePath != "" {
if err := os.MkdirAll(optsGlobal.server.artifactsCachePath, 0o755); err != nil {
return err
}
}
Expand All @@ -145,52 +147,52 @@ func serverCommand() *ffcli.Command {
CircleciClient: ccc,
BintrayClient: btc,
GithubClient: ghc,
AuthSalt: authSalt,
DevMode: devMode,
ArtifactsCachePath: artifactsCachePath,
IOSPrivkeyPath: iosPrivkeyPath,
IOSProvPath: iosProvPath,
IOSPrivkeyPass: iosPrivkeyPass,
AuthSalt: optsGlobal.server.authSalt,
DevMode: optsGlobal.server.devMode,
ArtifactsCachePath: optsGlobal.server.artifactsCachePath,
IOSPrivkeyPath: optsGlobal.server.iosPrivkeyPath,
IOSProvPath: optsGlobal.server.iosProvPath,
IOSPrivkeyPass: optsGlobal.server.iosPrivkeyPass,
})
if err != nil {
return err
}

// service workers
if bkc != nil {
opts := yolosvc.BuildkiteWorkerOpts{Logger: logger, MaxBuilds: maxBuilds, ClearCache: cc, Once: once}
opts := yolosvc.BuildkiteWorkerOpts{Logger: logger, MaxBuilds: optsGlobal.server.maxBuilds, ClearCache: cc, Once: optsGlobal.server.once}
gr.Add(func() error { return svc.BuildkiteWorker(ctx, opts) }, func(_ error) { cancel() })
}
if ccc != nil {
opts := yolosvc.CircleciWorkerOpts{Logger: logger, MaxBuilds: maxBuilds, ClearCache: cc, Once: once}
opts := yolosvc.CircleciWorkerOpts{Logger: logger, MaxBuilds: optsGlobal.server.maxBuilds, ClearCache: cc, Once: optsGlobal.server.once}
gr.Add(func() error { return svc.CircleciWorker(ctx, opts) }, func(_ error) { cancel() })
}
if btc != nil {
opts := yolosvc.BintrayWorkerOpts{Logger: logger, ClearCache: cc, Once: once}
opts := yolosvc.BintrayWorkerOpts{Logger: logger, ClearCache: cc, Once: optsGlobal.server.once}
gr.Add(func() error { return svc.BintrayWorker(ctx, opts) }, func(_ error) { cancel() })
}
if !once { // disable pkgman when running with --once
opts := yolosvc.PkgmanWorkerOpts{Logger: logger, ClearCache: cc, Once: once}
if !optsGlobal.server.once { // disable pkgman when running with --once
opts := yolosvc.PkgmanWorkerOpts{Logger: logger, ClearCache: cc, Once: optsGlobal.server.once}
gr.Add(func() error { return svc.PkgmanWorker(ctx, opts) }, func(_ error) { cancel() })
}
if githubToken != "" {
opts := yolosvc.GithubWorkerOpts{Logger: logger, MaxBuilds: maxBuilds, ClearCache: cc, Once: once, ReposFilter: githubRepos, Token: githubToken}
if optsGlobal.server.githubToken != "" {
opts := yolosvc.GithubWorkerOpts{Logger: logger, MaxBuilds: optsGlobal.server.maxBuilds, ClearCache: cc, Once: optsGlobal.server.once, ReposFilter: optsGlobal.server.githubRepos, Token: optsGlobal.server.githubToken}
gr.Add(func() error { return svc.GitHubWorker(ctx, opts) }, func(_ error) { cancel() })
}

// server/API
server, err := yolosvc.NewServer(ctx, svc, yolosvc.ServerOpts{
Logger: logger,
GRPCBind: grpcBind,
HTTPBind: httpBind,
RequestTimeout: requestTimeout,
ShutdownTimeout: shutdownTimeout,
CORSAllowedOrigins: corsAllowedOrigins,
BasicAuth: basicAuth,
Realm: realm,
AuthSalt: authSalt,
DevMode: devMode,
WithCache: withCache,
GRPCBind: optsGlobal.server.grpcBind,
HTTPBind: optsGlobal.server.httpBind,
RequestTimeout: optsGlobal.server.requestTimeout,
ShutdownTimeout: optsGlobal.server.shutdownTimeout,
CORSAllowedOrigins: optsGlobal.server.corsAllowedOrigins,
BasicAuth: optsGlobal.server.basicAuth,
Realm: optsGlobal.server.realm,
AuthSalt: optsGlobal.server.authSalt,
DevMode: optsGlobal.server.devMode,
WithCache: optsGlobal.server.withCache,
ClearCache: cc,
})
if err != nil {
Expand Down
Loading

0 comments on commit 42eb923

Please sign in to comment.