-
Notifications
You must be signed in to change notification settings - Fork 336
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
Conversation
@jerryshao Could you help me review this pull request? |
scripts/mysql/schema-0.5.0-mysql.sql
Outdated
@@ -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', |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this 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.
core/src/test/java/com/datastrato/gravitino/proto/TestEntityProtoSerDe.java
Outdated
Show resolved
Hide resolved
.name() | ||
.equals(role.getSecurableObjects(index).getPrivilegeConditions(privIndex))) { | ||
privileges.add( | ||
Privileges.allow(role.getSecurableObjects(index).getPrivilegeNames(privIndex))); |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
core/src/main/java/com/datastrato/gravitino/storage/relational/utils/POConverters.java
Show resolved
Hide resolved
@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) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"persistent" or "persist"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
core/src/main/java/com/datastrato/gravitino/storage/relational/utils/POConverters.java
Show resolved
Hide resolved
`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', |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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`; |
There was a problem hiding this comment.
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.
ALTER TABLE `role_meta` | ||
ADD COLUMN `securable_objects` VARCHAR(2048) NOT NULL COMMENT 'securable objects' AFTER `properties`; |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added the scripts.
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`; |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
All comments are addressed. |
"DELETE FROM " | ||
+ SECURABLE_OBJECT_TABLE_NAME | ||
+ " WHERE deleted_at > 0 AND deleted_at < #{legacyTimeLine} LIMIT #{limit}") | ||
Integer deleteSecurableObjectsByLegacyTimeLine( |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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 { |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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) { |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
private static final String ROOT = "ROOT"; | ||
private static final String ALL_METALAKES = "*"; | ||
private static final long ALL_METALAKES_ENTITY_ID = 0; |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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); |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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) { |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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) { |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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) { |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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())); |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
“securableObjectPOs”
There was a problem hiding this comment.
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(); |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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())); |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
throw new IllegalArgumentException(String.format("Doesn't support the type %s", type)); | ||
} | ||
|
||
// Securable object may be null because the securable object may be deleted. |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
LGTM overall except a minor issue. |
I will merge this tomorrow if there's no more comment. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
…#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>
…#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>
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.