Skip to content

Commit 0f50ed4

Browse files
committed
{185248490} Skip external auth tunable in cdb2_sqlreplay by default, add flag to override
Signed-off-by: Salil Chandra <schandra107@bloomberg.net>
1 parent bfb661f commit 0f50ed4

3 files changed

Lines changed: 120 additions & 0 deletions

File tree

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
ifeq ($(TESTSROOTDIR),)
2+
include ../testcase.mk
3+
else
4+
include $(TESTSROOTDIR)/testcase.mk
5+
endif
6+
ifeq ($(TEST_TIMEOUT),)
7+
export TEST_TIMEOUT=5m
8+
endif
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
#!/usr/bin/env bash
2+
bash -n "$0" | exit 1
3+
4+
# Verify that cdb2_sqlreplay skips 'PUT TUNABLE externalauth' by default, and
5+
# replays it when --replay-externalauth is given. We assert on the tool's own
6+
# (verbose) behavior rather than flipping externalauth on a live db, since
7+
# enabling externalauth can break connectivity for a db with no auth backend.
8+
9+
source ${TESTSROOTDIR}/tools/runit_common.sh
10+
11+
CDB2_SQLREPLAY_EXE=${CDB2_SQLREPLAY_EXE:-${BUILDDIR}/tools/cdb2_sqlreplay/cdb2_sqlreplay}
12+
13+
cdb2sql ${CDB2_OPTIONS} ${DBNAME} default "create table t1 { schema { int id } }"
14+
15+
# Build a replay log. Each line is one JSON event as emitted by the event
16+
# logger. We interleave marker inserts with several 'put tunable externalauth'
17+
# variants (quoted, uppercase) plus a similarly-named tunable that must NOT be
18+
# skipped (externalauth_warn).
19+
cat > replay.log <<'EOF'
20+
{"type":"sql","time":1,"sql":"insert into t1(id) values(1)"}
21+
{"type":"sql","time":2,"sql":"put tunable externalauth 'off'"}
22+
{"type":"sql","time":3,"sql":"PUT TUNABLE externalauth 'off'"}
23+
{"type":"sql","time":4,"sql":"put tunable externalauth_warn 'off'"}
24+
{"type":"sql","time":5,"sql":"insert into t1(id) values(2)"}
25+
EOF
26+
27+
########################################################################
28+
# Default behavior: externalauth statements are skipped.
29+
########################################################################
30+
echo "=== default replay (externalauth should be skipped) ==="
31+
${CDB2_SQLREPLAY_EXE} --verbose ${DBNAME} replay.log > default.out 2>&1
32+
cat default.out
33+
34+
# Both externalauth variants must be skipped ...
35+
skipped=$(grep -c "^skipping.*externalauth" default.out)
36+
assertres $skipped 2
37+
38+
# ... and the executed (bare) sql line for them must be absent.
39+
ran=$(grep -c "^put tunable externalauth 'off'$" default.out)
40+
assertres $ran 0
41+
ran=$(grep -c "^PUT TUNABLE externalauth 'off'$" default.out)
42+
assertres $ran 0
43+
44+
# The lookalike tunable must NOT be skipped.
45+
skippedwarn=$(grep -c "skipping.*externalauth_warn" default.out)
46+
assertres $skippedwarn 0
47+
48+
# Replay must continue past the skipped statements: both markers inserted.
49+
cnt=$(cdb2sql --tabs ${CDB2_OPTIONS} ${DBNAME} default "select count(*) from t1")
50+
assertres $cnt 2
51+
52+
########################################################################
53+
# --replay-externalauth: externalauth statements are replayed.
54+
########################################################################
55+
cdb2sql ${CDB2_OPTIONS} ${DBNAME} default "truncate t1"
56+
57+
echo "=== replay with --replay-externalauth (externalauth should run) ==="
58+
${CDB2_SQLREPLAY_EXE} --verbose --replay-externalauth ${DBNAME} replay.log > allow.out 2>&1
59+
cat allow.out
60+
61+
# Nothing should be skipped now.
62+
skipped=$(grep -c "^skipping" allow.out)
63+
assertres $skipped 0
64+
65+
# The externalauth statements must actually be handed to the server (verbose
66+
# prints the bare sql line right before running it).
67+
ran=$(grep -c "^put tunable externalauth 'off'$" allow.out)
68+
assertres $ran 1
69+
ran=$(grep -c "^PUT TUNABLE externalauth 'off'$" allow.out)
70+
assertres $ran 1
71+
72+
# Every replayed statement (including externalauth) executed without error.
73+
errs=$(grep -c "Error: run rc" allow.out)
74+
assertres $errs 0
75+
76+
# Connection stays healthy and markers still replay.
77+
cnt=$(cdb2sql --tabs ${CDB2_OPTIONS} ${DBNAME} default "select count(*) from t1")
78+
assertres $cnt 2
79+
80+
echo "Success"
81+
exit 0

tools/cdb2_sqlreplay/cdb2_sqlreplay.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ std::map<std::string, std::list<cson_value*>> transactions;
5050

5151
bool diffs = false;
5252
bool verbose = false;
53+
bool replay_externalauth = false; /* skip 'PUT TUNABLE externalauth' by default */
5354
int threshold_percent = 5;
5455

5556
int64_t maxevents = 0;
@@ -64,6 +65,8 @@ static const char *usage_text =
6465
" --verbose Lots of verbose output\n"
6566
" --threshold N Set diff threshold to N% (default 5)\n"
6667
" --stopat N Stop after N events processed\n"
68+
" --replay-externalauth Replay 'PUT TUNABLE externalauth' statements\n"
69+
" (skipped by default)\n"
6770
"\n"
6871
;
6972

@@ -699,6 +702,26 @@ void dump_sql_event(cson_value *event) {
699702
printf("tranid 0 %s", sql.c_str());
700703
}
701704

705+
/* Detect a 'PUT TUNABLE externalauth ...' statement (case-insensitive). The
706+
tunable name may optionally be quoted, e.g. put tunable 'externalauth' 1. */
707+
static bool is_put_tunable_externalauth(const char *sql) {
708+
if (sql == nullptr)
709+
return false;
710+
std::string s(sql);
711+
std::transform(s.begin(), s.end(), s.begin(), ::tolower);
712+
std::istringstream iss(s);
713+
std::vector<std::string> toks;
714+
std::string tok;
715+
while (iss >> tok)
716+
toks.push_back(tok);
717+
if (toks.size() < 3 || toks[0] != "put" || toks[1] != "tunable")
718+
return false;
719+
std::string name = toks[2];
720+
if (name.size() >= 2 && (name.front() == '\'' || name.front() == '"'))
721+
name = name.substr(1, name.size() - 2);
722+
return name == "externalauth";
723+
}
724+
702725
void replay(cdb2_hndl_tp *db, cson_value *event_val) {
703726
const char *sql = get_strprop(event_val, "sql");
704727
if(sql == nullptr) {
@@ -715,6 +738,12 @@ void replay(cdb2_hndl_tp *db, cson_value *event_val) {
715738
sql = (*s).second.c_str();
716739
}
717740

741+
if (!replay_externalauth && is_put_tunable_externalauth(sql)) {
742+
if (verbose)
743+
std::cout << "skipping (use --replay-externalauth to replay): " << sql << std::endl;
744+
return;
745+
}
746+
718747
std::vector<uint8_t *> blobs_vect;
719748
bool ok = do_bindings(db, event_val, blobs_vect);
720749
if (!ok) {
@@ -1126,6 +1155,8 @@ int main(int argc, char **argv) {
11261155
}
11271156
threshold_percent = (int) strtol(argv[0], nullptr, 10);
11281157
}
1158+
else if (strcmp(argv[0], "--replay-externalauth") == 0)
1159+
replay_externalauth = true;
11291160
else if (strcmp(argv[0], "--stopat") == 0) {
11301161
argc--;
11311162
argv++;

0 commit comments

Comments
 (0)