func TestClient_ParseConnectionString_IPv6(t *testing.T) { path := "[fdf5:9ede:1875:0:a9ee:a600:8fe3:d495]:8086" u, err := client.ParseConnectionString(path, false) if err != nil { t.Fatalf("unexpected error, expected %v, actual %v", nil, err) } if u.Host != path { t.Fatalf("ipv6 parse failed, expected %s, actual %s", path, u.Host) } }
// InfluxHandler factory function // reutrn *InfluxHandler and error func NewInfluxHandler(h string, p int, db string, u string, pwd string, max int, delay int) (*InfluxHandler, error) { url, err := client.ParseConnectionString(fmt.Sprintf("%s:%d", h, p), false) if err != nil { return nil, err } cfg := client.NewConfig() cfg.URL = url cfg.Username = u cfg.Password = pwd cfg.Precision = "s" // 秒级别的精度就行 c, e := client.NewClient(cfg) if e != nil { return nil, e } _, _, err = c.Ping() if err != nil { return nil, err } ih := new(InfluxHandler) ih.c = c ih.force = make(chan struct{}, 1) ih.last = time.Now() ih.h = h ih.p = p ih.db = db ih.u = u ih.pwd = pwd if max <= 10 || max > 4096 { ih.max = 4096 } else { ih.max = max } if delay <= 60 || delay > 600 { ih.delay = time.Second * 600 } else { ih.delay = time.Second * delay } ih.ch = make(chan unit, int(ih.max+ih.max/2)) go ih.consume() return ih, nil }
// Connect connects client to a server func (c *CommandLine) Connect(cmd string) error { var cl *client.Client var u url.URL // Remove the "connect" keyword if it exists path := strings.TrimSpace(strings.Replace(cmd, "connect", "", -1)) // If they didn't provide a connection string, use the current settings if path == "" { path = net.JoinHostPort(c.Host, strconv.Itoa(c.Port)) } var e error u, e = client.ParseConnectionString(path, c.Ssl) if e != nil { return e } config := client.NewConfig() config.URL = u config.UnixSocket = c.UnixSocket config.Username = c.Username config.Password = c.Password config.UserAgent = "InfluxDBShell/" + c.ClientVersion config.Precision = c.Precision config.UnsafeSsl = c.UnsafeSsl cl, err := client.NewClient(config) if err != nil { return fmt.Errorf("Could not create client %s", err) } c.Client = cl var v string if _, v, e = c.Client.Ping(); e != nil { return fmt.Errorf("Failed to connect to %s: %s\n", c.Client.Addr(), e.Error()) } c.ServerVersion = v // Update the command with the current connection information if h, p, err := net.SplitHostPort(config.URL.Host); err == nil { c.Host = h if i, err := strconv.Atoi(p); err == nil { c.Port = i } } return nil }
// Connect connects client to a server func (c *CommandLine) Connect(cmd string) error { // Remove the "connect" keyword if it exists addr := strings.TrimSpace(strings.Replace(cmd, "connect", "", -1)) if addr == "" { // If they didn't provide a connection string, use the current settings addr = net.JoinHostPort(c.Host, strconv.Itoa(c.Port)) } URL, err := client.ParseConnectionString(addr, c.Ssl) if err != nil { return err } // Create copy of the current client config and create a new client. ClientConfig := c.ClientConfig ClientConfig.UserAgent = "InfluxDBShell/" + c.ClientVersion ClientConfig.URL = URL client, err := client.NewClient(ClientConfig) if err != nil { return fmt.Errorf("Could not create client %s", err) } c.Client = client _, v, err := c.Client.Ping() if err != nil { return fmt.Errorf("Failed to connect to %s: %v\n", c.Client.Addr(), err) } c.ServerVersion = v // Update the command with the current connection information if host, port, err := net.SplitHostPort(ClientConfig.URL.Host); err == nil { c.Host = host if i, err := strconv.Atoi(port); err == nil { c.Port = i } } return nil }
// Run executes the CLI func (c *CommandLine) Run() error { if !c.IgnoreSignals { // register OS signals for graceful termination signal.Notify(c.osSignals, syscall.SIGINT, syscall.SIGTERM) } var promptForPassword bool // determine if they set the password flag but provided no value for _, v := range os.Args { v = strings.ToLower(v) if (strings.HasPrefix(v, "-password") || strings.HasPrefix(v, "--password")) && c.Password == "" { promptForPassword = true break } } c.Line = liner.NewLiner() defer c.Line.Close() c.Line.SetMultiLineMode(true) if promptForPassword { p, e := c.Line.PasswordPrompt("password: "******"Unable to parse password.") } else { c.Password = p } } if err := c.Connect(""); err != nil { return fmt.Errorf( "Failed to connect to %s\nPlease check your connection settings and ensure 'influxd' is running.", c.Client.Addr()) } // Modify precision. c.SetPrecision(c.Precision) if c.Execute == "" && !c.Import { token, err := c.DatabaseToken() if err != nil { return fmt.Errorf("Failed to check token: %s", err.Error()) } if token == "" { fmt.Printf(noTokenMsg) } fmt.Printf("Connected to %s version %s\n", c.Client.Addr(), c.ServerVersion) } if c.Execute != "" { // Make the non-interactive mode send everything through the CLI's parser // the same way the interactive mode works lines := strings.Split(c.Execute, "\n") for _, line := range lines { if err := c.ParseCommand(line); err != nil { return err } } c.Line.Close() return nil } if c.Import { path := net.JoinHostPort(c.Host, strconv.Itoa(c.Port)) u, e := client.ParseConnectionString(path, c.Ssl) if e != nil { return e } config := v8.NewConfig() config.Username = c.Username config.Password = c.Password config.Precision = "ns" config.WriteConsistency = "any" config.Path = c.Path config.Version = c.ClientVersion config.URL = u config.Compressed = c.Compressed config.PPS = c.PPS config.Precision = c.Precision i := v8.NewImporter(config) if err := i.Import(); err != nil { err = fmt.Errorf("ERROR: %s\n", err) c.Line.Close() return err } c.Line.Close() return nil } c.Version() // Only load/write history if HOME environment variable is set. if homeDir := os.Getenv("HOME"); homeDir != "" { // Attempt to load the history file. c.historyFilePath = filepath.Join(homeDir, ".influx_history") if historyFile, err := os.Open(c.historyFilePath); err == nil { c.Line.ReadHistory(historyFile) historyFile.Close() } } // read from prompt until exit is run return c.mainLoop() }
// Run executes the CLI func (c *CommandLine) Run() error { // register OS signals for graceful termination if !c.IgnoreSignals { signal.Notify(c.osSignals, os.Kill, os.Interrupt, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGHUP) } var promptForPassword bool // determine if they set the password flag but provided no value for _, v := range os.Args { v = strings.ToLower(v) if (strings.HasPrefix(v, "-password") || strings.HasPrefix(v, "--password")) && c.Password == "" { promptForPassword = true break } } c.Line = liner.NewLiner() defer c.Line.Close() c.Line.SetMultiLineMode(true) if promptForPassword { p, e := c.Line.PasswordPrompt("password: "******"Unable to parse password.") } else { c.Password = p } } if err := c.Connect(""); err != nil { return fmt.Errorf( "Failed to connect to %s\nPlease check your connection settings and ensure 'influxd' is running.", c.Client.Addr()) } // Modify precision. c.SetPrecision(c.Precision) if c.Execute == "" && !c.Import { token, err := c.DatabaseToken() if err != nil { return fmt.Errorf("Failed to check token: %s", err.Error()) } if token == "" { fmt.Printf(noTokenMsg) } fmt.Printf("Connected to %s version %s\n", c.Client.Addr(), c.ServerVersion) } if c.Execute != "" { // Make the non-interactive mode send everything through the CLI's parser // the same way the interactive mode works lines := strings.Split(c.Execute, "\n") for _, line := range lines { if err := c.ParseCommand(line); err != nil { return err } } c.Line.Close() return nil } if c.Import { path := net.JoinHostPort(c.Host, strconv.Itoa(c.Port)) u, e := client.ParseConnectionString(path, c.Ssl) if e != nil { return e } config := v8.NewConfig() config.Username = c.Username config.Password = c.Password config.Precision = "ns" config.WriteConsistency = "any" config.Path = c.Path config.Version = c.ClientVersion config.URL = u config.Compressed = c.Compressed config.PPS = c.PPS config.Precision = c.Precision i := v8.NewImporter(config) if err := i.Import(); err != nil { err = fmt.Errorf("ERROR: %s\n", err) c.Line.Close() return err } c.Line.Close() return nil } c.Version() usr, err := user.Current() // Only load/write history if we can get the user if err == nil { c.historyFilePath = filepath.Join(usr.HomeDir, ".influx_history") if historyFile, err := os.Open(c.historyFilePath); err == nil { c.Line.ReadHistory(historyFile) historyFile.Close() } } // read from prompt until exit is run for { select { case <-c.osSignals: close(c.Quit) case <-c.Quit: c.exit() return nil default: l, e := c.Line.Prompt("> ") if e == io.EOF { // Instead of die, register that someone exited the program gracefully l = "exit" } else if e != nil { break } if err := c.ParseCommand(l); err != ErrBlankCommand { c.Line.AppendHistory(l) c.saveHistory() } } } }
// Run executes the CLI func (c *CommandLine) Run() error { hasTTY := c.ForceTTY || terminal.IsTerminal(int(os.Stdin.Fd())) var promptForPassword bool // determine if they set the password flag but provided no value for _, v := range os.Args { v = strings.ToLower(v) if (strings.HasPrefix(v, "-password") || strings.HasPrefix(v, "--password")) && c.Password == "" { promptForPassword = true break } } // Check if we will be able to prompt for the password later. if promptForPassword && !hasTTY { return errors.New("Unable to prompt for a password with no TTY.") } // Read environment variables for username/password. if c.Username == "" { c.Username = os.Getenv("INFLUX_USERNAME") } // If we are going to be prompted for a password, always use the entered password. if promptForPassword { // Open the liner (temporarily) and prompt for the password. p, e := func() (string, error) { l := liner.NewLiner() defer l.Close() return l.PasswordPrompt("password: "******"Unable to parse password") } c.Password = p } else if c.Password == "" { c.Password = os.Getenv("INFLUX_PASSWORD") } if err := c.Connect(""); err != nil { return fmt.Errorf( "Failed to connect to %s: %s\nPlease check your connection settings and ensure 'influxd' is running.", c.Client.Addr(), err.Error()) } // Modify precision. c.SetPrecision(c.Precision) if c.Execute != "" { // Make the non-interactive mode send everything through the CLI's parser // the same way the interactive mode works lines := strings.Split(c.Execute, "\n") for _, line := range lines { if err := c.ParseCommand(line); err != nil { return err } } return nil } if c.Import { path := net.JoinHostPort(c.Host, strconv.Itoa(c.Port)) u, e := client.ParseConnectionString(path, c.Ssl) if e != nil { return e } config := v8.NewConfig() config.Username = c.Username config.Password = c.Password config.Precision = "ns" config.WriteConsistency = "any" config.Path = c.Path config.Version = c.ClientVersion config.URL = u config.Compressed = c.Compressed config.PPS = c.PPS config.Precision = c.Precision i := v8.NewImporter(config) if err := i.Import(); err != nil { err = fmt.Errorf("ERROR: %s\n", err) return err } return nil } if !hasTTY { cmd, err := ioutil.ReadAll(os.Stdin) if err != nil { return err } return c.ExecuteQuery(string(cmd)) } if !c.IgnoreSignals { // register OS signals for graceful termination signal.Notify(c.osSignals, syscall.SIGINT, syscall.SIGTERM) } c.Line = liner.NewLiner() defer c.Line.Close() c.Line.SetMultiLineMode(true) token, err := c.DatabaseToken() if err != nil { return fmt.Errorf("Failed to check token: %s", err.Error()) } if token == "" { fmt.Printf(noTokenMsg) } fmt.Printf("Connected to %s version %s\n", c.Client.Addr(), c.ServerVersion) c.Version() // Only load/write history if HOME environment variable is set. if homeDir := os.Getenv("HOME"); homeDir != "" { // Attempt to load the history file. c.historyFilePath = filepath.Join(homeDir, ".influx_history") if historyFile, err := os.Open(c.historyFilePath); err == nil { c.Line.ReadHistory(historyFile) historyFile.Close() } } // read from prompt until exit is run return c.mainLoop() }