Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[#3343] feat(core): Supports multiple securable objects #3497

Merged
merged 48 commits into from
Jun 7, 2024

Conversation

qqqttt123
Copy link
Contributor

What changes were proposed in this pull request?

Refactor the underlying layout to support multiple securable objects.

Why are the changes needed?

Fix: #3343

Does this PR introduce any user-facing change?

No.

How was this patch tested?

Existing UT.

@qqqttt123 qqqttt123 self-assigned this May 22, 2024
@qqqttt123 qqqttt123 requested a review from jerryshao May 22, 2024 06:05
@qqqttt123
Copy link
Contributor Author

@jerryshao Could you help me review this pull request?

@@ -135,10 +135,7 @@ CREATE TABLE IF NOT EXISTS `role_meta` (
`role_name` VARCHAR(128) NOT NULL COMMENT 'role name',
`metalake_id` BIGINT(20) UNSIGNED NOT NULL COMMENT 'metalake id',
`properties` MEDIUMTEXT DEFAULT NULL COMMENT 'schema properties',
`securable_object_full_name` VARCHAR(256) NOT NULL COMMENT 'securable object full name',
Copy link
Collaborator

@xloya xloya May 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you need to change the structure of the MySQL table, in the long run, I think it is best to provide some additional alter table statements, such as creating an upgrade-0.5.0-to-0.5.1-mysql.sql file to help users of lower versions can be upgraded smoothly. You can create a new version of the schema sql file, such as schema-0.5.1-mysql.sql, so that users can directly use the new schema when accessing version 0.5.1.

Copy link
Collaborator

@jerqi jerqi May 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feature isn't available. Maybe we don't need to provide it now. Once we released this feature, we should provide alter scripts.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Think twice. You're right. I will update the script. Although our feature isn't available, users can create legacy table using the script.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The layout is shipped with 0.5.0, even it is not available from feature level, we still need to provide a script to support users to upgrade their storage layout. You can refer to #3506 for the solution.

Copy link
Contributor

@jerryshao jerryshao left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall, I think you need to add more UTs to cover your changes. Currently, the UT is quite limited, doesn't cover all of your changes.

.name()
.equals(role.getSecurableObjects(index).getPrivilegeConditions(privIndex))) {
privileges.add(
Privileges.allow(role.getSecurableObjects(index).getPrivilegeNames(privIndex)));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please add more tests to verify the serialization and deserialization of this part?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@jerqi
Copy link
Collaborator

jerqi commented May 23, 2024

@jerryshao I modified the ut to cover more cases.

.withAuditInfo(
JsonUtils.anyFieldMapper().readValue(rolePO.getAuditInfo(), AuditInfo.class))
.build();
} catch (JsonProcessingException e) {
throw new RuntimeException("Failed to deserialize json object:", e);
}
}

private static List<SecurableObject> fromSecurablePersistObjects(String persisteSecurableObjects)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"persistent" or "persist"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

`securable_object_type` VARCHAR(32) NOT NULL COMMENT 'securable object type',
`privileges` VARCHAR(64) NOT NULL COMMENT 'securable privileges',
`privilege_conditions` VARCHAR(64) NOT NULL COMMENT 'securable privilege conditions',
`securable_objects` VARCHAR(2048) NOT NULL COMMENT 'securable objects',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm afraid 2048 may not be enough for lots of securable_objects if the role is a big role.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change to TEXT.

--

ALTER TABLE `role_meta`
ADD COLUMN `securable_objects` VARCHAR(2048) NOT NULL COMMENT 'securable objects' AFTER `properties`;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also here, 2048 may not be enough.

@apache apache deleted a comment from jerqi May 24, 2024
Comment on lines 6 to 7
ALTER TABLE `role_meta`
ADD COLUMN `securable_objects` VARCHAR(2048) NOT NULL COMMENT 'securable objects' AFTER `properties`;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we need an update script to migrate the existing securable_object data to the new securable_objects column

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Feature isn't available now. We don't need to assume that we have already data.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added the scripts.

Comment on lines 9 to 12
ALTER TABLE `role_meta` DROP COLUMN `securable_object_full_name`;
ALTER TABLE `role_meta` DROP COLUMN `securable_object_type`;
ALTER TABLE `role_meta` DROP COLUMN `privileges`;
ALTER TABLE `role_meta` DROP COLUMN `privilege_conditions`;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In upgrade script, we should never remove fields, we should maintain backward compatibility.

If we execute this script, the production environment will immediately report an error.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I change to use alter.

@qqqttt123 qqqttt123 closed this May 24, 2024
@qqqttt123 qqqttt123 reopened this May 24, 2024
@qqqttt123
Copy link
Contributor Author

All comments are addressed.

"DELETE FROM "
+ SECURABLE_OBJECT_TABLE_NAME
+ " WHERE deleted_at > 0 AND deleted_at < #{legacyTimeLine} LIMIT #{limit}")
Integer deleteSecurableObjectsByLegacyTimeLine(
Copy link
Contributor

@jerryshao jerryshao Jun 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@qqqttt123 can you please create a separate PR to fix all the typo "TimeLine" to "Timeline", timeline is a word, here it separates into two words.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, I will. I have created an issue to track this. #3813

import com.google.common.base.Objects;
import com.google.common.base.Preconditions;

public class SecurableObjectPO {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, do you need a securable object id, can you please think a bit on this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Securable object id seems not useful after think twice.

// Catalog may be deleted, so the CatalogPO may be null.
// We don't choose to delete the securable object when we delete the catalog,
// Because they will bring conflicts if we are updating securable object
public CatalogPO getCatalogPOById(Long catalogId) {
Copy link
Contributor

@jerryshao jerryshao Jun 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should add the nullable annotation, also the explanation should be in the right place, not here, it's a bit weird added here. Just the first sentence is enough.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Comment on lines 37 to 39
private static final String ROOT = "ROOT";
private static final String ALL_METALAKES = "*";
private static final long ALL_METALAKES_ENTITY_ID = 0;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe you also define this in other place, you should define them in a consoliated place, besides, this entity id should be defined in the Entity definition there, not here.

Can you please carefully think of how to better organize the code, not just simply achieve it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

RoleMetaMapper.class,
mapper -> {
if (overwritten) {
mapper.insertRoleMetaOnDuplicateKeyUpdate(rolePO);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you still need to call insert on duplicate since they're already marked as deleted above?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We just deleted the securable objects instead of role meta.


for (SecurableObjectPO securableObjectPO : securableObjectPOs) {
String fullName = getSecurableObjectFullName(securableObjectPO);
if (fullName != null) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should add log about the null situation.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

+ securableObjectsCount[0];
}

long getSecurableObjectEntityId(long metalakeId, String fullName, MetadataObject.Type type) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a) Why there's no access level modifier for this method?
b) This and below methods are generic to role, you should make them generic and put into a utility class, so that tag implementation can also leverage these methods.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

throw new IllegalArgumentException(String.format("Doesn't support the type %s", type));
}

String getSecurableObjectFullName(SecurableObjectPO securableObjectPO) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it returns null, please add an annotation, also add more comments here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

SecurableObjects.ofTopic(
schemaObject, "topic", Lists.newArrayList(Privileges.ReadTopic.deny()));
SecurableObject allMetalakesObject =
SecurableObjects.ofAllMetalakes(Lists.newArrayList(Privileges.UseMetalake.allow()));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make securable object related test class be a separate class and add test to verify all the entities with cases.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

"</script>"
})
void batchInsertSecurableObjects(
@Param("securableObjects") List<SecurableObjectPO> securableObjectPOS);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

“securableObjectPOs”

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

if (tablePO == null) {
return null;
}
return getSchemaFullName(tablePO.getSchemaId()) + "." + tablePO.getTableName();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use DOT joiner, instead of hard code "." here.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

roleEntity.id(), object, getEntityType(object));
objectBuilder.withEntityId(
MetadataObjectUtils.getSecurableObjectEntityId(
metalakeId, object.fullName(), object.type()));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the fullname used for? can we store the all pareants id at the same time, I notice you will split the fullanme every time and fetch the corresponding ID from DB.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's similar to NameIdenfitier. The behaviour is similar to other nameidentier's implement. It's inconvenient to store parentId. The length of parents isn't fixed.

Copy link
Contributor

@jerryshao jerryshao left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm generally OK with the current implementation with several small comments, @yuqi1129 please also help to review. I will merge this when @yuqi1129 's review and update is done.

throw new IllegalArgumentException(String.format("Doesn't support the type %s", type));
}

// Securable object may be null because the securable object may be deleted.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

extra space betwen be and null

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@yuqi1129
Copy link
Contributor

yuqi1129 commented Jun 7, 2024

LGTM overall except a minor issue.

@jerryshao
Copy link
Contributor

I will merge this tomorrow if there's no more comment.

Copy link
Contributor

@yuqi1129 yuqi1129 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@jerryshao jerryshao merged commit ab0eaf6 into apache:main Jun 7, 2024
33 checks passed
@jerqi jerqi deleted the ISSUE-3343 branch June 7, 2024 22:38
diqiu50 pushed a commit to diqiu50/gravitino that referenced this pull request Jun 13, 2024
…#3497)

### What changes were proposed in this pull request?
Refactor the underlying layout to support multiple securable objects.

### Why are the changes needed?

Fix: apache#3343 

### Does this PR introduce _any_ user-facing change?
No.

### How was this patch tested?
Existing UT.

---------

Co-authored-by: Heng Qin <qqtt@123.com>
shaofengshi pushed a commit to shaofengshi/gravitino that referenced this pull request Jun 24, 2024
…#3497)

### What changes were proposed in this pull request?
Refactor the underlying layout to support multiple securable objects.

### Why are the changes needed?

Fix: apache#3343 

### Does this PR introduce _any_ user-facing change?
No.

### How was this patch tested?
Existing UT.

---------

Co-authored-by: Heng Qin <qqtt@123.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Improvement] Role supports multiple securable objects
6 participants