YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/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