This is an automated email from the ASF dual-hosted git repository. jmclean 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 86ef6e8911 [#5963] feat(client): added delete cli command model (#6099) 86ef6e8911 is described below commit 86ef6e89112aba8c77d96ef2f23f2db1ef63c3f2 Author: Vignesh Suresh Kumar <55813127+vigneshs...@users.noreply.github.com> AuthorDate: Sun Jan 5 17:10:44 2025 -0500 [#5963] feat(client): added delete cli command model (#6099) ### What changes were proposed in this pull request? The delete command is one of the commands suggested by @justinmclean as part of adding Model entity support for the CLI. ### Why are the changes needed? To add delete functionality for a Model using the CLI Improvement: https://github.com/apache/gravitino/issues/5963 (NOTE: Create command is redundant with addition of Register command) ### Does this PR introduce any user-facing change? Yes. The delete command for a model was added. ### How was this patch tested? Unit tests were added for Model CLI support and ran successfully for the delete command, along with CI tests in forked repository --- .../apache/gravitino/cli/GravitinoCommandLine.java | 5 ++ .../apache/gravitino/cli/TestableCommandLine.java | 12 +++ .../apache/gravitino/cli/commands/DeleteModel.java | 96 ++++++++++++++++++++++ clients/cli/src/main/resources/model_help.txt | 37 ++++++++- .../apache/gravitino/cli/TestModelCommands.java | 30 ++++++- 5 files changed, 176 insertions(+), 4 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 f8347dfe1f..507416d9bb 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 @@ -1190,6 +1190,11 @@ public class GravitinoCommandLine extends TestableCommandLine { } break; + case CommandActions.DELETE: + boolean force = line.hasOption(GravitinoOptions.FORCE); + newDeleteModel(url, ignore, force, metalake, catalog, schema, model).handle(); + break; + case CommandActions.CREATE: String createComment = line.getOptionValue(GravitinoOptions.COMMENT); String[] createProperties = line.getOptionValues(GravitinoOptions.PROPERTIES); 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 8df9498d97..c08a095052 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 @@ -45,6 +45,7 @@ import org.apache.gravitino.cli.commands.DeleteColumn; import org.apache.gravitino.cli.commands.DeleteFileset; import org.apache.gravitino.cli.commands.DeleteGroup; import org.apache.gravitino.cli.commands.DeleteMetalake; +import org.apache.gravitino.cli.commands.DeleteModel; import org.apache.gravitino.cli.commands.DeleteRole; import org.apache.gravitino.cli.commands.DeleteSchema; import org.apache.gravitino.cli.commands.DeleteTable; @@ -940,6 +941,17 @@ public class TestableCommandLine { return new RegisterModel(url, ignore, 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); + } + protected LinkModel newLinkModel( String url, boolean ignore, 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 new file mode 100644 index 0000000000..f44814ce68 --- /dev/null +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/DeleteModel.java @@ -0,0 +1,96 @@ +/* + * 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.commands; + +import org.apache.gravitino.NameIdentifier; +import org.apache.gravitino.cli.AreYouSure; +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.NoSuchModelException; +import org.apache.gravitino.exceptions.NoSuchSchemaException; + +/** Deletes an existing model. */ +public class DeleteModel extends Command { + + protected final String metalake; + protected final String catalog; + protected final String schema; + protected final String model; + protected final boolean force; + + /** + * 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 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; + this.metalake = metalake; + this.catalog = catalog; + this.schema = schema; + this.model = model; + } + + /** Deletes an existing model. */ + public void handle() { + boolean deleted = false; + + if (!AreYouSure.really(force)) { + return; + } + + try (GravitinoClient client = buildClient(metalake)) { + NameIdentifier name = NameIdentifier.of(schema, model); + deleted = client.loadCatalog(catalog).asModelCatalog().deleteModel(name); + } catch (NoSuchMetalakeException noSuchMetalakeException) { + exitWithError(ErrorMessages.UNKNOWN_METALAKE); + } catch (NoSuchCatalogException noSuchCatalogException) { + exitWithError(ErrorMessages.UNKNOWN_CATALOG); + } catch (NoSuchSchemaException noSuchSchemaException) { + exitWithError(ErrorMessages.UNKNOWN_SCHEMA); + } catch (NoSuchModelException noSuchModelException) { + exitWithError(ErrorMessages.UNKNOWN_MODEL); + } catch (Exception err) { + exitWithError(err.getMessage()); + } + + if (deleted) { + System.out.println(model + " deleted."); + } else { + System.out.println(model + " not deleted."); + } + } +} diff --git a/clients/cli/src/main/resources/model_help.txt b/clients/cli/src/main/resources/model_help.txt index 04e9b8262e..7becf2fd55 100644 --- a/clients/cli/src/main/resources/model_help.txt +++ b/clients/cli/src/main/resources/model_help.txt @@ -1,8 +1,41 @@ -gcli model [details] +gcli model [list|details|create|update|delete] Please set the metalake in the Gravitino configuration file or the environment variable before running any of these commands. Example commands +Register a model +gcli model create --name hadoop.schema.model + +Register a model with comment +gcli model create --name hadoop.schema.model --comment comment + +Register a model with properties +gcli model create --name hadoop.schema.model --properties key1=val1 key2=val2 + +Register a model with properties" and comment +gcli model create --name hadoop.schema.model --properties key1=val1 key2=val2 --comment comment + +List models +gcli model list --name hadoop.schema + +Show a model's details +gcli model details --name hadoop.schema.model + Show model audit information -gcli model details --name catalog_postgres.hr --audit \ No newline at end of file +gcli model details --name hadoop.schema.model --audit + +Link a model +gcli model update --name hadoop.schema.model --uri file:///tmp/file + +Link a model with alias +gcli model update --name hadoop.schema.model --uri file:///tmp/file --alias aliasA aliasB + +Link a model with all component +gcli model update --name hadoop.schema.model --uri file:///tmp/file --alias aliasA aliasB --comment comment --properties key1=val1 key2=val2 + +Link a model without uri +gcli model update --name hadoop.schema.model + +Delete a model +gcli model delete --name hadoop.schema.model \ No newline at end of file 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 391201f292..7900022601 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 @@ -39,6 +39,7 @@ import java.util.Collections; import java.util.Map; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.Options; +import org.apache.gravitino.cli.commands.DeleteModel; import org.apache.gravitino.cli.commands.LinkModel; import org.apache.gravitino.cli.commands.ListModel; import org.apache.gravitino.cli.commands.ModelAudit; @@ -303,11 +304,11 @@ public class TestModelCommands { when(mockCommandLine.getOptionValue(GravitinoOptions.NAME)).thenReturn("catalog.schema.model"); when(mockCommandLine.hasOption(GravitinoOptions.PROPERTIES)).thenReturn(false); when(mockCommandLine.hasOption(GravitinoOptions.COMMENT)).thenReturn(false); + GravitinoCommandLine commandLine = spy( new GravitinoCommandLine( mockCommandLine, mockOptions, CommandEntities.MODEL, CommandActions.CREATE)); - doReturn(mockCreate) .when(commandLine) .newCreateModel( @@ -337,7 +338,6 @@ public class TestModelCommands { spy( new GravitinoCommandLine( mockCommandLine, mockOptions, CommandEntities.MODEL, CommandActions.CREATE)); - doReturn(mockCreate) .when(commandLine) .newCreateModel( @@ -424,6 +424,32 @@ public class TestModelCommands { verify(mockCreate).handle(); } + @Test + void testDeleteModelCommand() { + DeleteModel mockDelete = mock(DeleteModel.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.model"); + + GravitinoCommandLine commandLine = + spy( + new GravitinoCommandLine( + mockCommandLine, mockOptions, CommandEntities.MODEL, CommandActions.DELETE)); + doReturn(mockDelete) + .when(commandLine) + .newDeleteModel( + GravitinoCommandLine.DEFAULT_URL, + false, + false, + "metalake_demo", + "catalog", + "schema", + "model"); + commandLine.handleCommandLine(); + verify(mockDelete).handle(); + } + @Test void testLinkModelCommandWithoutAlias() { LinkModel linkModelMock = mock(LinkModel.class);