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 eba65cd86 [#5162] Add basic role commands to Gravitino CLI (#5291)
eba65cd86 is described below

commit eba65cd8648a4e10294e9b748a03d17b27d9b861
Author: Justin Mclean <[email protected]>
AuthorDate: Wed Nov 13 17:26:29 2024 +1100

    [#5162] Add basic role commands to Gravitino CLI (#5291)
    
    ### What changes were proposed in this pull request?
    
    Add basic role commands to Gravitino CLI
    
    ### Why are the changes needed?
    
    For the CLI to support roles.
    
    Fix: #5162
    
    ### Does this PR introduce _any_ user-facing change?
    
    No, but it adds roles to the CLI.
    
    ### How was this patch tested?
    
    Compiled and tested locally.
---
 .../org/apache/gravitino/cli/CommandEntities.java  |  2 +
 .../org/apache/gravitino/cli/ErrorMessages.java    |  2 +
 .../apache/gravitino/cli/GravitinoCommandLine.java | 25 +++++++
 .../org/apache/gravitino/cli/GravitinoOptions.java |  4 +-
 .../apache/gravitino/cli/commands/CreateRole.java  | 65 ++++++++++++++++++
 .../apache/gravitino/cli/commands/DeleteRole.java  | 80 ++++++++++++++++++++++
 .../apache/gravitino/cli/commands/ListRoles.java   | 62 +++++++++++++++++
 .../apache/gravitino/cli/commands/RoleDetails.java | 73 ++++++++++++++++++++
 .../apache/gravitino/cli/TestCommandEntities.java  |  2 +
 docs/cli.md                                        | 63 ++++++++++++-----
 10 files changed, 359 insertions(+), 19 deletions(-)

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 12d869c42..a68703a13 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
@@ -34,6 +34,7 @@ public class CommandEntities {
   public static final String USER = "user";
   public static final String GROUP = "group";
   public static final String TAG = "tag";
+  public static final String ROLE = "role";
 
   private static final HashSet<String> VALID_ENTITIES = new HashSet<>();
 
@@ -46,6 +47,7 @@ public class CommandEntities {
     VALID_ENTITIES.add(USER);
     VALID_ENTITIES.add(GROUP);
     VALID_ENTITIES.add(TAG);
+    VALID_ENTITIES.add(ROLE);
   }
 
   /**
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 f599964c9..0ad750f2c 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
@@ -39,6 +39,8 @@ public class ErrorMessages {
   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.";
+  public static final String UNKNOWN_ROLE = "Unknown role.";
+  public static final String ROLE_EXISTS = "Role already exists.";
   public static final String INVALID_SET_COMMAND =
       "Unsupported combination of options either use --name or --property and 
--value.";
   public static final String INVALID_REMOVE_COMMAND =
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 b544a6b80..630828bdb 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
@@ -29,12 +29,14 @@ import org.apache.gravitino.cli.commands.ClientVersion;
 import org.apache.gravitino.cli.commands.CreateCatalog;
 import org.apache.gravitino.cli.commands.CreateGroup;
 import org.apache.gravitino.cli.commands.CreateMetalake;
+import org.apache.gravitino.cli.commands.CreateRole;
 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.DeleteRole;
 import org.apache.gravitino.cli.commands.DeleteSchema;
 import org.apache.gravitino.cli.commands.DeleteTable;
 import org.apache.gravitino.cli.commands.DeleteTag;
@@ -48,6 +50,7 @@ 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;
+import org.apache.gravitino.cli.commands.ListRoles;
 import org.apache.gravitino.cli.commands.ListSchema;
 import org.apache.gravitino.cli.commands.ListSchemaProperties;
 import org.apache.gravitino.cli.commands.ListTables;
@@ -59,6 +62,7 @@ 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.RoleDetails;
 import org.apache.gravitino.cli.commands.SchemaAudit;
 import org.apache.gravitino.cli.commands.SchemaDetails;
 import org.apache.gravitino.cli.commands.ServerVersion;
@@ -181,6 +185,8 @@ public class GravitinoCommandLine {
       handleGroupCommand();
     } else if (entity.equals(CommandEntities.TAG)) {
       handleTagCommand();
+    } else if (entity.equals(CommandEntities.ROLE)) {
+      handleRoleCommand();
     }
   }
 
@@ -443,6 +449,25 @@ public class GravitinoCommandLine {
     }
   }
 
+  /** Handles the command execution for Roles based on command type and the 
command line options. */
+  protected void handleRoleCommand() {
+    String url = getUrl();
+    FullName name = new FullName(line);
+    String metalake = name.getMetalakeName();
+    String role = line.getOptionValue(GravitinoOptions.ROLE);
+
+    if (CommandActions.DETAILS.equals(command)) {
+      new RoleDetails(url, ignore, metalake, role).handle();
+    } else if (CommandActions.LIST.equals(command)) {
+      new ListRoles(url, ignore, metalake).handle();
+    } else if (CommandActions.CREATE.equals(command)) {
+      new CreateRole(url, ignore, metalake, role).handle();
+    } else if (CommandActions.DELETE.equals(command)) {
+      boolean force = line.hasOption(GravitinoOptions.FORCE);
+      new DeleteRole(url, ignore, force, metalake, role).handle();
+    }
+  }
+
   /**
    * Handles the command execution for Columns based on command type and the 
command line options.
    */
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 cb6cfc43d..63668fd3a 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
@@ -40,6 +40,7 @@ public class GravitinoOptions {
   public static final String USER = "user";
   public static final String GROUP = "group";
   public static final String TAG = "tag";
+  public static final String ROLE = "role";
   public static final String AUDIT = "audit";
   public static final String FORCE = "force";
 
@@ -62,7 +63,7 @@ public class GravitinoOptions {
     options.addOption(createSimpleOption("a", AUDIT, "display audit 
information"));
 
     // Create/update options
-    options.addOption(createArgOption("r", RENAME, "new entity name"));
+    options.addOption(createArgOption(null, RENAME, "new entity name"));
     options.addOption(createArgOption("c", COMMENT, "entity comment"));
     options.addOption(createArgOption("P", PROPERTY, "property name"));
     options.addOption(createArgOption("V", VALUE, "property value"));
@@ -72,6 +73,7 @@ public class GravitinoOptions {
     options.addOption(createArgOption("l", USER, "user name"));
     options.addOption(createArgOption("g", GROUP, "group name"));
     options.addOption(createArgOption("t", TAG, "tag name"));
+    options.addOption(createArgOption("r", ROLE, "role name"));
 
     // Properties option can have multiple values
     Option properties =
diff --git 
a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/CreateRole.java 
b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/CreateRole.java
new file mode 100644
index 000000000..d3b71f45a
--- /dev/null
+++ 
b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/CreateRole.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 java.util.Collections;
+import org.apache.gravitino.cli.ErrorMessages;
+import org.apache.gravitino.client.GravitinoClient;
+import org.apache.gravitino.exceptions.NoSuchMetalakeException;
+import org.apache.gravitino.exceptions.RoleAlreadyExistsException;
+
+public class CreateRole extends Command {
+  protected String metalake;
+  protected String role;
+
+  /**
+   * Create a new role.
+   *
+   * @param url The URL of the Gravitino server.
+   * @param ignoreVersions If true don't check the client/server versions 
match.
+   * @param metalake The name of the metalake.
+   * @param role The name of the role.
+   */
+  public CreateRole(String url, boolean ignoreVersions, String metalake, 
String role) {
+    super(url, ignoreVersions);
+    this.metalake = metalake;
+    this.role = role;
+  }
+
+  /** Create a new role. */
+  @Override
+  public void handle() {
+    try {
+      GravitinoClient client = buildClient(metalake);
+      client.createRole(role, null, Collections.EMPTY_LIST);
+    } catch (NoSuchMetalakeException err) {
+      System.err.println(ErrorMessages.UNKNOWN_METALAKE);
+      return;
+    } catch (RoleAlreadyExistsException err) {
+      System.err.println(ErrorMessages.ROLE_EXISTS);
+      return;
+    } catch (Exception exp) {
+      System.err.println(exp.getMessage());
+      return;
+    }
+
+    System.out.println(role + " created");
+  }
+}
diff --git 
a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/DeleteRole.java 
b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/DeleteRole.java
new file mode 100644
index 000000000..0338c0c37
--- /dev/null
+++ 
b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/DeleteRole.java
@@ -0,0 +1,80 @@
+/*
+ * 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.AreYouSure;
+import org.apache.gravitino.cli.ErrorMessages;
+import org.apache.gravitino.client.GravitinoClient;
+import org.apache.gravitino.exceptions.NoSuchMetalakeException;
+import org.apache.gravitino.exceptions.NoSuchRoleException;
+
+public class DeleteRole extends Command {
+
+  protected String metalake;
+  protected String role;
+  protected boolean force;
+
+  /**
+   * Delete a role.
+   *
+   * @param url The URL of the Gravitino server.
+   * @param ignoreVersions If true don't check the client/server versions 
match.
+   * @param force Force operation.
+   * @param metalake The name of the metalake.
+   * @param role The name of the role.
+   */
+  public DeleteRole(
+      String url, boolean ignoreVersions, boolean force, String metalake, 
String role) {
+    super(url, ignoreVersions);
+    this.metalake = metalake;
+    this.force = force;
+    this.role = role;
+  }
+
+  /** Delete a role. */
+  @Override
+  public void handle() {
+    boolean deleted = false;
+
+    if (!AreYouSure.really(force)) {
+      return;
+    }
+
+    try {
+      GravitinoClient client = buildClient(metalake);
+      deleted = client.deleteRole(role);
+    } catch (NoSuchMetalakeException err) {
+      System.err.println(ErrorMessages.UNKNOWN_METALAKE);
+      return;
+    } catch (NoSuchRoleException err) {
+      System.err.println(ErrorMessages.UNKNOWN_ROLE);
+      return;
+    } catch (Exception exp) {
+      System.err.println(exp.getMessage());
+      return;
+    }
+
+    if (deleted) {
+      System.out.println(role + " deleted.");
+    } else {
+      System.out.println(role + " not deleted.");
+    }
+  }
+}
diff --git 
a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListRoles.java 
b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListRoles.java
new file mode 100644
index 000000000..cca26336e
--- /dev/null
+++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/ListRoles.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.gravitino.cli.commands;
+
+import org.apache.gravitino.cli.ErrorMessages;
+import org.apache.gravitino.client.GravitinoClient;
+import org.apache.gravitino.exceptions.NoSuchMetalakeException;
+
+/* Lists all roles in a metalake. */
+public class ListRoles extends Command {
+
+  protected String metalake;
+
+  /**
+   * Lists all groups in a metalake.
+   *
+   * @param url The URL of the Gravitino server.
+   * @param ignoreVersions If true don't check the client/server versions 
match.
+   * @param metalake The name of the metalake.
+   */
+  public ListRoles(String url, boolean ignoreVersions, String metalake) {
+    super(url, ignoreVersions);
+    this.metalake = metalake;
+  }
+
+  /** Lists all roles in a metalake. */
+  @Override
+  public void handle() {
+    String[] roles = new String[0];
+    try {
+      GravitinoClient client = buildClient(metalake);
+      roles = client.listRoleNames();
+    } catch (NoSuchMetalakeException err) {
+      System.err.println(ErrorMessages.UNKNOWN_METALAKE);
+      return;
+    } catch (Exception exp) {
+      System.err.println(exp.getMessage());
+      return;
+    }
+
+    String all = String.join(",", roles);
+
+    System.out.println(all.toString());
+  }
+}
diff --git 
a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RoleDetails.java 
b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RoleDetails.java
new file mode 100644
index 000000000..613ee60d2
--- /dev/null
+++ 
b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RoleDetails.java
@@ -0,0 +1,73 @@
+/*
+ * 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.List;
+import java.util.stream.Collectors;
+import org.apache.gravitino.authorization.SecurableObject;
+import org.apache.gravitino.cli.ErrorMessages;
+import org.apache.gravitino.client.GravitinoClient;
+import org.apache.gravitino.exceptions.NoSuchMetalakeException;
+import org.apache.gravitino.exceptions.NoSuchUserException;
+
+public class RoleDetails extends Command {
+
+  protected String metalake;
+  protected String role;
+
+  /**
+   * Displays the securable objects in a role.
+   *
+   * @param url The URL of the Gravitino server.
+   * @param ignoreVersions If true don't check the client/server versions 
match.
+   * @param metalake The name of the metalake.
+   * @param role The name of the role.
+   */
+  public RoleDetails(String url, boolean ignoreVersions, String metalake, 
String role) {
+    super(url, ignoreVersions);
+    this.metalake = metalake;
+    this.role = role;
+  }
+
+  /** Displays the securable objects of a specified role. */
+  @Override
+  public void handle() {
+    List<SecurableObject> objects = null;
+
+    try {
+      GravitinoClient client = buildClient(metalake);
+      objects = client.getRole(role).securableObjects();
+    } catch (NoSuchMetalakeException err) {
+      System.err.println(ErrorMessages.UNKNOWN_METALAKE);
+      return;
+    } catch (NoSuchUserException err) {
+      System.err.println(ErrorMessages.UNKNOWN_GROUP);
+      return;
+    } catch (Exception exp) {
+      System.err.println(exp.getMessage());
+      return;
+    }
+
+    // TODO expand in securable objects PR
+    String all = 
objects.stream().map(SecurableObject::name).collect(Collectors.joining(","));
+
+    System.out.println(all.toString());
+  }
+}
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 cd2a55e2a..50743c1f3 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
@@ -38,6 +38,8 @@ public class TestCommandEntities {
     assertTrue(
         CommandEntities.isValidEntity(CommandEntities.TABLE), "TABLE should be 
a valid entity");
     assertTrue(CommandEntities.isValidEntity(CommandEntities.TAG), "TAG should 
be a valid entity");
+    assertTrue(
+        CommandEntities.isValidEntity(CommandEntities.ROLE), "ROLE should be a 
valid entity");
   }
 
   @Test
diff --git a/docs/cli.md b/docs/cli.md
index 14b14cf24..42c306674 100644
--- a/docs/cli.md
+++ b/docs/cli.md
@@ -29,24 +29,25 @@ The general structure for running commands with the 
Gravitino CLI is `gcli entit
  ```bash
  usage: gcli [metalake|catalog|schema|table|column] 
[list|details|create|delete|update|set|remove|properties] [options]
  Options
- -a,--audit              display audit information
- -c,--comment <arg>      entity comment
- -g,--group <arg>        group name
- -h,--help               command help information
- -i,--ignore             ignore client/sever version check
- -l,--user <arg>         user name
- -m,--metalake <arg>     metalake name
- -n,--name <arg>         full entity name (dot separated)
- -P,--property <arg>     property name
- -p,--properties <arg>   property name/value pairs
- -r,--rename <arg>       new entity name
- -s,--server             Gravitino server version
- -t,--tag <arg>          tag name
- -u,--url <arg>          Gravitino URL (default: http://localhost:8090)
- -v,--version            Gravitino client version
- -V,--value <arg>        property value
- -z,--provider <arg>     provider one of hadoop, hive, mysql, postgres,
-                         iceberg, kafka
+ -a,--audit            display audit information
+ -c,--comment <arg>    entity comment
+ -f,--force            force operation
+ -g,--group <arg>      group name
+ -h,--help             command help information
+ -i,--ignore           ignore client/sever version check
+ -l,--user <arg>       user name
+ -m,--metalake <arg>   metalake name
+ -n,--name <arg>       full entity name (dot separated)
+ -P,--property <arg>   property name
+ -r,--role <arg>       role name
+    --rename <arg>     new entity name
+ -s,--server           Gravitino server version
+ -t,--tag <arg>        tag name
+ -u,--url <arg>        Gravitino URL (default: http://localhost:8090)
+ -v,--version          Gravitino client version
+ -V,--value <arg>      property value
+ -z,--provider <arg>   provider one of hadoop, hive, mysql, postgres,
+                       iceberg, kafka
  ```
 
 ## Commands
@@ -503,3 +504,29 @@ gcli tag update --tag tagA --rename newTag
 ```bash
 gcli tag update --tag tagA --comment "new comment"
 ```
+
+### Role commands
+
+#### Display role details
+
+```bash
+gcli role details --role admin
+```
+
+#### List all roles
+
+```bash
+gcli role list
+```
+
+#### Create a role
+
+```bash
+gcli role create --role admin
+ ```
+
+#### Delete a role
+
+```bash
+gcli role delete --role admin
+ ```

Reply via email to