-
Notifications
You must be signed in to change notification settings - Fork 489
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
Add new method to set/get object retention & Legal Hold #836
Add new method to set/get object retention & Legal Hold #836
Conversation
4546da1
to
b5c1c80
Compare
api/src/main/java/io/minio/messages/ObjectLockRetentionConfiguration.java
Outdated
Show resolved
Hide resolved
api/src/main/java/io/minio/messages/ObjectLockRetentionConfiguration.java
Outdated
Show resolved
Hide resolved
api/src/main/java/io/minio/messages/ObjectLockRetentionConfiguration.java
Outdated
Show resolved
Hide resolved
api/src/main/java/io/minio/messages/ObjectLockRetentionConfiguration.java
Outdated
Show resolved
Hide resolved
b5c1c80
to
3dbb344
Compare
3dbb344
to
c6c316b
Compare
@balamurugana Need one confirmation . The exception is :
As per S3 the retainUntil Date is of this form But on Minio Server it is stored as Can you please suggest that is it a server side bug , or do i need to have some change in client side. |
You don't need to have
Server needs to comply with the spec, else its server bug. |
String[] hashes = Digest.sha256Md5Hashes(data, len); | ||
sha256Hash = hashes[0]; | ||
md5Hash = hashes[1]; | ||
headerMap.remove("retention",""); |
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.
Not a good approach to pass and remove headers or params for sake of checksum calculation. You could pass a flag from higher level calls whether MD5 checksum calculation is required or not. You could add this improvement and remove these nested if
guesses.
|
||
if (!versionId.isEmpty()) { | ||
queryParamMap.put("versionId", versionId); | ||
} |
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.
Treat null
versionId as empty string to support minio server and add it into query param i.e.
if (versionId == null) {
queryParamMap.put("versionId", "");
} else {
queryParamMap.put("versionId", versionId);
}
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 have to use this logic in all methods accepting versionId
* @throws InvalidResponseException upon a non-xml response from server | ||
*/ | ||
public void setObjectRetention(String bucketName, String objectName, String versionId, | ||
boolean bypassGovernanceRetention, ObjectRetentionConfiguration config) |
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.
move this boolean
as last param looks like its optional.
headerMap.put("x-amz-bypass-governance-retention", "True"); | ||
} | ||
|
||
HttpResponse response = executePut(bucketName, objectName, headerMap, queryParamMap, config, 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.
config
must be non-null and Mode
and RetainUntilDate
are mandatory configuration. You would need to add this validation properly.
* @throws InvalidResponseException upon a non-xml response from server | ||
*/ | ||
public void setObjectLegalHold(String bucketName, String objectName, String versionId, | ||
boolean legalHold) |
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 would need to have below more friendlier APIs than boolean
flag
public void enableObjectLegalHold(String bucketName, String objectName, String versionId)
public void disableObjectLegalHold(String bucketName, String objectName, String versionId)
public boolean isObjectLegalHoldEnabled(String bucketName, String objectName, String versionId)
* Indicates whether the specified object has a Legal Hold in place. | ||
*/ | ||
public String getStatus() { | ||
return status; |
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 need to retrurn boolean
depending on status
; not string
stream = new BufferedInputStream(stream); | ||
} | ||
if (objectLockRetention) { | ||
headerMap.put("retention",""); |
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.
Two things you can do at the time of put object.
- retention (
Mode
andRetainUntilDate
are required) - legal hold (
boolean
to sayON
orOFF
)
You could send these changes in put object as separate PR.
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.
Will send a separate PR for this
47d23da
to
e6668cb
Compare
@balamurugana PTAL |
* Indicates whether the specified object has a Legal Hold in place or not. | ||
*/ | ||
public Boolean getStatus() { | ||
return Boolean.parseBoolean(status); |
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.
- have
status()
, notgetStatus()
- I don't see javadoc of
Boolean
parses"ON"
/"OFF"
string. Are you sure it works? - Return
boolean
notBoolean
/** | ||
* Constructs a new CustomRetention object with given retention. | ||
*/ | ||
public ObjectLockLegalHold(boolean legalHold) throws XmlPullParserException { |
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.
argument is status
not legalHold
public ObjectRetentionConfiguration(RetentionMode mode, DateTime retainUntilDate) throws XmlPullParserException, | ||
InvalidArgumentException { | ||
super(); | ||
super.name = "Retention"; |
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.
call this()
than repeating these two lines
*/ | ||
public ObjectLockLegalHold(boolean legalHold) throws XmlPullParserException { | ||
super(); | ||
super.name = "LegalHold"; |
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 this()
and don't repeat logic
super(); | ||
super.name = "Retention"; | ||
if (mode == null) { | ||
throw new InvalidArgumentException("null is not allowed in mode. Valid values are 'COMPLIANCE' and 'GOVERNANCE'"); |
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 error message as null mode is not allowed
} | ||
this.mode = mode.toString(); | ||
if (retainUntilDate == null) { | ||
throw new InvalidArgumentException("retain until date cant be null, it must be a valid date."); |
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 error message as null retainUntilDate is not allowed
/** | ||
* Returns retain until date. | ||
*/ | ||
public Date retainUntil() { |
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.
Method name should be same as member field retainUntilDate()
and return DateTime
not Date
i.e. should be same as argument type in the constructor
@@ -1402,11 +1400,12 @@ private HttpResponse executeDelete(String bucketName, String objectName, Map<Str | |||
* @param data HTTP request body data. | |||
*/ | |||
private HttpResponse executePost(String bucketName, String objectName, Map<String,String> headerMap, | |||
Map<String,String> queryParamMap, Object data) | |||
Map<String,String> queryParamMap, Object data, boolean md5Required) |
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.
Have overloaded executePost()
i.e. with/without md5Required
argument.
@@ -1439,13 +1438,13 @@ private HttpResponse executePost(String bucketName, String objectName, Map<Strin | |||
* @param length Length of HTTP request body data. | |||
*/ | |||
private HttpResponse executePut(String bucketName, String objectName, Map<String,String> headerMap, | |||
Map<String,String> queryParamMap, String region, Object data, int length) | |||
Map<String,String> queryParamMap, String region, Object data, int length, boolean md5Required) |
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.
Have overloaded executePut()
i.e. with/without md5Required
@@ -1461,11 +1460,12 @@ private HttpResponse executePut(String bucketName, String objectName, Map<String | |||
* @param length Length of HTTP request body data. | |||
*/ | |||
private HttpResponse executePut(String bucketName, String objectName, Map<String,String> headerMap, | |||
Map<String,String> queryParamMap, Object data, int length) | |||
Map<String,String> queryParamMap, Object data, int length, boolean md5Required) |
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.
Same as above
@@ -2388,7 +2388,7 @@ public void copyObject(String bucketName, String objectName, Map<String,String> | |||
headerMap.putAll(copyConditions.getConditions()); | |||
} | |||
|
|||
HttpResponse response = executePut(bucketName, objectName, headerMap, null, "", 0); | |||
HttpResponse response = executePut(bucketName, objectName, headerMap, null, "", 0, false); |
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 overloaded executePut()
/executePost()
accepting md5Required
argument to avoid unnecessary diffs.
e6668cb
to
1462c63
Compare
0f3cd29
to
bb595dd
Compare
* Returns mode. | ||
*/ | ||
public RetentionMode mode() { | ||
return RetentionMode.fromString(mode); |
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.
mode
can be null
. You need to return null
accordingly
if (status.equals("ON")) { | ||
return true; | ||
} | ||
return false; |
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.
return status != null && status.equals("ON");
is correct and sufficient
|
||
if ( !(versionId == null || versionId.isEmpty())) { | ||
queryParamMap.put("versionId",versionId); | ||
} |
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 don't know why you are missing out of versionId
handling. Are you deferring in other places?
* @throws InsufficientDataException upon getting EOFException while reading given | ||
*/ | ||
public void putObject(String bucketName, String objectName, String fileName, Long size, Map<String, String> headerMap, | ||
ServerSideEncryption sse, String contentType, boolean objectLockRetention) |
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.
As we agreed previously, you are going to send separate PR to have putObject()
with retention and legal hold. Are you still considering to add in this PR?
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.
Yes, that i will send as another PR.
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 so, why are doing this change 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.
If so, why are doing this change here?
This change is needed .
There are two cases to this flow:
User creates a bucket with lock function enabled.
Case 1 : User can put the object on the bucket and then at later point of time, set the retenetion. This case is handled in this PR.
Case 2 : User asks for retention/legalhold at the time of putting object. This will be handled in another PR.
If we dont have the below overloaded putObject then we wont be able to put the object on
lock enabled buckets and hence not able to test the PR.
public void putObject(String bucketName, String objectName, String fileName, Long size, Map<String, String> headerMap,
ServerSideEncryption sse, String contentType, boolean objectLockRetention)
If you think that case 2 should also be present in this PR , then i can come up with that .
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 cannot add any changes to putObject() if you plan for separate PR.
bb595dd
to
fc431eb
Compare
@balamurugana PTAL |
fffaeec
to
2c5206f
Compare
Add new method to set/get object retention and Legal Hold
Function test not added as it will make the object WORM enabled and cant be deleted after successful run of test.