Adding support for creating, getting and deleting folders via the storage client
Implements: blueprint storage-folder-support Change-Id: Ie666b995cfb3dcf45dcf684908c9f0e455596d06
This commit is contained in:
parent
a469ad406c
commit
b17cddd189
|
@ -14,6 +14,8 @@
|
|||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
using System.IO;
|
||||
|
||||
namespace Openstack.Test.Storage
|
||||
{
|
||||
using System;
|
||||
|
@ -213,7 +215,7 @@ namespace Openstack.Test.Storage
|
|||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CanConvertFolders()
|
||||
public void CanConvertFoldersWithObjects()
|
||||
{
|
||||
var objects = new List<StorageObject>()
|
||||
{
|
||||
|
@ -261,5 +263,170 @@ namespace Openstack.Test.Storage
|
|||
var converter = new StorageFolderPayloadConverter();
|
||||
var resp = converter.Convert(null);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CanConvertFolderWithValidJsonAndNoSubFoldersOrFolderObject()
|
||||
{
|
||||
var containerName = "container";
|
||||
var folderName = "a/b/c/";
|
||||
var payload = @"[
|
||||
{
|
||||
""hash"": ""d41d8cd98f00b204e9800998ecf8427e"",
|
||||
""last_modified"": ""2014-03-07T21:31:31.588170"",
|
||||
""bytes"": 0,
|
||||
""name"": ""a/b/c/BLAH"",
|
||||
""content_type"": ""application/octet-stream""
|
||||
}]";
|
||||
|
||||
var converter = new StorageFolderPayloadConverter();
|
||||
var resp = converter.Convert(containerName, folderName, payload);
|
||||
|
||||
Assert.AreEqual(1, resp.Objects.Count);
|
||||
Assert.AreEqual(0, resp.Folders.Count);
|
||||
Assert.AreEqual("a/b/c", resp.FullName);
|
||||
Assert.AreEqual("c", resp.Name);
|
||||
|
||||
var obj = resp.Objects.First();
|
||||
Assert.AreEqual("a/b/c/BLAH", obj.Name);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(InvalidDataException))]
|
||||
public void CannotConvertEmptyJsonArrayPayload()
|
||||
{
|
||||
var containerName = "container";
|
||||
var folderName = "a/b/c/";
|
||||
var payload = @"[]";
|
||||
|
||||
var converter = new StorageFolderPayloadConverter();
|
||||
converter.Convert(containerName, folderName, payload);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CanConvertFolderWithValidJsonFolderObjectAndNoSubFolders()
|
||||
{
|
||||
var containerName = "container";
|
||||
var folderName = "a/b/c/";
|
||||
var payload = @"[
|
||||
{
|
||||
""hash"": ""d41d8cd98f00b204e9800998ecf8427e"",
|
||||
""last_modified"": ""2014-03-07T21:31:31.588170"",
|
||||
""bytes"": 0,
|
||||
""name"": ""a/b/c/"",
|
||||
""content_type"": ""application/octet-stream""
|
||||
},
|
||||
{
|
||||
""hash"": ""d41d8cd98f00b204e9800998ecf8427e"",
|
||||
""last_modified"": ""2014-03-07T21:31:31.588170"",
|
||||
""bytes"": 0,
|
||||
""name"": ""a/b/c/BLAH"",
|
||||
""content_type"": ""application/octet-stream""
|
||||
}]";
|
||||
|
||||
var converter = new StorageFolderPayloadConverter();
|
||||
var resp = converter.Convert(containerName, folderName, payload);
|
||||
|
||||
Assert.AreEqual(1, resp.Objects.Count);
|
||||
Assert.AreEqual(0, resp.Folders.Count);
|
||||
Assert.AreEqual("a/b/c", resp.FullName);
|
||||
Assert.AreEqual("c", resp.Name);
|
||||
|
||||
var obj = resp.Objects.First();
|
||||
Assert.AreEqual("a/b/c/BLAH", obj.Name);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CanConvertFolderWithValidJsonSubFoldersAndNoFolderObject()
|
||||
{
|
||||
var containerName = "container";
|
||||
var folderName = "a/b/c/";
|
||||
var payload = @"[
|
||||
{
|
||||
""hash"": ""d41d8cd98f00b204e9800998ecf8427e"",
|
||||
""last_modified"": ""2014-03-07T21:31:31.588170"",
|
||||
""bytes"": 0,
|
||||
""name"": ""a/b/c/BLAH"",
|
||||
""content_type"": ""application/octet-stream""
|
||||
},
|
||||
{
|
||||
""subdir"": ""a/b/c/d/""
|
||||
},
|
||||
{
|
||||
""subdir"": ""a/b/c/x/""
|
||||
}]";
|
||||
|
||||
var converter = new StorageFolderPayloadConverter();
|
||||
var resp = converter.Convert(containerName, folderName, payload);
|
||||
|
||||
Assert.AreEqual(1, resp.Objects.Count);
|
||||
Assert.AreEqual(2, resp.Folders.Count);
|
||||
Assert.AreEqual("a/b/c", resp.FullName);
|
||||
Assert.AreEqual("c", resp.Name);
|
||||
|
||||
var obj = resp.Objects.First();
|
||||
Assert.AreEqual("a/b/c/BLAH", obj.Name);
|
||||
|
||||
var dNode = resp.Folders.First(f => f.FullName == "a/b/c/d");
|
||||
var xNode = resp.Folders.First(f => f.FullName == "a/b/c/x");
|
||||
|
||||
Assert.AreEqual("d", dNode.Name);
|
||||
Assert.AreEqual(0, dNode.Folders.Count);
|
||||
Assert.AreEqual(0, dNode.Objects.Count);
|
||||
|
||||
Assert.AreEqual("x", xNode.Name);
|
||||
Assert.AreEqual(0, xNode.Folders.Count);
|
||||
Assert.AreEqual(0, xNode.Objects.Count);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CanConvertFolderWithValidJsonFolderObjectAndSubFolders()
|
||||
{
|
||||
var containerName = "container";
|
||||
var folderName = "a/b/c/";
|
||||
var payload = @"[
|
||||
{
|
||||
""hash"": ""d41d8cd98f00b204e9800998ecf8427e"",
|
||||
""last_modified"": ""2014-03-07T21:31:31.588170"",
|
||||
""bytes"": 0,
|
||||
""name"": ""a/b/c/"",
|
||||
""content_type"": ""application/octet-stream""
|
||||
},
|
||||
{
|
||||
""hash"": ""d41d8cd98f00b204e9800998ecf8427e"",
|
||||
""last_modified"": ""2014-03-07T21:31:31.588170"",
|
||||
""bytes"": 0,
|
||||
""name"": ""a/b/c/BLAH"",
|
||||
""content_type"": ""application/octet-stream""
|
||||
},
|
||||
{
|
||||
""subdir"": ""a/b/c/d/""
|
||||
},
|
||||
{
|
||||
""subdir"": ""a/b/c/x/""
|
||||
}
|
||||
]";
|
||||
|
||||
var converter = new StorageFolderPayloadConverter();
|
||||
var resp = converter.Convert(containerName, folderName, payload);
|
||||
|
||||
Assert.AreEqual("c", resp.Name);
|
||||
Assert.AreEqual("a/b/c", resp.FullName);
|
||||
Assert.AreEqual(1, resp.Objects.Count);
|
||||
Assert.AreEqual(2, resp.Folders.Count);
|
||||
|
||||
var obj = resp.Objects.First();
|
||||
Assert.AreEqual("a/b/c/BLAH", obj.Name);
|
||||
|
||||
var dNode = resp.Folders.First(f => f.FullName == "a/b/c/d");
|
||||
var xNode = resp.Folders.First(f => f.FullName == "a/b/c/x");
|
||||
|
||||
Assert.AreEqual("d", dNode.Name);
|
||||
Assert.AreEqual(0, dNode.Folders.Count);
|
||||
Assert.AreEqual(0, dNode.Objects.Count);
|
||||
|
||||
Assert.AreEqual("x", xNode.Name);
|
||||
Assert.AreEqual(0, xNode.Folders.Count);
|
||||
Assert.AreEqual(0, xNode.Objects.Count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -373,17 +373,15 @@ namespace Openstack.Test.Storage
|
|||
|
||||
if (objectName != null)
|
||||
{
|
||||
if (!this.Objects.ContainsKey(objectName))
|
||||
{
|
||||
return TestHelper.CreateResponse(HttpStatusCode.NotFound);
|
||||
}
|
||||
|
||||
var obj = this.Objects[objectName];
|
||||
var objectHeaders = GenerateObjectResponseHeaders(obj);
|
||||
|
||||
return TestHelper.CreateResponse(HttpStatusCode.OK, objectHeaders, obj.Content);
|
||||
return this.GetObject(objectName);
|
||||
}
|
||||
|
||||
var query = this.Uri.ParseQueryString();
|
||||
if (query.HasKeys() && query["prefix"] != null && query["delimiter"] != null)
|
||||
{
|
||||
return this.GetObject(query["prefix"]);
|
||||
}
|
||||
|
||||
if (!this.Containers.ContainsKey(containerName))
|
||||
{
|
||||
return TestHelper.CreateResponse(HttpStatusCode.NotFound);
|
||||
|
@ -396,6 +394,19 @@ namespace Openstack.Test.Storage
|
|||
return TestHelper.CreateResponse(HttpStatusCode.OK, headers, content);
|
||||
}
|
||||
|
||||
public IHttpResponseAbstraction GetObject(string objectName)
|
||||
{
|
||||
if (!this.Objects.ContainsKey(objectName))
|
||||
{
|
||||
return TestHelper.CreateResponse(HttpStatusCode.NotFound);
|
||||
}
|
||||
|
||||
var obj = this.Objects[objectName];
|
||||
var objectHeaders = GenerateObjectResponseHeaders(obj);
|
||||
|
||||
return TestHelper.CreateResponse(HttpStatusCode.OK, objectHeaders, obj.Content);
|
||||
}
|
||||
|
||||
public string GetContainerName(string[] uriSegments)
|
||||
{
|
||||
return uriSegments.Count() < 4 ? null : uriSegments[3].TrimEnd('/');
|
||||
|
|
|
@ -218,6 +218,88 @@ namespace Openstack.Test.Storage
|
|||
await client.GetStorageObject(containerName, string.Empty);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task CanGetStorageFolder()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var folderName = "TestFolder/";
|
||||
|
||||
var obj = new StorageFolder(folderName, new List<StorageFolder>());
|
||||
|
||||
this.ServicePocoClient.GetStorageFolderDelegate = (s, s1) =>
|
||||
{
|
||||
Assert.AreEqual(s, containerName);
|
||||
Assert.AreEqual(s1, folderName);
|
||||
return Task.Factory.StartNew(() => obj);
|
||||
};
|
||||
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
var resp = await client.GetStorageFolder(containerName, folderName);
|
||||
|
||||
Assert.AreEqual(obj, resp);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task CanGetStorageFolderWithoutTrailingSlash()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var folderName = "TestFolder";
|
||||
|
||||
var obj = new StorageFolder(folderName, new List<StorageFolder>());
|
||||
|
||||
this.ServicePocoClient.GetStorageFolderDelegate = (s, s1) =>
|
||||
{
|
||||
Assert.AreEqual(s, containerName);
|
||||
Assert.AreEqual(s1, folderName +"/");
|
||||
return Task.Factory.StartNew(() => obj);
|
||||
};
|
||||
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
var resp = await client.GetStorageFolder(containerName, folderName);
|
||||
|
||||
Assert.AreEqual(obj, resp);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public async Task GettingStorageFolderWithNullContainerNameThrows()
|
||||
{
|
||||
var folderName = "TestFolder";
|
||||
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
await client.GetStorageFolder(null, folderName);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentException))]
|
||||
public async Task GettingStorageFolderWithEmptyContainerNameThrows()
|
||||
{
|
||||
var folderName = "TestFolder";
|
||||
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
await client.GetStorageFolder(string.Empty, folderName);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public async Task GettingStorageFolderWithNullObjectNameThrows()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
await client.GetStorageFolder(containerName, null);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentException))]
|
||||
public async Task GettingStorageFolderWithEmptyObjectNameThrows()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
await client.GetStorageFolder(containerName, string.Empty);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task CanCreateStorageObjects()
|
||||
{
|
||||
|
@ -304,6 +386,99 @@ namespace Openstack.Test.Storage
|
|||
await client.CreateStorageObject(containerName, objectName, null, new MemoryStream());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task CanCreateStorageFolder()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var folderName = "TestFolder/";
|
||||
|
||||
var obj = new StorageFolder(folderName, new List<StorageFolder>());
|
||||
|
||||
this.ServicePocoClient.CreateStorageFolderDelegate = async (s, s1) =>
|
||||
{
|
||||
await Task.Run(() =>
|
||||
{
|
||||
Assert.AreEqual(s1, folderName);
|
||||
Assert.AreEqual(s, containerName);
|
||||
});
|
||||
};
|
||||
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
await client.CreateStorageFolder(containerName, folderName);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task CanCreateStorageFolderWithoutTrailingSlash()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var folderName = "TestFolder";
|
||||
|
||||
var obj = new StorageFolder(folderName, new List<StorageFolder>());
|
||||
|
||||
this.ServicePocoClient.CreateStorageFolderDelegate = async (s, s1) =>
|
||||
{
|
||||
await Task.Run(() =>
|
||||
{
|
||||
Assert.AreEqual(s1, folderName +"/");
|
||||
Assert.AreEqual(s, containerName);
|
||||
});
|
||||
};
|
||||
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
await client.CreateStorageFolder(containerName, folderName);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentException))]
|
||||
public async Task CreatingStorageFolderWithInvalidFolderNameThrows()
|
||||
{
|
||||
var containerName = "someContainer";
|
||||
var folderName = "Test//Folder";
|
||||
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
await client.CreateStorageFolder(containerName, folderName);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public async Task CreatingStorageFolderWithNullContainerNameThrows()
|
||||
{
|
||||
var folderName = "TestFolder";
|
||||
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
await client.CreateStorageFolder(null, folderName);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentException))]
|
||||
public async Task CreatingStorageFolderWithEmptyContainerNameThrows()
|
||||
{
|
||||
var folderName = "TestFolder";
|
||||
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
await client.CreateStorageFolder(string.Empty, folderName);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public async Task CreatingStorageFolderWithNullObjectNameThrows()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
await client.CreateStorageFolder(containerName, null);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentException))]
|
||||
public async Task CreatingStorageFolderWithEmptyObjectNameThrows()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
await client.CreateStorageFolder(containerName, string.Empty);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task CanCreateStorageContainers()
|
||||
{
|
||||
|
@ -490,6 +665,76 @@ namespace Openstack.Test.Storage
|
|||
await client.DeleteStorageObject("TestContainer", string.Empty);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task CanDeleteStorageFolder()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var folderName = "TestFolder/";
|
||||
|
||||
this.ServicePocoClient.DeleteStorageFolderDelegate = async (s, s1) =>
|
||||
{
|
||||
await Task.Run(() =>
|
||||
{
|
||||
Assert.AreEqual(s, containerName);
|
||||
Assert.AreEqual(s1, folderName);
|
||||
});
|
||||
};
|
||||
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
await client.DeleteStorageFolder(containerName, folderName);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task CanDeleteStorageFolderWithoutTrailingSlash()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var folderName = "TestFolder";
|
||||
|
||||
this.ServicePocoClient.DeleteStorageFolderDelegate = async (s, s1) =>
|
||||
{
|
||||
await Task.Run(() =>
|
||||
{
|
||||
Assert.AreEqual(s, containerName);
|
||||
Assert.AreEqual(s1, folderName +"/");
|
||||
});
|
||||
};
|
||||
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
await client.DeleteStorageFolder(containerName, folderName);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public async Task DeletingStorageFolderWithNullContainerNameThrows()
|
||||
{
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
await client.DeleteStorageFolder(null, "TestFolder");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentException))]
|
||||
public async Task DeletingStorageFolderWithEmptyContainerNameThrows()
|
||||
{
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
await client.DeleteStorageFolder(string.Empty, "TestFolder");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public async Task DeletingStorageFolderWithNullObjectNameThrows()
|
||||
{
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
await client.DeleteStorageFolder("TestContainer", null);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentException))]
|
||||
public async Task DeletingStorageFolderWithEmptyObjectNameThrows()
|
||||
{
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
await client.DeleteStorageFolder("TestContainer", string.Empty);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task CanUpdateStorageObject()
|
||||
{
|
||||
|
|
|
@ -551,6 +551,233 @@ namespace Openstack.Test.Storage
|
|||
await client.GetStorageObject("container", string.Empty);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Get Storage Folder Tests
|
||||
|
||||
[TestMethod]
|
||||
public async Task CanGetStorageFolderWithOkResponseAndNoSubFolders()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var folderName = "a/b/c/";
|
||||
var headers = new HttpHeadersAbstraction()
|
||||
{
|
||||
{"X-Container-Bytes-Used", "1234"},
|
||||
{"X-Container-Object-Count", "1"}
|
||||
};
|
||||
|
||||
var payload = @"[
|
||||
{
|
||||
""hash"": ""d41d8cd98f00b204e9800998ecf8427e"",
|
||||
""last_modified"": ""2014-03-07T21:31:31.588170"",
|
||||
""bytes"": 0,
|
||||
""name"": ""a/b/c/BLAH"",
|
||||
""content_type"": ""application/octet-stream""
|
||||
}]";
|
||||
|
||||
var content = TestHelper.CreateStream(payload);
|
||||
|
||||
var restResp = new HttpResponseAbstraction(content, headers, HttpStatusCode.OK);
|
||||
this.StorageServiceRestClient.Response = restResp;
|
||||
|
||||
var client = new StorageServicePocoClientFactory().Create(GetValidContext()) as StorageServicePocoClient;
|
||||
var result = await client.GetStorageFolder(containerName, folderName);
|
||||
|
||||
Assert.IsNotNull(result);
|
||||
Assert.AreEqual("a/b/c", result.FullName);
|
||||
Assert.AreEqual("c", result.Name);
|
||||
Assert.IsNotNull(result.Objects);
|
||||
Assert.AreEqual(1, result.Objects.Count());
|
||||
Assert.IsNotNull(result.Folders);
|
||||
Assert.AreEqual(0, result.Folders.Count());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task CanGetStorageFolderWithNoContentResponse()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var folderName = "a/b/c/";
|
||||
var headers = new HttpHeadersAbstraction()
|
||||
{
|
||||
{"X-Container-Bytes-Used", "1234"},
|
||||
{"X-Container-Object-Count", "1"}
|
||||
};
|
||||
|
||||
var restResp = new HttpResponseAbstraction(new MemoryStream(), headers, HttpStatusCode.NoContent);
|
||||
this.StorageServiceRestClient.Response = restResp;
|
||||
|
||||
var client = new StorageServicePocoClientFactory().Create(GetValidContext()) as StorageServicePocoClient;
|
||||
var result = await client.GetStorageFolder(containerName, folderName);
|
||||
|
||||
Assert.IsNotNull(result);
|
||||
Assert.AreEqual("a/b/c", result.FullName);
|
||||
Assert.AreEqual("c", result.Name);
|
||||
Assert.IsNotNull(result.Objects);
|
||||
Assert.AreEqual(0, result.Objects.Count());
|
||||
Assert.IsNotNull(result.Folders);
|
||||
Assert.AreEqual(0, result.Folders.Count());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task CanGetStorageFolderWithOkResponseAndSubFolders()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var folderName = "a/b/c/";
|
||||
var headers = new HttpHeadersAbstraction()
|
||||
{
|
||||
{"X-Container-Bytes-Used", "1234"},
|
||||
{"X-Container-Object-Count", "1"}
|
||||
};
|
||||
|
||||
var payload = @"[
|
||||
{
|
||||
""hash"": ""d41d8cd98f00b204e9800998ecf8427e"",
|
||||
""last_modified"": ""2014-03-07T21:31:31.588170"",
|
||||
""bytes"": 0,
|
||||
""name"": ""a/b/c/"",
|
||||
""content_type"": ""application/octet-stream""
|
||||
},
|
||||
{
|
||||
""hash"": ""d41d8cd98f00b204e9800998ecf8427e"",
|
||||
""last_modified"": ""2014-03-07T21:31:31.588170"",
|
||||
""bytes"": 0,
|
||||
""name"": ""a/b/c/BLAH"",
|
||||
""content_type"": ""application/octet-stream""
|
||||
},
|
||||
{
|
||||
""subdir"": ""a/b/c/d/""
|
||||
},
|
||||
{
|
||||
""subdir"": ""a/b/c/x/""
|
||||
}
|
||||
]";
|
||||
|
||||
var content = TestHelper.CreateStream(payload);
|
||||
|
||||
var restResp = new HttpResponseAbstraction(content, headers, HttpStatusCode.OK);
|
||||
this.StorageServiceRestClient.Response = restResp;
|
||||
|
||||
var client = new StorageServicePocoClientFactory().Create(GetValidContext()) as StorageServicePocoClient;
|
||||
var resp = await client.GetStorageFolder(containerName, folderName);
|
||||
|
||||
Assert.AreEqual("c", resp.Name);
|
||||
Assert.AreEqual("a/b/c", resp.FullName);
|
||||
Assert.AreEqual(1, resp.Objects.Count);
|
||||
Assert.AreEqual(2, resp.Folders.Count);
|
||||
|
||||
var obj = resp.Objects.First();
|
||||
Assert.AreEqual("a/b/c/BLAH", obj.Name);
|
||||
|
||||
var dNode = resp.Folders.First(f => f.FullName == "a/b/c/d");
|
||||
var xNode = resp.Folders.First(f => f.FullName == "a/b/c/x");
|
||||
|
||||
Assert.AreEqual("d", dNode.Name);
|
||||
Assert.AreEqual(0, dNode.Folders.Count);
|
||||
Assert.AreEqual(0, dNode.Objects.Count);
|
||||
|
||||
Assert.AreEqual("x", xNode.Name);
|
||||
Assert.AreEqual(0, xNode.Folders.Count);
|
||||
Assert.AreEqual(0, xNode.Objects.Count);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(InvalidOperationException))]
|
||||
public async Task ExceptionthrownWhenGettingAStorageFolderThatDoesNotExistAndCannotBeInferred()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var folderName = "a/b/c/";
|
||||
var headers = new HttpHeadersAbstraction()
|
||||
{
|
||||
{"X-Container-Bytes-Used", "1234"},
|
||||
{"X-Container-Object-Count", "1"}
|
||||
};
|
||||
|
||||
var payload = @"[]";
|
||||
|
||||
var content = TestHelper.CreateStream(payload);
|
||||
|
||||
var restResp = new HttpResponseAbstraction(content, headers, HttpStatusCode.OK);
|
||||
this.StorageServiceRestClient.Response = restResp;
|
||||
|
||||
var client = new StorageServicePocoClientFactory().Create(GetValidContext()) as StorageServicePocoClient;
|
||||
var resp = await client.GetStorageFolder(containerName, folderName);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(InvalidOperationException))]
|
||||
public async Task ExceptionthrownWhenGettingAStorageFolderThatDoesNotExist()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var fodlerName = "a/b/b/";
|
||||
|
||||
var restResp = new HttpResponseAbstraction(new MemoryStream(), new HttpHeadersAbstraction(), HttpStatusCode.NotFound);
|
||||
this.StorageServiceRestClient.Response = restResp;
|
||||
|
||||
var client = new StorageServicePocoClient(GetValidContext());
|
||||
await client.GetStorageFolder(containerName, fodlerName);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(InvalidOperationException))]
|
||||
public async Task ExceptionthrownWhenGettingAStoragFolderAndNotAuthed()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var fodlerName = "a/b/b/";
|
||||
|
||||
var restResp = new HttpResponseAbstraction(new MemoryStream(), new HttpHeadersAbstraction(), HttpStatusCode.Unauthorized);
|
||||
this.StorageServiceRestClient.Response = restResp;
|
||||
|
||||
var client = new StorageServicePocoClient(GetValidContext());
|
||||
await client.GetStorageFolder(containerName, fodlerName);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(InvalidOperationException))]
|
||||
public async Task ExceptionthrownWhenGettingAStorageFolderAndServerError()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var fodlerName = "a/b/b/";
|
||||
|
||||
var restResp = new HttpResponseAbstraction(new MemoryStream(), new HttpHeadersAbstraction(), HttpStatusCode.InternalServerError);
|
||||
this.StorageServiceRestClient.Response = restResp;
|
||||
|
||||
var client = new StorageServicePocoClient(GetValidContext());
|
||||
await client.GetStorageFolder(containerName, fodlerName);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public async Task CannotGetStorageFolderWithNullContainerName()
|
||||
{
|
||||
var client = new StorageServicePocoClientFactory().Create(GetValidContext()) as StorageServicePocoClient;
|
||||
await client.GetStorageFolder(null, "a/b/c/");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public async Task CannotGetStorageFolderWithNullFolderName()
|
||||
{
|
||||
var client = new StorageServicePocoClientFactory().Create(GetValidContext()) as StorageServicePocoClient;
|
||||
await client.GetStorageFolder("container", null);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentException))]
|
||||
public async Task CannotGetStorageFolderWithEmptyContainerName()
|
||||
{
|
||||
var client = new StorageServicePocoClientFactory().Create(GetValidContext()) as StorageServicePocoClient;
|
||||
await client.GetStorageFolder(string.Empty, "a/b/c/");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentException))]
|
||||
public async Task CannotGetStorageFolderWithEmptyFolderName()
|
||||
{
|
||||
var client = new StorageServicePocoClientFactory().Create(GetValidContext()) as StorageServicePocoClient;
|
||||
await client.GetStorageFolder("container", string.Empty);
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region Create Storage Object Tests
|
||||
|
@ -674,6 +901,109 @@ namespace Openstack.Test.Storage
|
|||
|
||||
#endregion
|
||||
|
||||
#region Create Storage Folder Tests
|
||||
|
||||
[TestMethod]
|
||||
public async Task CanCreateStorageFolderWithCreatedResponse()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var folderName = "a/b/b/";
|
||||
|
||||
var headers = new HttpHeadersAbstraction()
|
||||
{
|
||||
{"Content-Length", "1234"},
|
||||
{"Content-Type", "application/octet-stream"},
|
||||
{"Last-Modified", "Wed, 12 Mar 2014 23:42:23 GMT"},
|
||||
{"ETag", "d41d8cd98f00b204e9800998ecf8427e"}
|
||||
};
|
||||
|
||||
var restResp = new HttpResponseAbstraction(new MemoryStream(), headers, HttpStatusCode.Created);
|
||||
this.StorageServiceRestClient.Response = restResp;
|
||||
|
||||
var client = new StorageServicePocoClient(GetValidContext());
|
||||
await client.CreateStorageFolder(containerName, folderName);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(InvalidOperationException))]
|
||||
public async Task ExceptionThrownWhenCreatingaStorageFolderMissingLength()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var folderName = "a/b/b/";
|
||||
|
||||
var headers = new HttpHeadersAbstraction()
|
||||
{
|
||||
{"Content-Length", "1234"},
|
||||
{"Content-Type", "application/octet-stream"},
|
||||
{"Last-Modified", "Wed, 12 Mar 2014 23:42:23 GMT"},
|
||||
{"ETag", "d41d8cd98f00b204e9800998ecf8427e"}
|
||||
};
|
||||
|
||||
var restResp = new HttpResponseAbstraction(new MemoryStream(), headers, HttpStatusCode.LengthRequired);
|
||||
this.StorageServiceRestClient.Response = restResp;
|
||||
|
||||
var client = new StorageServicePocoClient(GetValidContext());
|
||||
await client.CreateStorageFolder(containerName, folderName);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(InvalidOperationException))]
|
||||
public async Task ExceptionThrownWhenCreatingaStorageFolderWithBadETag()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var folderName = "a/b/b/";
|
||||
|
||||
var restResp = new HttpResponseAbstraction(new MemoryStream(), new HttpHeadersAbstraction(), (HttpStatusCode)422);
|
||||
this.StorageServiceRestClient.Response = restResp;
|
||||
|
||||
var client = new StorageServicePocoClient(GetValidContext());
|
||||
await client.CreateStorageFolder(containerName, folderName);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(InvalidOperationException))]
|
||||
public async Task ExceptionThrownWhenCreatingaStorageFolderWithBadAuth()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var folderName = "a/b/b/";
|
||||
|
||||
var restResp = new HttpResponseAbstraction(new MemoryStream(), new HttpHeadersAbstraction(), HttpStatusCode.Unauthorized);
|
||||
this.StorageServiceRestClient.Response = restResp;
|
||||
|
||||
var client = new StorageServicePocoClient(GetValidContext());
|
||||
await client.CreateStorageFolder(containerName, folderName);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(InvalidOperationException))]
|
||||
public async Task ExceptionThrownWhenCreatingaStorageFolderHasInternalServerError()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var folderName = "a/b/b/";
|
||||
|
||||
var restResp = new HttpResponseAbstraction(new MemoryStream(), new HttpHeadersAbstraction(), HttpStatusCode.InternalServerError);
|
||||
this.StorageServiceRestClient.Response = restResp;
|
||||
|
||||
var client = new StorageServicePocoClient(GetValidContext());
|
||||
await client.CreateStorageFolder(containerName, folderName);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(InvalidOperationException))]
|
||||
public async Task ExceptionThrownWhenCreatingaStorageFolderTimesOut()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var folderName = "a/b/b/";
|
||||
|
||||
var restResp = new HttpResponseAbstraction(new MemoryStream(), new HttpHeadersAbstraction(), HttpStatusCode.RequestTimeout);
|
||||
this.StorageServiceRestClient.Response = restResp;
|
||||
|
||||
var client = new StorageServicePocoClient(GetValidContext());
|
||||
await client.CreateStorageFolder(containerName, folderName);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Create Storage Container Tests
|
||||
|
||||
[TestMethod]
|
||||
|
@ -881,6 +1211,94 @@ namespace Openstack.Test.Storage
|
|||
|
||||
#endregion
|
||||
|
||||
#region Delete Storage Folder Tests
|
||||
|
||||
[TestMethod]
|
||||
public async Task CanDeleteStorageFolderWithNoContentResponse()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var folderName = "a/b/c/";
|
||||
|
||||
var restResp = new HttpResponseAbstraction(new MemoryStream(), new HttpHeadersAbstraction(), HttpStatusCode.NoContent);
|
||||
this.StorageServiceRestClient.Response = restResp;
|
||||
|
||||
var client = new StorageServicePocoClient(GetValidContext());
|
||||
await client.DeleteStorageFolder(containerName, folderName);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task CanDeleteStorageFolderWithOkResponse()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var folderName = "a/b/c/";
|
||||
|
||||
var restResp = new HttpResponseAbstraction(new MemoryStream(), new HttpHeadersAbstraction(), HttpStatusCode.OK);
|
||||
this.StorageServiceRestClient.Response = restResp;
|
||||
|
||||
var client = new StorageServicePocoClient(GetValidContext());
|
||||
await client.DeleteStorageFolder(containerName, folderName);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(InvalidOperationException))]
|
||||
public async Task ExceptionThrownWhenDeletingAStorageFolderThatHasChildren()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var folderName = "a/b/c/";
|
||||
var headers = new HttpHeadersAbstraction()
|
||||
{
|
||||
{"X-Container-Bytes-Used", "1234"},
|
||||
{"X-Container-Object-Count", "1"}
|
||||
};
|
||||
|
||||
var payload = @"[
|
||||
{
|
||||
""hash"": ""d41d8cd98f00b204e9800998ecf8427e"",
|
||||
""last_modified"": ""2014-03-07T21:31:31.588170"",
|
||||
""bytes"": 0,
|
||||
""name"": ""a/b/c/BLAH"",
|
||||
""content_type"": ""application/octet-stream""
|
||||
}]";
|
||||
|
||||
var content = TestHelper.CreateStream(payload);
|
||||
|
||||
var restResp = new HttpResponseAbstraction(content, headers, HttpStatusCode.OK);
|
||||
this.StorageServiceRestClient.Response = restResp;
|
||||
|
||||
var client = new StorageServicePocoClient(GetValidContext());
|
||||
await client.DeleteStorageFolder(containerName, folderName);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(InvalidOperationException))]
|
||||
public async Task ExceptionThrownWhenDeletingAStorageFolderWithBadAuth()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var folderName = "a/b/c/";
|
||||
|
||||
var restResp = new HttpResponseAbstraction(new MemoryStream(), new HttpHeadersAbstraction(), HttpStatusCode.Unauthorized);
|
||||
this.StorageServiceRestClient.Response = restResp;
|
||||
|
||||
var client = new StorageServicePocoClient(GetValidContext());
|
||||
await client.DeleteStorageFolder(containerName, folderName);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(InvalidOperationException))]
|
||||
public async Task ExceptionThrownWhenDeletingAStorageFolderWithInternalServerError()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var folderName = "a/b/c/";
|
||||
|
||||
var restResp = new HttpResponseAbstraction(new MemoryStream(), new HttpHeadersAbstraction(), HttpStatusCode.InternalServerError);
|
||||
this.StorageServiceRestClient.Response = restResp;
|
||||
|
||||
var client = new StorageServicePocoClient(GetValidContext());
|
||||
await client.DeleteStorageFolder(containerName, folderName);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Update Storage Container Tests
|
||||
|
||||
[TestMethod]
|
||||
|
|
|
@ -543,6 +543,7 @@ namespace Openstack.Test.Storage
|
|||
|
||||
#region Get Storage Object Tests
|
||||
|
||||
[TestMethod]
|
||||
public async Task GetStorageObjectIncludesAuthHeader()
|
||||
{
|
||||
var containerName = "newContainer";
|
||||
|
@ -1289,5 +1290,96 @@ namespace Openstack.Test.Storage
|
|||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Get Storage Folder Tests
|
||||
|
||||
[TestMethod]
|
||||
public async Task GetStorageFolderIncludesAuthHeader()
|
||||
{
|
||||
var containerName = "newContainer";
|
||||
var folderName = "newFolder";
|
||||
|
||||
var client =
|
||||
new StorageServiceRestClient(GetValidContext());
|
||||
|
||||
await client.GetFolder(containerName, folderName);
|
||||
|
||||
Assert.IsTrue(this.simulator.Headers.ContainsKey("X-Auth-Token"));
|
||||
Assert.AreEqual(this.authId, this.simulator.Headers["X-Auth-Token"]);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task GetStorageFolderFormsCorrectUrlAndMethod()
|
||||
{
|
||||
var containerName = "newContainer";
|
||||
var folderName = "a/b/b/";
|
||||
|
||||
var client =
|
||||
new StorageServiceRestClient(GetValidContext());
|
||||
|
||||
await client.GetFolder(containerName, folderName);
|
||||
|
||||
Assert.AreEqual(string.Format("{0}/{1}?prefix={2}&delimiter=/", endpoint, containerName, folderName), this.simulator.Uri.ToString());
|
||||
Assert.AreEqual(HttpMethod.Get, this.simulator.Method);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task ErrorIsReturnedWhenFolderIsNotFound()
|
||||
{
|
||||
var containerName = "newContainer";
|
||||
var folderName = "a/b/b/";
|
||||
|
||||
var client =
|
||||
new StorageServiceRestClient(GetValidContext());
|
||||
|
||||
var resp = await client.GetFolder(containerName, folderName);
|
||||
|
||||
Assert.AreEqual(HttpStatusCode.NotFound, resp.StatusCode);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task CanGetStorageFolder()
|
||||
{
|
||||
var containerName = "newContainer";
|
||||
var folderName = "a/b/b/";
|
||||
|
||||
var content = TestHelper.CreateStream(string.Empty);
|
||||
content.Position = 0;
|
||||
|
||||
this.simulator.Objects.Add(folderName, new StorageRestSimulator.StorageItem(folderName) { Content = content });
|
||||
|
||||
var client =
|
||||
new StorageServiceRestClient(GetValidContext());
|
||||
|
||||
var resp = await client.GetFolder(containerName, folderName);
|
||||
|
||||
Assert.AreEqual(HttpStatusCode.OK, resp.StatusCode);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task CanGetStorageFolderWithMetadata()
|
||||
{
|
||||
var containerName = "newContainer";
|
||||
var folderName = "a/b/b/";
|
||||
|
||||
var content = TestHelper.CreateStream(string.Empty);
|
||||
content.Position = 0;
|
||||
|
||||
var metaData = new Dictionary<string, string> { { "X-Object-Meta-Test1", "Test1" }, { "X-Object-Meta-Test2", "Test2" } };
|
||||
|
||||
this.simulator.Objects.Add(folderName, new StorageRestSimulator.StorageItem(folderName) { MetaData = metaData, Content = content });
|
||||
|
||||
var client =
|
||||
new StorageServiceRestClient(GetValidContext());
|
||||
|
||||
var resp = await client.GetFolder(containerName, folderName);
|
||||
|
||||
Assert.AreEqual(HttpStatusCode.OK, resp.StatusCode);
|
||||
|
||||
Assert.IsTrue(resp.Headers.Any(kvp => kvp.Key == "X-Object-Meta-Test2"));
|
||||
Assert.AreEqual("Test2", resp.Headers.First(kvp => kvp.Key == "X-Object-Meta-Test2").Value.First());
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,16 +27,22 @@ namespace Openstack.Test.Storage
|
|||
|
||||
public Func<StorageContainer, Task<StorageContainer>> CreateStorageContainerDelegate { get; set; }
|
||||
|
||||
public Func<string, string, Task> CreateStorageFolderDelegate { get; set; }
|
||||
|
||||
public Func<string, Task<StorageContainer>> GetStorageContainerDelegate { get; set; }
|
||||
|
||||
public Func<Task<StorageAccount>> GetStorageAccountDelegate { get; set; }
|
||||
|
||||
public Func<string, string, Task<StorageObject>> GetStorageObjectDelegate { get; set; }
|
||||
|
||||
public Func<string, string, Task<StorageFolder>> GetStorageFolderDelegate { get; set; }
|
||||
|
||||
public Func<string, string, Stream, Task<StorageObject>> DownloadStorageObjectDelegate { get; set; }
|
||||
|
||||
public Func<string, string, Task> DeleteStorageObjectDelegate { get; set; }
|
||||
|
||||
public Func<string, string, Task> DeleteStorageFolderDelegate { get; set; }
|
||||
|
||||
public Func<StorageObject, Task> UpdateStorageObjectDelegate { get; set; }
|
||||
|
||||
public Func<string, Task> DeleteStorageConainerDelegate { get; set; }
|
||||
|
@ -92,6 +98,21 @@ namespace Openstack.Test.Storage
|
|||
{
|
||||
await this.UpdateStorageObjectDelegate(obj);
|
||||
}
|
||||
|
||||
public async Task<StorageFolder> GetStorageFolder(string containerName, string folderName)
|
||||
{
|
||||
return await this.GetStorageFolderDelegate(containerName, folderName);
|
||||
}
|
||||
|
||||
public async Task CreateStorageFolder(string containerName, string folderName)
|
||||
{
|
||||
await this.CreateStorageFolderDelegate(containerName, folderName);
|
||||
}
|
||||
|
||||
public async Task DeleteStorageFolder(string containerName, string folderName)
|
||||
{
|
||||
await this.DeleteStorageFolderDelegate(containerName, folderName);
|
||||
}
|
||||
}
|
||||
|
||||
public class TestStorageServicePocoClientFactory : IStorageServicePocoClientFactory
|
||||
|
|
|
@ -41,6 +41,11 @@ namespace Openstack.Test.Storage
|
|||
return Task.Factory.StartNew(() => Response);
|
||||
}
|
||||
|
||||
public Task<IHttpResponseAbstraction> GetFolder(string containerName, string folderName)
|
||||
{
|
||||
return Task.Factory.StartNew(() => Response);
|
||||
}
|
||||
|
||||
public Task<IHttpResponseAbstraction> GetContainer(string containerName)
|
||||
{
|
||||
return Task.Factory.StartNew(() => Response);
|
||||
|
|
|
@ -88,6 +88,7 @@
|
|||
<Compile Include="Identity\OpenstackServiceEndpointPayloadConverter.cs" />
|
||||
<Compile Include="Identity\OpenstackServiceEndpointResolver.cs" />
|
||||
<Compile Include="ServiceRegistrar.cs" />
|
||||
<Compile Include="Storage\FolderNameValidator.cs" />
|
||||
<Compile Include="Storage\ContainerNameValidator.cs" />
|
||||
<Compile Include="Storage\IStorageAccountPayloadConverter.cs" />
|
||||
<Compile Include="Storage\IStorageFolderPayloadConverter.cs" />
|
||||
|
|
|
@ -30,6 +30,7 @@ namespace Openstack
|
|||
manager.RegisterServiceInstance(typeof(IStorageServicePocoClientFactory), new StorageServicePocoClientFactory());
|
||||
manager.RegisterServiceInstance(typeof(IStorageServiceRestClientFactory), new StorageServiceRestClientFactory());
|
||||
manager.RegisterServiceInstance(typeof(IStorageContainerNameValidator), new StorageContainerNameValidator());
|
||||
manager.RegisterServiceInstance(typeof(IStorageFolderNameValidator), new StorageFolderNameValidator());
|
||||
|
||||
//Identity related clients/services
|
||||
manager.RegisterServiceInstance(typeof(IIdentityServicePocoClientFactory), new IdentityServicePocoClientFactory());
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
// /* ============================================================================
|
||||
// Copyright 2014 Hewlett Packard
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Openstack.Storage
|
||||
{
|
||||
/// <summary>
|
||||
/// Validates a container name.
|
||||
/// </summary>
|
||||
public interface IStorageFolderNameValidator
|
||||
{
|
||||
/// <summary>
|
||||
/// Validates a folder name.
|
||||
/// </summary>
|
||||
/// <param name="folderName">The name to validate.</param>
|
||||
/// <returns>A value indicating if the the name could be validated.</returns>
|
||||
bool Validate(string folderName);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
internal class StorageFolderNameValidator : IStorageFolderNameValidator
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public bool Validate(string folderName)
|
||||
{
|
||||
//Folder names cannot have consecutive slashes in their names.
|
||||
//This is not a swift limitation, but it's good practice, and helps simplify things in the rest of the client.
|
||||
return !Regex.IsMatch(folderName, @"/{2,}");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -20,6 +20,20 @@ namespace Openstack.Storage
|
|||
|
||||
public interface IStorageFolderPayloadConverter
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts a list of storage objects into a deep folder structure.
|
||||
/// </summary>
|
||||
/// <param name="objects">The list of objects to convert.</param>
|
||||
/// <returns>A deep folder structure.</returns>
|
||||
IEnumerable<StorageFolder> Convert(IEnumerable<StorageObject> objects);
|
||||
|
||||
/// <summary>
|
||||
/// Converts a Json payload into a shallow storage folder object.
|
||||
/// </summary>
|
||||
/// <param name="containerName">The name of the parent container.</param>
|
||||
/// <param name="folderName">The full name of the folder.</param>
|
||||
/// <param name="payload">The Json payload.</param>
|
||||
/// <returns>A shallow storage folder object.</returns>
|
||||
StorageFolder Convert(string containerName, string folderName, string payload);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ namespace Openstack.Storage
|
|||
{
|
||||
using System.Collections.Generic;
|
||||
using Openstack.Common.Http;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
/// <summary>
|
||||
/// Converts a Json payload into a storage object.
|
||||
|
@ -40,5 +41,13 @@ namespace Openstack.Storage
|
|||
/// <param name="headers">The collection of headers</param>
|
||||
/// <returns>The storage object.</returns>
|
||||
StorageObject Convert(string containerName, string objectName, IHttpHeadersAbstraction headers);
|
||||
|
||||
/// <summary>
|
||||
/// Converts a Json token into a storage object.
|
||||
/// </summary>
|
||||
/// <param name="obj">The token.</param>
|
||||
/// <param name="containerName">The name of the parent container.</param>
|
||||
/// <returns>The storage object.</returns>
|
||||
StorageObject ConvertSingle(JToken obj, string containerName);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,13 +14,12 @@
|
|||
// limitations under the License.
|
||||
// ============================================================================ */
|
||||
|
||||
using System;
|
||||
|
||||
namespace Openstack.Storage
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using System;
|
||||
|
||||
/// <summary>
|
||||
/// Client that can interact with an Openstack storage service.
|
||||
|
@ -122,5 +121,29 @@ namespace Openstack.Storage
|
|||
/// <param name="obj">The object to update.</param>
|
||||
/// <returns>An async task.</returns>
|
||||
Task UpdateStorageObject(StorageObject obj);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a storage folder from the remote Openstack instance. The returned folder is a shallow object graph representation.
|
||||
/// </summary>
|
||||
/// <param name="containerName">The name of the parent container.</param>
|
||||
/// <param name="folderName">The name of the folder to get.</param>
|
||||
/// <returns>A shallow object representation of the folder and it's contained objects and sub folders.</returns>
|
||||
Task<StorageFolder> GetStorageFolder(string containerName, string folderName);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a storage folder on the remote Openstack instance.
|
||||
/// </summary>
|
||||
/// <param name="containerName">The name of the parent container.</param>
|
||||
/// <param name="folderName">The name of the folder to create.</param>
|
||||
/// <returns>An async task.</returns>
|
||||
Task CreateStorageFolder(string containerName, string folderName);
|
||||
|
||||
/// <summary>
|
||||
/// Deletes a storage folder from the remote Openstack instance.
|
||||
/// </summary>
|
||||
/// <param name="containerName">The name of the parent container.</param>
|
||||
/// <param name="folderName">The name of the folder to delete.</param>
|
||||
/// <returns>An async task.</returns>
|
||||
Task DeleteStorageFolder(string containerName, string folderName);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -99,5 +99,28 @@ namespace Openstack.Storage
|
|||
/// <returns>An async task.</returns>
|
||||
Task UpdateStorageObject(StorageObject obj);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a storage folder from the remote Openstack instance. The returned folder is a shallow object graph representation.
|
||||
/// </summary>
|
||||
/// <param name="containerName">The name of the parent container.</param>
|
||||
/// <param name="folderName">The name of the folder to get.</param>
|
||||
/// <returns>A shallow object representation of the folder and it's contained objects and sub folders.</returns>
|
||||
Task<StorageFolder> GetStorageFolder(string containerName, string folderName);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a storage folder on the remote Openstack instance.
|
||||
/// </summary>
|
||||
/// <param name="containerName">The name of the parent container.</param>
|
||||
/// <param name="folderName">The name of the folder to create.</param>
|
||||
/// <returns>An async task.</returns>
|
||||
Task CreateStorageFolder(string containerName, string folderName);
|
||||
|
||||
/// <summary>
|
||||
/// Deletes a storage folder from the remote Openstack instance.
|
||||
/// </summary>
|
||||
/// <param name="containerName">The name of the parent container.</param>
|
||||
/// <param name="folderName">The name of the folder to delete.</param>
|
||||
/// <returns>An async task.</returns>
|
||||
Task DeleteStorageFolder(string containerName, string folderName);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,6 +52,14 @@ namespace Openstack.Storage
|
|||
/// <returns>The Http response from the remote service.</returns>
|
||||
Task<IHttpResponseAbstraction> GetObject(string containerName, string objectName);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a storage folder from the remote Openstack instance.
|
||||
/// </summary>
|
||||
/// <param name="containerName">The name of the parent storage container.</param>
|
||||
/// <param name="folderName">The name of the folder.</param>
|
||||
/// <returns>The Http response from the remote service.</returns>
|
||||
Task<IHttpResponseAbstraction> GetFolder(string containerName, string folderName);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a storage container from the remote Openstack instance.
|
||||
/// </summary>
|
||||
|
|
|
@ -20,19 +20,45 @@ namespace Openstack.Storage
|
|||
using Openstack.Common;
|
||||
using System.Collections.Generic;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a storage folder on a remote Openstack instance.
|
||||
/// </summary>
|
||||
public class StorageFolder
|
||||
{
|
||||
/// <summary>
|
||||
/// The "friendly" name of the folder
|
||||
/// </summary>
|
||||
public string Name { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The full name/path of the folder.
|
||||
/// </summary>
|
||||
public string FullName { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A collection of sub-folders inside this folder.
|
||||
/// </summary>
|
||||
public ICollection<StorageFolder> Folders { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A collection of objects inside this folder.
|
||||
/// </summary>
|
||||
public ICollection<StorageObject> Objects { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the StorageFolder class.
|
||||
/// </summary>
|
||||
/// <param name="fullName">The full name/path of the folder.</param>
|
||||
/// <param name="folders">A collection of sub-folders that are inside this folder.</param>
|
||||
public StorageFolder(string fullName, IEnumerable<StorageFolder> folders) : this(fullName, folders, new List<StorageObject>())
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the StorageFolder class.
|
||||
/// </summary>
|
||||
/// <param name="fullName">The full name/path of the folder.</param>
|
||||
/// <param name="folders">A collection of sub-folders that are inside this folder.</param>
|
||||
/// <param name="objects">A collection of objects that are inside this folder.</param>
|
||||
public StorageFolder(string fullName, IEnumerable<StorageFolder> folders, IEnumerable<StorageObject> objects )
|
||||
{
|
||||
fullName.AssertIsNotNullOrEmpty("fullName", "Cannot create a storage folder with a null or empty full name.");
|
||||
|
@ -45,6 +71,11 @@ namespace Openstack.Storage
|
|||
this.Objects = objects.ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extracts the "friendly" name from the folders full name/path.
|
||||
/// </summary>
|
||||
/// <param name="fullFolderName">The full name/path of the folder.</param>
|
||||
/// <returns>The "friendly" name of the folder. (e.g. "b" if the folder path is "a/b/")</returns>
|
||||
internal static string ExtractFolderName(string fullFolderName)
|
||||
{
|
||||
var fullName = fullFolderName.Trim('/');
|
||||
|
|
|
@ -17,16 +17,22 @@
|
|||
namespace Openstack.Storage
|
||||
{
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Web;
|
||||
using System.Linq;
|
||||
using Openstack.Common;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System.ComponentModel;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.RegularExpressions;
|
||||
using Openstack.Common.ServiceLocation;
|
||||
|
||||
/// <inheritdoc/>
|
||||
internal class StorageFolderPayloadConverter : IStorageFolderPayloadConverter
|
||||
{
|
||||
internal const string consecutiveSlashRegex = @"/{2,}";
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IEnumerable<StorageFolder> Convert(IEnumerable<StorageObject> objects)
|
||||
{
|
||||
objects.AssertIsNotNull("objects", "Cannot build folders with a null object collection.");
|
||||
|
@ -84,5 +90,64 @@ namespace Openstack.Storage
|
|||
}
|
||||
return folders;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public StorageFolder Convert(string containerName, string folderName, string payload)
|
||||
{
|
||||
if (String.IsNullOrEmpty(payload))
|
||||
{
|
||||
return new StorageFolder(folderName, new List<StorageFolder>());
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var array = JArray.Parse(payload);
|
||||
if (array.Count == 0)
|
||||
{
|
||||
throw new InvalidDataException("Folder cannot be converted. The folder does not exist, has no children, and cannot be inferred.");
|
||||
}
|
||||
|
||||
var subFolders = array.Where(t => t["subdir"] != null);
|
||||
var rawObjects = array.Where(t => t["subdir"] == null);
|
||||
|
||||
var objectConverter = ServiceLocator.Instance.Locate<IStorageObjectPayloadConverter>();
|
||||
|
||||
var objects = rawObjects.Select(t => objectConverter.ConvertSingle(t,containerName)).ToList();
|
||||
objects.RemoveAll(o => string.Compare(o.Name, folderName, StringComparison.InvariantCulture) == 0);
|
||||
|
||||
return new StorageFolder(folderName, subFolders.Select(ParseSubFolder), objects);
|
||||
|
||||
}
|
||||
catch (HttpParseException)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
catch (InvalidDataException)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new HttpParseException(string.Format("Storage Container payload could not be parsed. Payload: '{0}'", payload), ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a JToken object into a StorageFolder object.
|
||||
/// </summary>
|
||||
/// <param name="token">The JToken to convert.</param>
|
||||
/// <returns>A StorageFolder object.</returns>
|
||||
internal StorageFolder ParseSubFolder(JToken token)
|
||||
{
|
||||
try
|
||||
{
|
||||
var fullName = (string) token["subdir"];
|
||||
return new StorageFolder(fullName, new List<StorageFolder>());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new HttpParseException(string.Format("Storage Folder payload could not be parsed. Payload: '{0}'", token), ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -56,13 +56,8 @@ namespace Openstack.Storage
|
|||
return objects;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a Json token into a storage object.
|
||||
/// </summary>
|
||||
/// <param name="obj">The token.</param>
|
||||
/// <param name="containerName">The name of the parent container.</param>
|
||||
/// <returns>The storage object.</returns>
|
||||
internal StorageObject ConvertSingle(JToken obj, string containerName)
|
||||
/// <inheritdoc/>
|
||||
public StorageObject ConvertSingle(JToken obj, string containerName)
|
||||
{
|
||||
string name = string.Empty;
|
||||
|
||||
|
|
|
@ -121,6 +121,47 @@ namespace Openstack.Storage
|
|||
await client.UpdateStorageObject(obj);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task<StorageFolder> GetStorageFolder(string containerName, string folderName)
|
||||
{
|
||||
containerName.AssertIsNotNullOrEmpty("containerName", "Cannot get a storage folder with a container name that is null or empty.");
|
||||
folderName.AssertIsNotNullOrEmpty("folderName", "Cannot get a storage folder with a name that is null or empty.");
|
||||
|
||||
folderName = EnsureTrailingSlashOnFolderName(folderName);
|
||||
|
||||
var client = this.GetPocoClient();
|
||||
return await client.GetStorageFolder(containerName, folderName);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task CreateStorageFolder(string containerName, string folderName)
|
||||
{
|
||||
containerName.AssertIsNotNullOrEmpty("containerName", "Cannot create a storage folder with a container name that is null or empty.");
|
||||
folderName.AssertIsNotNullOrEmpty("folderName", "Cannot create a storage folder with a name that is null or empty.");
|
||||
|
||||
folderName = EnsureTrailingSlashOnFolderName(folderName);
|
||||
var validator = ServiceLocator.Instance.Locate<IStorageFolderNameValidator>();
|
||||
if (!validator.Validate(folderName))
|
||||
{
|
||||
throw new ArgumentException(string.Format("Folder name '{0}' is invalid. Folder names cannot includes consecutive slashes.", folderName), "folderName");
|
||||
}
|
||||
|
||||
var client = this.GetPocoClient();
|
||||
await client.CreateStorageFolder(containerName, folderName);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task DeleteStorageFolder(string containerName, string folderName)
|
||||
{
|
||||
containerName.AssertIsNotNullOrEmpty("containerName", "Cannot delete a storage folder with a container name that is null or empty.");
|
||||
folderName.AssertIsNotNullOrEmpty("folderName", "Cannot delete a storage folder with a name that is null or empty.");
|
||||
|
||||
folderName = EnsureTrailingSlashOnFolderName(folderName);
|
||||
|
||||
var client = this.GetPocoClient();
|
||||
await client.DeleteStorageFolder(containerName, folderName);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task<StorageContainer> GetStorageContainer(string containerName)
|
||||
{
|
||||
|
@ -188,5 +229,19 @@ namespace Openstack.Storage
|
|||
{
|
||||
return ServiceLocator.Instance.Locate<IStorageServicePocoClientFactory>().Create(this.Context);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ensures that a folder name has a single trailing slash on the end.
|
||||
/// </summary>
|
||||
/// <param name="folderName">The folder name.</param>
|
||||
/// <returns>The folder name with a slash on the end.</returns>
|
||||
internal string EnsureTrailingSlashOnFolderName(string folderName)
|
||||
{
|
||||
if (!folderName.EndsWith("/"))
|
||||
{
|
||||
folderName += "/";
|
||||
}
|
||||
return folderName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,9 +21,11 @@ namespace Openstack.Storage
|
|||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Threading.Tasks;
|
||||
using System.Collections.Generic;
|
||||
using Openstack.Common;
|
||||
using Openstack.Common.ServiceLocation;
|
||||
|
||||
|
||||
/// <inheritdoc/>
|
||||
internal class StorageServicePocoClient : IStorageServicePocoClient
|
||||
{
|
||||
|
@ -215,6 +217,68 @@ namespace Openstack.Storage
|
|||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task<StorageFolder> GetStorageFolder(string containerName, string folderName)
|
||||
{
|
||||
containerName.AssertIsNotNullOrEmpty("containerName", "Cannot get a storage folder with a container name that is null or empty.");
|
||||
folderName.AssertIsNotNullOrEmpty("folderName", "Cannot get a storage folder with a folder name that is null or empty.");
|
||||
|
||||
var client = this.GetRestClient();
|
||||
var resp = await client.GetFolder(containerName, folderName);
|
||||
|
||||
if (resp.StatusCode != HttpStatusCode.OK && resp.StatusCode != HttpStatusCode.NoContent)
|
||||
{
|
||||
throw new InvalidOperationException(string.Format("Failed to get storage folder '{0}'. The remote server returned the following status code: '{1}'.", folderName, resp.StatusCode));
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var converter = ServiceLocator.Instance.Locate<IStorageFolderPayloadConverter>();
|
||||
var folder = converter.Convert(containerName, folderName, await resp.ReadContentAsStringAsync());
|
||||
return folder;
|
||||
}
|
||||
catch (InvalidDataException)
|
||||
{
|
||||
throw new InvalidOperationException(string.Format("Failed to get storage folder '{0}'. The requested folder could not be found.", folderName));
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task CreateStorageFolder(string containerName, string folderName)
|
||||
{
|
||||
containerName.AssertIsNotNullOrEmpty("containerName", "Cannot create a storage folder with a container name that is null or empty.");
|
||||
folderName.AssertIsNotNullOrEmpty("folderName", "Cannot create a storage folder with a folder name that is null or empty.");
|
||||
|
||||
var client = this.GetRestClient();
|
||||
var resp = await client.CreateObject(containerName, folderName, new Dictionary<string, string>(), new MemoryStream());
|
||||
|
||||
if (resp.StatusCode != HttpStatusCode.Created)
|
||||
{
|
||||
throw new InvalidOperationException(string.Format("Failed to create storage folder '{0}'. The remote server returned the following status code: '{1}'.", folderName, resp.StatusCode));
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task DeleteStorageFolder(string containerName, string folderName)
|
||||
{
|
||||
containerName.AssertIsNotNullOrEmpty("containerName", "Cannot delete a storage object with a container name that is null or empty.");
|
||||
folderName.AssertIsNotNullOrEmpty("objectName", "Cannot delete a storage object with a name that is null or empty.");
|
||||
|
||||
var folder = await this.GetStorageFolder(containerName, folderName);
|
||||
if (folder.Folders.Count > 0 || folder.Objects.Count > 0)
|
||||
{
|
||||
throw new InvalidOperationException(string.Format("Failed to delete storage folder '{0}'. The folder is not empty and cannot be deleted.", folderName));
|
||||
}
|
||||
|
||||
var client = this.GetRestClient();
|
||||
var resp = await client.DeleteObject(containerName, folderName);
|
||||
|
||||
if (resp.StatusCode != HttpStatusCode.OK && resp.StatusCode != HttpStatusCode.NoContent)
|
||||
{
|
||||
throw new InvalidOperationException(string.Format("Failed to delete storage folder '{0}'. The remote server returned the following status code: '{1}'.", folderName, resp.StatusCode));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a client that can be used to connect to the REST endpoints of an Openstack storage service.
|
||||
/// </summary>
|
||||
|
|
|
@ -22,6 +22,7 @@ namespace Openstack.Storage
|
|||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Openstack.Common;
|
||||
using Openstack.Common.Http;
|
||||
using Openstack.Common.ServiceLocation;
|
||||
|
||||
|
@ -87,6 +88,21 @@ namespace Openstack.Storage
|
|||
return await client.SendAsync();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task<IHttpResponseAbstraction> GetFolder(string containerName, string folderName)
|
||||
{
|
||||
AssertContainerNameIsValid(containerName);
|
||||
folderName.AssertIsNotNullOrEmpty("folderName","Cannot get a folder with a null or empty folder name.");
|
||||
|
||||
var client = this.GetHttpClient(this.context);
|
||||
|
||||
var baseUri = CreateRequestUri(GetServiceEndpoint(this.context), containerName);
|
||||
client.Uri = new Uri(string.Format("{0}?prefix={1}&delimiter=/", baseUri, folderName));
|
||||
client.Method = HttpMethod.Get;
|
||||
|
||||
return await client.SendAsync();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task<IHttpResponseAbstraction> GetContainer(string containerName)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue