Use cobra & viper for parsing parameters & environment
This commit is contained in:
parent
7dd4f13ab7
commit
bbfc5ec7f6
7 changed files with 154 additions and 121 deletions
|
@ -1,140 +1,103 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
// "errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
"github.com/spf13/viper"
|
||||||
"strings"
|
"strings"
|
||||||
// "github.com/davecgh/go-spew/spew"
|
// "github.com/davecgh/go-spew/spew"
|
||||||
"log"
|
// "log"
|
||||||
"os"
|
"os"
|
||||||
// "reflect"
|
// "reflect"
|
||||||
"strconv"
|
// "strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ConfigEntry struct {
|
const (
|
||||||
Type string
|
programBinary string = "trello2mail"
|
||||||
Ptr interface{}
|
)
|
||||||
Values []string
|
|
||||||
}
|
|
||||||
|
|
||||||
type TrelloConfig struct {
|
var (
|
||||||
Url string
|
ALLOWED_AUTH_TYPES = []string{"none", "plain", "login"}
|
||||||
Token string
|
ALLOWED_SECURITY_TYPES = []string{"none", "tls", "starttls"}
|
||||||
}
|
)
|
||||||
|
|
||||||
type SmtpConfig struct {
|
|
||||||
Hostname string
|
|
||||||
Port uint16
|
|
||||||
Username string
|
|
||||||
Password string
|
|
||||||
AuthType string
|
|
||||||
SecurityType string
|
|
||||||
}
|
|
||||||
|
|
||||||
type EmailConfig struct {
|
|
||||||
From string
|
|
||||||
To []string
|
|
||||||
Subject string
|
|
||||||
}
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Email EmailConfig
|
EmailFrom string `mapstructure:"email-from"`
|
||||||
Smtp SmtpConfig
|
EmailTo []string `mapstructure:"email-to"`
|
||||||
Trello TrelloConfig
|
EmailSubject string `mapstructure:"email-subject"`
|
||||||
|
|
||||||
|
SmtpHostname string `mapstructure:"smtp-hostname"`
|
||||||
|
SmtpPort uint16 `mapstructure:"smtp-port"`
|
||||||
|
SmtpUsername string `mapstructure:"smtp-username"`
|
||||||
|
SmtpPassword string `mapstructure:"smtp-password"`
|
||||||
|
SmtpAuthType string `mapstructure:"smtp-auth-type"`
|
||||||
|
SmtpSecurityType string `mapstructure:"smtp-security-type"`
|
||||||
|
|
||||||
|
TrelloUrl string `mapstructure:"trello-url"`
|
||||||
|
TrelloToken string `mapstructure:"trello-token"`
|
||||||
|
|
||||||
|
Parser *cobra.Command `mapstructure:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewConfig() *Config {
|
func NewConfig() *Config {
|
||||||
return &Config{}
|
self := &Config{}
|
||||||
|
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
Use: programBinary,
|
||||||
|
Run: func(cmd *cobra.Command, args []string) { /* placeholder */ },
|
||||||
}
|
}
|
||||||
|
|
||||||
func (config *Config) ParseEnv() (int, error) {
|
viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_"))
|
||||||
// map env variables to config pointers
|
viper.AutomaticEnv()
|
||||||
dataMap := map[string](ConfigEntry){
|
|
||||||
"EMAIL_FROM": ConfigEntry{"string", &(config.Email.From), nil},
|
|
||||||
"EMAIL_TO": ConfigEntry{"stringlist", &(config.Email.To), nil},
|
|
||||||
"EMAIL_SUBJECT": ConfigEntry{"string", &(config.Email.Subject), nil},
|
|
||||||
"TRELLO_URL": ConfigEntry{"string", &(config.Trello.Url), nil},
|
|
||||||
"TRELLO_TOKEN": ConfigEntry{"string", &(config.Trello.Token), nil},
|
|
||||||
|
|
||||||
"SMTP_HOSTNAME": ConfigEntry{"string", &(config.Smtp.Hostname), nil},
|
cmd.PersistentFlags().StringVarP(&self.EmailFrom, "email-from", "", "", "address of sender")
|
||||||
"SMTP_USERNAME": ConfigEntry{"string", &(config.Smtp.Username), nil},
|
cmd.PersistentFlags().StringArrayVarP(&self.EmailTo, "email-to", "", []string{}, "address(es) of recipient(s)")
|
||||||
"SMTP_PASSWORD": ConfigEntry{"string", &(config.Smtp.Password), nil},
|
cmd.PersistentFlags().StringVarP(&self.EmailSubject, "email-subject", "", "", "email subject")
|
||||||
"SMTP_PORT": ConfigEntry{"uint16", &(config.Smtp.Port), nil},
|
viper.BindPFlag("email-from", cmd.PersistentFlags().Lookup("email-from"))
|
||||||
|
viper.BindPFlag("email-to", cmd.PersistentFlags().Lookup("email-to"))
|
||||||
|
viper.BindPFlag("email-subject", cmd.PersistentFlags().Lookup("email-subject"))
|
||||||
|
|
||||||
"SMTP_AUTH_TYPE": ConfigEntry{"string",
|
cmd.PersistentFlags().StringVarP(&self.TrelloUrl, "trello-url", "", "", "url of trello board")
|
||||||
&(config.Smtp.AuthType), []string{"none", "plain", "login"}},
|
cmd.PersistentFlags().StringVarP(&self.TrelloToken, "trello-token", "", "", "url of trello token")
|
||||||
"SMTP_SECURITY_TYPE": ConfigEntry{"string",
|
viper.BindPFlag("trello-url", cmd.PersistentFlags().Lookup("trello-url"))
|
||||||
&(config.Smtp.SecurityType), []string{"none", "tls", "starttls"}},
|
viper.BindPFlag("trello-token", cmd.PersistentFlags().Lookup("trello-token"))
|
||||||
|
|
||||||
|
cmd.PersistentFlags().StringVarP(&self.SmtpHostname, "smtp-hostname", "", "", "address of smtp server")
|
||||||
|
cmd.PersistentFlags().StringVarP(&self.SmtpUsername, "smtp-username", "", "", "username for smtp server")
|
||||||
|
cmd.PersistentFlags().StringVarP(&self.SmtpPassword, "smtp-password", "", "", "password for smtp server")
|
||||||
|
cmd.PersistentFlags().Uint16VarP(&self.SmtpPort, "smtp-port", "", 25, "port for smtp server")
|
||||||
|
cmd.PersistentFlags().StringVarP(&self.SmtpAuthType, "smtp-auth-type", "", "", "authentication type for smtp server")
|
||||||
|
cmd.PersistentFlags().StringVarP(&self.SmtpSecurityType, "smtp-security-type", "", "", "security type for smtp server")
|
||||||
|
viper.BindPFlag("smtp-hostname", cmd.PersistentFlags().Lookup("smtp-hostname"))
|
||||||
|
viper.BindPFlag("smtp-username", cmd.PersistentFlags().Lookup("smtp-username"))
|
||||||
|
viper.BindPFlag("smtp-password", cmd.PersistentFlags().Lookup("smtp-password"))
|
||||||
|
viper.BindPFlag("smtp-port", cmd.PersistentFlags().Lookup("smtp-port"))
|
||||||
|
viper.BindPFlag("smtp-auth-type", cmd.PersistentFlags().Lookup("smtp-auth-type"))
|
||||||
|
viper.BindPFlag("smtp-security-type", cmd.PersistentFlags().Lookup("smtp-security-type"))
|
||||||
|
|
||||||
|
self.Parser = cmd
|
||||||
|
return self
|
||||||
}
|
}
|
||||||
|
|
||||||
for envVar, mapEntry := range dataMap {
|
func (self *Config) Parse() error {
|
||||||
envValue := os.Getenv(envVar)
|
// set config defaults
|
||||||
if len(envValue) == 0 {
|
// persistent flags
|
||||||
errmsg := fmt.Sprintf(
|
// environment & config
|
||||||
"Empty environment variable. Please set %s value",
|
// viper.SetEnvPrefix("")
|
||||||
envVar,
|
|
||||||
)
|
fmt.Printf("all: %#v\n", viper.AllSettings())
|
||||||
log.Panic(errors.New(errmsg))
|
fmt.Printf("email-from %s\n", viper.Get("email-from"))
|
||||||
|
|
||||||
|
if err := self.Parser.Execute(); err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
if mapEntry.Values != nil {
|
if err := viper.Unmarshal(&self); err != nil {
|
||||||
allowedValue := false
|
panic("Unable to unmarshal config")
|
||||||
for _, v := range mapEntry.Values {
|
|
||||||
if v == envValue {
|
|
||||||
allowedValue = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !allowedValue {
|
|
||||||
errmsg := fmt.Sprintf(
|
|
||||||
"Wrong value for %s=%s. Value must be one of %v",
|
|
||||||
envVar,
|
|
||||||
envValue,
|
|
||||||
mapEntry.Values,
|
|
||||||
)
|
|
||||||
log.Panic(errors.New(errmsg))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch mapEntry.Type {
|
|
||||||
case "string":
|
|
||||||
*(mapEntry.Ptr.(*string)) = envValue
|
|
||||||
|
|
||||||
case "stringlist":
|
|
||||||
ptrs := strings.Split(envValue, ",")
|
|
||||||
mapEntry.Ptr = ptrs
|
|
||||||
|
|
||||||
case "uint16":
|
|
||||||
u64, err := strconv.ParseUint(envValue, 10, 16)
|
|
||||||
if err != nil {
|
|
||||||
errmsg := fmt.Sprintf(
|
|
||||||
"Unable to convert %s=%s to unsigned int",
|
|
||||||
envVar,
|
|
||||||
envValue,
|
|
||||||
)
|
|
||||||
log.Panic(errors.New(errmsg))
|
|
||||||
}
|
|
||||||
*(mapEntry.Ptr.(*uint16)) = uint16(u64)
|
|
||||||
|
|
||||||
case "bool":
|
|
||||||
b, err := strconv.ParseBool(envValue)
|
|
||||||
if err != nil {
|
|
||||||
errmsg := fmt.Sprintf(
|
|
||||||
"Unable to convert %s=%s to boolean",
|
|
||||||
envVar,
|
|
||||||
envValue,
|
|
||||||
)
|
|
||||||
log.Panic(errors.New(errmsg))
|
|
||||||
}
|
|
||||||
*(mapEntry.Ptr.(*bool)) = b
|
|
||||||
|
|
||||||
default:
|
|
||||||
errmsg := fmt.Sprintf(
|
|
||||||
"Undefined parser for %s<%s>",
|
|
||||||
envVar,
|
|
||||||
mapEntry.Type,
|
|
||||||
)
|
|
||||||
log.Panic(errors.New(errmsg))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// spew.Dump(config)
|
// spew.Dump(config)
|
||||||
return 0, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,12 @@ import (
|
||||||
|
|
||||||
type EmailHeaders map[string]string
|
type EmailHeaders map[string]string
|
||||||
|
|
||||||
|
type EmailConfig struct {
|
||||||
|
From string
|
||||||
|
To []string
|
||||||
|
Subject string
|
||||||
|
}
|
||||||
|
|
||||||
type EmailCtx struct {
|
type EmailCtx struct {
|
||||||
Headers EmailHeaders
|
Headers EmailHeaders
|
||||||
BodyPlain string
|
BodyPlain string
|
||||||
|
|
|
@ -9,22 +9,35 @@ import (
|
||||||
func main() {
|
func main() {
|
||||||
// Setup config
|
// Setup config
|
||||||
config := NewConfig()
|
config := NewConfig()
|
||||||
config.ParseEnv()
|
config.Parse()
|
||||||
|
fmt.Printf("%#v\n", config)
|
||||||
|
|
||||||
// Get task list as markdown
|
// Get task list as markdown
|
||||||
trelloCtx := NewTrello(config.Trello.Token)
|
trelloCtx := NewTrello(config.TrelloToken)
|
||||||
trelloBoard := trelloCtx.GetBoard(config.Trello.Url)
|
trelloBoard := trelloCtx.GetBoard(config.TrelloUrl)
|
||||||
trelloMarkdown := trelloBoard.ExportToMarkdown()
|
trelloMarkdown := trelloBoard.ExportToMarkdown()
|
||||||
trelloHtml := trelloBoard.ExportToHtml()
|
trelloHtml := trelloBoard.ExportToHtml()
|
||||||
config.Email.Subject = fmt.Sprintf("Daily mail for %s", trelloBoard.Name)
|
config.EmailSubject = fmt.Sprintf("Daily mail for %s", trelloBoard.Name)
|
||||||
|
|
||||||
// Create email enveloppe
|
// Create email enveloppe
|
||||||
email := NewEmail()
|
email := NewEmail()
|
||||||
email.SetHeaders(config.Email)
|
email.SetHeaders(EmailConfig{
|
||||||
|
From: config.EmailFrom,
|
||||||
|
To: config.EmailTo,
|
||||||
|
Subject: config.EmailSubject,
|
||||||
|
})
|
||||||
email.SetBody(trelloHtml, trelloMarkdown)
|
email.SetBody(trelloHtml, trelloMarkdown)
|
||||||
|
|
||||||
// Connect and send email
|
// Connect and send email
|
||||||
transport := NewTransport(config.Smtp)
|
transport := NewTransport(SmtpConfig{
|
||||||
|
Hostname: config.SmtpHostname,
|
||||||
|
Port: config.SmtpPort,
|
||||||
|
Username: config.SmtpUsername,
|
||||||
|
Password: config.SmtpPassword,
|
||||||
|
AuthType: config.SmtpAuthType,
|
||||||
|
SecurityType: config.SmtpSecurityType,
|
||||||
|
})
|
||||||
|
|
||||||
transport.Dial()
|
transport.Dial()
|
||||||
transport.Authenticate()
|
transport.Authenticate()
|
||||||
transport.Send(email)
|
transport.Send(email)
|
||||||
|
|
|
@ -8,6 +8,15 @@ import (
|
||||||
"net/smtp"
|
"net/smtp"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type SmtpConfig struct {
|
||||||
|
Hostname string
|
||||||
|
Port uint16
|
||||||
|
Username string
|
||||||
|
Password string
|
||||||
|
AuthType string
|
||||||
|
SecurityType string
|
||||||
|
}
|
||||||
|
|
||||||
type TransportCtx struct {
|
type TransportCtx struct {
|
||||||
Config SmtpConfig
|
Config SmtpConfig
|
||||||
Address string
|
Address string
|
||||||
|
|
|
@ -17,6 +17,11 @@ const (
|
||||||
APP_KEY string = "80dbcf6f88f62cc5639774e13342c20b"
|
APP_KEY string = "80dbcf6f88f62cc5639774e13342c20b"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type TrelloConfig struct {
|
||||||
|
Url string
|
||||||
|
Token string
|
||||||
|
}
|
||||||
|
|
||||||
type TrelloCtx struct {
|
type TrelloCtx struct {
|
||||||
Token string
|
Token string
|
||||||
Client *trello.Client
|
Client *trello.Client
|
||||||
|
@ -76,6 +81,9 @@ func (ctx *TrelloCtx) GetBoard(boardUrl string) TrelloBoard {
|
||||||
boardId := strings.Split(parsedUrl.Path, "/")[2]
|
boardId := strings.Split(parsedUrl.Path, "/")[2]
|
||||||
|
|
||||||
board, err := ctx.Client.GetBoard(boardId, trello.Defaults())
|
board, err := ctx.Client.GetBoard(boardId, trello.Defaults())
|
||||||
|
if err != nil {
|
||||||
|
log.Panic(err)
|
||||||
|
}
|
||||||
return TrelloBoard{Ctx: ctx, Ptr: board, Name: board.Name}
|
return TrelloBoard{Ctx: ctx, Ptr: board, Name: board.Name}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
3
go.mod
3
go.mod
|
@ -5,4 +5,7 @@ require (
|
||||||
github.com/pkg/errors v0.8.0 // indirect
|
github.com/pkg/errors v0.8.0 // indirect
|
||||||
github.com/russross/blackfriday/v2 v2.0.1
|
github.com/russross/blackfriday/v2 v2.0.1
|
||||||
github.com/shurcooL/sanitized_anchor_name v0.0.0-20170918181015-86672fcb3f95 // indirect
|
github.com/shurcooL/sanitized_anchor_name v0.0.0-20170918181015-86672fcb3f95 // indirect
|
||||||
|
github.com/spf13/cobra v0.0.3
|
||||||
|
github.com/spf13/pflag v1.0.3 // indirect
|
||||||
|
github.com/spf13/viper v1.2.1
|
||||||
)
|
)
|
||||||
|
|
31
go.sum
31
go.sum
|
@ -1,8 +1,39 @@
|
||||||
github.com/adlio/trello v0.0.0-20180621142300-8a458717123e h1:i5+hZJx4iTPT4+ojV5zi50UIPUxs7CH8r+P3BFB4Ofs=
|
github.com/adlio/trello v0.0.0-20180621142300-8a458717123e h1:i5+hZJx4iTPT4+ojV5zi50UIPUxs7CH8r+P3BFB4Ofs=
|
||||||
github.com/adlio/trello v0.0.0-20180621142300-8a458717123e/go.mod h1:VjzhFGdnEJGih1AsIWi/yU6y01yZh0DuEWCNAyOJ1WE=
|
github.com/adlio/trello v0.0.0-20180621142300-8a458717123e/go.mod h1:VjzhFGdnEJGih1AsIWi/yU6y01yZh0DuEWCNAyOJ1WE=
|
||||||
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
|
||||||
|
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||||
|
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
||||||
|
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||||
|
github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY=
|
||||||
|
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||||
|
github.com/mitchellh/mapstructure v1.0.0 h1:vVpGvMXJPqSDh2VYHF7gsfQj8Ncx+Xw5Y1KHeTRY+7I=
|
||||||
|
github.com/mitchellh/mapstructure v1.0.0/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||||
|
github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
|
||||||
|
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||||
github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw=
|
github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw=
|
||||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
|
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
|
||||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
github.com/shurcooL/sanitized_anchor_name v0.0.0-20170918181015-86672fcb3f95 h1:/vdW8Cb7EXrkqWGufVMES1OH2sU9gKVb2n9/1y5NMBY=
|
github.com/shurcooL/sanitized_anchor_name v0.0.0-20170918181015-86672fcb3f95 h1:/vdW8Cb7EXrkqWGufVMES1OH2sU9gKVb2n9/1y5NMBY=
|
||||||
github.com/shurcooL/sanitized_anchor_name v0.0.0-20170918181015-86672fcb3f95/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
github.com/shurcooL/sanitized_anchor_name v0.0.0-20170918181015-86672fcb3f95/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||||
|
github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI=
|
||||||
|
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||||
|
github.com/spf13/cast v1.2.0 h1:HHl1DSRbEQN2i8tJmtS6ViPyHx35+p51amrdsiTCrkg=
|
||||||
|
github.com/spf13/cast v1.2.0/go.mod h1:r2rcYCSwa1IExKTDiTfzaxqT2FNHs8hODu4LnUfgKEg=
|
||||||
|
github.com/spf13/cobra v0.0.3 h1:ZlrZ4XsMRm04Fr5pSFxBgfND2EBVa1nLpiy1stUsX/8=
|
||||||
|
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
||||||
|
github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk=
|
||||||
|
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||||
|
github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||||
|
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
|
||||||
|
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||||
|
github.com/spf13/viper v1.2.1 h1:bIcUwXqLseLF3BDAZduuNfekWG87ibtFxi59Bq+oI9M=
|
||||||
|
github.com/spf13/viper v1.2.1/go.mod h1:P4AexN0a+C9tGAnUFNwDMYYZv3pjFuvmeiMyKRaNVlI=
|
||||||
|
golang.org/x/sys v0.0.0-20180906133057-8cf3aee42992 h1:BH3eQWeGbwRU2+wxxuuPOdFBmaiBH81O8BugSjHeTFg=
|
||||||
|
golang.org/x/sys v0.0.0-20180906133057-8cf3aee42992/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||||
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=
|
||||||
|
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
|
Loading…
Reference in a new issue