2018-05-24 17:34:39 +00:00
package main
import (
2019-01-22 18:19:26 +00:00
"context"
2018-05-24 17:34:39 +00:00
"fmt"
2019-11-21 23:10:39 +00:00
"io"
2018-11-02 02:34:22 +00:00
"io/ioutil"
2018-05-24 17:34:39 +00:00
"os"
2018-11-02 02:34:22 +00:00
"path/filepath"
2018-05-24 17:34:39 +00:00
2019-02-19 23:47:19 +00:00
"github.com/influxdata/influxdb"
2019-03-28 08:42:38 +00:00
"github.com/influxdata/influxdb/bolt"
2019-01-22 18:19:26 +00:00
"github.com/influxdata/influxdb/cmd/influx/internal"
"github.com/influxdata/influxdb/http"
2019-01-08 00:37:16 +00:00
"github.com/influxdata/influxdb/internal/fs"
2019-03-28 08:42:38 +00:00
"github.com/influxdata/influxdb/kv"
2019-12-08 04:10:22 +00:00
"github.com/influxdata/influxdb/pkg/httpc"
2018-05-24 17:34:39 +00:00
"github.com/spf13/cobra"
"github.com/spf13/viper"
2019-12-04 23:10:23 +00:00
"go.uber.org/zap"
2018-05-24 17:34:39 +00:00
)
2019-10-24 19:20:49 +00:00
const maxTCPConnections = 128
2019-10-09 21:01:23 +00:00
2019-11-21 23:10:39 +00:00
func main ( ) {
influxCmd := influxCmd ( )
if err := influxCmd . Execute ( ) ; err != nil {
os . Exit ( 1 )
}
}
2019-12-07 18:54:03 +00:00
var (
2019-12-08 04:10:22 +00:00
httpClient * httpc . Client
2019-12-07 18:54:03 +00:00
)
2019-12-08 04:10:22 +00:00
func newHTTPClient ( ) ( * httpc . Client , error ) {
2019-12-07 18:54:03 +00:00
if httpClient != nil {
return httpClient , nil
}
c , err := http . NewHTTPClient ( flags . host , flags . token , flags . skipVerify )
if err != nil {
return nil , err
}
httpClient = c
return httpClient , nil
}
2019-11-21 23:10:39 +00:00
type genericCLIOptfn func ( * genericCLIOpts )
type genericCLIOpts struct {
in io . Reader
w io . Writer
}
func ( o genericCLIOpts ) newCmd ( use string ) * cobra . Command {
cmd := & cobra . Command { Use : use }
cmd . SetOutput ( o . w )
return cmd
}
func in ( r io . Reader ) genericCLIOptfn {
return func ( o * genericCLIOpts ) {
o . in = r
}
}
func out ( w io . Writer ) genericCLIOptfn {
return func ( o * genericCLIOpts ) {
o . w = w
2019-11-20 00:55:36 +00:00
}
}
func influxCmd ( ) * cobra . Command {
cmd := & cobra . Command {
Use : "influx" ,
Short : "Influx Client" ,
Run : func ( cmd * cobra . Command , args [ ] string ) {
if err := checkSetup ( flags . host ) ; err != nil {
fmt . Printf ( "Note: %v\n" , internal . ErrorFmt ( err ) )
}
cmd . Usage ( )
} ,
}
2019-12-17 19:55:35 +00:00
viper . SetEnvPrefix ( "INFLUX" )
2019-11-20 00:55:36 +00:00
cmd . AddCommand (
2019-11-15 18:23:24 +00:00
authCmd ( ) ,
2019-10-24 19:20:49 +00:00
bucketCmd ,
deleteCmd ,
2019-11-15 18:32:57 +00:00
organizationCmd ( ) ,
2019-10-24 19:20:49 +00:00
pingCmd ,
2019-11-21 21:12:15 +00:00
cmdPkg ( newPkgerSVC ) ,
2019-10-24 19:20:49 +00:00
queryCmd ,
2019-12-04 20:31:20 +00:00
transpileCmd ,
2019-10-24 19:20:49 +00:00
replCmd ,
setupCmd ,
taskCmd ,
2019-11-20 00:55:36 +00:00
userCmd ( ) ,
2019-10-24 19:20:49 +00:00
writeCmd ,
)
2019-11-20 00:55:36 +00:00
cmd . PersistentFlags ( ) . StringVarP ( & flags . token , "token" , "t" , "" , "API token to be used throughout client calls" )
2019-10-24 19:20:49 +00:00
viper . BindEnv ( "TOKEN" )
if h := viper . GetString ( "TOKEN" ) ; h != "" {
flags . token = h
} else if tok , err := getTokenFromDefaultPath ( ) ; err == nil {
flags . token = tok
}
2019-11-20 00:55:36 +00:00
cmd . PersistentFlags ( ) . StringVar ( & flags . host , "host" , "http://localhost:9999" , "HTTP address of Influx" )
2019-10-24 19:20:49 +00:00
viper . BindEnv ( "HOST" )
if h := viper . GetString ( "HOST" ) ; h != "" {
flags . host = h
}
2019-11-20 00:55:36 +00:00
cmd . PersistentFlags ( ) . BoolVar ( & flags . local , "local" , false , "Run commands locally against the filesystem" )
2019-10-24 19:20:49 +00:00
2019-11-20 00:55:36 +00:00
cmd . PersistentFlags ( ) . BoolVar ( & flags . skipVerify , "skip-verify" , false , "SkipVerify controls whether a client verifies the server's certificate chain and host name." )
2019-11-14 23:28:43 +00:00
2019-10-24 19:20:49 +00:00
// Override help on all the commands tree
2019-11-20 00:55:36 +00:00
walk ( cmd , func ( c * cobra . Command ) {
2019-10-24 19:20:49 +00:00
c . Flags ( ) . BoolP ( "help" , "h" , false , fmt . Sprintf ( "Help for the %s command " , c . Name ( ) ) )
} )
2019-11-20 00:55:36 +00:00
return cmd
2018-05-24 17:34:39 +00:00
}
// Flags contains all the CLI flag values for influx.
type Flags struct {
2019-11-14 23:28:43 +00:00
token string
host string
local bool
skipVerify bool
2018-05-24 17:34:39 +00:00
}
var flags Flags
2019-03-05 21:51:46 +00:00
func defaultTokenPath ( ) ( string , string , error ) {
2018-11-02 02:34:22 +00:00
dir , err := fs . InfluxDir ( )
if err != nil {
2019-03-05 21:51:46 +00:00
return "" , "" , err
2018-11-02 02:34:22 +00:00
}
2019-03-05 21:51:46 +00:00
return filepath . Join ( dir , "credentials" ) , dir , nil
2018-11-02 02:34:22 +00:00
}
2019-03-05 21:51:46 +00:00
func getTokenFromDefaultPath ( ) ( string , error ) {
path , _ , err := defaultTokenPath ( )
if err != nil {
return "" , err
}
2018-11-02 02:34:22 +00:00
b , err := ioutil . ReadFile ( path )
if err != nil {
return "" , err
}
return string ( b ) , nil
}
2019-03-05 21:51:46 +00:00
func writeTokenToPath ( tok , path , dir string ) error {
if err := os . MkdirAll ( dir , os . ModePerm ) ; err != nil {
return err
}
2018-11-02 02:34:22 +00:00
return ioutil . WriteFile ( path , [ ] byte ( tok ) , 0600 )
}
2019-01-22 18:19:26 +00:00
func checkSetup ( host string ) error {
s := & http . SetupService {
2019-11-14 23:28:43 +00:00
Addr : flags . host ,
InsecureSkipVerify : flags . skipVerify ,
2019-01-22 18:19:26 +00:00
}
2019-10-24 19:20:49 +00:00
isOnboarding , err := s . IsOnboarding ( context . Background ( ) )
2019-01-22 18:19:26 +00:00
if err != nil {
return err
}
if isOnboarding {
return fmt . Errorf ( "the instance at %q has not been setup. Please run `influx setup` before issuing any additional commands" , host )
}
return nil
}
func wrapCheckSetup ( fn func ( * cobra . Command , [ ] string ) error ) func ( * cobra . Command , [ ] string ) error {
2019-01-22 19:34:01 +00:00
return wrapErrorFmt ( func ( cmd * cobra . Command , args [ ] string ) error {
2019-01-22 18:19:26 +00:00
err := fn ( cmd , args )
if err == nil {
return nil
}
2019-02-19 23:47:19 +00:00
if setupErr := checkSetup ( flags . host ) ; setupErr != nil && influxdb . EUnauthorized != influxdb . ErrorCode ( setupErr ) {
2019-01-22 19:34:01 +00:00
return setupErr
}
return err
} )
}
func wrapErrorFmt ( fn func ( * cobra . Command , [ ] string ) error ) func ( * cobra . Command , [ ] string ) error {
return func ( cmd * cobra . Command , args [ ] string ) error {
err := fn ( cmd , args )
if err == nil {
return nil
2019-01-22 18:19:26 +00:00
}
return internal . ErrorFmt ( err )
}
}
2019-01-14 18:53:37 +00:00
// walk calls f for c and all of its children.
func walk ( c * cobra . Command , f func ( * cobra . Command ) ) {
f ( c )
for _ , c := range c . Commands ( ) {
walk ( c , f )
}
}
2019-03-28 08:42:38 +00:00
func newLocalKVService ( ) ( * kv . Service , error ) {
boltFile , err := fs . BoltFile ( )
if err != nil {
return nil , err
}
2019-12-04 23:10:23 +00:00
store := bolt . NewKVStore ( zap . NewNop ( ) , boltFile )
2019-03-28 08:42:38 +00:00
if err := store . Open ( context . Background ( ) ) ; err != nil {
return nil , err
}
2019-12-04 23:10:23 +00:00
return kv . NewService ( zap . NewNop ( ) , store ) , nil
2019-03-28 08:42:38 +00:00
}
2019-12-12 17:33:15 +00:00
2019-12-17 19:55:35 +00:00
type organization struct {
id , name string
}
func ( org * organization ) register ( cmd * cobra . Command ) {
cmd . Flags ( ) . StringVarP ( & org . id , "org-id" , "" , "" , "The ID of the organization that owns the bucket" )
viper . BindEnv ( "ORG_ID" )
if h := viper . GetString ( "ORG_ID" ) ; h != "" {
org . id = h
}
cmd . Flags ( ) . StringVarP ( & org . name , "org" , "o" , "" , "The name of the organization that owns the bucket" )
viper . BindEnv ( "ORG" )
if h := viper . GetString ( "ORG" ) ; h != "" {
org . name = h
}
}
func ( org * organization ) getID ( orgSVC influxdb . OrganizationService ) ( influxdb . ID , error ) {
if org . id != "" {
influxOrgID , err := influxdb . IDFromString ( org . id )
2019-12-12 17:33:15 +00:00
if err != nil {
return 0 , fmt . Errorf ( "invalid org ID provided: %s" , err . Error ( ) )
}
return * influxOrgID , nil
2019-12-17 19:55:35 +00:00
} else if org . name != "" {
2019-12-12 17:33:15 +00:00
org , err := orgSVC . FindOrganization ( context . Background ( ) , influxdb . OrganizationFilter {
2019-12-17 19:55:35 +00:00
Name : & org . name ,
2019-12-12 17:33:15 +00:00
} )
if err != nil {
return 0 , fmt . Errorf ( "%v" , err )
}
return org . ID , nil
}
2019-12-17 19:55:35 +00:00
return 0 , fmt . Errorf ( "failed to locate an organization id" )
}
2019-12-12 17:33:15 +00:00
2019-12-17 19:55:35 +00:00
func ( org * organization ) validOrgFlags ( ) error {
if org . id == "" && org . name == "" {
return fmt . Errorf ( "must specify org-id, or org name" )
} else if org . id != "" && org . name != "" {
return fmt . Errorf ( "must specify org-id, or org name not both" )
}
return nil
2019-12-12 17:33:15 +00:00
}