Skip to content

Commit

Permalink
[#5162] Add basic role commands to Gravitino CLI (#5291)
Browse files Browse the repository at this point in the history
### 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.
  • Loading branch information
justinmclean authored Nov 13, 2024
1 parent 3ccd89a commit eba65cd
Show file tree
Hide file tree
Showing 10 changed files with 359 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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<>();

Expand All @@ -46,6 +47,7 @@ public class CommandEntities {
VALID_ENTITIES.add(USER);
VALID_ENTITIES.add(GROUP);
VALID_ENTITIES.add(TAG);
VALID_ENTITIES.add(ROLE);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -181,6 +185,8 @@ private void executeCommand() {
handleGroupCommand();
} else if (entity.equals(CommandEntities.TAG)) {
handleTagCommand();
} else if (entity.equals(CommandEntities.ROLE)) {
handleRoleCommand();
}
}

Expand Down Expand Up @@ -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.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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";

Expand All @@ -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"));
Expand All @@ -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 =
Expand Down
Original file line number Diff line number Diff line change
@@ -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");
}
}
Original file line number Diff line number Diff line change
@@ -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.");
}
}
}
Original file line number Diff line number Diff line change
@@ -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());
}
}
Original file line number Diff line number Diff line change
@@ -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());
}
}
Loading

0 comments on commit eba65cd

Please sign in to comment.