Cleaner CLI options definition (env keys as tags)
This commit is contained in:
@@ -15,8 +15,12 @@ RUN apk add --no-cache ca-certificates
|
||||
|
||||
COPY --from=builder /tmp/corteza-server /bin
|
||||
|
||||
ENV COMPOSE_STORAGE_PATH /data/compose
|
||||
ENV MESSAGING_STORAGE_PATH /data/messaging
|
||||
ENV SYSTEM_STORAGE_PATH /data/system
|
||||
|
||||
VOLUME /data
|
||||
|
||||
EXPOSE 80
|
||||
ENTRYPOINT ["/bin/corteza-server"]
|
||||
|
||||
# Forcing exposed port
|
||||
CMD ["serve-api"]
|
||||
|
||||
@@ -15,9 +15,12 @@ RUN apk add --no-cache ca-certificates
|
||||
|
||||
COPY --from=builder /tmp/corteza-server-compose /bin
|
||||
|
||||
ENV COMPOSE_STORAGE_PATH /data/compose
|
||||
|
||||
VOLUME /data
|
||||
|
||||
EXPOSE 80
|
||||
ENTRYPOINT ["/bin/corteza-server-compose"]
|
||||
|
||||
# Forcing exposed port
|
||||
CMD ["serve-api"]
|
||||
|
||||
|
||||
@@ -15,9 +15,12 @@ RUN apk add --no-cache ca-certificates
|
||||
|
||||
COPY --from=builder /tmp/corteza-server-messaging /bin
|
||||
|
||||
ENV MESSAGING_STORAGE_PATH /data/messaging
|
||||
|
||||
VOLUME /data
|
||||
|
||||
EXPOSE 80
|
||||
ENTRYPOINT ["/bin/corteza-server-messaging"]
|
||||
|
||||
# Forcing exposed port
|
||||
CMD ["serve-api"]
|
||||
|
||||
|
||||
@@ -15,9 +15,13 @@ RUN apk add --no-cache ca-certificates
|
||||
|
||||
COPY --from=builder /tmp/corteza-server-system /bin
|
||||
|
||||
ENV SYSTEM_STORAGE_PATH /data/system
|
||||
|
||||
VOLUME /data
|
||||
|
||||
|
||||
EXPOSE 80
|
||||
ENTRYPOINT ["/bin/corteza-server-system"]
|
||||
|
||||
# Forcing exposed port
|
||||
CMD ["serve-api"]
|
||||
|
||||
|
||||
9
Gopkg.lock
generated
9
Gopkg.lock
generated
@@ -269,14 +269,6 @@
|
||||
revision = "c12348ce28de40eed0136aa2b644d0ee0650e56c"
|
||||
version = "v1.0.1"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:6221a3a452964b1ff30efdc22209b124d54d04373e5993264d3fa9b13da0659d"
|
||||
name = "github.com/namsral/flag"
|
||||
packages = ["."]
|
||||
pruneopts = "UT"
|
||||
revision = "71ceffbeb0ba60fccc853971bb3ed4d7d90bfd04"
|
||||
version = "v1.7.4-pre"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:cf31692c14422fa27c83a05292eb5cbe0fb2775972e8f1f8446a71549bd8980b"
|
||||
name = "github.com/pkg/errors"
|
||||
@@ -592,7 +584,6 @@
|
||||
"github.com/markbates/goth/providers/gplus",
|
||||
"github.com/markbates/goth/providers/linkedin",
|
||||
"github.com/markbates/goth/providers/openidConnect",
|
||||
"github.com/namsral/flag",
|
||||
"github.com/pkg/errors",
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp",
|
||||
"github.com/spf13/afero",
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"github.com/cortezaproject/corteza-server/compose/internal/service"
|
||||
"github.com/cortezaproject/corteza-server/compose/rest"
|
||||
"github.com/cortezaproject/corteza-server/pkg/cli"
|
||||
"github.com/cortezaproject/corteza-server/pkg/cli/options"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -36,7 +37,9 @@ func Configure() *cli.Config {
|
||||
cli.HandleError(c.ProvisionMigrateDatabase.Run(ctx, cmd, c))
|
||||
}
|
||||
|
||||
cli.HandleError(service.Init(ctx, c.Log))
|
||||
storagePath := options.EnvString("", "COMPOSE_STORAGE_PATH", "var/store")
|
||||
|
||||
cli.HandleError(service.Init(ctx, c.Log, storagePath))
|
||||
|
||||
if c.ProvisionOpt.AutoSetup {
|
||||
cli.HandleError(accessControlSetup(ctx, cmd, c))
|
||||
|
||||
@@ -60,7 +60,7 @@ func TestMain(m *testing.M) {
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
Init(ctx, zap.NewNop())
|
||||
Init(ctx, zap.NewNop(), "/tmp/corteza-compose-store")
|
||||
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
@@ -35,10 +35,11 @@ var (
|
||||
DefaultNamespace NamespaceService
|
||||
)
|
||||
|
||||
func Init(ctx context.Context, log *zap.Logger) (err error) {
|
||||
func Init(ctx context.Context, log *zap.Logger, storePath string) (err error) {
|
||||
DefaultLogger = log.Named("service")
|
||||
|
||||
fs, err := store.New("var/store")
|
||||
fs, err := store.New(storePath)
|
||||
log.Info("initializing store", zap.String("path", storePath), zap.Error(err))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ func TestMain(m *testing.M) {
|
||||
return
|
||||
}
|
||||
|
||||
Init(context.Background(), zap.NewNop())
|
||||
Init(context.Background(), zap.NewNop(), "/tmp/corteza-messaging-store")
|
||||
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
@@ -38,10 +38,11 @@ var (
|
||||
DefaultWebhook WebhookService
|
||||
)
|
||||
|
||||
func Init(ctx context.Context, log *zap.Logger) (err error) {
|
||||
func Init(ctx context.Context, log *zap.Logger, storePath string) (err error) {
|
||||
DefaultLogger = log.Named("service")
|
||||
|
||||
fs, err := store.New("var/store")
|
||||
fs, err := store.New(storePath)
|
||||
log.Info("initializing store", zap.String("path", storePath), zap.Error(err))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -42,7 +42,9 @@ func Configure() *cli.Config {
|
||||
cli.HandleError(c.ProvisionMigrateDatabase.Run(ctx, cmd, c))
|
||||
}
|
||||
|
||||
cli.HandleError(service.Init(ctx, c.Log))
|
||||
storagePath := options.EnvString("", "MESSAGING_STORAGE_PATH", "var/store")
|
||||
|
||||
cli.HandleError(service.Init(ctx, c.Log, storagePath))
|
||||
|
||||
var websocketOpt = options.Websocket(messaging)
|
||||
|
||||
|
||||
@@ -37,14 +37,15 @@ func NewServer(log *zap.Logger) *Server {
|
||||
}
|
||||
|
||||
func (s *Server) Command(ctx context.Context, cmdName, prefix string, preRun func(context.Context) error) (cmd *cobra.Command) {
|
||||
s.httpOpt = options.HTTP(prefix)
|
||||
s.monitorOpt = options.Monitor(prefix)
|
||||
|
||||
cmd = &cobra.Command{
|
||||
Use: cmdName,
|
||||
Short: "Start HTTP Server with REST API",
|
||||
|
||||
// Connect all the wires, prepare services, run watchers, bind endpoints
|
||||
PreRunE: func(cmd *cobra.Command, args []string) error {
|
||||
s.httpOpt = options.HTTP(prefix)
|
||||
s.monitorOpt = options.Monitor(prefix)
|
||||
|
||||
if s.monitorOpt.Interval > 0 {
|
||||
go NewMonitor(int(s.monitorOpt.Interval / time.Second))
|
||||
|
||||
@@ -2,16 +2,18 @@ package options
|
||||
|
||||
type (
|
||||
DBOpt struct {
|
||||
DSN string
|
||||
Profiler string
|
||||
DSN string `env:"DB_DSN"`
|
||||
Profiler string `env:"DB_PROFILER"`
|
||||
}
|
||||
)
|
||||
|
||||
func DB(pfix string) (o *DBOpt) {
|
||||
o = &DBOpt{
|
||||
DSN: EnvString(pfix, "DB_DSN", "corteza:corteza@tcp(db:3306)/corteza?collation=utf8mb4_general_ci"),
|
||||
Profiler: EnvString(pfix, "DB_PROFILER", "none"),
|
||||
DSN: "corteza:corteza@tcp(db:3306)/corteza?collation=utf8mb4_general_ci",
|
||||
Profiler: "none",
|
||||
}
|
||||
|
||||
fill(o, pfix)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -2,12 +2,60 @@ package options
|
||||
|
||||
import (
|
||||
"os"
|
||||
"reflect"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/cast"
|
||||
)
|
||||
|
||||
func fill(opt interface{}, pfix string) {
|
||||
v := reflect.ValueOf(opt)
|
||||
if v.Kind() != reflect.Ptr {
|
||||
panic("expecting a pointer, not a value")
|
||||
}
|
||||
|
||||
if v.IsNil() {
|
||||
panic("nil pointer passed")
|
||||
}
|
||||
|
||||
v = v.Elem()
|
||||
|
||||
length := v.NumField()
|
||||
for i := 0; i < length; i++ {
|
||||
f := v.Field(i)
|
||||
t := v.Type().Field(i)
|
||||
if tag := t.Tag.Get("env"); tag != "" {
|
||||
if !f.CanSet() {
|
||||
panic("unexpected pointer for field " + t.Name)
|
||||
}
|
||||
|
||||
if f.Type() == reflect.TypeOf(time.Duration(1)) {
|
||||
v.FieldByName(t.Name).SetInt(int64(EnvDuration(pfix, tag, time.Duration(f.Int()))))
|
||||
continue
|
||||
}
|
||||
|
||||
if f.Kind() == reflect.String {
|
||||
v.FieldByName(t.Name).SetString(EnvString(pfix, tag, f.String()))
|
||||
continue
|
||||
}
|
||||
|
||||
if f.Kind() == reflect.Bool {
|
||||
v.FieldByName(t.Name).SetBool(EnvBool(pfix, tag, f.Bool()))
|
||||
continue
|
||||
}
|
||||
|
||||
if f.Kind() == reflect.Int {
|
||||
v.FieldByName(t.Name).SetInt(int64(EnvInt(pfix, tag, int(f.Int()))))
|
||||
continue
|
||||
}
|
||||
|
||||
panic("unsupported type/kind for field " + t.Name)
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func makeEnvKeys(pfix, name string) []string {
|
||||
return []string{
|
||||
strings.ToUpper(strings.Trim(pfix, "_") + "_" + name),
|
||||
|
||||
@@ -6,34 +6,36 @@ import (
|
||||
|
||||
type (
|
||||
HTTPOpt struct {
|
||||
Addr string
|
||||
Logging bool
|
||||
Tracing bool
|
||||
Addr string `env:"HTTP_ADDR"`
|
||||
Logging bool `env:"HTTP_LOG_REQUESTS"`
|
||||
Tracing bool `env:"HTTP_ERROR_TRACING"`
|
||||
|
||||
EnableVersionRoute bool
|
||||
EnableDebugRoute bool
|
||||
EnableVersionRoute bool `env:"HTTP_ENABLE_VERSION_ROUTE"`
|
||||
EnableDebugRoute bool `env:"HTTP_ENABLE_DEBUG_ROUTE"`
|
||||
|
||||
EnableMetrics bool
|
||||
MetricsServiceLabel string
|
||||
MetricsUsername string
|
||||
MetricsPassword string
|
||||
EnableMetrics bool `env:"HTTP_METRICS"`
|
||||
MetricsServiceLabel string `env:"HTTP_METRICS_NAME"`
|
||||
MetricsUsername string `env:"HTTP_METRICS_USERNAME"`
|
||||
MetricsPassword string `env:"HTTP_METRICS_PASSWORD"`
|
||||
}
|
||||
)
|
||||
|
||||
func HTTP(pfix string) (o *HTTPOpt) {
|
||||
o = &HTTPOpt{
|
||||
Addr: EnvString(pfix, "HTTP_ADDR", ":80"),
|
||||
Logging: EnvBool(pfix, "HTTP_LOG_REQUESTS", true),
|
||||
Tracing: EnvBool(pfix, "HTTP_ERROR_TRACING", false),
|
||||
EnableVersionRoute: EnvBool(pfix, "HTTP_ENABLE_VERSION_ROUTE", true),
|
||||
EnableDebugRoute: EnvBool(pfix, "HTTP_ENABLE_DEBUG_ROUTE", false),
|
||||
EnableMetrics: EnvBool(pfix, "HTTP_METRICS", false),
|
||||
MetricsServiceLabel: EnvString(pfix, "HTTP_METRICS_NAME", "corteza"),
|
||||
MetricsUsername: EnvString(pfix, "HTTP_METRICS_USERNAME", "metrics"),
|
||||
Addr: ":80",
|
||||
Logging: true,
|
||||
Tracing: false,
|
||||
EnableVersionRoute: true,
|
||||
EnableDebugRoute: false,
|
||||
EnableMetrics: false,
|
||||
MetricsServiceLabel: "corteza",
|
||||
MetricsUsername: "metrics",
|
||||
|
||||
// Setting metrics password to random string to prevent security accidents...
|
||||
MetricsPassword: EnvString(pfix, "HTTP_METRICS_PASSWORD", string(rand.Bytes(5))),
|
||||
MetricsPassword: string(rand.Bytes(5)),
|
||||
}
|
||||
|
||||
fill(o, pfix)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -6,16 +6,18 @@ import (
|
||||
|
||||
type (
|
||||
HttpClientOpt struct {
|
||||
ClientTSLInsecure bool
|
||||
HttpClientTimeout time.Duration
|
||||
ClientTSLInsecure bool `env:"HTTP_CLIENT_TSL_INSECURE"`
|
||||
HttpClientTimeout time.Duration `env:"HTTP_CLIENT_TIMEOUT"`
|
||||
}
|
||||
)
|
||||
|
||||
func HttpClient(pfix string) (o *HttpClientOpt) {
|
||||
o = &HttpClientOpt{
|
||||
ClientTSLInsecure: EnvBool(pfix, "HTTP_CLIENT_TSL_INSECURE", false),
|
||||
HttpClientTimeout: EnvDuration(pfix, "HTTP_CLIENT_TIMEOUT", 30*time.Second),
|
||||
ClientTSLInsecure: false,
|
||||
HttpClientTimeout: 30 * time.Second,
|
||||
}
|
||||
|
||||
fill(o, pfix)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -8,17 +8,20 @@ import (
|
||||
|
||||
type (
|
||||
JWTOpt struct {
|
||||
Secret string
|
||||
Expiry time.Duration
|
||||
Secret string `env:"AUTH_JWT_SECRET"`
|
||||
Expiry time.Duration `env:"AUTH_JWT_EXPIRY"`
|
||||
}
|
||||
)
|
||||
|
||||
func JWT(pfix string) (o *JWTOpt) {
|
||||
o = &JWTOpt{
|
||||
Secret: EnvString(pfix, "AUTH_JWT_SECRET", string(rand.Bytes(32))),
|
||||
// Setting JWT secret to random string to prevent security accidents...
|
||||
Expiry: EnvDuration(pfix, "AUTH_JWT_EXPIRY", time.Hour*24*30),
|
||||
Secret: string(rand.Bytes(32)),
|
||||
|
||||
Expiry: time.Hour * 24 * 30,
|
||||
}
|
||||
|
||||
fill(o, pfix)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -4,14 +4,16 @@ type (
|
||||
// Logger's output leve is configured here, but
|
||||
// dev/prod configuration happens earlier
|
||||
LogOpt struct {
|
||||
Level string
|
||||
Level string `env:"LOG_LEVEL"`
|
||||
}
|
||||
)
|
||||
|
||||
func Log(pfix string) (o *LogOpt) {
|
||||
o = &LogOpt{
|
||||
Level: EnvString(pfix, "LOG_LEVEL", "info"),
|
||||
Level: "info",
|
||||
}
|
||||
|
||||
fill(o, pfix)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -6,14 +6,15 @@ import (
|
||||
|
||||
type (
|
||||
MonitorOpt struct {
|
||||
Interval time.Duration
|
||||
Interval time.Duration `env:"MONITOR_INTERVAL"`
|
||||
}
|
||||
)
|
||||
|
||||
func Monitor(pfix string) (o *MonitorOpt) {
|
||||
o = &MonitorOpt{
|
||||
Interval: EnvDuration(pfix, "MONITOR_INTERVAL", 300*time.Second),
|
||||
Interval: 300 * time.Second,
|
||||
}
|
||||
fill(o, pfix)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -2,17 +2,18 @@ package options
|
||||
|
||||
type (
|
||||
ProvisionOpt struct {
|
||||
MigrateDatabase bool
|
||||
|
||||
AutoSetup bool
|
||||
MigrateDatabase bool `env:"PROVISION_MIGRATE_DATABASE"`
|
||||
AutoSetup bool `env:"PROVISION_AUTO_SETUP"`
|
||||
}
|
||||
)
|
||||
|
||||
func Provision(pfix string) (o *ProvisionOpt) {
|
||||
o = &ProvisionOpt{
|
||||
MigrateDatabase: EnvBool(pfix, "PROVISION_MIGRATE_DATABASE", true),
|
||||
AutoSetup: EnvBool(pfix, "PROVISION_AUTO_SETUP", true),
|
||||
MigrateDatabase: true,
|
||||
AutoSetup: true,
|
||||
}
|
||||
|
||||
fill(o, pfix)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -6,16 +6,16 @@ import (
|
||||
|
||||
type (
|
||||
PubSubOpt struct {
|
||||
Mode string
|
||||
Mode string `env:"PUBSUB_MODE"`
|
||||
|
||||
// Mode
|
||||
PollingInterval time.Duration
|
||||
PollingInterval time.Duration `env:"PUBSUB_POLLING_INTERVAL"`
|
||||
|
||||
// Redis
|
||||
RedisAddr string
|
||||
RedisTimeout time.Duration
|
||||
RedisPingTimeout time.Duration
|
||||
RedisPingPeriod time.Duration
|
||||
RedisAddr string `env:"PUBSUB_REDIS_ADDR"`
|
||||
RedisTimeout time.Duration `env:"PUBSUB_REDIS_TIMEOUT"`
|
||||
RedisPingTimeout time.Duration `env:"PUBSUB_REDIS_PING_TIMEOUT"`
|
||||
RedisPingPeriod time.Duration `env:"PUBSUB_REDIS_PING_PERIOD"`
|
||||
}
|
||||
)
|
||||
|
||||
@@ -27,13 +27,15 @@ func PubSub(pfix string) (o *PubSubOpt) {
|
||||
)
|
||||
|
||||
o = &PubSubOpt{
|
||||
Mode: EnvString(pfix, "PUBSUB_MODE", "poll"),
|
||||
PollingInterval: EnvDuration(pfix, "PUBSUB_POLLING_INTERVAL", timeout),
|
||||
RedisAddr: EnvString(pfix, "PUBSUB_REDIS_ADDR", "redis:6379"),
|
||||
RedisTimeout: EnvDuration(pfix, "PUBSUB_REDIS_TIMEOUT", timeout),
|
||||
RedisPingTimeout: EnvDuration(pfix, "PUBSUB_REDIS_PING_TIMEOUT", pingTimeout),
|
||||
RedisPingPeriod: EnvDuration(pfix, "PUBSUB_REDIS_PING_PERIOD", pingPeriod),
|
||||
Mode: "poll",
|
||||
PollingInterval: timeout,
|
||||
RedisAddr: "redis:6379",
|
||||
RedisTimeout: timeout,
|
||||
RedisPingTimeout: pingTimeout,
|
||||
RedisPingPeriod: pingPeriod,
|
||||
}
|
||||
|
||||
fill(o, pfix)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -2,22 +2,24 @@ package options
|
||||
|
||||
type (
|
||||
SMTPOpt struct {
|
||||
Host string
|
||||
Port int
|
||||
User string
|
||||
Pass string
|
||||
From string
|
||||
Host string `env:"SMTP_HOST"`
|
||||
Port int `env:"SMTP_PORT"`
|
||||
User string `env:"SMTP_USERNAM"`
|
||||
Pass string `env:"SMTP_PASS"`
|
||||
From string `env:"SMTP_FROM"`
|
||||
}
|
||||
)
|
||||
|
||||
func SMTP(pfix string) (o *SMTPOpt) {
|
||||
o = &SMTPOpt{
|
||||
Host: EnvString(pfix, "SMTP_HOST", "localhost:25"),
|
||||
Port: EnvInt(pfix, "SMTP_PORT", 25),
|
||||
User: EnvString(pfix, "SMTP_USERNAME", ""),
|
||||
Pass: EnvString(pfix, "SMTP_PASS", ""),
|
||||
From: EnvString(pfix, "SMTP_FROM", ""),
|
||||
Host: "localhost:25",
|
||||
Port: 25,
|
||||
User: "",
|
||||
Pass: "",
|
||||
From: "",
|
||||
}
|
||||
|
||||
fill(o, pfix)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -6,9 +6,9 @@ import (
|
||||
|
||||
type (
|
||||
WebsocketOpt struct {
|
||||
Timeout time.Duration
|
||||
PingTimeout time.Duration
|
||||
PingPeriod time.Duration
|
||||
Timeout time.Duration `env:"WEBSOCKET_TIMEOUT"`
|
||||
PingTimeout time.Duration `env:"WEBSOCKET_PING_TIMEOUT"`
|
||||
PingPeriod time.Duration `env:"WEBSOCKET_PING_PERIOD"`
|
||||
}
|
||||
)
|
||||
|
||||
@@ -20,10 +20,12 @@ func Websocket(pfix string) (o *WebsocketOpt) {
|
||||
)
|
||||
|
||||
o = &WebsocketOpt{
|
||||
Timeout: EnvDuration(pfix, "WEBSOCKET_TIMEOUT", timeout),
|
||||
PingTimeout: EnvDuration(pfix, "WEBSOCKET_PING_TIMEOUT", pingTimeout),
|
||||
PingPeriod: EnvDuration(pfix, "WEBSOCKET_PING_PERIOD", pingPeriod),
|
||||
Timeout: timeout,
|
||||
PingTimeout: pingTimeout,
|
||||
PingPeriod: pingPeriod,
|
||||
}
|
||||
|
||||
fill(o, pfix)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -173,11 +173,20 @@ func (c *Config) Init() {
|
||||
c.DatabaseName = c.ServiceName
|
||||
}
|
||||
|
||||
c.LogOpt = options.Log(c.EnvPrefix)
|
||||
c.SmtpOpt = options.SMTP(c.EnvPrefix)
|
||||
c.JwtOpt = options.JWT(c.EnvPrefix)
|
||||
c.HttpClientOpt = options.HttpClient(c.EnvPrefix)
|
||||
c.DbOpt = options.DB(c.ServiceName)
|
||||
c.ProvisionOpt = options.Provision(c.ServiceName)
|
||||
|
||||
if c.RootCommandDBSetup == nil {
|
||||
c.RootCommandDBSetup = Runners{func(ctx context.Context, cmd *cobra.Command, c *Config) (err error) {
|
||||
_, err = db.TryToConnect(ctx, c.Log, c.DatabaseName, c.DbOpt.DSN, c.DbOpt.Profiler)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not connect to database")
|
||||
if c.DbOpt != nil {
|
||||
_, err = db.TryToConnect(ctx, c.Log, c.DatabaseName, c.DbOpt.DSN, c.DbOpt.Profiler)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not connect to database")
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
@@ -204,16 +213,8 @@ func (c *Config) MakeCLI(ctx context.Context) (cmd *cobra.Command) {
|
||||
Use: c.RootCommandName,
|
||||
TraverseChildren: true,
|
||||
PersistentPreRunE: func(cmd *cobra.Command, args []string) (err error) {
|
||||
c.LogOpt = options.Log(c.EnvPrefix)
|
||||
c.SmtpOpt = options.SMTP(c.EnvPrefix)
|
||||
c.JwtOpt = options.JWT(c.EnvPrefix)
|
||||
c.HttpClientOpt = options.HttpClient(c.EnvPrefix)
|
||||
|
||||
InitGeneralServices(c.LogOpt, c.SmtpOpt, c.JwtOpt, c.HttpClientOpt)
|
||||
|
||||
c.DbOpt = options.DB(c.ServiceName)
|
||||
c.ProvisionOpt = options.Provision(c.ServiceName)
|
||||
|
||||
err = c.RootCommandDBSetup.Run(ctx, cmd, c)
|
||||
if err != nil {
|
||||
c.Log.Error("Failed to connect to the database", zap.Error(err))
|
||||
|
||||
27
vendor/github.com/namsral/flag/LICENSE
generated
vendored
27
vendor/github.com/namsral/flag/LICENSE
generated
vendored
@@ -1,27 +0,0 @@
|
||||
Copyright (c) 2012 The Go Authors. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of Google Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
200
vendor/github.com/namsral/flag/README.md
generated
vendored
200
vendor/github.com/namsral/flag/README.md
generated
vendored
@@ -1,200 +0,0 @@
|
||||
Flag
|
||||
===
|
||||
|
||||
Flag is a drop in replacement for Go's flag package with the addition to parse files and environment variables. If you support the [twelve-factor app methodology][], Flag complies with the third factor; "Store config in the environment".
|
||||
|
||||
[twelve-factor app methodology]: http://12factor.net
|
||||
|
||||
An example using a gopher:
|
||||
|
||||
```go
|
||||
$ cat > gopher.go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/namsral/flag"
|
||||
)
|
||||
|
||||
var age int
|
||||
|
||||
flag.IntVar(&age, "age", 0, "age of gopher")
|
||||
flag.Parse()
|
||||
|
||||
fmt.Print("age:", age)
|
||||
|
||||
$ go run gopher.go -age 1
|
||||
age: 1
|
||||
```
|
||||
|
||||
Same code but using an environment variable:
|
||||
|
||||
```go
|
||||
$ export AGE=2
|
||||
$ go run gopher.go
|
||||
age: 2
|
||||
```
|
||||
|
||||
|
||||
Same code but using a configuration file:
|
||||
|
||||
```go
|
||||
$ cat > gopher.conf
|
||||
age 3
|
||||
|
||||
$ go run gopher.go -config gopher.conf
|
||||
age: 3
|
||||
```
|
||||
|
||||
The following table shows how flags are translated to environment variables and configuration files:
|
||||
|
||||
| Type | Flag | Environment | File |
|
||||
| ------ | :------------ |:------------ |:------------ |
|
||||
| int | -age 2 | AGE=2 | age 2 |
|
||||
| bool | -female | FEMALE=true | female true |
|
||||
| float | -length 175.5 | LENGTH=175.5 | length 175.5 |
|
||||
| string | -name Gloria | NAME=Gloria | name Gloria |
|
||||
|
||||
This package is a port of Go's [flag][] package from the standard library with the addition of two functions `ParseEnv` and `ParseFile`.
|
||||
|
||||
[flag]: http://golang.org/src/pkg/flagconfiguration
|
||||
|
||||
|
||||
Goals
|
||||
-----
|
||||
|
||||
- Compatability with the original `flag` package
|
||||
- Support the [twelve-factor app methodology][]
|
||||
- Uniform user experience between the three input methods
|
||||
|
||||
|
||||
Why?
|
||||
---
|
||||
|
||||
Why not use one of the many INI, JSON or YAML parsers?
|
||||
|
||||
I find it best practice to have simple configuration options to control the behaviour of an applications when it starts up. Use basic types like ints, floats and strings for configuration options and store more complex data structures in the "datastore" layer.
|
||||
|
||||
|
||||
Usage
|
||||
---
|
||||
|
||||
It's intended for projects which require a simple configuration made available through command-line flags, configuration files and shell environments. It's similar to the original `flag` package.
|
||||
|
||||
Example:
|
||||
|
||||
```go
|
||||
import "github.com/namsral/flag"
|
||||
|
||||
flag.String(flag.DefaultConfigFlagname, "", "path to config file")
|
||||
flag.Int("age", 24, "help message for age")
|
||||
|
||||
flag.Parse()
|
||||
```
|
||||
|
||||
Order of precedence:
|
||||
|
||||
1. Command line options
|
||||
2. Environment variables
|
||||
3. Configuration file
|
||||
4. Default values
|
||||
|
||||
|
||||
#### Parsing Configuration Files
|
||||
|
||||
Create a configuration file:
|
||||
|
||||
```go
|
||||
$ cat > ./gopher.conf
|
||||
# empty newlines and lines beginning with a "#" character are ignored.
|
||||
name bob
|
||||
|
||||
# keys and values can also be separated by the "=" character
|
||||
age=20
|
||||
|
||||
# booleans can be empty, set with 0, 1, true, false, etc
|
||||
hacker
|
||||
```
|
||||
|
||||
Add a "config" flag:
|
||||
|
||||
```go
|
||||
flag.String(flag.DefaultConfigFlagname, "", "path to config file")
|
||||
```
|
||||
|
||||
Run the command:
|
||||
|
||||
```go
|
||||
$ go run ./gopher.go -config ./gopher.conf
|
||||
```
|
||||
|
||||
The default flag name for the configuration file is "config" and can be changed
|
||||
by setting `flag.DefaultConfigFlagname`:
|
||||
|
||||
```go
|
||||
flag.DefaultConfigFlagname = "conf"
|
||||
flag.Parse()
|
||||
```
|
||||
|
||||
#### Parsing Environment Variables
|
||||
|
||||
Environment variables are parsed 1-on-1 with defined flags:
|
||||
|
||||
```go
|
||||
$ export AGE=44
|
||||
$ go run ./gopher.go
|
||||
age=44
|
||||
```
|
||||
|
||||
|
||||
You can also parse prefixed environment variables by setting a prefix name when creating a new empty flag set:
|
||||
|
||||
```go
|
||||
fs := flag.NewFlagSetWithEnvPrefix(os.Args[0], "GO", 0)
|
||||
fs.Int("age", 24, "help message for age")
|
||||
fs.Parse(os.Args[1:])
|
||||
...
|
||||
$ go export GO_AGE=33
|
||||
$ go run ./gopher.go
|
||||
age=33
|
||||
```
|
||||
|
||||
|
||||
For more examples see the [examples][] directory in the project repository.
|
||||
|
||||
[examples]: https://github.com/namsral/flag/tree/master/examples
|
||||
|
||||
That's it.
|
||||
|
||||
|
||||
License
|
||||
---
|
||||
|
||||
|
||||
Copyright (c) 2012 The Go Authors. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of Google Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
1068
vendor/github.com/namsral/flag/flag.go
generated
vendored
1068
vendor/github.com/namsral/flag/flag.go
generated
vendored
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user