mirror of https://github.com/apache/cassandra
Merge branch 'cassandra-5.0' into trunk
* cassandra-5.0: Add option to disable cqlsh history
This commit is contained in:
commit
ee273af1d6
|
|
@ -322,6 +322,7 @@ Merged from 4.1:
|
||||||
* Disk usage guardrail cannot be disabled when failure threshold is reached (CASSANDRA-21057)
|
* Disk usage guardrail cannot be disabled when failure threshold is reached (CASSANDRA-21057)
|
||||||
* ReadCommandController should close fast to avoid deadlock when building secondary index (CASSANDRA-19564)
|
* ReadCommandController should close fast to avoid deadlock when building secondary index (CASSANDRA-19564)
|
||||||
Merged from 4.0:
|
Merged from 4.0:
|
||||||
|
* Add option to disable cqlsh history (CASSANDRA-21180)
|
||||||
* Rate limit password changes (CASSANDRA-21202)
|
* Rate limit password changes (CASSANDRA-21202)
|
||||||
* Node does not send multiple inflight echos (CASSANDRA-18866)
|
* Node does not send multiple inflight echos (CASSANDRA-18866)
|
||||||
* Obsolete expired SSTables before compaction starts (CASSANDRA-19776)
|
* Obsolete expired SSTables before compaction starts (CASSANDRA-19776)
|
||||||
|
|
|
||||||
|
|
@ -104,6 +104,15 @@ port = 9042
|
||||||
; max_trace_wait = 10.0
|
; max_trace_wait = 10.0
|
||||||
|
|
||||||
|
|
||||||
|
[history]
|
||||||
|
;; Controls whether command history is saved to ~/.cassandra/cqlsh_history
|
||||||
|
;; When disabled, existing history will still be loaded but new commands
|
||||||
|
;; will not be saved. This can be useful for security purposes to prevent
|
||||||
|
;; sensitive commands (e.g., those containing passwords) from being persisted.
|
||||||
|
;; This can also be controlled via the --disable-history command line option.
|
||||||
|
; disabled = false
|
||||||
|
|
||||||
|
|
||||||
;[ssl]
|
;[ssl]
|
||||||
; certfile = ~/keys/cassandra.cert
|
; certfile = ~/keys/cassandra.cert
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -57,8 +57,8 @@ Example config values and documentation can be found in the
|
||||||
[[cql_history]]
|
[[cql_history]]
|
||||||
== cql history
|
== cql history
|
||||||
|
|
||||||
All CQL commands you execute are written to a history file. By default, CQL history will be written to `~/.cassandra/cql_history`. You can change this default by setting the environment variable `CQL_HISTORY` like `~/some/other/path/to/cqlsh_history` where `cqlsh_history` is a file. All parent directories to history file will be created if they do not exist. If you do not want to persist history, you can do so by setting CQL_HISTORY to /dev/null.
|
All CQL commands you execute are written to a history file. By default, CQL history will be written to `~/.cassandra/cql_history`.
|
||||||
This feature is supported from Cassandra 4.1.
|
You can change this default by setting the environment variable `CQL_HISTORY` like `~/some/other/path/to/cqlsh_history` where `cqlsh_history` is a file. All parent directories to history file will be created if they do not exist. If you do not want to persist history, you can do so by setting CQL_HISTORY to `/dev/null`. This can also be controlled via the --disable-history command line option or from the cqlshrc file. Disabling history is supported since Cassandra 4.0.
|
||||||
|
|
||||||
== Command Line Options
|
== Command Line Options
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ import subprocess
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
import traceback
|
import traceback
|
||||||
|
from typing import Any
|
||||||
import warnings
|
import warnings
|
||||||
import webbrowser
|
import webbrowser
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
|
|
@ -120,6 +121,16 @@ try:
|
||||||
except OSError:
|
except OSError:
|
||||||
print('\nWarning: Cannot create directory at `%s`. Command history will not be saved. Please check what was the environment property CQL_HISTORY set to.\n' % HISTORY_DIR)
|
print('\nWarning: Cannot create directory at `%s`. Command history will not be saved. Please check what was the environment property CQL_HISTORY set to.\n' % HISTORY_DIR)
|
||||||
|
|
||||||
|
OLD_HISTORY = os.path.expanduser(os.path.join('~', '.cqlsh_history'))
|
||||||
|
if os.path.exists(OLD_HISTORY):
|
||||||
|
if os.path.exists(HISTORY):
|
||||||
|
print('\nWarning: .cqlsh_history files were found at both the old location ({0})'
|
||||||
|
+ ' and the new location ({1}), the old file will not be migrated to the new'
|
||||||
|
+ ' location, and the new location will be used for now. You should manually'
|
||||||
|
+ ' consolidate these files at the new location, and remove the old file.'
|
||||||
|
.format(OLD_HISTORY, HISTORY))
|
||||||
|
else:
|
||||||
|
os.rename(OLD_HISTORY, HISTORY)
|
||||||
|
|
||||||
# END history config
|
# END history config
|
||||||
|
|
||||||
|
|
@ -272,7 +283,8 @@ class Shell(cmd.Cmd):
|
||||||
protocol_version=None,
|
protocol_version=None,
|
||||||
connect_timeout=DEFAULT_CONNECT_TIMEOUT_SECONDS,
|
connect_timeout=DEFAULT_CONNECT_TIMEOUT_SECONDS,
|
||||||
is_subshell=False,
|
is_subshell=False,
|
||||||
auth_provider=None):
|
auth_provider=None,
|
||||||
|
disable_history=False):
|
||||||
cmd.Cmd.__init__(self, completekey=completekey)
|
cmd.Cmd.__init__(self, completekey=completekey)
|
||||||
self.hostname = hostname
|
self.hostname = hostname
|
||||||
self.port = port
|
self.port = port
|
||||||
|
|
@ -354,6 +366,14 @@ class Shell(cmd.Cmd):
|
||||||
self.check_build_versions()
|
self.check_build_versions()
|
||||||
|
|
||||||
if tty:
|
if tty:
|
||||||
|
# Inform users about history logging if not disabled
|
||||||
|
if not disable_history and readline is not None:
|
||||||
|
print()
|
||||||
|
print("ATTENTION: All commands will be saved to history file: %s" % HISTORY)
|
||||||
|
print("This may include sensitive information such as passwords.")
|
||||||
|
print("To disable history, use --disable-history or set 'disabled = true' in the [history] section of cqlshrc.")
|
||||||
|
print("See https://cassandra.apache.org/doc/latest/tools/cqlsh.html for more information.")
|
||||||
|
print()
|
||||||
self.reset_prompt()
|
self.reset_prompt()
|
||||||
self.report_connection()
|
self.report_connection()
|
||||||
print('Use HELP for help.')
|
print('Use HELP for help.')
|
||||||
|
|
@ -1896,8 +1916,8 @@ class Shell(cmd.Cmd):
|
||||||
delims += '.'
|
delims += '.'
|
||||||
readline.set_completer_delims(delims)
|
readline.set_completer_delims(delims)
|
||||||
|
|
||||||
def save_history(self):
|
def save_history(self, history_disabled=False):
|
||||||
if readline is not None:
|
if readline is not None and not history_disabled:
|
||||||
try:
|
try:
|
||||||
readline.write_history_file(HISTORY)
|
readline.write_history_file(HISTORY)
|
||||||
except IOError:
|
except IOError:
|
||||||
|
|
@ -2037,7 +2057,7 @@ def read_options(cmdlineargs, parser, config_file, cql_dir, environment=os.envir
|
||||||
argvalues.request_timeout = option_with_default(configs.getint, 'connection', 'request_timeout', Shell.DEFAULT_REQUEST_TIMEOUT_SECONDS)
|
argvalues.request_timeout = option_with_default(configs.getint, 'connection', 'request_timeout', Shell.DEFAULT_REQUEST_TIMEOUT_SECONDS)
|
||||||
argvalues.execute = None
|
argvalues.execute = None
|
||||||
argvalues.insecure_password_without_warning = False
|
argvalues.insecure_password_without_warning = False
|
||||||
|
argvalues.disable_history = option_with_default(configs.getboolean, 'history', 'disabled', False)
|
||||||
options, arguments = parser.parse_known_args(cmdlineargs, argvalues)
|
options, arguments = parser.parse_known_args(cmdlineargs, argvalues)
|
||||||
|
|
||||||
# Credentials from cqlshrc will be expanded,
|
# Credentials from cqlshrc will be expanded,
|
||||||
|
|
@ -2208,6 +2228,8 @@ def main(cmdline, pkgpath):
|
||||||
help='Specify the default request timeout in seconds (default: %(default)s seconds).')
|
help='Specify the default request timeout in seconds (default: %(default)s seconds).')
|
||||||
parser.add_argument("-t", "--tty", action='store_true', dest='tty',
|
parser.add_argument("-t", "--tty", action='store_true', dest='tty',
|
||||||
help='Force tty mode (command prompt).')
|
help='Force tty mode (command prompt).')
|
||||||
|
parser.add_argument('--disable-history', default=False, action='store_true',
|
||||||
|
help='Disable saving of history (existing history will still be loaded)')
|
||||||
|
|
||||||
# This is a hidden option to suppress the warning when the -p/--password command line option is used.
|
# This is a hidden option to suppress the warning when the -p/--password command line option is used.
|
||||||
# Power users may use this option if they know no other people has access to the system where cqlsh is run or don't care about security.
|
# Power users may use this option if they know no other people has access to the system where cqlsh is run or don't care about security.
|
||||||
|
|
@ -2233,6 +2255,18 @@ def main(cmdline, pkgpath):
|
||||||
config_file = default_cqlshrc
|
config_file = default_cqlshrc
|
||||||
|
|
||||||
cql_dir = os.path.dirname(config_file)
|
cql_dir = os.path.dirname(config_file)
|
||||||
|
|
||||||
|
old_config_file = os.path.expanduser(os.path.join('~', '.cqlshrc'))
|
||||||
|
if os.path.exists(old_config_file):
|
||||||
|
if os.path.exists(config_file):
|
||||||
|
print('\nWarning: cqlshrc config files were found at both the old location ({0})'
|
||||||
|
+ ' and the new location ({1}), the old config file will not be migrated to the new'
|
||||||
|
+ ' location, and the new location will be used for now. You should manually'
|
||||||
|
+ ' consolidate the config files at the new location and remove the old file.'
|
||||||
|
.format(old_config_file, config_file))
|
||||||
|
else:
|
||||||
|
os.rename(old_config_file, config_file)
|
||||||
|
|
||||||
(options, hostname, port) = read_options(cmdline, parser, config_file, cql_dir)
|
(options, hostname, port) = read_options(cmdline, parser, config_file, cql_dir)
|
||||||
|
|
||||||
docspath = get_docspath(pkgpath)
|
docspath = get_docspath(pkgpath)
|
||||||
|
|
@ -2332,7 +2366,8 @@ def main(cmdline, pkgpath):
|
||||||
config_file=config_file,
|
config_file=config_file,
|
||||||
cred_file=options.credentials,
|
cred_file=options.credentials,
|
||||||
username=options.username,
|
username=options.username,
|
||||||
password=options.password))
|
password=options.password),
|
||||||
|
disable_history=options.disable_history)
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
sys.exit('Connection aborted.')
|
sys.exit('Connection aborted.')
|
||||||
except CQL_ERRORS as e:
|
except CQL_ERRORS as e:
|
||||||
|
|
@ -2353,7 +2388,7 @@ def main(cmdline, pkgpath):
|
||||||
|
|
||||||
shell.init_history()
|
shell.init_history()
|
||||||
shell.cmdloop()
|
shell.cmdloop()
|
||||||
shell.save_history()
|
shell.save_history(options.disable_history)
|
||||||
|
|
||||||
if shell.batch_mode and shell.statement_error:
|
if shell.batch_mode and shell.statement_error:
|
||||||
sys.exit(2)
|
sys.exit(2)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue