/Users/deen/code/yugabyte-db/ent/src/yb/tools/yb-admin-test_ent.cc
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright (c) YugaByte, Inc. |
2 | | // |
3 | | // |
4 | | // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except |
5 | | // in compliance with the License. You may obtain a copy of the License at |
6 | | // |
7 | | // http://www.apache.org/licenses/LICENSE-2.0 |
8 | | // |
9 | | // Unless required by applicable law or agreed to in writing, software distributed under the License |
10 | | // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express |
11 | | // or implied. See the License for the specific language governing permissions and limitations |
12 | | // under the License. |
13 | | |
14 | | // Tests for the EE yb-admin command-line tool. |
15 | | |
16 | | #include "yb/client/client.h" |
17 | | #include "yb/client/ql-dml-test-base.h" |
18 | | #include "yb/client/schema.h" |
19 | | #include "yb/client/table.h" |
20 | | #include "yb/client/table_info.h" |
21 | | |
22 | | #include "yb/integration-tests/external_mini_cluster_ent.h" |
23 | | |
24 | | #include "yb/master/master_backup.proxy.h" |
25 | | |
26 | | #include "yb/rpc/secure_stream.h" |
27 | | |
28 | | #include "yb/tools/admin-test-base.h" |
29 | | #include "yb/tools/yb-admin_util.h" |
30 | | |
31 | | #include "yb/tserver/mini_tablet_server.h" |
32 | | #include "yb/client/table_alterer.h" |
33 | | #include "yb/tserver/tablet_server.h" |
34 | | |
35 | | #include "yb/util/date_time.h" |
36 | | #include "yb/util/env_util.h" |
37 | | #include "yb/util/path_util.h" |
38 | | #include "yb/util/subprocess.h" |
39 | | #include "yb/util/test_util.h" |
40 | | #include "yb/util/tsan_util.h" |
41 | | |
42 | | DECLARE_string(certs_dir); |
43 | | |
44 | | namespace yb { |
45 | | namespace tools { |
46 | | |
47 | | using namespace std::literals; |
48 | | |
49 | | using std::shared_ptr; |
50 | | using std::string; |
51 | | |
52 | | using client::YBTable; |
53 | | using client::YBTableInfo; |
54 | | using client::YBTableName; |
55 | | using client::Transactional; |
56 | | using master::ListSnapshotsRequestPB; |
57 | | using master::ListSnapshotsResponsePB; |
58 | | using master::ListSnapshotRestorationsRequestPB; |
59 | | using master::ListSnapshotRestorationsResponsePB; |
60 | | using master::MasterBackupProxy; |
61 | | using master::SysCDCStreamEntryPB; |
62 | | using master::SysSnapshotEntryPB; |
63 | | using rpc::RpcController; |
64 | | |
65 | | class AdminCliTest : public client::KeyValueTableTest<MiniCluster> { |
66 | | protected: |
67 | 0 | Result<MasterBackupProxy*> BackupServiceProxy() { |
68 | 0 | if (!backup_service_proxy_) { |
69 | 0 | backup_service_proxy_.reset(new MasterBackupProxy( |
70 | 0 | &client_->proxy_cache(), |
71 | 0 | VERIFY_RESULT(cluster_->GetLeaderMasterBoundRpcAddr()))); |
72 | 0 | } |
73 | 0 | return backup_service_proxy_.get(); |
74 | 0 | } |
75 | | |
76 | | template <class... Args> |
77 | 0 | Result<std::string> RunAdminToolCommand(MiniCluster* cluster, Args&&... args) { |
78 | 0 | return tools::RunAdminToolCommand(cluster->GetMasterAddresses(), std::forward<Args>(args)...); |
79 | 0 | } Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA27_KcEEENS_6ResultINSt3__112basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEEPNS_11MiniClusterEDpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA17_KcEEENS_6ResultINSt3__112basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEEPNS_11MiniClusterEDpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA17_KcNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEES5_EEENS_6ResultISC_EEPNS_11MiniClusterEDpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA16_KcRKNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEESE_SE_EEENS_6ResultISC_EEPNS_11MiniClusterEDpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA16_KcRKNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEESE_SC_EEENS_6ResultISC_EEPNS_11MiniClusterEDpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA16_KcRKNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEEEEENS_6ResultISC_EEPNS_11MiniClusterEDpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA17_KcRKNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEEEEENS_6ResultISC_EEPNS_11MiniClusterEDpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA17_KcRKNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEESC_EEENS_6ResultISC_EEPNS_11MiniClusterEDpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA17_KcRKNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEERSC_EEENS_6ResultISC_EEPNS_11MiniClusterEDpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA17_KcRKNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEERA6_S3_RSC_EEENS_6ResultISC_EEPNS_11MiniClusterEDpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA16_KcRNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEERKSC_EEENS_6ResultISC_EEPNS_11MiniClusterEDpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA16_KcRKNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEESE_SE_SE_EEENS_6ResultISC_EEPNS_11MiniClusterEDpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA16_KcRKNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEESE_SC_SC_EEENS_6ResultISC_EEPNS_11MiniClusterEDpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA16_KcRKNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEESC_EEENS_6ResultISC_EEPNS_11MiniClusterEDpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA16_KcRKNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEESC_SE_EEENS_6ResultISC_EEPNS_11MiniClusterEDpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA16_KcRKNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEESC_SE_SE_EEENS_6ResultISC_EEPNS_11MiniClusterEDpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA16_KcRKNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEESC_SE_SC_EEENS_6ResultISC_EEPNS_11MiniClusterEDpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA16_KcRKNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEESC_SC_SC_EEENS_6ResultISC_EEPNS_11MiniClusterEDpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA16_KcRKNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEESC_SC_EEENS_6ResultISC_EEPNS_11MiniClusterEDpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA17_KcRNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEEEEENS_6ResultISC_EEPNS_11MiniClusterEDpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA27_KcRKNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEESC_SE_EEENS_6ResultISC_EEPNS_11MiniClusterEDpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA28_KcRKNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEEEEENS_6ResultISC_EEPNS_11MiniClusterEDpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA16_KcRKNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEESE_EEENS_6ResultISC_EEPNS_11MiniClusterEDpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA23_KcRKNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEEEEENS_6ResultISC_EEPNS_11MiniClusterEDpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA27_KcRKNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEESC_SE_RSC_EEENS_6ResultISC_EEPNS_11MiniClusterEDpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA27_KcRKNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEERA10_S3_RSC_EEENS_6ResultISC_EEPNS_11MiniClusterEDpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA33_KcRKNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEEiEEENS_6ResultISC_EEPNS_11MiniClusterEDpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA33_KcRNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEEiEEENS_6ResultISC_EEPNS_11MiniClusterEDpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA27_KcRNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEESC_RKSC_EEENS_6ResultISC_EEPNS_11MiniClusterEDpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA27_KcRNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEERA10_S3_SD_EEENS_6ResultISC_EEPNS_11MiniClusterEDpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA28_KcRNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEEEEENS_6ResultISC_EEPNS_11MiniClusterEDpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA27_KcRKNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEESC_SC_EEENS_6ResultISC_EEPNS_11MiniClusterEDpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA27_KcRKNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEERA21_S3_SC_EEENS_6ResultISC_EEPNS_11MiniClusterEDpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA27_KcRKNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEERA13_S3_SE_EEENS_6ResultISC_EEPNS_11MiniClusterEDpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA27_KcRKNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEERA10_S3_SE_EEENS_6ResultISC_EEPNS_11MiniClusterEDpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA27_KcRKNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEERA10_S3_SE_RSC_EEENS_6ResultISC_EEPNS_11MiniClusterEDpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA18_KcRNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEEEEENS_6ResultISC_EEPNS_11MiniClusterEDpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA18_KcRNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEERA13_S3_EEENS_6ResultISC_EEPNS_11MiniClusterEDpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA28_KcRKNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEERA14_S3_EEENS_6ResultISC_EEPNS_11MiniClusterEDpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA18_KcRKNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEEEEENS_6ResultISC_EEPNS_11MiniClusterEDpOT_ |
80 | | |
81 | | template <class... Args> |
82 | 0 | Result<std::string> RunAdminToolCommand(Args&&... args) { |
83 | 0 | return RunAdminToolCommand(cluster_.get(), std::forward<Args>(args)...); |
84 | 0 | } Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA27_KcEEENS_6ResultINSt3__112basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEEDpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA17_KcEEENS_6ResultINSt3__112basic_stringIcNS7_11char_traitsIcEENS7_9allocatorIcEEEEEEDpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA17_KcNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEES5_EEENS_6ResultISC_EEDpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA16_KcRKNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEESE_EEENS_6ResultISC_EEDpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA16_KcRKNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEESE_SE_EEENS_6ResultISC_EEDpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA16_KcRKNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEESE_SC_EEENS_6ResultISC_EEDpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA16_KcRKNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEEEEENS_6ResultISC_EEDpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA17_KcRKNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEEEEENS_6ResultISC_EEDpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA17_KcRKNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEESC_EEENS_6ResultISC_EEDpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA17_KcRKNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEERSC_EEENS_6ResultISC_EEDpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA17_KcRKNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEERA6_S3_RSC_EEENS_6ResultISC_EEDpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA16_KcRNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEERKSC_EEENS_6ResultISC_EEDpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA16_KcRKNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEESE_SE_SE_EEENS_6ResultISC_EEDpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA16_KcRKNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEESE_SC_SC_EEENS_6ResultISC_EEDpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA16_KcRKNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEESC_EEENS_6ResultISC_EEDpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA16_KcRKNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEESC_SE_EEENS_6ResultISC_EEDpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA16_KcRKNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEESC_SE_SE_EEENS_6ResultISC_EEDpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA16_KcRKNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEESC_SE_SC_EEENS_6ResultISC_EEDpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA16_KcRKNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEESC_SC_SC_EEENS_6ResultISC_EEDpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA16_KcRKNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEESC_SC_EEENS_6ResultISC_EEDpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA17_KcRNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEEEEENS_6ResultISC_EEDpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA27_KcRKNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEESC_SE_EEENS_6ResultISC_EEDpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA28_KcRKNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEEEEENS_6ResultISC_EEDpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA27_KcRKNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEESC_SE_RSC_EEENS_6ResultISC_EEDpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA27_KcRKNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEERA10_S3_RSC_EEENS_6ResultISC_EEDpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA33_KcRKNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEEiEEENS_6ResultISC_EEDpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA33_KcRNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEEiEEENS_6ResultISC_EEDpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA27_KcRNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEESC_RKSC_EEENS_6ResultISC_EEDpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA27_KcRNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEERA10_S3_SD_EEENS_6ResultISC_EEDpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA28_KcRNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEEEEENS_6ResultISC_EEDpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA27_KcRKNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEESC_SC_EEENS_6ResultISC_EEDpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA27_KcRKNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEERA21_S3_SC_EEENS_6ResultISC_EEDpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA27_KcRKNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEERA13_S3_SE_EEENS_6ResultISC_EEDpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA27_KcRKNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEERA10_S3_SE_EEENS_6ResultISC_EEDpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA27_KcRKNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEERA10_S3_SE_RSC_EEENS_6ResultISC_EEDpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest19RunAdminToolCommandIJRA28_KcRKNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEERA14_S3_EEENS_6ResultISC_EEDpOT_ |
85 | | |
86 | | template <class... Args> |
87 | 0 | Status RunAdminToolCommandAndGetErrorOutput(string* error_msg, Args&&... args) { |
88 | 0 | auto command = ToStringVector( |
89 | 0 | GetToolPath("yb-admin"), "-master_addresses", cluster_->GetMasterAddresses(), |
90 | 0 | std::forward<Args>(args)...); |
91 | 0 | LOG(INFO) << "Run tool: " << AsString(command); |
92 | 0 | return Subprocess::Call(command, error_msg, StdFdTypes{StdFdType::kErr}); |
93 | 0 | } Unexecuted instantiation: _ZN2yb5tools12AdminCliTest36RunAdminToolCommandAndGetErrorOutputIJRA27_KcRKNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEESC_SC_EEENS_6StatusEPSC_DpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest36RunAdminToolCommandAndGetErrorOutputIJRA27_KcRKNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEESC_SE_EEENS_6StatusEPSC_DpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest36RunAdminToolCommandAndGetErrorOutputIJRA27_KcRKNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEESC_SE_RA18_S3_EEENS_6StatusEPSC_DpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest36RunAdminToolCommandAndGetErrorOutputIJRA27_KcRKNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEERA22_S3_SE_EEENS_6StatusEPSC_DpOT_ Unexecuted instantiation: _ZN2yb5tools12AdminCliTest36RunAdminToolCommandAndGetErrorOutputIJRA27_KcRKNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEESC_RA23_S3_EEENS_6StatusEPSC_DpOT_ |
94 | | |
95 | | template <class... Args> |
96 | 0 | Result<rapidjson::Document> RunAdminToolCommandJson(Args&&... args) { |
97 | 0 | auto raw = VERIFY_RESULT(RunAdminToolCommand(std::forward<Args>(args)...)); |
98 | 0 | rapidjson::Document result; |
99 | 0 | if (result.Parse(raw.c_str(), raw.length()).HasParseError()) { |
100 | 0 | return STATUS_FORMAT( |
101 | 0 | InvalidArgument, "Failed to parse json output $0: $1", result.GetParseError(), raw); |
102 | 0 | } |
103 | 0 | return result; |
104 | 0 | } |
105 | | |
106 | 0 | CHECKED_STATUS WaitForRestoreSnapshot() { |
107 | 0 | return WaitFor([this]() -> Result<bool> { |
108 | 0 | auto document = VERIFY_RESULT(RunAdminToolCommandJson("list_snapshot_restorations")); |
109 | 0 | auto it = document.FindMember("restorations"); |
110 | 0 | if (it == document.MemberEnd()) { |
111 | 0 | LOG(INFO) << "No restorations"; |
112 | 0 | return false; |
113 | 0 | } |
114 | 0 | auto value = it->value.GetArray(); |
115 | 0 | for (const auto& restoration : value) { |
116 | 0 | auto state_it = restoration.FindMember("state"); |
117 | 0 | if (state_it == restoration.MemberEnd()) { |
118 | 0 | return STATUS(NotFound, "'state' not found"); |
119 | 0 | } |
120 | 0 | if (state_it->value.GetString() != "RESTORED"s) { |
121 | 0 | return false; |
122 | 0 | } |
123 | 0 | } |
124 | 0 | return true; |
125 | 0 | }, |
126 | 0 | 30s, "Waiting for snapshot restore to complete"); |
127 | 0 | } |
128 | | |
129 | | Result<ListSnapshotsResponsePB> WaitForAllSnapshots( |
130 | 0 | MasterBackupProxy* const alternate_proxy = nullptr) { |
131 | 0 | auto proxy = alternate_proxy; |
132 | 0 | if (!proxy) { |
133 | 0 | proxy = VERIFY_RESULT(BackupServiceProxy()); |
134 | 0 | } |
135 | |
|
136 | 0 | ListSnapshotsRequestPB req; |
137 | 0 | ListSnapshotsResponsePB resp; |
138 | 0 | RETURN_NOT_OK( |
139 | 0 | WaitFor([proxy, &req, &resp]() -> Result<bool> { |
140 | 0 | RpcController rpc; |
141 | 0 | RETURN_NOT_OK(proxy->ListSnapshots(req, &resp, &rpc)); |
142 | 0 | for (auto const& snapshot : resp.snapshots()) { |
143 | 0 | if (snapshot.entry().state() != SysSnapshotEntryPB::COMPLETE) { |
144 | 0 | return false; |
145 | 0 | } |
146 | 0 | } |
147 | 0 | return true; |
148 | 0 | }, |
149 | 0 | 30s, "Waiting for all snapshots to complete")); |
150 | 0 | return resp; |
151 | 0 | } |
152 | | |
153 | | Result<string> GetCompletedSnapshot(int num_snapshots = 1, |
154 | | int idx = 0, |
155 | 0 | MasterBackupProxy* const proxy = nullptr) { |
156 | 0 | auto resp = VERIFY_RESULT(WaitForAllSnapshots(proxy)); |
157 | |
|
158 | 0 | if (resp.snapshots_size() != num_snapshots) { |
159 | 0 | return STATUS_FORMAT(Corruption, "Wrong snapshot count $0", resp.snapshots_size()); |
160 | 0 | } |
161 | | |
162 | 0 | return SnapshotIdToString(resp.snapshots(idx).id()); |
163 | 0 | } |
164 | | |
165 | 0 | Result<SysSnapshotEntryPB::State> WaitForRestoration() { |
166 | 0 | auto* proxy = VERIFY_RESULT(BackupServiceProxy()); |
167 | |
|
168 | 0 | ListSnapshotRestorationsRequestPB req; |
169 | 0 | ListSnapshotRestorationsResponsePB resp; |
170 | 0 | RETURN_NOT_OK( |
171 | 0 | WaitFor([proxy, &req, &resp]() -> Result<bool> { |
172 | 0 | RpcController rpc; |
173 | 0 | RETURN_NOT_OK(proxy->ListSnapshotRestorations(req, &resp, &rpc)); |
174 | 0 | for (auto const& restoration : resp.restorations()) { |
175 | 0 | if (restoration.entry().state() == SysSnapshotEntryPB::RESTORING) { |
176 | 0 | return false; |
177 | 0 | } |
178 | 0 | } |
179 | 0 | return true; |
180 | 0 | }, |
181 | 0 | 30s, "Waiting for all restorations to complete")); |
182 | |
|
183 | 0 | SCHECK_EQ(resp.restorations_size(), 1, IllegalState, "Expected only one restoration"); |
184 | 0 | return resp.restorations(0).entry().state(); |
185 | 0 | } |
186 | | |
187 | 0 | Result<string> GetRecentStreamId(MiniCluster* cluster) { |
188 | 0 | const int kStreamUuidLength = 32; |
189 | 0 | string output = VERIFY_RESULT(RunAdminToolCommand(cluster, "list_cdc_streams")); |
190 | 0 | string find_stream_id = "stream_id: \""; |
191 | 0 | string::size_type pos = output.find(find_stream_id); |
192 | 0 | return output.substr((pos + find_stream_id.size()), kStreamUuidLength); |
193 | 0 | } |
194 | | |
195 | | Result<size_t> NumTables(const string& table_name) const; |
196 | | void ImportTableAs(const string& snapshot_file, const string& keyspace, const string& table_name); |
197 | | void CheckImportedTable( |
198 | | const YBTable* src_table, const YBTableName& yb_table_name, bool same_ids = false); |
199 | | void CheckAndDeleteImportedTable( |
200 | | const string& keyspace, const string& table_name, bool same_ids = false); |
201 | | void CheckImportedTableWithIndex( |
202 | | const string& keyspace, const string& table_name, const string& index_name, |
203 | | bool same_ids = false); |
204 | | |
205 | | void DoTestImportSnapshot(const string& format = ""); |
206 | | void DoTestExportImportIndexSnapshot(Transactional transactional); |
207 | | |
208 | | private: |
209 | | std::unique_ptr<MasterBackupProxy> backup_service_proxy_; |
210 | | }; |
211 | | |
212 | 0 | TEST_F(AdminCliTest, TestNonTLS) { |
213 | 0 | ASSERT_OK(RunAdminToolCommand("list_all_masters")); |
214 | 0 | } |
215 | | |
216 | | // TODO: Enabled once ENG-4900 is resolved. |
217 | 0 | TEST_F(AdminCliTest, DISABLED_TestTLS) { |
218 | 0 | const auto sub_dir = JoinPathSegments("ent", "test_certs"); |
219 | 0 | auto root_dir = env_util::GetRootDir(sub_dir) + "/../../"; |
220 | 0 | ASSERT_OK(RunAdminToolCommand( |
221 | 0 | "--certs_dir_name", JoinPathSegments(root_dir, sub_dir), "list_all_masters")); |
222 | 0 | } |
223 | | |
224 | 0 | TEST_F(AdminCliTest, TestCreateSnapshot) { |
225 | 0 | CreateTable(Transactional::kFalse); |
226 | 0 | const string& table_name = table_.name().table_name(); |
227 | 0 | const string& keyspace = table_.name().namespace_name(); |
228 | | |
229 | | // There is custom table. |
230 | 0 | const auto tables = ASSERT_RESULT(client_->ListTables(table_name, /* exclude_ysql */ true)); |
231 | 0 | ASSERT_EQ(1, tables.size()); |
232 | |
|
233 | 0 | ListSnapshotsRequestPB req; |
234 | 0 | ListSnapshotsResponsePB resp; |
235 | 0 | RpcController rpc; |
236 | 0 | ASSERT_OK(ASSERT_RESULT(BackupServiceProxy())->ListSnapshots(req, &resp, &rpc)); |
237 | 0 | ASSERT_EQ(resp.snapshots_size(), 0); |
238 | | |
239 | | // Create snapshot of default table that gets created. |
240 | 0 | ASSERT_OK(RunAdminToolCommand("create_snapshot", keyspace, table_name)); |
241 | |
|
242 | 0 | rpc.Reset(); |
243 | 0 | ASSERT_OK(ASSERT_RESULT(BackupServiceProxy())->ListSnapshots(req, &resp, &rpc)); |
244 | 0 | ASSERT_EQ(resp.snapshots_size(), 1); |
245 | |
|
246 | 0 | LOG(INFO) << "Test finished: " << CURRENT_TEST_CASE_AND_TEST_NAME_STR(); |
247 | 0 | } |
248 | | |
249 | 0 | Result<size_t> AdminCliTest::NumTables(const string& table_name) const { |
250 | 0 | auto tables = VERIFY_RESULT( |
251 | 0 | client_->ListTables(/* filter */ table_name, /* exclude_ysql */ true)); |
252 | 0 | return tables.size(); |
253 | 0 | } |
254 | | |
255 | | void AdminCliTest::CheckImportedTable(const YBTable* src_table, |
256 | | const YBTableName& yb_table_name, |
257 | | bool same_ids) { |
258 | | shared_ptr<YBTable> table; |
259 | | ASSERT_OK(client_->OpenTable(yb_table_name, &table)); |
260 | | |
261 | | ASSERT_EQ(same_ids, table->id() == src_table->id()); |
262 | | ASSERT_EQ(table->table_type(), src_table->table_type()); |
263 | | ASSERT_EQ(table->GetPartitionsCopy(), src_table->GetPartitionsCopy()); |
264 | | ASSERT_TRUE(table->partition_schema().Equals(src_table->partition_schema())); |
265 | | ASSERT_TRUE(table->schema().Equals(src_table->schema())); |
266 | | ASSERT_EQ(table->schema().table_properties().is_transactional(), |
267 | | src_table->schema().table_properties().is_transactional()); |
268 | | } |
269 | | |
270 | | void AdminCliTest::CheckAndDeleteImportedTable(const string& keyspace, |
271 | | const string& table_name, |
272 | 0 | bool same_ids) { |
273 | | // Wait for the new snapshot completion. |
274 | 0 | ASSERT_RESULT(WaitForAllSnapshots()); |
275 | |
|
276 | 0 | const YBTableName yb_table_name(YQL_DATABASE_CQL, keyspace, table_name); |
277 | 0 | CheckImportedTable(table_.get(), yb_table_name, same_ids); |
278 | 0 | ASSERT_EQ(1, ASSERT_RESULT(NumTables(table_name))); |
279 | 0 | ASSERT_OK(client_->DeleteTable(yb_table_name, /* wait */ true)); |
280 | 0 | ASSERT_EQ(0, ASSERT_RESULT(NumTables(table_name))); |
281 | 0 | } |
282 | | |
283 | | void AdminCliTest::ImportTableAs(const string& snapshot_file, |
284 | | const string& keyspace, |
285 | 0 | const string& table_name) { |
286 | 0 | ASSERT_OK(RunAdminToolCommand("import_snapshot", snapshot_file, keyspace, table_name)); |
287 | 0 | CheckAndDeleteImportedTable(keyspace, table_name); |
288 | 0 | } |
289 | | |
290 | 0 | void AdminCliTest::DoTestImportSnapshot(const string& format) { |
291 | 0 | CreateTable(Transactional::kFalse); |
292 | 0 | const string& table_name = table_.name().table_name(); |
293 | 0 | const string& keyspace = table_.name().namespace_name(); |
294 | | |
295 | | // Create snapshot of default table that gets created. |
296 | 0 | ASSERT_OK(RunAdminToolCommand("create_snapshot", keyspace, table_name)); |
297 | 0 | const auto snapshot_id = ASSERT_RESULT(GetCompletedSnapshot()); |
298 | |
|
299 | 0 | string tmp_dir; |
300 | 0 | ASSERT_OK(Env::Default()->GetTestDirectory(&tmp_dir)); |
301 | 0 | const auto snapshot_file = JoinPathSegments(tmp_dir, "exported_snapshot.dat"); |
302 | |
|
303 | 0 | if (format.empty()) { |
304 | 0 | ASSERT_OK(RunAdminToolCommand("export_snapshot", snapshot_id, snapshot_file)); |
305 | 0 | } else { |
306 | 0 | ASSERT_OK(RunAdminToolCommand("export_snapshot", snapshot_id, snapshot_file, |
307 | 0 | "-TEST_metadata_file_format_version=" + format)); |
308 | 0 | } |
309 | | |
310 | | // Import snapshot into the existing table. |
311 | 0 | ASSERT_OK(RunAdminToolCommand("import_snapshot", snapshot_file)); |
312 | 0 | CheckAndDeleteImportedTable(keyspace, table_name, /* same_ids */ true); |
313 | | |
314 | | // Import snapshot into original table from the snapshot. |
315 | | // (The table was deleted by the call above.) |
316 | 0 | ASSERT_OK(RunAdminToolCommand("import_snapshot", snapshot_file)); |
317 | 0 | CheckAndDeleteImportedTable(keyspace, table_name); |
318 | | |
319 | | // Import snapshot into non existing namespace. |
320 | 0 | ImportTableAs(snapshot_file, keyspace + "_new", table_name); |
321 | | // Import snapshot into already existing namespace. |
322 | 0 | ImportTableAs(snapshot_file, keyspace, table_name + "_new"); |
323 | | // Import snapshot into already existing namespace and table. |
324 | 0 | ImportTableAs(snapshot_file, keyspace, table_name); |
325 | 0 | } |
326 | | |
327 | 0 | TEST_F(AdminCliTest, TestImportSnapshot) { |
328 | 0 | DoTestImportSnapshot(); |
329 | 0 | LOG(INFO) << "Test finished: " << CURRENT_TEST_CASE_AND_TEST_NAME_STR(); |
330 | 0 | } |
331 | | |
332 | 0 | TEST_F(AdminCliTest, TestImportSnapshotInOldFormat1) { |
333 | 0 | DoTestImportSnapshot("1"); |
334 | 0 | LOG(INFO) << "Test finished: " << CURRENT_TEST_CASE_AND_TEST_NAME_STR(); |
335 | 0 | } |
336 | | |
337 | 0 | TEST_F(AdminCliTest, TestImportSnapshotInOldFormatNoNamespaceName) { |
338 | 0 | DoTestImportSnapshot("-1"); |
339 | 0 | LOG(INFO) << "Test finished: " << CURRENT_TEST_CASE_AND_TEST_NAME_STR(); |
340 | 0 | } |
341 | | |
342 | 0 | TEST_F(AdminCliTest, TestExportImportSnapshot) { |
343 | 0 | CreateTable(Transactional::kFalse); |
344 | 0 | const string& table_name = table_.name().table_name(); |
345 | 0 | const string& keyspace = table_.name().namespace_name(); |
346 | | |
347 | | // Create snapshot of default table that gets created. |
348 | 0 | ASSERT_OK(RunAdminToolCommand("create_snapshot", keyspace, table_name)); |
349 | 0 | const auto snapshot_id = ASSERT_RESULT(GetCompletedSnapshot()); |
350 | |
|
351 | 0 | string tmp_dir; |
352 | 0 | ASSERT_OK(Env::Default()->GetTestDirectory(&tmp_dir)); |
353 | 0 | const auto snapshot_file = JoinPathSegments(tmp_dir, "exported_snapshot.dat"); |
354 | 0 | ASSERT_OK(RunAdminToolCommand("export_snapshot", snapshot_id, snapshot_file)); |
355 | | // Import below will not create a new table - reusing the old one. |
356 | 0 | ASSERT_OK(RunAdminToolCommand("import_snapshot", snapshot_file, keyspace, table_name)); |
357 | |
|
358 | 0 | const YBTableName yb_table_name(YQL_DATABASE_CQL, keyspace, table_name); |
359 | 0 | CheckImportedTable(table_.get(), yb_table_name, /* same_ids */ true); |
360 | 0 | ASSERT_EQ(1, ASSERT_RESULT(NumTables(table_name))); |
361 | |
|
362 | 0 | LOG(INFO) << "Test finished: " << CURRENT_TEST_CASE_AND_TEST_NAME_STR(); |
363 | 0 | } |
364 | | |
365 | 0 | TEST_F(AdminCliTest, TestRestoreSnapshotBasic) { |
366 | 0 | CreateTable(Transactional::kFalse); |
367 | 0 | const string& table_name = table_.name().table_name(); |
368 | 0 | const string& keyspace = table_.name().namespace_name(); |
369 | |
|
370 | 0 | ASSERT_OK(WriteRow(CreateSession(), 1, 1)); |
371 | | |
372 | | // Create snapshot of default table that gets created. |
373 | 0 | LOG(INFO) << "Creating snapshot"; |
374 | 0 | ASSERT_OK(RunAdminToolCommand("create_snapshot", keyspace, table_name)); |
375 | 0 | const auto snapshot_id = ASSERT_RESULT(GetCompletedSnapshot()); |
376 | 0 | ASSERT_RESULT(WaitForAllSnapshots()); |
377 | |
|
378 | 0 | ASSERT_OK(DeleteRow(CreateSession(), 1)); |
379 | 0 | ASSERT_NOK(SelectRow(CreateSession(), 1)); |
380 | | |
381 | | // Restore snapshot into the existing table. |
382 | 0 | LOG(INFO) << "Restoring snapshot"; |
383 | 0 | ASSERT_OK(RunAdminToolCommand("restore_snapshot", snapshot_id)); |
384 | 0 | ASSERT_OK(WaitForRestoreSnapshot()); |
385 | 0 | LOG(INFO) << "Restored snapshot"; |
386 | |
|
387 | 0 | ASSERT_OK(WaitFor([&]() -> Result<bool> { |
388 | 0 | return SelectRow(CreateSession(), 1).ok(); |
389 | 0 | }, 20s, "Waiting for row from restored snapshot.")); |
390 | 0 | } |
391 | | |
392 | 0 | TEST_F(AdminCliTest, TestRestoreSnapshotHybridTime) { |
393 | 0 | CreateTable(Transactional::kFalse); |
394 | 0 | const string& table_name = table_.name().table_name(); |
395 | 0 | const string& keyspace = table_.name().namespace_name(); |
396 | |
|
397 | 0 | ASSERT_OK(WriteRow(CreateSession(), 1, 1)); |
398 | 0 | auto hybrid_time = cluster_->mini_tablet_server(0)->server()->Clock()->Now(); |
399 | 0 | ASSERT_OK(WriteRow(CreateSession(), 2, 2)); |
400 | | |
401 | | // Create snapshot of default table that gets created. |
402 | 0 | ASSERT_OK(RunAdminToolCommand("create_snapshot", keyspace, table_name)); |
403 | 0 | const auto snapshot_id = ASSERT_RESULT(GetCompletedSnapshot()); |
404 | 0 | ASSERT_RESULT(WaitForAllSnapshots()); |
405 | | |
406 | | // Restore snapshot into the existing table. |
407 | 0 | ASSERT_OK(RunAdminToolCommand("restore_snapshot", snapshot_id, |
408 | 0 | std::to_string(hybrid_time.GetPhysicalValueMicros()))); |
409 | 0 | ASSERT_OK(WaitForRestoreSnapshot()); |
410 | | |
411 | | // Row before HybridTime present, row after should be missing now. |
412 | 0 | ASSERT_OK(WaitFor([&]() -> Result<bool> { |
413 | 0 | return SelectRow(CreateSession(), 1).ok() && |
414 | 0 | !SelectRow(CreateSession(), 2).ok(); |
415 | 0 | }, 20s, "Waiting for row from restored snapshot.")); |
416 | 0 | } |
417 | | |
418 | 0 | TEST_F(AdminCliTest, TestRestoreSnapshotTimestamp) { |
419 | 0 | CreateTable(Transactional::kFalse); |
420 | 0 | const string& table_name = table_.name().table_name(); |
421 | 0 | const string& keyspace = table_.name().namespace_name(); |
422 | |
|
423 | 0 | ASSERT_OK(WriteRow(CreateSession(), 1, 1)); |
424 | 0 | auto timestamp = DateTime::TimestampToString(DateTime::TimestampNow()); |
425 | 0 | LOG(INFO) << "Timestamp: " << timestamp; |
426 | 0 | auto write_wait = 2s; |
427 | 0 | std::this_thread::sleep_for(write_wait); |
428 | 0 | ASSERT_OK(WriteRow(CreateSession(), 2, 2)); |
429 | | |
430 | | // Create snapshot of default table that gets created. |
431 | 0 | ASSERT_OK(RunAdminToolCommand("create_snapshot", keyspace, table_name)); |
432 | 0 | const auto snapshot_id = ASSERT_RESULT(GetCompletedSnapshot()); |
433 | 0 | ASSERT_RESULT(WaitForAllSnapshots()); |
434 | | |
435 | | // Restore snapshot into the existing table. |
436 | 0 | ASSERT_OK(RunAdminToolCommand("restore_snapshot", snapshot_id, timestamp)); |
437 | 0 | ASSERT_OK(WaitForRestoreSnapshot()); |
438 | | |
439 | | // Row before Timestamp present, row after should be missing now. |
440 | 0 | ASSERT_OK(WaitFor([&]() -> Result<bool> { |
441 | 0 | return SelectRow(CreateSession(), 1).ok() && |
442 | 0 | !SelectRow(CreateSession(), 2).ok(); |
443 | 0 | }, 20s, "Waiting for row from restored snapshot.")); |
444 | 0 | } |
445 | | |
446 | 0 | TEST_F(AdminCliTest, TestRestoreSnapshotInterval) { |
447 | 0 | CreateTable(Transactional::kFalse); |
448 | 0 | const string& table_name = table_.name().table_name(); |
449 | 0 | const string& keyspace = table_.name().namespace_name(); |
450 | |
|
451 | 0 | auto clock = cluster_->mini_tablet_server(0)->server()->Clock(); |
452 | 0 | ASSERT_OK(WriteRow(CreateSession(), 1, 1)); |
453 | 0 | auto pre_sleep_ht = clock->Now(); |
454 | 0 | auto write_wait = 5s; |
455 | 0 | std::this_thread::sleep_for(write_wait); |
456 | 0 | ASSERT_OK(WriteRow(CreateSession(), 2, 2)); |
457 | | |
458 | | // Create snapshot of default table that gets created. |
459 | 0 | ASSERT_OK(RunAdminToolCommand("create_snapshot", keyspace, table_name)); |
460 | 0 | const auto snapshot_id = ASSERT_RESULT(GetCompletedSnapshot()); |
461 | 0 | ASSERT_RESULT(WaitForAllSnapshots()); |
462 | | |
463 | | // Restore snapshot into the existing table. |
464 | 0 | auto restore_ht = clock->Now(); |
465 | 0 | auto interval = restore_ht.GetPhysicalValueMicros() - pre_sleep_ht.GetPhysicalValueMicros(); |
466 | 0 | auto i_str = std::to_string(interval/1000000) + "s"; |
467 | 0 | ASSERT_OK(RunAdminToolCommand("restore_snapshot", snapshot_id, "minus", i_str)); |
468 | 0 | ASSERT_OK(WaitForRestoreSnapshot()); |
469 | |
|
470 | 0 | ASSERT_OK(SelectRow(CreateSession(), 1)); |
471 | 0 | auto select2 = SelectRow(CreateSession(), 2); |
472 | 0 | ASSERT_NOK(select2); |
473 | 0 | } |
474 | | |
475 | | void AdminCliTest::CheckImportedTableWithIndex(const string& keyspace, |
476 | | const string& table_name, |
477 | | const string& index_name, |
478 | 0 | bool same_ids) { |
479 | 0 | const YBTableName yb_table_name(YQL_DATABASE_CQL, keyspace, table_name); |
480 | 0 | const YBTableName yb_index_name(YQL_DATABASE_CQL, keyspace, index_name); |
481 | |
|
482 | 0 | CheckImportedTable(table_.get(), yb_table_name, same_ids); |
483 | 0 | ASSERT_EQ(2, ASSERT_RESULT(NumTables(table_name))); |
484 | 0 | CheckImportedTable(index_.get(), yb_index_name, same_ids); |
485 | 0 | ASSERT_EQ(1, ASSERT_RESULT(NumTables(index_name))); |
486 | |
|
487 | 0 | YBTableInfo table_info = ASSERT_RESULT(client_->GetYBTableInfo(yb_table_name)); |
488 | 0 | YBTableInfo index_info = ASSERT_RESULT(client_->GetYBTableInfo(yb_index_name)); |
489 | | // Check index ---> table relation. |
490 | 0 | ASSERT_EQ(index_info.index_info->indexed_table_id(), table_info.table_id); |
491 | | // Check table ---> index relation. |
492 | 0 | ASSERT_EQ(table_info.index_map.size(), 1); |
493 | 0 | ASSERT_EQ(table_info.index_map.count(index_info.table_id), 1); |
494 | 0 | ASSERT_EQ(table_info.index_map.begin()->first, index_info.table_id); |
495 | 0 | ASSERT_EQ(table_info.index_map.begin()->second.table_id(), index_info.table_id); |
496 | 0 | ASSERT_EQ(table_info.index_map.begin()->second.indexed_table_id(), table_info.table_id); |
497 | |
|
498 | 0 | ASSERT_OK(client_->DeleteTable(yb_table_name, /* wait */ true)); |
499 | 0 | ASSERT_EQ(0, ASSERT_RESULT(NumTables(table_name))); |
500 | 0 | } |
501 | | |
502 | 0 | void AdminCliTest::DoTestExportImportIndexSnapshot(Transactional transactional) { |
503 | 0 | CreateTable(transactional); |
504 | 0 | CreateIndex(transactional); |
505 | | |
506 | | // Default tables that were created. |
507 | 0 | const string& table_name = table_.name().table_name(); |
508 | 0 | const string& keyspace = table_.name().namespace_name(); |
509 | 0 | const string& index_name = index_.name().table_name(); |
510 | 0 | const YBTableName yb_table_name(YQL_DATABASE_CQL, keyspace, table_name); |
511 | 0 | const YBTableName yb_index_name(YQL_DATABASE_CQL, keyspace, index_name); |
512 | | |
513 | | // Check there are 2 tables. |
514 | 0 | ASSERT_EQ(2, ASSERT_RESULT(NumTables(table_name))); |
515 | | |
516 | | // Create snapshot of default table and the attached index that gets created. |
517 | 0 | ASSERT_OK(RunAdminToolCommand("create_snapshot", keyspace, table_name)); |
518 | 0 | auto snapshot_id = ASSERT_RESULT(GetCompletedSnapshot()); |
519 | |
|
520 | 0 | string tmp_dir; |
521 | 0 | ASSERT_OK(Env::Default()->GetTestDirectory(&tmp_dir)); |
522 | 0 | const auto snapshot_file = JoinPathSegments(tmp_dir, "exported_snapshot.dat"); |
523 | 0 | ASSERT_OK(RunAdminToolCommand("export_snapshot", snapshot_id, snapshot_file)); |
524 | | |
525 | | // Import table and index into the existing table and index. |
526 | 0 | ASSERT_OK(RunAdminToolCommand("import_snapshot", snapshot_file)); |
527 | | // Wait for the new snapshot completion. |
528 | 0 | ASSERT_RESULT(WaitForAllSnapshots()); |
529 | 0 | CheckImportedTableWithIndex(keyspace, table_name, index_name, /* same_ids */ true); |
530 | | |
531 | | // Import table and index with original names - not providing any names. |
532 | | // (The table was deleted by the call above.) |
533 | 0 | ASSERT_OK(RunAdminToolCommand("import_snapshot", snapshot_file)); |
534 | | // Wait for the new snapshot completion. |
535 | 0 | ASSERT_RESULT(WaitForAllSnapshots()); |
536 | 0 | CheckImportedTableWithIndex(keyspace, table_name, index_name); |
537 | | |
538 | | // Import table and index with original names - using the old names. |
539 | 0 | ASSERT_OK(RunAdminToolCommand( |
540 | 0 | "import_snapshot", snapshot_file, keyspace, table_name, index_name)); |
541 | | // Wait for the new snapshot completion. |
542 | 0 | ASSERT_RESULT(WaitForAllSnapshots()); |
543 | 0 | CheckImportedTableWithIndex(keyspace, table_name, index_name); |
544 | | |
545 | | // Import table and index with original names - providing only old table name. |
546 | 0 | ASSERT_OK(RunAdminToolCommand("import_snapshot", snapshot_file, keyspace, table_name)); |
547 | | // Wait for the new snapshot completion. |
548 | 0 | ASSERT_RESULT(WaitForAllSnapshots()); |
549 | 0 | CheckImportedTableWithIndex(keyspace, table_name, index_name); |
550 | | |
551 | | // Renaming table and index, but keeping the same keyspace. |
552 | 0 | ASSERT_OK(RunAdminToolCommand( |
553 | 0 | "import_snapshot", snapshot_file, keyspace, "new_" + table_name, "new_" + index_name)); |
554 | | // Wait for the new snapshot completion. |
555 | 0 | ASSERT_RESULT(WaitForAllSnapshots()); |
556 | 0 | CheckImportedTableWithIndex(keyspace, "new_" + table_name, "new_" + index_name); |
557 | | |
558 | | // Keeping the same table and index names, but renaming the keyspace. |
559 | 0 | ASSERT_OK(RunAdminToolCommand("import_snapshot", snapshot_file, "new_" + keyspace)); |
560 | | // Wait for the new snapshot completion. |
561 | 0 | ASSERT_RESULT(WaitForAllSnapshots()); |
562 | 0 | CheckImportedTableWithIndex("new_" + keyspace, table_name, index_name); |
563 | | |
564 | | // Repeat previous keyspace renaming case, but pass explicitly the same table name |
565 | | // (and skip index name). |
566 | 0 | ASSERT_OK(RunAdminToolCommand("import_snapshot", snapshot_file, "new_" + keyspace, table_name)); |
567 | | // Wait for the new snapshot completion. |
568 | 0 | ASSERT_RESULT(WaitForAllSnapshots()); |
569 | 0 | CheckImportedTableWithIndex("new_" + keyspace, table_name, index_name); |
570 | | |
571 | | // Import table and index into a new keyspace with old table and index names. |
572 | 0 | ASSERT_OK(RunAdminToolCommand( |
573 | 0 | "import_snapshot", snapshot_file, "new_" + keyspace, table_name, index_name)); |
574 | | // Wait for the new snapshot completion. |
575 | 0 | ASSERT_RESULT(WaitForAllSnapshots()); |
576 | 0 | CheckImportedTableWithIndex("new_" + keyspace, table_name, index_name); |
577 | | |
578 | | // Rename only index and keyspace, but keep the main table name. |
579 | 0 | ASSERT_OK(RunAdminToolCommand( |
580 | 0 | "import_snapshot", snapshot_file, "new_" + keyspace, table_name, "new_" + index_name)); |
581 | | // Wait for the new snapshot completion. |
582 | 0 | ASSERT_RESULT(WaitForAllSnapshots()); |
583 | 0 | CheckImportedTableWithIndex("new_" + keyspace, table_name, "new_" + index_name); |
584 | | |
585 | | // Import table and index with renaming into a new keyspace. |
586 | 0 | ASSERT_OK(RunAdminToolCommand( |
587 | 0 | "import_snapshot", snapshot_file, "new_" + keyspace, |
588 | 0 | "new_" + table_name, "new_" + index_name)); |
589 | | // Wait for the new snapshot completion. |
590 | 0 | ASSERT_RESULT(WaitForAllSnapshots()); |
591 | 0 | CheckImportedTableWithIndex("new_" + keyspace, "new_" + table_name, "new_" + index_name); |
592 | | |
593 | | // Renaming table only, no new name for the index - expecting error. |
594 | 0 | ASSERT_NOK(RunAdminToolCommand( |
595 | 0 | "import_snapshot", snapshot_file, keyspace, "new_" + table_name)); |
596 | 0 | ASSERT_NOK(RunAdminToolCommand( |
597 | 0 | "import_snapshot", snapshot_file, "new_" + keyspace, "new_" + table_name)); |
598 | 0 | } |
599 | | |
600 | 0 | TEST_F(AdminCliTest, TestExportImportIndexSnapshot) { |
601 | | // Test non-transactional table. |
602 | 0 | DoTestExportImportIndexSnapshot(Transactional::kFalse); |
603 | 0 | LOG(INFO) << "Test finished: " << CURRENT_TEST_CASE_AND_TEST_NAME_STR(); |
604 | 0 | } |
605 | | |
606 | 0 | TEST_F(AdminCliTest, TestExportImportIndexSnapshot_ForTransactional) { |
607 | | // Test the recreated transactional table. |
608 | 0 | DoTestExportImportIndexSnapshot(Transactional::kTrue); |
609 | 0 | LOG(INFO) << "Test finished: " << CURRENT_TEST_CASE_AND_TEST_NAME_STR(); |
610 | 0 | } |
611 | | |
612 | 0 | TEST_F(AdminCliTest, TestFailedRestoration) { |
613 | 0 | CreateTable(Transactional::kTrue); |
614 | 0 | const string& table_name = table_.name().table_name(); |
615 | 0 | const string& keyspace = table_.name().namespace_name(); |
616 | | |
617 | | // Create snapshot of default table that gets created. |
618 | 0 | ASSERT_OK(RunAdminToolCommand("create_snapshot", keyspace, table_name)); |
619 | 0 | const auto snapshot_id = ASSERT_RESULT(GetCompletedSnapshot()); |
620 | 0 | LOG(INFO) << "Created snapshot: " << snapshot_id; |
621 | |
|
622 | 0 | string tmp_dir; |
623 | 0 | ASSERT_OK(Env::Default()->GetTestDirectory(&tmp_dir)); |
624 | 0 | const auto snapshot_file = JoinPathSegments(tmp_dir, "exported_snapshot.dat"); |
625 | 0 | ASSERT_OK(RunAdminToolCommand("export_snapshot", snapshot_id, snapshot_file)); |
626 | | // Import below will not create a new table - reusing the old one. |
627 | 0 | ASSERT_OK(RunAdminToolCommand("import_snapshot", snapshot_file)); |
628 | |
|
629 | 0 | const YBTableName yb_table_name(YQL_DATABASE_CQL, keyspace, table_name); |
630 | 0 | CheckImportedTable(table_.get(), yb_table_name, /* same_ids */ true); |
631 | 0 | ASSERT_EQ(1, ASSERT_RESULT(NumTables(table_name))); |
632 | |
|
633 | 0 | auto new_snapshot_id = ASSERT_RESULT(GetCompletedSnapshot(2)); |
634 | 0 | if (new_snapshot_id == snapshot_id) { |
635 | 0 | new_snapshot_id = ASSERT_RESULT(GetCompletedSnapshot(2, 1)); |
636 | 0 | } |
637 | 0 | LOG(INFO) << "Imported snapshot: " << new_snapshot_id; |
638 | |
|
639 | 0 | ASSERT_OK(RunAdminToolCommand("restore_snapshot", new_snapshot_id)); |
640 | |
|
641 | 0 | const SysSnapshotEntryPB::State state = ASSERT_RESULT(WaitForRestoration()); |
642 | 0 | LOG(INFO) << "Restoration: " << SysSnapshotEntryPB::State_Name(state); |
643 | 0 | ASSERT_EQ(state, SysSnapshotEntryPB::FAILED); |
644 | |
|
645 | 0 | LOG(INFO) << "Test finished: " << CURRENT_TEST_CASE_AND_TEST_NAME_STR(); |
646 | 0 | } |
647 | | |
648 | | // Configures two clusters with clients for the producer and consumer side of xcluster replication. |
649 | | class XClusterAdminCliTest : public AdminCliTest { |
650 | | public: |
651 | 0 | void SetUp() override { |
652 | | // Setup the default cluster as the consumer cluster. |
653 | 0 | AdminCliTest::SetUp(); |
654 | | // Only create a table on the consumer, producer table may differ in tests. |
655 | 0 | CreateTable(Transactional::kTrue); |
656 | | |
657 | | // Create the producer cluster. |
658 | 0 | opts.num_tablet_servers = 3; |
659 | 0 | opts.cluster_id = kProducerClusterId; |
660 | 0 | producer_cluster_ = std::make_unique<MiniCluster>(opts); |
661 | 0 | ASSERT_OK(producer_cluster_->StartSync()); |
662 | 0 | ASSERT_OK(producer_cluster_->WaitForTabletServerCount(3)); |
663 | 0 | producer_cluster_client_ = ASSERT_RESULT(producer_cluster_->CreateClient()); |
664 | 0 | } |
665 | | |
666 | 0 | void DoTearDown() override { |
667 | 0 | if (producer_cluster_) { |
668 | 0 | producer_cluster_->Shutdown(); |
669 | 0 | } |
670 | 0 | AdminCliTest::DoTearDown(); |
671 | 0 | } |
672 | | |
673 | | protected: |
674 | | Status CheckTableIsBeingReplicated( |
675 | | const std::vector<TableId>& tables, |
676 | 0 | SysCDCStreamEntryPB::State target_state = SysCDCStreamEntryPB::ACTIVE) { |
677 | 0 | string output = VERIFY_RESULT(RunAdminToolCommand(producer_cluster_.get(), "list_cdc_streams")); |
678 | 0 | string state_search_str = Format( |
679 | 0 | "value: \"$0\"", |
680 | 0 | SysCDCStreamEntryPB::State_Name(target_state)); |
681 | |
|
682 | 0 | for (const auto& table_id : tables) { |
683 | | // Ensure a stream object with table_id exists. |
684 | 0 | size_t table_id_pos = output.find(table_id); |
685 | 0 | if (table_id_pos == string::npos) { |
686 | 0 | return STATUS_FORMAT( |
687 | 0 | NotFound, |
688 | 0 | "Table id '$0' not found in output: $1", |
689 | 0 | table_id, output); |
690 | 0 | } |
691 | | |
692 | | // Ensure that the strem object has the expected state value. |
693 | 0 | size_t state_pos = output.find(state_search_str, table_id_pos); |
694 | 0 | if (state_pos == string::npos) { |
695 | 0 | return STATUS_FORMAT( |
696 | 0 | NotFound, |
697 | 0 | "Table id '$0' has the incorrect state value in output: $1", |
698 | 0 | table_id, output); |
699 | 0 | } |
700 | | |
701 | | // Ensure that the state value we captured earlier did not belong |
702 | | // to different stream object. |
703 | 0 | size_t next_stream_obj_pos = output.find("streams {", table_id_pos); |
704 | 0 | if (next_stream_obj_pos != string::npos && next_stream_obj_pos <= state_pos) { |
705 | 0 | return STATUS_FORMAT( |
706 | 0 | NotFound, |
707 | 0 | "Table id '$0' has no state value in output: $1", |
708 | 0 | table_id, output); |
709 | 0 | } |
710 | 0 | } |
711 | 0 | return Status::OK(); |
712 | 0 | } |
713 | | |
714 | 0 | Result<MasterBackupProxy*> ProducerBackupServiceProxy() { |
715 | 0 | if (!producer_backup_service_proxy_) { |
716 | 0 | producer_backup_service_proxy_.reset(new MasterBackupProxy( |
717 | 0 | &producer_cluster_client_->proxy_cache(), |
718 | 0 | VERIFY_RESULT(producer_cluster_->GetLeaderMasterBoundRpcAddr()))); |
719 | 0 | } |
720 | 0 | return producer_backup_service_proxy_.get(); |
721 | 0 | } |
722 | | |
723 | | const string kProducerClusterId = "producer"; |
724 | | std::unique_ptr<client::YBClient> producer_cluster_client_; |
725 | | std::unique_ptr<MiniCluster> producer_cluster_; |
726 | | MiniClusterOptions opts; |
727 | | |
728 | | private: |
729 | | std::unique_ptr<MasterBackupProxy> producer_backup_service_proxy_; |
730 | | }; |
731 | | |
732 | 0 | TEST_F(XClusterAdminCliTest, TestSetupUniverseReplication) { |
733 | 0 | client::TableHandle producer_cluster_table; |
734 | | |
735 | | // Create an identical table on the producer. |
736 | 0 | client::kv_table_test::CreateTable( |
737 | 0 | Transactional::kTrue, NumTablets(), producer_cluster_client_.get(), &producer_cluster_table); |
738 | | |
739 | | // Setup universe replication, this should only return once complete. |
740 | 0 | ASSERT_OK(RunAdminToolCommand("setup_universe_replication", |
741 | 0 | kProducerClusterId, |
742 | 0 | producer_cluster_->GetMasterAddresses(), |
743 | 0 | producer_cluster_table->id())); |
744 | | |
745 | | // Check that the stream was properly created for this table. |
746 | 0 | ASSERT_OK(CheckTableIsBeingReplicated({producer_cluster_table->id()})); |
747 | | |
748 | | // Delete this universe so shutdown can proceed. |
749 | 0 | ASSERT_OK(RunAdminToolCommand("delete_universe_replication", kProducerClusterId)); |
750 | 0 | } |
751 | | |
752 | 0 | TEST_F(XClusterAdminCliTest, TestSetupUniverseReplicationChecksForColumnIdMismatch) { |
753 | 0 | client::TableHandle producer_table; |
754 | 0 | client::TableHandle consumer_table; |
755 | 0 | const YBTableName table_name(YQL_DATABASE_CQL, |
756 | 0 | "my_keyspace", |
757 | 0 | "column_id_mismatch_test_table"); |
758 | |
|
759 | 0 | client::kv_table_test::CreateTable(Transactional::kTrue, |
760 | 0 | NumTablets(), |
761 | 0 | producer_cluster_client_.get(), |
762 | 0 | &producer_table, |
763 | 0 | table_name); |
764 | 0 | client::kv_table_test::CreateTable(Transactional::kTrue, |
765 | 0 | NumTablets(), |
766 | 0 | client_.get(), |
767 | 0 | &consumer_table, |
768 | 0 | table_name); |
769 | | |
770 | | // Drop a column from the consumer table. |
771 | 0 | { |
772 | 0 | auto table_alterer = client_.get()->NewTableAlterer(table_name); |
773 | 0 | ASSERT_OK(table_alterer->DropColumn(kValueColumn)->Alter()); |
774 | 0 | } |
775 | | |
776 | | // Add the same column back into the producer table. This results in a schema mismatch |
777 | | // between the producer and consumer versions of the table. |
778 | 0 | { |
779 | 0 | auto table_alterer = client_.get()->NewTableAlterer(table_name); |
780 | 0 | table_alterer->AddColumn(kValueColumn)->Type(INT32); |
781 | 0 | ASSERT_OK(table_alterer->timeout(MonoDelta::FromSeconds(60 * kTimeMultiplier))->Alter()); |
782 | 0 | } |
783 | | |
784 | | // Try setting up replication, this should fail due to the schema mismatch. |
785 | 0 | ASSERT_NOK(RunAdminToolCommand("setup_universe_replication", |
786 | 0 | kProducerClusterId, |
787 | 0 | producer_cluster_->GetMasterAddresses(), |
788 | |
|
789 | 0 | producer_table->id())); |
790 | | |
791 | | // Make a snapshot of the producer table. |
792 | 0 | auto timestamp = DateTime::TimestampToString(DateTime::TimestampNow()); |
793 | 0 | auto producer_backup_proxy = ASSERT_RESULT(ProducerBackupServiceProxy()); |
794 | 0 | ASSERT_OK(RunAdminToolCommand( |
795 | 0 | producer_cluster_.get(), "create_snapshot", producer_table.name().namespace_name(), |
796 | 0 | producer_table.name().table_name())); |
797 | |
|
798 | 0 | const auto snapshot_id = ASSERT_RESULT(GetCompletedSnapshot(1, 0, producer_backup_proxy)); |
799 | 0 | ASSERT_RESULT(WaitForAllSnapshots(producer_backup_proxy)); |
800 | |
|
801 | 0 | string tmp_dir; |
802 | 0 | ASSERT_OK(Env::Default()->GetTestDirectory(&tmp_dir)); |
803 | 0 | const auto snapshot_file = JoinPathSegments(tmp_dir, "exported_producer_snapshot.dat"); |
804 | 0 | ASSERT_OK(RunAdminToolCommand( |
805 | 0 | producer_cluster_.get(), "export_snapshot", snapshot_id, snapshot_file)); |
806 | | |
807 | | // Delete consumer table, then import snapshot of producer table into the existing |
808 | | // consumer table. This should fix the schema mismatch issue. |
809 | 0 | ASSERT_OK(client_->DeleteTable(table_name, /* wait */ true)); |
810 | 0 | ASSERT_OK(RunAdminToolCommand("import_snapshot", snapshot_file)); |
811 | | |
812 | | // Try running SetupUniverseReplication again, this time it should succeed. |
813 | 0 | ASSERT_OK(RunAdminToolCommand("setup_universe_replication", |
814 | 0 | kProducerClusterId, |
815 | 0 | producer_cluster_->GetMasterAddresses(), |
816 | 0 | producer_table->id())); |
817 | | |
818 | | // Delete this universe so shutdown can proceed. |
819 | 0 | ASSERT_OK(RunAdminToolCommand("delete_universe_replication", kProducerClusterId)); |
820 | 0 | } |
821 | | |
822 | 0 | TEST_F(XClusterAdminCliTest, TestSetupUniverseReplicationFailsWithInvalidSchema) { |
823 | 0 | client::TableHandle producer_cluster_table; |
824 | | |
825 | | // Create a table with a different schema on the producer. |
826 | 0 | client::kv_table_test::CreateTable(Transactional::kFalse, // Results in different schema! |
827 | 0 | NumTablets(), |
828 | 0 | producer_cluster_client_.get(), |
829 | 0 | &producer_cluster_table); |
830 | | |
831 | | // Try to setup universe replication, should return with a useful error. |
832 | 0 | string error_msg; |
833 | | // First provide a non-existant table id. |
834 | | // ASSERT_NOK since this should fail. |
835 | 0 | ASSERT_NOK(RunAdminToolCommandAndGetErrorOutput(&error_msg, |
836 | 0 | "setup_universe_replication", |
837 | 0 | kProducerClusterId, |
838 | 0 | producer_cluster_->GetMasterAddresses(), |
839 | 0 | producer_cluster_table->id() + "-BAD")); |
840 | | |
841 | | // Verify that error message has relevant information. |
842 | 0 | ASSERT_TRUE(error_msg.find(producer_cluster_table->id() + "-BAD not found") != string::npos); |
843 | | |
844 | | // Now try with the correct table id. |
845 | | // Note that SetupUniverseReplication should call DeleteUniverseReplication to |
846 | | // clean up the environment on failure, so we don't need to explicitly call |
847 | | // DeleteUniverseReplication here. |
848 | 0 | ASSERT_NOK(RunAdminToolCommandAndGetErrorOutput(&error_msg, |
849 | 0 | "setup_universe_replication", |
850 | 0 | kProducerClusterId, |
851 | 0 | producer_cluster_->GetMasterAddresses(), |
852 | 0 | producer_cluster_table->id())); |
853 | | |
854 | | // Verify that error message has relevant information. |
855 | 0 | ASSERT_TRUE(error_msg.find("Source and target schemas don't match") != string::npos); |
856 | 0 | } |
857 | | |
858 | 0 | TEST_F(XClusterAdminCliTest, TestSetupUniverseReplicationFailsWithInvalidBootstrapId) { |
859 | 0 | client::TableHandle producer_cluster_table; |
860 | | |
861 | | // Create an identical table on the producer. |
862 | 0 | client::kv_table_test::CreateTable( |
863 | 0 | Transactional::kTrue, NumTablets(), producer_cluster_client_.get(), &producer_cluster_table); |
864 | | |
865 | | // Try to setup universe replication with a fake bootstrap id, should return with a useful error. |
866 | 0 | string error_msg; |
867 | | // ASSERT_NOK since this should fail. |
868 | 0 | ASSERT_NOK(RunAdminToolCommandAndGetErrorOutput(&error_msg, |
869 | 0 | "setup_universe_replication", |
870 | 0 | kProducerClusterId, |
871 | 0 | producer_cluster_->GetMasterAddresses(), |
872 | 0 | producer_cluster_table->id(), |
873 | 0 | "fake-bootstrap-id")); |
874 | | |
875 | | // Verify that error message has relevant information. |
876 | 0 | ASSERT_TRUE(error_msg.find( |
877 | 0 | "Could not find CDC stream: stream_id: \"fake-bootstrap-id\"") != string::npos); |
878 | 0 | } |
879 | | |
880 | 0 | TEST_F(XClusterAdminCliTest, TestSetupUniverseReplicationCleanupOnFailure) { |
881 | 0 | client::TableHandle producer_cluster_table; |
882 | | |
883 | | // Create an identical table on the producer. |
884 | 0 | client::kv_table_test::CreateTable( |
885 | 0 | Transactional::kTrue, NumTablets(), producer_cluster_client_.get(), &producer_cluster_table); |
886 | |
|
887 | 0 | string error_msg; |
888 | | // Try to setup universe replication with a fake bootstrap id, should result in failure. |
889 | | // ASSERT_NOK since this should fail. We should be able to make consecutive calls to |
890 | | // SetupUniverseReplication without having to call DeleteUniverseReplication first. |
891 | 0 | ASSERT_NOK(RunAdminToolCommandAndGetErrorOutput(&error_msg, |
892 | 0 | "setup_universe_replication", |
893 | 0 | kProducerClusterId, |
894 | 0 | producer_cluster_->GetMasterAddresses(), |
895 | 0 | producer_cluster_table->id(), |
896 | 0 | "fake-bootstrap-id")); |
897 | | |
898 | | // Try to setup universe replication with fake producer master address. |
899 | 0 | ASSERT_NOK(RunAdminToolCommandAndGetErrorOutput(&error_msg, |
900 | 0 | "setup_universe_replication", |
901 | 0 | kProducerClusterId, |
902 | 0 | "fake-producer-address", |
903 | 0 | producer_cluster_table->id())); |
904 | | |
905 | | // Try to setup universe replication with fake producer master address. |
906 | 0 | ASSERT_NOK(RunAdminToolCommandAndGetErrorOutput(&error_msg, |
907 | 0 | "setup_universe_replication", |
908 | 0 | kProducerClusterId, |
909 | 0 | producer_cluster_->GetMasterAddresses(), |
910 | 0 | "fake-producer-table-id")); |
911 | | |
912 | | // Test when producer and local table have different schema. |
913 | 0 | client::TableHandle producer_cluster_table2; |
914 | 0 | client::TableHandle consumer_table2; |
915 | 0 | const YBTableName kTableName2(YQL_DATABASE_CQL, "my_keyspace", "different_schema_test_table"); |
916 | |
|
917 | 0 | client::kv_table_test::CreateTable(Transactional::kFalse, // Results in different schema! |
918 | 0 | NumTablets(), |
919 | 0 | producer_cluster_client_.get(), |
920 | 0 | &producer_cluster_table2, |
921 | 0 | kTableName2); |
922 | 0 | client::kv_table_test::CreateTable(Transactional::kTrue, |
923 | 0 | NumTablets(), |
924 | 0 | client_.get(), |
925 | 0 | &consumer_table2, |
926 | 0 | kTableName2); |
927 | 0 | ASSERT_NOK(RunAdminToolCommandAndGetErrorOutput(&error_msg, |
928 | 0 | "setup_universe_replication", |
929 | 0 | kProducerClusterId, |
930 | 0 | producer_cluster_->GetMasterAddresses(), |
931 | 0 | producer_cluster_table2->id())); |
932 | | |
933 | | // Verify that the environment is cleaned up correctly after failure. |
934 | | // A valid call to SetupUniverseReplication after the failure should succeed |
935 | | // without us having to first call DeleteUniverseReplication. |
936 | 0 | ASSERT_OK(RunAdminToolCommandAndGetErrorOutput(&error_msg, |
937 | 0 | "setup_universe_replication", |
938 | 0 | kProducerClusterId, |
939 | 0 | producer_cluster_->GetMasterAddresses(), |
940 | 0 | producer_cluster_table->id())); |
941 | | // Verify table is being replicated. |
942 | 0 | ASSERT_OK(CheckTableIsBeingReplicated({producer_cluster_table->id()})); |
943 | | |
944 | | // Try calling SetupUniverseReplication again. This should fail as the producer |
945 | | // is already present. However, in this case, DeleteUniverseReplication should |
946 | | // not be called since the error was due to failing a sanity check. |
947 | 0 | ASSERT_NOK(RunAdminToolCommandAndGetErrorOutput(&error_msg, |
948 | 0 | "setup_universe_replication", |
949 | 0 | kProducerClusterId, |
950 | 0 | producer_cluster_->GetMasterAddresses(), |
951 | 0 | producer_cluster_table->id())); |
952 | | // Verify the universe replication has not been deleted is still there. |
953 | 0 | ASSERT_OK(CheckTableIsBeingReplicated({producer_cluster_table->id()})); |
954 | | |
955 | | // Delete universe. |
956 | 0 | ASSERT_OK(RunAdminToolCommand("delete_universe_replication", kProducerClusterId)); |
957 | 0 | } |
958 | | |
959 | 0 | TEST_F(XClusterAdminCliTest, TestListCdcStreamsWithBootstrappedStreams) { |
960 | 0 | const int kStreamUuidLength = 32; |
961 | 0 | client::TableHandle producer_cluster_table; |
962 | | |
963 | | // Create an identical table on the producer. |
964 | 0 | client::kv_table_test::CreateTable( |
965 | 0 | Transactional::kTrue, NumTablets(), producer_cluster_client_.get(), &producer_cluster_table); |
966 | |
|
967 | 0 | string output = ASSERT_RESULT(RunAdminToolCommand(producer_cluster_.get(), "list_cdc_streams")); |
968 | | // First check that the table and bootstrap status are not present. |
969 | 0 | ASSERT_EQ(output.find(producer_cluster_table->id()), string::npos); |
970 | 0 | ASSERT_EQ(output.find(SysCDCStreamEntryPB::State_Name(SysCDCStreamEntryPB::INITIATED)), |
971 | 0 | string::npos); |
972 | | |
973 | | // Bootstrap the producer. |
974 | 0 | output = ASSERT_RESULT(RunAdminToolCommand( |
975 | 0 | producer_cluster_.get(), "bootstrap_cdc_producer", producer_cluster_table->id())); |
976 | | // Get the bootstrap id (output format is "table id: 123, CDC bootstrap id: 123\n"). |
977 | 0 | string bootstrap_id = output.substr(output.find_last_of(' ') + 1, kStreamUuidLength); |
978 | | |
979 | | // Check list_cdc_streams again for the table and the status INITIATED. |
980 | 0 | ASSERT_OK(CheckTableIsBeingReplicated( |
981 | 0 | {producer_cluster_table->id()}, SysCDCStreamEntryPB::INITIATED)); |
982 | | |
983 | | // Setup universe replication using the bootstrap_id |
984 | 0 | ASSERT_OK(RunAdminToolCommand("setup_universe_replication", |
985 | 0 | kProducerClusterId, |
986 | 0 | producer_cluster_->GetMasterAddresses(), |
987 | 0 | producer_cluster_table->id(), |
988 | 0 | bootstrap_id)); |
989 | | |
990 | | |
991 | | // Check list_cdc_streams again for the table and the status ACTIVE. |
992 | 0 | ASSERT_OK(CheckTableIsBeingReplicated({producer_cluster_table->id()})); |
993 | | |
994 | | // Try restarting the producer to ensure that the status persists. |
995 | 0 | ASSERT_OK(producer_cluster_->RestartSync()); |
996 | 0 | ASSERT_OK(CheckTableIsBeingReplicated({producer_cluster_table->id()})); |
997 | | |
998 | | // Delete this universe so shutdown can proceed. |
999 | 0 | ASSERT_OK(RunAdminToolCommand("delete_universe_replication", kProducerClusterId)); |
1000 | 0 | } |
1001 | | |
1002 | 0 | TEST_F(XClusterAdminCliTest, TestRenameUniverseReplication) { |
1003 | 0 | client::TableHandle producer_cluster_table; |
1004 | | |
1005 | | // Create an identical table on the producer. |
1006 | 0 | client::kv_table_test::CreateTable( |
1007 | 0 | Transactional::kTrue, NumTablets(), producer_cluster_client_.get(), &producer_cluster_table); |
1008 | | |
1009 | | // Setup universe replication, this should only return once complete. |
1010 | 0 | ASSERT_OK(RunAdminToolCommand("setup_universe_replication", |
1011 | 0 | kProducerClusterId, |
1012 | 0 | producer_cluster_->GetMasterAddresses(), |
1013 | 0 | producer_cluster_table->id())); |
1014 | | |
1015 | | // Check that the stream was properly created for this table. |
1016 | 0 | ASSERT_OK(CheckTableIsBeingReplicated({producer_cluster_table->id()})); |
1017 | | |
1018 | | // Now rename the replication group and then try to perform operations on it. |
1019 | 0 | std::string new_replication_id = "new_replication_id"; |
1020 | 0 | ASSERT_OK(RunAdminToolCommand("alter_universe_replication", |
1021 | 0 | kProducerClusterId, |
1022 | 0 | "rename_id", |
1023 | 0 | new_replication_id)); |
1024 | | |
1025 | | // Assert that using old universe id fails. |
1026 | 0 | ASSERT_NOK(RunAdminToolCommand("set_universe_replication_enabled", |
1027 | 0 | kProducerClusterId, |
1028 | 0 | 0)); |
1029 | | // But using correct name should succeed. |
1030 | 0 | ASSERT_OK(RunAdminToolCommand("set_universe_replication_enabled", |
1031 | 0 | new_replication_id, |
1032 | 0 | 0)); |
1033 | | |
1034 | | // Also create a second stream so we can verify name collisions. |
1035 | 0 | std::string collision_id = "collision_id"; |
1036 | 0 | ASSERT_OK(RunAdminToolCommand("setup_universe_replication", |
1037 | 0 | collision_id, |
1038 | 0 | producer_cluster_->GetMasterAddresses(), |
1039 | 0 | producer_cluster_table->id())); |
1040 | 0 | ASSERT_NOK(RunAdminToolCommand("alter_universe_replication", |
1041 | 0 | new_replication_id, |
1042 | 0 | "rename_id", |
1043 | 0 | collision_id)); |
1044 | | |
1045 | | // Using correct name should still succeed. |
1046 | 0 | ASSERT_OK(RunAdminToolCommand("set_universe_replication_enabled", |
1047 | 0 | new_replication_id, |
1048 | 0 | 1)); |
1049 | | |
1050 | | // Also test that we can rename again. |
1051 | 0 | std::string new_replication_id2 = "new_replication_id2"; |
1052 | 0 | ASSERT_OK(RunAdminToolCommand("alter_universe_replication", |
1053 | 0 | new_replication_id, |
1054 | 0 | "rename_id", |
1055 | 0 | new_replication_id2)); |
1056 | | |
1057 | | // Assert that using old universe ids fails. |
1058 | 0 | ASSERT_NOK(RunAdminToolCommand("set_universe_replication_enabled", |
1059 | 0 | kProducerClusterId, |
1060 | 0 | 1)); |
1061 | 0 | ASSERT_NOK(RunAdminToolCommand("set_universe_replication_enabled", |
1062 | 0 | new_replication_id, |
1063 | 0 | 1)); |
1064 | | // But using new correct name should succeed. |
1065 | 0 | ASSERT_OK(RunAdminToolCommand("set_universe_replication_enabled", |
1066 | 0 | new_replication_id2, |
1067 | 0 | 1)); |
1068 | | |
1069 | | // Delete this universe so shutdown can proceed. |
1070 | 0 | ASSERT_OK(RunAdminToolCommand("delete_universe_replication", new_replication_id2)); |
1071 | | // Also delete second one too. |
1072 | 0 | ASSERT_OK(RunAdminToolCommand("delete_universe_replication", collision_id)); |
1073 | 0 | } |
1074 | | |
1075 | | |
1076 | | class XClusterAlterUniverseAdminCliTest : public XClusterAdminCliTest { |
1077 | | public: |
1078 | 0 | void SetUp() override { |
1079 | | // Use more masters so we can test set_master_addresses |
1080 | 0 | opts.num_masters = 3; |
1081 | |
|
1082 | 0 | XClusterAdminCliTest::SetUp(); |
1083 | 0 | } |
1084 | | }; |
1085 | | |
1086 | 0 | TEST_F(XClusterAlterUniverseAdminCliTest, TestAlterUniverseReplication) { |
1087 | 0 | YB_SKIP_TEST_IN_TSAN(); |
1088 | 0 | client::TableHandle producer_table; |
1089 | | |
1090 | | // Create an identical table on the producer. |
1091 | 0 | client::kv_table_test::CreateTable( |
1092 | 0 | Transactional::kTrue, NumTablets(), producer_cluster_client_.get(), &producer_table); |
1093 | | |
1094 | | // Create an additional table to test with as well. |
1095 | 0 | const YBTableName kTableName2(YQL_DATABASE_CQL, "my_keyspace", "ql_client_test_table2"); |
1096 | 0 | client::TableHandle consumer_table2; |
1097 | 0 | client::TableHandle producer_table2; |
1098 | 0 | client::kv_table_test::CreateTable( |
1099 | 0 | Transactional::kTrue, NumTablets(), client_.get(), &consumer_table2, kTableName2); |
1100 | 0 | client::kv_table_test::CreateTable( |
1101 | 0 | Transactional::kTrue, NumTablets(), producer_cluster_client_.get(), &producer_table2, |
1102 | 0 | kTableName2); |
1103 | | |
1104 | | // Setup replication with both tables, this should only return once complete. |
1105 | | // Only use the leader master address initially. |
1106 | 0 | ASSERT_OK(RunAdminToolCommand( |
1107 | 0 | "setup_universe_replication", |
1108 | 0 | kProducerClusterId, |
1109 | 0 | ASSERT_RESULT(producer_cluster_->GetLeaderMiniMaster())->bound_rpc_addr_str(), |
1110 | 0 | producer_table->id() + "," + producer_table2->id())); |
1111 | | |
1112 | | // Test set_master_addresses, use all the master addresses now. |
1113 | 0 | ASSERT_OK(RunAdminToolCommand("alter_universe_replication", |
1114 | 0 | kProducerClusterId, |
1115 | 0 | "set_master_addresses", |
1116 | 0 | producer_cluster_->GetMasterAddresses())); |
1117 | 0 | ASSERT_OK(CheckTableIsBeingReplicated({producer_table->id(), producer_table2->id()})); |
1118 | | |
1119 | | // Test removing a table. |
1120 | 0 | ASSERT_OK(RunAdminToolCommand("alter_universe_replication", |
1121 | 0 | kProducerClusterId, |
1122 | 0 | "remove_table", |
1123 | 0 | producer_table->id())); |
1124 | 0 | ASSERT_OK(CheckTableIsBeingReplicated({producer_table2->id()})); |
1125 | 0 | ASSERT_NOK(CheckTableIsBeingReplicated({producer_table->id()})); |
1126 | | |
1127 | | // Test adding a table. |
1128 | 0 | ASSERT_OK(RunAdminToolCommand("alter_universe_replication", |
1129 | 0 | kProducerClusterId, |
1130 | 0 | "add_table", |
1131 | 0 | producer_table->id())); |
1132 | 0 | ASSERT_OK(CheckTableIsBeingReplicated({producer_table->id(), producer_table2->id()})); |
1133 | |
|
1134 | 0 | ASSERT_OK(RunAdminToolCommand("delete_universe_replication", kProducerClusterId)); |
1135 | 0 | } |
1136 | | |
1137 | 0 | TEST_F(XClusterAlterUniverseAdminCliTest, TestAlterUniverseReplicationWithBootstrapId) { |
1138 | 0 | YB_SKIP_TEST_IN_TSAN(); |
1139 | 0 | const int kStreamUuidLength = 32; |
1140 | 0 | client::TableHandle producer_table; |
1141 | | |
1142 | | // Create an identical table on the producer. |
1143 | 0 | client::kv_table_test::CreateTable( |
1144 | 0 | Transactional::kTrue, NumTablets(), producer_cluster_client_.get(), &producer_table); |
1145 | | |
1146 | | // Create an additional table to test with as well. |
1147 | 0 | const YBTableName kTableName2(YQL_DATABASE_CQL, "my_keyspace", "ql_client_test_table2"); |
1148 | 0 | client::TableHandle consumer_table2; |
1149 | 0 | client::TableHandle producer_table2; |
1150 | 0 | client::kv_table_test::CreateTable( |
1151 | 0 | Transactional::kTrue, NumTablets(), client_.get(), &consumer_table2, kTableName2); |
1152 | 0 | client::kv_table_test::CreateTable( |
1153 | 0 | Transactional::kTrue, NumTablets(), producer_cluster_client_.get(), &producer_table2, |
1154 | 0 | kTableName2); |
1155 | | |
1156 | | // Get bootstrap ids for both producer tables and get bootstrap ids. |
1157 | 0 | string output = ASSERT_RESULT(RunAdminToolCommand( |
1158 | 0 | producer_cluster_.get(), "bootstrap_cdc_producer", producer_table->id())); |
1159 | 0 | string bootstrap_id1 = output.substr(output.find_last_of(' ') + 1, kStreamUuidLength); |
1160 | 0 | ASSERT_OK(CheckTableIsBeingReplicated( |
1161 | 0 | {producer_table->id()}, |
1162 | 0 | master::SysCDCStreamEntryPB_State_INITIATED)); |
1163 | |
|
1164 | 0 | output = ASSERT_RESULT(RunAdminToolCommand( |
1165 | 0 | producer_cluster_.get(), "bootstrap_cdc_producer", producer_table2->id())); |
1166 | 0 | string bootstrap_id2 = output.substr(output.find_last_of(' ') + 1, kStreamUuidLength); |
1167 | 0 | ASSERT_OK(CheckTableIsBeingReplicated( |
1168 | 0 | {producer_table2->id()}, |
1169 | 0 | master::SysCDCStreamEntryPB_State_INITIATED)); |
1170 | | |
1171 | | // Setup replication with first table, this should only return once complete. |
1172 | | // Only use the leader master address initially. |
1173 | 0 | ASSERT_OK(RunAdminToolCommand( |
1174 | 0 | "setup_universe_replication", |
1175 | 0 | kProducerClusterId, |
1176 | 0 | ASSERT_RESULT(producer_cluster_->GetLeaderMiniMaster())->bound_rpc_addr_str(), |
1177 | 0 | producer_table->id(), |
1178 | 0 | bootstrap_id1)); |
1179 | | |
1180 | | // Test adding the second table with bootstrap id |
1181 | 0 | ASSERT_OK(RunAdminToolCommand("alter_universe_replication", |
1182 | 0 | kProducerClusterId, |
1183 | 0 | "add_table", |
1184 | 0 | producer_table2->id(), |
1185 | 0 | bootstrap_id2)); |
1186 | 0 | ASSERT_OK(CheckTableIsBeingReplicated({producer_table->id(), producer_table2->id()})); |
1187 | |
|
1188 | 0 | ASSERT_OK(RunAdminToolCommand("delete_universe_replication", kProducerClusterId)); |
1189 | 0 | } |
1190 | | |
1191 | | // delete_cdc_stream tests |
1192 | 0 | TEST_F(XClusterAdminCliTest, TestDeleteCDCStreamWithConsumerSetup) { |
1193 | 0 | client::TableHandle producer_table; |
1194 | | |
1195 | | // Create an identical table on the producer. |
1196 | 0 | client::kv_table_test::CreateTable( |
1197 | 0 | Transactional::kTrue, NumTablets(), producer_cluster_client_.get(), &producer_table); |
1198 | | |
1199 | | // Setup universe replication, this should only return once complete. |
1200 | 0 | ASSERT_OK(RunAdminToolCommand("setup_universe_replication", |
1201 | 0 | kProducerClusterId, |
1202 | 0 | producer_cluster_->GetMasterAddresses(), |
1203 | 0 | producer_table->id())); |
1204 | 0 | ASSERT_OK(CheckTableIsBeingReplicated({producer_table->id()})); |
1205 | |
|
1206 | 0 | string stream_id = ASSERT_RESULT(GetRecentStreamId(producer_cluster_.get())); |
1207 | | |
1208 | | // Should fail as it should meet the conditions to be stopped. |
1209 | 0 | ASSERT_NOK(RunAdminToolCommand(producer_cluster_.get(), "delete_cdc_stream", stream_id)); |
1210 | | // Should pass as we force it. |
1211 | 0 | ASSERT_OK(RunAdminToolCommand(producer_cluster_.get(), "delete_cdc_stream", stream_id, |
1212 | 0 | "force_delete")); |
1213 | | // Delete universe should fail as we've force deleted the stream. |
1214 | 0 | ASSERT_NOK(RunAdminToolCommand("delete_universe_replication", kProducerClusterId)); |
1215 | 0 | ASSERT_OK(RunAdminToolCommand("delete_universe_replication", |
1216 | 0 | kProducerClusterId, |
1217 | 0 | "ignore-errors")); |
1218 | 0 | } |
1219 | | |
1220 | 0 | TEST_F(XClusterAdminCliTest, TestDeleteCDCStreamWithBootstrap) { |
1221 | 0 | const int kStreamUuidLength = 32; |
1222 | 0 | client::TableHandle producer_table; |
1223 | | |
1224 | | // Create an identical table on the producer. |
1225 | 0 | client::kv_table_test::CreateTable( |
1226 | 0 | Transactional::kTrue, NumTablets(), producer_cluster_client_.get(), &producer_table); |
1227 | |
|
1228 | 0 | string output = ASSERT_RESULT(RunAdminToolCommand( |
1229 | 0 | producer_cluster_.get(), "bootstrap_cdc_producer", producer_table->id())); |
1230 | | // Get the bootstrap id (output format is "table id: 123, CDC bootstrap id: 123\n"). |
1231 | 0 | string bootstrap_id = output.substr(output.find_last_of(' ') + 1, kStreamUuidLength); |
1232 | | |
1233 | | // Setup universe replication, this should only return once complete. |
1234 | 0 | ASSERT_OK(RunAdminToolCommand("setup_universe_replication", |
1235 | 0 | kProducerClusterId, |
1236 | 0 | producer_cluster_->GetMasterAddresses(), |
1237 | 0 | producer_table->id(), |
1238 | 0 | bootstrap_id)); |
1239 | 0 | ASSERT_OK(CheckTableIsBeingReplicated({producer_table->id()})); |
1240 | | |
1241 | | // Should fail as it should meet the conditions to be stopped. |
1242 | 0 | ASSERT_NOK(RunAdminToolCommand(producer_cluster_.get(), "delete_cdc_stream", bootstrap_id)); |
1243 | | // Delete should work fine from deleting from universe. |
1244 | 0 | ASSERT_OK(RunAdminToolCommand("delete_universe_replication", kProducerClusterId)); |
1245 | 0 | } |
1246 | | |
1247 | 0 | TEST_F(AdminCliTest, TestDeleteCDCStreamWithCreateCDCStream) { |
1248 | | |
1249 | | // Create an identical table on the producer. |
1250 | 0 | client::kv_table_test::CreateTable( |
1251 | 0 | Transactional::kTrue, NumTablets(), client_.get(), &table_); |
1252 | | |
1253 | | // Create CDC stream |
1254 | 0 | ASSERT_OK(RunAdminToolCommand(cluster_.get(), |
1255 | 0 | "create_cdc_stream", |
1256 | 0 | table_->id())); |
1257 | |
|
1258 | 0 | string stream_id = ASSERT_RESULT(GetRecentStreamId(cluster_.get())); |
1259 | | |
1260 | | // Should be deleted. |
1261 | 0 | ASSERT_OK(RunAdminToolCommand(cluster_.get(), "delete_cdc_stream", stream_id)); |
1262 | 0 | } |
1263 | | |
1264 | | } // namespace tools |
1265 | | } // namespace yb |