This is an automated email from the ASF dual-hosted git repository. shaofengshi pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/gravitino.git
The following commit(s) were added to refs/heads/main by this push: new 2e034b26d [#5294] Add topic property command to Gravitino CLI (#5352) 2e034b26d is described below commit 2e034b26d2a45e090af3741e6c31d31f4ca68b90 Author: Justin Mclean <jus...@classsoftware.com> AuthorDate: Mon Dec 2 11:43:08 2024 +1100 [#5294] Add topic property command to Gravitino CLI (#5352) ### What changes were proposed in this pull request? Add topic property command to Gravitino CLI ### Why are the changes needed? To expand Gravitino CLI. Fix: #5294 ### Does this PR introduce _any_ user-facing change? No but it adds additional command to the Gravitino CLi. ### How was this patch tested? Tested locally with a running Apache Kafka instance. --- .../apache/gravitino/cli/GravitinoCommandLine.java | 9 +++ .../apache/gravitino/cli/TestableCommandLine.java | 31 ++++++++ .../cli/commands/ListSchemaProperties.java | 6 +- ...emaProperties.java => ListTopicProperties.java} | 35 ++++++--- ...emaProperties.java => RemoveTopicProperty.java} | 41 +++++++---- ...SchemaProperties.java => SetTopicProperty.java} | 46 ++++++++---- .../apache/gravitino/cli/TestTopicCommands.java | 82 ++++++++++++++++++++++ docs/cli.md | 18 +++++ 8 files changed, 231 insertions(+), 37 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 7bb455ae4..23efe28bd 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 @@ -519,6 +519,15 @@ public class GravitinoCommandLine extends TestableCommandLine { String comment = line.getOptionValue(GravitinoOptions.COMMENT); newUpdateTopicComment(url, ignore, metalake, catalog, schema, topic, comment).handle(); } + } else if (CommandActions.SET.equals(command)) { + String property = line.getOptionValue(GravitinoOptions.PROPERTY); + String value = line.getOptionValue(GravitinoOptions.VALUE); + newSetTopicProperty(url, ignore, metalake, catalog, schema, topic, property, value).handle(); + } else if (CommandActions.REMOVE.equals(command)) { + String property = line.getOptionValue(GravitinoOptions.PROPERTY); + newRemoveTopicProperty(url, ignore, metalake, catalog, schema, topic, property).handle(); + } else if (CommandActions.PROPERTIES.equals(command)) { + newListTopicProperties(url, ignore, metalake, catalog, schema, topic).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 a5db451eb..adcfd7eff 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 @@ -63,6 +63,7 @@ import org.apache.gravitino.cli.commands.ListSchema; import org.apache.gravitino.cli.commands.ListSchemaProperties; import org.apache.gravitino.cli.commands.ListTables; import org.apache.gravitino.cli.commands.ListTagProperties; +import org.apache.gravitino.cli.commands.ListTopicProperties; import org.apache.gravitino.cli.commands.ListTopics; import org.apache.gravitino.cli.commands.ListUsers; import org.apache.gravitino.cli.commands.MetalakeAudit; @@ -75,6 +76,7 @@ import org.apache.gravitino.cli.commands.RemoveRoleFromGroup; import org.apache.gravitino.cli.commands.RemoveRoleFromUser; import org.apache.gravitino.cli.commands.RemoveSchemaProperty; import org.apache.gravitino.cli.commands.RemoveTagProperty; +import org.apache.gravitino.cli.commands.RemoveTopicProperty; import org.apache.gravitino.cli.commands.RoleDetails; import org.apache.gravitino.cli.commands.SchemaAudit; import org.apache.gravitino.cli.commands.SchemaDetails; @@ -85,6 +87,7 @@ import org.apache.gravitino.cli.commands.SetMetalakeProperty; import org.apache.gravitino.cli.commands.SetOwner; import org.apache.gravitino.cli.commands.SetSchemaProperty; import org.apache.gravitino.cli.commands.SetTagProperty; +import org.apache.gravitino.cli.commands.SetTopicProperty; import org.apache.gravitino.cli.commands.TableAudit; import org.apache.gravitino.cli.commands.TableDetails; import org.apache.gravitino.cli.commands.TableDistribution; @@ -500,6 +503,34 @@ public class TestableCommandLine { return new UpdateTopicComment(url, ignore, metalake, catalog, schema, topic, comment); } + protected SetTopicProperty newSetTopicProperty( + String url, + boolean ignore, + String metalake, + String catalog, + String schema, + String topic, + String property, + String value) { + return new SetTopicProperty(url, ignore, metalake, catalog, schema, topic, property, value); + } + + protected RemoveTopicProperty newRemoveTopicProperty( + String url, + boolean ignore, + String metalake, + String catalog, + String schema, + String topic, + String property) { + return new RemoveTopicProperty(url, ignore, 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); + } + protected FilesetDetails newFilesetDetails( String url, boolean ignore, String metalake, String catalog, String schema, String fileset) { return new FilesetDetails(url, ignore, metalake, catalog, schema, fileset); 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 3a48196b8..210bda087 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 @@ -27,7 +27,7 @@ import org.apache.gravitino.exceptions.NoSuchCatalogException; import org.apache.gravitino.exceptions.NoSuchMetalakeException; import org.apache.gravitino.exceptions.NoSuchSchemaException; -/** List the properties of a catalog. */ +/** List the properties of a schema. */ public class ListSchemaProperties extends ListProperties { protected final String metalake; @@ -35,7 +35,7 @@ public class ListSchemaProperties extends ListProperties { protected final String schema; /** - * List the properties of a catalog. + * 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. @@ -51,7 +51,7 @@ public class ListSchemaProperties extends ListProperties { this.schema = schema; } - /** List the properties of a catalog. */ + /** List the properties of a schema. */ @Override public void handle() { Schema gSchema = null; 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/ListTopicProperties.java similarity index 70% copy from clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListSchemaProperties.java copy to clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListTopicProperties.java index 3a48196b8..5063c61b9 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/ListTopicProperties.java @@ -20,44 +20,56 @@ package org.apache.gravitino.cli.commands; import java.util.Map; -import org.apache.gravitino.Schema; +import org.apache.gravitino.NameIdentifier; import org.apache.gravitino.cli.ErrorMessages; 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.NoSuchTopicException; +import org.apache.gravitino.messaging.Topic; -/** List the properties of a catalog. */ -public class ListSchemaProperties extends ListProperties { +/** List the properties of a topic. */ +public class ListTopicProperties extends ListProperties { protected final String metalake; protected final String catalog; protected final String schema; + protected final String topic; /** - * List the properties of a catalog. + * 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 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 ListSchemaProperties( - String url, boolean ignoreVersions, String metalake, String catalog, String schema) { + public ListTopicProperties( + String url, + boolean ignoreVersions, + String metalake, + String catalog, + String schema, + String topic) { super(url, ignoreVersions); this.metalake = metalake; this.catalog = catalog; this.schema = schema; + this.topic = topic; } - /** List the properties of a catalog. */ + /** List the properties of a topic. */ @Override public void handle() { - Schema gSchema = null; + NameIdentifier name = NameIdentifier.of(schema, topic); + Topic gTopic = null; + try { GravitinoClient client = buildClient(metalake); - gSchema = client.loadCatalog(catalog).asSchemas().loadSchema(schema); + gTopic = client.loadCatalog(catalog).asTopicCatalog().loadTopic(name); } catch (NoSuchMetalakeException err) { System.err.println(ErrorMessages.UNKNOWN_METALAKE); return; @@ -67,12 +79,15 @@ public class ListSchemaProperties extends ListProperties { } catch (NoSuchSchemaException err) { System.err.println(ErrorMessages.UNKNOWN_SCHEMA); return; + } catch (NoSuchTopicException err) { + System.err.println(ErrorMessages.UNKNOWN_TOPIC); + return; } catch (Exception exp) { System.err.println(exp.getMessage()); return; } - Map<String, String> properties = gSchema.properties(); + Map<String, String> properties = gTopic.properties(); printProperties(properties); } } 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/RemoveTopicProperty.java similarity index 66% copy from clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListSchemaProperties.java copy to clients/cli/src/main/java/org/apache/gravitino/cli/commands/RemoveTopicProperty.java index 3a48196b8..4c2131759 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/RemoveTopicProperty.java @@ -19,45 +19,60 @@ package org.apache.gravitino.cli.commands; -import java.util.Map; -import org.apache.gravitino.Schema; +import org.apache.gravitino.NameIdentifier; import org.apache.gravitino.cli.ErrorMessages; 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.NoSuchTopicException; +import org.apache.gravitino.messaging.TopicChange; -/** List the properties of a catalog. */ -public class ListSchemaProperties extends ListProperties { +/** Remove a property of a topic. */ +public class RemoveTopicProperty extends Command { protected final String metalake; protected final String catalog; protected final String schema; + protected final String topic; + protected final String property; /** - * List the properties of a catalog. + * 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 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 schema. + * @param property The name of the property. */ - public ListSchemaProperties( - String url, boolean ignoreVersions, String metalake, String catalog, String schema) { + public RemoveTopicProperty( + String url, + boolean ignoreVersions, + String metalake, + String catalog, + String schema, + String topic, + String property) { super(url, ignoreVersions); this.metalake = metalake; this.catalog = catalog; this.schema = schema; + this.topic = topic; + this.property = property; } - /** List the properties of a catalog. */ + /** Remove a property of a topic. */ @Override public void handle() { - Schema gSchema = null; + NameIdentifier name = NameIdentifier.of(schema, topic); + try { GravitinoClient client = buildClient(metalake); - gSchema = client.loadCatalog(catalog).asSchemas().loadSchema(schema); + TopicChange change = TopicChange.removeProperty(property); + client.loadCatalog(catalog).asTopicCatalog().alterTopic(name, change); } catch (NoSuchMetalakeException err) { System.err.println(ErrorMessages.UNKNOWN_METALAKE); return; @@ -67,12 +82,14 @@ public class ListSchemaProperties extends ListProperties { } catch (NoSuchSchemaException err) { System.err.println(ErrorMessages.UNKNOWN_SCHEMA); return; + } catch (NoSuchTopicException err) { + System.err.println(ErrorMessages.UNKNOWN_TOPIC); + return; } catch (Exception exp) { System.err.println(exp.getMessage()); return; } - Map<String, String> properties = gSchema.properties(); - printProperties(properties); + System.out.println(property + " property removed."); } } 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/SetTopicProperty.java similarity index 64% copy from clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListSchemaProperties.java copy to clients/cli/src/main/java/org/apache/gravitino/cli/commands/SetTopicProperty.java index 3a48196b8..55ed1c05c 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/SetTopicProperty.java @@ -19,45 +19,65 @@ package org.apache.gravitino.cli.commands; -import java.util.Map; -import org.apache.gravitino.Schema; +import org.apache.gravitino.NameIdentifier; import org.apache.gravitino.cli.ErrorMessages; 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.NoSuchTopicException; +import org.apache.gravitino.messaging.TopicChange; -/** List the properties of a catalog. */ -public class ListSchemaProperties extends ListProperties { +/** Set a property of a topic. */ +public class SetTopicProperty extends Command { protected final String metalake; protected final String catalog; protected final String schema; + protected final String topic; + protected final String property; + protected final String value; /** - * List the properties of a catalog. + * 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 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. + * @param property The name of the property. + * @param value The value of the property. */ - public ListSchemaProperties( - String url, boolean ignoreVersions, String metalake, String catalog, String schema) { + public SetTopicProperty( + String url, + boolean ignoreVersions, + String metalake, + String catalog, + String schema, + String topic, + String property, + String value) { super(url, ignoreVersions); this.metalake = metalake; this.catalog = catalog; this.schema = schema; + this.topic = topic; + this.property = property; + this.value = value; } - /** List the properties of a catalog. */ + /** Set a property of a topic. */ @Override public void handle() { - Schema gSchema = null; + NameIdentifier name = NameIdentifier.of(schema, topic); + try { GravitinoClient client = buildClient(metalake); - gSchema = client.loadCatalog(catalog).asSchemas().loadSchema(schema); + TopicChange change = TopicChange.setProperty(property, value); + client.loadCatalog(catalog).asTopicCatalog().alterTopic(name, change); + } catch (NoSuchMetalakeException err) { System.err.println(ErrorMessages.UNKNOWN_METALAKE); return; @@ -67,12 +87,14 @@ public class ListSchemaProperties extends ListProperties { } catch (NoSuchSchemaException err) { System.err.println(ErrorMessages.UNKNOWN_SCHEMA); return; + } catch (NoSuchTopicException err) { + System.err.println(ErrorMessages.UNKNOWN_TOPIC); + return; } catch (Exception exp) { System.err.println(exp.getMessage()); return; } - Map<String, String> properties = gSchema.properties(); - printProperties(properties); + System.out.println(property + " property set."); } } 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 9e69b09ec..50b580eaf 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 @@ -29,7 +29,10 @@ import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.Options; import org.apache.gravitino.cli.commands.CreateTopic; import org.apache.gravitino.cli.commands.DeleteTopic; +import org.apache.gravitino.cli.commands.ListTopicProperties; import org.apache.gravitino.cli.commands.ListTopics; +import org.apache.gravitino.cli.commands.RemoveTopicProperty; +import org.apache.gravitino.cli.commands.SetTopicProperty; import org.apache.gravitino.cli.commands.TopicDetails; import org.apache.gravitino.cli.commands.UpdateTopicComment; import org.junit.jupiter.api.BeforeEach; @@ -189,4 +192,83 @@ class TestTopicCommands { commandLine.handleCommandLine(); verify(mockUpdate).handle(); } + + @Test + void testListTopicPropertiesCommand() { + ListTopicProperties mockListProperties = mock(ListTopicProperties.class); + + when(mockCommandLine.hasOption(GravitinoOptions.METALAKE)).thenReturn(true); + when(mockCommandLine.getOptionValue(GravitinoOptions.METALAKE)).thenReturn("metalake_demo"); + when(mockCommandLine.hasOption(GravitinoOptions.NAME)).thenReturn(true); + when(mockCommandLine.getOptionValue(GravitinoOptions.NAME)).thenReturn("catalog.schema.topic"); + GravitinoCommandLine commandLine = + spy( + new GravitinoCommandLine( + mockCommandLine, mockOptions, CommandEntities.TOPIC, CommandActions.PROPERTIES)); + doReturn(mockListProperties) + .when(commandLine) + .newListTopicProperties( + GravitinoCommandLine.DEFAULT_URL, false, "metalake_demo", "catalog", "schema", "topic"); + commandLine.handleCommandLine(); + verify(mockListProperties).handle(); + } + + @Test + void testSetTopicPropertyCommand() { + SetTopicProperty mockSetProperties = mock(SetTopicProperty.class); + + when(mockCommandLine.hasOption(GravitinoOptions.METALAKE)).thenReturn(true); + when(mockCommandLine.getOptionValue(GravitinoOptions.METALAKE)).thenReturn("metalake_demo"); + when(mockCommandLine.hasOption(GravitinoOptions.NAME)).thenReturn(true); + when(mockCommandLine.getOptionValue(GravitinoOptions.NAME)).thenReturn("catalog.schema.topic"); + when(mockCommandLine.hasOption(GravitinoOptions.PROPERTY)).thenReturn(true); + when(mockCommandLine.getOptionValue(GravitinoOptions.PROPERTY)).thenReturn("property"); + when(mockCommandLine.hasOption(GravitinoOptions.VALUE)).thenReturn(true); + when(mockCommandLine.getOptionValue(GravitinoOptions.VALUE)).thenReturn("value"); + GravitinoCommandLine commandLine = + spy( + new GravitinoCommandLine( + mockCommandLine, mockOptions, CommandEntities.TOPIC, CommandActions.SET)); + doReturn(mockSetProperties) + .when(commandLine) + .newSetTopicProperty( + GravitinoCommandLine.DEFAULT_URL, + false, + "metalake_demo", + "catalog", + "schema", + "topic", + "property", + "value"); + commandLine.handleCommandLine(); + verify(mockSetProperties).handle(); + } + + @Test + void testRemoveTopicPropertyCommand() { + RemoveTopicProperty mockSetProperties = mock(RemoveTopicProperty.class); + + when(mockCommandLine.hasOption(GravitinoOptions.METALAKE)).thenReturn(true); + when(mockCommandLine.getOptionValue(GravitinoOptions.METALAKE)).thenReturn("metalake_demo"); + when(mockCommandLine.hasOption(GravitinoOptions.NAME)).thenReturn(true); + when(mockCommandLine.getOptionValue(GravitinoOptions.NAME)).thenReturn("catalog.schema.topic"); + when(mockCommandLine.hasOption(GravitinoOptions.PROPERTY)).thenReturn(true); + when(mockCommandLine.getOptionValue(GravitinoOptions.PROPERTY)).thenReturn("property"); + GravitinoCommandLine commandLine = + spy( + new GravitinoCommandLine( + mockCommandLine, mockOptions, CommandEntities.TOPIC, CommandActions.REMOVE)); + doReturn(mockSetProperties) + .when(commandLine) + .newRemoveTopicProperty( + GravitinoCommandLine.DEFAULT_URL, + false, + "metalake_demo", + "catalog", + "schema", + "topic", + "property"); + commandLine.handleCommandLine(); + verify(mockSetProperties).handle(); + } } diff --git a/docs/cli.md b/docs/cli.md index 979922162..334057b0b 100644 --- a/docs/cli.md +++ b/docs/cli.md @@ -628,6 +628,24 @@ gcli topic delete --name kafka.default.topic3 gcli topic update --name kafka.default.topic3 --comment new_comment ``` +#### Display a topics's properties + +```bash +gcli topic properties --name kafka.default.topic3 +``` + +#### Set a topics's property + +```bash +gcli topic set --name kafka.default.topic3 --property test --value value +``` + +#### Remove a topics's property + +```bash +gcli topic remove --name kafka.default.topic3 --property test +``` + ### Fileset commands #### Create a fileset