Updates to Rackspace CDN Container Metadata handling. Added feature to Purge CDN Object. Added feature to set default index and error pages for CDN based static website.

This commit is contained in:
Everett Toews 2012-09-10 14:56:53 -05:00
parent 27fea13a61
commit e19d27f97c
12 changed files with 608 additions and 57 deletions

View File

@ -19,10 +19,12 @@
package org.jclouds.cloudfiles;
import java.net.URI;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.HEAD;
import javax.ws.rs.HeaderParam;
@ -33,6 +35,7 @@ import javax.ws.rs.PathParam;
import javax.ws.rs.core.MediaType;
import org.jclouds.blobstore.functions.ReturnNullOnContainerNotFound;
import org.jclouds.cloudfiles.binders.BindIterableToHeadersWithPurgeCDNObjectEmail;
import org.jclouds.cloudfiles.domain.ContainerCDNMetadata;
import org.jclouds.cloudfiles.functions.ParseCdnUriFromHeaders;
import org.jclouds.cloudfiles.functions.ParseContainerCDNMetadataFromHeaders;
@ -42,6 +45,7 @@ import org.jclouds.cloudfiles.reference.CloudFilesHeaders;
import org.jclouds.openstack.filters.AuthenticateRequest;
import org.jclouds.openstack.swift.CommonSwiftAsyncClient;
import org.jclouds.openstack.swift.Storage;
import org.jclouds.rest.annotations.BinderParam;
import org.jclouds.rest.annotations.Endpoint;
import org.jclouds.rest.annotations.ExceptionParser;
import org.jclouds.rest.annotations.Headers;
@ -78,9 +82,6 @@ public interface CloudFilesAsyncClient extends CommonSwiftAsyncClient {
@Endpoint(CDNManagement.class)
ListenableFuture<? extends Set<ContainerCDNMetadata>> listCDNContainers(ListCdnContainerOptions... options);
// TODO: Container name is not included in CDN HEAD response headers, so we
// cannot populate it
// here.
/**
* @see CloudFilesClient#getCDNMetadata
*/
@ -91,6 +92,18 @@ public interface CloudFilesAsyncClient extends CommonSwiftAsyncClient {
@Endpoint(CDNManagement.class)
ListenableFuture<ContainerCDNMetadata> getCDNMetadata(@PathParam("container") String container);
/**
* @see CloudFilesClient#enableCDN(String, long, boolean);
*/
@PUT
@Path("/{container}")
@Headers(keys = CloudFilesHeaders.CDN_ENABLED, values = "True")
@ResponseParser(ParseCdnUriFromHeaders.class)
@Endpoint(CDNManagement.class)
ListenableFuture<URI> enableCDN(@PathParam("container") String container,
@HeaderParam(CloudFilesHeaders.CDN_TTL) long ttl,
@HeaderParam(CloudFilesHeaders.CDN_LOG_RETENTION) boolean logRetention);
/**
* @see CloudFilesClient#enableCDN(String, long);
*/
@ -100,7 +113,7 @@ public interface CloudFilesAsyncClient extends CommonSwiftAsyncClient {
@ResponseParser(ParseCdnUriFromHeaders.class)
@Endpoint(CDNManagement.class)
ListenableFuture<URI> enableCDN(@PathParam("container") String container,
@HeaderParam(CloudFilesHeaders.CDN_TTL) long ttl);
@HeaderParam(CloudFilesHeaders.CDN_TTL) long ttl);
/**
* @see CloudFilesClient#enableCDN(String)
@ -113,14 +126,35 @@ public interface CloudFilesAsyncClient extends CommonSwiftAsyncClient {
ListenableFuture<URI> enableCDN(@PathParam("container") String container);
/**
* @see CloudFilesClient#updateCDN
* @see CloudFilesClient#updateCDN(long, boolean)
*/
@POST
@Path("/{container}")
@ResponseParser(ParseCdnUriFromHeaders.class)
@Endpoint(CDNManagement.class)
ListenableFuture<URI> updateCDN(@PathParam("container") String container,
@HeaderParam(CloudFilesHeaders.CDN_TTL) long ttl);
@HeaderParam(CloudFilesHeaders.CDN_TTL) long ttl,
@HeaderParam(CloudFilesHeaders.CDN_LOG_RETENTION) boolean logRetention);
/**
* @see CloudFilesClient#updateCDN(boolean)
*/
@POST
@Path("/{container}")
@ResponseParser(ParseCdnUriFromHeaders.class)
@Endpoint(CDNManagement.class)
ListenableFuture<URI> updateCDN(@PathParam("container") String container,
@HeaderParam(CloudFilesHeaders.CDN_LOG_RETENTION) boolean logRetention);
/**
* @see CloudFilesClient#updateCDN(long)
*/
@POST
@Path("/{container}")
@ResponseParser(ParseCdnUriFromHeaders.class)
@Endpoint(CDNManagement.class)
ListenableFuture<URI> updateCDN(@PathParam("container") String container,
@HeaderParam(CloudFilesHeaders.CDN_TTL) long ttl);
/**
* @see CloudFilesClient#disableCDN
@ -131,6 +165,43 @@ public interface CloudFilesAsyncClient extends CommonSwiftAsyncClient {
@Endpoint(CDNManagement.class)
ListenableFuture<Boolean> disableCDN(@PathParam("container") String container);
/**
* @see CloudFilesClient#purgeCDNObject(String, String, List)
*/
@DELETE
@Path("/{container}/{object}")
@Headers(keys = CloudFilesHeaders.CDN_CONTAINER_PURGE_OBJECT_EMAIL, values = "{email}")
@Endpoint(CDNManagement.class)
ListenableFuture<Boolean> purgeCDNObject(@PathParam("container") String container,
@PathParam("object") String object,
@BinderParam(BindIterableToHeadersWithPurgeCDNObjectEmail.class) Iterable<String> emails);
/**
* @see CloudFilesClient#purgeCDNObject(String, String)
*/
@DELETE
@Path("/{container}/{object}")
@Endpoint(CDNManagement.class)
ListenableFuture<Boolean> purgeCDNObject(@PathParam("container") String container,
@PathParam("object") String object);
/**
* @see CloudFilesClient#setCDNStaticWebsiteIndex
*/
@POST
@Path("/{container}")
@Headers(keys = CloudFilesHeaders.CDN_WEBSITE_INDEX, values = "{index}")
ListenableFuture<Boolean> setCDNStaticWebsiteIndex(@PathParam("container") String container,
@PathParam("index") String index);
/**
* @see CloudFilesClient#setCDNStaticWebsiteError
*/
@POST
@Path("/{container}")
@Headers(keys = CloudFilesHeaders.CDN_WEBSITE_ERROR, values = "{error}")
ListenableFuture<Boolean> setCDNStaticWebsiteError(@PathParam("container") String container,
@PathParam("error") String error);
/**
* @see CloudFilesClient#getTemporaryUrlKey

View File

@ -40,17 +40,71 @@ import org.jclouds.openstack.swift.CommonSwiftClient;
*/
@Timeout(duration = 120, timeUnit = TimeUnit.SECONDS)
public interface CloudFilesClient extends CommonSwiftClient {
/**
* See http://docs.rackspace.com/files/api/v1/cf-devguide/content/List_CDN-Enabled_Containers-d1e2414.html
*/
Set<ContainerCDNMetadata> listCDNContainers(ListCdnContainerOptions... options);
/**
* See http://docs.rackspace.com/files/api/v1/cf-devguide/content/List_CDN-Enabled_Container_Metadata-d1e2711.html
*/
ContainerCDNMetadata getCDNMetadata(String container);
/**
* See http://docs.rackspace.com/files/api/v1/cf-devguide/content/CDN-Enabled_Container-d1e2665.html
*/
URI enableCDN(String container, long ttl, boolean logRetention);
/**
* See http://docs.rackspace.com/files/api/v1/cf-devguide/content/CDN-Enabled_Container-d1e2665.html
*/
URI enableCDN(String container, long ttl);
/**
* See http://docs.rackspace.com/files/api/v1/cf-devguide/content/CDN-Enabled_Container-d1e2665.html
*/
URI enableCDN(String container);
/**
* See http://docs.rackspace.com/files/api/v1/cf-devguide/content/Update_CDN-Enabled_Container_Metadata-d1e2787.html
*/
URI updateCDN(String container, long ttl, boolean logRetention);
/**
* See http://docs.rackspace.com/files/api/v1/cf-devguide/content/Update_CDN-Enabled_Container_Metadata-d1e2787.html
*/
URI updateCDN(String container, boolean logRetention);
/**
* See http://docs.rackspace.com/files/api/v1/cf-devguide/content/Update_CDN-Enabled_Container_Metadata-d1e2787.html
*/
URI updateCDN(String container, long ttl);
/**
* See http://docs.rackspace.com/files/api/v1/cf-devguide/content/CDN-Enabled_Container-d1e2665.html
*/
boolean disableCDN(String container);
/**
* See http://docs.rackspace.com/files/api/v1/cf-devguide/content/Purge_CDN-Enabled_Objects-d1e3858.html
*/
boolean purgeCDNObject(String container, String object, Iterable<String> emails);
/**
* See http://docs.rackspace.com/files/api/v1/cf-devguide/content/Purge_CDN-Enabled_Objects-d1e3858.html
*/
boolean purgeCDNObject(String container, String object);
/**
* http://docs.rackspace.com/files/api/v1/cf-devguide/content/Create_Static_Website-dle4000.html
*/
boolean setCDNStaticWebsiteIndex(String container, String index);
/*
* http://docs.rackspace.com/files/api/v1/cf-devguide/content/Set_Error_Pages_for_Static_Website-dle4005.html
*/
boolean setCDNStaticWebsiteError(String container, String error);
/**
* Retrieve the key used to generate Temporary object access URLs

View File

@ -0,0 +1,53 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds 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.cloudfiles.binders;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.List;
import javax.inject.Singleton;
import org.jclouds.cloudfiles.reference.CloudFilesHeaders;
import org.jclouds.http.HttpRequest;
import org.jclouds.rest.Binder;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableMultimap;
/**
* @author Everett Toews
*/
@Singleton
public class BindIterableToHeadersWithPurgeCDNObjectEmail implements Binder {
@SuppressWarnings("unchecked")
@Override
public <R extends HttpRequest> R bindToRequest(R request, Object input) {
checkArgument(checkNotNull(input, "input") instanceof Iterable<?>, "this binder is only valid for Iterable!");
checkNotNull(request, "request");
Iterable<String> emails = (Iterable<String>) input;
String emailCSV = Joiner.on(", ").join((List<String>) emails);
ImmutableMultimap<String, String> headers =
ImmutableMultimap.<String, String> of(CloudFilesHeaders.CDN_CONTAINER_PURGE_OBJECT_EMAIL, emailCSV);
return (R) request.toBuilder().replaceHeaders(headers).build();
}
}

View File

@ -29,17 +29,22 @@ public class ContainerCDNMetadata implements Comparable<ContainerCDNMetadata> {
private String name;
private boolean cdn_enabled;
private boolean log_retention;
private long ttl;
private URI cdn_uri;
private URI cdn_ssl_uri;
private URI cdn_streaming_uri;
private String referrer_acl;
private String useragent_acl;
private boolean log_retention;
public ContainerCDNMetadata(String name, boolean cdnEnabled, long ttl, URI cdnUri) {
public ContainerCDNMetadata(String name, boolean cdnEnabled, boolean logRetention, long ttl, URI cdnUri, URI cdnSslUri, URI cdnStreamingUri) {
this.name = name;
this.cdn_enabled = cdnEnabled;
this.log_retention = logRetention;
this.ttl = ttl;
this.cdn_uri = cdnUri;
this.cdn_ssl_uri = cdnSslUri;
this.cdn_streaming_uri = cdnStreamingUri;
}
public ContainerCDNMetadata() {
@ -53,16 +58,36 @@ public class ContainerCDNMetadata implements Comparable<ContainerCDNMetadata> {
return name;
}
public URI getCDNUri() {
return cdn_uri;
public boolean isCDNEnabled() {
return cdn_enabled;
}
public boolean isLogRetention() {
return log_retention;
}
public long getTTL() {
return ttl;
}
public boolean isCDNEnabled() {
return cdn_enabled;
public URI getCDNUri() {
return cdn_uri;
}
public URI getCDNSslUri() {
return cdn_ssl_uri;
}
public URI getCDNStreamingUri() {
return cdn_streaming_uri;
}
public String getReferrerACL() {
return referrer_acl;
}
public String getUseragentACL() {
return useragent_acl;
}
public int compareTo(ContainerCDNMetadata o) {
@ -87,31 +112,21 @@ public class ContainerCDNMetadata implements Comparable<ContainerCDNMetadata> {
return false;
if (getClass() != obj.getClass())
return false;
ContainerCDNMetadata other = (ContainerCDNMetadata) obj;
if (cdn_uri == null) {
if (other.cdn_uri != null)
return false;
} else if (!cdn_uri.equals(other.cdn_uri))
return false;
return true;
}
public String getReferrerACL() {
return referrer_acl;
}
public String getUseragentACL() {
return useragent_acl;
}
public boolean isLogRetention() {
return log_retention;
}
@Override
public String toString() {
return String.format(
"[name=%s, cdn_uri=%s, cdn_enabled=%s, log_retention=%s, referrer_acl=%s, ttl=%s, useragent_acl=%s]",
name, cdn_uri, cdn_enabled, log_retention, referrer_acl, ttl, useragent_acl);
"[name=%s, cdn_enabled=%s, log_retention=%s, ttl=%s, cdn_uri=%s, cdn_ssl_uri=%s, cdn_streaming_uri=%s, referrer_acl=%s, useragent_acl=%s]",
name, cdn_enabled, log_retention, ttl, cdn_uri, cdn_ssl_uri, cdn_streaming_uri, referrer_acl, useragent_acl);
}
}

View File

@ -45,18 +45,26 @@ public class ParseContainerCDNMetadataFromHeaders implements
* parses the http response headers to create a new {@link ContainerCDNMetadata} object.
*/
public ContainerCDNMetadata apply(final HttpResponse from) {
String cdnUri = checkNotNull(from.getFirstHeaderOrNull(CloudFilesHeaders.CDN_URI),
CloudFilesHeaders.CDN_URI);
String cdnTTL = checkNotNull(from.getFirstHeaderOrNull(CloudFilesHeaders.CDN_TTL),
CloudFilesHeaders.CDN_TTL);
String cdnEnabled = checkNotNull(from.getFirstHeaderOrNull(CloudFilesHeaders.CDN_ENABLED),
CloudFilesHeaders.CDN_ENABLED);
String cdnEnabled = checkNotNull(from.getFirstHeaderOrNull(CloudFilesHeaders.CDN_ENABLED), CloudFilesHeaders.CDN_ENABLED);
String cdnLogRetention = checkNotNull(from.getFirstHeaderOrNull(CloudFilesHeaders.CDN_LOG_RETENTION), CloudFilesHeaders.CDN_LOG_RETENTION);
String cdnTTL = checkNotNull(from.getFirstHeaderOrNull(CloudFilesHeaders.CDN_TTL), CloudFilesHeaders.CDN_TTL);
String cdnUri = checkNotNull(from.getFirstHeaderOrNull(CloudFilesHeaders.CDN_URI), CloudFilesHeaders.CDN_URI);
String cdnSslUri = checkNotNull(from.getFirstHeaderOrNull(CloudFilesHeaders.CDN_SSL_URI), CloudFilesHeaders.CDN_SSL_URI);
String cdnStreamingUri = checkNotNull(from.getFirstHeaderOrNull(CloudFilesHeaders.CDN_STREAMING_URI), CloudFilesHeaders.CDN_STREAMING_URI);
if (cdnUri == null) {
// CDN is not, and has never, been enabled for this container.
return null;
} else {
return new ContainerCDNMetadata(request.getEndpoint().getPath(), Boolean
.parseBoolean(cdnEnabled), Long.parseLong(cdnTTL), URI.create(cdnUri));
}
else {
return new ContainerCDNMetadata(
request.getEndpoint().getPath(),
Boolean.parseBoolean(cdnEnabled),
Boolean.parseBoolean(cdnLogRetention),
Long.parseLong(cdnTTL),
URI.create(cdnUri),
URI.create(cdnSslUri),
URI.create(cdnStreamingUri));
}
}

View File

@ -33,8 +33,15 @@ public interface CloudFilesHeaders extends SwiftHeaders {
public static final String ACCOUNT_TEMPORARY_URL_KEY = "X-Account-Meta-Temp-Url-Key";
public static final String CDN_ENABLED = "X-CDN-Enabled";
public static final String CDN_REFERRER_ACL = "X-Referrer-ACL ";
public static final String CDN_LOG_RETENTION = "X-Log-Retention";
public static final String CDN_TTL = "X-TTL";
public static final String CDN_URI = "X-CDN-URI";
public static final String CDN_SSL_URI = "X-Cdn-Ssl-Uri";
public static final String CDN_STREAMING_URI = "X-Cdn-Streaming-Uri";
public static final String CDN_REFERRER_ACL = "X-Referrer-ACL ";
public static final String CDN_USER_AGENT_ACL = "X-User-Agent-ACL";
public static final String CDN_CONTAINER_PURGE_OBJECT_EMAIL = "X-Purge-Email";
public static final String CDN_WEBSITE_INDEX = "X-Container-Meta-Web-Index";
public static final String CDN_WEBSITE_ERROR = "X-Container-Meta-Web-Error";
}

View File

@ -18,7 +18,16 @@
*/
package org.jclouds.cloudfiles;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertTrue;
import java.net.URI;
import org.jclouds.blobstore.ContainerNotFoundException;
import org.jclouds.cloudfiles.domain.ContainerCDNMetadata;
import org.jclouds.cloudfiles.internal.BaseCloudFilesRestClientExpectTest;
import org.jclouds.cloudfiles.reference.CloudFilesHeaders;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.testng.annotations.Test;
@ -30,7 +39,8 @@ import org.testng.annotations.Test;
@Test(groups = "unit", testName = "CloudFilesClientExpectTest")
public class CloudFilesClientExpectTest extends BaseCloudFilesRestClientExpectTest {
public void deleteContainerReturnsTrueOn200And404() {
@Test
public void testDeleteContainerReturnsTrueOn200And404() {
HttpRequest deleteContainer = HttpRequest
.builder()
@ -50,7 +60,194 @@ public class CloudFilesClientExpectTest extends BaseCloudFilesRestClientExpectTe
CloudFilesClient clientWhenContainerDoesntExist = requestsSendResponses(initialAuth, responseWithAuth, deleteContainer,
containerNotFound);
assert clientWhenContainerDoesntExist.deleteContainerIfEmpty("container");
}
@Test
public void testGetCDNMetadataWhenResponseIs2xxReturnsContainerCDNMetadata() {
HttpRequest cdnContainerRequest = HttpRequest.builder()
.method("HEAD")
.endpoint("https://cdn3.clouddrive.com/v1/MossoCloudFS_83a9d536-2e25-4166-bd3b-a503a934f953/container")
.addHeader("X-Auth-Token", authToken)
.build();
HttpResponse cdnContainerResponse = HttpResponse.builder()
.addHeader(CloudFilesHeaders.CDN_ENABLED, "True")
.addHeader(CloudFilesHeaders.CDN_LOG_RETENTION, "True")
.addHeader(CloudFilesHeaders.CDN_TTL, "259200")
.addHeader(CloudFilesHeaders.CDN_URI, "http://546406d62bf471d7435d-36c33e76d676c80251b3c13ecb603b67.r19.cf1.rackcdn.com")
.addHeader(CloudFilesHeaders.CDN_SSL_URI, "https://e9f6fe92d217dc013369-36c33e76d676c80251b3c13ecb603b67.ssl.cf1.rackcdn.com")
.addHeader(CloudFilesHeaders.CDN_STREAMING_URI, "http://0e79346bc0a2564dcc5e-36c33e76d676c80251b3c13ecb603b67.r19.stream.cf1.rackcdn.com")
.statusCode(204)
.build();
CloudFilesClient cdnContainerClient = requestsSendResponses(
initialAuth, responseWithAuth, cdnContainerRequest, cdnContainerResponse);
ContainerCDNMetadata containerCDNMetadata = cdnContainerClient.getCDNMetadata("container");
assertTrue(containerCDNMetadata.isCDNEnabled());
assertTrue(containerCDNMetadata.isLogRetention());
assertEquals(containerCDNMetadata.getTTL(), 259200);
assertEquals(containerCDNMetadata.getCDNUri().toString(), "http://546406d62bf471d7435d-36c33e76d676c80251b3c13ecb603b67.r19.cf1.rackcdn.com");
assertEquals(containerCDNMetadata.getCDNSslUri().toString(), "https://e9f6fe92d217dc013369-36c33e76d676c80251b3c13ecb603b67.ssl.cf1.rackcdn.com");
assertEquals(containerCDNMetadata.getCDNStreamingUri().toString(), "http://0e79346bc0a2564dcc5e-36c33e76d676c80251b3c13ecb603b67.r19.stream.cf1.rackcdn.com");
}
@Test
public void testGetCDNMetadataWhenResponseIs404ReturnsNull() {
HttpRequest cdnContainerRequest = HttpRequest.builder()
.method("HEAD")
.endpoint("https://cdn3.clouddrive.com/v1/MossoCloudFS_83a9d536-2e25-4166-bd3b-a503a934f953/container")
.addHeader("X-Auth-Token", authToken)
.build();
HttpResponse cdnContainerResponse = HttpResponse.builder()
.statusCode(404)
.build();
CloudFilesClient cdnContainerClient = requestsSendResponses(
initialAuth, responseWithAuth, cdnContainerRequest, cdnContainerResponse);
assertNull(cdnContainerClient.getCDNMetadata("container"));
}
@Test
public void testUpdateCDNMetadataWhenResponseIs2xxReturnsURI() {
HttpRequest cdnContainerRequest = HttpRequest.builder()
.method("POST")
.endpoint("https://cdn3.clouddrive.com/v1/MossoCloudFS_83a9d536-2e25-4166-bd3b-a503a934f953/container")
.addHeader(CloudFilesHeaders.CDN_LOG_RETENTION, "true")
.addHeader(CloudFilesHeaders.CDN_TTL, "259200")
.addHeader("X-Auth-Token", authToken)
.build();
HttpResponse cdnContainerResponse = HttpResponse.builder()
.addHeader(CloudFilesHeaders.CDN_ENABLED, "True")
.addHeader(CloudFilesHeaders.CDN_LOG_RETENTION, "True")
.addHeader(CloudFilesHeaders.CDN_TTL, "259200")
.addHeader(CloudFilesHeaders.CDN_URI, "http://546406d62bf471d7435d-36c33e76d676c80251b3c13ecb603b67.r19.cf1.rackcdn.com")
.addHeader(CloudFilesHeaders.CDN_SSL_URI, "https://e9f6fe92d217dc013369-36c33e76d676c80251b3c13ecb603b67.ssl.cf1.rackcdn.com")
.addHeader(CloudFilesHeaders.CDN_STREAMING_URI, "http://0e79346bc0a2564dcc5e-36c33e76d676c80251b3c13ecb603b67.r19.stream.cf1.rackcdn.com")
.statusCode(204)
.build();
CloudFilesClient cdnContainerClient = requestsSendResponses(
initialAuth, responseWithAuth, cdnContainerRequest, cdnContainerResponse);
URI cdnURI = cdnContainerClient.updateCDN("container", 259200, true);
assertEquals(cdnURI.toString(), "http://546406d62bf471d7435d-36c33e76d676c80251b3c13ecb603b67.r19.cf1.rackcdn.com");
}
@Test(expectedExceptions = ContainerNotFoundException.class)
public void testUpdateCDNMetadataWhenResponseIs404ThrowsException() {
HttpRequest cdnContainerRequest = HttpRequest.builder()
.method("POST")
.endpoint("https://cdn3.clouddrive.com/v1/MossoCloudFS_83a9d536-2e25-4166-bd3b-a503a934f953/container")
.addHeader(CloudFilesHeaders.CDN_LOG_RETENTION, "true")
.addHeader(CloudFilesHeaders.CDN_TTL, "259200")
.addHeader("X-Auth-Token", authToken)
.build();
HttpResponse cdnContainerResponse = HttpResponse.builder()
.statusCode(404)
.build();
CloudFilesClient cdnContainerClient = requestsSendResponses(
initialAuth, responseWithAuth, cdnContainerRequest, cdnContainerResponse);
cdnContainerClient.updateCDN("container", 259200, true);
}
@Test
public void testPurgeCDNObjectWhenResponseIs2xxReturnsTrue() {
HttpRequest cdnContainerRequest = HttpRequest.builder()
.method("DELETE")
.endpoint("https://cdn3.clouddrive.com/v1/MossoCloudFS_83a9d536-2e25-4166-bd3b-a503a934f953/container/foo.txt")
.addHeader("X-Auth-Token", authToken)
.build();
HttpResponse cdnContainerResponse = HttpResponse.builder()
.statusCode(204)
.build();
CloudFilesClient cdnContainerClient = requestsSendResponses(
initialAuth, responseWithAuth, cdnContainerRequest, cdnContainerResponse);
assertTrue(cdnContainerClient.purgeCDNObject("container", "foo.txt"));
}
@Test
public void testSetCDNStaticWebsiteIndexWhenResponseIs2xxReturnsTrue() {
HttpRequest cdnContainerRequest = HttpRequest.builder()
.method("POST")
.endpoint("https://storage101.lon3.clouddrive.com/v1/MossoCloudFS_83a9d536-2e25-4166-bd3b-a503a934f953/container")
.addHeader(CloudFilesHeaders.CDN_WEBSITE_INDEX, "index.html")
.addHeader("X-Auth-Token", authToken)
.build();
HttpResponse cdnContainerResponse = HttpResponse.builder()
.statusCode(204)
.build();
CloudFilesClient cdnContainerClient = requestsSendResponses(
initialAuth, responseWithAuth, cdnContainerRequest, cdnContainerResponse);
assertTrue(cdnContainerClient.setCDNStaticWebsiteIndex("container", "index.html"));
}
@Test(expectedExceptions = ContainerNotFoundException.class)
public void testSetCDNStaticWebsiteIndexWhenResponseIs404ThrowsException() {
HttpRequest cdnContainerRequest = HttpRequest.builder()
.method("POST")
.endpoint("https://storage101.lon3.clouddrive.com/v1/MossoCloudFS_83a9d536-2e25-4166-bd3b-a503a934f953/container")
.addHeader(CloudFilesHeaders.CDN_WEBSITE_INDEX, "index.html")
.addHeader("X-Auth-Token", authToken)
.build();
HttpResponse cdnContainerResponse = HttpResponse.builder()
.statusCode(404)
.build();
CloudFilesClient cdnContainerClient = requestsSendResponses(
initialAuth, responseWithAuth, cdnContainerRequest, cdnContainerResponse);
cdnContainerClient.setCDNStaticWebsiteIndex("container", "index.html");
}
@Test
public void testSetCDNStaticWebsiteErrorWhenResponseIs2xxReturnsTrue() {
HttpRequest cdnContainerRequest = HttpRequest.builder()
.method("POST")
.endpoint("https://storage101.lon3.clouddrive.com/v1/MossoCloudFS_83a9d536-2e25-4166-bd3b-a503a934f953/container")
.addHeader(CloudFilesHeaders.CDN_WEBSITE_ERROR, "error.html")
.addHeader("X-Auth-Token", authToken)
.build();
HttpResponse cdnContainerResponse = HttpResponse.builder()
.statusCode(204)
.build();
CloudFilesClient cdnContainerClient = requestsSendResponses(
initialAuth, responseWithAuth, cdnContainerRequest, cdnContainerResponse);
assertTrue(cdnContainerClient.setCDNStaticWebsiteError("container", "error.html"));
}
@Test(expectedExceptions = ContainerNotFoundException.class)
public void testSetCDNStaticWebsiteErrorWhenResponseIs404ThrowsException() {
HttpRequest cdnContainerRequest = HttpRequest.builder()
.method("POST")
.endpoint("https://storage101.lon3.clouddrive.com/v1/MossoCloudFS_83a9d536-2e25-4166-bd3b-a503a934f953/container")
.addHeader(CloudFilesHeaders.CDN_WEBSITE_ERROR, "error.html")
.addHeader("X-Auth-Token", authToken)
.build();
HttpResponse cdnContainerResponse = HttpResponse.builder()
.statusCode(404)
.build();
CloudFilesClient cdnContainerClient = requestsSendResponses(
initialAuth, responseWithAuth, cdnContainerRequest, cdnContainerResponse);
cdnContainerClient.setCDNStaticWebsiteError("container", "error.html");
}
}

View File

@ -27,6 +27,7 @@ import java.util.Set;
import org.jclouds.cloudfiles.domain.ContainerCDNMetadata;
import org.jclouds.cloudfiles.options.ListCdnContainerOptions;
import org.jclouds.openstack.swift.CommonSwiftClientLiveTest;
import org.jclouds.openstack.swift.domain.ContainerMetadata;
import org.jclouds.openstack.swift.domain.SwiftObject;
import org.testng.annotations.Test;
@ -80,16 +81,23 @@ public class CloudFilesClientLiveTest extends CommonSwiftClientLiveTest<CloudFil
cdnMetadata = getApi().getCDNMetadata(containerNameWithCDN);
assertTrue(cdnMetadata.isCDNEnabled());
assertEquals(cdnMetadata.getCDNUri(), cdnUri);
// Test static website metadata
getApi().setCDNStaticWebsiteIndex(containerNameWithCDN, "index.html");
getApi().setCDNStaticWebsiteError(containerNameWithCDN, "error.html");
ContainerMetadata containerMetadata = getApi().getContainerMetadata(containerNameWithCDN);
assertEquals(containerMetadata.getMetadata().get("web-index"), "index.html");
assertEquals(containerMetadata.getMetadata().get("web-error"), "error.html");
cdnMetadata = getApi().getCDNMetadata(containerNameWithoutCDN);
assert cdnMetadata == null || !cdnMetadata.isCDNEnabled() : containerNameWithoutCDN
+ " should not have metadata";
assert getApi().getCDNMetadata("DoesNotExist") == null;
// List CDN metadata for containers, and ensure all CDN info is
// available for enabled
// container
@ -97,9 +105,16 @@ public class CloudFilesClientLiveTest extends CommonSwiftClientLiveTest<CloudFil
assertTrue(cdnMetadataList.size() >= 1);
cdnMetadata = getApi().getCDNMetadata(containerNameWithCDN);
final boolean cdnEnabled = cdnMetadata.isCDNEnabled();
final boolean logRetention = cdnMetadata.isLogRetention();
final long initialTTL = cdnMetadata.getTTL();
assertTrue(cdnMetadataList.contains(new ContainerCDNMetadata(containerNameWithCDN, true, initialTTL, cdnUri)));
final URI cdnSslUri = cdnMetadata.getCDNSslUri();
final URI cdnStreamingUri = cdnMetadata.getCDNStreamingUri();
assertTrue(cdnMetadataList.contains(new ContainerCDNMetadata(
containerNameWithCDN, cdnEnabled, logRetention, initialTTL, cdnUri, cdnSslUri, cdnStreamingUri)));
// Test listing with options
cdnMetadataList = getApi().listCDNContainers(ListCdnContainerOptions.Builder.enabledOnly());
assertTrue(Iterables.all(cdnMetadataList, new Predicate<ContainerCDNMetadata>() {
@ -113,10 +128,9 @@ public class CloudFilesClientLiveTest extends CommonSwiftClientLiveTest<CloudFil
containerNameWithCDN.substring(0, containerNameWithCDN.length() - 1)).maxResults(1));
assertEquals(cdnMetadataList.size(), 1);
// Enable CDN with PUT for the same container, this time with a custom
// TTL
// Enable CDN with PUT for the same container, this time with a custom TTL and Log Retention
long ttl = 4000;
getApi().enableCDN(containerNameWithCDN, ttl);
getApi().enableCDN(containerNameWithCDN, ttl, true);
cdnMetadata = getApi().getCDNMetadata(containerNameWithCDN);
@ -126,7 +140,7 @@ public class CloudFilesClientLiveTest extends CommonSwiftClientLiveTest<CloudFil
// Check POST by updating TTL settings
ttl = minimumTTL;
getApi().updateCDN(containerNameWithCDN, minimumTTL);
getApi().updateCDN(containerNameWithCDN, minimumTTL, false);
cdnMetadata = getApi().getCDNMetadata(containerNameWithCDN);
assertTrue(cdnMetadata.isCDNEnabled());
@ -135,9 +149,15 @@ public class CloudFilesClientLiveTest extends CommonSwiftClientLiveTest<CloudFil
// Confirm that minimum allowed value for TTL is 3600, lower values are
// ignored.
getApi().updateCDN(containerNameWithCDN, 3599L);
getApi().updateCDN(containerNameWithCDN, 3599L, false);
cdnMetadata = getApi().getCDNMetadata(containerNameWithCDN);
assertEquals(cdnMetadata.getTTL(), 3599L);
// Test purging an object from a CDN container
SwiftObject swiftObject = newSwiftObject("hello", "hello.txt");
getApi().putObject(containerNameWithCDN, swiftObject);
assertTrue(getApi().purgeCDNObject(containerNameWithCDN, swiftObject.getInfo().getName()));
// Disable CDN with POST
assertTrue(getApi().disableCDN(containerNameWithCDN));

View File

@ -0,0 +1,76 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds 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.cloudfiles.binders;
import static org.testng.Assert.assertEquals;
import java.util.List;
import org.jclouds.cloudfiles.reference.CloudFilesHeaders;
import org.jclouds.http.HttpRequest;
import org.jclouds.openstack.swift.CommonSwiftClientTest;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableList;
/**
* Tests behavior of {@code BindIterableToHeadersWithPurgeCDNObjectEmail}
*
* @author Everett Toews
*/
// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
@Test(groups = "unit", testName = "BindIterableToHeadersWithPurgeCDNObjectEmailTest")
public class BindIterableToHeadersWithPurgeCDNObjectEmailTest extends CommonSwiftClientTest {
@Test
public void testEmailBind() {
List<String> emails = ImmutableList.of("foo@bar.com", "bar@foo.com");
HttpRequest request = HttpRequest.builder().method("DELETE").endpoint("http://localhost").build();
BindIterableToHeadersWithPurgeCDNObjectEmail binder =
injector.getInstance(BindIterableToHeadersWithPurgeCDNObjectEmail.class);
HttpRequest actualRequest = binder.bindToRequest(request, emails);
HttpRequest expectedRequest = HttpRequest.builder()
.method("DELETE")
.endpoint("http://localhost")
.addHeader(CloudFilesHeaders.CDN_CONTAINER_PURGE_OBJECT_EMAIL, "foo@bar.com, bar@foo.com")
.build();
assertEquals(actualRequest, expectedRequest);
}
@Test(expectedExceptions = NullPointerException.class)
public void testNullListIsBad() {
HttpRequest request = HttpRequest.builder().method("DELETE").endpoint("http://localhost").build();
BindIterableToHeadersWithPurgeCDNObjectEmail binder =
injector.getInstance(BindIterableToHeadersWithPurgeCDNObjectEmail.class);
binder.bindToRequest(request, null);
}
@Test(expectedExceptions = NullPointerException.class)
public void testNullRequestIsBad() {
List<String> emails = ImmutableList.of("foo@bar.com", "bar@foo.com");
BindIterableToHeadersWithPurgeCDNObjectEmail binder =
injector.getInstance(BindIterableToHeadersWithPurgeCDNObjectEmail.class);
binder.bindToRequest(null, emails);
}
}

View File

@ -51,12 +51,32 @@ public class ParseContainerCDNMetadataListFromJsonResponseTest {
InputStream is = getClass().getResourceAsStream("/test_list_cdn.json");
Set<ContainerCDNMetadata> expects = ImmutableSortedSet.of(
new ContainerCDNMetadata("adriancole-blobstore.testCDNOperationsContainerWithCDN", false, 3600, URI
.create("http://c0354712.cdn.cloudfiles.rackspacecloud.com")), new ContainerCDNMetadata(
"adriancole-blobstore5", true, 28800, URI.create("http://c0404671.cdn.cloudfiles.rackspacecloud.com")),
new ContainerCDNMetadata("adriancole-cfcdnint.testCDNOperationsContainerWithCDN", false, 3600, URI
.create("http://c0320431.cdn.cloudfiles.rackspacecloud.com")));
new ContainerCDNMetadata(
"adriancole-blobstore.testCDNOperationsContainerWithCDN",
false,
false,
3600,
URI.create("http://c0354712.cdn.cloudfiles.rackspacecloud.com"),
URI.create("https://c0354712.cdn.ssl.cloudfiles.rackspacecloud.com"),
URI.create("http://c0354712.cdn.stream.cloudfiles.rackspacecloud.com")),
new ContainerCDNMetadata(
"adriancole-blobstore5",
true,
false,
28800,
URI.create("http://c0404671.cdn.cloudfiles.rackspacecloud.com"),
URI.create("https://c0404671.cdn.ssl.cloudfiles.rackspacecloud.com"),
URI.create("http://c0404671.cdn.stream.cloudfiles.rackspacecloud.com")),
new ContainerCDNMetadata(
"adriancole-cfcdnint.testCDNOperationsContainerWithCDN",
false,
false,
3600,
URI.create("http://c0320431.cdn.cloudfiles.rackspacecloud.com"),
URI.create("https://c0320431.cdn.ssl.cloudfiles.rackspacecloud.com"),
URI.create("http://c0320431.cdn.stream.cloudfiles.rackspacecloud.com"))
);
ParseJson<SortedSet<ContainerCDNMetadata>> parser = i.getInstance(Key
.get(new TypeLiteral<ParseJson<SortedSet<ContainerCDNMetadata>>>() {
}));

View File

@ -1,5 +1,35 @@
[
{"name":"adriancole-blobstore.testCDNOperationsContainerWithCDN","cdn_enabled":"false","ttl":3600,"cdn_uri":"http://c0354712.cdn.cloudfiles.rackspacecloud.com","referrer_acl":"","useragent_acl":"", "log_retention":"false"},
{"name":"adriancole-blobstore5","cdn_enabled":"true","ttl":28800,"cdn_uri":"http://c0404671.cdn.cloudfiles.rackspacecloud.com","referrer_acl":"","useragent_acl":"", "log_retention":"false"},
{"name":"adriancole-cfcdnint.testCDNOperationsContainerWithCDN","cdn_enabled":"false","ttl":3600,"cdn_uri":"http://c0320431.cdn.cloudfiles.rackspacecloud.com","referrer_acl":"","useragent_acl":"", "log_retention":"false"}
{
"name":"adriancole-blobstore.testCDNOperationsContainerWithCDN",
"cdn_enabled":"false",
"log_retention":"false",
"ttl":3600,
"cdn_uri":"http://c0354712.cdn.cloudfiles.rackspacecloud.com",
"cdn_ssl_uri":"https://c0354712.cdn.ssl.cloudfiles.rackspacecloud.com",
"cdn_streaming_uri":"http://c0354712.cdn.stream.cloudfiles.rackspacecloud.com",
"referrer_acl":"",
"useragent_acl":""
},
{
"name":"adriancole-blobstore5",
"cdn_enabled":"true",
"log_retention":"false",
"ttl":28800,
"cdn_uri":"http://c0404671.cdn.cloudfiles.rackspacecloud.com",
"cdn_ssl_uri":"https://c0404671.cdn.ssl.cloudfiles.rackspacecloud.com",
"cdn_streaming_uri":"http://c0404671.cdn.stream.cloudfiles.rackspacecloud.com",
"referrer_acl":"",
"useragent_acl":""
},
{
"name":"adriancole-cfcdnint.testCDNOperationsContainerWithCDN",
"cdn_enabled":"false",
"log_retention":"false",
"ttl":3600,
"cdn_uri":"http://c0320431.cdn.cloudfiles.rackspacecloud.com",
"cdn_ssl_uri":"https://c0320431.cdn.ssl.cloudfiles.rackspacecloud.com",
"cdn_streaming_uri":"http://c0320431.cdn.stream.cloudfiles.rackspacecloud.com",
"referrer_acl":"",
"useragent_acl":""
}
]

View File

@ -339,7 +339,7 @@ public abstract class CommonSwiftClientLiveTest<C extends CommonSwiftClient> ext
assert contentType.startsWith("text/plain") || "application/x-www-form-urlencoded".equals(contentType): contentType;
}
private SwiftObject newSwiftObject(String data, String key) throws IOException {
protected SwiftObject newSwiftObject(String data, String key) throws IOException {
SwiftObject object = getApi().newSwiftObject();
object.getInfo().setName(key);
object.setPayload(data);