@@ -108,17 +108,23 @@ int TProxy::Run() {
108
108
if (const auto res = Init ()) {
109
109
return res;
110
110
}
111
- if (Initialize_ ) {
112
- if (const auto res = InitDatabase ()) {
111
+ if (!ExportTo_. empty () ) {
112
+ if (const auto res = ExportDatabase ()) {
113
113
return res;
114
114
}
115
- }
116
- if (!ImportPrefix_.empty ()) {
117
- if (const auto res = ImportDatabase ()) {
118
- return res;
115
+ } else {
116
+ if (Initialize_) {
117
+ if (const auto res = InitDatabase ()) {
118
+ return res;
119
+ }
120
+ }
121
+ if (!ImportPrefix_.empty ()) {
122
+ if (const auto res = ImportDatabase ()) {
123
+ return res;
124
+ }
119
125
}
120
126
}
121
- if (!Initialize_ && ImportPrefix_.empty ()) {
127
+ if (!Initialize_ && ImportPrefix_.empty () && ExportTo_. empty () ) {
122
128
if (const auto res = StartServer ()) {
123
129
return res;
124
130
}
@@ -225,6 +231,75 @@ int TProxy::ImportDatabase() {
225
231
return 0 ;
226
232
}
227
233
234
+ int TProxy::ExportDatabase () {
235
+ auto credentials = grpc::InsecureChannelCredentials ();
236
+ if (!Root.empty () || !Cert.empty () || !Key.empty ()) {
237
+ const grpc::SslCredentialsOptions opts {
238
+ .pem_root_certs = TFileInput (Root).ReadAll (),
239
+ .pem_private_key = TFileInput (Key).ReadAll (),
240
+ .pem_cert_chain = TFileInput (Cert).ReadAll ()
241
+ };
242
+ credentials = grpc::SslCredentials (opts);
243
+ }
244
+
245
+ const auto channel = grpc::CreateChannel (TString (ExportTo_), credentials);
246
+ const std::unique_ptr<etcdserverpb::KV::Stub> kv = etcdserverpb::KV::NewStub (channel);
247
+
248
+ NYdb::TDriverConfig config;
249
+ config.SetEndpoint (Endpoint);
250
+ config.SetDatabase (Database);
251
+ if (!Token.empty ())
252
+ config.SetAuthToken (Token);
253
+ if (!CA.empty ())
254
+ config.UseSecureConnection (TFileInput (CA).ReadAll ());
255
+
256
+ const auto driver = NYdb::TDriver (config);
257
+ auto client = NYdb::NTable::TTableClient (driver);
258
+ auto count = 0ULL ;
259
+ if (const auto res = client.CreateSession ().ExtractValueSync (); res.IsSuccess ()) {
260
+ NYdb::NTable::TReadTableSettings settings;
261
+ settings.BatchLimitRows (97ULL ).AppendColumns (" key" ).AppendColumns (" value" ).AppendColumns (" lease" );
262
+ if (auto it = res.GetSession ().ReadTable (Database + Folder + " /current" , settings).ExtractValueSync (); it.IsSuccess ()) {
263
+ for (;;) {
264
+ auto streamPart = it.ReadNext ().ExtractValueSync ();
265
+ if (streamPart.EOS ())
266
+ break ;
267
+
268
+ if (!streamPart.IsSuccess ()) {
269
+ std::cout << streamPart.GetIssues ().ToString () << std::endl;
270
+ return 1 ;
271
+ }
272
+
273
+ etcdserverpb::TxnRequest txnRequest;
274
+ for (auto parser = NYdb::TResultSetParser (streamPart.ExtractPart ()); parser.TryNextRow ();) {
275
+ if (const auto lease = NYdb::TValueParser (parser.GetValue (" lease" )).GetOptionalInt64 (); lease && !*lease) {
276
+ ++count;
277
+ const auto put = txnRequest.add_success ()->mutable_request_put ();
278
+ put->set_key (*NYdb::TValueParser (parser.GetValue (" key" )).GetOptionalString ());
279
+ put->set_value (*NYdb::TValueParser (parser.GetValue (" value" )).GetOptionalString ());
280
+ }
281
+ }
282
+
283
+ grpc::ClientContext txnCtx;
284
+ etcdserverpb::TxnResponse txnResponse;
285
+ if (const auto & status = kv->Txn (&txnCtx, txnRequest, &txnResponse); !status.ok ()) {
286
+ std::cout << status.error_message () << std::endl;
287
+ return 1 ;
288
+ }
289
+ }
290
+ } else {
291
+ std::cout << it.GetIssues ().ToString () << std::endl;
292
+ return 1 ;
293
+ }
294
+ } else {
295
+ std::cout << res.GetIssues ().ToString () << std::endl;
296
+ return 1 ;
297
+ }
298
+
299
+ std::cout << count << " keys exported successfully." << std::endl;
300
+ return 0 ;
301
+ }
302
+
228
303
int TProxy::Shutdown () {
229
304
if (GRpcServer)
230
305
GRpcServer->Stop ();
@@ -252,6 +327,7 @@ TProxy::TProxy(int argc, char** argv)
252
327
253
328
opts.AddLongOption (" import-from" , " Import existing data from etcd base" ).RequiredArgument (" ENDPOINT" ).DefaultValue (" localhost:2379" ).StoreResult (&ImportFrom_);
254
329
opts.AddLongOption (" import-prefix" , " Prefix of data to import" ).RequiredArgument (" PREFIX" ).StoreResult (&ImportPrefix_);
330
+ opts.AddLongOption (" export-to" , " Export existing data to etcd from ydb" ).RequiredArgument (" ENDPOINT" ).StoreResult (&ExportTo_);
255
331
256
332
opts.AddLongOption (" ca" , " SSL CA certificate file" ).Optional ().RequiredArgument (" CA" ).StoreResult (&Root);
257
333
opts.AddLongOption (" cert" , " SSL certificate file" ).Optional ().RequiredArgument (" CERT" ).StoreResult (&Cert);
0 commit comments