From 9320324f3e454699a22bf5ab385dff5805f4f57b Mon Sep 17 00:00:00 2001 From: Justin Mclean Date: Mon, 14 Oct 2024 16:07:24 -0700 Subject: [PATCH 1/3] basic CLI for tags --- clients/cli/examples.sh | 19 +++- .../apache/gravitino/cli/CommandEntities.java | 2 + .../apache/gravitino/cli/ErrorMessages.java | 2 + .../org/apache/gravitino/cli/FullName.java | 66 +++++++++++- .../gravitino/cli/GravitinoCommandLine.java | 58 ++++++++++ .../gravitino/cli/GravitinoOptions.java | 2 + .../gravitino/cli/commands/CreateTag.java | 65 ++++++++++++ .../gravitino/cli/commands/DeleteTag.java | 69 ++++++++++++ .../cli/commands/ListTagProperties.java | 68 ++++++++++++ .../gravitino/cli/commands/ListTags.java | 66 ++++++++++++ .../cli/commands/RemoveTagProperty.java | 69 ++++++++++++ .../cli/commands/SetTagProperty.java | 72 +++++++++++++ .../gravitino/cli/commands/TagDetails.java | 68 ++++++++++++ .../gravitino/cli/commands/TagEntity.java | 100 ++++++++++++++++++ .../gravitino/cli/commands/UntagEntity.java | 100 ++++++++++++++++++ .../cli/commands/UpdateCatalogName.java | 4 + .../cli/commands/UpdateTagComment.java | 69 ++++++++++++ .../gravitino/cli/commands/UpdateTagName.java | 69 ++++++++++++ .../gravitino/cli/TestCommandEntities.java | 1 + .../apache/gravitino/cli/TestFulllName.java | 46 ++++++++ 20 files changed, 1012 insertions(+), 3 deletions(-) create mode 100644 clients/cli/src/main/java/org/apache/gravitino/cli/commands/CreateTag.java create mode 100644 clients/cli/src/main/java/org/apache/gravitino/cli/commands/DeleteTag.java create mode 100644 clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListTagProperties.java create mode 100644 clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListTags.java create mode 100644 clients/cli/src/main/java/org/apache/gravitino/cli/commands/RemoveTagProperty.java create mode 100644 clients/cli/src/main/java/org/apache/gravitino/cli/commands/SetTagProperty.java create mode 100644 clients/cli/src/main/java/org/apache/gravitino/cli/commands/TagDetails.java create mode 100644 clients/cli/src/main/java/org/apache/gravitino/cli/commands/TagEntity.java create mode 100644 clients/cli/src/main/java/org/apache/gravitino/cli/commands/UntagEntity.java create mode 100644 clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateTagComment.java create mode 100644 clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateTagName.java diff --git a/clients/cli/examples.sh b/clients/cli/examples.sh index 0cb8b4fe2f8..23ce348026e 100755 --- a/clients/cli/examples.sh +++ b/clients/cli/examples.sh @@ -158,4 +158,21 @@ gcli user delete --name metalake_demo --user new_user gcli group create --name metalake_demo --user new_group gcli group details --name metalake_demo --user new_group gcli group list --name metalake_demo -gcli group delete --name metalake_demo --user new_group \ No newline at end of file +gcli group delete --name metalake_demo --user new_group + +# Tag examples +gcli tag create --name metalake_demo --tag tagA +gcli tag details --name metalake_demo --tag tagA +gcli tag list --name metalake_demo # all tags in a metalake +gcli tag delete --name metalake_demo --tag tagA +gcli tag update --name metalake_demo --tag tagA --rename new_tag +gcli tag update --name metalake_demo --tag tagA --comment "new comment" +gcli tag properties --name metalake_demo --tag tagA +gcli tag set --name metalake_demo --tag tagA --property color --value green +gcli tag remove --name metalake_demo --tag tagA --property color +gcli tag create --name metalake_demo --tag hr +gcli tag set --name metalake_demo.catalog_postgres.hr --tag hr # tag entity +gcli tag remove --name metalake_demo.catalog_postgres.hr --tag hr # untag entity + +gcli tag list --name metalake_demo.catalog_postgres.hr # all tags hr has been taged with +gcli tag list --tag tagA --name metalake_demo # all objects with tagA diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/CommandEntities.java b/clients/cli/src/main/java/org/apache/gravitino/cli/CommandEntities.java index fa9cd02756e..390ed5c05b2 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/CommandEntities.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/CommandEntities.java @@ -32,6 +32,7 @@ public class CommandEntities { public static final String TABLE = "table"; public static final String USER = "user"; public static final String GROUP = "group"; + public static final String TAG = "tag"; private static final HashSet VALID_ENTITIES = new HashSet<>(); @@ -42,6 +43,7 @@ public class CommandEntities { VALID_ENTITIES.add(TABLE); VALID_ENTITIES.add(USER); VALID_ENTITIES.add(GROUP); + VALID_ENTITIES.add(TAG); } /** 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 c3da72ce878..6a6d4e5bbe8 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 @@ -37,4 +37,6 @@ public class ErrorMessages { public static final String USER_EXISTS = "User already exists."; public static final String UNKNOWN_GROUP = "Unknown group."; public static final String GROUP_EXISTS = "Group already exists."; + public static final String UNKNOWN_TAG = "Unknown tag."; + public static final String TAG_EXISTS = "Tag already exists."; } diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/FullName.java b/clients/cli/src/main/java/org/apache/gravitino/cli/FullName.java index b5418fe3105..ecae6c7c437 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/FullName.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/FullName.java @@ -119,12 +119,11 @@ public String getNamePart(String entity, int position) { String[] names = line.getOptionValue(GravitinoOptions.NAME).split("\\."); /* Adjust position if metalake is part of the full name. */ - String metalakeEnv = System.getenv("GRAVITINO_METALAKE"); if (metalakeEnv != null) { position = position - 1; } - if (names.length - 1 < position) { + if (position >= names.length) { System.err.println(ErrorMessages.MALFORMED_NAME); return null; } @@ -135,4 +134,67 @@ public String getNamePart(String entity, int position) { System.err.println(ErrorMessages.MISSING_NAME); return null; } + + /** + * Helper method to determine a specific part of the full name exits. + * + * @param entity The part of the name to obtain. + * @return True if the part exitsts. + */ + public boolean hasNamePart(String entity) { + /* Check if the name is specified as a command line option. */ + if (line.hasOption(entity)) { + return true; + /* Extract the name part from the full name if available. */ + } else if (line.hasOption(GravitinoOptions.NAME)) { + String[] names = line.getOptionValue(GravitinoOptions.NAME).split("\\."); + int length = names.length; + String [] order = {GravitinoOptions.METALAKE, GravitinoOptions.CATALOG,GravitinoOptions.SCHEMA,GravitinoOptions.TABLE}; + int position = order.indexOf(entity); + + /* Adjust position if metalake is part of the full name. */ + if (metalakeEnv != null) { + position = position - 1; + } + return position < length; + } + + return false; + } + + /** + * Does the metalake name exist? + * + * @return True if the catalog name exists, or false if it does not. + */ + public boolean hasMetalakeName() { + return hasNamePart(GravitinoOptions.METALAKE); + } + + /** + * Does the catalog name exist? + * + * @return True if the catalog name exists, or false if it does not. + */ + public boolean hasCatalogName() { + return hasNamePart(GravitinoOptions.CATALOG); + } + + /** + * Does the schema name exist? + * + * @return True if the schema name exists, or false if it does not. + */ + public boolean hasSchemaName() { + return hasNamePart(GravitinoOptions.SCHEMA); + } + + /** + * Does the table name exist? + * + * @return True if the table name exists, or false if it does not. + */ + public boolean hasTableName() { + return hasNamePart(GravitinoOptions.TABLE); + } } 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 c39b2261aee..938dbdaf390 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 @@ -34,12 +34,14 @@ import org.apache.gravitino.cli.commands.CreateMySQLCatalog; import org.apache.gravitino.cli.commands.CreatePostgresCatalog; import org.apache.gravitino.cli.commands.CreateSchema; +import org.apache.gravitino.cli.commands.CreateTag; import org.apache.gravitino.cli.commands.CreateUser; import org.apache.gravitino.cli.commands.DeleteCatalog; import org.apache.gravitino.cli.commands.DeleteGroup; import org.apache.gravitino.cli.commands.DeleteMetalake; import org.apache.gravitino.cli.commands.DeleteSchema; import org.apache.gravitino.cli.commands.DeleteTable; +import org.apache.gravitino.cli.commands.DeleteTag; import org.apache.gravitino.cli.commands.DeleteUser; import org.apache.gravitino.cli.commands.GroupDetails; import org.apache.gravitino.cli.commands.ListCatalogProperties; @@ -51,21 +53,30 @@ 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.ListTags; import org.apache.gravitino.cli.commands.ListUsers; import org.apache.gravitino.cli.commands.MetalakeDetails; import org.apache.gravitino.cli.commands.RemoveCatalogProperty; import org.apache.gravitino.cli.commands.RemoveMetalakeProperty; import org.apache.gravitino.cli.commands.RemoveSchemaProperty; +import org.apache.gravitino.cli.commands.RemoveTagProperty; import org.apache.gravitino.cli.commands.SchemaDetails; import org.apache.gravitino.cli.commands.ServerVersion; import org.apache.gravitino.cli.commands.SetCatalogProperty; import org.apache.gravitino.cli.commands.SetMetalakeProperty; import org.apache.gravitino.cli.commands.SetSchemaProperty; +import org.apache.gravitino.cli.commands.SetTagProperty; import org.apache.gravitino.cli.commands.TableDetails; +import org.apache.gravitino.cli.commands.TagDetails; +import org.apache.gravitino.cli.commands.TagEntity; +import org.apache.gravitino.cli.commands.UntagEntity; import org.apache.gravitino.cli.commands.UpdateCatalogComment; import org.apache.gravitino.cli.commands.UpdateCatalogName; import org.apache.gravitino.cli.commands.UpdateMetalakeComment; import org.apache.gravitino.cli.commands.UpdateMetalakeName; +import org.apache.gravitino.cli.commands.UpdateTagComment; +import org.apache.gravitino.cli.commands.UpdateTagName; import org.apache.gravitino.cli.commands.UserDetails; /* Gravitino Command line */ @@ -135,6 +146,8 @@ private void executeCommand() { handleUserCommand(); } else if (entity.equals(CommandEntities.GROUP)) { handleGroupCommand(); + } else if (entity.equals(CommandEntities.TAG)) { + handleTagCommand(); } } else { handleGeneralCommand(); @@ -335,6 +348,51 @@ protected void handleGroupCommand() { } } + /** Handles the command execution for Tags based on command type and the command line options. */ + protected void handleTagCommand() { + String url = getUrl(); + FullName name = new FullName(line); + String metalake = name.getMetalakeName(); + String tag = line.getOptionValue(GravitinoOptions.TAG); + + if (CommandActions.DETAILS.equals(command)) { + new TagDetails(url, metalake, tag).handle(); + } else if (CommandActions.LIST.equals(command)) { + new ListTags(url, metalake).handle(); + } else if (CommandActions.CREATE.equals(command)) { + String comment = line.getOptionValue(GravitinoOptions.COMMENT); + new CreateTag(url, metalake, tag, comment).handle(); + } else if (CommandActions.DELETE.equals(command)) { + new DeleteTag(url, metalake, tag).handle(); + } else if (CommandActions.SET.equals(command)) { + String property = line.getOptionValue(GravitinoOptions.PROPERTY); + String value = line.getOptionValue(GravitinoOptions.VALUE); + if (property != null && value != null) { + new SetTagProperty(url, metalake, tag, property, value).handle(); + } else { + new TagEntity(url, metalake, name, tag).handle(); + } + } else if (CommandActions.REMOVE.equals(command)) { + String property = line.getOptionValue(GravitinoOptions.PROPERTY); + if (property != null) { + new RemoveTagProperty(url, metalake, tag, property).handle(); + } else { + new UntagEntity(url, metalake, name, tag).handle(); + } + } else if (CommandActions.PROPERTIES.equals(command)) { + new ListTagProperties(url, metalake, tag).handle(); + } else if (CommandActions.UPDATE.equals(command)) { + if (line.hasOption(GravitinoOptions.COMMENT)) { + String comment = line.getOptionValue(GravitinoOptions.COMMENT); + new UpdateTagComment(url, metalake, tag, comment).handle(); + } + if (line.hasOption(GravitinoOptions.RENAME)) { + String newName = line.getOptionValue(GravitinoOptions.RENAME); + new UpdateTagName(url, metalake, tag, newName).handle(); + } + } + } + /** Handles the command execution based on command type and the command line options. */ protected void handleGeneralCommand() { String url = getUrl(); 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 ef02481124c..5d14f29f6ed 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 @@ -54,6 +54,7 @@ public class GravitinoOptions { public static final String DATABASE = "database"; public static final String BOOTSTRAP = "bootstrap"; public static final String GROUP = "group"; + public static final String TAG = "tag"; /** * Builds and returns the CLI options for Gravitino. @@ -103,6 +104,7 @@ public Options options() { options.addOption(createArgOption("p", PASSWORD, "database password")); options.addOption(createArgOption("d", DATABASE, "database name")); options.addOption(createArgOption("g", GROUP, "group name")); + options.addOption(createArgOption("t", TAG, "tag name")); return options; } 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 new file mode 100644 index 00000000000..022daccdae3 --- /dev/null +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/CreateTag.java @@ -0,0 +1,65 @@ +/* + * 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.cli.ErrorMessages; +import org.apache.gravitino.client.GravitinoClient; +import org.apache.gravitino.exceptions.NoSuchMetalakeException; +import org.apache.gravitino.exceptions.TagAlreadyExistsException; + +public class CreateTag extends Command { + protected String metalake; + protected String tag; + protected String comment; + + /** + * Create a new tag. + * + * @param url The URL of the Gravitino server. + * @param metalake The name of the metalake. + * @param tag The name of the tag. + * @param comment The comment of the tag. + */ + public CreateTag(String url, String metalake, String tag, String comment) { + super(url); + this.metalake = metalake; + this.tag = tag; + this.comment = comment; + } + + /** Create a new tag. */ + public void handle() { + try { + GravitinoClient client = buildClient(metalake); + client.createTag(tag, comment, null); + } catch (NoSuchMetalakeException err) { + System.err.println(ErrorMessages.UNKNOWN_METALAKE); + return; + } catch (TagAlreadyExistsException err) { + System.err.println(ErrorMessages.TAG_EXISTS); + return; + } catch (Exception exp) { + System.err.println(exp.getMessage()); + return; + } + + System.out.println(tag + " 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 new file mode 100644 index 00000000000..7b717f3d0a7 --- /dev/null +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/DeleteTag.java @@ -0,0 +1,69 @@ +/* + * 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.cli.ErrorMessages; +import org.apache.gravitino.client.GravitinoClient; +import org.apache.gravitino.exceptions.NoSuchMetalakeException; +import org.apache.gravitino.exceptions.NoSuchTagException; + +public class DeleteTag extends Command { + + protected String metalake; + protected String tag; + + /** + * Delete a tag. + * + * @param url The URL of the Gravitino server. + * @param metalake The name of the metalake. + * @param tag The name of the tag. + */ + public DeleteTag(String url, String metalake, String tag) { + super(url); + this.metalake = metalake; + this.tag = tag; + } + + /** Delete a catalog. */ + public void handle() { + boolean deleted = false; + + try { + GravitinoClient client = buildClient(metalake); + deleted = client.deleteTag(tag); + } catch (NoSuchMetalakeException err) { + System.err.println(ErrorMessages.UNKNOWN_METALAKE); + return; + } catch (NoSuchTagException err) { + System.err.println(ErrorMessages.UNKNOWN_TAG); + return; + } catch (Exception exp) { + System.err.println(exp.getMessage()); + return; + } + + if (deleted) { + System.out.println(tag + " deleted."); + } else { + System.out.println(tag + " not deleted."); + } + } +} 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 new file mode 100644 index 00000000000..7f0f48c18eb --- /dev/null +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListTagProperties.java @@ -0,0 +1,68 @@ +/* + * 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 java.util.Map; +import org.apache.gravitino.cli.ErrorMessages; +import org.apache.gravitino.client.GravitinoClient; +import org.apache.gravitino.exceptions.NoSuchMetalakeException; +import org.apache.gravitino.exceptions.NoSuchTagException; +import org.apache.gravitino.tag.Tag; + +/** List the properties of a tag. */ +public class ListTagProperties extends ListProperties { + + protected String metalake; + protected String tag; + + /** + * List the properties of a tag. + * + * @param url The URL of the Gravitino server. + * @param metalake The name of the metalake. + * @param tag The name of the tag. + */ + public ListTagProperties(String url, String metalake, String tag) { + super(url); + this.metalake = metalake; + this.tag = tag; + } + + /** List the properties of a tag. */ + public void handle() { + Tag gTag = null; + try { + GravitinoClient client = buildClient(metalake); + gTag = client.getTag(tag); + } catch (NoSuchMetalakeException err) { + System.err.println(ErrorMessages.UNKNOWN_METALAKE); + return; + } catch (NoSuchTagException err) { + System.err.println(ErrorMessages.UNKNOWN_TAG); + return; + } catch (Exception exp) { + System.err.println(exp.getMessage()); + return; + } + + Map properties = gTag.properties(); + printProperties(properties); + } +} diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListTags.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListTags.java new file mode 100644 index 00000000000..1ef2d8491af --- /dev/null +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListTags.java @@ -0,0 +1,66 @@ +/* + * 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.cli.ErrorMessages; +import org.apache.gravitino.client.GravitinoClient; +import org.apache.gravitino.exceptions.NoSuchMetalakeException; + +/* Lists all tags in a metalake. */ +public class ListTags extends Command { + + protected String metalake; + + /** + * Lists all tags in a metalake. + * + * @param url The URL of the Gravitino server. + * @param metalake The name of the metalake. + */ + public ListTags(String url, String metalake) { + super(url); + this.metalake = metalake; + } + + /** Lists all tags in a metalake. */ + public void handle() { + String[] tags = new String[0]; + try { + GravitinoClient client = buildClient(metalake); + tags = client.listTags(); + } catch (NoSuchMetalakeException err) { + System.err.println(ErrorMessages.UNKNOWN_METALAKE); + return; + } catch (Exception exp) { + System.err.println(exp.getMessage()); + return; + } + + StringBuilder all = new StringBuilder(); + for (int i = 0; i < tags.length; i++) { + if (i > 0) { + all.append(","); + } + all.append(tags[i]); + } + + System.out.println(all.toString()); + } +} 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 new file mode 100644 index 00000000000..8a815b38e51 --- /dev/null +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RemoveTagProperty.java @@ -0,0 +1,69 @@ +/* + * 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.cli.ErrorMessages; +import org.apache.gravitino.client.GravitinoClient; +import org.apache.gravitino.exceptions.NoSuchMetalakeException; +import org.apache.gravitino.exceptions.NoSuchTagException; +import org.apache.gravitino.tag.TagChange; + +/** Remove a property of a tag. */ +public class RemoveTagProperty extends Command { + + protected String metalake; + protected String tag; + protected String property; + + /** + * Remove a property of a tag. + * + * @param url The URL of the Gravitino server. + * @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, String metalake, String tag, String property) { + super(url); + this.metalake = metalake; + this.tag = tag; + this.property = property; + } + + /** Remove a property of a catalog. */ + public void handle() { + try { + GravitinoClient client = buildClient(metalake); + TagChange change = TagChange.removeProperty(property); + client.alterTag(tag, change); + } catch (NoSuchMetalakeException err) { + System.err.println(ErrorMessages.UNKNOWN_METALAKE); + return; + } catch (NoSuchTagException err) { + System.err.println(ErrorMessages.UNKNOWN_TAG); + return; + } catch (Exception exp) { + System.err.println(exp.getMessage()); + return; + } + + System.out.println(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 new file mode 100644 index 00000000000..4383a4c3fd2 --- /dev/null +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/SetTagProperty.java @@ -0,0 +1,72 @@ +/* + * 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.cli.ErrorMessages; +import org.apache.gravitino.client.GravitinoClient; +import org.apache.gravitino.exceptions.NoSuchMetalakeException; +import org.apache.gravitino.exceptions.NoSuchTagException; +import org.apache.gravitino.tag.TagChange; + +/** Set a property of a tag. */ +public class SetTagProperty extends Command { + + protected String metalake; + protected String tag; + protected String property; + protected String value; + + /** + * Set a property of a tag. + * + * @param url The URL of the Gravitino server. + * @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, String metalake, String tag, String property, String value) { + super(url); + this.metalake = metalake; + this.tag = tag; + this.property = property; + this.value = value; + } + + /** Set a property of a tag. */ + public void handle() { + try { + GravitinoClient client = buildClient(metalake); + TagChange change = TagChange.setProperty(property, value); + client.alterTag(tag, change); + } catch (NoSuchMetalakeException err) { + System.err.println(ErrorMessages.UNKNOWN_METALAKE); + return; + } catch (NoSuchTagException err) { + System.err.println(ErrorMessages.UNKNOWN_TAG); + return; + } catch (Exception exp) { + System.err.println(exp.getMessage()); + return; + } + + System.out.println(tag + " property set."); + } +} 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 new file mode 100644 index 00000000000..63db84608ce --- /dev/null +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/TagDetails.java @@ -0,0 +1,68 @@ +/* + * 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.cli.ErrorMessages; +import org.apache.gravitino.client.GravitinoClient; +import org.apache.gravitino.exceptions.NoSuchCatalogException; +import org.apache.gravitino.exceptions.NoSuchMetalakeException; +import org.apache.gravitino.tag.Tag; + +public class TagDetails extends Command { + + protected String metalake; + protected String tag; + + /** + * Displays the name and comment of a catalog. + * + * @param url The URL of the Gravitino server. + * @param metalake The name of the metalake. + * @param tag The name of the tag. + */ + public TagDetails(String url, String metalake, String tag) { + super(url); + this.metalake = metalake; + this.tag = tag; + } + + /** Displays the name and details of a specified tag. */ + public void handle() { + Tag result = null; + + try { + GravitinoClient client = buildClient(metalake); + result = client.getTag(tag); + } catch (NoSuchMetalakeException err) { + System.err.println(ErrorMessages.UNKNOWN_METALAKE); + return; + } catch (NoSuchCatalogException err) { + System.err.println(ErrorMessages.UNKNOWN_CATALOG); + return; + } catch (Exception exp) { + System.err.println(exp.getMessage()); + return; + } + + if (result != null) { + System.out.println(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 new file mode 100644 index 00000000000..1b5e7034446 --- /dev/null +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/TagEntity.java @@ -0,0 +1,100 @@ +/* + * 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.Catalog; +import org.apache.gravitino.NameIdentifier; +import org.apache.gravitino.Schema; +import org.apache.gravitino.cli.ErrorMessages; +import org.apache.gravitino.cli.FullName; +import org.apache.gravitino.client.GravitinoClient; +import org.apache.gravitino.exceptions.NoSuchCatalogException; +import org.apache.gravitino.exceptions.NoSuchMetalakeException; +import org.apache.gravitino.exceptions.NoSuchTableException; +import org.apache.gravitino.rel.Table; + +public class TagEntity extends Command { + protected String metalake; + protected FullName name; + protected String tag; + + /** + * Tag an entity with an existing tag. + * + * @param url The URL of the Gravitino server. + * @param metalake The name of the metalake. + * @param name The name of the entity. + * @param tag The name of the tag. + */ + public TagEntity(String url, String metalake, FullName name, String tag) { + super(url); + this.metalake = metalake; + this.name = name; + this.tag = tag; + } + + /** Create a new tag. */ + public void handle() { + String entity = "unknown"; + + try { + GravitinoClient client = buildClient(metalake); + + // TODO fileset and topic + if (name.hasTableName()) { + String catalog = name.getCatalogName(); + String schema = name.getSchemaName(); + String table = name.getTableName(); + Table gTable = + client + .loadCatalog(catalog) + .asTableCatalog() + .loadTable(NameIdentifier.of(schema, table)); + gTable.supportsTags().associateTags(new String[] {tag}, null); + entity = table; + } else if (name.hasSchemaName()) { + String catalog = name.getCatalogName(); + String schema = name.getSchemaName(); + Schema gSchema = client.loadCatalog(catalog).asSchemas().loadSchema(schema); + gSchema.supportsTags().associateTags(new String[] {tag}, null); + entity = schema; + } else if (name.hasCatalogName()) { + String catalog = name.getCatalogName(); + Catalog gCatalog = client.loadCatalog(catalog); + gCatalog.supportsTags().associateTags(new String[] {tag}, null); + entity = catalog; + } + } catch (NoSuchMetalakeException err) { + System.err.println(ErrorMessages.UNKNOWN_METALAKE); + return; + } catch (NoSuchCatalogException err) { + System.err.println(ErrorMessages.UNKNOWN_CATALOG); + return; + } catch (NoSuchTableException err) { + System.err.println(ErrorMessages.UNKNOWN_TABLE); + return; + } catch (Exception exp) { + System.err.println(exp.getMessage()); + return; + } + + System.out.println(entity + " tagged"); + } +} 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 new file mode 100644 index 00000000000..c78939233f3 --- /dev/null +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UntagEntity.java @@ -0,0 +1,100 @@ +/* + * 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.Catalog; +import org.apache.gravitino.NameIdentifier; +import org.apache.gravitino.Schema; +import org.apache.gravitino.cli.ErrorMessages; +import org.apache.gravitino.cli.FullName; +import org.apache.gravitino.client.GravitinoClient; +import org.apache.gravitino.exceptions.NoSuchCatalogException; +import org.apache.gravitino.exceptions.NoSuchMetalakeException; +import org.apache.gravitino.exceptions.NoSuchTableException; +import org.apache.gravitino.rel.Table; + +public class UntagEntity extends Command { + protected String metalake; + protected FullName name; + protected String tag; + + /** + * Untag an entity with an existing tag. + * + * @param url The URL of the Gravitino server. + * @param metalake The name of the metalake. + * @param name The name of the entity. + * @param tag The name of the tag. + */ + public UntagEntity(String url, String metalake, FullName name, String tag) { + super(url); + this.metalake = metalake; + this.name = name; + this.tag = tag; + } + + /** Create a new tag. */ + public void handle() { + String entity = "unknown"; + + try { + GravitinoClient client = buildClient(metalake); + + // TODO fileset and topic + if (name.hasTableName()) { + String catalog = name.getCatalogName(); + String schema = name.getSchemaName(); + String table = name.getTableName(); + Table gTable = + client + .loadCatalog(catalog) + .asTableCatalog() + .loadTable(NameIdentifier.of(schema, table)); + gTable.supportsTags().associateTags(null, new String[] {tag}); + entity = table; + } else if (name.hasSchemaName()) { + String catalog = name.getCatalogName(); + String schema = name.getSchemaName(); + Schema gSchema = client.loadCatalog(catalog).asSchemas().loadSchema(schema); + gSchema.supportsTags().associateTags(null, new String[] {tag}); + entity = schema; + } else if (name.hasCatalogName()) { + String catalog = name.getCatalogName(); + Catalog gCatalog = client.loadCatalog(catalog); + gCatalog.supportsTags().associateTags(null, new String[] {tag}); + entity = catalog; + } + } catch (NoSuchMetalakeException err) { + System.err.println(ErrorMessages.UNKNOWN_METALAKE); + return; + } catch (NoSuchCatalogException err) { + System.err.println(ErrorMessages.UNKNOWN_CATALOG); + return; + } catch (NoSuchTableException err) { + System.err.println(ErrorMessages.UNKNOWN_TABLE); + return; + } catch (Exception exp) { + System.err.println(exp.getMessage()); + return; + } + + System.out.println(entity + " untagged"); + } +} 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 34722b19b6f..ff500515bfd 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 @@ -22,6 +22,7 @@ import org.apache.gravitino.CatalogChange; import org.apache.gravitino.cli.ErrorMessages; import org.apache.gravitino.client.GravitinoClient; +import org.apache.gravitino.exceptions.NoSuchCatalogException; import org.apache.gravitino.exceptions.NoSuchMetalakeException; /** Update the name of a catalog. */ @@ -55,6 +56,9 @@ public void handle() { } catch (NoSuchMetalakeException err) { System.err.println(ErrorMessages.UNKNOWN_METALAKE); return; + } catch (NoSuchCatalogException err) { + System.err.println(ErrorMessages.UNKNOWN_CATALOG); + return; } catch (Exception exp) { System.err.println(exp.getMessage()); return; 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 new file mode 100644 index 00000000000..29e6e84c9ee --- /dev/null +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateTagComment.java @@ -0,0 +1,69 @@ +/* + * 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.cli.ErrorMessages; +import org.apache.gravitino.client.GravitinoClient; +import org.apache.gravitino.exceptions.NoSuchMetalakeException; +import org.apache.gravitino.exceptions.NoSuchTagException; +import org.apache.gravitino.tag.TagChange; + +/** Update the comment of a tag. */ +public class UpdateTagComment extends Command { + + protected String metalake; + protected String tag; + protected String comment; + + /** + * Update the comment of a tag. + * + * @param url The URL of the Gravitino server. + * @param metalake The name of the metalake. + * @param tag The name of the tag. + * @param comment New metalake comment. + */ + public UpdateTagComment(String url, String metalake, String tag, String comment) { + super(url); + this.metalake = metalake; + this.tag = tag; + this.comment = comment; + } + + /** Update the comment of a tag. */ + public void handle() { + try { + GravitinoClient client = buildClient(metalake); + TagChange change = TagChange.updateComment(comment); + client.alterTag(tag, change); + } catch (NoSuchMetalakeException err) { + System.err.println(ErrorMessages.UNKNOWN_METALAKE); + return; + } catch (NoSuchTagException err) { + System.err.println(ErrorMessages.UNKNOWN_TAG); + return; + } catch (Exception exp) { + System.err.println(exp.getMessage()); + return; + } + + System.out.println(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 new file mode 100644 index 00000000000..b66751ed9d2 --- /dev/null +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UpdateTagName.java @@ -0,0 +1,69 @@ +/* + * 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.cli.ErrorMessages; +import org.apache.gravitino.client.GravitinoClient; +import org.apache.gravitino.exceptions.NoSuchMetalakeException; +import org.apache.gravitino.exceptions.NoSuchTagException; +import org.apache.gravitino.tag.TagChange; + +/** Update the name of a tag. */ +public class UpdateTagName extends Command { + + protected String metalake; + protected String tag; + protected String name; + + /** + * Update the name of a tag. + * + * @param url The URL of the Gravitino server. + * @param metalake The name of the tag. + * @param tag The name of the catalog. + * @param name The new metalake name. + */ + public UpdateTagName(String url, String metalake, String tag, String name) { + super(url); + this.metalake = metalake; + this.tag = tag; + this.name = name; + } + + /** Update the name of a catalog. */ + public void handle() { + try { + GravitinoClient client = buildClient(metalake); + TagChange change = TagChange.rename(name); + client.alterTag(tag, change); + } catch (NoSuchMetalakeException err) { + System.err.println(ErrorMessages.UNKNOWN_METALAKE); + return; + } catch (NoSuchTagException err) { + System.err.println(ErrorMessages.UNKNOWN_TAG); + return; + } catch (Exception exp) { + System.err.println(exp.getMessage()); + return; + } + + System.out.println(tag + " name changed."); + } +} diff --git a/clients/cli/src/test/java/org/apache/gravitino/cli/TestCommandEntities.java b/clients/cli/src/test/java/org/apache/gravitino/cli/TestCommandEntities.java index 5290f89055a..6feddde7d7d 100644 --- a/clients/cli/src/test/java/org/apache/gravitino/cli/TestCommandEntities.java +++ b/clients/cli/src/test/java/org/apache/gravitino/cli/TestCommandEntities.java @@ -41,6 +41,7 @@ public void validEntities() { CommandEntities.isValidEntity(CommandEntities.USER), "USER should be a valid entity"); assertTrue( CommandEntities.isValidEntity(CommandEntities.GROUP), "GROUP should be a valid entity"); + assertTrue(CommandEntities.isValidEntity(CommandEntities.TAG), "TAG should be a valid entity"); } @Test diff --git a/clients/cli/src/test/java/org/apache/gravitino/cli/TestFulllName.java b/clients/cli/src/test/java/org/apache/gravitino/cli/TestFulllName.java index 448ab2dbf6c..2afeec7ed80 100644 --- a/clients/cli/src/test/java/org/apache/gravitino/cli/TestFulllName.java +++ b/clients/cli/src/test/java/org/apache/gravitino/cli/TestFulllName.java @@ -18,8 +18,10 @@ */ import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.DefaultParser; @@ -139,4 +141,48 @@ public void missingName() throws Exception { String namePart = fullName.getNamePart(GravitinoOptions.TABLE, 3); assertNull(namePart); } + + @Test + public void hasPartNameMetalake() throws Exception { + String[] args = {"metalake", "details", "--name", "metalake"}; + CommandLine commandLine = new DefaultParser().parse(options, args); + FullName fullName = new FullName(commandLine); + assertTrue(fullName.hasMetalakeName()); + assertFalse(fullName.hasCatalogName()); + assertFalse(fullName.hasSchemaName()); + assertFalse(fullName.hasTableName()); + } + + @Test + public void hasPartNameCatalog() throws Exception { + String[] args = {"catalog", "details", "--name", "metalake.catalog"}; + CommandLine commandLine = new DefaultParser().parse(options, args); + FullName fullName = new FullName(commandLine); + assertTrue(fullName.hasMetalakeName()); + assertTrue(fullName.hasCatalogName()); + assertFalse(fullName.hasSchemaName()); + assertFalse(fullName.hasTableName()); + } + + @Test + public void hasPartNameSchema() throws Exception { + String[] args = {"schema", "details", "--name", "metalake.catalog.schema"}; + CommandLine commandLine = new DefaultParser().parse(options, args); + FullName fullName = new FullName(commandLine); + assertTrue(fullName.hasMetalakeName()); + assertTrue(fullName.hasCatalogName()); + assertTrue(fullName.hasSchemaName()); + assertFalse(fullName.hasTableName()); + } + + @Test + public void hasPartNameTable() throws Exception { + String[] args = {"table", "details", "--name", "metalake.catalog.schema.table"}; + CommandLine commandLine = new DefaultParser().parse(options, args); + FullName fullName = new FullName(commandLine); + assertTrue(fullName.hasMetalakeName()); + assertTrue(fullName.hasCatalogName()); + assertTrue(fullName.hasSchemaName()); + assertTrue(fullName.hasTableName()); + } } From b3f081a4b8475222dd36a0b5b009b21d8afa9d67 Mon Sep 17 00:00:00 2001 From: Justin Mclean Date: Tue, 15 Oct 2024 12:42:02 -0700 Subject: [PATCH 2/3] complete tag CLI --- clients/cli/examples.sh | 56 +++++---- .../org/apache/gravitino/cli/FullName.java | 10 +- .../gravitino/cli/GravitinoCommandLine.java | 9 +- .../java/org/apache/gravitino/cli/Main.java | 5 + .../{ListTags.java => ListAllTags.java} | 4 +- .../cli/commands/ListEntityTags.java | 107 ++++++++++++++++++ .../gravitino/cli/commands/TagEntity.java | 21 +++- .../gravitino/cli/commands/UntagEntity.java | 21 +++- 8 files changed, 190 insertions(+), 43 deletions(-) rename clients/cli/src/main/java/org/apache/gravitino/cli/commands/{ListTags.java => ListAllTags.java} (95%) create mode 100644 clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListEntityTags.java diff --git a/clients/cli/examples.sh b/clients/cli/examples.sh index 23ce348026e..cc2d6cc5a22 100755 --- a/clients/cli/examples.sh +++ b/clients/cli/examples.sh @@ -112,6 +112,33 @@ gcli schema remove --name metalake_demo.catalog_postgres.hr --property test # no # Table operations gcli table delete -name metalake_demo.catalog_postgres.hr.salaries +# User examples +gcli user create --name metalake_demo --user new_user +gcli user details --name metalake_demo --user new_user +gcli user list --name metalake_demo +gcli user delete --name metalake_demo --user new_user + +# Group examples +gcli group create --name metalake_demo --user new_group +gcli group details --name metalake_demo --user new_group +gcli group list --name metalake_demo +gcli group delete --name metalake_demo --user new_group + +# Tag examples +gcli tag create --name metalake_demo --tag tagA +gcli tag details --name metalake_demo --tag tagA +gcli tag list --name metalake_demo # all tags in a metalake +gcli tag delete --name metalake_demo --tag tagA +gcli tag update --name metalake_demo --tag tagA --rename new_tag +gcli tag update --name metalake_demo --tag tagA --comment "new comment" +gcli tag properties --name metalake_demo --tag tagA +gcli tag set --name metalake_demo --tag tagA --property color --value green +gcli tag remove --name metalake_demo --tag tagA --property color +gcli tag create --name metalake_demo --tag hr +gcli tag set --name metalake_demo.catalog_postgres.hr --tag hr # tag entity +gcli tag remove --name metalake_demo.catalog_postgres.hr --tag hr # untag entity +gcli tag list --name metalake_demo.catalog_postgres.hr # all tags hr has been taged with + # Exmaples where metalake is set in an evironment variable export GRAVITINO_METALAKE=metalake_demo @@ -147,32 +174,3 @@ gcli schema details --name catalog_hive.sales gcli table list --name catalog_postgres.hr.departments gcli table list --name catalog_mysql.db.iceberg_tables gcli table list --name catalog_hive.sales.products - -# User examples -gcli user create --name metalake_demo --user new_user -gcli user details --name metalake_demo --user new_user -gcli user list --name metalake_demo -gcli user delete --name metalake_demo --user new_user - -# Group examples -gcli group create --name metalake_demo --user new_group -gcli group details --name metalake_demo --user new_group -gcli group list --name metalake_demo -gcli group delete --name metalake_demo --user new_group - -# Tag examples -gcli tag create --name metalake_demo --tag tagA -gcli tag details --name metalake_demo --tag tagA -gcli tag list --name metalake_demo # all tags in a metalake -gcli tag delete --name metalake_demo --tag tagA -gcli tag update --name metalake_demo --tag tagA --rename new_tag -gcli tag update --name metalake_demo --tag tagA --comment "new comment" -gcli tag properties --name metalake_demo --tag tagA -gcli tag set --name metalake_demo --tag tagA --property color --value green -gcli tag remove --name metalake_demo --tag tagA --property color -gcli tag create --name metalake_demo --tag hr -gcli tag set --name metalake_demo.catalog_postgres.hr --tag hr # tag entity -gcli tag remove --name metalake_demo.catalog_postgres.hr --tag hr # untag entity - -gcli tag list --name metalake_demo.catalog_postgres.hr # all tags hr has been taged with -gcli tag list --tag tagA --name metalake_demo # all objects with tagA diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/FullName.java b/clients/cli/src/main/java/org/apache/gravitino/cli/FullName.java index ecae6c7c437..0fe85026dec 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/FullName.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/FullName.java @@ -19,6 +19,7 @@ package org.apache.gravitino.cli; +import java.util.Arrays; import org.apache.commons.cli.CommandLine; /** @@ -149,8 +150,13 @@ public boolean hasNamePart(String entity) { } else if (line.hasOption(GravitinoOptions.NAME)) { String[] names = line.getOptionValue(GravitinoOptions.NAME).split("\\."); int length = names.length; - String [] order = {GravitinoOptions.METALAKE, GravitinoOptions.CATALOG,GravitinoOptions.SCHEMA,GravitinoOptions.TABLE}; - int position = order.indexOf(entity); + String[] order = { + GravitinoOptions.METALAKE, + GravitinoOptions.CATALOG, + GravitinoOptions.SCHEMA, + GravitinoOptions.TABLE + }; + int position = Arrays.asList(order).indexOf(entity); /* Adjust position if metalake is part of the full name. */ if (metalakeEnv != null) { 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 938dbdaf390..a909c08a4f0 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 @@ -44,9 +44,11 @@ import org.apache.gravitino.cli.commands.DeleteTag; import org.apache.gravitino.cli.commands.DeleteUser; import org.apache.gravitino.cli.commands.GroupDetails; +import org.apache.gravitino.cli.commands.ListAllTags; import org.apache.gravitino.cli.commands.ListCatalogProperties; import org.apache.gravitino.cli.commands.ListCatalogs; import org.apache.gravitino.cli.commands.ListColumns; +import org.apache.gravitino.cli.commands.ListEntityTags; import org.apache.gravitino.cli.commands.ListGroups; import org.apache.gravitino.cli.commands.ListMetalakeProperties; import org.apache.gravitino.cli.commands.ListMetalakes; @@ -54,7 +56,6 @@ 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.ListTags; import org.apache.gravitino.cli.commands.ListUsers; import org.apache.gravitino.cli.commands.MetalakeDetails; import org.apache.gravitino.cli.commands.RemoveCatalogProperty; @@ -358,7 +359,11 @@ protected void handleTagCommand() { if (CommandActions.DETAILS.equals(command)) { new TagDetails(url, metalake, tag).handle(); } else if (CommandActions.LIST.equals(command)) { - new ListTags(url, metalake).handle(); + if (name.hasMetalakeName() && !name.hasCatalogName()) { + new ListAllTags(url, metalake).handle(); + } else { + new ListEntityTags(url, metalake, name).handle(); + } } else if (CommandActions.CREATE.equals(command)) { String comment = line.getOptionValue(GravitinoOptions.COMMENT); new CreateTag(url, metalake, tag, comment).handle(); diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/Main.java b/clients/cli/src/main/java/org/apache/gravitino/cli/Main.java index 62196c2368b..c9853ca970a 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/Main.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/Main.java @@ -122,6 +122,11 @@ protected static String resolveEntity(CommandLine line, boolean command) { /* Or as the bare first argument of one or two arguments. */ String[] args = line.getArgs(); + + if (args.length == 0) { + return null; + } + String entity = args[0]; if (args.length == 1) { diff --git a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListTags.java b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListAllTags.java similarity index 95% rename from clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListTags.java rename to clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListAllTags.java index 1ef2d8491af..967d77096f6 100644 --- a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListTags.java +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListAllTags.java @@ -24,7 +24,7 @@ import org.apache.gravitino.exceptions.NoSuchMetalakeException; /* Lists all tags in a metalake. */ -public class ListTags extends Command { +public class ListAllTags extends Command { protected String metalake; @@ -34,7 +34,7 @@ public class ListTags extends Command { * @param url The URL of the Gravitino server. * @param metalake The name of the metalake. */ - public ListTags(String url, String metalake) { + public ListAllTags(String url, String metalake) { super(url); this.metalake = metalake; } 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 new file mode 100644 index 00000000000..2de2eb8da5b --- /dev/null +++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListEntityTags.java @@ -0,0 +1,107 @@ +/* + * 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.Catalog; +import org.apache.gravitino.NameIdentifier; +import org.apache.gravitino.Schema; +import org.apache.gravitino.cli.ErrorMessages; +import org.apache.gravitino.cli.FullName; +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.rel.Table; + +/* Lists all tags in a metalake. */ +public class ListEntityTags extends Command { + + protected String metalake; + protected FullName name; + + /** + * Lists all tags in a metalake. + * + * @param url The URL of the Gravitino server. + * @param metalake The name of the metalake. + * @param name The name of the entity. + */ + public ListEntityTags(String url, String metalake, FullName name) { + super(url); + this.metalake = metalake; + this.name = name; + } + + /** Lists all tags in a metalake. */ + public void handle() { + String[] tags = new String[0]; + try { + GravitinoClient client = buildClient(metalake); + + // TODO fileset and topic + if (name.hasTableName()) { + 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(); + } else if (name.hasSchemaName()) { + String catalog = name.getCatalogName(); + String schema = name.getSchemaName(); + Schema gSchema = client.loadCatalog(catalog).asSchemas().loadSchema(schema); + tags = gSchema.supportsTags().listTags(); + } else if (name.hasCatalogName()) { + String catalog = name.getCatalogName(); + Catalog gCatalog = client.loadCatalog(catalog); + tags = gCatalog.supportsTags().listTags(); + } + } catch (NoSuchMetalakeException err) { + System.err.println(ErrorMessages.UNKNOWN_METALAKE); + return; + } catch (NoSuchCatalogException err) { + System.err.println(ErrorMessages.UNKNOWN_CATALOG); + return; + } catch (NoSuchSchemaException err) { + System.err.println(ErrorMessages.UNKNOWN_SCHEMA); + return; + } catch (NoSuchTableException err) { + System.err.println(ErrorMessages.UNKNOWN_TABLE); + return; + } catch (Exception exp) { + System.err.println(exp.getMessage()); + return; + } + + StringBuilder all = new StringBuilder(); + for (int i = 0; i < tags.length; i++) { + if (i > 0) { + all.append(","); + } + all.append(tags[i]); + } + + System.out.println(all.toString()); + } +} 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 1b5e7034446..84885fd62b6 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 @@ -27,6 +27,7 @@ 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.rel.Table; @@ -53,6 +54,7 @@ public TagEntity(String url, String metalake, FullName name, String tag) { /** Create a new tag. */ public void handle() { String entity = "unknown"; + String[] tags = new String[0]; try { GravitinoClient client = buildClient(metalake); @@ -67,18 +69,18 @@ public void handle() { .loadCatalog(catalog) .asTableCatalog() .loadTable(NameIdentifier.of(schema, table)); - gTable.supportsTags().associateTags(new String[] {tag}, null); + tags = gTable.supportsTags().associateTags(new String[] {tag}, null); entity = table; } else if (name.hasSchemaName()) { String catalog = name.getCatalogName(); String schema = name.getSchemaName(); Schema gSchema = client.loadCatalog(catalog).asSchemas().loadSchema(schema); - gSchema.supportsTags().associateTags(new String[] {tag}, null); + tags = gSchema.supportsTags().associateTags(new String[] {tag}, null); entity = schema; } else if (name.hasCatalogName()) { String catalog = name.getCatalogName(); Catalog gCatalog = client.loadCatalog(catalog); - gCatalog.supportsTags().associateTags(new String[] {tag}, null); + tags = gCatalog.supportsTags().associateTags(new String[] {tag}, null); entity = catalog; } } catch (NoSuchMetalakeException err) { @@ -87,6 +89,9 @@ public void handle() { } catch (NoSuchCatalogException err) { System.err.println(ErrorMessages.UNKNOWN_CATALOG); return; + } catch (NoSuchSchemaException err) { + System.err.println(ErrorMessages.UNKNOWN_SCHEMA); + return; } catch (NoSuchTableException err) { System.err.println(ErrorMessages.UNKNOWN_TABLE); return; @@ -95,6 +100,14 @@ public void handle() { return; } - System.out.println(entity + " tagged"); + StringBuilder all = new StringBuilder(); + for (int i = 0; i < tags.length; i++) { + if (i > 0) { + all.append(","); + } + all.append(tags[i]); + } + + System.out.println(entity + " tagged with " + all); } } 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 c78939233f3..c47929ad445 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 @@ -27,6 +27,7 @@ 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.rel.Table; @@ -53,6 +54,7 @@ public UntagEntity(String url, String metalake, FullName name, String tag) { /** Create a new tag. */ public void handle() { String entity = "unknown"; + String[] tags = new String[0]; try { GravitinoClient client = buildClient(metalake); @@ -67,18 +69,18 @@ public void handle() { .loadCatalog(catalog) .asTableCatalog() .loadTable(NameIdentifier.of(schema, table)); - gTable.supportsTags().associateTags(null, new String[] {tag}); + tags = gTable.supportsTags().associateTags(null, new String[] {tag}); entity = table; } else if (name.hasSchemaName()) { String catalog = name.getCatalogName(); String schema = name.getSchemaName(); Schema gSchema = client.loadCatalog(catalog).asSchemas().loadSchema(schema); - gSchema.supportsTags().associateTags(null, new String[] {tag}); + tags = gSchema.supportsTags().associateTags(null, new String[] {tag}); entity = schema; } else if (name.hasCatalogName()) { String catalog = name.getCatalogName(); Catalog gCatalog = client.loadCatalog(catalog); - gCatalog.supportsTags().associateTags(null, new String[] {tag}); + tags = gCatalog.supportsTags().associateTags(null, new String[] {tag}); entity = catalog; } } catch (NoSuchMetalakeException err) { @@ -87,6 +89,9 @@ public void handle() { } catch (NoSuchCatalogException err) { System.err.println(ErrorMessages.UNKNOWN_CATALOG); return; + } catch (NoSuchSchemaException err) { + System.err.println(ErrorMessages.UNKNOWN_TABLE); + return; } catch (NoSuchTableException err) { System.err.println(ErrorMessages.UNKNOWN_TABLE); return; @@ -95,6 +100,14 @@ public void handle() { return; } - System.out.println(entity + " untagged"); + StringBuilder all = new StringBuilder(); + for (int i = 0; i < tags.length; i++) { + if (i > 0) { + all.append(","); + } + all.append(tags[i]); + } + + System.out.println(entity + " untagged, tagged with " + all); } } From 29c9222fd08e8253b71f2e45c7c6645909a8279d Mon Sep 17 00:00:00 2001 From: Justin Mclean Date: Tue, 15 Oct 2024 13:03:48 -0700 Subject: [PATCH 3/3] update docs --- clients/cli/README.md | 90 ++++++++++++++++++- .../gravitino/cli/GravitinoOptions.java | 7 +- 2 files changed, 92 insertions(+), 5 deletions(-) diff --git a/clients/cli/README.md b/clients/cli/README.md index b4f7c2cfc88..3a7d6b1ea0a 100644 --- a/clients/cli/README.md +++ b/clients/cli/README.md @@ -74,13 +74,15 @@ Before you can build and run this project, it is suggested you have the followin To run the Gravitino CLI, use the following command structure: ```bash -usage: gcli [metalake|catalog|schema|table] [list|details|create|delete|update|set|remove|properties] [options] +usage: gcli [metalake|catalog|schema|table|user|group|tag] [list|details|create|delete|update|set|remove|properties] [options] + -a,--tag tag name -b,--bootstrap Kafka bootstrap servers -c,--catalog catalog name -C,--create create an entity -D,--details list details about an entity -d,--database database name -e,--entity entity type + -g,--group group name -h,--help command help information -j,--jdbcurl JDBC URL -L,--list list entity children @@ -88,15 +90,16 @@ usage: gcli [metalake|catalog|schema|table] [list|details|create|delete|update|s -n,--name full entity name (dot separated) -P,--properties show an entities properties -p,--password database password - -R,--delete delete an entity -r,--rename new entity name + -R,--delete delete an entity -s,--schema schema name -t,--table table name -u,--user database username -U,--update update an entity -v,--value property value -w,--warehouse warehouse name - -x,--command one of: list, details, create, delete, or update + -x,--command one of: list, details, create, delete, update, + set, remove or properties ``` The command line can be used in several ways to achieve the same results, depending on your preference. @@ -119,6 +122,9 @@ details: Show detailed information about an entity create: Create a new entity delete: Delete an existing entity update: Update an existing entity +set: Used to set properties and tags +remove: Used to remove properties and tags +properties: Used to list properties ### Examples List All Metalakes @@ -169,6 +175,84 @@ Update a Metalake's comment gcli metalake update -name metalake_demo -comment "new comment" ``` +List the properties of a Metalake + +```bash +gcli metalake properties --name metalake_demo +``` + +Set a Metalake's property + +```bash +gcli metalake set --name metalake_demo --property color --value red +``` + +Remove a Metalake's property + +```bash +gcli metalake remove --name metalake_demo --property color +``` + +Create a new User + +```bash +gcli user create --name metalake_demo --user new_user +``` + +Show a User's information + +```bash +gcli user details --name metalake_demo --user new_user +``` + +Show all Users + +```bash +gcli user list --name metalake_demo +``` + +Delete a User + +```bash +gcli user delete --name metalake_demo --user new_user +``` + +Create a Tag + +```bash +gcli tag create --name metalake_demo --tag tagA +``` + +List all Tags in a Metalake + +```bash +gcli tag list --name metalake_demo +``` + +Delete a Tag + +```bash +gcli tag delete --name metalake_demo --tag tagA +``` + +Add a Tag to a Schema + +```bash +gcli tag set --name metalake_demo.catalog_postgres.hr --tag hr +``` + +Remove a Tag from a Schema + +```bash +gcli tag remove --name metalake_demo.catalog_postgres.hr --tag hr +``` + +List all tags on a Schema + +```bash +gcli tag list --name metalake_demo.catalog_postgres.hr +``` + ### Setting Metalake name As dealing with one Metalake is a typical scenario, you can set the Metalake name in several ways. 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 5d14f29f6ed..2a299caa15f 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 @@ -78,7 +78,10 @@ public Options options() { // One way of specifying the command options.addOption( - createArgOption("x", COMMAND, "one of: list, details, create, delete, or update")); + createArgOption( + "x", + COMMAND, + "one of: list, details, create, delete, update, set, remove or properties")); // Another way of specifying the command options.addOption(createSimpleOption("L", LIST, "list entity children")); @@ -104,7 +107,7 @@ public Options options() { options.addOption(createArgOption("p", PASSWORD, "database password")); options.addOption(createArgOption("d", DATABASE, "database name")); options.addOption(createArgOption("g", GROUP, "group name")); - options.addOption(createArgOption("t", TAG, "tag name")); + options.addOption(createArgOption("a", TAG, "tag name")); return options; }