diff --git a/.envrc b/.envrc index 37b1096..b0b0a9a 100644 --- a/.envrc +++ b/.envrc @@ -1 +1,4 @@ export GO111MODULE=on +export PATH=$PATH:$PWD/bin +export PATH=$PATH:$PWD/build +export PATH=$PATH:$PWD/script diff --git a/Makefile b/Makefile index 53f80a6..e8f3ed6 100644 --- a/Makefile +++ b/Makefile @@ -8,6 +8,10 @@ vendor: go get github.com/izumin5210/gex/cmd/gex go mod download +PHONY: generate +generate: + go generate ./... + PHONY: go-test go-test: vendor go test -v ./... | gex cgt diff --git a/cmd/add/add.go b/cmd/add/add.go new file mode 100644 index 0000000..951ab35 --- /dev/null +++ b/cmd/add/add.go @@ -0,0 +1,20 @@ +package add + +import ( + "context" + + "github.com/rerost/es-cli/cmd/add/alias" + "github.com/rerost/es-cli/domain" + "github.com/spf13/cobra" +) + +func NewAddCommand(ctx context.Context, ind domain.Index, alis domain.Alias) *cobra.Command { + cmd := &cobra.Command{ + Use: "add", + Short: "Add elasitcsearch resources", + Args: cobra.ExactArgs(1), + } + + cmd.AddCommand(alias.NewAliasCommand(ctx, alis)) // FIXME Cmd -> Command + return cmd +} diff --git a/cmd/add/alias/alias.go b/cmd/add/alias/alias.go new file mode 100644 index 0000000..15bd538 --- /dev/null +++ b/cmd/add/alias/alias.go @@ -0,0 +1,23 @@ +package alias + +import ( + "context" + + "github.com/rerost/es-cli/domain" + "github.com/spf13/cobra" + "github.com/srvc/fail" +) + +func NewAliasCommand(ctx context.Context, alis domain.Alias) *cobra.Command { + cmd := &cobra.Command{ + Use: "alias", + Short: "add alias", + Args: cobra.MinimumNArgs(2), + RunE: func(_ *cobra.Command, args []string) error { + err := alis.Add(ctx, args[0], args[1:]...) + return fail.Wrap(err) + }, + } + + return cmd +} diff --git a/cmd/cmd.go b/cmd/cmd.go new file mode 100644 index 0000000..e79cb3b --- /dev/null +++ b/cmd/cmd.go @@ -0,0 +1,66 @@ +package cmd + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/rerost/es-cli/config" + "github.com/spf13/pflag" + "github.com/spf13/viper" + "github.com/srvc/fail" + "go.uber.org/zap" +) + +func Run() error { + ctx := context.TODO() + + cfg, err := NewConfig() + if err != nil { + return fail.Wrap(err) + } + + l, err := InitializeLogger(cfg) + if err != nil { + return fail.Wrap(err) + } + defer l.Sync() + + zap.ReplaceGlobals(l) + + cfgJSON, err := json.Marshal(cfg) + if err != nil { + return fail.Wrap(err) + } + zap.L().Debug("config", zap.String("config", string(cfgJSON))) + + cmd, err := InitializeCmd(ctx, cfg) + if err != nil { + return fail.Wrap(err) + } + + if err := cmd.Execute(); err != nil { + zap.L().Debug("error", zap.String("stack trace", fmt.Sprintf("%#v\n", err))) + return fail.Wrap(err) + } + return nil +} + +func NewConfig() (config.Config, error) { + pflag.StringP("host", "", "http://localhost:9200", "ES hostname") + pflag.StringP("type", "t", "_doc", "ES type") + pflag.StringP("user", "u", "", "ES basic auth user") + pflag.StringP("pass", "p", "", "ES basic auth password") + pflag.BoolP("insecure", "k", false, "Same as curl insecure") + pflag.StringP("namespace", "n", "localhost", "Specify config in es-cli") // For conf. Think alter position + + pflag.BoolP("verbose", "v", false, "") + pflag.BoolP("debug", "d", false, "") + + viper.BindPFlags(pflag.CommandLine) + + var cfg config.Config + pflag.Parse() + err := viper.Unmarshal(&cfg) + return cfg, fail.Wrap(err) +} diff --git a/cmd/copy/copy.go b/cmd/copy/copy.go new file mode 100644 index 0000000..edb523f --- /dev/null +++ b/cmd/copy/copy.go @@ -0,0 +1,20 @@ +package copy + +import ( + "context" + + copy "github.com/rerost/es-cli/cmd/copy/index" + "github.com/rerost/es-cli/domain" + "github.com/spf13/cobra" +) + +func NewCopyCommand(ctx context.Context, ind domain.Index) *cobra.Command { + cmd := &cobra.Command{ + Use: "copy", + Short: "Copy elasticsearch resources", + Args: cobra.ExactArgs(2), + } + + cmd.AddCommand(copy.NewIndexCmd(ctx, ind)) + return cmd +} diff --git a/cmd/copy/index/index.go b/cmd/copy/index/index.go new file mode 100644 index 0000000..6f0e594 --- /dev/null +++ b/cmd/copy/index/index.go @@ -0,0 +1,26 @@ +package copy + +import ( + "context" + + "github.com/rerost/es-cli/domain" + "github.com/spf13/cobra" + "github.com/srvc/fail" +) + +func NewIndexCmd(ctx context.Context, ind domain.Index) *cobra.Command { + cmd := &cobra.Command{ + Use: "index", + Short: "list up index", + Args: cobra.ExactArgs(2), + RunE: func(_ *cobra.Command, args []string) error { + err := ind.Copy(ctx, args[0], args[1]) + if err != nil { + return fail.Wrap(err) + } + return nil + }, + } + + return cmd +} diff --git a/cmd/count/count.go b/cmd/count/count.go new file mode 100644 index 0000000..5c35858 --- /dev/null +++ b/cmd/count/count.go @@ -0,0 +1,20 @@ +package count + +import ( + "context" + + count "github.com/rerost/es-cli/cmd/count/index" + "github.com/rerost/es-cli/domain" + "github.com/spf13/cobra" +) + +func NewCountCommand(ctx context.Context, ind domain.Index) *cobra.Command { + cmd := &cobra.Command{ + Use: "count", + Short: "Count elasticsearch resources", + Args: cobra.ExactArgs(1), + } + + cmd.AddCommand(count.NewIndexCmd(ctx, ind)) + return cmd +} diff --git a/cmd/count/index/index.go b/cmd/count/index/index.go new file mode 100644 index 0000000..bdf161a --- /dev/null +++ b/cmd/count/index/index.go @@ -0,0 +1,29 @@ +package count + +import ( + "context" + "fmt" + "os" + + "github.com/rerost/es-cli/domain" + "github.com/spf13/cobra" + "github.com/srvc/fail" +) + +func NewIndexCmd(ctx context.Context, ind domain.Index) *cobra.Command { + cmd := &cobra.Command{ + Use: "index", + Short: "count index", + Args: cobra.ExactArgs(1), + RunE: func(_ *cobra.Command, args []string) error { + cnt, err := ind.Count(ctx, args[0]) + if err != nil { + return fail.Wrap(err) + } + fmt.Fprintln(os.Stdout, cnt) + return nil + }, + } + + return cmd +} diff --git a/cmd/create/create.go b/cmd/create/create.go new file mode 100644 index 0000000..b34b4a4 --- /dev/null +++ b/cmd/create/create.go @@ -0,0 +1,20 @@ +package create + +import ( + "context" + + create "github.com/rerost/es-cli/cmd/create/index" + "github.com/rerost/es-cli/domain" + "github.com/spf13/cobra" +) + +func NewCreateCommand(ctx context.Context, ind domain.Index) *cobra.Command { + cmd := &cobra.Command{ + Use: "create", + Short: "Create elasticsearch resources", + Args: cobra.ExactArgs(2), + } + + cmd.AddCommand(create.NewIndexCmd(ctx, ind)) + return cmd +} diff --git a/cmd/create/index/index.go b/cmd/create/index/index.go new file mode 100644 index 0000000..a9afdaa --- /dev/null +++ b/cmd/create/index/index.go @@ -0,0 +1,41 @@ +package create + +import ( + "context" + "io" + "os" + + "github.com/rerost/es-cli/domain" + "github.com/spf13/cobra" + "github.com/srvc/fail" +) + +func NewIndexCmd(ctx context.Context, ind domain.Index) *cobra.Command { + cmd := &cobra.Command{ + Use: "index", + Short: "create index", + Args: cobra.RangeArgs(1, 2), + RunE: func(_ *cobra.Command, args []string) error { + var fp io.Reader + switch len(args) { + case 1: + fp = os.Stdin + case 2: + // Read file from filename + fileName := args[1] + var err error + fp, err = os.Open(fileName) + if err != nil { + return fail.Wrap(err) + } + } + err := ind.Create(ctx, args[0], fp) + if err != nil { + return fail.Wrap(err) + } + return nil + }, + } + + return cmd +} diff --git a/cmd/delete/delete.go b/cmd/delete/delete.go new file mode 100644 index 0000000..a04a47a --- /dev/null +++ b/cmd/delete/delete.go @@ -0,0 +1,20 @@ +package delete + +import ( + "context" + + delete "github.com/rerost/es-cli/cmd/delete/index" + "github.com/rerost/es-cli/domain" + "github.com/spf13/cobra" +) + +func NewDeleteCommand(ctx context.Context, ind domain.Index) *cobra.Command { + cmd := &cobra.Command{ + Use: "delete", + Short: "Delete elasticsearch resources", + Args: cobra.ExactArgs(1), + } + + cmd.AddCommand(delete.NewIndexCmd(ctx, ind)) + return cmd +} diff --git a/cmd/delete/index/index.go b/cmd/delete/index/index.go new file mode 100644 index 0000000..b9f614c --- /dev/null +++ b/cmd/delete/index/index.go @@ -0,0 +1,26 @@ +package delete + +import ( + "context" + + "github.com/rerost/es-cli/domain" + "github.com/spf13/cobra" + "github.com/srvc/fail" +) + +func NewIndexCmd(ctx context.Context, ind domain.Index) *cobra.Command { + cmd := &cobra.Command{ + Use: "index", + Short: "delete index", + Args: cobra.ExactArgs(1), + RunE: func(_ *cobra.Command, args []string) error { + err := ind.Delete(ctx, args[0]) + if err != nil { + return fail.Wrap(err) + } + return nil + }, + } + + return cmd +} diff --git a/cmd/dump/dump.go b/cmd/dump/dump.go new file mode 100644 index 0000000..45535e8 --- /dev/null +++ b/cmd/dump/dump.go @@ -0,0 +1,20 @@ +package dump + +import ( + "context" + + dump "github.com/rerost/es-cli/cmd/dump/index" + "github.com/rerost/es-cli/domain" + "github.com/spf13/cobra" +) + +func NewDumpCommand(ctx context.Context, ind domain.Index) *cobra.Command { + cmd := &cobra.Command{ + Use: "dump", + Short: "Delete elasticsearch resources", + Args: cobra.ExactArgs(2), + } + + cmd.AddCommand(dump.NewIndexCmd(ctx, ind)) + return cmd +} diff --git a/cmd/dump/index/index.go b/cmd/dump/index/index.go new file mode 100644 index 0000000..ea04e70 --- /dev/null +++ b/cmd/dump/index/index.go @@ -0,0 +1,41 @@ +package dump + +import ( + "context" + "io" + "os" + + "github.com/rerost/es-cli/domain" + "github.com/spf13/cobra" + "github.com/srvc/fail" +) + +func NewIndexCmd(ctx context.Context, ind domain.Index) *cobra.Command { + cmd := &cobra.Command{ + Use: "index", + Short: "dump index", + Args: cobra.RangeArgs(1, 2), + RunE: func(_ *cobra.Command, args []string) error { + var fp io.Writer + switch len(args) { + case 1: + fp = os.Stdout + case 2: + // Read file from filename + fileName := args[1] + var err error + fp, err = os.Open(fileName) + if err != nil { + return fail.Wrap(err) + } + } + err := ind.Dump(ctx, args[0], fp) + if err != nil { + return fail.Wrap(err) + } + return nil + }, + } + + return cmd +} diff --git a/cmd/gen.go b/cmd/gen.go new file mode 100644 index 0000000..975bf31 --- /dev/null +++ b/cmd/gen.go @@ -0,0 +1,3 @@ +package cmd + +//go:generate wire diff --git a/cmd/get/detai/detail.go b/cmd/get/detai/detail.go new file mode 100644 index 0000000..10f7eeb --- /dev/null +++ b/cmd/get/detai/detail.go @@ -0,0 +1,31 @@ +package get + +import ( + "context" + "fmt" + "os" + + "github.com/rerost/es-cli/domain" + "github.com/spf13/cobra" + "github.com/srvc/fail" +) + +func NewDetailCmd(ctx context.Context, dtl domain.Detail) *cobra.Command { + cmd := &cobra.Command{ + Use: "detail", + Short: "get detail", + Args: cobra.ExactArgs(1), + RunE: func(_ *cobra.Command, args []string) error { + detail, err := dtl.Get(ctx, args[0]) + if err != nil { + return fail.Wrap(err) + } + + fmt.Fprintf(os.Stdout, detail) + + return nil + }, + } + + return cmd +} diff --git a/cmd/get/get.go b/cmd/get/get.go new file mode 100644 index 0000000..be85281 --- /dev/null +++ b/cmd/get/get.go @@ -0,0 +1,20 @@ +package get + +import ( + "context" + + get "github.com/rerost/es-cli/cmd/get/detai" + "github.com/rerost/es-cli/domain" + "github.com/spf13/cobra" +) + +func NewGetCommand(ctx context.Context, dtl domain.Detail) *cobra.Command { + cmd := &cobra.Command{ + Use: "get", + Short: "Get up elasitcsearch resources", + Args: cobra.ExactArgs(1), + } + + cmd.AddCommand(get.NewDetailCmd(ctx, dtl)) + return cmd +} diff --git a/cmd/list/alias/alias.go b/cmd/list/alias/alias.go new file mode 100644 index 0000000..c8144a0 --- /dev/null +++ b/cmd/list/alias/alias.go @@ -0,0 +1,29 @@ +package alias + +import ( + "context" + "fmt" + "os" + + "github.com/rerost/es-cli/domain" + "github.com/spf13/cobra" + "github.com/srvc/fail" +) + +func NewAliasCommand(ctx context.Context, alis domain.Alias) *cobra.Command { + cmd := &cobra.Command{ + Use: "alias", + Short: "list up index in alias", + Args: cobra.ExactArgs(1), + RunE: func(_ *cobra.Command, args []string) error { + indices, err := alis.List(ctx, args[0]) + if err != nil { + return fail.Wrap(err) + } + fmt.Fprintln(os.Stdout, indices.String()) + return nil + }, + } + + return cmd +} diff --git a/cmd/list/index/index.go b/cmd/list/index/index.go new file mode 100644 index 0000000..0bd1c84 --- /dev/null +++ b/cmd/list/index/index.go @@ -0,0 +1,29 @@ +package list + +import ( + "context" + "fmt" + "os" + + "github.com/rerost/es-cli/domain" + "github.com/spf13/cobra" + "github.com/srvc/fail" +) + +func NewIndexCmd(ctx context.Context, ind domain.Index) *cobra.Command { + cmd := &cobra.Command{ + Use: "index", + Short: "list up index", + Args: cobra.ExactArgs(0), + RunE: func(_ *cobra.Command, args []string) error { + indices, err := ind.List(ctx) + if err != nil { + return fail.Wrap(err) + } + fmt.Fprintln(os.Stdout, indices.String()) + return nil + }, + } + + return cmd +} diff --git a/cmd/list/list.go b/cmd/list/list.go new file mode 100644 index 0000000..751467d --- /dev/null +++ b/cmd/list/list.go @@ -0,0 +1,22 @@ +package list + +import ( + "context" + + alist "github.com/rerost/es-cli/cmd/list/alias" // FIXME pkg name + ilist "github.com/rerost/es-cli/cmd/list/index" + "github.com/rerost/es-cli/domain" + "github.com/spf13/cobra" +) + +func NewListCommand(ctx context.Context, ind domain.Index, alis domain.Alias) *cobra.Command { + cmd := &cobra.Command{ + Use: "list", + Short: "List up elasitcsearch resources", + Args: cobra.ExactArgs(1), + } + + cmd.AddCommand(ilist.NewIndexCmd(ctx, ind)) // TODO Cmd -> Command + cmd.AddCommand(alist.NewAliasCommand(ctx, alis)) + return cmd +} diff --git a/cmd/remove/alias/alias.go b/cmd/remove/alias/alias.go new file mode 100644 index 0000000..2c22c8d --- /dev/null +++ b/cmd/remove/alias/alias.go @@ -0,0 +1,23 @@ +package alias + +import ( + "context" + + "github.com/rerost/es-cli/domain" + "github.com/spf13/cobra" + "github.com/srvc/fail" +) + +func NewAliasCommand(ctx context.Context, alis domain.Alias) *cobra.Command { + cmd := &cobra.Command{ + Use: "alias", + Short: "unlink alias", + Args: cobra.MinimumNArgs(2), + RunE: func(_ *cobra.Command, args []string) error { + err := alis.Remove(ctx, args[0], args[1:]...) + return fail.Wrap(err) + }, + } + + return cmd +} diff --git a/cmd/remove/remove.go b/cmd/remove/remove.go new file mode 100644 index 0000000..9619913 --- /dev/null +++ b/cmd/remove/remove.go @@ -0,0 +1,20 @@ +package remove + +import ( + "context" + + "github.com/rerost/es-cli/cmd/remove/alias" + "github.com/rerost/es-cli/domain" + "github.com/spf13/cobra" +) + +func NewRemoveCommand(ctx context.Context, alis domain.Alias) *cobra.Command { + cmd := &cobra.Command{ + Use: "remove", + Short: "Remove elasitcsearch resources", + Args: cobra.ExactArgs(1), + } + + cmd.AddCommand(alias.NewAliasCommand(ctx, alis)) + return cmd +} diff --git a/cmd/restore/index/index.go b/cmd/restore/index/index.go new file mode 100644 index 0000000..36860d3 --- /dev/null +++ b/cmd/restore/index/index.go @@ -0,0 +1,41 @@ +package restore + +import ( + "context" + "io" + "os" + + "github.com/rerost/es-cli/domain" + "github.com/spf13/cobra" + "github.com/srvc/fail" +) + +func NewIndexCmd(ctx context.Context, ind domain.Index) *cobra.Command { + cmd := &cobra.Command{ + Use: "index", + Short: "restore index", + Args: cobra.RangeArgs(0, 1), + RunE: func(_ *cobra.Command, args []string) error { + var fp io.Reader + switch len(args) { + case 1: + fp = os.Stdin + case 2: + // Read file from filename + fileName := args[0] + var err error + fp, err = os.Open(fileName) + if err != nil { + return fail.Wrap(err) + } + } + err := ind.Restore(ctx, fp) + if err != nil { + return fail.Wrap(err) + } + return nil + }, + } + + return cmd +} diff --git a/cmd/restore/restore.go b/cmd/restore/restore.go new file mode 100644 index 0000000..56aed50 --- /dev/null +++ b/cmd/restore/restore.go @@ -0,0 +1,20 @@ +package restore + +import ( + "context" + + restore "github.com/rerost/es-cli/cmd/restore/index" + "github.com/rerost/es-cli/domain" + "github.com/spf13/cobra" +) + +func NewRestoreCommand(ctx context.Context, ind domain.Index) *cobra.Command { + cmd := &cobra.Command{ + Use: "restore", + Short: "Restore elasticsearch resources", + Args: cobra.ExactArgs(1), + } + + cmd.AddCommand(restore.NewIndexCmd(ctx, ind)) + return cmd +} diff --git a/cmd/root.go b/cmd/root.go new file mode 100644 index 0000000..afa1e4d --- /dev/null +++ b/cmd/root.go @@ -0,0 +1,47 @@ +package cmd + +import ( + "context" + + "github.com/rerost/es-cli/cmd/add" + "github.com/rerost/es-cli/cmd/copy" + "github.com/rerost/es-cli/cmd/count" + "github.com/rerost/es-cli/cmd/create" + "github.com/rerost/es-cli/cmd/delete" + "github.com/rerost/es-cli/cmd/dump" + "github.com/rerost/es-cli/cmd/get" + "github.com/rerost/es-cli/cmd/list" + "github.com/rerost/es-cli/cmd/remove" + "github.com/rerost/es-cli/cmd/restore" + "github.com/rerost/es-cli/cmd/update" + "github.com/rerost/es-cli/domain" + "github.com/spf13/cobra" +) + +func NewCmdRoot( + ctx context.Context, + ind domain.Index, + dtl domain.Detail, + alis domain.Alias, +) *cobra.Command { + cmd := &cobra.Command{ + Use: "es-cli", + Short: "Elasticsearch control tool", + } + + cmd.AddCommand( + add.NewAddCommand(ctx, ind, alis), + list.NewListCommand(ctx, ind, alis), + copy.NewCopyCommand(ctx, ind), + count.NewCountCommand(ctx, ind), + create.NewCreateCommand(ctx, ind), + delete.NewDeleteCommand(ctx, ind), + dump.NewDumpCommand(ctx, ind), + restore.NewRestoreCommand(ctx, ind), + get.NewGetCommand(ctx, dtl), + update.NewUpdateCommand(ctx, dtl), + remove.NewRemoveCommand(ctx, alis), + ) + + return cmd +} diff --git a/cmd/update/detail/detail.go b/cmd/update/detail/detail.go new file mode 100644 index 0000000..3af4ac4 --- /dev/null +++ b/cmd/update/detail/detail.go @@ -0,0 +1,42 @@ +package update + +import ( + "context" + "io" + "os" + + "github.com/rerost/es-cli/domain" + "github.com/spf13/cobra" + "github.com/srvc/fail" +) + +func NewDetailCmd(ctx context.Context, dtl domain.Detail) *cobra.Command { + cmd := &cobra.Command{ + Use: "detail", + Short: "update detail", + Args: cobra.RangeArgs(1, 2), + RunE: func(_ *cobra.Command, args []string) error { + var detailFp io.Reader + + switch len(args) { + case 1: + detailFp = os.Stdin + case 2: + var err error + detailFp, err = os.Open(args[1]) + if err != nil { + return fail.Wrap(err) + } + } + + err := dtl.Update(ctx, args[0], detailFp) + if err != nil { + return fail.Wrap(err) + } + + return nil + }, + } + + return cmd +} diff --git a/cmd/update/update.go b/cmd/update/update.go new file mode 100644 index 0000000..053ec4d --- /dev/null +++ b/cmd/update/update.go @@ -0,0 +1,20 @@ +package update + +import ( + "context" + + update "github.com/rerost/es-cli/cmd/update/detail" + "github.com/rerost/es-cli/domain" + "github.com/spf13/cobra" +) + +func NewUpdateCommand(ctx context.Context, dtl domain.Detail) *cobra.Command { + cmd := &cobra.Command{ + Use: "update", + Short: "Update up elasitcsearch resources", + Args: cobra.ExactArgs(1), + } + + cmd.AddCommand(update.NewDetailCmd(ctx, dtl)) + return cmd +} diff --git a/cmd/wire.go b/cmd/wire.go new file mode 100644 index 0000000..3906fee --- /dev/null +++ b/cmd/wire.go @@ -0,0 +1,26 @@ +//+build wireinject + +package cmd + +import ( + "context" + + "github.com/google/wire" + "github.com/rerost/es-cli/config" + "github.com/rerost/es-cli/domain" + "github.com/rerost/es-cli/infra/es" + "github.com/rerost/es-cli/infra/http" + "github.com/rerost/es-cli/infra/logger" + "github.com/spf13/cobra" + "go.uber.org/zap" +) + +func InitializeCmd(ctx context.Context, cfg config.Config) (*cobra.Command, error) { + wire.Build(NewCmdRoot, es.NewBaseClient, http.NewClient, domain.NewIndex, domain.NewDetail, domain.NewAlias) + return &cobra.Command{}, nil +} + +func InitializeLogger(cfg config.Config) (*zap.Logger, error) { + wire.Build(logger.NewLogger) + return &zap.Logger{}, nil +} diff --git a/cmd/wire_gen.go b/cmd/wire_gen.go new file mode 100644 index 0000000..9ced337 --- /dev/null +++ b/cmd/wire_gen.go @@ -0,0 +1,40 @@ +// Code generated by Wire. DO NOT EDIT. + +//go:generate wire +//+build !wireinject + +package cmd + +import ( + "context" + "github.com/rerost/es-cli/config" + "github.com/rerost/es-cli/domain" + "github.com/rerost/es-cli/infra/es" + "github.com/rerost/es-cli/infra/http" + "github.com/rerost/es-cli/infra/logger" + "github.com/spf13/cobra" + "go.uber.org/zap" +) + +// Injectors from wire.go: + +func InitializeCmd(ctx context.Context, cfg config.Config) (*cobra.Command, error) { + client := http.NewClient(cfg) + baseClient, err := es.NewBaseClient(cfg, client) + if err != nil { + return nil, err + } + index := domain.NewIndex(baseClient) + detail := domain.NewDetail(baseClient, index) + alias := domain.NewAlias(baseClient) + command := NewCmdRoot(ctx, index, detail, alias) + return command, nil +} + +func InitializeLogger(cfg config.Config) (*zap.Logger, error) { + zapLogger, err := logger.NewLogger(cfg) + if err != nil { + return nil, err + } + return zapLogger, nil +} diff --git a/config/config.go b/config/config.go index 5bd3625..2fbb4fe 100644 --- a/config/config.go +++ b/config/config.go @@ -5,15 +5,16 @@ import ( "fmt" "github.com/srvc/fail" - "gopkg.in/guregu/null.v3" ) type Config struct { - Host string `json:"host"` - Type string `json:"type"` - User string `json:"user"` - Pass string `json:"pass"` - Insecure null.Bool `json:"insecure"` // Use null.Bool for overwrite. + Host string `json:"host"` + Type string `json:"type"` + User string `json:"user"` + Pass string `json:"pass"` + Insecure bool `json:"insecure"` // Use null.Bool for overwrite. + Verbose bool `json:"verbose"` + Debug bool `json:"debug"` } func DefaultConfig() Config { @@ -75,7 +76,7 @@ func Overwrite(cfgOrg, cfgOverwrite Config) Config { if p := cfgOverwrite.Pass; p != "" { cfgDst.Pass = cfgOverwrite.Pass } - if i := cfgOverwrite.Insecure; i.Valid { + if i := cfgOverwrite.Insecure; i { cfgDst.Insecure = i } diff --git a/domain/alias.go b/domain/alias.go new file mode 100644 index 0000000..0a7b334 --- /dev/null +++ b/domain/alias.go @@ -0,0 +1,43 @@ +package domain + +import ( + "context" + + "github.com/rerost/es-cli/infra/es" + "github.com/srvc/fail" +) + +type Alias interface { + Add(ctx context.Context, aliasName string, indexNames ...string) error + Remove(ctx context.Context, aliasName string, indexNames ...string) error + // List all index in alias + List(ctx context.Context, aliasName string) (es.Indices, error) +} + +func NewAlias(esBaseClient es.BaseClient) Alias { + return aliasImpl{ + esBaseClient: esBaseClient, + } +} + +type aliasImpl struct { + esBaseClient es.BaseClient +} + +func (a aliasImpl) Add(ctx context.Context, aliasName string, indexNames ...string) error { + err := a.esBaseClient.AddAlias(ctx, aliasName, indexNames...) + return fail.Wrap(err) +} + +func (a aliasImpl) Remove(ctx context.Context, aliasName string, indexNames ...string) error { + err := a.esBaseClient.RemoveAlias(ctx, aliasName, indexNames...) + return fail.Wrap(err) +} + +func (a aliasImpl) List(ctx context.Context, aliasName string) (es.Indices, error) { + indices, err := a.esBaseClient.ListAlias(ctx, aliasName) + if err != nil { + return nil, fail.Wrap(err) + } + return indices, nil +} diff --git a/domain/detail.go b/domain/detail.go new file mode 100644 index 0000000..7c79570 --- /dev/null +++ b/domain/detail.go @@ -0,0 +1,75 @@ +package domain + +import ( + "context" + "io" + "io/ioutil" + "time" + + "github.com/rerost/es-cli/infra/es" + "github.com/srvc/fail" +) + +type Detail interface { + Get(ctx context.Context, index string) (string, error) + Update(ctx context.Context, aliasName string, detail io.Reader) error +} + +func NewDetail(esBaseClient es.BaseClient, indexDomain Index) Detail { + return detailImpl{ + esBaseClient: esBaseClient, + indexDomain: indexDomain, + } +} + +type detailImpl struct { + esBaseClient es.BaseClient + indexDomain Index +} + +func (d detailImpl) Get(ctx context.Context, index string) (string, error) { + detail, err := d.esBaseClient.DetailIndex(ctx, index) + return detail.String(), fail.Wrap(err) +} + +func (d detailImpl) Update(ctx context.Context, aliasName string, fp io.Reader) error { + // Thinking only alias case + // Rethink when index + // TODO think index case + + var detailJSON string + + body, err := ioutil.ReadAll(fp) + detailJSON = string(body) + + indices, err := d.esBaseClient.ListAlias(ctx, aliasName) + if err != nil { + return fail.Wrap(err) + } + + if len(indices) != 1 { + return fail.New("Support only 1-alias 1-index case") + } + + oldIndexName := indices[0].Name + + newIndexName := aliasName + time.Now().Format("_20060102_150405") + err = d.esBaseClient.CreateIndex(ctx, newIndexName, detailJSON) + if err != nil { + return fail.Wrap(err) + } + + err = d.indexDomain.Copy(ctx, oldIndexName, newIndexName) + if err != nil { + return fail.Wrap(err) + } + err = d.esBaseClient.SwapAlias(ctx, aliasName, oldIndexName, newIndexName) + if err != nil { + return fail.Wrap(err) + } + err = d.esBaseClient.DeleteIndex(ctx, oldIndexName) + if err != nil { + return fail.Wrap(err) + } + return nil +} diff --git a/domain/index.go b/domain/index.go new file mode 100644 index 0000000..cacd54e --- /dev/null +++ b/domain/index.go @@ -0,0 +1,239 @@ +package domain + +import ( + "bufio" + "context" + "encoding/json" + "fmt" + "io" + "io/ioutil" + "os" + "strings" + "time" + + "github.com/rerost/es-cli/infra/es" + "github.com/srvc/fail" + "go.uber.org/zap" +) + +const ( + BATCH_SIZE = 1000 + initBufSize = 65536 + maxBufSize = 65536000 +) + +type Index interface { + List(ctx context.Context) (es.Indices, error) + Create(ctx context.Context, indexName string, mapping io.Reader) error + Delete(ctx context.Context, indexName string) error + Copy(ctx context.Context, srcIndex, destIndex string) error + Count(ctx context.Context, indexName string) (int64, error) + Dump(ctx context.Context, indexName string, fp io.Writer) error + Restore(ctx context.Context, fp io.Reader) error +} + +func NewIndex(esBaseClient es.BaseClient) Index { + return indexImpl{ + esBaseClient: esBaseClient, + } +} + +type indexImpl struct { + esBaseClient es.BaseClient +} + +func (i indexImpl) List(ctx context.Context) (es.Indices, error) { + return i.esBaseClient.ListIndex(ctx) +} + +func (i indexImpl) Create(ctx context.Context, indexName string, mapping io.Reader) error { + b, err := ioutil.ReadAll(mapping) + if err != nil { + return fail.Wrap(err) + } + + err = i.esBaseClient.CreateIndex(ctx, indexName, string(b)) + return fail.Wrap(err) +} + +func (i indexImpl) Delete(ctx context.Context, indexName string) error { + err := i.esBaseClient.DeleteIndex(ctx, indexName) + return fail.Wrap(err) +} + +func (i indexImpl) Copy(ctx context.Context, srcIndex, destIndex string) error { + { + indices, err := i.esBaseClient.ListIndex(ctx) + if err != nil { + return fail.Wrap(err) + } + var srcExists bool + var destExists bool + + zap.L().Debug( + "Already exists index", + zap.String("indicies", indices.String()), + ) + // TODO Add test + for _, index := range indices { + zap.L().Debug( + "Checking", + zap.String("source index", srcIndex), + zap.String("destination index", destIndex), + zap.String("checking index", index.String()), + ) + if index.String() == srcIndex { + srcExists = true + } + if index.String() == destIndex { + destExists = true + } + } + + if !srcExists { + return fail.Wrap(fail.New("Source index is not found"), fail.WithParam("index", srcIndex)) + } + if !destExists { + return fail.Wrap(fail.New("Destination index is not found"), fail.WithParam("index", destIndex)) + } + } + task, err := i.esBaseClient.CopyIndex(ctx, srcIndex, destIndex) + + if err != nil { + return fail.Wrap(err) + } + + fmt.Fprintf(os.Stdout, "TaskID is %s\n", task.ID) + zap.L().Debug("Start task", zap.String("task_id: ", task.ID)) + + for try := 1; ; try++ { + // Back off + wait := time.Second * time.Duration(try*try) + time.Sleep(wait) + zap.L().Debug("Waiting for complete copy", zap.Duration("waited(s)", wait)) + task, err := i.esBaseClient.GetTask(ctx, task.ID) + + if err != nil { + return fail.Wrap(err) + } + + if task.Complete == true { + break + } + } + srcIndexCount, err := i.esBaseClient.CountIndex(ctx, srcIndex) + if err != nil { + return fail.Wrap(err) + } + dstIndexCount, err := i.esBaseClient.CountIndex(ctx, destIndex) + if err != nil { + return fail.Wrap(err) + } + if srcIndexCount.Num != dstIndexCount.Num { + return fail.Wrap( + fail.New(fmt.Sprintf("Copy is faild. Prease delete index %s Not match document count src: %d, dst: %d", destIndex, srcIndexCount.Num, dstIndexCount.Num)), + fail.WithCode("Invalid arguments"), + ) + } + zap.L().Info("Done") + + return nil +} + +func (i indexImpl) Count(ctx context.Context, indexName string) (int64, error) { + c, err := i.esBaseClient.CountIndex(ctx, indexName) + if err != nil { + return 0, fail.Wrap(err) + } + + return c.Num, nil +} + +func (i indexImpl) Dump(ctx context.Context, indexName string, detailFile io.Writer) error { + detail, err := i.esBaseClient.DetailIndex(ctx, indexName) + if err != nil { + return fail.Wrap(err) + } + + _, err = detailFile.Write([]byte(detail.String())) + if err != nil { + return fail.Wrap(err) + } + + dumpFile, err := os.Create(fmt.Sprintf("./%s_dump.ndjson", indexName)) + if err != nil { + return fail.Wrap(err) + } + defer dumpFile.Close() + + lastID := "" + for { + query := fmt.Sprintf(`{"query": {"match_all": {}}, "size": %d, "sort": [{"_id": "desc"}]}`, BATCH_SIZE) + if lastID != "" { + zap.L().Info("Copying search after", zap.String("ID", lastID)) + query = fmt.Sprintf(`{"query": {"match_all": {}}, "size": %d, "sort": [{"_id": "desc"}], "search_after": ["%s"]}`, BATCH_SIZE, lastID) + } + searchResult, err := i.esBaseClient.SearchIndex(ctx, indexName, query) + + if err != nil { + return fail.Wrap(err) + } + + for _, hit := range searchResult.Hits.Hits { + metaData := fmt.Sprintf(`{ "index" : { "_index": "%s", "_type": "%s", "_id": "%s" }}`, hit.Index, hit.Type, hit.ID) + queryBytes, err := json.Marshal(hit.Source) + if err != nil { + return fail.Wrap(err) + } + _, err = dumpFile.Write([]byte(metaData + "\n" + string(queryBytes) + "\n")) + if err != nil { + return fail.Wrap(err) + } + } + + hitsSize := len(searchResult.Hits.Hits) + if hitsSize == 0 { + break + } + + lastID = searchResult.Hits.Hits[hitsSize-1].ID + } + + return nil +} + +func (i indexImpl) Restore(ctx context.Context, fp io.Reader) error { + scanner := bufio.NewScanner(fp) + + scanner.Split(bufio.ScanLines) + { + buf := make([]byte, initBufSize) + scanner.Buffer(buf, maxBufSize) + } + + // twice, because metadata + document pair + buf := make([]string, BATCH_SIZE*2, BATCH_SIZE*2) + iter := 0 + batchTime := 1 + for scanner.Scan() { + buf[iter] = scanner.Text() + + if iter == len(buf)-1 { + zap.L().Debug("Copied", zap.Int("size", len(buf)/2*batchTime)) + err := i.esBaseClient.BulkIndex(ctx, strings.Join(buf, "\n")+"\n") + if err != nil { + return fail.Wrap(err) + } + + buf = make([]string, len(buf), len(buf)) + iter = 0 + batchTime++ + } else { + iter++ + } + } + if err := scanner.Err(); err != nil { + return fail.Wrap(err) + } + return nil +} diff --git a/go.mod b/go.mod index 372251b..1e3239c 100644 --- a/go.mod +++ b/go.mod @@ -4,25 +4,33 @@ go 1.12 require ( github.com/Songmu/retry v0.0.0-20181014062827-902aa877ec14 // indirect - github.com/google/go-cmp v0.2.0 + github.com/golang/protobuf v1.3.1 // indirect + github.com/google/go-cmp v0.3.0 + github.com/google/wire v0.2.2 github.com/hashicorp/go-version v1.0.0 // indirect github.com/izumin5210/cgt v0.0.0-20181103063432-ac2ef913eb51 github.com/izumin5210/gex v0.4.5 // indirect github.com/mattn/go-colorable v0.1.0 // indirect github.com/mattn/go-isatty v0.0.4 // indirect - github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db + github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect + github.com/moul/http2curl v1.0.0 github.com/onsi/gomega v1.5.0 // indirect + github.com/spf13/cobra v0.0.5 + github.com/spf13/pflag v1.0.3 + github.com/spf13/viper v1.3.2 github.com/srvc/fail v3.1.0+incompatible github.com/stretchr/testify v1.3.0 // indirect github.com/tcnksm/ghr v0.0.0-20181005104214-1dabd986f323 github.com/tcnksm/go-gitconfig v0.0.0-20150505151006-6411ba19847f // indirect github.com/tcnksm/go-latest v0.0.0-20170313132115-e3007ae9052e // indirect - github.com/urfave/cli v1.20.0 - golang.org/x/crypto v0.0.0-20181106171534-e4dc69e5b2fd // indirect - golang.org/x/net v0.0.0-20181108082009-03003ca0c849 // indirect - golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288 // indirect - golang.org/x/sync v0.0.0-20181108010431-42b317875d0f // indirect + go.uber.org/atomic v1.4.0 // indirect + go.uber.org/multierr v1.1.0 // indirect + go.uber.org/zap v1.10.0 + golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c // indirect + golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 // indirect golang.org/x/sys v0.0.0-20190614160838-b47fdc937951 // indirect - google.golang.org/appengine v1.3.0 // indirect + golang.org/x/text v0.3.2 // indirect + golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c // indirect + google.golang.org/appengine v1.5.0 // indirect gopkg.in/guregu/null.v3 v3.4.0 ) diff --git a/go.sum b/go.sum index bf7a9dc..177e4a7 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,13 @@ +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/Songmu/retry v0.0.0-20181014062827-902aa877ec14 h1:jGKn6KhODQv42rqWWwJxtw0DAYOsd8mZvejaV1sXrJQ= github.com/Songmu/retry v0.0.0-20181014062827-902aa877ec14/go.mod h1:7sXIW7eseB9fq0FUvigRcQMVLR9tuHI0Scok+rkpAuA= +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/bradleyjkemp/cupaloy v2.2.0+incompatible/go.mod h1:Au1Xw1sgaJ5iSFktEhYsS0dbQiS1B0/XMXl+42y9Ilk= +github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -9,18 +16,28 @@ github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY= github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= +github.com/google/wire v0.2.2 h1:fSIRzE/K12IaNgV6X0173X/oLrTwHKRiMcFZhiDrN3s= +github.com/google/wire v0.2.2/go.mod h1:7FHVg6mFpFQrjeUZrm+BaD50N5jnDKm50uVPTpyYOmU= github.com/hashicorp/go-version v1.0.0 h1:21MVWPKDphxa7ineQQTrCU5brh7OuVVAzGOCnnCPtE8= github.com/hashicorp/go-version v1.0.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +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/haya14busa/errorformat v0.0.0-20180607161917-689b7d67b7a8/go.mod h1:TNvdwGsVM9pBShG9giP++XhdzBWSSKnvNAO9K7ERnyw= github.com/haya14busa/reviewdog v0.0.0-20180723114510-ffb00ef78fd3/go.mod h1:6S1pmGlj8cAOvGnz97vdbRPjFTZhHQ0NLSIka21vY8A= github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/izumin5210/cgt v0.0.0-20181103063432-ac2ef913eb51 h1:tRFwGJ+Qjqge7JG8t+/SdkP6hJsxebrNKZTOms2LHxI= github.com/izumin5210/cgt v0.0.0-20181103063432-ac2ef913eb51/go.mod h1:Hjovtk9gOx0RnMaMZDBhlRhSHrK9dEOmTdR0OGcijfc= github.com/izumin5210/gex v0.4.5 h1:qa9MWsGgRislHyNM98786YxolDgEbPP595Ajz/p7VXQ= @@ -28,30 +45,51 @@ github.com/izumin5210/gex v0.4.5/go.mod h1:a3mEUh4AHD05YgcgPnLqyScKTqG39Ap5wHLQZ github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e h1:9MlwzLdW7QSDrhDjFlsEYmxpFyIoXmYRon3dt0io31k= github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= +github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY= +github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/mattn/go-colorable v0.1.0 h1:v2XXALHHh6zHfYTJ+cSkwtyffnaOyR1MXaA91mTrb8o= github.com/mattn/go-colorable v0.1.0/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-isatty v0.0.4 h1:bnP0vzxcAdeI1zdubAl5PjU6zsERjGZb7raWodagDYs= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= -github.com/mitchellh/colorstring v0.0.0-20150917214807-8631ce90f286 h1:KHyL+3mQOF9sPfs26lsefckcFNDcIZtiACQiECzIUkw= -github.com/mitchellh/colorstring v0.0.0-20150917214807-8631ce90f286/go.mod h1:l0dey0ia/Uv7NcFFVbCLtqEBQbrT4OCwCSKTEv6enCw= +github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db h1:62I3jR2EmQ4l5rM/4FEfDWcRD+abF5XlKShorW5LRoQ= github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db/go.mod h1:l0dey0ia/Uv7NcFFVbCLtqEBQbrT4OCwCSKTEv6enCw= +github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/moul/http2curl v1.0.0 h1:dRMWoAtb+ePxMlLkrCbAqh4TlPHXvoGUSQ323/9Zahs= +github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ= github.com/onsi/ginkgo v1.6.0 h1:Ix8l273rp3QzYgXSR+c8d1fTG7UPgYkOSELPhiY/YGw= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/gomega v1.5.0 h1:izbySO9zDPmjJ8rDjLvkA2zJHIo+HkYXHnf7eN7SSyo= github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +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/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/spf13/afero v1.1.1 h1:Lt3ihYMlE+lreX1GS4Qw4ZsNpYQLxIXKBTEOXm3nt6I= +github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/spf13/afero v1.1.1/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/pflag v1.0.2 h1:Fy0orTDgHdbnzHcsOgfCN4LtHf0ec3wwtiwJqwvf3Gc= +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.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8= +github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v0.0.5 h1:f0B+LkLX6DtmRH1isoNA9VTtNUK9K8xYd28JNNfOv/s= +github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= +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.3.2 h1:VUFqw5KcqRf7i70GOzW7N+Q7+gxVBkSSqiXB12+JQ4M= +github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/srvc/fail v3.1.0+incompatible h1:zsUTdpsvSXIXuRdVQqjnUb3ncUL0nugt3mtEnjQcHx0= github.com/srvc/fail v3.1.0+incompatible/go.mod h1:O6qL3O5sUrJlIh2oGAZ5J9RKGGae3D1U6jMGyzM6RK4= github.com/srvc/wraperr v0.1.1/go.mod h1:nAsw6YoIOEyO1zJqdS0MM1UyDbREVrcOwByUrguMjSU= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/tcnksm/ghr v0.0.0-20181005104214-1dabd986f323 h1:c1zVOIK8AKS2C568oB1bwC4Oj6Cq6VVOR6iHZBqfVOU= @@ -60,34 +98,60 @@ github.com/tcnksm/go-gitconfig v0.0.0-20150505151006-6411ba19847f h1:99nosetRYX8 github.com/tcnksm/go-gitconfig v0.0.0-20150505151006-6411ba19847f/go.mod h1:/8EhP4H7oJZdIPyT+/UIsG87kTzrzM4UsLGSItWYCpE= github.com/tcnksm/go-latest v0.0.0-20170313132115-e3007ae9052e h1:IWllFTiDjjLIf2oeKxpIUmtiDV5sn71VgeQgg6vcE7k= github.com/tcnksm/go-latest v0.0.0-20170313132115-e3007ae9052e/go.mod h1:d7u6HkTYKSv5m6MCKkOQlHwaShTMl3HjqSGW3XtVhXM= -github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw= -github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/xanzy/go-gitlab v0.11.1/go.mod h1:CRKHkvFWNU6C3AEfqLWjnCNnAs4nj8Zk95rX2S3X6Mw= +github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU= +go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181106171534-e4dc69e5b2fd h1:VtIkGDhk0ph3t+THbvXHfMZ8QHgsBO39Nh52+74pq7w= -golang.org/x/crypto v0.0.0-20181106171534-e4dc69e5b2fd/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190422183909-d864b10871cd h1:sMHc2rZHuzQmrbVoSpt9HgerkXPyIeCSO6k0zUMGfFk= +golang.org/x/crypto v0.0.0-20190422183909-d864b10871cd/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180926154720-4dfa2610cdf3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181108082009-03003ca0c849 h1:FSqE2GGG7wzsYUsWiQ8MZrvEd1EOyU3NCF0AW3Wtltg= -golang.org/x/net v0.0.0-20181108082009-03003ca0c849/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190420063019-afa5a82059c6 h1:HdqqaWmYAUI7/dmByKKEw+yxDksGSo+9GjkUc9Zp34E= +golang.org/x/net v0.0.0-20190420063019-afa5a82059c6/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c h1:uOCk1iQW6Vc18bnC13MfzScl+wdKBmM9Y9kU7Z83/lw= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288 h1:JIqe8uIcRBHXDQVvZtHwp80ai3Lw3IJAeJEs55Dc1W0= -golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f h1:Bl/8QSvNqXvPGPGXa2z5xUTmV7VDcZyvRZ+QQXkXTZQ= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181031143558-9b800f95dbbc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190614160838-b47fdc937951 h1:ZUgGZ7PSkne6oY+VgAvayrB16owfm9/DKAtgWubzgzU= golang.org/x/sys v0.0.0-20190614160838-b47fdc937951/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/tools v0.0.0-20180904205237-0aa4b8830f48/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190422233926-fe54fb35175b h1:NVD8gBK33xpdqCaZVVtd6OFJp+3dxkXuz7+U7KaVN6s= +golang.org/x/tools v0.0.0-20190422233926-fe54fb35175b/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c h1:97SnQk1GYRXJgvwZ8fadnxDOWfKvkNQHH3CtZntPSrM= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.3.0 h1:FBSsiFRMz3LBeXIomRnVzrQwSDj4ibvcRexLG0LZGQk= -google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0 h1:KxkO13IPW4Lslp2bz+KHP2E3gtFlrIGNThxkZQ3g+4c= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= @@ -98,5 +162,7 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkep gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= k8s.io/utils v0.0.0-20181011165025-cd6a8f44fe79 h1:2l1Z5VkVYHbrAAPW8UKGymkI6WAk14oFmVGXHwohUPk= k8s.io/utils v0.0.0-20181011165025-cd6a8f44fe79/go.mod h1:8k8uAuAQ0rXslZKaEWd0c3oVhZz7sSzSiPnVZayjIX0= diff --git a/infra/es/base_client.go b/infra/es/base_client.go index 7e0535f..526f2ac 100644 --- a/infra/es/base_client.go +++ b/infra/es/base_client.go @@ -9,8 +9,10 @@ import ( "net/http" "strings" + "github.com/moul/http2curl" "github.com/rerost/es-cli/config" "github.com/srvc/fail" + "go.uber.org/zap" ) type Index struct { @@ -172,6 +174,20 @@ func (client baseClientImp) httpRequest(ctx context.Context, method string, url request.SetBasicAuth(client.Config.User, client.Config.Pass) } + // Request log + { + c, err := http2curl.GetCurlCommand(request) + if err != nil { + zap.L().Debug( + "Failed to convert to curl", + zap.Error(err), + ) + } + zap.L().Debug( + "request", + zap.String("curl", c.String()), + ) + } response, err := client.HttpClient.Do(request) if err != nil { return nil, fail.Wrap(err) @@ -185,6 +201,15 @@ func (client baseClientImp) httpRequest(ctx context.Context, method string, url } defer response.Body.Close() + // Response log + { + zap.L().Debug( + "response", + zap.String("response status", string(response.Status)), + zap.String("response body", string(responseBody)), + ) + } + if errMsg, ok := responseMap["error"]; ok { return nil, fail.New(fmt.Sprintf("%v", errMsg)) } diff --git a/infra/es/base_client_test.go b/infra/es/base_client_test.go index 2ed1bad..92360d7 100644 --- a/infra/es/base_client_test.go +++ b/infra/es/base_client_test.go @@ -14,7 +14,6 @@ import ( func TestNewClient(t *testing.T) { t.Parallel() - ctx := context.Background() cfg := config.Config{ Host: "http://localhost:9200", Type: "_doc", diff --git a/infra/http/client.go b/infra/http/client.go new file mode 100644 index 0000000..143a282 --- /dev/null +++ b/infra/http/client.go @@ -0,0 +1,22 @@ +package http + +import ( + "crypto/tls" + nhttp "net/http" + + "github.com/rerost/es-cli/config" +) + +func NewClient(cfg config.Config) *nhttp.Client { + var httpClient *nhttp.Client + if cfg.Insecure { + tr := &nhttp.Transport{ + TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, + } + httpClient = &nhttp.Client{Transport: tr} + } else { + httpClient = new(nhttp.Client) + } + + return httpClient +} diff --git a/infra/logger/logger.go b/infra/logger/logger.go new file mode 100644 index 0000000..93543a0 --- /dev/null +++ b/infra/logger/logger.go @@ -0,0 +1,19 @@ +package logger + +import ( + "github.com/rerost/es-cli/config" + "github.com/srvc/fail" + "go.uber.org/zap" +) + +func NewLogger(cfg config.Config) (*zap.Logger, error) { + zcfg := zap.NewProductionConfig() + if cfg.Debug { + zcfg.Level = zap.NewAtomicLevelAt(zap.DebugLevel) + } + if cfg.Verbose { + zcfg.Level = zap.NewAtomicLevelAt(zap.InfoLevel) + } + l, err := zcfg.Build() + return l, fail.Wrap(err) +} diff --git a/main.go b/main.go index 15ff475..a5bdd9f 100644 --- a/main.go +++ b/main.go @@ -1,133 +1,15 @@ package main import ( - "context" - "crypto/tls" "fmt" - "io/ioutil" - "net/http" "os" - "github.com/rerost/es-cli/config" - "github.com/rerost/es-cli/executer" - "github.com/rerost/es-cli/infra/es" - "github.com/srvc/fail" - "github.com/urfave/cli" - "gopkg.in/guregu/null.v3" + "github.com/rerost/es-cli/cmd" ) func main() { - app := cli.NewApp() - - app.Name = "es-cli" - app.Usage = "TODO" - - app.Action = func(cliContext *cli.Context) error { - ctx := context.Background() - - cfg := config.DefaultConfig() - - // Check namespace - namespace := cliContext.String("namespace") - - // Local Config file - if f, err := ioutil.ReadFile(".escli.json"); err == nil { - if namespace == "" { - localCfg, err := config.LoadConfig(f) - if err != nil { - return fail.Wrap(err) - } - cfg = config.Overwrite(cfg, localCfg) - } else { - localCfg, err := config.LoadConfigWithNamespace(f, namespace) - if err != nil { - return fail.Wrap(err) - } - cfg = config.Overwrite(cfg, localCfg) - } - } - - // Params Config - paramsCfg := config.Config{ - Host: cliContext.String("host"), - Type: cliContext.String("type"), - User: cliContext.String("user"), - Pass: cliContext.String("pass"), - Insecure: null.BoolFrom(cliContext.Bool("insecure")), - } - cfg = config.Overwrite(cfg, paramsCfg) - - var httpClient *http.Client - if cfg.Insecure.Valid && cfg.Insecure.Bool { - tr := &http.Transport{ - TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, - } - httpClient = &http.Client{Transport: tr} - } else { - httpClient = new(http.Client) - } - - esBaseClient, err := es.NewBaseClient(cfg, httpClient) - if err != nil { - return err - } - - head := cliContext.Args().First() - args := cliContext.Args().Tail() - - if head == "" { - cli.ShowAppHelp(cliContext) - return fail.Wrap(fail.New("You need "), fail.WithCode("Invalid arguments")) - } - operation := head - - head = cli.Args(args).First() - args = cli.Args(args).Tail() - if head == "" { - cli.ShowAppHelp(cliContext) - return fail.Wrap(fail.New("You need "), fail.WithCode("Invalid arguments")) - } - target := head - - e := executer.NewExecuter(esBaseClient, httpClient) - result, err := e.Run(ctx, operation, target, args) - - if err != nil && fail.Unwrap(err).Code == "Invalid arguments" { - cli.ShowAppHelp(cliContext) - } - fmt.Fprintf(os.Stdout, result.String()) - return fail.Wrap(err) - } - app.Flags = []cli.Flag{ - cli.StringFlag{ - Name: "host", - Usage: "ES hostname", - }, - cli.StringFlag{ - Name: "type, t", - Usage: "Elasticsearch documents type", - }, - cli.StringFlag{ - Name: "user, U", - Usage: "ES basic auth user", - }, - cli.StringFlag{ - Name: "pass, P", - Usage: "ES basic auth password", - }, - cli.BoolFlag{ - Name: "insecure, k", - Usage: "Same as curl insecure", - }, - cli.StringFlag{ - Name: "namespace, n", - Usage: "Specify namespace in es-cli", - }, - } - - err := app.Run(os.Args) - if err != nil { - fmt.Fprintf(os.Stderr, "%v\n", err) + if err := cmd.Run(); err != nil { + fmt.Fprintln(os.Stderr, err) os.Exit(1) } } diff --git a/script/e2e-test b/script/e2e-test index ea51dad..f116707 100755 --- a/script/e2e-test +++ b/script/e2e-test @@ -3,7 +3,7 @@ set -eo pipefail function exec_only() { - cmd="go run main.go --host http://localhost:$1 " + cmd="go run main.go --host http://localhost:$1 --debug" ## Index echo "# list index" diff --git a/script/es b/script/es new file mode 100755 index 0000000..18e3ac7 --- /dev/null +++ b/script/es @@ -0,0 +1,3 @@ +#!/bin/bash + +docker run -p 9200:9200 -d -e ES_JAVA_OPTS='-Xms1g -Xmx1g' elasticsearch:6.8.0 diff --git a/script/es-clid b/script/es-clid new file mode 100755 index 0000000..7328336 --- /dev/null +++ b/script/es-clid @@ -0,0 +1,3 @@ +#!/bin/bash + +eval "go run $GOPATH/src/github.com/rerost/es-cli/main.go $*" diff --git a/tools.go b/tools.go index 11a8b6c..9673e3f 100644 --- a/tools.go +++ b/tools.go @@ -6,6 +6,7 @@ package tools // tool dependencies import ( + _ "github.com/google/wire/cmd/wire" _ "github.com/izumin5210/cgt" _ "github.com/tcnksm/ghr" )