Skip to content

Commit

Permalink
feat(influxd): Migrate influxd binary to cobra Command package
Browse files Browse the repository at this point in the history
This commit consists of several improvements or changes:

* migrate the influxd binary to cobra.Command
* introduce a default run sub-command to start the server
* register the run sub-command flags with viper
  to maintain compatibility with the existing behavior of automatic
  binding of flags to environment variables.

Closes #12602
  • Loading branch information
stuartcarnie committed Mar 14, 2019
1 parent f5c54a0 commit e8045ae
Show file tree
Hide file tree
Showing 4 changed files with 215 additions and 156 deletions.
226 changes: 137 additions & 89 deletions cmd/influxd/launcher/launcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,11 @@ import (

"github.com/influxdata/flux/control"
"github.com/influxdata/flux/execute"
"github.com/influxdata/influxdb/kit/signals"
"github.com/influxdata/influxdb/telemetry"
"github.com/opentracing/opentracing-go"
"github.com/prometheus/client_golang/prometheus"
"github.com/spf13/cobra"
jaegerconfig "github.com/uber/jaeger-client-go/config"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
Expand Down Expand Up @@ -65,6 +68,128 @@ const (
JaegerTracing = "jaeger"
)

func NewCommand() *cobra.Command {
l := NewLauncher()
cmd := &cobra.Command{
Use: "run",
Short: "Start the influxd server (default)",
Run: func(cmd *cobra.Command, args []string) {
// exit with SIGINT and SIGTERM
ctx := context.Background()
ctx = signals.WithStandardSignals(ctx)

// m.SetBuild(version, commit, date)
if err := l.run(ctx); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
} else if !l.Running() {
os.Exit(1)
}

var wg sync.WaitGroup
if !l.ReportingDisabled() {
reporter := telemetry.NewReporter(l.Registry())
reporter.Interval = 8 * time.Hour
reporter.Logger = l.Logger()
wg.Add(1)
go func() {
defer wg.Done()
reporter.Report(ctx)
}()
}

<-ctx.Done()

// Attempt clean shutdown.
ctx, cancel := context.WithTimeout(ctx, 2*time.Second)
defer cancel()
l.Shutdown(ctx)
wg.Wait()
},
}

buildLauncherCommand(l, cmd)

return cmd
}

func buildLauncherCommand(l *Launcher, cmd *cobra.Command) {
dir, err := fs.InfluxDir()
if err != nil {
panic(fmt.Errorf("failed to determine influx directory: %v", err))
}

opts := []cli.Opt{
{
DestP: &l.logLevel,
Flag: "log-level",
Default: "info",
Desc: "supported log levels are debug, info, and error",
},
{
DestP: &l.tracingType,
Flag: "tracing-type",
Default: "",
Desc: fmt.Sprintf("supported tracing types are %s, %s", LogTracing, JaegerTracing),
},
{
DestP: &l.httpBindAddress,
Flag: "http-bind-address",
Default: ":9999",
Desc: "bind address for the REST HTTP API",
},
{
DestP: &l.boltPath,
Flag: "bolt-path",
Default: filepath.Join(dir, "influxd.bolt"),
Desc: "path to boltdb database",
},
{
DestP: &l.assetsPath,
Flag: "assets-path",
Desc: "override default assets by serving from a specific directory (developer mode)",
},
{
DestP: &l.storeType,
Flag: "store",
Default: "bolt",
Desc: "backing store for REST resources (bolt or memory)",
},
{
DestP: &l.testing,
Flag: "e2e-testing",
Default: false,
Desc: "add /debug/flush endpoint to clear stores; used for end-to-end tests",
},
{
DestP: &l.enginePath,
Flag: "engine-path",
Default: filepath.Join(dir, "engine"),
Desc: "path to persistent engine files",
},
{
DestP: &l.secretStore,
Flag: "secret-store",
Default: "bolt",
Desc: "data store for secrets (bolt or vault)",
},
{
DestP: &l.protosPath,
Flag: "protos-path",
Default: filepath.Join(dir, "protos"),
Desc: "path to protos on the filesystem",
},
{
DestP: &l.reportingDisabled,
Flag: "reporting-disabled",
Default: false,
Desc: "disable sending telemetry data to https://telemetry.influxdata.com every 8 hours",
},
}

cli.BindOptions(cmd, opts)
}

// Launcher represents the main program execution.
type Launcher struct {
wg sync.WaitGroup
Expand Down Expand Up @@ -103,9 +228,6 @@ type Launcher struct {
logger *zap.Logger
reg *prom.Registry

// BuildInfo contains commit, version and such of influxdb.
BuildInfo platform.BuildInfo

Stdin io.Reader
Stdout io.Writer
Stderr io.Writer
Expand Down Expand Up @@ -141,13 +263,6 @@ func (m *Launcher) Logger() *zap.Logger {
return m.logger
}

// SetBuild adds version, commit, and date to prometheus metrics.
func (m *Launcher) SetBuild(version, commit, date string) {
m.BuildInfo.Version = version
m.BuildInfo.Commit = commit
m.BuildInfo.Date = date
}

// URL returns the URL to connect to the HTTP server.
func (m *Launcher) URL() string {
return fmt.Sprintf("http://127.0.0.1:%d", m.httpPort)
Expand Down Expand Up @@ -200,84 +315,16 @@ func (m *Launcher) Cancel() { m.cancel() }

// Run executes the program with the given CLI arguments.
func (m *Launcher) Run(ctx context.Context, args ...string) error {
dir, err := fs.InfluxDir()
if err != nil {
return fmt.Errorf("failed to determine influx directory: %v", err)
}

prog := &cli.Program{
Name: "influxd",
Run: func() error { return m.run(ctx) },
Opts: []cli.Opt{
{
DestP: &m.logLevel,
Flag: "log-level",
Default: "info",
Desc: "supported log levels are debug, info, and error",
},
{
DestP: &m.tracingType,
Flag: "tracing-type",
Default: "",
Desc: fmt.Sprintf("supported tracing types are %s, %s", LogTracing, JaegerTracing),
},
{
DestP: &m.httpBindAddress,
Flag: "http-bind-address",
Default: ":9999",
Desc: "bind address for the REST HTTP API",
},
{
DestP: &m.boltPath,
Flag: "bolt-path",
Default: filepath.Join(dir, "influxd.bolt"),
Desc: "path to boltdb database",
},
{
DestP: &m.assetsPath,
Flag: "assets-path",
Desc: "override default assets by serving from a specific directory (developer mode)",
},
{
DestP: &m.storeType,
Flag: "store",
Default: "bolt",
Desc: "backing store for REST resources (bolt or memory)",
},
{
DestP: &m.testing,
Flag: "e2e-testing",
Default: false,
Desc: "add /debug/flush endpoint to clear stores; used for end-to-end tests",
},
{
DestP: &m.enginePath,
Flag: "engine-path",
Default: filepath.Join(dir, "engine"),
Desc: "path to persistent engine files",
},
{
DestP: &m.secretStore,
Flag: "secret-store",
Default: "bolt",
Desc: "data store for secrets (bolt or vault)",
},
{
DestP: &m.protosPath,
Flag: "protos-path",
Default: filepath.Join(dir, "protos"),
Desc: "path to protos on the filesystem",
},
{
DestP: &m.reportingDisabled,
Flag: "reporting-disabled",
Default: false,
Desc: "disable sending telemetry data to https://telemetry.influxdata.com every 8 hours",
},
cmd := &cobra.Command{
Use: "run",
Short: "Start the influxd server (default)",
RunE: func(cmd *cobra.Command, args []string) error {
return m.run(ctx)
},
}

cmd := cli.NewCommand(prog)
buildLauncherCommand(m, cmd)

cmd.SetArgs(args)
return cmd.Execute()
}
Expand All @@ -304,10 +351,11 @@ func (m *Launcher) run(ctx context.Context) (err error) {
return err
}

info := platform.GetBuildInfo()
m.logger.Info("Welcome to InfluxDB",
zap.String("version", m.BuildInfo.Version),
zap.String("commit", m.BuildInfo.Commit),
zap.String("build_date", m.BuildInfo.Date),
zap.String("version", info.Version),
zap.String("commit", info.Commit),
zap.String("build_date", info.Date),
)

switch m.tracingType {
Expand Down Expand Up @@ -373,7 +421,7 @@ func (m *Launcher) run(ctx context.Context) (err error) {
m.reg = prom.NewRegistry()
m.reg.MustRegister(
prometheus.NewGoCollector(),
infprom.NewInfluxCollector(m.boltClient, m.BuildInfo),
infprom.NewInfluxCollector(m.boltClient, info),
)
m.reg.WithLogger(m.logger)
m.reg.MustRegister(m.boltClient)
Expand Down
67 changes: 32 additions & 35 deletions cmd/influxd/main.go
Original file line number Diff line number Diff line change
@@ -1,19 +1,17 @@
package main

import (
"context"
"fmt"
_ "net/http/pprof"
"os"
"sync"
"time"
"strings"

"github.com/influxdata/influxdb"
"github.com/influxdata/influxdb/cmd/influxd/launcher"
"github.com/influxdata/influxdb/kit/signals"
_ "github.com/influxdata/influxdb/query/builtin"
"github.com/influxdata/influxdb/telemetry"
_ "github.com/influxdata/influxdb/tsdb/tsi1"
_ "github.com/influxdata/influxdb/tsdb/tsm1"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)

var (
Expand All @@ -22,37 +20,36 @@ var (
date = "unknown"
)

func main() {
// exit with SIGINT and SIGTERM
ctx := context.Background()
ctx = signals.WithStandardSignals(ctx)

m := launcher.NewLauncher()
m.SetBuild(version, commit, date)
if err := m.Run(ctx, os.Args[1:]...); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
} else if !m.Running() {
os.Exit(1)
}
var rootCmd = &cobra.Command{
Use: "influxd",
Short: "Influx Server",
}

var wg sync.WaitGroup
if !m.ReportingDisabled() {
reporter := telemetry.NewReporter(m.Registry())
reporter.Interval = 8 * time.Hour
reporter.Logger = m.Logger()
wg.Add(1)
go func() {
defer wg.Done()
reporter.Report(ctx)
}()
func init() {
influxdb.SetBuildInfo(version, commit, date)
viper.SetEnvPrefix("INFLUXD")
viper.AutomaticEnv()
viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_"))
rootCmd.InitDefaultHelpCmd()
rootCmd.AddCommand(launcher.NewCommand())
}

// find determines the default behavior when running influxd.
// Specifically, find will return the influxd run command if no sub-command
// was specified.
func find(args []string) *cobra.Command {
cmd, _, err := rootCmd.Find(args)
if err == nil && cmd == rootCmd {
// Execute the run command if no sub-command is specified
return launcher.NewCommand()
}

<-ctx.Done()
return rootCmd
}

// Attempt clean shutdown.
ctx, cancel := context.WithTimeout(ctx, 2*time.Second)
defer cancel()
m.Shutdown(ctx)
wg.Wait()
func main() {
cmd := find(os.Args[1:])
if err := cmd.Execute(); err != nil {
os.Exit(1)
}
}
3 changes: 0 additions & 3 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -157,9 +157,6 @@ github.com/google/uuid v1.0.0 h1:b4Gk+7WdP/d3HZH8EJsZpvV7EtDOgaZLtnaNGIu1adA=
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e h1:JKmoR8x90Iww1ks85zJ1lfDGgIiMDuIptTOhJq+zKyg=
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/goreleaser/goreleaser v0.94.0/go.mod h1:OjbYR2NhOI6AEUWCowMSBzo9nP1aRif3sYtx+rhp+Zo=
github.com/goreleaser/goreleaser v0.97.0 h1:2/GZKg0cLk5HgIiiSaW/lbDfj0T/GMgF6qEFexy0Vfs=
github.com/goreleaser/goreleaser v0.97.0/go.mod h1:MnjA0e0Uq6ISqjG1WxxMAl+3VS1QYjILSWVnMYDxasE=
github.com/goreleaser/nfpm v0.9.7 h1:h8RQMDztu6cW7b0/s4PGbdeMYykAbJG0UMXaWG5uBMI=
github.com/goreleaser/nfpm v0.9.7/go.mod h1:F2yzin6cBAL9gb+mSiReuXdsfTrOQwDMsuSpULof+y4=
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
Expand Down
Loading

0 comments on commit e8045ae

Please sign in to comment.