2018-06-27 09:02:49 +01:00
|
|
|
// Copyright (C) 2018 Storj Labs, Inc.
|
|
|
|
// See LICENSE for copying information.
|
|
|
|
|
|
|
|
package process
|
|
|
|
|
|
|
|
import (
|
2018-07-09 23:43:32 +01:00
|
|
|
"context"
|
2018-06-27 09:02:49 +01:00
|
|
|
"flag"
|
|
|
|
"fmt"
|
|
|
|
"log"
|
|
|
|
"os"
|
|
|
|
"path/filepath"
|
|
|
|
|
|
|
|
homedir "github.com/mitchellh/go-homedir"
|
|
|
|
"github.com/spf13/cobra"
|
|
|
|
"github.com/spf13/pflag"
|
|
|
|
"github.com/spf13/viper"
|
|
|
|
)
|
|
|
|
|
|
|
|
func defaultConfigPath(name string) string {
|
|
|
|
if name == "" {
|
|
|
|
name = filepath.Base(os.Args[0])
|
|
|
|
}
|
|
|
|
path := filepath.Join(".storj", fmt.Sprintf("%s.json", name))
|
|
|
|
home, err := homedir.Dir()
|
|
|
|
if err != nil {
|
|
|
|
log.Println(err)
|
|
|
|
return path
|
|
|
|
}
|
|
|
|
return filepath.Join(home, path)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Execute runs a *cobra.Command and sets up Storj-wide process configuration
|
|
|
|
// like a configuration file and logging.
|
|
|
|
func Execute(cmd *cobra.Command) {
|
|
|
|
cfgFile := flag.String("config", defaultConfigPath(cmd.Name()),
|
|
|
|
"config file")
|
|
|
|
|
|
|
|
pflag.CommandLine.AddGoFlagSet(flag.CommandLine)
|
|
|
|
|
|
|
|
cobra.OnInitialize(func() {
|
2018-07-16 20:22:34 +01:00
|
|
|
if err := viper.BindPFlags(cmd.Flags()); err != nil {
|
|
|
|
log.Fatalf("Failed to bind flags: %s\n", err)
|
|
|
|
}
|
|
|
|
|
2018-06-27 09:02:49 +01:00
|
|
|
viper.SetEnvPrefix("storj")
|
|
|
|
viper.AutomaticEnv()
|
|
|
|
if *cfgFile != "" {
|
|
|
|
viper.SetConfigFile(*cfgFile)
|
2018-07-16 20:22:34 +01:00
|
|
|
if err := viper.ReadInConfig(); err != nil {
|
|
|
|
log.Fatalf("Failed to read configs: %s\n", err)
|
|
|
|
}
|
2018-06-27 09:02:49 +01:00
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
Must(cmd.Execute())
|
|
|
|
}
|
|
|
|
|
2018-07-09 23:43:32 +01:00
|
|
|
// ConfigEnvironment sets up a standard Viper environment and parses CLI flags
|
|
|
|
func ConfigEnvironment() error {
|
2018-06-27 09:02:49 +01:00
|
|
|
cfgFile := flag.String("config", defaultConfigPath(""), "config file")
|
|
|
|
pflag.CommandLine.AddGoFlagSet(flag.CommandLine)
|
|
|
|
pflag.Parse()
|
2018-07-16 20:22:34 +01:00
|
|
|
if err := viper.BindPFlags(pflag.CommandLine); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2018-06-27 09:02:49 +01:00
|
|
|
viper.SetEnvPrefix("storj")
|
|
|
|
viper.AutomaticEnv()
|
|
|
|
if *cfgFile != "" {
|
|
|
|
viper.SetConfigFile(*cfgFile)
|
2018-07-16 20:22:34 +01:00
|
|
|
if err := viper.ReadInConfig(); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2018-06-27 09:02:49 +01:00
|
|
|
}
|
|
|
|
|
2018-07-09 23:43:32 +01:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Main runs a Service
|
|
|
|
func Main(configFn func() error, s ...Service) error {
|
2018-07-16 20:22:34 +01:00
|
|
|
if err := configFn(); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2018-07-09 23:43:32 +01:00
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
2018-07-16 20:22:34 +01:00
|
|
|
defer cancel()
|
|
|
|
|
2018-07-09 23:43:32 +01:00
|
|
|
errors := make(chan error, len(s))
|
|
|
|
|
|
|
|
for _, service := range s {
|
|
|
|
go func(ctx context.Context, s Service, ch <-chan error) {
|
|
|
|
errors <- CtxService(s)(&cobra.Command{}, pflag.Args())
|
|
|
|
}(ctx, service, errors)
|
|
|
|
}
|
|
|
|
|
|
|
|
select {
|
|
|
|
case <-ctx.Done():
|
|
|
|
return nil
|
|
|
|
case err := <-errors:
|
|
|
|
return err
|
|
|
|
}
|
2018-06-27 09:02:49 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Must checks for errors
|
|
|
|
func Must(err error) {
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
}
|