diff --git a/client/influxdb.go b/client/influxdb.go index e28ac70fe4..909fe747f1 100644 --- a/client/influxdb.go +++ b/client/influxdb.go @@ -87,14 +87,15 @@ func ParseConnectionString(path string, ssl bool) (url.URL, error) { // UserAgent: If not provided, will default "InfluxDBClient", // Timeout: If not provided, will default to 0 (no timeout) type Config struct { - URL url.URL - UnixSocket string - Username string - Password string - UserAgent string - Timeout time.Duration - Precision string - UnsafeSsl bool + URL url.URL + UnixSocket string + Username string + Password string + UserAgent string + Timeout time.Duration + Precision string + WriteConsistency string + UnsafeSsl bool } // NewConfig will create a config to be used in connecting to the client diff --git a/cmd/influx/cli/cli.go b/cmd/influx/cli/cli.go index f5cd2c48c9..b122f0da2a 100644 --- a/cmd/influx/cli/cli.go +++ b/cmd/influx/cli/cli.go @@ -9,7 +9,6 @@ import ( "io" "io/ioutil" "net" - "net/url" "os" "os/signal" "path/filepath" @@ -36,35 +35,29 @@ var ErrBlankCommand = errors.New("empty input") // CommandLine holds CLI configuration and state type CommandLine struct { - Client *client.Client - Line *liner.State - Host string - Port int - UnixSocket string - Username string - Password string - Database string - Ssl bool - UnsafeSsl bool - RetentionPolicy string - ClientVersion string - ServerVersion string - Pretty bool // controls pretty print for json - Format string // controls the output format. Valid values are json, csv, or column - Precision string - WriteConsistency string - Execute string - ShowVersion bool - Import bool - PPS int // Controls how many points per second the import will allow via throttling - Path string - Compressed bool - Chunked bool - Quit chan struct{} - IgnoreSignals bool // Ignore signals normally caught by this process (used primarily for testing) - ForceTTY bool // Force the CLI to act as if it were connected to a TTY - osSignals chan os.Signal - historyFilePath string + Line *liner.State + Host string + Port int + Database string + Ssl bool + RetentionPolicy string + ClientVersion string + ServerVersion string + Pretty bool // controls pretty print for json + Format string // controls the output format. Valid values are json, csv, or column + Execute string + ShowVersion bool + Import bool + Chunked bool + Quit chan struct{} + IgnoreSignals bool // Ignore signals normally caught by this process (used primarily for testing) + ForceTTY bool // Force the CLI to act as if it were connected to a TTY + osSignals chan os.Signal + historyFilePath string + + Client *client.Client + ClientConfig client.Config // Client config options. + ImporterConfig v8.Config // Importer configuration options. } // New returns an instance of CommandLine @@ -84,7 +77,7 @@ func (c *CommandLine) Run() error { // 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 == "" { + if (strings.HasPrefix(v, "-password") || strings.HasPrefix(v, "--password")) && c.ClientConfig.Password == "" { promptForPassword = true break } @@ -96,8 +89,8 @@ func (c *CommandLine) Run() error { } // Read environment variables for username/password. - if c.Username == "" { - c.Username = os.Getenv("INFLUX_USERNAME") + if c.ClientConfig.Username == "" { + c.ClientConfig.Username = os.Getenv("INFLUX_USERNAME") } // If we are going to be prompted for a password, always use the entered password. if promptForPassword { @@ -110,9 +103,9 @@ func (c *CommandLine) Run() error { if e != nil { return errors.New("Unable to parse password") } - c.Password = p - } else if c.Password == "" { - c.Password = os.Getenv("INFLUX_PASSWORD") + c.ClientConfig.Password = p + } else if c.ClientConfig.Password == "" { + c.ClientConfig.Password = os.Getenv("INFLUX_PASSWORD") } if err := c.Connect(""); err != nil { @@ -122,7 +115,7 @@ func (c *CommandLine) Run() error { } // Modify precision. - c.SetPrecision(c.Precision) + c.SetPrecision(c.ClientConfig.Precision) if c.Execute != "" { // Make the non-interactive mode send everything through the CLI's parser @@ -137,25 +130,17 @@ func (c *CommandLine) Run() error { } if c.Import { - path := net.JoinHostPort(c.Host, strconv.Itoa(c.Port)) - u, e := client.ParseConnectionString(path, c.Ssl) + addr := net.JoinHostPort(c.Host, strconv.Itoa(c.Port)) + u, e := client.ParseConnectionString(addr, 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 + // Copy the latest importer config and inject the latest client config + // into it. + config := c.ImporterConfig + config.Config = c.ClientConfig config.URL = u - config.Compressed = c.Compressed - config.PPS = c.PPS - config.UnixSocket = c.UnixSocket - config.UnsafeSsl = c.UnsafeSsl - config.Precision = c.Precision i := v8.NewImporter(config) if err := i.Import(); err != nil { @@ -284,46 +269,39 @@ func (c *CommandLine) ParseCommand(cmd string) error { // 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)) + 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)) } - var e error - u, e = client.ParseConnectionString(path, c.Ssl) - if e != nil { - return e + URL, err := client.ParseConnectionString(addr, c.Ssl) + if err != nil { + return err } - 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) + // 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 = cl + c.Client = client - 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()) + _, 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 h, p, err := net.SplitHostPort(config.URL.Host); err == nil { - c.Host = h - if i, err := strconv.Atoi(p); err == nil { + 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 } } @@ -343,25 +321,25 @@ func (c *CommandLine) SetAuth(cmd string) { } if len(args) == 2 { - c.Username = args[0] - c.Password = args[1] + c.ClientConfig.Username = args[0] + c.ClientConfig.Password = args[1] } else { u, e := c.Line.Prompt("username: ") if e != nil { fmt.Printf("Unable to process input: %s", e) return } - c.Username = strings.TrimSpace(u) + c.ClientConfig.Username = strings.TrimSpace(u) p, e := c.Line.PasswordPrompt("password: ") if e != nil { fmt.Printf("Unable to process input: %s", e) return } - c.Password = p + c.ClientConfig.Password = p } // Update the client as well - c.Client.SetAuth(c.Username, c.Password) + c.Client.SetAuth(c.ClientConfig.Username, c.ClientConfig.Password) } func (c *CommandLine) use(cmd string) { @@ -378,7 +356,7 @@ func (c *CommandLine) use(cmd string) { fmt.Printf("ERR: %s\n", err) return } else if err := response.Error(); err != nil { - if c.Username == "" { + if c.ClientConfig.Username == "" { fmt.Printf("ERR: %s\n", err) return } @@ -423,11 +401,11 @@ func (c *CommandLine) SetPrecision(cmd string) { switch cmd { case "h", "m", "s", "ms", "u", "ns": - c.Precision = cmd - c.Client.SetPrecision(c.Precision) + c.ClientConfig.Precision = cmd + c.Client.SetPrecision(c.ClientConfig.Precision) case "rfc3339": - c.Precision = "" - c.Client.SetPrecision(c.Precision) + c.ClientConfig.Precision = "" + c.Client.SetPrecision(c.ClientConfig.Precision) default: fmt.Printf("Unknown precision %q. Please use rfc3339, h, m, s, ms, u or ns.\n", cmd) } @@ -460,7 +438,7 @@ func (c *CommandLine) SetWriteConsistency(cmd string) { fmt.Printf("Unknown consistency level %q. Please use any, one, quorum, or all.\n", cmd) return } - c.WriteConsistency = cmd + c.ClientConfig.WriteConsistency = cmd } // isWhitespace returns true if the rune is a space, tab, or newline. @@ -549,8 +527,8 @@ func (c *CommandLine) Insert(stmt string) error { }, Database: c.Database, RetentionPolicy: c.RetentionPolicy, - Precision: c.Precision, - WriteConsistency: c.WriteConsistency, + Precision: c.ClientConfig.Precision, + WriteConsistency: c.ClientConfig.WriteConsistency, }) if err != nil { fmt.Printf("ERR: %s\n", err) @@ -776,11 +754,11 @@ func (c *CommandLine) Settings() { } else { fmt.Fprintf(w, "Host\t%s\n", c.Host) } - fmt.Fprintf(w, "Username\t%s\n", c.Username) + fmt.Fprintf(w, "Username\t%s\n", c.ClientConfig.Username) fmt.Fprintf(w, "Database\t%s\n", c.Database) fmt.Fprintf(w, "Pretty\t%v\n", c.Pretty) fmt.Fprintf(w, "Format\t%s\n", c.Format) - fmt.Fprintf(w, "Write Consistency\t%s\n", c.WriteConsistency) + fmt.Fprintf(w, "Write Consistency\t%s\n", c.ClientConfig.WriteConsistency) fmt.Fprintln(w) w.Flush() } diff --git a/cmd/influx/cli/cli_test.go b/cmd/influx/cli/cli_test.go index 2e1816acda..895f37816e 100644 --- a/cmd/influx/cli/cli_test.go +++ b/cmd/influx/cli/cli_test.go @@ -67,7 +67,7 @@ func TestRunCLI_ExecuteInsert(t *testing.T) { c := cli.New(CLIENT_VERSION) c.Host = h c.Port, _ = strconv.Atoi(p) - c.Precision = "ms" + c.ClientConfig.Precision = "ms" c.Execute = "INSERT sensor,floor=1 value=2" c.IgnoreSignals = true c.ForceTTY = true @@ -87,11 +87,11 @@ func TestSetAuth(t *testing.T) { c.SetAuth("auth " + u + " " + p) // validate CLI configuration - if c.Username != u { - t.Fatalf("Username is %s but should be %s", c.Username, u) + if c.ClientConfig.Username != u { + t.Fatalf("Username is %s but should be %s", c.ClientConfig.Username, u) } - if c.Password != p { - t.Fatalf("Password is %s but should be %s", c.Password, p) + if c.ClientConfig.Password != p { + t.Fatalf("Password is %s but should be %s", c.ClientConfig.Password, p) } } @@ -105,15 +105,15 @@ func TestSetPrecision(t *testing.T) { // validate set non-default precision p := "ns" c.SetPrecision("precision " + p) - if c.Precision != p { - t.Fatalf("Precision is %s but should be %s", c.Precision, p) + if c.ClientConfig.Precision != p { + t.Fatalf("Precision is %s but should be %s", c.ClientConfig.Precision, p) } // validate set default precision which equals empty string p = "rfc3339" c.SetPrecision("precision " + p) - if c.Precision != "" { - t.Fatalf("Precision is %s but should be empty", c.Precision) + if c.ClientConfig.Precision != "" { + t.Fatalf("Precision is %s but should be empty", c.ClientConfig.Precision) } } @@ -142,22 +142,22 @@ func TestSetWriteConsistency(t *testing.T) { // set valid write consistency consistency := "all" c.SetWriteConsistency("consistency " + consistency) - if c.WriteConsistency != consistency { - t.Fatalf("WriteConsistency is %s but should be %s", c.WriteConsistency, consistency) + if c.ClientConfig.WriteConsistency != consistency { + t.Fatalf("WriteConsistency is %s but should be %s", c.ClientConfig.WriteConsistency, consistency) } // set different valid write consistency and validate change consistency = "quorum" c.SetWriteConsistency("consistency " + consistency) - if c.WriteConsistency != consistency { - t.Fatalf("WriteConsistency is %s but should be %s", c.WriteConsistency, consistency) + if c.ClientConfig.WriteConsistency != consistency { + t.Fatalf("WriteConsistency is %s but should be %s", c.ClientConfig.WriteConsistency, consistency) } // set invalid write consistency and verify there was no change invalidConsistency := "invalid_consistency" c.SetWriteConsistency("consistency " + invalidConsistency) - if c.WriteConsistency == invalidConsistency { - t.Fatalf("WriteConsistency is %s but should be %s", c.WriteConsistency, consistency) + if c.ClientConfig.WriteConsistency == invalidConsistency { + t.Fatalf("WriteConsistency is %s but should be %s", c.ClientConfig.WriteConsistency, consistency) } } @@ -340,7 +340,8 @@ func TestParseCommand_UseAuth(t *testing.T) { t.Errorf("%d. unexpected error. expected %v, actual %v", i, nil, err) continue } - m := cli.CommandLine{Client: c, Username: tt.user} + m := cli.CommandLine{Client: c} + m.ClientConfig.Username = tt.user if err := m.ParseCommand(tt.cmd); err != nil { t.Fatalf(`%d. Got error %v for command %q, expected nil.`, i, err, tt.cmd) @@ -371,8 +372,8 @@ func TestParseCommand_Consistency(t *testing.T) { t.Fatalf(`Got error %v for command %q, expected nil.`, err, test.cmd) } - if c.WriteConsistency != "one" { - t.Fatalf(`Command "consistency" changed consistency to %q. Expected one`, c.WriteConsistency) + if c.ClientConfig.WriteConsistency != "one" { + t.Fatalf(`Command "consistency" changed consistency to %q. Expected one`, c.ClientConfig.WriteConsistency) } } } diff --git a/cmd/influx/main.go b/cmd/influx/main.go index 2d5b0e0d70..7d8bccef0c 100644 --- a/cmd/influx/main.go +++ b/cmd/influx/main.go @@ -39,22 +39,22 @@ func main() { fs := flag.NewFlagSet("InfluxDB shell version "+version, flag.ExitOnError) fs.StringVar(&c.Host, "host", client.DefaultHost, "Influxdb host to connect to.") fs.IntVar(&c.Port, "port", client.DefaultPort, "Influxdb port to connect to.") - fs.StringVar(&c.UnixSocket, "socket", c.UnixSocket, "Influxdb unix socket to connect to.") - fs.StringVar(&c.Username, "username", c.Username, "Username to connect to the server.") - fs.StringVar(&c.Password, "password", c.Password, `Password to connect to the server. Leaving blank will prompt for password (--password="").`) + fs.StringVar(&c.ClientConfig.UnixSocket, "socket", "", "Influxdb unix socket to connect to.") + fs.StringVar(&c.ClientConfig.Username, "username", "", "Username to connect to the server.") + fs.StringVar(&c.ClientConfig.Password, "password", "", `Password to connect to the server. Leaving blank will prompt for password (--password="").`) fs.StringVar(&c.Database, "database", c.Database, "Database to connect to the server.") fs.BoolVar(&c.Ssl, "ssl", false, "Use https for connecting to cluster.") - fs.BoolVar(&c.UnsafeSsl, "unsafeSsl", false, "Set this when connecting to the cluster using https and not use SSL verification.") + fs.BoolVar(&c.ClientConfig.UnsafeSsl, "unsafeSsl", false, "Set this when connecting to the cluster using https and not use SSL verification.") fs.StringVar(&c.Format, "format", defaultFormat, "Format specifies the format of the server responses: json, csv, or column.") - fs.StringVar(&c.Precision, "precision", defaultPrecision, "Precision specifies the format of the timestamp: rfc3339,h,m,s,ms,u or ns.") - fs.StringVar(&c.WriteConsistency, "consistency", "all", "Set write consistency level: any, one, quorum, or all.") + fs.StringVar(&c.ClientConfig.Precision, "precision", defaultPrecision, "Precision specifies the format of the timestamp: rfc3339,h,m,s,ms,u or ns.") + fs.StringVar(&c.ClientConfig.WriteConsistency, "consistency", "all", "Set write consistency level: any, one, quorum, or all.") fs.BoolVar(&c.Pretty, "pretty", false, "Turns on pretty print for the json format.") fs.StringVar(&c.Execute, "execute", c.Execute, "Execute command and quit.") fs.BoolVar(&c.ShowVersion, "version", false, "Displays the InfluxDB version.") fs.BoolVar(&c.Import, "import", false, "Import a previous database.") - fs.IntVar(&c.PPS, "pps", defaultPPS, "How many points per second the import will allow. By default it is zero and will not throttle importing.") - fs.StringVar(&c.Path, "path", "", "path to the file to import") - fs.BoolVar(&c.Compressed, "compressed", false, "set to true if the import file is compressed") + fs.IntVar(&c.ImporterConfig.PPS, "pps", defaultPPS, "How many points per second the import will allow. By default it is zero and will not throttle importing.") + fs.StringVar(&c.ImporterConfig.Path, "path", "", "path to the file to import") + fs.BoolVar(&c.ImporterConfig.Compressed, "compressed", false, "set to true if the import file is compressed") // Define our own custom usage to print fs.Usage = func() { diff --git a/importer/v8/importer.go b/importer/v8/importer.go index 4738066f84..5dfa5f52e9 100644 --- a/importer/v8/importer.go +++ b/importer/v8/importer.go @@ -17,11 +17,10 @@ const batchSize = 5000 // Config is the config used to initialize a Importer importer type Config struct { - Path string - Version string - Compressed bool - WriteConsistency string - PPS int + Path string // Path to import data. + Version string + Compressed bool // Whether import data is gzipped. + PPS int // points per second importer imports with. client.Config }