Skip to content

Commit 06528a0

Browse files
committed
feat(enterprise): add database migration commands (#158)
- Get migration status by UID - Export database data - Import database data with JSON configuration - Support for stdin input via '-' flag - Comprehensive mdBook documentation
1 parent 352d009 commit 06528a0

File tree

6 files changed

+458
-0
lines changed

6 files changed

+458
-0
lines changed

crates/redisctl/src/cli.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1027,6 +1027,10 @@ pub enum EnterpriseCommands {
10271027
#[command(subcommand)]
10281028
Logs(crate::commands::enterprise::logs::LogsCommands),
10291029

1030+
/// Migration operations
1031+
#[command(subcommand)]
1032+
Migration(crate::commands::enterprise::migration::MigrationCommands),
1033+
10301034
/// Module management operations
10311035
#[command(subcommand)]
10321036
Module(crate::commands::enterprise::module::ModuleCommands),
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
use anyhow::Context;
2+
use clap::Subcommand;
3+
4+
use crate::{cli::OutputFormat, connection::ConnectionManager, error::Result as CliResult};
5+
6+
#[allow(dead_code)]
7+
pub async fn handle_migration_command(
8+
conn_mgr: &ConnectionManager,
9+
profile_name: Option<&str>,
10+
migration_cmd: MigrationCommands,
11+
output_format: OutputFormat,
12+
query: Option<&str>,
13+
) -> CliResult<()> {
14+
migration_cmd
15+
.execute(conn_mgr, profile_name, output_format, query)
16+
.await
17+
}
18+
19+
#[derive(Debug, Clone, Subcommand)]
20+
pub enum MigrationCommands {
21+
/// Get migration status
22+
Get {
23+
/// Migration UID
24+
uid: u64,
25+
},
26+
27+
/// Export database data
28+
Export {
29+
/// Database UID
30+
bdb_uid: u64,
31+
},
32+
33+
/// Import database data
34+
Import {
35+
/// Database UID
36+
bdb_uid: u64,
37+
/// Import data (use @filename or - for stdin)
38+
#[arg(short, long)]
39+
data: String,
40+
},
41+
}
42+
43+
impl MigrationCommands {
44+
#[allow(dead_code)]
45+
pub async fn execute(
46+
&self,
47+
conn_mgr: &ConnectionManager,
48+
profile_name: Option<&str>,
49+
output_format: OutputFormat,
50+
query: Option<&str>,
51+
) -> CliResult<()> {
52+
handle_migration_command_impl(conn_mgr, profile_name, self, output_format, query).await
53+
}
54+
}
55+
56+
#[allow(dead_code)]
57+
async fn handle_migration_command_impl(
58+
conn_mgr: &ConnectionManager,
59+
profile_name: Option<&str>,
60+
command: &MigrationCommands,
61+
output_format: OutputFormat,
62+
query: Option<&str>,
63+
) -> CliResult<()> {
64+
let client = conn_mgr.create_enterprise_client(profile_name).await?;
65+
66+
match command {
67+
MigrationCommands::Get { uid } => {
68+
let response: serde_json::Value = client
69+
.get(&format!("/v1/migrations/{}", uid))
70+
.await
71+
.context(format!("Failed to get migration {}", uid))?;
72+
73+
let output_data = if let Some(q) = query {
74+
super::utils::apply_jmespath(&response, q)?
75+
} else {
76+
response
77+
};
78+
79+
super::utils::print_formatted_output(output_data, output_format)?;
80+
}
81+
MigrationCommands::Export { bdb_uid } => {
82+
let response: serde_json::Value = client
83+
.post(
84+
&format!("/v1/bdbs/{}/actions/export", bdb_uid),
85+
&serde_json::json!({}),
86+
)
87+
.await
88+
.context(format!("Failed to export database {}", bdb_uid))?;
89+
90+
let output_data = if let Some(q) = query {
91+
super::utils::apply_jmespath(&response, q)?
92+
} else {
93+
response
94+
};
95+
96+
super::utils::print_formatted_output(output_data, output_format)?;
97+
}
98+
MigrationCommands::Import { bdb_uid, data } => {
99+
let payload = super::utils::read_json_data(data)?;
100+
101+
let response: serde_json::Value = client
102+
.post(&format!("/v1/bdbs/{}/actions/import", bdb_uid), &payload)
103+
.await
104+
.context(format!("Failed to import data to database {}", bdb_uid))?;
105+
106+
let output_data = if let Some(q) = query {
107+
super::utils::apply_jmespath(&response, q)?
108+
} else {
109+
response
110+
};
111+
112+
super::utils::print_formatted_output(output_data, output_format)?;
113+
}
114+
}
115+
116+
Ok(())
117+
}
118+
119+
#[cfg(test)]
120+
mod tests {
121+
use super::*;
122+
123+
#[test]
124+
fn test_migration_command_parsing() {
125+
use clap::Parser;
126+
127+
#[derive(Parser)]
128+
struct TestCli {
129+
#[command(subcommand)]
130+
cmd: MigrationCommands,
131+
}
132+
133+
// Test get command
134+
let cli = TestCli::parse_from(["test", "get", "1"]);
135+
if let MigrationCommands::Get { uid } = cli.cmd {
136+
assert_eq!(uid, 1);
137+
} else {
138+
panic!("Expected Get command");
139+
}
140+
141+
// Test export command
142+
let cli = TestCli::parse_from(["test", "export", "2"]);
143+
if let MigrationCommands::Export { bdb_uid } = cli.cmd {
144+
assert_eq!(bdb_uid, 2);
145+
} else {
146+
panic!("Expected Export command");
147+
}
148+
149+
// Test import command
150+
let cli = TestCli::parse_from(["test", "import", "3", "--data", "@import.json"]);
151+
if let MigrationCommands::Import { bdb_uid, data } = cli.cmd {
152+
assert_eq!(bdb_uid, 3);
153+
assert_eq!(data, "@import.json");
154+
} else {
155+
panic!("Expected Import command");
156+
}
157+
}
158+
}

crates/redisctl/src/commands/enterprise/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ pub mod endpoint;
1515
pub mod job_scheduler;
1616
pub mod logs;
1717
pub mod logs_impl;
18+
pub mod migration;
1819
pub mod module;
1920
pub mod module_impl;
2021
pub mod node;

crates/redisctl/src/main.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,16 @@ async fn execute_enterprise_command(
330330
)
331331
.await
332332
}
333+
Migration(migration_cmd) => {
334+
commands::enterprise::migration::handle_migration_command(
335+
conn_mgr,
336+
profile,
337+
migration_cmd.clone(),
338+
output,
339+
query,
340+
)
341+
.await
342+
}
333343
Module(module_cmd) => {
334344
commands::enterprise::module_impl::handle_module_commands(
335345
conn_mgr, profile, module_cmd, output, query,

docs/src/SUMMARY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
- [Usage Reports](./enterprise/usage-report.md)
4040
- [Modules](./enterprise/modules.md)
4141
- [Logs](./enterprise/logs.md)
42+
- [Database Migration](./enterprise/migration.md)
4243
- [Active-Active (CRDB)](./enterprise/crdb.md)
4344
- [CRDB Tasks](./enterprise/crdb-tasks.md)
4445
- [Actions (Tasks)](./enterprise/actions.md)

0 commit comments

Comments
 (0)