package cmd
import (
"context"
"encoding/json"
"fmt"
"io/ioutil"
"os"
"os/signal"
"strings"
"syscall"
"github.com/spf13/cobra"
"github.com/webmeisterei/lql-api/lql"
log "github.com/sirupsen/logrus"
)
func init ( ) {
localClientCmdLimit := 0
localClientCmd . Flags ( ) . StringP ( "socket" , "s" , "/opt/omd/sites/{site}/tmp/run/live" , "Socket on the Server" )
localClientCmd . Flags ( ) . StringP ( "liveproxydir" , "p" , "/opt/omd/sites/{site}/tmp/run/liveproxy" , "Directory which contains liveproxy sockets" )
localClientCmd . Flags ( ) . StringP ( "multsiteusers" , "m" , "/opt/omd/sites/{site}/etc/check_mk/multisite.d/wato/users.mk" , "Your checkmks users.mk file" )
localClientCmd . Flags ( ) . BoolP ( "debug" , "d" , false , "Enable Debug on stderr" )
localClientCmd . Flags ( ) . StringP ( "format" , "f" , "jsonparsed" , "Format one of: python, python3, json, csv, CSV, jsonparsed (default is jsonparsed, I parse json from the server)" )
localClientCmd . Flags ( ) . StringP ( "table" , "t" , "" , "Produce a GET request for the given table (default: supply request by stdin)" )
localClientCmd . Flags ( ) . StringArrayP ( "columns" , "c" , [ ] string { "" } , "Columns to show from the given table, this is required if you give a table!" )
localClientCmd . Flags ( ) . StringP ( "user" , "u" , "" , "CheckMK user to limit this request on" )
localClientCmd . Flags ( ) . IntVarP ( & localClientCmdLimit , "limit" , "l" , 0 , "Limit request lines" )
rootCmd . AddCommand ( localClientCmd )
}
var localClientCmd = & cobra . Command {
Use : "localclient [site]" ,
Short : "Local LQL Client" ,
Long : ` Local LQL Client
Requires a local lql unix socket .
Examples :
- Fetch first row from the hosts table :
$ lql - api localclient mysite - t hosts - c name - c address - c groups - l 1
- The same with stdin :
$ echo - e "GET hosts\nColumns: name address groups\nLimit: 1" | lql - api localclient mysite
` ,
Args : cobra . ExactArgs ( 1 ) ,
Run : func ( cmd * cobra . Command , args [ ] string ) {
sReplacer := strings . NewReplacer ( "{site}" , args [ 0 ] )
destSocket := sReplacer . Replace ( cmd . Flag ( "socket" ) . Value . String ( ) )
liveproxyDir := sReplacer . Replace ( cmd . Flag ( "liveproxydir" ) . Value . String ( ) )
multisiteUsersFile := sReplacer . Replace ( cmd . Flag ( "multsiteusers" ) . Value . String ( ) )
var lqlClient lql . Client
logger := log . New ( )
logger . SetOutput ( os . Stderr )
if ! cmd . Flag ( "debug" ) . Changed {
logger . SetLevel ( log . InfoLevel )
} else {
logger . SetLevel ( log . TraceLevel )
}
logger . WithField ( "destSocket" , destSocket ) . Debug ( "Sockets" )
var msg string
stat , _ := os . Stdin . Stat ( )
if ( stat . Mode ( ) & os . ModeCharDevice ) == 0 {
stdinBuff , err := ioutil . ReadAll ( os . Stdin )
if err != nil {
logger . WithField ( "error" , err ) . Error ( )
return
}
logger . WithField ( "request" , string ( stdinBuff ) ) . Debug ( "Got a request from stdin" )
msg = string ( stdinBuff ) + "\n"
} else if cmd . Flag ( "table" ) . Changed {
if ! cmd . Flag ( "columns" ) . Changed {
logger . Error ( "Columns is required if you want to query a table" )
return
}
columns , err := cmd . Flags ( ) . GetStringArray ( "columns" )
if err != nil {
logger . Error ( "Failed to parse columns flag" )
return
}
msg = fmt . Sprintf ( "GET %s\n" , cmd . Flag ( "table" ) . Value . String ( ) )
msg += fmt . Sprintf ( "Columns: %s\n" , strings . Join ( columns , " " ) )
} else {
logger . Error ( "Entering data interactive is not supported yet" )
return
}
sigc := make ( chan os . Signal , 1 )
signal . Notify ( sigc , os . Interrupt , os . Kill , syscall . SIGTERM )
go func ( c chan os . Signal ) {
// Wait for a SIGINT or SIGKILL:
sig := <- c
logger . WithFields ( log . Fields { "signal" : sig } ) . Info ( "Caught signal shutting down." )
// Stop listening (and unlink the socket if unix type):
if lqlClient != nil {
lqlClient . Close ( )
}
os . Exit ( 1 )
} ( sigc )
lqlClient , err := lql . NewMultiClient ( 1 , 1 , destSocket , liveproxyDir , multisiteUsersFile )
if err != nil {
logger . WithField ( "error" , err ) . Error ( )
return
}
defer lqlClient . Close ( )
lqlClient . SetLogger ( logger )
limit , err := cmd . Flags ( ) . GetInt ( "limit" )
if err != nil {
logger . WithField ( "error" , err ) . Error ( )
return
}
format , err := cmd . Flags ( ) . GetString ( "format" )
if err != nil {
logger . WithField ( "error" , err ) . Error ( )
return
}
if format != "jsonparsed" {
result , err := lqlClient . RequestRaw ( context . TODO ( ) , msg , format , cmd . Flag ( "user" ) . Value . String ( ) , limit )
if err != nil {
logger . WithField ( "error" , err ) . Error ( )
return
}
os . Stdout . Write ( result )
os . Stdout . Write ( [ ] byte { '\n' } )
return
}
result , err := lqlClient . Request ( context . TODO ( ) , msg , cmd . Flag ( "user" ) . Value . String ( ) , limit )
if err != nil {
logger . WithField ( "error" , err ) . Error ( )
return
}
json , err := json . Marshal ( result )
if err != nil {
logger . WithField ( "error" , err ) . Error ( )
return
}
os . Stdout . Write ( json )
os . Stdout . Write ( [ ] byte { '\n' } )
} ,
}