JCLOUDS-457: Added list Multipart operations

Added listParts and listMultipartUploads operations to the Glacier
client.
This commit is contained in:
Roman C. Coedo 2014-06-01 23:03:29 +02:00 committed by Andrew Gaul
parent 50df899c53
commit 3f68c3f0c7
12 changed files with 543 additions and 1 deletions

View File

@ -38,12 +38,16 @@ import org.jclouds.glacier.binders.BindDescriptionToHeaders;
import org.jclouds.glacier.binders.BindHashesToHeaders;
import org.jclouds.glacier.binders.BindMultipartTreeHashToHeaders;
import org.jclouds.glacier.binders.BindPartSizeToHeaders;
import org.jclouds.glacier.domain.MultipartUploadMetadata;
import org.jclouds.glacier.domain.PaginatedMultipartUploadCollection;
import org.jclouds.glacier.domain.PaginatedVaultCollection;
import org.jclouds.glacier.domain.VaultMetadata;
import org.jclouds.glacier.fallbacks.FalseOnIllegalArgumentException;
import org.jclouds.glacier.filters.RequestAuthorizeSignature;
import org.jclouds.glacier.functions.ParseArchiveIdHeader;
import org.jclouds.glacier.functions.ParseMultipartUploadIdHeader;
import org.jclouds.glacier.functions.ParseMultipartUploadListFromHttpContent;
import org.jclouds.glacier.functions.ParseMultipartUploadPartListFromHttpContent;
import org.jclouds.glacier.functions.ParseMultipartUploadTreeHashHeader;
import org.jclouds.glacier.functions.ParseVaultMetadataFromHttpContent;
import org.jclouds.glacier.functions.ParseVaultMetadataListFromHttpContent;
@ -214,4 +218,48 @@ public interface GlacierAsyncClient extends Closeable {
ListenableFuture<Boolean> abortMultipartUpload(
@ParamValidators(VaultNameValidator.class) @PathParam("vault") String vaultName,
@PathParam("uploadId") String uploadId);
/**
* @see GlacierClient#listParts
*/
@Named("ListParts")
@GET
@Path("/-/vaults/{vault}/multipart-uploads/{uploadId}")
@ResponseParser(ParseMultipartUploadPartListFromHttpContent.class)
ListenableFuture<MultipartUploadMetadata> listParts(
@ParamValidators(VaultNameValidator.class) @PathParam("vault") String vaultName,
@PathParam("uploadId") String uploadId,
PaginationOptions options);
/**
* @see GlacierClient#listParts
*/
@Named("ListParts")
@GET
@Path("/-/vaults/{vault}/multipart-uploads/{uploadId}")
@ResponseParser(ParseMultipartUploadPartListFromHttpContent.class)
ListenableFuture<MultipartUploadMetadata> listParts(
@ParamValidators(VaultNameValidator.class) @PathParam("vault") String vaultName,
@PathParam("uploadId") String uploadId);
/**
* @see GlacierClient#listMultipartUploads
*/
@Named("ListMultipartUploads")
@GET
@Path("/-/vaults/{vault}/multipart-uploads")
@ResponseParser(ParseMultipartUploadListFromHttpContent.class)
ListenableFuture<PaginatedMultipartUploadCollection> listMultipartUploads(
@ParamValidators(VaultNameValidator.class) @PathParam("vault") String vaultName,
PaginationOptions options);
/**
* @see GlacierClient#listMultipartUploads
*/
@Named("ListMultipartUploads")
@GET
@Path("/-/vaults/{vault}/multipart-uploads")
@ResponseParser(ParseMultipartUploadListFromHttpContent.class)
ListenableFuture<PaginatedMultipartUploadCollection> listMultipartUploads(
@ParamValidators(VaultNameValidator.class) @PathParam("vault") String vaultName);
}

View File

@ -20,6 +20,8 @@ import java.io.Closeable;
import java.net.URI;
import java.util.Map;
import org.jclouds.glacier.domain.MultipartUploadMetadata;
import org.jclouds.glacier.domain.PaginatedMultipartUploadCollection;
import org.jclouds.glacier.domain.PaginatedVaultCollection;
import org.jclouds.glacier.domain.VaultMetadata;
import org.jclouds.glacier.options.PaginationOptions;
@ -180,4 +182,40 @@ public interface GlacierClient extends Closeable {
* @see <a href="http://docs.aws.amazon.com/amazonglacier/latest/dev/api-multipart-abort-upload.html" />
*/
boolean abortMultipartUpload(String vaultName, String uploadId);
/**
* Lists the multipart upload parts.
*
* @param vaultName
* Name of the Vault where the archive is going to be stored.
* @param uploadId
* Multipart upload identifier.
* @param options
* Options used for pagination.
* @return A MultipartUploadMetadata, containing an iterable part list with a marker.
* @see <a href="http://docs.aws.amazon.com/amazonglacier/latest/dev/api-multipart-list-parts.html" />
*/
MultipartUploadMetadata listParts(String vaultName, String uploadId, PaginationOptions options);
/**
* Lists the multipart upload parts.
*/
MultipartUploadMetadata listParts(String vaultName, String uploadId);
/**
* Lists the multipart uploads in a vault.
*
* @param vaultName
* Name of the Vault where the archive is going to be stored.
* @param options
* Options used for pagination.
* @return A PaginatedMultipartUploadCollection, containing an iterable multipart upload list with a marker.
* @see <a href="http://docs.aws.amazon.com/amazonglacier/latest/dev/api-multipart-list-uploads.html" />
*/
PaginatedMultipartUploadCollection listMultipartUploads(String vaultName, PaginationOptions options);
/**
* Lists the multipart uploads in a vault.
*/
PaginatedMultipartUploadCollection listMultipartUploads(String vaultName);
}

View File

@ -0,0 +1,141 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.
*/
package org.jclouds.glacier.domain;
import static com.google.common.base.Preconditions.checkNotNull;
import java.beans.ConstructorProperties;
import java.util.Date;
import java.util.Iterator;
import org.jclouds.collect.IterableWithMarker;
import org.jclouds.glacier.options.PaginationOptions;
import org.jclouds.javax.annotation.Nullable;
import com.google.common.base.Objects;
import com.google.common.base.Optional;
import com.google.common.collect.ComparisonChain;
import com.google.gson.annotations.SerializedName;
/**
* Defines the attributes needed for Multipart uploads. Extends IterableWithMarker to support requesting paginated
* multipart upload parts.
*/
public class MultipartUploadMetadata extends IterableWithMarker<PartMetadata> implements Comparable<MultipartUploadMetadata> {
@SerializedName("ArchiveDescription")
private final String archiveDescription;
@SerializedName("CreationDate")
private final Date creationDate;
@SerializedName("MultipartUploadId")
private final String multipartUploadId;
@SerializedName("PartSizeInBytes")
private final long partSizeInBytes;
@SerializedName("VaultARN")
private final String vaultARN;
@SerializedName("Parts")
private final Iterable<PartMetadata> parts;
@SerializedName("Marker")
private final String marker;
@ConstructorProperties({ "ArchiveDescription", "CreationDate", "MultipartUploadId", "PartSizeInBytes", "VaultARN",
"Parts", "Marker" })
public MultipartUploadMetadata(@Nullable String archiveDescription, Date creationDate, String multipartUploadId,
long partSizeInBytes, String vaultARN, @Nullable Iterable<PartMetadata> parts, @Nullable String marker) {
super();
this.archiveDescription = archiveDescription;
this.creationDate = (Date) checkNotNull(creationDate, "creationDate").clone();
this.multipartUploadId = checkNotNull(multipartUploadId, "multipartUploadId");
this.partSizeInBytes = partSizeInBytes;
this.vaultARN = checkNotNull(vaultARN, "vaultARN");
this.parts = parts;
this.marker = marker;
}
public String getArchiveDescription() {
return archiveDescription;
}
public Date getCreationDate() {
return (Date) creationDate.clone();
}
public String getMultipartUploadId() {
return multipartUploadId;
}
public long getPartSizeInBytes() {
return partSizeInBytes;
}
public long getPartSizeInMB() {
return partSizeInBytes >> 20;
}
public String getVaultARN() {
return vaultARN;
}
@Override
public Iterator<PartMetadata> iterator() {
return parts == null ? null : parts.iterator();
}
@Override
public Optional<Object> nextMarker() {
return Optional.<Object>fromNullable(marker);
}
public PaginationOptions nextPaginationOptions() {
return PaginationOptions.class.cast(nextMarker().get());
}
@Override
public int hashCode() {
return Objects.hashCode(this.archiveDescription, this.creationDate, this.multipartUploadId, this.partSizeInBytes,
this.vaultARN, this.marker, this.parts);
}
@Override
public boolean equals(Object obj) {
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
MultipartUploadMetadata other = (MultipartUploadMetadata) obj;
return Objects.equal(this.archiveDescription, other.archiveDescription)
&& Objects.equal(this.creationDate, other.creationDate)
&& Objects.equal(this.multipartUploadId, other.multipartUploadId)
&& Objects.equal(this.partSizeInBytes, other.partSizeInBytes)
&& Objects.equal(this.vaultARN, other.vaultARN)
&& Objects.equal(this.marker, other.marker)
&& Objects.equal(this.parts, other.parts);
}
@Override
public String toString() {
return "MultipartUploadMetadata [archiveDescription=" + archiveDescription + ", creationDate=" + creationDate
+ ", multipartUploadId=" + multipartUploadId + ", partSizeInBytes=" + partSizeInBytes + ", vaultARN="
+ vaultARN + ", marker=" + marker + ", parts=" + parts + "]";
}
@Override
public int compareTo(MultipartUploadMetadata o) {
return ComparisonChain.start().compare(this.creationDate, o.creationDate).result();
}
}

View File

@ -0,0 +1,60 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.
*/
package org.jclouds.glacier.domain;
import static com.google.common.base.Preconditions.checkNotNull;
import java.beans.ConstructorProperties;
import java.util.Iterator;
import org.jclouds.collect.IterableWithMarker;
import org.jclouds.glacier.options.PaginationOptions;
import org.jclouds.javax.annotation.Nullable;
import com.google.common.base.Optional;
import com.google.gson.annotations.SerializedName;
/**
* Paginated collection used to store multipart upload lists.
*/
public class PaginatedMultipartUploadCollection extends IterableWithMarker<MultipartUploadMetadata> {
@SerializedName("UploadsList")
private final Iterable<MultipartUploadMetadata> uploads;
@SerializedName("Marker")
private final String marker;
@ConstructorProperties({ "UploadsList", "Marker" })
public PaginatedMultipartUploadCollection(Iterable<MultipartUploadMetadata> uploads, @Nullable String marker) {
this.uploads = checkNotNull(uploads, "uploads");
this.marker = marker;
}
@Override
public Iterator<MultipartUploadMetadata> iterator() {
return uploads.iterator();
}
@Override
public Optional<Object> nextMarker() {
return Optional.<Object>fromNullable(marker);
}
public PaginationOptions nextPaginationOptions() {
return PaginationOptions.class.cast(nextMarker().get());
}
}

View File

@ -0,0 +1,53 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.
*/
package org.jclouds.glacier.domain;
import static com.google.common.base.Preconditions.checkNotNull;
import java.beans.ConstructorProperties;
import org.jclouds.glacier.util.ContentRange;
import com.google.common.hash.HashCode;
import com.google.gson.annotations.SerializedName;
/**
* Defines the attributes needed for a multipart upload part.
*/
public class PartMetadata {
@SerializedName("SHA256TreeHash")
private final HashCode treeHash;
@SerializedName("RangeInBytes")
private final ContentRange range;
@ConstructorProperties({ "SHA256TreeHash", "RangeInBytes" })
public PartMetadata(String treeHash, String range) {
super();
this.treeHash = HashCode.fromString(checkNotNull(treeHash, "treeHash"));
this.range = ContentRange.fromString(checkNotNull(range, "range"));
}
public ContentRange getRange() {
return range;
}
public HashCode getTreeHash() {
return treeHash;
}
}

View File

@ -0,0 +1,35 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.
*/
package org.jclouds.glacier.functions;
import org.jclouds.glacier.domain.PaginatedMultipartUploadCollection;
import org.jclouds.http.functions.ParseJson;
import org.jclouds.json.Json;
import com.google.inject.Inject;
import com.google.inject.TypeLiteral;
/**
* Parses the JSON multipart upload list from the HttpResponse.
*/
public class ParseMultipartUploadListFromHttpContent extends ParseJson<PaginatedMultipartUploadCollection> {
@Inject
public ParseMultipartUploadListFromHttpContent(Json json) {
super(json, TypeLiteral.get(PaginatedMultipartUploadCollection.class));
}
}

View File

@ -0,0 +1,35 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.
*/
package org.jclouds.glacier.functions;
import org.jclouds.glacier.domain.MultipartUploadMetadata;
import org.jclouds.http.functions.ParseJson;
import org.jclouds.json.Json;
import com.google.inject.Inject;
import com.google.inject.TypeLiteral;
/**
* Parses the JSON multipart upload part list from the HttpResponse.
*/
public class ParseMultipartUploadPartListFromHttpContent extends ParseJson<MultipartUploadMetadata> {
@Inject
public ParseMultipartUploadPartListFromHttpContent(Json json) {
super(json, TypeLiteral.get(MultipartUploadMetadata.class));
}
}

View File

@ -16,16 +16,25 @@
*/
package org.jclouds.glacier;
import static org.jclouds.glacier.util.TestUtils.MiB;
import static org.jclouds.glacier.util.TestUtils.buildPayload;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertTrue;
import java.util.UUID;
import org.jclouds.apis.BaseApiLiveTest;
import org.jclouds.glacier.domain.MultipartUploadMetadata;
import org.jclouds.glacier.domain.PaginatedMultipartUploadCollection;
import org.jclouds.glacier.domain.PaginatedVaultCollection;
import org.jclouds.glacier.domain.VaultMetadata;
import org.jclouds.glacier.util.ContentRange;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableList;
/**
* Live test for Glacier.
*/
@ -68,7 +77,43 @@ public class GlacierClientLiveTest extends BaseApiLiveTest<GlacierClient>{
assertTrue(vaults.contains(api.describeVault(VAULT_NAME3)));
}
@Test(groups = { "integration", "live" }, dependsOnMethods = { "testListAndDescribeVaults" })
@Test(groups = { "integration", "live" }, dependsOnMethods = { "testCreateVault" })
public void testListMultipartUploadsWithEmptyList() throws Exception {
assertEquals(api.listMultipartUploads(VAULT_NAME1).size(), 0);
}
@Test(groups = { "integration", "live" }, dependsOnMethods = { "testListMultipartUploadsWithEmptyList" })
public void testInitiateAndAbortMultipartUpload() throws Exception {
String uploadId = api.initiateMultipartUpload(VAULT_NAME1, 8);
try {
assertNotNull(uploadId);
} finally {
api.abortMultipartUpload(VAULT_NAME1, uploadId);
}
}
@Test(groups = { "integration", "live" }, dependsOnMethods = { "testInitiateAndAbortMultipartUpload" })
public void testListMultipartUploads() throws Exception {
long partSizeInMb = 1;
String uploadId = api.initiateMultipartUpload(VAULT_NAME1, partSizeInMb);
try {
assertNotNull(api.uploadPart(VAULT_NAME1, uploadId,
ContentRange.fromPartNumber(0, partSizeInMb), buildPayload(partSizeInMb * MiB)));
PaginatedMultipartUploadCollection uploads = api.listMultipartUploads(VAULT_NAME1);
ImmutableList.Builder<String> list = ImmutableList.builder();
for (MultipartUploadMetadata upload : uploads) {
list.add(upload.getMultipartUploadId());
}
assertTrue(list.build().contains(uploadId));
assertTrue(api.abortMultipartUpload(VAULT_NAME1, uploadId));
} finally {
api.abortMultipartUpload(VAULT_NAME1, uploadId);
}
}
@Test(groups = { "integration", "live" },
dependsOnMethods = { "testListAndDescribeVaults", "testListMultipartUploadsWithEmptyList",
"testInitiateAndAbortMultipartUpload", "testListMultipartUploads" })
public void testDeleteVault() throws Exception {
assertTrue(api.deleteVault(VAULT_NAME1));
assertTrue(api.deleteVault(VAULT_NAME2));

View File

@ -37,7 +37,10 @@ import java.util.Set;
import org.jclouds.ContextBuilder;
import org.jclouds.concurrent.config.ExecutorServiceModule;
import org.jclouds.glacier.domain.MultipartUploadMetadata;
import org.jclouds.glacier.domain.PaginatedMultipartUploadCollection;
import org.jclouds.glacier.domain.PaginatedVaultCollection;
import org.jclouds.glacier.domain.PartMetadata;
import org.jclouds.glacier.domain.VaultMetadata;
import org.jclouds.glacier.options.PaginationOptions;
import org.jclouds.glacier.reference.GlacierHeaders;
@ -85,6 +88,7 @@ public class GlacierClientMockTest {
private static final String DESCRIPTION = "test description";
private static final String MULTIPART_UPLOAD_LOCATION = VAULT_LOCATION + "/multipart-uploads/" + ARCHIVE_ID;
private static final String MULTIPART_UPLOAD_ID = "OW2fM5iVylEpFEMM9_HpKowRapC3vn5sSL39_396UW9zLFUWVrnRHaPjUJddQ5OxSHVXjYtrN47NBZ-khxOjyEXAMPLE";
private static final String MARKER = "xsQdFIRsfJr20CW2AbZBKpRZAFTZSJIMtL2hYf8mvp8dM0m4RUzlaqoEye6g3h3ecqB_zqwB7zLDMeSWhwo65re4C4Ev";
private static final Set<Module> modules = ImmutableSet.<Module> of(new ExecutorServiceModule(sameThreadExecutor(),
sameThreadExecutor()));
@ -305,4 +309,58 @@ public class GlacierClientMockTest {
assertEquals(server.takeRequest().getRequestLine(),
"DELETE /-/vaults/" + VAULT_NAME + "/multipart-uploads/" + MULTIPART_UPLOAD_ID + " " + HTTP);
}
@Test
public void testListParts() throws IOException, InterruptedException {
MockResponse mr = buildBaseResponse(200);
mr.addHeader(HttpHeaders.CONTENT_TYPE, MediaType.JSON_UTF_8);
mr.setBody(getResponseBody("/json/listPartsResponseBody.json"));
mr.addHeader(HttpHeaders.CONTENT_LENGTH, mr.getBody().length);
server.enqueue(mr);
MultipartUploadMetadata result = client.listParts(VAULT_NAME, MULTIPART_UPLOAD_ID,
PaginationOptions.Builder.limit(1).marker("1001"));
assertEquals(result.getArchiveDescription(), "archive description 1");
assertEquals(result.getMultipartUploadId(), MULTIPART_UPLOAD_ID);
assertEquals(result.getPartSizeInBytes(), 4194304);
PartMetadata part = result.iterator().next();
assertEquals(part.getTreeHash(), HashCode.fromString("01d34dabf7be316472c93b1ef80721f5d4"));
assertEquals("4194304-8388607", part.getRange().getFrom() + "-" + part.getRange().getTo());
assertEquals(server.takeRequest().getRequestLine(),
"GET /-/vaults/examplevault/multipart-uploads/" + MULTIPART_UPLOAD_ID + "?limit=1&marker=1001 " + HTTP);
}
@Test
public void testListMultipartUploads() throws IOException, InterruptedException {
MockResponse mr = buildBaseResponse(200);
mr.addHeader(HttpHeaders.CONTENT_TYPE, MediaType.JSON_UTF_8);
mr.setBody(getResponseBody("/json/listMultipartUploadsResponseBody.json"));
mr.addHeader(HttpHeaders.CONTENT_LENGTH, mr.getBody().length);
server.enqueue(mr);
PaginatedMultipartUploadCollection result = client.listMultipartUploads(
VAULT_NAME, PaginationOptions.Builder.limit(1).marker(MARKER));
MultipartUploadMetadata mum = result.iterator().next();
assertEquals(mum.getArchiveDescription(), "archive 2");
assertEquals(mum.getMultipartUploadId(),
"nPyGOnyFcx67qqX7E-0tSGiRi88hHMOwOxR-_jNyM6RjVMFfV29lFqZ3rNsSaWBugg6OP92pRtufeHdQH7ClIpSF6uJc");
assertEquals(mum.iterator(), null);
assertEquals(mum.getPartSizeInBytes(), 4194304);
assertEquals(mum.getVaultARN(), VAULT_ARN);
assertEquals(server.takeRequest().getRequestLine(),
"GET /-/vaults/examplevault/multipart-uploads?limit=1&marker=" + MARKER + " " + HTTP);
}
@Test
public void testListMultipartUploadsWithEmptyList() throws IOException, InterruptedException {
MockResponse mr = buildBaseResponse(200);
mr.addHeader(HttpHeaders.CONTENT_TYPE, MediaType.JSON_UTF_8);
mr.setBody(getResponseBody("/json/listMultipartUploadsWithEmptyListResponseBody.json"));
mr.addHeader(HttpHeaders.CONTENT_LENGTH, mr.getBody().length);
server.enqueue(mr);
assertEquals(client.listMultipartUploads(VAULT_NAME, PaginationOptions.Builder.limit(1).marker(MARKER)).size(), 0);
assertEquals(server.takeRequest().getRequestLine(),
"GET /-/vaults/examplevault/multipart-uploads?limit=1&marker=" + MARKER + " " + HTTP);
}
}

View File

@ -0,0 +1,12 @@
{
"Marker": "qt-RBst_7yO8gVIonIBsAxr2t-db0pE4s8MNeGjKjGdNpuU-cdSAcqG62guwV9r5jh5mLyFPzFEitTpNE7iQfHiu1XoV",
"UploadsList" : [
{
"ArchiveDescription": "archive 2",
"CreationDate": "2012-04-01T15:00:00.000Z",
"MultipartUploadId": "nPyGOnyFcx67qqX7E-0tSGiRi88hHMOwOxR-_jNyM6RjVMFfV29lFqZ3rNsSaWBugg6OP92pRtufeHdQH7ClIpSF6uJc",
"PartSizeInBytes": 4194304,
"VaultARN": "arn:aws:glacier:us-east-1:012345678901:vaults/examplevault"
}
]
}

View File

@ -0,0 +1,4 @@
{
"Marker": "qt-RBst_7yO8gVIonIBsAxr2t-db0pE4s8MNeGjKjGdNpuU-cdSAcqG62guwV9r5jh5mLyFPzFEitTpNE7iQfHiu1XoV",
"UploadsList" : []
}

View File

@ -0,0 +1,13 @@
{
"ArchiveDescription" : "archive description 1",
"CreationDate" : "2012-03-20T17:03:43.221Z",
"Marker": "MfgsKHVjbQ6EldVl72bn3_n5h2TaGZQUO-Qb3B9j3TITf7WajQ",
"MultipartUploadId" : "OW2fM5iVylEpFEMM9_HpKowRapC3vn5sSL39_396UW9zLFUWVrnRHaPjUJddQ5OxSHVXjYtrN47NBZ-khxOjyEXAMPLE",
"PartSizeInBytes" : 4194304,
"Parts" :
[ {
"RangeInBytes" : "4194304-8388607",
"SHA256TreeHash" : "01d34dabf7be316472c93b1ef80721f5d4"
}],
"VaultARN" : "arn:aws:glacier:us-east-1:012345678901:vaults/demo1-vault"
}