Refine on Recursive ACL. (#1501)

* SetRecursiveAcl refinement.

* Added UT for remove/update acl recursively

* Resolve test issues.

* Refine changelog

* Move SetAclRecursive to path

* Update readme

* Access Control List
This commit is contained in:
Kan Tang 2021-01-28 00:25:46 -08:00 committed by GitHub
parent 9c2d02244e
commit 98b15b820e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 348 additions and 55 deletions

View File

@ -15,6 +15,8 @@
- Added `Metadata`, `AccessType`, `HasImmutabilityPolicy`, `HasLegalHold`, `LeaseDuration`, `LeaseState` and `LeaseStatus` to `FileSystemItem`.
- Added new type `LeaseDurationType` to indicate if a lease duration is fixed or infinite.
- Added `RequestId` in each return type for REST API calls, except for concurrent APIs.
- Added `UpdateAccessControlListRecursiveSinglePage` to update the access control recursively for a datalake path.
- Added `RemoveAccessControlListRecursiveSinglePage` to remove the access control recursively for a datalake path.
### Breaking Changes
@ -32,6 +34,9 @@
- Changed all previous `LeaseDuration` members to a new type named `LeaseDurationType`.
- `startsOn` parameter for `GetUserDelegationKey` was changed to optional.
- Removed `PreviousContinuationToken` from `ListFileSystemsSinglePageResult`.
- Changed `SetAccessControlRecursive` to `SetAccessControlRecursiveListSinglePage`, to mark that it is a single page operation, and removed the `mode` parameter, separated the modify/delete functionality to two new APIs.
- Moved `SetAccessControlRecursiveListSinglePage` to `DataLakePathClient`.
- Changed `MaxRecord` to `MaxEntries`, `ForceFlag` to `ContinueOnFailure` to be more accurate names.
### Other Changes and Improvements

View File

@ -157,28 +157,6 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake {
bool recursive,
const DeleteDataLakeDirectoryOptions& options = DeleteDataLakeDirectoryOptions()) const;
/**
* @brief Sets POSIX access control rights on files and directories under given directory
* recursively.
* @param mode Mode PathSetAccessControlRecursiveMode::Set sets POSIX access control rights on
* files and directories, PathSetAccessControlRecursiveMode::Modify modifies one or more POSIX
* access control rights that pre-exist on files and directories,
* PathSetAccessControlRecursiveMode::Remove removes one or more POSIX access control rights
* that were present earlier on files and directories
* @param acls Sets POSIX access control rights on files and directories. Each access control
* entry (ACE) consists of a scope, a type, a user or group identifier, and permissions.
* @param options Optional parameters to set an access control recursively to the resource the
* directory points to.
* @return Azure::Core::Response<Models::SetDataLakeDirectoryAccessControlRecursiveResult>
* @remark This request is sent to dfs endpoint.
*/
Azure::Core::Response<Models::SetDataLakeDirectoryAccessControlRecursiveResult>
SetAccessControlRecursive(
Models::PathSetAccessControlRecursiveMode mode,
std::vector<Models::Acl> acls,
const SetDataLakeDirectoryAccessControlRecursiveOptions& options
= SetDataLakeDirectoryAccessControlRecursiveOptions()) const;
/**
* @brief List the paths in this file system.
* @param recursive If "true", all paths are listed; otherwise, the list will only
@ -200,6 +178,7 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake {
: DataLakePathClient(std::move(dfsUrl), std::move(blobClient), pipeline)
{
}
friend class DataLakeFileSystemClient;
};
}}}} // namespace Azure::Storage::Files::DataLake

View File

@ -697,9 +697,9 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake {
};
/**
* @brief Optional parameters for PathClient::SetAccessControlRecursive
* @brief Optional parameters for DirectoryClient::SetAccessControlRecursiveListSinglePage
*/
struct SetDataLakeDirectoryAccessControlRecursiveOptions
struct SetDataLakePathAccessControlRecursiveListSinglePageOptions
{
/**
* @brief Context for cancelling long running operations.
@ -721,18 +721,24 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake {
* be applied. If omitted or greater than 2,000, the request will process up to 2,000
* items.
*/
Azure::Core::Nullable<int32_t> MaxRecords;
Azure::Core::Nullable<int32_t> MaxEntries;
/**
* @brief Optional. Valid for "SetAccessControlRecursive" operation. If set to false, the
* operation will terminate quickly on encountering user errors (4XX). If true, the operation
* will ignore user errors and proceed with the operation on other sub-entities of the
* directory. Continuation token will only be returned when forceFlag is true in case of user
* errors. If not set the default value is false for this.
* @brief Optional. If set to false, the operation will terminate quickly on encountering user
* errors (4XX). If true, the operation will ignore user errors and proceed with the operation
* on other sub-entities of the directory. Continuation token will only be returned when
* ContinueOnFailure is true in case of user errors. If not set the default value is false for
* this.
*/
Azure::Core::Nullable<bool> ForceFlag;
Azure::Core::Nullable<bool> ContinueOnFailure;
};
using UpdateDataLakePathAccessControlRecursiveListSinglePageOptions
= SetDataLakePathAccessControlRecursiveListSinglePageOptions;
using RemoveDataLakePathAccessControlRecursiveListSinglePageOptions
= SetDataLakePathAccessControlRecursiveListSinglePageOptions;
using CreateDataLakeFileOptions = CreateDataLakePathOptions;
using CreateDataLakeDirectoryOptions = CreateDataLakePathOptions;

View File

@ -204,6 +204,69 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake {
Storage::Metadata metadata,
const SetDataLakePathMetadataOptions& options = SetDataLakePathMetadataOptions()) const;
/**
* @brief Sets POSIX access control rights on files and directories under given directory
* recursively.
* @param acls Sets POSIX access control rights on files and directories. Each access control
* entry (ACE) consists of a scope, a type, a user or group identifier, and permissions.
* @param options Optional parameters to set an access control recursively to the resource the
* directory points to.
* @return
* Azure::Core::Response<Models::SetDataLakePathAccessControlRecursiveListSinglePageResult>
* @remark This request is sent to dfs endpoint.
*/
Azure::Core::Response<Models::SetDataLakePathAccessControlRecursiveListSinglePageResult>
SetAccessControlRecursiveListSinglePage(
std::vector<Models::Acl> acls,
const SetDataLakePathAccessControlRecursiveListSinglePageOptions& options
= SetDataLakePathAccessControlRecursiveListSinglePageOptions()) const
{
return SetAccessControlRecursiveListSinglePageInternal(
Models::PathSetAccessControlRecursiveMode::Set, acls, options);
}
/**
* @brief Updates POSIX access control rights on files and directories under given directory
* recursively.
* @param acls Updates POSIX access control rights on files and directories. Each access control
* entry (ACE) consists of a scope, a type, a user or group identifier, and permissions.
* @param options Optional parameters to set an access control recursively to the resource the
* directory points to.
* @return
* Azure::Core::Response<Models::UpdateDataLakePathAccessControlRecursiveListSinglePageResult>
* @remark This request is sent to dfs endpoint.
*/
Azure::Core::Response<Models::UpdateDataLakePathAccessControlRecursiveListSinglePageResult>
UpdateAccessControlRecursiveListSinglePage(
std::vector<Models::Acl> acls,
const UpdateDataLakePathAccessControlRecursiveListSinglePageOptions& options
= UpdateDataLakePathAccessControlRecursiveListSinglePageOptions()) const
{
return SetAccessControlRecursiveListSinglePageInternal(
Models::PathSetAccessControlRecursiveMode::Modify, acls, options);
}
/**
* @brief Removes POSIX access control rights on files and directories under given directory
* recursively.
* @param acls Removes POSIX access control rights on files and directories. Each access control
* entry (ACE) consists of a scope, a type, a user or group identifier, and permissions.
* @param options Optional parameters to set an access control recursively to the resource the
* directory points to.
* @return
* Azure::Core::Response<Models::RemoveDataLakePathAccessControlRecursiveListSinglePageResult>
* @remark This request is sent to dfs endpoint.
*/
Azure::Core::Response<Models::RemoveDataLakePathAccessControlRecursiveListSinglePageResult>
RemoveAccessControlRecursiveListSinglePage(
std::vector<Models::Acl> acls,
const RemoveDataLakePathAccessControlRecursiveListSinglePageOptions& options
= RemoveDataLakePathAccessControlRecursiveListSinglePageOptions()) const
{
return SetAccessControlRecursiveListSinglePageInternal(
Models::PathSetAccessControlRecursiveMode::Remove, acls, options);
}
protected:
Azure::Core::Http::Url m_dfsUrl;
Blobs::BlobClient m_blobClient;
@ -218,6 +281,13 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake {
{
}
Azure::Core::Response<Models::SetDataLakePathAccessControlRecursiveListSinglePageResult>
SetAccessControlRecursiveListSinglePageInternal(
Models::PathSetAccessControlRecursiveMode mode,
std::vector<Models::Acl> acls,
const SetDataLakePathAccessControlRecursiveListSinglePageOptions& options
= SetDataLakePathAccessControlRecursiveListSinglePageOptions()) const;
friend class DataLakeFileSystemClient;
friend class DataLakeLeaseClient;
};

View File

@ -260,8 +260,12 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake { nam
std::string RequestId;
};
using SetDataLakeDirectoryAccessControlRecursiveResult
using SetDataLakePathAccessControlRecursiveListSinglePageResult
= Details::PathSetAccessControlRecursiveResult;
using UpdateDataLakePathAccessControlRecursiveListSinglePageResult
= SetDataLakePathAccessControlRecursiveListSinglePageResult;
using RemoveDataLakePathAccessControlRecursiveListSinglePageResult
= SetDataLakePathAccessControlRecursiveListSinglePageResult;
using CreateDataLakeDirectoryResult = CreateDataLakePathResult;
using DeleteDataLakeDirectoryResult = DeleteDataLakePathResult;

View File

@ -208,22 +208,6 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake {
return DataLakePathClient::DeleteIfExists(deleteOptions);
}
Azure::Core::Response<Models::SetDataLakeDirectoryAccessControlRecursiveResult>
DataLakeDirectoryClient::SetAccessControlRecursive(
Models::PathSetAccessControlRecursiveMode mode,
std::vector<Models::Acl> acls,
const SetDataLakeDirectoryAccessControlRecursiveOptions& options) const
{
Details::DataLakeRestClient::Path::SetAccessControlRecursiveOptions protocolLayerOptions;
protocolLayerOptions.Mode = mode;
protocolLayerOptions.ContinuationToken = options.ContinuationToken;
protocolLayerOptions.MaxRecords = options.MaxRecords;
protocolLayerOptions.ForceFlag = options.ForceFlag;
protocolLayerOptions.Acl = Models::Acl::SerializeAcls(acls);
return Details::DataLakeRestClient::Path::SetAccessControlRecursive(
m_dfsUrl, *m_pipeline, options.Context, protocolLayerOptions);
}
Azure::Core::Response<Models::ListPathsSinglePageResult> DataLakeDirectoryClient::
ListPathsSinglePage(bool recursive, const ListPathsSinglePageOptions& options) const
{

View File

@ -457,4 +457,21 @@ namespace Azure { namespace Storage { namespace Files { namespace DataLake {
return Azure::Core::Response<Models::SetDataLakePathMetadataResult>(
std::move(ret), result.ExtractRawResponse());
}
Azure::Core::Response<Models::SetDataLakePathAccessControlRecursiveListSinglePageResult>
DataLakePathClient::SetAccessControlRecursiveListSinglePageInternal(
Models::PathSetAccessControlRecursiveMode mode,
std::vector<Models::Acl> acls,
const SetDataLakePathAccessControlRecursiveListSinglePageOptions& options) const
{
Details::DataLakeRestClient::Path::SetAccessControlRecursiveOptions protocolLayerOptions;
protocolLayerOptions.Mode = mode;
protocolLayerOptions.ContinuationToken = options.ContinuationToken;
protocolLayerOptions.MaxRecords = options.MaxEntries;
protocolLayerOptions.ForceFlag = options.ContinueOnFailure;
protocolLayerOptions.Acl = Models::Acl::SerializeAcls(acls);
return Details::DataLakeRestClient::Path::SetAccessControlRecursive(
m_dfsUrl, *m_pipeline, options.Context, protocolLayerOptions);
}
}}}} // namespace Azure::Storage::Files::DataLake

View File

@ -326,7 +326,7 @@ namespace Azure { namespace Storage { namespace Test {
}
}
TEST_F(DataLakeDirectoryClientTest, DirectorySetAccessControlRecursive)
TEST_F(DataLakeDirectoryClientTest, DirectoryAccessControlRecursive)
{
// Setup directories.
auto rootDirectoryName = RandomString();
@ -342,11 +342,9 @@ namespace Azure { namespace Storage { namespace Test {
directoryClient2.Create();
{
// Set/Get Acls recursive works.
// Set Acls recursive.
std::vector<Files::DataLake::Models::Acl> acls = GetValidAcls();
EXPECT_NO_THROW(directoryClient1.SetAccessControlList(acls));
EXPECT_NO_THROW(rootDirectoryClient.SetAccessControlRecursive(
Files::DataLake::Models::PathSetAccessControlRecursiveMode::Modify, acls));
EXPECT_NO_THROW(rootDirectoryClient.SetAccessControlRecursiveListSinglePage(acls));
std::vector<Files::DataLake::Models::Acl> resultAcls1;
std::vector<Files::DataLake::Models::Acl> resultAcls2;
EXPECT_NO_THROW(resultAcls1 = directoryClient1.GetAccessControlList()->Acls);
@ -364,12 +362,243 @@ namespace Azure { namespace Storage { namespace Test {
EXPECT_EQ(iter->Permissions, acl.Permissions);
}
}
{
// Update Acls recursive.
std::vector<Files::DataLake::Models::Acl> originalAcls = GetValidAcls();
Files::DataLake::Models::Acl newAcl;
newAcl.Type = "group";
newAcl.Id = "";
newAcl.Permissions = "rw-";
std::vector<Files::DataLake::Models::Acl> acls;
acls.emplace_back(std::move(newAcl));
EXPECT_NO_THROW(rootDirectoryClient.UpdateAccessControlRecursiveListSinglePage(acls));
std::vector<Files::DataLake::Models::Acl> resultAcls1;
std::vector<Files::DataLake::Models::Acl> resultAcls2;
EXPECT_NO_THROW(resultAcls1 = directoryClient1.GetAccessControlList()->Acls);
EXPECT_NO_THROW(resultAcls2 = directoryClient2.GetAccessControlList()->Acls);
for (const auto& acl : resultAcls2)
{
auto iter = std::find_if(
resultAcls1.begin(),
resultAcls1.end(),
[&acl](const Files::DataLake::Models::Acl& targetAcl) {
return (targetAcl.Type == acl.Type) && (targetAcl.Id == acl.Id)
&& (targetAcl.Scope == acl.Scope);
});
EXPECT_TRUE(iter != resultAcls1.end());
EXPECT_EQ(iter->Permissions, acl.Permissions);
}
{
// verify group has changed
auto groupFinder = [](const Files::DataLake::Models::Acl& targetAcl) {
return targetAcl.Type == "group";
};
auto iter = std::find_if(resultAcls1.begin(), resultAcls1.end(), groupFinder);
EXPECT_TRUE(iter != resultAcls1.end());
EXPECT_EQ("rw-", iter->Permissions);
iter = std::find_if(resultAcls2.begin(), resultAcls2.end(), groupFinder);
EXPECT_TRUE(iter != resultAcls2.end());
EXPECT_EQ("rw-", iter->Permissions);
}
{
// verify other has not changed
{
auto otherFinder = [](const Files::DataLake::Models::Acl& targetAcl) {
return targetAcl.Type == "other";
};
auto iter = std::find_if(resultAcls1.begin(), resultAcls1.end(), otherFinder);
EXPECT_TRUE(iter != resultAcls1.end());
EXPECT_EQ(originalAcls[3].Permissions, iter->Permissions);
iter = std::find_if(resultAcls2.begin(), resultAcls2.end(), otherFinder);
EXPECT_TRUE(iter != resultAcls2.end());
EXPECT_EQ(originalAcls[3].Permissions, iter->Permissions);
}
{
auto userFinder = [](const Files::DataLake::Models::Acl& targetAcl) {
return targetAcl.Type == "user";
};
auto iter = std::find_if(resultAcls1.begin(), resultAcls1.end(), userFinder);
EXPECT_TRUE(iter != resultAcls1.end());
if (iter->Id == originalAcls[0].Id)
{
EXPECT_EQ(originalAcls[0].Permissions, iter->Permissions);
}
else
{
EXPECT_EQ(originalAcls[1].Permissions, iter->Permissions);
}
iter = std::find_if(resultAcls2.begin(), resultAcls2.end(), userFinder);
EXPECT_TRUE(iter != resultAcls2.end());
if (iter->Id == originalAcls[0].Id)
{
EXPECT_EQ(originalAcls[0].Permissions, iter->Permissions);
}
else
{
EXPECT_EQ(originalAcls[1].Permissions, iter->Permissions);
}
}
}
}
{
// Remove Acls recursive.
std::vector<Files::DataLake::Models::Acl> originalAcls = GetValidAcls();
Files::DataLake::Models::Acl removeAcl;
removeAcl.Type = "user";
removeAcl.Id = "72a3f86f-271f-439e-b031-25678907d381";
std::vector<Files::DataLake::Models::Acl> acls;
acls.emplace_back(std::move(removeAcl));
EXPECT_NO_THROW(rootDirectoryClient.RemoveAccessControlRecursiveListSinglePage(acls));
std::vector<Files::DataLake::Models::Acl> resultAcls1;
std::vector<Files::DataLake::Models::Acl> resultAcls2;
EXPECT_NO_THROW(resultAcls1 = directoryClient1.GetAccessControlList()->Acls);
EXPECT_NO_THROW(resultAcls2 = directoryClient2.GetAccessControlList()->Acls);
for (const auto& acl : resultAcls2)
{
auto iter = std::find_if(
resultAcls1.begin(),
resultAcls1.end(),
[&acl](const Files::DataLake::Models::Acl& targetAcl) {
return (targetAcl.Type == acl.Type) && (targetAcl.Id == acl.Id)
&& (targetAcl.Scope == acl.Scope);
});
EXPECT_TRUE(iter != resultAcls1.end());
EXPECT_EQ(iter->Permissions, acl.Permissions);
}
{
// verify group policy has been removed.
auto userFinder = [](const Files::DataLake::Models::Acl& targetAcl) {
return targetAcl.Type == "user" && targetAcl.Id == "72a3f86f-271f-439e-b031-25678907d381";
};
auto iter = std::find_if(resultAcls1.begin(), resultAcls1.end(), userFinder);
EXPECT_TRUE(iter == resultAcls1.end());
iter = std::find_if(resultAcls2.begin(), resultAcls2.end(), userFinder);
EXPECT_TRUE(iter == resultAcls2.end());
}
{
// verify other has not changed
{
auto otherFinder = [](const Files::DataLake::Models::Acl& targetAcl) {
return targetAcl.Type == "other";
};
auto iter = std::find_if(resultAcls1.begin(), resultAcls1.end(), otherFinder);
EXPECT_TRUE(iter != resultAcls1.end());
EXPECT_EQ(originalAcls[3].Permissions, iter->Permissions);
iter = std::find_if(resultAcls2.begin(), resultAcls2.end(), otherFinder);
EXPECT_TRUE(iter != resultAcls2.end());
EXPECT_EQ(originalAcls[3].Permissions, iter->Permissions);
}
{
auto userFinder = [](const Files::DataLake::Models::Acl& targetAcl) {
return targetAcl.Type == "user";
};
auto iter = std::find_if(resultAcls1.begin(), resultAcls1.end(), userFinder);
EXPECT_TRUE(iter != resultAcls1.end());
EXPECT_EQ(originalAcls[1].Id, iter->Id);
EXPECT_EQ(originalAcls[1].Permissions, iter->Permissions);
iter = std::find_if(resultAcls2.begin(), resultAcls2.end(), userFinder);
EXPECT_TRUE(iter != resultAcls2.end());
EXPECT_EQ(originalAcls[1].Id, iter->Id);
EXPECT_EQ(originalAcls[1].Permissions, iter->Permissions);
}
}
}
{
// Set Acls recursive, with new set of acls
std::vector<Files::DataLake::Models::Acl> acls;
{
Files::DataLake::Models::Acl newAcl;
newAcl.Type = "user";
newAcl.Permissions = "rw-";
acls.emplace_back(std::move(newAcl));
}
{
Files::DataLake::Models::Acl newAcl;
newAcl.Type = "group";
newAcl.Permissions = "rw-";
acls.emplace_back(std::move(newAcl));
}
{
Files::DataLake::Models::Acl newAcl;
newAcl.Type = "other";
newAcl.Permissions = "rw-";
acls.emplace_back(std::move(newAcl));
}
(rootDirectoryClient.SetAccessControlRecursiveListSinglePage(acls));
std::vector<Files::DataLake::Models::Acl> resultAcls1;
std::vector<Files::DataLake::Models::Acl> resultAcls2;
EXPECT_NO_THROW(resultAcls1 = directoryClient1.GetAccessControlList()->Acls);
EXPECT_NO_THROW(resultAcls2 = directoryClient2.GetAccessControlList()->Acls);
for (const auto& acl : resultAcls2)
{
auto iter = std::find_if(
resultAcls1.begin(),
resultAcls1.end(),
[&acl](const Files::DataLake::Models::Acl& targetAcl) {
return (targetAcl.Type == acl.Type) && (targetAcl.Id == acl.Id)
&& (targetAcl.Scope == acl.Scope);
});
EXPECT_TRUE(iter != resultAcls1.end());
EXPECT_EQ(iter->Permissions, acl.Permissions);
}
{
// verify group has changed
auto groupFinder = [](const Files::DataLake::Models::Acl& targetAcl) {
return targetAcl.Type == "group";
};
auto iter = std::find_if(resultAcls1.begin(), resultAcls1.end(), groupFinder);
EXPECT_TRUE(iter != resultAcls1.end());
EXPECT_EQ("rw-", iter->Permissions);
EXPECT_EQ("", iter->Id);
iter = std::find_if(resultAcls2.begin(), resultAcls2.end(), groupFinder);
EXPECT_EQ("rw-", iter->Permissions);
EXPECT_EQ("", iter->Id);
}
{
// verify other has changed
auto otherFinder = [](const Files::DataLake::Models::Acl& targetAcl) {
return targetAcl.Type == "other";
};
auto iter = std::find_if(resultAcls1.begin(), resultAcls1.end(), otherFinder);
EXPECT_TRUE(iter != resultAcls1.end());
EXPECT_EQ("rw-", iter->Permissions);
EXPECT_EQ("", iter->Id);
iter = std::find_if(resultAcls2.begin(), resultAcls2.end(), otherFinder);
EXPECT_EQ("rw-", iter->Permissions);
EXPECT_EQ("", iter->Id);
}
{
// verify user has only one entry
std::vector<Files::DataLake::Models::Acl> originalAcls = GetValidAcls();
auto userFinder = [&originalAcls](const Files::DataLake::Models::Acl& targetAcl) {
return targetAcl.Type == "user" && targetAcl.Id == originalAcls[0].Id;
};
auto iter = std::find_if(resultAcls1.begin(), resultAcls1.end(), userFinder);
EXPECT_TRUE(iter == resultAcls1.end());
iter = std::find_if(resultAcls2.begin(), resultAcls2.end(), userFinder);
EXPECT_TRUE(iter == resultAcls2.end());
}
{
// verify user has changed
auto userFinder = [](const Files::DataLake::Models::Acl& targetAcl) {
return targetAcl.Type == "user";
};
auto iter = std::find_if(resultAcls1.begin(), resultAcls1.end(), userFinder);
EXPECT_TRUE(iter != resultAcls1.end());
EXPECT_EQ("rw-", iter->Permissions);
EXPECT_EQ("", iter->Id);
iter = std::find_if(resultAcls2.begin(), resultAcls2.end(), userFinder);
EXPECT_EQ("rw-", iter->Permissions);
EXPECT_EQ("", iter->Id);
}
}
}
TEST_F(DataLakeDirectoryClientTest, ConstructorsWorks)
{
{
// Create from connection string validates static creator function and shared key constructor.
// Create from connection string validates static creator function and shared key
// constructor.
auto directoryName = RandomString(10);
auto connectionStringClient
= Azure::Storage::Files::DataLake::DataLakeDirectoryClient::CreateFromConnectionString(
@ -415,5 +644,4 @@ namespace Azure { namespace Storage { namespace Test {
EXPECT_NO_THROW(anonymousClient.GetProperties());
}
}
}}} // namespace Azure::Storage::Test