From 316efc26184dba7d8b2ad6f8818c820747277a24 Mon Sep 17 00:00:00 2001 From: Pucheng Yang <8072956+puchengy@users.noreply.github.com> Date: Tue, 4 Feb 2025 03:28:22 -0800 Subject: [PATCH 01/33] [#6384] fix: Gravitino default JVM config mismatches with comments from gravitino-env.sh (#6385) ### What changes were proposed in this pull request? Update Gravitino JVM memory default. ### Why are the changes needed? Fix: https://github.com/apache/gravitino/issues/6384 ### Does this PR introduce _any_ user-facing change? No ### How was this patch tested? No test --- bin/common.sh.template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/common.sh.template b/bin/common.sh.template index b81710a3fc5..a5de3bd38ca 100644 --- a/bin/common.sh.template +++ b/bin/common.sh.template @@ -106,7 +106,7 @@ function addDirToClasspath(){ } if [[ -z "${GRAVITINO_MEM}" ]]; then - export GRAVITINO_MEM="-Xmx1024m" + export GRAVITINO_MEM="-Xms1024m -Xmx1024m -XX:MaxMetaspaceSize=512m" fi if [[ -n "${JAVA_HOME}" ]]; then From 71998d9df4f7af0c5cedcb8ee845721a86d8455b Mon Sep 17 00:00:00 2001 From: Yuhui Date: Wed, 5 Feb 2025 16:02:19 +0800 Subject: [PATCH 02/33] [#6279] feat (gvfs-fuse): Add gvfs-fuse integration tests for big files and open-file flag test cases (#6280) ### What changes were proposed in this pull request? Add gvfs-fuse integration tests for big files and open-file flag test cases ### Why are the changes needed? Fix: #6279 ### Does this PR introduce _any_ user-facing change? No ### How was this patch tested? IT --- clients/filesystem-fuse/Makefile | 2 + clients/filesystem-fuse/src/filesystem.rs | 20 +- clients/filesystem-fuse/src/main.rs | 2 +- .../filesystem-fuse/src/memory_filesystem.rs | 35 +- .../src/open_dal_filesystem.rs | 142 ++++- .../tests/bin/run_fuse_testers.sh | 11 +- .../tests/bin/run_s3fs_testers.sh | 9 + clients/filesystem-fuse/tests/fuse_test.rs | 487 +++++++++++++++--- 8 files changed, 587 insertions(+), 121 deletions(-) diff --git a/clients/filesystem-fuse/Makefile b/clients/filesystem-fuse/Makefile index 86dd2f22152..21a97ceec7e 100644 --- a/clients/filesystem-fuse/Makefile +++ b/clients/filesystem-fuse/Makefile @@ -71,5 +71,7 @@ test-s3: test: doc-test cargo test --no-fail-fast --all-targets --all-features --workspace +test-all: test test-s3 test-fuse-it + clean: cargo clean diff --git a/clients/filesystem-fuse/src/filesystem.rs b/clients/filesystem-fuse/src/filesystem.rs index dcf35f8ebca..c0c27a5fbe2 100644 --- a/clients/filesystem-fuse/src/filesystem.rs +++ b/clients/filesystem-fuse/src/filesystem.rs @@ -297,7 +297,7 @@ pub trait FileWriter: Sync + Send { #[cfg(test)] pub(crate) mod tests { use super::*; - use libc::{O_APPEND, O_CREAT, O_RDONLY}; + use libc::{O_CREAT, O_RDONLY, O_WRONLY}; use std::collections::HashMap; use std::path::Component; @@ -461,7 +461,11 @@ pub(crate) mod tests { // Test create file let file_handle = self - .test_create_file(parent_file_id, "file1.txt".as_ref()) + .test_create_file( + parent_file_id, + "file1.txt".as_ref(), + (O_CREAT | O_WRONLY) as u32, + ) .await; // Test write file @@ -545,11 +549,13 @@ pub(crate) mod tests { self.files.insert(file_stat.file_id, file_stat); } - async fn test_create_file(&mut self, root_file_id: u64, name: &OsStr) -> FileHandle { - let file = self - .fs - .create_file(root_file_id, name, (O_CREAT | O_APPEND) as u32) - .await; + async fn test_create_file( + &mut self, + root_file_id: u64, + name: &OsStr, + flags: u32, + ) -> FileHandle { + let file = self.fs.create_file(root_file_id, name, flags).await; assert!(file.is_ok()); let file = file.unwrap(); assert!(file.handle_id > 0); diff --git a/clients/filesystem-fuse/src/main.rs b/clients/filesystem-fuse/src/main.rs index 3534e033465..4e517c76b37 100644 --- a/clients/filesystem-fuse/src/main.rs +++ b/clients/filesystem-fuse/src/main.rs @@ -24,7 +24,7 @@ use tokio::signal; #[tokio::main] async fn main() -> fuse3::Result<()> { - tracing_subscriber::fmt().init(); + tracing_subscriber::fmt::init(); // todo need inmprove the args parsing let args: Vec = std::env::args().collect(); diff --git a/clients/filesystem-fuse/src/memory_filesystem.rs b/clients/filesystem-fuse/src/memory_filesystem.rs index f56e65ea33a..d0385390729 100644 --- a/clients/filesystem-fuse/src/memory_filesystem.rs +++ b/clients/filesystem-fuse/src/memory_filesystem.rs @@ -91,7 +91,7 @@ impl PathFileSystem for MemoryFileSystem { Ok(results) } - async fn open_file(&self, path: &Path, _flags: OpenFileFlags) -> Result { + async fn open_file(&self, path: &Path, flags: OpenFileFlags) -> Result { let file_stat = self.stat(path).await?; let mut opened_file = OpenedFile::new(file_stat); match opened_file.file_stat.kind { @@ -105,8 +105,17 @@ impl PathFileSystem for MemoryFileSystem { .unwrap() .data .clone(); - opened_file.reader = Some(Box::new(MemoryFileReader { data: data.clone() })); - opened_file.writer = Some(Box::new(MemoryFileWriter { data: data })); + if flags.is_read() { + opened_file.reader = Some(Box::new(MemoryFileReader { data: data.clone() })); + } + if flags.is_write() || flags.is_append() || flags.is_truncate() { + opened_file.writer = Some(Box::new(MemoryFileWriter { data: data.clone() })); + } + + if flags.is_truncate() { + let mut data = data.lock().unwrap(); + data.clear(); + } Ok(opened_file) } _ => Err(Errno::from(libc::EBADF)), @@ -117,27 +126,19 @@ impl PathFileSystem for MemoryFileSystem { self.open_file(path, flags).await } - async fn create_file(&self, path: &Path, _flags: OpenFileFlags) -> Result { - let mut file_map = self.file_map.write().unwrap(); - if file_map.contains_key(path) { + async fn create_file(&self, path: &Path, flags: OpenFileFlags) -> Result { + if self.file_map.read().unwrap().contains_key(path) && flags.is_exclusive() { return Err(Errno::from(libc::EEXIST)); } - let mut opened_file = OpenedFile::new(FileStat::new_file_filestat_with_path(path, 0)); - - let data = Arc::new(Mutex::new(Vec::new())); - file_map.insert( - opened_file.file_stat.path.clone(), + self.file_map.write().unwrap().insert( + path.to_path_buf(), MemoryFile { kind: RegularFile, - data: data.clone(), + data: Arc::new(Mutex::new(Vec::new())), }, ); - - opened_file.reader = Some(Box::new(MemoryFileReader { data: data.clone() })); - opened_file.writer = Some(Box::new(MemoryFileWriter { data: data })); - - Ok(opened_file) + self.open_file(path, flags).await } async fn create_dir(&self, path: &Path) -> Result { diff --git a/clients/filesystem-fuse/src/open_dal_filesystem.rs b/clients/filesystem-fuse/src/open_dal_filesystem.rs index d32b014d1f0..9e094873f56 100644 --- a/clients/filesystem-fuse/src/open_dal_filesystem.rs +++ b/clients/filesystem-fuse/src/open_dal_filesystem.rs @@ -26,19 +26,26 @@ use bytes::Bytes; use fuse3::FileType::{Directory, RegularFile}; use fuse3::{Errno, FileType, Timestamp}; use log::error; -use opendal::{EntryMode, ErrorKind, Metadata, Operator}; +use opendal::{Buffer, EntryMode, ErrorKind, Metadata, Operator}; +use std::mem::swap; use std::path::{Path, PathBuf}; use std::time::SystemTime; pub(crate) struct OpenDalFileSystem { op: Operator, + block_size: u32, } impl OpenDalFileSystem {} impl OpenDalFileSystem { - pub(crate) fn new(op: Operator, _config: &AppConfig, _fs_context: &FileSystemContext) -> Self { - Self { op: op } + const WRITE_BUFFER_SIZE: usize = 5 * 1024 * 1024; + + pub(crate) fn new(op: Operator, config: &AppConfig, _fs_context: &FileSystemContext) -> Self { + Self { + op: op, + block_size: config.filesystem.block_size, + } } fn opendal_meta_to_file_stat(&self, meta: &Metadata, file_stat: &mut FileStat) { @@ -120,14 +127,30 @@ impl PathFileSystem for OpenDalFileSystem { .map_err(opendal_error_to_errno)?; file.reader = Some(Box::new(FileReaderImpl { reader })); } - if flags.is_write() || flags.is_create() || flags.is_append() || flags.is_truncate() { + if !flags.is_create() && flags.is_append() { + error!("The file system does not support open a exists file with the append mode"); + return Err(Errno::from(libc::EINVAL)); + } + + if flags.is_truncate() { + self.op + .write(&file_name, Buffer::new()) + .await + .map_err(opendal_error_to_errno)?; + } + + if flags.is_write() || flags.is_append() || flags.is_truncate() { let writer = self .op .writer_with(&file_name) .await .map_err(opendal_error_to_errno)?; - file.writer = Some(Box::new(FileWriterImpl { writer })); + file.writer = Some(Box::new(FileWriterImpl::new( + writer, + Self::WRITE_BUFFER_SIZE + self.block_size as usize, + ))); } + Ok(file) } @@ -141,15 +164,17 @@ impl PathFileSystem for OpenDalFileSystem { async fn create_file(&self, path: &Path, flags: OpenFileFlags) -> Result { let file_name = path.to_string_lossy().to_string(); + if flags.is_exclusive() { + let meta = self.op.stat(&file_name).await; + if meta.is_ok() { + return Err(Errno::from(libc::EEXIST)); + } + } - let mut writer = self - .op - .writer_with(&file_name) + self.op + .write(&file_name, Buffer::new()) .await .map_err(opendal_error_to_errno)?; - - writer.close().await.map_err(opendal_error_to_errno)?; - let file = self.open_file(path, flags).await?; Ok(file) } @@ -210,19 +235,45 @@ impl FileReader for FileReaderImpl { struct FileWriterImpl { writer: opendal::Writer, + buffer: Vec, + buffer_size: usize, +} + +impl FileWriterImpl { + fn new(writer: opendal::Writer, buffer_size: usize) -> Self { + Self { + writer, + buffer_size: buffer_size, + buffer: Vec::with_capacity(buffer_size), + } + } } #[async_trait] impl FileWriter for FileWriterImpl { async fn write(&mut self, _offset: u64, data: &[u8]) -> Result { - self.writer - .write(data.to_vec()) - .await - .map_err(opendal_error_to_errno)?; + if self.buffer.len() > OpenDalFileSystem::WRITE_BUFFER_SIZE { + let mut new_buffer: Vec = Vec::with_capacity(self.buffer_size); + swap(&mut new_buffer, &mut self.buffer); + + self.writer + .write(new_buffer) + .await + .map_err(opendal_error_to_errno)?; + } + self.buffer.extend(data); Ok(data.len() as u32) } async fn close(&mut self) -> Result<()> { + if !self.buffer.is_empty() { + let mut new_buffer: Vec = vec![]; + swap(&mut new_buffer, &mut self.buffer); + self.writer + .write(new_buffer) + .await + .map_err(opendal_error_to_errno)?; + } self.writer.close().await.map_err(opendal_error_to_errno)?; Ok(()) } @@ -260,10 +311,12 @@ fn opendal_filemode_to_filetype(mode: EntryMode) -> FileType { #[cfg(test)] mod test { use crate::config::AppConfig; + use crate::open_dal_filesystem::OpenDalFileSystem; use crate::s3_filesystem::extract_s3_config; use crate::s3_filesystem::tests::s3_test_config; use crate::test_enable_with; use crate::RUN_TEST_WITH_S3; + use bytes::Buf; use opendal::layers::LoggingLayer; use opendal::{services, Builder, Operator}; @@ -327,4 +380,63 @@ mod test { } } } + + #[tokio::test] + async fn s3_ut_test_s3_write() { + test_enable_with!(RUN_TEST_WITH_S3); + let config = s3_test_config(); + + let op = create_opendal(&config); + let path = "/s1/fileset1/gvfs_test/test_dir/test_file"; + let mut writer = op.writer_with(path).await.unwrap(); + + let mut buffer: Vec = vec![]; + let num_batch = 10 * 1024; + for i in 0..num_batch { + let data = vec![i as u8; num_batch]; + buffer.extend(&data); + + if buffer.len() > OpenDalFileSystem::WRITE_BUFFER_SIZE { + writer.write(buffer).await.unwrap(); + buffer = vec![]; + }; + } + + if !buffer.is_empty() { + writer.write(buffer).await.unwrap(); + } + writer.close().await.unwrap(); + } + + #[tokio::test] + async fn s3_ut_test_s3_read() { + test_enable_with!(RUN_TEST_WITH_S3); + let config = s3_test_config(); + + let op = create_opendal(&config); + let path = "/s1/fileset1/test_dir/test_big_file"; + let meta = op.stat(path).await; + if meta.is_err() { + println!("stat error: {:?}", meta.err()); + return; + } + let reader = op.reader(path).await.unwrap(); + + let mut buffer = Vec::new(); + + let batch_size = 1024; + let mut start = 0; + let mut end = batch_size; + loop { + let buf = reader.read(start..end).await.unwrap(); + if buf.is_empty() { + break; + } + buffer.extend_from_slice(buf.chunk()); + start = end; + end += batch_size; + } + + println!("Read {} bytes.", buffer.len()); + } } diff --git a/clients/filesystem-fuse/tests/bin/run_fuse_testers.sh b/clients/filesystem-fuse/tests/bin/run_fuse_testers.sh index 6dc38c48f07..7088a310b50 100755 --- a/clients/filesystem-fuse/tests/bin/run_fuse_testers.sh +++ b/clients/filesystem-fuse/tests/bin/run_fuse_testers.sh @@ -50,13 +50,22 @@ if [ "$1" == "test" ]; then echo "Running tests..." cd $CLIENT_FUSE_DIR export RUN_TEST_WITH_FUSE=1 - cargo test --test fuse_test fuse_it_ + cargo test --test fuse_test fuse_it_ -- weak_consistency elif [ "$1" == "start" ]; then # Start the servers echo "Starting servers..." start_servers +elif [ "$1" == "restart" ]; then + # Stop the servers + echo "Stopping servers..." + stop_servers + + # Start the servers + echo "Starting servers..." + start_servers + elif [ "$1" == "stop" ]; then # Stop the servers echo "Stopping servers..." diff --git a/clients/filesystem-fuse/tests/bin/run_s3fs_testers.sh b/clients/filesystem-fuse/tests/bin/run_s3fs_testers.sh index ac5f9812c93..8f25c0b3954 100644 --- a/clients/filesystem-fuse/tests/bin/run_s3fs_testers.sh +++ b/clients/filesystem-fuse/tests/bin/run_s3fs_testers.sh @@ -51,6 +51,15 @@ elif [ "$1" == "start" ]; then echo "Starting servers..." start_servers +elif [ "$1" == "restart" ]; then + # Stop the servers + echo "Stopping servers..." + stop_servers + + # Start the servers + echo "Starting servers..." + start_servers + elif [ "$1" == "stop" ]; then # Stop the servers echo "Stopping servers..." diff --git a/clients/filesystem-fuse/tests/fuse_test.rs b/clients/filesystem-fuse/tests/fuse_test.rs index 41e385c49f1..1d1ef80b78b 100644 --- a/clients/filesystem-fuse/tests/fuse_test.rs +++ b/clients/filesystem-fuse/tests/fuse_test.rs @@ -22,29 +22,32 @@ use gvfs_fuse::config::AppConfig; use gvfs_fuse::RUN_TEST_WITH_FUSE; use gvfs_fuse::{gvfs_mount, gvfs_unmount, test_enable_with}; use log::{error, info}; -use std::fs::File; -use std::path::Path; -use std::sync::Arc; -use std::thread::sleep; +use once_cell::sync::Lazy; +use std::collections::HashSet; +use std::fs::{File, OpenOptions}; +use std::io::{Read, Write}; +use std::path::{Path, PathBuf}; use std::time::{Duration, Instant}; -use std::{fs, panic, process}; +use std::{env, fs}; use tokio::runtime::Runtime; use tokio::task::JoinHandle; +use tokio::time::interval; -struct FuseTest { - runtime: Arc, +static ASYNC_RUNTIME: Lazy = Lazy::new(|| Runtime::new().unwrap()); + +struct FuseTestEnv { mount_point: String, gvfs_mount: Option>>, } -impl FuseTest { +impl FuseTestEnv { pub fn setup(&mut self) { info!("Start gvfs fuse server"); let mount_point = self.mount_point.clone(); let config = AppConfig::from_file(Some("tests/conf/gvfs_fuse_memory.toml")) .expect("Failed to load config"); - self.runtime.spawn(async move { + ASYNC_RUNTIME.spawn(async move { let result = gvfs_mount(&mount_point, "", &config).await; if let Err(e) = result { error!("Failed to mount gvfs: {:?}", e); @@ -57,116 +60,440 @@ impl FuseTest { } pub fn shutdown(&mut self) { - self.runtime.block_on(async { + ASYNC_RUNTIME.block_on(async { let _ = gvfs_unmount().await; }); } fn wait_for_fuse_server_ready(path: &str, timeout: Duration) -> bool { let test_file = format!("{}/.gvfs_meta", path); - let start_time = Instant::now(); + AwaitUtil::wait(timeout, Duration::from_millis(500), || { + file_exists(&test_file) + }) + } +} + +struct AwaitUtil(); - while start_time.elapsed() < timeout { - if file_exists(&test_file) { - info!("Fuse server is ready",); - return true; +impl AwaitUtil { + pub(crate) fn wait( + max_wait: Duration, + poll_interval: Duration, + check_fn: impl Fn() -> bool + Send, + ) -> bool { + ASYNC_RUNTIME.block_on(async { + let start = Instant::now(); + let mut interval = interval(poll_interval); + + while start.elapsed() < max_wait { + interval.tick().await; + if check_fn() { + return true; + } } - info!("Wait for fuse server ready",); - sleep(Duration::from_secs(1)); - } - false + false + }) } } -impl Drop for FuseTest { +impl Drop for FuseTestEnv { fn drop(&mut self) { info!("Shutdown fuse server"); self.shutdown(); } } -#[test] -fn test_fuse_with_memory_fs() { - tracing_subscriber::fmt().init(); +struct SequenceFileOperationTest { + test_dir: PathBuf, + weak_consistency: bool, +} - panic::set_hook(Box::new(|info| { - error!("A panic occurred: {:?}", info); - process::exit(1); - })); +impl SequenceFileOperationTest { + fn new(test_dir: &Path) -> Self { + let args: Vec = env::args().collect(); + let weak_consistency = args.contains(&"weak_consistency".to_string()); - let mount_point = "target/gvfs"; - let _ = fs::create_dir_all(mount_point); + SequenceFileOperationTest { + test_dir: test_dir.to_path_buf(), + weak_consistency: weak_consistency, + } + } + fn test_create_file(&self, name: &str, open_options: Option<&OpenOptions>) -> File { + let path = self.test_dir.join(name); + let file = { + match open_options { + None => File::create(&path) + .unwrap_or_else(|_| panic!("Failed to create file: {:?}", path)), + Some(options) => options.open(&path).unwrap_or_else(|_| { + panic!( + "Failed to create file: {:?}, + options {:?}", + path, options + ) + }), + } + }; + let file_metadata = file + .metadata() + .unwrap_or_else(|_| panic!("Failed to get file metadata: {:?}", path)); + assert!(file_exists(path)); + if !self.weak_consistency { + assert_eq!(file_metadata.len(), 0); + } + file + } - let mut test = FuseTest { - runtime: Arc::new(Runtime::new().unwrap()), - mount_point: mount_point.to_string(), - gvfs_mount: None, - }; + fn test_open_file(&self, name: &str, open_options: Option<&OpenOptions>) -> File { + let path = self.test_dir.join(name); + let file = { + match open_options { + None => { + File::open(&path).unwrap_or_else(|_| panic!("Failed to open file: {:?}", path)) + } + Some(options) => options.open(&path).unwrap_or_else(|_| { + panic!( + "Failed to open file: {:?}, + options {:?}", + path, options + ) + }), + } + }; + let file_metadata = file + .metadata() + .unwrap_or_else(|_| panic!("Failed to get file metadata: {:?}", path)); + assert!(file_metadata.is_file()); + assert!(file_exists(path)); + file + } - test.setup(); - test_fuse_filesystem(mount_point); -} + fn test_read_file(&self, file: &mut File, expect: &[u8]) { + let mut content = vec![0; expect.len()]; + file.read_exact(&mut content).expect("Failed to read file"); + assert_eq!(content, *expect, "File content mismatch"); + } -#[test] -fn fuse_it_test_fuse() { - test_enable_with!(RUN_TEST_WITH_FUSE); + fn test_read_data(&self, file: &mut File, len: usize) -> Vec { + let mut content = vec![0; len]; + file.read_exact(&mut content).expect("Failed to read file"); + content + } - test_fuse_filesystem("target/gvfs/gvfs_test"); -} + fn test_append_file(&self, file: &mut File, content: &[u8]) { + let old_len = file.metadata().unwrap().len(); + let size = content.len(); + file.write_all(content).expect("Failed to write file"); + + if !self.weak_consistency { + let new_len = file.metadata().unwrap().len(); + assert_eq!(new_len, old_len + size as u64, "File size mismatch"); + } + } + + fn test_remove_file(&self, name: &str) { + let path = self.test_dir.join(name); + fs::remove_file(&path).unwrap_or_else(|_| panic!("Failed to remove file: {:?}", path)); + assert!(!file_exists(path)); + } + + fn test_create_dir(&self, name: &str) { + let path = self.test_dir.join(name); + fs::create_dir(&path).unwrap_or_else(|_| panic!("Failed to create directory: {:?}", path)); + assert!(file_exists(path)); + } + + fn test_list_dir_with_expect(&self, name: &str, expect_childs: &Vec<&str>) { + self.test_list_dir(name, expect_childs, &vec![]); + } + + fn test_list_dir_with_unexpected(&self, name: &str, unexpected_childs: &Vec<&str>) { + self.test_list_dir(name, &vec![], unexpected_childs); + } + + fn test_list_dir(&self, name: &str, expect_childs: &Vec<&str>, unexpected_childs: &Vec<&str>) { + let path = self.test_dir.join(name); + let dir_childs = + fs::read_dir(&path).unwrap_or_else(|_| panic!("Failed to list directory: {:?}", path)); + let mut childs_set: HashSet = HashSet::default(); + for child in dir_childs { + let entry = child.expect("Failed to get entry"); + childs_set.insert(entry.file_name().to_string_lossy().to_string()); + } + for expect_child in expect_childs { + assert!( + childs_set.contains(*expect_child), + "Expect child not found: {}", + expect_child + ); + } + + for unexpected_child in unexpected_childs { + assert!( + !childs_set.contains(*unexpected_child), + "Unexpected child found: {}", + unexpected_child + ); + } + } + + fn test_remove_dir(&self, name: &str) { + let path = self.test_dir.join(name); + fs::remove_dir(&path).unwrap_or_else(|_| panic!("Failed to remove directory: {:?}", path)); + assert!(!file_exists(path)); + } -fn test_fuse_filesystem(mount_point: &str) { - info!("Test startup"); - let base_path = Path::new(mount_point); + // some file storage can't sync file immediately, so we need to sync file to make sure the file is written to disk + fn sync_file(&self, file: File, name: &str, expect_len: u64) -> Result<(), ()> { + if !self.weak_consistency { + return Ok(()); + } + drop(file); - if !file_exists(base_path) { - fs::create_dir_all(base_path).expect("Failed to create test dir"); + let path = self.test_dir.join(name); + let success = AwaitUtil::wait(Duration::from_secs(3), Duration::from_millis(200), || { + let file = + File::open(&path).unwrap_or_else(|_| panic!("Failed to open file: {:?}", path)); + let file_len = file.metadata().unwrap().len(); + file_len >= expect_len + }); + if !success { + return Err(()); + } + Ok(()) } - //test create file - let test_file = base_path.join("test_create"); - let file = File::create(&test_file).expect("Failed to create file"); - assert!(file.metadata().is_ok(), "Failed to get file metadata"); - assert!(file_exists(&test_file)); + fn test_basic_filesystem(fs_test: &SequenceFileOperationTest) { + let file_name1 = "test_create"; + //test create file + let mut file1 = fs_test.test_create_file(file_name1, None); + + //test write file + let content = "write test".as_bytes(); + fs_test.test_append_file(&mut file1, content); + fs_test + .sync_file(file1, file_name1, content.len() as u64) + .expect("Failed to sync file"); + + //test read file + let mut file1 = fs_test.test_open_file(file_name1, None); + fs_test.test_read_file(&mut file1, content); + + //test delete file + fs_test.test_remove_file(file_name1); + + //test create directory + let dir_name1 = "test_dir"; + fs_test.test_create_dir(dir_name1); - //test write file - fs::write(&test_file, "read test").expect("Failed to write file"); + //test create file in directory + let test_file2 = "test_dir/test_file"; + let mut file2 = fs_test.test_create_file(test_file2, None); - //test read file - let content = fs::read_to_string(&test_file).expect("Failed to read file"); - assert_eq!(content, "read test", "File content mismatch"); + //test write file in directory + fs_test.test_append_file(&mut file2, content); + fs_test + .sync_file(file2, test_file2, content.len() as u64) + .expect("Failed to sync file"); - //test delete file - fs::remove_file(&test_file).expect("Failed to delete file"); - assert!(!file_exists(&test_file)); + //test read file in directory + let mut file2 = fs_test.test_open_file(test_file2, None); + fs_test.test_read_file(&mut file2, content); - //test create directory - let test_dir = base_path.join("test_dir"); - fs::create_dir(&test_dir).expect("Failed to create directory"); + //test list directory + fs_test.test_list_dir_with_expect(dir_name1, &vec!["test_file"]); - //test create file in directory - let test_file = base_path.join("test_dir/test_file"); - let file = File::create(&test_file).expect("Failed to create file"); - assert!(file.metadata().is_ok(), "Failed to get file metadata"); + //test delete file in directory + fs_test.test_remove_file(test_file2); - //test write file in directory - let test_file = base_path.join("test_dir/test_read"); - fs::write(&test_file, "read test").expect("Failed to write file"); + //test list directory after delete file + fs_test.test_list_dir_with_unexpected(dir_name1, &vec!["test_file"]); - //test read file in directory - let content = fs::read_to_string(&test_file).expect("Failed to read file"); - assert_eq!(content, "read test", "File content mismatch"); + //test delete directory + fs_test.test_remove_dir(dir_name1); + } + + #[allow(clippy::needless_range_loop)] + fn test_big_file(fs_test: &SequenceFileOperationTest) { + let test_file = "test_big_file"; + let round_size: usize = 1024 * 1024; + let round: u8 = 1; + + //test write big file + { + let mut file = fs_test.test_create_file(test_file, None); + + for i in 0..round { + let mut content = vec![0; round_size]; + for j in 0..round_size { + content[j] = (i as usize + j) as u8; + } - //test delete file in directory - fs::remove_file(&test_file).expect("Failed to delete file"); - assert!(!file_exists(&test_file)); + fs_test.test_append_file(&mut file, &content); + } + fs_test + .sync_file(file, test_file, round_size as u64 * round as u64) + .expect("Failed to sync file"); + } - //test delete directory - fs::remove_dir_all(&test_dir).expect("Failed to delete directory"); - assert!(!file_exists(&test_dir)); + //test read big file + { + let mut file = fs_test.test_open_file(test_file, None); + for i in 0..round { + let buffer = fs_test.test_read_data(&mut file, round_size); - info!("Success test"); + for j in 0..round_size { + assert_eq!(buffer[j], (i as usize + j) as u8, "File content mismatch"); + } + } + } + + fs_test.test_remove_file(test_file); + } + + fn test_open_file_flag(fs_test: &SequenceFileOperationTest) { + let write_content = "write content"; + { + // test open file with read and write create flag + let file_name = "test_open_file"; + let mut file = fs_test.test_create_file( + file_name, + Some(OpenOptions::new().read(true).write(true).create(true)), + ); + + // test write can be done + fs_test.test_append_file(&mut file, write_content.as_bytes()); + + // test read end of file + let result = file.read_exact(&mut [1]); + assert!(result.is_err()); + if let Err(e) = result { + assert_eq!(e.to_string(), "failed to fill whole buffer"); + } + } + + { + // test open file with write flag + let file_name = "test_open_file2"; + let mut file = fs_test + .test_create_file(file_name, Some(OpenOptions::new().write(true).create(true))); + + // test write can be done + fs_test.test_append_file(&mut file, write_content.as_bytes()); + + // test read can be have error + let result = file.read(&mut [0; 10]); + assert!(result.is_err()); + if let Err(e) = result { + assert_eq!(e.to_string(), "Bad file descriptor (os error 9)"); + } + } + + { + // test open file with read flag + let file_name = "test_open_file2"; + let mut file = fs_test.test_open_file(file_name, Some(OpenOptions::new().read(true))); + + // test read can be done + fs_test.test_read_file(&mut file, write_content.as_bytes()); + + // test write can be have error + let result = file.write_all(write_content.as_bytes()); + assert!(result.is_err()); + if let Err(e) = result { + assert_eq!(e.to_string(), "Bad file descriptor (os error 9)"); + } + } + + { + // test open file with truncate file + let file_name = "test_open_file2"; + let file = fs_test.test_open_file( + file_name, + Some(OpenOptions::new().write(true).truncate(true)), + ); + + // test file size is 0 + assert_eq!(file.metadata().unwrap().len(), 0); + } + + { + // test open file with append flag + let file_name = "test_open_file"; + + // opendal_fs does not support open and appand + let result = OpenOptions::new() + .append(true) + .open(fs_test.test_dir.join(file_name)); + if let Err(e) = result { + assert_eq!(e.to_string(), "Invalid argument (os error 22)"); + return; + } + + let mut file = fs_test.test_open_file(file_name, Some(OpenOptions::new().append(true))); + + assert_eq!(file.metadata().unwrap().len(), write_content.len() as u64); + + // test append + fs_test.test_append_file(&mut file, write_content.as_bytes()); + let file_len = file.metadata().unwrap().len(); + assert_eq!(file_len, 2 * write_content.len() as u64); + } + } } fn file_exists>(path: P) -> bool { fs::metadata(path).is_ok() } + +fn run_tests(test_dir: &Path) { + fs::create_dir_all(test_dir).expect("Failed to create test dir"); + + let fs_test = SequenceFileOperationTest::new(test_dir); + + info!("test_fuse_filesystem started"); + SequenceFileOperationTest::test_basic_filesystem(&fs_test); + info!("testtest_fuse_filesystem finished"); + + info!("test_big_file started"); + SequenceFileOperationTest::test_big_file(&fs_test); + info!("test_big_file finished"); + + info!("test_open_file_flag started"); + SequenceFileOperationTest::test_open_file_flag(&fs_test); + info!("test_open_file_flag finished"); +} + +fn test_manually() { + let mount_point = Path::new("target/gvfs"); + let test_dir = mount_point.join("test_dir"); + run_tests(&test_dir); +} + +#[test] +fn fuse_it_test_fuse() { + test_enable_with!(RUN_TEST_WITH_FUSE); + tracing_subscriber::fmt().init(); + + let mount_point = Path::new("target/gvfs"); + let test_dir = mount_point.join("test_dir"); + + run_tests(&test_dir); +} + +#[test] +fn test_fuse_with_memory_fs() { + tracing_subscriber::fmt().init(); + + let mount_point = "target/gvfs"; + let _ = fs::create_dir_all(mount_point); + + let mut test = FuseTestEnv { + mount_point: mount_point.to_string(), + gvfs_mount: None, + }; + + test.setup(); + + let test_dir = Path::new(&test.mount_point).join("test_dir"); + run_tests(&test_dir); +} From d74ce369701ce6a950ef4be485395c814ae34baf Mon Sep 17 00:00:00 2001 From: Qi Yu Date: Thu, 6 Feb 2025 10:53:31 +0800 Subject: [PATCH 03/33] [#6380] fix(postgres-sql): Fix errors for PG backend about `delete...limit..` clause. (#6393) ### What changes were proposed in this pull request? PostgreSQL does not support SQL sentences like `DELETE FROM xxxx_table where xxxx limit 10` , Cluase `limit xxx` is not allowed in the `Delete syntax` ### Why are the changes needed? it's a bug. Fix: #6380 ### Does this PR introduce _any_ user-facing change? N/A ### How was this patch tested? UT --- .../relational/RelationalGarbageCollector.java | 3 ++- .../postgresql/CatalogMetaPostgreSQLProvider.java | 10 ++++++++++ .../postgresql/FilesetMetaPostgreSQLProvider.java | 11 +++++++++++ .../FilesetVersionPostgreSQLProvider.java | 11 +++++++++++ .../postgresql/GroupMetaPostgreSQLProvider.java | 11 +++++++++++ .../GroupRoleRelPostgreSQLProvider.java | 11 +++++++++++ .../MetalakeMetaPostgreSQLProvider.java | 10 ++++++++++ .../postgresql/ModelMetaPostgreSQLProvider.java | 10 ++++++++++ .../ModelVersionAliasRelPostgreSQLProvider.java | 10 ++++++++++ .../ModelVersionMetaPostgreSQLProvider.java | 10 ++++++++++ .../postgresql/OwnerMetaPostgreSQLProvider.java | 11 +++++++++++ .../postgresql/RoleMetaPostgreSQLProvider.java | 11 +++++++++++ .../postgresql/SchemaMetaPostgreSQLProvider.java | 10 ++++++++++ .../SecurableObjectPostgreSQLProvider.java | 10 ++++++++++ .../postgresql/TableColumnPostgreSQLProvider.java | 10 ++++++++++ .../postgresql/TableMetaPostgreSQLProvider.java | 11 +++++++++++ .../postgresql/TagMetaPostgreSQLProvider.java | 10 ++++++++++ .../TagMetadataObjectRelPostgreSQLProvider.java | 10 ++++++++++ .../postgresql/TopicMetaPostgreSQLProvider.java | 11 +++++++++++ .../postgresql/UserMetaPostgreSQLProvider.java | 11 +++++++++++ .../postgresql/UserRoleRelPostgreSQLProvider.java | 11 +++++++++++ .../gravitino/storage/TestEntityStorage.java | 15 ++++++++++++++- 22 files changed, 226 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/org/apache/gravitino/storage/relational/RelationalGarbageCollector.java b/core/src/main/java/org/apache/gravitino/storage/relational/RelationalGarbageCollector.java index 3cf72aeae5d..135f2536291 100644 --- a/core/src/main/java/org/apache/gravitino/storage/relational/RelationalGarbageCollector.java +++ b/core/src/main/java/org/apache/gravitino/storage/relational/RelationalGarbageCollector.java @@ -68,7 +68,8 @@ public void start() { garbageCollectorPool.scheduleAtFixedRate(this::collectAndClean, 5, frequency, TimeUnit.MINUTES); } - private void collectAndClean() { + @VisibleForTesting + public void collectAndClean() { long threadId = Thread.currentThread().getId(); LOG.info("Thread {} start to collect garbage...", threadId); diff --git a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/CatalogMetaPostgreSQLProvider.java b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/CatalogMetaPostgreSQLProvider.java index 77bf3c4e285..a945a709c74 100644 --- a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/CatalogMetaPostgreSQLProvider.java +++ b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/CatalogMetaPostgreSQLProvider.java @@ -43,6 +43,16 @@ public String softDeleteCatalogMetasByMetalakeId(Long metalakeId) { + " WHERE metalake_id = #{metalakeId} AND deleted_at = 0"; } + @Override + public String deleteCatalogMetasByLegacyTimeline( + @Param("legacyTimeline") Long legacyTimeline, @Param("limit") int limit) { + return "DELETE FROM " + + TABLE_NAME + + " WHERE catalog_id IN (SELECT catalog_id FROM " + + TABLE_NAME + + " WHERE deleted_at > 0 AND deleted_at < #{legacyTimeline} LIMIT #{limit})"; + } + @Override public String insertCatalogMetaOnDuplicateKeyUpdate(CatalogPO catalogPO) { return "INSERT INTO " diff --git a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/FilesetMetaPostgreSQLProvider.java b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/FilesetMetaPostgreSQLProvider.java index c3200d63510..7b55549c1c2 100644 --- a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/FilesetMetaPostgreSQLProvider.java +++ b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/FilesetMetaPostgreSQLProvider.java @@ -22,6 +22,7 @@ import org.apache.gravitino.storage.relational.mapper.provider.base.FilesetMetaBaseSQLProvider; import org.apache.gravitino.storage.relational.po.FilesetPO; +import org.apache.ibatis.annotations.Param; public class FilesetMetaPostgreSQLProvider extends FilesetMetaBaseSQLProvider { @Override @@ -60,6 +61,16 @@ public String softDeleteFilesetMetasByFilesetId(Long filesetId) { + " WHERE fileset_id = #{filesetId} AND deleted_at = 0"; } + @Override + public String deleteFilesetMetasByLegacyTimeline( + @Param("legacyTimeline") Long legacyTimeline, @Param("limit") int limit) { + return "DELETE FROM " + + META_TABLE_NAME + + " WHERE fileset_id IN (SELECT fileset_id FROM " + + META_TABLE_NAME + + " WHERE deleted_at > 0 AND deleted_at < #{legacyTimeline} LIMIT #{limit})"; + } + @Override public String insertFilesetMetaOnDuplicateKeyUpdate(FilesetPO filesetPO) { return "INSERT INTO " diff --git a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/FilesetVersionPostgreSQLProvider.java b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/FilesetVersionPostgreSQLProvider.java index b9e6d4c5b1c..b7c165cc046 100644 --- a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/FilesetVersionPostgreSQLProvider.java +++ b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/FilesetVersionPostgreSQLProvider.java @@ -22,6 +22,7 @@ import org.apache.gravitino.storage.relational.mapper.provider.base.FilesetVersionBaseSQLProvider; import org.apache.gravitino.storage.relational.po.FilesetVersionPO; +import org.apache.ibatis.annotations.Param; public class FilesetVersionPostgreSQLProvider extends FilesetVersionBaseSQLProvider { @Override @@ -60,6 +61,16 @@ public String softDeleteFilesetVersionsByFilesetId(Long filesetId) { + " WHERE fileset_id = #{filesetId} AND deleted_at = 0"; } + @Override + public String deleteFilesetVersionsByLegacyTimeline( + @Param("legacyTimeline") Long legacyTimeline, @Param("limit") int limit) { + return "DELETE FROM " + + VERSION_TABLE_NAME + + " WHERE id IN (SELECT id FROM " + + VERSION_TABLE_NAME + + " WHERE deleted_at > 0 AND deleted_at < #{legacyTimeline} LIMIT #{limit})"; + } + @Override public String softDeleteFilesetVersionsByRetentionLine( Long filesetId, long versionRetentionLine, int limit) { diff --git a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/GroupMetaPostgreSQLProvider.java b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/GroupMetaPostgreSQLProvider.java index 3ace33f6f84..063136c0b86 100644 --- a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/GroupMetaPostgreSQLProvider.java +++ b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/GroupMetaPostgreSQLProvider.java @@ -24,6 +24,7 @@ import org.apache.gravitino.storage.relational.mapper.provider.base.GroupMetaBaseSQLProvider; import org.apache.gravitino.storage.relational.po.GroupPO; +import org.apache.ibatis.annotations.Param; public class GroupMetaPostgreSQLProvider extends GroupMetaBaseSQLProvider { @Override @@ -95,4 +96,14 @@ public String listExtendedGroupPOsByMetalakeId(Long metalakeId) { + " gt.metalake_id = #{metalakeId}" + " GROUP BY gt.group_id"; } + + @Override + public String deleteGroupMetasByLegacyTimeline( + @Param("legacyTimeline") Long legacyTimeline, @Param("limit") int limit) { + return "DELETE FROM " + + GROUP_TABLE_NAME + + " WHERE group_id IN (SELECT group_id FROM " + + GROUP_TABLE_NAME + + " WHERE deleted_at > 0 AND deleted_at < #{legacyTimeline} LIMIT #{limit})"; + } } diff --git a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/GroupRoleRelPostgreSQLProvider.java b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/GroupRoleRelPostgreSQLProvider.java index 40514123931..8148c957285 100644 --- a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/GroupRoleRelPostgreSQLProvider.java +++ b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/GroupRoleRelPostgreSQLProvider.java @@ -23,6 +23,7 @@ import java.util.List; import org.apache.gravitino.storage.relational.mapper.provider.base.GroupRoleRelBaseSQLProvider; +import org.apache.ibatis.annotations.Param; public class GroupRoleRelPostgreSQLProvider extends GroupRoleRelBaseSQLProvider { @Override @@ -70,4 +71,14 @@ public String softDeleteGroupRoleRelByRoleId(Long roleId) { + " timestamp '1970-01-01 00:00:00')*1000)))" + " WHERE role_id = #{roleId} AND deleted_at = 0"; } + + @Override + public String deleteGroupRoleRelMetasByLegacyTimeline( + @Param("legacyTimeline") Long legacyTimeline, @Param("limit") int limit) { + return "DELETE FROM " + + GROUP_ROLE_RELATION_TABLE_NAME + + " WHERE id IN (SELECT id FROM " + + GROUP_ROLE_RELATION_TABLE_NAME + + " WHERE deleted_at > 0 AND deleted_at < #{legacyTimeline} LIMIT #{limit})"; + } } diff --git a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/MetalakeMetaPostgreSQLProvider.java b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/MetalakeMetaPostgreSQLProvider.java index 06dde29751c..f52eafb8a2a 100644 --- a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/MetalakeMetaPostgreSQLProvider.java +++ b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/MetalakeMetaPostgreSQLProvider.java @@ -87,4 +87,14 @@ public String updateMetalakeMeta( + " AND last_version = #{oldMetalakeMeta.lastVersion}" + " AND deleted_at = 0"; } + + @Override + public String deleteMetalakeMetasByLegacyTimeline( + @Param("legacyTimeline") Long legacyTimeline, @Param("limit") int limit) { + return "DELETE FROM " + + TABLE_NAME + + " WHERE metalake_id IN (SELECT metalake_id FROM " + + TABLE_NAME + + " WHERE deleted_at > 0 AND deleted_at < #{legacyTimeline} LIMIT #{limit})"; + } } diff --git a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/ModelMetaPostgreSQLProvider.java b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/ModelMetaPostgreSQLProvider.java index 8f62252aa81..b7db5a4d70e 100644 --- a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/ModelMetaPostgreSQLProvider.java +++ b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/ModelMetaPostgreSQLProvider.java @@ -83,4 +83,14 @@ public String softDeleteModelMetasBySchemaId(@Param("schemaId") Long schemaId) { + " timestamp '1970-01-01 00:00:00')*1000)))" + " WHERE schema_id = #{schemaId} AND deleted_at = 0"; } + + @Override + public String deleteModelMetasByLegacyTimeline( + @Param("legacyTimeline") Long legacyTimeline, @Param("limit") int limit) { + return "DELETE FROM " + + ModelMetaMapper.TABLE_NAME + + " WHERE model_id IN (SELECT model_id FROM " + + ModelMetaMapper.TABLE_NAME + + " WHERE deleted_at > 0 AND deleted_at < #{legacyTimeline} LIMIT #{limit})"; + } } diff --git a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/ModelVersionAliasRelPostgreSQLProvider.java b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/ModelVersionAliasRelPostgreSQLProvider.java index da23bdca2d4..7bcac308afc 100644 --- a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/ModelVersionAliasRelPostgreSQLProvider.java +++ b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/ModelVersionAliasRelPostgreSQLProvider.java @@ -98,4 +98,14 @@ public String softDeleteModelVersionAliasRelsByMetalakeId(@Param("metalakeId") L + ModelMetaMapper.TABLE_NAME + " WHERE metalake_id = #{metalakeId} AND deleted_at = 0) AND deleted_at = 0"; } + + @Override + public String deleteModelVersionAliasRelsByLegacyTimeline( + @Param("legacyTimeline") Long legacyTimeline, @Param("limit") int limit) { + return "DELETE FROM " + + ModelVersionAliasRelMapper.TABLE_NAME + + " WHERE id IN (SELECT id FROM " + + ModelVersionAliasRelMapper.TABLE_NAME + + " WHERE deleted_at > 0 AND deleted_at < #{legacyTimeline} LIMIT #{limit})"; + } } diff --git a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/ModelVersionMetaPostgreSQLProvider.java b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/ModelVersionMetaPostgreSQLProvider.java index 4183a53617c..28fa2d5001b 100644 --- a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/ModelVersionMetaPostgreSQLProvider.java +++ b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/ModelVersionMetaPostgreSQLProvider.java @@ -90,4 +90,14 @@ public String softDeleteModelVersionMetasByMetalakeId(@Param("metalakeId") Long + " timestamp '1970-01-01 00:00:00')*1000)))" + " WHERE metalake_id = #{metalakeId} AND deleted_at = 0"; } + + @Override + public String deleteModelVersionMetasByLegacyTimeline( + @Param("legacyTimeline") Long legacyTimeline, @Param("limit") int limit) { + return "DELETE FROM " + + ModelVersionMetaMapper.TABLE_NAME + + " WHERE id IN (SELECT id FROM " + + ModelMetaMapper.TABLE_NAME + + " WHERE deleted_at > 0 AND deleted_at < #{legacyTimeline} LIMIT #{limit})"; + } } diff --git a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/OwnerMetaPostgreSQLProvider.java b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/OwnerMetaPostgreSQLProvider.java index ba594f7732d..c0f5d73d8e2 100644 --- a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/OwnerMetaPostgreSQLProvider.java +++ b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/OwnerMetaPostgreSQLProvider.java @@ -26,6 +26,7 @@ import org.apache.gravitino.storage.relational.mapper.TableMetaMapper; import org.apache.gravitino.storage.relational.mapper.TopicMetaMapper; import org.apache.gravitino.storage.relational.mapper.provider.base.OwnerMetaBaseSQLProvider; +import org.apache.ibatis.annotations.Param; public class OwnerMetaPostgreSQLProvider extends OwnerMetaBaseSQLProvider { @Override @@ -117,4 +118,14 @@ public String sotDeleteOwnerRelBySchemaId(Long schemaId) { + "ft.fileset_id = ot.metadata_object_id AND ot.metadata_object_type = 'FILESET'" + ")"; } + + @Override + public String deleteOwnerMetasByLegacyTimeline( + @Param("legacyTimeline") Long legacyTimeline, @Param("limit") int limit) { + return "DELETE FROM " + + OWNER_TABLE_NAME + + " WHERE id IN (SELECT id FROM " + + OWNER_TABLE_NAME + + " WHERE deleted_at > 0 AND deleted_at < #{legacyTimeline} LIMIT #{limit})"; + } } diff --git a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/RoleMetaPostgreSQLProvider.java b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/RoleMetaPostgreSQLProvider.java index 0558c0b3c66..b4b1054be7d 100644 --- a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/RoleMetaPostgreSQLProvider.java +++ b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/RoleMetaPostgreSQLProvider.java @@ -22,6 +22,7 @@ import org.apache.gravitino.storage.relational.mapper.provider.base.RoleMetaBaseSQLProvider; import org.apache.gravitino.storage.relational.po.RolePO; +import org.apache.ibatis.annotations.Param; public class RoleMetaPostgreSQLProvider extends RoleMetaBaseSQLProvider { @Override @@ -67,4 +68,14 @@ public String insertRoleMetaOnDuplicateKeyUpdate(RolePO rolePO) { + " last_version = #{roleMeta.lastVersion}," + " deleted_at = #{roleMeta.deletedAt}"; } + + @Override + public String deleteRoleMetasByLegacyTimeline( + @Param("legacyTimeline") Long legacyTimeline, @Param("limit") int limit) { + return "DELETE FROM " + + ROLE_TABLE_NAME + + " WHERE role_id IN (SELECT role_id FROM " + + ROLE_TABLE_NAME + + " WHERE deleted_at > 0 AND deleted_at < #{legacyTimeline} LIMIT #{limit})"; + } } diff --git a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/SchemaMetaPostgreSQLProvider.java b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/SchemaMetaPostgreSQLProvider.java index c39b244581d..8e96a7024d8 100644 --- a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/SchemaMetaPostgreSQLProvider.java +++ b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/SchemaMetaPostgreSQLProvider.java @@ -22,6 +22,7 @@ import org.apache.gravitino.storage.relational.mapper.provider.base.SchemaMetaBaseSQLProvider; import org.apache.gravitino.storage.relational.po.SchemaPO; +import org.apache.ibatis.annotations.Param; public class SchemaMetaPostgreSQLProvider extends SchemaMetaBaseSQLProvider { @Override @@ -81,4 +82,13 @@ public String softDeleteSchemaMetasByCatalogId(Long catalogId) { + " timestamp '1970-01-01 00:00:00')*1000)))" + " WHERE catalog_id = #{catalogId} AND deleted_at = 0"; } + + public String deleteSchemaMetasByLegacyTimeline( + @Param("legacyTimeline") Long legacyTimeline, @Param("limit") int limit) { + return "DELETE FROM " + + TABLE_NAME + + " WHERE schema_id IN (SELECT schema_id FROM " + + TABLE_NAME + + " WHERE deleted_at > 0 AND deleted_at < #{legacyTimeline} LIMIT #{limit})"; + } } diff --git a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/SecurableObjectPostgreSQLProvider.java b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/SecurableObjectPostgreSQLProvider.java index 6de57dbdc48..c67324f9a7c 100644 --- a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/SecurableObjectPostgreSQLProvider.java +++ b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/SecurableObjectPostgreSQLProvider.java @@ -144,4 +144,14 @@ public String softDeleteObjectRelsBySchemaId(@Param("schemaId") Long schemaId) { + "ft.fileset_id = sect.metadata_object_id AND sect.type = 'FILESET'" + ")"; } + + @Override + public String deleteSecurableObjectsByLegacyTimeline( + @Param("legacyTimeline") Long legacyTimeline, @Param("limit") int limit) { + return "DELETE FROM " + + SECURABLE_OBJECT_TABLE_NAME + + " WHERE id IN (SELECT id FROM " + + ROLE_TABLE_NAME + + " WHERE deleted_at > 0 AND deleted_at < #{legacyTimeline} LIMIT #{limit})"; + } } diff --git a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/TableColumnPostgreSQLProvider.java b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/TableColumnPostgreSQLProvider.java index bf99438c8b2..e8ae522ac7d 100644 --- a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/TableColumnPostgreSQLProvider.java +++ b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/TableColumnPostgreSQLProvider.java @@ -59,4 +59,14 @@ public String softDeleteColumnsBySchemaId(@Param("schemaId") Long schemaId) { + " timestamp '1970-01-01 00:00:00')*1000)))" + " WHERE schema_id = #{schemaId} AND deleted_at = 0"; } + + @Override + public String deleteColumnPOsByLegacyTimeline( + @Param("legacyTimeline") Long legacyTimeline, @Param("limit") int limit) { + return "DELETE FROM " + + TableColumnMapper.COLUMN_TABLE_NAME + + " WHERE id IN (SELECT id FROM " + + TableColumnMapper.COLUMN_TABLE_NAME + + " WHERE deleted_at > 0 AND deleted_at < #{legacyTimeline} LIMIT #{limit})"; + } } diff --git a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/TableMetaPostgreSQLProvider.java b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/TableMetaPostgreSQLProvider.java index 94cb571c3ff..227f73f5851 100644 --- a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/TableMetaPostgreSQLProvider.java +++ b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/TableMetaPostgreSQLProvider.java @@ -22,6 +22,7 @@ import org.apache.gravitino.storage.relational.mapper.provider.base.TableMetaBaseSQLProvider; import org.apache.gravitino.storage.relational.po.TablePO; +import org.apache.ibatis.annotations.Param; public class TableMetaPostgreSQLProvider extends TableMetaBaseSQLProvider { @Override @@ -88,4 +89,14 @@ public String softDeleteTableMetasBySchemaId(Long schemaId) { + " timestamp '1970-01-01 00:00:00')*1000)))" + " WHERE schema_id = #{schemaId} AND deleted_at = 0"; } + + @Override + public String deleteTableMetasByLegacyTimeline( + @Param("legacyTimeline") Long legacyTimeline, @Param("limit") int limit) { + return "DELETE FROM " + + TABLE_NAME + + " WHERE table_id IN (SELECT table_id FROM " + + TABLE_NAME + + " WHERE deleted_at > 0 AND deleted_at < #{legacyTimeline} LIMIT #{limit})"; + } } diff --git a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/TagMetaPostgreSQLProvider.java b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/TagMetaPostgreSQLProvider.java index 582307b6b12..9f30b3f3f6e 100644 --- a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/TagMetaPostgreSQLProvider.java +++ b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/TagMetaPostgreSQLProvider.java @@ -100,4 +100,14 @@ public String updateTagMeta( + " AND last_version = #{oldTagMeta.lastVersion}" + " AND deleted_at = 0"; } + + @Override + public String deleteTagMetasByLegacyTimeline( + @Param("legacyTimeline") Long legacyTimeline, @Param("limit") int limit) { + return "DELETE FROM " + + TAG_TABLE_NAME + + " WHERE tag_id IN (SELECT tag_id FROM " + + TAG_TABLE_NAME + + " WHERE deleted_at > 0 AND deleted_at < #{legacyTimeline} LIMIT #{limit})"; + } } diff --git a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/TagMetadataObjectRelPostgreSQLProvider.java b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/TagMetadataObjectRelPostgreSQLProvider.java index 827098b6e27..9045ead8ea5 100644 --- a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/TagMetadataObjectRelPostgreSQLProvider.java +++ b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/TagMetadataObjectRelPostgreSQLProvider.java @@ -198,4 +198,14 @@ public String listTagMetadataObjectRelsByMetalakeAndTagName(String metalakeName, + " WHERE mm.metalake_name = #{metalakeName} AND tm.tag_name = #{tagName}" + " AND te.deleted_at = 0 AND tm.deleted_at = 0 AND mm.deleted_at = 0"; } + + @Override + public String deleteTagEntityRelsByLegacyTimeline( + @Param("legacyTimeline") Long legacyTimeline, @Param("limit") int limit) { + return "DELETE FROM " + + TagMetadataObjectRelMapper.TAG_METADATA_OBJECT_RELATION_TABLE_NAME + + " WHERE id IN (SELECT id FROM " + + TagMetadataObjectRelMapper.TAG_METADATA_OBJECT_RELATION_TABLE_NAME + + " WHERE deleted_at > 0 AND deleted_at < #{legacyTimeline} LIMIT #{limit})"; + } } diff --git a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/TopicMetaPostgreSQLProvider.java b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/TopicMetaPostgreSQLProvider.java index 411662ef659..5ddcb4eb41b 100644 --- a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/TopicMetaPostgreSQLProvider.java +++ b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/TopicMetaPostgreSQLProvider.java @@ -22,6 +22,7 @@ import org.apache.gravitino.storage.relational.mapper.provider.base.TopicMetaBaseSQLProvider; import org.apache.gravitino.storage.relational.po.TopicPO; +import org.apache.ibatis.annotations.Param; public class TopicMetaPostgreSQLProvider extends TopicMetaBaseSQLProvider { @@ -93,4 +94,14 @@ public String insertTopicMetaOnDuplicateKeyUpdate(TopicPO topicPO) { + " last_version = #{topicMeta.lastVersion}," + " deleted_at = #{topicMeta.deletedAt}"; } + + @Override + public String deleteTopicMetasByLegacyTimeline( + @Param("legacyTimeline") Long legacyTimeline, @Param("limit") int limit) { + return "DELETE FROM " + + TABLE_NAME + + " WHERE topic_id IN (SELECT topic_id FROM " + + TABLE_NAME + + " WHERE deleted_at != 0 AND deleted_at < #{legacyTimeline} LIMIT #{limit})"; + } } diff --git a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/UserMetaPostgreSQLProvider.java b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/UserMetaPostgreSQLProvider.java index 84ab965582c..e5c24277916 100644 --- a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/UserMetaPostgreSQLProvider.java +++ b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/UserMetaPostgreSQLProvider.java @@ -24,6 +24,7 @@ import org.apache.gravitino.storage.relational.mapper.provider.base.UserMetaBaseSQLProvider; import org.apache.gravitino.storage.relational.po.UserPO; +import org.apache.ibatis.annotations.Param; public class UserMetaPostgreSQLProvider extends UserMetaBaseSQLProvider { @Override @@ -95,4 +96,14 @@ public String listExtendedUserPOsByMetalakeId(Long metalakeId) { + " ut.metalake_id = #{metalakeId}" + " GROUP BY ut.user_id"; } + + @Override + public String deleteUserMetasByLegacyTimeline( + @Param("legacyTimeline") Long legacyTimeline, @Param("limit") int limit) { + return "DELETE FROM " + + USER_TABLE_NAME + + " WHERE user_id IN (SELECT user_id FROM " + + USER_TABLE_NAME + + " WHERE deleted_at > 0 AND deleted_at < #{legacyTimeline} LIMIT #{limit})"; + } } diff --git a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/UserRoleRelPostgreSQLProvider.java b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/UserRoleRelPostgreSQLProvider.java index 48a1be22335..c5f1d7124a0 100644 --- a/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/UserRoleRelPostgreSQLProvider.java +++ b/core/src/main/java/org/apache/gravitino/storage/relational/mapper/provider/postgresql/UserRoleRelPostgreSQLProvider.java @@ -25,6 +25,7 @@ import java.util.List; import org.apache.gravitino.storage.relational.mapper.provider.base.UserRoleRelBaseSQLProvider; import org.apache.gravitino.storage.relational.po.UserRoleRelPO; +import org.apache.ibatis.annotations.Param; public class UserRoleRelPostgreSQLProvider extends UserRoleRelBaseSQLProvider { @Override @@ -99,4 +100,14 @@ public String batchInsertUserRoleRelOnDuplicateKeyUpdate(List use + " deleted_at = VALUES(deleted_at)" + ""; } + + @Override + public String deleteUserRoleRelMetasByLegacyTimeline( + @Param("legacyTimeline") Long legacyTimeline, @Param("limit") int limit) { + return "DELETE FROM " + + USER_ROLE_RELATION_TABLE_NAME + + " WHERE id IN (SELECT id FROM " + + USER_ROLE_RELATION_TABLE_NAME + + " WHERE deleted_at > 0 AND deleted_at < #{legacyTimeline} LIMIT #{limit})"; + } } diff --git a/core/src/test/java/org/apache/gravitino/storage/TestEntityStorage.java b/core/src/test/java/org/apache/gravitino/storage/TestEntityStorage.java index a85f896281b..c1a52c5154b 100644 --- a/core/src/test/java/org/apache/gravitino/storage/TestEntityStorage.java +++ b/core/src/test/java/org/apache/gravitino/storage/TestEntityStorage.java @@ -37,6 +37,7 @@ import com.google.common.collect.Lists; import java.io.File; import java.io.IOException; +import java.lang.reflect.Field; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; @@ -83,6 +84,9 @@ import org.apache.gravitino.meta.UserEntity; import org.apache.gravitino.rel.types.Type; import org.apache.gravitino.rel.types.Types; +import org.apache.gravitino.storage.relational.RelationalBackend; +import org.apache.gravitino.storage.relational.RelationalEntityStore; +import org.apache.gravitino.storage.relational.RelationalGarbageCollector; import org.apache.gravitino.storage.relational.TestJDBCBackend; import org.apache.gravitino.storage.relational.converters.H2ExceptionConverter; import org.apache.gravitino.storage.relational.converters.MySQLExceptionConverter; @@ -136,7 +140,7 @@ private void init(String type, Config config) { if (type.equalsIgnoreCase("h2")) { // The following properties are used to create the JDBC connection; they are just for test, // in the real world, they will be set automatically by the configuration file if you set - // ENTITY_RELATIONAL_STOR as EMBEDDED_ENTITY_RELATIONAL_STORE. + // ENTITY_RELATIONAL_STORE as EMBEDDED_ENTITY_RELATIONAL_STORE. Mockito.when(config.get(ENTITY_RELATIONAL_JDBC_BACKEND_URL)) .thenReturn(String.format("jdbc:h2:%s;DB_CLOSE_DELAY=-1;MODE=MYSQL", DB_DIR)); Mockito.when(config.get(ENTITY_RELATIONAL_JDBC_BACKEND_USER)).thenReturn("gravitino"); @@ -171,6 +175,15 @@ private void init(String type, Config config) { new PostgreSQLExceptionConverter(), true); + RelationalEntityStore store = + (RelationalEntityStore) EntityStoreFactory.createEntityStore(config); + store.initialize(config); + Field f = FieldUtils.getField(RelationalEntityStore.class, "backend", true); + RelationalBackend backend = (RelationalBackend) f.get(store); + RelationalGarbageCollector garbageCollector = + new RelationalGarbageCollector(backend, config); + garbageCollector.collectAndClean(); + } else { throw new UnsupportedOperationException("Unsupported entity store type: " + type); } From f4a0ebb85cf8c12da486bc63a0e02b19e86298b7 Mon Sep 17 00:00:00 2001 From: Lord of Abyss <103809695+Abyss-lord@users.noreply.github.com> Date: Thu, 6 Feb 2025 11:59:15 +0800 Subject: [PATCH 04/33] [#6356] improve(CLI): Add tag support for model in CLI (#6360) ### What changes were proposed in this pull request? Add tag support for model in CLI. 1. `UntagEntity` 2. `TagEntity` 3. `ListEntityTags` The logic for handling models in these three methods has been added. need to add the processing logic to the `RemoveAllTags` method. ### Why are the changes needed? Fix: #6356 ### Does this PR introduce _any_ user-facing change? No ### How was this patch tested? local test. --- .../gravitino/cli/commands/RemoveAllTags.java | 68 +++++++++++++++---- 1 file changed, 54 insertions(+), 14 deletions(-) diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RemoveAllTags.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RemoveAllTags.java index 5221100a8e9..9c774dfaacb 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RemoveAllTags.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RemoveAllTags.java @@ -20,17 +20,24 @@ package org.apache.gravitino.cli.commands; import org.apache.gravitino.Catalog; -import org.apache.gravitino.NameIdentifier; import org.apache.gravitino.Schema; import org.apache.gravitino.cli.AreYouSure; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.cli.FullName; +import org.apache.gravitino.cli.utils.FullNameUtil; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchCatalogException; import org.apache.gravitino.exceptions.NoSuchMetalakeException; import org.apache.gravitino.exceptions.NoSuchSchemaException; import org.apache.gravitino.exceptions.NoSuchTableException; +import org.apache.gravitino.file.Fileset; +import org.apache.gravitino.file.FilesetCatalog; +import org.apache.gravitino.messaging.Topic; +import org.apache.gravitino.messaging.TopicCatalog; +import org.apache.gravitino.model.Model; +import org.apache.gravitino.model.ModelCatalog; import org.apache.gravitino.rel.Table; +import org.apache.gravitino.rel.TableCatalog; /* Removes all the tags of an entity. */ public class RemoveAllTags extends Command { @@ -66,21 +73,54 @@ public void handle() { try { GravitinoClient client = buildClient(metalake); - // TODO fileset and topic - if (name.hasTableName()) { + + if (name.getLevel() == 3) { String catalog = name.getCatalogName(); - String schema = name.getSchemaName(); - String table = name.getTableName(); - Table gTable = - client - .loadCatalog(catalog) - .asTableCatalog() - .loadTable(NameIdentifier.of(schema, table)); - tags = gTable.supportsTags().listTags(); - if (tags.length > 0) { - gTable.supportsTags().associateTags(null, tags); + Catalog catalogObject = client.loadCatalog(catalog); + switch (catalogObject.type()) { + case RELATIONAL: + entity = "table"; + TableCatalog tableCatalog = catalogObject.asTableCatalog(); + Table gTable = tableCatalog.loadTable(FullNameUtil.toTable(name)); + tags = gTable.supportsTags().listTags(); + if (tags.length > 0) { + gTable.supportsTags().associateTags(null, tags); + } + break; + + case MODEL: + entity = "model"; + ModelCatalog modelCatalog = catalogObject.asModelCatalog(); + Model gModel = modelCatalog.getModel(FullNameUtil.toModel(name)); + tags = gModel.supportsTags().listTags(); + if (tags.length > 0) { + gModel.supportsTags().associateTags(null, tags); + } + break; + + case FILESET: + entity = "fileset"; + FilesetCatalog filesetCatalog = catalogObject.asFilesetCatalog(); + Fileset gFileset = filesetCatalog.loadFileset(FullNameUtil.toFileset(name)); + tags = gFileset.supportsTags().listTags(); + if (tags.length > 0) { + gFileset.supportsTags().associateTags(null, tags); + } + break; + + case MESSAGING: + entity = "topic"; + TopicCatalog topicCatalog = catalogObject.asTopicCatalog(); + Topic gTopic = topicCatalog.loadTopic(FullNameUtil.toTopic(name)); + tags = gTopic.supportsTags().listTags(); + if (tags.length > 0) { + gTopic.supportsTags().associateTags(null, tags); + } + break; + + default: + break; } - entity = table; } else if (name.hasSchemaName()) { String catalog = name.getCatalogName(); String schema = name.getSchemaName(); From ca20c94b0a167581e3b5791a8146ed652a440c43 Mon Sep 17 00:00:00 2001 From: Jerry Shao Date: Thu, 6 Feb 2025 13:26:11 +0800 Subject: [PATCH 05/33] [MINOR] fix(gvfs): expose the nested exception for better understanding (#6398) ### What changes were proposed in this pull request? Improve the gvfs to expose the nested exception for better understanding. ### Why are the changes needed? The exception message may not be enough to understand the problem why the fs initialization is failed. So we should expose the whole stack for better understanding. ### Does this PR introduce _any_ user-facing change? No. ### How was this patch tested? Existing tests. --- .../filesystem/hadoop/GravitinoVirtualFileSystem.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/clients/filesystem-hadoop3/src/main/java/org/apache/gravitino/filesystem/hadoop/GravitinoVirtualFileSystem.java b/clients/filesystem-hadoop3/src/main/java/org/apache/gravitino/filesystem/hadoop/GravitinoVirtualFileSystem.java index 26d248736a9..67bfe961a22 100644 --- a/clients/filesystem-hadoop3/src/main/java/org/apache/gravitino/filesystem/hadoop/GravitinoVirtualFileSystem.java +++ b/clients/filesystem-hadoop3/src/main/java/org/apache/gravitino/filesystem/hadoop/GravitinoVirtualFileSystem.java @@ -322,8 +322,10 @@ private FilesetContextPair getFilesetContext(Path virtualPath, FilesetDataOperat return provider.getFileSystem(filePath, totalProperty); } catch (IOException ioe) { throw new GravitinoRuntimeException( + ioe, "Exception occurs when create new FileSystem for actual uri: %s, msg: %s", - uri, ioe); + uri, + ioe.getMessage()); } }); From 45349852629d00eb38eff531af1a0f2bd1dab852 Mon Sep 17 00:00:00 2001 From: Qi Yu Date: Thu, 6 Feb 2025 17:43:08 +0800 Subject: [PATCH 06/33] [#6375] improvment(catalog-hadoop): Remove `protobuf-java` to avoid conflict with authorization module (#6376) ### What changes were proposed in this pull request? Remove jar `protobuf-java.jar` from the distribution package to avoid conflicts ### Why are the changes needed? To make authorization works for GCS fileset. Fix: #6375 ### Does this PR introduce _any_ user-facing change? N/A. ### How was this patch tested? N/A --- catalogs/catalog-hadoop/build.gradle.kts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/catalogs/catalog-hadoop/build.gradle.kts b/catalogs/catalog-hadoop/build.gradle.kts index 3108d993c1a..b8877646f5a 100644 --- a/catalogs/catalog-hadoop/build.gradle.kts +++ b/catalogs/catalog-hadoop/build.gradle.kts @@ -52,6 +52,12 @@ dependencies { exclude("org.eclipse.jetty", "*") exclude("io.netty") exclude("org.fusesource.leveldbjni") + // Exclude `protobuf-java` 2.5.0 to avoid conflict with a higher version of `protobuf-java` + // in the authorization module. The reason is that the class loader of `catalog-hadoop` is the + // parent of the class loader of the authorization module, so the class loader of `catalog-hadoop` + // will load the class `protobuf-java` 2.5.0 first, which will cause the authorization module to + // fail to load the class `protobuf-java` 3.15.8. + exclude("com.google.protobuf", "protobuf-java") } implementation(libs.slf4j.api) implementation(libs.awaitility) From b1e5931b27174a73bcc00921f392e0db02bba2d7 Mon Sep 17 00:00:00 2001 From: FANNG Date: Fri, 7 Feb 2025 14:26:10 +0800 Subject: [PATCH 07/33] [#6394] feat(iceberg): upgrade Iceberg version from 1.5.2 to 1.6.1 (#6374) ### What changes were proposed in this pull request? Upgrade Iceberg version from 1.5.2 to 1.6.1 In 1.6, the `token` endpoint is deprecated and there're no new endpoint is added. ### Why are the changes needed? Fix: #6394 ### Does this PR introduce _any_ user-facing change? no ### How was this patch tested? run pass existing ITs --- build.gradle.kts | 3 +++ .../iceberg-rest-server-dependency.sh | 14 ++++++++------ docs/iceberg-rest-service.md | 5 ++--- docs/lakehouse-iceberg-catalog.md | 2 +- gradle/libs.versions.toml | 2 +- .../integration/test/IcebergRESTADLSTokenIT.java | 8 ++++---- .../test/IcebergRESTAzureAccountKeyIT.java | 8 ++++---- .../iceberg/integration/test/IcebergRESTGCSIT.java | 8 +++++--- .../iceberg/integration/test/IcebergRESTOSSIT.java | 8 ++++---- .../integration/test/IcebergRESTOSSSecretIT.java | 8 ++++---- .../integration/test/IcebergRESTS3TokenIT.java | 8 ++++---- .../gravitino/integration/test/util/ITUtils.java | 4 ++++ .../trino-test-tools/download_jar.sh | 4 ++-- 13 files changed, 46 insertions(+), 36 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 1fe3c80d9b7..b56f6f4d79b 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -191,6 +191,9 @@ allprojects { param.environment("NEED_CREATE_DOCKER_NETWORK", "true") } + val icebergVersion: String = libs.versions.iceberg.get() + param.systemProperty("ICEBERG_VERSION", icebergVersion) + // Change poll image pause time from 30s to 60s param.environment("TESTCONTAINERS_PULL_PAUSE_TIMEOUT", "60") val jdbcDatabase = project.properties["jdbcBackend"] as? String ?: "h2" diff --git a/dev/docker/iceberg-rest-server/iceberg-rest-server-dependency.sh b/dev/docker/iceberg-rest-server/iceberg-rest-server-dependency.sh index aced0224f48..1640d0195bb 100755 --- a/dev/docker/iceberg-rest-server/iceberg-rest-server-dependency.sh +++ b/dev/docker/iceberg-rest-server/iceberg-rest-server-dependency.sh @@ -49,19 +49,21 @@ cp ${gravitino_home}/bundles/aws/build/libs/gravitino-aws-*.jar bundles/ cp ${gravitino_home}/bundles/azure/build/libs/gravitino-azure-*.jar bundles/ cp ${gravitino_home}/bundles/aliyun-bundle/build/libs/gravitino-aliyun-bundle-*.jar bundles/ -iceberg_gcp_bundle="iceberg-gcp-bundle-1.5.2.jar" +iceberg_version="1.6.1" + +iceberg_gcp_bundle="iceberg-gcp-bundle-${iceberg_version}.jar" if [ ! -f "bundles/${iceberg_gcp_bundle}" ]; then - curl -L -s -o bundles/${iceberg_gcp_bundle} https://repo1.maven.org/maven2/org/apache/iceberg/iceberg-gcp-bundle/1.5.2/${iceberg_gcp_bundle} + curl -L -s -o bundles/${iceberg_gcp_bundle} https://repo1.maven.org/maven2/org/apache/iceberg/iceberg-gcp-bundle/${iceberg_version}/${iceberg_gcp_bundle} fi -iceberg_aws_bundle="iceberg-aws-bundle-1.5.2.jar" +iceberg_aws_bundle="iceberg-aws-bundle-${iceberg_version}.jar" if [ ! -f "bundles/${iceberg_aws_bundle}" ]; then - curl -L -s -o bundles/${iceberg_aws_bundle} https://repo1.maven.org/maven2/org/apache/iceberg/iceberg-aws-bundle/1.5.2/${iceberg_aws_bundle} + curl -L -s -o bundles/${iceberg_aws_bundle} https://repo1.maven.org/maven2/org/apache/iceberg/iceberg-aws-bundle/${iceberg_version}/${iceberg_aws_bundle} fi -iceberg_azure_bundle="iceberg-azure-bundle-1.5.2.jar" +iceberg_azure_bundle="iceberg-azure-bundle-${iceberg_version}.jar" if [ ! -f "bundles/${iceberg_azure_bundle}" ]; then - curl -L -s -o bundles/${iceberg_azure_bundle} https://repo1.maven.org/maven2/org/apache/iceberg/iceberg-azure-bundle/1.5.2/${iceberg_azure_bundle} + curl -L -s -o bundles/${iceberg_azure_bundle} https://repo1.maven.org/maven2/org/apache/iceberg/iceberg-azure-bundle/${iceberg_version}/${iceberg_azure_bundle} fi # download jdbc driver diff --git a/docs/iceberg-rest-service.md b/docs/iceberg-rest-service.md index a4846d0e0dd..f89b6f2672f 100644 --- a/docs/iceberg-rest-service.md +++ b/docs/iceberg-rest-service.md @@ -13,7 +13,6 @@ The Apache Gravitino Iceberg REST Server follows the [Apache Iceberg REST API sp ### Capabilities - Supports the Apache Iceberg REST API defined in Iceberg 1.5, and supports all namespace and table interfaces. The following interfaces are not implemented yet: - - token - multi table transaction - pagination - Works as a catalog proxy, supporting `Hive` and `JDBC` as catalog backend. @@ -317,7 +316,7 @@ gravitino.iceberg-rest.gravitino-metalake = test ### Other Apache Iceberg catalog properties -You can add other properties defined in [Iceberg catalog properties](https://iceberg.apache.org/docs/1.5.2/configuration/#catalog-properties). +You can add other properties defined in [Iceberg catalog properties](https://iceberg.apache.org/docs/1.6.1/configuration/#catalog-properties). The `clients` property for example: | Configuration item | Description | Default value | Required | @@ -379,7 +378,7 @@ Normally you will see the output like `{"defaults":{},"overrides":{}}%`. ### Deploying Apache Spark with Apache Iceberg support -Follow the [Spark Iceberg start guide](https://iceberg.apache.org/docs/1.5.2/spark-getting-started/) to set up Apache Spark's and Apache Iceberg's environment. +Follow the [Spark Iceberg start guide](https://iceberg.apache.org/docs/1.6.1/spark-getting-started/) to set up Apache Spark's and Apache Iceberg's environment. ### Starting the Apache Spark client with the Apache Iceberg REST catalog diff --git a/docs/lakehouse-iceberg-catalog.md b/docs/lakehouse-iceberg-catalog.md index f8b462b24e5..8fb9c61f327 100644 --- a/docs/lakehouse-iceberg-catalog.md +++ b/docs/lakehouse-iceberg-catalog.md @@ -18,7 +18,7 @@ Apache Gravitino provides the ability to manage Apache Iceberg metadata. ### Requirements and limitations :::info -Builds with Apache Iceberg `1.5.2`. The Apache Iceberg table format version is `2` by default. +Builds with Apache Iceberg `1.6.1`. The Apache Iceberg table format version is `2` by default. ::: ## Catalog diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 767cbe0827f..736691c4b52 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -55,7 +55,7 @@ commons-collections3 = "3.2.2" commons-configuration1 = "1.6" commons-dbcp2 = "2.11.0" caffeine = "2.9.3" -iceberg = '1.5.2' # used for Gravitino Iceberg catalog and Iceberg REST service +iceberg = '1.6.1' # used for Gravitino Iceberg catalog and Iceberg REST service iceberg4spark = "1.4.1" # used for compile spark connector paimon = '0.8.0' spark33 = "3.3.4" diff --git a/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/integration/test/IcebergRESTADLSTokenIT.java b/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/integration/test/IcebergRESTADLSTokenIT.java index bf718d601d7..b4c70a38293 100644 --- a/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/integration/test/IcebergRESTADLSTokenIT.java +++ b/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/integration/test/IcebergRESTADLSTokenIT.java @@ -117,11 +117,11 @@ private Map getADLSConfig() { } private void downloadIcebergAzureBundleJar() throws IOException { - String icebergBundleJarName = "iceberg-azure-bundle-1.5.2.jar"; String icebergBundleJarUri = - "https://repo1.maven.org/maven2/org/apache/iceberg/" - + "iceberg-azure-bundle/1.5.2/" - + icebergBundleJarName; + String.format( + "https://repo1.maven.org/maven2/org/apache/iceberg/" + + "iceberg-azure-bundle/%s/iceberg-azure-bundle-%s.jar", + ITUtils.icebergVersion(), ITUtils.icebergVersion()); String gravitinoHome = System.getenv("GRAVITINO_HOME"); String targetDir = String.format("%s/iceberg-rest-server/libs/", gravitinoHome); DownloaderUtils.downloadFile(icebergBundleJarUri, targetDir); diff --git a/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/integration/test/IcebergRESTAzureAccountKeyIT.java b/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/integration/test/IcebergRESTAzureAccountKeyIT.java index 4f3c608fe3b..e74a8db6778 100644 --- a/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/integration/test/IcebergRESTAzureAccountKeyIT.java +++ b/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/integration/test/IcebergRESTAzureAccountKeyIT.java @@ -100,11 +100,11 @@ private Map getADLSConfig() { } private void downloadIcebergAzureBundleJar() throws IOException { - String icebergBundleJarName = "iceberg-azure-bundle-1.5.2.jar"; String icebergBundleJarUri = - "https://repo1.maven.org/maven2/org/apache/iceberg/" - + "iceberg-azure-bundle/1.5.2/" - + icebergBundleJarName; + String.format( + "https://repo1.maven.org/maven2/org/apache/iceberg/" + + "iceberg-azure-bundle/%s/iceberg-azure-bundle-%s.jar", + ITUtils.icebergVersion(), ITUtils.icebergVersion()); String gravitinoHome = System.getenv("GRAVITINO_HOME"); String targetDir = String.format("%s/iceberg-rest-server/libs/", gravitinoHome); DownloaderUtils.downloadFile(icebergBundleJarUri, targetDir); diff --git a/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/integration/test/IcebergRESTGCSIT.java b/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/integration/test/IcebergRESTGCSIT.java index 74bf55edc09..1ada58189ea 100644 --- a/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/integration/test/IcebergRESTGCSIT.java +++ b/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/integration/test/IcebergRESTGCSIT.java @@ -35,6 +35,7 @@ // You should export GRAVITINO_GCS_BUCKET and GOOGLE_APPLICATION_CREDENTIALS to run the test @EnabledIfEnvironmentVariable(named = "GRAVITINO_TEST_CLOUD_IT", matches = "true") public class IcebergRESTGCSIT extends IcebergRESTJdbcCatalogIT { + private String gcsWarehouse; private String gcsCredentialPath; @@ -92,10 +93,11 @@ private void copyGCSBundleJar() { } private void downloadIcebergBundleJar() throws IOException { - String icebergBundleJarName = "iceberg-gcp-bundle-1.5.2.jar"; String icebergBundleJarUri = - "https://repo1.maven.org/maven2/org/apache/iceberg/iceberg-gcp-bundle/1.5.2/" - + icebergBundleJarName; + String.format( + "https://repo1.maven.org/maven2/org/apache/iceberg/" + + "iceberg-gcp-bundle/%s/iceberg-gcp-bundle-%s.jar", + ITUtils.icebergVersion(), ITUtils.icebergVersion()); String gravitinoHome = System.getenv("GRAVITINO_HOME"); String targetDir = String.format("%s/iceberg-rest-server/libs/", gravitinoHome); DownloaderUtils.downloadFile(icebergBundleJarUri, targetDir); diff --git a/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/integration/test/IcebergRESTOSSIT.java b/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/integration/test/IcebergRESTOSSIT.java index 8e72ce33f1b..a867071dda6 100644 --- a/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/integration/test/IcebergRESTOSSIT.java +++ b/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/integration/test/IcebergRESTOSSIT.java @@ -113,11 +113,11 @@ private Map getOSSConfig() { } private void downloadIcebergForAliyunJar() throws IOException { - String icebergBundleJarName = "iceberg-aliyun-1.5.2.jar"; String icebergBundleJarUri = - "https://repo1.maven.org/maven2/org/apache/iceberg/" - + "iceberg-aliyun/1.5.2/" - + icebergBundleJarName; + String.format( + "https://repo1.maven.org/maven2/org/apache/iceberg/" + + "iceberg-aliyun/%s/iceberg-aliyun-%s.jar", + ITUtils.icebergVersion(), ITUtils.icebergVersion()); String gravitinoHome = System.getenv("GRAVITINO_HOME"); String targetDir = String.format("%s/iceberg-rest-server/libs/", gravitinoHome); DownloaderUtils.downloadFile(icebergBundleJarUri, targetDir); diff --git a/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/integration/test/IcebergRESTOSSSecretIT.java b/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/integration/test/IcebergRESTOSSSecretIT.java index 3b198c9d29e..38239bb1d9a 100644 --- a/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/integration/test/IcebergRESTOSSSecretIT.java +++ b/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/integration/test/IcebergRESTOSSSecretIT.java @@ -98,11 +98,11 @@ private Map getOSSConfig() { } private void downloadIcebergForAliyunJar() throws IOException { - String icebergBundleJarName = "iceberg-aliyun-1.5.2.jar"; String icebergBundleJarUri = - "https://repo1.maven.org/maven2/org/apache/iceberg/" - + "iceberg-aliyun/1.5.2/" - + icebergBundleJarName; + String.format( + "https://repo1.maven.org/maven2/org/apache/iceberg/" + + "iceberg-aliyun/%s/iceberg-aliyun-%s.jar", + ITUtils.icebergVersion(), ITUtils.icebergVersion()); String gravitinoHome = System.getenv("GRAVITINO_HOME"); String targetDir = String.format("%s/iceberg-rest-server/libs/", gravitinoHome); DownloaderUtils.downloadFile(icebergBundleJarUri, targetDir); diff --git a/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/integration/test/IcebergRESTS3TokenIT.java b/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/integration/test/IcebergRESTS3TokenIT.java index ef1551f91b4..989dce834c1 100644 --- a/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/integration/test/IcebergRESTS3TokenIT.java +++ b/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/integration/test/IcebergRESTS3TokenIT.java @@ -111,11 +111,11 @@ private Map getS3Config() { } private void downloadIcebergAwsBundleJar() throws IOException { - String icebergBundleJarName = "iceberg-aws-bundle-1.5.2.jar"; String icebergBundleJarUri = - "https://repo1.maven.org/maven2/org/apache/iceberg/" - + "iceberg-aws-bundle/1.5.2/" - + icebergBundleJarName; + String.format( + "https://repo1.maven.org/maven2/org/apache/iceberg/" + + "iceberg-aws-bundle/%s/iceberg-aws-bundle-%s.jar", + ITUtils.icebergVersion(), ITUtils.icebergVersion()); String gravitinoHome = System.getenv("GRAVITINO_HOME"); String targetDir = String.format("%s/iceberg-rest-server/libs/", gravitinoHome); DownloaderUtils.downloadFile(icebergBundleJarUri, targetDir); diff --git a/integration-test-common/src/test/java/org/apache/gravitino/integration/test/util/ITUtils.java b/integration-test-common/src/test/java/org/apache/gravitino/integration/test/util/ITUtils.java index d7c099dc7ac..508c5fb42e1 100644 --- a/integration-test-common/src/test/java/org/apache/gravitino/integration/test/util/ITUtils.java +++ b/integration-test-common/src/test/java/org/apache/gravitino/integration/test/util/ITUtils.java @@ -187,6 +187,10 @@ public static boolean isEmbedded() { return Objects.equals(mode, ITUtils.EMBEDDED_TEST_MODE); } + public static String icebergVersion() { + return System.getProperty("ICEBERG_VERSION"); + } + public static String getBundleJarSourceFile(String bundleName) { String jarName = ITUtils.getBundleJarName(bundleName); String gcsJars = ITUtils.joinPath(ITUtils.getBundleJarDirectory(bundleName), jarName); diff --git a/trino-connector/integration-test/trino-test-tools/download_jar.sh b/trino-connector/integration-test/trino-test-tools/download_jar.sh index 36cba2bce9d..3dcdf8803c0 100755 --- a/trino-connector/integration-test/trino-test-tools/download_jar.sh +++ b/trino-connector/integration-test/trino-test-tools/download_jar.sh @@ -62,8 +62,8 @@ download_postgresql_jar() { } download_iceberg_aws_bundle() { - download_jar "iceberg-aws-bundle--1.5.2.jar" \ - "https://jdbc.postgresql.org/download/iceberg-aws-bundle--1.5.2.jar" \ + download_jar "iceberg-aws-bundle-1.6.1.jar" \ + "https://jdbc.postgresql.org/download/iceberg-aws-bundle-1.6.1.jar" \ "$GRAVITINO_SERVER_DIR/catalogs/lakehouse-iceberg/libs" } From e85e47dcd859008a123f141945cc70546f36f725 Mon Sep 17 00:00:00 2001 From: Yuhui Date: Fri, 7 Feb 2025 14:28:20 +0800 Subject: [PATCH 08/33] [#6320] feat (gvfs-fuse): Support mount and umount command for gvfs-fuse command line tools (#6321) ### What changes were proposed in this pull request? 1. Support mount and umount command 2. Make mount create a daemon process to run background ### Why are the changes needed? Fix: #6320 ### Does this PR introduce _any_ user-facing change? No ### How was this patch tested? IT --------- Co-authored-by: Qiming Teng --- clients/filesystem-fuse/Cargo.toml | 2 + clients/filesystem-fuse/conf/gvfs_fuse.toml | 1 + clients/filesystem-fuse/src/command_args.rs | 59 +++++ clients/filesystem-fuse/src/config.rs | 72 ++++-- clients/filesystem-fuse/src/fuse_server.rs | 3 +- clients/filesystem-fuse/src/lib.rs | 3 + clients/filesystem-fuse/src/main.rs | 229 +++++++++++++++--- clients/filesystem-fuse/src/s3_filesystem.rs | 2 +- .../filesystem-fuse/tests/bin/gvfs_fuse.sh | 9 +- .../tests/conf/config_test.toml | 2 + .../tests/conf/gvfs_fuse_s3.toml | 1 + clients/filesystem-fuse/tests/fuse_test.rs | 2 +- 12 files changed, 328 insertions(+), 57 deletions(-) create mode 100644 clients/filesystem-fuse/src/command_args.rs diff --git a/clients/filesystem-fuse/Cargo.toml b/clients/filesystem-fuse/Cargo.toml index 3760bd5285f..e6006836894 100644 --- a/clients/filesystem-fuse/Cargo.toml +++ b/clients/filesystem-fuse/Cargo.toml @@ -35,7 +35,9 @@ name = "gvfs_fuse" [dependencies] async-trait = "0.1" bytes = "1.6.0" +clap = { version = "4.5.24", features = ["derive"] } config = "0.13" +daemonize = "0.5.0" dashmap = "6.1.0" fuse3 = { version = "0.8.1", "features" = ["tokio-runtime", "unprivileged"] } futures-util = "0.3.30" diff --git a/clients/filesystem-fuse/conf/gvfs_fuse.toml b/clients/filesystem-fuse/conf/gvfs_fuse.toml index 4bde0e9e1bd..27e52fc7d57 100644 --- a/clients/filesystem-fuse/conf/gvfs_fuse.toml +++ b/clients/filesystem-fuse/conf/gvfs_fuse.toml @@ -20,6 +20,7 @@ file_mask = 0o600 dir_mask = 0o700 fs_type = "memory" +data_path = "target/gvfs-fuse" [fuse.properties] diff --git a/clients/filesystem-fuse/src/command_args.rs b/clients/filesystem-fuse/src/command_args.rs new file mode 100644 index 00000000000..bb442f167d0 --- /dev/null +++ b/clients/filesystem-fuse/src/command_args.rs @@ -0,0 +1,59 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +use clap::{Parser, Subcommand}; + +#[derive(Parser, Debug)] +#[command( + name = "gvfs-fuse", + version = "0.1", + about = "A FUSE-based file system client" +)] +pub(crate) struct Arguments { + #[command(subcommand)] + pub(crate) command: Commands, +} + +#[derive(Subcommand, Debug)] +pub(crate) enum Commands { + Mount { + #[arg(help = "Mount point for the filesystem")] + mount_point: String, + + #[arg( + help = "The URI of the GVFS fileset, like gvfs://fileset/my_catalog/my_schema/my_fileset" + )] + fileset_location: String, + + #[arg(short, long, help = "Path to the configuration file")] + config: Option, + + #[arg(short, long, help = "Debug level", default_value_t = 0)] + debug: u8, + + #[arg(short, long, default_value_t = false, help = "Run in foreground")] + foreground: bool, + }, + Umount { + #[arg(help = "Mount point to umount")] + mount_point: String, + + #[arg(short, long, help = "Force umount")] + force: bool, + }, +} diff --git a/clients/filesystem-fuse/src/config.rs b/clients/filesystem-fuse/src/config.rs index 17908fd08fc..890cb7d31dc 100644 --- a/clients/filesystem-fuse/src/config.rs +++ b/clients/filesystem-fuse/src/config.rs @@ -24,6 +24,7 @@ use serde::Deserialize; use std::collections::HashMap; use std::fs; +// FuseConfig pub(crate) const CONF_FUSE_FILE_MASK: ConfigEntity = ConfigEntity::new( FuseConfig::MODULE_NAME, "file_mask", @@ -45,13 +46,28 @@ pub(crate) const CONF_FUSE_FS_TYPE: ConfigEntity<&'static str> = ConfigEntity::n "memory", ); -pub(crate) const CONF_FUSE_CONFIG_PATH: ConfigEntity<&'static str> = ConfigEntity::new( +pub(crate) const CONF_FUSE_CONFIG_FILE_PATH: ConfigEntity<&'static str> = ConfigEntity::new( FuseConfig::MODULE_NAME, "config_path", "The path of the FUSE configuration file", - "/etc/gvfs/gvfs.toml", + "/etc/gvfs-fuse/config.toml", ); +pub(crate) const CONF_FUSE_DATA_DIR: ConfigEntity<&'static str> = ConfigEntity::new( + FuseConfig::MODULE_NAME, + "data_dir", + "The data path of GVFS FUSE", + "/var/data/gvfs-fuse", +); + +pub(crate) const CONF_FUSE_LOG_DIR: ConfigEntity<&'static str> = ConfigEntity::new( + FuseConfig::MODULE_NAME, + "log_dir", + "The log path of GVFS FUSE", + "logs", //relative to the data path +); + +// FilesystemConfig pub(crate) const CONF_FILESYSTEM_BLOCK_SIZE: ConfigEntity = ConfigEntity::new( FilesystemConfig::MODULE_NAME, "block_size", @@ -59,6 +75,7 @@ pub(crate) const CONF_FILESYSTEM_BLOCK_SIZE: ConfigEntity = ConfigEntity::n 4096, ); +// GravitinoConfig pub(crate) const CONF_GRAVITINO_URI: ConfigEntity<&'static str> = ConfigEntity::new( GravitinoConfig::MODULE_NAME, "uri", @@ -125,22 +142,32 @@ impl Default for DefaultConfig { ConfigValue::String(CONF_FUSE_FS_TYPE), ); configs.insert( - Self::compose_key(CONF_FUSE_CONFIG_PATH), - ConfigValue::String(CONF_FUSE_CONFIG_PATH), + Self::compose_key(CONF_FUSE_CONFIG_FILE_PATH), + ConfigValue::String(CONF_FUSE_CONFIG_FILE_PATH), ); configs.insert( - Self::compose_key(CONF_GRAVITINO_URI), - ConfigValue::String(CONF_GRAVITINO_URI), + Self::compose_key(CONF_FUSE_DATA_DIR), + ConfigValue::String(CONF_FUSE_DATA_DIR), ); configs.insert( - Self::compose_key(CONF_GRAVITINO_METALAKE), - ConfigValue::String(CONF_GRAVITINO_METALAKE), + Self::compose_key(CONF_FUSE_LOG_DIR), + ConfigValue::String(CONF_FUSE_LOG_DIR), ); + configs.insert( Self::compose_key(CONF_FILESYSTEM_BLOCK_SIZE), ConfigValue::U32(CONF_FILESYSTEM_BLOCK_SIZE), ); + configs.insert( + Self::compose_key(CONF_GRAVITINO_URI), + ConfigValue::String(CONF_GRAVITINO_URI), + ); + configs.insert( + Self::compose_key(CONF_GRAVITINO_METALAKE), + ConfigValue::String(CONF_GRAVITINO_METALAKE), + ); + DefaultConfig { configs } } } @@ -205,38 +232,39 @@ impl AppConfig { .unwrap_or_else(|e| panic!("Failed to set default for {}: {}", entity.name, e)) } - pub fn from_file(config_file_path: Option<&str>) -> GvfsResult { + pub fn from_file(config_file_path: Option) -> GvfsResult { let builder = Self::crete_default_config_builder(); let config_path = { if config_file_path.is_some() { let path = config_file_path.unwrap(); //check config file exists - if fs::metadata(path).is_err() { + if fs::metadata(&path).is_err() { return Err( ConfigNotFound.to_error("The configuration file not found".to_string()) ); } - info!("Use configuration file: {}", path); + info!("Use configuration file: {}", &path); path } else { - //use default config - if fs::metadata(CONF_FUSE_CONFIG_PATH.default).is_err() { + if fs::metadata(CONF_FUSE_CONFIG_FILE_PATH.default).is_err() { + //use default config warn!( "The default configuration file is not found, using the default configuration" ); return Ok(AppConfig::default()); } else { + //use the default configuration file warn!( "Using the default config file {}", - CONF_FUSE_CONFIG_PATH.default + CONF_FUSE_CONFIG_FILE_PATH.default ); } - CONF_FUSE_CONFIG_PATH.default + CONF_FUSE_CONFIG_FILE_PATH.default.to_string() } }; let config = builder - .add_source(config::File::with_name(config_path).required(true)) + .add_source(config::File::with_name(&config_path).required(true)) .build(); if let Err(e) = config { let msg = format!("Failed to build configuration: {}", e); @@ -265,7 +293,11 @@ pub struct FuseConfig { #[serde(default)] pub fs_type: String, #[serde(default)] - pub config_path: String, + pub config_file_path: String, + #[serde(default)] + pub data_dir: String, + #[serde(default)] + pub log_dir: String, #[serde(default)] pub properties: HashMap, } @@ -302,9 +334,11 @@ mod test { #[test] fn test_config_from_file() { - let config = AppConfig::from_file(Some("tests/conf/config_test.toml")).unwrap(); + let config = AppConfig::from_file(Some("tests/conf/config_test.toml".to_string())).unwrap(); assert_eq!(config.fuse.file_mask, 0o644); assert_eq!(config.fuse.dir_mask, 0o755); + assert_eq!(config.fuse.data_dir, "/target/gvfs-fuse"); + assert_eq!(config.fuse.log_dir, "/target/gvfs-fuse/logs"); assert_eq!(config.filesystem.block_size, 8192); assert_eq!(config.gravitino.uri, "http://localhost:8090"); assert_eq!(config.gravitino.metalake, "test"); @@ -323,6 +357,8 @@ mod test { let config = AppConfig::default(); assert_eq!(config.fuse.file_mask, 0o600); assert_eq!(config.fuse.dir_mask, 0o700); + assert_eq!(config.fuse.data_dir, "/var/data/gvfs-fuse"); + assert_eq!(config.fuse.log_dir, "logs"); assert_eq!(config.filesystem.block_size, 4096); assert_eq!(config.gravitino.uri, "http://localhost:8090"); assert_eq!(config.gravitino.metalake, ""); diff --git a/clients/filesystem-fuse/src/fuse_server.rs b/clients/filesystem-fuse/src/fuse_server.rs index a059686e16c..0e8bd518334 100644 --- a/clients/filesystem-fuse/src/fuse_server.rs +++ b/clients/filesystem-fuse/src/fuse_server.rs @@ -20,6 +20,7 @@ use crate::utils::GvfsResult; use fuse3::raw::{Filesystem, Session}; use fuse3::MountOptions; use log::{error, info}; +use std::path::Path; use std::process::exit; use std::sync::Arc; use tokio::select; @@ -46,7 +47,7 @@ impl FuseServer { /// Starts the FUSE filesystem and blocks until it is stopped. pub async fn start(&self, fuse_fs: impl Filesystem + Sync + 'static) -> GvfsResult<()> { //check if the mount point exists - if !std::path::Path::new(&self.mount_point).exists() { + if !Path::new(&self.mount_point).exists() { error!("Mount point {} does not exist", self.mount_point); exit(libc::ENOENT); } diff --git a/clients/filesystem-fuse/src/lib.rs b/clients/filesystem-fuse/src/lib.rs index 41a9a5335d5..65cd878f34d 100644 --- a/clients/filesystem-fuse/src/lib.rs +++ b/clients/filesystem-fuse/src/lib.rs @@ -49,6 +49,9 @@ macro_rules! test_enable_with { pub const RUN_TEST_WITH_S3: &str = "RUN_TEST_WITH_S3"; pub const RUN_TEST_WITH_FUSE: &str = "RUN_TEST_WITH_FUSE"; +pub const LOG_FILE_NAME: &str = "gvfs-fuse.log"; +pub const PID_FILE_NAME: &str = "gvfs-fuse.pid"; + pub async fn gvfs_mount(mount_to: &str, mount_from: &str, config: &AppConfig) -> GvfsResult<()> { gvfs_fuse::mount(mount_to, mount_from, config).await } diff --git a/clients/filesystem-fuse/src/main.rs b/clients/filesystem-fuse/src/main.rs index 4e517c76b37..6c8c0f4e0ed 100644 --- a/clients/filesystem-fuse/src/main.rs +++ b/clients/filesystem-fuse/src/main.rs @@ -16,49 +16,214 @@ * specific language governing permissions and limitations * under the License. */ -use fuse3::Errno; +mod command_args; + +use crate::command_args::Commands; +use clap::Parser; +use daemonize::Daemonize; use gvfs_fuse::config::AppConfig; -use gvfs_fuse::{gvfs_mount, gvfs_unmount}; +use gvfs_fuse::{gvfs_mount, gvfs_unmount, LOG_FILE_NAME, PID_FILE_NAME}; use log::{error, info}; +use std::fs::{create_dir, OpenOptions}; +use std::io; +use std::path::Path; +use std::process::Command; +use tokio::runtime::Runtime; use tokio::signal; +use tokio::signal::unix::{signal, SignalKind}; -#[tokio::main] -async fn main() -> fuse3::Result<()> { - tracing_subscriber::fmt::init(); - - // todo need inmprove the args parsing - let args: Vec = std::env::args().collect(); - let (mount_point, mount_from, config_path) = match args.len() { - 4 => (args[1].clone(), args[2].clone(), args[3].clone()), - _ => { - error!("Usage: {} ", args[0]); - return Err(Errno::from(libc::EINVAL)); - } +fn init_work_dirs(config: &AppConfig, mount_point: &str) -> io::Result<()> { + let data_dir_name = Path::new(&config.fuse.data_dir).to_path_buf(); + let data_dir_name = data_dir_name.canonicalize()?; + if !data_dir_name.exists() { + Err(io::Error::new( + io::ErrorKind::NotFound, + format!("Data directory {} not found", &config.fuse.data_dir), + ))? + }; + + let mount_point_name = data_dir_name.join(mount_point); + if !mount_point_name.exists() { + create_dir(&mount_point_name)? + }; + + let log_dir_name = data_dir_name.join(&config.fuse.log_dir); + if !log_dir_name.exists() { + create_dir(&log_dir_name)? }; - //todo(read config file from args) - let config = AppConfig::from_file(Some(&config_path)); - if let Err(e) = &config { - error!("Failed to load config: {:?}", e); - return Err(Errno::from(libc::EINVAL)); + Ok(()) +} + +fn make_daemon(config: &AppConfig) -> io::Result<()> { + let data_dir_name = Path::new(&config.fuse.data_dir); + let log_dir_name = data_dir_name.join(&config.fuse.log_dir); + let log_file_name = log_dir_name.join(LOG_FILE_NAME); + let log_file = OpenOptions::new() + .create(true) + .append(true) + .open(&log_file_name) + .unwrap(); + let log_err_file = OpenOptions::new().append(true).open(log_file_name).unwrap(); + + let pid_file_name = data_dir_name.join(PID_FILE_NAME); + + let daemonize = Daemonize::new() + .pid_file(pid_file_name) + .chown_pid_file(true) + .working_directory(data_dir_name) + .stdout(log_file) + .stderr(log_err_file); + + match daemonize.start() { + Ok(_) => info!("Gvfs-fuse Daemon started successfully"), + Err(e) => { + return Err(io::Error::new( + io::ErrorKind::Other, + format!("Gvfs-fuse Daemon failed to start: {:?}", e), + )) + } } - let config = config.unwrap(); - let handle = tokio::spawn(async move { - let result = gvfs_mount(&mount_point, &mount_from, &config).await; - if let Err(e) = result { - error!("Failed to mount gvfs: {:?}", e); - return Err(Errno::from(libc::EINVAL)); + Ok(()) +} + +fn mount_fuse(config: AppConfig, mount_point: String, target: String) -> io::Result<()> { + let rt = Runtime::new()?; + rt.block_on(async { + let handle = tokio::spawn(async move { + let result = gvfs_mount(&mount_point, &target, &config).await; + if let Err(e) = result { + error!("Failed to mount gvfs: {:?}", e); + return Err(io::Error::from(io::ErrorKind::InvalidInput)); + } + Ok(()) + }); + + let mut term_signal = signal(SignalKind::terminate())?; + tokio::select! { + _ = handle => {} + _ = signal::ctrl_c() => { + info!("Received Ctrl+C, unmounting gvfs...") + } + _ = term_signal.recv()=> { + info!("Received SIGTERM, unmounting gvfs...") + } } + + let _ = gvfs_unmount().await; Ok(()) - }); + }) +} - tokio::select! { - _ = handle => {} - _ = signal::ctrl_c() => { - info!("Received Ctrl+C, unmounting gvfs..."); +#[cfg(target_os = "macos")] +fn do_umount(mp: &str, force: bool) -> std::io::Result<()> { + let cmd_result = if force { + Command::new("umount").arg("-f").arg(mp).output() + } else { + Command::new("umount").arg(mp).output() + }; + + handle_command_result(cmd_result) +} + +#[cfg(target_os = "linux")] +fn do_umount(mp: &str, force: bool) -> std::io::Result<()> { + let cmd_result = + if Path::new("/bin/fusermount").exists() || Path::new("/usr/bin/fusermount").exists() { + if force { + Command::new("fusermount").arg("-uz").arg(mp).output() + } else { + Command::new("fusermount").arg("-u").arg(mp).output() + } + } else if force { + Command::new("umount").arg("-l").arg(mp).output() + } else { + Command::new("umount").arg(mp).output() + }; + + handle_command_result(cmd_result) +} + +fn handle_command_result(cmd_result: io::Result) -> io::Result<()> { + match cmd_result { + Ok(output) => { + if !output.status.success() { + let stderr = String::from_utf8_lossy(&output.stderr); + Err(io::Error::new(io::ErrorKind::Other, stderr.to_string())) + } else { + Ok(()) + } } + Err(e) => Err(e), } +} - let _ = gvfs_unmount().await; - Ok(()) +#[cfg(not(any(target_os = "macos", target_os = "linux")))] +fn do_umount(_mp: &str, _force: bool) -> std::io::Result<()> { + Err(std::io::Error::new( + std::io::ErrorKind::Other, + format!("OS {} is not supported", env::consts::OS), + )) +} + +fn main() -> Result<(), i32> { + tracing_subscriber::fmt().init(); + let args = command_args::Arguments::parse(); + match args.command { + Commands::Mount { + mount_point, + fileset_location, + config, + debug: _, + foreground, + } => { + let app_config = AppConfig::from_file(config); + if let Err(e) = &app_config { + error!("Failed to load config: {:?}", e); + return Err(-1); + }; + let app_config = app_config.unwrap(); + + let mount_point = { + let path = Path::new(&mount_point).canonicalize(); + if let Err(e) = path { + error!("Failed to resolve mount point: {:?}", e); + return Err(-1); + }; + let path = path.unwrap(); + path.to_string_lossy().to_string() + }; + + let result = init_work_dirs(&app_config, &mount_point); + if let Err(e) = result { + error!("Failed to initialize working directories: {:?}", e); + return Err(-1); + } + + let result = if foreground { + mount_fuse(app_config, mount_point, fileset_location) + } else { + let result = make_daemon(&app_config); + if let Err(e) = result { + error!("Failed to daemonize: {:?}", e); + return Err(-1); + }; + mount_fuse(app_config, mount_point, fileset_location) + }; + + if let Err(e) = result { + error!("Failed to mount gvfs: {:?}", e.to_string()); + return Err(-1); + }; + Ok(()) + } + Commands::Umount { mount_point, force } => { + let result = do_umount(&mount_point, force); + if let Err(e) = result { + error!("Failed to unmount gvfs: {:?}", e.to_string()); + return Err(-1); + }; + Ok(()) + } + } } diff --git a/clients/filesystem-fuse/src/s3_filesystem.rs b/clients/filesystem-fuse/src/s3_filesystem.rs index 35a091b3fe1..e397d31ccf3 100644 --- a/clients/filesystem-fuse/src/s3_filesystem.rs +++ b/clients/filesystem-fuse/src/s3_filesystem.rs @@ -255,7 +255,7 @@ pub(crate) mod tests { config_file_name = source_file_name; } - AppConfig::from_file(Some(config_file_name)).unwrap() + AppConfig::from_file(Some(config_file_name.to_string())).unwrap() } #[tokio::test] diff --git a/clients/filesystem-fuse/tests/bin/gvfs_fuse.sh b/clients/filesystem-fuse/tests/bin/gvfs_fuse.sh index e706d8e2c0d..3089a9a1a1f 100644 --- a/clients/filesystem-fuse/tests/bin/gvfs_fuse.sh +++ b/clients/filesystem-fuse/tests/bin/gvfs_fuse.sh @@ -52,14 +52,15 @@ start_gvfs_fuse() { make build echo "Starting gvfs-fuse-daemon" - $CLIENT_FUSE_DIR/target/debug/gvfs-fuse $MOUNT_DIR $MOUNT_FROM_LOCATION $TEST_CONFIG_FILE > \ + mkdir -p target/debug/gvfs-dir + $CLIENT_FUSE_DIR/target/debug/gvfs-fuse mount $MOUNT_DIR $MOUNT_FROM_LOCATION -c $TEST_CONFIG_FILE -f > \ $CLIENT_FUSE_DIR/target/debug/fuse.log 2>&1 & check_gvfs_fuse_ready cd - } stop_gvfs_fuse() { - # Stop the gvfs-fuse process if it's running - pkill -INT gvfs-fuse || true + # Unmount the gvfs-fuse + $CLIENT_FUSE_DIR/target/debug/gvfs-fuse umount $MOUNT_DIR echo "Stopping gvfs-fuse-daemon" -} \ No newline at end of file +} diff --git a/clients/filesystem-fuse/tests/conf/config_test.toml b/clients/filesystem-fuse/tests/conf/config_test.toml index 524e0aa94fb..e7cbf02c7f3 100644 --- a/clients/filesystem-fuse/tests/conf/config_test.toml +++ b/clients/filesystem-fuse/tests/conf/config_test.toml @@ -20,6 +20,8 @@ file_mask= 0o644 dir_mask= 0o755 fs_type = "memory" +data_dir = "/target/gvfs-fuse" +log_dir = "/target/gvfs-fuse/logs" [fuse.properties] key1 = "value1" diff --git a/clients/filesystem-fuse/tests/conf/gvfs_fuse_s3.toml b/clients/filesystem-fuse/tests/conf/gvfs_fuse_s3.toml index d0ff8e5ddec..69a3fcaf36d 100644 --- a/clients/filesystem-fuse/tests/conf/gvfs_fuse_s3.toml +++ b/clients/filesystem-fuse/tests/conf/gvfs_fuse_s3.toml @@ -20,6 +20,7 @@ file_mask= 0o600 dir_mask= 0o700 fs_type = "gvfs" +data_dir = "target/debug/gvfs-dir" [fuse.properties] key1 = "value1" diff --git a/clients/filesystem-fuse/tests/fuse_test.rs b/clients/filesystem-fuse/tests/fuse_test.rs index 1d1ef80b78b..cd7dbf7ea9f 100644 --- a/clients/filesystem-fuse/tests/fuse_test.rs +++ b/clients/filesystem-fuse/tests/fuse_test.rs @@ -45,7 +45,7 @@ impl FuseTestEnv { info!("Start gvfs fuse server"); let mount_point = self.mount_point.clone(); - let config = AppConfig::from_file(Some("tests/conf/gvfs_fuse_memory.toml")) + let config = AppConfig::from_file(Some("tests/conf/gvfs_fuse_memory.toml".to_string())) .expect("Failed to load config"); ASYNC_RUNTIME.spawn(async move { let result = gvfs_mount(&mount_point, "", &config).await; From 3417fc33f9515f1e02ef3d37559246d35515d031 Mon Sep 17 00:00:00 2001 From: Yuhui Date: Fri, 7 Feb 2025 16:24:10 +0800 Subject: [PATCH 09/33] [#6357] feat (gvfs-fuse): Passing file type argument in the Filesystem::stat() to improve the performance of open_dal_filesystem (#6358) ### What changes were proposed in this pull request? Passing file type argument in the Filesystem::stat() to improve the performance of open_dal_filesystem ### Why are the changes needed? Fix: #6357 ### Does this PR introduce _any_ user-facing change? No ### How was this patch tested? UI --------- Co-authored-by: Qiming Teng --- .../src/default_raw_filesystem.rs | 33 ++++++++++++++----- clients/filesystem-fuse/src/filesystem.rs | 11 ++++--- .../src/gravitino_fileset_filesystem.rs | 13 ++++++-- .../filesystem-fuse/src/memory_filesystem.rs | 8 +++-- .../src/open_dal_filesystem.rs | 25 +++++++++++--- clients/filesystem-fuse/src/s3_filesystem.rs | 9 +++-- .../filesystem-fuse/tests/bin/gvfs_fuse.sh | 2 -- .../tests/bin/run_fuse_testers.sh | 2 ++ .../tests/bin/run_s3fs_testers.sh | 1 - 9 files changed, 78 insertions(+), 26 deletions(-) mode change 100644 => 100755 clients/filesystem-fuse/tests/bin/run_s3fs_testers.sh diff --git a/clients/filesystem-fuse/src/default_raw_filesystem.rs b/clients/filesystem-fuse/src/default_raw_filesystem.rs index d1d8e7605df..08b480e43ef 100644 --- a/clients/filesystem-fuse/src/default_raw_filesystem.rs +++ b/clients/filesystem-fuse/src/default_raw_filesystem.rs @@ -26,6 +26,7 @@ use crate::opened_file::{FileHandle, OpenFileFlags, OpenedFile}; use crate::opened_file_manager::OpenedFileManager; use async_trait::async_trait; use bytes::Bytes; +use fuse3::FileType::{Directory, RegularFile}; use fuse3::{Errno, FileType}; use std::collections::HashMap; use std::ffi::OsStr; @@ -86,7 +87,12 @@ impl DefaultRawFileSystem { None => { // allocate new file id file_stat.set_file_id(parent_file_id, self.next_file_id()); - file_manager.insert(file_stat.parent_file_id, file_stat.file_id, &file_stat.path); + file_manager.insert( + file_stat.parent_file_id, + file_stat.file_id, + &file_stat.path, + file_stat.kind, + ); } Some(file) => { // use the exist file id @@ -130,9 +136,15 @@ impl DefaultRawFileSystem { file_manager.remove(path); } - async fn insert_file_entry_locked(&self, parent_file_id: u64, file_id: u64, path: &Path) { + async fn insert_file_entry_locked( + &self, + parent_file_id: u64, + file_id: u64, + path: &Path, + kind: FileType, + ) { let mut file_manager = self.file_entry_manager.write().await; - file_manager.insert(parent_file_id, file_id, path); + file_manager.insert(parent_file_id, file_id, path, kind); } fn get_meta_file_stat(&self) -> FileStat { @@ -159,6 +171,7 @@ impl RawFileSystem for DefaultRawFileSystem { ROOT_DIR_PARENT_FILE_ID, ROOT_DIR_FILE_ID, Path::new(ROOT_DIR_PATH), + Directory, ) .await; @@ -166,6 +179,7 @@ impl RawFileSystem for DefaultRawFileSystem { ROOT_DIR_FILE_ID, FS_META_FILE_ID, Path::new(FS_META_FILE_PATH), + RegularFile, ) .await; self.fs.init().await @@ -197,7 +211,7 @@ impl RawFileSystem for DefaultRawFileSystem { } let file_entry = self.get_file_entry(file_id).await?; - let mut file_stat = self.fs.stat(&file_entry.path).await?; + let mut file_stat = self.fs.stat(&file_entry.path, file_entry.kind).await?; file_stat.set_file_id(file_entry.parent_file_id, file_entry.file_id); Ok(file_stat) } @@ -209,7 +223,7 @@ impl RawFileSystem for DefaultRawFileSystem { let parent_file_entry = self.get_file_entry(parent_file_id).await?; let path = parent_file_entry.path.join(name); - let mut file_stat = self.fs.stat(&path).await?; + let mut file_stat = self.fs.lookup(&path).await?; // fill the file id to file stat self.resolve_file_id_to_filestat(&mut file_stat, parent_file_id) .await; @@ -270,6 +284,7 @@ impl RawFileSystem for DefaultRawFileSystem { parent_file_id, file_without_id.file_stat.file_id, &file_without_id.file_stat.path, + RegularFile, ) .await; @@ -287,7 +302,7 @@ impl RawFileSystem for DefaultRawFileSystem { filestat.set_file_id(parent_file_id, self.next_file_id()); // insert the new file to file entry manager - self.insert_file_entry_locked(parent_file_id, filestat.file_id, &filestat.path) + self.insert_file_entry_locked(parent_file_id, filestat.file_id, &filestat.path, Directory) .await; Ok(filestat.file_id) } @@ -401,6 +416,7 @@ struct FileEntry { file_id: u64, parent_file_id: u64, path: PathBuf, + kind: FileType, } /// FileEntryManager is manage all the file entries in memory. it is used manger the file relationship and name mapping. @@ -428,11 +444,12 @@ impl FileEntryManager { self.file_path_map.get(path).cloned() } - fn insert(&mut self, parent_file_id: u64, file_id: u64, path: &Path) { + fn insert(&mut self, parent_file_id: u64, file_id: u64, path: &Path, kind: FileType) { let file_entry = FileEntry { file_id, parent_file_id, path: path.into(), + kind: kind, }; self.file_id_map.insert(file_id, file_entry.clone()); self.file_path_map.insert(path.into(), file_entry); @@ -452,7 +469,7 @@ mod tests { #[test] fn test_file_entry_manager() { let mut manager = FileEntryManager::new(); - manager.insert(1, 2, Path::new("a/b")); + manager.insert(1, 2, Path::new("a/b"), Directory); let file = manager.get_file_entry_by_id(2).unwrap(); assert_eq!(file.file_id, 2); assert_eq!(file.parent_file_id, 1); diff --git a/clients/filesystem-fuse/src/filesystem.rs b/clients/filesystem-fuse/src/filesystem.rs index c0c27a5fbe2..a260f2053ab 100644 --- a/clients/filesystem-fuse/src/filesystem.rs +++ b/clients/filesystem-fuse/src/filesystem.rs @@ -115,7 +115,10 @@ pub(crate) trait PathFileSystem: Send + Sync { async fn init(&self) -> Result<()>; /// Get the file stat by file path, if the file exists, return the file stat - async fn stat(&self, path: &Path) -> Result; + async fn stat(&self, path: &Path, kind: FileType) -> Result; + + /// Lookup the file stat by file path, if the file exists, return the file stat + async fn lookup(&self, path: &Path) -> Result; /// Read the directory by file path, if the directory exists, return the file stat list async fn read_dir(&self, path: &Path) -> Result>; @@ -318,7 +321,7 @@ pub(crate) mod tests { pub(crate) async fn test_path_file_system(&mut self) { // test root dir - let resutl = self.fs.stat(Path::new("/")).await; + let resutl = self.fs.stat(Path::new("/"), Directory).await; assert!(resutl.is_ok()); let root_file_stat = resutl.unwrap(); self.assert_file_stat(&root_file_stat, Path::new("/"), Directory, 0); @@ -347,7 +350,7 @@ pub(crate) mod tests { } async fn test_stat_file(&mut self, path: &Path, expect_kind: FileType, expect_size: u64) { - let file_stat = self.fs.stat(path).await; + let file_stat = self.fs.stat(path, expect_kind).await; assert!(file_stat.is_ok()); let file_stat = file_stat.unwrap(); self.assert_file_stat(&file_stat, path, expect_kind, expect_size); @@ -403,7 +406,7 @@ pub(crate) mod tests { } async fn test_file_not_found(&self, path: &Path) { - let not_found_file = self.fs.stat(path).await; + let not_found_file = self.fs.stat(path, RegularFile).await; assert!(not_found_file.is_err()); } diff --git a/clients/filesystem-fuse/src/gravitino_fileset_filesystem.rs b/clients/filesystem-fuse/src/gravitino_fileset_filesystem.rs index 04236dfe841..ba717673b90 100644 --- a/clients/filesystem-fuse/src/gravitino_fileset_filesystem.rs +++ b/clients/filesystem-fuse/src/gravitino_fileset_filesystem.rs @@ -21,7 +21,7 @@ use crate::filesystem::{FileStat, FileSystemCapacity, FileSystemContext, PathFil use crate::gravitino_client::GravitinoClient; use crate::opened_file::{OpenFileFlags, OpenedFile}; use async_trait::async_trait; -use fuse3::Errno; +use fuse3::{Errno, FileType}; use std::path::{Path, PathBuf}; /// GravitinoFileSystem is a filesystem that is associated with a fileset in Gravitino. @@ -74,9 +74,16 @@ impl PathFileSystem for GravitinoFilesetFileSystem { self.physical_fs.init().await } - async fn stat(&self, path: &Path) -> Result { + async fn stat(&self, path: &Path, kind: FileType) -> Result { let raw_path = self.gvfs_path_to_raw_path(path); - let mut file_stat = self.physical_fs.stat(&raw_path).await?; + let mut file_stat = self.physical_fs.stat(&raw_path, kind).await?; + file_stat.path = self.raw_path_to_gvfs_path(&file_stat.path)?; + Ok(file_stat) + } + + async fn lookup(&self, path: &Path) -> Result { + let raw_path = self.gvfs_path_to_raw_path(path); + let mut file_stat = self.physical_fs.lookup(&raw_path).await?; file_stat.path = self.raw_path_to_gvfs_path(&file_stat.path)?; Ok(file_stat) } diff --git a/clients/filesystem-fuse/src/memory_filesystem.rs b/clients/filesystem-fuse/src/memory_filesystem.rs index d0385390729..204a91c171e 100644 --- a/clients/filesystem-fuse/src/memory_filesystem.rs +++ b/clients/filesystem-fuse/src/memory_filesystem.rs @@ -70,7 +70,7 @@ impl PathFileSystem for MemoryFileSystem { Ok(()) } - async fn stat(&self, path: &Path) -> Result { + async fn stat(&self, path: &Path, _kind: FileType) -> Result { self.file_map .read() .unwrap() @@ -79,6 +79,10 @@ impl PathFileSystem for MemoryFileSystem { .ok_or(Errno::from(libc::ENOENT)) } + async fn lookup(&self, path: &Path) -> Result { + self.stat(path, RegularFile).await + } + async fn read_dir(&self, path: &Path) -> Result> { let file_map = self.file_map.read().unwrap(); @@ -92,7 +96,7 @@ impl PathFileSystem for MemoryFileSystem { } async fn open_file(&self, path: &Path, flags: OpenFileFlags) -> Result { - let file_stat = self.stat(path).await?; + let file_stat = self.stat(path, RegularFile).await?; let mut opened_file = OpenedFile::new(file_stat); match opened_file.file_stat.kind { Directory => Ok(opened_file), diff --git a/clients/filesystem-fuse/src/open_dal_filesystem.rs b/clients/filesystem-fuse/src/open_dal_filesystem.rs index 9e094873f56..01969d74e02 100644 --- a/clients/filesystem-fuse/src/open_dal_filesystem.rs +++ b/clients/filesystem-fuse/src/open_dal_filesystem.rs @@ -66,7 +66,24 @@ impl PathFileSystem for OpenDalFileSystem { Ok(()) } - async fn stat(&self, path: &Path) -> Result { + async fn stat(&self, path: &Path, kind: FileType) -> Result { + let file_name = match kind { + Directory => build_dir_path(path), + _ => path.to_string_lossy().to_string(), + }; + let meta = self + .op + .stat(&file_name) + .await + .map_err(opendal_error_to_errno)?; + + let mut file_stat = FileStat::new_file_filestat_with_path(path, 0); + self.opendal_meta_to_file_stat(&meta, &mut file_stat); + + Ok(file_stat) + } + + async fn lookup(&self, path: &Path) -> Result { let file_name = path.to_string_lossy().to_string(); let meta_result = self.op.stat(&file_name).await; @@ -114,7 +131,7 @@ impl PathFileSystem for OpenDalFileSystem { } async fn open_file(&self, path: &Path, flags: OpenFileFlags) -> Result { - let file_stat = self.stat(path).await?; + let file_stat = self.stat(path, RegularFile).await?; debug_assert!(file_stat.kind == RegularFile); let mut file = OpenedFile::new(file_stat); @@ -155,7 +172,7 @@ impl PathFileSystem for OpenDalFileSystem { } async fn open_dir(&self, path: &Path, _flags: OpenFileFlags) -> Result { - let file_stat = self.stat(path).await?; + let file_stat = self.stat(path, Directory).await?; debug_assert!(file_stat.kind == Directory); let opened_file = OpenedFile::new(file_stat); @@ -185,7 +202,7 @@ impl PathFileSystem for OpenDalFileSystem { .create_dir(&dir_name) .await .map_err(opendal_error_to_errno)?; - let file_stat = self.stat(path).await?; + let file_stat = self.stat(path, Directory).await?; Ok(file_stat) } diff --git a/clients/filesystem-fuse/src/s3_filesystem.rs b/clients/filesystem-fuse/src/s3_filesystem.rs index e397d31ccf3..f4e9fd440d7 100644 --- a/clients/filesystem-fuse/src/s3_filesystem.rs +++ b/clients/filesystem-fuse/src/s3_filesystem.rs @@ -24,6 +24,7 @@ use crate::open_dal_filesystem::OpenDalFileSystem; use crate::opened_file::{OpenFileFlags, OpenedFile}; use crate::utils::{parse_location, GvfsResult}; use async_trait::async_trait; +use fuse3::FileType; use log::error; use opendal::layers::LoggingLayer; use opendal::services::S3; @@ -94,8 +95,12 @@ impl PathFileSystem for S3FileSystem { Ok(()) } - async fn stat(&self, path: &Path) -> Result { - self.open_dal_fs.stat(path).await + async fn stat(&self, path: &Path, kind: FileType) -> Result { + self.open_dal_fs.stat(path, kind).await + } + + async fn lookup(&self, path: &Path) -> Result { + self.open_dal_fs.lookup(path).await } async fn read_dir(&self, path: &Path) -> Result> { diff --git a/clients/filesystem-fuse/tests/bin/gvfs_fuse.sh b/clients/filesystem-fuse/tests/bin/gvfs_fuse.sh index 3089a9a1a1f..4f500c7bf8c 100644 --- a/clients/filesystem-fuse/tests/bin/gvfs_fuse.sh +++ b/clients/filesystem-fuse/tests/bin/gvfs_fuse.sh @@ -37,8 +37,6 @@ check_gvfs_fuse_ready() { } start_gvfs_fuse() { - MOUNT_DIR=$CLIENT_FUSE_DIR/target/gvfs - umount $MOUNT_DIR > /dev/null 2>&1 || true if [ ! -d "$MOUNT_DIR" ]; then echo "Create the mount point" diff --git a/clients/filesystem-fuse/tests/bin/run_fuse_testers.sh b/clients/filesystem-fuse/tests/bin/run_fuse_testers.sh index 7088a310b50..4d83ee03311 100755 --- a/clients/filesystem-fuse/tests/bin/run_fuse_testers.sh +++ b/clients/filesystem-fuse/tests/bin/run_fuse_testers.sh @@ -27,6 +27,8 @@ source ./gvfs_fuse.sh source ./localstatck.sh TEST_CONFIG_FILE=$CLIENT_FUSE_DIR/target/debug/gvfs-fuse.toml +MOUNT_DIR=$CLIENT_FUSE_DIR/target/gvfs + start_servers() { start_localstack diff --git a/clients/filesystem-fuse/tests/bin/run_s3fs_testers.sh b/clients/filesystem-fuse/tests/bin/run_s3fs_testers.sh old mode 100644 new mode 100755 index 8f25c0b3954..d4451e0dbe9 --- a/clients/filesystem-fuse/tests/bin/run_s3fs_testers.sh +++ b/clients/filesystem-fuse/tests/bin/run_s3fs_testers.sh @@ -70,4 +70,3 @@ else exit 1 fi - From 739dcea2273b5d8230c35d5aac16dd52c4bf120c Mon Sep 17 00:00:00 2001 From: Justin Mclean Date: Fri, 7 Feb 2025 22:45:49 +1100 Subject: [PATCH 10/33] [#6326] Refactor to add a command context to CLI (#6343) ### What changes were proposed in this pull request? Refactor to add a command context and simple wrappers on output to make it easy for "global" command like a "--quiet" option to be added. Note this in progress as this only has changed Metlake. Some duplicate code can be removed once everything is done. ### Why are the changes needed? For maintainability. Fix: #6326 ### Does this PR introduce _any_ user-facing change? No. ### How was this patch tested? Tested locally. --------- Co-authored-by: Shaofeng Shi --- .../apache/gravitino/cli/CommandContext.java | 104 ++++++++++++++++++ .../gravitino/cli/GravitinoCommandLine.java | 6 +- .../gravitino/cli/MetalakeCommandHandler.java | 54 ++++----- .../gravitino/cli/TestableCommandLine.java | 50 ++++----- .../cli/commands/AllMetalakeDetails.java | 10 +- .../gravitino/cli/commands/AuditCommand.java | 8 +- .../gravitino/cli/commands/Command.java | 35 ++++++ .../cli/commands/CreateMetalake.java | 10 +- .../cli/commands/DeleteMetalake.java | 15 ++- .../gravitino/cli/commands/DeleteRole.java | 4 +- .../cli/commands/ListMetalakeProperties.java | 8 +- .../gravitino/cli/commands/ListMetalakes.java | 9 +- .../cli/commands/ListProperties.java | 10 ++ .../cli/commands/MetadataCommand.java | 10 ++ .../gravitino/cli/commands/MetalakeAudit.java | 8 +- .../cli/commands/MetalakeDetails.java | 9 +- .../cli/commands/MetalakeDisable.java | 10 +- .../cli/commands/MetalakeEnable.java | 11 +- .../cli/commands/RemoveMetalakeProperty.java | 11 +- .../cli/commands/SetMetalakeProperty.java | 10 +- .../cli/commands/UpdateMetalakeComment.java | 11 +- .../cli/commands/UpdateMetalakeName.java | 14 +-- .../gravitino/cli/TestMetalakeCommands.java | 70 ++++++------ 23 files changed, 315 insertions(+), 172 deletions(-) create mode 100644 clients/cli/src/main/java/org/apache/gravitino/cli/CommandContext.java diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/CommandContext.java b/clients/cli/src/main/java/org/apache/gravitino/cli/CommandContext.java new file mode 100644 index 00000000000..994b97226e9 --- /dev/null +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/CommandContext.java @@ -0,0 +1,104 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.gravitino.cli; + +import org.apache.gravitino.cli.commands.Command; + +/* Context for a command */ +public class CommandContext { + private String url; + private boolean ignoreVersions; + private boolean force; + private String outputFormat; + // Can add more "global" command flags here without any major changes e.g. a guiet flag + + /** + * Command constructor. + * + * @param url The URL of the Gravitino server. + * @param ignoreVersions If true don't check the client/server versions match. + */ + public CommandContext(String url, boolean ignoreVersions) { + this.url = url; + this.ignoreVersions = ignoreVersions; + this.force = false; + this.outputFormat = Command.OUTPUT_FORMAT_PLAIN; + } + + /** + * Command constructor. + * + * @param url The URL of the Gravitino server. + * @param ignoreVersions If true don't check the client/server versions match. + * @param force Force operation. + * @param outputFormat Display output format. + */ + public CommandContext(String url, boolean ignoreVersions, boolean force, String outputFormat) { + this.url = url; + this.ignoreVersions = ignoreVersions; + this.force = force; + this.outputFormat = outputFormat; + } + + /** + * Returns the URL. + * + * @return The URL. + */ + public String url() { + return url; + } + + /** + * Sets the URL. + * + * @param url The URL to be set. + */ + public void setUrl(String url) { + this.url = url; + } + + /** + * Indicates whether versions should be ignored. + * + * @return False if versions should be ignored. + */ + public boolean ignoreVersions() { + return ignoreVersions; + } + + /** + * Indicates whether the operation should be forced. + * + * @return True if the operation should be forced. + */ + public boolean force() { + return force; + } + + /** + * Returns the output format. + * + * @return The output format. + */ + public String outputFormat() { + return outputFormat; + } +} diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/GravitinoCommandLine.java b/clients/cli/src/main/java/org/apache/gravitino/cli/GravitinoCommandLine.java index d7e257a8a81..1923562e1f4 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/GravitinoCommandLine.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/GravitinoCommandLine.java @@ -107,6 +107,10 @@ public static void displayHelp(Options options) { /** Executes the appropriate command based on the command type. */ private void executeCommand() { + boolean force = line.hasOption(GravitinoOptions.FORCE); + String outputFormat = line.getOptionValue(GravitinoOptions.OUTPUT); + CommandContext context = new CommandContext(null, ignore, force, outputFormat); + if (CommandActions.HELP.equals(command)) { handleHelpCommand(); } else if (line.hasOption(GravitinoOptions.OWNER)) { @@ -120,7 +124,7 @@ private void executeCommand() { } else if (entity.equals(CommandEntities.CATALOG)) { new CatalogCommandHandler(this, line, command, ignore).handle(); } else if (entity.equals(CommandEntities.METALAKE)) { - new MetalakeCommandHandler(this, line, command, ignore).handle(); + new MetalakeCommandHandler(this, line, command, context).handle(); } else if (entity.equals(CommandEntities.TOPIC)) { new TopicCommandHandler(this, line, command, ignore).handle(); } else if (entity.equals(CommandEntities.FILESET)) { diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/MetalakeCommandHandler.java b/clients/cli/src/main/java/org/apache/gravitino/cli/MetalakeCommandHandler.java index 993116f19f5..7d396838421 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/MetalakeCommandHandler.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/MetalakeCommandHandler.java @@ -29,9 +29,8 @@ public class MetalakeCommandHandler extends CommandHandler { private final GravitinoCommandLine gravitinoCommandLine; private final CommandLine line; + private final CommandContext context; private final String command; - private final boolean ignore; - private final String url; private String metalake; /** @@ -40,15 +39,18 @@ public class MetalakeCommandHandler extends CommandHandler { * @param gravitinoCommandLine The Gravitino command line instance. * @param line The command line arguments. * @param command The command to execute. - * @param ignore Ignore server version mismatch. + * @param context The command context. */ public MetalakeCommandHandler( - GravitinoCommandLine gravitinoCommandLine, CommandLine line, String command, boolean ignore) { + GravitinoCommandLine gravitinoCommandLine, + CommandLine line, + String command, + CommandContext context) { this.gravitinoCommandLine = gravitinoCommandLine; this.line = line; this.command = command; - this.ignore = ignore; - this.url = getUrl(line); + this.context = context; + this.context.setUrl(getUrl(line)); } /** Handles the command execution logic based on the provided command. */ @@ -112,33 +114,27 @@ private boolean executeCommand() { /** Handles the "LIST" command. */ private void handleListCommand() { - String outputFormat = line.getOptionValue(GravitinoOptions.OUTPUT); - gravitinoCommandLine.newListMetalakes(url, ignore, outputFormat).validate().handle(); + gravitinoCommandLine.newListMetalakes(context).validate().handle(); } /** Handles the "DETAILS" command. */ private void handleDetailsCommand() { if (line.hasOption(GravitinoOptions.AUDIT)) { - gravitinoCommandLine.newMetalakeAudit(url, ignore, metalake).validate().handle(); + gravitinoCommandLine.newMetalakeAudit(context, metalake).validate().handle(); } else { - String outputFormat = line.getOptionValue(GravitinoOptions.OUTPUT); - gravitinoCommandLine - .newMetalakeDetails(url, ignore, outputFormat, metalake) - .validate() - .handle(); + gravitinoCommandLine.newMetalakeDetails(context, metalake).validate().handle(); } } /** Handles the "CREATE" command. */ private void handleCreateCommand() { String comment = line.getOptionValue(GravitinoOptions.COMMENT); - gravitinoCommandLine.newCreateMetalake(url, ignore, metalake, comment).validate().handle(); + gravitinoCommandLine.newCreateMetalake(context, metalake, comment).validate().handle(); } /** Handles the "DELETE" command. */ private void handleDeleteCommand() { - boolean force = line.hasOption(GravitinoOptions.FORCE); - gravitinoCommandLine.newDeleteMetalake(url, ignore, force, metalake).validate().handle(); + gravitinoCommandLine.newDeleteMetalake(context, metalake).validate().handle(); } /** Handles the "SET" command. */ @@ -146,7 +142,7 @@ private void handleSetCommand() { String property = line.getOptionValue(GravitinoOptions.PROPERTY); String value = line.getOptionValue(GravitinoOptions.VALUE); gravitinoCommandLine - .newSetMetalakeProperty(url, ignore, metalake, property, value) + .newSetMetalakeProperty(context, metalake, property, value) .validate() .handle(); } @@ -154,15 +150,12 @@ private void handleSetCommand() { /** Handles the "REMOVE" command. */ private void handleRemoveCommand() { String property = line.getOptionValue(GravitinoOptions.PROPERTY); - gravitinoCommandLine - .newRemoveMetalakeProperty(url, ignore, metalake, property) - .validate() - .handle(); + gravitinoCommandLine.newRemoveMetalakeProperty(context, metalake, property).validate().handle(); } /** Handles the "PROPERTIES" command. */ private void handlePropertiesCommand() { - gravitinoCommandLine.newListMetalakeProperties(url, ignore, metalake).validate().handle(); + gravitinoCommandLine.newListMetalakeProperties(context, metalake).validate().handle(); } /** Handles the "UPDATE" command. */ @@ -174,28 +167,21 @@ private void handleUpdateCommand() { if (line.hasOption(GravitinoOptions.ENABLE)) { boolean enableAllCatalogs = line.hasOption(GravitinoOptions.ALL); gravitinoCommandLine - .newMetalakeEnable(url, ignore, metalake, enableAllCatalogs) + .newMetalakeEnable(context, metalake, enableAllCatalogs) .validate() .handle(); } if (line.hasOption(GravitinoOptions.DISABLE)) { - gravitinoCommandLine.newMetalakeDisable(url, ignore, metalake).validate().handle(); + gravitinoCommandLine.newMetalakeDisable(context, metalake).validate().handle(); } if (line.hasOption(GravitinoOptions.COMMENT)) { String comment = line.getOptionValue(GravitinoOptions.COMMENT); - gravitinoCommandLine - .newUpdateMetalakeComment(url, ignore, metalake, comment) - .validate() - .handle(); + gravitinoCommandLine.newUpdateMetalakeComment(context, metalake, comment).validate().handle(); } if (line.hasOption(GravitinoOptions.RENAME)) { String newName = line.getOptionValue(GravitinoOptions.RENAME); - boolean force = line.hasOption(GravitinoOptions.FORCE); - gravitinoCommandLine - .newUpdateMetalakeName(url, ignore, force, metalake, newName) - .validate() - .handle(); + gravitinoCommandLine.newUpdateMetalakeName(context, metalake, newName).validate().handle(); } } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/TestableCommandLine.java b/clients/cli/src/main/java/org/apache/gravitino/cli/TestableCommandLine.java index b229ef16aa3..21eec0c8650 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/TestableCommandLine.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/TestableCommandLine.java @@ -157,52 +157,50 @@ protected ServerVersion newServerVersion(String url, boolean ignore) { return new ServerVersion(url, ignore); } - protected MetalakeAudit newMetalakeAudit(String url, boolean ignore, String metalake) { - return new MetalakeAudit(url, ignore, metalake); + protected MetalakeAudit newMetalakeAudit(CommandContext context, String metalake) { + return new MetalakeAudit(context, metalake); } - protected MetalakeDetails newMetalakeDetails( - String url, boolean ignore, String outputFormat, String metalake) { - return new MetalakeDetails(url, ignore, outputFormat, metalake); + protected MetalakeDetails newMetalakeDetails(CommandContext context, String metalake) { + return new MetalakeDetails(context, metalake); } - protected ListMetalakes newListMetalakes(String url, boolean ignore, String outputFormat) { - return new ListMetalakes(url, ignore, outputFormat); + protected ListMetalakes newListMetalakes(CommandContext context) { + return new ListMetalakes(context); } protected CreateMetalake newCreateMetalake( - String url, boolean ignore, String metalake, String comment) { - return new CreateMetalake(url, ignore, metalake, comment); + CommandContext context, String metalake, String comment) { + return new CreateMetalake(context, metalake, comment); } - protected DeleteMetalake newDeleteMetalake( - String url, boolean ignore, boolean force, String metalake) { - return new DeleteMetalake(url, ignore, force, metalake); + protected DeleteMetalake newDeleteMetalake(CommandContext context, String metalake) { + return new DeleteMetalake(context, metalake); } protected SetMetalakeProperty newSetMetalakeProperty( - String url, boolean ignore, String metalake, String property, String value) { - return new SetMetalakeProperty(url, ignore, metalake, property, value); + CommandContext context, String metalake, String property, String value) { + return new SetMetalakeProperty(context, metalake, property, value); } protected RemoveMetalakeProperty newRemoveMetalakeProperty( - String url, boolean ignore, String metalake, String property) { - return new RemoveMetalakeProperty(url, ignore, metalake, property); + CommandContext context, String metalake, String property) { + return new RemoveMetalakeProperty(context, metalake, property); } protected ListMetalakeProperties newListMetalakeProperties( - String url, boolean ignore, String metalake) { - return new ListMetalakeProperties(url, ignore, metalake); + CommandContext context, String metalake) { + return new ListMetalakeProperties(context, metalake); } protected UpdateMetalakeComment newUpdateMetalakeComment( - String url, boolean ignore, String metalake, String comment) { - return new UpdateMetalakeComment(url, ignore, metalake, comment); + CommandContext context, String metalake, String comment) { + return new UpdateMetalakeComment(context, metalake, comment); } protected UpdateMetalakeName newUpdateMetalakeName( - String url, boolean ignore, boolean force, String metalake, String newName) { - return new UpdateMetalakeName(url, ignore, force, metalake, newName); + CommandContext context, String metalake, String newName) { + return new UpdateMetalakeName(context, metalake, newName); } protected CatalogAudit newCatalogAudit( @@ -908,12 +906,12 @@ protected RevokeAllPrivileges newRevokeAllPrivileges( } protected MetalakeEnable newMetalakeEnable( - String url, boolean ignore, String metalake, boolean enableAllCatalogs) { - return new MetalakeEnable(url, ignore, metalake, enableAllCatalogs); + CommandContext context, String metalake, boolean enableAllCatalogs) { + return new MetalakeEnable(context, metalake, enableAllCatalogs); } - protected MetalakeDisable newMetalakeDisable(String url, boolean ignore, String metalake) { - return new MetalakeDisable(url, ignore, metalake); + protected MetalakeDisable newMetalakeDisable(CommandContext context, String metalake) { + return new MetalakeDisable(context, metalake); } protected CatalogEnable newCatalogEnable( diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/AllMetalakeDetails.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/AllMetalakeDetails.java index b76138cb5c9..cd8deb9c13d 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/AllMetalakeDetails.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/AllMetalakeDetails.java @@ -23,6 +23,7 @@ import java.util.ArrayList; import java.util.List; import org.apache.gravitino.Metalake; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.client.GravitinoAdminClient; public class AllMetalakeDetails extends Command { @@ -30,11 +31,10 @@ public class AllMetalakeDetails extends Command { /** * Parameters needed to list all metalakes. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. */ - public AllMetalakeDetails(String url, boolean ignoreVersions) { - super(url, ignoreVersions); + public AllMetalakeDetails(CommandContext context) { + super(context); } /** Displays the name and comment of all metalakes. */ @@ -55,6 +55,6 @@ public void handle() { String all = Joiner.on(System.lineSeparator()).join(metalakeDetails); - System.out.print(all); + printResults(all); } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/AuditCommand.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/AuditCommand.java index 09eee347821..9c27295bddb 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/AuditCommand.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/AuditCommand.java @@ -20,6 +20,7 @@ package org.apache.gravitino.cli.commands; import org.apache.gravitino.Audit; +import org.apache.gravitino.cli.CommandContext; public abstract class AuditCommand extends Command { /** @@ -30,6 +31,11 @@ public AuditCommand(String url, boolean ignoreVersions) { super(url, ignoreVersions); } + /** @param context The command context. */ + public AuditCommand(CommandContext context) { + super(context); + } + /* Overridden in parent - do nothing */ @Override public void handle() {} @@ -51,6 +57,6 @@ public void displayAuditInfo(Audit audit) { + "," + audit.lastModifiedTime(); - System.out.println(auditInfo); + printResults(auditInfo); } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/Command.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/Command.java index ea6abdd6393..7d259ed18ba 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/Command.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/Command.java @@ -23,6 +23,7 @@ import com.google.common.base.Joiner; import java.io.File; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.cli.GravitinoConfig; import org.apache.gravitino.cli.KerberosData; @@ -49,10 +50,25 @@ public abstract class Command { private static final String SIMPLE_AUTH = "simple"; private static final String OAUTH_AUTH = "oauth"; private static final String KERBEROS_AUTH = "kerberos"; + private final String url; private final boolean ignoreVersions; private final String outputFormat; + protected CommandContext context = null; // TODO make final + + /** + * Command constructor. + * + * @param context The command context. + */ + public Command(CommandContext context) { + this.context = context; + this.url = context.url(); + this.ignoreVersions = context.ignoreVersions(); + this.outputFormat = context.outputFormat(); + } + /** * Command constructor. * @@ -88,6 +104,25 @@ public void exitWithError(String error) { Main.exit(-1); } + /** + * Prints out an informational message, often to indicate a command has finished. + * + * @param message The message to display. + */ + public void printInformation(String message) { + // so that future outoput could be suppressed + System.out.print(message); + } + + /** + * Prints out an a results of a command. + * + * @param results The results to display. + */ + public void printResults(String results) { + System.out.print(results); + } + /** * Sets the authentication mode and user credentials for the command. * diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/CreateMetalake.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/CreateMetalake.java index 9a3c033f028..cdb9472f20a 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/CreateMetalake.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/CreateMetalake.java @@ -19,6 +19,7 @@ package org.apache.gravitino.cli.commands; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoAdminClient; import org.apache.gravitino.exceptions.MetalakeAlreadyExistsException; @@ -30,13 +31,12 @@ public class CreateMetalake extends Command { /** * Create a new metalake. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param comment The metalake's comment. */ - public CreateMetalake(String url, boolean ignoreVersions, String metalake, String comment) { - super(url, ignoreVersions); + public CreateMetalake(CommandContext context, String metalake, String comment) { + super(context); this.metalake = metalake; this.comment = comment; } @@ -53,6 +53,6 @@ public void handle() { exitWithError(exp.getMessage()); } - System.out.println(metalake + " created"); + printInformation(metalake + " created"); } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/DeleteMetalake.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/DeleteMetalake.java index 3bad108a9ec..4f72058cd14 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/DeleteMetalake.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/DeleteMetalake.java @@ -20,6 +20,7 @@ package org.apache.gravitino.cli.commands; import org.apache.gravitino.cli.AreYouSure; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoAdminClient; import org.apache.gravitino.exceptions.MetalakeInUseException; @@ -32,14 +33,12 @@ public class DeleteMetalake extends Command { /** * Delete a metalake. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. - * @param force Force operation. + * @param context The command context. * @param metalake The name of the metalake. */ - public DeleteMetalake(String url, boolean ignoreVersions, boolean force, String metalake) { - super(url, ignoreVersions); - this.force = force; + public DeleteMetalake(CommandContext context, String metalake) { + super(context); + this.force = context.force(); this.metalake = metalake; } @@ -64,9 +63,9 @@ public void handle() { } if (deleted) { - System.out.println(metalake + " deleted."); + printInformation(metalake + " deleted."); } else { - System.out.println(metalake + " not deleted."); + printInformation(metalake + " not deleted."); } } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/DeleteRole.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/DeleteRole.java index fa7c8cacc2c..4e0bb508d19 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/DeleteRole.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/DeleteRole.java @@ -74,9 +74,9 @@ public void handle() { } if (failedRoles.isEmpty()) { - System.out.println(COMMA_JOINER.join(successRoles) + " deleted."); + printInformation(COMMA_JOINER.join(successRoles) + " deleted."); } else { - System.err.println( + printInformation( COMMA_JOINER.join(successRoles) + " deleted, " + "but " diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListMetalakeProperties.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListMetalakeProperties.java index b7d794d4455..2e85058d123 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListMetalakeProperties.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListMetalakeProperties.java @@ -21,6 +21,7 @@ import java.util.Map; import org.apache.gravitino.Metalake; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoAdminClient; import org.apache.gravitino.exceptions.NoSuchMetalakeException; @@ -33,12 +34,11 @@ public class ListMetalakeProperties extends ListProperties { /** * List the properties of a metalake. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. */ - public ListMetalakeProperties(String url, boolean ignoreVersions, String metalake) { - super(url, ignoreVersions); + public ListMetalakeProperties(CommandContext context, String metalake) { + super(context); this.metalake = metalake; } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListMetalakes.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListMetalakes.java index ee5ac81d646..a97e89bca2e 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListMetalakes.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListMetalakes.java @@ -20,6 +20,7 @@ package org.apache.gravitino.cli.commands; import org.apache.gravitino.Metalake; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.client.GravitinoAdminClient; /** Lists all metalakes. */ @@ -28,12 +29,10 @@ public class ListMetalakes extends Command { /** * List all metalakes. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. - * @param outputFormat The output format. + * @param context The command context. */ - public ListMetalakes(String url, boolean ignoreVersions, String outputFormat) { - super(url, ignoreVersions, outputFormat); + public ListMetalakes(CommandContext context) { + super(context); } /** Lists all metalakes. */ diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListProperties.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListProperties.java index a7d08ba36e2..55c750aa712 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListProperties.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListProperties.java @@ -20,10 +20,20 @@ package org.apache.gravitino.cli.commands; import java.util.Map; +import org.apache.gravitino.cli.CommandContext; /** List the properties of a metalake. */ public class ListProperties extends Command { + /** + * List the properties of an entity. + * + * @param context The command context. + */ + public ListProperties(CommandContext context) { + super(context); + } + /** * List the properties of an entity. * diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/MetadataCommand.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/MetadataCommand.java index 3f1e347c1fd..0ff7bce294f 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/MetadataCommand.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/MetadataCommand.java @@ -22,6 +22,7 @@ import org.apache.gravitino.Catalog; import org.apache.gravitino.MetadataObject; import org.apache.gravitino.MetadataObjects; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.FullName; import org.apache.gravitino.client.GravitinoClient; @@ -37,6 +38,15 @@ public MetadataCommand(String url, boolean ignoreVersions) { super(url, ignoreVersions); } + /** + * MetadataCommand constructor. + * + * @param context The command context. + */ + public MetadataCommand(CommandContext context) { + super(context); + } + /** * Constructs a {@link MetadataObject} based on the provided client, existing metadata object, and * entity name. diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/MetalakeAudit.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/MetalakeAudit.java index b966a1ae291..76d953e5b8e 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/MetalakeAudit.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/MetalakeAudit.java @@ -20,6 +20,7 @@ package org.apache.gravitino.cli.commands; import org.apache.gravitino.Audit; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchMetalakeException; @@ -31,12 +32,11 @@ public class MetalakeAudit extends AuditCommand { /** * Displays metalake audit information. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. */ - public MetalakeAudit(String url, boolean ignoreVersions, String metalake) { - super(url, ignoreVersions); + public MetalakeAudit(CommandContext context, String metalake) { + super(context); this.metalake = metalake; } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/MetalakeDetails.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/MetalakeDetails.java index ea503710d42..cc2bf6ce4b4 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/MetalakeDetails.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/MetalakeDetails.java @@ -20,6 +20,7 @@ package org.apache.gravitino.cli.commands; import org.apache.gravitino.Metalake; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchMetalakeException; @@ -31,13 +32,11 @@ public class MetalakeDetails extends Command { /** * Displays metalake details. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. - * @param outputFormat The output format. + * @param context The command context. * @param metalake The name of the metalake. */ - public MetalakeDetails(String url, boolean ignoreVersions, String outputFormat, String metalake) { - super(url, ignoreVersions, outputFormat); + public MetalakeDetails(CommandContext context, String metalake) { + super(context); this.metalake = metalake; } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/MetalakeDisable.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/MetalakeDisable.java index 02e33a45d45..ad05d293433 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/MetalakeDisable.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/MetalakeDisable.java @@ -19,6 +19,7 @@ package org.apache.gravitino.cli.commands; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoAdminClient; import org.apache.gravitino.exceptions.NoSuchMetalakeException; @@ -30,12 +31,11 @@ public class MetalakeDisable extends Command { /** * Disable metalake * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. */ - public MetalakeDisable(String url, boolean ignoreVersions, String metalake) { - super(url, ignoreVersions); + public MetalakeDisable(CommandContext context, String metalake) { + super(context); this.metalake = metalake; } @@ -51,6 +51,6 @@ public void handle() { exitWithError(exp.getMessage()); } - System.out.println(metalake + " has been disabled."); + printInformation(metalake + " has been disabled."); } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/MetalakeEnable.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/MetalakeEnable.java index 34ba23a61bb..f402c376081 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/MetalakeEnable.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/MetalakeEnable.java @@ -20,6 +20,7 @@ package org.apache.gravitino.cli.commands; import java.util.Arrays; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoAdminClient; import org.apache.gravitino.client.GravitinoMetalake; @@ -34,14 +35,12 @@ public class MetalakeEnable extends Command { /** * Enable a metalake * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param enableAllCatalogs Whether to enable all catalogs. */ - public MetalakeEnable( - String url, boolean ignoreVersions, String metalake, boolean enableAllCatalogs) { - super(url, ignoreVersions); + public MetalakeEnable(CommandContext context, String metalake, boolean enableAllCatalogs) { + super(context); this.metalake = metalake; this.enableAllCatalogs = enableAllCatalogs; } @@ -67,6 +66,6 @@ public void handle() { exitWithError(exp.getMessage()); } - System.out.println(msgBuilder); + printInformation(msgBuilder.toString()); } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RemoveMetalakeProperty.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RemoveMetalakeProperty.java index ce3a50fee16..ad00aa2fd21 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RemoveMetalakeProperty.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RemoveMetalakeProperty.java @@ -20,6 +20,7 @@ package org.apache.gravitino.cli.commands; import org.apache.gravitino.MetalakeChange; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoAdminClient; import org.apache.gravitino.exceptions.NoSuchMetalakeException; @@ -33,14 +34,12 @@ public class RemoveMetalakeProperty extends Command { /** * Remove a property of a metalake. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param property The name of the property. */ - public RemoveMetalakeProperty( - String url, boolean ignoreVersions, String metalake, String property) { - super(url, ignoreVersions); + public RemoveMetalakeProperty(CommandContext context, String metalake, String property) { + super(context); this.metalake = metalake; this.property = property; } @@ -58,7 +57,7 @@ public void handle() { exitWithError(exp.getMessage()); } - System.out.println(property + " property removed."); + printInformation(property + " property removed."); } @Override diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/SetMetalakeProperty.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/SetMetalakeProperty.java index ef67d008bc8..330ebb6398d 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/SetMetalakeProperty.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/SetMetalakeProperty.java @@ -20,6 +20,7 @@ package org.apache.gravitino.cli.commands; import org.apache.gravitino.MetalakeChange; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoAdminClient; import org.apache.gravitino.exceptions.NoSuchMetalakeException; @@ -34,15 +35,14 @@ public class SetMetalakeProperty extends Command { /** * Set a property of a metalake. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param property The name of the property. * @param value The value of the property. */ public SetMetalakeProperty( - String url, boolean ignoreVersions, String metalake, String property, String value) { - super(url, ignoreVersions); + CommandContext context, String metalake, String property, String value) { + super(context); this.metalake = metalake; this.property = property; this.value = value; @@ -61,7 +61,7 @@ public void handle() { exitWithError(exp.getMessage()); } - System.out.println(metalake + " property set."); + printInformation(metalake + " property set."); } @Override diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateMetalakeComment.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateMetalakeComment.java index 9ca63084e75..96a5a927418 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateMetalakeComment.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateMetalakeComment.java @@ -20,6 +20,7 @@ package org.apache.gravitino.cli.commands; import org.apache.gravitino.MetalakeChange; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoAdminClient; import org.apache.gravitino.exceptions.NoSuchMetalakeException; @@ -33,14 +34,12 @@ public class UpdateMetalakeComment extends Command { /** * Update the comment of a metalake. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param comment New metalake comment. */ - public UpdateMetalakeComment( - String url, boolean ignoreVersions, String metalake, String comment) { - super(url, ignoreVersions); + public UpdateMetalakeComment(CommandContext context, String metalake, String comment) { + super(context); this.metalake = metalake; this.comment = comment; } @@ -58,6 +57,6 @@ public void handle() { exitWithError(exp.getMessage()); } - System.out.println(metalake + " comment changed."); + printInformation(metalake + " comment changed."); } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateMetalakeName.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateMetalakeName.java index 275ba3165df..60497d034df 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateMetalakeName.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateMetalakeName.java @@ -21,6 +21,7 @@ import org.apache.gravitino.MetalakeChange; import org.apache.gravitino.cli.AreYouSure; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoAdminClient; import org.apache.gravitino.exceptions.NoSuchMetalakeException; @@ -35,16 +36,13 @@ public class UpdateMetalakeName extends Command { /** * Update the name of a metalake. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. - * @param force Force operation. + * @param context The command context. * @param metalake The name of the metalake. * @param name The new metalake name. */ - public UpdateMetalakeName( - String url, boolean ignoreVersions, boolean force, String metalake, String name) { - super(url, ignoreVersions); - this.force = force; + public UpdateMetalakeName(CommandContext context, String metalake, String name) { + super(context); + this.force = context.force(); this.metalake = metalake; this.name = name; } @@ -67,6 +65,6 @@ public void handle() { exitWithError(exp.getMessage()); } - System.out.println(metalake + " name changed."); + printInformation(metalake + " name changed."); } } diff --git a/clients/cli/src/test/java/org/apache/gravitino/cli/TestMetalakeCommands.java b/clients/cli/src/test/java/org/apache/gravitino/cli/TestMetalakeCommands.java index dae2fe63400..37e3acd2896 100644 --- a/clients/cli/src/test/java/org/apache/gravitino/cli/TestMetalakeCommands.java +++ b/clients/cli/src/test/java/org/apache/gravitino/cli/TestMetalakeCommands.java @@ -22,7 +22,10 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.any; import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.eq; +import static org.mockito.Mockito.isNull; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; @@ -65,6 +68,7 @@ void setUp() { mockOptions = mock(Options.class); System.setOut(new PrintStream(outContent)); System.setErr(new PrintStream(errContent)); + Main.useExit = false; } @AfterEach @@ -87,9 +91,7 @@ void testListMetalakesCommand() { spy( new GravitinoCommandLine( mockCommandLine, mockOptions, CommandEntities.METALAKE, CommandActions.LIST)); - doReturn(mockList) - .when(commandLine) - .newListMetalakes(GravitinoCommandLine.DEFAULT_URL, false, null); + doReturn(mockList).when(commandLine).newListMetalakes(any(CommandContext.class)); doReturn(mockList).when(mockList).validate(); commandLine.handleCommandLine(); verify(mockList).handle(); @@ -107,7 +109,7 @@ void testMetalakeDetailsCommand() { mockCommandLine, mockOptions, CommandEntities.METALAKE, CommandActions.DETAILS)); doReturn(mockDetails) .when(commandLine) - .newMetalakeDetails(GravitinoCommandLine.DEFAULT_URL, false, null, "metalake_demo"); + .newMetalakeDetails(any(CommandContext.class), eq("metalake_demo")); doReturn(mockDetails).when(mockDetails).validate(); commandLine.handleCommandLine(); verify(mockDetails).handle(); @@ -125,7 +127,7 @@ void testMetalakeAuditCommand() { mockCommandLine, mockOptions, CommandEntities.METALAKE, CommandActions.DETAILS)); doReturn(mockAudit) .when(commandLine) - .newMetalakeAudit(GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo"); + .newMetalakeAudit(any(CommandContext.class), eq("metalake_demo")); doReturn(mockAudit).when(mockAudit).validate(); commandLine.handleCommandLine(); verify(mockAudit).handle(); @@ -144,7 +146,7 @@ void testCreateMetalakeCommand() { mockCommandLine, mockOptions, CommandEntities.METALAKE, CommandActions.CREATE)); doReturn(mockCreate) .when(commandLine) - .newCreateMetalake(GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "comment"); + .newCreateMetalake(any(CommandContext.class), eq("metalake_demo"), eq("comment")); doReturn(mockCreate).when(mockCreate).validate(); commandLine.handleCommandLine(); verify(mockCreate).handle(); @@ -161,7 +163,7 @@ void testCreateMetalakeCommandNoComment() { mockCommandLine, mockOptions, CommandEntities.METALAKE, CommandActions.CREATE)); doReturn(mockCreate) .when(commandLine) - .newCreateMetalake(GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", null); + .newCreateMetalake(any(CommandContext.class), eq("metalake_demo"), isNull()); doReturn(mockCreate).when(mockCreate).validate(); commandLine.handleCommandLine(); verify(mockCreate).handle(); @@ -178,7 +180,7 @@ void testDeleteMetalakeCommand() { mockCommandLine, mockOptions, CommandEntities.METALAKE, CommandActions.DELETE)); doReturn(mockDelete) .when(commandLine) - .newDeleteMetalake(GravitinoCommandLine.DEFAULT_URL, false, false, "metalake_demo"); + .newDeleteMetalake(any(CommandContext.class), eq("metalake_demo")); doReturn(mockDelete).when(mockDelete).validate(); commandLine.handleCommandLine(); verify(mockDelete).handle(); @@ -189,14 +191,13 @@ void testDeleteMetalakeForceCommand() { DeleteMetalake mockDelete = mock(DeleteMetalake.class); when(mockCommandLine.hasOption(GravitinoOptions.METALAKE)).thenReturn(true); when(mockCommandLine.getOptionValue(GravitinoOptions.METALAKE)).thenReturn("metalake_demo"); - when(mockCommandLine.hasOption(GravitinoOptions.FORCE)).thenReturn(true); GravitinoCommandLine commandLine = spy( new GravitinoCommandLine( mockCommandLine, mockOptions, CommandEntities.METALAKE, CommandActions.DELETE)); doReturn(mockDelete) .when(commandLine) - .newDeleteMetalake(GravitinoCommandLine.DEFAULT_URL, false, true, "metalake_demo"); + .newDeleteMetalake(any(CommandContext.class), eq("metalake_demo")); doReturn(mockDelete).when(mockDelete).validate(); commandLine.handleCommandLine(); verify(mockDelete).handle(); @@ -218,7 +219,7 @@ void testSetMetalakePropertyCommand() { doReturn(mockSetProperty) .when(commandLine) .newSetMetalakeProperty( - GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "property", "value"); + any(CommandContext.class), eq("metalake_demo"), eq("property"), eq("value")); doReturn(mockSetProperty).when(mockSetProperty).validate(); commandLine.handleCommandLine(); verify(mockSetProperty).handle(); @@ -226,11 +227,11 @@ void testSetMetalakePropertyCommand() { @Test void testSetMetalakePropertyCommandWithoutPropertyAndValue() { + CommandContext context = new CommandContext(GravitinoCommandLine.DEFAULT_URL, false); + Main.useExit = false; SetMetalakeProperty metalakeProperty = - spy( - new SetMetalakeProperty( - GravitinoCommandLine.DEFAULT_URL, false, "demo_metalake", null, null)); + spy(new SetMetalakeProperty(context, "demo_metalake", null, null)); assertThrows(RuntimeException.class, metalakeProperty::validate); String errOutput = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); @@ -239,11 +240,11 @@ void testSetMetalakePropertyCommandWithoutPropertyAndValue() { @Test void testSetMetalakePropertyCommandWithoutProperty() { + CommandContext context = new CommandContext(GravitinoCommandLine.DEFAULT_URL, false); + Main.useExit = false; SetMetalakeProperty metalakeProperty = - spy( - new SetMetalakeProperty( - GravitinoCommandLine.DEFAULT_URL, false, "demo_metalake", null, "val1")); + spy(new SetMetalakeProperty(context, "demo_metalake", null, "val1")); assertThrows(RuntimeException.class, metalakeProperty::validate); String errOutput = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); @@ -252,11 +253,11 @@ void testSetMetalakePropertyCommandWithoutProperty() { @Test void testSetMetalakePropertyCommandWithoutValue() { + CommandContext context = new CommandContext(GravitinoCommandLine.DEFAULT_URL, false); + Main.useExit = false; SetMetalakeProperty metalakeProperty = - spy( - new SetMetalakeProperty( - GravitinoCommandLine.DEFAULT_URL, false, "demo_metalake", "property1", null)); + spy(new SetMetalakeProperty(context, "demo_metalake", "property1", null)); assertThrows(RuntimeException.class, metalakeProperty::validate); String errOutput = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); @@ -276,8 +277,7 @@ void testRemoveMetalakePropertyCommand() { mockCommandLine, mockOptions, CommandEntities.METALAKE, CommandActions.REMOVE)); doReturn(mockRemoveProperty) .when(commandLine) - .newRemoveMetalakeProperty( - GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "property"); + .newRemoveMetalakeProperty(any(CommandContext.class), eq("metalake_demo"), eq("property")); doReturn(mockRemoveProperty).when(mockRemoveProperty).validate(); commandLine.handleCommandLine(); verify(mockRemoveProperty).handle(); @@ -285,11 +285,11 @@ void testRemoveMetalakePropertyCommand() { @Test void testRemoveMetalakePropertyCommandWithoutProperty() { + CommandContext context = new CommandContext(GravitinoCommandLine.DEFAULT_URL, false); + Main.useExit = false; RemoveMetalakeProperty mockRemoveProperty = - spy( - new RemoveMetalakeProperty( - GravitinoCommandLine.DEFAULT_URL, false, "demo_metalake", null)); + spy(new RemoveMetalakeProperty(context, "demo_metalake", null)); assertThrows(RuntimeException.class, mockRemoveProperty::validate); String errOutput = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); @@ -307,7 +307,7 @@ void testListMetalakePropertiesCommand() { mockCommandLine, mockOptions, CommandEntities.METALAKE, CommandActions.PROPERTIES)); doReturn(mockListProperties) .when(commandLine) - .newListMetalakeProperties(GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo"); + .newListMetalakeProperties(any(CommandContext.class), eq("metalake_demo")); doReturn(mockListProperties).when(mockListProperties).validate(); commandLine.handleCommandLine(); verify(mockListProperties).handle(); @@ -327,7 +327,7 @@ void testUpdateMetalakeCommentCommand() { doReturn(mockUpdateComment) .when(commandLine) .newUpdateMetalakeComment( - GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "new comment"); + any(CommandContext.class), eq("metalake_demo"), eq("new comment")); doReturn(mockUpdateComment).when(mockUpdateComment).validate(); commandLine.handleCommandLine(); verify(mockUpdateComment).handle(); @@ -346,8 +346,7 @@ void testUpdateMetalakeNameCommand() { mockCommandLine, mockOptions, CommandEntities.METALAKE, CommandActions.UPDATE)); doReturn(mockUpdateName) .when(commandLine) - .newUpdateMetalakeName( - GravitinoCommandLine.DEFAULT_URL, false, false, "metalake_demo", "new_name"); + .newUpdateMetalakeName(any(CommandContext.class), eq("metalake_demo"), eq("new_name")); doReturn(mockUpdateName).when(mockUpdateName).validate(); commandLine.handleCommandLine(); verify(mockUpdateName).handle(); @@ -367,8 +366,7 @@ void testUpdateMetalakeNameForceCommand() { mockCommandLine, mockOptions, CommandEntities.METALAKE, CommandActions.UPDATE)); doReturn(mockUpdateName) .when(commandLine) - .newUpdateMetalakeName( - GravitinoCommandLine.DEFAULT_URL, false, true, "metalake_demo", "new_name"); + .newUpdateMetalakeName(any(CommandContext.class), eq("metalake_demo"), eq("new_name")); doReturn(mockUpdateName).when(mockUpdateName).validate(); commandLine.handleCommandLine(); verify(mockUpdateName).handle(); @@ -386,7 +384,7 @@ void testEnableMetalakeCommand() { mockCommandLine, mockOptions, CommandEntities.METALAKE, CommandActions.UPDATE)); doReturn(mockEnable) .when(commandLine) - .newMetalakeEnable(GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", false); + .newMetalakeEnable(any(CommandContext.class), eq("metalake_demo"), eq(false)); doReturn(mockEnable).when(mockEnable).validate(); commandLine.handleCommandLine(); verify(mockEnable).handle(); @@ -405,7 +403,7 @@ void testEnableMetalakeCommandWithRecursive() { mockCommandLine, mockOptions, CommandEntities.METALAKE, CommandActions.UPDATE)); doReturn(mockEnable) .when(commandLine) - .newMetalakeEnable(GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", true); + .newMetalakeEnable(any(CommandContext.class), eq("metalake_demo"), eq(true)); doReturn(mockEnable).when(mockEnable).validate(); commandLine.handleCommandLine(); verify(mockEnable).handle(); @@ -424,7 +422,7 @@ void testDisableMetalakeCommand() { mockCommandLine, mockOptions, CommandEntities.METALAKE, CommandActions.UPDATE)); doReturn(mockDisable) .when(commandLine) - .newMetalakeDisable(GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo"); + .newMetalakeDisable(any(CommandContext.class), eq("metalake_demo")); doReturn(mockDisable).when(mockDisable).validate(); commandLine.handleCommandLine(); verify(mockDisable).handle(); @@ -446,9 +444,9 @@ void testMetalakeWithDisableAndEnableOptions() { Assert.assertThrows(RuntimeException.class, commandLine::handleCommandLine); verify(commandLine, never()) - .newMetalakeEnable(GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", false); + .newMetalakeEnable(any(CommandContext.class), eq("metalake_demo"), eq(false)); verify(commandLine, never()) - .newMetalakeEnable(GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", false); + .newMetalakeEnable(any(CommandContext.class), eq("metalake_demo"), eq(false)); assertTrue(errContent.toString().contains(ErrorMessages.INVALID_ENABLE_DISABLE)); } } From e50e00ed84b73e45e268dd2da00d08dfecbca530 Mon Sep 17 00:00:00 2001 From: Jerry Shao Date: Sat, 8 Feb 2025 10:01:03 +0800 Subject: [PATCH 11/33] [#6407] improve(client-python): Reorganize the python package (#6408) ### What changes were proposed in this pull request? Move the `Fileset` and `Model` related classes to the sub-package for better organized. ### Why are the changes needed? For better organized. Fix: #6407 ### Does this PR introduce _any_ user-facing change? No. ### How was this patch tested? Existing tests. --- clients/client-python/gravitino/__init__.py | 4 ++-- .../client-python/gravitino/api/file/__init__.py | 16 ++++++++++++++++ .../gravitino/api/{ => file}/fileset.py | 0 .../gravitino/api/{ => file}/fileset_change.py | 0 .../gravitino/api/model/__init__.py | 16 ++++++++++++++++ .../gravitino/api/{ => model}/model.py | 0 .../gravitino/api/{ => model}/model_version.py | 0 .../gravitino/client/fileset_catalog.py | 4 ++-- .../gravitino/client/generic_fileset.py | 2 +- .../gravitino/client/generic_model.py | 2 +- .../gravitino/client/generic_model_catalog.py | 4 ++-- .../gravitino/client/generic_model_version.py | 2 +- .../client-python/gravitino/dto/fileset_dto.py | 2 +- clients/client-python/gravitino/dto/model_dto.py | 2 +- .../gravitino/dto/model_version_dto.py | 2 +- .../dto/requests/fileset_create_request.py | 2 +- .../dto/requests/fileset_update_request.py | 2 +- .../tests/unittests/test_model_catalog_api.py | 4 ++-- docs/how-to-use-gvfs.md | 2 +- 19 files changed, 49 insertions(+), 17 deletions(-) create mode 100644 clients/client-python/gravitino/api/file/__init__.py rename clients/client-python/gravitino/api/{ => file}/fileset.py (100%) rename clients/client-python/gravitino/api/{ => file}/fileset_change.py (100%) create mode 100644 clients/client-python/gravitino/api/model/__init__.py rename clients/client-python/gravitino/api/{ => model}/model.py (100%) rename clients/client-python/gravitino/api/{ => model}/model_version.py (100%) diff --git a/clients/client-python/gravitino/__init__.py b/clients/client-python/gravitino/__init__.py index 4818e68989f..c9f4aac347b 100644 --- a/clients/client-python/gravitino/__init__.py +++ b/clients/client-python/gravitino/__init__.py @@ -17,8 +17,8 @@ from gravitino.api.catalog import Catalog from gravitino.api.schema import Schema -from gravitino.api.fileset import Fileset -from gravitino.api.fileset_change import FilesetChange +from gravitino.api.file.fileset import Fileset +from gravitino.api.file.fileset_change import FilesetChange from gravitino.api.metalake_change import MetalakeChange from gravitino.api.schema_change import SchemaChange from gravitino.client.gravitino_client import GravitinoClient diff --git a/clients/client-python/gravitino/api/file/__init__.py b/clients/client-python/gravitino/api/file/__init__.py new file mode 100644 index 00000000000..13a83393a91 --- /dev/null +++ b/clients/client-python/gravitino/api/file/__init__.py @@ -0,0 +1,16 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. diff --git a/clients/client-python/gravitino/api/fileset.py b/clients/client-python/gravitino/api/file/fileset.py similarity index 100% rename from clients/client-python/gravitino/api/fileset.py rename to clients/client-python/gravitino/api/file/fileset.py diff --git a/clients/client-python/gravitino/api/fileset_change.py b/clients/client-python/gravitino/api/file/fileset_change.py similarity index 100% rename from clients/client-python/gravitino/api/fileset_change.py rename to clients/client-python/gravitino/api/file/fileset_change.py diff --git a/clients/client-python/gravitino/api/model/__init__.py b/clients/client-python/gravitino/api/model/__init__.py new file mode 100644 index 00000000000..13a83393a91 --- /dev/null +++ b/clients/client-python/gravitino/api/model/__init__.py @@ -0,0 +1,16 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. diff --git a/clients/client-python/gravitino/api/model.py b/clients/client-python/gravitino/api/model/model.py similarity index 100% rename from clients/client-python/gravitino/api/model.py rename to clients/client-python/gravitino/api/model/model.py diff --git a/clients/client-python/gravitino/api/model_version.py b/clients/client-python/gravitino/api/model/model_version.py similarity index 100% rename from clients/client-python/gravitino/api/model_version.py rename to clients/client-python/gravitino/api/model/model_version.py diff --git a/clients/client-python/gravitino/client/fileset_catalog.py b/clients/client-python/gravitino/client/fileset_catalog.py index 2fd51d967fb..df0ecf579e2 100644 --- a/clients/client-python/gravitino/client/fileset_catalog.py +++ b/clients/client-python/gravitino/client/fileset_catalog.py @@ -21,8 +21,8 @@ from gravitino.api.catalog import Catalog from gravitino.api.credential.supports_credentials import SupportsCredentials from gravitino.api.credential.credential import Credential -from gravitino.api.fileset import Fileset -from gravitino.api.fileset_change import FilesetChange +from gravitino.api.file.fileset import Fileset +from gravitino.api.file.fileset_change import FilesetChange from gravitino.audit.caller_context import CallerContextHolder, CallerContext from gravitino.client.base_schema_catalog import BaseSchemaCatalog from gravitino.client.generic_fileset import GenericFileset diff --git a/clients/client-python/gravitino/client/generic_fileset.py b/clients/client-python/gravitino/client/generic_fileset.py index 3b7aa5326c4..52a2975f98a 100644 --- a/clients/client-python/gravitino/client/generic_fileset.py +++ b/clients/client-python/gravitino/client/generic_fileset.py @@ -16,7 +16,7 @@ # under the License. from typing import Optional, Dict, List -from gravitino.api.fileset import Fileset +from gravitino.api.file.fileset import Fileset from gravitino.api.metadata_object import MetadataObject from gravitino.api.credential.supports_credentials import SupportsCredentials from gravitino.api.credential.credential import Credential diff --git a/clients/client-python/gravitino/client/generic_model.py b/clients/client-python/gravitino/client/generic_model.py index a5f0ef08c38..68c479232f6 100644 --- a/clients/client-python/gravitino/client/generic_model.py +++ b/clients/client-python/gravitino/client/generic_model.py @@ -16,7 +16,7 @@ # under the License. from typing import Optional -from gravitino.api.model import Model +from gravitino.api.model.model import Model from gravitino.dto.audit_dto import AuditDTO from gravitino.dto.model_dto import ModelDTO diff --git a/clients/client-python/gravitino/client/generic_model_catalog.py b/clients/client-python/gravitino/client/generic_model_catalog.py index 89bf29be13a..17d6ed0f1cd 100644 --- a/clients/client-python/gravitino/client/generic_model_catalog.py +++ b/clients/client-python/gravitino/client/generic_model_catalog.py @@ -19,8 +19,8 @@ from gravitino.name_identifier import NameIdentifier from gravitino.api.catalog import Catalog -from gravitino.api.model import Model -from gravitino.api.model_version import ModelVersion +from gravitino.api.model.model import Model +from gravitino.api.model.model_version import ModelVersion from gravitino.client.base_schema_catalog import BaseSchemaCatalog from gravitino.client.generic_model import GenericModel from gravitino.client.generic_model_version import GenericModelVersion diff --git a/clients/client-python/gravitino/client/generic_model_version.py b/clients/client-python/gravitino/client/generic_model_version.py index baf05ef51f5..cbeab85ac47 100644 --- a/clients/client-python/gravitino/client/generic_model_version.py +++ b/clients/client-python/gravitino/client/generic_model_version.py @@ -16,7 +16,7 @@ # under the License. from typing import Optional, Dict, List -from gravitino.api.model_version import ModelVersion +from gravitino.api.model.model_version import ModelVersion from gravitino.dto.audit_dto import AuditDTO from gravitino.dto.model_version_dto import ModelVersionDTO diff --git a/clients/client-python/gravitino/dto/fileset_dto.py b/clients/client-python/gravitino/dto/fileset_dto.py index 7f068373d0c..528ae3c74a6 100644 --- a/clients/client-python/gravitino/dto/fileset_dto.py +++ b/clients/client-python/gravitino/dto/fileset_dto.py @@ -20,7 +20,7 @@ from dataclasses_json import config, DataClassJsonMixin -from gravitino.api.fileset import Fileset +from gravitino.api.file.fileset import Fileset from gravitino.dto.audit_dto import AuditDTO diff --git a/clients/client-python/gravitino/dto/model_dto.py b/clients/client-python/gravitino/dto/model_dto.py index 83287beacc9..cde6d5d8dc8 100644 --- a/clients/client-python/gravitino/dto/model_dto.py +++ b/clients/client-python/gravitino/dto/model_dto.py @@ -19,7 +19,7 @@ from dataclasses_json import DataClassJsonMixin, config -from gravitino.api.model import Model +from gravitino.api.model.model import Model from gravitino.dto.audit_dto import AuditDTO diff --git a/clients/client-python/gravitino/dto/model_version_dto.py b/clients/client-python/gravitino/dto/model_version_dto.py index d945cc39e8b..2b287069e7a 100644 --- a/clients/client-python/gravitino/dto/model_version_dto.py +++ b/clients/client-python/gravitino/dto/model_version_dto.py @@ -20,7 +20,7 @@ from dataclasses_json import DataClassJsonMixin, config -from gravitino.api.model_version import ModelVersion +from gravitino.api.model.model_version import ModelVersion from gravitino.dto.audit_dto import AuditDTO diff --git a/clients/client-python/gravitino/dto/requests/fileset_create_request.py b/clients/client-python/gravitino/dto/requests/fileset_create_request.py index a7d8eaa0419..980287ba0e0 100644 --- a/clients/client-python/gravitino/dto/requests/fileset_create_request.py +++ b/clients/client-python/gravitino/dto/requests/fileset_create_request.py @@ -20,7 +20,7 @@ from dataclasses_json import config -from gravitino.api.fileset import Fileset +from gravitino.api.file.fileset import Fileset from gravitino.rest.rest_message import RESTRequest diff --git a/clients/client-python/gravitino/dto/requests/fileset_update_request.py b/clients/client-python/gravitino/dto/requests/fileset_update_request.py index 9a640d2071d..da7f4d7035f 100644 --- a/clients/client-python/gravitino/dto/requests/fileset_update_request.py +++ b/clients/client-python/gravitino/dto/requests/fileset_update_request.py @@ -20,7 +20,7 @@ from dataclasses_json import config -from gravitino.api.fileset_change import FilesetChange +from gravitino.api.file.fileset_change import FilesetChange from gravitino.rest.rest_message import RESTRequest diff --git a/clients/client-python/tests/unittests/test_model_catalog_api.py b/clients/client-python/tests/unittests/test_model_catalog_api.py index 5005f8737bb..91d5d5ec78a 100644 --- a/clients/client-python/tests/unittests/test_model_catalog_api.py +++ b/clients/client-python/tests/unittests/test_model_catalog_api.py @@ -20,8 +20,8 @@ from unittest.mock import Mock, patch from gravitino import NameIdentifier, GravitinoClient -from gravitino.api.model import Model -from gravitino.api.model_version import ModelVersion +from gravitino.api.model.model import Model +from gravitino.api.model.model_version import ModelVersion from gravitino.dto.audit_dto import AuditDTO from gravitino.dto.model_dto import ModelDTO from gravitino.dto.model_version_dto import ModelVersionDTO diff --git a/docs/how-to-use-gvfs.md b/docs/how-to-use-gvfs.md index cbbb67dd37c..ef084dad0e2 100644 --- a/docs/how-to-use-gvfs.md +++ b/docs/how-to-use-gvfs.md @@ -585,4 +585,4 @@ options = { } fs = gvfs.GravitinoVirtualFileSystem(server_uri="http://localhost:8090", metalake_name="test_metalake", options=options) print(fs.ls("gvfs://fileset/fileset_catlaog/tmp/test_fileset")) -``` \ No newline at end of file +``` From a84fd189ac1ae2313888beb718918f9639d84dbe Mon Sep 17 00:00:00 2001 From: Lychee <62695685+amazingLychee@users.noreply.github.com> Date: Sun, 9 Feb 2025 05:02:15 -0500 Subject: [PATCH 12/33] [#5900] feat(tag): support tag pre-event to Gravitino server (#5980) ### What changes were proposed in this pull request? Implemented pre-event handling for all tag-related operations, including: - listTags - listTagsInfo - getTag - createTag - alterTag - deleteTag - listMetadataObjectsForTag - listTagsForMetadataObject - listTagsInfoForMetadataObject - associateTagsForMetadataObject - getTagForMetadataObject ### Why are the changes needed? Fix: #5900 ### Does this PR introduce _any_ user-facing change? No ### How was this patch tested? add UT --- .../listener/TagEventDispatcher.java | 55 +++++- .../listener/api/event/AlterTagPreEvent.java | 63 ++++++ ...ssociateTagsForMetadataObjectPreEvent.java | 78 ++++++++ .../listener/api/event/CreateTagPreEvent.java | 61 ++++++ .../listener/api/event/DeleteTagPreEvent.java | 48 +++++ .../GetTagForMetadataObjectPreEvent.java | 62 ++++++ .../listener/api/event/GetTagPreEvent.java | 47 +++++ .../ListMetadataObjectsForTagPreEvent.java | 47 +++++ .../ListTagsForMetadataObjectPreEvent.java | 49 +++++ ...ListTagsInfoForMetadataObjectPreEvent.java | 52 +++++ .../api/event/ListTagsInfoPreEvent.java | 46 +++++ .../listener/api/event/ListTagsPreEvent.java | 46 +++++ .../listener/api/event/TagPreEvent.java | 37 ++++ .../gravitino/listener/api/info/TagInfo.java | 1 - .../listener/api/event/TestTagEvent.java | 187 ++++++++++++++++++ 15 files changed, 868 insertions(+), 11 deletions(-) create mode 100644 core/src/main/java/org/apache/gravitino/listener/api/event/AlterTagPreEvent.java create mode 100644 core/src/main/java/org/apache/gravitino/listener/api/event/AssociateTagsForMetadataObjectPreEvent.java create mode 100644 core/src/main/java/org/apache/gravitino/listener/api/event/CreateTagPreEvent.java create mode 100644 core/src/main/java/org/apache/gravitino/listener/api/event/DeleteTagPreEvent.java create mode 100644 core/src/main/java/org/apache/gravitino/listener/api/event/GetTagForMetadataObjectPreEvent.java create mode 100644 core/src/main/java/org/apache/gravitino/listener/api/event/GetTagPreEvent.java create mode 100644 core/src/main/java/org/apache/gravitino/listener/api/event/ListMetadataObjectsForTagPreEvent.java create mode 100644 core/src/main/java/org/apache/gravitino/listener/api/event/ListTagsForMetadataObjectPreEvent.java create mode 100644 core/src/main/java/org/apache/gravitino/listener/api/event/ListTagsInfoForMetadataObjectPreEvent.java create mode 100644 core/src/main/java/org/apache/gravitino/listener/api/event/ListTagsInfoPreEvent.java create mode 100644 core/src/main/java/org/apache/gravitino/listener/api/event/ListTagsPreEvent.java create mode 100644 core/src/main/java/org/apache/gravitino/listener/api/event/TagPreEvent.java diff --git a/core/src/main/java/org/apache/gravitino/listener/TagEventDispatcher.java b/core/src/main/java/org/apache/gravitino/listener/TagEventDispatcher.java index 302d82a93c7..c02c4eda655 100644 --- a/core/src/main/java/org/apache/gravitino/listener/TagEventDispatcher.java +++ b/core/src/main/java/org/apache/gravitino/listener/TagEventDispatcher.java @@ -22,16 +22,27 @@ import org.apache.gravitino.MetadataObject; import org.apache.gravitino.exceptions.NoSuchTagException; import org.apache.gravitino.listener.api.event.AlterTagFailureEvent; +import org.apache.gravitino.listener.api.event.AlterTagPreEvent; import org.apache.gravitino.listener.api.event.AssociateTagsForMetadataObjectFailureEvent; +import org.apache.gravitino.listener.api.event.AssociateTagsForMetadataObjectPreEvent; import org.apache.gravitino.listener.api.event.CreateTagFailureEvent; +import org.apache.gravitino.listener.api.event.CreateTagPreEvent; import org.apache.gravitino.listener.api.event.DeleteTagFailureEvent; +import org.apache.gravitino.listener.api.event.DeleteTagPreEvent; import org.apache.gravitino.listener.api.event.GetTagFailureEvent; import org.apache.gravitino.listener.api.event.GetTagForMetadataObjectFailureEvent; +import org.apache.gravitino.listener.api.event.GetTagForMetadataObjectPreEvent; +import org.apache.gravitino.listener.api.event.GetTagPreEvent; import org.apache.gravitino.listener.api.event.ListMetadataObjectsForTagFailureEvent; +import org.apache.gravitino.listener.api.event.ListMetadataObjectsForTagPreEvent; import org.apache.gravitino.listener.api.event.ListTagsFailureEvent; import org.apache.gravitino.listener.api.event.ListTagsForMetadataObjectFailureEvent; +import org.apache.gravitino.listener.api.event.ListTagsForMetadataObjectPreEvent; import org.apache.gravitino.listener.api.event.ListTagsInfoFailureEvent; import org.apache.gravitino.listener.api.event.ListTagsInfoForMetadataObjectFailureEvent; +import org.apache.gravitino.listener.api.event.ListTagsInfoForMetadataObjectPreEvent; +import org.apache.gravitino.listener.api.event.ListTagsInfoPreEvent; +import org.apache.gravitino.listener.api.event.ListTagsPreEvent; import org.apache.gravitino.listener.api.info.TagInfo; import org.apache.gravitino.tag.Tag; import org.apache.gravitino.tag.TagChange; @@ -55,7 +66,7 @@ public TagEventDispatcher(EventBus eventBus, TagDispatcher dispatcher) { @Override public String[] listTags(String metalake) { - // TODO: listTagsPreEvent + eventBus.dispatchEvent(new ListTagsPreEvent(PrincipalUtils.getCurrentUserName(), metalake)); try { // TODO: listTagsEvent return dispatcher.listTags(metalake); @@ -68,7 +79,7 @@ public String[] listTags(String metalake) { @Override public Tag[] listTagsInfo(String metalake) { - // TODO: listTagsInfoPreEvent + eventBus.dispatchEvent(new ListTagsInfoPreEvent(PrincipalUtils.getCurrentUserName(), metalake)); try { // TODO: listTagsInfoEvent return dispatcher.listTagsInfo(metalake); @@ -81,7 +92,7 @@ public Tag[] listTagsInfo(String metalake) { @Override public Tag getTag(String metalake, String name) throws NoSuchTagException { - // TODO: getTagPreEvent + eventBus.dispatchEvent(new GetTagPreEvent(PrincipalUtils.getCurrentUserName(), metalake, name)); try { // TODO: getTagEvent return dispatcher.getTag(metalake, name); @@ -97,6 +108,9 @@ public Tag createTag( String metalake, String name, String comment, Map properties) { TagInfo tagInfo = new TagInfo(name, comment, properties); // TODO: createTagPreEvent + + eventBus.dispatchEvent( + new CreateTagPreEvent(PrincipalUtils.getCurrentUserName(), metalake, tagInfo)); try { // TODO: createTagEvent return dispatcher.createTag(metalake, name, comment, properties); @@ -109,7 +123,10 @@ public Tag createTag( @Override public Tag alterTag(String metalake, String name, TagChange... changes) { - // TODO: alterTagPreEvent + AlterTagPreEvent preEvent = + new AlterTagPreEvent(PrincipalUtils.getCurrentUserName(), metalake, name, changes); + + eventBus.dispatchEvent(preEvent); try { // TODO: alterTagEvent return dispatcher.alterTag(metalake, name, changes); @@ -123,7 +140,10 @@ public Tag alterTag(String metalake, String name, TagChange... changes) { @Override public boolean deleteTag(String metalake, String name) { - // TODO: deleteTagPreEvent + DeleteTagPreEvent preEvent = + new DeleteTagPreEvent(PrincipalUtils.getCurrentUserName(), metalake, name); + + eventBus.dispatchEvent(preEvent); try { // TODO: deleteTagEvent return dispatcher.deleteTag(metalake, name); @@ -136,7 +156,8 @@ public boolean deleteTag(String metalake, String name) { @Override public MetadataObject[] listMetadataObjectsForTag(String metalake, String name) { - // TODO: listMetadataObjectsForTagPreEvent + eventBus.dispatchEvent( + new ListMetadataObjectsForTagPreEvent(PrincipalUtils.getCurrentUserName(), metalake, name)); try { // TODO: listMetadataObjectsForTagEvent return dispatcher.listMetadataObjectsForTag(metalake, name); @@ -150,7 +171,10 @@ public MetadataObject[] listMetadataObjectsForTag(String metalake, String name) @Override public String[] listTagsForMetadataObject(String metalake, MetadataObject metadataObject) { - // TODO: listTagsForMetadataObjectPreEvent + eventBus.dispatchEvent( + new ListTagsForMetadataObjectPreEvent( + PrincipalUtils.getCurrentUserName(), metalake, metadataObject)); + try { // TODO: listTagsForMetadataObjectEvent return dispatcher.listTagsForMetadataObject(metalake, metadataObject); @@ -164,7 +188,9 @@ public String[] listTagsForMetadataObject(String metalake, MetadataObject metada @Override public Tag[] listTagsInfoForMetadataObject(String metalake, MetadataObject metadataObject) { - // TODO: listTagsInfoForMetadataObjectPreEvent + eventBus.dispatchEvent( + new ListTagsInfoForMetadataObjectPreEvent( + PrincipalUtils.getCurrentUserName(), metalake, metadataObject)); try { // TODO: listTagsInfoForMetadataObjectEvent return dispatcher.listTagsInfoForMetadataObject(metalake, metadataObject); @@ -179,7 +205,14 @@ public Tag[] listTagsInfoForMetadataObject(String metalake, MetadataObject metad @Override public String[] associateTagsForMetadataObject( String metalake, MetadataObject metadataObject, String[] tagsToAdd, String[] tagsToRemove) { - // TODO: associateTagsForMetadataObjectPreEvent + eventBus.dispatchEvent( + new AssociateTagsForMetadataObjectPreEvent( + PrincipalUtils.getCurrentUserName(), + metalake, + metadataObject, + tagsToAdd, + tagsToRemove)); + try { // TODO: associateTagsForMetadataObjectEvent return dispatcher.associateTagsForMetadataObject( @@ -199,7 +232,9 @@ public String[] associateTagsForMetadataObject( @Override public Tag getTagForMetadataObject(String metalake, MetadataObject metadataObject, String name) { - // TODO: getTagForMetadataObjectPreEvent + eventBus.dispatchEvent( + new GetTagForMetadataObjectPreEvent( + PrincipalUtils.getCurrentUserName(), metalake, metadataObject, name)); try { // TODO: getTagForMetadataObjectEvent return dispatcher.getTagForMetadataObject(metalake, metadataObject, name); diff --git a/core/src/main/java/org/apache/gravitino/listener/api/event/AlterTagPreEvent.java b/core/src/main/java/org/apache/gravitino/listener/api/event/AlterTagPreEvent.java new file mode 100644 index 00000000000..1328d8418b6 --- /dev/null +++ b/core/src/main/java/org/apache/gravitino/listener/api/event/AlterTagPreEvent.java @@ -0,0 +1,63 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.gravitino.listener.api.event; + +import org.apache.gravitino.annotation.DeveloperApi; +import org.apache.gravitino.tag.TagChange; +import org.apache.gravitino.utils.NameIdentifierUtil; + +/** Represents an event triggered before altering a tag. */ +@DeveloperApi +public class AlterTagPreEvent extends TagPreEvent { + + private final TagChange[] changes; + + /** + * Constructs a new AlterTagPreEvent instance. + * + * @param user The user responsible for the operation. + * @param metalake The namespace of the tag. + * @param name The name of the tag being altered. + * @param changes The changes being applied to the tag. + */ + public AlterTagPreEvent(String user, String metalake, String name, TagChange[] changes) { + super(user, NameIdentifierUtil.ofTag(metalake, name)); + this.changes = changes; + } + + /** + * Returns the changes being applied to the tag. + * + * @return An array of {@link TagChange}. + */ + public TagChange[] changes() { + return changes; + } + + /** + * Returns the operation type for this event. + * + * @return The operation type {@link OperationType#ALTER_TAG}. + */ + @Override + public OperationType operationType() { + return OperationType.ALTER_TAG; + } +} diff --git a/core/src/main/java/org/apache/gravitino/listener/api/event/AssociateTagsForMetadataObjectPreEvent.java b/core/src/main/java/org/apache/gravitino/listener/api/event/AssociateTagsForMetadataObjectPreEvent.java new file mode 100644 index 00000000000..6a2ea2a4b94 --- /dev/null +++ b/core/src/main/java/org/apache/gravitino/listener/api/event/AssociateTagsForMetadataObjectPreEvent.java @@ -0,0 +1,78 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.gravitino.listener.api.event; + +import org.apache.gravitino.MetadataObject; +import org.apache.gravitino.annotation.DeveloperApi; +import org.apache.gravitino.utils.MetadataObjectUtil; + +/** Represents an event triggered before associating tags with a specific metadata object. */ +@DeveloperApi +public class AssociateTagsForMetadataObjectPreEvent extends TagPreEvent { + private final String[] tagsToAdd; + private final String[] tagsToRemove; + + /** + * Constructs the pre-event with user, metalake, metadata object, tags to add, and tags to remove. + * + * @param user The user initiating the operation. + * @param metalake The metalake environment name. + * @param metadataObject The metadata object for which tags will be associated. + * @param tagsToAdd Tags to be added to the metadata object. + * @param tagsToRemove Tags to be removed from the metadata object. + */ + public AssociateTagsForMetadataObjectPreEvent( + String user, + String metalake, + MetadataObject metadataObject, + String[] tagsToAdd, + String[] tagsToRemove) { + super(user, MetadataObjectUtil.toEntityIdent(metalake, metadataObject)); + this.tagsToAdd = tagsToAdd; + this.tagsToRemove = tagsToRemove; + } + + /** + * Returns the tags to be added. + * + * @return Array of tag names to be added. + */ + public String[] tagsToAdd() { + return tagsToAdd; + } + + /** + * Returns the tags to be removed. + * + * @return Array of tag names to be removed. + */ + public String[] tagsToRemove() { + return tagsToRemove; + } + + /** + * Returns the operation type for this event. + * + * @return The operation type, which is ASSOCIATE_TAGS_FOR_METADATA_OBJECT. + */ + @Override + public OperationType operationType() { + return OperationType.ASSOCIATE_TAGS_FOR_METADATA_OBJECT; + } +} diff --git a/core/src/main/java/org/apache/gravitino/listener/api/event/CreateTagPreEvent.java b/core/src/main/java/org/apache/gravitino/listener/api/event/CreateTagPreEvent.java new file mode 100644 index 00000000000..28db4b5119a --- /dev/null +++ b/core/src/main/java/org/apache/gravitino/listener/api/event/CreateTagPreEvent.java @@ -0,0 +1,61 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.gravitino.listener.api.event; + +import org.apache.gravitino.annotation.DeveloperApi; +import org.apache.gravitino.listener.api.info.TagInfo; +import org.apache.gravitino.utils.NameIdentifierUtil; + +/** Represents an event triggered before the creation of a tag. */ +@DeveloperApi +public class CreateTagPreEvent extends TagPreEvent { + private final TagInfo tagInfo; + + /** + * Constructs a new {@code CreateTagPreEvent} instance. + * + * @param user The user who initiated the tag creation operation. + * @param metalake The metalake name where the tag resides. + * @param tagInfo The information about the tag to be created. + */ + public CreateTagPreEvent(String user, String metalake, TagInfo tagInfo) { + super(user, NameIdentifierUtil.ofTag(metalake, tagInfo.name())); + this.tagInfo = tagInfo; + } + + /** + * Returns the information about the tag. + * + * @return the tag information + */ + public TagInfo tagInfo() { + return tagInfo; + } + + /** + * Returns the type of operation. + * + * @return the operation type. + */ + @Override + public OperationType operationType() { + return OperationType.CREATE_TAG; + } +} diff --git a/core/src/main/java/org/apache/gravitino/listener/api/event/DeleteTagPreEvent.java b/core/src/main/java/org/apache/gravitino/listener/api/event/DeleteTagPreEvent.java new file mode 100644 index 00000000000..1dafdcc58bb --- /dev/null +++ b/core/src/main/java/org/apache/gravitino/listener/api/event/DeleteTagPreEvent.java @@ -0,0 +1,48 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.gravitino.listener.api.event; + +import org.apache.gravitino.annotation.DeveloperApi; +import org.apache.gravitino.utils.NameIdentifierUtil; + +/** Represents an event triggered before deleting a tag. */ +@DeveloperApi +public class DeleteTagPreEvent extends TagPreEvent { + + /** + * Constructs a new {@code DeleteTagPreEvent} instance. + * + * @param user The user who initiated the tag deletion operation. + * @param metalake The metalake name where the tag resides. + * @param name The name of the tag to delete. + */ + public DeleteTagPreEvent(String user, String metalake, String name) { + super(user, NameIdentifierUtil.ofTag(metalake, name)); + } + + /** + * Returns the type of operation. + * + * @return the operation type. + */ + @Override + public OperationType operationType() { + return OperationType.DELETE_TAG; + } +} diff --git a/core/src/main/java/org/apache/gravitino/listener/api/event/GetTagForMetadataObjectPreEvent.java b/core/src/main/java/org/apache/gravitino/listener/api/event/GetTagForMetadataObjectPreEvent.java new file mode 100644 index 00000000000..cae41d954fc --- /dev/null +++ b/core/src/main/java/org/apache/gravitino/listener/api/event/GetTagForMetadataObjectPreEvent.java @@ -0,0 +1,62 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.gravitino.listener.api.event; + +import org.apache.gravitino.MetadataObject; +import org.apache.gravitino.annotation.DeveloperApi; +import org.apache.gravitino.utils.MetadataObjectUtil; + +/** Represents an event triggered before retrieving a tag for a specific metadata object. */ +@DeveloperApi +public class GetTagForMetadataObjectPreEvent extends TagPreEvent { + private final String tagName; + + /** + * Constructs the pre-event with user, metalake, metadata object, and tag name. + * + * @param user The user initiating the operation. + * @param metalake The metalake environment name. + * @param metadataObject The metadata object associated with the tag. + * @param name The name of the tag being retrieved. + */ + public GetTagForMetadataObjectPreEvent( + String user, String metalake, MetadataObject metadataObject, String name) { + super(user, MetadataObjectUtil.toEntityIdent(metalake, metadataObject)); + this.tagName = name; + } + + /** + * Returns the name of the tag being retrieved. + * + * @return The tag name. + */ + public String tagName() { + return tagName; + } + + /** + * Returns the operation type for this event. + * + * @return The operation type, which is GET_TAG_FOR_METADATA_OBJECT. + */ + @Override + public OperationType operationType() { + return OperationType.GET_TAG_FOR_METADATA_OBJECT; + } +} diff --git a/core/src/main/java/org/apache/gravitino/listener/api/event/GetTagPreEvent.java b/core/src/main/java/org/apache/gravitino/listener/api/event/GetTagPreEvent.java new file mode 100644 index 00000000000..f4238f76ae8 --- /dev/null +++ b/core/src/main/java/org/apache/gravitino/listener/api/event/GetTagPreEvent.java @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.gravitino.listener.api.event; + +import org.apache.gravitino.annotation.DeveloperApi; +import org.apache.gravitino.utils.NameIdentifierUtil; + +/** Represents an event triggered before getting a tag. */ +@DeveloperApi +public class GetTagPreEvent extends TagPreEvent { + /** + * Constructs a new {@code GetTagPreEvent} instance. + * + * @param user The user who initiated the get tag operation. + * @param metalake The metalake name where the tag resides. + * @param name The name of the tag to get. + */ + public GetTagPreEvent(String user, String metalake, String name) { + super(user, NameIdentifierUtil.ofTag(metalake, name)); + } + + /** + * Returns the type of operation. + * + * @return the operation type. + */ + @Override + public OperationType operationType() { + return OperationType.GET_TAG; + } +} diff --git a/core/src/main/java/org/apache/gravitino/listener/api/event/ListMetadataObjectsForTagPreEvent.java b/core/src/main/java/org/apache/gravitino/listener/api/event/ListMetadataObjectsForTagPreEvent.java new file mode 100644 index 00000000000..0bcb3abb994 --- /dev/null +++ b/core/src/main/java/org/apache/gravitino/listener/api/event/ListMetadataObjectsForTagPreEvent.java @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.gravitino.listener.api.event; + +import org.apache.gravitino.annotation.DeveloperApi; +import org.apache.gravitino.utils.NameIdentifierUtil; + +/** Represents a pre-event for listing metadata objects associated with a tag. */ +@DeveloperApi +public class ListMetadataObjectsForTagPreEvent extends TagPreEvent { + /** + * Constructs a new ListMetadataObjectsForTagPreEvent instance. + * + * @param user The user performing the operation. + * @param metalake The name of the Metalake environment. + * @param name The name of the tag. + */ + public ListMetadataObjectsForTagPreEvent(String user, String metalake, String name) { + super(user, NameIdentifierUtil.ofTag(metalake, name)); + } + + /** + * Returns the type of operation. + * + * @return the operation type. + */ + @Override + public OperationType operationType() { + return OperationType.LIST_METADATA_OBJECTS_FOR_TAG; + } +} diff --git a/core/src/main/java/org/apache/gravitino/listener/api/event/ListTagsForMetadataObjectPreEvent.java b/core/src/main/java/org/apache/gravitino/listener/api/event/ListTagsForMetadataObjectPreEvent.java new file mode 100644 index 00000000000..f4ebc2abd38 --- /dev/null +++ b/core/src/main/java/org/apache/gravitino/listener/api/event/ListTagsForMetadataObjectPreEvent.java @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.gravitino.listener.api.event; + +import org.apache.gravitino.MetadataObject; +import org.apache.gravitino.annotation.DeveloperApi; +import org.apache.gravitino.utils.MetadataObjectUtil; + +/** Represents an event triggered before listing tags for a metadata object. */ +@DeveloperApi +public class ListTagsForMetadataObjectPreEvent extends TagPreEvent { + /** + * Constructs a new {@code ListTagsForMetadataObjectPreEvent} instance. + * + * @param user The user who initiated the operation. + * @param metalake The metalake name where the metadata object resides. + * @param metadataObject The metadata object for which tags are being listed. + */ + public ListTagsForMetadataObjectPreEvent( + String user, String metalake, MetadataObject metadataObject) { + super(user, MetadataObjectUtil.toEntityIdent(metalake, metadataObject)); + } + + /** + * Returns the type of operation. + * + * @return the operation type. + */ + @Override + public OperationType operationType() { + return OperationType.LIST_TAGS_FOR_METADATA_OBJECT; + } +} diff --git a/core/src/main/java/org/apache/gravitino/listener/api/event/ListTagsInfoForMetadataObjectPreEvent.java b/core/src/main/java/org/apache/gravitino/listener/api/event/ListTagsInfoForMetadataObjectPreEvent.java new file mode 100644 index 00000000000..6b03746e905 --- /dev/null +++ b/core/src/main/java/org/apache/gravitino/listener/api/event/ListTagsInfoForMetadataObjectPreEvent.java @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.gravitino.listener.api.event; + +import org.apache.gravitino.MetadataObject; +import org.apache.gravitino.annotation.DeveloperApi; +import org.apache.gravitino.utils.MetadataObjectUtil; + +/** + * Represents an event triggered before listing detailed tag information for a specific metadata + * object. + */ +@DeveloperApi +public class ListTagsInfoForMetadataObjectPreEvent extends TagPreEvent { + /** + * Constructs the pre-event with user, metalake, and metadata object details. + * + * @param user The user initiating the operation. + * @param metalake The metalake environment name. + * @param metadataObject The metadata object for which tags' information will be listed. + */ + public ListTagsInfoForMetadataObjectPreEvent( + String user, String metalake, MetadataObject metadataObject) { + super(user, MetadataObjectUtil.toEntityIdent(metalake, metadataObject)); + } + + /** + * Returns the operation type for this event. + * + * @return The operation type, which is LIST_TAGS_INFO_FOR_METADATA_OBJECT. + */ + @Override + public OperationType operationType() { + return OperationType.LIST_TAGS_INFO_FOR_METADATA_OBJECT; + } +} diff --git a/core/src/main/java/org/apache/gravitino/listener/api/event/ListTagsInfoPreEvent.java b/core/src/main/java/org/apache/gravitino/listener/api/event/ListTagsInfoPreEvent.java new file mode 100644 index 00000000000..542fac5a73f --- /dev/null +++ b/core/src/main/java/org/apache/gravitino/listener/api/event/ListTagsInfoPreEvent.java @@ -0,0 +1,46 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.gravitino.listener.api.event; + +import org.apache.gravitino.NameIdentifier; +import org.apache.gravitino.annotation.DeveloperApi; + +/** Represents an event triggered before listing tags info. */ +@DeveloperApi +public class ListTagsInfoPreEvent extends TagPreEvent { + /** + * Constructs a new {@code ListTagsInfoPreEvent} instance. + * + * @param user The user who initiated the tag listing operation. + * @param metalake The metalake name where the tags are being listed. + */ + public ListTagsInfoPreEvent(String user, String metalake) { + super(user, NameIdentifier.of(metalake)); + } + + /** + * Returns the type of operation. + * + * @return the operation type. + */ + @Override + public OperationType operationType() { + return OperationType.LIST_TAGS_INFO; + } +} diff --git a/core/src/main/java/org/apache/gravitino/listener/api/event/ListTagsPreEvent.java b/core/src/main/java/org/apache/gravitino/listener/api/event/ListTagsPreEvent.java new file mode 100644 index 00000000000..e9f8013b46f --- /dev/null +++ b/core/src/main/java/org/apache/gravitino/listener/api/event/ListTagsPreEvent.java @@ -0,0 +1,46 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.gravitino.listener.api.event; + +import org.apache.gravitino.NameIdentifier; +import org.apache.gravitino.annotation.DeveloperApi; + +/** Represents an event triggered before listing tags. */ +@DeveloperApi +public class ListTagsPreEvent extends TagPreEvent { + /** + * Constructs a new {@code ListTagsPreEvent} instance. + * + * @param user The user who initiated the tag listing operation. + * @param metalake The metalake name where the tags are being listed. + */ + public ListTagsPreEvent(String user, String metalake) { + super(user, NameIdentifier.of(metalake)); + } + + /** + * Returns the type of operation. + * + * @return the operation type. + */ + @Override + public OperationType operationType() { + return OperationType.LIST_TAG; + } +} diff --git a/core/src/main/java/org/apache/gravitino/listener/api/event/TagPreEvent.java b/core/src/main/java/org/apache/gravitino/listener/api/event/TagPreEvent.java new file mode 100644 index 00000000000..4cdac415a1a --- /dev/null +++ b/core/src/main/java/org/apache/gravitino/listener/api/event/TagPreEvent.java @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.gravitino.listener.api.event; + +import org.apache.gravitino.NameIdentifier; +import org.apache.gravitino.annotation.DeveloperApi; + +/** Represents a pre-event for tag operations. */ +@DeveloperApi +public abstract class TagPreEvent extends PreEvent { + /** + * Constructs a new {@code TagPreEvent} instance. + * + * @param user The user who initiated the tag operation. + * @param identifier The identifier of the tag involved in the operation. + */ + protected TagPreEvent(String user, NameIdentifier identifier) { + super(user, identifier); + } +} diff --git a/core/src/main/java/org/apache/gravitino/listener/api/info/TagInfo.java b/core/src/main/java/org/apache/gravitino/listener/api/info/TagInfo.java index 20164f4c931..81d6444ab5f 100644 --- a/core/src/main/java/org/apache/gravitino/listener/api/info/TagInfo.java +++ b/core/src/main/java/org/apache/gravitino/listener/api/info/TagInfo.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.apache.gravitino.listener.api.info; import com.google.common.collect.ImmutableMap; diff --git a/core/src/test/java/org/apache/gravitino/listener/api/event/TestTagEvent.java b/core/src/test/java/org/apache/gravitino/listener/api/event/TestTagEvent.java index 1ac3001bd2c..2eaa2a5a419 100644 --- a/core/src/test/java/org/apache/gravitino/listener/api/event/TestTagEvent.java +++ b/core/src/test/java/org/apache/gravitino/listener/api/event/TestTagEvent.java @@ -24,15 +24,19 @@ import com.google.common.collect.ImmutableMap; import java.util.Arrays; +import java.util.Objects; import org.apache.gravitino.Entity; import org.apache.gravitino.MetadataObject; +import org.apache.gravitino.NameIdentifier; import org.apache.gravitino.exceptions.GravitinoRuntimeException; import org.apache.gravitino.listener.DummyEventListener; import org.apache.gravitino.listener.EventBus; import org.apache.gravitino.listener.TagEventDispatcher; +import org.apache.gravitino.listener.api.info.TagInfo; import org.apache.gravitino.tag.Tag; import org.apache.gravitino.tag.TagChange; import org.apache.gravitino.tag.TagDispatcher; +import org.apache.gravitino.utils.MetadataObjectUtil; import org.apache.gravitino.utils.NameIdentifierUtil; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; @@ -43,6 +47,7 @@ @TestInstance(Lifecycle.PER_CLASS) public class TestTagEvent { private TagEventDispatcher failureDispatcher; + private TagEventDispatcher dispatcher; private DummyEventListener dummyEventListener; private Tag tag; @@ -53,6 +58,183 @@ void init() { EventBus eventBus = new EventBus(Arrays.asList(dummyEventListener)); TagDispatcher tagExceptionDispatcher = mockExceptionTagDispatcher(); this.failureDispatcher = new TagEventDispatcher(eventBus, tagExceptionDispatcher); + TagDispatcher tagDispatcher = mockTagDispatcher(); + this.dispatcher = new TagEventDispatcher(eventBus, tagDispatcher); + } + + @Test + void testListTagsEvent() { + dispatcher.listTags("metalake"); + PreEvent preEvent = dummyEventListener.popPreEvent(); + + Assertions.assertEquals("metalake", Objects.requireNonNull(preEvent.identifier()).toString()); + Assertions.assertEquals(ListTagsPreEvent.class, preEvent.getClass()); + Assertions.assertEquals(OperationType.LIST_TAG, preEvent.operationType()); + Assertions.assertEquals(OperationStatus.UNPROCESSED, preEvent.operationStatus()); + } + + @Test + void testListTagsInfo() { + dispatcher.listTagsInfo("metalake"); + PreEvent preEvent = dummyEventListener.popPreEvent(); + + Assertions.assertEquals("metalake", Objects.requireNonNull(preEvent.identifier()).toString()); + Assertions.assertEquals(ListTagsInfoPreEvent.class, preEvent.getClass()); + Assertions.assertEquals(OperationType.LIST_TAGS_INFO, preEvent.operationType()); + Assertions.assertEquals(OperationStatus.UNPROCESSED, preEvent.operationStatus()); + } + + @Test + void testGetTag() { + dispatcher.getTag("metalake", tag.name()); + PreEvent preEvent = dummyEventListener.popPreEvent(); + NameIdentifier identifier = NameIdentifierUtil.ofTag("metalake", tag.name()); + + Assertions.assertEquals(identifier.toString(), preEvent.identifier().toString()); + Assertions.assertEquals(GetTagPreEvent.class, preEvent.getClass()); + Assertions.assertEquals(OperationType.GET_TAG, preEvent.operationType()); + Assertions.assertEquals(OperationStatus.UNPROCESSED, preEvent.operationStatus()); + } + + @Test + void testCreateTag() { + dispatcher.createTag("metalake", tag.name(), tag.comment(), tag.properties()); + PreEvent preEvent = dummyEventListener.popPreEvent(); + NameIdentifier identifier = NameIdentifierUtil.ofTag("metalake", tag.name()); + + Assertions.assertEquals(identifier.toString(), preEvent.identifier().toString()); + Assertions.assertEquals(CreateTagPreEvent.class, preEvent.getClass()); + + TagInfo tagInfo = ((CreateTagPreEvent) preEvent).tagInfo(); + Assertions.assertEquals(tag.name(), tagInfo.name()); + Assertions.assertEquals(tag.properties(), tagInfo.properties()); + Assertions.assertEquals(tag.comment(), tagInfo.comment()); + + Assertions.assertEquals(OperationType.CREATE_TAG, preEvent.operationType()); + Assertions.assertEquals(OperationStatus.UNPROCESSED, preEvent.operationStatus()); + } + + @Test + void testAlterTag() { + TagChange change1 = TagChange.rename("newName"); + TagChange[] changes = {change1}; + + dispatcher.alterTag("metalake", tag.name(), changes); + PreEvent preEvent = dummyEventListener.popPreEvent(); + NameIdentifier identifier = NameIdentifierUtil.ofTag("metalake", tag.name()); + + Assertions.assertEquals(identifier.toString(), preEvent.identifier().toString()); + Assertions.assertEquals(AlterTagPreEvent.class, preEvent.getClass()); + Assertions.assertEquals(OperationType.ALTER_TAG, preEvent.operationType()); + Assertions.assertEquals(OperationStatus.UNPROCESSED, preEvent.operationStatus()); + + TagChange[] eventChanges = ((AlterTagPreEvent) preEvent).changes(); + Assertions.assertArrayEquals(changes, eventChanges); + } + + @Test + void testDeleteTag() { + dispatcher.deleteTag("metalake", tag.name()); + PreEvent preEvent = dummyEventListener.popPreEvent(); + NameIdentifier identifier = NameIdentifierUtil.ofTag("metalake", tag.name()); + + Assertions.assertEquals(identifier.toString(), preEvent.identifier().toString()); + Assertions.assertEquals(DeleteTagPreEvent.class, preEvent.getClass()); + Assertions.assertEquals(OperationType.DELETE_TAG, preEvent.operationType()); + Assertions.assertEquals(OperationStatus.UNPROCESSED, preEvent.operationStatus()); + } + + @Test + void testListMetadataObjectsForTag() { + dispatcher.listMetadataObjectsForTag("metalake", tag.name()); + PreEvent preEvent = dummyEventListener.popPreEvent(); + NameIdentifier identifier = NameIdentifierUtil.ofTag("metalake", tag.name()); + + Assertions.assertEquals(identifier.toString(), preEvent.identifier().toString()); + Assertions.assertEquals(ListMetadataObjectsForTagPreEvent.class, preEvent.getClass()); + Assertions.assertEquals(OperationType.LIST_METADATA_OBJECTS_FOR_TAG, preEvent.operationType()); + Assertions.assertEquals(OperationStatus.UNPROCESSED, preEvent.operationStatus()); + } + + @Test + void testListTagsForMetadataObject() { + MetadataObject metadataObject = + NameIdentifierUtil.toMetadataObject( + NameIdentifierUtil.ofCatalog("metalake", "catalog_for_test"), + Entity.EntityType.CATALOG); + + dispatcher.listTagsForMetadataObject("metalake", metadataObject); + PreEvent preEvent = dummyEventListener.popPreEvent(); + NameIdentifier identifier = MetadataObjectUtil.toEntityIdent("metalake", metadataObject); + + Assertions.assertEquals(identifier.toString(), preEvent.identifier().toString()); + Assertions.assertEquals(ListTagsForMetadataObjectPreEvent.class, preEvent.getClass()); + Assertions.assertEquals(OperationType.LIST_TAGS_FOR_METADATA_OBJECT, preEvent.operationType()); + Assertions.assertEquals(OperationStatus.UNPROCESSED, preEvent.operationStatus()); + } + + @Test + void testListTagsInfoForMetadataObject() { + MetadataObject metadataObject = + NameIdentifierUtil.toMetadataObject( + NameIdentifierUtil.ofCatalog("metalake", "catalog_for_test"), + Entity.EntityType.CATALOG); + dispatcher.listTagsInfoForMetadataObject("metalake", metadataObject); + + PreEvent preEvent = dummyEventListener.popPreEvent(); + NameIdentifier identifier = MetadataObjectUtil.toEntityIdent("metalake", metadataObject); + + Assertions.assertEquals(identifier.toString(), preEvent.identifier().toString()); + Assertions.assertEquals(ListTagsInfoForMetadataObjectPreEvent.class, preEvent.getClass()); + Assertions.assertEquals( + OperationType.LIST_TAGS_INFO_FOR_METADATA_OBJECT, preEvent.operationType()); + Assertions.assertEquals(OperationStatus.UNPROCESSED, preEvent.operationStatus()); + } + + @Test + void testAssociateTagsForMetadataObject() { + MetadataObject metadataObject = + NameIdentifierUtil.toMetadataObject( + NameIdentifierUtil.ofCatalog("metalake", "catalog_for_test"), + Entity.EntityType.CATALOG); + + String[] tagsToAdd = {"tag1", "tag2"}; + String[] tagsToRemove = {"tag3"}; + + dispatcher.associateTagsForMetadataObject("metalake", metadataObject, tagsToAdd, tagsToRemove); + PreEvent preEvent = dummyEventListener.popPreEvent(); + + NameIdentifier identifier = MetadataObjectUtil.toEntityIdent("metalake", metadataObject); + + Assertions.assertEquals(identifier.toString(), preEvent.identifier().toString()); + Assertions.assertEquals(AssociateTagsForMetadataObjectPreEvent.class, preEvent.getClass()); + Assertions.assertArrayEquals( + tagsToAdd, ((AssociateTagsForMetadataObjectPreEvent) preEvent).tagsToAdd()); + Assertions.assertArrayEquals( + tagsToRemove, ((AssociateTagsForMetadataObjectPreEvent) preEvent).tagsToRemove()); + + Assertions.assertEquals( + OperationType.ASSOCIATE_TAGS_FOR_METADATA_OBJECT, preEvent.operationType()); + Assertions.assertEquals(OperationStatus.UNPROCESSED, preEvent.operationStatus()); + } + + @Test + void testGetTagForMetadataObject() { + MetadataObject metadataObject = + NameIdentifierUtil.toMetadataObject( + NameIdentifierUtil.ofCatalog("metalake", "catalog_for_test"), + Entity.EntityType.CATALOG); + + dispatcher.getTagForMetadataObject("metalake", metadataObject, tag.name()); + PreEvent preEvent = dummyEventListener.popPreEvent(); + + NameIdentifier identifier = MetadataObjectUtil.toEntityIdent("metalake", metadataObject); + + Assertions.assertEquals(identifier.toString(), preEvent.identifier().toString()); + Assertions.assertEquals(GetTagForMetadataObjectPreEvent.class, preEvent.getClass()); + Assertions.assertEquals(tag.name(), ((GetTagForMetadataObjectPreEvent) preEvent).tagName()); + Assertions.assertEquals(OperationType.GET_TAG_FOR_METADATA_OBJECT, preEvent.operationType()); + Assertions.assertEquals(OperationStatus.UNPROCESSED, preEvent.operationStatus()); } @Test @@ -241,4 +423,9 @@ private TagDispatcher mockExceptionTagDispatcher() { throw new GravitinoRuntimeException("Exception for all methods"); }); } + + private TagDispatcher mockTagDispatcher() { + TagDispatcher mockDispatcher = mock(TagDispatcher.class); + return mockDispatcher; + } } From 708b61055c196c2d7042b452d41de3f97092024f Mon Sep 17 00:00:00 2001 From: Jerry Shao Date: Mon, 10 Feb 2025 14:22:52 +0800 Subject: [PATCH 13/33] [#6409] fix(client-python): Change to use `GenericFileset` for the return value of fileset catalog (#6410) ### What changes were proposed in this pull request? This PR changes the return value to `GenericFileset` for fileset operation. ### Why are the changes needed? Previously, it returns the plain fileset dto, so that it cannot support some operations like get credentials. Fix: #6409 ### Does this PR introduce _any_ user-facing change? No. ### How was this patch tested? Existing tests. --- clients/client-python/gravitino/client/fileset_catalog.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/clients/client-python/gravitino/client/fileset_catalog.py b/clients/client-python/gravitino/client/fileset_catalog.py index df0ecf579e2..39a095ba9ac 100644 --- a/clients/client-python/gravitino/client/fileset_catalog.py +++ b/clients/client-python/gravitino/client/fileset_catalog.py @@ -178,7 +178,7 @@ def create_fileset( fileset_resp = FilesetResponse.from_json(resp.body, infer_missing=True) fileset_resp.validate() - return fileset_resp.fileset() + return GenericFileset(fileset_resp.fileset(), self.rest_client, full_namespace) def alter_fileset(self, ident: NameIdentifier, *changes) -> Fileset: """Update a fileset metadata in the catalog. @@ -187,7 +187,7 @@ def alter_fileset(self, ident: NameIdentifier, *changes) -> Fileset: ident: A fileset identifier, which should be "schema.fileset" format. changes: The changes to apply to the fileset. - Args: + Raises: IllegalArgumentException If the changes are invalid. NoSuchFilesetException If the fileset does not exist. @@ -212,7 +212,7 @@ def alter_fileset(self, ident: NameIdentifier, *changes) -> Fileset: fileset_resp = FilesetResponse.from_json(resp.body, infer_missing=True) fileset_resp.validate() - return fileset_resp.fileset() + return GenericFileset(fileset_resp.fileset(), self.rest_client, full_namespace) def drop_fileset(self, ident: NameIdentifier) -> bool: """Drop a fileset from the catalog. From 0dc49caee02ab9edf7c9a2f31d4a7998d4f2374d Mon Sep 17 00:00:00 2001 From: Lord of Abyss <103809695+Abyss-lord@users.noreply.github.com> Date: Tue, 11 Feb 2025 06:24:14 +0800 Subject: [PATCH 14/33] [#5932] improve(CLI): Fix the CLI delete the anonymous user (#6359) ### What changes were proposed in this pull request? Fix the CLI delete the anonymous user ### Why are the changes needed? Fix: #5932 ### Does this PR introduce _any_ user-facing change? (Please list the user-facing changes introduced by your change, including 1. Change in user-facing APIs. 2. Addition or removal of property keys.) ### How was this patch tested? local test ```bash gcli user delete -m demo_metalake --user anonymous # Can't delete anonymous user. This will cause unexpected behavior. ``` image --- .../main/java/org/apache/gravitino/cli/ErrorMessages.java | 2 ++ .../java/org/apache/gravitino/cli/commands/DeleteUser.java | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/ErrorMessages.java b/clients/cli/src/main/java/org/apache/gravitino/cli/ErrorMessages.java index ecf1dbff4c7..554f3a8503c 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/ErrorMessages.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/ErrorMessages.java @@ -23,6 +23,8 @@ public class ErrorMessages { public static final String CATALOG_EXISTS = "Catalog already exists."; public static final String COLUMN_EXISTS = "Column already exists."; + public static final String DELETE_ANONYMOUS_USER = + "Can't delete anonymous user. This will cause unexpected behavior."; public static final String FILESET_EXISTS = "Fileset already exists."; public static final String GROUP_EXISTS = "Group already exists."; public static final String METALAKE_EXISTS = "Metalake already exists."; diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/DeleteUser.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/DeleteUser.java index 3774c4501cb..aa53a4d9f66 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/DeleteUser.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/DeleteUser.java @@ -19,6 +19,7 @@ package org.apache.gravitino.cli.commands; +import org.apache.gravitino.auth.AuthConstants; import org.apache.gravitino.cli.AreYouSure; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; @@ -53,6 +54,10 @@ public DeleteUser( public void handle() { boolean deleted = false; + if (AuthConstants.ANONYMOUS_USER.equalsIgnoreCase(user)) { + exitWithError(ErrorMessages.DELETE_ANONYMOUS_USER); + } + if (!AreYouSure.really(force)) { return; } From d88306855196988e6e574b4c9fb8b0f0d89cc6c2 Mon Sep 17 00:00:00 2001 From: Lord of Abyss <103809695+Abyss-lord@users.noreply.github.com> Date: Tue, 11 Feb 2025 08:23:33 +0800 Subject: [PATCH 15/33] [#6419] improve(CLI): Add table command context CLI (#6428) ### What changes were proposed in this pull request? Add table command context CLI. ### Why are the changes needed? Fix: #6419 ### Does this PR introduce _any_ user-facing change? No ### How was this patch tested? local test. --- .../gravitino/cli/GravitinoCommandLine.java | 2 +- .../gravitino/cli/TableCommandHandler.java | 43 ++-- .../gravitino/cli/TestableCommandLine.java | 67 +++--- .../gravitino/cli/commands/CreateTable.java | 11 +- .../gravitino/cli/commands/DeleteTable.java | 21 +- .../gravitino/cli/commands/ListIndexes.java | 15 +- .../cli/commands/ListTableProperties.java | 13 +- .../gravitino/cli/commands/ListTables.java | 11 +- .../cli/commands/RemoveTableProperty.java | 11 +- .../cli/commands/SetTableProperty.java | 11 +- .../gravitino/cli/commands/TableAudit.java | 13 +- .../gravitino/cli/commands/TableCommand.java | 7 + .../gravitino/cli/commands/TableDetails.java | 15 +- .../cli/commands/TableDistribution.java | 15 +- .../cli/commands/TablePartition.java | 17 +- .../cli/commands/TableSortOrder.java | 19 +- .../cli/commands/UpdateTableComment.java | 11 +- .../cli/commands/UpdateTableName.java | 11 +- .../gravitino/cli/TestTableCommands.java | 206 +++++++++--------- 19 files changed, 233 insertions(+), 286 deletions(-) diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/GravitinoCommandLine.java b/clients/cli/src/main/java/org/apache/gravitino/cli/GravitinoCommandLine.java index 1923562e1f4..29094207b55 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/GravitinoCommandLine.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/GravitinoCommandLine.java @@ -118,7 +118,7 @@ private void executeCommand() { } else if (entity.equals(CommandEntities.COLUMN)) { new ColumnCommandHandler(this, line, command, ignore).handle(); } else if (entity.equals(CommandEntities.TABLE)) { - new TableCommandHandler(this, line, command, ignore).handle(); + new TableCommandHandler(this, line, command, context).handle(); } else if (entity.equals(CommandEntities.SCHEMA)) { new SchemaCommandHandler(this, line, command, ignore).handle(); } else if (entity.equals(CommandEntities.CATALOG)) { diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/TableCommandHandler.java b/clients/cli/src/main/java/org/apache/gravitino/cli/TableCommandHandler.java index b6d90ccd0a1..520b655c25b 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/TableCommandHandler.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/TableCommandHandler.java @@ -29,8 +29,7 @@ public class TableCommandHandler extends CommandHandler { private final GravitinoCommandLine gravitinoCommandLine; private final CommandLine line; private final String command; - private final boolean ignore; - private final String url; + private final CommandContext context; private final FullName name; private final String metalake; private final String catalog; @@ -43,16 +42,19 @@ public class TableCommandHandler extends CommandHandler { * @param gravitinoCommandLine The Gravitino command line instance. * @param line The command line arguments. * @param command The command to execute. - * @param ignore Ignore server version mismatch. + * @param context The command context. */ public TableCommandHandler( - GravitinoCommandLine gravitinoCommandLine, CommandLine line, String command, boolean ignore) { + GravitinoCommandLine gravitinoCommandLine, + CommandLine line, + String command, + CommandContext context) { this.gravitinoCommandLine = gravitinoCommandLine; this.line = line; this.command = command; - this.ignore = ignore; + this.context = context; - this.url = getUrl(line); + this.context.setUrl(getUrl(line)); this.name = new FullName(line); this.metalake = name.getMetalakeName(); this.catalog = name.getCatalogName(); @@ -129,32 +131,32 @@ private boolean executeCommand() { private void handleDetailsCommand() { if (line.hasOption(GravitinoOptions.AUDIT)) { gravitinoCommandLine - .newTableAudit(url, ignore, metalake, catalog, schema, table) + .newTableAudit(context, metalake, catalog, schema, table) .validate() .handle(); } else if (line.hasOption(GravitinoOptions.INDEX)) { gravitinoCommandLine - .newListIndexes(url, ignore, metalake, catalog, schema, table) + .newListIndexes(context, metalake, catalog, schema, table) .validate() .handle(); } else if (line.hasOption(GravitinoOptions.DISTRIBUTION)) { gravitinoCommandLine - .newTableDistribution(url, ignore, metalake, catalog, schema, table) + .newTableDistribution(context, metalake, catalog, schema, table) .validate() .handle(); } else if (line.hasOption(GravitinoOptions.PARTITION)) { gravitinoCommandLine - .newTablePartition(url, ignore, metalake, catalog, schema, table) + .newTablePartition(context, metalake, catalog, schema, table) .validate() .handle(); } else if (line.hasOption(GravitinoOptions.SORTORDER)) { gravitinoCommandLine - .newTableSortOrder(url, ignore, metalake, catalog, schema, table) + .newTableSortOrder(context, metalake, catalog, schema, table) .validate() .handle(); } else { gravitinoCommandLine - .newTableDetails(url, ignore, metalake, catalog, schema, table) + .newTableDetails(context, metalake, catalog, schema, table) .validate() .handle(); } @@ -165,16 +167,15 @@ private void handleCreateCommand() { String columnFile = line.getOptionValue(GravitinoOptions.COLUMNFILE); String comment = line.getOptionValue(GravitinoOptions.COMMENT); gravitinoCommandLine - .newCreateTable(url, ignore, metalake, catalog, schema, table, columnFile, comment) + .newCreateTable(context, metalake, catalog, schema, table, columnFile, comment) .validate() .handle(); } /** Handles the "DELETE" command. */ private void handleDeleteCommand() { - boolean force = line.hasOption(GravitinoOptions.FORCE); gravitinoCommandLine - .newDeleteTable(url, ignore, force, metalake, catalog, schema, table) + .newDeleteTable(context, metalake, catalog, schema, table) .validate() .handle(); } @@ -184,7 +185,7 @@ private void handleSetCommand() { String property = line.getOptionValue(GravitinoOptions.PROPERTY); String value = line.getOptionValue(GravitinoOptions.VALUE); gravitinoCommandLine - .newSetTableProperty(url, ignore, metalake, catalog, schema, table, property, value) + .newSetTableProperty(context, metalake, catalog, schema, table, property, value) .validate() .handle(); } @@ -193,21 +194,21 @@ private void handleSetCommand() { private void handleRemoveCommand() { String property = line.getOptionValue(GravitinoOptions.PROPERTY); gravitinoCommandLine - .newRemoveTableProperty(url, ignore, metalake, catalog, schema, table, property) + .newRemoveTableProperty(context, metalake, catalog, schema, table, property) .validate() .handle(); } /** Handles the "PROPERTIES" command. */ private void handlePropertiesCommand() { gravitinoCommandLine - .newListTableProperties(url, ignore, metalake, catalog, schema, table) + .newListTableProperties(context, metalake, catalog, schema, table) .validate() .handle(); } /** Handles the "LIST" command. */ private void handleListCommand() { - gravitinoCommandLine.newListTables(url, ignore, metalake, catalog, schema).validate().handle(); + gravitinoCommandLine.newListTables(context, metalake, catalog, schema).validate().handle(); } /** Handles the "UPDATE" command. */ @@ -215,14 +216,14 @@ private void handleUpdateCommand() { if (line.hasOption(GravitinoOptions.COMMENT)) { String comment = line.getOptionValue(GravitinoOptions.COMMENT); gravitinoCommandLine - .newUpdateTableComment(url, ignore, metalake, catalog, schema, table, comment) + .newUpdateTableComment(context, metalake, catalog, schema, table, comment) .validate() .handle(); } if (line.hasOption(GravitinoOptions.RENAME)) { String newName = line.getOptionValue(GravitinoOptions.RENAME); gravitinoCommandLine - .newUpdateTableName(url, ignore, metalake, catalog, schema, table, newName) + .newUpdateTableName(context, metalake, catalog, schema, table, newName) .validate() .handle(); } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/TestableCommandLine.java b/clients/cli/src/main/java/org/apache/gravitino/cli/TestableCommandLine.java index 21eec0c8650..9fd2428d404 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/TestableCommandLine.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/TestableCommandLine.java @@ -305,99 +305,89 @@ protected ListSchemaProperties newListSchemaProperties( } protected TableAudit newTableAudit( - String url, boolean ignore, String metalake, String catalog, String schema, String table) { - return new TableAudit(url, ignore, metalake, catalog, schema, table); + CommandContext context, String metalake, String catalog, String schema, String table) { + return new TableAudit(context, metalake, catalog, schema, table); } protected TableDetails newTableDetails( - String url, boolean ignore, String metalake, String catalog, String schema, String table) { - return new TableDetails(url, ignore, metalake, catalog, schema, table); + CommandContext context, String metalake, String catalog, String schema, String table) { + return new TableDetails(context, metalake, catalog, schema, table); } protected ListTables newListTables( - String url, boolean ignore, String metalake, String catalog, String schema) { - return new ListTables(url, ignore, metalake, catalog, schema); + CommandContext context, String metalake, String catalog, String schema) { + return new ListTables(context, metalake, catalog, schema); } protected DeleteTable newDeleteTable( - String url, - boolean ignore, - boolean force, - String metalake, - String catalog, - String schema, - String table) { - return new DeleteTable(url, ignore, force, metalake, catalog, schema, table); + CommandContext context, String metalake, String catalog, String schema, String table) { + return new DeleteTable(context, metalake, catalog, schema, table); } protected ListIndexes newListIndexes( - String url, boolean ignore, String metalake, String catalog, String schema, String table) { - return new ListIndexes(url, ignore, metalake, catalog, schema, table); + CommandContext context, String metalake, String catalog, String schema, String table) { + return new ListIndexes(context, metalake, catalog, schema, table); } protected TablePartition newTablePartition( - String url, boolean ignore, String metalake, String catalog, String schema, String table) { - return new TablePartition(url, ignore, metalake, catalog, schema, table); + CommandContext context, String metalake, String catalog, String schema, String table) { + return new TablePartition(context, metalake, catalog, schema, table); } protected TableDistribution newTableDistribution( - String url, boolean ignore, String metalake, String catalog, String schema, String table) { - return new TableDistribution(url, ignore, metalake, catalog, schema, table); + CommandContext context, String metalake, String catalog, String schema, String table) { + return new TableDistribution(context, metalake, catalog, schema, table); } protected TableSortOrder newTableSortOrder( - String url, boolean ignore, String metalake, String catalog, String schema, String table) { - return new TableSortOrder(url, ignore, metalake, catalog, schema, table); + CommandContext context, String metalake, String catalog, String schema, String table) { + return new TableSortOrder(context, metalake, catalog, schema, table); } protected UpdateTableComment newUpdateTableComment( - String url, - boolean ignore, + CommandContext context, String metalake, String catalog, String schema, String table, String comment) { - return new UpdateTableComment(url, ignore, metalake, catalog, schema, table, comment); + return new UpdateTableComment(context, metalake, catalog, schema, table, comment); } protected UpdateTableName newUpdateTableName( - String url, - boolean ignore, + CommandContext context, String metalake, String catalog, String schema, String table, String rename) { - return new UpdateTableName(url, ignore, metalake, catalog, schema, table, rename); + return new UpdateTableName(context, metalake, catalog, schema, table, rename); } protected SetTableProperty newSetTableProperty( - String url, - boolean ignore, + CommandContext context, String metalake, String catalog, String schema, String table, String property, String value) { - return new SetTableProperty(url, ignore, metalake, catalog, schema, table, property, value); + return new SetTableProperty(context, metalake, catalog, schema, table, property, value); } protected RemoveTableProperty newRemoveTableProperty( - String url, - boolean ignore, + CommandContext context, String metalake, String catalog, String schema, String table, String property) { - return new RemoveTableProperty(url, ignore, metalake, catalog, schema, table, property); + return new RemoveTableProperty(context, metalake, catalog, schema, table, property); } protected ListTableProperties newListTableProperties( - String url, boolean ignore, String metalake, String catalog, String schema, String table) { - return new ListTableProperties(url, ignore, metalake, catalog, schema, table); + CommandContext context, String metalake, String catalog, String schema, String table) { + return new ListTableProperties(context, metalake, catalog, schema, table); } protected UserDetails newUserDetails(String url, boolean ignore, String metalake, String user) { @@ -869,15 +859,14 @@ protected UpdateColumnDefault newUpdateColumnDefault( } protected CreateTable newCreateTable( - String url, - boolean ignore, + CommandContext context, String metalake, String catalog, String schema, String table, String columnFile, String comment) { - return new CreateTable(url, ignore, metalake, catalog, schema, table, columnFile, comment); + return new CreateTable(context, metalake, catalog, schema, table, columnFile, comment); } protected GrantPrivilegesToRole newGrantPrivilegesToRole( diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/CreateTable.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/CreateTable.java index aa409941e59..9c9ce76c9f5 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/CreateTable.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/CreateTable.java @@ -22,6 +22,7 @@ import java.util.List; import java.util.Map; import org.apache.gravitino.NameIdentifier; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.cli.ReadTableCSV; import org.apache.gravitino.client.GravitinoClient; @@ -42,8 +43,7 @@ public class CreateTable extends Command { /** * Create a new table. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param catalog The name of the catalog. * @param schema The name of the schema. @@ -52,15 +52,14 @@ public class CreateTable extends Command { * @param comment The table's comment. */ public CreateTable( - String url, - boolean ignoreVersions, + CommandContext context, String metalake, String catalog, String schema, String table, String columnFile, String comment) { - super(url, ignoreVersions); + super(context); this.metalake = metalake; this.catalog = catalog; this.schema = schema; @@ -106,7 +105,7 @@ public void handle() { exitWithError(exp.getMessage()); } - System.out.println(table + " created"); + printInformation(table + " created"); } @Override diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/DeleteTable.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/DeleteTable.java index be4e8466204..594c49ba5bc 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/DeleteTable.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/DeleteTable.java @@ -21,6 +21,7 @@ import org.apache.gravitino.NameIdentifier; import org.apache.gravitino.cli.AreYouSure; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchCatalogException; @@ -39,24 +40,16 @@ public class DeleteTable extends Command { /** * Delete a table. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. - * @param force Force operation. + * @param context The command context. * @param metalake The name of the metalake. * @param catalog The name of the catalog. * @param schema The name of the schema. * @param table The name of the table. */ public DeleteTable( - String url, - boolean ignoreVersions, - boolean force, - String metalake, - String catalog, - String schema, - String table) { - super(url, ignoreVersions); - this.force = force; + CommandContext context, String metalake, String catalog, String schema, String table) { + super(context); + this.force = context.force(); this.metalake = metalake; this.catalog = catalog; this.schema = schema; @@ -89,9 +82,9 @@ public void handle() { } if (deleted) { - System.out.println(table + " deleted."); + printInformation(table + " deleted."); } else { - System.out.println(table + " not deleted."); + printInformation(table + " not deleted."); } } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListIndexes.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListIndexes.java index 2d1a900baa8..9996a7d475a 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListIndexes.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListIndexes.java @@ -21,6 +21,7 @@ import java.util.Arrays; import org.apache.gravitino.NameIdentifier; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.rel.indexes.Index; /** Displays the index of a table. */ @@ -32,21 +33,15 @@ public class ListIndexes extends TableCommand { /** * Displays the index of a table. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param catalog The name of the catalog. * @param schema The name of the schema. * @param table The name of the table. */ public ListIndexes( - String url, - boolean ignoreVersions, - String metalake, - String catalog, - String schema, - String table) { - super(url, ignoreVersions, metalake, catalog); + CommandContext context, String metalake, String catalog, String schema, String table) { + super(context, metalake, catalog); this.schema = schema; this.table = table; } @@ -77,6 +72,6 @@ public void handle() { .append(System.lineSeparator())); } - System.out.print(all); + printResults(all.toString()); } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListTableProperties.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListTableProperties.java index 61ebf5652dc..1b9f6fbbbb2 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListTableProperties.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListTableProperties.java @@ -21,6 +21,7 @@ import java.util.Map; import org.apache.gravitino.NameIdentifier; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchCatalogException; @@ -40,21 +41,15 @@ public class ListTableProperties extends ListProperties { /** * List the properties of a table. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param catalog The name of the catalog. * @param schema The name of the schema. * @param table The name of the table. */ public ListTableProperties( - String url, - boolean ignoreVersions, - String metalake, - String catalog, - String schema, - String table) { - super(url, ignoreVersions); + CommandContext context, String metalake, String catalog, String schema, String table) { + super(context); this.metalake = metalake; this.catalog = catalog; this.schema = schema; diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListTables.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListTables.java index 515fb28678c..e1389ed9d1a 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListTables.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListTables.java @@ -24,6 +24,7 @@ import java.util.List; import org.apache.gravitino.NameIdentifier; import org.apache.gravitino.Namespace; +import org.apache.gravitino.cli.CommandContext; /** List the names of all tables in a schema. */ public class ListTables extends TableCommand { @@ -33,15 +34,13 @@ public class ListTables extends TableCommand { /** * List the names of all tables in a schema. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param catalog The name of the catalog. * @param schema The name of the schenma. */ - public ListTables( - String url, boolean ignoreVersions, String metalake, String catalog, String schema) { - super(url, ignoreVersions, metalake, catalog); + public ListTables(CommandContext context, String metalake, String catalog, String schema) { + super(context, metalake, catalog); this.schema = schema; } @@ -66,6 +65,6 @@ public void handle() { ? "No tables exist." : Joiner.on(System.lineSeparator()).join(tableNames); - System.out.println(all); + printResults(all); } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RemoveTableProperty.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RemoveTableProperty.java index af370ce64b7..6197a162054 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RemoveTableProperty.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RemoveTableProperty.java @@ -20,6 +20,7 @@ package org.apache.gravitino.cli.commands; import org.apache.gravitino.NameIdentifier; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchCatalogException; @@ -40,8 +41,7 @@ public class RemoveTableProperty extends Command { /** * Remove a property of a table. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param catalog The name of the catalog. * @param schema The name of the schema. @@ -49,14 +49,13 @@ public class RemoveTableProperty extends Command { * @param property The name of the property. */ public RemoveTableProperty( - String url, - boolean ignoreVersions, + CommandContext context, String metalake, String catalog, String schema, String table, String property) { - super(url, ignoreVersions); + super(context); this.metalake = metalake; this.catalog = catalog; this.schema = schema; @@ -84,7 +83,7 @@ public void handle() { exitWithError(exp.getMessage()); } - System.out.println(property + " property removed."); + printInformation(property + " property removed."); } @Override diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/SetTableProperty.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/SetTableProperty.java index 54ab88f3435..53b121e1d3a 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/SetTableProperty.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/SetTableProperty.java @@ -20,6 +20,7 @@ package org.apache.gravitino.cli.commands; import org.apache.gravitino.NameIdentifier; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchCatalogException; @@ -41,8 +42,7 @@ public class SetTableProperty extends Command { /** * Set a property of a table. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param catalog The name of the catalog. * @param schema The name of the schema. @@ -51,15 +51,14 @@ public class SetTableProperty extends Command { * @param value The value of the property. */ public SetTableProperty( - String url, - boolean ignoreVersions, + CommandContext context, String metalake, String catalog, String schema, String table, String property, String value) { - super(url, ignoreVersions); + super(context); this.metalake = metalake; this.catalog = catalog; this.schema = schema; @@ -88,7 +87,7 @@ public void handle() { exitWithError(exp.getMessage()); } - System.out.println(table + " property set."); + printInformation(table + " property set."); } @Override diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/TableAudit.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/TableAudit.java index 0a89076f657..1e4ef0b91fc 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/TableAudit.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/TableAudit.java @@ -20,6 +20,7 @@ package org.apache.gravitino.cli.commands; import org.apache.gravitino.NameIdentifier; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.rel.Table; /** Displays the audit information of a table. */ @@ -31,21 +32,15 @@ public class TableAudit extends TableCommand { /** * Displays the audit information of a table. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param catalog The name of the catalog. * @param schema The name of the schenma. * @param table The name of the table. */ public TableAudit( - String url, - boolean ignoreVersions, - String metalake, - String catalog, - String schema, - String table) { - super(url, ignoreVersions, metalake, catalog); + CommandContext context, String metalake, String catalog, String schema, String table) { + super(context, metalake, catalog); this.schema = schema; this.table = table; } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/TableCommand.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/TableCommand.java index 8ade3c11a78..471baad1c9e 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/TableCommand.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/TableCommand.java @@ -19,6 +19,7 @@ package org.apache.gravitino.cli.commands; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchCatalogException; @@ -33,6 +34,12 @@ public class TableCommand extends AuditCommand { protected final String metalake; protected final String catalog; + public TableCommand(CommandContext context, String metalake, String catalog) { + super(context); + this.metalake = metalake; + this.catalog = catalog; + } + /** * Common code for all table commands. * diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/TableDetails.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/TableDetails.java index 0f38218f7c8..8ac9fb4fb63 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/TableDetails.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/TableDetails.java @@ -20,6 +20,7 @@ package org.apache.gravitino.cli.commands; import org.apache.gravitino.NameIdentifier; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.rel.Table; /** Displays the details of a table. */ @@ -31,21 +32,15 @@ public class TableDetails extends TableCommand { /** * Displays the details of a table. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param catalog The name of the catalog. * @param schema The name of the schenma. * @param table The name of the table. */ public TableDetails( - String url, - boolean ignoreVersions, - String metalake, - String catalog, - String schema, - String table) { - super(url, ignoreVersions, metalake, catalog); + CommandContext context, String metalake, String catalog, String schema, String table) { + super(context, metalake, catalog); this.schema = schema; this.table = table; } @@ -62,6 +57,6 @@ public void handle() { exitWithError(exp.getMessage()); } - System.out.println(gTable.name() + "," + gTable.comment()); + printInformation(gTable.name() + "," + gTable.comment()); } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/TableDistribution.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/TableDistribution.java index 72a0f3ef3fb..958715ead59 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/TableDistribution.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/TableDistribution.java @@ -20,6 +20,7 @@ package org.apache.gravitino.cli.commands; import org.apache.gravitino.NameIdentifier; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.rel.expressions.distributions.Distribution; /** Displays the details of a table's distirbution. */ @@ -31,21 +32,15 @@ public class TableDistribution extends TableCommand { /** * Displays the details of a table's distirbution. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param catalog The name of the catalog. * @param schema The name of the schenma. * @param table The name of the table. */ public TableDistribution( - String url, - boolean ignoreVersions, - String metalake, - String catalog, - String schema, - String table) { - super(url, ignoreVersions, metalake, catalog); + CommandContext context, String metalake, String catalog, String schema, String table) { + super(context, metalake, catalog); this.schema = schema; this.table = table; } @@ -62,6 +57,6 @@ public void handle() { exitWithError(exp.getMessage()); } - System.out.println(distribution.strategy() + "," + distribution.number()); + printInformation(distribution.strategy() + "," + distribution.number()); } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/TablePartition.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/TablePartition.java index bbf86303d5b..352386383b9 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/TablePartition.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/TablePartition.java @@ -20,6 +20,7 @@ package org.apache.gravitino.cli.commands; import org.apache.gravitino.NameIdentifier; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.rel.expressions.transforms.Transform; import org.apache.gravitino.rel.partitions.Partition; @@ -32,21 +33,15 @@ public class TablePartition extends TableCommand { /** * Displays the details of a table's partition. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param catalog The name of the catalog. * @param schema The name of the schenma. * @param table The name of the table. */ public TablePartition( - String url, - boolean ignoreVersions, - String metalake, - String catalog, - String schema, - String table) { - super(url, ignoreVersions, metalake, catalog); + CommandContext context, String metalake, String catalog, String schema, String table) { + super(context, metalake, catalog); this.schema = schema; this.table = table; } @@ -64,10 +59,10 @@ public void handle() { for (Transform transform : transforms) { Partition[] partitions = transform.assignments(); if (partitions.length == 0) { - System.out.println("None"); + printInformation("None"); } else { for (Partition partition : partitions) { - System.out.println(partition.name() + "," + partition.properties()); + printResults(partition.name() + "," + partition.properties()); } } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/TableSortOrder.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/TableSortOrder.java index 54fc1cca273..2d352b16b3c 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/TableSortOrder.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/TableSortOrder.java @@ -20,6 +20,7 @@ package org.apache.gravitino.cli.commands; import org.apache.gravitino.NameIdentifier; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.rel.expressions.sorts.SortOrder; /** Displays the details of a table's sort order. */ @@ -31,21 +32,15 @@ public class TableSortOrder extends TableCommand { /** * Displays the details of a table's sort order. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param catalog The name of the catalog. * @param schema The name of the schenma. * @param table The name of the table. */ public TableSortOrder( - String url, - boolean ignoreVersions, - String metalake, - String catalog, - String schema, - String table) { - super(url, ignoreVersions, metalake, catalog); + CommandContext context, String metalake, String catalog, String schema, String table) { + super(context, metalake, catalog); this.schema = schema; this.table = table; } @@ -62,8 +57,10 @@ public void handle() { exitWithError(exp.getMessage()); } for (SortOrder sortOrder : sortOrders) { - System.out.printf( - "%s,%s,%s%n", sortOrder.expression(), sortOrder.direction(), sortOrder.nullOrdering()); + String result = + String.format( + "%s,%s,%s", sortOrder.expression(), sortOrder.direction(), sortOrder.nullOrdering()); + printResults(result); } } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateTableComment.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateTableComment.java index c71795a9ec4..8983b40c06e 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateTableComment.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateTableComment.java @@ -20,6 +20,7 @@ package org.apache.gravitino.cli.commands; import org.apache.gravitino.NameIdentifier; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchCatalogException; @@ -40,8 +41,7 @@ public class UpdateTableComment extends Command { /** * Update the comment of a table. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param catalog The name of the catalog. * @param schema The name of the schema. @@ -49,14 +49,13 @@ public class UpdateTableComment extends Command { * @param comment New metalake comment. */ public UpdateTableComment( - String url, - boolean ignoreVersions, + CommandContext context, String metalake, String catalog, String schema, String table, String comment) { - super(url, ignoreVersions); + super(context); this.metalake = metalake; this.catalog = catalog; this.schema = schema; @@ -85,6 +84,6 @@ public void handle() { exitWithError(exp.getMessage()); } - System.out.println(table + " comment changed."); + printInformation(table + " comment changed."); } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateTableName.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateTableName.java index 51a5b68722b..0756e7124fd 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateTableName.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateTableName.java @@ -20,6 +20,7 @@ package org.apache.gravitino.cli.commands; import org.apache.gravitino.NameIdentifier; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchCatalogException; @@ -40,8 +41,7 @@ public class UpdateTableName extends Command { /** * Update the name of a table. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param catalog The name of the catalog. * @param schema The name of the schema. @@ -49,14 +49,13 @@ public class UpdateTableName extends Command { * @param name The new table name. */ public UpdateTableName( - String url, - boolean ignoreVersions, + CommandContext context, String metalake, String catalog, String schema, String table, String name) { - super(url, ignoreVersions); + super(context); this.metalake = metalake; this.catalog = catalog; this.schema = schema; @@ -85,6 +84,6 @@ public void handle() { exitWithError(exp.getMessage()); } - System.out.println(table + " name changed."); + printInformation(table + " name changed."); } } diff --git a/clients/cli/src/test/java/org/apache/gravitino/cli/TestTableCommands.java b/clients/cli/src/test/java/org/apache/gravitino/cli/TestTableCommands.java index f0683320457..77166babd29 100644 --- a/clients/cli/src/test/java/org/apache/gravitino/cli/TestTableCommands.java +++ b/clients/cli/src/test/java/org/apache/gravitino/cli/TestTableCommands.java @@ -21,6 +21,9 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThrows; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; @@ -93,8 +96,7 @@ void testListTablesCommand() { mockCommandLine, mockOptions, CommandEntities.TABLE, CommandActions.LIST)); doReturn(mockList) .when(commandLine) - .newListTables( - GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "catalog", "schema"); + .newListTables(any(CommandContext.class), eq("metalake_demo"), eq("catalog"), eq("schema")); doReturn(mockList).when(mockList).validate(); commandLine.handleCommandLine(); verify(mockList).handle(); @@ -115,7 +117,11 @@ void testTableDetailsCommand() { doReturn(mockDetails) .when(commandLine) .newTableDetails( - GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "catalog", "schema", "users"); + any(CommandContext.class), + eq("metalake_demo"), + eq("catalog"), + eq("schema"), + eq("users")); doReturn(mockDetails).when(mockDetails).validate(); commandLine.handleCommandLine(); verify(mockDetails).handle(); @@ -136,7 +142,11 @@ void testTableIndexCommand() { doReturn(mockIndex) .when(commandLine) .newListIndexes( - GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "catalog", "schema", "users"); + any(CommandContext.class), + eq("metalake_demo"), + eq("catalog"), + eq("schema"), + eq("users")); doReturn(mockIndex).when(mockIndex).validate(); commandLine.handleCommandLine(); verify(mockIndex).handle(); @@ -157,7 +167,11 @@ void testTablePartitionCommand() { doReturn(mockPartition) .when(commandLine) .newTablePartition( - GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "catalog", "schema", "users"); + any(CommandContext.class), + eq("metalake_demo"), + eq("catalog"), + eq("schema"), + eq("users")); doReturn(mockPartition).when(mockPartition).validate(); commandLine.handleCommandLine(); verify(mockPartition).handle(); @@ -178,7 +192,11 @@ void testTableDistributionCommand() { doReturn(mockDistribution) .when(commandLine) .newTableDistribution( - GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "catalog", "schema", "users"); + any(CommandContext.class), + eq("metalake_demo"), + eq("catalog"), + eq("schema"), + eq("users")); doReturn(mockDistribution).when(mockDistribution).validate(); commandLine.handleCommandLine(); verify(mockDistribution).handle(); @@ -201,7 +219,11 @@ void testTableSortOrderCommand() { doReturn(mockSortOrder) .when(commandLine) .newTableSortOrder( - GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "catalog", "schema", "users"); + any(CommandContext.class), + eq("metalake_demo"), + eq("catalog"), + eq("schema"), + eq("users")); doReturn(mockSortOrder).when(mockSortOrder).validate(); commandLine.handleCommandLine(); verify(mockSortOrder).handle(); @@ -222,7 +244,11 @@ void testTableAuditCommand() { doReturn(mockAudit) .when(commandLine) .newTableAudit( - GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "catalog", "schema", "users"); + any(CommandContext.class), + eq("metalake_demo"), + eq("catalog"), + eq("schema"), + eq("users")); doReturn(mockAudit).when(mockAudit).validate(); commandLine.handleCommandLine(); verify(mockAudit).handle(); @@ -242,13 +268,11 @@ void testDeleteTableCommand() { doReturn(mockDelete) .when(commandLine) .newDeleteTable( - GravitinoCommandLine.DEFAULT_URL, - false, - false, - "metalake_demo", - "catalog", - "schema", - "users"); + any(CommandContext.class), + eq("metalake_demo"), + eq("catalog"), + eq("schema"), + eq("users")); doReturn(mockDelete).when(mockDelete).validate(); commandLine.handleCommandLine(); verify(mockDelete).handle(); @@ -269,13 +293,11 @@ void testDeleteTableForceCommand() { doReturn(mockDelete) .when(commandLine) .newDeleteTable( - GravitinoCommandLine.DEFAULT_URL, - false, - true, - "metalake_demo", - "catalog", - "schema", - "users"); + any(CommandContext.class), + eq("metalake_demo"), + eq("catalog"), + eq("schema"), + eq("users")); doReturn(mockDelete).when(mockDelete).validate(); commandLine.handleCommandLine(); verify(mockDelete).handle(); @@ -296,7 +318,11 @@ void testListTablePropertiesCommand() { doReturn(mockListProperties) .when(commandLine) .newListTableProperties( - GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "catalog", "schema", "users"); + any(CommandContext.class), + eq("metalake_demo"), + eq("catalog"), + eq("schema"), + eq("users")); doReturn(mockListProperties).when(mockListProperties).validate(); commandLine.handleCommandLine(); verify(mockListProperties).handle(); @@ -321,14 +347,13 @@ void testSetTablePropertyCommand() { doReturn(mockSetProperties) .when(commandLine) .newSetTableProperty( - GravitinoCommandLine.DEFAULT_URL, - false, - "metalake_demo", - "catalog", - "schema", - "user", - "property", - "value"); + any(CommandContext.class), + eq("metalake_demo"), + eq("catalog"), + eq("schema"), + eq("user"), + eq("property"), + eq("value")); doReturn(mockSetProperties).when(mockSetProperties).validate(); commandLine.handleCommandLine(); verify(mockSetProperties).handle(); @@ -337,18 +362,12 @@ void testSetTablePropertyCommand() { @Test void testSetTablePropertyCommandWithoutPropertyAndValue() { Main.useExit = false; + CommandContext mockContext = mock(CommandContext.class); + when(mockContext.url()).thenReturn(GravitinoCommandLine.DEFAULT_URL); SetTableProperty spySetProperty = spy( new SetTableProperty( - GravitinoCommandLine.DEFAULT_URL, - false, - "metalake_demo", - "catalog", - "schema", - "table", - null, - null)); - + mockContext, "metalake_demo", "catalog", "schema", "table", null, null)); assertThrows(RuntimeException.class, spySetProperty::validate); verify(spySetProperty, never()).handle(); String output = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); @@ -358,17 +377,12 @@ void testSetTablePropertyCommandWithoutPropertyAndValue() { @Test void testSetTablePropertyCommandWithoutProperty() { Main.useExit = false; + CommandContext mockContext = mock(CommandContext.class); + when(mockContext.url()).thenReturn(GravitinoCommandLine.DEFAULT_URL); SetTableProperty spySetProperty = spy( new SetTableProperty( - GravitinoCommandLine.DEFAULT_URL, - false, - "metalake_demo", - "catalog", - "schema", - "table", - null, - "value")); + mockContext, "metalake_demo", "catalog", "schema", "table", null, "value")); assertThrows(RuntimeException.class, spySetProperty::validate); verify(spySetProperty, never()).handle(); @@ -379,17 +393,12 @@ void testSetTablePropertyCommandWithoutProperty() { @Test void testSetTablePropertyCommandWithoutValue() { Main.useExit = false; + CommandContext mockContext = mock(CommandContext.class); + when(mockContext.url()).thenReturn(GravitinoCommandLine.DEFAULT_URL); SetTableProperty spySetProperty = spy( new SetTableProperty( - GravitinoCommandLine.DEFAULT_URL, - false, - "metalake_demo", - "catalog", - "schema", - "table", - "property", - null)); + mockContext, "metalake_demo", "catalog", "schema", "table", "property", null)); assertThrows(RuntimeException.class, spySetProperty::validate); verify(spySetProperty, never()).handle(); @@ -414,13 +423,12 @@ void testRemoveTablePropertyCommand() { doReturn(mockSetProperties) .when(commandLine) .newRemoveTableProperty( - GravitinoCommandLine.DEFAULT_URL, - false, - "metalake_demo", - "catalog", - "schema", - "users", - "property"); + any(CommandContext.class), + eq("metalake_demo"), + eq("catalog"), + eq("schema"), + eq("users"), + eq("property")); doReturn(mockSetProperties).when(mockSetProperties).validate(); commandLine.handleCommandLine(); verify(mockSetProperties).handle(); @@ -429,16 +437,12 @@ void testRemoveTablePropertyCommand() { @Test void testRemoveTablePropertyCommandWithoutProperty() { Main.useExit = false; + CommandContext mockContext = mock(CommandContext.class); + when(mockContext.url()).thenReturn(GravitinoCommandLine.DEFAULT_URL); RemoveTableProperty spyRemoveProperty = spy( new RemoveTableProperty( - GravitinoCommandLine.DEFAULT_URL, - false, - "metalake_demo", - "catalog", - "schema", - "table", - null)); + mockContext, "metalake_demo", "catalog", "schema", "table", null)); assertThrows(RuntimeException.class, spyRemoveProperty::validate); verify(spyRemoveProperty, never()).handle(); @@ -462,13 +466,12 @@ void testUpdateTableCommentsCommand() { doReturn(mockUpdate) .when(commandLine) .newUpdateTableComment( - GravitinoCommandLine.DEFAULT_URL, - false, - "metalake_demo", - "catalog", - "schema", - "users", - "New comment"); + any(CommandContext.class), + eq("metalake_demo"), + eq("catalog"), + eq("schema"), + eq("users"), + eq("New comment")); doReturn(mockUpdate).when(mockUpdate).validate(); commandLine.handleCommandLine(); verify(mockUpdate).handle(); @@ -490,13 +493,12 @@ void testupdateTableNmeCommand() { doReturn(mockUpdate) .when(commandLine) .newUpdateTableName( - GravitinoCommandLine.DEFAULT_URL, - false, - "metalake_demo", - "catalog", - "schema", - "users", - "people"); + any(CommandContext.class), + eq("metalake_demo"), + eq("catalog"), + eq("schema"), + eq("users"), + eq("people")); doReturn(mockUpdate).when(mockUpdate).validate(); commandLine.handleCommandLine(); verify(mockUpdate).handle(); @@ -520,14 +522,13 @@ void testCreateTable() { doReturn(mockCreate) .when(commandLine) .newCreateTable( - GravitinoCommandLine.DEFAULT_URL, - false, - "metalake_demo", - "catalog", - "schema", - "users", - "users.csv", - "comment"); + any(CommandContext.class), + eq("metalake_demo"), + eq("catalog"), + eq("schema"), + eq("users"), + eq("users.csv"), + eq("comment")); doReturn(mockCreate).when(mockCreate).validate(); commandLine.handleCommandLine(); verify(mockCreate).handle(); @@ -536,17 +537,12 @@ void testCreateTable() { @Test void testCreateTableWithoutFile() { Main.useExit = false; + CommandContext mockContext = mock(CommandContext.class); + when(mockContext.url()).thenReturn(GravitinoCommandLine.DEFAULT_URL); CreateTable spyCreate = spy( new CreateTable( - GravitinoCommandLine.DEFAULT_URL, - false, - "metalake_demo", - "catalog", - "schema", - "table", - null, - "comment")); + mockContext, "metalake_demo", "catalog", "schema", "table", null, "comment")); assertThrows(RuntimeException.class, spyCreate::validate); verify(spyCreate, never()).handle(); @@ -569,7 +565,7 @@ void testListTableWithoutCatalog() { assertThrows(RuntimeException.class, commandLine::handleCommandLine); verify(commandLine, never()) - .newListTables(GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", null, null); + .newListTables(any(CommandContext.class), eq("metalake_demo"), isNull(), isNull()); String output = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); assertEquals( output, @@ -597,7 +593,7 @@ void testListTableWithoutSchema() { assertThrows(RuntimeException.class, commandLine::handleCommandLine); verify(commandLine, never()) - .newListTables(GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "catalog", null); + .newListTables(any(CommandContext.class), eq("metalake_demo"), eq("catalog"), isNull()); String output = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); assertEquals( output, @@ -622,7 +618,7 @@ void testDetailTableWithoutCatalog() { assertThrows(RuntimeException.class, commandLine::handleCommandLine); verify(commandLine, never()) .newTableDetails( - GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", null, null, null); + any(CommandContext.class), eq("metalake_demo"), isNull(), isNull(), isNull()); String output = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); assertEquals( output, @@ -651,7 +647,7 @@ void testDetailTableWithoutSchema() { assertThrows(RuntimeException.class, commandLine::handleCommandLine); verify(commandLine, never()) .newTableDetails( - GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "catalog", null, null); + any(CommandContext.class), eq("metalake_demo"), eq("catalog"), isNull(), isNull()); String output = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); assertEquals( output, @@ -680,7 +676,7 @@ void testDetailTableWithoutTable() { assertThrows(RuntimeException.class, commandLine::handleCommandLine); verify(commandLine, never()) .newTableDetails( - GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "catalog", "schema", null); + any(CommandContext.class), eq("metalake_demo"), eq("catalog"), eq("schema"), isNull()); String output = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); assertEquals( output, From c8ef9b8ea883a8a094cfc09f5218c24b155d820d Mon Sep 17 00:00:00 2001 From: Lord of Abyss <103809695+Abyss-lord@users.noreply.github.com> Date: Tue, 11 Feb 2025 08:23:49 +0800 Subject: [PATCH 16/33] [#6415] improve(CLI): Add Fileset command context CLI (#6431) ### What changes were proposed in this pull request? Add Fileset command context CLI ### Why are the changes needed? Fix: #6415 ### Does this PR introduce _any_ user-facing change? No ### How was this patch tested? local test --- .../gravitino/cli/FilesetCommandHandler.java | 36 ++-- .../gravitino/cli/GravitinoCommandLine.java | 2 +- .../gravitino/cli/TestableCommandLine.java | 47 ++---- .../gravitino/cli/commands/CreateFileset.java | 11 +- .../gravitino/cli/commands/DeleteFileset.java | 21 +-- .../cli/commands/FilesetDetails.java | 15 +- .../cli/commands/ListFilesetProperties.java | 13 +- .../gravitino/cli/commands/ListFilesets.java | 11 +- .../cli/commands/RemoveFilesetProperty.java | 11 +- .../cli/commands/SetFilesetProperty.java | 11 +- .../cli/commands/UpdateFilesetComment.java | 11 +- .../cli/commands/UpdateFilesetName.java | 11 +- .../gravitino/cli/TestFilesetCommands.java | 159 +++++++----------- 13 files changed, 147 insertions(+), 212 deletions(-) diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/FilesetCommandHandler.java b/clients/cli/src/main/java/org/apache/gravitino/cli/FilesetCommandHandler.java index dce797294d8..54db3ea6bd9 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/FilesetCommandHandler.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/FilesetCommandHandler.java @@ -31,8 +31,7 @@ public class FilesetCommandHandler extends CommandHandler { private final GravitinoCommandLine gravitinoCommandLine; private final CommandLine line; private final String command; - private final boolean ignore; - private final String url; + private final CommandContext context; private final FullName name; private final String metalake; private final String catalog; @@ -45,16 +44,19 @@ public class FilesetCommandHandler extends CommandHandler { * @param gravitinoCommandLine The Gravitino command line instance. * @param line The command line arguments. * @param command The command to execute. - * @param ignore Ignore server version mismatch. + * @param context The command context. */ public FilesetCommandHandler( - GravitinoCommandLine gravitinoCommandLine, CommandLine line, String command, boolean ignore) { + GravitinoCommandLine gravitinoCommandLine, + CommandLine line, + String command, + CommandContext context) { this.gravitinoCommandLine = gravitinoCommandLine; this.line = line; this.command = command; - this.ignore = ignore; + this.context = context; - this.url = getUrl(line); + this.context.setUrl(getUrl(line)); this.name = new FullName(line); this.metalake = name.getMetalakeName(); this.catalog = name.getCatalogName(); @@ -130,7 +132,7 @@ private boolean executeCommand() { /** Handles the "DETAILS" command. */ private void handleDetailsCommand() { gravitinoCommandLine - .newFilesetDetails(url, ignore, metalake, catalog, schema, fileset) + .newFilesetDetails(context, metalake, catalog, schema, fileset) .validate() .handle(); } @@ -141,16 +143,15 @@ private void handleCreateCommand() { String[] properties = line.getOptionValues(CommandActions.PROPERTIES); Map propertyMap = new Properties().parse(properties); gravitinoCommandLine - .newCreateFileset(url, ignore, metalake, catalog, schema, fileset, comment, propertyMap) + .newCreateFileset(context, metalake, catalog, schema, fileset, comment, propertyMap) .validate() .handle(); } /** Handles the "DELETE" command. */ private void handleDeleteCommand() { - boolean force = line.hasOption(GravitinoOptions.FORCE); gravitinoCommandLine - .newDeleteFileset(url, ignore, force, metalake, catalog, schema, fileset) + .newDeleteFileset(context, metalake, catalog, schema, fileset) .validate() .handle(); } @@ -160,7 +161,7 @@ private void handleSetCommand() { String property = line.getOptionValue(GravitinoOptions.PROPERTY); String value = line.getOptionValue(GravitinoOptions.VALUE); gravitinoCommandLine - .newSetFilesetProperty(url, ignore, metalake, catalog, schema, fileset, property, value) + .newSetFilesetProperty(context, metalake, catalog, schema, fileset, property, value) .validate() .handle(); } @@ -169,7 +170,7 @@ private void handleSetCommand() { private void handleRemoveCommand() { String property = line.getOptionValue(GravitinoOptions.PROPERTY); gravitinoCommandLine - .newRemoveFilesetProperty(url, ignore, metalake, catalog, schema, fileset, property) + .newRemoveFilesetProperty(context, metalake, catalog, schema, fileset, property) .validate() .handle(); } @@ -177,17 +178,14 @@ private void handleRemoveCommand() { /** Handles the "PROPERTIES" command. */ private void handlePropertiesCommand() { gravitinoCommandLine - .newListFilesetProperties(url, ignore, metalake, catalog, schema, fileset) + .newListFilesetProperties(context, metalake, catalog, schema, fileset) .validate() .handle(); } /** Handles the "LIST" command. */ private void handleListCommand() { - gravitinoCommandLine - .newListFilesets(url, ignore, metalake, catalog, schema) - .validate() - .handle(); + gravitinoCommandLine.newListFilesets(context, metalake, catalog, schema).validate().handle(); } /** Handles the "UPDATE" command. */ @@ -195,14 +193,14 @@ private void handleUpdateCommand() { if (line.hasOption(GravitinoOptions.COMMENT)) { String comment = line.getOptionValue(GravitinoOptions.COMMENT); gravitinoCommandLine - .newUpdateFilesetComment(url, ignore, metalake, catalog, schema, fileset, comment) + .newUpdateFilesetComment(context, metalake, catalog, schema, fileset, comment) .validate() .handle(); } if (line.hasOption(GravitinoOptions.RENAME)) { String newName = line.getOptionValue(GravitinoOptions.RENAME); gravitinoCommandLine - .newUpdateFilesetName(url, ignore, metalake, catalog, schema, fileset, newName) + .newUpdateFilesetName(context, metalake, catalog, schema, fileset, newName) .validate() .handle(); } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/GravitinoCommandLine.java b/clients/cli/src/main/java/org/apache/gravitino/cli/GravitinoCommandLine.java index 29094207b55..c3404334be2 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/GravitinoCommandLine.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/GravitinoCommandLine.java @@ -128,7 +128,7 @@ private void executeCommand() { } else if (entity.equals(CommandEntities.TOPIC)) { new TopicCommandHandler(this, line, command, ignore).handle(); } else if (entity.equals(CommandEntities.FILESET)) { - new FilesetCommandHandler(this, line, command, ignore).handle(); + new FilesetCommandHandler(this, line, command, context).handle(); } else if (entity.equals(CommandEntities.USER)) { new UserCommandHandler(this, line, command, ignore).handle(); } else if (entity.equals(CommandEntities.GROUP)) { diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/TestableCommandLine.java b/clients/cli/src/main/java/org/apache/gravitino/cli/TestableCommandLine.java index 9fd2428d404..3c6193f9d8a 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/TestableCommandLine.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/TestableCommandLine.java @@ -645,86 +645,75 @@ protected ListTopicProperties newListTopicProperties( } protected FilesetDetails newFilesetDetails( - String url, boolean ignore, String metalake, String catalog, String schema, String fileset) { - return new FilesetDetails(url, ignore, metalake, catalog, schema, fileset); + CommandContext context, String metalake, String catalog, String schema, String fileset) { + return new FilesetDetails(context, metalake, catalog, schema, fileset); } protected ListFilesets newListFilesets( - String url, boolean ignore, String metalake, String catalog, String schema) { - return new ListFilesets(url, ignore, metalake, catalog, schema); + CommandContext context, String metalake, String catalog, String schema) { + return new ListFilesets(context, metalake, catalog, schema); } protected CreateFileset newCreateFileset( - String url, - boolean ignore, + CommandContext context, String metalake, String catalog, String schema, String fileset, String comment, Map propertyMap) { - return new CreateFileset(url, ignore, metalake, catalog, schema, fileset, comment, propertyMap); + return new CreateFileset(context, metalake, catalog, schema, fileset, comment, propertyMap); } protected DeleteFileset newDeleteFileset( - String url, - boolean ignore, - boolean force, - String metalake, - String catalog, - String schema, - String fileset) { - return new DeleteFileset(url, ignore, force, metalake, catalog, schema, fileset); + CommandContext context, String metalake, String catalog, String schema, String fileset) { + return new DeleteFileset(context, metalake, catalog, schema, fileset); } protected UpdateFilesetComment newUpdateFilesetComment( - String url, - boolean ignore, + CommandContext context, String metalake, String catalog, String schema, String fileset, String comment) { - return new UpdateFilesetComment(url, ignore, metalake, catalog, schema, fileset, comment); + return new UpdateFilesetComment(context, metalake, catalog, schema, fileset, comment); } protected UpdateFilesetName newUpdateFilesetName( - String url, - boolean ignore, + CommandContext context, String metalake, String catalog, String schema, String fileset, String rename) { - return new UpdateFilesetName(url, ignore, metalake, catalog, schema, fileset, rename); + return new UpdateFilesetName(context, metalake, catalog, schema, fileset, rename); } protected ListFilesetProperties newListFilesetProperties( - String url, boolean ignore, String metalake, String catalog, String schema, String fileset) { - return new ListFilesetProperties(url, ignore, metalake, catalog, schema, fileset); + CommandContext context, String metalake, String catalog, String schema, String fileset) { + return new ListFilesetProperties(context, metalake, catalog, schema, fileset); } protected SetFilesetProperty newSetFilesetProperty( - String url, - boolean ignore, + CommandContext context, String metalake, String catalog, String schema, String fileset, String property, String value) { - return new SetFilesetProperty(url, ignore, metalake, catalog, schema, fileset, property, value); + return new SetFilesetProperty(context, metalake, catalog, schema, fileset, property, value); } protected RemoveFilesetProperty newRemoveFilesetProperty( - String url, - boolean ignore, + CommandContext context, String metalake, String catalog, String schema, String fileset, String property) { - return new RemoveFilesetProperty(url, ignore, metalake, catalog, schema, fileset, property); + return new RemoveFilesetProperty(context, metalake, catalog, schema, fileset, property); } protected AddColumn newAddColumn( diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/CreateFileset.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/CreateFileset.java index 1abcb5d3cbe..e50e3f91689 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/CreateFileset.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/CreateFileset.java @@ -21,6 +21,7 @@ import java.util.Map; import org.apache.gravitino.NameIdentifier; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.FilesetAlreadyExistsException; @@ -40,8 +41,7 @@ public class CreateFileset extends Command { /** * Create a new fileset. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param catalog The name of the catalog. * @param schema The name of the schema. @@ -50,15 +50,14 @@ public class CreateFileset extends Command { * @param properties The catalog's properties. */ public CreateFileset( - String url, - boolean ignoreVersions, + CommandContext context, String metalake, String catalog, String schema, String fileset, String comment, Map properties) { - super(url, ignoreVersions); + super(context); this.metalake = metalake; this.catalog = catalog; this.schema = schema; @@ -93,6 +92,6 @@ public void handle() { exitWithError(exp.getMessage()); } - System.out.println(fileset + " created"); + printInformation(fileset + " created"); } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/DeleteFileset.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/DeleteFileset.java index 2a818f64b3b..8384e1c4bdb 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/DeleteFileset.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/DeleteFileset.java @@ -21,6 +21,7 @@ import org.apache.gravitino.NameIdentifier; import org.apache.gravitino.cli.AreYouSure; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchCatalogException; @@ -39,24 +40,16 @@ public class DeleteFileset extends Command { /** * Delete a fileset. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. - * @param force Force operation. + * @param context The command context. * @param metalake The name of the metalake. * @param catalog The name of the catalog. * @param schema The name of the schema. * @param fileset The name of the fileset. */ public DeleteFileset( - String url, - boolean ignoreVersions, - boolean force, - String metalake, - String catalog, - String schema, - String fileset) { - super(url, ignoreVersions); - this.force = force; + CommandContext context, String metalake, String catalog, String schema, String fileset) { + super(context); + this.force = context.force(); this.metalake = metalake; this.catalog = catalog; this.schema = schema; @@ -89,9 +82,9 @@ public void handle() { } if (deleted) { - System.out.println(fileset + " deleted."); + printInformation(fileset + " deleted."); } else { - System.out.println(fileset + " not deleted."); + printInformation(fileset + " not deleted."); } } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/FilesetDetails.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/FilesetDetails.java index 3db387e39c7..5654f44a627 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/FilesetDetails.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/FilesetDetails.java @@ -20,6 +20,7 @@ package org.apache.gravitino.cli.commands; import org.apache.gravitino.NameIdentifier; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchCatalogException; @@ -39,21 +40,15 @@ public class FilesetDetails extends Command { /** * Displays the details of a fileset. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param catalog The name of the catalog. * @param schema The name of the schenma. * @param fileset The name of the fileset. */ public FilesetDetails( - String url, - boolean ignoreVersions, - String metalake, - String catalog, - String schema, - String fileset) { - super(url, ignoreVersions); + CommandContext context, String metalake, String catalog, String schema, String fileset) { + super(context); this.metalake = metalake; this.catalog = catalog; this.schema = schema; @@ -83,7 +78,7 @@ public void handle() { if (result != null) { String filesetType = (result.type() == Fileset.Type.MANAGED) ? "managed" : "external"; - System.out.println( + printResults( result.name() + "," + filesetType diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListFilesetProperties.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListFilesetProperties.java index e090718abc3..bdaeaccd1e7 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListFilesetProperties.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListFilesetProperties.java @@ -21,6 +21,7 @@ import java.util.Map; import org.apache.gravitino.NameIdentifier; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchCatalogException; @@ -39,21 +40,15 @@ public class ListFilesetProperties extends ListProperties { /** * List the properties of a catalog. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param catalog The name of the catalog. * @param schema The name of the schema. * @param fileset The name of the fileset. */ public ListFilesetProperties( - String url, - boolean ignoreVersions, - String metalake, - String catalog, - String schema, - String fileset) { - super(url, ignoreVersions); + CommandContext context, String metalake, String catalog, String schema, String fileset) { + super(context); this.metalake = metalake; this.catalog = catalog; this.schema = schema; diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListFilesets.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListFilesets.java index cb46b7953c3..ab5e97a5493 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListFilesets.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListFilesets.java @@ -22,6 +22,7 @@ import com.google.common.base.Joiner; import org.apache.gravitino.NameIdentifier; import org.apache.gravitino.Namespace; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchCatalogException; @@ -38,15 +39,13 @@ public class ListFilesets extends Command { /** * Lists all filesets in a schema. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param catalog The name of the catalog. * @param schema The name of the schema. */ - public ListFilesets( - String url, boolean ignoreVersions, String metalake, String catalog, String schema) { - super(url, ignoreVersions); + public ListFilesets(CommandContext context, String metalake, String catalog, String schema) { + super(context); this.metalake = metalake; this.catalog = catalog; this.schema = schema; @@ -73,6 +72,6 @@ public void handle() { String all = filesets.length == 0 ? "No filesets exist." : Joiner.on(",").join(filesets); - System.out.println(all); + printResults(all); } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RemoveFilesetProperty.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RemoveFilesetProperty.java index c443bf0fdfe..da2bc73f43c 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RemoveFilesetProperty.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RemoveFilesetProperty.java @@ -20,6 +20,7 @@ package org.apache.gravitino.cli.commands; import org.apache.gravitino.NameIdentifier; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchCatalogException; @@ -40,8 +41,7 @@ public class RemoveFilesetProperty extends Command { /** * Remove a property of a fileset. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param catalog The name of the catalog. * @param schema The name of the schema. @@ -49,14 +49,13 @@ public class RemoveFilesetProperty extends Command { * @param property The name of the property. */ public RemoveFilesetProperty( - String url, - boolean ignoreVersions, + CommandContext context, String metalake, String catalog, String schema, String fileset, String property) { - super(url, ignoreVersions); + super(context); this.metalake = metalake; this.catalog = catalog; this.schema = schema; @@ -84,7 +83,7 @@ public void handle() { exitWithError(exp.getMessage()); } - System.out.println(property + " property removed."); + printInformation(property + " property removed."); } @Override diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/SetFilesetProperty.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/SetFilesetProperty.java index afafa3c9dbd..8f837dc7667 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/SetFilesetProperty.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/SetFilesetProperty.java @@ -20,6 +20,7 @@ package org.apache.gravitino.cli.commands; import org.apache.gravitino.NameIdentifier; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchCatalogException; @@ -41,8 +42,7 @@ public class SetFilesetProperty extends Command { /** * Set a property of a schema. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param catalog The name of the catalog. * @param schema The name of the schema. @@ -51,15 +51,14 @@ public class SetFilesetProperty extends Command { * @param value The value of the property. */ public SetFilesetProperty( - String url, - boolean ignoreVersions, + CommandContext context, String metalake, String catalog, String schema, String fileset, String property, String value) { - super(url, ignoreVersions); + super(context); this.metalake = metalake; this.catalog = catalog; this.schema = schema; @@ -88,7 +87,7 @@ public void handle() { exitWithError(exp.getMessage()); } - System.out.println(schema + " property set."); + printInformation(schema + " property set."); } @Override diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateFilesetComment.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateFilesetComment.java index 886c3dc3cdc..b3ba771ad42 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateFilesetComment.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateFilesetComment.java @@ -20,6 +20,7 @@ package org.apache.gravitino.cli.commands; import org.apache.gravitino.NameIdentifier; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchCatalogException; @@ -40,8 +41,7 @@ public class UpdateFilesetComment extends Command { /** * Update the comment of a fileset. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param catalog The name of the catalog. * @param schema The name of the schema. @@ -49,14 +49,13 @@ public class UpdateFilesetComment extends Command { * @param comment New metalake comment. */ public UpdateFilesetComment( - String url, - boolean ignoreVersions, + CommandContext context, String metalake, String catalog, String schema, String fileset, String comment) { - super(url, ignoreVersions); + super(context); this.metalake = metalake; this.catalog = catalog; this.schema = schema; @@ -85,6 +84,6 @@ public void handle() { exitWithError(exp.getMessage()); } - System.out.println(fileset + " comment changed."); + printInformation(fileset + " comment changed."); } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateFilesetName.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateFilesetName.java index a613c1f9d9b..21a192522a9 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateFilesetName.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateFilesetName.java @@ -20,6 +20,7 @@ package org.apache.gravitino.cli.commands; import org.apache.gravitino.NameIdentifier; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchCatalogException; @@ -40,8 +41,7 @@ public class UpdateFilesetName extends Command { /** * Update the name of a fileset. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param catalog The name of the catalog. * @param schema The name of the schema. @@ -49,14 +49,13 @@ public class UpdateFilesetName extends Command { * @param name The new fileset name. */ public UpdateFilesetName( - String url, - boolean ignoreVersions, + CommandContext context, String metalake, String catalog, String schema, String fileset, String name) { - super(url, ignoreVersions); + super(context); this.metalake = metalake; this.catalog = catalog; this.schema = schema; @@ -84,6 +83,6 @@ public void handle() { exitWithError(exp.getMessage()); } - System.out.println(fileset + " name changed."); + printInformation(fileset + " name changed."); } } diff --git a/clients/cli/src/test/java/org/apache/gravitino/cli/TestFilesetCommands.java b/clients/cli/src/test/java/org/apache/gravitino/cli/TestFilesetCommands.java index 3529e60bf77..1b73958c981 100644 --- a/clients/cli/src/test/java/org/apache/gravitino/cli/TestFilesetCommands.java +++ b/clients/cli/src/test/java/org/apache/gravitino/cli/TestFilesetCommands.java @@ -21,6 +21,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThrows; +import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.Mockito.any; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.eq; @@ -91,7 +92,7 @@ void testListFilesetsCommand() { doReturn(mockList) .when(commandLine) .newListFilesets( - GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "catalog", "schema"); + any(CommandContext.class), eq("metalake_demo"), eq("catalog"), eq("schema")); doReturn(mockList).when(mockList).validate(); commandLine.handleCommandLine(); verify(mockList).handle(); @@ -112,12 +113,11 @@ void testFilesetDetailsCommand() { doReturn(mockDetails) .when(commandLine) .newFilesetDetails( - GravitinoCommandLine.DEFAULT_URL, - false, - "metalake_demo", - "catalog", - "schema", - "fileset"); + any(CommandContext.class), + eq("metalake_demo"), + eq("catalog"), + eq("schema"), + eq("fileset")); doReturn(mockDetails).when(mockDetails).validate(); commandLine.handleCommandLine(); verify(mockDetails).handle(); @@ -141,8 +141,7 @@ void testCreateFilesetCommand() { doReturn(mockCreate) .when(commandLine) .newCreateFileset( - eq(GravitinoCommandLine.DEFAULT_URL), - eq(false), + any(CommandContext.class), eq("metalake_demo"), eq("catalog"), eq("schema"), @@ -169,13 +168,11 @@ void testDeleteFilesetCommand() { doReturn(mockDelete) .when(commandLine) .newDeleteFileset( - GravitinoCommandLine.DEFAULT_URL, - false, - false, - "metalake_demo", - "catalog", - "schema", - "fileset"); + any(CommandContext.class), + eq("metalake_demo"), + eq("catalog"), + eq("schema"), + eq("fileset")); doReturn(mockDelete).when(mockDelete).validate(); commandLine.handleCommandLine(); verify(mockDelete).handle(); @@ -197,13 +194,11 @@ void testDeleteFilesetForceCommand() { doReturn(mockDelete) .when(commandLine) .newDeleteFileset( - GravitinoCommandLine.DEFAULT_URL, - false, - true, - "metalake_demo", - "catalog", - "schema", - "fileset"); + any(CommandContext.class), + eq("metalake_demo"), + eq("catalog"), + eq("schema"), + eq("fileset")); doReturn(mockDelete).when(mockDelete).validate(); commandLine.handleCommandLine(); verify(mockDelete).handle(); @@ -227,13 +222,12 @@ void testUpdateFilesetCommentCommand() { doReturn(mockUpdateComment) .when(commandLine) .newUpdateFilesetComment( - GravitinoCommandLine.DEFAULT_URL, - false, - "metalake_demo", - "catalog", - "schema", - "fileset", - "new_comment"); + any(CommandContext.class), + eq("metalake_demo"), + eq("catalog"), + eq("schema"), + eq("fileset"), + eq("new_comment")); doReturn(mockUpdateComment).when(mockUpdateComment).validate(); commandLine.handleCommandLine(); verify(mockUpdateComment).handle(); @@ -257,13 +251,12 @@ void testUpdateFilesetNameCommand() { doReturn(mockUpdateName) .when(commandLine) .newUpdateFilesetName( - GravitinoCommandLine.DEFAULT_URL, - false, - "metalake_demo", - "catalog", - "schema", - "fileset", - "new_name"); + any(CommandContext.class), + eq("metalake_demo"), + eq("catalog"), + eq("schema"), + eq("fileset"), + eq("new_name")); doReturn(mockUpdateName).when(mockUpdateName).validate(); commandLine.handleCommandLine(); verify(mockUpdateName).handle(); @@ -285,12 +278,11 @@ void testListFilesetPropertiesCommand() { doReturn(mockListProperties) .when(commandLine) .newListFilesetProperties( - GravitinoCommandLine.DEFAULT_URL, - false, - "metalake_demo", - "catalog", - "schema", - "fileset"); + any(CommandContext.class), + eq("metalake_demo"), + eq("catalog"), + eq("schema"), + eq("fileset")); doReturn(mockListProperties).when(mockListProperties).validate(); commandLine.handleCommandLine(); verify(mockListProperties).handle(); @@ -316,14 +308,13 @@ void testSetFilesetPropertyCommand() { doReturn(mockSetProperties) .when(commandLine) .newSetFilesetProperty( - GravitinoCommandLine.DEFAULT_URL, - false, - "metalake_demo", - "catalog", - "schema", - "fileset", - "property", - "value"); + any(CommandContext.class), + eq("metalake_demo"), + eq("catalog"), + eq("schema"), + eq("fileset"), + eq("property"), + eq("value")); doReturn(mockSetProperties).when(mockSetProperties).validate(); commandLine.handleCommandLine(); verify(mockSetProperties).handle(); @@ -332,17 +323,12 @@ void testSetFilesetPropertyCommand() { @Test void testSetFilesetPropertyCommandWithoutPropertyAndValue() { Main.useExit = false; + CommandContext mockContext = mock(CommandContext.class); + when(mockContext.url()).thenReturn(GravitinoCommandLine.DEFAULT_URL); SetFilesetProperty spySetProperty = spy( new SetFilesetProperty( - GravitinoCommandLine.DEFAULT_URL, - false, - "metalake_demo", - "catalog", - "schema", - "fileset", - null, - null)); + mockContext, "metalake_demo", "catalog", "schema", "fileset", null, null)); assertThrows(RuntimeException.class, spySetProperty::validate); verify(spySetProperty, never()).handle(); @@ -353,17 +339,12 @@ void testSetFilesetPropertyCommandWithoutPropertyAndValue() { @Test void testSetFilesetPropertyCommandWithoutProperty() { Main.useExit = false; + CommandContext mockContext = mock(CommandContext.class); + when(mockContext.url()).thenReturn(GravitinoCommandLine.DEFAULT_URL); SetFilesetProperty spySetProperty = spy( new SetFilesetProperty( - GravitinoCommandLine.DEFAULT_URL, - false, - "metalake_demo", - "catalog", - "schema", - "fileset", - null, - "value")); + mockContext, "metalake_demo", "catalog", "schema", "fileset", null, "value")); assertThrows(RuntimeException.class, spySetProperty::validate); verify(spySetProperty, never()).handle(); @@ -374,17 +355,12 @@ void testSetFilesetPropertyCommandWithoutProperty() { @Test void testSetFilesetPropertyCommandWithoutValue() { Main.useExit = false; + CommandContext mockContext = mock(CommandContext.class); + when(mockContext.url()).thenReturn(GravitinoCommandLine.DEFAULT_URL); SetFilesetProperty spySetProperty = spy( new SetFilesetProperty( - GravitinoCommandLine.DEFAULT_URL, - false, - "metalake_demo", - "catalog", - "schema", - "fileset", - "property", - null)); + mockContext, "metalake_demo", "catalog", "schema", "fileset", "property", null)); assertThrows(RuntimeException.class, spySetProperty::validate); verify(spySetProperty, never()).handle(); @@ -410,13 +386,12 @@ void testRemoveFilesetPropertyCommand() { doReturn(mockSetProperties) .when(commandLine) .newRemoveFilesetProperty( - GravitinoCommandLine.DEFAULT_URL, - false, - "metalake_demo", - "catalog", - "schema", - "fileset", - "property"); + any(CommandContext.class), + eq("metalake_demo"), + eq("catalog"), + eq("schema"), + eq("fileset"), + eq("property")); doReturn(mockSetProperties).when(mockSetProperties).validate(); commandLine.handleCommandLine(); verify(mockSetProperties).handle(); @@ -425,16 +400,12 @@ void testRemoveFilesetPropertyCommand() { @Test void testRemoveFilesetPropertyCommandWithoutProperty() { Main.useExit = false; + CommandContext mockContext = mock(CommandContext.class); + when(mockContext.url()).thenReturn(GravitinoCommandLine.DEFAULT_URL); RemoveFilesetProperty spyRemoveProperty = spy( new RemoveFilesetProperty( - GravitinoCommandLine.DEFAULT_URL, - false, - "metalake_demo", - "catalog", - "schema", - "fileset", - null)); + mockContext, "metalake_demo", "catalog", "schema", "fileset", null)); assertThrows(RuntimeException.class, spyRemoveProperty::validate); verify(spyRemoveProperty, never()).handle(); @@ -456,7 +427,7 @@ void testListFilesetCommandWithoutCatalog() { assertThrows(RuntimeException.class, commandLine::handleCommandLine); verify(commandLine, never()) - .newListFilesets(GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", null, null); + .newListFilesets(any(CommandContext.class), eq("metalake_demo"), eq(null), isNull()); String output = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); assertEquals( output, @@ -481,7 +452,7 @@ void testListFilesetCommandWithoutSchema() { assertThrows(RuntimeException.class, commandLine::handleCommandLine); verify(commandLine, never()) - .newListFilesets(GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "catalog", null); + .newListFilesets(any(CommandContext.class), eq("metalake_demo"), eq("catalog"), isNull()); String output = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); assertEquals( output, @@ -506,7 +477,7 @@ void testFilesetDetailCommandWithoutCatalog() { assertThrows(RuntimeException.class, commandLine::handleCommandLine); verify(commandLine, never()) .newFilesetDetails( - GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", null, null, null); + any(CommandContext.class), eq("metalake_demo"), isNull(), isNull(), isNull()); String output = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); assertEquals( output, @@ -535,7 +506,7 @@ void testFilesetDetailCommandWithoutSchema() { assertThrows(RuntimeException.class, commandLine::handleCommandLine); verify(commandLine, never()) .newFilesetDetails( - GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "catalog", null, null); + any(CommandContext.class), eq("metalake_demo"), eq("catalog"), isNull(), isNull()); String output = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); assertEquals( output, @@ -561,7 +532,7 @@ void testFilesetDetailCommandWithoutFileset() { assertThrows(RuntimeException.class, commandLine::handleCommandLine); verify(commandLine, never()) .newFilesetDetails( - GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "catalog", "schema", null); + any(CommandContext.class), eq("metalake_demo"), eq("catalog"), eq("schema"), isNull()); String output = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); assertEquals( output, From c24f1d60e9842ab8f2c744d60b729621cb850b0e Mon Sep 17 00:00:00 2001 From: Lord of Abyss <103809695+Abyss-lord@users.noreply.github.com> Date: Tue, 11 Feb 2025 08:24:49 +0800 Subject: [PATCH 17/33] [#6417] improve(CLI): Add model command context CLI (#6430) ### What changes were proposed in this pull request? Add model command context CLI ### Why are the changes needed? Fix: #6417 ### Does this PR introduce _any_ user-facing change? No ### How was this patch tested? local test --- .../gravitino/cli/GravitinoCommandLine.java | 2 +- .../gravitino/cli/ModelCommandHandler.java | 37 ++++------- .../gravitino/cli/TestableCommandLine.java | 32 ++++----- .../gravitino/cli/commands/DeleteModel.java | 21 ++---- .../gravitino/cli/commands/LinkModel.java | 11 ++-- .../gravitino/cli/commands/ListModel.java | 11 ++-- .../gravitino/cli/commands/ModelAudit.java | 21 +++--- .../gravitino/cli/commands/ModelDetails.java | 15 ++--- .../gravitino/cli/commands/RegisterModel.java | 15 ++--- .../gravitino/cli/TestModelCommands.java | 65 +++++++++---------- 10 files changed, 95 insertions(+), 135 deletions(-) diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/GravitinoCommandLine.java b/clients/cli/src/main/java/org/apache/gravitino/cli/GravitinoCommandLine.java index c3404334be2..3106c3ea504 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/GravitinoCommandLine.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/GravitinoCommandLine.java @@ -138,7 +138,7 @@ private void executeCommand() { } else if (entity.equals(CommandEntities.ROLE)) { new RoleCommandHandler(this, line, command, ignore).handle(); } else if (entity.equals(CommandEntities.MODEL)) { - new ModelCommandHandler(this, line, command, ignore).handle(); + new ModelCommandHandler(this, line, command, context).handle(); } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/ModelCommandHandler.java b/clients/cli/src/main/java/org/apache/gravitino/cli/ModelCommandHandler.java index 9e3c385757f..0a0c8e88857 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/ModelCommandHandler.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/ModelCommandHandler.java @@ -30,8 +30,7 @@ public class ModelCommandHandler extends CommandHandler { private final GravitinoCommandLine gravitinoCommandLine; private final CommandLine line; private final String command; - private final boolean ignore; - private final String url; + private final CommandContext context; private final FullName name; private final String metalake; private final String catalog; @@ -44,16 +43,19 @@ public class ModelCommandHandler extends CommandHandler { * @param gravitinoCommandLine The Gravitino command line instance. * @param line The command line arguments. * @param command The command to execute. - * @param ignore Ignore server version mismatch. + * @param context The command context. */ public ModelCommandHandler( - GravitinoCommandLine gravitinoCommandLine, CommandLine line, String command, boolean ignore) { + GravitinoCommandLine gravitinoCommandLine, + CommandLine line, + String command, + CommandContext context) { this.gravitinoCommandLine = gravitinoCommandLine; this.line = line; this.command = command; - this.ignore = ignore; - this.url = getUrl(line); + this.context = context; + this.context.setUrl(getUrl(line)); this.name = new FullName(line); this.metalake = name.getMetalakeName(); this.catalog = name.getCatalogName(); @@ -119,12 +121,12 @@ private boolean executeCommand() { private void handleDetailsCommand() { if (line.hasOption(GravitinoOptions.AUDIT)) { gravitinoCommandLine - .newModelAudit(url, ignore, metalake, catalog, schema, model) + .newModelAudit(context, metalake, catalog, schema, model) .validate() .handle(); } else { gravitinoCommandLine - .newModelDetails(url, ignore, metalake, catalog, schema, model) + .newModelDetails(context, metalake, catalog, schema, model) .validate() .handle(); } @@ -136,17 +138,15 @@ private void handleCreateCommand() { String[] createProperties = line.getOptionValues(GravitinoOptions.PROPERTIES); Map createPropertyMap = new Properties().parse(createProperties); gravitinoCommandLine - .newCreateModel( - url, ignore, metalake, catalog, schema, model, createComment, createPropertyMap) + .newCreateModel(context, metalake, catalog, schema, model, createComment, createPropertyMap) .validate() .handle(); } /** Handles the "DELETE" command. */ private void handleDeleteCommand() { - boolean force = line.hasOption(GravitinoOptions.FORCE); gravitinoCommandLine - .newDeleteModel(url, ignore, force, metalake, catalog, schema, model) + .newDeleteModel(context, metalake, catalog, schema, model) .validate() .handle(); } @@ -160,22 +160,13 @@ private void handleUpdateCommand() { Map linkPropertityMap = new Properties().parse(linkProperties); gravitinoCommandLine .newLinkModel( - url, - ignore, - metalake, - catalog, - schema, - model, - uri, - alias, - linkComment, - linkPropertityMap) + context, metalake, catalog, schema, model, uri, alias, linkComment, linkPropertityMap) .validate() .handle(); } /** Handles the "LIST" command. */ private void handleListCommand() { - gravitinoCommandLine.newListModel(url, ignore, metalake, catalog, schema).validate().handle(); + gravitinoCommandLine.newListModel(context, metalake, catalog, schema).validate().handle(); } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/TestableCommandLine.java b/clients/cli/src/main/java/org/apache/gravitino/cli/TestableCommandLine.java index 3c6193f9d8a..58dc0ac9e8a 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/TestableCommandLine.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/TestableCommandLine.java @@ -903,46 +903,38 @@ protected CatalogDisable newCatalogDisable( } protected ListModel newListModel( - String url, boolean ignore, String metalake, String catalog, String schema) { - return new ListModel(url, ignore, metalake, catalog, schema); + CommandContext context, String metalake, String catalog, String schema) { + return new ListModel(context, metalake, catalog, schema); } protected ModelAudit newModelAudit( - String url, boolean ignore, String metalake, String catalog, String schema, String model) { - return new ModelAudit(url, ignore, metalake, catalog, schema, model); + CommandContext context, String metalake, String catalog, String schema, String model) { + return new ModelAudit(context, metalake, catalog, schema, model); } protected ModelDetails newModelDetails( - String url, boolean ignore, String metalake, String catalog, String schema, String model) { - return new ModelDetails(url, ignore, metalake, catalog, schema, model); + CommandContext context, String metalake, String catalog, String schema, String model) { + return new ModelDetails(context, metalake, catalog, schema, model); } protected RegisterModel newCreateModel( - String url, - boolean ignore, + CommandContext context, String metalake, String catalog, String schema, String model, String comment, Map properties) { - return new RegisterModel(url, ignore, metalake, catalog, schema, model, comment, properties); + return new RegisterModel(context, metalake, catalog, schema, model, comment, properties); } protected DeleteModel newDeleteModel( - String url, - boolean ignore, - boolean force, - String metalake, - String catalog, - String schema, - String model) { - return new DeleteModel(url, ignore, force, metalake, catalog, schema, model); + CommandContext context, String metalake, String catalog, String schema, String model) { + return new DeleteModel(context, metalake, catalog, schema, model); } protected LinkModel newLinkModel( - String url, - boolean ignore, + CommandContext context, String metalake, String catalog, String schema, @@ -952,6 +944,6 @@ protected LinkModel newLinkModel( String comment, Map properties) { return new LinkModel( - url, ignore, metalake, catalog, schema, model, uri, alias, comment, properties); + context, metalake, catalog, schema, model, uri, alias, comment, properties); } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/DeleteModel.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/DeleteModel.java index f44814ce68c..8dc283ee4d8 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/DeleteModel.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/DeleteModel.java @@ -21,6 +21,7 @@ import org.apache.gravitino.NameIdentifier; import org.apache.gravitino.cli.AreYouSure; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchCatalogException; @@ -40,24 +41,16 @@ public class DeleteModel extends Command { /** * Deletes an existing model. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. - * @param force Force operation. + * @param context The command context. * @param metalake The name of the metalake. * @param catalog The name of the catalog. * @param schema The name of the schema. * @param model The name of the model. */ public DeleteModel( - String url, - boolean ignoreVersions, - boolean force, - String metalake, - String catalog, - String schema, - String model) { - super(url, ignoreVersions); - this.force = force; + CommandContext context, String metalake, String catalog, String schema, String model) { + super(context); + this.force = context.force(); this.metalake = metalake; this.catalog = catalog; this.schema = schema; @@ -88,9 +81,9 @@ public void handle() { } if (deleted) { - System.out.println(model + " deleted."); + printInformation(model + " deleted."); } else { - System.out.println(model + " not deleted."); + printInformation(model + " not deleted."); } } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/LinkModel.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/LinkModel.java index cf34eae882a..94a5f99a5ba 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/LinkModel.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/LinkModel.java @@ -22,6 +22,7 @@ import java.util.Arrays; import java.util.Map; import org.apache.gravitino.NameIdentifier; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.ModelVersionAliasesAlreadyExistException; @@ -44,8 +45,7 @@ public class LinkModel extends Command { /** * Link a new model version to the registered model. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param catalog The name of the catalog. * @param schema The name of schema. @@ -56,8 +56,7 @@ public class LinkModel extends Command { * @param properties The properties of the model version. */ public LinkModel( - String url, - boolean ignoreVersions, + CommandContext context, String metalake, String catalog, String schema, @@ -66,7 +65,7 @@ public LinkModel( String[] alias, String comment, Map properties) { - super(url, ignoreVersions); + super(context); this.metalake = metalake; this.catalog = catalog; this.schema = schema; @@ -100,7 +99,7 @@ public void handle() { exitWithError(err.getMessage()); } - System.out.println( + printResults( "Linked model " + model + " to " + uri + " with aliases " + Arrays.toString(alias)); } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListModel.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListModel.java index 1528e954b1c..fb39e08a938 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListModel.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListModel.java @@ -22,6 +22,7 @@ import java.util.Arrays; import org.apache.gravitino.NameIdentifier; import org.apache.gravitino.Namespace; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchCatalogException; @@ -37,15 +38,13 @@ public class ListModel extends Command { /** * List the names of all models in a schema. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param catalog The name of the catalog. * @param schema The name of schema. */ - public ListModel( - String url, boolean ignoreVersions, String metalake, String catalog, String schema) { - super(url, ignoreVersions); + public ListModel(CommandContext context, String metalake, String catalog, String schema) { + super(context); this.metalake = metalake; this.catalog = catalog; this.schema = schema; @@ -75,6 +74,6 @@ public void handle() { ? "No models exist." : Joiner.on(",").join(Arrays.stream(models).map(model -> model.name()).iterator()); - System.out.println(output); + printResults(output); } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ModelAudit.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ModelAudit.java index 841afd2de9e..b6127937f91 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ModelAudit.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ModelAudit.java @@ -20,6 +20,7 @@ package org.apache.gravitino.cli.commands; import org.apache.gravitino.NameIdentifier; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchCatalogException; @@ -39,21 +40,15 @@ public class ModelAudit extends AuditCommand { /** * Displays the audit information of a model. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param catalog The name of the catalog. * @param schema The name of the schema. * @param model The name of the model. */ public ModelAudit( - String url, - boolean ignoreVersions, - String metalake, - String catalog, - String schema, - String model) { - super(url, ignoreVersions); + CommandContext context, String metalake, String catalog, String schema, String model) { + super(context); this.metalake = metalake; this.catalog = catalog; this.schema = schema; @@ -70,16 +65,16 @@ public void handle() { ModelCatalog modelCatalog = client.loadCatalog(catalog).asModelCatalog(); result = modelCatalog.getModel(name); } catch (NoSuchMetalakeException err) { - System.err.println(ErrorMessages.UNKNOWN_METALAKE); + exitWithError(ErrorMessages.UNKNOWN_METALAKE); return; } catch (NoSuchCatalogException err) { - System.err.println(ErrorMessages.UNKNOWN_CATALOG); + exitWithError(ErrorMessages.UNKNOWN_CATALOG); return; } catch (NoSuchModelException err) { - System.err.println(ErrorMessages.UNKNOWN_MODEL); + exitWithError(ErrorMessages.UNKNOWN_MODEL); return; } catch (Exception exp) { - System.err.println(exp.getMessage()); + exitWithError(exp.getMessage()); return; } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ModelDetails.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ModelDetails.java index 6c3aec08fa5..4c5f1a57d4f 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ModelDetails.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ModelDetails.java @@ -21,6 +21,7 @@ import java.util.Arrays; import org.apache.gravitino.NameIdentifier; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchCatalogException; @@ -40,21 +41,15 @@ public class ModelDetails extends Command { /** * Displays the details of a model. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param catalog The name of the catalog. * @param schema The name of schema. * @param model The name of model. */ public ModelDetails( - String url, - boolean ignoreVersions, - String metalake, - String catalog, - String schema, - String model) { - super(url, ignoreVersions); + CommandContext context, String metalake, String catalog, String schema, String model) { + super(context); this.metalake = metalake; this.catalog = catalog; this.schema = schema; @@ -87,6 +82,6 @@ public void handle() { String basicInfo = String.format("Model name %s, latest version: %s%n", gModel.name(), gModel.latestVersion()); String versionInfo = Arrays.toString(versions); - System.out.printf(basicInfo + "versions: " + versionInfo); + printResults(basicInfo + "versions: " + versionInfo); } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RegisterModel.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RegisterModel.java index 7c8cd120bf4..8d86bd32f79 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RegisterModel.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RegisterModel.java @@ -21,8 +21,8 @@ import java.util.Map; import org.apache.gravitino.NameIdentifier; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; -import org.apache.gravitino.cli.Main; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.ModelAlreadyExistsException; import org.apache.gravitino.exceptions.NoSuchCatalogException; @@ -44,8 +44,7 @@ public class RegisterModel extends Command { /** * Register a model in the catalog * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param catalog The name of the catalog. * @param schema The name of schema. @@ -54,15 +53,14 @@ public class RegisterModel extends Command { * @param properties The properties of the model version. */ public RegisterModel( - String url, - boolean ignoreVersions, + CommandContext context, String metalake, String catalog, String schema, String model, String comment, Map properties) { - super(url, ignoreVersions); + super(context); this.metalake = metalake; this.catalog = catalog; this.schema = schema; @@ -94,10 +92,9 @@ public void handle() { } if (registeredModel != null) { - System.out.println("Successful register " + registeredModel.name() + "."); + printInformation("Successful register " + registeredModel.name() + "."); } else { - System.err.println(ErrorMessages.REGISTER_FAILED + model + "."); - Main.exit(-1); + exitWithError(ErrorMessages.REGISTER_FAILED + model + "."); } } } diff --git a/clients/cli/src/test/java/org/apache/gravitino/cli/TestModelCommands.java b/clients/cli/src/test/java/org/apache/gravitino/cli/TestModelCommands.java index 4f1507cc703..6f5e607c916 100644 --- a/clients/cli/src/test/java/org/apache/gravitino/cli/TestModelCommands.java +++ b/clients/cli/src/test/java/org/apache/gravitino/cli/TestModelCommands.java @@ -21,6 +21,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThrows; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.isNull; @@ -88,8 +89,7 @@ void testListModelCommand() { doReturn(mockList) .when(commandLine) - .newListModel( - GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "catalog", "schema"); + .newListModel(any(CommandContext.class), eq("metalake_demo"), eq("catalog"), eq("schema")); doReturn(mockList).when(mockList).validate(); commandLine.handleCommandLine(); verify(mockList).handle(); @@ -108,7 +108,7 @@ void testListModelCommandWithoutCatalog() { assertThrows(RuntimeException.class, commandLine::handleCommandLine); verify(commandLine, never()) - .newListModel(GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", null, null); + .newListModel(any(CommandContext.class), eq("metalake_demo"), isNull(), isNull()); String output = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); assertEquals( ErrorMessages.MISSING_NAME @@ -132,7 +132,7 @@ void testListModelCommandWithoutSchema() { assertThrows(RuntimeException.class, commandLine::handleCommandLine); verify(commandLine, never()) - .newListModel(GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "catalog", null); + .newListModel(any(CommandContext.class), eq("metalake_demo"), eq("catalog"), isNull()); String output = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); assertEquals( ErrorMessages.MALFORMED_NAME @@ -157,7 +157,11 @@ void testModelDetailsCommand() { doReturn(mockList) .when(commandLine) .newModelDetails( - GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "catalog", "schema", "model"); + any(CommandContext.class), + eq("metalake_demo"), + eq("catalog"), + eq("schema"), + eq("model")); doReturn(mockList).when(mockList).validate(); commandLine.handleCommandLine(); verify(mockList).handle(); @@ -178,7 +182,7 @@ void testModelDetailsCommandWithoutCatalog() { verify(commandLine, never()) .newModelDetails( - GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", null, null, null); + any(CommandContext.class), eq("metalake_demo"), isNull(), isNull(), isNull()); String output = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); assertEquals( ErrorMessages.MISSING_NAME @@ -206,7 +210,7 @@ void testModelDetailsCommandWithoutSchema() { verify(commandLine, never()) .newModelDetails( - GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "catalog", null, null); + any(CommandContext.class), eq("metalake_demo"), eq("catalog"), isNull(), isNull()); String output = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); assertEquals( ErrorMessages.MALFORMED_NAME @@ -232,7 +236,7 @@ void testModelDetailsCommandWithoutModel() { verify(commandLine, never()) .newModelDetails( - GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "catalog", "schema", null); + any(CommandContext.class), eq("metalake_demo"), eq("catalog"), eq("schema"), isNull()); String output = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); assertEquals( ErrorMessages.MALFORMED_NAME @@ -258,7 +262,11 @@ void testModelAuditCommand() { doReturn(mockAudit) .when(commandLine) .newModelAudit( - GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "catalog", "schema", "model"); + any(CommandContext.class), + eq("metalake_demo"), + eq("catalog"), + eq("schema"), + eq("model")); doReturn(mockAudit).when(mockAudit).validate(); commandLine.handleCommandLine(); verify(mockAudit).handle(); @@ -281,8 +289,7 @@ void testRegisterModelCommand() { doReturn(mockCreate) .when(commandLine) .newCreateModel( - eq(GravitinoCommandLine.DEFAULT_URL), - eq(false), + any(CommandContext.class), eq("metalake_demo"), eq("catalog"), eq("schema"), @@ -311,8 +318,7 @@ void testRegisterModelCommandWithComment() { doReturn(mockCreate) .when(commandLine) .newCreateModel( - eq(GravitinoCommandLine.DEFAULT_URL), - eq(false), + any(CommandContext.class), eq("metalake_demo"), eq("catalog"), eq("schema"), @@ -343,8 +349,7 @@ void testRegisterModelCommandWithProperties() { doReturn(mockCreate) .when(commandLine) .newCreateModel( - eq(GravitinoCommandLine.DEFAULT_URL), - eq(false), + any(CommandContext.class), eq("metalake_demo"), eq("catalog"), eq("schema"), @@ -380,8 +385,7 @@ void testRegisterModelCommandWithCommentAndProperties() { doReturn(mockCreate) .when(commandLine) .newCreateModel( - eq(GravitinoCommandLine.DEFAULT_URL), - eq(false), + any(CommandContext.class), eq("metalake_demo"), eq("catalog"), eq("schema"), @@ -412,13 +416,11 @@ void testDeleteModelCommand() { doReturn(mockDelete) .when(commandLine) .newDeleteModel( - GravitinoCommandLine.DEFAULT_URL, - false, - false, - "metalake_demo", - "catalog", - "schema", - "model"); + any(CommandContext.class), + eq("metalake_demo"), + eq("catalog"), + eq("schema"), + eq("model")); doReturn(mockDelete).when(mockDelete).validate(); commandLine.handleCommandLine(); verify(mockDelete).handle(); @@ -442,8 +444,7 @@ void testLinkModelCommandWithoutAlias() { doReturn(linkModelMock) .when(commandLine) .newLinkModel( - eq(GravitinoCommandLine.DEFAULT_URL), - eq(false), + any(CommandContext.class), eq("metalake_demo"), eq("catalog"), eq("schema"), @@ -477,8 +478,7 @@ void testLinkModelCommandWithAlias() { doReturn(linkModelMock) .when(commandLine) .newLinkModel( - eq(GravitinoCommandLine.DEFAULT_URL), - eq(false), + any(CommandContext.class), eq("metalake_demo"), eq("catalog"), eq("schema"), @@ -499,12 +499,12 @@ void testLinkModelCommandWithAlias() { @Test void testLinkModelCommandWithoutURI() { Main.useExit = false; - + CommandContext mockContext = mock(CommandContext.class); + when(mockContext.url()).thenReturn(GravitinoCommandLine.DEFAULT_URL); LinkModel spyLinkModel = spy( new LinkModel( - GravitinoCommandLine.DEFAULT_URL, - false, + mockContext, "metalake_demo", "catalog", "schema", @@ -545,8 +545,7 @@ void testLinkModelCommandWithAllComponent() { doReturn(linkModelMock) .when(commandLine) .newLinkModel( - eq(GravitinoCommandLine.DEFAULT_URL), - eq(false), + any(CommandContext.class), eq("metalake_demo"), eq("catalog"), eq("schema"), From 086278e8f93f563b7bb2c539c7a502cca89b5be2 Mon Sep 17 00:00:00 2001 From: Lord of Abyss <103809695+Abyss-lord@users.noreply.github.com> Date: Tue, 11 Feb 2025 08:26:26 +0800 Subject: [PATCH 18/33] [#6416] improve(CLI): Add schema command context CLI (#6427) ### What changes were proposed in this pull request? Add schema command context CLI ### Why are the changes needed? Fix: #6416 ### Does this PR introduce _any_ user-facing change? No ### How was this patch tested? local test. --- .../gravitino/cli/GravitinoCommandLine.java | 2 +- .../gravitino/cli/SchemaCommandHandler.java | 40 ++++---- .../gravitino/cli/TestableCommandLine.java | 33 ++++--- .../gravitino/cli/commands/CreateSchema.java | 15 +-- .../gravitino/cli/commands/DeleteSchema.java | 21 ++-- .../gravitino/cli/commands/ListSchema.java | 10 +- .../cli/commands/ListSchemaProperties.java | 8 +- .../cli/commands/RemoveSchemaProperty.java | 15 +-- .../gravitino/cli/commands/SchemaAudit.java | 9 +- .../gravitino/cli/commands/SchemaDetails.java | 11 +-- .../cli/commands/SetSchemaProperty.java | 9 +- .../gravitino/cli/TestSchemaCommands.java | 95 ++++++++----------- 12 files changed, 110 insertions(+), 158 deletions(-) diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/GravitinoCommandLine.java b/clients/cli/src/main/java/org/apache/gravitino/cli/GravitinoCommandLine.java index 3106c3ea504..5ab3ed5c93f 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/GravitinoCommandLine.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/GravitinoCommandLine.java @@ -120,7 +120,7 @@ private void executeCommand() { } else if (entity.equals(CommandEntities.TABLE)) { new TableCommandHandler(this, line, command, context).handle(); } else if (entity.equals(CommandEntities.SCHEMA)) { - new SchemaCommandHandler(this, line, command, ignore).handle(); + new SchemaCommandHandler(this, line, command, context).handle(); } else if (entity.equals(CommandEntities.CATALOG)) { new CatalogCommandHandler(this, line, command, ignore).handle(); } else if (entity.equals(CommandEntities.METALAKE)) { diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/SchemaCommandHandler.java b/clients/cli/src/main/java/org/apache/gravitino/cli/SchemaCommandHandler.java index 4a0cf919fb8..4b6a11496ec 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/SchemaCommandHandler.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/SchemaCommandHandler.java @@ -29,8 +29,7 @@ public class SchemaCommandHandler extends CommandHandler { private final GravitinoCommandLine gravitinoCommandLine; private final CommandLine line; private final String command; - private final boolean ignore; - private final String url; + private final CommandContext context; private final FullName name; private final String metalake; private final String catalog; @@ -42,16 +41,19 @@ public class SchemaCommandHandler extends CommandHandler { * @param gravitinoCommandLine The Gravitino command line instance. * @param line The command line arguments. * @param command The command to execute. - * @param ignore Ignore server version mismatch. + * @param context The command context. */ public SchemaCommandHandler( - GravitinoCommandLine gravitinoCommandLine, CommandLine line, String command, boolean ignore) { + GravitinoCommandLine gravitinoCommandLine, + CommandLine line, + String command, + CommandContext context) { this.gravitinoCommandLine = gravitinoCommandLine; this.line = line; this.command = command; - this.ignore = ignore; + this.context = context; - this.url = getUrl(line); + this.context.setUrl(getUrl(line)); this.name = new FullName(line); this.metalake = name.getMetalakeName(); this.catalog = name.getCatalogName(); @@ -120,21 +122,15 @@ private boolean executeCommand() { /** Handles the "LIST" command. */ private void handleListCommand() { - gravitinoCommandLine.newListSchema(url, ignore, metalake, catalog).validate().handle(); + gravitinoCommandLine.newListSchema(context, metalake, catalog).validate().handle(); } /** Handles the "DETAILS" command. */ private void handleDetailsCommand() { if (line.hasOption(GravitinoOptions.AUDIT)) { - gravitinoCommandLine - .newSchemaAudit(url, ignore, metalake, catalog, schema) - .validate() - .handle(); + gravitinoCommandLine.newSchemaAudit(context, metalake, catalog, schema).validate().handle(); } else { - gravitinoCommandLine - .newSchemaDetails(url, ignore, metalake, catalog, schema) - .validate() - .handle(); + gravitinoCommandLine.newSchemaDetails(context, metalake, catalog, schema).validate().handle(); } } @@ -142,18 +138,14 @@ private void handleDetailsCommand() { private void handleCreateCommand() { String comment = line.getOptionValue(GravitinoOptions.COMMENT); gravitinoCommandLine - .newCreateSchema(url, ignore, metalake, catalog, schema, comment) + .newCreateSchema(context, metalake, catalog, schema, comment) .validate() .handle(); } /** Handles the "DELETE" command. */ private void handleDeleteCommand() { - boolean force = line.hasOption(GravitinoOptions.FORCE); - gravitinoCommandLine - .newDeleteSchema(url, ignore, force, metalake, catalog, schema) - .validate() - .handle(); + gravitinoCommandLine.newDeleteSchema(context, metalake, catalog, schema).validate().handle(); } /** Handles the "SET" command. */ @@ -161,7 +153,7 @@ private void handleSetCommand() { String property = line.getOptionValue(GravitinoOptions.PROPERTY); String value = line.getOptionValue(GravitinoOptions.VALUE); gravitinoCommandLine - .newSetSchemaProperty(url, ignore, metalake, catalog, schema, property, value) + .newSetSchemaProperty(context, metalake, catalog, schema, property, value) .validate() .handle(); } @@ -170,7 +162,7 @@ private void handleSetCommand() { private void handleRemoveCommand() { String property = line.getOptionValue(GravitinoOptions.PROPERTY); gravitinoCommandLine - .newRemoveSchemaProperty(url, ignore, metalake, catalog, schema, property) + .newRemoveSchemaProperty(context, metalake, catalog, schema, property) .validate() .handle(); } @@ -178,7 +170,7 @@ private void handleRemoveCommand() { /** Handles the "PROPERTIES" command. */ private void handlePropertiesCommand() { gravitinoCommandLine - .newListSchemaProperties(url, ignore, metalake, catalog, schema) + .newListSchemaProperties(context, metalake, catalog, schema) .validate() .handle(); } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/TestableCommandLine.java b/clients/cli/src/main/java/org/apache/gravitino/cli/TestableCommandLine.java index 58dc0ac9e8a..de2583f698d 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/TestableCommandLine.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/TestableCommandLine.java @@ -260,48 +260,47 @@ protected UpdateCatalogName newUpdateCatalogName( } protected SchemaAudit newSchemaAudit( - String url, boolean ignore, String metalake, String catalog, String schema) { - return new SchemaAudit(url, ignore, metalake, catalog, schema); + CommandContext context, String metalake, String catalog, String schema) { + return new SchemaAudit(context, metalake, catalog, schema); } protected SchemaDetails newSchemaDetails( - String url, boolean ignore, String metalake, String catalog, String schema) { - return new SchemaDetails(url, ignore, metalake, catalog, schema); + CommandContext context, String metalake, String catalog, String schema) { + return new SchemaDetails(context, metalake, catalog, schema); } - protected ListSchema newListSchema(String url, boolean ignore, String metalake, String catalog) { - return new ListSchema(url, ignore, metalake, catalog); + protected ListSchema newListSchema(CommandContext context, String metalake, String catalog) { + return new ListSchema(context, metalake, catalog); } protected CreateSchema newCreateSchema( - String url, boolean ignore, String metalake, String catalog, String schema, String comment) { - return new CreateSchema(url, ignore, metalake, catalog, schema, comment); + CommandContext context, String metalake, String catalog, String schema, String comment) { + return new CreateSchema(context, metalake, catalog, schema, comment); } protected DeleteSchema newDeleteSchema( - String url, boolean ignore, boolean force, String metalake, String catalog, String schema) { - return new DeleteSchema(url, ignore, force, metalake, catalog, schema); + CommandContext context, String metalake, String catalog, String schema) { + return new DeleteSchema(context, metalake, catalog, schema); } protected SetSchemaProperty newSetSchemaProperty( - String url, - boolean ignore, + CommandContext context, String metalake, String catalog, String schema, String property, String value) { - return new SetSchemaProperty(url, ignore, metalake, catalog, schema, property, value); + return new SetSchemaProperty(context, metalake, catalog, schema, property, value); } protected RemoveSchemaProperty newRemoveSchemaProperty( - String url, boolean ignore, String metalake, String catalog, String schema, String property) { - return new RemoveSchemaProperty(url, ignore, metalake, catalog, schema, property); + CommandContext context, String metalake, String catalog, String schema, String property) { + return new RemoveSchemaProperty(context, metalake, catalog, schema, property); } protected ListSchemaProperties newListSchemaProperties( - String url, boolean ignore, String metalake, String catalog, String schema) { - return new ListSchemaProperties(url, ignore, metalake, catalog, schema); + CommandContext context, String metalake, String catalog, String schema) { + return new ListSchemaProperties(context, metalake, catalog, schema); } protected TableAudit newTableAudit( diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/CreateSchema.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/CreateSchema.java index 34243c1e4ed..532130403ec 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/CreateSchema.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/CreateSchema.java @@ -19,6 +19,7 @@ package org.apache.gravitino.cli.commands; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchCatalogException; @@ -34,21 +35,15 @@ public class CreateSchema extends Command { /** * Create a new schema. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param catalog The name of the catalog. * @param schema The name of the schema. * @param comment The schema's comment. */ public CreateSchema( - String url, - boolean ignoreVersions, - String metalake, - String catalog, - String schema, - String comment) { - super(url, ignoreVersions); + CommandContext context, String metalake, String catalog, String schema, String comment) { + super(context); this.metalake = metalake; this.catalog = catalog; this.schema = schema; @@ -71,6 +66,6 @@ public void handle() { exitWithError(exp.getMessage()); } - System.out.println(schema + " created"); + printInformation(schema + " created"); } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/DeleteSchema.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/DeleteSchema.java index 826bdba2fb5..14544196763 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/DeleteSchema.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/DeleteSchema.java @@ -20,6 +20,7 @@ package org.apache.gravitino.cli.commands; import org.apache.gravitino.cli.AreYouSure; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchCatalogException; @@ -36,22 +37,14 @@ public class DeleteSchema extends Command { /** * Delete a schema. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. - * @param force Force operation. + * @param context The command context. * @param metalake The name of the metalake. * @param catalog The name of the catalog. * @param schema The name of the schema. */ - public DeleteSchema( - String url, - boolean ignoreVersions, - boolean force, - String metalake, - String catalog, - String schema) { - super(url, ignoreVersions); - this.force = force; + public DeleteSchema(CommandContext context, String metalake, String catalog, String schema) { + super(context); + this.force = context.force(); this.metalake = metalake; this.catalog = catalog; this.schema = schema; @@ -80,9 +73,9 @@ public void handle() { } if (deleted) { - System.out.println(schema + " deleted."); + printInformation(schema + " deleted."); } else { - System.out.println(schema + " not deleted."); + printInformation(schema + " not deleted."); } } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListSchema.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListSchema.java index 695f44d42d7..bbc881ce06e 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListSchema.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListSchema.java @@ -20,6 +20,7 @@ package org.apache.gravitino.cli.commands; import com.google.common.base.Joiner; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchCatalogException; @@ -34,13 +35,12 @@ public class ListSchema extends Command { /** * Lists all schemas in a catalog. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param catalog The name of the catalog. */ - public ListSchema(String url, boolean ignoreVersions, String metalake, String catalog) { - super(url, ignoreVersions); + public ListSchema(CommandContext context, String metalake, String catalog) { + super(context); this.metalake = metalake; this.catalog = catalog; } @@ -62,6 +62,6 @@ public void handle() { String all = schemas.length == 0 ? "No schemas exist." : Joiner.on(",").join(schemas); - System.out.println(all); + printInformation(all); } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListSchemaProperties.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListSchemaProperties.java index 76a99b8eb65..ff28d4970c2 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListSchemaProperties.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListSchemaProperties.java @@ -21,6 +21,7 @@ import java.util.Map; import org.apache.gravitino.Schema; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchCatalogException; @@ -37,15 +38,14 @@ public class ListSchemaProperties extends ListProperties { /** * List the properties of a schema. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param catalog The name of the catalog. * @param schema The name of the schema. */ public ListSchemaProperties( - String url, boolean ignoreVersions, String metalake, String catalog, String schema) { - super(url, ignoreVersions); + CommandContext context, String metalake, String catalog, String schema) { + super(context); this.metalake = metalake; this.catalog = catalog; this.schema = schema; diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RemoveSchemaProperty.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RemoveSchemaProperty.java index 8fedcb62168..7a7c9dd62dd 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RemoveSchemaProperty.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RemoveSchemaProperty.java @@ -20,6 +20,7 @@ package org.apache.gravitino.cli.commands; import org.apache.gravitino.SchemaChange; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchCatalogException; @@ -37,21 +38,15 @@ public class RemoveSchemaProperty extends Command { /** * Remove a property of a schema. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param catalog The name of the catalog. * @param schema The name of the schema. * @param property The name of the property. */ public RemoveSchemaProperty( - String url, - boolean ignoreVersions, - String metalake, - String catalog, - String schema, - String property) { - super(url, ignoreVersions); + CommandContext context, String metalake, String catalog, String schema, String property) { + super(context); this.metalake = metalake; this.catalog = catalog; this.schema = schema; @@ -75,7 +70,7 @@ public void handle() { exitWithError(exp.getMessage()); } - System.out.println(property + " property removed."); + printInformation(property + " property removed."); } @Override diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/SchemaAudit.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/SchemaAudit.java index ea891964da6..17a0c31e452 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/SchemaAudit.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/SchemaAudit.java @@ -20,6 +20,7 @@ package org.apache.gravitino.cli.commands; import org.apache.gravitino.Schema; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchCatalogException; @@ -36,15 +37,13 @@ public class SchemaAudit extends AuditCommand { /** * Displays the audit information of a schema. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param catalog The name of the catalog. * @param schema The name of the schenma. */ - public SchemaAudit( - String url, boolean ignoreVersions, String metalake, String catalog, String schema) { - super(url, ignoreVersions); + public SchemaAudit(CommandContext context, String metalake, String catalog, String schema) { + super(context); this.metalake = metalake; this.catalog = catalog; this.schema = schema; diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/SchemaDetails.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/SchemaDetails.java index 7369c0d1b41..b9c530aea5e 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/SchemaDetails.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/SchemaDetails.java @@ -20,6 +20,7 @@ package org.apache.gravitino.cli.commands; import org.apache.gravitino.Schema; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchCatalogException; @@ -36,15 +37,13 @@ public class SchemaDetails extends Command { /** * Displays the details of a schema. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param catalog The name of the catalog. * @param schema The name of the schenma. */ - public SchemaDetails( - String url, boolean ignoreVersions, String metalake, String catalog, String schema) { - super(url, ignoreVersions); + public SchemaDetails(CommandContext context, String metalake, String catalog, String schema) { + super(context); this.metalake = metalake; this.catalog = catalog; this.schema = schema; @@ -69,7 +68,7 @@ public void handle() { } if (result != null) { - System.out.println(result.name() + "," + result.comment()); + printInformation(result.name() + "," + result.comment()); } } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/SetSchemaProperty.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/SetSchemaProperty.java index bd9851ba8cb..854befc7477 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/SetSchemaProperty.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/SetSchemaProperty.java @@ -20,6 +20,7 @@ package org.apache.gravitino.cli.commands; import org.apache.gravitino.SchemaChange; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchCatalogException; @@ -38,8 +39,7 @@ public class SetSchemaProperty extends Command { /** * Set a property of a schema. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param catalog The name of the catalog. * @param schema The name of the schema. @@ -47,14 +47,13 @@ public class SetSchemaProperty extends Command { * @param value The value of the property. */ public SetSchemaProperty( - String url, - boolean ignoreVersions, + CommandContext context, String metalake, String catalog, String schema, String property, String value) { - super(url, ignoreVersions); + super(context); this.metalake = metalake; this.catalog = catalog; this.schema = schema; diff --git a/clients/cli/src/test/java/org/apache/gravitino/cli/TestSchemaCommands.java b/clients/cli/src/test/java/org/apache/gravitino/cli/TestSchemaCommands.java index 6b8770d8edf..12b3d72ba1f 100644 --- a/clients/cli/src/test/java/org/apache/gravitino/cli/TestSchemaCommands.java +++ b/clients/cli/src/test/java/org/apache/gravitino/cli/TestSchemaCommands.java @@ -22,6 +22,8 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; @@ -87,7 +89,7 @@ void testListSchemasCommand() { mockCommandLine, mockOptions, CommandEntities.SCHEMA, CommandActions.LIST)); doReturn(mockList) .when(commandLine) - .newListSchema(GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "catalog"); + .newListSchema(any(CommandContext.class), eq("metalake_demo"), eq("catalog")); doReturn(mockList).when(mockList).validate(); commandLine.handleCommandLine(); verify(mockList).handle(); @@ -108,7 +110,7 @@ void testSchemaDetailsCommand() { doReturn(mockDetails) .when(commandLine) .newSchemaDetails( - GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "catalog", "schema"); + any(CommandContext.class), eq("metalake_demo"), eq("catalog"), eq("schema")); doReturn(mockDetails).when(mockDetails).validate(); commandLine.handleCommandLine(); verify(mockDetails).handle(); @@ -129,7 +131,7 @@ void testSchemaAuditCommand() { doReturn(mockAudit) .when(commandLine) .newSchemaAudit( - GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "catalog", "schema"); + any(CommandContext.class), eq("metalake_demo"), eq("catalog"), eq("schema")); doReturn(mockAudit).when(mockAudit).validate(); commandLine.handleCommandLine(); verify(mockAudit).handle(); @@ -152,12 +154,11 @@ void testCreateSchemaCommand() { doReturn(mockCreate) .when(commandLine) .newCreateSchema( - GravitinoCommandLine.DEFAULT_URL, - false, - "metalake_demo", - "catalog", - "schema", - "comment"); + any(CommandContext.class), + eq("metalake_demo"), + eq("catalog"), + eq("schema"), + eq("comment")); doReturn(mockCreate).when(mockCreate).validate(); commandLine.handleCommandLine(); verify(mockCreate).handle(); @@ -177,7 +178,7 @@ void testDeleteSchemaCommand() { doReturn(mockDelete) .when(commandLine) .newDeleteSchema( - GravitinoCommandLine.DEFAULT_URL, false, false, "metalake_demo", "catalog", "schema"); + any(CommandContext.class), eq("metalake_demo"), eq("catalog"), eq("schema")); doReturn(mockDelete).when(mockDelete).validate(); commandLine.handleCommandLine(); verify(mockDelete).handle(); @@ -198,7 +199,7 @@ void testDeleteSchemaForceCommand() { doReturn(mockDelete) .when(commandLine) .newDeleteSchema( - GravitinoCommandLine.DEFAULT_URL, false, true, "metalake_demo", "catalog", "schema"); + any(CommandContext.class), eq("metalake_demo"), eq("catalog"), eq("schema")); doReturn(mockDelete).when(mockDelete).validate(); commandLine.handleCommandLine(); verify(mockDelete).handle(); @@ -222,13 +223,12 @@ void testSetSchemaPropertyCommand() { doReturn(mockSetProperty) .when(commandLine) .newSetSchemaProperty( - GravitinoCommandLine.DEFAULT_URL, - false, - "metalake_demo", - "catalog", - "schema", - "property", - "value"); + any(CommandContext.class), + eq("metalake_demo"), + eq("catalog"), + eq("schema"), + eq("property"), + eq("value")); doReturn(mockSetProperty).when(mockSetProperty).validate(); commandLine.handleCommandLine(); verify(mockSetProperty).handle(); @@ -237,16 +237,10 @@ void testSetSchemaPropertyCommand() { @Test void testSetSchemaPropertyCommandWithoutPropertyAndValue() { Main.useExit = false; + CommandContext mockContext = mock(CommandContext.class); + when(mockContext.url()).thenReturn(GravitinoCommandLine.DEFAULT_URL); SetSchemaProperty spySetProperty = - spy( - new SetSchemaProperty( - GravitinoCommandLine.DEFAULT_URL, - false, - "metalake_demo", - "catalog", - "schema", - null, - null)); + spy(new SetSchemaProperty(mockContext, "metalake_demo", "catalog", "schema", null, null)); assertThrows(RuntimeException.class, spySetProperty::validate); verify(spySetProperty, never()).handle(); @@ -257,16 +251,12 @@ void testSetSchemaPropertyCommandWithoutPropertyAndValue() { @Test void testSetSchemaPropertyCommandWithoutProperty() { Main.useExit = false; + CommandContext mockContext = mock(CommandContext.class); + when(mockContext.url()).thenReturn(GravitinoCommandLine.DEFAULT_URL); SetSchemaProperty spySetProperty = spy( new SetSchemaProperty( - GravitinoCommandLine.DEFAULT_URL, - false, - "metalake_demo", - "catalog", - "schema", - null, - "value")); + mockContext, "metalake_demo", "catalog", "schema", null, "value")); assertThrows(RuntimeException.class, spySetProperty::validate); verify(spySetProperty, never()).handle(); @@ -277,16 +267,12 @@ void testSetSchemaPropertyCommandWithoutProperty() { @Test void testSetSchemaPropertyCommandWithoutValue() { Main.useExit = false; + CommandContext mockContext = mock(CommandContext.class); + when(mockContext.url()).thenReturn(GravitinoCommandLine.DEFAULT_URL); SetSchemaProperty spySetProperty = spy( new SetSchemaProperty( - GravitinoCommandLine.DEFAULT_URL, - false, - "metalake_demo", - "catalog", - "schema", - "property", - null)); + mockContext, "metalake_demo", "catalog", "schema", "property", null)); assertThrows(RuntimeException.class, spySetProperty::validate); verify(spySetProperty, never()).handle(); @@ -310,12 +296,12 @@ void testRemoveSchemaPropertyCommand() { doReturn(mockRemoveProperty) .when(commandLine) .newRemoveSchemaProperty( - GravitinoCommandLine.DEFAULT_URL, - false, - "metalake_demo", - "catalog", - "schema", - "property"); + any(CommandContext.class), + eq("metalake_demo"), + eq("catalog"), + eq("schema"), + eq("property")); + doReturn(mockRemoveProperty).when(mockRemoveProperty).validate(); commandLine.handleCommandLine(); verify(mockRemoveProperty).handle(); @@ -324,15 +310,10 @@ void testRemoveSchemaPropertyCommand() { @Test void testRemoveSchemaPropertyCommandWithoutProperty() { Main.useExit = false; + CommandContext mockContext = mock(CommandContext.class); + when(mockContext.url()).thenReturn(GravitinoCommandLine.DEFAULT_URL); RemoveSchemaProperty mockRemoveProperty = - spy( - new RemoveSchemaProperty( - GravitinoCommandLine.DEFAULT_URL, - false, - "demo_metalake", - "catalog", - "schema", - null)); + spy(new RemoveSchemaProperty(mockContext, "demo_metalake", "catalog", "schema", null)); assertThrows(RuntimeException.class, mockRemoveProperty::validate); String errOutput = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); @@ -353,7 +334,7 @@ void testListSchemaPropertiesCommand() { doReturn(mockListProperties) .when(commandLine) .newListSchemaProperties( - GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "catalog", "schema"); + any(CommandContext.class), eq("metalake_demo"), eq("catalog"), eq("schema")); doReturn(mockListProperties).when(mockListProperties).validate(); commandLine.handleCommandLine(); verify(mockListProperties).handle(); @@ -374,7 +355,7 @@ void testListSchemaWithoutCatalog() { assertThrows(RuntimeException.class, commandLine::handleCommandLine); verify(commandLine, never()) - .newListSchema(GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", null); + .newListSchema(any(CommandContext.class), eq("metalake_demo"), eq(null)); assertTrue( errContent.toString().contains(ErrorMessages.MISSING_ENTITIES + CommandEntities.CATALOG)); } From 1e85c3d3334f52646ee8b71512fb148743bed52f Mon Sep 17 00:00:00 2001 From: Lord of Abyss <103809695+Abyss-lord@users.noreply.github.com> Date: Tue, 11 Feb 2025 12:40:57 +0800 Subject: [PATCH 19/33] [#6414] improve(CLI): Add catalog command context CLI (#6425) ### What changes were proposed in this pull request? Add catalog command context CLI ### Why are the changes needed? Fix: #6414 ### Does this PR introduce _any_ user-facing change? No ### How was this patch tested? local test. --- .../gravitino/cli/CatalogCommandHandler.java | 50 +++---- .../gravitino/cli/GravitinoCommandLine.java | 2 +- .../gravitino/cli/TestableCommandLine.java | 51 ++++--- .../gravitino/cli/commands/CatalogAudit.java | 8 +- .../cli/commands/CatalogDetails.java | 11 +- .../cli/commands/CatalogDisable.java | 10 +- .../gravitino/cli/commands/CatalogEnable.java | 10 +- .../gravitino/cli/commands/CreateCatalog.java | 11 +- .../gravitino/cli/commands/DeleteCatalog.java | 16 +-- .../cli/commands/ListCatalogProperties.java | 9 +- .../gravitino/cli/commands/ListCatalogs.java | 9 +- .../cli/commands/RemoveCatalogProperty.java | 10 +- .../cli/commands/SetCatalogProperty.java | 15 +-- .../cli/commands/UpdateCatalogComment.java | 10 +- .../cli/commands/UpdateCatalogName.java | 11 +- .../gravitino/cli/TestCatalogCommands.java | 126 +++++++----------- .../gravitino/cli/TestCommandContext.java | 46 +++++++ 17 files changed, 199 insertions(+), 206 deletions(-) create mode 100644 clients/cli/src/test/java/org/apache/gravitino/cli/TestCommandContext.java diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/CatalogCommandHandler.java b/clients/cli/src/main/java/org/apache/gravitino/cli/CatalogCommandHandler.java index 8e238406854..a702856f65d 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/CatalogCommandHandler.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/CatalogCommandHandler.java @@ -33,12 +33,10 @@ public class CatalogCommandHandler extends CommandHandler { private final GravitinoCommandLine gravitinoCommandLine; private final CommandLine line; private final String command; - private final boolean ignore; - private final String url; + private final CommandContext context; private final FullName name; private final String metalake; private String catalog; - private final String outputFormat; /** * Constructs a {@link CatalogCommandHandler} instance. @@ -46,19 +44,21 @@ public class CatalogCommandHandler extends CommandHandler { * @param gravitinoCommandLine The Gravitino command line instance. * @param line The command line arguments. * @param command The command to execute. - * @param ignore Ignore server version mismatch. + * @param context The command context. */ public CatalogCommandHandler( - GravitinoCommandLine gravitinoCommandLine, CommandLine line, String command, boolean ignore) { + GravitinoCommandLine gravitinoCommandLine, + CommandLine line, + String command, + CommandContext context) { this.gravitinoCommandLine = gravitinoCommandLine; this.line = line; this.command = command; - this.ignore = ignore; + this.context = context; - this.url = getUrl(line); + this.context.setUrl(getUrl(line)); this.name = new FullName(line); this.metalake = name.getMetalakeName(); - this.outputFormat = line.getOptionValue(GravitinoOptions.OUTPUT); } /** Handles the command execution logic based on the provided command. */ @@ -126,12 +126,9 @@ private boolean executeCommand() { /** Handles the "DETAILS" command. */ private void handleDetailsCommand() { if (line.hasOption(GravitinoOptions.AUDIT)) { - gravitinoCommandLine.newCatalogAudit(url, ignore, metalake, catalog).validate().handle(); + gravitinoCommandLine.newCatalogAudit(context, metalake, catalog).validate().handle(); } else { - gravitinoCommandLine - .newCatalogDetails(url, ignore, outputFormat, metalake, catalog) - .validate() - .handle(); + gravitinoCommandLine.newCatalogDetails(context, metalake, catalog).validate().handle(); } } @@ -143,18 +140,14 @@ private void handleCreateCommand() { Map propertyMap = new Properties().parse(properties); gravitinoCommandLine - .newCreateCatalog(url, ignore, metalake, catalog, provider, comment, propertyMap) + .newCreateCatalog(context, metalake, catalog, provider, comment, propertyMap) .validate() .handle(); } /** Handles the "DELETE" command. */ private void handleDeleteCommand() { - boolean force = line.hasOption(GravitinoOptions.FORCE); - gravitinoCommandLine - .newDeleteCatalog(url, ignore, force, metalake, catalog) - .validate() - .handle(); + gravitinoCommandLine.newDeleteCatalog(context, metalake, catalog).validate().handle(); } /** Handles the "SET" command. */ @@ -162,7 +155,7 @@ private void handleSetCommand() { String property = line.getOptionValue(GravitinoOptions.PROPERTY); String value = line.getOptionValue(GravitinoOptions.VALUE); gravitinoCommandLine - .newSetCatalogProperty(url, ignore, metalake, catalog, property, value) + .newSetCatalogProperty(context, metalake, catalog, property, value) .validate() .handle(); } @@ -171,17 +164,14 @@ private void handleSetCommand() { private void handleRemoveCommand() { String property = line.getOptionValue(GravitinoOptions.PROPERTY); gravitinoCommandLine - .newRemoveCatalogProperty(url, ignore, metalake, catalog, property) + .newRemoveCatalogProperty(context, metalake, catalog, property) .validate() .handle(); } /** Handles the "PROPERTIES" command. */ private void handlePropertiesCommand() { - gravitinoCommandLine - .newListCatalogProperties(url, ignore, metalake, catalog) - .validate() - .handle(); + gravitinoCommandLine.newListCatalogProperties(context, metalake, catalog).validate().handle(); } /** Handles the "UPDATE" command. */ @@ -193,25 +183,25 @@ private void handleUpdateCommand() { if (line.hasOption(GravitinoOptions.ENABLE)) { boolean enableMetalake = line.hasOption(GravitinoOptions.ALL); gravitinoCommandLine - .newCatalogEnable(url, ignore, metalake, catalog, enableMetalake) + .newCatalogEnable(context, metalake, catalog, enableMetalake) .validate() .handle(); } if (line.hasOption(GravitinoOptions.DISABLE)) { - gravitinoCommandLine.newCatalogDisable(url, ignore, metalake, catalog).validate().handle(); + gravitinoCommandLine.newCatalogDisable(context, metalake, catalog).validate().handle(); } if (line.hasOption(GravitinoOptions.COMMENT)) { String updateComment = line.getOptionValue(GravitinoOptions.COMMENT); gravitinoCommandLine - .newUpdateCatalogComment(url, ignore, metalake, catalog, updateComment) + .newUpdateCatalogComment(context, metalake, catalog, updateComment) .validate() .handle(); } if (line.hasOption(GravitinoOptions.RENAME)) { String newName = line.getOptionValue(GravitinoOptions.RENAME); gravitinoCommandLine - .newUpdateCatalogName(url, ignore, metalake, catalog, newName) + .newUpdateCatalogName(context, metalake, catalog, newName) .validate() .handle(); } @@ -219,6 +209,6 @@ private void handleUpdateCommand() { /** Handles the "LIST" command. */ private void handleListCommand() { - gravitinoCommandLine.newListCatalogs(url, ignore, outputFormat, metalake).validate().handle(); + gravitinoCommandLine.newListCatalogs(context, metalake).validate().handle(); } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/GravitinoCommandLine.java b/clients/cli/src/main/java/org/apache/gravitino/cli/GravitinoCommandLine.java index 5ab3ed5c93f..97fca069a9c 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/GravitinoCommandLine.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/GravitinoCommandLine.java @@ -122,7 +122,7 @@ private void executeCommand() { } else if (entity.equals(CommandEntities.SCHEMA)) { new SchemaCommandHandler(this, line, command, context).handle(); } else if (entity.equals(CommandEntities.CATALOG)) { - new CatalogCommandHandler(this, line, command, ignore).handle(); + new CatalogCommandHandler(this, line, command, context).handle(); } else if (entity.equals(CommandEntities.METALAKE)) { new MetalakeCommandHandler(this, line, command, context).handle(); } else if (entity.equals(CommandEntities.TOPIC)) { diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/TestableCommandLine.java b/clients/cli/src/main/java/org/apache/gravitino/cli/TestableCommandLine.java index de2583f698d..d1c757345a2 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/TestableCommandLine.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/TestableCommandLine.java @@ -203,60 +203,57 @@ protected UpdateMetalakeName newUpdateMetalakeName( return new UpdateMetalakeName(context, metalake, newName); } - protected CatalogAudit newCatalogAudit( - String url, boolean ignore, String metalake, String catalog) { - return new CatalogAudit(url, ignore, metalake, catalog); + protected CatalogAudit newCatalogAudit(CommandContext context, String metalake, String catalog) { + return new CatalogAudit(context, metalake, catalog); } protected CatalogDetails newCatalogDetails( - String url, boolean ignore, String outputFormat, String metalake, String catalog) { - return new CatalogDetails(url, ignore, outputFormat, metalake, catalog); + CommandContext context, String metalake, String catalog) { + return new CatalogDetails(context, metalake, catalog); } - protected ListCatalogs newListCatalogs( - String url, boolean ignore, String outputFormat, String metalake) { - return new ListCatalogs(url, ignore, outputFormat, metalake); + protected ListCatalogs newListCatalogs(CommandContext context, String metalake) { + return new ListCatalogs(context, metalake); } protected CreateCatalog newCreateCatalog( - String url, - boolean ignore, + CommandContext context, String metalake, String catalog, String provider, String comment, Map properties) { - return new CreateCatalog(url, ignore, metalake, catalog, provider, comment, properties); + return new CreateCatalog(context, metalake, catalog, provider, comment, properties); } protected DeleteCatalog newDeleteCatalog( - String url, boolean ignore, boolean force, String metalake, String catalog) { - return new DeleteCatalog(url, ignore, force, metalake, catalog); + CommandContext context, String metalake, String catalog) { + return new DeleteCatalog(context, metalake, catalog); } protected SetCatalogProperty newSetCatalogProperty( - String url, boolean ignore, String metalake, String catalog, String property, String value) { - return new SetCatalogProperty(url, ignore, metalake, catalog, property, value); + CommandContext context, String metalake, String catalog, String property, String value) { + return new SetCatalogProperty(context, metalake, catalog, property, value); } protected RemoveCatalogProperty newRemoveCatalogProperty( - String url, boolean ignore, String metalake, String catalog, String property) { - return new RemoveCatalogProperty(url, ignore, metalake, catalog, property); + CommandContext context, String metalake, String catalog, String property) { + return new RemoveCatalogProperty(context, metalake, catalog, property); } protected ListCatalogProperties newListCatalogProperties( - String url, boolean ignore, String metalake, String catalog) { - return new ListCatalogProperties(url, ignore, metalake, catalog); + CommandContext context, String metalake, String catalog) { + return new ListCatalogProperties(context, metalake, catalog); } protected UpdateCatalogComment newUpdateCatalogComment( - String url, boolean ignore, String metalake, String catalog, String comment) { - return new UpdateCatalogComment(url, ignore, metalake, catalog, comment); + CommandContext context, String metalake, String catalog, String comment) { + return new UpdateCatalogComment(context, metalake, catalog, comment); } protected UpdateCatalogName newUpdateCatalogName( - String url, boolean ignore, String metalake, String catalog, String newName) { - return new UpdateCatalogName(url, ignore, metalake, catalog, newName); + CommandContext context, String metalake, String catalog, String newName) { + return new UpdateCatalogName(context, metalake, catalog, newName); } protected SchemaAudit newSchemaAudit( @@ -892,13 +889,13 @@ protected MetalakeDisable newMetalakeDisable(CommandContext context, String meta } protected CatalogEnable newCatalogEnable( - String url, boolean ignore, String metalake, String catalog, boolean enableMetalake) { - return new CatalogEnable(url, ignore, metalake, catalog, enableMetalake); + CommandContext context, String metalake, String catalog, boolean enableMetalake) { + return new CatalogEnable(context, metalake, catalog, enableMetalake); } protected CatalogDisable newCatalogDisable( - String url, boolean ignore, String metalake, String catalog) { - return new CatalogDisable(url, ignore, metalake, catalog); + CommandContext context, String metalake, String catalog) { + return new CatalogDisable(context, metalake, catalog); } protected ListModel newListModel( diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/CatalogAudit.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/CatalogAudit.java index f1ea8ac7b52..6600e1d4291 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/CatalogAudit.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/CatalogAudit.java @@ -20,6 +20,7 @@ package org.apache.gravitino.cli.commands; import org.apache.gravitino.Catalog; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchCatalogException; @@ -33,13 +34,12 @@ public class CatalogAudit extends AuditCommand { /** * Displays the audit information of a catalog. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param catalog The name of the catalog. */ - public CatalogAudit(String url, boolean ignoreVersions, String metalake, String catalog) { - super(url, ignoreVersions); + public CatalogAudit(CommandContext context, String metalake, String catalog) { + super(context); this.metalake = metalake; this.catalog = catalog; } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/CatalogDetails.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/CatalogDetails.java index a204f560d09..fac504a0083 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/CatalogDetails.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/CatalogDetails.java @@ -20,6 +20,7 @@ package org.apache.gravitino.cli.commands; import org.apache.gravitino.Catalog; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchCatalogException; @@ -33,16 +34,12 @@ public class CatalogDetails extends Command { /** * Displays the name and comment of a catalog. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. - * @param outputFormat The output format. + * @param context The command context. * @param metalake The name of the metalake. * @param catalog The name of the catalog. */ - public CatalogDetails( - String url, boolean ignoreVersions, String outputFormat, String metalake, String catalog) { - - super(url, ignoreVersions, outputFormat); + public CatalogDetails(CommandContext context, String metalake, String catalog) { + super(context); this.metalake = metalake; this.catalog = catalog; } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/CatalogDisable.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/CatalogDisable.java index 620a4291eea..7a9954b1ee0 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/CatalogDisable.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/CatalogDisable.java @@ -18,6 +18,7 @@ */ package org.apache.gravitino.cli.commands; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchCatalogException; @@ -32,13 +33,12 @@ public class CatalogDisable extends Command { /** * Disable catalog * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param catalog The name of the catalog. */ - public CatalogDisable(String url, boolean ignoreVersions, String metalake, String catalog) { - super(url, ignoreVersions); + public CatalogDisable(CommandContext context, String metalake, String catalog) { + super(context); this.metalake = metalake; this.catalog = catalog; } @@ -57,6 +57,6 @@ public void handle() { exitWithError(exp.getMessage()); } - System.out.println(metalake + "." + catalog + " has been disabled."); + printInformation(metalake + "." + catalog + " has been disabled."); } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/CatalogEnable.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/CatalogEnable.java index 8646baee292..8c5ca513540 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/CatalogEnable.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/CatalogEnable.java @@ -18,6 +18,7 @@ */ package org.apache.gravitino.cli.commands; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoAdminClient; import org.apache.gravitino.client.GravitinoClient; @@ -34,15 +35,14 @@ public class CatalogEnable extends Command { /** * Enable catalog * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param catalog The name of the catalog. * @param enableMetalake Whether to enable it's metalake */ public CatalogEnable( - String url, boolean ignoreVersions, String metalake, String catalog, boolean enableMetalake) { - super(url, ignoreVersions); + CommandContext context, String metalake, String catalog, boolean enableMetalake) { + super(context); this.metalake = metalake; this.catalog = catalog; this.enableMetalake = enableMetalake; @@ -69,6 +69,6 @@ public void handle() { exitWithError(exp.getMessage()); } - System.out.println(metalake + "." + catalog + " has been enabled."); + printInformation(metalake + "." + catalog + " has been enabled."); } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/CreateCatalog.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/CreateCatalog.java index 2870dd7103e..af90cda73b6 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/CreateCatalog.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/CreateCatalog.java @@ -20,6 +20,7 @@ package org.apache.gravitino.cli.commands; import java.util.Map; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.cli.Providers; import org.apache.gravitino.client.GravitinoClient; @@ -36,8 +37,7 @@ public class CreateCatalog extends Command { /** * Create a new catalog. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param catalog The name of the catalog. * @param provider The provider/type of catalog. @@ -45,14 +45,13 @@ public class CreateCatalog extends Command { * @param properties The catalog's properties. */ public CreateCatalog( - String url, - boolean ignoreVersions, + CommandContext context, String metalake, String catalog, String provider, String comment, Map properties) { - super(url, ignoreVersions); + super(context); this.metalake = metalake; this.catalog = catalog; this.provider = provider; @@ -79,7 +78,7 @@ public void handle() { exitWithError(exp.getMessage()); } - System.out.println(catalog + " catalog created"); + printInformation(catalog + " catalog created"); } @Override diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/DeleteCatalog.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/DeleteCatalog.java index 7cb9bf7d9c8..60d49772ca4 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/DeleteCatalog.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/DeleteCatalog.java @@ -20,6 +20,7 @@ package org.apache.gravitino.cli.commands; import org.apache.gravitino.cli.AreYouSure; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.CatalogInUseException; @@ -35,16 +36,13 @@ public class DeleteCatalog extends Command { /** * Delete a catalog. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. - * @param force Force operation. + * @param context The command context. * @param metalake The name of the metalake. * @param catalog The name of the catalog. */ - public DeleteCatalog( - String url, boolean ignoreVersions, boolean force, String metalake, String catalog) { - super(url, ignoreVersions); - this.force = force; + public DeleteCatalog(CommandContext context, String metalake, String catalog) { + super(context); + this.force = context.force(); this.metalake = metalake; this.catalog = catalog; } @@ -72,9 +70,9 @@ public void handle() { } if (deleted) { - System.out.println(catalog + " deleted."); + printInformation(catalog + " deleted."); } else { - System.out.println(catalog + " not deleted."); + printInformation(catalog + " not deleted."); } } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListCatalogProperties.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListCatalogProperties.java index f94213eef42..54312b8e437 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListCatalogProperties.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListCatalogProperties.java @@ -21,6 +21,7 @@ import java.util.Map; import org.apache.gravitino.Catalog; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchCatalogException; @@ -35,14 +36,12 @@ public class ListCatalogProperties extends ListProperties { /** * List the properties of a catalog. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param catalog The name of the catalog. */ - public ListCatalogProperties( - String url, boolean ignoreVersions, String metalake, String catalog) { - super(url, ignoreVersions); + public ListCatalogProperties(CommandContext context, String metalake, String catalog) { + super(context); this.metalake = metalake; this.catalog = catalog; } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListCatalogs.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListCatalogs.java index e6aaf811ec9..ad8d171fec6 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListCatalogs.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListCatalogs.java @@ -20,6 +20,7 @@ package org.apache.gravitino.cli.commands; import org.apache.gravitino.Catalog; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchMetalakeException; @@ -32,13 +33,11 @@ public class ListCatalogs extends Command { /** * Lists all catalogs in a metalake. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. - * @param outputFormat The output format. + * @param context The command context. * @param metalake The name of the metalake. */ - public ListCatalogs(String url, boolean ignoreVersions, String outputFormat, String metalake) { - super(url, ignoreVersions, outputFormat); + public ListCatalogs(CommandContext context, String metalake) { + super(context); this.metalake = metalake; } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RemoveCatalogProperty.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RemoveCatalogProperty.java index dc1a76765b1..dd22b583e20 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RemoveCatalogProperty.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RemoveCatalogProperty.java @@ -20,6 +20,7 @@ package org.apache.gravitino.cli.commands; import org.apache.gravitino.CatalogChange; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchCatalogException; @@ -35,15 +36,14 @@ public class RemoveCatalogProperty extends Command { /** * Remove a property of a catalog. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param catalog The name of the catalog. * @param property The name of the property. */ public RemoveCatalogProperty( - String url, boolean ignoreVersions, String metalake, String catalog, String property) { - super(url, ignoreVersions); + CommandContext context, String metalake, String catalog, String property) { + super(context); this.metalake = metalake; this.catalog = catalog; this.property = property; @@ -64,7 +64,7 @@ public void handle() { exitWithError(exp.getMessage()); } - System.out.println(property + " property removed."); + printInformation(property + " property removed."); } @Override diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/SetCatalogProperty.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/SetCatalogProperty.java index 034b1b8e2a3..a255835f432 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/SetCatalogProperty.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/SetCatalogProperty.java @@ -20,6 +20,7 @@ package org.apache.gravitino.cli.commands; import org.apache.gravitino.CatalogChange; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchCatalogException; @@ -36,21 +37,15 @@ public class SetCatalogProperty extends Command { /** * Set a property of a catalog. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param catalog The name of the catalog. * @param property The name of the property. * @param value The value of the property. */ public SetCatalogProperty( - String url, - boolean ignoreVersions, - String metalake, - String catalog, - String property, - String value) { - super(url, ignoreVersions); + CommandContext context, String metalake, String catalog, String property, String value) { + super(context); this.metalake = metalake; this.catalog = catalog; this.property = property; @@ -72,7 +67,7 @@ public void handle() { exitWithError(exp.getMessage()); } - System.out.println(catalog + " property set."); + printInformation(catalog + " property set."); } @Override diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateCatalogComment.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateCatalogComment.java index ed12dbc7caa..b058bf32f5e 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateCatalogComment.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateCatalogComment.java @@ -20,6 +20,7 @@ package org.apache.gravitino.cli.commands; import org.apache.gravitino.CatalogChange; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchCatalogException; @@ -35,15 +36,14 @@ public class UpdateCatalogComment extends Command { /** * Update the comment of a catalog. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param catalog The name of the catalog. * @param comment New metalake comment. */ public UpdateCatalogComment( - String url, boolean ignoreVersions, String metalake, String catalog, String comment) { - super(url, ignoreVersions); + CommandContext context, String metalake, String catalog, String comment) { + super(context); this.metalake = metalake; this.catalog = catalog; this.comment = comment; @@ -64,6 +64,6 @@ public void handle() { exitWithError(exp.getMessage()); } - System.out.println(catalog + " comment changed."); + printInformation(catalog + " comment changed."); } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateCatalogName.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateCatalogName.java index 8d4fcb60b96..ab7a1db4e53 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateCatalogName.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateCatalogName.java @@ -20,6 +20,7 @@ package org.apache.gravitino.cli.commands; import org.apache.gravitino.CatalogChange; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchCatalogException; @@ -35,15 +36,13 @@ public class UpdateCatalogName extends Command { /** * Update the name of a catalog. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param catalog The name of the catalog. * @param name The new catalog name. */ - public UpdateCatalogName( - String url, boolean ignoreVersions, String metalake, String catalog, String name) { - super(url, ignoreVersions); + public UpdateCatalogName(CommandContext context, String metalake, String catalog, String name) { + super(context); this.metalake = metalake; this.catalog = catalog; this.name = name; @@ -64,6 +63,6 @@ public void handle() { exitWithError(exp.getMessage()); } - System.out.println(catalog + " name changed."); + printInformation(catalog + " name changed."); } } diff --git a/clients/cli/src/test/java/org/apache/gravitino/cli/TestCatalogCommands.java b/clients/cli/src/test/java/org/apache/gravitino/cli/TestCatalogCommands.java index afa19b94c5a..26639368a6a 100644 --- a/clients/cli/src/test/java/org/apache/gravitino/cli/TestCatalogCommands.java +++ b/clients/cli/src/test/java/org/apache/gravitino/cli/TestCatalogCommands.java @@ -22,6 +22,10 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.argThat; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; @@ -39,7 +43,6 @@ import org.apache.gravitino.cli.commands.CatalogDetails; import org.apache.gravitino.cli.commands.CatalogDisable; import org.apache.gravitino.cli.commands.CatalogEnable; -import org.apache.gravitino.cli.commands.Command; import org.apache.gravitino.cli.commands.CreateCatalog; import org.apache.gravitino.cli.commands.DeleteCatalog; import org.apache.gravitino.cli.commands.ListCatalogProperties; @@ -69,11 +72,6 @@ void setUp() { System.setErr(new PrintStream(errContent)); } - @AfterEach - void restoreExitFlg() { - Main.useExit = true; - } - @AfterEach public void restoreStreams() { System.setOut(originalOut); @@ -91,7 +89,7 @@ void testListCatalogsCommand() { mockCommandLine, mockOptions, CommandEntities.CATALOG, CommandActions.LIST)); doReturn(mockList) .when(commandLine) - .newListCatalogs(GravitinoCommandLine.DEFAULT_URL, false, null, "metalake_demo"); + .newListCatalogs(any(CommandContext.class), eq("metalake_demo")); doReturn(mockList).when(mockList).validate(); commandLine.handleCommandLine(); verify(mockList).handle(); @@ -111,8 +109,7 @@ void testCatalogDetailsCommand() { mockCommandLine, mockOptions, CommandEntities.CATALOG, CommandActions.DETAILS)); doReturn(mockDetails) .when(commandLine) - .newCatalogDetails( - GravitinoCommandLine.DEFAULT_URL, false, null, "metalake_demo", "catalog"); + .newCatalogDetails(any(CommandContext.class), eq("metalake_demo"), eq("catalog")); doReturn(mockDetails).when(mockDetails).validate(); commandLine.handleCommandLine(); verify(mockDetails).handle(); @@ -132,7 +129,7 @@ void testCatalogAuditCommand() { mockCommandLine, mockOptions, CommandEntities.CATALOG, CommandActions.DETAILS)); doReturn(mockAudit) .when(commandLine) - .newCatalogAudit(GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "catalog"); + .newCatalogAudit(any(CommandContext.class), eq("metalake_demo"), eq("catalog")); doReturn(mockAudit).when(mockAudit).validate(); commandLine.handleCommandLine(); verify(mockAudit).handle(); @@ -163,13 +160,17 @@ void testCreateCatalogCommand() { doReturn(mockCreate) .when(commandLine) .newCreateCatalog( - GravitinoCommandLine.DEFAULT_URL, - false, - "metalake_demo", - "catalog", - "postgres", - "comment", - map); + any(CommandContext.class), + eq("metalake_demo"), + eq("catalog"), + eq("postgres"), + eq("comment"), + argThat( + stringStringMap -> + stringStringMap.containsKey("key1") + && stringStringMap.get("key1").equals(map.get("key1")) + && stringStringMap.containsKey("key2") + && stringStringMap.get("key2").equals("value2"))); doReturn(mockCreate).when(mockCreate).validate(); commandLine.handleCommandLine(); verify(mockCreate).handle(); @@ -178,16 +179,10 @@ void testCreateCatalogCommand() { @Test void testCreateCatalogCommandWithoutProvider() { Main.useExit = false; + CommandContext mockContext = mock(CommandContext.class); + when(mockContext.url()).thenReturn("http://localhost:8080"); CreateCatalog mockCreateCatalog = - spy( - new CreateCatalog( - GravitinoCommandLine.DEFAULT_URL, - false, - "metalake_demo", - "catalog", - null, - "comment", - null)); + spy(new CreateCatalog(mockContext, "metalake_demo", "catalog", null, "comment", null)); assertThrows(RuntimeException.class, mockCreateCatalog::validate); String errOutput = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); @@ -207,8 +202,7 @@ void testDeleteCatalogCommand() { mockCommandLine, mockOptions, CommandEntities.CATALOG, CommandActions.DELETE)); doReturn(mockDelete) .when(commandLine) - .newDeleteCatalog( - GravitinoCommandLine.DEFAULT_URL, false, false, "metalake_demo", "catalog"); + .newDeleteCatalog(any(CommandContext.class), eq("metalake_demo"), eq("catalog")); doReturn(mockDelete).when(mockDelete).validate(); commandLine.handleCommandLine(); verify(mockDelete).handle(); @@ -228,8 +222,7 @@ void testDeleteCatalogForceCommand() { mockCommandLine, mockOptions, CommandEntities.CATALOG, CommandActions.DELETE)); doReturn(mockDelete) .when(commandLine) - .newDeleteCatalog( - GravitinoCommandLine.DEFAULT_URL, false, true, "metalake_demo", "catalog"); + .newDeleteCatalog(any(CommandContext.class), eq("metalake_demo"), eq("catalog")); doReturn(mockDelete).when(mockDelete).validate(); commandLine.handleCommandLine(); verify(mockDelete).handle(); @@ -253,12 +246,11 @@ void testSetCatalogPropertyCommand() { doReturn(mockSetProperty) .when(commandLine) .newSetCatalogProperty( - GravitinoCommandLine.DEFAULT_URL, - false, - "metalake_demo", - "catalog", - "property", - "value"); + any(CommandContext.class), + eq("metalake_demo"), + eq("catalog"), + eq("property"), + eq("value")); doReturn(mockSetProperty).when(mockSetProperty).validate(); commandLine.handleCommandLine(); verify(mockSetProperty).handle(); @@ -267,10 +259,10 @@ void testSetCatalogPropertyCommand() { @Test void testSetCatalogPropertyCommandWithoutPropertyAndValue() { Main.useExit = false; + CommandContext mockContext = mock(CommandContext.class); + when(mockContext.url()).thenReturn("http://localhost:8080"); SetCatalogProperty mockSetProperty = - spy( - new SetCatalogProperty( - GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "catalog", null, null)); + spy(new SetCatalogProperty(mockContext, "metalake_demo", "catalog", null, null)); assertThrows(RuntimeException.class, mockSetProperty::validate); String errOutput = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); @@ -280,15 +272,10 @@ void testSetCatalogPropertyCommandWithoutPropertyAndValue() { @Test void testSetCatalogPropertyCommandWithoutProperty() { Main.useExit = false; + CommandContext mockContext = mock(CommandContext.class); + when(mockContext.url()).thenReturn("http://localhost:8080"); SetCatalogProperty mockSetProperty = - spy( - new SetCatalogProperty( - GravitinoCommandLine.DEFAULT_URL, - false, - "metalake_demo", - "catalog", - null, - "value")); + spy(new SetCatalogProperty(mockContext, "metalake_demo", "catalog", null, "value")); assertThrows(RuntimeException.class, mockSetProperty::validate); String errOutput = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); @@ -297,16 +284,10 @@ void testSetCatalogPropertyCommandWithoutProperty() { @Test void testSetCatalogPropertyCommandWithoutValue() { - Main.useExit = false; + CommandContext mockContext = mock(CommandContext.class); + when(mockContext.url()).thenReturn("http://localhost:8080"); SetCatalogProperty mockSetProperty = - spy( - new SetCatalogProperty( - GravitinoCommandLine.DEFAULT_URL, - false, - "metalake_demo", - "catalog", - "property", - null)); + spy(new SetCatalogProperty(mockContext, "metalake_demo", "catalog", "property", null)); assertThrows(RuntimeException.class, mockSetProperty::validate); String errOutput = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); @@ -329,7 +310,7 @@ void testRemoveCatalogPropertyCommand() { doReturn(mockRemoveProperty) .when(commandLine) .newRemoveCatalogProperty( - GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "catalog", "property"); + any(CommandContext.class), eq("metalake_demo"), eq("catalog"), eq("property")); doReturn(mockRemoveProperty).when(mockRemoveProperty).validate(); commandLine.handleCommandLine(); verify(mockRemoveProperty).handle(); @@ -337,11 +318,10 @@ void testRemoveCatalogPropertyCommand() { @Test void testRemoveCatalogPropertyCommandWithoutProperty() { - Main.useExit = false; + CommandContext mockContext = mock(CommandContext.class); + when(mockContext.url()).thenReturn("http://localhost:8080"); RemoveCatalogProperty mockRemoveProperty = - spy( - new RemoveCatalogProperty( - GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "catalog", null)); + spy(new RemoveCatalogProperty(mockContext, "metalake_demo", "catalog", null)); assertThrows(RuntimeException.class, mockRemoveProperty::validate); String errOutput = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); @@ -361,8 +341,7 @@ void testListCatalogPropertiesCommand() { mockCommandLine, mockOptions, CommandEntities.CATALOG, CommandActions.PROPERTIES)); doReturn(mockListProperties) .when(commandLine) - .newListCatalogProperties( - GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "catalog"); + .newListCatalogProperties(any(CommandContext.class), eq("metalake_demo"), eq("catalog")); doReturn(mockListProperties).when(mockListProperties).validate(); commandLine.handleCommandLine(); verify(mockListProperties).handle(); @@ -384,7 +363,7 @@ void testUpdateCatalogCommentCommand() { doReturn(mockUpdateComment) .when(commandLine) .newUpdateCatalogComment( - GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "catalog", "new comment"); + any(CommandContext.class), eq("metalake_demo"), eq("catalog"), eq("new comment")); doReturn(mockUpdateComment).when(mockUpdateComment).validate(); commandLine.handleCommandLine(); verify(mockUpdateComment).handle(); @@ -407,7 +386,7 @@ void testUpdateCatalogNameCommand() { doReturn(mockUpdateName) .when(commandLine) .newUpdateCatalogName( - GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "catalog", "new_name"); + any(CommandContext.class), eq("metalake_demo"), eq("catalog"), eq("new_name")); doReturn(mockUpdateName).when(mockUpdateName).validate(); commandLine.handleCommandLine(); verify(mockUpdateName).handle(); @@ -428,12 +407,7 @@ void testCatalogDetailsCommandWithoutCatalog() { assertThrows(RuntimeException.class, commandLine::handleCommandLine); verify(commandLine, never()) - .newCatalogDetails( - GravitinoCommandLine.DEFAULT_URL, - false, - Command.OUTPUT_FORMAT_TABLE, - "metalake_demo", - "catalog"); + .newCatalogDetails(any(CommandContext.class), eq("metalake_demo"), eq("catalog")); String output = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); assertEquals( output, @@ -459,7 +433,7 @@ void testEnableCatalogCommand() { doReturn(mockEnable) .when(commandLine) .newCatalogEnable( - GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "catalog", false); + any(CommandContext.class), eq("metalake_demo"), eq("catalog"), anyBoolean()); doReturn(mockEnable).when(mockEnable).validate(); commandLine.handleCommandLine(); verify(mockEnable).handle(); @@ -482,7 +456,7 @@ void testEnableCatalogCommandWithRecursive() { doReturn(mockEnable) .when(commandLine) .newCatalogEnable( - GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "catalog", true); + any(CommandContext.class), eq("metalake_demo"), eq("catalog"), anyBoolean()); doReturn(mockEnable).when(mockEnable).validate(); commandLine.handleCommandLine(); verify(mockEnable).handle(); @@ -503,7 +477,7 @@ void testDisableCatalogCommand() { mockCommandLine, mockOptions, CommandEntities.CATALOG, CommandActions.UPDATE)); doReturn(mockDisable) .when(commandLine) - .newCatalogDisable(GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "catalog"); + .newCatalogDisable(any(CommandContext.class), eq("metalake_demo"), eq("catalog")); doReturn(mockDisable).when(mockDisable).validate(); commandLine.handleCommandLine(); verify(mockDisable).handle(); @@ -528,9 +502,9 @@ void testCatalogWithDisableAndEnableOptions() { assertThrows(RuntimeException.class, commandLine::handleCommandLine); verify(commandLine, never()) .newCatalogEnable( - GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "catalog", false); + any(CommandContext.class), eq("metalake_demo"), eq("catalog"), anyBoolean()); verify(commandLine, never()) - .newCatalogDisable(GravitinoCommandLine.DEFAULT_URL, false, "melake_demo", "catalog"); + .newCatalogDisable(any(CommandContext.class), eq("metalake_demo"), eq("catalog")); assertTrue(errContent.toString().contains(ErrorMessages.INVALID_ENABLE_DISABLE)); } } diff --git a/clients/cli/src/test/java/org/apache/gravitino/cli/TestCommandContext.java b/clients/cli/src/test/java/org/apache/gravitino/cli/TestCommandContext.java new file mode 100644 index 00000000000..8919446826b --- /dev/null +++ b/clients/cli/src/test/java/org/apache/gravitino/cli/TestCommandContext.java @@ -0,0 +1,46 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.gravitino.cli; + +import org.apache.gravitino.cli.commands.Command; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class TestCommandContext { + + @Test + public void testCreateCommandContextWithDefaults() { + CommandContext commandContext = new CommandContext("http://localhost:8080", false); + Assertions.assertEquals("http://localhost:8080", commandContext.url()); + Assertions.assertFalse(commandContext.ignoreVersions()); + Assertions.assertFalse(commandContext.force()); + Assertions.assertEquals(Command.OUTPUT_FORMAT_PLAIN, commandContext.outputFormat()); + } + + @Test + public void testCreateCommandContextWithCustomValues() { + CommandContext commandContext = + new CommandContext("http://localhost:8080", true, true, Command.OUTPUT_FORMAT_TABLE); + Assertions.assertEquals("http://localhost:8080", commandContext.url()); + Assertions.assertTrue(commandContext.ignoreVersions()); + Assertions.assertTrue(commandContext.force()); + Assertions.assertEquals(Command.OUTPUT_FORMAT_TABLE, commandContext.outputFormat()); + } +} From 82087ef6ecdca54bd0bfe13e03028f665d4251ae Mon Sep 17 00:00:00 2001 From: Lord of Abyss <103809695+Abyss-lord@users.noreply.github.com> Date: Tue, 11 Feb 2025 12:41:12 +0800 Subject: [PATCH 20/33] [#6418] improve(CLI): Add stream command context CLI (#6434) ### What changes were proposed in this pull request? Add stream command context CLI ### Why are the changes needed? Fix: #6418 ### Does this PR introduce _any_ user-facing change? No ### How was this patch tested? local test. --- .../gravitino/cli/GravitinoCommandLine.java | 2 +- .../gravitino/cli/TestableCommandLine.java | 42 ++--- .../gravitino/cli/TopicCommandHandler.java | 31 ++-- .../gravitino/cli/commands/CreateTopic.java | 11 +- .../gravitino/cli/commands/DeleteTopic.java | 21 +-- .../cli/commands/ListTopicProperties.java | 13 +- .../gravitino/cli/commands/ListTopics.java | 11 +- .../cli/commands/RemoveTopicProperty.java | 11 +- .../cli/commands/SetTopicProperty.java | 11 +- .../gravitino/cli/commands/TopicDetails.java | 15 +- .../cli/commands/UpdateTopicComment.java | 11 +- .../gravitino/cli/TestTopicCommands.java | 149 ++++++++---------- 12 files changed, 140 insertions(+), 188 deletions(-) diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/GravitinoCommandLine.java b/clients/cli/src/main/java/org/apache/gravitino/cli/GravitinoCommandLine.java index 97fca069a9c..b5e5838f1bb 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/GravitinoCommandLine.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/GravitinoCommandLine.java @@ -126,7 +126,7 @@ private void executeCommand() { } else if (entity.equals(CommandEntities.METALAKE)) { new MetalakeCommandHandler(this, line, command, context).handle(); } else if (entity.equals(CommandEntities.TOPIC)) { - new TopicCommandHandler(this, line, command, ignore).handle(); + new TopicCommandHandler(this, line, command, context).handle(); } else if (entity.equals(CommandEntities.FILESET)) { new FilesetCommandHandler(this, line, command, context).handle(); } else if (entity.equals(CommandEntities.USER)) { diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/TestableCommandLine.java b/clients/cli/src/main/java/org/apache/gravitino/cli/TestableCommandLine.java index d1c757345a2..8a64c6c551e 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/TestableCommandLine.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/TestableCommandLine.java @@ -570,74 +570,64 @@ protected OwnerDetails newOwnerDetails( } protected ListTopics newListTopics( - String url, boolean ignore, String metalake, String catalog, String schema) { - return new ListTopics(url, ignore, metalake, catalog, schema); + CommandContext context, String metalake, String catalog, String schema) { + return new ListTopics(context, metalake, catalog, schema); } protected TopicDetails newTopicDetails( - String url, boolean ignore, String metalake, String catalog, String schema, String topic) { - return new TopicDetails(url, ignore, metalake, catalog, schema, topic); + CommandContext context, String metalake, String catalog, String schema, String topic) { + return new TopicDetails(context, metalake, catalog, schema, topic); } protected CreateTopic newCreateTopic( - String url, - boolean ignore, + CommandContext context, String metalake, String catalog, String schema, String topic, String comment) { - return new CreateTopic(url, ignore, metalake, catalog, schema, topic, comment); + return new CreateTopic(context, metalake, catalog, schema, topic, comment); } protected DeleteTopic newDeleteTopic( - String url, - boolean ignore, - boolean force, - String metalake, - String catalog, - String schema, - String topic) { - return new DeleteTopic(url, ignore, force, metalake, catalog, schema, topic); + CommandContext context, String metalake, String catalog, String schema, String topic) { + return new DeleteTopic(context, metalake, catalog, schema, topic); } protected UpdateTopicComment newUpdateTopicComment( - String url, - boolean ignore, + CommandContext context, String metalake, String catalog, String schema, String topic, String comment) { - return new UpdateTopicComment(url, ignore, metalake, catalog, schema, topic, comment); + return new UpdateTopicComment(context, metalake, catalog, schema, topic, comment); } protected SetTopicProperty newSetTopicProperty( - String url, - boolean ignore, + CommandContext context, String metalake, String catalog, String schema, String topic, String property, String value) { - return new SetTopicProperty(url, ignore, metalake, catalog, schema, topic, property, value); + return new SetTopicProperty(context, metalake, catalog, schema, topic, property, value); } protected RemoveTopicProperty newRemoveTopicProperty( - String url, - boolean ignore, + CommandContext context, String metalake, String catalog, String schema, String topic, String property) { - return new RemoveTopicProperty(url, ignore, metalake, catalog, schema, topic, property); + return new RemoveTopicProperty(context, metalake, catalog, schema, topic, property); } protected ListTopicProperties newListTopicProperties( - String url, boolean ignore, String metalake, String catalog, String schema, String topic) { - return new ListTopicProperties(url, ignore, metalake, catalog, schema, topic); + CommandContext context, String metalake, String catalog, String schema, String topic) { + return new ListTopicProperties(context, metalake, catalog, schema, topic); } protected FilesetDetails newFilesetDetails( diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/TopicCommandHandler.java b/clients/cli/src/main/java/org/apache/gravitino/cli/TopicCommandHandler.java index 7c2a75db91b..f67d003b28e 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/TopicCommandHandler.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/TopicCommandHandler.java @@ -29,8 +29,7 @@ public class TopicCommandHandler extends CommandHandler { private final GravitinoCommandLine gravitinoCommandLine; private final CommandLine line; private final String command; - private final boolean ignore; - private final String url; + private final CommandContext context; private final FullName name; private final String metalake; private final String catalog; @@ -43,16 +42,19 @@ public class TopicCommandHandler extends CommandHandler { * @param gravitinoCommandLine The Gravitino command line instance. * @param line The command line arguments. * @param command The command to execute. - * @param ignore Ignore server version mismatch. + * @param context The command context. */ public TopicCommandHandler( - GravitinoCommandLine gravitinoCommandLine, CommandLine line, String command, boolean ignore) { + GravitinoCommandLine gravitinoCommandLine, + CommandLine line, + String command, + CommandContext context) { this.gravitinoCommandLine = gravitinoCommandLine; this.line = line; this.command = command; - this.ignore = ignore; + this.context = context; - this.url = getUrl(line); + this.context.setUrl(getUrl(line)); this.name = new FullName(line); this.metalake = name.getMetalakeName(); this.catalog = name.getCatalogName(); @@ -128,7 +130,7 @@ private boolean executeCommand() { /** Handles the "DETAILS" command. */ private void handleDetailsCommand() { gravitinoCommandLine - .newTopicDetails(url, ignore, metalake, catalog, schema, topic) + .newTopicDetails(context, metalake, catalog, schema, topic) .validate() .handle(); } @@ -137,16 +139,15 @@ private void handleDetailsCommand() { private void handleCreateCommand() { String comment = line.getOptionValue(GravitinoOptions.COMMENT); gravitinoCommandLine - .newCreateTopic(url, ignore, metalake, catalog, schema, topic, comment) + .newCreateTopic(context, metalake, catalog, schema, topic, comment) .validate() .handle(); } /** Handles the "DELETE" command. */ private void handleDeleteCommand() { - boolean force = line.hasOption(GravitinoOptions.FORCE); gravitinoCommandLine - .newDeleteTopic(url, ignore, force, metalake, catalog, schema, topic) + .newDeleteTopic(context, metalake, catalog, schema, topic) .validate() .handle(); } @@ -156,7 +157,7 @@ private void handleUpdateCommand() { if (line.hasOption(GravitinoOptions.COMMENT)) { String comment = line.getOptionValue(GravitinoOptions.COMMENT); gravitinoCommandLine - .newUpdateTopicComment(url, ignore, metalake, catalog, schema, topic, comment) + .newUpdateTopicComment(context, metalake, catalog, schema, topic, comment) .validate() .handle(); } @@ -167,7 +168,7 @@ private void handleSetCommand() { String property = line.getOptionValue(GravitinoOptions.PROPERTY); String value = line.getOptionValue(GravitinoOptions.VALUE); gravitinoCommandLine - .newSetTopicProperty(url, ignore, metalake, catalog, schema, topic, property, value) + .newSetTopicProperty(context, metalake, catalog, schema, topic, property, value) .validate() .handle(); } @@ -176,7 +177,7 @@ private void handleSetCommand() { private void handleRemoveCommand() { String property = line.getOptionValue(GravitinoOptions.PROPERTY); gravitinoCommandLine - .newRemoveTopicProperty(url, ignore, metalake, catalog, schema, topic, property) + .newRemoveTopicProperty(context, metalake, catalog, schema, topic, property) .validate() .handle(); } @@ -184,13 +185,13 @@ private void handleRemoveCommand() { /** Handles the "PROPERTIES" command. */ private void handlePropertiesCommand() { gravitinoCommandLine - .newListTopicProperties(url, ignore, metalake, catalog, schema, topic) + .newListTopicProperties(context, metalake, catalog, schema, topic) .validate() .handle(); } /** Handles the "LIST" command. */ private void handleListCommand() { - gravitinoCommandLine.newListTopics(url, ignore, metalake, catalog, schema).validate().handle(); + gravitinoCommandLine.newListTopics(context, metalake, catalog, schema).validate().handle(); } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/CreateTopic.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/CreateTopic.java index 61d3db4472f..c1fd5c4118b 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/CreateTopic.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/CreateTopic.java @@ -20,6 +20,7 @@ package org.apache.gravitino.cli.commands; import org.apache.gravitino.NameIdentifier; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchMetalakeException; @@ -38,8 +39,7 @@ public class CreateTopic extends Command { /** * Add a topic. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param catalog The name of the catalog. * @param schema The name of the schema. @@ -47,14 +47,13 @@ public class CreateTopic extends Command { * @param comment The comment for the topic. */ public CreateTopic( - String url, - boolean ignoreVersions, + CommandContext context, String metalake, String catalog, String schema, String topic, String comment) { - super(url, ignoreVersions); + super(context); this.metalake = metalake; this.catalog = catalog; this.schema = schema; @@ -80,6 +79,6 @@ public void handle() { exitWithError(exp.getMessage()); } - System.out.println(topic + " topic created."); + printInformation(topic + " topic created."); } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/DeleteTopic.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/DeleteTopic.java index 5d6f440dba9..462c38a005d 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/DeleteTopic.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/DeleteTopic.java @@ -21,6 +21,7 @@ import org.apache.gravitino.NameIdentifier; import org.apache.gravitino.cli.AreYouSure; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchMetalakeException; @@ -39,24 +40,16 @@ public class DeleteTopic extends Command { /** * Delete a topic. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. - * @param force Force operation. + * @param context The command context. * @param metalake The name of the metalake. * @param catalog The name of the catalog. * @param schema The name of the schema. * @param topic The name of the topic. */ public DeleteTopic( - String url, - boolean ignoreVersions, - boolean force, - String metalake, - String catalog, - String schema, - String topic) { - super(url, ignoreVersions); - this.force = force; + CommandContext context, String metalake, String catalog, String schema, String topic) { + super(context); + this.force = context.force(); this.metalake = metalake; this.catalog = catalog; this.schema = schema; @@ -87,9 +80,9 @@ public void handle() { } if (deleted) { - System.out.println(topic + " deleted."); + printInformation(topic + " deleted."); } else { - System.out.println(topic + " not deleted."); + printInformation(topic + " not deleted."); } } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListTopicProperties.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListTopicProperties.java index e308b1c6a15..038c29b3cb7 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListTopicProperties.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListTopicProperties.java @@ -21,6 +21,7 @@ import java.util.Map; import org.apache.gravitino.NameIdentifier; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchCatalogException; @@ -40,21 +41,15 @@ public class ListTopicProperties extends ListProperties { /** * List the properties of a topic. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param catalog The name of the catalog. * @param schema The name of the schema. * @param topic The name of the topic. */ public ListTopicProperties( - String url, - boolean ignoreVersions, - String metalake, - String catalog, - String schema, - String topic) { - super(url, ignoreVersions); + CommandContext context, String metalake, String catalog, String schema, String topic) { + super(context); this.metalake = metalake; this.catalog = catalog; this.schema = schema; diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListTopics.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListTopics.java index a2da6a69ad7..9612ec0900b 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListTopics.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListTopics.java @@ -23,6 +23,7 @@ import java.util.Arrays; import org.apache.gravitino.NameIdentifier; import org.apache.gravitino.Namespace; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchMetalakeException; @@ -37,15 +38,13 @@ public class ListTopics extends Command { /** * List the names of all topics in a schema. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param catalog The name of the catalog. * @param schema The name of the schema. */ - public ListTopics( - String url, boolean ignoreVersions, String metalake, String catalog, String schema) { - super(url, ignoreVersions); + public ListTopics(CommandContext context, String metalake, String catalog, String schema) { + super(context); this.metalake = metalake; this.catalog = catalog; this.schema = schema; @@ -70,6 +69,6 @@ public void handle() { topics.length == 0 ? "No topics exist." : Joiner.on(",").join(Arrays.stream(topics).map(topic -> topic.name()).iterator()); - System.out.println(all); + printResults(all); } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RemoveTopicProperty.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RemoveTopicProperty.java index 51be0a139d9..497088c1be6 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RemoveTopicProperty.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RemoveTopicProperty.java @@ -20,6 +20,7 @@ package org.apache.gravitino.cli.commands; import org.apache.gravitino.NameIdentifier; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchCatalogException; @@ -40,8 +41,7 @@ public class RemoveTopicProperty extends Command { /** * Remove a property of a topic. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param catalog The name of the catalog. * @param schema The name of the schema. @@ -49,14 +49,13 @@ public class RemoveTopicProperty extends Command { * @param property The name of the property. */ public RemoveTopicProperty( - String url, - boolean ignoreVersions, + CommandContext context, String metalake, String catalog, String schema, String topic, String property) { - super(url, ignoreVersions); + super(context); this.metalake = metalake; this.catalog = catalog; this.schema = schema; @@ -85,7 +84,7 @@ public void handle() { exitWithError(exp.getMessage()); } - System.out.println(property + " property removed."); + printInformation(property + " property removed."); } @Override diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/SetTopicProperty.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/SetTopicProperty.java index 2641259cdde..67bedc88d78 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/SetTopicProperty.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/SetTopicProperty.java @@ -20,6 +20,7 @@ package org.apache.gravitino.cli.commands; import org.apache.gravitino.NameIdentifier; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchCatalogException; @@ -41,8 +42,7 @@ public class SetTopicProperty extends Command { /** * Set a property of a topic. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param catalog The name of the catalog. * @param schema The name of the schema. @@ -51,15 +51,14 @@ public class SetTopicProperty extends Command { * @param value The value of the property. */ public SetTopicProperty( - String url, - boolean ignoreVersions, + CommandContext context, String metalake, String catalog, String schema, String topic, String property, String value) { - super(url, ignoreVersions); + super(context); this.metalake = metalake; this.catalog = catalog; this.schema = schema; @@ -90,7 +89,7 @@ public void handle() { exitWithError(exp.getMessage()); } - System.out.println(property + " property set."); + printInformation(property + " property set."); } @Override diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/TopicDetails.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/TopicDetails.java index 0ab31bd8b36..d72002419d6 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/TopicDetails.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/TopicDetails.java @@ -20,6 +20,7 @@ package org.apache.gravitino.cli.commands; import org.apache.gravitino.NameIdentifier; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchCatalogException; @@ -39,21 +40,15 @@ public class TopicDetails extends Command { /** * Displays the details of a topic. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param catalog The name of the catalog. * @param schema The name of the schenma. * @param topic The name of the topic. */ public TopicDetails( - String url, - boolean ignoreVersions, - String metalake, - String catalog, - String schema, - String topic) { - super(url, ignoreVersions); + CommandContext context, String metalake, String catalog, String schema, String topic) { + super(context); this.metalake = metalake; this.catalog = catalog; this.schema = schema; @@ -81,6 +76,6 @@ public void handle() { exitWithError(exp.getMessage()); } - System.out.println(gTopic.name() + "," + gTopic.comment()); + printResults(gTopic.name() + "," + gTopic.comment()); } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateTopicComment.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateTopicComment.java index 1f81ad7fab3..37121db4ac0 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateTopicComment.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateTopicComment.java @@ -20,6 +20,7 @@ package org.apache.gravitino.cli.commands; import org.apache.gravitino.NameIdentifier; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchCatalogException; @@ -40,8 +41,7 @@ public class UpdateTopicComment extends Command { /** * Update the comment of a topic. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param catalog The name of the catalog. * @param schema The name of the schema. @@ -49,14 +49,13 @@ public class UpdateTopicComment extends Command { * @param comment New metalake comment. */ public UpdateTopicComment( - String url, - boolean ignoreVersions, + CommandContext context, String metalake, String catalog, String schema, String topic, String comment) { - super(url, ignoreVersions); + super(context); this.metalake = metalake; this.catalog = catalog; this.schema = schema; @@ -85,6 +84,6 @@ public void handle() { exitWithError(exp.getMessage()); } - System.out.println(topic + " comment changed."); + printInformation(topic + " comment changed."); } } diff --git a/clients/cli/src/test/java/org/apache/gravitino/cli/TestTopicCommands.java b/clients/cli/src/test/java/org/apache/gravitino/cli/TestTopicCommands.java index 31904b88563..695edb9dd48 100644 --- a/clients/cli/src/test/java/org/apache/gravitino/cli/TestTopicCommands.java +++ b/clients/cli/src/test/java/org/apache/gravitino/cli/TestTopicCommands.java @@ -21,6 +21,9 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThrows; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; @@ -87,8 +90,7 @@ void testListTopicsCommand() { mockCommandLine, mockOptions, CommandEntities.TOPIC, CommandActions.LIST)); doReturn(mockList) .when(commandLine) - .newListTopics( - GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "catalog", "schema"); + .newListTopics(any(CommandContext.class), eq("metalake_demo"), eq("catalog"), eq("schema")); doReturn(mockList).when(mockList).validate(); commandLine.handleCommandLine(); verify(mockList).handle(); @@ -108,7 +110,11 @@ void testTopicDetailsCommand() { doReturn(mockDetails) .when(commandLine) .newTopicDetails( - GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "catalog", "schema", "topic"); + any(CommandContext.class), + eq("metalake_demo"), + eq("catalog"), + eq("schema"), + eq("topic")); doReturn(mockDetails).when(mockDetails).validate(); commandLine.handleCommandLine(); verify(mockDetails).handle(); @@ -131,13 +137,12 @@ void testCreateTopicCommand() { doReturn(mockCreate) .when(commandLine) .newCreateTopic( - GravitinoCommandLine.DEFAULT_URL, - false, - "metalake_demo", - "catalog", - "schema", - "topic", - "comment"); + any(CommandContext.class), + eq("metalake_demo"), + eq("catalog"), + eq("schema"), + eq("topic"), + eq("comment")); doReturn(mockCreate).when(mockCreate).validate(); commandLine.handleCommandLine(); verify(mockCreate).handle(); @@ -157,13 +162,11 @@ void testDeleteTopicCommand() { doReturn(mockDelete) .when(commandLine) .newDeleteTopic( - GravitinoCommandLine.DEFAULT_URL, - false, - false, - "metalake_demo", - "catalog", - "schema", - "topic"); + any(CommandContext.class), + eq("metalake_demo"), + eq("catalog"), + eq("schema"), + eq("topic")); doReturn(mockDelete).when(mockDelete).validate(); commandLine.handleCommandLine(); verify(mockDelete).handle(); @@ -184,13 +187,11 @@ void testDeleteTopicForceCommand() { doReturn(mockDelete) .when(commandLine) .newDeleteTopic( - GravitinoCommandLine.DEFAULT_URL, - false, - true, - "metalake_demo", - "catalog", - "schema", - "topic"); + any(CommandContext.class), + eq("metalake_demo"), + eq("catalog"), + eq("schema"), + eq("topic")); doReturn(mockDelete).when(mockDelete).validate(); commandLine.handleCommandLine(); verify(mockDelete).handle(); @@ -213,13 +214,12 @@ void testUpdateCommentTopicCommand() { doReturn(mockUpdate) .when(commandLine) .newUpdateTopicComment( - GravitinoCommandLine.DEFAULT_URL, - false, - "metalake_demo", - "catalog", - "schema", - "topic", - "new comment"); + any(CommandContext.class), + eq("metalake_demo"), + eq("catalog"), + eq("schema"), + eq("topic"), + eq("new comment")); doReturn(mockUpdate).when(mockUpdate).validate(); commandLine.handleCommandLine(); verify(mockUpdate).handle(); @@ -240,7 +240,11 @@ void testListTopicPropertiesCommand() { doReturn(mockListProperties) .when(commandLine) .newListTopicProperties( - GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "catalog", "schema", "topic"); + any(CommandContext.class), + eq("metalake_demo"), + eq("catalog"), + eq("schema"), + eq("topic")); doReturn(mockListProperties).when(mockListProperties).validate(); commandLine.handleCommandLine(); verify(mockListProperties).handle(); @@ -265,14 +269,13 @@ void testSetTopicPropertyCommand() { doReturn(mockSetProperties) .when(commandLine) .newSetTopicProperty( - GravitinoCommandLine.DEFAULT_URL, - false, - "metalake_demo", - "catalog", - "schema", - "topic", - "property", - "value"); + any(CommandContext.class), + eq("metalake_demo"), + eq("catalog"), + eq("schema"), + eq("topic"), + eq("property"), + eq("value")); doReturn(mockSetProperties).when(mockSetProperties).validate(); commandLine.handleCommandLine(); verify(mockSetProperties).handle(); @@ -281,17 +284,12 @@ void testSetTopicPropertyCommand() { @Test void testSetTopicPropertyCommandWithoutPropertyAndValue() { Main.useExit = false; + CommandContext mockContext = mock(CommandContext.class); + when(mockContext.url()).thenReturn(GravitinoCommandLine.DEFAULT_URL); SetTopicProperty spySetProperty = spy( new SetTopicProperty( - GravitinoCommandLine.DEFAULT_URL, - false, - "metalake_demo", - "catalog", - "schema", - "topic", - null, - null)); + mockContext, "metalake_demo", "catalog", "schema", "topic", null, null)); assertThrows(RuntimeException.class, spySetProperty::validate); verify(spySetProperty, never()).handle(); String output = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); @@ -301,17 +299,12 @@ void testSetTopicPropertyCommandWithoutPropertyAndValue() { @Test void testSetTopicPropertyCommandWithoutProperty() { Main.useExit = false; + CommandContext mockContext = mock(CommandContext.class); + when(mockContext.url()).thenReturn(GravitinoCommandLine.DEFAULT_URL); SetTopicProperty spySetProperty = spy( new SetTopicProperty( - GravitinoCommandLine.DEFAULT_URL, - false, - "metalake_demo", - "catalog", - "schema", - "topic", - null, - "value")); + mockContext, "metalake_demo", "catalog", "schema", "topic", null, "value")); assertThrows(RuntimeException.class, spySetProperty::validate); verify(spySetProperty, never()).handle(); String output = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); @@ -321,17 +314,12 @@ void testSetTopicPropertyCommandWithoutProperty() { @Test void testSetTopicPropertyCommandWithoutValue() { Main.useExit = false; + CommandContext mockContext = mock(CommandContext.class); + when(mockContext.url()).thenReturn(GravitinoCommandLine.DEFAULT_URL); SetTopicProperty spySetProperty = spy( new SetTopicProperty( - GravitinoCommandLine.DEFAULT_URL, - false, - "metalake_demo", - "catalog", - "schema", - "topic", - "property", - null)); + mockContext, "metalake_demo", "catalog", "schema", "topic", "property", null)); assertThrows(RuntimeException.class, spySetProperty::validate); verify(spySetProperty, never()).handle(); String output = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); @@ -355,13 +343,12 @@ void testRemoveTopicPropertyCommand() { doReturn(mockSetProperties) .when(commandLine) .newRemoveTopicProperty( - GravitinoCommandLine.DEFAULT_URL, - false, - "metalake_demo", - "catalog", - "schema", - "topic", - "property"); + any(CommandContext.class), + eq("metalake_demo"), + eq("catalog"), + eq("schema"), + eq("topic"), + eq("property")); doReturn(mockSetProperties).when(mockSetProperties).validate(); commandLine.handleCommandLine(); verify(mockSetProperties).handle(); @@ -370,16 +357,12 @@ void testRemoveTopicPropertyCommand() { @Test void testRemoveTopicPropertyCommandWithoutProperty() { Main.useExit = false; + CommandContext mockContext = mock(CommandContext.class); + when(mockContext.url()).thenReturn(GravitinoCommandLine.DEFAULT_URL); RemoveTopicProperty spyRemoveProperty = spy( new RemoveTopicProperty( - GravitinoCommandLine.DEFAULT_URL, - false, - "metalake_demo", - "catalog", - "schema", - "topic", - null)); + mockContext, "metalake_demo", "catalog", "schema", "topic", null)); assertThrows(RuntimeException.class, spyRemoveProperty::validate); verify(spyRemoveProperty, never()).handle(); @@ -400,7 +383,7 @@ void testListTopicCommandWithoutCatalog() { assertThrows(RuntimeException.class, commandLine::handleCommandLine); verify(commandLine, never()) - .newListTopics(GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", null, null); + .newListTopics(any(CommandContext.class), eq("metalake_demo"), isNull(), isNull()); String output = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); assertEquals( output, @@ -425,7 +408,7 @@ void testListTopicCommandWithoutSchema() { assertThrows(RuntimeException.class, commandLine::handleCommandLine); verify(commandLine, never()) - .newListTopics(GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "catalog", null); + .newListTopics(any(CommandContext.class), eq("metalake_demo"), eq("catalog"), isNull()); String output = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); assertEquals( output, @@ -450,7 +433,7 @@ void testTopicDetailsCommandWithoutCatalog() { assertThrows(RuntimeException.class, commandLine::handleCommandLine); verify(commandLine, never()) .newTopicDetails( - GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", null, null, null); + any(CommandContext.class), eq("metalake_demo"), isNull(), isNull(), isNull()); String output = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); assertEquals( output, @@ -479,7 +462,7 @@ void testTopicDetailsCommandWithoutSchema() { assertThrows(RuntimeException.class, commandLine::handleCommandLine); verify(commandLine, never()) .newTopicDetails( - GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "catalog", null, null); + any(CommandContext.class), eq("metalake_demo"), eq("catalog"), isNull(), isNull()); String output = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); assertEquals( output, @@ -505,7 +488,7 @@ void testTopicDetailsCommandWithoutTopic() { assertThrows(RuntimeException.class, commandLine::handleCommandLine); verify(commandLine, never()) .newTopicDetails( - GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "schema", null, null); + any(CommandContext.class), eq("metalake_demo"), eq("schema"), isNull(), isNull()); String output = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); assertEquals( output, From 918fc49b775f463445a619e86aa0c15393dea9b3 Mon Sep 17 00:00:00 2001 From: Lord of Abyss <103809695+Abyss-lord@users.noreply.github.com> Date: Tue, 11 Feb 2025 13:50:14 +0800 Subject: [PATCH 21/33] [#6420] improve(CLI): Add column command context CLI (#6436) ### What changes were proposed in this pull request? Add column command context CLI ### Why are the changes needed? Fix: #6420 ### Does this PR introduce _any_ user-facing change? No ### How was this patch tested? local test. --- .../gravitino/cli/ColumnCommandHandler.java | 38 +-- .../gravitino/cli/GravitinoCommandLine.java | 2 +- .../gravitino/cli/TestableCommandLine.java | 58 ++--- .../gravitino/cli/commands/AddColumn.java | 11 +- .../gravitino/cli/commands/ColumnAudit.java | 26 +- .../gravitino/cli/commands/DeleteColumn.java | 11 +- .../gravitino/cli/commands/ListColumns.java | 18 +- .../commands/UpdateColumnAutoIncrement.java | 11 +- .../cli/commands/UpdateColumnComment.java | 11 +- .../cli/commands/UpdateColumnDatatype.java | 11 +- .../cli/commands/UpdateColumnDefault.java | 11 +- .../cli/commands/UpdateColumnName.java | 11 +- .../cli/commands/UpdateColumnNullability.java | 11 +- .../cli/commands/UpdateColumnPosition.java | 11 +- .../gravitino/cli/TestColumnCommands.java | 235 +++++++++--------- 15 files changed, 217 insertions(+), 259 deletions(-) diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/ColumnCommandHandler.java b/clients/cli/src/main/java/org/apache/gravitino/cli/ColumnCommandHandler.java index c0775dae966..58398585c31 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/ColumnCommandHandler.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/ColumnCommandHandler.java @@ -29,8 +29,7 @@ public class ColumnCommandHandler extends CommandHandler { private final GravitinoCommandLine gravitinoCommandLine; private final CommandLine line; private final String command; - private final boolean ignore; - private final String url; + private final CommandContext context; private final FullName name; private final String metalake; private final String catalog; @@ -44,16 +43,19 @@ public class ColumnCommandHandler extends CommandHandler { * @param gravitinoCommandLine The Gravitino command line instance. * @param line The command line arguments. * @param command The command to execute. - * @param ignore Ignore server version mismatch. + * @param context The command context. */ public ColumnCommandHandler( - GravitinoCommandLine gravitinoCommandLine, CommandLine line, String command, boolean ignore) { + GravitinoCommandLine gravitinoCommandLine, + CommandLine line, + String command, + CommandContext context) { this.gravitinoCommandLine = gravitinoCommandLine; this.line = line; this.command = command; - this.ignore = ignore; + this.context = context; - this.url = getUrl(line); + this.context.setUrl(getUrl(line)); this.name = new FullName(line); this.metalake = name.getMetalakeName(); this.catalog = name.getCatalogName(); @@ -120,7 +122,7 @@ private boolean executeCommand() { private void handleDetailsCommand() { if (line.hasOption(GravitinoOptions.AUDIT)) { gravitinoCommandLine - .newColumnAudit(url, ignore, metalake, catalog, schema, table, column) + .newColumnAudit(context, metalake, catalog, schema, table, column) .validate() .handle(); } else { @@ -144,8 +146,7 @@ private void handleCreateCommand() { gravitinoCommandLine .newAddColumn( - url, - ignore, + context, metalake, catalog, schema, @@ -164,7 +165,7 @@ private void handleCreateCommand() { /** Handles the "DELETE" command. */ private void handleDeleteCommand() { gravitinoCommandLine - .newDeleteColumn(url, ignore, metalake, catalog, schema, table, column) + .newDeleteColumn(context, metalake, catalog, schema, table, column) .validate() .handle(); } @@ -174,36 +175,35 @@ private void handleUpdateCommand() { if (line.hasOption(GravitinoOptions.COMMENT)) { String comment = line.getOptionValue(GravitinoOptions.COMMENT); gravitinoCommandLine - .newUpdateColumnComment(url, ignore, metalake, catalog, schema, table, column, comment) + .newUpdateColumnComment(context, metalake, catalog, schema, table, column, comment) .validate() .handle(); } if (line.hasOption(GravitinoOptions.RENAME)) { String newName = line.getOptionValue(GravitinoOptions.RENAME); gravitinoCommandLine - .newUpdateColumnName(url, ignore, metalake, catalog, schema, table, column, newName) + .newUpdateColumnName(context, metalake, catalog, schema, table, column, newName) .validate() .handle(); } if (line.hasOption(GravitinoOptions.DATATYPE) && !line.hasOption(GravitinoOptions.DEFAULT)) { String datatype = line.getOptionValue(GravitinoOptions.DATATYPE); gravitinoCommandLine - .newUpdateColumnDatatype(url, ignore, metalake, catalog, schema, table, column, datatype) + .newUpdateColumnDatatype(context, metalake, catalog, schema, table, column, datatype) .validate() .handle(); } if (line.hasOption(GravitinoOptions.POSITION)) { String position = line.getOptionValue(GravitinoOptions.POSITION); gravitinoCommandLine - .newUpdateColumnPosition(url, ignore, metalake, catalog, schema, table, column, position) + .newUpdateColumnPosition(context, metalake, catalog, schema, table, column, position) .validate() .handle(); } if (line.hasOption(GravitinoOptions.NULL)) { boolean nullable = line.getOptionValue(GravitinoOptions.NULL).equals("true"); gravitinoCommandLine - .newUpdateColumnNullability( - url, ignore, metalake, catalog, schema, table, column, nullable) + .newUpdateColumnNullability(context, metalake, catalog, schema, table, column, nullable) .validate() .handle(); } @@ -211,7 +211,7 @@ private void handleUpdateCommand() { boolean autoIncrement = line.getOptionValue(GravitinoOptions.AUTO).equals("true"); gravitinoCommandLine .newUpdateColumnAutoIncrement( - url, ignore, metalake, catalog, schema, table, column, autoIncrement) + context, metalake, catalog, schema, table, column, autoIncrement) .validate() .handle(); } @@ -220,7 +220,7 @@ private void handleUpdateCommand() { String dataType = line.getOptionValue(GravitinoOptions.DATATYPE); gravitinoCommandLine .newUpdateColumnDefault( - url, ignore, metalake, catalog, schema, table, column, defaultValue, dataType) + context, metalake, catalog, schema, table, column, defaultValue, dataType) .validate() .handle(); } @@ -229,7 +229,7 @@ private void handleUpdateCommand() { /** Handles the "LIST" command. */ private void handleListCommand() { gravitinoCommandLine - .newListColumns(url, ignore, metalake, catalog, schema, table) + .newListColumns(context, metalake, catalog, schema, table) .validate() .handle(); } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/GravitinoCommandLine.java b/clients/cli/src/main/java/org/apache/gravitino/cli/GravitinoCommandLine.java index b5e5838f1bb..7230604655d 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/GravitinoCommandLine.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/GravitinoCommandLine.java @@ -116,7 +116,7 @@ private void executeCommand() { } else if (line.hasOption(GravitinoOptions.OWNER)) { new OwnerCommandHandler(this, line, command, ignore, entity).handle(); } else if (entity.equals(CommandEntities.COLUMN)) { - new ColumnCommandHandler(this, line, command, ignore).handle(); + new ColumnCommandHandler(this, line, command, context).handle(); } else if (entity.equals(CommandEntities.TABLE)) { new TableCommandHandler(this, line, command, context).handle(); } else if (entity.equals(CommandEntities.SCHEMA)) { diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/TestableCommandLine.java b/clients/cli/src/main/java/org/apache/gravitino/cli/TestableCommandLine.java index 8a64c6c551e..b27e24fde9e 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/TestableCommandLine.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/TestableCommandLine.java @@ -538,19 +538,18 @@ protected UntagEntity newUntagEntity( } protected ColumnAudit newColumnAudit( - String url, - boolean ignore, + CommandContext context, String metalake, String catalog, String schema, String table, String column) { - return new ColumnAudit(url, ignore, metalake, catalog, schema, table, column); + return new ColumnAudit(context, metalake, catalog, schema, table, column); } protected ListColumns newListColumns( - String url, boolean ignore, String metalake, String catalog, String schema, String table) { - return new ListColumns(url, ignore, metalake, catalog, schema, table); + CommandContext context, String metalake, String catalog, String schema, String table) { + return new ListColumns(context, metalake, catalog, schema, table); } protected SetOwner newSetOwner( @@ -703,8 +702,7 @@ protected RemoveFilesetProperty newRemoveFilesetProperty( } protected AddColumn newAddColumn( - String url, - boolean ignore, + CommandContext context, String metalake, String catalog, String schema, @@ -717,8 +715,7 @@ protected AddColumn newAddColumn( boolean autoIncrement, String defaultValue) { return new AddColumn( - url, - ignore, + context, metalake, catalog, schema, @@ -733,82 +730,72 @@ protected AddColumn newAddColumn( } protected DeleteColumn newDeleteColumn( - String url, - boolean ignore, + CommandContext context, String metalake, String catalog, String schema, String table, String column) { - return new DeleteColumn(url, ignore, metalake, catalog, schema, table, column); + return new DeleteColumn(context, metalake, catalog, schema, table, column); } protected UpdateColumnComment newUpdateColumnComment( - String url, - boolean ignore, + CommandContext context, String metalake, String catalog, String schema, String table, String column, String comment) { - return new UpdateColumnComment(url, ignore, metalake, catalog, schema, table, column, comment); + return new UpdateColumnComment(context, metalake, catalog, schema, table, column, comment); } protected UpdateColumnName newUpdateColumnName( - String url, - boolean ignore, + CommandContext context, String metalake, String catalog, String schema, String table, String column, String rename) { - return new UpdateColumnName(url, ignore, metalake, catalog, schema, table, column, rename); + return new UpdateColumnName(context, metalake, catalog, schema, table, column, rename); } protected UpdateColumnDatatype newUpdateColumnDatatype( - String url, - boolean ignore, + CommandContext context, String metalake, String catalog, String schema, String table, String column, String datatype) { - return new UpdateColumnDatatype( - url, ignore, metalake, catalog, schema, table, column, datatype); + return new UpdateColumnDatatype(context, metalake, catalog, schema, table, column, datatype); } protected UpdateColumnPosition newUpdateColumnPosition( - String url, - boolean ignore, + CommandContext context, String metalake, String catalog, String schema, String table, String column, String position) { - return new UpdateColumnPosition( - url, ignore, metalake, catalog, schema, table, column, position); + return new UpdateColumnPosition(context, metalake, catalog, schema, table, column, position); } protected UpdateColumnNullability newUpdateColumnNullability( - String url, - boolean ignore, + CommandContext context, String metalake, String catalog, String schema, String table, String column, boolean nullable) { - return new UpdateColumnNullability( - url, ignore, metalake, catalog, schema, table, column, nullable); + return new UpdateColumnNullability(context, metalake, catalog, schema, table, column, nullable); } protected UpdateColumnAutoIncrement newUpdateColumnAutoIncrement( - String url, - boolean ignore, + CommandContext context, String metalake, String catalog, String schema, @@ -816,12 +803,11 @@ protected UpdateColumnAutoIncrement newUpdateColumnAutoIncrement( String column, boolean autoIncrement) { return new UpdateColumnAutoIncrement( - url, ignore, metalake, catalog, schema, table, column, autoIncrement); + context, metalake, catalog, schema, table, column, autoIncrement); } protected UpdateColumnDefault newUpdateColumnDefault( - String url, - boolean ignore, + CommandContext context, String metalake, String catalog, String schema, @@ -830,7 +816,7 @@ protected UpdateColumnDefault newUpdateColumnDefault( String defaultValue, String dataType) { return new UpdateColumnDefault( - url, ignore, metalake, catalog, schema, table, column, defaultValue, dataType); + context, metalake, catalog, schema, table, column, defaultValue, dataType); } protected CreateTable newCreateTable( diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/AddColumn.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/AddColumn.java index 71603607166..6227f695d96 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/AddColumn.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/AddColumn.java @@ -20,6 +20,7 @@ package org.apache.gravitino.cli.commands; import org.apache.gravitino.NameIdentifier; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.DefaultConverter; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.cli.ParseType; @@ -49,8 +50,7 @@ public class AddColumn extends Command { /** * Adds an optional column to a table. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param catalog The name of the catalog. * @param schema The name of the schema. @@ -64,8 +64,7 @@ public class AddColumn extends Command { * @param defaultValue Default value of the column (optional). */ public AddColumn( - String url, - boolean ignoreVersions, + CommandContext context, String metalake, String catalog, String schema, @@ -77,7 +76,7 @@ public AddColumn( boolean nullable, boolean autoIncrement, String defaultValue) { - super(url, ignoreVersions); + super(context); this.metalake = metalake; this.catalog = catalog; this.schema = schema; @@ -123,6 +122,6 @@ public void handle() { exitWithError(exp.getMessage()); } - System.out.println(column + " added to table " + table + "."); + printInformation(column + " added to table " + table + "."); } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ColumnAudit.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ColumnAudit.java index db17f6551f8..7cee2f9eb64 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ColumnAudit.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ColumnAudit.java @@ -20,6 +20,7 @@ package org.apache.gravitino.cli.commands; import org.apache.gravitino.Catalog; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchCatalogException; @@ -38,8 +39,7 @@ public class ColumnAudit extends AuditCommand { /** * Displays the audit information of a column. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param catalog The name of the catalog. * @param schema The name of the schema. @@ -47,14 +47,13 @@ public class ColumnAudit extends AuditCommand { * @param column The name of the column. */ public ColumnAudit( - String url, - boolean ignoreVersions, + CommandContext context, String metalake, String catalog, String schema, String table, String column) { - super(url, ignoreVersions); + super(context); this.metalake = metalake; this.catalog = catalog; this.schema = schema; @@ -65,25 +64,20 @@ public ColumnAudit( /** Displays the audit information of a specified column. */ @Override public void handle() { - Catalog result; + Catalog result = null; try (GravitinoClient client = buildClient(metalake)) { result = client.loadCatalog(this.catalog); } catch (NoSuchMetalakeException err) { - System.err.println(ErrorMessages.UNKNOWN_METALAKE); - return; + exitWithError(ErrorMessages.UNKNOWN_METALAKE); } catch (NoSuchCatalogException err) { - System.err.println(ErrorMessages.UNKNOWN_CATALOG); - return; + exitWithError(ErrorMessages.UNKNOWN_CATALOG); } catch (NoSuchTableException err) { - System.err.println(ErrorMessages.UNKNOWN_TABLE); - return; + exitWithError(ErrorMessages.UNKNOWN_TABLE); } catch (NoSuchColumnException err) { - System.err.println(ErrorMessages.UNKNOWN_COLUMN); - return; + exitWithError(ErrorMessages.UNKNOWN_COLUMN); } catch (Exception exp) { - System.err.println(exp.getMessage()); - return; + exitWithError(exp.getMessage()); } if (result != null) { diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/DeleteColumn.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/DeleteColumn.java index 17ac22d1284..34ed73b2ee2 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/DeleteColumn.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/DeleteColumn.java @@ -20,6 +20,7 @@ package org.apache.gravitino.cli.commands; import org.apache.gravitino.NameIdentifier; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchCatalogException; @@ -40,8 +41,7 @@ public class DeleteColumn extends Command { /** * Delete a column. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param catalog The name of the catalog. * @param schema The name of the schema. @@ -49,14 +49,13 @@ public class DeleteColumn extends Command { * @param column The name of the column. */ public DeleteColumn( - String url, - boolean ignoreVersions, + CommandContext context, String metalake, String catalog, String schema, String table, String column) { - super(url, ignoreVersions); + super(context); this.metalake = metalake; this.catalog = catalog; this.schema = schema; @@ -88,6 +87,6 @@ public void handle() { exitWithError(exp.getMessage()); } - System.out.println(column + " deleted."); + printInformation(column + " deleted."); } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListColumns.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListColumns.java index e1d8eac2086..f638caf687f 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListColumns.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListColumns.java @@ -21,6 +21,7 @@ import com.google.common.base.Joiner; import org.apache.gravitino.NameIdentifier; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.exceptions.NoSuchTableException; import org.apache.gravitino.rel.Column; @@ -34,21 +35,15 @@ public class ListColumns extends TableCommand { /** * Displays the details of a table's columns. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param catalog The name of the catalog. * @param schema The name of the schenma. * @param table The name of the table. */ public ListColumns( - String url, - boolean ignoreVersions, - String metalake, - String catalog, - String schema, - String table) { - super(url, ignoreVersions, metalake, catalog); + CommandContext context, String metalake, String catalog, String schema, String table) { + super(context, metalake, catalog); this.schema = schema; this.table = table; } @@ -62,9 +57,8 @@ public void handle() { NameIdentifier name = NameIdentifier.of(schema, table); columns = tableCatalog().loadTable(name).columns(); } catch (NoSuchTableException noSuchTableException) { - System.err.println( + exitWithError( ErrorMessages.UNKNOWN_TABLE + Joiner.on(".").join(metalake, catalog, schema, table)); - return; } catch (Exception exp) { exitWithError(exp.getMessage()); } @@ -94,6 +88,6 @@ public void handle() { + System.lineSeparator()); } - System.out.print(all); + printResults(all.toString()); } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateColumnAutoIncrement.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateColumnAutoIncrement.java index 99b27b200e8..44b114e0a27 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateColumnAutoIncrement.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateColumnAutoIncrement.java @@ -20,6 +20,7 @@ package org.apache.gravitino.cli.commands; import org.apache.gravitino.NameIdentifier; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchCatalogException; @@ -42,8 +43,7 @@ public class UpdateColumnAutoIncrement extends Command { /** * Update the auto increment of a column. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param catalog The name of the catalog. * @param schema The name of the schema. @@ -52,15 +52,14 @@ public class UpdateColumnAutoIncrement extends Command { * @param autoincrement True if the column can be null, false if it must have non-null values. */ public UpdateColumnAutoIncrement( - String url, - boolean ignoreVersions, + CommandContext context, String metalake, String catalog, String schema, String table, String column, boolean autoincrement) { - super(url, ignoreVersions); + super(context); this.metalake = metalake; this.catalog = catalog; this.schema = schema; @@ -94,6 +93,6 @@ public void handle() { exitWithError(exp.getMessage()); } - System.out.println(column + " auto increment changed to " + autoincrement + "."); + printInformation(column + " auto increment changed to " + autoincrement + "."); } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateColumnComment.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateColumnComment.java index 2c7f05a8fd9..85413f1e8f8 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateColumnComment.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateColumnComment.java @@ -20,6 +20,7 @@ package org.apache.gravitino.cli.commands; import org.apache.gravitino.NameIdentifier; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchCatalogException; @@ -42,8 +43,7 @@ public class UpdateColumnComment extends Command { /** * Update the comment of a column. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param catalog The name of the catalog. * @param schema The name of the schema. @@ -52,15 +52,14 @@ public class UpdateColumnComment extends Command { * @param comment New column comment. */ public UpdateColumnComment( - String url, - boolean ignoreVersions, + CommandContext context, String metalake, String catalog, String schema, String table, String column, String comment) { - super(url, ignoreVersions); + super(context); this.metalake = metalake; this.catalog = catalog; this.schema = schema; @@ -94,6 +93,6 @@ public void handle() { exitWithError(exp.getMessage()); } - System.out.println(column + " comment changed."); + printInformation(column + " comment changed."); } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateColumnDatatype.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateColumnDatatype.java index 6eac9da7ef9..29e44b648d1 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateColumnDatatype.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateColumnDatatype.java @@ -20,6 +20,7 @@ package org.apache.gravitino.cli.commands; import org.apache.gravitino.NameIdentifier; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.cli.ParseType; import org.apache.gravitino.client.GravitinoClient; @@ -44,8 +45,7 @@ public class UpdateColumnDatatype extends Command { /** * Update the data type of a column. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param catalog The name of the catalog. * @param schema The name of the schema. @@ -54,15 +54,14 @@ public class UpdateColumnDatatype extends Command { * @param datatype The new data type name. */ public UpdateColumnDatatype( - String url, - boolean ignoreVersions, + CommandContext context, String metalake, String catalog, String schema, String table, String column, String datatype) { - super(url, ignoreVersions); + super(context); this.metalake = metalake; this.catalog = catalog; this.schema = schema; @@ -97,6 +96,6 @@ public void handle() { exitWithError(exp.getMessage()); } - System.out.println(column + " datatype changed to " + datatype + "."); + printInformation(column + " datatype changed to " + datatype + "."); } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateColumnDefault.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateColumnDefault.java index 976cf623054..cf8a49c47cd 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateColumnDefault.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateColumnDefault.java @@ -20,6 +20,7 @@ package org.apache.gravitino.cli.commands; import org.apache.gravitino.NameIdentifier; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.DefaultConverter; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; @@ -44,8 +45,7 @@ public class UpdateColumnDefault extends Command { /** * Update the default type of a column. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param catalog The name of the catalog. * @param schema The name of the schema. @@ -55,8 +55,7 @@ public class UpdateColumnDefault extends Command { * @param dataType The new default data type. */ public UpdateColumnDefault( - String url, - boolean ignoreVersions, + CommandContext context, String metalake, String catalog, String schema, @@ -64,7 +63,7 @@ public UpdateColumnDefault( String column, String defaultValue, String dataType) { - super(url, ignoreVersions); + super(context); this.metalake = metalake; this.catalog = catalog; this.schema = schema; @@ -101,7 +100,7 @@ public void handle() { exitWithError(exp.getMessage()); } - System.out.println(column + " default changed."); + printInformation(column + " default changed."); } @Override diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateColumnName.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateColumnName.java index 124223dbd29..74865f4c44d 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateColumnName.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateColumnName.java @@ -20,6 +20,7 @@ package org.apache.gravitino.cli.commands; import org.apache.gravitino.NameIdentifier; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchCatalogException; @@ -42,8 +43,7 @@ public class UpdateColumnName extends Command { /** * Update the name of a column. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param catalog The name of the catalog. * @param schema The name of the schema. @@ -52,15 +52,14 @@ public class UpdateColumnName extends Command { * @param name The new column name. */ public UpdateColumnName( - String url, - boolean ignoreVersions, + CommandContext context, String metalake, String catalog, String schema, String table, String column, String name) { - super(url, ignoreVersions); + super(context); this.metalake = metalake; this.catalog = catalog; this.schema = schema; @@ -94,6 +93,6 @@ public void handle() { exitWithError(exp.getMessage()); } - System.out.println(column + " name changed."); + printInformation(column + " name changed."); } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateColumnNullability.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateColumnNullability.java index 868b426868f..dce5c23aa20 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateColumnNullability.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateColumnNullability.java @@ -20,6 +20,7 @@ package org.apache.gravitino.cli.commands; import org.apache.gravitino.NameIdentifier; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchCatalogException; @@ -42,8 +43,7 @@ public class UpdateColumnNullability extends Command { /** * Update the nullability of a column. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param catalog The name of the catalog. * @param schema The name of the schema. @@ -52,15 +52,14 @@ public class UpdateColumnNullability extends Command { * @param nullability True if the column can be null, false if it must have non-null values. */ public UpdateColumnNullability( - String url, - boolean ignoreVersions, + CommandContext context, String metalake, String catalog, String schema, String table, String column, boolean nullability) { - super(url, ignoreVersions); + super(context); this.metalake = metalake; this.catalog = catalog; this.schema = schema; @@ -94,6 +93,6 @@ public void handle() { exitWithError(exp.getMessage()); } - System.out.println(column + " nullability changed to " + nullability + "."); + printInformation(column + " nullability changed to " + nullability + "."); } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateColumnPosition.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateColumnPosition.java index 4bbe809d448..ba79aece7c8 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateColumnPosition.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateColumnPosition.java @@ -20,6 +20,7 @@ package org.apache.gravitino.cli.commands; import org.apache.gravitino.NameIdentifier; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.cli.PositionConverter; import org.apache.gravitino.client.GravitinoClient; @@ -43,8 +44,7 @@ public class UpdateColumnPosition extends Command { /** * Update the position of a column. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param catalog The name of the catalog. * @param schema The name of the schema. @@ -53,15 +53,14 @@ public class UpdateColumnPosition extends Command { * @param position The new position of the column. */ public UpdateColumnPosition( - String url, - boolean ignoreVersions, + CommandContext context, String metalake, String catalog, String schema, String table, String column, String position) { - super(url, ignoreVersions); + super(context); this.metalake = metalake; this.catalog = catalog; this.schema = schema; @@ -97,6 +96,6 @@ public void handle() { exitWithError(exp.getMessage()); } - System.out.println(column + " position changed to " + position + "."); + printInformation(column + " position changed to " + position + "."); } } diff --git a/clients/cli/src/test/java/org/apache/gravitino/cli/TestColumnCommands.java b/clients/cli/src/test/java/org/apache/gravitino/cli/TestColumnCommands.java index 31a3139482c..521b1e2b61d 100644 --- a/clients/cli/src/test/java/org/apache/gravitino/cli/TestColumnCommands.java +++ b/clients/cli/src/test/java/org/apache/gravitino/cli/TestColumnCommands.java @@ -21,6 +21,10 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThrows; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; @@ -92,7 +96,11 @@ void testListColumnsCommand() { doReturn(mockList) .when(commandLine) .newListColumns( - GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "catalog", "schema", "users"); + any(CommandContext.class), + eq("metalake_demo"), + eq("catalog"), + eq("schema"), + eq("users")); doReturn(mockList).when(mockList).validate(); commandLine.handleCommandLine(); verify(mockList).handle(); @@ -114,13 +122,12 @@ void testColumnAuditCommand() { doReturn(mockAudit) .when(commandLine) .newColumnAudit( - GravitinoCommandLine.DEFAULT_URL, - false, - "metalake_demo", - "catalog", - "schema", - "users", - "name"); + any(CommandContext.class), + eq("metalake_demo"), + eq("catalog"), + eq("schema"), + eq("users"), + eq("name")); doReturn(mockAudit).when(mockAudit).validate(); commandLine.handleCommandLine(); verify(mockAudit).handle(); @@ -142,14 +149,12 @@ void testColumnDetailsCommand() { assertThrows(RuntimeException.class, commandLine::handleCommandLine); verify(commandLine, never()) .newColumnAudit( - GravitinoCommandLine.DEFAULT_URL, - false, - "metalake_demo", - "catalog", - "schema", - "users", - "name"); - + any(CommandContext.class), + eq("metalake_demo"), + eq("catalog"), + eq("schema"), + eq("users"), + eq("name")); String output = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); assertEquals(output, ErrorMessages.UNSUPPORTED_ACTION); } @@ -176,19 +181,18 @@ void testAddColumn() { doReturn(mockAddColumn) .when(commandLine) .newAddColumn( - GravitinoCommandLine.DEFAULT_URL, - false, - "metalake_demo", - "catalog", - "schema", - "users", - "name", - "varchar(100)", - "comment", - null, - true, - false, - null); + any(CommandContext.class), + eq("metalake_demo"), + eq("catalog"), + eq("schema"), + eq("users"), + eq("name"), + eq("varchar(100)"), + eq("comment"), + isNull(), + anyBoolean(), + anyBoolean(), + isNull()); doReturn(mockAddColumn).when(mockAddColumn).validate(); commandLine.handleCommandLine(); verify(mockAddColumn).handle(); @@ -210,13 +214,12 @@ void testDeleteColumn() { doReturn(mockDelete) .when(commandLine) .newDeleteColumn( - GravitinoCommandLine.DEFAULT_URL, - false, - "metalake_demo", - "catalog", - "schema", - "users", - "name"); + any(CommandContext.class), + eq("metalake_demo"), + eq("catalog"), + eq("schema"), + eq("users"), + eq("name")); doReturn(mockDelete).when(mockDelete).validate(); commandLine.handleCommandLine(); verify(mockDelete).handle(); @@ -242,14 +245,13 @@ void testUpdateColumnComment() { doReturn(mockUpdateColumn) .when(commandLine) .newUpdateColumnComment( - GravitinoCommandLine.DEFAULT_URL, - false, - "metalake_demo", - "catalog", - "schema", - "users", - "name", - "new comment"); + any(CommandContext.class), + eq("metalake_demo"), + eq("catalog"), + eq("schema"), + eq("users"), + eq("name"), + eq("new comment")); doReturn(mockUpdateColumn).when(mockUpdateColumn).validate(); commandLine.handleCommandLine(); verify(mockUpdateColumn).handle(); @@ -275,14 +277,13 @@ void testUpdateColumnName() { doReturn(mockUpdateName) .when(commandLine) .newUpdateColumnName( - GravitinoCommandLine.DEFAULT_URL, - false, - "metalake_demo", - "catalog", - "schema", - "users", - "name", - "renamed"); + any(CommandContext.class), + eq("metalake_demo"), + eq("catalog"), + eq("schema"), + eq("users"), + eq("name"), + eq("renamed")); doReturn(mockUpdateName).when(mockUpdateName).validate(); commandLine.handleCommandLine(); verify(mockUpdateName).handle(); @@ -308,14 +309,13 @@ void testUpdateColumnDatatype() { doReturn(mockUpdateDatatype) .when(commandLine) .newUpdateColumnDatatype( - GravitinoCommandLine.DEFAULT_URL, - false, - "metalake_demo", - "catalog", - "schema", - "users", - "name", - "varchar(250)"); + any(CommandContext.class), + eq("metalake_demo"), + eq("catalog"), + eq("schema"), + eq("users"), + eq("name"), + eq("varchar(250)")); doReturn(mockUpdateDatatype).when(mockUpdateDatatype).validate(); commandLine.handleCommandLine(); verify(mockUpdateDatatype).handle(); @@ -341,14 +341,13 @@ void testUpdateColumnPosition() { doReturn(mockUpdatePosition) .when(commandLine) .newUpdateColumnPosition( - GravitinoCommandLine.DEFAULT_URL, - false, - "metalake_demo", - "catalog", - "schema", - "users", - "name", - "first"); + any(CommandContext.class), + eq("metalake_demo"), + eq("catalog"), + eq("schema"), + eq("users"), + eq("name"), + eq("first")); doReturn(mockUpdatePosition).when(mockUpdatePosition).validate(); commandLine.handleCommandLine(); verify(mockUpdatePosition).handle(); @@ -373,14 +372,13 @@ void testUpdateColumnNullability() { doReturn(mockUpdateNull) .when(commandLine) .newUpdateColumnNullability( - GravitinoCommandLine.DEFAULT_URL, - false, - "metalake_demo", - "catalog", - "schema", - "users", - "name", - true); + any(CommandContext.class), + eq("metalake_demo"), + eq("catalog"), + eq("schema"), + eq("users"), + eq("name"), + anyBoolean()); doReturn(mockUpdateNull).when(mockUpdateNull).validate(); commandLine.handleCommandLine(); verify(mockUpdateNull).handle(); @@ -405,14 +403,13 @@ void testUpdateColumnAutoIncrement() { doReturn(mockUpdateAuto) .when(commandLine) .newUpdateColumnAutoIncrement( - GravitinoCommandLine.DEFAULT_URL, - false, - "metalake_demo", - "catalog", - "schema", - "users", - "name", - true); + any(CommandContext.class), + eq("metalake_demo"), + eq("catalog"), + eq("schema"), + eq("users"), + eq("name"), + anyBoolean()); doReturn(mockUpdateAuto).when(mockUpdateAuto).validate(); commandLine.handleCommandLine(); verify(mockUpdateAuto).handle(); @@ -440,15 +437,14 @@ void testUpdateColumnDefault() { doReturn(mockUpdateDefault) .when(commandLine) .newUpdateColumnDefault( - GravitinoCommandLine.DEFAULT_URL, - false, - "metalake_demo", - "catalog", - "schema", - "users", - "name", - "Fred Smith", - "varchar(100)"); + any(CommandContext.class), + eq("metalake_demo"), + eq("catalog"), + eq("schema"), + eq("users"), + eq("name"), + eq("Fred Smith"), + eq("varchar(100)")); doReturn(mockUpdateDefault).when(mockUpdateDefault).validate(); commandLine.handleCommandLine(); verify(mockUpdateDefault).handle(); @@ -457,18 +453,12 @@ void testUpdateColumnDefault() { @Test void testUpdateColumnDefaultWithoutDataType() { Main.useExit = false; + CommandContext mockContext = mock(CommandContext.class); + when(mockContext.url()).thenReturn(GravitinoCommandLine.DEFAULT_URL); UpdateColumnDefault spyUpdate = spy( new UpdateColumnDefault( - GravitinoCommandLine.DEFAULT_URL, - false, - "metalake_demo", - "catalog", - "schema", - "user", - "name", - "", - null)); + mockContext, "metalake_demo", "catalog", "schema", "user", "name", "", null)); assertThrows(RuntimeException.class, spyUpdate::validate); verify(spyUpdate, never()).handle(); @@ -491,7 +481,7 @@ void testDeleteColumnCommandWithoutCatalog() { assertThrows(RuntimeException.class, commandLine::handleCommandLine); verify(commandLine, never()) .newDeleteColumn( - GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", null, null, null, null); + any(CommandContext.class), eq("metalake_demo"), isNull(), isNull(), isNull(), isNull()); String output = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); assertEquals( output, @@ -523,7 +513,12 @@ void testDeleteColumnCommandWithoutSchema() { assertThrows(RuntimeException.class, commandLine::handleCommandLine); verify(commandLine, never()) .newDeleteColumn( - GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "catalog", null, null, null); + any(CommandContext.class), + eq("metalake_demo"), + eq("catalog"), + isNull(), + isNull(), + isNull()); String output = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); assertEquals( output, @@ -552,13 +547,12 @@ void testDeleteColumnCommandWithoutTable() { assertThrows(RuntimeException.class, commandLine::handleCommandLine); verify(commandLine, never()) .newDeleteColumn( - GravitinoCommandLine.DEFAULT_URL, - false, - "metalake_demo", - "catalog", - "schema", - null, - null); + any(CommandContext.class), + eq("metalake_demo"), + eq("catalog"), + eq("schema"), + isNull(), + isNull()); String output = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); assertEquals( output, @@ -584,13 +578,12 @@ void testDeleteColumnCommandWithoutColumn() { assertThrows(RuntimeException.class, commandLine::handleCommandLine); verify(commandLine, never()) .newDeleteColumn( - GravitinoCommandLine.DEFAULT_URL, - false, - "metalake_demo", - "catalog", - "schema", - "users", - null); + any(CommandContext.class), + eq("metalake_demo"), + eq("catalog"), + eq("schema"), + eq("users"), + isNull()); String output = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); assertEquals( output, @@ -615,7 +608,7 @@ void testListColumnCommandWithoutCatalog() { assertThrows(RuntimeException.class, commandLine::handleCommandLine); verify(commandLine, never()) .newListColumns( - GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "catalog", "schema", null); + any(CommandContext.class), eq("metalake_demo"), eq("catalog"), eq("schema"), isNull()); String output = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); assertEquals( output, @@ -644,7 +637,7 @@ void testListColumnCommandWithoutSchema() { assertThrows(RuntimeException.class, commandLine::handleCommandLine); verify(commandLine, never()) .newListColumns( - GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "catalog", "schema", null); + any(CommandContext.class), eq("metalake_demo"), eq("catalog"), eq("schema"), isNull()); String output = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); assertEquals( output, @@ -670,7 +663,7 @@ void testListColumnCommandWithoutTable() { assertThrows(RuntimeException.class, commandLine::handleCommandLine); verify(commandLine, never()) .newListColumns( - GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "catalog", "schema", null); + any(CommandContext.class), eq("metalake_demo"), eq("catalog"), eq("schema"), isNull()); String output = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); assertEquals( output, From e7ab4414eacae097c35aab7a56b576358d55d9e3 Mon Sep 17 00:00:00 2001 From: YangJie Date: Tue, 11 Feb 2025 20:36:51 +0800 Subject: [PATCH 22/33] [MINOR] docs: Fix the description of `Multi-engine support` in `overview.md` (#6439) ### What changes were proposed in this pull request? This PR fixes the description of the `Multi-engine support` section in `overview.md`, as Gravitino now supports connectors for Apache Spark and Apache Flink. ### Why are the changes needed? Gravitino now supports connectors for Apache Spark and Apache Flink. ### Does this PR introduce _any_ user-facing change? No ### How was this patch tested? manual review --- docs/overview.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/overview.md b/docs/overview.md index 17d0ee48e30..e5f1dd5ac18 100644 --- a/docs/overview.md +++ b/docs/overview.md @@ -60,8 +60,9 @@ Gravitino supports different query engines to access the metadata. Currently, it [Trino](https://trino.io/), users can use Trino to query the metadata and data without needing to change the existing SQL dialects. -In the meantime, other query engine support is on the roadmap, including -[Apache Spark](https://spark.apache.org/), [Apache Flink](https://flink.apache.org/) and others. +In addition, Gravitino has expanded its support to include [Apache Spark](https://spark.apache.org/) +and [Apache Flink](https://flink.apache.org/), among other query engines. Further enhancements and +additions to the supported query engines are also on the roadmap. ### AI asset management From 734993e1bf70fbba18deabf92347dd833556b2d8 Mon Sep 17 00:00:00 2001 From: Lord of Abyss <103809695+Abyss-lord@users.noreply.github.com> Date: Wed, 12 Feb 2025 07:32:18 +0800 Subject: [PATCH 23/33] [#6423] improve(CLI): Add tags command context CLI (#6435) ### What changes were proposed in this pull request? Add tags command context CLI ### Why are the changes needed? Fix: #6423 ### Does this PR introduce _any_ user-facing change? No ### How was this patch tested? local test --- .../gravitino/cli/GravitinoCommandLine.java | 2 +- .../gravitino/cli/TagCommandHandler.java | 43 ++--- .../gravitino/cli/TestableCommandLine.java | 54 +++--- .../gravitino/cli/commands/CreateTag.java | 15 +- .../gravitino/cli/commands/DeleteTag.java | 22 +-- .../gravitino/cli/commands/ListAllTags.java | 16 +- .../cli/commands/ListEntityTags.java | 10 +- .../cli/commands/ListTagProperties.java | 8 +- .../gravitino/cli/commands/RemoveAllTags.java | 16 +- .../cli/commands/RemoveTagProperty.java | 11 +- .../cli/commands/SetTagProperty.java | 15 +- .../gravitino/cli/commands/TagDetails.java | 10 +- .../gravitino/cli/commands/TagEntity.java | 11 +- .../gravitino/cli/commands/UntagEntity.java | 13 +- .../cli/commands/UpdateTagComment.java | 11 +- .../gravitino/cli/commands/UpdateTagName.java | 11 +- .../apache/gravitino/cli/TestTagCommands.java | 176 +++++++----------- 17 files changed, 197 insertions(+), 247 deletions(-) diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/GravitinoCommandLine.java b/clients/cli/src/main/java/org/apache/gravitino/cli/GravitinoCommandLine.java index 7230604655d..2bb40373a69 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/GravitinoCommandLine.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/GravitinoCommandLine.java @@ -134,7 +134,7 @@ private void executeCommand() { } else if (entity.equals(CommandEntities.GROUP)) { new GroupCommandHandler(this, line, command, ignore).handle(); } else if (entity.equals(CommandEntities.TAG)) { - new TagCommandHandler(this, line, command, ignore).handle(); + new TagCommandHandler(this, line, command, context).handle(); } else if (entity.equals(CommandEntities.ROLE)) { new RoleCommandHandler(this, line, command, ignore).handle(); } else if (entity.equals(CommandEntities.MODEL)) { diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/TagCommandHandler.java b/clients/cli/src/main/java/org/apache/gravitino/cli/TagCommandHandler.java index e274c271f9c..13567ac0648 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/TagCommandHandler.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/TagCommandHandler.java @@ -26,18 +26,20 @@ public class TagCommandHandler extends CommandHandler { private final GravitinoCommandLine gravitinoCommandLine; private final CommandLine line; private final String command; - private final boolean ignore; - private final String url; + private final CommandContext context; private String[] tags; private String metalake; public TagCommandHandler( - GravitinoCommandLine gravitinoCommandLine, CommandLine line, String command, boolean ignore) { + GravitinoCommandLine gravitinoCommandLine, + CommandLine line, + String command, + CommandContext context) { this.gravitinoCommandLine = gravitinoCommandLine; this.line = line; this.command = command; - this.ignore = ignore; - this.url = getUrl(line); + this.context = context; + this.context.setUrl(getUrl(line)); this.tags = line.getOptionValues(GravitinoOptions.TAG); if (tags != null) { @@ -107,27 +109,26 @@ private boolean executeCommand() { private void handleListCommand() { FullName name = new FullName(line); if (!name.hasCatalogName()) { - gravitinoCommandLine.newListTags(url, ignore, metalake).validate().handle(); + gravitinoCommandLine.newListTags(context, metalake).validate().handle(); } else { - gravitinoCommandLine.newListEntityTags(url, ignore, metalake, name).validate().handle(); + gravitinoCommandLine.newListEntityTags(context, metalake, name).validate().handle(); } } /** Handles the "DETAILS" command. */ private void handleDetailsCommand() { - gravitinoCommandLine.newTagDetails(url, ignore, metalake, getOneTag(tags)).validate().handle(); + gravitinoCommandLine.newTagDetails(context, metalake, getOneTag(tags)).validate().handle(); } /** Handles the "CREATE" command. */ private void handleCreateCommand() { String comment = line.getOptionValue(GravitinoOptions.COMMENT); - gravitinoCommandLine.newCreateTags(url, ignore, metalake, tags, comment).validate().handle(); + gravitinoCommandLine.newCreateTags(context, metalake, tags, comment).validate().handle(); } /** Handles the "DELETE" command. */ private void handleDeleteCommand() { - boolean forceDelete = line.hasOption(GravitinoOptions.FORCE); - gravitinoCommandLine.newDeleteTag(url, ignore, forceDelete, metalake, tags).validate().handle(); + gravitinoCommandLine.newDeleteTag(context, metalake, tags).validate().handle(); } /** Handles the "SET" command. */ @@ -136,12 +137,12 @@ private void handleSetCommand() { String value = line.getOptionValue(GravitinoOptions.VALUE); if (property == null && value == null) { gravitinoCommandLine - .newTagEntity(url, ignore, metalake, new FullName(line), tags) + .newTagEntity(context, metalake, new FullName(line), tags) .validate() .handle(); } else { gravitinoCommandLine - .newSetTagProperty(url, ignore, metalake, getOneTag(tags), property, value) + .newSetTagProperty(context, metalake, getOneTag(tags), property, value) .validate() .handle(); } @@ -152,20 +153,16 @@ private void handleRemoveCommand() { boolean isTag = line.hasOption(GravitinoOptions.TAG); FullName name = new FullName(line); if (!isTag) { - boolean forceRemove = line.hasOption(GravitinoOptions.FORCE); - gravitinoCommandLine - .newRemoveAllTags(url, ignore, metalake, name, forceRemove) - .validate() - .handle(); + gravitinoCommandLine.newRemoveAllTags(context, metalake, name).validate().handle(); } else { String propertyRemove = line.getOptionValue(GravitinoOptions.PROPERTY); if (propertyRemove != null) { gravitinoCommandLine - .newRemoveTagProperty(url, ignore, metalake, getOneTag(tags), propertyRemove) + .newRemoveTagProperty(context, metalake, getOneTag(tags), propertyRemove) .validate() .handle(); } else { - gravitinoCommandLine.newUntagEntity(url, ignore, metalake, name, tags).validate().handle(); + gravitinoCommandLine.newUntagEntity(context, metalake, name, tags).validate().handle(); } } } @@ -173,7 +170,7 @@ private void handleRemoveCommand() { /** Handles the "PROPERTIES" command. */ private void handlePropertiesCommand() { gravitinoCommandLine - .newListTagProperties(url, ignore, metalake, getOneTag(tags)) + .newListTagProperties(context, metalake, getOneTag(tags)) .validate() .handle(); } @@ -184,14 +181,14 @@ private void handleUpdateCommand() { if (line.hasOption(GravitinoOptions.COMMENT)) { String updateComment = line.getOptionValue(GravitinoOptions.COMMENT); gravitinoCommandLine - .newUpdateTagComment(url, ignore, metalake, getOneTag(tags), updateComment) + .newUpdateTagComment(context, metalake, getOneTag(tags), updateComment) .validate() .handle(); } if (line.hasOption(GravitinoOptions.RENAME)) { String newName = line.getOptionValue(GravitinoOptions.RENAME); gravitinoCommandLine - .newUpdateTagName(url, ignore, metalake, getOneTag(tags), newName) + .newUpdateTagName(context, metalake, getOneTag(tags), newName) .validate() .handle(); } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/TestableCommandLine.java b/clients/cli/src/main/java/org/apache/gravitino/cli/TestableCommandLine.java index b27e24fde9e..0217d21d273 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/TestableCommandLine.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/TestableCommandLine.java @@ -474,67 +474,65 @@ protected DeleteRole newDeleteRole( return new DeleteRole(url, ignore, force, metalake, roles); } - protected TagDetails newTagDetails(String url, boolean ignore, String metalake, String tag) { - return new TagDetails(url, ignore, metalake, tag); + protected TagDetails newTagDetails(CommandContext context, String metalake, String tag) { + return new TagDetails(context, metalake, tag); } - protected ListAllTags newListTags(String url, boolean ignore, String metalake) { - return new ListAllTags(url, ignore, metalake); + protected ListAllTags newListTags(CommandContext context, String metalake) { + return new ListAllTags(context, metalake); } protected CreateTag newCreateTags( - String url, boolean ignore, String metalake, String[] tags, String comment) { - return new CreateTag(url, ignore, metalake, tags, comment); + CommandContext context, String metalake, String[] tags, String comment) { + return new CreateTag(context, metalake, tags, comment); } - protected DeleteTag newDeleteTag( - String url, boolean ignore, boolean force, String metalake, String[] tags) { - return new DeleteTag(url, ignore, force, metalake, tags); + protected DeleteTag newDeleteTag(CommandContext context, String metalake, String[] tags) { + return new DeleteTag(context, metalake, tags); } protected SetTagProperty newSetTagProperty( - String url, boolean ignore, String metalake, String tag, String property, String value) { - return new SetTagProperty(url, ignore, metalake, tag, property, value); + CommandContext context, String metalake, String tag, String property, String value) { + return new SetTagProperty(context, metalake, tag, property, value); } protected RemoveTagProperty newRemoveTagProperty( - String url, boolean ignore, String metalake, String tag, String property) { - return new RemoveTagProperty(url, ignore, metalake, tag, property); + CommandContext context, String metalake, String tag, String property) { + return new RemoveTagProperty(context, metalake, tag, property); } - protected RemoveAllTags newRemoveAllTags( - String url, boolean ignore, String metalake, FullName name, boolean force) { - return new RemoveAllTags(url, ignore, metalake, name, force); + protected RemoveAllTags newRemoveAllTags(CommandContext context, String metalake, FullName name) { + return new RemoveAllTags(context, metalake, name); } protected ListTagProperties newListTagProperties( - String url, boolean ignore, String metalake, String tag) { - return new ListTagProperties(url, ignore, metalake, tag); + CommandContext context, String metalake, String tag) { + return new ListTagProperties(context, metalake, tag); } protected UpdateTagComment newUpdateTagComment( - String url, boolean ignore, String metalake, String tag, String comment) { - return new UpdateTagComment(url, ignore, metalake, tag, comment); + CommandContext context, String metalake, String tag, String comment) { + return new UpdateTagComment(context, metalake, tag, comment); } protected UpdateTagName newUpdateTagName( - String url, boolean ignore, String metalake, String tag, String newName) { - return new UpdateTagName(url, ignore, metalake, tag, newName); + CommandContext context, String metalake, String tag, String newName) { + return new UpdateTagName(context, metalake, tag, newName); } protected ListEntityTags newListEntityTags( - String url, boolean ignore, String metalake, FullName name) { - return new ListEntityTags(url, ignore, metalake, name); + CommandContext context, String metalake, FullName name) { + return new ListEntityTags(context, metalake, name); } protected TagEntity newTagEntity( - String url, boolean ignore, String metalake, FullName name, String[] tags) { - return new TagEntity(url, ignore, metalake, name, tags); + CommandContext context, String metalake, FullName name, String[] tags) { + return new TagEntity(context, metalake, name, tags); } protected UntagEntity newUntagEntity( - String url, boolean ignore, String metalake, FullName name, String[] tags) { - return new UntagEntity(url, ignore, metalake, name, tags); + CommandContext context, String metalake, FullName name, String[] tags) { + return new UntagEntity(context, metalake, name, tags); } protected ColumnAudit newColumnAudit( diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/CreateTag.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/CreateTag.java index dabf34c8b1b..46bd517f344 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/CreateTag.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/CreateTag.java @@ -22,6 +22,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchMetalakeException; @@ -35,15 +36,13 @@ public class CreateTag extends Command { /** * Create tags. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param tags The names of the tags. * @param comment The comment of the tag. */ - public CreateTag( - String url, boolean ignoreVersions, String metalake, String[] tags, String comment) { - super(url, ignoreVersions); + public CreateTag(CommandContext context, String metalake, String[] tags, String comment) { + super(context); this.metalake = metalake; this.tags = tags; this.comment = comment; @@ -76,7 +75,7 @@ private void handleOnlyOneTag() { exitWithError(exp.getMessage()); } - System.out.println("Tag " + tags[0] + " created"); + printInformation("Tag " + tags[0] + " created"); } private void handleMultipleTags() { @@ -95,12 +94,12 @@ private void handleMultipleTags() { exitWithError(exp.getMessage()); } if (!created.isEmpty()) { - System.out.println("Tags " + String.join(",", created) + " created"); + printInformation("Tags " + String.join(",", created) + " created"); } if (created.size() < tags.length) { List remaining = Arrays.asList(tags); remaining.removeAll(created); - System.out.println("Tags " + String.join(",", remaining) + " not created"); + printInformation("Tags " + String.join(",", remaining) + " not created"); } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/DeleteTag.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/DeleteTag.java index 26919e06acf..f0bdf2f3c5a 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/DeleteTag.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/DeleteTag.java @@ -23,6 +23,7 @@ import java.util.Arrays; import java.util.List; import org.apache.gravitino.cli.AreYouSure; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchMetalakeException; @@ -37,16 +38,13 @@ public class DeleteTag extends Command { /** * Delete tags. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. - * @param force Force operation. + * @param context The command context. * @param metalake The name of the metalake. * @param tags The names of the tags. */ - public DeleteTag( - String url, boolean ignoreVersions, boolean force, String metalake, String[] tags) { - super(url, ignoreVersions); - this.force = force; + public DeleteTag(CommandContext context, String metalake, String[] tags) { + super(context); + this.force = context.force(); this.metalake = metalake; this.tags = tags; } @@ -59,7 +57,7 @@ public void handle() { } if (tags == null || tags.length == 0) { - System.err.println(ErrorMessages.MISSING_TAG); + exitWithError(ErrorMessages.MISSING_TAG); } else { boolean hasOnlyOneTag = tags.length == 1; if (hasOnlyOneTag) { @@ -87,12 +85,12 @@ private void handleMultipleTags() { exitWithError(exp.getMessage()); } if (!deleted.isEmpty()) { - System.out.println("Tags " + String.join(",", deleted) + " deleted."); + printInformation("Tags " + String.join(",", deleted) + " deleted."); } if (deleted.size() < tags.length) { List remaining = Arrays.asList(tags); remaining.removeAll(deleted); - System.out.println("Tags " + String.join(",", remaining) + " not deleted."); + printInformation("Tags " + String.join(",", remaining) + " not deleted."); } } @@ -111,9 +109,9 @@ private void handleOnlyOneTag() { } if (deleted) { - System.out.println("Tag " + tags[0] + " deleted."); + printInformation("Tag " + tags[0] + " deleted."); } else { - System.out.println("Tag " + tags[0] + " not deleted."); + printInformation("Tag " + tags[0] + " not deleted."); } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListAllTags.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListAllTags.java index e3bd42ae04c..63657bb0fd1 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListAllTags.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListAllTags.java @@ -19,6 +19,7 @@ package org.apache.gravitino.cli.commands; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchMetalakeException; @@ -31,12 +32,11 @@ public class ListAllTags extends Command { /** * Lists all tags in a metalake. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. */ - public ListAllTags(String url, boolean ignoreVersions, String metalake) { - super(url, ignoreVersions); + public ListAllTags(CommandContext context, String metalake) { + super(context); this.metalake = metalake; } @@ -53,8 +53,10 @@ public void handle() { exitWithError(exp.getMessage()); } - String all = tags.length == 0 ? "No tags exist." : String.join(",", tags); - - System.out.println(all); + if (tags.length == 0) { + printInformation("No tags exist."); + } else { + printResults(String.join(",", tags)); + } } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListEntityTags.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListEntityTags.java index 90b1000fa05..e0ebf4b58f2 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListEntityTags.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListEntityTags.java @@ -21,6 +21,7 @@ import org.apache.gravitino.Catalog; import org.apache.gravitino.Schema; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.cli.FullName; import org.apache.gravitino.cli.utils.FullNameUtil; @@ -43,13 +44,12 @@ public class ListEntityTags extends Command { /** * Lists all tags in a metalake. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param name The name of the entity. */ - public ListEntityTags(String url, boolean ignoreVersions, String metalake, FullName name) { - super(url, ignoreVersions); + public ListEntityTags(CommandContext context, String metalake, FullName name) { + super(context); this.metalake = metalake; this.name = name; } @@ -113,6 +113,6 @@ public void handle() { String all = String.join(",", tags); - System.out.println(all); + printResults(all); } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListTagProperties.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListTagProperties.java index 5e191003ede..13ace743f7c 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListTagProperties.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListTagProperties.java @@ -20,6 +20,7 @@ package org.apache.gravitino.cli.commands; import java.util.Map; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchMetalakeException; @@ -35,13 +36,12 @@ public class ListTagProperties extends ListProperties { /** * List the properties of a tag. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param tag The name of the tag. */ - public ListTagProperties(String url, boolean ignoreVersions, String metalake, String tag) { - super(url, ignoreVersions); + public ListTagProperties(CommandContext context, String metalake, String tag) { + super(context); this.metalake = metalake; this.tag = tag; } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RemoveAllTags.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RemoveAllTags.java index 9c774dfaacb..123f6d32f8e 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RemoveAllTags.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RemoveAllTags.java @@ -22,6 +22,7 @@ import org.apache.gravitino.Catalog; import org.apache.gravitino.Schema; import org.apache.gravitino.cli.AreYouSure; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.cli.FullName; import org.apache.gravitino.cli.utils.FullNameUtil; @@ -49,18 +50,15 @@ public class RemoveAllTags extends Command { /** * Removes all the tags of an entity * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param name The name of the entity. - * @param force Force operation. */ - public RemoveAllTags( - String url, boolean ignoreVersions, String metalake, FullName name, boolean force) { - super(url, ignoreVersions); + public RemoveAllTags(CommandContext context, String metalake, FullName name) { + super(context); this.metalake = metalake; this.name = name; - this.force = force; + this.force = context.force(); } @Override @@ -152,10 +150,10 @@ public void handle() { } if (tags.length > 0) { - System.out.println( + printInformation( entity + " removed tags " + String.join(",", tags) + " now tagged with nothing"); } else { - System.out.println(entity + " has no tags"); + printInformation(entity + " has no tags"); } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RemoveTagProperty.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RemoveTagProperty.java index a91395baf8f..b92cd5cc453 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RemoveTagProperty.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RemoveTagProperty.java @@ -19,6 +19,7 @@ package org.apache.gravitino.cli.commands; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchMetalakeException; @@ -35,15 +36,13 @@ public class RemoveTagProperty extends Command { /** * Remove a property of a tag. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param tag The name of the tag. * @param property The name of the property. */ - public RemoveTagProperty( - String url, boolean ignoreVersions, String metalake, String tag, String property) { - super(url, ignoreVersions); + public RemoveTagProperty(CommandContext context, String metalake, String tag, String property) { + super(context); this.metalake = metalake; this.tag = tag; this.property = property; @@ -64,6 +63,6 @@ public void handle() { exitWithError(exp.getMessage()); } - System.out.println(property + " property removed."); + printInformation(property + " property removed."); } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/SetTagProperty.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/SetTagProperty.java index da7a267b8d4..e0b66e6e6d8 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/SetTagProperty.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/SetTagProperty.java @@ -19,6 +19,7 @@ package org.apache.gravitino.cli.commands; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchMetalakeException; @@ -36,21 +37,15 @@ public class SetTagProperty extends Command { /** * Set a property of a tag. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param tag The name of the tag. * @param property The name of the property. * @param value The value of the property. */ public SetTagProperty( - String url, - boolean ignoreVersions, - String metalake, - String tag, - String property, - String value) { - super(url, ignoreVersions); + CommandContext context, String metalake, String tag, String property, String value) { + super(context); this.metalake = metalake; this.tag = tag; this.property = property; @@ -72,7 +67,7 @@ public void handle() { exitWithError(exp.getMessage()); } - System.out.println(tag + " property set."); + printInformation(tag + " property set."); } @Override diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/TagDetails.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/TagDetails.java index 871a7e70742..75b127cf55e 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/TagDetails.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/TagDetails.java @@ -19,6 +19,7 @@ package org.apache.gravitino.cli.commands; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchCatalogException; @@ -33,13 +34,12 @@ public class TagDetails extends Command { /** * Displays the name and comment of a catalog. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param tag The name of the tag. */ - public TagDetails(String url, boolean ignoreVersions, String metalake, String tag) { - super(url, ignoreVersions); + public TagDetails(CommandContext context, String metalake, String tag) { + super(context); this.metalake = metalake; this.tag = tag; } @@ -61,7 +61,7 @@ public void handle() { } if (result != null) { - System.out.println(result.name() + "," + result.comment()); + printResults(result.name() + "," + result.comment()); } } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/TagEntity.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/TagEntity.java index 3b97778818e..2ea2de5df73 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/TagEntity.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/TagEntity.java @@ -21,6 +21,7 @@ import org.apache.gravitino.Catalog; import org.apache.gravitino.Schema; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.cli.FullName; import org.apache.gravitino.cli.utils.FullNameUtil; @@ -43,15 +44,13 @@ public class TagEntity extends Command { /** * Tag an entity with existing tags. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param name The name of the entity. * @param tags The names of the tags. */ - public TagEntity( - String url, boolean ignoreVersions, String metalake, FullName name, String[] tags) { - super(url, ignoreVersions); + public TagEntity(CommandContext context, String metalake, FullName name, String[] tags) { + super(context); this.metalake = metalake; this.name = name; this.tags = tags; @@ -130,7 +129,7 @@ public void handle() { String all = tagsToAdd.length == 0 ? "nothing" : String.join(",", tagsToAdd); - System.out.println(entity + " now tagged with " + all); + printInformation(entity + " now tagged with " + all); } @Override diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UntagEntity.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UntagEntity.java index 205242135b4..9fd1c4ca394 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UntagEntity.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UntagEntity.java @@ -21,6 +21,7 @@ import org.apache.gravitino.Catalog; import org.apache.gravitino.Schema; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.cli.FullName; import org.apache.gravitino.cli.utils.FullNameUtil; @@ -42,15 +43,13 @@ public class UntagEntity extends Command { /** * Remove existing tags from an entity. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param name The name of the entity. * @param tags The names of the tags. */ - public UntagEntity( - String url, boolean ignoreVersions, String metalake, FullName name, String[] tags) { - super(url, ignoreVersions); + public UntagEntity(CommandContext context, String metalake, FullName name, String[] tags) { + super(context); this.metalake = metalake; this.name = name; this.tags = tags; @@ -132,10 +131,10 @@ public void handle() { } if (tags.length > 1) { - System.out.println( + printInformation( entity + " removed tags " + String.join(",", tags) + " now tagged with " + all); } else { - System.out.println(entity + " removed tag " + tags[0].toString() + " now tagged with " + all); + printInformation(entity + " removed tag " + tags[0].toString() + " now tagged with " + all); } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateTagComment.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateTagComment.java index 2994d78f302..3abc7f29c31 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateTagComment.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateTagComment.java @@ -19,6 +19,7 @@ package org.apache.gravitino.cli.commands; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchMetalakeException; @@ -35,15 +36,13 @@ public class UpdateTagComment extends Command { /** * Update the comment of a tag. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param tag The name of the tag. * @param comment New metalake comment. */ - public UpdateTagComment( - String url, boolean ignoreVersions, String metalake, String tag, String comment) { - super(url, ignoreVersions); + public UpdateTagComment(CommandContext context, String metalake, String tag, String comment) { + super(context); this.metalake = metalake; this.tag = tag; this.comment = comment; @@ -64,6 +63,6 @@ public void handle() { exitWithError(exp.getMessage()); } - System.out.println(tag + " comment changed."); + printInformation(tag + " comment changed."); } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateTagName.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateTagName.java index f4ef43412db..1dc79b76e9b 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateTagName.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateTagName.java @@ -19,6 +19,7 @@ package org.apache.gravitino.cli.commands; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchMetalakeException; @@ -35,15 +36,13 @@ public class UpdateTagName extends Command { /** * Update the name of a tag. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the tag. * @param tag The name of the catalog. * @param name The new tag name. */ - public UpdateTagName( - String url, boolean ignoreVersions, String metalake, String tag, String name) { - super(url, ignoreVersions); + public UpdateTagName(CommandContext context, String metalake, String tag, String name) { + super(context); this.metalake = metalake; this.tag = tag; this.name = name; @@ -64,6 +63,6 @@ public void handle() { exitWithError(exp.getMessage()); } - System.out.println(tag + " name changed."); + printInformation(tag + " name changed."); } } diff --git a/clients/cli/src/test/java/org/apache/gravitino/cli/TestTagCommands.java b/clients/cli/src/test/java/org/apache/gravitino/cli/TestTagCommands.java index a94ccee7daa..4a7549510b3 100644 --- a/clients/cli/src/test/java/org/apache/gravitino/cli/TestTagCommands.java +++ b/clients/cli/src/test/java/org/apache/gravitino/cli/TestTagCommands.java @@ -22,6 +22,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThrows; import static org.mockito.ArgumentMatchers.argThat; +import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.Mockito.any; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.eq; @@ -93,7 +94,7 @@ void testListTagsCommand() { mockCommandLine, mockOptions, CommandEntities.TAG, CommandActions.LIST)); doReturn(mockList) .when(commandLine) - .newListTags(GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo"); + .newListTags(any(CommandContext.class), eq("metalake_demo")); doReturn(mockList).when(mockList).validate(); commandLine.handleCommandLine(); verify(mockList).handle(); @@ -112,7 +113,7 @@ void testTagDetailsCommand() { mockCommandLine, mockOptions, CommandEntities.TAG, CommandActions.DETAILS)); doReturn(mockDetails) .when(commandLine) - .newTagDetails(GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "tagA"); + .newTagDetails(any(CommandContext.class), eq("metalake_demo"), eq("tagA")); doReturn(mockDetails).when(mockDetails).validate(); commandLine.handleCommandLine(); verify(mockDetails).handle(); @@ -132,7 +133,7 @@ void testTagDetailsCommandWithMultipleTag() { assertThrows(RuntimeException.class, commandLine::handleCommandLine); verify(commandLine, never()) - .newTagDetails(eq(GravitinoCommandLine.DEFAULT_URL), eq(false), eq("metalake_demo"), any()); + .newTagDetails(any(CommandContext.class), eq("metalake_demo"), any()); String output = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); assertEquals(ErrorMessages.MULTIPLE_TAG_COMMAND_ERROR, output); } @@ -153,11 +154,10 @@ void testCreateTagCommand() { doReturn(mockCreate) .when(commandLine) .newCreateTags( - GravitinoCommandLine.DEFAULT_URL, - false, - "metalake_demo", - new String[] {"tagA"}, - "comment"); + any(CommandContext.class), + eq("metalake_demo"), + argThat(argument -> argument.length == 1 && argument[0].equals("tagA")), + eq("comment")); doReturn(mockCreate).when(mockCreate).validate(); commandLine.handleCommandLine(); verify(mockCreate).handle(); @@ -166,10 +166,9 @@ void testCreateTagCommand() { @Test void testCreateCommandWithoutTagOption() { Main.useExit = false; - CreateTag spyCreate = - spy( - new CreateTag( - GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", null, "comment")); + CommandContext mockContext = mock(CommandContext.class); + when(mockContext.url()).thenReturn(GravitinoCommandLine.DEFAULT_URL); + CreateTag spyCreate = spy(new CreateTag(mockContext, "metalake_demo", null, "comment")); assertThrows(RuntimeException.class, spyCreate::validate); verify(spyCreate, never()).handle(); @@ -194,8 +193,7 @@ void testCreateTagsCommand() { doReturn(mockCreate) .when(commandLine) .newCreateTags( - eq(GravitinoCommandLine.DEFAULT_URL), - eq(false), + any(CommandContext.class), eq("metalake_demo"), argThat( argument -> @@ -222,7 +220,10 @@ void testCreateTagCommandNoComment() { doReturn(mockCreate) .when(commandLine) .newCreateTags( - GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", new String[] {"tagA"}, null); + any(CommandContext.class), + eq("metalake_demo"), + argThat(argument -> argument.length == 1), + isNull()); doReturn(mockCreate).when(mockCreate).validate(); commandLine.handleCommandLine(); verify(mockCreate).handle(); @@ -242,7 +243,9 @@ void testDeleteTagCommand() { doReturn(mockDelete) .when(commandLine) .newDeleteTag( - GravitinoCommandLine.DEFAULT_URL, false, false, "metalake_demo", new String[] {"tagA"}); + any(CommandContext.class), + eq("metalake_demo"), + argThat(argument -> argument.length == 1 && argument[0].equals("tagA"))); doReturn(mockDelete).when(mockDelete).validate(); commandLine.handleCommandLine(); verify(mockDelete).handle(); @@ -263,11 +266,13 @@ void testDeleteTagsCommand() { doReturn(mockDelete) .when(commandLine) .newDeleteTag( - GravitinoCommandLine.DEFAULT_URL, - false, - false, - "metalake_demo", - new String[] {"tagA", "tagB"}); + any(CommandContext.class), + eq("metalake_demo"), + argThat( + argument -> + argument.length == 2 + && argument[0].equals("tagA") + && argument[1].equals("tagB"))); doReturn(mockDelete).when(mockDelete).validate(); commandLine.handleCommandLine(); verify(mockDelete).handle(); @@ -288,7 +293,9 @@ void testDeleteTagForceCommand() { doReturn(mockDelete) .when(commandLine) .newDeleteTag( - GravitinoCommandLine.DEFAULT_URL, false, true, "metalake_demo", new String[] {"tagA"}); + any(CommandContext.class), + eq("metalake_demo"), + argThat(argument -> argument.length == 1 && argument[0].equals("tagA"))); doReturn(mockDelete).when(mockDelete).validate(); commandLine.handleCommandLine(); verify(mockDelete).handle(); @@ -312,7 +319,11 @@ void testSetTagPropertyCommand() { doReturn(mockSetProperty) .when(commandLine) .newSetTagProperty( - GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "tagA", "property", "value"); + any(CommandContext.class), + eq("metalake_demo"), + eq("tagA"), + eq("property"), + eq("value")); doReturn(mockSetProperty).when(mockSetProperty).validate(); commandLine.handleCommandLine(); verify(mockSetProperty).handle(); @@ -321,10 +332,10 @@ void testSetTagPropertyCommand() { @Test void testSetTagPropertyCommandWithoutPropertyAndValue() { Main.useExit = false; + CommandContext mockContext = mock(CommandContext.class); + when(mockContext.url()).thenReturn(GravitinoCommandLine.DEFAULT_URL); SetTagProperty spySetProperty = - spy( - new SetTagProperty( - GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "tagA", null, null)); + spy(new SetTagProperty(mockContext, "metalake_demo", "tagA", null, null)); assertThrows(RuntimeException.class, spySetProperty::validate); verify(spySetProperty, never()).handle(); String output = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); @@ -334,10 +345,10 @@ void testSetTagPropertyCommandWithoutPropertyAndValue() { @Test void testSetTagPropertyCommandWithoutPropertyOption() { Main.useExit = false; + CommandContext mockContext = mock(CommandContext.class); + when(mockContext.url()).thenReturn(GravitinoCommandLine.DEFAULT_URL); SetTagProperty spySetProperty = - spy( - new SetTagProperty( - GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "tagA", null, "value")); + spy(new SetTagProperty(mockContext, "metalake_demo", "tagA", null, "value")); assertThrows(RuntimeException.class, spySetProperty::validate); verify(spySetProperty, never()).handle(); String output = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); @@ -347,15 +358,10 @@ void testSetTagPropertyCommandWithoutPropertyOption() { @Test void testSetTagPropertyCommandWithoutValueOption() { Main.useExit = false; + CommandContext mockContext = mock(CommandContext.class); + when(mockContext.url()).thenReturn(GravitinoCommandLine.DEFAULT_URL); SetTagProperty spySetProperty = - spy( - new SetTagProperty( - GravitinoCommandLine.DEFAULT_URL, - false, - "metalake_demo", - "tagA", - "property", - null)); + spy(new SetTagProperty(mockContext, "metalake_demo", "tagA", "property", null)); assertThrows(RuntimeException.class, spySetProperty::validate); verify(spySetProperty, never()).handle(); String output = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); @@ -381,12 +387,7 @@ void testSetMultipleTagPropertyCommandError() { Assertions.assertThrows(RuntimeException.class, commandLine::handleCommandLine); verify(commandLine, never()) .newSetTagProperty( - eq(GravitinoCommandLine.DEFAULT_URL), - eq(false), - eq("metalake_demo"), - any(), - eq("property"), - eq("value")); + any(CommandContext.class), eq("metalake_demo"), any(), eq("property"), eq("value")); String output = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); assertEquals(ErrorMessages.MULTIPLE_TAG_COMMAND_ERROR, output); } @@ -407,7 +408,7 @@ void testRemoveTagPropertyCommand() { doReturn(mockRemoveProperty) .when(commandLine) .newRemoveTagProperty( - GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "tagA", "property"); + any(CommandContext.class), eq("metalake_demo"), eq("tagA"), eq("property")); doReturn(mockRemoveProperty).when(mockRemoveProperty).validate(); commandLine.handleCommandLine(); verify(mockRemoveProperty).handle(); @@ -431,13 +432,9 @@ void testRemoveTagPropertyCommandWithMultipleTags() { assertThrows(RuntimeException.class, commandLine::handleCommandLine); verify(commandLine, never()) .newRemoveTagProperty( - eq(GravitinoCommandLine.DEFAULT_URL), - eq(false), - eq("metalake_demo"), - any(), - eq("property")); + any(CommandContext.class), eq("metalake_demo"), any(), eq("property")); String output = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); - assertEquals(ErrorMessages.MULTIPLE_TAG_COMMAND_ERROR, output); + Assertions.assertEquals(ErrorMessages.MULTIPLE_TAG_COMMAND_ERROR, output); } @Test @@ -453,7 +450,7 @@ void testListTagPropertiesCommand() { mockCommandLine, mockOptions, CommandEntities.TAG, CommandActions.PROPERTIES)); doReturn(mockListProperties) .when(commandLine) - .newListTagProperties(GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "tagA"); + .newListTagProperties(any(CommandContext.class), eq("metalake_demo"), eq("tagA")); doReturn(mockListProperties).when(mockListProperties).validate(); commandLine.handleCommandLine(); verify(mockListProperties).handle(); @@ -474,12 +471,7 @@ void testDeleteAllTagCommand() { mockCommandLine, mockOptions, CommandEntities.TAG, CommandActions.REMOVE)); doReturn(mockRemoveAllTags) .when(commandLine) - .newRemoveAllTags( - eq(GravitinoCommandLine.DEFAULT_URL), - eq(false), - eq("metalake_demo"), - any(FullName.class), - eq(true)); + .newRemoveAllTags(any(CommandContext.class), eq("metalake_demo"), any(FullName.class)); doReturn(mockRemoveAllTags).when(mockRemoveAllTags).validate(); commandLine.handleCommandLine(); verify(mockRemoveAllTags).handle(); @@ -501,7 +493,7 @@ void testUpdateTagCommentCommand() { doReturn(mockUpdateComment) .when(commandLine) .newUpdateTagComment( - GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "tagA", "new comment"); + any(CommandContext.class), eq("metalake_demo"), eq("tagA"), eq("new comment")); doReturn(mockUpdateComment).when(mockUpdateComment).validate(); commandLine.handleCommandLine(); verify(mockUpdateComment).handle(); @@ -525,11 +517,7 @@ void testUpdateTagCommentCommandWithMultipleTags() { assertThrows(RuntimeException.class, commandLine::handleCommandLine); verify(commandLine, never()) .newUpdateTagComment( - eq(GravitinoCommandLine.DEFAULT_URL), - eq(false), - eq("metalake_demo"), - any(), - eq("new comment")); + any(CommandContext.class), eq("metalake_demo"), any(), eq("new comment")); String output = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); assertEquals(ErrorMessages.MULTIPLE_TAG_COMMAND_ERROR, output); } @@ -549,7 +537,7 @@ void testUpdateTagNameCommand() { mockCommandLine, mockOptions, CommandEntities.TAG, CommandActions.UPDATE)); doReturn(mockUpdateName) .when(commandLine) - .newUpdateTagName(GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "tagA", "tagB"); + .newUpdateTagName(any(CommandContext.class), eq("metalake_demo"), eq("tagA"), eq("tagB")); doReturn(mockUpdateName).when(mockUpdateName).validate(); commandLine.handleCommandLine(); verify(mockUpdateName).handle(); @@ -572,12 +560,7 @@ void testUpdateTagNameCommandWithMultipleTags() { assertThrows(RuntimeException.class, commandLine::handleCommandLine); verify(commandLine, never()) - .newUpdateTagName( - eq(GravitinoCommandLine.DEFAULT_URL), - eq(false), - eq("metalake_demo"), - any(), - eq("tagC")); + .newUpdateTagName(any(CommandContext.class), eq("metalake_demo"), any(), eq("tagC")); String output = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); assertEquals(ErrorMessages.MULTIPLE_TAG_COMMAND_ERROR, output); } @@ -595,8 +578,7 @@ void testListEntityTagsCommand() { mockCommandLine, mockOptions, CommandEntities.TAG, CommandActions.LIST)); doReturn(mockListTags) .when(commandLine) - .newListEntityTags( - eq(GravitinoCommandLine.DEFAULT_URL), eq(false), eq("metalake_demo"), any()); + .newListEntityTags(any(CommandContext.class), eq("metalake_demo"), any(FullName.class)); doReturn(mockListTags).when(mockListTags).validate(); commandLine.handleCommandLine(); verify(mockListTags).handle(); @@ -618,8 +600,7 @@ void testTagEntityCommand() { doReturn(mockTagEntity) .when(commandLine) .newTagEntity( - eq(GravitinoCommandLine.DEFAULT_URL), - eq(false), + any(CommandContext.class), eq("metalake_demo"), any(), argThat( @@ -637,14 +618,10 @@ public boolean matches(String[] argument) { @Test void testTagEntityCommandWithoutName() { Main.useExit = false; + CommandContext mockContext = mock(CommandContext.class); + when(mockContext.url()).thenReturn(GravitinoCommandLine.DEFAULT_URL); TagEntity spyTagEntity = - spy( - new TagEntity( - GravitinoCommandLine.DEFAULT_URL, - false, - "metalake_demo", - null, - new String[] {"tagA"})); + spy(new TagEntity(mockContext, "metalake_demo", null, new String[] {"tagA"})); assertThrows(RuntimeException.class, spyTagEntity::validate); verify(spyTagEntity, never()).handle(); @@ -669,8 +646,7 @@ void testTagsEntityCommand() { doReturn(mockTagEntity) .when(commandLine) .newTagEntity( - eq(GravitinoCommandLine.DEFAULT_URL), - eq(false), + any(CommandContext.class), eq("metalake_demo"), any(), argThat( @@ -707,8 +683,7 @@ void testUntagEntityCommand() { doReturn(mockUntagEntity) .when(commandLine) .newUntagEntity( - eq(GravitinoCommandLine.DEFAULT_URL), - eq(false), + any(CommandContext.class), eq("metalake_demo"), any(), argThat( @@ -726,14 +701,10 @@ public boolean matches(String[] argument) { @Test void testUntagEntityCommandWithoutName() { Main.useExit = false; + CommandContext mockContext = mock(CommandContext.class); + when(mockContext.url()).thenReturn(GravitinoCommandLine.DEFAULT_URL); UntagEntity spyUntagEntity = - spy( - new UntagEntity( - GravitinoCommandLine.DEFAULT_URL, - false, - "metalake_demo", - null, - new String[] {"tagA"})); + spy(new UntagEntity(mockContext, "metalake_demo", null, new String[] {"tagA"})); assertThrows(RuntimeException.class, spyUntagEntity::validate); verify(spyUntagEntity, never()).handle(); @@ -760,8 +731,7 @@ void testUntagsEntityCommand() { doReturn(mockUntagEntity) .when(commandLine) .newUntagEntity( - eq(GravitinoCommandLine.DEFAULT_URL), - eq(false), + any(CommandContext.class), eq("metalake_demo"), any(), argThat( @@ -782,8 +752,9 @@ public boolean matches(String[] argument) { @Test void testDeleteTagCommandWithoutTagOption() { Main.useExit = false; - DeleteTag spyDeleteTag = - spy(new DeleteTag(GravitinoCommandLine.DEFAULT_URL, false, false, "metalake", null)); + CommandContext mockContext = mock(CommandContext.class); + when(mockContext.url()).thenReturn(GravitinoCommandLine.DEFAULT_URL); + DeleteTag spyDeleteTag = spy(new DeleteTag(mockContext, "metalake", null)); assertThrows(RuntimeException.class, spyDeleteTag::validate); verify(spyDeleteTag, never()).handle(); @@ -809,16 +780,14 @@ void testRemoveAllTagsCommand() { doReturn(mockRemoveAllTags) .when(commandLine) .newRemoveAllTags( - eq(GravitinoCommandLine.DEFAULT_URL), - eq(false), + any(CommandContext.class), eq("metalake_demo"), argThat( argument -> argument != null && "catalog".equals(argument.getCatalogName()) && "schema".equals(argument.getSchemaName()) - && "table".equals(argument.getTableName())), - eq(true)); + && "table".equals(argument.getTableName()))); doReturn(mockRemoveAllTags).when(mockRemoveAllTags).validate(); commandLine.handleCommandLine(); verify(mockRemoveAllTags).handle(); @@ -827,10 +796,9 @@ void testRemoveAllTagsCommand() { @Test void testRemoveAllTagsCommandWithoutName() { Main.useExit = false; - RemoveAllTags spyRemoveAllTags = - spy( - new RemoveAllTags( - GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", null, false)); + CommandContext mockContext = mock(CommandContext.class); + when(mockContext.url()).thenReturn(GravitinoCommandLine.DEFAULT_URL); + RemoveAllTags spyRemoveAllTags = spy(new RemoveAllTags(mockContext, "metalake_demo", null)); assertThrows(RuntimeException.class, spyRemoveAllTags::validate); verify(spyRemoveAllTags, never()).handle(); From 67f25efb26e6b8a99aa304eff6590bb658f1c7a8 Mon Sep 17 00:00:00 2001 From: Lord of Abyss <103809695+Abyss-lord@users.noreply.github.com> Date: Wed, 12 Feb 2025 07:33:28 +0800 Subject: [PATCH 24/33] [#6421] improve(CLI): Add user and group command context CLI (#6437) ### What changes were proposed in this pull request? Add user and group command context CLI ### Why are the changes needed? Fix: #6421 ### Does this PR introduce _any_ user-facing change? No ### How was this patch tested? local test. --- .../gravitino/cli/GravitinoCommandLine.java | 4 +- .../gravitino/cli/GroupCommandHandler.java | 34 +++++----- .../gravitino/cli/TestableCommandLine.java | 62 +++++++++---------- .../gravitino/cli/UserCommandHandler.java | 49 +++++---------- .../cli/commands/AddRoleToGroup.java | 11 ++-- .../gravitino/cli/commands/AddRoleToUser.java | 11 ++-- .../gravitino/cli/commands/CreateGroup.java | 10 +-- .../gravitino/cli/commands/CreateUser.java | 10 +-- .../gravitino/cli/commands/DeleteGroup.java | 16 +++-- .../gravitino/cli/commands/DeleteUser.java | 16 +++-- .../gravitino/cli/commands/GroupAudit.java | 19 +++--- .../gravitino/cli/commands/GroupDetails.java | 16 ++--- .../gravitino/cli/commands/ListGroups.java | 16 ++--- .../gravitino/cli/commands/ListUsers.java | 16 ++--- .../cli/commands/RemoveAllRoles.java | 13 ++-- .../cli/commands/RemoveRoleFromGroup.java | 11 ++-- .../cli/commands/RemoveRoleFromUser.java | 11 ++-- .../gravitino/cli/commands/UserAudit.java | 19 +++--- .../gravitino/cli/commands/UserDetails.java | 16 ++--- .../gravitino/cli/TestGroupCommands.java | 38 ++++++------ .../gravitino/cli/TestUserCommands.java | 34 +++++----- 21 files changed, 205 insertions(+), 227 deletions(-) diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/GravitinoCommandLine.java b/clients/cli/src/main/java/org/apache/gravitino/cli/GravitinoCommandLine.java index 2bb40373a69..e61051e5382 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/GravitinoCommandLine.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/GravitinoCommandLine.java @@ -130,9 +130,9 @@ private void executeCommand() { } else if (entity.equals(CommandEntities.FILESET)) { new FilesetCommandHandler(this, line, command, context).handle(); } else if (entity.equals(CommandEntities.USER)) { - new UserCommandHandler(this, line, command, ignore).handle(); + new UserCommandHandler(this, line, command, context).handle(); } else if (entity.equals(CommandEntities.GROUP)) { - new GroupCommandHandler(this, line, command, ignore).handle(); + new GroupCommandHandler(this, line, command, context).handle(); } else if (entity.equals(CommandEntities.TAG)) { new TagCommandHandler(this, line, command, context).handle(); } else if (entity.equals(CommandEntities.ROLE)) { diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/GroupCommandHandler.java b/clients/cli/src/main/java/org/apache/gravitino/cli/GroupCommandHandler.java index 7542b17974b..6fcec1447b2 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/GroupCommandHandler.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/GroupCommandHandler.java @@ -27,8 +27,7 @@ public class GroupCommandHandler extends CommandHandler { private final GravitinoCommandLine gravitinoCommandLine; private final CommandLine line; private final String command; - private final boolean ignore; - private final String url; + private final CommandContext context; private final FullName name; private final String metalake; private String group; @@ -39,16 +38,19 @@ public class GroupCommandHandler extends CommandHandler { * @param gravitinoCommandLine The Gravitino command line instance. * @param line The command line arguments. * @param command The command to execute. - * @param ignore Ignore server version mismatch. + * @param context The command context. */ public GroupCommandHandler( - GravitinoCommandLine gravitinoCommandLine, CommandLine line, String command, boolean ignore) { + GravitinoCommandLine gravitinoCommandLine, + CommandLine line, + String command, + CommandContext context) { this.gravitinoCommandLine = gravitinoCommandLine; this.line = line; this.command = command; - this.ignore = ignore; + this.context = context; - this.url = getUrl(line); + this.context.setUrl(getUrl(line)); this.name = new FullName(line); this.metalake = name.getMetalakeName(); } @@ -111,21 +113,20 @@ private boolean executeCommand() { /** Handles the "DETAILS" command. */ private void handleDetailsCommand() { if (line.hasOption(GravitinoOptions.AUDIT)) { - gravitinoCommandLine.newGroupAudit(url, ignore, metalake, group).validate().handle(); + gravitinoCommandLine.newGroupAudit(context, metalake, group).validate().handle(); } else { - gravitinoCommandLine.newGroupDetails(url, ignore, metalake, group).validate().handle(); + gravitinoCommandLine.newGroupDetails(context, metalake, group).validate().handle(); } } /** Handles the "CREATE" command. */ private void handleCreateCommand() { - gravitinoCommandLine.newCreateGroup(url, ignore, metalake, group).validate().handle(); + gravitinoCommandLine.newCreateGroup(context, metalake, group).validate().handle(); } /** Handles the "DELETE" command. */ private void handleDeleteCommand() { - boolean force = line.hasOption(GravitinoOptions.FORCE); - gravitinoCommandLine.newDeleteGroup(url, ignore, force, metalake, group).validate().handle(); + gravitinoCommandLine.newDeleteGroup(context, metalake, group).validate().handle(); } /** Handles the "REVOKE" command. */ @@ -133,7 +134,7 @@ private void handleRevokeCommand() { boolean revokeAll = line.hasOption(GravitinoOptions.ALL); if (revokeAll) { gravitinoCommandLine - .newRemoveAllRoles(url, ignore, metalake, group, CommandEntities.GROUP) + .newRemoveAllRoles(context, metalake, group, CommandEntities.GROUP) .validate() .handle(); System.out.printf("Removed all roles from group %s%n", group); @@ -141,7 +142,7 @@ private void handleRevokeCommand() { String[] revokeRoles = line.getOptionValues(GravitinoOptions.ROLE); for (String role : revokeRoles) { gravitinoCommandLine - .newRemoveRoleFromGroup(url, ignore, metalake, group, role) + .newRemoveRoleFromGroup(context, metalake, group, role) .validate() .handle(); } @@ -153,16 +154,13 @@ private void handleRevokeCommand() { private void handleGrantCommand() { String[] grantRoles = line.getOptionValues(GravitinoOptions.ROLE); for (String role : grantRoles) { - gravitinoCommandLine - .newAddRoleToGroup(url, ignore, metalake, group, role) - .validate() - .handle(); + gravitinoCommandLine.newAddRoleToGroup(context, metalake, group, role).validate().handle(); } System.out.printf("Grant roles %s to group %s%n", COMMA_JOINER.join(grantRoles), group); } /** Handles the "LIST" command. */ private void handleListCommand() { - gravitinoCommandLine.newListGroups(url, ignore, metalake).validate().handle(); + gravitinoCommandLine.newListGroups(context, metalake).validate().handle(); } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/TestableCommandLine.java b/clients/cli/src/main/java/org/apache/gravitino/cli/TestableCommandLine.java index 0217d21d273..a4f47239c71 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/TestableCommandLine.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/TestableCommandLine.java @@ -386,71 +386,69 @@ protected ListTableProperties newListTableProperties( return new ListTableProperties(context, metalake, catalog, schema, table); } - protected UserDetails newUserDetails(String url, boolean ignore, String metalake, String user) { - return new UserDetails(url, ignore, metalake, user); + protected UserDetails newUserDetails(CommandContext context, String metalake, String user) { + return new UserDetails(context, metalake, user); } - protected ListUsers newListUsers(String url, boolean ignore, String metalake) { - return new ListUsers(url, ignore, metalake); + protected ListUsers newListUsers(CommandContext context, String metalake) { + return new ListUsers(context, metalake); } - protected UserAudit newUserAudit(String url, boolean ignore, String metalake, String user) { - return new UserAudit(url, ignore, metalake, user); + protected UserAudit newUserAudit(CommandContext context, String metalake, String user) { + return new UserAudit(context, metalake, user); } - protected CreateUser newCreateUser(String url, boolean ignore, String metalake, String user) { - return new CreateUser(url, ignore, metalake, user); + protected CreateUser newCreateUser(CommandContext context, String metalake, String user) { + return new CreateUser(context, metalake, user); } - protected DeleteUser newDeleteUser( - String url, boolean ignore, boolean force, String metalake, String user) { - return new DeleteUser(url, ignore, force, metalake, user); + protected DeleteUser newDeleteUser(CommandContext context, String metalake, String user) { + return new DeleteUser(context, metalake, user); } protected RemoveRoleFromUser newRemoveRoleFromUser( - String url, boolean ignore, String metalake, String user, String role) { - return new RemoveRoleFromUser(url, ignore, metalake, user, role); + CommandContext context, String metalake, String user, String role) { + return new RemoveRoleFromUser(context, metalake, user, role); } protected AddRoleToUser newAddRoleToUser( - String url, boolean ignore, String metalake, String user, String role) { - return new AddRoleToUser(url, ignore, metalake, user, role); + CommandContext context, String metalake, String user, String role) { + return new AddRoleToUser(context, metalake, user, role); } - protected GroupDetails newGroupDetails(String url, boolean ignore, String metalake, String user) { - return new GroupDetails(url, ignore, metalake, user); + protected GroupDetails newGroupDetails(CommandContext context, String metalake, String user) { + return new GroupDetails(context, metalake, user); } - protected ListGroups newListGroups(String url, boolean ignore, String metalake) { - return new ListGroups(url, ignore, metalake); + protected ListGroups newListGroups(CommandContext context, String metalake) { + return new ListGroups(context, metalake); } - protected GroupAudit newGroupAudit(String url, boolean ignore, String metalake, String group) { - return new GroupAudit(url, ignore, metalake, group); + protected GroupAudit newGroupAudit(CommandContext context, String metalake, String group) { + return new GroupAudit(context, metalake, group); } - protected CreateGroup newCreateGroup(String url, boolean ignore, String metalake, String user) { - return new CreateGroup(url, ignore, metalake, user); + protected CreateGroup newCreateGroup(CommandContext context, String metalake, String user) { + return new CreateGroup(context, metalake, user); } - protected DeleteGroup newDeleteGroup( - String url, boolean ignore, boolean force, String metalake, String user) { - return new DeleteGroup(url, ignore, force, metalake, user); + protected DeleteGroup newDeleteGroup(CommandContext context, String metalake, String user) { + return new DeleteGroup(context, metalake, user); } protected RemoveRoleFromGroup newRemoveRoleFromGroup( - String url, boolean ignore, String metalake, String group, String role) { - return new RemoveRoleFromGroup(url, ignore, metalake, group, role); + CommandContext context, String metalake, String group, String role) { + return new RemoveRoleFromGroup(context, metalake, group, role); } protected RemoveAllRoles newRemoveAllRoles( - String url, boolean ignore, String metalake, String entity, String entityType) { - return new RemoveAllRoles(url, ignore, metalake, entity, entityType); + CommandContext context, String metalake, String entity, String entityType) { + return new RemoveAllRoles(context, metalake, entity, entityType); } protected AddRoleToGroup newAddRoleToGroup( - String url, boolean ignore, String metalake, String group, String role) { - return new AddRoleToGroup(url, ignore, metalake, group, role); + CommandContext context, String metalake, String group, String role) { + return new AddRoleToGroup(context, metalake, group, role); } protected RoleDetails newRoleDetails(String url, boolean ignore, String metalake, String role) { diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/UserCommandHandler.java b/clients/cli/src/main/java/org/apache/gravitino/cli/UserCommandHandler.java index 23698aa5cf8..964d2ba6d99 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/UserCommandHandler.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/UserCommandHandler.java @@ -27,8 +27,7 @@ public class UserCommandHandler extends CommandHandler { private final GravitinoCommandLine gravitinoCommandLine; private final CommandLine line; private final String command; - private final boolean ignore; - private final String url; + private final CommandContext context; private final FullName name; private final String metalake; private String user; @@ -39,16 +38,19 @@ public class UserCommandHandler extends CommandHandler { * @param gravitinoCommandLine The Gravitino command line instance. * @param line The command line arguments. * @param command The command to execute. - * @param ignore Ignore server version mismatch. + * @param context The command context. */ public UserCommandHandler( - GravitinoCommandLine gravitinoCommandLine, CommandLine line, String command, boolean ignore) { + GravitinoCommandLine gravitinoCommandLine, + CommandLine line, + String command, + CommandContext context) { this.gravitinoCommandLine = gravitinoCommandLine; this.line = line; this.command = command; - this.ignore = ignore; + this.context = context; - this.url = getUrl(line); + this.context.setUrl(getUrl(line)); this.name = new FullName(line); this.metalake = name.getMetalakeName(); } @@ -110,42 +112,26 @@ private boolean executeCommand() { /** Handles the "LIST" command. */ private void handleListCommand() { - this.gravitinoCommandLine - .newListUsers(this.url, this.ignore, this.metalake) - .validate() - .handle(); + this.gravitinoCommandLine.newListUsers(context, metalake).validate().handle(); } /** Handles the "DETAILS" command. */ private void handleDetailsCommand() { if (line.hasOption(GravitinoOptions.AUDIT)) { - this.gravitinoCommandLine - .newUserAudit(this.url, this.ignore, this.metalake, user) - .validate() - .handle(); + this.gravitinoCommandLine.newUserAudit(context, metalake, user).validate().handle(); } else { - this.gravitinoCommandLine - .newUserDetails(this.url, this.ignore, this.metalake, user) - .validate() - .handle(); + this.gravitinoCommandLine.newUserDetails(context, metalake, user).validate().handle(); } } /** Handles the "CREATE" command. */ private void handleCreateCommand() { - this.gravitinoCommandLine - .newCreateUser(this.url, this.ignore, this.metalake, user) - .validate() - .handle(); + this.gravitinoCommandLine.newCreateUser(context, metalake, user).validate().handle(); } /** Handles the "DELETE" command. */ private void handleDeleteCommand() { - boolean force = line.hasOption(GravitinoOptions.FORCE); - this.gravitinoCommandLine - .newDeleteUser(this.url, this.ignore, force, this.metalake, user) - .validate() - .handle(); + this.gravitinoCommandLine.newDeleteUser(context, metalake, user).validate().handle(); } /** Handles the "REVOKE" command. */ @@ -153,7 +139,7 @@ private void handleRevokeCommand() { boolean removeAll = line.hasOption(GravitinoOptions.ALL); if (removeAll) { gravitinoCommandLine - .newRemoveAllRoles(url, ignore, metalake, user, CommandEntities.USER) + .newRemoveAllRoles(context, metalake, user, CommandEntities.USER) .validate() .handle(); System.out.printf("Removed all roles from user %s%n", user); @@ -161,7 +147,7 @@ private void handleRevokeCommand() { String[] revokeRoles = line.getOptionValues(GravitinoOptions.ROLE); for (String role : revokeRoles) { this.gravitinoCommandLine - .newRemoveRoleFromUser(this.url, this.ignore, this.metalake, user, role) + .newRemoveRoleFromUser(context, metalake, user, role) .validate() .handle(); } @@ -173,10 +159,7 @@ private void handleRevokeCommand() { private void handleGrantCommand() { String[] grantRoles = line.getOptionValues(GravitinoOptions.ROLE); for (String role : grantRoles) { - this.gravitinoCommandLine - .newAddRoleToUser(this.url, this.ignore, this.metalake, user, role) - .validate() - .handle(); + this.gravitinoCommandLine.newAddRoleToUser(context, metalake, user, role).validate().handle(); } System.out.printf("Add roles %s to user %s%n", COMMA_JOINER.join(grantRoles), user); } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/AddRoleToGroup.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/AddRoleToGroup.java index ebe3ea15200..7ea3d6b8e4a 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/AddRoleToGroup.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/AddRoleToGroup.java @@ -20,6 +20,7 @@ package org.apache.gravitino.cli.commands; import java.util.ArrayList; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchMetalakeException; @@ -36,15 +37,13 @@ public class AddRoleToGroup extends Command { /** * Adds a role to a group. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param group The name of the group. * @param role The name of the role. */ - public AddRoleToGroup( - String url, boolean ignoreVersions, String metalake, String group, String role) { - super(url, ignoreVersions); + public AddRoleToGroup(CommandContext context, String metalake, String group, String role) { + super(context); this.metalake = metalake; this.group = group; this.role = role; @@ -68,6 +67,6 @@ public void handle() { exitWithError(exp.getMessage()); } - System.out.println(role + " added to " + group); + printInformation(role + " added to " + group); } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/AddRoleToUser.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/AddRoleToUser.java index 66985b7dfb8..fd76ccfe2f5 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/AddRoleToUser.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/AddRoleToUser.java @@ -20,6 +20,7 @@ package org.apache.gravitino.cli.commands; import java.util.ArrayList; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchMetalakeException; @@ -36,15 +37,13 @@ public class AddRoleToUser extends Command { /** * Adds a role to a user. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param user The name of the user. * @param role The name of the role. */ - public AddRoleToUser( - String url, boolean ignoreVersions, String metalake, String user, String role) { - super(url, ignoreVersions); + public AddRoleToUser(CommandContext context, String metalake, String user, String role) { + super(context); this.metalake = metalake; this.user = user; this.role = role; @@ -68,6 +67,6 @@ public void handle() { exitWithError(exp.getMessage()); } - System.out.println(role + " added to " + user); + printInformation(role + " added to " + user); } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/CreateGroup.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/CreateGroup.java index 8afd35c6403..9cdefe3a7ad 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/CreateGroup.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/CreateGroup.java @@ -19,6 +19,7 @@ package org.apache.gravitino.cli.commands; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.GroupAlreadyExistsException; @@ -31,13 +32,12 @@ public class CreateGroup extends Command { /** * Create a new group. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param group The name of the group. */ - public CreateGroup(String url, boolean ignoreVersions, String metalake, String group) { - super(url, ignoreVersions); + public CreateGroup(CommandContext context, String metalake, String group) { + super(context); this.metalake = metalake; this.group = group; } @@ -56,6 +56,6 @@ public void handle() { exitWithError(exp.getMessage()); } - System.out.println(group + " created"); + printInformation(group + " created"); } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/CreateUser.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/CreateUser.java index 6f786778e17..233f3eedc54 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/CreateUser.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/CreateUser.java @@ -19,6 +19,7 @@ package org.apache.gravitino.cli.commands; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchMetalakeException; @@ -31,13 +32,12 @@ public class CreateUser extends Command { /** * Create a new User. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param user The name of the user. */ - public CreateUser(String url, boolean ignoreVersions, String metalake, String user) { - super(url, ignoreVersions); + public CreateUser(CommandContext context, String metalake, String user) { + super(context); this.metalake = metalake; this.user = user; } @@ -56,6 +56,6 @@ public void handle() { exitWithError(exp.getMessage()); } - System.out.println(user + " created"); + printInformation(user + " created"); } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/DeleteGroup.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/DeleteGroup.java index 641b43ddac9..12a9304eae4 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/DeleteGroup.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/DeleteGroup.java @@ -20,6 +20,7 @@ package org.apache.gravitino.cli.commands; import org.apache.gravitino.cli.AreYouSure; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchGroupException; @@ -34,16 +35,13 @@ public class DeleteGroup extends Command { /** * Delete a group. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. - * @param force Force operation. + * @param context The command context. * @param metalake The name of the metalake. * @param group The name of the group. */ - public DeleteGroup( - String url, boolean ignoreVersions, boolean force, String metalake, String group) { - super(url, ignoreVersions); - this.force = force; + public DeleteGroup(CommandContext context, String metalake, String group) { + super(context); + this.force = context.force(); this.metalake = metalake; this.group = group; } @@ -69,9 +67,9 @@ public void handle() { } if (deleted) { - System.out.println(group + " deleted."); + printInformation(group + " deleted."); } else { - System.out.println(group + " not deleted."); + printInformation(group + " not deleted."); } } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/DeleteUser.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/DeleteUser.java index aa53a4d9f66..3e2000199ef 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/DeleteUser.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/DeleteUser.java @@ -21,6 +21,7 @@ import org.apache.gravitino.auth.AuthConstants; import org.apache.gravitino.cli.AreYouSure; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchMetalakeException; @@ -35,16 +36,13 @@ public class DeleteUser extends Command { /** * Delete a user. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. - * @param force Force operation. + * @param context The command context. * @param metalake The name of the metalake. * @param user The name of the user. */ - public DeleteUser( - String url, boolean ignoreVersions, boolean force, String metalake, String user) { - super(url, ignoreVersions); - this.force = force; + public DeleteUser(CommandContext context, String metalake, String user) { + super(context); + this.force = context.force(); this.metalake = metalake; this.user = user; } @@ -74,9 +72,9 @@ public void handle() { } if (deleted) { - System.out.println(user + " deleted."); + printInformation(user + " deleted."); } else { - System.out.println(user + " not deleted."); + printInformation(user + " not deleted."); } } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/GroupAudit.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/GroupAudit.java index 9e79705bca3..8e52f09bb55 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/GroupAudit.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/GroupAudit.java @@ -20,6 +20,7 @@ package org.apache.gravitino.cli.commands; import org.apache.gravitino.authorization.Group; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchGroupException; @@ -33,13 +34,12 @@ public class GroupAudit extends AuditCommand { /** * Displays the audit information of a group. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param group The name of the group. */ - public GroupAudit(String url, boolean ignoreVersions, String metalake, String group) { - super(url, ignoreVersions); + public GroupAudit(CommandContext context, String metalake, String group) { + super(context); this.metalake = metalake; this.group = group; } @@ -47,19 +47,16 @@ public GroupAudit(String url, boolean ignoreVersions, String metalake, String gr /** Displays the audit information of a specified group. */ @Override public void handle() { - Group result; + Group result = null; try (GravitinoClient client = buildClient(metalake)) { result = client.getGroup(this.group); } catch (NoSuchMetalakeException err) { - System.err.println(ErrorMessages.UNKNOWN_METALAKE); - return; + exitWithError(ErrorMessages.UNKNOWN_METALAKE); } catch (NoSuchGroupException err) { - System.err.println(ErrorMessages.UNKNOWN_GROUP); - return; + exitWithError(ErrorMessages.UNKNOWN_GROUP); } catch (Exception exp) { - System.err.println(exp.getMessage()); - return; + exitWithError(exp.getMessage()); } if (result != null) { diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/GroupDetails.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/GroupDetails.java index 58188c38a3f..8667dc4b67b 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/GroupDetails.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/GroupDetails.java @@ -20,6 +20,7 @@ package org.apache.gravitino.cli.commands; import java.util.List; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchMetalakeException; @@ -33,13 +34,12 @@ public class GroupDetails extends Command { /** * Displays the roles in a group. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param group The name of the group. */ - public GroupDetails(String url, boolean ignoreVersions, String metalake, String group) { - super(url, ignoreVersions); + public GroupDetails(CommandContext context, String metalake, String group) { + super(context); this.metalake = metalake; this.group = group; } @@ -60,8 +60,10 @@ public void handle() { exitWithError(exp.getMessage()); } - String all = roles.isEmpty() ? "The group has no roles." : String.join(",", roles); - - System.out.println(all); + if (roles == null) { + printInformation("The group has no roles."); + } else { + printResults(String.join(",", roles)); + } } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListGroups.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListGroups.java index 844b8e21d09..b7374981152 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListGroups.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListGroups.java @@ -19,6 +19,7 @@ package org.apache.gravitino.cli.commands; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchMetalakeException; @@ -31,12 +32,11 @@ public class ListGroups extends Command { /** * Lists all groups in a metalake. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. */ - public ListGroups(String url, boolean ignoreVersions, String metalake) { - super(url, ignoreVersions); + public ListGroups(CommandContext context, String metalake) { + super(context); this.metalake = metalake; } @@ -53,8 +53,10 @@ public void handle() { exitWithError(exp.getMessage()); } - String all = groups.length == 0 ? "No groups exist." : String.join(",", groups); - - System.out.println(all); + if (groups.length == 0) { + printInformation("No groups found in metalake " + metalake); + } else { + printResults(String.join(",", groups)); + } } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListUsers.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListUsers.java index 3df4b7ca6bc..250d71e2f18 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListUsers.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListUsers.java @@ -19,6 +19,7 @@ package org.apache.gravitino.cli.commands; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchMetalakeException; @@ -31,12 +32,11 @@ public class ListUsers extends Command { /** * Lists all users in a metalake. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. */ - public ListUsers(String url, boolean ignoreVersions, String metalake) { - super(url, ignoreVersions); + public ListUsers(CommandContext context, String metalake) { + super(context); this.metalake = metalake; } @@ -53,8 +53,10 @@ public void handle() { exitWithError(exp.getMessage()); } - String all = users.length == 0 ? "No users exist." : String.join(",", users); - - System.out.println(all); + if (users.length == 0) { + printInformation("No users exist."); + } else { + printResults(String.join(",", users)); + } } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RemoveAllRoles.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RemoveAllRoles.java index eb7b354223d..70dacfd4179 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RemoveAllRoles.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RemoveAllRoles.java @@ -22,6 +22,7 @@ import java.util.List; import org.apache.gravitino.authorization.Group; import org.apache.gravitino.authorization.User; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.CommandEntities; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; @@ -38,15 +39,13 @@ public class RemoveAllRoles extends Command { /** * Removes all roles from a group or user. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param entity the name of the group or user. * @param entityType The type of the entity (group or user). */ - public RemoveAllRoles( - String url, boolean ignoreVersions, String metalake, String entity, String entityType) { - super(url, ignoreVersions); + public RemoveAllRoles(CommandContext context, String metalake, String entity, String entityType) { + super(context); this.metalake = metalake; this.entity = entity; this.entityType = entityType; @@ -77,6 +76,8 @@ private void revokeAllRolesFromGroup() { } catch (Exception e) { exitWithError(e.getMessage()); } + + printInformation("All roles have been revoked from group " + entity); } /** Removes all roles from a user. */ @@ -94,5 +95,7 @@ private void revokeAllRolesFromUser() { } catch (Exception e) { exitWithError(e.getMessage()); } + + printInformation("All roles have been revoked from user " + entity); } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RemoveRoleFromGroup.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RemoveRoleFromGroup.java index 7f2f7e2b2c4..8cd1f18339a 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RemoveRoleFromGroup.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RemoveRoleFromGroup.java @@ -20,6 +20,7 @@ package org.apache.gravitino.cli.commands; import java.util.ArrayList; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchMetalakeException; @@ -36,15 +37,13 @@ public class RemoveRoleFromGroup extends Command { /** * Remove a role from a group. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param group The name of the group. * @param role The name of the role. */ - public RemoveRoleFromGroup( - String url, boolean ignoreVersions, String metalake, String group, String role) { - super(url, ignoreVersions); + public RemoveRoleFromGroup(CommandContext context, String metalake, String group, String role) { + super(context); this.metalake = metalake; this.group = group; this.role = role; @@ -68,6 +67,6 @@ public void handle() { exitWithError(exp.getMessage()); } - System.out.println(role + " removed from " + group); + printInformation(role + " removed from " + group); } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RemoveRoleFromUser.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RemoveRoleFromUser.java index 85a1edbeae4..d45db161338 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RemoveRoleFromUser.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RemoveRoleFromUser.java @@ -20,6 +20,7 @@ package org.apache.gravitino.cli.commands; import java.util.ArrayList; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchMetalakeException; @@ -36,15 +37,13 @@ public class RemoveRoleFromUser extends Command { /** * Removes a role from a user. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param user The name of the user. * @param role The name of the role. */ - public RemoveRoleFromUser( - String url, boolean ignoreVersions, String metalake, String user, String role) { - super(url, ignoreVersions); + public RemoveRoleFromUser(CommandContext context, String metalake, String user, String role) { + super(context); this.metalake = metalake; this.user = user; this.role = role; @@ -68,6 +67,6 @@ public void handle() { exitWithError(exp.getMessage()); } - System.out.println(role + " removed from " + user); + printInformation(role + " removed from " + user); } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UserAudit.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UserAudit.java index 44ac2babc6f..73b4f32e5fa 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UserAudit.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UserAudit.java @@ -20,6 +20,7 @@ package org.apache.gravitino.cli.commands; import org.apache.gravitino.authorization.User; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchMetalakeException; @@ -33,13 +34,12 @@ public class UserAudit extends AuditCommand { /** * Displays the audit information of a user. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param user The name of the user. */ - public UserAudit(String url, boolean ignoreVersions, String metalake, String user) { - super(url, ignoreVersions); + public UserAudit(CommandContext context, String metalake, String user) { + super(context); this.metalake = metalake; this.user = user; } @@ -47,19 +47,16 @@ public UserAudit(String url, boolean ignoreVersions, String metalake, String use /** Displays the audit information of a specified user. */ @Override public void handle() { - User result; + User result = null; try (GravitinoClient client = buildClient(metalake)) { result = client.getUser(this.user); } catch (NoSuchMetalakeException err) { - System.err.println(ErrorMessages.UNKNOWN_METALAKE); - return; + exitWithError(ErrorMessages.UNKNOWN_METALAKE); } catch (NoSuchUserException err) { - System.err.println(ErrorMessages.UNKNOWN_USER); - return; + exitWithError(ErrorMessages.UNKNOWN_USER); } catch (Exception exp) { - System.err.println(exp.getMessage()); - return; + exitWithError(exp.getMessage()); } if (result != null) { diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UserDetails.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UserDetails.java index d89597d1698..26c11a0e12b 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UserDetails.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UserDetails.java @@ -20,6 +20,7 @@ package org.apache.gravitino.cli.commands; import java.util.List; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchMetalakeException; @@ -33,13 +34,12 @@ public class UserDetails extends Command { /** * Displays the roles of a user. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param user The name of the user. */ - public UserDetails(String url, boolean ignoreVersions, String metalake, String user) { - super(url, ignoreVersions); + public UserDetails(CommandContext context, String metalake, String user) { + super(context); this.metalake = metalake; this.user = user; } @@ -60,8 +60,10 @@ public void handle() { exitWithError(exp.getMessage()); } - String all = roles.isEmpty() ? "The user has no roles." : String.join(",", roles); - - System.out.println(all); + if (roles.isEmpty()) { + printInformation("The user has no roles."); + } else { + printResults(String.join(",", roles)); + } } } diff --git a/clients/cli/src/test/java/org/apache/gravitino/cli/TestGroupCommands.java b/clients/cli/src/test/java/org/apache/gravitino/cli/TestGroupCommands.java index cae8402d8bb..eb8b923112c 100644 --- a/clients/cli/src/test/java/org/apache/gravitino/cli/TestGroupCommands.java +++ b/clients/cli/src/test/java/org/apache/gravitino/cli/TestGroupCommands.java @@ -21,6 +21,9 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThrows; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; @@ -83,7 +86,7 @@ void testListGroupsCommand() { mockCommandLine, mockOptions, CommandEntities.GROUP, CommandActions.LIST)); doReturn(mockList) .when(commandLine) - .newListGroups(GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo"); + .newListGroups(any(CommandContext.class), eq("metalake_demo")); doReturn(mockList).when(mockList).validate(); commandLine.handleCommandLine(); verify(mockList).handle(); @@ -102,7 +105,7 @@ void testGroupDetailsCommand() { mockCommandLine, mockOptions, CommandEntities.GROUP, CommandActions.DETAILS)); doReturn(mockDetails) .when(commandLine) - .newGroupDetails(GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "groupA"); + .newGroupDetails(any(CommandContext.class), eq("metalake_demo"), eq("groupA")); doReturn(mockDetails).when(mockDetails).validate(); commandLine.handleCommandLine(); verify(mockDetails).handle(); @@ -122,7 +125,7 @@ void testGroupAuditCommand() { mockCommandLine, mockOptions, CommandEntities.GROUP, CommandActions.DETAILS)); doReturn(mockAudit) .when(commandLine) - .newGroupAudit(GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "group"); + .newGroupAudit(any(CommandContext.class), eq("metalake_demo"), eq("group")); doReturn(mockAudit).when(mockAudit).validate(); commandLine.handleCommandLine(); verify(mockAudit).handle(); @@ -141,7 +144,7 @@ void testCreateGroupCommand() { mockCommandLine, mockOptions, CommandEntities.GROUP, CommandActions.CREATE)); doReturn(mockCreate) .when(commandLine) - .newCreateGroup(GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "groupA"); + .newCreateGroup(any(CommandContext.class), eq("metalake_demo"), eq("groupA")); doReturn(mockCreate).when(mockCreate).validate(); commandLine.handleCommandLine(); verify(mockCreate).handle(); @@ -160,7 +163,7 @@ void testDeleteGroupCommand() { mockCommandLine, mockOptions, CommandEntities.GROUP, CommandActions.DELETE)); doReturn(mockDelete) .when(commandLine) - .newDeleteGroup(GravitinoCommandLine.DEFAULT_URL, false, false, "metalake_demo", "groupA"); + .newDeleteGroup(any(CommandContext.class), eq("metalake_demo"), eq("groupA")); doReturn(mockDelete).when(mockDelete).validate(); commandLine.handleCommandLine(); verify(mockDelete).handle(); @@ -180,7 +183,7 @@ void testDeleteGroupForceCommand() { mockCommandLine, mockOptions, CommandEntities.GROUP, CommandActions.DELETE)); doReturn(mockDelete) .when(commandLine) - .newDeleteGroup(GravitinoCommandLine.DEFAULT_URL, false, true, "metalake_demo", "groupA"); + .newDeleteGroup(any(CommandContext.class), eq("metalake_demo"), eq("groupA")); doReturn(mockDelete).when(mockDelete).validate(); commandLine.handleCommandLine(); verify(mockDelete).handle(); @@ -201,7 +204,7 @@ void testRemoveRoleFromGroupCommand() { doReturn(mockRemove) .when(commandLine) .newRemoveRoleFromGroup( - GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "groupA", "admin"); + any(CommandContext.class), eq("metalake_demo"), eq("groupA"), eq("admin")); commandLine.handleCommandLine(); verify(mockRemove).handle(); } @@ -221,7 +224,7 @@ void testAddRoleToGroupCommand() { doReturn(mockAdd) .when(commandLine) .newAddRoleToGroup( - GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "groupA", "admin"); + any(CommandContext.class), eq("metalake_demo"), eq("groupA"), eq("admin")); commandLine.handleCommandLine(); verify(mockAdd).handle(); } @@ -245,13 +248,13 @@ void testRemoveRolesFromGroupCommand() { doReturn(mockRemoveFirstRole) .when(commandLine) .newRemoveRoleFromGroup( - GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "groupA", "admin"); + any(CommandContext.class), eq("metalake_demo"), eq("groupA"), eq("admin")); // Verify second role doReturn(mockRemoveSecondRole) .when(commandLine) .newRemoveRoleFromGroup( - GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "groupA", "role1"); + any(CommandContext.class), eq("metalake_demo"), eq("groupA"), eq("role1")); doReturn(mockRemoveFirstRole).when(mockRemoveFirstRole).validate(); doReturn(mockRemoveSecondRole).when(mockRemoveSecondRole).validate(); @@ -277,11 +280,10 @@ void testRemoveAllRolesFromGroupCommand() { doReturn(mock) .when(commandLine) .newRemoveAllRoles( - GravitinoCommandLine.DEFAULT_URL, - false, - "metalake_demo", - "groupA", - CommandEntities.GROUP); + any(CommandContext.class), + eq("metalake_demo"), + eq("groupA"), + eq(CommandEntities.GROUP)); doReturn(mock).when(mock).validate(); commandLine.handleCommandLine(); verify(mock).handle(); @@ -306,13 +308,13 @@ void testAddRolesToGroupCommand() { doReturn(mockAddFirstRole) .when(commandLine) .newAddRoleToGroup( - GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "groupA", "admin"); + any(CommandContext.class), eq("metalake_demo"), eq("groupA"), eq("admin")); // Verify second role doReturn(mockAddSecondRole) .when(commandLine) .newAddRoleToGroup( - GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "groupA", "role1"); + any(CommandContext.class), eq("metalake_demo"), eq("groupA"), eq("role1")); doReturn(mockAddFirstRole).when(mockAddFirstRole).validate(); doReturn(mockAddSecondRole).when(mockAddSecondRole).validate(); @@ -336,7 +338,7 @@ void testDeleteGroupCommandWithoutGroupOption() { assertThrows(RuntimeException.class, commandLine::handleCommandLine); verify(commandLine, never()) - .newDeleteGroup(GravitinoCommandLine.DEFAULT_URL, false, false, "metalake_demo", null); + .newDeleteGroup(any(CommandContext.class), eq("metalake_demo"), isNull()); String output = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); assertEquals(output, ErrorMessages.MISSING_GROUP); } diff --git a/clients/cli/src/test/java/org/apache/gravitino/cli/TestUserCommands.java b/clients/cli/src/test/java/org/apache/gravitino/cli/TestUserCommands.java index 47f003c96b4..2d004ab9599 100644 --- a/clients/cli/src/test/java/org/apache/gravitino/cli/TestUserCommands.java +++ b/clients/cli/src/test/java/org/apache/gravitino/cli/TestUserCommands.java @@ -21,6 +21,9 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThrows; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; @@ -83,7 +86,7 @@ void testListUsersCommand() { mockCommandLine, mockOptions, CommandEntities.USER, CommandActions.LIST)); doReturn(mockList) .when(commandLine) - .newListUsers(GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo"); + .newListUsers(any(CommandContext.class), eq("metalake_demo")); doReturn(mockList).when(mockList).validate(); commandLine.handleCommandLine(); verify(mockList).handle(); @@ -102,7 +105,7 @@ void testUserDetailsCommand() { mockCommandLine, mockOptions, CommandEntities.USER, CommandActions.DETAILS)); doReturn(mockDetails) .when(commandLine) - .newUserDetails(GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "user"); + .newUserDetails(any(CommandContext.class), eq("metalake_demo"), eq("user")); doReturn(mockDetails).when(mockDetails).validate(); commandLine.handleCommandLine(); verify(mockDetails).handle(); @@ -122,7 +125,7 @@ void testUserAuditCommand() { mockCommandLine, mockOptions, CommandEntities.USER, CommandActions.DETAILS)); doReturn(mockAudit) .when(commandLine) - .newUserAudit(GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "admin"); + .newUserAudit(any(CommandContext.class), eq("metalake_demo"), eq("admin")); doReturn(mockAudit).when(mockAudit).validate(); commandLine.handleCommandLine(); verify(mockAudit).handle(); @@ -141,7 +144,7 @@ void testCreateUserCommand() { mockCommandLine, mockOptions, CommandEntities.USER, CommandActions.CREATE)); doReturn(mockCreate) .when(commandLine) - .newCreateUser(GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "user"); + .newCreateUser(any(CommandContext.class), eq("metalake_demo"), eq("user")); doReturn(mockCreate).when(mockCreate).validate(); commandLine.handleCommandLine(); verify(mockCreate).handle(); @@ -160,7 +163,7 @@ void testDeleteUserCommand() { mockCommandLine, mockOptions, CommandEntities.USER, CommandActions.DELETE)); doReturn(mockDelete) .when(commandLine) - .newDeleteUser(GravitinoCommandLine.DEFAULT_URL, false, false, "metalake_demo", "user"); + .newDeleteUser(any(CommandContext.class), eq("metalake_demo"), eq("user")); doReturn(mockDelete).when(mockDelete).validate(); commandLine.handleCommandLine(); verify(mockDelete).handle(); @@ -180,7 +183,7 @@ void testDeleteUserForceCommand() { mockCommandLine, mockOptions, CommandEntities.USER, CommandActions.DELETE)); doReturn(mockDelete) .when(commandLine) - .newDeleteUser(GravitinoCommandLine.DEFAULT_URL, false, true, "metalake_demo", "user"); + .newDeleteUser(any(CommandContext.class), eq("metalake_demo"), eq("user")); doReturn(mockDelete).when(mockDelete).validate(); commandLine.handleCommandLine(); verify(mockDelete).handle(); @@ -201,7 +204,7 @@ void testRemoveRoleFromUserCommand() { doReturn(mockRemove) .when(commandLine) .newRemoveRoleFromUser( - GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "user", "admin"); + any(CommandContext.class), eq("metalake_demo"), eq("user"), eq("admin")); commandLine.handleCommandLine(); verify(mockRemove).handle(); } @@ -221,7 +224,7 @@ void testAddRoleToUserCommand() { doReturn(mockAdd) .when(commandLine) .newRemoveRoleFromUser( - GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "user", "admin"); + any(CommandContext.class), eq("metalake_demo"), eq("user"), eq("admin")); commandLine.handleCommandLine(); verify(mockAdd).handle(); } @@ -246,13 +249,13 @@ void testRemoveRolesFromUserCommand() { doReturn(mockRemoveFirstRole) .when(commandLine) .newRemoveRoleFromUser( - GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "user", "admin"); + any(CommandContext.class), eq("metalake_demo"), eq("user"), eq("admin")); // Verify second role doReturn(mockRemoveSecondRole) .when(commandLine) .newRemoveRoleFromUser( - GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "user", "role1"); + any(CommandContext.class), eq("metalake_demo"), eq("user"), eq("role1")); doReturn(mockRemoveFirstRole).when(mockRemoveFirstRole).validate(); doReturn(mockRemoveSecondRole).when(mockRemoveSecondRole).validate(); @@ -276,8 +279,7 @@ void removeAllRolesFromUserCommand() { mockCommandLine, mockOptions, CommandEntities.USER, CommandActions.REVOKE)); doReturn(mockRemove) .when(commandLine) - .newRemoveAllRoles( - GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "user", CommandEntities.USER); + .newRemoveAllRoles(any(CommandContext.class), eq("metalake_demo"), eq("user"), any()); doReturn(mockRemove).when(mockRemove).validate(); commandLine.handleCommandLine(); verify(mockRemove).handle(); @@ -302,14 +304,12 @@ void testAddRolesToUserCommand() { // Verify first role doReturn(mockAddFirstRole) .when(commandLine) - .newAddRoleToUser( - GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "user", "admin"); + .newAddRoleToUser(any(CommandContext.class), eq("metalake_demo"), eq("user"), eq("admin")); // Verify second role doReturn(mockAddSecondRole) .when(commandLine) - .newAddRoleToUser( - GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "user", "role1"); + .newAddRoleToUser(any(CommandContext.class), eq("metalake_demo"), eq("user"), eq("role1")); doReturn(mockAddFirstRole).when(mockAddFirstRole).validate(); doReturn(mockAddSecondRole).when(mockAddSecondRole).validate(); @@ -332,7 +332,7 @@ void testDeleteUserWithoutUserOption() { assertThrows(RuntimeException.class, commandLine::handleCommandLine); verify(commandLine, never()) - .newDeleteUser(GravitinoCommandLine.DEFAULT_URL, false, false, "metalake_demo", null); + .newDeleteUser(any(CommandContext.class), eq("metalake_demo"), isNull()); String output = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); assertEquals(output, ErrorMessages.MISSING_USER); } From 423d311ccb39c113f45d658775ef3677d9373fad Mon Sep 17 00:00:00 2001 From: Lord of Abyss <103809695+Abyss-lord@users.noreply.github.com> Date: Wed, 12 Feb 2025 07:37:12 +0800 Subject: [PATCH 25/33] [#6422] improve(CLI): Add roles and owner command context CLI (#6438) ### What changes were proposed in this pull request? Add roles and owner command context CLI ### Why are the changes needed? Fix: #6422 ### Does this PR introduce _any_ user-facing change? No. ### How was this patch tested? local test. --- .../gravitino/cli/GravitinoCommandLine.java | 4 +- .../gravitino/cli/OwnerCommandHandler.java | 20 ++--- .../gravitino/cli/RoleCommandHandler.java | 33 ++++---- .../gravitino/cli/TestableCommandLine.java | 52 +++++------- .../gravitino/cli/commands/CreateRole.java | 10 +-- .../gravitino/cli/commands/DeleteRole.java | 12 ++- .../cli/commands/GrantPrivilegesToRole.java | 30 +++---- .../gravitino/cli/commands/ListRoles.java | 17 ++-- .../gravitino/cli/commands/OwnerDetails.java | 13 ++- .../cli/commands/RevokeAllPrivileges.java | 23 +++-- .../commands/RevokePrivilegesFromRole.java | 18 ++-- .../gravitino/cli/commands/RoleAudit.java | 19 ++--- .../gravitino/cli/commands/RoleDetails.java | 14 ++-- .../gravitino/cli/commands/SetOwner.java | 11 ++- .../gravitino/cli/TestOwnerCommands.java | 51 ++++++------ .../gravitino/cli/TestRoleCommands.java | 83 ++++++++----------- 16 files changed, 174 insertions(+), 236 deletions(-) diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/GravitinoCommandLine.java b/clients/cli/src/main/java/org/apache/gravitino/cli/GravitinoCommandLine.java index e61051e5382..3a7c656691a 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/GravitinoCommandLine.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/GravitinoCommandLine.java @@ -114,7 +114,7 @@ private void executeCommand() { if (CommandActions.HELP.equals(command)) { handleHelpCommand(); } else if (line.hasOption(GravitinoOptions.OWNER)) { - new OwnerCommandHandler(this, line, command, ignore, entity).handle(); + new OwnerCommandHandler(this, line, command, context, entity).handle(); } else if (entity.equals(CommandEntities.COLUMN)) { new ColumnCommandHandler(this, line, command, context).handle(); } else if (entity.equals(CommandEntities.TABLE)) { @@ -136,7 +136,7 @@ private void executeCommand() { } else if (entity.equals(CommandEntities.TAG)) { new TagCommandHandler(this, line, command, context).handle(); } else if (entity.equals(CommandEntities.ROLE)) { - new RoleCommandHandler(this, line, command, ignore).handle(); + new RoleCommandHandler(this, line, command, context).handle(); } else if (entity.equals(CommandEntities.MODEL)) { new ModelCommandHandler(this, line, command, context).handle(); } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/OwnerCommandHandler.java b/clients/cli/src/main/java/org/apache/gravitino/cli/OwnerCommandHandler.java index 7e41fb478ae..28fb7fb3803 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/OwnerCommandHandler.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/OwnerCommandHandler.java @@ -27,8 +27,7 @@ public class OwnerCommandHandler extends CommandHandler { private final GravitinoCommandLine gravitinoCommandLine; private final CommandLine line; private final String command; - private final boolean ignore; - private final String url; + private final CommandContext context; private final FullName name; private final String metalake; private final String entityName; @@ -42,21 +41,21 @@ public class OwnerCommandHandler extends CommandHandler { * @param gravitinoCommandLine The Gravitino command line instance. * @param line The command line arguments. * @param command The command to execute. - * @param ignore Ignore server version mismatch. + * @param context The command context. * @param entity The entity to execute the command on. */ public OwnerCommandHandler( GravitinoCommandLine gravitinoCommandLine, CommandLine line, String command, - boolean ignore, + CommandContext context, String entity) { this.gravitinoCommandLine = gravitinoCommandLine; this.line = line; this.command = command; - this.ignore = ignore; + this.context = context; - this.url = getUrl(line); + this.context.setUrl(getUrl(line)); this.owner = line.getOptionValue(GravitinoOptions.USER); this.group = line.getOptionValue(GravitinoOptions.GROUP); this.name = new FullName(line); @@ -102,22 +101,19 @@ private boolean executeCommand() { /** Handles the "DETAILS" command. */ private void handleDetailsCommand() { - gravitinoCommandLine - .newOwnerDetails(url, ignore, metalake, entityName, entity) - .validate() - .handle(); + gravitinoCommandLine.newOwnerDetails(context, metalake, entityName, entity).validate().handle(); } /** Handles the "SET" command. */ private void handleSetCommand() { if (owner != null && group == null) { gravitinoCommandLine - .newSetOwner(url, ignore, metalake, entityName, entity, owner, false) + .newSetOwner(context, metalake, entityName, entity, owner, false) .validate() .handle(); } else if (owner == null && group != null) { gravitinoCommandLine - .newSetOwner(url, ignore, metalake, entityName, entity, group, true) + .newSetOwner(context, metalake, entityName, entity, group, true) .validate() .handle(); } else { diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/RoleCommandHandler.java b/clients/cli/src/main/java/org/apache/gravitino/cli/RoleCommandHandler.java index 327ef21fdd8..ef21ec5c419 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/RoleCommandHandler.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/RoleCommandHandler.java @@ -28,19 +28,21 @@ public class RoleCommandHandler extends CommandHandler { private final GravitinoCommandLine gravitinoCommandLine; private final CommandLine line; private final String command; - private final boolean ignore; - private final String url; + private final CommandContext context; private String metalake; private String[] roles; private String[] privileges; public RoleCommandHandler( - GravitinoCommandLine gravitinoCommandLine, CommandLine line, String command, boolean ignore) { + GravitinoCommandLine gravitinoCommandLine, + CommandLine line, + String command, + CommandContext context) { this.gravitinoCommandLine = gravitinoCommandLine; this.line = line; this.command = command; - this.ignore = ignore; - this.url = getUrl(line); + this.context = context; + this.context.setUrl(getUrl(line)); } /** Handles the command execution logic based on the provided command. */ @@ -106,32 +108,27 @@ private boolean executeCommand() { private void handleDetailsCommand() { if (line.hasOption(GravitinoOptions.AUDIT)) { - gravitinoCommandLine.newRoleAudit(url, ignore, metalake, getOneRole()).validate().handle(); + gravitinoCommandLine.newRoleAudit(context, metalake, getOneRole()).validate().handle(); } else { - gravitinoCommandLine.newRoleDetails(url, ignore, metalake, getOneRole()).validate().handle(); + gravitinoCommandLine.newRoleDetails(context, metalake, getOneRole()).validate().handle(); } } private void handleListCommand() { - gravitinoCommandLine.newListRoles(url, ignore, metalake).validate().handle(); + gravitinoCommandLine.newListRoles(context, metalake).validate().handle(); } private void handleCreateCommand() { - gravitinoCommandLine.newCreateRole(url, ignore, metalake, roles).validate().handle(); + gravitinoCommandLine.newCreateRole(context, metalake, roles).validate().handle(); } private void handleDeleteCommand() { - boolean forceDelete = line.hasOption(GravitinoOptions.FORCE); - gravitinoCommandLine - .newDeleteRole(url, ignore, forceDelete, metalake, roles) - .validate() - .handle(); + gravitinoCommandLine.newDeleteRole(context, metalake, roles).validate().handle(); } private void handleGrantCommand() { gravitinoCommandLine - .newGrantPrivilegesToRole( - url, ignore, metalake, getOneRole(), new FullName(line), privileges) + .newGrantPrivilegesToRole(context, metalake, getOneRole(), new FullName(line), privileges) .validate() .handle(); } @@ -140,13 +137,13 @@ private void handleRevokeCommand() { boolean removeAll = line.hasOption(GravitinoOptions.ALL); if (removeAll) { gravitinoCommandLine - .newRevokeAllPrivileges(url, ignore, metalake, getOneRole(), new FullName(line)) + .newRevokeAllPrivileges(context, metalake, getOneRole(), new FullName(line)) .validate() .handle(); } else { gravitinoCommandLine .newRevokePrivilegesFromRole( - url, ignore, metalake, getOneRole(), new FullName(line), privileges) + context, metalake, getOneRole(), new FullName(line), privileges) .validate() .handle(); } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/TestableCommandLine.java b/clients/cli/src/main/java/org/apache/gravitino/cli/TestableCommandLine.java index a4f47239c71..22425b621b6 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/TestableCommandLine.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/TestableCommandLine.java @@ -451,25 +451,24 @@ protected AddRoleToGroup newAddRoleToGroup( return new AddRoleToGroup(context, metalake, group, role); } - protected RoleDetails newRoleDetails(String url, boolean ignore, String metalake, String role) { - return new RoleDetails(url, ignore, metalake, role); + protected RoleDetails newRoleDetails(CommandContext context, String metalake, String role) { + return new RoleDetails(context, metalake, role); } - protected ListRoles newListRoles(String url, boolean ignore, String metalake) { - return new ListRoles(url, ignore, metalake); + protected ListRoles newListRoles(CommandContext context, String metalake) { + return new ListRoles(context, metalake); } - protected RoleAudit newRoleAudit(String url, boolean ignore, String metalake, String role) { - return new RoleAudit(url, ignore, metalake, role); + protected RoleAudit newRoleAudit(CommandContext context, String metalake, String role) { + return new RoleAudit(context, metalake, role); } - protected CreateRole newCreateRole(String url, boolean ignore, String metalake, String[] roles) { - return new CreateRole(url, ignore, metalake, roles); + protected CreateRole newCreateRole(CommandContext context, String metalake, String[] roles) { + return new CreateRole(context, metalake, roles); } - protected DeleteRole newDeleteRole( - String url, boolean ignore, boolean force, String metalake, String[] roles) { - return new DeleteRole(url, ignore, force, metalake, roles); + protected DeleteRole newDeleteRole(CommandContext context, String metalake, String[] roles) { + return new DeleteRole(context, metalake, roles); } protected TagDetails newTagDetails(CommandContext context, String metalake, String tag) { @@ -549,19 +548,18 @@ protected ListColumns newListColumns( } protected SetOwner newSetOwner( - String url, - boolean ignore, + CommandContext context, String metalake, String entity, String entityType, String owner, boolean isGroup) { - return new SetOwner(url, ignore, metalake, entity, entityType, owner, isGroup); + return new SetOwner(context, metalake, entity, entityType, owner, isGroup); } protected OwnerDetails newOwnerDetails( - String url, boolean ignore, String metalake, String entity, String entityType) { - return new OwnerDetails(url, ignore, metalake, entity, entityType); + CommandContext context, String metalake, String entity, String entityType) { + return new OwnerDetails(context, metalake, entity, entityType); } protected ListTopics newListTopics( @@ -827,28 +825,18 @@ protected CreateTable newCreateTable( } protected GrantPrivilegesToRole newGrantPrivilegesToRole( - String url, - boolean ignore, - String metalake, - String role, - FullName entity, - String[] privileges) { - return new GrantPrivilegesToRole(url, ignore, metalake, role, entity, privileges); + CommandContext context, String metalake, String role, FullName entity, String[] privileges) { + return new GrantPrivilegesToRole(context, metalake, role, entity, privileges); } protected RevokePrivilegesFromRole newRevokePrivilegesFromRole( - String url, - boolean ignore, - String metalake, - String role, - FullName entity, - String[] privileges) { - return new RevokePrivilegesFromRole(url, ignore, metalake, role, entity, privileges); + CommandContext context, String metalake, String role, FullName entity, String[] privileges) { + return new RevokePrivilegesFromRole(context, metalake, role, entity, privileges); } protected RevokeAllPrivileges newRevokeAllPrivileges( - String url, boolean ignore, String metalake, String role, FullName entity) { - return new RevokeAllPrivileges(url, ignore, metalake, role, entity); + CommandContext context, String metalake, String role, FullName entity) { + return new RevokeAllPrivileges(context, metalake, role, entity); } protected MetalakeEnable newMetalakeEnable( diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/CreateRole.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/CreateRole.java index e821013471f..aeecaaf0a3f 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/CreateRole.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/CreateRole.java @@ -21,6 +21,7 @@ import com.google.common.base.Joiner; import java.util.Collections; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchMetalakeException; @@ -33,13 +34,12 @@ public class CreateRole extends Command { /** * Create a new role. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param roles The array of roles. */ - public CreateRole(String url, boolean ignoreVersions, String metalake, String[] roles) { - super(url, ignoreVersions); + public CreateRole(CommandContext context, String metalake, String[] roles) { + super(context); this.metalake = metalake; this.roles = roles; } @@ -60,6 +60,6 @@ public void handle() { exitWithError(exp.getMessage()); } - System.out.println(Joiner.on(", ").join(roles) + " created"); + printInformation(Joiner.on(", ").join(roles) + " created"); } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/DeleteRole.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/DeleteRole.java index 4e0bb508d19..f596ed09631 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/DeleteRole.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/DeleteRole.java @@ -23,6 +23,7 @@ import com.google.common.collect.Lists; import java.util.List; import org.apache.gravitino.cli.AreYouSure; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchMetalakeException; @@ -37,17 +38,14 @@ public class DeleteRole extends Command { /** * Delete a role. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. - * @param force Force operation. + * @param context The command context. * @param metalake The name of the metalake. * @param roles The name of the role. */ - public DeleteRole( - String url, boolean ignoreVersions, boolean force, String metalake, String[] roles) { - super(url, ignoreVersions); + public DeleteRole(CommandContext context, String metalake, String[] roles) { + super(context); this.metalake = metalake; - this.force = force; + this.force = context.force(); this.roles = roles; } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/GrantPrivilegesToRole.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/GrantPrivilegesToRole.java index b21a74ff48c..4bdcc618b4c 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/GrantPrivilegesToRole.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/GrantPrivilegesToRole.java @@ -23,6 +23,7 @@ import java.util.Set; import org.apache.gravitino.MetadataObject; import org.apache.gravitino.authorization.Privilege; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.cli.FullName; import org.apache.gravitino.cli.Privileges; @@ -43,21 +44,15 @@ public class GrantPrivilegesToRole extends MetadataCommand { /** * Grants one or more privileges. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param role The name of the role. * @param entity The name of the entity. * @param privileges The list of privileges. */ public GrantPrivilegesToRole( - String url, - boolean ignoreVersions, - String metalake, - String role, - FullName entity, - String[] privileges) { - super(url, ignoreVersions); + CommandContext context, String metalake, String role, FullName entity, String[] privileges) { + super(context); this.metalake = metalake; this.entity = entity; this.role = role; @@ -73,8 +68,7 @@ public void handle() { for (String privilege : privileges) { if (!Privileges.isValid(privilege)) { - System.err.println(ErrorMessages.UNKNOWN_PRIVILEGE + " " + privilege); - return; + exitWithError(ErrorMessages.UNKNOWN_PRIVILEGE + " " + privilege); } PrivilegeDTO privilegeDTO = PrivilegeDTO.builder() @@ -87,21 +81,17 @@ public void handle() { MetadataObject metadataObject = constructMetadataObject(entity, client); client.grantPrivilegesToRole(role, metadataObject, privilegesSet); } catch (NoSuchMetalakeException err) { - System.err.println(ErrorMessages.UNKNOWN_METALAKE); - return; + exitWithError(ErrorMessages.UNKNOWN_METALAKE); } catch (NoSuchRoleException err) { - System.err.println(ErrorMessages.UNKNOWN_ROLE); - return; + exitWithError(ErrorMessages.UNKNOWN_ROLE); } catch (NoSuchMetadataObjectException err) { - System.err.println(ErrorMessages.UNKNOWN_USER); - return; + exitWithError(ErrorMessages.UNKNOWN_USER); } catch (Exception exp) { - System.err.println(exp.getMessage()); - return; + exitWithError(exp.getMessage()); } String all = String.join(",", privileges); - System.out.println(role + " granted " + all + " on " + entity.getName()); + printInformation(role + " granted " + all + " on " + entity.getName()); } @Override diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListRoles.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListRoles.java index 760fe21e3bc..d859c377c7f 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListRoles.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListRoles.java @@ -19,6 +19,7 @@ package org.apache.gravitino.cli.commands; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchMetalakeException; @@ -31,12 +32,11 @@ public class ListRoles extends Command { /** * Lists all groups in a metalake. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. */ - public ListRoles(String url, boolean ignoreVersions, String metalake) { - super(url, ignoreVersions); + public ListRoles(CommandContext context, String metalake) { + super(context); this.metalake = metalake; } @@ -52,9 +52,10 @@ public void handle() { } catch (Exception exp) { exitWithError(exp.getMessage()); } - - String all = roles.length == 0 ? "No roles exist." : String.join(",", roles); - - System.out.println(all); + if (roles.length == 0) { + printInformation("No roles exist."); + } else { + printResults(String.join(",", roles)); + } } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/OwnerDetails.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/OwnerDetails.java index a815d6ba14d..2c8d17a9f77 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/OwnerDetails.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/OwnerDetails.java @@ -23,6 +23,7 @@ import org.apache.gravitino.MetadataObject; import org.apache.gravitino.MetadataObjects; import org.apache.gravitino.authorization.Owner; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.CommandEntities; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; @@ -38,15 +39,13 @@ public class OwnerDetails extends Command { /** * Displays the owner of an entity. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param entity The name of the entity. * @param entityType The type entity. */ - public OwnerDetails( - String url, boolean ignoreVersions, String metalake, String entity, String entityType) { - super(url, ignoreVersions); + public OwnerDetails(CommandContext context, String metalake, String entity, String entityType) { + super(context); this.metalake = metalake; this.entity = entity; @@ -83,9 +82,9 @@ public void handle() { } if (owner.isPresent()) { - System.out.println(owner.get().name()); + printResults(owner.get().name()); } else { - System.out.println("No owner"); + printInformation("No owner"); } } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RevokeAllPrivileges.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RevokeAllPrivileges.java index 3167c4b6c37..2b059b9afff 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RevokeAllPrivileges.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RevokeAllPrivileges.java @@ -30,6 +30,7 @@ import org.apache.gravitino.authorization.Privilege; import org.apache.gravitino.authorization.Role; import org.apache.gravitino.authorization.SecurableObject; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.cli.FullName; import org.apache.gravitino.client.GravitinoClient; @@ -46,15 +47,14 @@ public class RevokeAllPrivileges extends MetadataCommand { /** * Revokes all privileges from a role to an entity or all entities. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param role The name of the role. * @param entity The name of the entity. */ public RevokeAllPrivileges( - String url, boolean ignoreVersions, String metalake, String role, FullName entity) { - super(url, ignoreVersions); + CommandContext context, String metalake, String role, FullName entity) { + super(context); this.metalake = metalake; this.role = role; this.entity = entity; @@ -86,8 +86,11 @@ public void handle() { exitWithError(e.getMessage()); } - if (revokedPrivileges.isEmpty()) outputRevokedPrivileges("No privileges revoked."); - outputRevokedPrivileges(revokedPrivileges); + if (revokedPrivileges.isEmpty()) { + printInformation("No privileges revoked."); + } else { + outputRevokedPrivileges(revokedPrivileges); + } } private List getMatchedObjects(GravitinoClient client) { @@ -106,16 +109,12 @@ private void outputRevokedPrivileges(Map> revokedPrivileg revokedInfoList.add(entry.getKey() + ": " + COMMA_JOINER.join(revokedPrivilegesList)); } - System.out.println("Revoked privileges:"); + printInformation("Revoked privileges:"); for (String info : revokedInfoList) { - System.out.println(info); + printResults(info); } } - private void outputRevokedPrivileges(String message) { - System.out.println(message); - } - /** * verify the arguments. * diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RevokePrivilegesFromRole.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RevokePrivilegesFromRole.java index 5907c494c05..c1e80708b32 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RevokePrivilegesFromRole.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RevokePrivilegesFromRole.java @@ -23,6 +23,7 @@ import java.util.Set; import org.apache.gravitino.MetadataObject; import org.apache.gravitino.authorization.Privilege; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.cli.FullName; import org.apache.gravitino.cli.Privileges; @@ -43,21 +44,15 @@ public class RevokePrivilegesFromRole extends MetadataCommand { /** * Revokes one or more privileges. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param role The name of the role. * @param entity The name of the entity. * @param privileges The list of privileges. */ public RevokePrivilegesFromRole( - String url, - boolean ignoreVersions, - String metalake, - String role, - FullName entity, - String[] privileges) { - super(url, ignoreVersions); + CommandContext context, String metalake, String role, FullName entity, String[] privileges) { + super(context); this.metalake = metalake; this.entity = entity; this.role = role; @@ -73,8 +68,7 @@ public void handle() { for (String privilege : privileges) { if (!Privileges.isValid(privilege)) { - System.err.println(ErrorMessages.UNKNOWN_PRIVILEGE + " " + privilege); - return; + exitWithError(ErrorMessages.UNKNOWN_PRIVILEGE + " " + privilege); } PrivilegeDTO privilegeDTO = PrivilegeDTO.builder() @@ -97,7 +91,7 @@ public void handle() { } String all = String.join(",", privileges); - System.out.println(role + " revoked " + all + " on " + entity.getName()); + printInformation(role + " revoked " + all + " on " + entity.getName()); } @Override diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RoleAudit.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RoleAudit.java index e497ca836f5..f512a3089ba 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RoleAudit.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RoleAudit.java @@ -20,6 +20,7 @@ package org.apache.gravitino.cli.commands; import org.apache.gravitino.authorization.Role; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchMetalakeException; @@ -33,13 +34,12 @@ public class RoleAudit extends AuditCommand { /** * Displays the audit information of a role. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param role The name of the role. */ - public RoleAudit(String url, boolean ignoreVersions, String metalake, String role) { - super(url, ignoreVersions); + public RoleAudit(CommandContext context, String metalake, String role) { + super(context); this.metalake = metalake; this.role = role; } @@ -47,19 +47,16 @@ public RoleAudit(String url, boolean ignoreVersions, String metalake, String rol /** Displays the audit information of a specified role. */ @Override public void handle() { - Role result; + Role result = null; try (GravitinoClient client = buildClient(metalake)) { result = client.getRole(this.role); } catch (NoSuchMetalakeException err) { - System.err.println(ErrorMessages.UNKNOWN_METALAKE); - return; + exitWithError(ErrorMessages.UNKNOWN_METALAKE); } catch (NoSuchRoleException err) { - System.err.println(ErrorMessages.UNKNOWN_ROLE); - return; + exitWithError(ErrorMessages.UNKNOWN_ROLE); } catch (Exception exp) { - System.err.println(exp.getMessage()); - return; + exitWithError(exp.getMessage()); } if (result != null) { diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RoleDetails.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RoleDetails.java index 57e314ac56e..94af016df37 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RoleDetails.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RoleDetails.java @@ -22,6 +22,7 @@ import java.util.List; import org.apache.gravitino.authorization.Privilege; import org.apache.gravitino.authorization.SecurableObject; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; import org.apache.gravitino.exceptions.NoSuchMetalakeException; @@ -35,13 +36,12 @@ public class RoleDetails extends Command { /** * Displays the securable objects in a role. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param role The name of the role. */ - public RoleDetails(String url, boolean ignoreVersions, String metalake, String role) { - super(url, ignoreVersions); + public RoleDetails(CommandContext context, String metalake, String role) { + super(context); this.metalake = metalake; this.role = role; } @@ -63,11 +63,11 @@ public void handle() { } for (SecurableObject object : objects) { - System.out.print(object.name() + "," + object.type() + ","); + printInformation(object.name() + "," + object.type() + ","); for (Privilege privilege : object.privileges()) { - System.out.print(privilege.simpleString() + " "); + printInformation(privilege.simpleString() + " "); } } - System.out.println(""); + printInformation(""); } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/SetOwner.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/SetOwner.java index 45de461043a..a13f278b359 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/SetOwner.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/SetOwner.java @@ -22,6 +22,7 @@ import org.apache.gravitino.MetadataObject; import org.apache.gravitino.MetadataObjects; import org.apache.gravitino.authorization.Owner; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.cli.CommandEntities; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; @@ -39,8 +40,7 @@ public class SetOwner extends Command { /** * Sets the owner of an entity. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context The command context. * @param metalake The name of the metalake. * @param entity The name of the entity. * @param entityType The type entity. @@ -48,14 +48,13 @@ public class SetOwner extends Command { * @param isGroup True if the owner is a group, false if it is not. */ public SetOwner( - String url, - boolean ignoreVersions, + CommandContext context, String metalake, String entity, String entityType, String owner, boolean isGroup) { - super(url, ignoreVersions); + super(context); this.metalake = metalake; this.entity = entity; this.owner = owner; @@ -97,6 +96,6 @@ public void handle() { exitWithError(exp.getMessage()); } - System.out.println("Set owner to " + owner); + printInformation("Set owner to " + owner); } } diff --git a/clients/cli/src/test/java/org/apache/gravitino/cli/TestOwnerCommands.java b/clients/cli/src/test/java/org/apache/gravitino/cli/TestOwnerCommands.java index f3928fba28f..9cd28389840 100644 --- a/clients/cli/src/test/java/org/apache/gravitino/cli/TestOwnerCommands.java +++ b/clients/cli/src/test/java/org/apache/gravitino/cli/TestOwnerCommands.java @@ -21,6 +21,10 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThrows; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; @@ -80,13 +84,12 @@ void testSetOwnerUserCommand() { doReturn(mockSetOwner) .when(commandLine) .newSetOwner( - GravitinoCommandLine.DEFAULT_URL, - false, - "metalake_demo", - "postgres", - "catalog", - "admin", - false); + any(CommandContext.class), + eq("metalake_demo"), + eq("postgres"), + eq("catalog"), + eq("admin"), + anyBoolean()); doReturn(mockSetOwner).when(mockSetOwner).validate(); commandLine.handleCommandLine(); verify(mockSetOwner).handle(); @@ -110,13 +113,12 @@ void testSetOwnerGroupCommand() { doReturn(mockSetOwner) .when(commandLine) .newSetOwner( - GravitinoCommandLine.DEFAULT_URL, - false, - "metalake_demo", - "postgres", - "catalog", - "ITdept", - true); + any(CommandContext.class), + eq("metalake_demo"), + eq("postgres"), + eq("catalog"), + eq("ITdept"), + anyBoolean()); doReturn(mockSetOwner).when(mockSetOwner).validate(); commandLine.handleCommandLine(); verify(mockSetOwner).handle(); @@ -137,7 +139,7 @@ void testOwnerDetailsCommand() { doReturn(mockOwnerDetails) .when(commandLine) .newOwnerDetails( - GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "postgres", "catalog"); + any(CommandContext.class), eq("metalake_demo"), eq("postgres"), eq("catalog")); doReturn(mockOwnerDetails).when(mockOwnerDetails).validate(); commandLine.handleCommandLine(); verify(mockOwnerDetails).handle(); @@ -158,11 +160,7 @@ void testOwnerDetailsCommandWithoutName() { assertThrows(RuntimeException.class, commandLine::handleCommandLine); verify(commandLine, never()) .newOwnerDetails( - GravitinoCommandLine.DEFAULT_URL, - false, - "metalake_demo", - null, - CommandEntities.CATALOG); + any(CommandContext.class), eq("metalake_demo"), isNull(), eq(CommandEntities.CATALOG)); String errOutput = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); assertEquals(ErrorMessages.MISSING_NAME, errOutput); @@ -186,13 +184,12 @@ void testSetOwnerUserCommandWithoutUserAndGroup() { assertThrows(RuntimeException.class, commandLine::handleCommandLine); verify(commandLine, never()) .newSetOwner( - GravitinoCommandLine.DEFAULT_URL, - false, - "metalake_demo", - "postgres", - CommandEntities.CATALOG, - null, - false); + any(CommandContext.class), + eq("metalaek_demo"), + eq("postgres"), + eq(CommandEntities.CATALOG), + any(), + anyBoolean()); String errOutput = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); assertEquals(ErrorMessages.INVALID_SET_COMMAND, errOutput); } diff --git a/clients/cli/src/test/java/org/apache/gravitino/cli/TestRoleCommands.java b/clients/cli/src/test/java/org/apache/gravitino/cli/TestRoleCommands.java index be463019fd3..845c7bea7fb 100644 --- a/clients/cli/src/test/java/org/apache/gravitino/cli/TestRoleCommands.java +++ b/clients/cli/src/test/java/org/apache/gravitino/cli/TestRoleCommands.java @@ -21,6 +21,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThrows; +import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.Mockito.any; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.eq; @@ -84,7 +85,7 @@ void testListRolesCommand() { mockCommandLine, mockOptions, CommandEntities.ROLE, CommandActions.LIST)); doReturn(mockList) .when(commandLine) - .newListRoles(GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo"); + .newListRoles(any(CommandContext.class), eq("metalake_demo")); doReturn(mockList).when(mockList).validate(); commandLine.handleCommandLine(); verify(mockList).handle(); @@ -103,7 +104,7 @@ void testRoleDetailsCommand() { mockCommandLine, mockOptions, CommandEntities.ROLE, CommandActions.DETAILS)); doReturn(mockDetails) .when(commandLine) - .newRoleDetails(GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "admin"); + .newRoleDetails(any(CommandContext.class), eq("metalake_demo"), eq("admin")); doReturn(mockDetails).when(mockDetails).validate(); commandLine.handleCommandLine(); @@ -125,8 +126,7 @@ void testRoleDetailsCommandWithMultipleRoles() { assertThrows(RuntimeException.class, commandLine::handleCommandLine); verify(commandLine, never()) - .newRoleDetails( - eq(GravitinoCommandLine.DEFAULT_URL), eq(false), eq("metalake_demo"), any()); + .newRoleDetails(any(CommandContext.class), eq("metalake_demo"), any()); } @Test @@ -143,7 +143,7 @@ void testRoleAuditCommand() { mockCommandLine, mockOptions, CommandEntities.ROLE, CommandActions.DETAILS)); doReturn(mockAudit) .when(commandLine) - .newRoleAudit(GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "group"); + .newRoleAudit(any(CommandContext.class), eq("metalake_demo"), eq("group")); doReturn(mockAudit).when(mockAudit).validate(); commandLine.handleCommandLine(); verify(mockAudit).handle(); @@ -163,7 +163,9 @@ void testCreateRoleCommand() { doReturn(mockCreate) .when(commandLine) .newCreateRole( - GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", new String[] {"admin"}); + any(CommandContext.class), + eq("metalake_demo"), + argThat(strings -> strings.length == 1 && "admin".equals(strings[0]))); doReturn(mockCreate).when(mockCreate).validate(); commandLine.handleCommandLine(); verify(mockCreate).handle(); @@ -185,10 +187,9 @@ void testCreateRolesCommand() { doReturn(mockCreate) .when(commandLine) .newCreateRole( - GravitinoCommandLine.DEFAULT_URL, - false, - "metalake_demo", - new String[] {"admin", "engineer", "scientist"}); + any(CommandContext.class), + eq("metalake_demo"), + argThat(strings -> strings.length == 3)); doReturn(mockCreate).when(mockCreate).validate(); commandLine.handleCommandLine(); verify(mockCreate).handle(); @@ -208,11 +209,9 @@ void testDeleteRoleCommand() { doReturn(mockDelete) .when(commandLine) .newDeleteRole( - GravitinoCommandLine.DEFAULT_URL, - false, - false, - "metalake_demo", - new String[] {"admin"}); + any(CommandContext.class), + eq("metalake_demo"), + argThat(strings -> strings.length == 1 && "admin".equals(strings[0]))); doReturn(mockDelete).when(mockDelete).validate(); commandLine.handleCommandLine(); verify(mockDelete).handle(); @@ -235,11 +234,9 @@ void testDeleteRolesCommand() { doReturn(mockDelete) .when(commandLine) .newDeleteRole( - GravitinoCommandLine.DEFAULT_URL, - false, - false, - "metalake_demo", - new String[] {"admin", "engineer", "scientist"}); + any(CommandContext.class), + eq("metalake_demo"), + argThat(strings -> strings.length == 3)); doReturn(mockDelete).when(mockDelete).validate(); commandLine.handleCommandLine(); verify(mockDelete).handle(); @@ -260,7 +257,9 @@ void testDeleteRoleForceCommand() { doReturn(mockDelete) .when(commandLine) .newDeleteRole( - GravitinoCommandLine.DEFAULT_URL, false, true, "metalake_demo", new String[] {"admin"}); + any(CommandContext.class), + eq("metalake_demo"), + argThat(strings -> strings.length == 1 && "admin".equals(strings[0]))); doReturn(mockDelete).when(mockDelete).validate(); commandLine.handleCommandLine(); verify(mockDelete).handle(); @@ -285,12 +284,7 @@ void testGrantPrivilegesToRole() { doReturn(mockGrant) .when(commandLine) .newGrantPrivilegesToRole( - eq(GravitinoCommandLine.DEFAULT_URL), - eq(false), - eq("metalake_demo"), - eq("admin"), - any(), - eq(privileges)); + any(CommandContext.class), eq("metalake_demo"), eq("admin"), any(), eq(privileges)); doReturn(mockGrant).when(mockGrant).validate(); commandLine.handleCommandLine(); verify(mockGrant).handle(); @@ -299,10 +293,10 @@ void testGrantPrivilegesToRole() { @Test void testGrantPrivilegesToRoleWithoutPrivileges() { Main.useExit = false; + CommandContext mockContext = mock(CommandContext.class); + when(mockContext.url()).thenReturn(GravitinoCommandLine.DEFAULT_URL); GrantPrivilegesToRole spyGrantRole = - spy( - new GrantPrivilegesToRole( - GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "admin", null, null)); + spy(new GrantPrivilegesToRole(mockContext, "metalake_demo", "admin", null, null)); assertThrows(RuntimeException.class, spyGrantRole::validate); verify(spyGrantRole, never()).handle(); String errOutput = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); @@ -328,12 +322,7 @@ void testRevokePrivilegesFromRole() { doReturn(mockRevoke) .when(commandLine) .newRevokePrivilegesFromRole( - eq(GravitinoCommandLine.DEFAULT_URL), - eq(false), - eq("metalake_demo"), - eq("admin"), - any(), - eq(privileges)); + any(CommandContext.class), eq("metalake_demo"), eq("admin"), any(), eq(privileges)); doReturn(mockRevoke).when(mockRevoke).validate(); commandLine.handleCommandLine(); verify(mockRevoke).handle(); @@ -355,12 +344,7 @@ void testRevokeAllPrivilegesFromRole() { mockCommandLine, mockOptions, CommandEntities.ROLE, CommandActions.REVOKE)); doReturn(mockRevoke) .when(commandLine) - .newRevokeAllPrivileges( - eq(GravitinoCommandLine.DEFAULT_URL), - eq(false), - eq("metalake_demo"), - eq("admin"), - any()); + .newRevokeAllPrivileges(any(CommandContext.class), eq("metalake_demo"), eq("admin"), any()); doReturn(mockRevoke).when(mockRevoke).validate(); commandLine.handleCommandLine(); verify(mockRevoke).handle(); @@ -369,14 +353,14 @@ void testRevokeAllPrivilegesFromRole() { @Test void testRevokeAllPrivilegesFromRoleWithoutName() throws ParseException { Main.useExit = false; + CommandContext mockContext = mock(CommandContext.class); + when(mockContext.url()).thenReturn(GravitinoCommandLine.DEFAULT_URL); String[] args = {"role", "revoke", "-m", "metalake_demo", "--role", "admin", "--all"}; CommandLine commandLine = new DefaultParser().parse(options, args); FullName fullName = new FullName(commandLine); RevokeAllPrivileges spyRevokeAllPrivileges = - spy( - new RevokeAllPrivileges( - GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "admin", fullName)); + spy(new RevokeAllPrivileges(mockContext, "metalake_demo", "admin", fullName)); assertThrows(RuntimeException.class, spyRevokeAllPrivileges::validate); verify(spyRevokeAllPrivileges, never()).handle(); @@ -387,10 +371,10 @@ void testRevokeAllPrivilegesFromRoleWithoutName() throws ParseException { @Test void testRevokePrivilegesFromRoleWithoutPrivileges() { Main.useExit = false; + CommandContext mockContext = mock(CommandContext.class); + when(mockContext.url()).thenReturn(GravitinoCommandLine.DEFAULT_URL); RevokePrivilegesFromRole spyGrantRole = - spy( - new RevokePrivilegesFromRole( - GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "admin", null, null)); + spy(new RevokePrivilegesFromRole(mockContext, "metalake_demo", "admin", null, null)); assertThrows(RuntimeException.class, spyGrantRole::validate); verify(spyGrantRole, never()).handle(); String errOutput = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); @@ -410,8 +394,7 @@ void testDeleteRoleCommandWithoutRole() { assertThrows(RuntimeException.class, commandLine::handleCommandLine); verify(commandLine, never()) - .newDeleteRole( - eq(GravitinoCommandLine.DEFAULT_URL), eq(false), eq(false), eq("metalake_demo"), any()); + .newDeleteRole(any(CommandContext.class), eq("metalake_demo"), any()); String output = new String(errContent.toByteArray(), StandardCharsets.UTF_8).trim(); assertEquals(output, ErrorMessages.MISSING_ROLE); } From 4b5d6a5b0c6a6ce1469353ddd681d56647699a1e Mon Sep 17 00:00:00 2001 From: Lord of Abyss <103809695+Abyss-lord@users.noreply.github.com> Date: Wed, 12 Feb 2025 16:49:22 +0800 Subject: [PATCH 26/33] [#6424] improve(CLI): Refactor getURL in CLI and add context to simple commands. (#6440) ### What changes were proposed in this pull request? Refactor getURL in CLI and add context to simple commands. ### Why are the changes needed? Fix: #6424 ### Does this PR introduce _any_ user-facing change? No ### How was this patch tested? local test. --- .../gravitino/cli/CatalogCommandHandler.java | 1 - .../gravitino/cli/ColumnCommandHandler.java | 1 - .../apache/gravitino/cli/CommandContext.java | 122 +++++++++++++----- .../apache/gravitino/cli/CommandHandler.java | 44 ------- .../gravitino/cli/FilesetCommandHandler.java | 1 - .../gravitino/cli/GravitinoCommandLine.java | 37 +----- .../gravitino/cli/GroupCommandHandler.java | 1 - .../gravitino/cli/MetalakeCommandHandler.java | 1 - .../gravitino/cli/ModelCommandHandler.java | 1 - .../gravitino/cli/OwnerCommandHandler.java | 1 - .../gravitino/cli/RoleCommandHandler.java | 1 - .../gravitino/cli/SchemaCommandHandler.java | 1 - .../gravitino/cli/SimpleCommandHandler.java | 12 +- .../gravitino/cli/TableCommandHandler.java | 1 - .../gravitino/cli/TagCommandHandler.java | 1 - .../gravitino/cli/TestableCommandLine.java | 8 +- .../gravitino/cli/TopicCommandHandler.java | 1 - .../gravitino/cli/UserCommandHandler.java | 1 - .../gravitino/cli/commands/ClientVersion.java | 10 +- .../gravitino/cli/commands/ServerVersion.java | 10 +- .../gravitino/cli/TestCommandContext.java | 35 ++++- .../gravitino/cli/TestMetalakeCommands.java | 8 +- .../gravitino/cli/TestSimpleCommands.java | 9 +- 23 files changed, 150 insertions(+), 158 deletions(-) diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/CatalogCommandHandler.java b/clients/cli/src/main/java/org/apache/gravitino/cli/CatalogCommandHandler.java index a702856f65d..edef9138e33 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/CatalogCommandHandler.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/CatalogCommandHandler.java @@ -56,7 +56,6 @@ public CatalogCommandHandler( this.command = command; this.context = context; - this.context.setUrl(getUrl(line)); this.name = new FullName(line); this.metalake = name.getMetalakeName(); } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/ColumnCommandHandler.java b/clients/cli/src/main/java/org/apache/gravitino/cli/ColumnCommandHandler.java index 58398585c31..01de9ca2a9d 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/ColumnCommandHandler.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/ColumnCommandHandler.java @@ -55,7 +55,6 @@ public ColumnCommandHandler( this.command = command; this.context = context; - this.context.setUrl(getUrl(line)); this.name = new FullName(line); this.metalake = name.getMetalakeName(); this.catalog = name.getCatalogName(); diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/CommandContext.java b/clients/cli/src/main/java/org/apache/gravitino/cli/CommandContext.java index 994b97226e9..fc713ba5775 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/CommandContext.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/CommandContext.java @@ -19,42 +19,40 @@ package org.apache.gravitino.cli; +import com.google.common.base.Preconditions; +import org.apache.commons.cli.CommandLine; import org.apache.gravitino.cli.commands.Command; /* Context for a command */ public class CommandContext { - private String url; - private boolean ignoreVersions; - private boolean force; - private String outputFormat; + private final boolean force; + private final boolean ignoreVersions; + private final String outputFormat; + private final String url; + private final CommandLine line; + + private String ignoreEnv; + private boolean ignoreSet = false; + private String urlEnv; + private boolean urlSet = false; // Can add more "global" command flags here without any major changes e.g. a guiet flag /** * Command constructor. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param line The command line. */ - public CommandContext(String url, boolean ignoreVersions) { - this.url = url; - this.ignoreVersions = ignoreVersions; - this.force = false; - this.outputFormat = Command.OUTPUT_FORMAT_PLAIN; - } + public CommandContext(CommandLine line) { + Preconditions.checkNotNull(line); + this.line = line; + this.force = line.hasOption(GravitinoOptions.FORCE); + this.outputFormat = + line.hasOption(GravitinoOptions.OUTPUT) + ? line.getOptionValue(GravitinoOptions.OUTPUT) + : Command.OUTPUT_FORMAT_PLAIN; - /** - * Command constructor. - * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. - * @param force Force operation. - * @param outputFormat Display output format. - */ - public CommandContext(String url, boolean ignoreVersions, boolean force, String outputFormat) { - this.url = url; - this.ignoreVersions = ignoreVersions; - this.force = force; - this.outputFormat = outputFormat; + this.url = getUrl(); + this.ignoreVersions = getIgnore(); } /** @@ -66,15 +64,6 @@ public String url() { return url; } - /** - * Sets the URL. - * - * @param url The URL to be set. - */ - public void setUrl(String url) { - this.url = url; - } - /** * Indicates whether versions should be ignored. * @@ -101,4 +90,69 @@ public boolean force() { public String outputFormat() { return outputFormat; } + + /** + * Retrieves the Gravitino URL from the command line options or the GRAVITINO_URL environment + * variable or the Gravitino config file. + * + * @return The Gravitino URL, or null if not found. + */ + private String getUrl() { + GravitinoConfig config = new GravitinoConfig(null); + + // If specified on the command line use that + if (line.hasOption(GravitinoOptions.URL)) { + return line.getOptionValue(GravitinoOptions.URL); + } + + // Cache the Gravitino URL environment variable + if (urlEnv == null && !urlSet) { + urlEnv = System.getenv("GRAVITINO_URL"); + urlSet = true; + } + + // If set return the Gravitino URL environment variable + if (urlEnv != null) { + return urlEnv; + } + + // Check if the Gravitino URL is specified in the configuration file + if (config.fileExists()) { + config.read(); + String configURL = config.getGravitinoURL(); + if (configURL != null) { + return configURL; + } + } + + // Return the default localhost URL + return GravitinoCommandLine.DEFAULT_URL; + } + + private boolean getIgnore() { + GravitinoConfig config = new GravitinoConfig(null); + boolean ignore = false; + + /* Check if you should ignore client/version versions */ + if (line.hasOption(GravitinoOptions.IGNORE)) { + ignore = true; + } else { + // Cache the ignore environment variable + if (ignoreEnv == null && !ignoreSet) { + ignoreEnv = System.getenv("GRAVITINO_IGNORE"); + ignore = ignoreEnv != null && ignoreEnv.equals("true"); + ignoreSet = true; + } + + // Check if the ignore name is specified in the configuration file + if (ignoreEnv == null) { + if (config.fileExists()) { + config.read(); + ignore = config.getIgnore(); + } + } + } + + return ignore; + } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/CommandHandler.java b/clients/cli/src/main/java/org/apache/gravitino/cli/CommandHandler.java index 2af2487cc89..79462e81021 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/CommandHandler.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/CommandHandler.java @@ -25,53 +25,9 @@ public abstract class CommandHandler { public static final Joiner COMMA_JOINER = Joiner.on(", ").skipNulls(); - - public static final String DEFAULT_URL = "http://localhost:8090"; - - private String urlEnv; - private boolean urlSet = false; private String authEnv; private boolean authSet = false; - /** - * Retrieves the Gravitino URL from the command line options or the GRAVITINO_URL environment - * variable or the Gravitino config file. - * - * @param line The command line instance. - * @return The Gravitino URL, or null if not found. - */ - public String getUrl(CommandLine line) { - GravitinoConfig config = new GravitinoConfig(null); - - // If specified on the command line use that - if (line.hasOption(GravitinoOptions.URL)) { - return line.getOptionValue(GravitinoOptions.URL); - } - - // Cache the Gravitino URL environment variable - if (urlEnv == null && !urlSet) { - urlEnv = System.getenv("GRAVITINO_URL"); - urlSet = true; - } - - // If set return the Gravitino URL environment variable - if (urlEnv != null) { - return urlEnv; - } - - // Check if the Gravitino URL is specified in the configuration file - if (config.fileExists()) { - config.read(); - String configURL = config.getGravitinoURL(); - if (configURL != null) { - return configURL; - } - } - - // Return the default localhost URL - return DEFAULT_URL; - } - /** * Retrieves the Gravitino authentication from the command line options or the GRAVITINO_AUTH * environment variable or the Gravitino config file. diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/FilesetCommandHandler.java b/clients/cli/src/main/java/org/apache/gravitino/cli/FilesetCommandHandler.java index 54db3ea6bd9..9eec933ddf5 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/FilesetCommandHandler.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/FilesetCommandHandler.java @@ -56,7 +56,6 @@ public FilesetCommandHandler( this.command = command; this.context = context; - this.context.setUrl(getUrl(line)); this.name = new FullName(line); this.metalake = name.getMetalakeName(); this.catalog = name.getCatalogName(); diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/GravitinoCommandLine.java b/clients/cli/src/main/java/org/apache/gravitino/cli/GravitinoCommandLine.java index 3a7c656691a..de9ff12d666 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/GravitinoCommandLine.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/GravitinoCommandLine.java @@ -35,9 +35,6 @@ public class GravitinoCommandLine extends TestableCommandLine { private final Options options; private final String entity; private final String command; - private boolean ignore = false; - private String ignoreEnv; - private boolean ignoreSet = false; public static final String CMD = "gcli"; // recommended name public static final String DEFAULT_URL = "http://localhost:8090"; @@ -60,29 +57,8 @@ public GravitinoCommandLine(CommandLine line, Options options, String entity, St /** Handles the parsed command line arguments and executes the corresponding actions. */ public void handleCommandLine() { - GravitinoConfig config = new GravitinoConfig(null); - - /* Check if you should ignore client/version versions */ - if (line.hasOption(GravitinoOptions.IGNORE)) { - ignore = true; - } else { - // Cache the ignore environment variable - if (ignoreEnv == null && !ignoreSet) { - ignoreEnv = System.getenv("GRAVITINO_IGNORE"); - ignore = ignoreEnv != null && ignoreEnv.equals("true"); - ignoreSet = true; - } - - // Check if the ignore name is specified in the configuration file - if (ignoreEnv == null) { - if (config.fileExists()) { - config.read(); - ignore = config.getIgnore(); - } - } - } - - executeCommand(); + CommandContext context = new CommandContext(line); + executeCommand(context); } /** Handles the parsed command line arguments and executes the corresponding actions. */ @@ -91,7 +67,8 @@ public void handleSimpleLine() { if (line.hasOption(GravitinoOptions.HELP)) { displayHelp(options); } else { - new SimpleCommandHandler(this, line, ignore).handle(); + CommandContext context = new CommandContext(line); + new SimpleCommandHandler(this, line, context).handle(); } } @@ -106,11 +83,7 @@ public static void displayHelp(Options options) { } /** Executes the appropriate command based on the command type. */ - private void executeCommand() { - boolean force = line.hasOption(GravitinoOptions.FORCE); - String outputFormat = line.getOptionValue(GravitinoOptions.OUTPUT); - CommandContext context = new CommandContext(null, ignore, force, outputFormat); - + private void executeCommand(CommandContext context) { if (CommandActions.HELP.equals(command)) { handleHelpCommand(); } else if (line.hasOption(GravitinoOptions.OWNER)) { diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/GroupCommandHandler.java b/clients/cli/src/main/java/org/apache/gravitino/cli/GroupCommandHandler.java index 6fcec1447b2..deaad3df3ef 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/GroupCommandHandler.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/GroupCommandHandler.java @@ -50,7 +50,6 @@ public GroupCommandHandler( this.command = command; this.context = context; - this.context.setUrl(getUrl(line)); this.name = new FullName(line); this.metalake = name.getMetalakeName(); } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/MetalakeCommandHandler.java b/clients/cli/src/main/java/org/apache/gravitino/cli/MetalakeCommandHandler.java index 7d396838421..1fe32f3fea8 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/MetalakeCommandHandler.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/MetalakeCommandHandler.java @@ -50,7 +50,6 @@ public MetalakeCommandHandler( this.line = line; this.command = command; this.context = context; - this.context.setUrl(getUrl(line)); } /** Handles the command execution logic based on the provided command. */ diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/ModelCommandHandler.java b/clients/cli/src/main/java/org/apache/gravitino/cli/ModelCommandHandler.java index 0a0c8e88857..2a0dee0bf6f 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/ModelCommandHandler.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/ModelCommandHandler.java @@ -55,7 +55,6 @@ public ModelCommandHandler( this.command = command; this.context = context; - this.context.setUrl(getUrl(line)); this.name = new FullName(line); this.metalake = name.getMetalakeName(); this.catalog = name.getCatalogName(); diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/OwnerCommandHandler.java b/clients/cli/src/main/java/org/apache/gravitino/cli/OwnerCommandHandler.java index 28fb7fb3803..cef7a9822f6 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/OwnerCommandHandler.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/OwnerCommandHandler.java @@ -55,7 +55,6 @@ public OwnerCommandHandler( this.command = command; this.context = context; - this.context.setUrl(getUrl(line)); this.owner = line.getOptionValue(GravitinoOptions.USER); this.group = line.getOptionValue(GravitinoOptions.GROUP); this.name = new FullName(line); diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/RoleCommandHandler.java b/clients/cli/src/main/java/org/apache/gravitino/cli/RoleCommandHandler.java index ef21ec5c419..a02d7f0ca86 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/RoleCommandHandler.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/RoleCommandHandler.java @@ -42,7 +42,6 @@ public RoleCommandHandler( this.line = line; this.command = command; this.context = context; - this.context.setUrl(getUrl(line)); } /** Handles the command execution logic based on the provided command. */ diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/SchemaCommandHandler.java b/clients/cli/src/main/java/org/apache/gravitino/cli/SchemaCommandHandler.java index 4b6a11496ec..30c051ccf23 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/SchemaCommandHandler.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/SchemaCommandHandler.java @@ -53,7 +53,6 @@ public SchemaCommandHandler( this.command = command; this.context = context; - this.context.setUrl(getUrl(line)); this.name = new FullName(line); this.metalake = name.getMetalakeName(); this.catalog = name.getCatalogName(); diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/SimpleCommandHandler.java b/clients/cli/src/main/java/org/apache/gravitino/cli/SimpleCommandHandler.java index 48aca9f9569..113be4f20b7 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/SimpleCommandHandler.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/SimpleCommandHandler.java @@ -25,29 +25,29 @@ public class SimpleCommandHandler extends CommandHandler { private final GravitinoCommandLine gravitinoCommandLine; private final CommandLine line; - private final boolean ignore; + private final CommandContext context; /** * Constructs a {@link SimpleCommandHandler} instance. * * @param gravitinoCommandLine The Gravitino command line instance. * @param line The command line arguments. - * @param ignore Ignore server version mismatch. + * @param context The command context. */ public SimpleCommandHandler( - GravitinoCommandLine gravitinoCommandLine, CommandLine line, boolean ignore) { + GravitinoCommandLine gravitinoCommandLine, CommandLine line, CommandContext context) { this.gravitinoCommandLine = gravitinoCommandLine; this.line = line; - this.ignore = ignore; + this.context = context; } /** Handles the command execution logic based on the provided command. */ @Override protected void handle() { if (line.hasOption(GravitinoOptions.VERSION)) { - gravitinoCommandLine.newClientVersion(getUrl(line), ignore).validate().handle(); + gravitinoCommandLine.newClientVersion(context).validate().handle(); } else if (line.hasOption(GravitinoOptions.SERVER)) { - gravitinoCommandLine.newServerVersion(getUrl(line), ignore).validate().handle(); + gravitinoCommandLine.newServerVersion(context).validate().handle(); } } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/TableCommandHandler.java b/clients/cli/src/main/java/org/apache/gravitino/cli/TableCommandHandler.java index 520b655c25b..82876917040 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/TableCommandHandler.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/TableCommandHandler.java @@ -54,7 +54,6 @@ public TableCommandHandler( this.command = command; this.context = context; - this.context.setUrl(getUrl(line)); this.name = new FullName(line); this.metalake = name.getMetalakeName(); this.catalog = name.getCatalogName(); diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/TagCommandHandler.java b/clients/cli/src/main/java/org/apache/gravitino/cli/TagCommandHandler.java index 13567ac0648..2c8612a33c4 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/TagCommandHandler.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/TagCommandHandler.java @@ -39,7 +39,6 @@ public TagCommandHandler( this.line = line; this.command = command; this.context = context; - this.context.setUrl(getUrl(line)); this.tags = line.getOptionValues(GravitinoOptions.TAG); if (tags != null) { diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/TestableCommandLine.java b/clients/cli/src/main/java/org/apache/gravitino/cli/TestableCommandLine.java index 22425b621b6..346e2691f42 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/TestableCommandLine.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/TestableCommandLine.java @@ -149,12 +149,12 @@ */ public class TestableCommandLine { - protected ClientVersion newClientVersion(String url, boolean ignore) { - return new ClientVersion(url, ignore); + protected ClientVersion newClientVersion(CommandContext context) { + return new ClientVersion(context); } - protected ServerVersion newServerVersion(String url, boolean ignore) { - return new ServerVersion(url, ignore); + protected ServerVersion newServerVersion(CommandContext context) { + return new ServerVersion(context); } protected MetalakeAudit newMetalakeAudit(CommandContext context, String metalake) { diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/TopicCommandHandler.java b/clients/cli/src/main/java/org/apache/gravitino/cli/TopicCommandHandler.java index f67d003b28e..34315fa971d 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/TopicCommandHandler.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/TopicCommandHandler.java @@ -54,7 +54,6 @@ public TopicCommandHandler( this.command = command; this.context = context; - this.context.setUrl(getUrl(line)); this.name = new FullName(line); this.metalake = name.getMetalakeName(); this.catalog = name.getCatalogName(); diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/UserCommandHandler.java b/clients/cli/src/main/java/org/apache/gravitino/cli/UserCommandHandler.java index 964d2ba6d99..5fd7d906b9b 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/UserCommandHandler.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/UserCommandHandler.java @@ -50,7 +50,6 @@ public UserCommandHandler( this.command = command; this.context = context; - this.context.setUrl(getUrl(line)); this.name = new FullName(line); this.metalake = name.getMetalakeName(); } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ClientVersion.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ClientVersion.java index 6bc2200b7b2..28c702e39fb 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ClientVersion.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ClientVersion.java @@ -19,6 +19,7 @@ package org.apache.gravitino.cli.commands; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.client.GravitinoAdminClient; /** Displays the Gravitino client version. */ @@ -27,11 +28,10 @@ public class ClientVersion extends Command { /** * Displays the client version. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context the command context */ - public ClientVersion(String url, boolean ignoreVersions) { - super(url, ignoreVersions); + public ClientVersion(CommandContext context) { + super(context); } /** Displays the client version. */ @@ -44,6 +44,6 @@ public void handle() { } catch (Exception exp) { exitWithError(exp.getMessage()); } - System.out.println("Apache Gravitino " + version); + printResults("Apache Gravitino " + version); } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ServerVersion.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ServerVersion.java index 218fa71bb88..b94076db69f 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ServerVersion.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ServerVersion.java @@ -19,6 +19,7 @@ package org.apache.gravitino.cli.commands; +import org.apache.gravitino.cli.CommandContext; import org.apache.gravitino.client.GravitinoAdminClient; /** Displays the Gravitino server version. */ @@ -27,11 +28,10 @@ public class ServerVersion extends Command { /** * Displays the server version. * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. + * @param context the command context */ - public ServerVersion(String url, boolean ignoreVersions) { - super(url, ignoreVersions); + public ServerVersion(CommandContext context) { + super(context); } /** Displays the server version. */ @@ -45,6 +45,6 @@ public void handle() { exitWithError(exp.getMessage()); } - System.out.println("Apache Gravitino " + version); + printResults("Apache Gravitino " + version); } } diff --git a/clients/cli/src/test/java/org/apache/gravitino/cli/TestCommandContext.java b/clients/cli/src/test/java/org/apache/gravitino/cli/TestCommandContext.java index 8919446826b..5bdd822b333 100644 --- a/clients/cli/src/test/java/org/apache/gravitino/cli/TestCommandContext.java +++ b/clients/cli/src/test/java/org/apache/gravitino/cli/TestCommandContext.java @@ -19,16 +19,29 @@ package org.apache.gravitino.cli; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import org.apache.commons.cli.CommandLine; import org.apache.gravitino.cli.commands.Command; import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; public class TestCommandContext { + private CommandLine mockCommandLine; + + @BeforeEach + void setUp() { + mockCommandLine = mock(CommandLine.class); + } + @Test public void testCreateCommandContextWithDefaults() { - CommandContext commandContext = new CommandContext("http://localhost:8080", false); - Assertions.assertEquals("http://localhost:8080", commandContext.url()); + CommandContext commandContext = new CommandContext(mockCommandLine); + + Assertions.assertEquals(GravitinoCommandLine.DEFAULT_URL, commandContext.url()); Assertions.assertFalse(commandContext.ignoreVersions()); Assertions.assertFalse(commandContext.force()); Assertions.assertEquals(Command.OUTPUT_FORMAT_PLAIN, commandContext.outputFormat()); @@ -36,11 +49,23 @@ public void testCreateCommandContextWithDefaults() { @Test public void testCreateCommandContextWithCustomValues() { - CommandContext commandContext = - new CommandContext("http://localhost:8080", true, true, Command.OUTPUT_FORMAT_TABLE); - Assertions.assertEquals("http://localhost:8080", commandContext.url()); + when(mockCommandLine.hasOption(GravitinoOptions.URL)).thenReturn(true); + when(mockCommandLine.getOptionValue(GravitinoOptions.URL)).thenReturn("http://localhost:8090"); + when(mockCommandLine.hasOption(GravitinoOptions.IGNORE)).thenReturn(true); + when(mockCommandLine.hasOption(GravitinoOptions.FORCE)).thenReturn(true); + when(mockCommandLine.hasOption(GravitinoOptions.OUTPUT)).thenReturn(true); + when(mockCommandLine.getOptionValue(GravitinoOptions.OUTPUT)) + .thenReturn(Command.OUTPUT_FORMAT_TABLE); + + CommandContext commandContext = new CommandContext(mockCommandLine); + Assertions.assertEquals("http://localhost:8090", commandContext.url()); Assertions.assertTrue(commandContext.ignoreVersions()); Assertions.assertTrue(commandContext.force()); Assertions.assertEquals(Command.OUTPUT_FORMAT_TABLE, commandContext.outputFormat()); } + + @Test + public void testCreateCommandContextWithNull() { + Assertions.assertThrows(NullPointerException.class, () -> new CommandContext(null)); + } } diff --git a/clients/cli/src/test/java/org/apache/gravitino/cli/TestMetalakeCommands.java b/clients/cli/src/test/java/org/apache/gravitino/cli/TestMetalakeCommands.java index 37e3acd2896..e01b652c644 100644 --- a/clients/cli/src/test/java/org/apache/gravitino/cli/TestMetalakeCommands.java +++ b/clients/cli/src/test/java/org/apache/gravitino/cli/TestMetalakeCommands.java @@ -227,7 +227,7 @@ void testSetMetalakePropertyCommand() { @Test void testSetMetalakePropertyCommandWithoutPropertyAndValue() { - CommandContext context = new CommandContext(GravitinoCommandLine.DEFAULT_URL, false); + CommandContext context = new CommandContext(mockCommandLine); Main.useExit = false; SetMetalakeProperty metalakeProperty = @@ -240,7 +240,7 @@ void testSetMetalakePropertyCommandWithoutPropertyAndValue() { @Test void testSetMetalakePropertyCommandWithoutProperty() { - CommandContext context = new CommandContext(GravitinoCommandLine.DEFAULT_URL, false); + CommandContext context = new CommandContext(mockCommandLine); Main.useExit = false; SetMetalakeProperty metalakeProperty = @@ -253,7 +253,7 @@ void testSetMetalakePropertyCommandWithoutProperty() { @Test void testSetMetalakePropertyCommandWithoutValue() { - CommandContext context = new CommandContext(GravitinoCommandLine.DEFAULT_URL, false); + CommandContext context = new CommandContext(mockCommandLine); Main.useExit = false; SetMetalakeProperty metalakeProperty = @@ -285,7 +285,7 @@ void testRemoveMetalakePropertyCommand() { @Test void testRemoveMetalakePropertyCommandWithoutProperty() { - CommandContext context = new CommandContext(GravitinoCommandLine.DEFAULT_URL, false); + CommandContext context = new CommandContext(mockCommandLine); Main.useExit = false; RemoveMetalakeProperty mockRemoveProperty = diff --git a/clients/cli/src/test/java/org/apache/gravitino/cli/TestSimpleCommands.java b/clients/cli/src/test/java/org/apache/gravitino/cli/TestSimpleCommands.java index 044e06c58f7..8024189112b 100644 --- a/clients/cli/src/test/java/org/apache/gravitino/cli/TestSimpleCommands.java +++ b/clients/cli/src/test/java/org/apache/gravitino/cli/TestSimpleCommands.java @@ -19,6 +19,7 @@ package org.apache.gravitino.cli; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; @@ -50,9 +51,7 @@ void testServerVersion() { GravitinoCommandLine commandLine = spy(new GravitinoCommandLine(mockCommandLine, mockOptions, null, null)); - doReturn(mockServerVersion) - .when(commandLine) - .newServerVersion(GravitinoCommandLine.DEFAULT_URL, false); + doReturn(mockServerVersion).when(commandLine).newServerVersion(any(CommandContext.class)); doReturn(mockServerVersion).when(mockServerVersion).validate(); commandLine.handleSimpleLine(); verify(mockServerVersion).handle(); @@ -65,9 +64,7 @@ void testClientVersion() { GravitinoCommandLine commandLine = spy(new GravitinoCommandLine(mockCommandLine, mockOptions, null, null)); - doReturn(mockClientVersion) - .when(commandLine) - .newClientVersion(GravitinoCommandLine.DEFAULT_URL, false); + doReturn(mockClientVersion).when(commandLine).newClientVersion(any(CommandContext.class)); doReturn(mockClientVersion).when(mockClientVersion).validate(); commandLine.handleSimpleLine(); verify(mockClientVersion).handle(); From 43480899938002406de04259b3e6ea8190dff1db Mon Sep 17 00:00:00 2001 From: Aryan Mahawar Date: Thu, 13 Feb 2025 07:37:55 +0530 Subject: [PATCH 27/33] [#6429] Fixed Wrong log format codes (#6433) ### What changes were proposed in this pull request? The PR updates incorrect log format codes from `%s` to `{}` in the following lines: - Line 420 - Line 483 - Line 504 - Line 525 The original code in these lines used the `%s` placeholder, which is invalid for the logging framework used. It has been corrected to use `{}` to match the proper syntax for log messages. ### Why are the changes needed? This change is necessary to fix the incorrect log format codes in the codebase. The `%s` placeholder is not valid and can lead to incorrect log formatting or errors when the logs are generated. The correct placeholder syntax for this logging framework is `{}`. Fix: #6429 ### Does this PR introduce _any_ user-facing change? No user-facing changes are introduced. This is an internal fix for the logging format. ### How was this patch tested? The changes were verified manually by reviewing the code and ensuring that all instances of `%s` were replaced with `{}` in the affected lines. No new functionality was added, so no additional tests were required. --- .../gravitino/authorization/AuthorizationUtils.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core/src/main/java/org/apache/gravitino/authorization/AuthorizationUtils.java b/core/src/main/java/org/apache/gravitino/authorization/AuthorizationUtils.java index 60ffe3e83c8..cbae0a5c917 100644 --- a/core/src/main/java/org/apache/gravitino/authorization/AuthorizationUtils.java +++ b/core/src/main/java/org/apache/gravitino/authorization/AuthorizationUtils.java @@ -417,7 +417,7 @@ private static String getHiveDefaultLocation(String metalakeName, String catalog if (defaultSchemaLocation != null && !defaultSchemaLocation.isEmpty()) { return defaultSchemaLocation; } else { - LOG.warn("Schema %s location is not found", defaultSchemaIdent); + LOG.warn("Schema {} location is not found", defaultSchemaIdent); } } @@ -480,7 +480,7 @@ public static List getMetadataObjectLocation( if (StringUtils.isNotBlank(schemaLocation)) { locations.add(schemaLocation); } else { - LOG.warn("Schema %s location is not found", ident); + LOG.warn("Schema {} location is not found", ident); } } } @@ -501,7 +501,7 @@ public static List getMetadataObjectLocation( if (StringUtils.isNotBlank(tableLocation)) { locations.add(tableLocation); } else { - LOG.warn("Table %s location is not found", ident); + LOG.warn("Table {} location is not found", ident); } } } @@ -522,7 +522,7 @@ public static List getMetadataObjectLocation( "Failed to get location paths for metadata object %s type %s", ident, type); } } catch (Exception e) { - LOG.warn("Failed to get location paths for metadata object %s type %s", ident, type, e); + LOG.warn("Failed to get location paths for metadata object {} type {}", ident, type, e); } return locations; From 650232cf28e20c5a8d7d76c9cb30e4e904ac3334 Mon Sep 17 00:00:00 2001 From: yangyang zhong <35210666+hdygxsj@users.noreply.github.com> Date: Thu, 13 Feb 2025 10:21:40 +0800 Subject: [PATCH 28/33] [#6361] feat(paimon):Support specifying primary keys during create paimon table by flink (#6362) ### What changes were proposed in this pull request? Support specifying primary keys during create paimon table by flink ### Why are the changes needed? Fix: #6361 ### Does this PR introduce _any_ user-facing change? None ### How was this patch tested? Add testCreateTableWithPrimaryKey case in org.apache.gravitino.flink.connector.integration.test.FlinkCommonIT --- .../flink/connector/catalog/BaseCatalog.java | 61 ++++++++++++- .../integration/test/FlinkCommonIT.java | 90 +++++++++++++++++++ .../test/hive/FlinkHiveCatalogIT.java | 5 ++ .../test/iceberg/FlinkIcebergCatalogIT.java | 5 ++ 4 files changed, 160 insertions(+), 1 deletion(-) diff --git a/flink-connector/flink/src/main/java/org/apache/gravitino/flink/connector/catalog/BaseCatalog.java b/flink-connector/flink/src/main/java/org/apache/gravitino/flink/connector/catalog/BaseCatalog.java index fd8e118ee49..e9320c786cd 100644 --- a/flink-connector/flink/src/main/java/org/apache/gravitino/flink/connector/catalog/BaseCatalog.java +++ b/flink-connector/flink/src/main/java/org/apache/gravitino/flink/connector/catalog/BaseCatalog.java @@ -27,6 +27,7 @@ import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.Optional; import java.util.stream.Collectors; import java.util.stream.Stream; import org.apache.commons.compress.utils.Lists; @@ -40,6 +41,7 @@ import org.apache.flink.table.catalog.CatalogTable; import org.apache.flink.table.catalog.ObjectPath; import org.apache.flink.table.catalog.ResolvedCatalogBaseTable; +import org.apache.flink.table.catalog.UniqueConstraint; import org.apache.flink.table.catalog.exceptions.CatalogException; import org.apache.flink.table.catalog.exceptions.DatabaseAlreadyExistException; import org.apache.flink.table.catalog.exceptions.DatabaseNotEmptyException; @@ -75,7 +77,11 @@ import org.apache.gravitino.rel.Column; import org.apache.gravitino.rel.Table; import org.apache.gravitino.rel.TableChange; +import org.apache.gravitino.rel.expressions.distributions.Distributions; +import org.apache.gravitino.rel.expressions.sorts.SortOrder; import org.apache.gravitino.rel.expressions.transforms.Transform; +import org.apache.gravitino.rel.indexes.Index; +import org.apache.gravitino.rel.indexes.Indexes; /** * The BaseCatalog that provides a default implementation for all methods in the {@link @@ -276,8 +282,21 @@ public void createTable(ObjectPath tablePath, CatalogBaseTable table, boolean ig propertiesConverter.toGravitinoTableProperties(table.getOptions()); Transform[] partitions = partitionConverter.toGravitinoPartitions(((CatalogTable) table).getPartitionKeys()); + try { - catalog().asTableCatalog().createTable(identifier, columns, comment, properties, partitions); + + Index[] indices = getGrivatinoIndices(resolvedTable); + catalog() + .asTableCatalog() + .createTable( + identifier, + columns, + comment, + properties, + partitions, + Distributions.NONE, + new SortOrder[0], + indices); } catch (NoSuchSchemaException e) { throw new DatabaseNotExistException(catalogName(), tablePath.getDatabaseName(), e); } catch (TableAlreadyExistsException e) { @@ -289,6 +308,20 @@ public void createTable(ObjectPath tablePath, CatalogBaseTable table, boolean ig } } + private static Index[] getGrivatinoIndices(ResolvedCatalogBaseTable resolvedTable) { + Optional primaryKey = resolvedTable.getResolvedSchema().getPrimaryKey(); + List primaryColumns = primaryKey.map(UniqueConstraint::getColumns).orElse(null); + if (primaryColumns == null) { + return new Index[0]; + } + String[][] primaryField = + primaryColumns.stream() + .map(primaryColumn -> new String[] {primaryColumn}) + .toArray(String[][]::new); + Index primary = Indexes.primary("primary", primaryField); + return new Index[] {primary}; + } + /** * The method only is used to change the comments. To alter columns, use the other alterTable API * and provide a list of TableChanges. @@ -521,12 +554,38 @@ protected CatalogBaseTable toFlinkTable(Table table) { .column(column.name(), column.nullable() ? flinkType.nullable() : flinkType.notNull()) .withComment(column.comment()); } + Optional> flinkPrimaryKey = getFlinkPrimaryKey(table); + flinkPrimaryKey.ifPresent(builder::primaryKey); Map flinkTableProperties = propertiesConverter.toFlinkTableProperties(table.properties()); List partitionKeys = partitionConverter.toFlinkPartitionKeys(table.partitioning()); return CatalogTable.of(builder.build(), table.comment(), partitionKeys, flinkTableProperties); } + private static Optional> getFlinkPrimaryKey(Table table) { + List primaryKeyList = + Arrays.stream(table.index()) + .filter(index -> index.type() == Index.IndexType.PRIMARY_KEY) + .collect(Collectors.toList()); + if (primaryKeyList.isEmpty()) { + return Optional.empty(); + } + Preconditions.checkArgument( + primaryKeyList.size() == 1, "More than one primary key is not supported."); + List primaryKeyFieldList = + Arrays.stream(primaryKeyList.get(0).fieldNames()) + .map( + fieldNames -> { + Preconditions.checkArgument( + fieldNames.length == 1, "The primary key columns should not be nested."); + return fieldNames[0]; + }) + .collect(Collectors.toList()); + Preconditions.checkArgument( + !primaryKeyFieldList.isEmpty(), "The primary key must contain at least one field."); + return Optional.of(primaryKeyFieldList); + } + private Column toGravitinoColumn(org.apache.flink.table.catalog.Column column) { return Column.of( column.getName(), diff --git a/flink-connector/flink/src/test/java/org/apache/gravitino/flink/connector/integration/test/FlinkCommonIT.java b/flink-connector/flink/src/test/java/org/apache/gravitino/flink/connector/integration/test/FlinkCommonIT.java index b45e5f46ec2..8ff6f8db7a2 100644 --- a/flink-connector/flink/src/test/java/org/apache/gravitino/flink/connector/integration/test/FlinkCommonIT.java +++ b/flink-connector/flink/src/test/java/org/apache/gravitino/flink/connector/integration/test/FlinkCommonIT.java @@ -51,6 +51,7 @@ import org.apache.gravitino.flink.connector.integration.test.utils.TestUtils; import org.apache.gravitino.rel.Column; import org.apache.gravitino.rel.Table; +import org.apache.gravitino.rel.indexes.Index; import org.apache.gravitino.rel.types.Types; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -80,6 +81,10 @@ protected boolean supportGetSchemaWithoutCommentAndOption() { protected abstract boolean supportDropCascade(); + protected boolean supportsPrimaryKey() { + return true; + } + @Test public void testCreateSchema() { doWithCatalog( @@ -280,6 +285,91 @@ public void testCreateSimpleTable() { supportDropCascade()); } + @Test + @EnabledIf("supportsPrimaryKey") + public void testCreateTableWithPrimaryKey() { + String databaseName = "test_create_table_with_primary_key_db"; + String tableName = "test_create_primary_key_table"; + String comment = "test comment"; + String key = "test key"; + String value = "test value"; + + doWithSchema( + currentCatalog(), + databaseName, + catalog -> { + sql( + "CREATE TABLE %s " + + "(aa int, " + + " bb int," + + " cc int," + + " PRIMARY KEY (aa,bb) NOT ENFORCED" + + ")" + + " COMMENT '%s' WITH (" + + "'%s' = '%s')", + tableName, comment, key, value); + Table table = + catalog.asTableCatalog().loadTable(NameIdentifier.of(databaseName, tableName)); + Assertions.assertEquals(1, table.index().length); + Index index = table.index()[0]; + Assertions.assertEquals("aa", index.fieldNames()[0][0]); + Assertions.assertEquals("bb", index.fieldNames()[1][0]); + + TestUtils.assertTableResult( + sql("INSERT INTO %s VALUES(1,2,3)", tableName), + ResultKind.SUCCESS_WITH_CONTENT, + Row.of(-1)); + TestUtils.assertTableResult( + sql("SELECT count(*) num FROM %s", tableName), + ResultKind.SUCCESS_WITH_CONTENT, + Row.of(1)); + TestUtils.assertTableResult( + sql("SELECT * FROM %s", tableName), ResultKind.SUCCESS_WITH_CONTENT, Row.of(1, 2, 3)); + + TestUtils.assertTableResult( + sql("INSERT INTO %s VALUES(1,2,4)", tableName), + ResultKind.SUCCESS_WITH_CONTENT, + Row.of(-1)); + TestUtils.assertTableResult( + sql("SELECT count(*) num FROM %s", tableName), + ResultKind.SUCCESS_WITH_CONTENT, + Row.of(1)); + TestUtils.assertTableResult( + sql("SELECT * FROM %s", tableName), ResultKind.SUCCESS_WITH_CONTENT, Row.of(1, 2, 4)); + + TestUtils.assertTableResult( + sql("INSERT INTO %s VALUES(1,3,4)", tableName), + ResultKind.SUCCESS_WITH_CONTENT, + Row.of(-1)); + TestUtils.assertTableResult( + sql("SELECT count(*) num FROM %s", tableName), + ResultKind.SUCCESS_WITH_CONTENT, + Row.of(2)); + TestUtils.assertTableResult( + sql("SELECT * FROM %s", tableName), + ResultKind.SUCCESS_WITH_CONTENT, + Row.of(1, 2, 4), + Row.of(1, 3, 4)); + + TestUtils.assertTableResult( + sql("INSERT INTO %s VALUES(2,2,4)", tableName), + ResultKind.SUCCESS_WITH_CONTENT, + Row.of(-1)); + TestUtils.assertTableResult( + sql("SELECT count(*) num FROM %s", tableName), + ResultKind.SUCCESS_WITH_CONTENT, + Row.of(3)); + TestUtils.assertTableResult( + sql("SELECT * FROM %s", tableName), + ResultKind.SUCCESS_WITH_CONTENT, + Row.of(1, 2, 4), + Row.of(1, 3, 4), + Row.of(2, 2, 4)); + }, + true, + supportDropCascade()); + } + @Test @EnabledIf("supportTableOperation") public void testListTables() { diff --git a/flink-connector/flink/src/test/java/org/apache/gravitino/flink/connector/integration/test/hive/FlinkHiveCatalogIT.java b/flink-connector/flink/src/test/java/org/apache/gravitino/flink/connector/integration/test/hive/FlinkHiveCatalogIT.java index 7792068e249..3add18211f1 100644 --- a/flink-connector/flink/src/test/java/org/apache/gravitino/flink/connector/integration/test/hive/FlinkHiveCatalogIT.java +++ b/flink-connector/flink/src/test/java/org/apache/gravitino/flink/connector/integration/test/hive/FlinkHiveCatalogIT.java @@ -71,6 +71,11 @@ public class FlinkHiveCatalogIT extends FlinkCommonIT { private static org.apache.gravitino.Catalog hiveCatalog; + @Override + protected boolean supportsPrimaryKey() { + return false; + } + @BeforeAll void hiveStartUp() { initDefaultHiveCatalog(); diff --git a/flink-connector/flink/src/test/java/org/apache/gravitino/flink/connector/integration/test/iceberg/FlinkIcebergCatalogIT.java b/flink-connector/flink/src/test/java/org/apache/gravitino/flink/connector/integration/test/iceberg/FlinkIcebergCatalogIT.java index cedf0e8d591..f8a3cdf2e17 100644 --- a/flink-connector/flink/src/test/java/org/apache/gravitino/flink/connector/integration/test/iceberg/FlinkIcebergCatalogIT.java +++ b/flink-connector/flink/src/test/java/org/apache/gravitino/flink/connector/integration/test/iceberg/FlinkIcebergCatalogIT.java @@ -63,6 +63,11 @@ public abstract class FlinkIcebergCatalogIT extends FlinkCommonIT { private static org.apache.gravitino.Catalog icebergCatalog; + @Override + protected boolean supportsPrimaryKey() { + return false; + } + @BeforeAll public void before() { Preconditions.checkNotNull(metalake); From d1ec00506448500f25382cbd92430c02f0369ab3 Mon Sep 17 00:00:00 2001 From: FANNG Date: Thu, 13 Feb 2025 12:14:14 +0800 Subject: [PATCH 29/33] [MINOR] docs: polish Iceberg REST server document (#6444) ### What changes were proposed in this pull request? multi catalog and view operation should shown in document side bars. ### Why are the changes needed? User could find multi catalog configuration easily ### Does this PR introduce _any_ user-facing change? no ### How was this patch tested? just document --- docs/iceberg-rest-service.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/iceberg-rest-service.md b/docs/iceberg-rest-service.md index f89b6f2672f..823ae5b03a3 100644 --- a/docs/iceberg-rest-service.md +++ b/docs/iceberg-rest-service.md @@ -242,7 +242,7 @@ You must download the corresponding JDBC driver to the `iceberg-rest-server/libs If you want to use a custom Iceberg Catalog as `catalog-backend`, you can add a corresponding jar file to the classpath and load a custom Iceberg Catalog implementation by specifying the `catalog-backend-impl` property. -#### View support +### View support You could access the view interface if using JDBC backend and enable `jdbc.schema-version` property. @@ -250,7 +250,7 @@ You could access the view interface if using JDBC backend and enable `jdbc.schem |----------------------------------------------|--------------------------------------------------------------------------------------------|---------------|----------|------------------| | `gravitino.iceberg-rest.jdbc.schema-version` | The schema version of JDBC catalog backend, setting to `V1` if supporting view operations. | (none) | NO | 0.7.0-incubating | -#### Multi catalog support +### Multi catalog support The Gravitino Iceberg REST server supports multiple catalogs, and you could manage the catalog by different ways. @@ -258,7 +258,7 @@ The Gravitino Iceberg REST server supports multiple catalogs, and you could mana |--------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------|----------|------------------| | `gravitino.iceberg-rest.catalog-config-provider` | The className of catalog configuration provider, Gravitino provides build-in `static-config-provider` and `dynamic-config-provider`, you could also develop a custom class that implements `apache.gravitino.iceberg.service.provider.IcebergConfigProvider` and add the corresponding jar file to the Iceberg REST service classpath directory. | `static-config-provider` | No | 0.7.0-incubating | -##### Static catalog configuration provider +#### Static catalog configuration provider The static catalog configuration provider retrieves the catalog configuration from the configuration file of the Gravitino Iceberg REST server. You could configure the default catalog with `gravitino.iceberg-rest.=`. For specific catalogs, use the format `gravitino.iceberg-rest.catalog..=`. @@ -297,7 +297,7 @@ You can access different catalogs by setting the `prefix` to the specific catalo ... ``` -##### Dynamic catalog configuration provider +#### Dynamic catalog configuration provider The dynamic catalog configuration provider retrieves the catalog configuration from the Gravitino server. From 794703f49ff729c1524f28949b939b5d3d5f751c Mon Sep 17 00:00:00 2001 From: Lord of Abyss <103809695+Abyss-lord@users.noreply.github.com> Date: Thu, 13 Feb 2025 14:14:12 +0800 Subject: [PATCH 30/33] [MINOR] improve(CLI): Remove redundant code in CLI (#6443) ### What changes were proposed in this pull request? Remove redundant code in CLI, and make context argument final in Command class. ### Why are the changes needed? The constructor should take only one argument, CommandContext. ### Does this PR introduce _any_ user-facing change? No. ### How was this patch tested? local test. --- .../gravitino/cli/commands/AuditCommand.java | 7 ----- .../gravitino/cli/commands/Command.java | 27 +------------------ .../cli/commands/ListProperties.java | 10 ------- .../cli/commands/MetadataCommand.java | 10 ------- .../gravitino/cli/commands/TableCommand.java | 14 ---------- 5 files changed, 1 insertion(+), 67 deletions(-) diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/AuditCommand.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/AuditCommand.java index 9c27295bddb..951ad33cc0a 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/AuditCommand.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/AuditCommand.java @@ -23,13 +23,6 @@ import org.apache.gravitino.cli.CommandContext; public abstract class AuditCommand extends Command { - /** - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. - */ - public AuditCommand(String url, boolean ignoreVersions) { - super(url, ignoreVersions); - } /** @param context The command context. */ public AuditCommand(CommandContext context) { diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/Command.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/Command.java index 7d259ed18ba..c9d758c17a9 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/Command.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/Command.java @@ -55,7 +55,7 @@ public abstract class Command { private final boolean ignoreVersions; private final String outputFormat; - protected CommandContext context = null; // TODO make final + protected final CommandContext context; /** * Command constructor. @@ -69,31 +69,6 @@ public Command(CommandContext context) { this.outputFormat = context.outputFormat(); } - /** - * Command constructor. - * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. - */ - public Command(String url, boolean ignoreVersions) { - this.url = url; - this.ignoreVersions = ignoreVersions; - this.outputFormat = OUTPUT_FORMAT_PLAIN; - } - - /** - * Command constructor. - * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. - * @param outputFormat output format used in some commands - */ - public Command(String url, boolean ignoreVersions, String outputFormat) { - this.url = url; - this.ignoreVersions = ignoreVersions; - this.outputFormat = outputFormat; - } - /** * Prints an error message and exits with a non-zero status. * diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListProperties.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListProperties.java index 55c750aa712..5ad7e53256a 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListProperties.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListProperties.java @@ -34,16 +34,6 @@ public ListProperties(CommandContext context) { super(context); } - /** - * List the properties of an entity. - * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. - */ - public ListProperties(String url, boolean ignoreVersions) { - super(url, ignoreVersions); - } - @Override public void handle() { /* Do nothing */ diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/MetadataCommand.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/MetadataCommand.java index 0ff7bce294f..8a417d0e008 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/MetadataCommand.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/MetadataCommand.java @@ -28,16 +28,6 @@ public class MetadataCommand extends Command { - /** - * MetadataCommand constructor. - * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. - */ - public MetadataCommand(String url, boolean ignoreVersions) { - super(url, ignoreVersions); - } - /** * MetadataCommand constructor. * diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/TableCommand.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/TableCommand.java index 471baad1c9e..11390cf6333 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/TableCommand.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/TableCommand.java @@ -40,20 +40,6 @@ public TableCommand(CommandContext context, String metalake, String catalog) { this.catalog = catalog; } - /** - * Common code for all table commands. - * - * @param url The URL of the Gravitino server. - * @param ignoreVersions If true don't check the client/server versions match. - * @param metalake The name of the metalake. - * @param catalog The name of the catalog. - */ - public TableCommand(String url, boolean ignoreVersions, String metalake, String catalog) { - super(url, ignoreVersions); - this.metalake = metalake; - this.catalog = catalog; - } - /* Overridden in parent - do nothing */ @Override public void handle() {} From cdc5f8fdc098d36246a103806f6d5191c2b2c4f2 Mon Sep 17 00:00:00 2001 From: Lord of Abyss <103809695+Abyss-lord@users.noreply.github.com> Date: Thu, 13 Feb 2025 16:10:11 +0800 Subject: [PATCH 31/33] [#6097] improve(CLI): Add --quiet option to the Gravitino CLI (#6447) ### What changes were proposed in this pull request? Add --quiet option to the Gravitino CLI ### Why are the changes needed? Fix: #6097 ### Does this PR introduce _any_ user-facing change? user can use --quiet option suppress the output. ### How was this patch tested? local test ```bash gcli tag create -m cli_demo --tag tagA tagB -i # Tags tagA,tagB created gcli tag create -m cli_demo --tag tagC tagD -i --quiet # no output ``` --- .../java/org/apache/gravitino/cli/CommandContext.java | 11 +++++++++++ .../org/apache/gravitino/cli/GravitinoOptions.java | 2 ++ .../org/apache/gravitino/cli/commands/Command.java | 5 ++++- 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/CommandContext.java b/clients/cli/src/main/java/org/apache/gravitino/cli/CommandContext.java index fc713ba5775..b684ede48f0 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/CommandContext.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/CommandContext.java @@ -29,6 +29,7 @@ public class CommandContext { private final boolean ignoreVersions; private final String outputFormat; private final String url; + private final boolean quiet; private final CommandLine line; private String ignoreEnv; @@ -50,6 +51,7 @@ public CommandContext(CommandLine line) { line.hasOption(GravitinoOptions.OUTPUT) ? line.getOptionValue(GravitinoOptions.OUTPUT) : Command.OUTPUT_FORMAT_PLAIN; + this.quiet = line.hasOption(GravitinoOptions.QUIET); this.url = getUrl(); this.ignoreVersions = getIgnore(); @@ -91,6 +93,15 @@ public String outputFormat() { return outputFormat; } + /** + * Returns whether the command information should be suppressed. + * + * @return True if the command information should be suppressed. + */ + public boolean quiet() { + return quiet; + } + /** * Retrieves the Gravitino URL from the command line options or the GRAVITINO_URL environment * variable or the Gravitino config file. diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/GravitinoOptions.java b/clients/cli/src/main/java/org/apache/gravitino/cli/GravitinoOptions.java index 47f9914233d..9d304c8775e 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/GravitinoOptions.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/GravitinoOptions.java @@ -48,6 +48,7 @@ public class GravitinoOptions { public static final String PRIVILEGE = "privilege"; public static final String PROPERTIES = "properties"; public static final String PROPERTY = "property"; + public static final String QUIET = "quiet"; public static final String PROVIDER = "provider"; public static final String RENAME = "rename"; public static final String ROLE = "role"; @@ -91,6 +92,7 @@ public Options options() { options.addOption(createSimpleOption(null, SORTORDER, "display sortorder information")); options.addOption(createSimpleOption(null, ENABLE, "enable entities")); options.addOption(createSimpleOption(null, DISABLE, "disable entities")); + options.addOption(createSimpleOption(null, QUIET, "quiet mode")); // Create/update options options.addOption(createArgOption(RENAME, "new entity name")); diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/Command.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/Command.java index c9d758c17a9..6ecef9278b5 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/Command.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/Command.java @@ -85,7 +85,10 @@ public void exitWithError(String error) { * @param message The message to display. */ public void printInformation(String message) { - // so that future outoput could be suppressed + if (context.quiet()) { + return; + } + System.out.print(message); } From 300c79b00578b592cdc152c06c196bfb015b69e6 Mon Sep 17 00:00:00 2001 From: Lord of Abyss <103809695+Abyss-lord@users.noreply.github.com> Date: Fri, 14 Feb 2025 12:24:48 +0800 Subject: [PATCH 32/33] [#6449] improve(CLI): Refactor getAuth method in CLI (#6451) ### What changes were proposed in this pull request? Refactor getAuth method in CLI. ### Why are the changes needed? Fix: #6449 ### Does this PR introduce _any_ user-facing change? No ### How was this patch tested? local test. --- .../gravitino/cli/CatalogCommandHandler.java | 2 +- .../gravitino/cli/ColumnCommandHandler.java | 2 +- .../apache/gravitino/cli/CommandContext.java | 43 +++++++++++++++++++ .../apache/gravitino/cli/CommandHandler.java | 40 ----------------- .../gravitino/cli/FilesetCommandHandler.java | 2 +- .../gravitino/cli/GroupCommandHandler.java | 2 +- .../gravitino/cli/MetalakeCommandHandler.java | 2 +- .../gravitino/cli/ModelCommandHandler.java | 2 +- .../gravitino/cli/OwnerCommandHandler.java | 2 +- .../gravitino/cli/RoleCommandHandler.java | 3 +- .../gravitino/cli/SchemaCommandHandler.java | 2 +- .../gravitino/cli/TableCommandHandler.java | 2 +- .../gravitino/cli/TagCommandHandler.java | 2 +- .../gravitino/cli/TopicCommandHandler.java | 2 +- .../gravitino/cli/UserCommandHandler.java | 2 +- 15 files changed, 56 insertions(+), 54 deletions(-) diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/CatalogCommandHandler.java b/clients/cli/src/main/java/org/apache/gravitino/cli/CatalogCommandHandler.java index edef9138e33..4e5a50fd379 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/CatalogCommandHandler.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/CatalogCommandHandler.java @@ -64,7 +64,7 @@ public CatalogCommandHandler( @Override protected void handle() { String userName = line.getOptionValue(GravitinoOptions.LOGIN); - Command.setAuthenticationMode(getAuth(line), userName); + Command.setAuthenticationMode(context.auth(), userName); List missingEntities = Lists.newArrayList(); if (CommandActions.LIST.equals(command)) { diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/ColumnCommandHandler.java b/clients/cli/src/main/java/org/apache/gravitino/cli/ColumnCommandHandler.java index 01de9ca2a9d..76f2cfdc191 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/ColumnCommandHandler.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/ColumnCommandHandler.java @@ -66,7 +66,7 @@ public ColumnCommandHandler( @Override protected void handle() { String userName = line.getOptionValue(GravitinoOptions.LOGIN); - Command.setAuthenticationMode(getAuth(line), userName); + Command.setAuthenticationMode(context.auth(), userName); List missingEntities = Lists.newArrayList(); if (catalog == null) missingEntities.add(CommandEntities.CATALOG); diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/CommandContext.java b/clients/cli/src/main/java/org/apache/gravitino/cli/CommandContext.java index b684ede48f0..6f41e3697eb 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/CommandContext.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/CommandContext.java @@ -31,11 +31,14 @@ public class CommandContext { private final String url; private final boolean quiet; private final CommandLine line; + private final String auth; private String ignoreEnv; private boolean ignoreSet = false; private String urlEnv; private boolean urlSet = false; + private String authEnv; + private boolean authSet = false; // Can add more "global" command flags here without any major changes e.g. a guiet flag /** @@ -55,6 +58,7 @@ public CommandContext(CommandLine line) { this.url = getUrl(); this.ignoreVersions = getIgnore(); + this.auth = this.getAuth(); } /** @@ -102,6 +106,15 @@ public boolean quiet() { return quiet; } + /** + * Returns the authentication type. + * + * @return The authentication type. + */ + public String auth() { + return auth; + } + /** * Retrieves the Gravitino URL from the command line options or the GRAVITINO_URL environment * variable or the Gravitino config file. @@ -166,4 +179,34 @@ private boolean getIgnore() { return ignore; } + + private String getAuth() { + // If specified on the command line use that + if (line.hasOption(GravitinoOptions.SIMPLE)) { + return GravitinoOptions.SIMPLE; + } + + // Cache the Gravitino authentication type environment variable + if (authEnv == null && !authSet) { + authEnv = System.getenv("GRAVITINO_AUTH"); + authSet = true; + } + + // If set return the Gravitino authentication type environment variable + if (authEnv != null) { + return authEnv; + } + + // Check if the authentication type is specified in the configuration file + GravitinoConfig config = new GravitinoConfig(null); + if (config.fileExists()) { + config.read(); + String configAuthType = config.getGravitinoAuthType(); + if (configAuthType != null) { + return configAuthType; + } + } + + return null; + } } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/CommandHandler.java b/clients/cli/src/main/java/org/apache/gravitino/cli/CommandHandler.java index 79462e81021..90f509bba5a 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/CommandHandler.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/CommandHandler.java @@ -21,49 +21,9 @@ import com.google.common.base.Joiner; import java.util.List; -import org.apache.commons.cli.CommandLine; public abstract class CommandHandler { public static final Joiner COMMA_JOINER = Joiner.on(", ").skipNulls(); - private String authEnv; - private boolean authSet = false; - - /** - * Retrieves the Gravitino authentication from the command line options or the GRAVITINO_AUTH - * environment variable or the Gravitino config file. - * - * @param line The command line instance. - * @return The Gravitino authentication, or null if not found. - */ - public String getAuth(CommandLine line) { - // If specified on the command line use that - if (line.hasOption(GravitinoOptions.SIMPLE)) { - return GravitinoOptions.SIMPLE; - } - - // Cache the Gravitino authentication type environment variable - if (authEnv == null && !authSet) { - authEnv = System.getenv("GRAVITINO_AUTH"); - authSet = true; - } - - // If set return the Gravitino authentication type environment variable - if (authEnv != null) { - return authEnv; - } - - // Check if the authentication type is specified in the configuration file - GravitinoConfig config = new GravitinoConfig(null); - if (config.fileExists()) { - config.read(); - String configAuthType = config.getGravitinoAuthType(); - if (configAuthType != null) { - return configAuthType; - } - } - - return null; - } protected abstract void handle(); diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/FilesetCommandHandler.java b/clients/cli/src/main/java/org/apache/gravitino/cli/FilesetCommandHandler.java index 9eec933ddf5..bdcc809ac9c 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/FilesetCommandHandler.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/FilesetCommandHandler.java @@ -66,7 +66,7 @@ public FilesetCommandHandler( @Override protected void handle() { String userName = line.getOptionValue(GravitinoOptions.LOGIN); - Command.setAuthenticationMode(getAuth(line), userName); + Command.setAuthenticationMode(context.auth(), userName); List missingEntities = Lists.newArrayList(); if (catalog == null) missingEntities.add(CommandEntities.CATALOG); diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/GroupCommandHandler.java b/clients/cli/src/main/java/org/apache/gravitino/cli/GroupCommandHandler.java index deaad3df3ef..c53aa0dd39b 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/GroupCommandHandler.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/GroupCommandHandler.java @@ -58,7 +58,7 @@ public GroupCommandHandler( @Override protected void handle() { String userName = line.getOptionValue(GravitinoOptions.LOGIN); - Command.setAuthenticationMode(getAuth(line), userName); + Command.setAuthenticationMode(context.auth(), userName); if (CommandActions.LIST.equals(command)) { handleListCommand(); diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/MetalakeCommandHandler.java b/clients/cli/src/main/java/org/apache/gravitino/cli/MetalakeCommandHandler.java index 1fe32f3fea8..218f6e14588 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/MetalakeCommandHandler.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/MetalakeCommandHandler.java @@ -56,7 +56,7 @@ public MetalakeCommandHandler( public void handle() { String userName = line.getOptionValue(GravitinoOptions.LOGIN); FullName name = new FullName(line); - Command.setAuthenticationMode(getAuth(line), userName); + Command.setAuthenticationMode(context.auth(), userName); if (CommandActions.LIST.equals(command)) { handleListCommand(); diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/ModelCommandHandler.java b/clients/cli/src/main/java/org/apache/gravitino/cli/ModelCommandHandler.java index 2a0dee0bf6f..9bab9355a66 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/ModelCommandHandler.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/ModelCommandHandler.java @@ -65,7 +65,7 @@ public ModelCommandHandler( @Override protected void handle() { String userName = line.getOptionValue(GravitinoOptions.LOGIN); - Command.setAuthenticationMode(getAuth(line), userName); + Command.setAuthenticationMode(context.auth(), userName); List missingEntities = Lists.newArrayList(); if (catalog == null) missingEntities.add(CommandEntities.CATALOG); diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/OwnerCommandHandler.java b/clients/cli/src/main/java/org/apache/gravitino/cli/OwnerCommandHandler.java index cef7a9822f6..fe78d0926ef 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/OwnerCommandHandler.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/OwnerCommandHandler.java @@ -66,7 +66,7 @@ public OwnerCommandHandler( @Override protected void handle() { String userName = line.getOptionValue(GravitinoOptions.LOGIN); - Command.setAuthenticationMode(getAuth(line), userName); + Command.setAuthenticationMode(context.auth(), userName); if (entityName == null && !CommandEntities.METALAKE.equals(entity)) { System.err.println(ErrorMessages.MISSING_NAME); diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/RoleCommandHandler.java b/clients/cli/src/main/java/org/apache/gravitino/cli/RoleCommandHandler.java index a02d7f0ca86..f9e654cc432 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/RoleCommandHandler.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/RoleCommandHandler.java @@ -46,9 +46,8 @@ public RoleCommandHandler( /** Handles the command execution logic based on the provided command. */ public void handle() { - String auth = getAuth(line); String userName = line.getOptionValue(GravitinoOptions.LOGIN); - Command.setAuthenticationMode(auth, userName); + Command.setAuthenticationMode(context.auth(), userName); metalake = new FullName(line).getMetalakeName(); diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/SchemaCommandHandler.java b/clients/cli/src/main/java/org/apache/gravitino/cli/SchemaCommandHandler.java index 30c051ccf23..149746c0ecf 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/SchemaCommandHandler.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/SchemaCommandHandler.java @@ -61,7 +61,7 @@ public SchemaCommandHandler( @Override protected void handle() { String userName = line.getOptionValue(GravitinoOptions.LOGIN); - Command.setAuthenticationMode(getAuth(line), userName); + Command.setAuthenticationMode(context.auth(), userName); List missingEntities = Lists.newArrayList(); if (metalake == null) missingEntities.add(CommandEntities.METALAKE); diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/TableCommandHandler.java b/clients/cli/src/main/java/org/apache/gravitino/cli/TableCommandHandler.java index 82876917040..1e88150775c 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/TableCommandHandler.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/TableCommandHandler.java @@ -64,7 +64,7 @@ public TableCommandHandler( @Override protected void handle() { String userName = line.getOptionValue(GravitinoOptions.LOGIN); - Command.setAuthenticationMode(getAuth(line), userName); + Command.setAuthenticationMode(context.auth(), userName); List missingEntities = Lists.newArrayList(); if (catalog == null) missingEntities.add(CommandEntities.CATALOG); diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/TagCommandHandler.java b/clients/cli/src/main/java/org/apache/gravitino/cli/TagCommandHandler.java index 2c8612a33c4..a5963d26dd7 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/TagCommandHandler.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/TagCommandHandler.java @@ -50,7 +50,7 @@ public TagCommandHandler( public void handle() { String userName = line.getOptionValue(GravitinoOptions.LOGIN); FullName name = new FullName(line); - Command.setAuthenticationMode(getAuth(line), userName); + Command.setAuthenticationMode(context.auth(), userName); metalake = name.getMetalakeName(); diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/TopicCommandHandler.java b/clients/cli/src/main/java/org/apache/gravitino/cli/TopicCommandHandler.java index 34315fa971d..1db669f00ad 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/TopicCommandHandler.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/TopicCommandHandler.java @@ -64,7 +64,7 @@ public TopicCommandHandler( @Override protected void handle() { String userName = line.getOptionValue(GravitinoOptions.LOGIN); - Command.setAuthenticationMode(getAuth(line), userName); + Command.setAuthenticationMode(context.auth(), userName); List missingEntities = Lists.newArrayList(); if (catalog == null) missingEntities.add(CommandEntities.CATALOG); diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/UserCommandHandler.java b/clients/cli/src/main/java/org/apache/gravitino/cli/UserCommandHandler.java index 5fd7d906b9b..58fe011ef5d 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/UserCommandHandler.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/UserCommandHandler.java @@ -58,7 +58,7 @@ public UserCommandHandler( @Override protected void handle() { String userName = line.getOptionValue(GravitinoOptions.LOGIN); - Command.setAuthenticationMode(getAuth(line), userName); + Command.setAuthenticationMode(context.auth(), userName); user = line.getOptionValue(GravitinoOptions.USER); From 74435c9b83b382daf0dc4753a2af9fe7af1c89a7 Mon Sep 17 00:00:00 2001 From: Qian Xia Date: Fri, 14 Feb 2025 17:33:25 +0800 Subject: [PATCH 33/33] [#6450] fix(web): fix authentication.type issue (#6452) ### What changes were proposed in this pull request? authentication.type of catalog property should send correct request to server ### Why are the changes needed? N/A Fix: #6450 ### Does this PR introduce _any_ user-facing change? N/A ### How was this patch tested? manually --- .../app/metalakes/metalake/rightContent/CreateCatalogDialog.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/web/src/app/metalakes/metalake/rightContent/CreateCatalogDialog.js b/web/web/src/app/metalakes/metalake/rightContent/CreateCatalogDialog.js index 6f0cf70edf9..b44ba22bc76 100644 --- a/web/web/src/app/metalakes/metalake/rightContent/CreateCatalogDialog.js +++ b/web/web/src/app/metalakes/metalake/rightContent/CreateCatalogDialog.js @@ -306,7 +306,7 @@ const CreateCatalogDialog = props => { jdbcUser && (properties['jdbc-user'] = jdbcUser) jdbcPwd && (properties['jdbc-password'] = jdbcPwd) } - authType && (properties['authType'] = authType) + authType && (properties['authentication.type'] = authType) kerberosPrincipal && (properties['authentication.kerberos.principal'] = kerberosPrincipal) kerberosKeytabUri && (properties['authentication.kerberos.keytab-uri'] = kerberosKeytabUri)