Issue 905:create openstack-swift api

This commit is contained in:
Adrian Cole 2012-04-19 23:18:36 -07:00
parent b87e1397ee
commit eda3f05c8e
36 changed files with 2174 additions and 0 deletions

View File

@ -0,0 +1,151 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.jclouds</groupId>
<artifactId>jclouds-project</artifactId>
<version>1.5.0-SNAPSHOT</version>
<relativePath>../../project/pom.xml</relativePath>
</parent>
<groupId>org.jclouds.labs</groupId>
<artifactId>openstack-swift</artifactId>
<name>jcloud openstack-swift api</name>
<description>jclouds components to access an implementation of OpenStack Swift</description>
<packaging>bundle</packaging>
<properties>
<!-- keystone endpoint -->
<test.openstack-swift.endpoint>http://localhost:5000</test.openstack-swift.endpoint>
<!-- keystone version -->
<test.openstack-swift.api-version>1.0</test.openstack-swift.api-version>
<test.openstack-swift.build-version></test.openstack-swift.build-version>
<test.openstack-swift.identity>FIXME_IDENTITY</test.openstack-swift.identity>
<test.openstack-swift.credential>FIXME_CREDENTIALS</test.openstack-swift.credential>
<test.jclouds.keystone.credential-type>passwordCredentials</test.jclouds.keystone.credential-type>
<jclouds.blobstore.httpstream.url>FIXME_HTTPURL</jclouds.blobstore.httpstream.url>
<jclouds.blobstore.httpstream.md5>FIXME_HTTPMD5</jclouds.blobstore.httpstream.md5>
</properties>
<dependencies>
<dependency>
<groupId>org.jclouds.common</groupId>
<artifactId>openstack-common</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.jclouds</groupId>
<artifactId>jclouds-blobstore</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.jclouds</groupId>
<artifactId>jclouds-core</artifactId>
<version>${project.version}</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jclouds.common</groupId>
<artifactId>openstack-common</artifactId>
<version>${project.version}</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jclouds</groupId>
<artifactId>jclouds-blobstore</artifactId>
<version>${project.version}</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jclouds.driver</groupId>
<artifactId>jclouds-slf4j</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.0.0</version>
<scope>test</scope>
</dependency>
</dependencies>
<profiles>
<profile>
<id>live</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<executions>
<execution>
<id>integration</id>
<phase>integration-test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<systemPropertyVariables>
<test.openstack-swift.endpoint>${test.openstack-swift.endpoint}</test.openstack-swift.endpoint>
<test.openstack-swift.api-version>${test.openstack-swift.api-version}</test.openstack-swift.api-version>
<test.openstack-swift.build-version>${test.openstack-swift.build-version}</test.openstack-swift.build-version>
<test.openstack-swift.identity>${test.openstack-swift.identity}</test.openstack-swift.identity>
<test.openstack-swift.credential>${test.openstack-swift.credential}</test.openstack-swift.credential>
<test.jclouds.keystone.credential-type>${test.jclouds.keystone.credential-type}</test.jclouds.keystone.credential-type>
<jclouds.blobstore.httpstream.url>${jclouds.blobstore.httpstream.url}</jclouds.blobstore.httpstream.url>
<jclouds.blobstore.httpstream.md5>${jclouds.blobstore.httpstream.md5}</jclouds.blobstore.httpstream.md5>
</systemPropertyVariables>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Export-Package>org.jclouds.openstack.swift.v1*;version="${project.version}"</Export-Package>
<Import-Package>
org.jclouds.blobstore.internal;version="${project.version}",
org.jclouds.rest.internal;version="${project.version}",
org.jclouds*;version="${project.version}",
*
</Import-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,100 @@
/**
* 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.openstack.swift.v1;
import static org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.SERVICE_TYPE;
import java.net.URI;
import java.util.Properties;
import org.jclouds.apis.ApiMetadata;
import org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties;
import org.jclouds.openstack.services.ServiceType;
import org.jclouds.openstack.swift.v1.config.SwiftRestClientModule;
import org.jclouds.rest.RestContext;
import org.jclouds.rest.internal.BaseRestApiMetadata;
import com.google.common.collect.ImmutableSet;
import com.google.common.reflect.TypeToken;
import com.google.inject.Module;
/**
* Implementation of {@link ApiMetadata} for Swift 1.0 API
*
* @author Adrian Cole
*/
public class SwiftApiMetadata extends BaseRestApiMetadata {
/** The serialVersionUID */
private static final long serialVersionUID = 6725672099385580694L;
public static final TypeToken<RestContext<SwiftClient, SwiftAsyncClient>> CONTEXT_TOKEN = new TypeToken<RestContext<SwiftClient, SwiftAsyncClient>>() {
private static final long serialVersionUID = -5070937833892503232L;
};
@Override
public Builder toBuilder() {
return new Builder().fromApiMetadata(this);
}
public SwiftApiMetadata() {
this(new Builder());
}
protected SwiftApiMetadata(Builder builder) {
super(builder);
}
public static Properties defaultProperties() {
Properties properties = BaseRestApiMetadata.defaultProperties();
properties.setProperty(SERVICE_TYPE, ServiceType.OBJECT_STORE);
// TODO: this doesn't actually do anything yet.
properties.setProperty(KeystoneProperties.VERSION, "2.0");
return properties;
}
public static class Builder extends BaseRestApiMetadata.Builder {
protected Builder() {
super(SwiftClient.class, SwiftAsyncClient.class);
id("openstack-swift")
.name("OpenStack Swift Diablo+ API")
.identityName("tenantId:user")
.credentialName("password")
.documentation(URI.create("http://docs.openstack.org/api/openstack-object-storage/1.0/content/ch_object-storage-dev-overview.html"))
.version("1.0")
.defaultEndpoint("http://localhost:5000")
.defaultProperties(SwiftApiMetadata.defaultProperties())
.defaultModules(ImmutableSet.<Class<? extends Module>>of(SwiftRestClientModule.class));
}
@Override
public SwiftApiMetadata build() {
return new SwiftApiMetadata(this);
}
@Override
public Builder fromApiMetadata(ApiMetadata in) {
super.fromApiMetadata(in);
return this;
}
}
}

View File

@ -0,0 +1,69 @@
/**
* 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.openstack.swift.v1;
import java.util.Set;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.location.Region;
import org.jclouds.location.functions.RegionToEndpoint;
import org.jclouds.openstack.swift.v1.features.AccountAsyncClient;
import org.jclouds.openstack.swift.v1.features.ContainerAsyncClient;
import org.jclouds.openstack.swift.v1.features.ObjectAsyncClient;
import org.jclouds.rest.annotations.Delegate;
import org.jclouds.rest.annotations.EndpointParam;
import com.google.inject.Provides;
/**
* Provides asynchronous access to Swift via their REST API.
* <p/>
*
* @see SwiftClient
* @see <a href="http://docs.openstack.org/api/openstack-object-storage/1.0/content">api doc</a>
* @author Adrian Cole
*/
public interface SwiftAsyncClient {
/**
*
* @return the Region codes configured
*/
@Provides
@Region
Set<String> getConfiguredRegions();
/**
* Provides asynchronous access to Account features.
*/
@Delegate
AccountAsyncClient getAccountClientForRegion(@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region);
/**
* Provides asynchronous access to Container features.
*/
@Delegate
ContainerAsyncClient getContainerClientForRegion(
@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region);
/**
* Provides asynchronous access to Object features.
*/
@Delegate
ObjectAsyncClient getObjectClientForRegion(@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region);
}

View File

@ -0,0 +1,71 @@
/**
* 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.openstack.swift.v1;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.jclouds.concurrent.Timeout;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.location.Region;
import org.jclouds.location.functions.RegionToEndpoint;
import org.jclouds.openstack.swift.v1.features.AccountClient;
import org.jclouds.openstack.swift.v1.features.ContainerClient;
import org.jclouds.openstack.swift.v1.features.ObjectClient;
import org.jclouds.rest.annotations.Delegate;
import org.jclouds.rest.annotations.EndpointParam;
import com.google.inject.Provides;
/**
* Provides synchronous access to Swift.
* <p/>
*
* @see SwiftAsyncClient
* @see <a href="http://docs.openstack.org/api/openstack-object-storage/1.0/content">api doc</a>
* @author Adrian Cole
*/
@Timeout(duration = 60, timeUnit = TimeUnit.SECONDS)
public interface SwiftClient {
/**
*
* @return the Region codes configured
*/
@Provides
@Region
Set<String> getConfiguredRegions();
/**
* Provides synchronous access to Account features.
*/
@Delegate
AccountClient getAccountClientForRegion(@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region);
/**
* Provides synchronous access to Container features.
*/
@Delegate
ContainerClient getContainerClientForRegion(@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region);
/**
* Provides synchronous access to Object features.
*/
@Delegate
ObjectClient getObjectClientForRegion(@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region);
}

View File

@ -0,0 +1,28 @@
/**
* 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.openstack.swift.v1.config;
/**
* Configuration properties and constants used in openstack Swift connections.
*
* @author Adam Lowe
*/
public class SwiftProperties {
}

View File

@ -0,0 +1,85 @@
/**
* 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.openstack.swift.v1.config;
import java.util.Map;
import org.jclouds.http.HttpErrorHandler;
import org.jclouds.http.annotation.ClientError;
import org.jclouds.http.annotation.Redirection;
import org.jclouds.http.annotation.ServerError;
import org.jclouds.json.config.GsonModule.DateAdapter;
import org.jclouds.json.config.GsonModule.Iso8601DateAdapter;
import org.jclouds.openstack.keystone.v2_0.config.KeystoneAuthenticationModule;
import org.jclouds.openstack.swift.v1.SwiftAsyncClient;
import org.jclouds.openstack.swift.v1.SwiftClient;
import org.jclouds.openstack.swift.v1.features.AccountAsyncClient;
import org.jclouds.openstack.swift.v1.features.AccountClient;
import org.jclouds.openstack.swift.v1.features.ContainerAsyncClient;
import org.jclouds.openstack.swift.v1.features.ContainerClient;
import org.jclouds.openstack.swift.v1.features.ObjectAsyncClient;
import org.jclouds.openstack.swift.v1.features.ObjectClient;
import org.jclouds.openstack.swift.v1.handlers.SwiftErrorHandler;
import org.jclouds.rest.ConfiguresRestClient;
import org.jclouds.rest.config.RestClientModule;
import com.google.common.collect.ImmutableMap;
/**
* Configures the Swift connection.
*
* @author Adrian Cole
*/
@ConfiguresRestClient
public class SwiftRestClientModule extends RestClientModule<SwiftClient, SwiftAsyncClient> {
public static final Map<Class<?>, Class<?>> DELEGATE_MAP = ImmutableMap.<Class<?>, Class<?>> builder()
.put(AccountClient.class, AccountAsyncClient.class)
.put(ContainerClient.class, ContainerAsyncClient.class)
.put(ObjectClient.class, ObjectAsyncClient.class)
.build();
public SwiftRestClientModule() {
super(DELEGATE_MAP);
}
@Override
protected void configure() {
bind(DateAdapter.class).to(Iso8601DateAdapter.class);
super.configure();
}
@Override
protected void installLocations() {
// TODO: select this from KeystoneProperties.VERSION; note you select from
// a guice provided
// property, so it will have to come from somewhere else, maybe we move
// this to the the
// ContextBuilder
install(KeystoneAuthenticationModule.forRegions());
super.installLocations();
}
@Override
protected void bindErrorHandlers() {
bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(SwiftErrorHandler.class);
bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(SwiftErrorHandler.class);
bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(SwiftErrorHandler.class);
}
}

View File

@ -0,0 +1,101 @@
package org.jclouds.openstack.swift.v1.domain;
import static com.google.common.base.Objects.equal;
import static com.google.common.base.Objects.toStringHelper;
import com.google.common.base.Objects;
import com.google.common.base.Objects.ToStringHelper;
/**
* @author Adrian Cole
* @see <a href="http://docs.openstack.org/api/openstack-object-storage/1.0/content/retrieve-account-metadata.html">api doc</a>
*/
public class AccountMetadata {
public static Builder builder() {
return new Builder();
}
public Builder toBuilder() {
return builder().fromAccountMetadata(this);
}
public static class Builder {
protected int containerCount;
protected long bytesUsed;
/**
* @see AccountMetadata#getContainerCount()
*/
public Builder containerCount(int containerCount) {
this.containerCount = containerCount;
return this;
}
/**
* @see AccountMetadata#getBytesUsed()
*/
public Builder bytesUsed(long bytesUsed) {
this.bytesUsed = bytesUsed;
return this;
}
public AccountMetadata build() {
return new AccountMetadata(containerCount, bytesUsed);
}
public Builder fromAccountMetadata(AccountMetadata from) {
return containerCount(from.getContainerCount()).bytesUsed(from.getBytesUsed());
}
}
protected final int containerCount;
protected final long bytesUsed;
public AccountMetadata(int containerCount, long bytesUsed) {
this.containerCount = containerCount;
this.bytesUsed = bytesUsed;
}
/**
*
* @return the number of containers in OpenStack Object Storage for the account
*/
public int getContainerCount() {
return containerCount;
}
/**
* @return the total bytes stored in OpenStack Object Storage for the account
*/
public long getBytesUsed() {
return bytesUsed;
}
@Override
public boolean equals(Object object) {
if (this == object) {
return true;
}
if (object instanceof AccountMetadata) {
final AccountMetadata other = AccountMetadata.class.cast(object);
return equal(getContainerCount(), other.getContainerCount()) && equal(getBytesUsed(), other.getBytesUsed());
} else {
return false;
}
}
@Override
public int hashCode() {
return Objects.hashCode(getContainerCount(), getBytesUsed());
}
@Override
public String toString() {
return string().toString();
}
protected ToStringHelper string() {
return toStringHelper("").add("containerCount", getContainerCount()).add("bytesUsed", getBytesUsed());
}
}

View File

@ -0,0 +1,138 @@
package org.jclouds.openstack.swift.v1.domain;
import static com.google.common.base.Objects.equal;
import static com.google.common.base.Objects.toStringHelper;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.base.Objects;
import com.google.common.base.Objects.ToStringHelper;
/**
* retrieve a list of existing storage containers ordered by name. The sort order for the name is
* based on a binary comparison, a single built-in collating sequence that compares string data
* using SQLite's memcmp() function, regardless of text encoding.
*
* @author Adrian Cole
* @see <a
* href="http://docs.openstack.org/api/openstack-object-storage/1.0/content/s_listcontainers.html">api
* doc</a>
*/
public class ContainerMetadata implements Comparable<ContainerMetadata> {
public static Builder builder() {
return new Builder();
}
public Builder toBuilder() {
return builder().fromAccountMetadata(this);
}
public static class Builder {
protected String name;
protected int count;
protected int bytes;
/**
* @see ContainerMetadata#getName()
*/
public Builder name(String name) {
this.name = checkNotNull(name, "name");
return this;
}
/**
* @see ContainerMetadata#getCount()
*/
public Builder count(int count) {
this.count = count;
return this;
}
/**
* @see ContainerMetadata#getBytes()
*/
public Builder bytes(int bytes) {
this.bytes = bytes;
return this;
}
public ContainerMetadata build() {
return new ContainerMetadata(name, count, bytes);
}
public Builder fromAccountMetadata(ContainerMetadata from) {
return name(from.getName()).count(from.getCount()).bytes(from.getBytes());
}
}
protected final String name;
protected final int count;
protected final int bytes;
public ContainerMetadata(String name, int count, int bytes) {
this.name = checkNotNull(name, "name");
this.count = count;
this.bytes = bytes;
}
/**
*
* @return the name of the container
*/
public String getName() {
return name;
}
/**
*
* @return the number of objects in the container
*/
public int getCount() {
return count;
}
/**
* @return the total bytes stored in this container
*/
public int getBytes() {
return bytes;
}
@Override
public boolean equals(Object object) {
if (this == object) {
return true;
}
if (object instanceof ContainerMetadata) {
final ContainerMetadata other = ContainerMetadata.class.cast(object);
return equal(getName(), other.getName()) && equal(getCount(), other.getCount())
&& equal(getBytes(), other.getBytes());
} else {
return false;
}
}
@Override
public int hashCode() {
return Objects.hashCode(getName(), getCount(), getBytes());
}
@Override
public String toString() {
return string().toString();
}
protected ToStringHelper string() {
return toStringHelper("").add("name", getName()).add("count", getCount()).add("bytes", getBytes());
}
@Override
public int compareTo(ContainerMetadata that) {
if (that == null)
return 1;
if (this == that)
return 0;
return this.getName().compareTo(that.getName());
}
}

View File

@ -0,0 +1,83 @@
/**
* 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.openstack.swift.v1.features;
import java.util.Set;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.HEAD;
import javax.ws.rs.Path;
import javax.ws.rs.core.MediaType;
import org.jclouds.openstack.filters.AuthenticateRequest;
import org.jclouds.openstack.swift.v1.domain.AccountMetadata;
import org.jclouds.openstack.swift.v1.domain.ContainerMetadata;
import org.jclouds.openstack.swift.v1.functions.ParseAccountMetadataResponseFromHeaders;
import org.jclouds.openstack.swift.v1.options.ListContainersOptions;
import org.jclouds.rest.annotations.ExceptionParser;
import org.jclouds.rest.annotations.QueryParams;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.SkipEncoding;
import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404;
import com.google.common.util.concurrent.ListenableFuture;
/**
* Storage Account Services
*
* @see AccountClient
* @author Adrian Cole
* @see <a
* href="http://docs.openstack.org/api/openstack-object-storage/1.0/content/storage-account-services.html"
* >api doc</a>
*/
@SkipEncoding( { '/', '=' })
@RequestFilters(AuthenticateRequest.class)
public interface AccountAsyncClient {
/**
* @see AccountClient#getAccountMetadata
*/
@HEAD
@ResponseParser(ParseAccountMetadataResponseFromHeaders.class)
@Path("/")
ListenableFuture<AccountMetadata> getAccountMetadata();
/**
* @see AccountClient#listContainers()
*/
@GET
@Consumes(MediaType.APPLICATION_JSON)
@QueryParams(keys = "format", values = "json")
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
@Path("/")
ListenableFuture<Set<ContainerMetadata>> listContainers();
/**
* @see AccountClient#listContainers(ListContainersOptions)
*/
@GET
@Consumes(MediaType.APPLICATION_JSON)
@QueryParams(keys = "format", values = "json")
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
@Path("/")
ListenableFuture<Set<ContainerMetadata>> listContainers(ListContainersOptions options);
}

View File

@ -0,0 +1,62 @@
/**
* 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.openstack.swift.v1.features;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.jclouds.concurrent.Timeout;
import org.jclouds.openstack.swift.v1.domain.AccountMetadata;
import org.jclouds.openstack.swift.v1.domain.ContainerMetadata;
import org.jclouds.openstack.swift.v1.options.ListContainersOptions;
/**
* Storage Account Services
*
* @see AccountAsyncClient
* @author Adrian Cole
* @see <a
* href="http://docs.openstack.org/api/openstack-object-storage/1.0/content/storage-account-services.html"
* >api doc</a>
*/
@Timeout(duration = 180, timeUnit = TimeUnit.SECONDS)
public interface AccountClient {
/**
* Retrieve Account Metadata
*
* @return account metadata including container count and bytes used
*/
AccountMetadata getAccountMetadata();
/**
* @see #listContainers(ListContainersOptions)
*/
Set<ContainerMetadata> listContainers();
/**
* retrieve a list of existing storage containers ordered by name. The sort order for the name is
* based on a binary comparison, a single built-in collating sequence that compares string data
* using SQLite's memcmp() function, regardless of text encoding.
*
* @param options
* @return a list of existing storage containers ordered by name.
*/
Set<ContainerMetadata> listContainers(ListContainersOptions options);
}

View File

@ -0,0 +1,38 @@
/**
* 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.openstack.swift.v1.features;
import org.jclouds.openstack.filters.AuthenticateRequest;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.SkipEncoding;
/**
* Storage Container Services
*
* @see ContainerClient
* @author Adrian Cole
* @see <a href=
* "http://docs.openstack.org/api/openstack-object-storage/1.0/content/storage-container-services.html"
* >api doc</a>
*/
@SkipEncoding({ '/', '=' })
@RequestFilters(AuthenticateRequest.class)
public interface ContainerAsyncClient {
}

View File

@ -0,0 +1,37 @@
/**
* 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.openstack.swift.v1.features;
import java.util.concurrent.TimeUnit;
import org.jclouds.concurrent.Timeout;
/**
* Storage Container Services
*
* @see ContainerAsyncClient
* @author Adrian Cole
* @see <a href=
* "http://docs.openstack.org/api/openstack-object-storage/1.0/content/storage-container-services.html"
* >api doc</a>
*/
@Timeout(duration = 180, timeUnit = TimeUnit.SECONDS)
public interface ContainerClient {
}

View File

@ -0,0 +1,38 @@
/**
* 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.openstack.swift.v1.features;
import org.jclouds.openstack.filters.AuthenticateRequest;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.SkipEncoding;
/**
* Storage Object Services
*
* @see ObjectClient
* @author Adrian Cole
* @see <a href=
* "http://docs.openstack.org/api/openstack-object-storage/1.0/content/storage-container-services.html"
* >api doc</a>
*/
@SkipEncoding( { '/', '=' })
@RequestFilters(AuthenticateRequest.class)
public interface ObjectAsyncClient {
}

View File

@ -0,0 +1,43 @@
/**
* 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.openstack.swift.v1.features;
import java.util.concurrent.TimeUnit;
import org.jclouds.concurrent.Timeout;
/**
* Storage Object Services An object represents the data and any metadata for the files stored in
* the system. Through the ReST interface, metadata for an object can be included by adding custom
* HTTP headers to the request and the data payload as the request body. Objects cannot exceed 5GB
* and must have names that do not exceed 1024 bytes after URL encoding. However, objects larger
* than 5GB can be segmented and then concatenated together so that you can upload 5 GB segments and
* download a single concatenated object. You can work with the segments and manifests directly with
* HTTP requests.
*
* @see ObjectAsyncClient
* @author Adrian Cole
* @see <a href=
* "http://docs.openstack.org/api/openstack-object-storage/1.0/content/storage-object-services.html"
* >api doc</a>
*/
@Timeout(duration = 180, timeUnit = TimeUnit.SECONDS)
public interface ObjectClient {
}

View File

@ -0,0 +1,42 @@
/**
* 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.openstack.swift.v1.functions;
import org.jclouds.http.HttpResponse;
import org.jclouds.openstack.swift.v1.domain.AccountMetadata;
import com.google.common.base.Function;
/**
* This parses {@link AccountMetadata} from HTTP headers.
*
* @author James Murty
*/
public class ParseAccountMetadataResponseFromHeaders implements Function<HttpResponse, AccountMetadata> {
/**
* parses the http response headers to create a new {@link AccountMetadata} object.
*/
public AccountMetadata apply(HttpResponse from) {
return AccountMetadata.builder()
.bytesUsed(Long.parseLong(from.getFirstHeaderOrNull("X-Account-Bytes-Used")))
.containerCount(Integer.parseInt(from.getFirstHeaderOrNull("X-Account-Container-Count")))
.build();
}
}

View File

@ -0,0 +1,82 @@
/**
* 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.openstack.swift.v1.handlers;
import static org.jclouds.http.HttpUtils.closeClientButKeepContentStream;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.inject.Singleton;
import org.jclouds.blobstore.ContainerNotFoundException;
import org.jclouds.blobstore.KeyNotFoundException;
import org.jclouds.http.HttpCommand;
import org.jclouds.http.HttpErrorHandler;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpResponseException;
import org.jclouds.rest.AuthorizationException;
/**
* This will parse and set an appropriate exception on the command object.
*
* @author Adrian Cole
*
*/
// TODO: is there error spec someplace? let's type errors, etc.
@Singleton
public class SwiftErrorHandler implements HttpErrorHandler {
public static final String PREFIX = "^/v[0-9][^/]*/[a-zA-Z]+_[^/]+/";
public static final Pattern CONTAINER_PATH = Pattern.compile(PREFIX + "([^/]+)$");
public static final Pattern CONTAINER_KEY_PATH = Pattern.compile(PREFIX + "([^/]+)/(.*)");
public void handleError(HttpCommand command, HttpResponse response) {
// it is important to always read fully and close streams
byte[] data = closeClientButKeepContentStream(response);
String message = data != null ? new String(data) : null;
Exception exception = message != null ? new HttpResponseException(command, response, message)
: new HttpResponseException(command, response);
message = message != null ? message : String.format("%s -> %s", command.getCurrentRequest().getRequestLine(),
response.getStatusLine());
switch (response.getStatusCode()) {
case 401:
exception = new AuthorizationException(exception.getMessage(), exception);
break;
case 404:
if (!command.getCurrentRequest().getMethod().equals("DELETE")) {
String path = command.getCurrentRequest().getEndpoint().getPath();
Matcher matcher = CONTAINER_PATH.matcher(path);
Exception oldException = exception;
if (matcher.find()) {
exception = new ContainerNotFoundException(matcher.group(1), message);
exception.initCause(oldException);
} else {
matcher = CONTAINER_KEY_PATH.matcher(path);
if (matcher.find()) {
exception = new KeyNotFoundException(matcher.group(1), matcher.group(2), message);
exception.initCause(oldException);
}
}
}
break;
}
command.setException(exception);
}
}

View File

@ -0,0 +1,79 @@
/**
* 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.openstack.swift.v1.options;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import org.jclouds.http.options.BaseHttpRequestOptions;
/**
* Contains options supported in the REST API for the GET container operation. <h2>
*/
public class ListContainersOptions extends BaseHttpRequestOptions {
public static final ListContainersOptions NONE = new ListContainersOptions();
/**
* Given a string value x, return object names greater in value than the specified marker.
*/
public ListContainersOptions marker(String marker) {
queryParameters.put("marker", checkNotNull(marker, "marker"));
return this;
}
public String getMarker() {
return getFirstQueryOrNull("marker");
}
/**
* For an integer value n, limits the number of results to n values.
*/
public ListContainersOptions limit(int limit) {
checkState(limit >= 0, "limit must be >= 0");
checkState(limit <= 10000, "limit must be <= 10000");
queryParameters.put("limit", Integer.toString(limit));
return this;
}
public int getLimit() {
String val = getFirstQueryOrNull("limit");
return val != null ? new Integer(val) : 10000;
}
public static class Builder {
/**
* @see ListContainersOptions#marker(String)
*/
public static ListContainersOptions marker(String marker) {
ListContainersOptions options = new ListContainersOptions();
return options.marker(marker);
}
/**
* @see ListContainersOptions#limit(int)
*/
public static ListContainersOptions limit(int limit) {
ListContainersOptions options = new ListContainersOptions();
return options.limit(limit);
}
}
}

View File

@ -0,0 +1 @@
org.jclouds.openstack.swift.v1.SwiftApiMetadata

View File

@ -0,0 +1,75 @@
/**
* 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.openstack.swift.v1;
import static org.testng.Assert.assertEquals;
import java.net.URI;
import java.util.Properties;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties;
import org.jclouds.openstack.swift.v1.internal.BaseSwiftClientExpectTest;
import org.jclouds.openstack.swift.v1.parse.ParseContainerListTest;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableSet;
/**
*
* @see KeystoneProperties#CREDENTIAL_TYPE
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "PasswordAuthenticationExpectTest")
public class PasswordAuthenticationExpectTest extends BaseSwiftClientExpectTest {
/**
* this reflects the properties that a user would pass to createContext
*/
@Override
protected Properties setupProperties() {
Properties contextProperties = super.setupProperties();
contextProperties.setProperty("jclouds.keystone.credential-type", "passwordCredentials");
return contextProperties;
}
public void testListContainersWhenResponseIs2xx() throws Exception {
HttpRequest listContainers = HttpRequest
.builder()
.method("GET")
.endpoint(URI.create("https://objects.jclouds.org/v1.0/40806637803162/?format=json"))
.headers(
ImmutableMultimap.<String, String> builder().put("Accept", "application/json")
.put("X-Auth-Token", authToken).build()).build();
HttpResponse listContainersResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/container_list.json")).build();
SwiftClient clientWhenContainersExist = requestsSendResponses(keystoneAuthWithUsernameAndPassword,
responseWithKeystoneAccess, listContainers, listContainersResponse);
assertEquals(clientWhenContainersExist.getConfiguredRegions(), ImmutableSet.of("region-a.geo-1"));
assertEquals(clientWhenContainersExist.getAccountClientForRegion("region-a.geo-1").listContainers().toString(),
new ParseContainerListTest().expected().toString());
}
}

View File

@ -0,0 +1,38 @@
/**
* 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.openstack.swift.v1;
import org.jclouds.Wrapper;
import org.jclouds.apis.internal.BaseApiMetadataTest;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableSet;
import com.google.common.reflect.TypeToken;
/**
*
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "SwiftApiMetadataTest")
// public class SwiftApiMetadataTest extends BaseBlobStoreApiMetadataTest {
public class SwiftApiMetadataTest extends BaseApiMetadataTest {
public SwiftApiMetadataTest() {
super(new SwiftApiMetadata(), ImmutableSet.<TypeToken<? extends Wrapper>> of());
}
}

View File

@ -0,0 +1,120 @@
/**
* 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.openstack.swift.v1;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.reportMatcher;
import static org.easymock.EasyMock.verify;
import java.net.URI;
import org.easymock.IArgumentMatcher;
import org.jclouds.blobstore.ContainerNotFoundException;
import org.jclouds.blobstore.KeyNotFoundException;
import org.jclouds.http.HttpCommand;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.io.Payloads;
import org.jclouds.openstack.swift.v1.handlers.SwiftErrorHandler;
import org.jclouds.util.Strings2;
import org.testng.annotations.Test;
/**
*
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "SwiftErrorHandlerTest")
public class SwiftErrorHandlerTest {
@Test
public void test404SetsKeyNotFoundExceptionMosso() {
assertCodeMakes("HEAD", URI
.create("http://host/v1/MossoCloudFS_7064cdb1d49d4dcba3c899ac33e8409d/adriancole-blobstore1/key"), 404,
"Not Found", "", KeyNotFoundException.class);
}
@Test
public void test404SetsKeyNotFoundExceptionSwift() {
assertCodeMakes("HEAD", URI
.create("http://67.202.39.175:8080/v1/AUTH_7064cdb1d49d4dcba3c899ac33e8409d/adriancole-blobstore1/key"),
404, "Not Found", "", KeyNotFoundException.class);
}
@Test
public void test404SetsContainerNotFoundExceptionMosso() {
assertCodeMakes("HEAD", URI
.create("http://host/v1/MossoCloudFS_7064cdb1d49d4dcba3c899ac33e8409d/adriancole-blobstore1"), 404,
"Not Found", "", ContainerNotFoundException.class);
}
@Test
public void test404SetsContainerNotFoundExceptionSwift() {
assertCodeMakes("HEAD", URI
.create("http://67.202.39.175:8080/v1/AUTH_7064cdb1d49d4dcba3c899ac33e8409d/adriancole-blobstore1"),
404, "Not Found", "", ContainerNotFoundException.class);
}
private void assertCodeMakes(String method, URI uri, int statusCode, String message, String content,
Class<? extends Exception> expected) {
assertCodeMakes(method, uri, statusCode, message, "text/plain", content, expected);
}
private void assertCodeMakes(String method, URI uri, int statusCode, String message, String contentType,
String content, Class<? extends Exception> expected) {
SwiftErrorHandler function = new SwiftErrorHandler();
HttpCommand command = createMock(HttpCommand.class);
HttpRequest request = new HttpRequest(method, uri);
HttpResponse response = new HttpResponse(statusCode, message, Payloads.newInputStreamPayload(Strings2
.toInputStream(content)));
response.getPayload().getContentMetadata().setContentType(contentType);
expect(command.getCurrentRequest()).andReturn(request).atLeastOnce();
command.setException(classEq(expected));
replay(command);
function.handleError(command, response);
verify(command);
}
public static Exception classEq(final Class<? extends Exception> in) {
reportMatcher(new IArgumentMatcher() {
@Override
public void appendTo(StringBuffer buffer) {
buffer.append("classEq(");
buffer.append(in);
buffer.append(")");
}
@Override
public boolean matches(Object arg) {
return arg.getClass() == in;
}
});
return null;
}
}

View File

@ -0,0 +1,104 @@
/**
* 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
*
* Unles 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 expres or implied. See the License for the
* specific language governing permisions and limitations
* under the License.
*/
package org.jclouds.openstack.swift.v1.features;
import static org.testng.Assert.assertEquals;
import java.net.URI;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.openstack.swift.v1.SwiftClient;
import org.jclouds.openstack.swift.v1.domain.AccountMetadata;
import org.jclouds.openstack.swift.v1.internal.BaseSwiftClientExpectTest;
import org.jclouds.openstack.swift.v1.parse.ParseContainerListTest;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableSet;
/**
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "AccountClientExpectTest")
public class AccountClientExpectTest extends BaseSwiftClientExpectTest {
public void testGetAccountMetadataWhenResponseIs2xx() throws Exception {
HttpRequest getAccountMetadata = HttpRequest
.builder()
.method("HEAD")
.endpoint(URI.create("https://objects.jclouds.org/v1.0/40806637803162/"))
.headers(
ImmutableMultimap.<String, String> builder()
.put("X-Auth-Token", authToken).build()).build();
HttpResponse listContainersResponse = HttpResponse.builder().statusCode(204)
.headers(ImmutableMultimap.of(
"X-Account-Container-Count", "3",
"X-Account-Bytes-Used", "323479")).build();
SwiftClient clientWhenContainersExist = requestsSendResponses(keystoneAuthWithUsernameAndPassword,
responseWithKeystoneAccess, getAccountMetadata, listContainersResponse);
assertEquals(
clientWhenContainersExist.getAccountClientForRegion("region-a.geo-1").getAccountMetadata(),
AccountMetadata.builder().containerCount(3).bytesUsed(323479).build());
}
public void testListContainersWhenResponseIs2xx() throws Exception {
HttpRequest listContainers = HttpRequest
.builder()
.method("GET")
.endpoint(URI.create("https://objects.jclouds.org/v1.0/40806637803162/?format=json"))
.headers(
ImmutableMultimap.<String, String> builder().put("Accept", "application/json")
.put("X-Auth-Token", authToken).build()).build();
HttpResponse listContainersResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/container_list.json")).build();
SwiftClient clientWhenContainersExist = requestsSendResponses(keystoneAuthWithUsernameAndPassword,
responseWithKeystoneAccess, listContainers, listContainersResponse);
assertEquals(
clientWhenContainersExist.getAccountClientForRegion("region-a.geo-1").listContainers()
.toString(), new ParseContainerListTest().expected().toString());
}
public void testListContainersWhenResponseIs404() throws Exception {
HttpRequest listContainers = HttpRequest
.builder()
.method("GET")
.endpoint(URI.create("https://objects.jclouds.org/v1.0/40806637803162/?format=json"))
.headers(
ImmutableMultimap.<String, String> builder().put("Accept", "application/json")
.put("X-Auth-Token", authToken).build()).build();
HttpResponse listContainersResponse = HttpResponse.builder().statusCode(404).build();
SwiftClient clientWhenNoContainersExist = requestsSendResponses(keystoneAuthWithUsernameAndPassword,
responseWithKeystoneAccess, listContainers, listContainersResponse);
assertEquals(clientWhenNoContainersExist.getAccountClientForRegion("region-a.geo-1").listContainers(), ImmutableSet.of());
}
}

View File

@ -0,0 +1,61 @@
/**
* 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.openstack.swift.v1.features;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;
import java.util.Set;
import org.jclouds.openstack.swift.v1.domain.AccountMetadata;
import org.jclouds.openstack.swift.v1.domain.ContainerMetadata;
import org.jclouds.openstack.swift.v1.internal.BaseSwiftClientLiveTest;
import org.testng.annotations.Test;
/**
* @author Adrian Cole
*/
@Test(groups = "live", testName = "ContainerClientLiveTest")
public class AccountClientLiveTest extends BaseSwiftClientLiveTest {
@Test
public void testGetAccountMetadata() throws Exception {
for (String regionId : swiftContext.getApi().getConfiguredRegions()) {
AccountClient client = swiftContext.getApi().getAccountClientForRegion(regionId);
AccountMetadata account = client.getAccountMetadata();
assertNotNull(account);
assertTrue(account.getContainerCount() >= 0);
assertTrue(account.getBytesUsed() >= 0);
}
}
@Test
public void testListContainers() throws Exception {
for (String regionId : swiftContext.getApi().getConfiguredRegions()) {
AccountClient client = swiftContext.getApi().getAccountClientForRegion(regionId);
Set<ContainerMetadata> response = client.listContainers();
assertNotNull(response);
for (ContainerMetadata container : response) {
assertNotNull(container.getName());
assertTrue(container.getCount() >= 0);
assertTrue(container.getBytes() >= 0);
}
}
}
}

View File

@ -0,0 +1,31 @@
/**
* 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.openstack.swift.v1.features;
import org.jclouds.openstack.swift.v1.internal.BaseSwiftClientExpectTest;
import org.testng.annotations.Test;
/**
*
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "ContainerAsyncClientTest")
public class ContainerClientExpectTest extends BaseSwiftClientExpectTest {
}

View File

@ -0,0 +1,31 @@
/**
* 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.openstack.swift.v1.features;
import org.jclouds.openstack.swift.v1.internal.BaseSwiftClientLiveTest;
import org.testng.annotations.Test;
/**
*
* @author Adrian Cole
*/
@Test(groups = "live", testName = "ContainerClientLiveTest")
public class ContainerClientLiveTest extends BaseSwiftClientLiveTest {
}

View File

@ -0,0 +1,30 @@
/**
* 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.openstack.swift.v1.features;
import org.jclouds.openstack.swift.v1.internal.BaseSwiftClientExpectTest;
import org.testng.annotations.Test;
/**
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "ObjectAsyncClientTest")
public class ObjectClientExpectTest extends BaseSwiftClientExpectTest {
}

View File

@ -0,0 +1,30 @@
/**
* 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.openstack.swift.v1.features;
import org.jclouds.openstack.swift.v1.internal.BaseSwiftClientLiveTest;
import org.testng.annotations.Test;
/**
* @author Adrian Cole
*/
@Test(groups = "live", testName = "ObjectClientLiveTest")
public class ObjectClientLiveTest extends BaseSwiftClientLiveTest {
}

View File

@ -0,0 +1,39 @@
/**
* 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.openstack.swift.v1.internal;
import java.util.Properties;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.openstack.swift.v1.SwiftAsyncClient;
import com.google.common.base.Function;
import com.google.inject.Module;
/**
* Base class for writing KeyStone Rest Client Expect tests
*
* @author Adrian Cole
*/
public class BaseSwiftAsyncClientExpectTest extends BaseSwiftExpectTest<SwiftAsyncClient> {
public SwiftAsyncClient createClient(Function<HttpRequest, HttpResponse> fn, Module module, Properties props) {
return createInjector(fn, module, props).getInstance(SwiftAsyncClient.class);
}
}

View File

@ -0,0 +1,30 @@
/**
* 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.openstack.swift.v1.internal;
import org.jclouds.openstack.swift.v1.SwiftClient;
/**
* Base class for writing KeyStone Rest Client Expect tests
*
* @author Adrian Cole
*/
public class BaseSwiftClientExpectTest extends BaseSwiftExpectTest<SwiftClient> {
}

View File

@ -0,0 +1,74 @@
/**
* 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.openstack.swift.v1.internal;
import java.util.Properties;
import org.jclouds.apis.BaseContextLiveTest;
import org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties;
import org.jclouds.openstack.swift.v1.SwiftApiMetadata;
import org.jclouds.openstack.swift.v1.SwiftAsyncClient;
import org.jclouds.openstack.swift.v1.SwiftClient;
import org.jclouds.rest.RestContext;
import org.testng.annotations.AfterGroups;
import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test;
import com.google.common.reflect.TypeToken;
/**
* Tests behavior of {@code SwiftClient}
*
* @author Adrian Cole
*/
@Test(groups = "live")
public class BaseSwiftClientLiveTest extends BaseContextLiveTest<RestContext<SwiftClient, SwiftAsyncClient>> {
public BaseSwiftClientLiveTest() {
provider = "openstack-swift";
}
protected RestContext<SwiftClient, SwiftAsyncClient> swiftContext;
@BeforeGroups(groups = { "integration", "live" })
@Override
public void setupContext() {
super.setupContext();
swiftContext = context;
}
@Override
protected Properties setupProperties() {
Properties props = super.setupProperties();
setIfTestSystemPropertyPresent(props, KeystoneProperties.CREDENTIAL_TYPE);
return props;
}
@AfterGroups(groups = "live")
protected void tearDown() {
if (swiftContext != null)
swiftContext.close();
}
@Override
protected TypeToken<RestContext<SwiftClient, SwiftAsyncClient>> contextType() {
return SwiftApiMetadata.CONTEXT_TOKEN;
}
}

View File

@ -0,0 +1,52 @@
/**
* 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.openstack.swift.v1.internal;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.openstack.keystone.v2_0.internal.KeystoneFixture;
import org.jclouds.rest.internal.BaseRestClientExpectTest;
/**
* Base class for writing Swift Expect tests
*
* @author Adrian Cole
*/
public class BaseSwiftExpectTest<T> extends BaseRestClientExpectTest<T> {
protected HttpRequest keystoneAuthWithUsernameAndPassword;
protected HttpRequest keystoneAuthWithAccessKeyAndSecretKey;
protected String authToken;
protected HttpResponse responseWithKeystoneAccess;
protected HttpRequest extensionsOfSwiftRequest;
protected HttpResponse extensionsOfSwiftResponse;
protected HttpResponse unmatchedExtensionsOfSwiftResponse;
public BaseSwiftExpectTest() {
provider = "openstack-swift";
keystoneAuthWithUsernameAndPassword = KeystoneFixture.INSTANCE.initialAuthWithUsernameAndPassword(identity,
credential);
keystoneAuthWithAccessKeyAndSecretKey = KeystoneFixture.INSTANCE.initialAuthWithAccessKeyAndSecretKey(identity,
credential);
authToken = KeystoneFixture.INSTANCE.getAuthToken();
responseWithKeystoneAccess = KeystoneFixture.INSTANCE.responseWithAccess();
// now, createContext arg will need tenant prefix
identity = KeystoneFixture.INSTANCE.getTenantName() + ":" + identity;
}
}

View File

@ -0,0 +1,96 @@
/**
* 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.openstack.swift.v1.options;
import static org.jclouds.openstack.swift.v1.options.ListContainersOptions.Builder.limit;
import static org.jclouds.openstack.swift.v1.options.ListContainersOptions.Builder.marker;
import static org.testng.Assert.assertEquals;
import java.util.Collections;
import org.jclouds.http.options.HttpRequestOptions;
import org.testng.annotations.Test;
/**
* Tests possible uses of ListContainerOptions and ListContainerOptions.Builder.*
*
* @author Adrian Cole
*/
@Test(testName = "ListContainersOptionsTest")
public class ListContainersOptionsTest {
@Test
public void testAssignability() {
assert HttpRequestOptions.class.isAssignableFrom(ListContainersOptions.class);
assert !String.class.isAssignableFrom(ListContainersOptions.class);
}
@Test
public void testNoOptionsQueryString() {
HttpRequestOptions options = new ListContainersOptions();
assertEquals(options.buildQueryParameters().size(), 0);
}
@Test
public void testMarker() {
ListContainersOptions options = new ListContainersOptions();
options.marker("test");
assertEquals(options.buildQueryParameters().get("marker"), Collections.singletonList("test"));
}
@Test
public void testNullMarker() {
ListContainersOptions options = new ListContainersOptions();
assertEquals(options.buildQueryParameters().get("marker"), Collections.EMPTY_LIST);
}
@Test
public void testMarkerStatic() {
ListContainersOptions options = marker("test");
assertEquals(options.buildQueryParameters().get("marker"), Collections.singletonList("test"));
}
@Test(expectedExceptions = NullPointerException.class)
public void testMarkerNPE() {
marker(null);
}
@Test
public void testLimit() {
ListContainersOptions options = new ListContainersOptions();
options.limit(1000);
assertEquals(options.buildQueryParameters().get("limit"), Collections.singletonList("1000"));
}
@Test
public void testNullLimit() {
ListContainersOptions options = new ListContainersOptions();
assertEquals(options.buildQueryParameters().get("limit"), Collections.EMPTY_LIST);
}
@Test
public void testLimitStatic() {
ListContainersOptions options = limit(1000);
assertEquals(options.buildQueryParameters().get("limit"), Collections.singletonList("1000"));
}
@Test(expectedExceptions = IllegalStateException.class)
public void testLimitNegative() {
limit(-1);
}
}

View File

@ -0,0 +1,59 @@
/**
* 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.openstack.swift.v1.parse;
import java.util.Set;
import javax.ws.rs.Consumes;
import javax.ws.rs.core.MediaType;
import org.jclouds.json.BaseSetParserTest;
import org.jclouds.openstack.swift.v1.domain.ContainerMetadata;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableSet;
/**
*
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "ParseContainerListTest")
public class ParseContainerListTest extends BaseSetParserTest<ContainerMetadata> {
@Override
public String resource() {
return "/container_list.json";
}
@Override
@Consumes(MediaType.APPLICATION_JSON)
public Set<ContainerMetadata> expected() {
return ImmutableSet
.of(ContainerMetadata.builder()
.name("test_container_1")
.count(2)
.bytes(78)
.build(),
ContainerMetadata.builder()
.name("test_container_2")
.count(1)
.bytes(17)
.build());
}
}

View File

@ -0,0 +1,4 @@
[
{"name":"test_container_1", "count":2, "bytes":78},
{"name":"test_container_2", "count":1, "bytes":17}
]

View File

@ -0,0 +1,51 @@
<?xml version="1.0"?>
<configuration scan="false">
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>target/test-data/jclouds.log</file>
<encoder>
<Pattern>%d %-5p [%c] [%thread] %m%n</Pattern>
</encoder>
</appender>
<appender name="WIREFILE" class="ch.qos.logback.core.FileAppender">
<file>target/test-data/jclouds-wire.log</file>
<encoder>
<Pattern>%d %-5p [%c] [%thread] %m%n</Pattern>
</encoder>
</appender>
<appender name="BLOBSTOREFILE" class="ch.qos.logback.core.FileAppender">
<file>target/test-data/jclouds-blobstore.log</file>
<encoder>
<Pattern>%d %-5p [%c] [%thread] %m%n</Pattern>
</encoder>
</appender>
<root>
<level value="warn" />
</root>
<logger name="org.jclouds">
<level value="DEBUG" />
<appender-ref ref="FILE" />
</logger>
<logger name="jclouds.wire">
<level value="DEBUG" />
<appender-ref ref="WIREFILE" />
</logger>
<logger name="jclouds.headers">
<level value="DEBUG" />
<appender-ref ref="WIREFILE" />
</logger>
<logger name="jclouds.blobstore">
<level value="DEBUG" />
<appender-ref ref="BLOBSTOREFILE" />
</logger>
</configuration>

View File

@ -41,5 +41,6 @@
<module>savvis-symphonyvpdc</module> <module>savvis-symphonyvpdc</module>
<module>dmtf</module> <module>dmtf</module>
<module>carrenza-vcloud-director</module> <module>carrenza-vcloud-director</module>
<module>openstack-swift</module>
</modules> </modules>
</project> </project>