Adding support for storage manifests at the poco level. Includes basic CRUD operations.
Implements: blueprint large-file-support Change-Id: I46e05f9692dccad5a2ddfd250f7ba3decba29d20
This commit is contained in:
parent
b17cddd189
commit
2f91391b7a
|
@ -338,7 +338,7 @@ namespace Openstack.Test.Storage
|
|||
Assert.AreEqual("a", aNode.Name);
|
||||
Assert.AreEqual(2, aNode.Folders.Count);
|
||||
Assert.AreEqual(1, aNode.Objects.Count);
|
||||
Assert.IsTrue(aNode.Objects.Any(f => f.Name == "a/object2"));
|
||||
Assert.IsTrue(aNode.Objects.Any(f => f.FullName == "a/object2"));
|
||||
|
||||
var xNode = aNode.Folders.First(f => f.Name == "x");
|
||||
Assert.AreEqual(0, xNode.Folders.Count);
|
||||
|
@ -348,13 +348,13 @@ namespace Openstack.Test.Storage
|
|||
Assert.AreEqual(1, bNode.Folders.Count);
|
||||
Assert.AreEqual(2, bNode.Objects.Count);
|
||||
Assert.IsTrue(bNode.Folders.Any(f => f.Name == "c"));
|
||||
Assert.IsTrue(bNode.Objects.Any(f => f.Name == "a/b/c"));
|
||||
Assert.IsTrue(bNode.Objects.Any(f => f.Name == "a/b/b"));
|
||||
Assert.IsTrue(bNode.Objects.Any(f => f.FullName == "a/b/c"));
|
||||
Assert.IsTrue(bNode.Objects.Any(f => f.FullName == "a/b/b"));
|
||||
|
||||
var cNode = bNode.Folders.First(f => f.Name == "c");
|
||||
Assert.AreEqual(0, cNode.Folders.Count);
|
||||
Assert.AreEqual(1, cNode.Objects.Count);
|
||||
Assert.IsTrue(cNode.Objects.Any(f => f.Name == "a/b/c/object3"));
|
||||
Assert.IsTrue(cNode.Objects.Any(f => f.FullName == "a/b/c/object3"));
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -119,8 +119,8 @@ namespace Openstack.Test.Storage
|
|||
var leaf = folders[0].Folders.First().Folders.First().Folders.First();
|
||||
Assert.AreEqual("d", leaf.Name);
|
||||
Assert.AreEqual(2,leaf.Objects.Count);
|
||||
Assert.IsTrue(leaf.Objects.Any(o => o.Name == "a/b/c/d/foo"));
|
||||
Assert.IsTrue(leaf.Objects.Any(o => o.Name == "a/b/c/d/bar"));
|
||||
Assert.IsTrue(leaf.Objects.Any(o => o.FullName == "a/b/c/d/foo"));
|
||||
Assert.IsTrue(leaf.Objects.Any(o => o.FullName == "a/b/c/d/bar"));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
|
@ -142,8 +142,8 @@ namespace Openstack.Test.Storage
|
|||
var leaf = folders[0].Folders.First().Folders.First().Folders.First();
|
||||
Assert.AreEqual("d", leaf.Name);
|
||||
Assert.AreEqual(2, leaf.Objects.Count);
|
||||
Assert.IsTrue(leaf.Objects.Any(o => o.Name == "a/b/c/d/foo"));
|
||||
Assert.IsTrue(leaf.Objects.Any(o => o.Name == "a/b/c/d/bar"));
|
||||
Assert.IsTrue(leaf.Objects.Any(o => o.FullName == "a/b/c/d/foo"));
|
||||
Assert.IsTrue(leaf.Objects.Any(o => o.FullName == "a/b/c/d/bar"));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
|
@ -165,8 +165,8 @@ namespace Openstack.Test.Storage
|
|||
var leaf = folders[0].Folders.First().Folders.First().Folders.First();
|
||||
Assert.AreEqual("d", leaf.Name);
|
||||
Assert.AreEqual(2, leaf.Objects.Count);
|
||||
Assert.IsTrue(leaf.Objects.Any(o => o.Name == "a/b/c/d/foo"));
|
||||
Assert.IsTrue(leaf.Objects.Any(o => o.Name == "a/b/c/d/bar"));
|
||||
Assert.IsTrue(leaf.Objects.Any(o => o.FullName == "a/b/c/d/foo"));
|
||||
Assert.IsTrue(leaf.Objects.Any(o => o.FullName == "a/b/c/d/bar"));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
|
@ -194,24 +194,24 @@ namespace Openstack.Test.Storage
|
|||
Assert.AreEqual("a", aNode.Name);
|
||||
Assert.AreEqual(1, aNode.Folders.Count);
|
||||
Assert.AreEqual(1, aNode.Objects.Count);
|
||||
Assert.IsTrue(aNode.Objects.Any(o => o.Name == "a/string"));
|
||||
Assert.IsTrue(aNode.Objects.Any(o => o.FullName == "a/string"));
|
||||
|
||||
Assert.AreEqual("b", bNode.Name);
|
||||
Assert.AreEqual("a/b", bNode.FullName);
|
||||
Assert.AreEqual(1, bNode.Folders.Count);
|
||||
Assert.AreEqual(1, bNode.Objects.Count);
|
||||
Assert.IsTrue(bNode.Objects.Any(o => o.Name == "a/b/bar"));
|
||||
Assert.IsTrue(bNode.Objects.Any(o => o.FullName == "a/b/bar"));
|
||||
|
||||
Assert.AreEqual("c", cNode.Name);
|
||||
Assert.AreEqual("a/b/c", cNode.FullName);
|
||||
Assert.AreEqual(1, cNode.Folders.Count);
|
||||
Assert.AreEqual(1, cNode.Objects.Count);
|
||||
Assert.IsTrue(cNode.Objects.Any(o => o.Name == "a/b/c/beans"));
|
||||
Assert.IsTrue(cNode.Objects.Any(o => o.FullName == "a/b/c/beans"));
|
||||
|
||||
Assert.AreEqual("d", dNode.Name);
|
||||
Assert.AreEqual("a/b/c/d", dNode.FullName);
|
||||
Assert.AreEqual(1, dNode.Objects.Count);
|
||||
Assert.IsTrue(dNode.Objects.Any(o => o.Name == "a/b/c/d/foo"));
|
||||
Assert.IsTrue(dNode.Objects.Any(o => o.FullName == "a/b/c/d/foo"));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
|
@ -287,7 +287,7 @@ namespace Openstack.Test.Storage
|
|||
Assert.AreEqual("c", resp.Name);
|
||||
|
||||
var obj = resp.Objects.First();
|
||||
Assert.AreEqual("a/b/c/BLAH", obj.Name);
|
||||
Assert.AreEqual("a/b/c/BLAH", obj.FullName);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
|
@ -332,7 +332,7 @@ namespace Openstack.Test.Storage
|
|||
Assert.AreEqual("c", resp.Name);
|
||||
|
||||
var obj = resp.Objects.First();
|
||||
Assert.AreEqual("a/b/c/BLAH", obj.Name);
|
||||
Assert.AreEqual("a/b/c/BLAH", obj.FullName);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
|
@ -364,7 +364,7 @@ namespace Openstack.Test.Storage
|
|||
Assert.AreEqual("c", resp.Name);
|
||||
|
||||
var obj = resp.Objects.First();
|
||||
Assert.AreEqual("a/b/c/BLAH", obj.Name);
|
||||
Assert.AreEqual("a/b/c/BLAH", obj.FullName);
|
||||
|
||||
var dNode = resp.Folders.First(f => f.FullName == "a/b/c/d");
|
||||
var xNode = resp.Folders.First(f => f.FullName == "a/b/c/x");
|
||||
|
@ -415,7 +415,7 @@ namespace Openstack.Test.Storage
|
|||
Assert.AreEqual(2, resp.Folders.Count);
|
||||
|
||||
var obj = resp.Objects.First();
|
||||
Assert.AreEqual("a/b/c/BLAH", obj.Name);
|
||||
Assert.AreEqual("a/b/c/BLAH", obj.FullName);
|
||||
|
||||
var dNode = resp.Folders.First(f => f.FullName == "a/b/c/d");
|
||||
var xNode = resp.Folders.First(f => f.FullName == "a/b/c/x");
|
||||
|
|
|
@ -15,9 +15,12 @@
|
|||
// ============================================================================ */
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Openstack.Common.Http;
|
||||
using Openstack.Storage;
|
||||
|
||||
|
@ -294,7 +297,7 @@ namespace Openstack.Test.Storage
|
|||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CanParseFromHeaders()
|
||||
public void CanParseObjectFromHeaders()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var objectName = "TestObject";
|
||||
|
@ -311,6 +314,7 @@ namespace Openstack.Test.Storage
|
|||
var obj = converter.Convert(containerName, objectName, headers);
|
||||
|
||||
Assert.IsNotNull(obj);
|
||||
Assert.IsInstanceOfType(obj, typeof(StorageObject));
|
||||
Assert.AreEqual(1234, obj.Length);
|
||||
Assert.AreEqual("d41d8cd98f00b204e9800998ecf8427e", obj.ETag);
|
||||
Assert.AreEqual("application/octet-stream", obj.ContentType);
|
||||
|
@ -320,7 +324,7 @@ namespace Openstack.Test.Storage
|
|||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CanParseFromHeadersWithMetadata()
|
||||
public void CanParseObjectFromHeadersWithMetadata()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var objectName = "TestObject";
|
||||
|
@ -338,6 +342,7 @@ namespace Openstack.Test.Storage
|
|||
var obj = converter.Convert(containerName, objectName, headers);
|
||||
|
||||
Assert.IsNotNull(obj);
|
||||
Assert.IsInstanceOfType(obj, typeof(StorageObject));
|
||||
Assert.AreEqual(1234, obj.Length);
|
||||
Assert.AreEqual("d41d8cd98f00b204e9800998ecf8427e", obj.ETag);
|
||||
Assert.AreEqual("application/octet-stream", obj.ContentType);
|
||||
|
@ -349,6 +354,200 @@ namespace Openstack.Test.Storage
|
|||
Assert.AreEqual("Test1", obj.Metadata["Test1"]);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CanParseStaticManifestFromHeadersWithMetadata()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var objectName = "TestObject";
|
||||
|
||||
var headers = new HttpHeadersAbstraction()
|
||||
{
|
||||
{"Content-Length", "1234"},
|
||||
{"Content-Type", "application/octet-stream"},
|
||||
{"Last-Modified", "Wed, 12 Mar 2014 23:42:23 GMT"},
|
||||
{"ETag", "d41d8cd98f00b204e9800998ecf8427e"},
|
||||
{"X-Object-Meta-Test1","Test1"},
|
||||
{"X-Static-Large-Object","True"}
|
||||
};
|
||||
|
||||
var converter = new StorageObjectPayloadConverter();
|
||||
var obj = converter.Convert(containerName, objectName, headers);
|
||||
|
||||
Assert.IsNotNull(obj);
|
||||
Assert.IsInstanceOfType(obj, typeof(StaticLargeObjectManifest));
|
||||
Assert.AreEqual(1234, obj.Length);
|
||||
Assert.AreEqual("d41d8cd98f00b204e9800998ecf8427e", obj.ETag);
|
||||
Assert.AreEqual("application/octet-stream", obj.ContentType);
|
||||
Assert.AreEqual(DateTime.Parse("Wed, 12 Mar 2014 23:42:23 GMT"), obj.LastModified);
|
||||
Assert.AreEqual(objectName, obj.Name);
|
||||
Assert.AreEqual(containerName, obj.ContainerName);
|
||||
Assert.AreEqual(1, obj.Metadata.Count());
|
||||
Assert.IsTrue(obj.Metadata.ContainsKey("Test1"));
|
||||
Assert.AreEqual("Test1", obj.Metadata["Test1"]);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CanParseObjectFromHeadersWithStaticManifestFlagSetToNonTrue()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var objectName = "TestObject";
|
||||
|
||||
var headers = new HttpHeadersAbstraction()
|
||||
{
|
||||
{"Content-Length", "1234"},
|
||||
{"Content-Type", "application/octet-stream"},
|
||||
{"Last-Modified", "Wed, 12 Mar 2014 23:42:23 GMT"},
|
||||
{"ETag", "d41d8cd98f00b204e9800998ecf8427e"},
|
||||
{"X-Object-Meta-Test1","Test1"},
|
||||
{"X-Static-Large-Object","False"}
|
||||
};
|
||||
|
||||
var converter = new StorageObjectPayloadConverter();
|
||||
var obj = converter.Convert(containerName, objectName, headers);
|
||||
|
||||
Assert.IsNotNull(obj);
|
||||
Assert.IsInstanceOfType(obj, typeof(StorageObject));
|
||||
Assert.AreEqual(1234, obj.Length);
|
||||
Assert.AreEqual("d41d8cd98f00b204e9800998ecf8427e", obj.ETag);
|
||||
Assert.AreEqual("application/octet-stream", obj.ContentType);
|
||||
Assert.AreEqual(DateTime.Parse("Wed, 12 Mar 2014 23:42:23 GMT"), obj.LastModified);
|
||||
Assert.AreEqual(objectName, obj.Name);
|
||||
Assert.AreEqual(containerName, obj.ContainerName);
|
||||
Assert.AreEqual(1, obj.Metadata.Count());
|
||||
Assert.IsTrue(obj.Metadata.ContainsKey("Test1"));
|
||||
Assert.AreEqual("Test1", obj.Metadata["Test1"]);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CanParseObjectFromHeadersWithStaticManifestFlagSetToNull()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var objectName = "TestObject";
|
||||
|
||||
var headers = new HttpHeadersAbstraction()
|
||||
{
|
||||
{"Content-Length", "1234"},
|
||||
{"Content-Type", "application/octet-stream"},
|
||||
{"Last-Modified", "Wed, 12 Mar 2014 23:42:23 GMT"},
|
||||
{"ETag", "d41d8cd98f00b204e9800998ecf8427e"},
|
||||
{"X-Object-Meta-Test1","Test1"},
|
||||
{"X-Static-Large-Object", (string)null}
|
||||
};
|
||||
|
||||
var converter = new StorageObjectPayloadConverter();
|
||||
var obj = converter.Convert(containerName, objectName, headers);
|
||||
|
||||
Assert.IsNotNull(obj);
|
||||
Assert.IsInstanceOfType(obj, typeof(StorageObject));
|
||||
Assert.AreEqual(1234, obj.Length);
|
||||
Assert.AreEqual("d41d8cd98f00b204e9800998ecf8427e", obj.ETag);
|
||||
Assert.AreEqual("application/octet-stream", obj.ContentType);
|
||||
Assert.AreEqual(DateTime.Parse("Wed, 12 Mar 2014 23:42:23 GMT"), obj.LastModified);
|
||||
Assert.AreEqual(objectName, obj.Name);
|
||||
Assert.AreEqual(containerName, obj.ContainerName);
|
||||
Assert.AreEqual(1, obj.Metadata.Count());
|
||||
Assert.IsTrue(obj.Metadata.ContainsKey("Test1"));
|
||||
Assert.AreEqual("Test1", obj.Metadata["Test1"]);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CanParseObjectFromHeadersWithDynamicFlagSetToNull()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var objectName = "TestObject";
|
||||
|
||||
var headers = new HttpHeadersAbstraction()
|
||||
{
|
||||
{"Content-Length", "1234"},
|
||||
{"Content-Type", "application/octet-stream"},
|
||||
{"Last-Modified", "Wed, 12 Mar 2014 23:42:23 GMT"},
|
||||
{"ETag", "d41d8cd98f00b204e9800998ecf8427e"},
|
||||
{"X-Object-Meta-Test1","Test1"},
|
||||
{"X-Object-Manifest", (string)null}
|
||||
};
|
||||
|
||||
var converter = new StorageObjectPayloadConverter();
|
||||
var obj = converter.Convert(containerName, objectName, headers);
|
||||
|
||||
Assert.IsNotNull(obj);
|
||||
Assert.IsInstanceOfType(obj, typeof(StorageObject));
|
||||
Assert.AreEqual(1234, obj.Length);
|
||||
Assert.AreEqual("d41d8cd98f00b204e9800998ecf8427e", obj.ETag);
|
||||
Assert.AreEqual("application/octet-stream", obj.ContentType);
|
||||
Assert.AreEqual(DateTime.Parse("Wed, 12 Mar 2014 23:42:23 GMT"), obj.LastModified);
|
||||
Assert.AreEqual(objectName, obj.Name);
|
||||
Assert.AreEqual(containerName, obj.ContainerName);
|
||||
Assert.AreEqual(1, obj.Metadata.Count());
|
||||
Assert.IsTrue(obj.Metadata.ContainsKey("Test1"));
|
||||
Assert.AreEqual("Test1", obj.Metadata["Test1"]);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CanParseObjectFromHeadersWithDynamicFlagSetToEmpty()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var objectName = "TestObject";
|
||||
|
||||
var headers = new HttpHeadersAbstraction()
|
||||
{
|
||||
{"Content-Length", "1234"},
|
||||
{"Content-Type", "application/octet-stream"},
|
||||
{"Last-Modified", "Wed, 12 Mar 2014 23:42:23 GMT"},
|
||||
{"ETag", "d41d8cd98f00b204e9800998ecf8427e"},
|
||||
{"X-Object-Meta-Test1","Test1"},
|
||||
{"X-Object-Manifest", string.Empty}
|
||||
};
|
||||
|
||||
var converter = new StorageObjectPayloadConverter();
|
||||
var obj = converter.Convert(containerName, objectName, headers);
|
||||
|
||||
Assert.IsNotNull(obj);
|
||||
Assert.IsInstanceOfType(obj, typeof(StorageObject));
|
||||
Assert.AreEqual(1234, obj.Length);
|
||||
Assert.AreEqual("d41d8cd98f00b204e9800998ecf8427e", obj.ETag);
|
||||
Assert.AreEqual("application/octet-stream", obj.ContentType);
|
||||
Assert.AreEqual(DateTime.Parse("Wed, 12 Mar 2014 23:42:23 GMT"), obj.LastModified);
|
||||
Assert.AreEqual(objectName, obj.Name);
|
||||
Assert.AreEqual(containerName, obj.ContainerName);
|
||||
Assert.AreEqual(1, obj.Metadata.Count());
|
||||
Assert.IsTrue(obj.Metadata.ContainsKey("Test1"));
|
||||
Assert.AreEqual("Test1", obj.Metadata["Test1"]);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CanParseDynamicManifestFromHeadersWithMetadata()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var objectName = "TestObject";
|
||||
|
||||
var headers = new HttpHeadersAbstraction()
|
||||
{
|
||||
{"Content-Length", "1234"},
|
||||
{"Content-Type", "application/octet-stream"},
|
||||
{"Last-Modified", "Wed, 12 Mar 2014 23:42:23 GMT"},
|
||||
{"ETag", "d41d8cd98f00b204e9800998ecf8427e"},
|
||||
{"X-Object-Meta-Test1","Test1"},
|
||||
{"X-Object-Manifest","a/b"}
|
||||
};
|
||||
|
||||
var converter = new StorageObjectPayloadConverter();
|
||||
var obj = converter.Convert(containerName, objectName, headers);
|
||||
|
||||
Assert.IsNotNull(obj);
|
||||
Assert.IsInstanceOfType(obj, typeof(DynamicLargeObjectManifest));
|
||||
Assert.AreEqual(1234, obj.Length);
|
||||
Assert.AreEqual("d41d8cd98f00b204e9800998ecf8427e", obj.ETag);
|
||||
Assert.AreEqual("application/octet-stream", obj.ContentType);
|
||||
Assert.AreEqual(DateTime.Parse("Wed, 12 Mar 2014 23:42:23 GMT"), obj.LastModified);
|
||||
Assert.AreEqual(objectName, obj.Name);
|
||||
Assert.AreEqual(containerName, obj.ContainerName);
|
||||
Assert.AreEqual(1, obj.Metadata.Count());
|
||||
Assert.IsTrue(obj.Metadata.ContainsKey("Test1"));
|
||||
Assert.AreEqual("Test1", obj.Metadata["Test1"]);
|
||||
|
||||
var manifest = obj as DynamicLargeObjectManifest;
|
||||
Assert.AreEqual("a/b", manifest.SegmentsPath);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
|
@ -544,5 +743,66 @@ namespace Openstack.Test.Storage
|
|||
var converter = new StorageObjectPayloadConverter();
|
||||
converter.Convert(containerName, objectName, headers);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CanConvertSingleStorageObjectToJson()
|
||||
{
|
||||
var obj = new StorageObject("a/b/c", "TestContainer", DateTime.UtcNow, "12345", 54321, string.Empty,
|
||||
new Dictionary<string, string>());
|
||||
|
||||
var converter = new StorageObjectPayloadConverter();
|
||||
var payload = converter.Convert(new List<StorageObject>() { obj});
|
||||
|
||||
var result = JArray.Parse(payload);
|
||||
Assert.AreEqual(1,result.Count);
|
||||
|
||||
var item = result[0];
|
||||
Assert.AreEqual("TestContainer/a/b/c", item["path"]);
|
||||
Assert.AreEqual(54321, item["size_bytes"]);
|
||||
Assert.AreEqual("12345", item["etag"]);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CanConvertMultipleStorageObjectToJson()
|
||||
{
|
||||
var obj = new StorageObject("a/b/c", "TestContainer", DateTime.UtcNow, "12345", 54321, string.Empty,
|
||||
new Dictionary<string, string>());
|
||||
|
||||
var obj2 = new StorageObject("a/b/d", "TestContainer", DateTime.UtcNow, "00000", 11111, string.Empty,
|
||||
new Dictionary<string, string>());
|
||||
|
||||
var converter = new StorageObjectPayloadConverter();
|
||||
var payload = converter.Convert(new List<StorageObject>() { obj, obj2 });
|
||||
|
||||
var result = JArray.Parse(payload);
|
||||
Assert.AreEqual(2, result.Count);
|
||||
|
||||
var item = result[0];
|
||||
Assert.AreEqual("TestContainer/a/b/c", item["path"]);
|
||||
Assert.AreEqual(54321, item["size_bytes"]);
|
||||
Assert.AreEqual("12345", item["etag"]);
|
||||
|
||||
var item2 = result[1];
|
||||
Assert.AreEqual("TestContainer/a/b/d", item2["path"]);
|
||||
Assert.AreEqual(11111, item2["size_bytes"]);
|
||||
Assert.AreEqual("00000", item2["etag"]);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CanConvertEmptyStorageObjectsToJson()
|
||||
{
|
||||
var converter = new StorageObjectPayloadConverter();
|
||||
var payload = converter.Convert(new List<StorageObject>());
|
||||
var result = JArray.Parse(payload);
|
||||
Assert.AreEqual(0, result.Count);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public void CannotConvertNullStorageObjectsToJson()
|
||||
{
|
||||
var converter = new StorageObjectPayloadConverter();
|
||||
converter.Convert(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -386,6 +386,200 @@ namespace Openstack.Test.Storage
|
|||
await client.CreateStorageObject(containerName, objectName, null, new MemoryStream());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task CanCreateStaticStorageManifest()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var objectName = "TestObject";
|
||||
|
||||
var obj = new StorageObject(objectName, containerName, DateTime.UtcNow, "12345", 12345,
|
||||
"application/octet-stream", new Dictionary<string, string>());
|
||||
|
||||
this.ServicePocoClient.CreateStorageManifestDelegate = async (m) =>
|
||||
{
|
||||
Assert.IsInstanceOfType(m,typeof(StaticLargeObjectManifest));
|
||||
return await Task.Run(() => m);
|
||||
};
|
||||
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
await client.CreateStorageManifest(containerName, objectName, new Dictionary<string, string>(), new List<StorageObject>() { obj });
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task CanCreateDynamicStorageManifest()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var objectName = "TestObject";
|
||||
|
||||
this.ServicePocoClient.CreateStorageManifestDelegate = async (m) =>
|
||||
{
|
||||
Assert.IsInstanceOfType(m, typeof(DynamicLargeObjectManifest));
|
||||
return await Task.Run(() => m);
|
||||
};
|
||||
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
await client.CreateStorageManifest(containerName, objectName, new Dictionary<string, string>(), "segments");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public async Task CreatingDynamicStorageManifestWithNullContainerNameThrows()
|
||||
{
|
||||
var manifestName = "TestManifest";
|
||||
var segmentPath = "segments";
|
||||
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
await client.CreateStorageManifest(null, manifestName, new Dictionary<string, string>(), segmentPath);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentException))]
|
||||
public async Task CreatingDynamicStorageManifestWithEmptyContainerNameThrows()
|
||||
{
|
||||
var manifestName = "TestManifest";
|
||||
var segmentPath = "segments";
|
||||
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
await client.CreateStorageManifest(string.Empty, manifestName, new Dictionary<string, string>(), segmentPath);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public async Task CreatingDynamicStorageManifestWithNullManifestNameThrows()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var segmentPath = "segments";
|
||||
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
await client.CreateStorageManifest(containerName, null, new Dictionary<string, string>(), segmentPath);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentException))]
|
||||
public async Task CreatingDynamicStorageManifestWithEmptyManifestNameThrows()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var segmentPath = "segments";
|
||||
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
await client.CreateStorageManifest(containerName, string.Empty, new Dictionary<string, string>(), segmentPath);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public async Task CreatingDynamicStorageManifestWithNullSegmentPathThrows()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var manifestName = "TestManifest";
|
||||
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
await client.CreateStorageManifest(containerName, manifestName, new Dictionary<string, string>(), (string)null);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentException))]
|
||||
public async Task CreatingDynamicStorageManifestWithEmptySegmentPathThrows()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var manifestName = "TestManifest";
|
||||
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
await client.CreateStorageManifest(containerName, manifestName, new Dictionary<string, string>(), string.Empty);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public async Task CreatingDynamicStorageManifestWithNullMetadataThrows()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var manifestName = "TestManifest";
|
||||
var segmentPath = "segments";
|
||||
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
await client.CreateStorageManifest(containerName, manifestName, null, segmentPath);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public async Task CreatingStaticStorageManifestWithNullContainerNameThrows()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var objectName = "TestObject";
|
||||
|
||||
var obj = new StorageObject(objectName, containerName, DateTime.UtcNow, "12345", 12345,
|
||||
"application/octet-stream", new Dictionary<string, string>());
|
||||
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
await client.CreateStorageManifest(null, objectName, new Dictionary<string, string>(), new List<StorageObject>() { obj });
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentException))]
|
||||
public async Task CreatingStaticStorageManifestWithEmptyContainerNameThrows()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var objectName = "TestObject";
|
||||
|
||||
var obj = new StorageObject(objectName, containerName, DateTime.UtcNow, "12345", 12345,
|
||||
"application/octet-stream", new Dictionary<string, string>());
|
||||
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
await client.CreateStorageManifest(string.Empty, objectName, new Dictionary<string, string>(), new List<StorageObject>() { obj });
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public async Task CreatingStaticStorageManifestWithNullManifestNameThrows()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var objectName = "TestObject";
|
||||
|
||||
var obj = new StorageObject(objectName, containerName, DateTime.UtcNow, "12345", 12345,
|
||||
"application/octet-stream", new Dictionary<string, string>());
|
||||
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
await client.CreateStorageManifest(containerName, null, new Dictionary<string, string>(), new List<StorageObject>() { obj });
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentException))]
|
||||
public async Task CreatingStaticStorageManifestWithEmptyManifestNameThrows()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var objectName = "TestObject";
|
||||
|
||||
var obj = new StorageObject(objectName, containerName, DateTime.UtcNow, "12345", 12345,
|
||||
"application/octet-stream", new Dictionary<string, string>());
|
||||
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
await client.CreateStorageManifest(containerName, string.Empty, new Dictionary<string, string>(), new List<StorageObject>() { obj });
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public async Task CreatingStaticStorageManifestWithNullObjectListThrows()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var objectName = "TestObject";
|
||||
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
await client.CreateStorageManifest(containerName, objectName, new Dictionary<string, string>(), (List<StorageObject>)null);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[ExpectedException(typeof(ArgumentNullException))]
|
||||
public async Task CreatingStaticStorageManifestWithNullMetadataThrows()
|
||||
{
|
||||
var containerName = "TestContainer";
|
||||
var objectName = "TestObject";
|
||||
|
||||
var obj = new StorageObject(objectName, containerName, DateTime.UtcNow, "12345", 12345,
|
||||
"application/octet-stream", new Dictionary<string, string>());
|
||||
|
||||
var client = new StorageServiceClient(GetValidCreds(), CancellationToken.None);
|
||||
await client.CreateStorageManifest(containerName, objectName, null, new List<StorageObject>() { obj });
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task CanCreateStorageFolder()
|
||||
{
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -74,6 +74,76 @@ namespace Openstack.Test.Storage
|
|||
return new StorageServiceClientContext(creds, token, "Object Storage");
|
||||
}
|
||||
|
||||
#region CreateManifest Tests
|
||||
|
||||
[TestMethod]
|
||||
public async Task CreateStaticStorageManifestIncludesAuthHeader()
|
||||
{
|
||||
var manifestName = "NewManifest";
|
||||
var containerName = "newContainer";
|
||||
|
||||
var client =
|
||||
new StorageServiceRestClient(GetValidContext());
|
||||
var data = "Some random data";
|
||||
var content = TestHelper.CreateStream(data);
|
||||
|
||||
await client.CreateStaticManifest(containerName, manifestName, new Dictionary<string, string>(), content);
|
||||
|
||||
Assert.IsTrue(this.simulator.Headers.ContainsKey("X-Auth-Token"));
|
||||
Assert.AreEqual(this.authId, this.simulator.Headers["X-Auth-Token"]);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task CreateDynamicStorageManifestIncludesAuthHeader()
|
||||
{
|
||||
var manifestName = "NewManifest";
|
||||
var segPath = "blah/blah";
|
||||
var containerName = "newContainer";
|
||||
|
||||
var client = new StorageServiceRestClient(GetValidContext());
|
||||
|
||||
await client.CreateDynamicManifest(containerName, manifestName, new Dictionary<string, string>(), segPath);
|
||||
|
||||
Assert.IsTrue(this.simulator.Headers.ContainsKey("X-Auth-Token"));
|
||||
Assert.AreEqual(this.authId, this.simulator.Headers["X-Auth-Token"]);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task CreateStaticManifestFormsCorrectUrlAndMethod()
|
||||
{
|
||||
var manifestName = "NewManifest";
|
||||
var containerName = "newContainer";
|
||||
|
||||
var client =
|
||||
new StorageServiceRestClient(GetValidContext());
|
||||
var data = "Some random data";
|
||||
var content = TestHelper.CreateStream(data);
|
||||
|
||||
await client.CreateStaticManifest(containerName, manifestName, new Dictionary<string, string>(), content);
|
||||
|
||||
Assert.AreEqual(string.Format("{0}/{1}/{2}?multipart-manifest=put", endpoint, containerName, manifestName), this.simulator.Uri.ToString());
|
||||
Assert.AreEqual(HttpMethod.Put, this.simulator.Method);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task CreateDynamicManifestFormsCorrectUrlMethodAndHeader()
|
||||
{
|
||||
var manifestName = "NewManifest";
|
||||
var segPath = "blah/blah";
|
||||
var containerName = "newContainer";
|
||||
|
||||
var client = new StorageServiceRestClient(GetValidContext());
|
||||
|
||||
await client.CreateDynamicManifest(containerName, manifestName, new Dictionary<string, string>(), segPath);
|
||||
|
||||
Assert.AreEqual(string.Format("{0}/{1}/{2}", endpoint, containerName, manifestName), this.simulator.Uri.ToString());
|
||||
Assert.AreEqual(HttpMethod.Put, this.simulator.Method);
|
||||
Assert.IsTrue(this.simulator.Headers.ContainsKey("X-Object-Manifest"));
|
||||
Assert.AreEqual(segPath, this.simulator.Headers["X-Object-Manifest"]);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region CreateObject Tests
|
||||
|
||||
[TestMethod]
|
||||
|
@ -1381,5 +1451,96 @@ namespace Openstack.Test.Storage
|
|||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Get Storage Manifest Tests
|
||||
|
||||
[TestMethod]
|
||||
public async Task GetStorageManifestIncludesAuthHeader()
|
||||
{
|
||||
var containerName = "newContainer";
|
||||
var manifestName = "newManifest";
|
||||
|
||||
var client =
|
||||
new StorageServiceRestClient(GetValidContext());
|
||||
|
||||
await client.GetManifestMetadata(containerName, manifestName);
|
||||
|
||||
Assert.IsTrue(this.simulator.Headers.ContainsKey("X-Auth-Token"));
|
||||
Assert.AreEqual(this.authId, this.simulator.Headers["X-Auth-Token"]);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task GetStorageManifestFormsCorrectUrlAndMethod()
|
||||
{
|
||||
var containerName = "newContainer";
|
||||
var manifestName = "a/b/b/manifest";
|
||||
|
||||
var client =
|
||||
new StorageServiceRestClient(GetValidContext());
|
||||
|
||||
await client.GetManifestMetadata(containerName, manifestName);
|
||||
|
||||
Assert.AreEqual(string.Format("{0}/{1}/{2}?multipart-manifest=get", endpoint, containerName, manifestName), this.simulator.Uri.ToString());
|
||||
Assert.AreEqual(HttpMethod.Get, this.simulator.Method);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task ErrorIsReturnedWhenManifestIsNotFound()
|
||||
{
|
||||
var containerName = "newContainer";
|
||||
var manifestName = "a/b/b/manifest";
|
||||
|
||||
var client =
|
||||
new StorageServiceRestClient(GetValidContext());
|
||||
|
||||
var resp = await client.GetManifestMetadata(containerName, manifestName);
|
||||
|
||||
Assert.AreEqual(HttpStatusCode.NotFound, resp.StatusCode);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task CanGetStorageManifest()
|
||||
{
|
||||
var containerName = "newContainer";
|
||||
var manifestName = "a/b/b/manifest";
|
||||
|
||||
var content = TestHelper.CreateStream("[]");
|
||||
content.Position = 0;
|
||||
|
||||
this.simulator.Objects.Add(manifestName, new StorageRestSimulator.StorageItem(manifestName) { Content = content });
|
||||
|
||||
var client =
|
||||
new StorageServiceRestClient(GetValidContext());
|
||||
|
||||
var resp = await client.GetManifestMetadata(containerName, manifestName);
|
||||
|
||||
Assert.AreEqual(HttpStatusCode.OK, resp.StatusCode);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task CanGetStorageManifestWithMetadata()
|
||||
{
|
||||
var containerName = "newContainer";
|
||||
var manifestName = "a/b/b/manifest";
|
||||
|
||||
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(manifestName, new StorageRestSimulator.StorageItem(manifestName) { MetaData = metaData, Content = content });
|
||||
|
||||
var client =
|
||||
new StorageServiceRestClient(GetValidContext());
|
||||
|
||||
var resp = await client.GetManifestMetadata(containerName, manifestName);
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,6 +25,8 @@ namespace Openstack.Test.Storage
|
|||
{
|
||||
public Func<StorageObject, Stream, Task<StorageObject>> CreateStorageObjectDelegate { get; set; }
|
||||
|
||||
public Func<StorageManifest,Task<StorageManifest>> CreateStorageManifestDelegate { get; set; }
|
||||
|
||||
public Func<StorageContainer, Task<StorageContainer>> CreateStorageContainerDelegate { get; set; }
|
||||
|
||||
public Func<string, string, Task> CreateStorageFolderDelegate { get; set; }
|
||||
|
@ -35,6 +37,8 @@ namespace Openstack.Test.Storage
|
|||
|
||||
public Func<string, string, Task<StorageObject>> GetStorageObjectDelegate { get; set; }
|
||||
|
||||
public Func<string, string, Task<StorageManifest>> GetStorageManifestDelegate { get; set; }
|
||||
|
||||
public Func<string, string, Task<StorageFolder>> GetStorageFolderDelegate { get; set; }
|
||||
|
||||
public Func<string, string, Stream, Task<StorageObject>> DownloadStorageObjectDelegate { get; set; }
|
||||
|
@ -54,6 +58,11 @@ namespace Openstack.Test.Storage
|
|||
return await this.CreateStorageObjectDelegate(obj, content);
|
||||
}
|
||||
|
||||
public async Task<StorageManifest> CreateStorageManifest(StorageManifest manifest)
|
||||
{
|
||||
return await this.CreateStorageManifestDelegate(manifest);
|
||||
}
|
||||
|
||||
public async Task CreateStorageContainer(StorageContainer container)
|
||||
{
|
||||
await this.CreateStorageContainerDelegate(container);
|
||||
|
@ -74,14 +83,19 @@ namespace Openstack.Test.Storage
|
|||
return await this.GetStorageObjectDelegate(containerName, objectName);
|
||||
}
|
||||
|
||||
public async Task<StorageManifest> GetStorageManifest(string containerName, string manifestName)
|
||||
{
|
||||
return await this.GetStorageManifestDelegate(containerName, manifestName);
|
||||
}
|
||||
|
||||
public async Task<StorageObject> DownloadStorageObject(string containerName, string objectName, Stream outputStream)
|
||||
{
|
||||
return await this.DownloadStorageObjectDelegate(containerName, objectName, outputStream);
|
||||
}
|
||||
|
||||
public async Task DeleteStorageObject(string containerName, string objectName)
|
||||
public async Task DeleteStorageObject(string containerName, string itemName)
|
||||
{
|
||||
await this.DeleteStorageObjectDelegate(containerName, objectName);
|
||||
await this.DeleteStorageObjectDelegate(containerName, itemName);
|
||||
}
|
||||
|
||||
public async Task DeleteStorageContainer(string containerName)
|
||||
|
@ -94,9 +108,9 @@ namespace Openstack.Test.Storage
|
|||
await this.UpdateStorageContainerDelegate(container);
|
||||
}
|
||||
|
||||
public async Task UpdateStorageObject(StorageObject obj)
|
||||
public async Task UpdateStorageObject(StorageObject item)
|
||||
{
|
||||
await this.UpdateStorageObjectDelegate(obj);
|
||||
await this.UpdateStorageObjectDelegate(item);
|
||||
}
|
||||
|
||||
public async Task<StorageFolder> GetStorageFolder(string containerName, string folderName)
|
||||
|
|
|
@ -24,72 +24,97 @@ namespace Openstack.Test.Storage
|
|||
{
|
||||
public class TestStorageServiceRestClient : IStorageServiceRestClient
|
||||
{
|
||||
public IHttpResponseAbstraction Response { get; set; }
|
||||
public bool CreateStaticManifestCalled = false;
|
||||
public bool CreatedDynamicManifestCalled = false;
|
||||
|
||||
public TestStorageServiceRestClient()
|
||||
{
|
||||
this.Responses = new Queue<IHttpResponseAbstraction>();
|
||||
}
|
||||
|
||||
public Queue<IHttpResponseAbstraction> Responses { get; set; }
|
||||
|
||||
public Task<IHttpResponseAbstraction> CreateObject(string containerName, string objectName, IDictionary<string, string> metadata, Stream content)
|
||||
{
|
||||
return Task.Factory.StartNew(() => Response);
|
||||
return Task.Factory.StartNew(() => Responses.Dequeue());
|
||||
}
|
||||
|
||||
public Task<IHttpResponseAbstraction> CreateDynamicManifest(string containerName, string manifestName, IDictionary<string, string> metadata, string segmentsPath)
|
||||
{
|
||||
CreatedDynamicManifestCalled = true;
|
||||
return Task.Factory.StartNew(() => Responses.Dequeue());
|
||||
}
|
||||
|
||||
public Task<IHttpResponseAbstraction> CreateStaticManifest(string containerName, string manifestName, IDictionary<string, string> metadata, Stream content)
|
||||
{
|
||||
CreateStaticManifestCalled = true;
|
||||
return Task.Factory.StartNew(() => Responses.Dequeue());
|
||||
}
|
||||
|
||||
public Task<IHttpResponseAbstraction> CreateContainer(string containerName, IDictionary<string, string> metadata)
|
||||
{
|
||||
return Task.Factory.StartNew(() => Response);
|
||||
return Task.Factory.StartNew(() => Responses.Dequeue());
|
||||
}
|
||||
|
||||
public Task<IHttpResponseAbstraction> GetObject(string containerName, string objectName)
|
||||
{
|
||||
return Task.Factory.StartNew(() => Response);
|
||||
return Task.Factory.StartNew(() => Responses.Dequeue());
|
||||
}
|
||||
|
||||
public Task<IHttpResponseAbstraction> GetFolder(string containerName, string folderName)
|
||||
{
|
||||
return Task.Factory.StartNew(() => Response);
|
||||
return Task.Factory.StartNew(() => Responses.Dequeue());
|
||||
}
|
||||
|
||||
public Task<IHttpResponseAbstraction> GetContainer(string containerName)
|
||||
{
|
||||
return Task.Factory.StartNew(() => Response);
|
||||
return Task.Factory.StartNew(() => Responses.Dequeue());
|
||||
}
|
||||
|
||||
public Task<IHttpResponseAbstraction> DeleteObject(string containerName, string objectName)
|
||||
{
|
||||
return Task.Factory.StartNew(() => Response);
|
||||
return Task.Factory.StartNew(() => Responses.Dequeue());
|
||||
}
|
||||
|
||||
public Task<IHttpResponseAbstraction> DeleteContainer(string containerName)
|
||||
{
|
||||
return Task.Factory.StartNew(() => Response);
|
||||
return Task.Factory.StartNew(() => Responses.Dequeue());
|
||||
}
|
||||
|
||||
public Task<IHttpResponseAbstraction> UpdateObject(string containerName, string objectName, IDictionary<string, string> metadata)
|
||||
{
|
||||
return Task.Factory.StartNew(() => Response);
|
||||
return Task.Factory.StartNew(() => Responses.Dequeue());
|
||||
}
|
||||
|
||||
public Task<IHttpResponseAbstraction> UpdateContainer(string containerName, IDictionary<string, string> metadata)
|
||||
{
|
||||
return Task.Factory.StartNew(() => Response);
|
||||
return Task.Factory.StartNew(() => Responses.Dequeue());
|
||||
}
|
||||
|
||||
public Task<IHttpResponseAbstraction> GetContainerMetadata(string containerName)
|
||||
{
|
||||
return Task.Factory.StartNew(() => Response);
|
||||
return Task.Factory.StartNew(() => Responses.Dequeue());
|
||||
}
|
||||
|
||||
public Task<IHttpResponseAbstraction> GetObjectMetadata(string containerName, string objectName)
|
||||
{
|
||||
return Task.Factory.StartNew(() => Response);
|
||||
return Task.Factory.StartNew(() => Responses.Dequeue());
|
||||
}
|
||||
|
||||
public Task<IHttpResponseAbstraction> GetManifestMetadata(string containerName, string manifestName)
|
||||
{
|
||||
return Task.Factory.StartNew(() => Responses.Dequeue());
|
||||
}
|
||||
|
||||
public Task<IHttpResponseAbstraction> CopyObject(string sourceContainerName, string sourceObjectName, string targetContainerName,
|
||||
string targetObjectName)
|
||||
{
|
||||
return Task.Factory.StartNew(() => Response);
|
||||
return Task.Factory.StartNew(() => Responses.Dequeue());
|
||||
}
|
||||
|
||||
public Task<IHttpResponseAbstraction> GetAccount()
|
||||
{
|
||||
return Task.Factory.StartNew(() => Response);
|
||||
return Task.Factory.StartNew(() => Responses.Dequeue());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -88,6 +88,7 @@
|
|||
<Compile Include="Identity\OpenstackServiceEndpointPayloadConverter.cs" />
|
||||
<Compile Include="Identity\OpenstackServiceEndpointResolver.cs" />
|
||||
<Compile Include="ServiceRegistrar.cs" />
|
||||
<Compile Include="Storage\DynamicLargeObjectManifest.cs" />
|
||||
<Compile Include="Storage\FolderNameValidator.cs" />
|
||||
<Compile Include="Storage\ContainerNameValidator.cs" />
|
||||
<Compile Include="Storage\IStorageAccountPayloadConverter.cs" />
|
||||
|
@ -99,8 +100,11 @@
|
|||
<Compile Include="Storage\IStorageServicePocoClientFactory.cs" />
|
||||
<Compile Include="Storage\IStorageServiceRestClient.cs" />
|
||||
<Compile Include="Storage\IStorageServiceRestClientFactory.cs" />
|
||||
<Compile Include="Storage\StaticLargeObjectManifest.cs" />
|
||||
<Compile Include="Storage\StorageFolder.cs" />
|
||||
<Compile Include="Storage\StorageFolderPayloadConverter.cs" />
|
||||
<Compile Include="Storage\StorageItemNameExtractor.cs" />
|
||||
<Compile Include="Storage\StorageManifest.cs" />
|
||||
<Compile Include="Storage\StorageServiceClient.cs" />
|
||||
<Compile Include="Storage\StorageServiceClientContext.cs" />
|
||||
<Compile Include="Storage\StorageServiceClientDefinition.cs" />
|
||||
|
|
|
@ -31,6 +31,7 @@ namespace Openstack
|
|||
manager.RegisterServiceInstance(typeof(IStorageServiceRestClientFactory), new StorageServiceRestClientFactory());
|
||||
manager.RegisterServiceInstance(typeof(IStorageContainerNameValidator), new StorageContainerNameValidator());
|
||||
manager.RegisterServiceInstance(typeof(IStorageFolderNameValidator), new StorageFolderNameValidator());
|
||||
manager.RegisterServiceInstance(typeof(IStorageItemNameExtractor), new StorageItemNameExtractor());
|
||||
|
||||
//Identity related clients/services
|
||||
manager.RegisterServiceInstance(typeof(IIdentityServicePocoClientFactory), new IdentityServicePocoClientFactory());
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
// /* ============================================================================
|
||||
// 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.
|
||||
// ============================================================================ */
|
||||
|
||||
namespace Openstack.Storage
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Openstack.Common;
|
||||
|
||||
/// <summary>
|
||||
/// Represents the manifest for a dynamic large object on the remote instance of Openstack.
|
||||
/// </summary>
|
||||
public class DynamicLargeObjectManifest : StorageManifest
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the path where the object segments that make up the manifest can be found.
|
||||
/// </summary>
|
||||
public string SegmentsPath { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the DynamicLargeObjectManifest class.
|
||||
/// </summary>
|
||||
/// <param name="containerName">The name of the parent container.</param>
|
||||
/// <param name="manifestFullName">The full name of the manifest file</param>
|
||||
/// <param name="segmentsPath">The path where the segments that make up this manifest can be found.</param>
|
||||
public DynamicLargeObjectManifest(string containerName, string manifestFullName, string segmentsPath) : this(containerName, manifestFullName, new Dictionary<string, string>(), segmentsPath)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the DynamicLargeObjectManifest class.
|
||||
/// </summary>
|
||||
/// <param name="containerName">The name of the parent container.</param>
|
||||
/// <param name="manifestFullName">The full name of the manifest file</param>
|
||||
/// <param name="metadata">The metadata associated with the storage manifest.</param>
|
||||
/// <param name="segmentsPath">The path where the segments that make up this manifest can be found.</param>
|
||||
public DynamicLargeObjectManifest(string containerName, string manifestFullName, IDictionary<string,string> metadata, string segmentsPath)
|
||||
: base(containerName, manifestFullName, metadata)
|
||||
{
|
||||
segmentsPath.AssertIsNotNullOrEmpty("segmentsPath", "Cannot create a dynamic large object manifest with a null or empty segments path.");
|
||||
this.SegmentsPath = segmentsPath;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the DynamicLargeObjectManifest class.
|
||||
/// </summary>
|
||||
/// <param name="fullName">The full name of the storage manifest.</param>
|
||||
/// <param name="containerName">The name of the parent storage container for the storage manifest.</param>
|
||||
/// <param name="lastModified">The last modified data for the storage manifest.</param>
|
||||
/// <param name="eTag">The ETag for the storage manifest.</param>
|
||||
/// <param name="length">The length/size of the storage manifest.</param>
|
||||
/// <param name="contentType">The content type of the storage manifest.</param>
|
||||
/// <param name="metadata">The metadata associated with the storage manifest.</param>
|
||||
/// <param name="segmentsPath">The path where the segments that make up this manifest can be found.</param>
|
||||
internal DynamicLargeObjectManifest(string fullName, string containerName, DateTime lastModified, string eTag,
|
||||
long length, string contentType, IDictionary<string, string> metadata, string segmentsPath)
|
||||
: base(fullName, containerName, lastModified, eTag, length, contentType, metadata)
|
||||
{
|
||||
this.SegmentsPath = segmentsPath;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -42,6 +42,13 @@ namespace Openstack.Storage
|
|||
/// <returns>The storage object.</returns>
|
||||
StorageObject Convert(string containerName, string objectName, IHttpHeadersAbstraction headers);
|
||||
|
||||
/// <summary>
|
||||
/// Converts a collection of StorageObjects into a Json payload.
|
||||
/// </summary>
|
||||
/// <param name="objects">A collection of StorageObjects to convert.</param>
|
||||
/// <returns>The Json payload.</returns>
|
||||
string Convert(IEnumerable<StorageObject> objects);
|
||||
|
||||
/// <summary>
|
||||
/// Converts a Json token into a storage object.
|
||||
/// </summary>
|
||||
|
|
|
@ -122,6 +122,26 @@ namespace Openstack.Storage
|
|||
/// <returns>An async task.</returns>
|
||||
Task UpdateStorageObject(StorageObject obj);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a storage manifest on the remote Openstack instance.
|
||||
/// </summary>
|
||||
/// <param name="containerName">The name of the parent container.</param>
|
||||
/// <param name="manifestName">The name of the manifest.</param>
|
||||
/// <param name="metadata">Metadata for the manifest.</param>
|
||||
/// <param name="objects">The list of storage objects.</param>
|
||||
/// <returns>An async task.</returns>
|
||||
Task<StorageManifest> CreateStorageManifest(string containerName, string manifestName, IDictionary<string, string> metadata, IEnumerable<StorageObject> objects);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a storage manifest on the remote Openstack instance.
|
||||
/// </summary>
|
||||
/// <param name="containerName">The name of the parent container.</param>
|
||||
/// <param name="manifestName">The name of the manifest.</param>
|
||||
/// <param name="metadata">Metadata for the manifest.</param>
|
||||
/// <param name="segmentsPath">The path to the segment objects in the manifest.</param>
|
||||
/// <returns>An async task.</returns>
|
||||
Task<StorageManifest> CreateStorageManifest(string containerName, string manifestName, IDictionary<string, string> metadata, string segmentsPath);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a storage folder from the remote Openstack instance. The returned folder is a shallow object graph representation.
|
||||
/// </summary>
|
||||
|
|
|
@ -33,6 +33,13 @@ namespace Openstack.Storage
|
|||
/// <returns>A storage object.</returns>
|
||||
Task<StorageObject> CreateStorageObject(StorageObject obj, Stream content);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a storage manifest on the remote Openstack instance.
|
||||
/// </summary>
|
||||
/// <param name="manifest">The storage manifest to create.</param>
|
||||
/// <returns>A storage manifest.</returns>
|
||||
Task<StorageManifest> CreateStorageManifest(StorageManifest manifest);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a storage container on the remote Openstack instance.
|
||||
/// </summary>
|
||||
|
@ -61,6 +68,14 @@ namespace Openstack.Storage
|
|||
/// <returns>The storage object.</returns>
|
||||
Task<StorageObject> GetStorageObject(string containerName, string objectName);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a storage manifest from the remote Openstack instance.
|
||||
/// </summary>
|
||||
/// <param name="containerName">The name of the parent storage container.</param>
|
||||
/// <param name="manifestName">The name of the storage manifest.</param>
|
||||
/// <returns>The storage manifest.</returns>
|
||||
Task<StorageManifest> GetStorageManifest(string containerName, string manifestName);
|
||||
|
||||
/// <summary>
|
||||
/// Downloads the content of a storage object from the remote Openstack instance.
|
||||
/// </summary>
|
||||
|
@ -74,7 +89,7 @@ namespace Openstack.Storage
|
|||
/// Deletes a storage object from the remote Openstack instance.
|
||||
/// </summary>
|
||||
/// <param name="containerName">The name of the parent storage container.</param>
|
||||
/// <param name="objectName">The name of the storage object.</param>
|
||||
/// <param name="objectName">The name of the object to delete.</param>
|
||||
/// <returns>An async task.</returns>
|
||||
Task DeleteStorageObject(string containerName, string objectName);
|
||||
|
||||
|
|
|
@ -36,6 +36,26 @@ namespace Openstack.Storage
|
|||
/// <returns>The Http response from the remote service.</returns>
|
||||
Task<IHttpResponseAbstraction> CreateObject(string containerName, string objectName, IDictionary<string, string> metadata, Stream content);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a dynamic large object manifest on the remote Openstack instance.
|
||||
/// </summary>
|
||||
/// <param name="containerName">The name of the parent storage container.</param>
|
||||
/// <param name="manifestName">The name of the storage manifest.</param>
|
||||
/// <param name="metadata">Metadata associated with the storage manifest.</param>
|
||||
/// <param name="segmentsPath">The path to the segment objects that the manifest points to.</param>
|
||||
/// <returns>The Http response from the remote service.</returns>
|
||||
Task<IHttpResponseAbstraction> CreateDynamicManifest(string containerName, string manifestName, IDictionary<string, string> metadata, string segmentsPath);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a static large object manifest on the remote Openstack instance.
|
||||
/// </summary>
|
||||
/// <param name="containerName">The name of the parent storage container.</param>
|
||||
/// <param name="manifestName">The name of the storage manifest.</param>
|
||||
/// <param name="metadata">Metadata associated with the storage manifest.</param>
|
||||
/// <param name="content">The manifests content.</param>
|
||||
/// <returns>The Http response from the remote service.</returns>
|
||||
Task<IHttpResponseAbstraction> CreateStaticManifest(string containerName, string manifestName, IDictionary<string, string> metadata, Stream content);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a storage container on the remote Openstack instance.
|
||||
/// </summary>
|
||||
|
@ -114,6 +134,14 @@ namespace Openstack.Storage
|
|||
/// <returns>The Http response from the remote service.</returns>
|
||||
Task<IHttpResponseAbstraction> GetObjectMetadata(string containerName, string objectName);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the metadata for a storage manifest from the remote Openstack instance.
|
||||
/// </summary>
|
||||
/// <param name="containerName">The name of the parent storage container.</param>
|
||||
/// <param name="manifestName">The name of the storage manifest.</param>
|
||||
/// <returns>The Http response from the remote service.</returns>
|
||||
Task<IHttpResponseAbstraction> GetManifestMetadata(string containerName, string manifestName);
|
||||
|
||||
/// <summary>
|
||||
/// Copies an object on the remote Openstack instance.
|
||||
/// </summary>
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
// /* ============================================================================
|
||||
// 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.
|
||||
// ============================================================================ */
|
||||
|
||||
namespace Openstack.Storage
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Openstack.Common;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a manifest for a static large object on the remote Openstack instance.
|
||||
/// </summary>
|
||||
public class StaticLargeObjectManifest : StorageManifest
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets a collection of objects in the manifest.
|
||||
/// </summary>
|
||||
public ICollection<StorageObject> Objects { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the StaticLargeObjectManifest class.
|
||||
/// </summary>
|
||||
/// <param name="containerName">The name of the parent container.</param>
|
||||
/// <param name="manifestFullName">The full name of the manifest.</param>
|
||||
/// <param name="objects">A collection of objects that are included in the manifest.</param>
|
||||
public StaticLargeObjectManifest(string containerName, string manifestFullName, ICollection<StorageObject> objects ) : base(containerName, manifestFullName)
|
||||
{
|
||||
objects.AssertIsNotNull("objects","Cannot create a static large object manifest with a null object collection.");
|
||||
this.Objects = objects;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the StaticLargeObjectManifest class.
|
||||
/// </summary>
|
||||
/// <param name="containerName">The name of the parent container.</param>
|
||||
/// <param name="manifestFullName">The full name of the manifest.</param>
|
||||
/// <param name="objects">A collection of objects that are included in the manifest.</param>
|
||||
/// <param name="metadata">The metadata associated with the storage manifest.</param>
|
||||
public StaticLargeObjectManifest(string containerName, string manifestFullName, IDictionary<string, string> metadata, ICollection<StorageObject> objects)
|
||||
: base(containerName, manifestFullName, metadata)
|
||||
{
|
||||
objects.AssertIsNotNull("objects", "Cannot create a static large object manifest with a null object collection.");
|
||||
this.Objects = objects;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the StaticLargeObjectManifest class.
|
||||
/// </summary>
|
||||
/// <param name="fullName">The full name of the storage manifest.</param>
|
||||
/// <param name="containerName">The name of the parent storage container for the storage manifest.</param>
|
||||
/// <param name="lastModified">The last modified data for the storage manifest.</param>
|
||||
/// <param name="eTag">The ETag for the storage manifest.</param>
|
||||
/// <param name="length">The length/size of the storage manifest.</param>
|
||||
/// <param name="contentType">The content type of the storage manifest.</param>
|
||||
/// <param name="metadata">The metadata associated with the storage manifest.</param>
|
||||
internal StaticLargeObjectManifest(string fullName, string containerName, DateTime lastModified, string eTag,
|
||||
long length, string contentType, IDictionary<string, string> metadata)
|
||||
: base(fullName, containerName, lastModified, eTag, length, contentType, metadata)
|
||||
{
|
||||
this.Objects = new List<StorageObject>();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -19,6 +19,7 @@ namespace Openstack.Storage
|
|||
using System.Linq;
|
||||
using Openstack.Common;
|
||||
using System.Collections.Generic;
|
||||
using Openstack.Common.ServiceLocation;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a storage folder on a remote Openstack instance.
|
||||
|
@ -78,10 +79,8 @@ namespace Openstack.Storage
|
|||
/// <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('/');
|
||||
var lastIndex = fullName.LastIndexOf('/');
|
||||
lastIndex++;
|
||||
return fullName.Substring(lastIndex, fullName.Length - lastIndex);
|
||||
var extractor = ServiceLocator.Instance.Locate<IStorageItemNameExtractor>();
|
||||
return extractor.ExtractName(fullFolderName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,13 +44,13 @@ namespace Openstack.Storage
|
|||
foreach (var obj in sortedObjectList)
|
||||
{
|
||||
//if the name has any consecutive slashes in the name, skip it.
|
||||
if (Regex.IsMatch(obj.Name, consecutiveSlashRegex))
|
||||
if (Regex.IsMatch(obj.FullName, consecutiveSlashRegex))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
//split the input using a forward slash as the folder delimiter, and separate the object name (if we have one) and the folder path.
|
||||
var folderParts = obj.Name.TrimStart('/').Split('/');
|
||||
var folderParts = obj.FullName.TrimStart('/').Split('/');
|
||||
var objectName = folderParts.Last(); //this will be string.empty if the object name ends in a "/" indicating that it's a folder.
|
||||
folderParts = folderParts.Take(folderParts.Length - 1).ToArray();
|
||||
|
||||
|
@ -113,7 +113,7 @@ namespace Openstack.Storage
|
|||
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);
|
||||
objects.RemoveAll(o => string.Compare(o.FullName, folderName, StringComparison.InvariantCulture) == 0);
|
||||
|
||||
return new StorageFolder(folderName, subFolders.Select(ParseSubFolder), objects);
|
||||
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
// /* ============================================================================
|
||||
// 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.
|
||||
// ============================================================================ */
|
||||
|
||||
namespace Openstack.Storage
|
||||
{
|
||||
/// <summary>
|
||||
/// Extracts the "friendly" name of a storage item.
|
||||
/// </summary>
|
||||
public interface IStorageItemNameExtractor
|
||||
{
|
||||
/// <summary>
|
||||
/// Extracts the "friendly" name of a storage item, given the items full name.
|
||||
/// </summary>
|
||||
/// <param name="fullName">The items full name.</param>
|
||||
/// <returns>The items friendly name. (e.g. returns 'b' if the items full name is 'a/b')</returns>
|
||||
string ExtractName(string fullName);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
internal class StorageItemNameExtractor : IStorageItemNameExtractor
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string ExtractName(string fullItemName)
|
||||
{
|
||||
var fullName = fullItemName.Trim('/');
|
||||
var lastIndex = fullName.LastIndexOf('/');
|
||||
lastIndex++;
|
||||
return fullName.Substring(lastIndex, fullName.Length - lastIndex);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
// /* ============================================================================
|
||||
// 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.
|
||||
// ============================================================================ */
|
||||
|
||||
namespace Openstack.Storage
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
/// <summary>
|
||||
/// Base class for storage manifest objects.
|
||||
/// </summary>
|
||||
public abstract class StorageManifest : StorageObject
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new instance of the StorageManifest class.
|
||||
/// </summary>
|
||||
/// <param name="containerName">The name of the parent container.</param>
|
||||
/// <param name="manifestName">The name of the manifest.</param>
|
||||
internal StorageManifest(string containerName, string manifestName)
|
||||
: base(manifestName, containerName)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the StorageManifest class.
|
||||
/// </summary>
|
||||
/// <param name="containerName">The name of the parent container.</param>
|
||||
/// <param name="manifestName">The name of the manifest.</param>
|
||||
/// <param name="metadata">The related metadata for the manifest.</param>
|
||||
internal StorageManifest(string containerName, string manifestName,IDictionary<string, string> metadata )
|
||||
: base(manifestName, containerName, metadata)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the StorageManifest class.
|
||||
/// </summary>
|
||||
/// <param name="containerName">The name of the parent container.</param>
|
||||
/// <param name="fullName">The name of the manifest.</param>
|
||||
/// <param name="length">The length of the manifest.</param>
|
||||
/// /// <param name="contentType">The content type of the manifest.</param>
|
||||
/// <param name="lastModified">The time that the last modification of the manifest was made.</param>
|
||||
/// <param name="eTag">The eTag for the manifest.</param>
|
||||
/// <param name="metadata">The related metadata for the manifest.</param>
|
||||
internal StorageManifest(string fullName, string containerName, DateTime lastModified, string eTag,
|
||||
long length, string contentType, IDictionary<string, string> metadata)
|
||||
: base(fullName, containerName, lastModified, eTag, length, contentType, metadata)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -19,6 +19,7 @@ namespace Openstack.Storage
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Openstack.Common;
|
||||
using Openstack.Common.ServiceLocation;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a storage object.
|
||||
|
@ -26,37 +27,42 @@ namespace Openstack.Storage
|
|||
public class StorageObject
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the name of the storage object.
|
||||
/// Gets the friendly name of the storage item.
|
||||
/// </summary>
|
||||
public string Name { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the parent storage container for the storage object.
|
||||
/// Gets the full name of the storage item.
|
||||
/// </summary>
|
||||
public string FullName { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the parent storage container for the storage item.
|
||||
/// </summary>
|
||||
public string ContainerName { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the last modified data for the storage object.
|
||||
/// Gets the last modified data for the storage item.
|
||||
/// </summary>
|
||||
public DateTime LastModified { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the ETag for the storage object.
|
||||
/// Gets the ETag for the storage item.
|
||||
/// </summary>
|
||||
public string ETag { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the length/size of the storage object.
|
||||
/// Gets the length/size of the storage item.
|
||||
/// </summary>
|
||||
public long Length { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the content type of the storage object.
|
||||
/// Gets the content type of the storage item.
|
||||
/// </summary>
|
||||
public string ContentType { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the metadata associated with the storage object.
|
||||
/// Gets the metadata associated with the storage item.
|
||||
/// </summary>
|
||||
public IDictionary<string, string> Metadata { get; private set; }
|
||||
|
||||
|
@ -70,7 +76,6 @@ namespace Openstack.Storage
|
|||
public StorageObject(string name, string containerName, string contentType, IDictionary<string, string> metadata)
|
||||
: this(name, containerName, DateTime.UtcNow, string.Empty, 0, contentType, metadata)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -81,7 +86,17 @@ namespace Openstack.Storage
|
|||
public StorageObject(string name, string containerName)
|
||||
: this(name, containerName, DateTime.UtcNow, string.Empty, 0, string.Empty, new Dictionary<string, string>())
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the StorageObject class.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the storage object.</param>
|
||||
/// <param name="containerName">The name of the parent storage container for the storage object.</param>
|
||||
/// <param name="metadata">The metadata associated with the storage object.</param>
|
||||
public StorageObject(string name, string containerName, IDictionary<string, string> metadata )
|
||||
: this(name, containerName, DateTime.UtcNow, string.Empty, 0, string.Empty, metadata)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -101,16 +116,16 @@ namespace Openstack.Storage
|
|||
/// <summary>
|
||||
/// Creates a new instance of the StorageObject class.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the storage object.</param>
|
||||
/// <param name="fullName">The full name of the storage object.</param>
|
||||
/// <param name="containerName">The name of the parent storage container for the storage object.</param>
|
||||
/// <param name="lastModified">The last modified data for the storage object.</param>
|
||||
/// <param name="eTag">The ETag for the storage object.</param>
|
||||
/// <param name="length">The length/size of the storage object.</param>
|
||||
/// <param name="contentType">The content type of the storage object.</param>
|
||||
/// <param name="metadata">The metadata associated with the storage object.</param>
|
||||
internal StorageObject(string name, string containerName, DateTime lastModified, string eTag, long length, string contentType, IDictionary<string, string> metadata )
|
||||
internal StorageObject(string fullName, string containerName, DateTime lastModified, string eTag, long length, string contentType, IDictionary<string, string> metadata)
|
||||
{
|
||||
name.AssertIsNotNullOrEmpty("name");
|
||||
fullName.AssertIsNotNullOrEmpty("fullName");
|
||||
containerName.AssertIsNotNullOrEmpty("containerName");
|
||||
lastModified.AssertIsNotNull("lastModified");
|
||||
eTag.AssertIsNotNull("eTag");
|
||||
|
@ -118,7 +133,8 @@ namespace Openstack.Storage
|
|||
contentType.AssertIsNotNull("contentType");
|
||||
metadata.AssertIsNotNull("metadata");
|
||||
|
||||
this.Name = name;
|
||||
this.FullName = fullName;
|
||||
this.Name = ExtractName(fullName);
|
||||
this.ContainerName = containerName;
|
||||
this.LastModified = lastModified;
|
||||
this.ETag = eTag;
|
||||
|
@ -126,5 +142,16 @@ namespace Openstack.Storage
|
|||
this.ContentType = contentType;
|
||||
this.Metadata = metadata;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extracts the "friendly" name from the objects full name.
|
||||
/// </summary>
|
||||
/// <param name="fullItemName">The full name of the object.</param>
|
||||
/// <returns>The "friendly" name of the object. (e.g. "b" if the item path is "a/b")</returns>
|
||||
internal static string ExtractName(string fullItemName)
|
||||
{
|
||||
var extractor = ServiceLocator.Instance.Locate<IStorageItemNameExtractor>();
|
||||
return extractor.ExtractName(fullItemName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -56,6 +56,25 @@ namespace Openstack.Storage
|
|||
return objects;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string Convert(IEnumerable<StorageObject> objects)
|
||||
{
|
||||
objects.AssertIsNotNull("objects","Cannot convert a null storage object collection to Json.");
|
||||
|
||||
var objectsPayload = new JArray();
|
||||
foreach (var obj in objects)
|
||||
{
|
||||
dynamic item = new System.Dynamic.ExpandoObject();
|
||||
item.path = string.Format("{0}/{1}",obj.ContainerName, obj.FullName);
|
||||
item.size_bytes = obj.Length;
|
||||
item.etag = obj.ETag;
|
||||
|
||||
objectsPayload.Add(JToken.FromObject(item));
|
||||
}
|
||||
|
||||
return objectsPayload.ToString();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public StorageObject ConvertSingle(JToken obj, string containerName)
|
||||
{
|
||||
|
@ -101,12 +120,47 @@ namespace Openstack.Storage
|
|||
var contentType = headers["Content-Type"].First();
|
||||
var metadata = headers.Where(kvp => kvp.Key.StartsWith("X-Object-Meta")).ToDictionary(header => header.Key.Substring(14, header.Key.Length - 14), header => header.Value.First());
|
||||
|
||||
return new StorageObject(objectName, containerName, lastModified, eTag, length, contentType, metadata);
|
||||
return CreateStorageObject(objectName, containerName, lastModified, eTag, length, contentType, metadata, headers);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new HttpParseException(string.Format("Storage object '{0}' could not be parsed.", objectName), ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the appropriate storage object based on the given parameters.
|
||||
/// </summary>
|
||||
/// <param name="objectName">the name of the object.</param>
|
||||
/// <param name="containerName">The name of the parent container.</param>
|
||||
/// <param name="lastModified">The last modified date of the object.</param>
|
||||
/// <param name="eTag">The eTag for the object.</param>
|
||||
/// <param name="length">The length of the object.</param>
|
||||
/// <param name="contentType">The content type of the object.</param>
|
||||
/// <param name="metadata">The associated metadata for the object.</param>
|
||||
/// <param name="headers">The http headers from the object request.</param>
|
||||
/// <returns>An instance of the StorageObject class.</returns>
|
||||
internal StorageObject CreateStorageObject(string objectName, string containerName, DateTime lastModified, string eTag, long length, string contentType, IDictionary<string, string> metadata, IHttpHeadersAbstraction headers)
|
||||
{
|
||||
IEnumerable<string> values;
|
||||
if (headers.TryGetValue("X-Static-Large-Object", out values))
|
||||
{
|
||||
if (values.Any(v => string.Compare(v, "true", StringComparison.InvariantCultureIgnoreCase) == 0))
|
||||
{
|
||||
return new StaticLargeObjectManifest(objectName, containerName, lastModified, eTag, length, contentType, metadata);
|
||||
}
|
||||
}
|
||||
|
||||
if (headers.TryGetValue("X-Object-Manifest", out values))
|
||||
{
|
||||
var segPath = values.FirstOrDefault(v => !string.IsNullOrEmpty(v));
|
||||
if (!string.IsNullOrEmpty(segPath))
|
||||
{
|
||||
return new DynamicLargeObjectManifest(objectName, containerName, lastModified, eTag, length, contentType, metadata, segPath);
|
||||
}
|
||||
}
|
||||
|
||||
return new StorageObject(objectName, containerName, lastModified, eTag, length, contentType, metadata);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -121,6 +121,35 @@ namespace Openstack.Storage
|
|||
await client.UpdateStorageObject(obj);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task<StorageManifest> CreateStorageManifest(string containerName, string manifestName, IDictionary<string, string> metadata, IEnumerable<StorageObject> objects)
|
||||
{
|
||||
containerName.AssertIsNotNullOrEmpty("containerName", "Cannot create a storage manifest with a container name that is null or empty.");
|
||||
manifestName.AssertIsNotNullOrEmpty("manifestNamee", "Cannot create a storage manifest with a name that is null or empty.");
|
||||
metadata.AssertIsNotNull("metadata","Cannot create a storage manifest with null metadata.");
|
||||
|
||||
var client = this.GetPocoClient();
|
||||
|
||||
var manifest = new StaticLargeObjectManifest(containerName, manifestName, metadata, objects.ToList());
|
||||
|
||||
return await client.CreateStorageManifest(manifest);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task<StorageManifest> CreateStorageManifest(string containerName, string manifestName, IDictionary<string, string> metadata, string segmentsPath)
|
||||
{
|
||||
containerName.AssertIsNotNullOrEmpty("containerName", "Cannot create a storage manifest with a container name that is null or empty.");
|
||||
manifestName.AssertIsNotNullOrEmpty("manifestNamee", "Cannot create a storage manifest with a name that is null or empty.");
|
||||
metadata.AssertIsNotNull("metadata", "Cannot create a storage manifest with null metadata.");
|
||||
segmentsPath.AssertIsNotNullOrEmpty("segmentsPath", "Cannot create storage manifest with a null or empty segments path.");
|
||||
|
||||
var client = this.GetPocoClient();
|
||||
|
||||
var manifest = new DynamicLargeObjectManifest(containerName, manifestName, metadata, segmentsPath);
|
||||
|
||||
return await client.CreateStorageManifest(manifest);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task<StorageFolder> GetStorageFolder(string containerName, string folderName)
|
||||
{
|
||||
|
@ -200,7 +229,7 @@ namespace Openstack.Storage
|
|||
var container = await client.GetStorageContainer(containerName);
|
||||
foreach (var storageObject in container.Objects)
|
||||
{
|
||||
objects.Add(await client.GetStorageObject(containerName, storageObject.Name));
|
||||
objects.Add(await client.GetStorageObject(containerName, storageObject.FullName));
|
||||
}
|
||||
|
||||
return objects;
|
||||
|
|
|
@ -24,7 +24,7 @@ namespace Openstack.Storage
|
|||
using System.Collections.Generic;
|
||||
using Openstack.Common;
|
||||
using Openstack.Common.ServiceLocation;
|
||||
|
||||
using Openstack.Common.Http;
|
||||
|
||||
/// <inheritdoc/>
|
||||
internal class StorageServicePocoClient : IStorageServicePocoClient
|
||||
|
@ -43,12 +43,12 @@ namespace Openstack.Storage
|
|||
/// <inheritdoc/>
|
||||
public async Task<StorageObject> CreateStorageObject(StorageObject obj, Stream content)
|
||||
{
|
||||
obj.ContainerName.AssertIsNotNullOrEmpty("containerName", "Cannot create a storage object with a null or empty container name.");
|
||||
obj.AssertIsNotNull("obj","Cannot Create a null storage object.");
|
||||
obj.AssertIsNotNull("obj", "Cannot create a null storage object.");
|
||||
obj.ContainerName.AssertIsNotNullOrEmpty("obj.ContainerName", "Cannot create a storage object with a null or empty container name.");
|
||||
obj.Name.AssertIsNotNullOrEmpty("obj.Name","Cannot create a storage object without a name.");
|
||||
|
||||
var client = this.GetRestClient();
|
||||
var resp = await client.CreateObject(obj.ContainerName, obj.Name, obj.Metadata, content);
|
||||
var resp = await client.CreateObject(obj.ContainerName, obj.FullName, obj.Metadata, content);
|
||||
|
||||
if (resp.StatusCode != HttpStatusCode.Created)
|
||||
{
|
||||
|
@ -56,11 +56,48 @@ namespace Openstack.Storage
|
|||
}
|
||||
|
||||
var converter = ServiceLocator.Instance.Locate<IStorageObjectPayloadConverter>();
|
||||
var respObj = converter.Convert(obj.ContainerName, obj.Name, resp.Headers);
|
||||
var respObj = converter.Convert(obj.ContainerName, obj.FullName, resp.Headers);
|
||||
|
||||
return respObj;
|
||||
}
|
||||
|
||||
public async Task<StorageManifest> CreateStorageManifest(StorageManifest manifest)
|
||||
{
|
||||
manifest.AssertIsNotNull("manifest", "Cannot create a null storage manifest.");
|
||||
manifest.ContainerName.AssertIsNotNullOrEmpty("manifest.ContainerName", "Cannot create a storage manifest with a null or empty container name.");
|
||||
manifest.Name.AssertIsNotNullOrEmpty("manifest.Name", "Cannot create a storage manifest without a name.");
|
||||
|
||||
var client = this.GetRestClient();
|
||||
IHttpResponseAbstraction resp;
|
||||
|
||||
var dynamicManifest = manifest as DynamicLargeObjectManifest;
|
||||
var staticManifest = manifest as StaticLargeObjectManifest;
|
||||
|
||||
if (dynamicManifest == null && staticManifest == null)
|
||||
{
|
||||
throw new InvalidOperationException(string.Format("Failed to create storage manifest '{0}'. The given manifest type is not supported: '{1}'.", manifest.Name, manifest.GetType().Name));
|
||||
}
|
||||
|
||||
if (dynamicManifest != null) //dynamic large object manifest
|
||||
{
|
||||
resp = await client.CreateDynamicManifest(dynamicManifest.ContainerName, dynamicManifest.FullName, dynamicManifest.Metadata, dynamicManifest.SegmentsPath);
|
||||
}
|
||||
else //static large object manifest
|
||||
{
|
||||
var converter = ServiceLocator.Instance.Locate<IStorageObjectPayloadConverter>();
|
||||
var manifestPayload = converter.Convert(staticManifest.Objects).ConvertToStream();
|
||||
|
||||
resp = await client.CreateStaticManifest(staticManifest.ContainerName, staticManifest.FullName, staticManifest.Metadata, manifestPayload);
|
||||
}
|
||||
|
||||
if (resp.StatusCode != HttpStatusCode.Created)
|
||||
{
|
||||
throw new InvalidOperationException(string.Format("Failed to create storage manifest '{0}'. The remote server returned the following status code: '{1}'.", manifest.Name, resp.StatusCode));
|
||||
}
|
||||
|
||||
return await this.GetStorageManifest(manifest.ContainerName, manifest.FullName);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task CreateStorageContainer(StorageContainer container)
|
||||
{
|
||||
|
@ -132,9 +169,45 @@ namespace Openstack.Storage
|
|||
var converter = ServiceLocator.Instance.Locate<IStorageObjectPayloadConverter>();
|
||||
var obj = converter.Convert(containerName, objectName, resp.Headers);
|
||||
|
||||
//If the request object is actually a manifest object, then make sure we go back out and get the details of the manifest.
|
||||
if (obj is StorageManifest)
|
||||
{
|
||||
return await GetStorageManifest(containerName, objectName);
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
public async Task<StorageManifest> GetStorageManifest(string containerName, string manifestName)
|
||||
{
|
||||
containerName.AssertIsNotNullOrEmpty("containerName", "Cannot get a storage manifest with a container name that is null or empty.");
|
||||
manifestName.AssertIsNotNullOrEmpty("manifestName", "Cannot get a storage manifest with a name that is null or empty.");
|
||||
|
||||
var client = this.GetRestClient();
|
||||
var resp = await client.GetManifestMetadata(containerName, manifestName);
|
||||
|
||||
if (resp.StatusCode != HttpStatusCode.OK && resp.StatusCode != HttpStatusCode.NoContent)
|
||||
{
|
||||
throw new InvalidOperationException(string.Format("Failed to get storage manifest '{0}'. The remote server returned the following status code: '{1}'.", manifestName, resp.StatusCode));
|
||||
}
|
||||
|
||||
var objectConverter = ServiceLocator.Instance.Locate<IStorageObjectPayloadConverter>();
|
||||
var obj = objectConverter.Convert(containerName, manifestName, resp.Headers);
|
||||
|
||||
if (!(obj is StorageManifest))
|
||||
{
|
||||
throw new InvalidOperationException(string.Format("Failed to get storage manifest '{0}'. The requested object is not a manifest.", manifestName));
|
||||
}
|
||||
|
||||
if (obj is StaticLargeObjectManifest)
|
||||
{
|
||||
var manifest = obj as StaticLargeObjectManifest;
|
||||
manifest.Objects = objectConverter.Convert(containerName, await resp.ReadContentAsStringAsync()).ToList();
|
||||
}
|
||||
|
||||
return obj as StorageManifest;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task<StorageObject> DownloadStorageObject(string containerName, string objectName, Stream outputStream)
|
||||
{
|
||||
|
@ -160,17 +233,17 @@ namespace Openstack.Storage
|
|||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task DeleteStorageObject(string containerName, string objectName)
|
||||
public async Task DeleteStorageObject(string containerName, string itemName)
|
||||
{
|
||||
containerName.AssertIsNotNullOrEmpty("containerName", "Cannot delete a storage object with a container name that is null or empty.");
|
||||
objectName.AssertIsNotNullOrEmpty("objectName", "Cannot delete a storage object with a name that is null or empty.");
|
||||
itemName.AssertIsNotNullOrEmpty("objectName", "Cannot delete a storage object with a name that is null or empty.");
|
||||
|
||||
var client = this.GetRestClient();
|
||||
var resp = await client.DeleteObject(containerName, objectName);
|
||||
var resp = await client.DeleteObject(containerName, itemName);
|
||||
|
||||
if (resp.StatusCode != HttpStatusCode.OK && resp.StatusCode != HttpStatusCode.NoContent)
|
||||
{
|
||||
throw new InvalidOperationException(string.Format("Failed to delete storage object '{0}'. The remote server returned the following status code: '{1}'.", objectName, resp.StatusCode));
|
||||
throw new InvalidOperationException(string.Format("Failed to delete storage object '{0}'. The remote server returned the following status code: '{1}'.", itemName, resp.StatusCode));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -203,17 +276,17 @@ namespace Openstack.Storage
|
|||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task UpdateStorageObject(StorageObject obj)
|
||||
public async Task UpdateStorageObject(StorageObject item)
|
||||
{
|
||||
obj.ContainerName.AssertIsNotNullOrEmpty("containerName", "Cannot update a storage object with a container name that is null or empty.");
|
||||
obj.Name.AssertIsNotNullOrEmpty("objectName", "Cannot update a storage object with a name that is null or empty.");
|
||||
item.ContainerName.AssertIsNotNullOrEmpty("containerName", "Cannot update a storage object with a container name that is null or empty.");
|
||||
item.Name.AssertIsNotNullOrEmpty("objectName", "Cannot update a storage object with a name that is null or empty.");
|
||||
|
||||
var client = this.GetRestClient();
|
||||
var resp = await client.UpdateObject(obj.ContainerName, obj.Name, obj.Metadata);
|
||||
var resp = await client.UpdateObject(item.ContainerName, item.Name, item.Metadata);
|
||||
|
||||
if (resp.StatusCode != HttpStatusCode.Accepted)
|
||||
{
|
||||
throw new InvalidOperationException(string.Format("Failed to update storage object '{0}'. The remote server returned the following status code: '{1}'.", obj.Name, resp.StatusCode));
|
||||
throw new InvalidOperationException(string.Format("Failed to update storage object '{0}'. The remote server returned the following status code: '{1}'.", item.Name, resp.StatusCode));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -59,6 +59,46 @@ namespace Openstack.Storage
|
|||
return await client.SendAsync();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task<IHttpResponseAbstraction> CreateDynamicManifest(string containerName, string manifestName, IDictionary<string, string> metadata, string segmentsPath)
|
||||
{
|
||||
AssertContainerNameIsValid(containerName);
|
||||
manifestName.AssertIsNotNullOrEmpty("manifestName","Cannot create a storage manifest with a null or empty name.");
|
||||
segmentsPath.AssertIsNotNullOrEmpty("segmentsPath","Cannot create a dynamic large object manifest with a null or empty segments path.");
|
||||
metadata.AssertIsNotNull("metadata","Cannot create a storage manifest with null metadata.");
|
||||
|
||||
var client = this.GetHttpClient(this.context);
|
||||
|
||||
client.Uri = CreateRequestUri(GetServiceEndpoint(this.context), containerName, manifestName);
|
||||
client.Method = HttpMethod.Put;
|
||||
client.Content = new MemoryStream();
|
||||
|
||||
client.Headers.Add("X-Object-Manifest", segmentsPath);
|
||||
this.AddItemMetadata(metadata, client);
|
||||
|
||||
return await client.SendAsync();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task<IHttpResponseAbstraction> CreateStaticManifest(string containerName, string manifestName, IDictionary<string, string> metadata, Stream content)
|
||||
{
|
||||
AssertContainerNameIsValid(containerName);
|
||||
manifestName.AssertIsNotNullOrEmpty("manifestName", "Cannot create a storage manifest with a null or empty name.");
|
||||
metadata.AssertIsNotNull("metadata", "Cannot create a storage manifest with null metadata.");
|
||||
content.AssertIsNotNull("content","Cannot create a static large object manifest with null content.");
|
||||
|
||||
var client = this.GetHttpClient(this.context);
|
||||
|
||||
var baseUri = CreateRequestUri(GetServiceEndpoint(this.context), containerName);
|
||||
client.Uri = new Uri(string.Format("{0}/{1}?multipart-manifest=put", baseUri, manifestName));
|
||||
client.Method = HttpMethod.Put;
|
||||
client.Content = content;
|
||||
|
||||
this.AddItemMetadata(metadata, client);
|
||||
|
||||
return await client.SendAsync();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task<IHttpResponseAbstraction> CreateContainer(string containerName, IDictionary<string, string> metadata)
|
||||
{
|
||||
|
@ -196,6 +236,21 @@ namespace Openstack.Storage
|
|||
return await client.SendAsync();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task<IHttpResponseAbstraction> GetManifestMetadata(string containerName, string manifestName)
|
||||
{
|
||||
AssertContainerNameIsValid(containerName);
|
||||
manifestName.AssertIsNotNullOrEmpty("manifestName", "Cannot get a manifest 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}/{1}?multipart-manifest=get", baseUri, manifestName));
|
||||
client.Method = HttpMethod.Get;
|
||||
|
||||
return await client.SendAsync();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task<IHttpResponseAbstraction> CopyObject(string sourceContainerName, string sourceObjectName, string targetContainerName, string targetObjectName)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue