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 71005e7bf [#5527] Add audit command to roles, users and groups in the 
Gravitino CLI (#5802)
71005e7bf is described below

commit 71005e7bff0738683aa9615434d5c7aeaf44aefa
Author: Justin Mclean <[email protected]>
AuthorDate: Tue Dec 17 18:11:00 2024 +1100

    [#5527] Add audit command to roles, users and groups in the Gravitino CLI 
(#5802)
    
    ### What changes were proposed in this pull request?
    
    Added audit command to roles, users and groups in the Gravitino CLI.
    
    ### Why are the changes needed?
    
    So all entities support the audit command.
    
    Fix: #5527
    
    ### Does this PR introduce _any_ user-facing change?
    
    No, but add more commands.
    
    ### How was this patch tested?
    
    Tested locally.
---
 .../apache/gravitino/cli/GravitinoCommandLine.java | 18 +++++-
 .../apache/gravitino/cli/TestableCommandLine.java  | 15 +++++
 .../apache/gravitino/cli/commands/GroupAudit.java  | 69 ++++++++++++++++++++++
 .../apache/gravitino/cli/commands/RoleAudit.java   | 69 ++++++++++++++++++++++
 .../apache/gravitino/cli/commands/UserAudit.java   | 69 ++++++++++++++++++++++
 .../apache/gravitino/cli/TestGroupCommands.java    | 20 +++++++
 .../org/apache/gravitino/cli/TestRoleCommands.java | 20 +++++++
 .../org/apache/gravitino/cli/TestUserCommands.java | 20 +++++++
 docs/cli.md                                        | 24 +++++++-
 9 files changed, 318 insertions(+), 6 deletions(-)

diff --git 
a/clients/cli/src/main/java/org/apache/gravitino/cli/GravitinoCommandLine.java 
b/clients/cli/src/main/java/org/apache/gravitino/cli/GravitinoCommandLine.java
index 151b90a83..18389aaa4 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
@@ -397,7 +397,11 @@ public class GravitinoCommandLine extends 
TestableCommandLine {
     Command.setAuthenticationMode(auth, userName);
 
     if (CommandActions.DETAILS.equals(command)) {
-      newUserDetails(url, ignore, metalake, user).handle();
+      if (line.hasOption(GravitinoOptions.AUDIT)) {
+        newUserAudit(url, ignore, metalake, user).handle();
+      } else {
+        newUserDetails(url, ignore, metalake, user).handle();
+      }
     } else if (CommandActions.LIST.equals(command)) {
       newListUsers(url, ignore, metalake).handle();
     } else if (CommandActions.CREATE.equals(command)) {
@@ -434,7 +438,11 @@ public class GravitinoCommandLine extends 
TestableCommandLine {
     Command.setAuthenticationMode(auth, userName);
 
     if (CommandActions.DETAILS.equals(command)) {
-      newGroupDetails(url, ignore, metalake, group).handle();
+      if (line.hasOption(GravitinoOptions.AUDIT)) {
+        newGroupAudit(url, ignore, metalake, group).handle();
+      } else {
+        newGroupDetails(url, ignore, metalake, group).handle();
+      }
     } else if (CommandActions.LIST.equals(command)) {
       newListGroups(url, ignore, metalake).handle();
     } else if (CommandActions.CREATE.equals(command)) {
@@ -539,7 +547,11 @@ public class GravitinoCommandLine extends 
TestableCommandLine {
     Command.setAuthenticationMode(auth, userName);
 
     if (CommandActions.DETAILS.equals(command)) {
-      newRoleDetails(url, ignore, metalake, role).handle();
+      if (line.hasOption(GravitinoOptions.AUDIT)) {
+        newRoleAudit(url, ignore, metalake, role).handle();
+      } else {
+        newRoleDetails(url, ignore, metalake, role).handle();
+      }
     } else if (CommandActions.LIST.equals(command)) {
       newListRoles(url, ignore, metalake).handle();
     } else if (CommandActions.CREATE.equals(command)) {
diff --git 
a/clients/cli/src/main/java/org/apache/gravitino/cli/TestableCommandLine.java 
b/clients/cli/src/main/java/org/apache/gravitino/cli/TestableCommandLine.java
index 93ec3adaa..21fa65d99 100644
--- 
a/clients/cli/src/main/java/org/apache/gravitino/cli/TestableCommandLine.java
+++ 
b/clients/cli/src/main/java/org/apache/gravitino/cli/TestableCommandLine.java
@@ -50,6 +50,7 @@ import org.apache.gravitino.cli.commands.DeleteTag;
 import org.apache.gravitino.cli.commands.DeleteTopic;
 import org.apache.gravitino.cli.commands.DeleteUser;
 import org.apache.gravitino.cli.commands.FilesetDetails;
+import org.apache.gravitino.cli.commands.GroupAudit;
 import org.apache.gravitino.cli.commands.GroupDetails;
 import org.apache.gravitino.cli.commands.ListAllTags;
 import org.apache.gravitino.cli.commands.ListCatalogProperties;
@@ -84,6 +85,7 @@ import org.apache.gravitino.cli.commands.RemoveSchemaProperty;
 import org.apache.gravitino.cli.commands.RemoveTableProperty;
 import org.apache.gravitino.cli.commands.RemoveTagProperty;
 import org.apache.gravitino.cli.commands.RemoveTopicProperty;
+import org.apache.gravitino.cli.commands.RoleAudit;
 import org.apache.gravitino.cli.commands.RoleDetails;
 import org.apache.gravitino.cli.commands.SchemaAudit;
 import org.apache.gravitino.cli.commands.SchemaDetails;
@@ -123,6 +125,7 @@ import org.apache.gravitino.cli.commands.UpdateTableName;
 import org.apache.gravitino.cli.commands.UpdateTagComment;
 import org.apache.gravitino.cli.commands.UpdateTagName;
 import org.apache.gravitino.cli.commands.UpdateTopicComment;
+import org.apache.gravitino.cli.commands.UserAudit;
 import org.apache.gravitino.cli.commands.UserDetails;
 
 /*
@@ -393,6 +396,10 @@ public class TestableCommandLine {
     return new ListUsers(url, ignore, metalake);
   }
 
+  protected UserAudit newUserAudit(String url, boolean ignore, String 
metalake, String user) {
+    return new UserAudit(url, ignore, metalake, user);
+  }
+
   protected CreateUser newCreateUser(String url, boolean ignore, String 
metalake, String user) {
     return new CreateUser(url, ignore, metalake, user);
   }
@@ -420,6 +427,10 @@ public class TestableCommandLine {
     return new ListGroups(url, ignore, metalake);
   }
 
+  protected GroupAudit newGroupAudit(String url, boolean ignore, String 
metalake, String group) {
+    return new GroupAudit(url, ignore, metalake, group);
+  }
+
   protected CreateGroup newCreateGroup(String url, boolean ignore, String 
metalake, String user) {
     return new CreateGroup(url, ignore, metalake, user);
   }
@@ -447,6 +458,10 @@ public class TestableCommandLine {
     return new ListRoles(url, ignore, metalake);
   }
 
+  protected RoleAudit newRoleAudit(String url, boolean ignore, String 
metalake, String role) {
+    return new RoleAudit(url, ignore, metalake, role);
+  }
+
   protected CreateRole newCreateRole(String url, boolean ignore, String 
metalake, String role) {
     return new CreateRole(url, ignore, metalake, role);
   }
diff --git 
a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/GroupAudit.java 
b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/GroupAudit.java
new file mode 100644
index 000000000..9e79705bc
--- /dev/null
+++ 
b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/GroupAudit.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.authorization.Group;
+import org.apache.gravitino.cli.ErrorMessages;
+import org.apache.gravitino.client.GravitinoClient;
+import org.apache.gravitino.exceptions.NoSuchGroupException;
+import org.apache.gravitino.exceptions.NoSuchMetalakeException;
+
+public class GroupAudit extends AuditCommand {
+
+  protected final String metalake;
+  protected final String group;
+
+  /**
+   * Displays the audit information of a group.
+   *
+   * @param url The URL of the Gravitino server.
+   * @param ignoreVersions If true don't check the client/server versions 
match.
+   * @param metalake The name of the metalake.
+   * @param group The name of the group.
+   */
+  public GroupAudit(String url, boolean ignoreVersions, String metalake, 
String group) {
+    super(url, ignoreVersions);
+    this.metalake = metalake;
+    this.group = group;
+  }
+
+  /** Displays the audit information of a specified group. */
+  @Override
+  public void handle() {
+    Group result;
+
+    try (GravitinoClient client = buildClient(metalake)) {
+      result = client.getGroup(this.group);
+    } catch (NoSuchMetalakeException err) {
+      System.err.println(ErrorMessages.UNKNOWN_METALAKE);
+      return;
+    } catch (NoSuchGroupException err) {
+      System.err.println(ErrorMessages.UNKNOWN_GROUP);
+      return;
+    } catch (Exception exp) {
+      System.err.println(exp.getMessage());
+      return;
+    }
+
+    if (result != null) {
+      displayAuditInfo(result.auditInfo());
+    }
+  }
+}
diff --git 
a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RoleAudit.java 
b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RoleAudit.java
new file mode 100644
index 000000000..e497ca836
--- /dev/null
+++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/RoleAudit.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.authorization.Role;
+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 RoleAudit extends AuditCommand {
+
+  protected final String metalake;
+  protected final String role;
+
+  /**
+   * Displays the audit information of a role.
+   *
+   * @param url The URL of the Gravitino server.
+   * @param ignoreVersions If true don't check the client/server versions 
match.
+   * @param metalake The name of the metalake.
+   * @param role The name of the role.
+   */
+  public RoleAudit(String url, boolean ignoreVersions, String metalake, String 
role) {
+    super(url, ignoreVersions);
+    this.metalake = metalake;
+    this.role = role;
+  }
+
+  /** Displays the audit information of a specified role. */
+  @Override
+  public void handle() {
+    Role result;
+
+    try (GravitinoClient client = buildClient(metalake)) {
+      result = client.getRole(this.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 (result != null) {
+      displayAuditInfo(result.auditInfo());
+    }
+  }
+}
diff --git 
a/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UserAudit.java 
b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UserAudit.java
new file mode 100644
index 000000000..44ac2babc
--- /dev/null
+++ b/clients/cli/src/main/java/org/apache/gravitino/cli/commands/UserAudit.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.authorization.User;
+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 UserAudit extends AuditCommand {
+
+  protected final String metalake;
+  protected final String user;
+
+  /**
+   * Displays the audit information of a user.
+   *
+   * @param url The URL of the Gravitino server.
+   * @param ignoreVersions If true don't check the client/server versions 
match.
+   * @param metalake The name of the metalake.
+   * @param user The name of the user.
+   */
+  public UserAudit(String url, boolean ignoreVersions, String metalake, String 
user) {
+    super(url, ignoreVersions);
+    this.metalake = metalake;
+    this.user = user;
+  }
+
+  /** Displays the audit information of a specified user. */
+  @Override
+  public void handle() {
+    User result;
+
+    try (GravitinoClient client = buildClient(metalake)) {
+      result = client.getUser(this.user);
+    } catch (NoSuchMetalakeException err) {
+      System.err.println(ErrorMessages.UNKNOWN_METALAKE);
+      return;
+    } catch (NoSuchUserException err) {
+      System.err.println(ErrorMessages.UNKNOWN_USER);
+      return;
+    } catch (Exception exp) {
+      System.err.println(exp.getMessage());
+      return;
+    }
+
+    if (result != null) {
+      displayAuditInfo(result.auditInfo());
+    }
+  }
+}
diff --git 
a/clients/cli/src/test/java/org/apache/gravitino/cli/TestGroupCommands.java 
b/clients/cli/src/test/java/org/apache/gravitino/cli/TestGroupCommands.java
index 780f33844..00fe52e9f 100644
--- a/clients/cli/src/test/java/org/apache/gravitino/cli/TestGroupCommands.java
+++ b/clients/cli/src/test/java/org/apache/gravitino/cli/TestGroupCommands.java
@@ -30,6 +30,7 @@ import org.apache.commons.cli.Options;
 import org.apache.gravitino.cli.commands.AddRoleToGroup;
 import org.apache.gravitino.cli.commands.CreateGroup;
 import org.apache.gravitino.cli.commands.DeleteGroup;
+import org.apache.gravitino.cli.commands.GroupAudit;
 import org.apache.gravitino.cli.commands.GroupDetails;
 import org.apache.gravitino.cli.commands.ListGroups;
 import org.apache.gravitino.cli.commands.RemoveRoleFromGroup;
@@ -80,6 +81,25 @@ class TestGroupCommands {
     verify(mockDetails).handle();
   }
 
+  @Test
+  void testGroupAuditCommand() {
+    GroupAudit mockAudit = mock(GroupAudit.class);
+    
when(mockCommandLine.hasOption(GravitinoOptions.METALAKE)).thenReturn(true);
+    
when(mockCommandLine.getOptionValue(GravitinoOptions.METALAKE)).thenReturn("metalake_demo");
+    when(mockCommandLine.hasOption(GravitinoOptions.GROUP)).thenReturn(true);
+    
when(mockCommandLine.getOptionValue(GravitinoOptions.GROUP)).thenReturn("group");
+    when(mockCommandLine.hasOption(GravitinoOptions.AUDIT)).thenReturn(true);
+    GravitinoCommandLine commandLine =
+        spy(
+            new GravitinoCommandLine(
+                mockCommandLine, mockOptions, CommandEntities.GROUP, 
CommandActions.DETAILS));
+    doReturn(mockAudit)
+        .when(commandLine)
+        .newGroupAudit(GravitinoCommandLine.DEFAULT_URL, false, 
"metalake_demo", "group");
+    commandLine.handleCommandLine();
+    verify(mockAudit).handle();
+  }
+
   @Test
   void testCreateGroupCommand() {
     CreateGroup mockCreate = mock(CreateGroup.class);
diff --git 
a/clients/cli/src/test/java/org/apache/gravitino/cli/TestRoleCommands.java 
b/clients/cli/src/test/java/org/apache/gravitino/cli/TestRoleCommands.java
index 47b4bb1b1..179dba14f 100644
--- a/clients/cli/src/test/java/org/apache/gravitino/cli/TestRoleCommands.java
+++ b/clients/cli/src/test/java/org/apache/gravitino/cli/TestRoleCommands.java
@@ -30,6 +30,7 @@ import org.apache.commons.cli.Options;
 import org.apache.gravitino.cli.commands.CreateRole;
 import org.apache.gravitino.cli.commands.DeleteRole;
 import org.apache.gravitino.cli.commands.ListRoles;
+import org.apache.gravitino.cli.commands.RoleAudit;
 import org.apache.gravitino.cli.commands.RoleDetails;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
@@ -78,6 +79,25 @@ class TestRoleCommands {
     verify(mockDetails).handle();
   }
 
+  @Test
+  void testRoleAuditCommand() {
+    RoleAudit mockAudit = mock(RoleAudit.class);
+    
when(mockCommandLine.hasOption(GravitinoOptions.METALAKE)).thenReturn(true);
+    
when(mockCommandLine.getOptionValue(GravitinoOptions.METALAKE)).thenReturn("metalake_demo");
+    when(mockCommandLine.hasOption(GravitinoOptions.ROLE)).thenReturn(true);
+    
when(mockCommandLine.getOptionValue(GravitinoOptions.ROLE)).thenReturn("group");
+    when(mockCommandLine.hasOption(GravitinoOptions.AUDIT)).thenReturn(true);
+    GravitinoCommandLine commandLine =
+        spy(
+            new GravitinoCommandLine(
+                mockCommandLine, mockOptions, CommandEntities.ROLE, 
CommandActions.DETAILS));
+    doReturn(mockAudit)
+        .when(commandLine)
+        .newRoleAudit(GravitinoCommandLine.DEFAULT_URL, false, 
"metalake_demo", "group");
+    commandLine.handleCommandLine();
+    verify(mockAudit).handle();
+  }
+
   @Test
   void testCreateRoleCommand() {
     CreateRole mockCreate = mock(CreateRole.class);
diff --git 
a/clients/cli/src/test/java/org/apache/gravitino/cli/TestUserCommands.java 
b/clients/cli/src/test/java/org/apache/gravitino/cli/TestUserCommands.java
index 0628d1f63..21c574364 100644
--- a/clients/cli/src/test/java/org/apache/gravitino/cli/TestUserCommands.java
+++ b/clients/cli/src/test/java/org/apache/gravitino/cli/TestUserCommands.java
@@ -32,6 +32,7 @@ import org.apache.gravitino.cli.commands.CreateUser;
 import org.apache.gravitino.cli.commands.DeleteUser;
 import org.apache.gravitino.cli.commands.ListUsers;
 import org.apache.gravitino.cli.commands.RemoveRoleFromUser;
+import org.apache.gravitino.cli.commands.UserAudit;
 import org.apache.gravitino.cli.commands.UserDetails;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
@@ -80,6 +81,25 @@ class TestUserCommands {
     verify(mockDetails).handle();
   }
 
+  @Test
+  void testUserAuditCommand() {
+    UserAudit mockAudit = mock(UserAudit.class);
+    
when(mockCommandLine.hasOption(GravitinoOptions.METALAKE)).thenReturn(true);
+    
when(mockCommandLine.getOptionValue(GravitinoOptions.METALAKE)).thenReturn("metalake_demo");
+    when(mockCommandLine.hasOption(GravitinoOptions.USER)).thenReturn(true);
+    
when(mockCommandLine.getOptionValue(GravitinoOptions.USER)).thenReturn("admin");
+    when(mockCommandLine.hasOption(GravitinoOptions.AUDIT)).thenReturn(true);
+    GravitinoCommandLine commandLine =
+        spy(
+            new GravitinoCommandLine(
+                mockCommandLine, mockOptions, CommandEntities.USER, 
CommandActions.DETAILS));
+    doReturn(mockAudit)
+        .when(commandLine)
+        .newUserAudit(GravitinoCommandLine.DEFAULT_URL, false, 
"metalake_demo", "admin");
+    commandLine.handleCommandLine();
+    verify(mockAudit).handle();
+  }
+
   @Test
   void testCreateUserCommand() {
     CreateUser mockCreate = mock(CreateUser.class);
diff --git a/docs/cli.md b/docs/cli.md
index f8e9a4f56..11b9f18e5 100644
--- a/docs/cli.md
+++ b/docs/cli.md
@@ -228,7 +228,7 @@ gcli metalake list
 gcli metalake details
 ```
 
-#### Show a metalake audit information
+#### Show a metalake's audit information
 
 ```bash
 gcli metalake details --audit
@@ -290,7 +290,7 @@ gcli catalog list
 gcli catalog details --name catalog_postgres
 ```
 
-#### Show a catalog audit information
+#### Show a catalog's audit information
 
 ```bash
 gcli catalog details --name catalog_postgres --audit
@@ -404,7 +404,7 @@ gcli schema list --name catalog_postgres
 gcli schema details --name catalog_postgres.hr
 ```
 
-#### Show schema audit information
+#### Show schema's audit information
 
 ```bash
 gcli schema details --name catalog_postgres.hr --audit
@@ -526,6 +526,12 @@ gcli user details --user new_user
 gcli user list
 ```
 
+#### Show a roles's audit information
+
+```bash
+gcli user details --user new_user --audit
+```
+
 #### Delete a user
 
 ```bash
@@ -552,6 +558,12 @@ gcli group details --group new_group
 gcli group list
 ```
 
+#### Show a groups's audit information
+
+```bash
+gcli group details --group new_group --audit
+```
+
 #### Delete a group
 
 ```bash
@@ -672,6 +684,12 @@ gcli role details --role admin
 gcli role list
 ```
 
+#### Show a roles's audit information
+
+```bash
+gcli role details --role admin --audit
+```
+
 #### Create a role
 
 ```bash

Reply via email to