-
Notifications
You must be signed in to change notification settings - Fork 2k
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
Initial checkin for Storage file #4414
Initial checkin for Storage file #4414
Conversation
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.
General question around the large model classes that were created, should they be simplified to only contain the most important pieces of information related to the service. If so remove the common HTTP headers as that information will still be available using the Response
class headers.
storage/client/file/src/main/java/com/azure/storage/file/DirectoryAsyncClient.java
Outdated
Show resolved
Hide resolved
storage/client/file/src/main/java/com/azure/storage/file/DirectoryClient.java
Outdated
Show resolved
Hide resolved
storage/client/file/src/main/java/com/azure/storage/file/DirectoryClientBuilder.java
Outdated
Show resolved
Hide resolved
storage/client/file/src/main/java/com/azure/storage/file/DirectoryClientBuilder.java
Outdated
Show resolved
Hide resolved
storage/client/file/src/main/java/com/azure/storage/file/DirectoryClientBuilder.java
Show resolved
Hide resolved
storage/client/file/src/main/java/com/azure/storage/file/models/FileProperties.java
Outdated
Show resolved
Hide resolved
storage/client/file/src/main/java/com/azure/storage/file/models/FileRange.java
Outdated
Show resolved
Hide resolved
storage/client/file/src/main/java/com/azure/storage/file/models/FileRange.java
Show resolved
Hide resolved
storage/client/file/src/main/java/com/azure/storage/file/models/FileRange.java
Outdated
Show resolved
Hide resolved
storage/client/file/src/main/java/com/azure/storage/file/models/FileRef.java
Outdated
Show resolved
Hide resolved
I have simplified the model class. Etag is the essential information we want to return. |
* @param directoryName Name of the directory | ||
* @param snapshot The snapshot of the share | ||
*/ | ||
DirectoryAsyncClient(AzureFileStorageImpl azureFileStorageClient, String shareName, String directoryName, String snapshot) { |
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 all of our constructors create their own builders? This leads us to a code path where we create a builder to pass all the relevant info to the client which creates a new builder with the same info to compile the relevant info correctly for the client. We can probably remove these extra steps.
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.
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.
Sima - I still see the builder code that James is calling out. What has been done 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.
I did not push the commit at the time you reviewed. It is there right now. Could you check?
} | ||
|
||
/** | ||
* Creates a directory in the storage account and returns a response of {@link DirectoryInfo} to interact with 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.
Convey that it creates the directory this client corresponds to, not just a directory. Also, the directory is technically created in the share. Two identical directory paths can exist in different shares. Perhaps Creates a directory in the storage account
--> Creates this directory in the file share
.
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.
public Mono<Response<DirectoryInfo>> setMetadata(Map<String, String> metadata) { | ||
throw new UnsupportedOperationException(); | ||
/** | ||
* Lists all directories and files in the storage account without their prefix or maxResult. |
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.
Lists all directories and files in the storage account
--> Lists all sub-directories and files in this directory
There are several instances where you scope the operation to the account, when it's really just to the contents of this directory. Be sure to address them. Additionally, double check the sync DirectoryClient for these issues as well.
* @param recursive Specifies operation should apply to the directory specified in the URI, its files, its subdirectories and their files. | ||
* @return {@link HandleItem handles} in the directory that satisfy the requirements | ||
*/ | ||
public Flux<HandleItem> getHandles(Integer maxResult, boolean recursive) { |
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.
maxResult
-> pageSize
While it's technically maxResult in REST, that's per paged request.
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'd prefer to address this across all storage SDK
* @param handleId Specifies the handle ID to be closed. Use an asterisk ('*') as a wildcard string to specify all handles. | ||
* @param recursive A boolean value that specifies if the operation should also apply to the files and subdirectories of the directory specified in the URI. | ||
* @return The counts of number of handles closed | ||
*/ | ||
public Flux<Integer> forceCloseHandles(String handleId, boolean recursive) { |
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 is technically correct according to the REST layer, but its usage is a bit flexible. For instance, handleId can be either the name of the handle to close, or *
, meaning close all handles. Additionally, recursive
doesn't make much sense if we've provided the specific handleId to close, and the REST endpoint actually has undefined behavior (unless they patched this) when both the wildcard and recursive=false are specified.
The way we handled this in track 1 was by exposing two different methods: forceCloseHandle(String handleId)
and forceCloseAllHandles(boolean recursive)
, supplying the appropriate missing parameter. This allowed us to better guide users to what is expected use.
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.
Issue created.
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 an issue is created, link to if when you reference it so other interested people can find it and subscribe / offer comments.
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.
Linked the issue in Java doc
* @return A response containing the subdirectory client and the status of creating the directory. | ||
* @throws StorageErrorException If the subdirectory has already existed, the parent directory does not exist or directory is an invalid resource name. | ||
*/ | ||
public Mono<Response<DirectoryAsyncClient>> createSubDirectory(String subDirectoryName) { |
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 this method call this.createSubDirectory(subDirectoryName, null)
. Same pattern we follow for overloads of service calls.
Similar comment for createFile()
.
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
*/ | ||
public Mono<Response<DirectoryAsyncClient>> createSubDirectory(String subDirectoryName, Map<String, String> metadata) { | ||
String directoryPath = directoryName + "/" + subDirectoryName; | ||
DirectoryAsyncClient createSubClient = new DirectoryAsyncClient(azureFileStorageClient, shareName, directoryPath, snapshot); |
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.
Just call getSubDirectoryClient()
. It's these exact lines.
Similar comment for createFile()
.
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
public Mono<VoidResponse> deleteFile(String fileName) { | ||
throw new UnsupportedOperationException(); | ||
String filePath = directoryName + "/" + fileName; | ||
FileAsyncClient fileAsyncClient = new FileAsyncClient(azureFileStorageClient, shareName, filePath, snapshot); |
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 before. We have methods for this logic. Just use them here and for deleting directories.
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.
this.sasTokenCredential = credential; | ||
return 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.
Where is the credential method that takes a SharedKeyCredential?
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.
Added.
* @param snapshot Identifier of the snapshot | ||
* @return the updated DirectoryClientBuilder object. | ||
*/ | ||
public DirectoryClientBuilder snapshot(String snapshot) { |
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 should probably specify that this is a snapshot of the file share, not the directory.
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.
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 seeing a lot of "done" comments that don't have the changes showing. I imagine this is because they haven't been pushed to GitHub. Please push the fixes, and consider my feedback, and then I will review again.
|
||
```Java | ||
fileClient.setHttpHeaders(httpHeaders); | ||
``` |
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 all these code samples be fleshed out? If not, I don't think they provide any value as single-line code samples.
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 will make up some necessary code.
Thanks for reminding.
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 has link in description which point to the place how we build a client.
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 will have more codes show how to build up the Object other than String type. e.g httpHeaders.
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.
storage/client/file/pom.xml
Outdated
<dependency> | ||
<groupId>org.slf4j</groupId> | ||
<artifactId>slf4j-api</artifactId> | ||
</dependency> |
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.
slf4j-api should come in transitively and not need to be included 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.
Removed.
storage/client/file/pom.xml
Outdated
<groupId>com.microsoft.azure</groupId> | ||
<artifactId>adal4j</artifactId> | ||
<scope>test</scope> | ||
</dependency> |
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 in queues - is slf4j-simple, reactor-test, and adal4j required 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.
reactor-test is necessary for async tests.
Removed adal4j , slf4j-simple
* <ul> | ||
* <li> If the HMAC-SHA256 signature for {@code sharedKeyCredentials} fails to generate. </li> | ||
* <li> If the an invalid key has been given to the client. </li> | ||
* </ul> |
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 to the left.
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
} catch (final NoSuchAlgorithmException e) { | ||
throw new RuntimeException("There is no such algorithm. Error Details: " + e.getMessage()); | ||
} catch (InvalidKeyException e) { | ||
throw new RuntimeException("Please double check the account key. Error details: " + e.getMessage()); |
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 clientLogger logAndThrow API
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.
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 log and throw API is not available to preview 2.
Issue opened. #4551
* <ul> | ||
* <li> There is only one null value for retryDelay and maxRetryDelay.<li/> | ||
* <li> Unrecognized retry policy type.<li/> | ||
* </ul> |
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 left.
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.
storage/client/file/src/main/java/com/azure/storage/file/DirectoryAsyncClient.java
Outdated
Show resolved
Hide resolved
* @param directoryName Name of the directory | ||
* @param snapshot The snapshot of the share | ||
*/ | ||
DirectoryAsyncClient(AzureFileStorageImpl azureFileStorageClient, String shareName, String directoryName, String snapshot) { |
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.
Sima - I still see the builder code that James is calling out. What has been done here?
* | ||
* {@codesnippet com.azure.storage.file.directoryAsyncClient.setMetadata#map.clearMetadata} | ||
* | ||
* @param metadata Optional. Metadata to set on the directory, if null is passed the metadata for the directory is cleared |
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.
Don't write these as "Optional. Metadata ..." - make it a full sentence, e.g. "Optional metadata to set on the directory..".
Do this in all cases where the "Optional. " approach is being used currently.
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.
* @param handleId Specifies the handle ID to be closed. Use an asterisk ('*') as a wildcard string to specify all handles. | ||
* @param recursive A boolean value that specifies if the operation should also apply to the files and subdirectories of the directory specified in the URI. | ||
* @return The counts of number of handles closed | ||
*/ | ||
public Flux<Integer> forceCloseHandles(String handleId, boolean recursive) { |
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 an issue is created, link to if when you reference it so other interested people can find it and subscribe / offer comments.
…toryAsyncClient.java Co-Authored-By: Jonathan Giles <[email protected]>
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.
Approving based on the major comments not being addressed in this PR being documented as issues.
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.
Given the approval of Rick, James, and Alan, this PR doesn't need me to cast my eyes over it also.
<Match> | ||
<Class name="~com\.azure\.(.+)Impl"/> | ||
<Bug pattern="NP_LOAD_OF_KNOWN_NULL_VALUE"/> | ||
</Match> |
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.
Don't duplicate the pattern - put it in the Or
clause above instead.
* Storage SAS implementation (#4404) * SAS implementation * Fixed some minor formatting issues * Fixed checkstyle problems and test issue * Remove RawClients from Blobs (#4375) Removes RawClients from Storage Blobs * Add deleteContainer to StorageClient and getBlobClient with Snapshot to ContainerClient (#4376) * Removed raw clients * Added deleteContainer to StorageClient * Added getAppendBlob with snapshot to ContainerClient * Storage queue linting, builder refactor, tests (#4383) * Initial check in for storage queue * Initial checkin for Storage file (#4414) * Finished the restructure, refactor builder. Added sleep in record feature. Linting * Merge Storage Blob Client Builders (#4468) Merges AppendBlobClientBuilder, BlobClientBuilder, BlockBlobClientBuilder, and PageBlobClientBuilder into a single builder class BlobClientBuilder. Additionally, JavaDoc comments for the other builder classes, ContainerClientBuilder and StorageAccountClientBuilder, were cleaned up and the way the endpoint is handled in builders was changed.
* Storage SAS implementation (#4404) * SAS implementation * Fixed some minor formatting issues * Fixed checkstyle problems and test issue * Remove RawClients from Blobs (#4375) Removes RawClients from Storage Blobs * Add storage swaggers * Update Storage to azure-core preview 3 * Add deleteContainer to StorageClient and getBlobClient with Snapshot to ContainerClient (#4376) * Removed raw clients * Added deleteContainer to StorageClient * Added getAppendBlob with snapshot to ContainerClient * Storage queue linting, builder refactor, tests (#4383) * Initial check in for storage queue * Address code review feedback in AutoRest * Initial checkin for Storage file (#4414) * Finished the restructure, refactor builder. Added sleep in record feature. Linting * Merge Storage Blob Client Builders (#4468) Merges AppendBlobClientBuilder, BlobClientBuilder, BlockBlobClientBuilder, and PageBlobClientBuilder into a single builder class BlobClientBuilder. Additionally, JavaDoc comments for the other builder classes, ContainerClientBuilder and StorageAccountClientBuilder, were cleaned up and the way the endpoint is handled in builders was changed. * Regenerate blob file queue after merge * Up azure core version for file & queue * Apply all the manual fixes in swagger * Change directoryName to directoryPath * Use non-fluent pattern for generated clients * Fix build after merging with master * Return void on setters * Revert spotbugs config change
Linting, Junit test, builder refactor