182 lines
4.4 KiB
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)
|
|
}
|