Skip to content

Commit

Permalink
Subcommands enhancements (#4510)
Browse files Browse the repository at this point in the history
* Add deprecation messages for deprecated flags

* Ensure RootCmd works when imported somewhere outside main.go

* Add `completion` command

* Add `export config` subcommand

* Add `export template` subcommand

* Be more verbose on cmd errors

* Do not fail when no template settings are given

* Do not deprecate `-setup` flag

* Remove version mangling in `export template`

* Remove `output_to_file` template settings

Deprecated in favor of `beat export template`
  • Loading branch information
exekias authored and tsg committed Jun 26, 2017
1 parent 4ad2066 commit dc6e846
Show file tree
Hide file tree
Showing 25 changed files with 261 additions and 304 deletions.
2 changes: 1 addition & 1 deletion filebeat/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,6 @@ func init() {

RootCmd = cmd.GenRootCmdWithRunFlags(Name, "", beater.New, runFlags)
RootCmd.PersistentFlags().AddGoFlag(flag.CommandLine.Lookup("M"))
RootCmd.ConfigTest.Flags().AddGoFlag(flag.CommandLine.Lookup("modules"))
RootCmd.ConfigTestCmd.Flags().AddGoFlag(flag.CommandLine.Lookup("modules"))
RootCmd.SetupCmd.Flags().AddGoFlag(flag.CommandLine.Lookup("modules"))
}
9 changes: 7 additions & 2 deletions heartbeat/cmd/root.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
package cmd

import cmd "github.com/elastic/beats/libbeat/cmd"
import "github.com/elastic/beats/heartbeat/beater"
import (
// register default heartbeat monitors
_ "github.com/elastic/beats/heartbeat/monitors/defaults"

"github.com/elastic/beats/heartbeat/beater"
cmd "github.com/elastic/beats/libbeat/cmd"
)

// Name of this beat
var Name = "heartbeat"
Expand Down
3 changes: 0 additions & 3 deletions heartbeat/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,6 @@ import (
"os"

"github.com/elastic/beats/heartbeat/cmd"

// register default heartbeat monitors
_ "github.com/elastic/beats/heartbeat/monitors/defaults"
)

func main() {
Expand Down
27 changes: 9 additions & 18 deletions libbeat/beat/beat.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ func New(name, v string) (*Beat, error) {
}

// init does initialization of things common to all actions (read confs, flags)
func (b *Beat) init() error {
func (b *Beat) Init() error {
err := b.handleFlags()
if err != nil {
return err
Expand Down Expand Up @@ -266,7 +266,7 @@ func (b *Beat) createBeater(bt Creator) (Beater, error) {
}

func (b *Beat) launch(bt Creator) error {
err := b.init()
err := b.Init()
if err != nil {
return err
}
Expand All @@ -289,13 +289,17 @@ func (b *Beat) launch(bt Creator) error {

// If -configtest was specified, exit now prior to run.
if cfgfile.IsTestConfig() {
logp.Deprecate("6.0", "-configtest flag has been deprecated, use configtest subcommand")
fmt.Println("Config OK")
return GracefulExit
}

svc.HandleSignals(beater.Stop)

// TODO Deprecate this in favor of setup subcommand (7.0)
if *setup {
logp.Deprecate("6.0", "-setup flag has been deprectad, use setup subcommand")
}
err = b.loadDashboards(false)
if err != nil {
return err
Expand All @@ -321,7 +325,7 @@ func (b *Beat) launch(bt Creator) error {
// TestConfig check all settings are ok and the beat can be run
func (b *Beat) TestConfig(bt Creator) error {
return handleError(func() error {
err := b.init()
err := b.Init()
if err != nil {
return err
}
Expand All @@ -340,7 +344,7 @@ func (b *Beat) TestConfig(bt Creator) error {
// Setup registers ES index template and kibana dashboards
func (b *Beat) Setup(bt Creator, template, dashboards, machineLearning bool) error {
return handleError(func() error {
err := b.init()
err := b.Init()
if err != nil {
return err
}
Expand Down Expand Up @@ -414,6 +418,7 @@ func (b *Beat) handleFlags() error {
flag.Parse()

if *printVersion {
logp.Deprecate("6.0", "-version flag has been deprectad, use version subcommand")
fmt.Printf("%s version %s (%s), libbeat %s\n",
b.Info.Beat, b.Info.Version, runtime.GOARCH, version.GetDefaultVersion())
return GracefulExit
Expand Down Expand Up @@ -595,20 +600,6 @@ func (b *Beat) registerTemplateLoading() error {
if err != nil {
return fmt.Errorf("unpacking template config fails: %v", err)
}
if len(cfg.OutputToFile.Path) > 0 {
// output to file is enabled
loader, err := template.NewLoader(b.Config.Template, nil, b.Info)
if err != nil {
return fmt.Errorf("Error creating Elasticsearch template loader: %v", err)
}
err = loader.Generate()
if err != nil {
return fmt.Errorf("Error generating template: %v", err)
}

// XXX: Should we kill the Beat here or just continue?
return fmt.Errorf("Stopping after successfully writing the template to the file.")
}
}

// Loads template by default if esOutput is enabled
Expand Down
11 changes: 5 additions & 6 deletions libbeat/beat/setup.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
package beat

type TemplateConfig struct {
Enabled bool `config:"enabled"`
Name string `config:"name"`
Fields string `config:"fields"`
Overwrite bool `config:"overwrite"`
OutputToFile string `config:"output_to_file"`
Settings map[string]string `config:"settings"`
Enabled bool `config:"enabled"`
Name string `config:"name"`
Fields string `config:"fields"`
Overwrite bool `config:"overwrite"`
Settings map[string]string `config:"settings"`
}
32 changes: 32 additions & 0 deletions libbeat/cmd/completion.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package cmd

import (
"fmt"
"os"

"github.com/spf13/cobra"
)

func genCompletionCmd(name, version string, rootCmd *BeatsRootCmd) *cobra.Command {
completionCmd := cobra.Command{
Use: "completion SHELL",
Short: "Output shell completion code for the specified shell (bash only by the moment)",
// We don't want to expose this one in help:
Hidden: true,
Run: func(cmd *cobra.Command, args []string) {
if len(args) != 1 {
fmt.Println("Expected one argument with the desired shell")
os.Exit(1)
}

switch args[0] {
case "bash":
rootCmd.GenBashCompletion(os.Stdout)
default:
fmt.Printf("Unknown shell %s, only bash is available\n", args[0])
}
},
}

return &completionCmd
}
2 changes: 2 additions & 0 deletions libbeat/cmd/configtest.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package cmd

import (
"fmt"
"os"

"github.com/spf13/cobra"
Expand All @@ -15,6 +16,7 @@ func genConfigTestCmd(name, version string, beatCreator beat.Creator) *cobra.Com
Run: func(cmd *cobra.Command, args []string) {
b, err := beat.New(name, version)
if err != nil {
fmt.Fprintf(os.Stderr, "Error initializing beat: %s\n", err)
os.Exit(1)
}

Expand Down
20 changes: 20 additions & 0 deletions libbeat/cmd/export.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package cmd

import (
"github.com/spf13/cobra"

"github.com/elastic/beats/libbeat/beat"
"github.com/elastic/beats/libbeat/cmd/export"
)

func genExportCmd(name, beatVersion string, beatCreator beat.Creator) *cobra.Command {
exportCmd := &cobra.Command{
Use: "export",
Short: "Export current config or index template",
}

exportCmd.AddCommand(export.GenExportConfigCmd(name, beatVersion, beatCreator))
exportCmd.AddCommand(export.GenTemplateConfigCmd(name, beatVersion, beatCreator))

return exportCmd
}
45 changes: 45 additions & 0 deletions libbeat/cmd/export/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package export

import (
"fmt"
"os"

"github.com/spf13/cobra"
"gopkg.in/yaml.v2"

"github.com/elastic/beats/libbeat/beat"
)

func GenExportConfigCmd(name, beatVersion string, beatCreator beat.Creator) *cobra.Command {
return &cobra.Command{
Use: "config",
Short: "Export current config to stdout",
Run: func(cmd *cobra.Command, args []string) {
b, err := beat.New(name, beatVersion)
if err != nil {
fmt.Fprintf(os.Stderr, "Error initializing beat: %s\n", err)
os.Exit(1)
}

err = b.Init()
if err != nil {
fmt.Fprintf(os.Stderr, "Error initializing beat: %s\n", err)
os.Exit(1)
}

var config map[string]interface{}
err = b.RawConfig.Unpack(&config)
if err != nil {
fmt.Fprintf(os.Stderr, "Error unpacking config")
os.Exit(1)
}
res, err := yaml.Marshal(config)
if err != nil {
fmt.Fprintf(os.Stderr, "Error converting config to YAML format")
os.Exit(1)
}

os.Stdout.Write(res)
},
}
}
65 changes: 65 additions & 0 deletions libbeat/cmd/export/template.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package export

import (
"fmt"
"os"

"github.com/spf13/cobra"

"github.com/elastic/beats/libbeat/beat"
"github.com/elastic/beats/libbeat/template"
)

func GenTemplateConfigCmd(name, beatVersion string, beatCreator beat.Creator) *cobra.Command {
genTemplateConfigCmd := &cobra.Command{
Use: "template",
Short: "Export index template to stdout",
Run: func(cmd *cobra.Command, args []string) {
version, _ := cmd.Flags().GetString("es.version")
index, _ := cmd.Flags().GetString("index")

b, err := beat.New(name, beatVersion)
if err != nil {
fmt.Fprintf(os.Stderr, "Error initializing beat: %s\n", err)
os.Exit(1)
}
err = b.Init()
if err != nil {
fmt.Fprintf(os.Stderr, "Error initializing beat: %s\n", err)
os.Exit(1)
}

cfg := template.DefaultConfig
if b.Config.Template.Enabled() {
err = b.Config.Template.Unpack(&cfg)
if err != nil {
fmt.Fprintf(os.Stderr, "Error getting template settings: %+v", err)
os.Exit(1)
}
}

tmpl, err := template.New(b.Info.Version, version, index, cfg.Settings)
if err != nil {
fmt.Fprintf(os.Stderr, "Error generating template: %+v", err)
os.Exit(1)
}

templateString, err := tmpl.Load(cfg.Fields)
if err != nil {
fmt.Fprintf(os.Stderr, "Error generating template: %+v", err)
os.Exit(1)
}

_, err = os.Stdout.WriteString(templateString.StringToPrint() + "\n")
if err != nil {
fmt.Fprintf(os.Stderr, "Error writing template: %+v", err)
os.Exit(1)
}
},
}

genTemplateConfigCmd.Flags().String("es.version", beatVersion, "Elasticsearch version")
genTemplateConfigCmd.Flags().String("index", name, "Base index name")

return genTemplateConfigCmd
}
20 changes: 12 additions & 8 deletions libbeat/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,12 @@ import (
"github.com/spf13/pflag"

"github.com/elastic/beats/libbeat/beat"
"github.com/elastic/beats/libbeat/logp"
)

func init() {
// backwards compatibility workaround, convert -flags to --flags:
for i, arg := range os.Args[1:] {
if strings.HasPrefix(arg, "-") && !strings.HasPrefix(arg, "--") && len(arg) > 2 {
logp.Deprecate("6.0", "Argument %s should be -%s", arg, arg)
os.Args[1+i] = "-" + arg
}
}
Expand All @@ -26,10 +24,12 @@ func init() {
// flags and runs subcommands
type BeatsRootCmd struct {
cobra.Command
RunCmd *cobra.Command
SetupCmd *cobra.Command
VersionCmd *cobra.Command
ConfigTest *cobra.Command
RunCmd *cobra.Command
SetupCmd *cobra.Command
VersionCmd *cobra.Command
ConfigTestCmd *cobra.Command
CompletionCmd *cobra.Command
ExportCmd *cobra.Command
}

// GenRootCmd returns the root command to use for your beat. It takes
Expand All @@ -50,7 +50,9 @@ func GenRootCmdWithRunFlags(name, version string, beatCreator beat.Creator, runF
rootCmd.RunCmd = genRunCmd(name, version, beatCreator, runFlags)
rootCmd.SetupCmd = genSetupCmd(name, version, beatCreator)
rootCmd.VersionCmd = genVersionCmd(name, version)
rootCmd.ConfigTest = genConfigTestCmd(name, version, beatCreator)
rootCmd.ConfigTestCmd = genConfigTestCmd(name, version, beatCreator)
rootCmd.CompletionCmd = genCompletionCmd(name, version, rootCmd)
rootCmd.ExportCmd = genExportCmd(name, version, beatCreator)

// Root command is an alias for run
rootCmd.Run = rootCmd.RunCmd.Run
Expand All @@ -75,7 +77,9 @@ func GenRootCmdWithRunFlags(name, version string, beatCreator beat.Creator, runF
rootCmd.AddCommand(rootCmd.RunCmd)
rootCmd.AddCommand(rootCmd.SetupCmd)
rootCmd.AddCommand(rootCmd.VersionCmd)
rootCmd.AddCommand(rootCmd.ConfigTest)
rootCmd.AddCommand(rootCmd.ConfigTestCmd)
rootCmd.AddCommand(rootCmd.CompletionCmd)
rootCmd.AddCommand(rootCmd.ExportCmd)

return rootCmd
}
3 changes: 3 additions & 0 deletions libbeat/cmd/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ func genRunCmd(name, version string, beatCreator beat.Creator, runFlags *pflag.F
runCmd.Flags().AddGoFlag(flag.CommandLine.Lookup("setup"))
runCmd.Flags().AddGoFlag(flag.CommandLine.Lookup("version"))

runCmd.Flags().MarkDeprecated("version", "version flag has been deprectad, use version subcommand")
runCmd.Flags().MarkDeprecated("configtest", "setup flag has been deprectad, use configtest subcommand")

if runFlags != nil {
runCmd.Flags().AddFlagSet(runFlags)
}
Expand Down
2 changes: 2 additions & 0 deletions libbeat/cmd/setup.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package cmd

import (
"fmt"
"os"

"github.com/spf13/cobra"
Expand All @@ -20,6 +21,7 @@ func genSetupCmd(name, version string, beatCreator beat.Creator) *cobra.Command
Run: func(cmd *cobra.Command, args []string) {
beat, err := beat.New(name, version)
if err != nil {
fmt.Fprintf(os.Stderr, "Error initializing beat: %s\n", err)
os.Exit(1)
}

Expand Down
Loading

0 comments on commit dc6e846

Please sign in to comment.