influxdb/cmd/influx_tools/main.go

182 lines
4.4 KiB
Go

// The influx_tools command displays detailed information about InfluxDB data files.
package main
import (
"errors"
"fmt"
"io"
"os"
"time"
"github.com/influxdata/influxdb/cmd"
"github.com/influxdata/influxdb/cmd/influx_tools/compact"
"github.com/influxdata/influxdb/cmd/influx_tools/export"
genexec "github.com/influxdata/influxdb/cmd/influx_tools/generate/exec"
geninit "github.com/influxdata/influxdb/cmd/influx_tools/generate/init"
"github.com/influxdata/influxdb/cmd/influx_tools/help"
"github.com/influxdata/influxdb/cmd/influx_tools/importer"
"github.com/influxdata/influxdb/cmd/influx_tools/server"
"github.com/influxdata/influxdb/cmd/influxd/run"
"github.com/influxdata/influxdb/services/meta"
"github.com/influxdata/influxdb/tsdb"
_ "github.com/influxdata/influxdb/tsdb/engine"
"go.uber.org/zap"
)
func main() {
m := NewMain()
if err := m.Run(os.Args[1:]...); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}
// Main represents the program execution.
type Main struct {
Stdin io.Reader
Stdout io.Writer
Stderr io.Writer
}
// NewMain returns a new instance of Main.
func NewMain() *Main {
return &Main{
Stdin: os.Stdin,
Stdout: os.Stdout,
Stderr: os.Stderr,
}
}
// Run determines and runs the command specified by the CLI args.
func (m *Main) Run(args ...string) error {
name, args := cmd.ParseCommandName(args)
// Extract name from args.
switch name {
case "", "help":
if err := help.NewCommand().Run(args...); err != nil {
return fmt.Errorf("help failed: %s", err)
}
case "compact-shard":
c := compact.NewCommand()
if err := c.Run(args); err != nil {
return fmt.Errorf("compact-shard failed: %s", err)
}
case "export":
c := export.NewCommand(&ossServer{logger: zap.NewNop()})
if err := c.Run(args); err != nil {
return fmt.Errorf("export failed: %s", err)
}
case "import":
c := importer.NewCommand(&ossServer{logger: zap.NewNop()})
if err := c.Run(args); err != nil {
return fmt.Errorf("import failed: %s", err)
}
case "gen-init":
c := geninit.NewCommand(&ossServer{logger: zap.NewNop()})
if err := c.Run(args); err != nil {
return fmt.Errorf("gen-init failed: %s", err)
}
case "gen-exec":
deps := genexec.Dependencies{Server: &ossServer{logger: zap.NewNop()}}
c := genexec.NewCommand(deps)
if err := c.Run(args); err != nil {
return fmt.Errorf("gen-exec failed: %s", err)
}
default:
return fmt.Errorf(`unknown command "%s"`+"\n"+`Run 'influx-tools help' for usage`+"\n\n", name)
}
return nil
}
type ossServer struct {
logger *zap.Logger
config *run.Config
noClient bool
client *meta.Client
mc server.MetaClient
}
func (s *ossServer) Open(path string) (err error) {
s.config, err = s.parseConfig(path)
if err != nil {
return err
}
// Validate the configuration.
if err = s.config.Validate(); err != nil {
return fmt.Errorf("validate config: %s", err)
}
if s.noClient {
return nil
}
s.client = meta.NewClient(s.config.Meta)
if err = s.client.Open(); err != nil {
s.client = nil
return err
}
s.mc = &ossMetaClient{s.client}
return nil
}
func (s *ossServer) Close() {
if s.client != nil {
s.client.Close()
s.client = nil
}
}
func (s *ossServer) MetaClient() server.MetaClient { return s.mc }
func (s *ossServer) TSDBConfig() tsdb.Config { return s.config.Data }
func (s *ossServer) Logger() *zap.Logger { return s.logger }
func (s *ossServer) NodeID() uint64 { return 0 }
// ParseConfig parses the config at path.
// It returns a demo configuration if path is blank.
func (s *ossServer) parseConfig(path string) (*run.Config, error) {
path = s.resolvePath(path)
// Use demo configuration if no config path is specified.
if path == "" {
return nil, errors.New("missing config file")
}
config := run.NewConfig()
if err := config.FromTomlFile(path); err != nil {
return nil, err
}
return config, nil
}
func (s *ossServer) resolvePath(path string) string {
if path != "" {
if path == os.DevNull {
return ""
}
return path
}
for _, p := range []string{
os.ExpandEnv("${HOME}/.influxdb/influxdb.conf"),
"/etc/influxdb/influxdb.conf",
} {
if _, err := os.Stat(p); err == nil {
return p
}
}
return ""
}
type ossMetaClient struct {
*meta.Client
}
func (*ossMetaClient) NodeID() uint64 { return 0 }
func (c *ossMetaClient) NodeShardGroupsByTimeRange(database, policy string, min, max time.Time) (a []meta.ShardGroupInfo, err error) {
return c.ShardGroupsByTimeRange(database, policy, min, max)
}