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 12d869c429c..a68703a136f 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 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 f599964c961..0ad750f2c9b 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 b544a6b8028..630828bdb0a 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.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.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.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 @@ private void executeCommand() { handleGroupCommand(); } else if (entity.equals(CommandEntities.TAG)) { handleTagCommand(); + } else if (entity.equals(CommandEntities.ROLE)) { + handleRoleCommand(); } } @@ -443,6 +449,25 @@ protected void handleTagCommand() { } } + /** 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 cb6cfc43d66..63668fd3a65 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 Options options() { 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 Options options() { 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 00000000000..d3b71f45aaa --- /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 00000000000..0338c0c370f --- /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 00000000000..cca26336e82 --- /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 00000000000..613ee60d2ce --- /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 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 cd2a55e2a3b..50743c1f387 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 void validEntities() { 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 14b14cf240a..42c30667417 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 entity comment - -g,--group group name - -h,--help command help information - -i,--ignore ignore client/sever version check - -l,--user user name - -m,--metalake metalake name - -n,--name full entity name (dot separated) - -P,--property property name - -p,--properties property name/value pairs - -r,--rename new entity name - -s,--server Gravitino server version - -t,--tag tag name - -u,--url Gravitino URL (default: http://localhost:8090) - -v,--version Gravitino client version - -V,--value property value - -z,--provider provider one of hadoop, hive, mysql, postgres, - iceberg, kafka + -a,--audit display audit information + -c,--comment entity comment + -f,--force force operation + -g,--group group name + -h,--help command help information + -i,--ignore ignore client/sever version check + -l,--user user name + -m,--metalake metalake name + -n,--name full entity name (dot separated) + -P,--property property name + -r,--role role name + --rename new entity name + -s,--server Gravitino server version + -t,--tag tag name + -u,--url Gravitino URL (default: http://localhost:8090) + -v,--version Gravitino client version + -V,--value property value + -z,--provider 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 + ```