mirror of https://gitee.com/bigwinds/arangodb
675 lines
21 KiB
C++
675 lines
21 KiB
C++
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief arango shell client base
|
|
///
|
|
/// @file
|
|
///
|
|
/// DISCLAIMER
|
|
///
|
|
/// Copyright 2004-2012 triAGENS GmbH, Cologne, Germany
|
|
///
|
|
/// Licensed under the Apache License, Version 2.0 (the "License");
|
|
/// you may not use this file except in compliance with the License.
|
|
/// You may obtain a copy of the License at
|
|
///
|
|
/// http://www.apache.org/licenses/LICENSE-2.0
|
|
///
|
|
/// Unless required by applicable law or agreed to in writing, software
|
|
/// distributed under the License is distributed on an "AS IS" BASIS,
|
|
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
/// See the License for the specific language governing permissions and
|
|
/// limitations under the License.
|
|
///
|
|
/// Copyright holder is triAGENS GmbH, Cologne, Germany
|
|
///
|
|
/// @author Dr. Frank Celler
|
|
/// @author Copyright 2012, triAGENS GmbH, Cologne, Germany
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "ArangoClient.h"
|
|
|
|
#include "BasicsC/logging.h"
|
|
#include "BasicsC/terminal-utils.h"
|
|
#include "Basics/FileUtils.h"
|
|
#include "Basics/ProgramOptionsDescription.h"
|
|
#include "Basics/ProgramOptions.h"
|
|
#include "Logger/Logger.h"
|
|
|
|
using namespace std;
|
|
using namespace triagens::basics;
|
|
using namespace triagens::rest;
|
|
using namespace triagens::arango;
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// --SECTION-- class ArangoClient
|
|
// -----------------------------------------------------------------------------
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// --SECTION-- public constants
|
|
// -----------------------------------------------------------------------------
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @addtogroup ArangoShell
|
|
/// @{
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief color red
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
char const * ArangoClient::COLOR_RED = "\x1b[31m";
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief color blod red
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
char const * ArangoClient::COLOR_BOLD_RED = "\x1b[1;31m";
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief color green
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
char const * ArangoClient::COLOR_GREEN = "\x1b[32m";
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief color bold green
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
char const * ArangoClient::COLOR_BOLD_GREEN = "\x1b[1;32m";
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief color blue
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
char const * ArangoClient::COLOR_BLUE = "\x1b[34m";
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief color bold blue
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
char const * ArangoClient::COLOR_BOLD_BLUE = "\x1b[1;34m";
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief color yellow
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
char const * ArangoClient::COLOR_YELLOW = "\x1b[33m";
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief color yellow
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
char const * ArangoClient::COLOR_BOLD_YELLOW = "\x1b[1;33m";
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief color white
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
char const * ArangoClient::COLOR_WHITE = "\x1b[37m";
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief color bold white
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
char const * ArangoClient::COLOR_BOLD_WHITE = "\x1b[1;37m";
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief color black
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
char const * ArangoClient::COLOR_BLACK = "\x1b[30m";
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief color bold black
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
char const * ArangoClient::COLOR_BOLD_BLACK = "\x1b[1;39m";
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief color blink
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
char const * ArangoClient::COLOR_BLINK = "\x1b[5m";
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief color bright
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
char const * ArangoClient::COLOR_BRIGHT = "\x1b[1m";
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief color reset
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
char const * ArangoClient::COLOR_RESET = "\x1b[0m";
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @}
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// --SECTION-- constructors and destructors
|
|
// -----------------------------------------------------------------------------
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @addtogroup ArangoShell
|
|
/// @{
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief constructor
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
ArangoClient::ArangoClient ()
|
|
: _configFile(),
|
|
_logLevel("info"),
|
|
_quiet(false),
|
|
|
|
_colorOptions(false),
|
|
_noColors(false),
|
|
|
|
_autoCompleteOptions(false),
|
|
_noAutoComplete(false),
|
|
|
|
_prettyPrintOptions(false),
|
|
_prettyPrint(false),
|
|
|
|
_pagerOptions(false),
|
|
_outputPager("less -X -R -F -L"),
|
|
_pager(stdout),
|
|
_usePager(false),
|
|
|
|
_serverOptions(false),
|
|
_endpointString(),
|
|
_endpointServer(0),
|
|
_username("root"),
|
|
_password(""),
|
|
_hasPassword(false),
|
|
_connectTimeout(DEFAULT_CONNECTION_TIMEOUT),
|
|
_requestTimeout(DEFAULT_REQUEST_TIMEOUT) {
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @}
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// --SECTION-- public methods
|
|
// -----------------------------------------------------------------------------
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @addtogroup ArangoShell
|
|
/// @{
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief sets up the general and logging options
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void ArangoClient::setupGeneral (ProgramOptionsDescription& description) {
|
|
ProgramOptionsDescription loggingOptions("LOGGING options");
|
|
|
|
loggingOptions
|
|
("log.level,l", &_logLevel, "log level")
|
|
;
|
|
|
|
description
|
|
("configuration,c", &_configFile, "read configuration file")
|
|
("help,h", "help message")
|
|
("quiet,s", "no banner")
|
|
(loggingOptions, false)
|
|
;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief sets up the color options
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void ArangoClient::setupColors (ProgramOptionsDescription& description) {
|
|
ProgramOptionsDescription hiddenOptions("HIDDEN options");
|
|
|
|
hiddenOptions
|
|
("colors", "activate color support")
|
|
;
|
|
|
|
description
|
|
("no-colors", "deactivate color support")
|
|
(hiddenOptions, true)
|
|
;
|
|
|
|
_colorOptions = true;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief sets up the auto-complete options
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void ArangoClient::setupAutoComplete (ProgramOptionsDescription& description) {
|
|
ProgramOptionsDescription hiddenOptions("HIDDEN options");
|
|
|
|
hiddenOptions
|
|
("auto-complete", "enable auto completion, use no-auto-complete to disable")
|
|
;
|
|
|
|
description
|
|
("no-auto-complete", "disable auto completion")
|
|
(hiddenOptions, true)
|
|
;
|
|
|
|
_autoCompleteOptions = true;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief sets up the pretty-printing options
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void ArangoClient::setupPrettyPrint (ProgramOptionsDescription& description) {
|
|
ProgramOptionsDescription hiddenOptions("HIDDEN options");
|
|
|
|
hiddenOptions
|
|
("no-pretty-print", "disable pretty printting")
|
|
;
|
|
|
|
description
|
|
("pretty-print", "pretty print values")
|
|
(hiddenOptions, true)
|
|
;
|
|
|
|
_prettyPrintOptions = true;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief sets up the pager options
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void ArangoClient::setupPager (ProgramOptionsDescription& description) {
|
|
description
|
|
("pager", &_outputPager, "output pager")
|
|
("use-pager", "use pager")
|
|
;
|
|
|
|
_pagerOptions = true;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief sets up the server options
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void ArangoClient::setupServer (ProgramOptionsDescription& description) {
|
|
ProgramOptionsDescription clientOptions("CLIENT options");
|
|
|
|
clientOptions
|
|
("server.endpoint", &_endpointString, "endpoint to connect to, use 'none' to start without a server")
|
|
("server.username", &_username, "username to use when connecting")
|
|
("server.password", &_password, "password to use when connecting (leave empty for prompt)")
|
|
("server.connect-timeout", &_connectTimeout, "connect timeout in seconds")
|
|
("server.request-timeout", &_requestTimeout, "request timeout in seconds")
|
|
;
|
|
|
|
description(clientOptions, false);
|
|
|
|
_serverOptions = true;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief parses command line and config file and prepares logging
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void ArangoClient::parse (ProgramOptions& options, ProgramOptionsDescription& description, int argc, char* argv[]) {
|
|
if (! options.parse(description, argc, argv)) {
|
|
cerr << options.lastError() << "\n";
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
// check for help
|
|
set<string> help = options.needHelp("help");
|
|
|
|
if (! help.empty()) {
|
|
cout << description.usage(help) << endl;
|
|
exit(EXIT_SUCCESS);
|
|
}
|
|
|
|
// setup the logging
|
|
TRI_SetLogLevelLogging(_logLevel.c_str());
|
|
TRI_CreateLogAppenderFile("-");
|
|
TRI_SetLineNumberLogging(false);
|
|
|
|
// parse config file
|
|
string configFile = "";
|
|
|
|
if (! _configFile.empty()) {
|
|
if (StringUtils::tolower(_configFile) == string("none")) {
|
|
LOGGER_INFO << "using no init file at all";
|
|
}
|
|
else {
|
|
configFile = _configFile;
|
|
}
|
|
}
|
|
|
|
#ifdef _SYSCONFDIR_
|
|
|
|
else {
|
|
string sysDir = string(_SYSCONFDIR_);
|
|
string systemConfigFile = "arangosh.conf";
|
|
|
|
if (! sysDir.empty()) {
|
|
if (sysDir[sysDir.size() - 1] != '/') {
|
|
sysDir += "/" + systemConfigFile;
|
|
}
|
|
else {
|
|
sysDir += systemConfigFile;
|
|
}
|
|
|
|
if (FileUtils::exists(sysDir)) {
|
|
configFile = sysDir;
|
|
}
|
|
else {
|
|
LOGGER_DEBUG << "no system init file '" << sysDir << "'";
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
if (! configFile.empty()) {
|
|
LOGGER_DEBUG << "using init file '" << configFile << "'";
|
|
|
|
if (! options.parse(description, configFile)) {
|
|
cout << "cannot parse config file '" << configFile << "': " << options.lastError() << endl;
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
}
|
|
|
|
// check if have a password
|
|
_hasPassword = options.has("server.password");
|
|
|
|
// set colors
|
|
if (options.has("colors")) {
|
|
_noColors = false;
|
|
}
|
|
|
|
if (options.has("no-colors")) {
|
|
_noColors = true;
|
|
}
|
|
|
|
// set auto-completion
|
|
if (options.has("auto-complete")) {
|
|
_noAutoComplete = false;
|
|
}
|
|
|
|
if (options.has("no-auto-complete")) {
|
|
_noAutoComplete = true;
|
|
}
|
|
|
|
// set pretty print
|
|
if (options.has("pretty-print")) {
|
|
_prettyPrint = true;
|
|
}
|
|
|
|
if (options.has("no-pretty-print")) {
|
|
_prettyPrint = false;
|
|
}
|
|
|
|
// set pager
|
|
if (options.has("use-pager")) {
|
|
_usePager = true;
|
|
}
|
|
|
|
// set quiet
|
|
if (options.has("quiet")) {
|
|
_quiet = true;
|
|
}
|
|
|
|
// .............................................................................
|
|
// server options
|
|
// .............................................................................
|
|
|
|
if (_serverOptions) {
|
|
|
|
// check connection args
|
|
if (_connectTimeout <= 0) {
|
|
cerr << "invalid value for --server.connect-timeout, must be positive" << endl;
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
if (_requestTimeout <= 0) {
|
|
cerr << "invalid value for --server.request-timeout, must be positive" << endl;
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
// must specify a user name
|
|
if (_username.size() == 0) {
|
|
cerr << "no value specified for --server.username" << endl;
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
// no password given on command-line
|
|
if (! _hasPassword) {
|
|
cout << "Please specify a password: " << flush;
|
|
|
|
// now prompt for it
|
|
#ifdef TRI_HAVE_TERMIOS_H
|
|
TRI_SetStdinVisibility(false);
|
|
getline(cin, _password);
|
|
|
|
TRI_SetStdinVisibility(true);
|
|
#else
|
|
getline(cin, _password);
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief starts pager
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void ArangoClient::startPager () {
|
|
if (! _usePager || _outputPager == "" || _outputPager == "stdout" || _outputPager == "-") {
|
|
_pager = stdout;
|
|
return;
|
|
}
|
|
|
|
_pager = popen(_outputPager.c_str(), "w");
|
|
|
|
if (_pager == 0) {
|
|
printf("popen() failed! Using stdout instead!\n");
|
|
_pager = stdout;
|
|
_usePager = false;
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief stops pager
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void ArangoClient::stopPager () {
|
|
if (_pager != stdout) {
|
|
pclose(_pager);
|
|
_pager = stdout;
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief print to pager
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void ArangoClient::internalPrint (const char* format, const char* str) {
|
|
if (str) {
|
|
fprintf(_pager, format, str);
|
|
}
|
|
else {
|
|
fprintf(_pager, "%s", format);
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief print info message
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void ArangoClient::printWelcomeInfo () {
|
|
if (_usePager) {
|
|
cout << "Using pager '" << _outputPager << "' for output buffering." << endl;
|
|
}
|
|
|
|
if (_prettyPrint) {
|
|
cout << "Pretty print values." << endl;
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief print bye-bye
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void ArangoClient::printByeBye () {
|
|
if (! _quiet) {
|
|
cout << endl << "Bye Bye! Auf Wiedersehen! До свидания! さようなら" << endl;
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief creates an new endpoint
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void ArangoClient::createEndpoint () {
|
|
createEndpoint(_endpointString);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief creates an new endpoint
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void ArangoClient::createEndpoint (string const& definition) {
|
|
|
|
// close previous endpoint
|
|
if (_endpointServer != 0) {
|
|
delete _endpointServer;
|
|
}
|
|
|
|
_endpointServer = Endpoint::clientFactory(definition);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief quiet start
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
bool ArangoClient::quiet () const {
|
|
return _quiet;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief deactivate colors
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
bool ArangoClient::colors () const {
|
|
return ! _noColors;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief gets the auto completion flag
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
bool ArangoClient::autoComplete () const {
|
|
return ! _noAutoComplete;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief use pretty print
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
bool ArangoClient::prettyPrint () const {
|
|
return _prettyPrint;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief gets the output pager
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
string const& ArangoClient::outputPager () const {
|
|
return _outputPager;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief gets use pager
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
bool ArangoClient::usePager () const {
|
|
return _usePager;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief sets use pager
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void ArangoClient::setUsePager (bool value) {
|
|
_usePager = value;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief gets endpoint to connect to as string
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
string const& ArangoClient::endpointString () const {
|
|
return _endpointString;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief sets endpoint to connect to as string
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void ArangoClient::setEndpointString (string const& value) {
|
|
_endpointString = value;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief endpoint
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
Endpoint* ArangoClient::endpointServer() const {
|
|
return _endpointServer;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief user to send to endpoint
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
string const& ArangoClient::username () const {
|
|
return _username;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief password to send to endpoint
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
string const& ArangoClient::password () const {
|
|
return _password;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief connect timeout (in seconds)
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
double ArangoClient::connectTimeout () const {
|
|
return _connectTimeout;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief request timeout (in seconds)
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
double ArangoClient::requestTimeout () const {
|
|
return _requestTimeout;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @}
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// --SECTION-- END-OF-FILE
|
|
// -----------------------------------------------------------------------------
|
|
|
|
// Local Variables:
|
|
// mode: outline-minor
|
|
// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|/// @page\\|// --SECTION--\\|/// @\\}\\)"
|
|
// End:
|