JCLOUDS-702: JCloud ProfitBricks provider implementation

This commit is contained in:
Reijhanniel Jearl Campos 2015-01-10 11:08:09 +08:00 committed by Ignasi Barrera
commit cb45048a68
50 changed files with 3122 additions and 0 deletions

View File

@ -0,0 +1,147 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<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.apache.jclouds.labs</groupId>
<artifactId>jclouds-labs</artifactId>
<version>2.0.0-SNAPSHOT</version>
</parent>
<!-- TODO: when out of labs, switch to org.jclouds.api -->
<artifactId>profitbricks</artifactId>
<name>jclouds ProfitBricks api</name>
<description>jclouds components to access an implementation of ProfitBricks</description>
<packaging>bundle</packaging>
<properties>
<test.profitbricks.endpoint>https://api.profitbricks.com/1.3</test.profitbricks.endpoint>
<test.profitbricks.identity>FIXME</test.profitbricks.identity>
<test.profitbricks.credential>FIXME</test.profitbricks.credential>
<test.profitbricks.api-version>1.3</test.profitbricks.api-version>
<test.profitbricks.template />
<jclouds.osgi.export>org.jclouds.profitbricks*;version="${project.version}"</jclouds.osgi.export>
<jclouds.osgi.import>
org.jclouds.labs*;version="${project.version}",
org.jclouds*;version="${jclouds.version}",
*
</jclouds.osgi.import>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.jclouds</groupId>
<artifactId>jclouds-core</artifactId>
<version>${jclouds.version}</version>
</dependency>
<dependency>
<groupId>org.apache.jclouds</groupId>
<artifactId>jclouds-compute</artifactId>
<version>${jclouds.version}</version>
</dependency>
<dependency>
<groupId>com.google.auto.value</groupId>
<artifactId>auto-value</artifactId>
<scope>provided</scope>
</dependency>
<!-- Test dependencies -->
<dependency>
<groupId>org.apache.jclouds</groupId>
<artifactId>jclouds-core</artifactId>
<version>${jclouds.version}</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.jclouds</groupId>
<artifactId>jclouds-compute</artifactId>
<version>${jclouds.version}</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.jclouds.driver</groupId>
<artifactId>jclouds-sshj</artifactId>
<version>${jclouds.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.squareup.okhttp</groupId>
<artifactId>mockwebserver</artifactId>
<scope>test</scope>
<exclusions>
<!-- Already provided by jclouds-sshj -->
<exclusion>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.jclouds.driver</groupId>
<artifactId>jclouds-slf4j</artifactId>
<version>${jclouds.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<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>
<threadCount>1</threadCount>
<systemPropertyVariables>
<test.profitbricks.endpoint>${test.profitbricks.endpoint}</test.profitbricks.endpoint>
<test.profitbricks.identity>${test.profitbricks.identity}</test.profitbricks.identity>
<test.profitbricks.credential>${test.profitbricks.credential}</test.profitbricks.credential>
<test.profitbricks.api-version>${test.profitbricks.api-version}</test.profitbricks.api-version>
<test.profitbricks.template>${test.profitbricks.template}</test.profitbricks.template>
</systemPropertyVariables>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>

View File

@ -0,0 +1,28 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.profitbricks;
import java.io.Closeable;
import org.jclouds.profitbricks.features.DataCenterApi;
import org.jclouds.rest.annotations.Delegate;
public interface ProfitBricksApi extends Closeable {
@Delegate
DataCenterApi dataCenterApi();
}

View File

@ -0,0 +1,82 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.profitbricks;
import java.net.URI;
import java.util.Properties;
import org.jclouds.profitbricks.config.ProfitBricksHttpApiModule;
import org.jclouds.apis.ApiMetadata;
import org.jclouds.profitbricks.config.ProfitBricksHttpApiModule.ProfitBricksHttpCommandExecutorServiceModule;
import org.jclouds.rest.internal.BaseHttpApiMetadata;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Module;
/**
* Implementation of {@link ApiMetadata} for ProfitBricks API.
*/
public class ProfitBricksApiMetadata extends BaseHttpApiMetadata<ProfitBricksApi> {
public ProfitBricksApiMetadata() {
this(new Builder());
}
@Override
public Builder toBuilder() {
return new Builder().fromApiMetadata(this);
}
protected ProfitBricksApiMetadata(Builder builder) {
super(builder);
}
public static Properties defaultProperties() {
Properties properties = BaseHttpApiMetadata.defaultProperties();
return properties;
}
public static class Builder extends BaseHttpApiMetadata.Builder<ProfitBricksApi, Builder> {
protected Builder() {
id("profitbricks")
.name("ProfitBricks API")
.identityName("API Username")
.credentialName("API Password")
.documentation(URI.create("https://www.profitbricks.com/sites/default/files/profitbricks_api_1_3.pdf"))
.defaultEndpoint("https://api.profitbricks.com/1.3")
.version("1.3")
// .view(ComputeServiceContext.class)
.defaultProperties(ProfitBricksApiMetadata.defaultProperties())
.defaultModules(ImmutableSet.<Class<? extends Module>>of(
ProfitBricksHttpApiModule.class,
ProfitBricksHttpCommandExecutorServiceModule.class
));
}
@Override
public ProfitBricksApiMetadata build() {
return new ProfitBricksApiMetadata(this);
}
@Override
protected Builder self() {
return this;
}
}
}

View File

@ -0,0 +1,66 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.profitbricks;
import com.google.auto.service.AutoService;
import java.net.URI;
import org.jclouds.providers.ProviderMetadata;
import org.jclouds.providers.internal.BaseProviderMetadata;
@AutoService(ProviderMetadata.class)
public class ProfitBricksProviderMetadata extends BaseProviderMetadata {
public ProfitBricksProviderMetadata(Builder builder) {
super(builder);
}
public ProfitBricksProviderMetadata() {
super(builder());
}
@Override
public Builder toBuilder() {
return builder().fromProviderMetadata(this);
}
public static Builder builder() {
return new Builder();
}
public static class Builder extends BaseProviderMetadata.Builder {
protected Builder() {
id("profitbricks")
.name("ProfitBricks Cloud Compute 2.0")
.homepage(URI.create("http://www.profitbricks.com"))
.console(URI.create("https://my.profitbricks.com/dashboard/dcdr2/"))
.linkedServices("profitbricks")
.apiMetadata(new ProfitBricksApiMetadata());
}
@Override
public ProfitBricksProviderMetadata build() {
return new ProfitBricksProviderMetadata(this);
}
@Override
public Builder fromProviderMetadata(ProviderMetadata in) {
super.fromProviderMetadata(in);
return this;
}
}
}

View File

@ -0,0 +1,75 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.profitbricks.binder;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Map;
import javax.ws.rs.core.MediaType;
import org.jclouds.http.HttpRequest;
import org.jclouds.rest.MapBinder;
import com.google.common.base.Strings;
import org.jclouds.io.MutableContentMetadata;
import org.jclouds.io.payloads.BaseMutableContentMetadata;
public abstract class BaseProfitBricksRequestBinder<T> implements MapBinder {
protected final String paramName;
protected BaseProfitBricksRequestBinder(String paramName) {
this.paramName = checkNotNull(paramName, "Initialize 'paramName' in constructor");
}
@Override
public <R extends HttpRequest> R bindToRequest(R request, Map<String, Object> postParams) {
checkNotNull(request, "request");
Object obj = checkNotNull(postParams.get(paramName), "Param '%s' cannot be null.", paramName);
T payload = (T) obj;
return createRequest(request, createPayload(payload));
}
@Override
public <R extends HttpRequest> R bindToRequest(R request, Object input) {
throw new UnsupportedOperationException("Not supported yet.");
}
protected abstract String createPayload(T payload);
protected String formatIfNotEmpty(String pattern, Object param) {
return Strings.isNullOrEmpty(param.toString()) ? "" : String.format(pattern, param);
}
protected String nullableToString(Object object) {
return object == null ? "" : object.toString();
}
protected <R extends HttpRequest> R createRequest(R fromRequest, String payload) {
MutableContentMetadata metadata = new BaseMutableContentMetadata();
metadata.setContentType(MediaType.TEXT_XML);
metadata.setContentLength(Long.valueOf(payload.getBytes().length));
fromRequest.setPayload(payload);
fromRequest.getPayload().setContentMetadata(metadata);
return fromRequest;
}
}

View File

@ -0,0 +1,44 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.profitbricks.binder.datacenter;
import static java.lang.String.format;
import org.jclouds.profitbricks.binder.BaseProfitBricksRequestBinder;
import org.jclouds.profitbricks.domain.DataCenter;
public class CreateDataCenterRequestBinder extends BaseProfitBricksRequestBinder<DataCenter.Request.CreatePayload> {
protected final StringBuilder requestBuilder;
CreateDataCenterRequestBinder() {
super("dataCenter");
this.requestBuilder = new StringBuilder(128);
}
@Override
protected String createPayload(DataCenter.Request.CreatePayload payload) {
requestBuilder.append("<ws:createDataCenter>")
.append("<request>")
.append(format("<dataCenterName>%s</dataCenterName>", payload.name()))
.append(format("<location>%s</location>", payload.location().value()))
.append("</request>")
.append("</ws:createDataCenter>");
return requestBuilder.toString();
}
}

View File

@ -0,0 +1,44 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.profitbricks.binder.datacenter;
import static java.lang.String.format;
import org.jclouds.profitbricks.binder.BaseProfitBricksRequestBinder;
import org.jclouds.profitbricks.domain.DataCenter;
public class UpdateDataCenterRequestBinder extends BaseProfitBricksRequestBinder<DataCenter.Request.UpdatePayload> {
protected final StringBuilder requestBuilder;
UpdateDataCenterRequestBinder() {
super("dataCenter");
this.requestBuilder = new StringBuilder(128);
}
@Override
protected String createPayload(DataCenter.Request.UpdatePayload payload) {
requestBuilder.append("<ws:updateDataCenter>")
.append("<request>")
.append(format("<dataCenterId>%s</dataCenterId>", payload.id()))
.append(format("<dataCenterName>%s</dataCenterName>", payload.name()))
.append("</request>")
.append("</ws:updateDataCenter>");
return requestBuilder.toString();
}
}

View File

@ -0,0 +1,27 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.profitbricks.compute.internal;
/**
* An enumeration of ProfitBricks domain classes containing a property 'ProvisioningState'.
*
* @see ProvisioningStatusPollingPredicate
*/
public enum ProvisioningStatusAware {
DATACENTER;
}

View File

@ -0,0 +1,56 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.profitbricks.compute.internal;
import static com.google.common.base.Preconditions.checkNotNull;
import org.jclouds.profitbricks.ProfitBricksApi;
import org.jclouds.profitbricks.domain.ProvisioningState;
import com.google.common.base.Predicate;
/**
* A custom predicate for waiting until a virtual resource satisfies the given expected status
* <p>
* Performing api requests on a datacenter that is not {@link ProvisioningState#AVAILABLE} is not allowed. On some
* cases, the API user gets blocked from further requests, and will then need to contact tech support for api lock
* release.
*/
public class ProvisioningStatusPollingPredicate implements Predicate<String> {
private final ProfitBricksApi api;
private final ProvisioningStatusAware domain;
private final ProvisioningState expect;
public ProvisioningStatusPollingPredicate(ProfitBricksApi api, ProvisioningStatusAware domain, ProvisioningState expect) {
this.api = checkNotNull(api, "API null");
this.expect = checkNotNull(expect, "Expected state null");
this.domain = checkNotNull(domain, "Domain null");
}
@Override
public boolean apply(String input) {
checkNotNull(input, "Virtual item id can't be null.");
switch (domain) {
case DATACENTER:
return expect == api.dataCenterApi().getDataCenterState(input);
default:
throw new IllegalArgumentException("Unknown domain '" + domain + "'");
}
}
}

View File

@ -0,0 +1,70 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.profitbricks.config;
import org.jclouds.http.HttpCommandExecutorService;
import org.jclouds.profitbricks.ProfitBricksApi;
import org.jclouds.profitbricks.handlers.ProfitBricksHttpErrorHandler;
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.http.config.ConfiguresHttpCommandExecutorService;
import org.jclouds.http.config.SSLModule;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.profitbricks.domain.ServiceFault;
import org.jclouds.profitbricks.http.ResponseStatusFromPayloadHttpCommandExecutorService;
import org.jclouds.profitbricks.http.parser.ServiceFaultResponseHandler;
import org.jclouds.rest.ConfiguresHttpApi;
import org.jclouds.rest.config.HttpApiModule;
import com.google.inject.AbstractModule;
import com.google.inject.Injector;
import com.google.inject.Provides;
import com.google.inject.Scopes;
/**
* Configures the ProfitBricks connection.
*/
@ConfiguresHttpApi
public class ProfitBricksHttpApiModule extends HttpApiModule<ProfitBricksApi> {
@Override
protected void bindErrorHandlers() {
bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(ProfitBricksHttpErrorHandler.class);
bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(ProfitBricksHttpErrorHandler.class);
bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(ProfitBricksHttpErrorHandler.class);
}
@ConfiguresHttpCommandExecutorService
public static class ProfitBricksHttpCommandExecutorServiceModule extends AbstractModule {
@Override
protected void configure() {
install(new SSLModule());
bind(HttpCommandExecutorService.class).to(ResponseStatusFromPayloadHttpCommandExecutorService.class)
.in(Scopes.SINGLETON);
}
@Provides
public ParseSax<ServiceFault> serviceFaultParser(ParseSax.Factory factory, Injector injector) {
return factory.create(injector.getInstance(ServiceFaultResponseHandler.class));
}
}
}

View File

@ -0,0 +1,137 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.profitbricks.domain;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Strings.isNullOrEmpty;
import java.util.regex.Pattern;
import org.jclouds.javax.annotation.Nullable;
import com.google.auto.value.AutoValue;
@AutoValue
public abstract class DataCenter {
public abstract String id();
@Nullable public abstract String name();
public abstract int version();
@Nullable public abstract ProvisioningState state();
@Nullable public abstract Location location();
// @Nullable public abstract List<Server> servers();
// @Nullable public abstract List<Storage> storages();
// @Nullable public abstract List<LoadBalancer> loadBalancers();
public static DataCenter create(String id, String name, int version, ProvisioningState state, Location location) {
return new AutoValue_DataCenter(id, name, version, state, location);
}
public static Builder builder() {
return new Builder();
}
public Builder toBuilder() {
return builder().fromDataCenter(this);
}
public static final class Builder {
private String id;
private String name;
private ProvisioningState state;
private Location location;
private int version;
// private List<Server> servers;
// private List<Storage> storage;
// private List<LoadBalancer> loadBalancer;
public Builder id(String id) {
this.id = id;
return this;
}
public Builder name(String name) {
this.name = name;
return this;
}
public Builder state(ProvisioningState state) {
this.state = state;
return this;
}
public Builder location(Location location) {
this.location = location;
return this;
}
public Builder version(int version) {
this.version = version;
return this;
}
public DataCenter build() {
return DataCenter.create(id, name, version, state, location);
}
public Builder fromDataCenter(DataCenter in) {
return this.id(in.id()).name(in.name()).version(in.version()).state(in.state()).location(in.location());
}
}
public static final class Request {
@AutoValue
public abstract static class CreatePayload {
public abstract String name();
public abstract Location location();
public static CreatePayload create(String name, Location location) {
checkInvalidChars(name);
return new AutoValue_DataCenter_Request_CreatePayload(name, location);
}
}
@AutoValue
public abstract static class UpdatePayload {
public abstract String id();
public abstract String name();
public static UpdatePayload create(String id, String name) {
checkInvalidChars(name);
return new AutoValue_DataCenter_Request_UpdatePayload(id, name);
}
}
private static final Pattern INVALID_CHARS = Pattern.compile("^.*[@/\\|'`^].*$");
private static void checkInvalidChars(String name){
checkArgument(!isNullOrEmpty(name), "Name is required.");
checkArgument(!INVALID_CHARS.matcher(name).matches(), "Name must not contain any of: @ / \\ | ' ` ^");
}
}
}

View File

@ -0,0 +1,50 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.profitbricks.domain;
public enum Location {
DE_FKB("de/fkb"),
DE_FRA("de/fra"),
US_LAS("us/las"),
UNRECOGNIZED("unknown");
private final String id;
Location(String id) {
this.id = id;
}
public String value() {
return id;
}
public static Location fromValue(String v) {
try {
return valueOf(v);
} catch (IllegalArgumentException ex) {
return UNRECOGNIZED;
}
}
public static Location fromId(String id) {
for (Location location : values())
if (location.id.equals(id))
return location;
return UNRECOGNIZED;
}
}

View File

@ -0,0 +1,30 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.profitbricks.domain;
public enum ProvisioningState {
INACTIVE, INPROCESS, AVAILABLE, DELETED, ERROR, UNRECOGNIZED;
public static ProvisioningState fromValue(String value) {
try {
return valueOf(value);
} catch (IllegalArgumentException e) {
return UNRECOGNIZED;
}
}
}

View File

@ -0,0 +1,95 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.profitbricks.domain;
import com.google.auto.value.AutoValue;
@AutoValue
public abstract class ServiceFault {
public enum FaultCode {
BAD_REQUEST,
UNEXPECTED,
UNAUTHORIZED,
RESOURCE_NOT_FOUND,
RESOURCE_DELETED,
PROVISIONING_IN_PROCESS,
PROVISIONING_NO_CHANGES,
OVER_LIMIT_SETTING,
SERVER_EXCEED_CAPACITY,
SERVICE_UNAVAILABLE,
UNRECOGNIZED;
public static FaultCode fromValue(String v) {
try {
return valueOf(v);
} catch (IllegalArgumentException ex) {
return UNRECOGNIZED;
}
}
}
public abstract FaultCode faultCode();
public abstract int httpCode();
public abstract String message();
public abstract int requestId();
public static ServiceFault create(FaultCode faultCode, int httpCode, String message, int requestId) {
return new AutoValue_ServiceFault(faultCode, httpCode, message, requestId);
}
public static Builder builder() {
return new Builder();
}
public static final class Builder {
private FaultCode faultCode;
private int httpCode;
private String message;
private int requestId;
public Builder faultCode(FaultCode code) {
this.faultCode = code;
return this;
}
public Builder httpCode(int httpCode) {
this.httpCode = httpCode;
return this;
}
public Builder message(String message) {
this.message = message;
return this;
}
public Builder requestId(int requestId) {
this.requestId = requestId;
return this;
}
public ServiceFault build() {
return create(faultCode, httpCode, message, requestId);
}
}
}

View File

@ -0,0 +1,134 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.profitbricks.features;
import java.util.List;
import javax.inject.Named;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.jclouds.Fallbacks;
import org.jclouds.http.filters.BasicAuthentication;
import org.jclouds.profitbricks.binder.datacenter.CreateDataCenterRequestBinder;
import org.jclouds.profitbricks.binder.datacenter.UpdateDataCenterRequestBinder;
import org.jclouds.profitbricks.domain.DataCenter;
import org.jclouds.profitbricks.domain.ProvisioningState;
import org.jclouds.profitbricks.http.filters.ProfitBricksSoapMessageEnvelope;
import org.jclouds.profitbricks.http.parser.datacenter.DataCenterInfoResponseHandler;
import org.jclouds.profitbricks.http.parser.datacenter.DataCenterListResponseHandler;
import org.jclouds.profitbricks.http.parser.state.GetProvisioningStateResponseHandler;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.MapBinder;
import org.jclouds.rest.annotations.Payload;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.XMLResponseParser;
@RequestFilters({BasicAuthentication.class, ProfitBricksSoapMessageEnvelope.class})
@Consumes(MediaType.TEXT_XML)
@Produces(MediaType.TEXT_XML)
public interface DataCenterApi {
/**
* @return Returns a list of all Virtual Data Centers created by the user, including ID, name and version number.
*/
@POST
@Named("datacenter:getall")
@Payload("<ws:getAllDataCenters/>")
@XMLResponseParser(DataCenterListResponseHandler.class)
@Fallback(Fallbacks.EmptyListOnNotFoundOr404.class)
List<DataCenter> getAllDataCenters();
/**
* @param identifier Data Center identifier
* @return Returns information about an existing virtual data center's state and configuration or <code>null</code>
* if it doesn't exist.
*/
@POST
@Named("datacenter:get")
@Payload("<ws:getDataCenter><dataCenterId>{id}</dataCenterId></ws:getDataCenter>")
@XMLResponseParser(DataCenterInfoResponseHandler.class)
@Fallback(Fallbacks.NullOnNotFoundOr404.class)
DataCenter getDataCenter(@PayloadParam("id") String identifier);
/**
* This is a lightweight function for polling the current provisioning state of the Virtual Data Center. It is
* recommended to use this function for large Virtual Data Centers to query request results.
* <p>
* @param identifier Data Center identifier
*/
@POST
@Named("datacenter:getstate")
@Payload("<ws:getDataCenterState><dataCenterId>{id}</dataCenterId></ws:getDataCenterState>")
@XMLResponseParser(GetProvisioningStateResponseHandler.class)
ProvisioningState getDataCenterState(@PayloadParam("id") String identifier);
/**
* Creates and saves a new, empty Virtual Data Center. Returns its identifier for further reference.
* <p>
* <b>Note: </b>Data center names cannot start with or contain (@, /, \, |, , )
* <p>
* @param createRequest VDC payload containing dataCenterName, region
* @return Response containing requestId, dataCenterId, version, and location
*/
@POST
@Named("datacenter:create")
@MapBinder(CreateDataCenterRequestBinder.class)
@XMLResponseParser(DataCenterInfoResponseHandler.class)
DataCenter createDataCenter(@PayloadParam("dataCenter") DataCenter.Request.CreatePayload createRequest);
/**
* Updates the information associated to an existing Virtual Data Center.
* <p>
* @param updateRequest VDC payload containing dataCenterId, and name
* @return Response containing requestId, dataCenterId, version
*/
@POST
@Named("datacenter:update")
@MapBinder(UpdateDataCenterRequestBinder.class)
@XMLResponseParser(DataCenterInfoResponseHandler.class)
DataCenter updateDataCenter(@PayloadParam("dataCenter") DataCenter.Request.UpdatePayload updateRequest);
/**
* Removes all components from an existing Virtual Data Center.
* <p>
* @param identifier Identifier of the virtual data center
* @return Response containing requestId, dataCenterId, version
*/
@POST
@Named("datacenter:clear")
@Payload("<ws:clearDataCenter><dataCenterId>{id}</dataCenterId></ws:clearDataCenter>")
@XMLResponseParser(DataCenterInfoResponseHandler.class)
DataCenter clearDataCenter(@PayloadParam("id") String identifier);
/**
* Deletes an Virtual Data Center. If a previous request on the target data center is still in progress, the data
* center is going to be deleted after this request has been completed. Once a Data Center has been deleted, no
* further request can be performed on it.
* <p>
* @param identifier Identifier of the virtual data center
* @return Returns a boolean indicating whether delete operation was made
*/
@POST
@Named("datacenter:delete")
@Payload("<ws:deleteDataCenter><dataCenterId>{id}</dataCenterId></ws:deleteDataCenter>")
@Fallback(Fallbacks.FalseOnNotFoundOr404.class)
boolean deleteDataCenter(@PayloadParam("id") String identifier);
}

View File

@ -0,0 +1,70 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.profitbricks.handlers;
import static org.jclouds.util.Closeables2.closeQuietly;
import javax.inject.Singleton;
import org.jclouds.http.HttpCommand;
import org.jclouds.http.HttpErrorHandler;
import org.jclouds.http.HttpResponse;
import org.jclouds.rest.AuthorizationException;
import org.jclouds.rest.InsufficientResourcesException;
import org.jclouds.rest.ResourceNotFoundException;
/**
* Parse ProfitBricks API errors and set the appropriate exception.
*
* @see org.jclouds.profitbricks.http.ResponseStatusFromPayloadHttpCommandExecutorService
*
*/
@Singleton
public class ProfitBricksHttpErrorHandler implements HttpErrorHandler {
@Override
public void handleError(final HttpCommand command, final HttpResponse response) {
Exception exception = null;
try {
switch (response.getStatusCode()) {
case 400:
case 405:
exception = new IllegalArgumentException(response.getMessage(), exception);
break;
case 401:
exception = new AuthorizationException(response.getMessage(), exception);
break;
case 402:
case 409:
exception = new IllegalStateException(response.getMessage(), exception);
break;
case 404:
case 410:
if (!command.getCurrentRequest().getMethod().equals("DELETE"))
exception = new ResourceNotFoundException(response.getMessage(), exception);
break;
case 413:
case 503:
exception = new InsufficientResourcesException(response.getMessage(), exception);
break;
}
} finally {
closeQuietly(response.getPayload());
command.setException(exception);
}
}
}

View File

@ -0,0 +1,122 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.profitbricks.http;
import static org.jclouds.util.Closeables2.closeQuietly;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.Proxy;
import java.net.URI;
import javax.inject.Named;
import javax.inject.Singleton;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpUtils;
import org.jclouds.http.IOExceptionRetryHandler;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.http.handlers.DelegatingErrorHandler;
import org.jclouds.http.handlers.DelegatingRetryHandler;
import org.jclouds.http.internal.HttpWire;
import org.jclouds.http.internal.JavaUrlHttpCommandExecutorService;
import org.jclouds.io.ContentMetadataCodec;
import org.jclouds.io.Payload;
import org.jclouds.io.Payloads;
import org.jclouds.profitbricks.domain.ServiceFault;
import com.google.common.base.Function;
import com.google.common.base.Supplier;
import com.google.common.io.ByteStreams;
import com.google.inject.Inject;
/**
* Custom implementation of the HTTP driver to read actual http status and message from SOAP Fault.
* <br/>
* ProfitBricks API errors are always returned with 500 HTTP code. This class parses and reads the SOAP response to map the actual http code
* and message
*/
@Singleton
public class ResponseStatusFromPayloadHttpCommandExecutorService extends JavaUrlHttpCommandExecutorService {
private final ParseSax<ServiceFault> faultHandler;
@Inject
ResponseStatusFromPayloadHttpCommandExecutorService(HttpUtils utils, ContentMetadataCodec contentMetadataCodec,
DelegatingRetryHandler retryHandler, IOExceptionRetryHandler ioRetryHandler,
DelegatingErrorHandler errorHandler, HttpWire wire, @Named("untrusted") HostnameVerifier verifier,
@Named("untrusted") Supplier<SSLContext> untrustedSSLContextProvider, Function<URI, Proxy> proxyForURI,
ParseSax<ServiceFault> faultHandler) {
super(utils, contentMetadataCodec, retryHandler, ioRetryHandler, errorHandler, wire, verifier, untrustedSSLContextProvider, proxyForURI);
this.faultHandler = faultHandler;
}
@Override
protected HttpResponse invoke(HttpURLConnection connection) throws IOException, InterruptedException {
HttpResponse originalResponse = super.invoke(connection);
HttpResponse.Builder<?> responseBuilder = originalResponse.toBuilder();
if (hasPayload(originalResponse) && hasServerError(originalResponse)) {
// As we need to read the response body to determine if there are errors, but we may need to process the body
// again later in the response parsers if everything is OK, we buffer the body into an InputStream we can reset
InputStream in = null;
InputStream originalInputStream = originalResponse.getPayload().openStream();
if (originalInputStream instanceof ByteArrayInputStream)
in = originalInputStream;
else
try {
in = new ByteArrayInputStream(ByteStreams.toByteArray(originalInputStream));
} finally {
closeQuietly(originalInputStream);
}
try {
ServiceFault fault = faultHandler.parse(in);
if (fault != null)
responseBuilder
.statusCode(fault.httpCode())
.message(fault.message());
} catch (Exception ex) {
// ignore
} finally {
// Reset the input stream and set the payload, so it can be read again
// by the response and error parsers
if (in != null) {
in.reset();
Payload payload = Payloads.newInputStreamPayload(in);
contentMetadataCodec.fromHeaders(payload.getContentMetadata(), originalResponse.getHeaders());
responseBuilder.payload(payload);
}
}
}
return responseBuilder.build();
}
private static boolean hasServerError(final HttpResponse response) {
return response.getStatusCode() >= 500;
}
private static boolean hasPayload(final HttpResponse response) {
return response.getPayload() != null && response.getPayload().getRawContent() != null;
}
}

View File

@ -0,0 +1,59 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.profitbricks.http.filters;
import static com.google.common.base.Preconditions.checkNotNull;
import org.jclouds.http.HttpException;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpRequestFilter;
import org.jclouds.http.HttpUtils;
import org.jclouds.io.ContentMetadata;
import org.jclouds.io.Payload;
import org.jclouds.io.Payloads;
/**
* Filters {@link HttpRequest} request and wraps request body into SOAP envelope.
*/
public class ProfitBricksSoapMessageEnvelope implements HttpRequestFilter {
private final String SOAP_PREFIX
= "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:ws=\"http://ws.api.profitbricks.com/\">"
+ "<soapenv:Header/>"
+ "<soapenv:Body>";
private final String SOAP_SUFFIX = "</soapenv:Body></soapenv:Envelope>";
@Override
public HttpRequest filter(HttpRequest request) throws HttpException {
checkNotNull(request.getPayload(), "HTTP Request must contain payload message.");
return createSoapRequest(request);
}
private HttpRequest createSoapRequest(HttpRequest request) {
Payload oldPayload = request.getPayload();
ContentMetadata oldMetadata = oldPayload.getContentMetadata();
String body = SOAP_PREFIX.concat(oldPayload.getRawContent().toString()).concat(SOAP_SUFFIX);
Payload newPayload = Payloads.newStringPayload(body);
HttpUtils.copy(oldMetadata, newPayload.getContentMetadata());
newPayload.getContentMetadata().setContentLength(Long.valueOf(body.length())); // resize, add prefix/suffix length
return request.toBuilder().payload(newPayload).build();
}
}

View File

@ -0,0 +1,69 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.profitbricks.http.parser;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Date;
import org.jclouds.date.DateCodec;
import org.jclouds.date.DateCodecFactory;
import org.jclouds.http.functions.ParseSax;
import org.xml.sax.SAXException;
public abstract class BaseProfitBricksResponseHandler<T> extends ParseSax.HandlerForGeneratedRequestWithResult<T> {
protected final DateCodec dateCodec;
private final StringBuilder strBuilder;
public BaseProfitBricksResponseHandler(DateCodecFactory dateCodec) {
this.dateCodec = checkNotNull(checkNotNull(dateCodec, "dateCodecFactory null").iso8601(), "iso8601 date codec null");
this.strBuilder = new StringBuilder();
}
@Override
public void characters(char ch[], int start, int length) {
strBuilder.append(ch, start, length);
}
protected final Date textToIso8601Date() {
return dateCodec.toDate(textToStringValue());
}
protected String textToStringValue() {
return strBuilder.toString().trim();
}
protected int textToIntValue() {
return Integer.parseInt(textToStringValue());
}
protected boolean textToBooleanValue() {
return Boolean.parseBoolean(textToStringValue());
}
protected void clearTextBuffer() {
strBuilder.setLength(0);
}
@Override
public abstract void endElement(String uri, String localName, String qName) throws SAXException;
protected abstract void setPropertyOnEndTag(String qName);
}

View File

@ -0,0 +1,63 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.profitbricks.http.parser;
import org.jclouds.date.DateCodecFactory;
import org.jclouds.profitbricks.domain.ServiceFault;
import org.xml.sax.SAXException;
import com.google.inject.Inject;
public class ServiceFaultResponseHandler extends BaseProfitBricksResponseHandler<ServiceFault> {
private final ServiceFault.Builder builder;
private boolean done = false;
@Inject
ServiceFaultResponseHandler(DateCodecFactory dateCodec) {
super(dateCodec);
this.builder = ServiceFault.builder();
}
@Override
protected void setPropertyOnEndTag(String qName) {
if ("faultCode".equals(qName))
builder.faultCode(ServiceFault.FaultCode.fromValue(textToStringValue()));
else if ("httpCode".equals(qName))
builder.httpCode(textToIntValue());
else if ("message".equals(qName))
builder.message(textToStringValue());
else if ("requestId".equals(qName))
builder.requestId(textToIntValue());
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
if (done)
return;
setPropertyOnEndTag(qName);
if ("detail".equals(qName))
done = true;
clearTextBuffer();
}
@Override
public ServiceFault getResult() {
return builder.build();
}
}

View File

@ -0,0 +1,43 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.profitbricks.http.parser.datacenter;
import javax.inject.Inject;
import org.jclouds.date.DateCodecFactory;
import org.jclouds.profitbricks.domain.DataCenter;
import org.jclouds.profitbricks.http.parser.BaseProfitBricksResponseHandler;
public abstract class BaseDataCenterResponseHandler<T> extends BaseProfitBricksResponseHandler<T> {
protected DataCenter.Builder builder;
@Inject
BaseDataCenterResponseHandler(DateCodecFactory dateCodecFactory) {
super(dateCodecFactory);
this.builder = DataCenter.builder();
}
@Override
protected void setPropertyOnEndTag(String qName) {
if ("dataCenterId".equals(qName))
builder.id(textToStringValue());
else if ("dataCenterVersion".equals(qName))
builder.version(textToIntValue());
}
}

View File

@ -0,0 +1,62 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.profitbricks.http.parser.datacenter;
import org.jclouds.date.DateCodecFactory;
import org.jclouds.profitbricks.domain.DataCenter;
import org.jclouds.profitbricks.domain.Location;
import org.jclouds.profitbricks.domain.ProvisioningState;
import org.xml.sax.SAXException;
import com.google.inject.Inject;
public class DataCenterInfoResponseHandler extends BaseDataCenterResponseHandler<DataCenter> {
private boolean done = false;
@Inject
DataCenterInfoResponseHandler(DateCodecFactory dateCodecFactory) {
super(dateCodecFactory);
}
@Override
protected void setPropertyOnEndTag(String qName) {
super.setPropertyOnEndTag(qName);
if ("dataCenterName".equals(qName))
builder.name(textToStringValue());
else if ("location".equals(qName))
builder.location(Location.fromId(textToStringValue()));
else if ("provisioningState".equals(qName))
builder.state(ProvisioningState.fromValue(textToStringValue()));
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
if (done)
return;
setPropertyOnEndTag(qName);
if ("return".equals(qName))
done = true;
clearTextBuffer();
}
@Override
public DataCenter getResult() {
return builder.build();
}
}

View File

@ -0,0 +1,65 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.profitbricks.http.parser.datacenter;
import java.util.List;
import org.jclouds.date.DateCodecFactory;
import org.jclouds.profitbricks.domain.DataCenter;
import org.jclouds.profitbricks.domain.Location;
import org.jclouds.profitbricks.domain.ProvisioningState;
import org.xml.sax.SAXException;
import com.google.common.collect.Lists;
import com.google.inject.Inject;
public class DataCenterListResponseHandler extends BaseDataCenterResponseHandler<List<DataCenter>> {
private final List<DataCenter> dataCenters;
@Inject
DataCenterListResponseHandler(DateCodecFactory dateCodec) {
super(dateCodec);
this.dataCenters = Lists.newArrayList();
}
@Override
public List<DataCenter> getResult() {
return dataCenters;
}
@Override
protected void setPropertyOnEndTag(String qName) {
super.setPropertyOnEndTag(qName);
if ("dataCenterName".equals(qName))
builder.name(textToStringValue());
else if ("location".equals(qName))
builder.location(Location.fromValue(textToStringValue()));
else if ("provisioningState".equals(qName))
builder.state(ProvisioningState.fromValue(textToStringValue()));
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
setPropertyOnEndTag(qName);
if ("return".equals(qName)) {
dataCenters.add(builder.build());
builder = DataCenter.builder();
}
clearTextBuffer();
}
}

View File

@ -0,0 +1,52 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.profitbricks.http.parser.state;
import org.jclouds.date.DateCodecFactory;
import org.jclouds.profitbricks.domain.ProvisioningState;
import org.jclouds.profitbricks.http.parser.BaseProfitBricksResponseHandler;
import org.xml.sax.SAXException;
import com.google.inject.Inject;
public class GetProvisioningStateResponseHandler extends BaseProfitBricksResponseHandler<ProvisioningState> {
private ProvisioningState state = ProvisioningState.UNRECOGNIZED;
@Inject
GetProvisioningStateResponseHandler(DateCodecFactory dateCodec) {
super(dateCodec);
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
setPropertyOnEndTag(qName);
clearTextBuffer();
}
@Override
protected void setPropertyOnEndTag(String qName) {
if ("return".equals(qName))
state = ProvisioningState.fromValue(textToStringValue());
}
@Override
public ProvisioningState getResult() {
return state;
}
}

View File

@ -0,0 +1,45 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.profitbricks;
import java.util.concurrent.TimeUnit;
import org.jclouds.apis.BaseApiLiveTest;
import org.jclouds.profitbricks.compute.internal.ProvisioningStatusAware;
import org.jclouds.profitbricks.compute.internal.ProvisioningStatusPollingPredicate;
import org.jclouds.profitbricks.domain.ProvisioningState;
import org.jclouds.util.Predicates2;
import com.google.common.base.Predicate;
public abstract class BaseProfitBricksLiveTest extends BaseApiLiveTest<ProfitBricksApi> {
protected Predicate<String> dcWaitingPredicate;
public BaseProfitBricksLiveTest() {
provider = "profitbricks";
}
@Override
protected void initialize() {
super.initialize();
this.dcWaitingPredicate = Predicates2.retry(
new ProvisioningStatusPollingPredicate(api, ProvisioningStatusAware.DATACENTER, ProvisioningState.AVAILABLE),
2l * 60l, 2l, TimeUnit.SECONDS);
}
}

View File

@ -0,0 +1,29 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.profitbricks;
import org.jclouds.providers.internal.BaseProviderMetadataTest;
import org.testng.annotations.Test;
@Test(groups = "unit", testName = "ProfitBricksProviderMetadataTest")
public class ProfitBricksProviderMetadataTest extends BaseProviderMetadataTest {
public ProfitBricksProviderMetadataTest() {
super(new ProfitBricksProviderMetadata(), new ProfitBricksApiMetadata());
}
}

View File

@ -0,0 +1,47 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.profitbricks.binder.datacenter;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import org.jclouds.profitbricks.domain.DataCenter;
import org.jclouds.profitbricks.domain.Location;
import org.testng.annotations.Test;
@Test(groups = "unit", testName = "CreateDataCenterRequestBinderTest")
public class CreateDataCenterRequestBinderTest {
@Test
public void testCreatePayload() {
CreateDataCenterRequestBinder binder = new CreateDataCenterRequestBinder();
DataCenter.Request.CreatePayload payload = DataCenter.Request.CreatePayload.create("JClouds-DC", Location.DE_FKB);
String actual = binder.createPayload(payload);
assertNotNull(actual, "Binder returned null payload");
assertEquals(expectedPayload, actual);
}
private final String expectedPayload
= (" <ws:createDataCenter>\n"
+ " <request>\n"
+ " <dataCenterName>JClouds-DC</dataCenterName>\n"
+ " <location>de/fkb</location>\n"
+ " </request>\n"
+ " </ws:createDataCenter>\n").replaceAll("\\s+", "");
}

View File

@ -0,0 +1,46 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.profitbricks.binder.datacenter;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import org.jclouds.profitbricks.domain.DataCenter;
import org.testng.annotations.Test;
@Test(groups = "unit", testName = "UpdateDataCenterRequestBinderTest")
public class UpdateDataCenterRequestBinderTest {
@Test
public void testCreatePayload() {
UpdateDataCenterRequestBinder binder = new UpdateDataCenterRequestBinder();
DataCenter.Request.UpdatePayload payload = DataCenter.Request.UpdatePayload.create("aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee", "Apache-DC");
String actual = binder.createPayload(payload);
assertNotNull(actual, "Binder returned null payload");
assertEquals(expectedPayload, actual);
}
private final String expectedPayload
= (" <ws:updateDataCenter>\n"
+ " <request>\n"
+ " <dataCenterId>aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee</dataCenterId>\n"
+ " <dataCenterName>Apache-DC</dataCenterName>\n"
+ " </request>\n"
+ " </ws:updateDataCenter>").replaceAll("\\s+", "");
}

View File

@ -0,0 +1,74 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.profitbricks.compute.internal;
import static org.jclouds.profitbricks.internal.BaseProfitBricksMockTest.mockWebServer;
import static org.testng.Assert.assertEquals;
import java.util.concurrent.TimeUnit;
import org.jclouds.profitbricks.ProfitBricksApi;
import org.jclouds.profitbricks.domain.ProvisioningState;
import org.jclouds.profitbricks.internal.BaseProfitBricksMockTest;
import org.jclouds.util.Predicates2;
import org.testng.annotations.Test;
import com.google.common.base.Predicate;
import com.squareup.okhttp.mockwebserver.MockResponse;
import com.squareup.okhttp.mockwebserver.MockWebServer;
/**
* Tests for the {@link ProvisioningStatusPollingPredicate} class.
* <p>
*/
@Test(groups = "unit", testName = "ProvisioningStatusPollingPredicateTest")
public class ProvisioningStatusPollingPredicateTest extends BaseProfitBricksMockTest {
@Test
public void testPredicate() throws Exception {
MockWebServer server = mockWebServer();
byte[] payloadInProcess = payloadFromResource("/datacenter/datacenter-state-inprocess.xml");
byte[] payloadAvailable = payloadFromResource("/datacenter/datacenter-state.xml");
// wait 3 times
server.enqueue(new MockResponse().setBody(payloadInProcess));
server.enqueue(new MockResponse().setBody(payloadInProcess));
server.enqueue(new MockResponse().setBody(payloadInProcess));
server.enqueue(new MockResponse().setBody(payloadAvailable));
server.enqueue(new MockResponse().setBody(payloadAvailable));
ProfitBricksApi pbApi = api(server.getUrl(rootUrl));
Predicate<String> waitUntilAvailable = Predicates2.retry(
new ProvisioningStatusPollingPredicate(pbApi, ProvisioningStatusAware.DATACENTER, ProvisioningState.AVAILABLE),
30l, 1l, TimeUnit.SECONDS);
String id = "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee";
try {
waitUntilAvailable.apply(id);
ProvisioningState finalState = pbApi.dataCenterApi().getDataCenterState(id);
assertRequestHasCommonProperties(server.takeRequest());
assertEquals(finalState, ProvisioningState.AVAILABLE);
} finally {
pbApi.close();
server.shutdown();
}
}
}

View File

@ -0,0 +1,127 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.profitbricks.features;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertNull;
import java.util.List;
import org.jclouds.profitbricks.BaseProfitBricksLiveTest;
import org.jclouds.profitbricks.domain.DataCenter;
import org.jclouds.profitbricks.domain.Location;
import org.jclouds.profitbricks.domain.ProvisioningState;
import static org.testng.Assert.assertTrue;
import org.testng.annotations.AfterClass;
import org.testng.annotations.Test;
@Test(groups = "live", testName = "DataCenterApiLiveTest", singleThreaded = true)
public class DataCenterApiLiveTest extends BaseProfitBricksLiveTest {
private String dcId;
@Test
public void testCreateDataCenter() {
DataCenter dc = api.dataCenterApi().createDataCenter(
DataCenter.Request.CreatePayload.create("JClouds", Location.DE_FKB)
);
assertNotNull(dc);
dcWaitingPredicate.apply(dc.id());
dcId = dc.id();
}
@Test(dependsOnMethods = "testCreateDataCenter")
public void testGetDataCenter() {
assertNotNull(dcId, "No available datacenter found.");
DataCenter dataCenter = api.dataCenterApi().getDataCenter(dcId);
assertNotNull(dataCenter);
assertEquals(dataCenter.id(), dcId);
}
@Test(dependsOnMethods = "testCreateDataCenter")
public void testGetAllDataCenters() {
List<DataCenter> dataCenters = api.dataCenterApi().getAllDataCenters();
assertNotNull(dataCenters);
assertFalse(dataCenters.isEmpty(), "No datacenter found.");
}
@Test(dependsOnMethods = "testCreateDataCenter")
public void testGetDataCenterState() {
assertNotNull(dcId, "No available datacenter found.");
ProvisioningState state = api.dataCenterApi().getDataCenterState(dcId);
assertNotNull(state);
}
@Test(dependsOnMethods = "testGetDataCenter")
public void testUpdateDataCenter() {
assertNotNull(dcId, "No available datacenter found.");
final String newName = "Apache";
DataCenter dataCenter = api.dataCenterApi().updateDataCenter(
DataCenter.Request.UpdatePayload.create(dcId, newName)
);
assertNotNull(dataCenter);
dcWaitingPredicate.apply(dcId);
DataCenter fetchedDc = api.dataCenterApi().getDataCenter(dcId);
assertNotNull(fetchedDc);
assertEquals(newName, fetchedDc.name());
}
@Test(dependsOnMethods = "testUpdateDataCenter")
public void testClearDataCenter() {
DataCenter dataCenter = api.dataCenterApi().clearDataCenter(dcId);
assertNotNull(dataCenter);
}
@Test
public void testGetNonExistingDataCenter() {
DataCenter dataCenter = api.dataCenterApi().getDataCenter("random-non-existing-id");
assertNull(dataCenter);
}
@Test
public void testDeleteNonExistingDataCenterMustReturnFalse() {
boolean result = api.dataCenterApi().deleteDataCenter("random-non-existing-id");
assertFalse(result);
}
@AfterClass(alwaysRun = true)
public void testDeleteDataCenter() {
if (dcId != null) {
boolean result = api.dataCenterApi().deleteDataCenter(dcId);
assertTrue(result, "Created test data center was not deleted.");
}
}
}

View File

@ -0,0 +1,255 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.profitbricks.features;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;
import java.util.List;
import org.jclouds.profitbricks.ProfitBricksApi;
import org.jclouds.profitbricks.domain.DataCenter;
import org.jclouds.profitbricks.domain.Location;
import org.jclouds.profitbricks.domain.ProvisioningState;
import org.jclouds.profitbricks.internal.BaseProfitBricksMockTest;
import org.testng.annotations.Test;
import com.squareup.okhttp.mockwebserver.MockResponse;
import com.squareup.okhttp.mockwebserver.MockWebServer;
/**
* Mock tests for the {@link org.jclouds.profitbricks.features.DataCenterApi} class
*/
@Test(groups = "unit", testName = "DataCenterApiMockTest")
public class DataCenterApiMockTest extends BaseProfitBricksMockTest {
@Test
public void testGetAllDataCenters() throws Exception {
MockWebServer server = mockWebServer();
server.enqueue(new MockResponse().setBody(payloadFromResource("/datacenter/datacenters.xml")));
ProfitBricksApi pbApi = api(server.getUrl(rootUrl));
DataCenterApi api = pbApi.dataCenterApi();
try {
List<DataCenter> dataCenters = api.getAllDataCenters();
assertRequestHasCommonProperties(server.takeRequest());
assertNotNull(dataCenters);
assertEquals(dataCenters.size(), 2);
} finally {
pbApi.close();
server.shutdown();
}
}
@Test
public void testGetAllDataCentersReturning404() throws Exception {
MockWebServer server = mockWebServer();
server.enqueue(new MockResponse().setResponseCode(404));
ProfitBricksApi pbApi = api(server.getUrl(rootUrl));
DataCenterApi api = pbApi.dataCenterApi();
try {
List<DataCenter> dataCenters = api.getAllDataCenters();
assertRequestHasCommonProperties(server.takeRequest());
assertTrue(dataCenters.isEmpty());
} finally {
pbApi.close();
server.shutdown();
}
}
@Test
public void testGetDataCenter() throws Exception {
MockWebServer server = mockWebServer();
server.enqueue(new MockResponse().setBody(payloadFromResource("/datacenter/datacenter.xml")));
ProfitBricksApi pbApi = api(server.getUrl(rootUrl));
DataCenterApi api = pbApi.dataCenterApi();
String id = "12345678-abcd-efgh-ijkl-987654321000";
try {
DataCenter dataCenter = api.getDataCenter(id);
assertRequestHasCommonProperties(server.takeRequest());
assertNotNull(dataCenter);
assertEquals(dataCenter.id(), id);
} finally {
pbApi.close();
server.shutdown();
}
}
@Test
public void testGetNonExistingDataCenter() throws Exception {
MockWebServer server = mockWebServer();
server.enqueue(new MockResponse().setResponseCode(500).setBody(payloadFromResource("/fault-404.xml")));
ProfitBricksApi pbApi = api(server.getUrl(rootUrl));
DataCenterApi api = pbApi.dataCenterApi();
String id = "random-non-existing-id";
try {
DataCenter dataCenter = api.getDataCenter(id);
assertRequestHasCommonProperties(server.takeRequest());
assertNull(dataCenter);
} finally {
pbApi.close();
server.shutdown();
}
}
@Test
public void testGetDataCenterState() throws Exception {
MockWebServer server = mockWebServer();
server.enqueue(new MockResponse().setBody(payloadFromResource("/datacenter/datacenter-state.xml")));
ProfitBricksApi pbApi = api(server.getUrl(rootUrl));
DataCenterApi api = pbApi.dataCenterApi();
String id = "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee";
try {
ProvisioningState state = api.getDataCenterState(id);
assertRequestHasCommonProperties(server.takeRequest());
assertNotNull(state);
assertEquals(state, ProvisioningState.AVAILABLE);
} finally {
pbApi.close();
server.shutdown();
}
}
@Test
public void testCreateDataCenter() throws Exception {
MockWebServer server = mockWebServer();
server.enqueue(new MockResponse().setBody(payloadFromResource("/datacenter/datacenter-created.xml")));
ProfitBricksApi pbApi = api(server.getUrl(rootUrl));
DataCenterApi api = pbApi.dataCenterApi();
try {
DataCenter dataCenter = api.createDataCenter(
DataCenter.Request.CreatePayload.create("JClouds-DC", Location.DE_FRA)
);
assertRequestHasCommonProperties(server.takeRequest());
assertNotNull(dataCenter);
assertEquals(dataCenter.id(), "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee");
assertEquals(dataCenter.version(), 1);
} finally {
pbApi.close();
server.shutdown();
}
}
@Test
public void testCreateDataCenterWithIllegalArguments() throws Exception {
String[] names = {"JCl@ouds", "JC|ouds", "^clouds", ""};
for (String name : names) {
try {
DataCenter.Request.CreatePayload.create(name, Location.US_LAS);
fail("Should have failed for name: ".concat(name));
} catch (IllegalArgumentException ex) {
// expected exception
}
}
}
@Test
public void testUpdateDataCenter() throws Exception {
MockWebServer server = mockWebServer();
server.enqueue(new MockResponse().setBody(payloadFromResource("/datacenter/datacenter-updated.xml")));
ProfitBricksApi pbApi = api(server.getUrl(rootUrl));
DataCenterApi api = pbApi.dataCenterApi();
String id = "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee";
try {
DataCenter dataCenter = api.updateDataCenter(
DataCenter.Request.UpdatePayload.create(id, "Apache")
);
assertRequestHasCommonProperties(server.takeRequest());
assertNotNull(dataCenter);
assertEquals(dataCenter.id(), id);
assertEquals(dataCenter.version(), 2);
} finally {
pbApi.close();
server.shutdown();
}
}
@Test
public void testClearDataCenter() throws Exception {
MockWebServer server = mockWebServer();
server.enqueue(new MockResponse().setBody(payloadFromResource("/datacenter/datacenter-cleared.xml")));
ProfitBricksApi pbApi = api(server.getUrl(rootUrl));
DataCenterApi api = pbApi.dataCenterApi();
String id = "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee";
try {
DataCenter dataCenter = api.clearDataCenter(id);
assertRequestHasCommonProperties(server.takeRequest());
assertNotNull(dataCenter);
assertEquals(dataCenter.id(), id);
assertEquals(dataCenter.version(), 3);
} finally {
pbApi.close();
server.shutdown();
}
}
@Test
public void testDeleteDataCenter() throws Exception {
MockWebServer server = mockWebServer();
server.enqueue(new MockResponse().setBody(payloadFromResource("/datacenter/datacenter-deleted.xml")));
ProfitBricksApi pbApi = api(server.getUrl(rootUrl));
DataCenterApi api = pbApi.dataCenterApi();
try {
boolean result = api.deleteDataCenter("aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee");
assertRequestHasCommonProperties(server.takeRequest());
assertTrue(result);
} finally {
pbApi.close();
server.shutdown();
}
}
@Test
public void testDeleteNonExistingDataCenter() throws Exception {
MockWebServer server = mockWebServer();
server.enqueue(new MockResponse().setResponseCode(500).setBody(payloadFromResource("/fault-404.xml")));
ProfitBricksApi pbApi = api(server.getUrl(rootUrl));
DataCenterApi api = pbApi.dataCenterApi();
try {
boolean result = api.deleteDataCenter("aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee");
assertRequestHasCommonProperties(server.takeRequest());
assertFalse(result);
} finally {
pbApi.close();
server.shutdown();
}
}
}

View File

@ -0,0 +1,98 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.profitbricks.http;
import static org.jclouds.profitbricks.internal.BaseProfitBricksMockTest.mockWebServer;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;
import org.jclouds.profitbricks.ProfitBricksApi;
import org.jclouds.profitbricks.domain.DataCenter;
import org.jclouds.profitbricks.domain.Location;
import org.jclouds.profitbricks.features.DataCenterApi;
import org.jclouds.profitbricks.internal.BaseProfitBricksMockTest;
import org.jclouds.rest.AuthorizationException;
import org.jclouds.rest.ResourceNotFoundException;
import org.testng.annotations.Test;
import com.squareup.okhttp.mockwebserver.MockResponse;
import com.squareup.okhttp.mockwebserver.MockWebServer;
/**
* Mock tests for the {@link ResponseStatusFromPayloadHttpCommandExecutorService} class.
*/
@Test(groups = "unit", testName = "ResponseStatusFromPayloadHttpCommandExecutorServiceTest")
public class ResponseStatusFromPayloadHttpCommandExecutorServiceTest extends BaseProfitBricksMockTest {
@Test
public void testNotFound() throws Exception {
MockWebServer server = mockWebServer();
server.enqueue(new MockResponse().setResponseCode(500).setBody(payloadFromResource("/fault-404.xml")));
ProfitBricksApi pbApi = api(server.getUrl("/"));
DataCenterApi api = pbApi.dataCenterApi();
String id = "random-non-existing-id";
try {
api.clearDataCenter(id);
fail("Request should have failed");
} catch (Exception ex) {
assertTrue(ex instanceof ResourceNotFoundException, "Exception should be an ResourceNotFoundException");
} finally {
pbApi.close();
server.shutdown();
}
}
@Test
public void testBadRequest() throws Exception {
MockWebServer server = mockWebServer();
server.enqueue(new MockResponse().setResponseCode(500).setBody(payloadFromResource("/fault-400.xml")));
ProfitBricksApi pbApi = api(server.getUrl("/"));
DataCenterApi api = pbApi.dataCenterApi();
try {
api.createDataCenter(DataCenter.Request.CreatePayload.create("D@tacenter", Location.DE_FKB));
fail("Request should have failed");
} catch (Exception ex) {
assertTrue(ex instanceof IllegalArgumentException, "Exception should be an IllegalArgumentException");
} finally {
pbApi.close();
server.shutdown();
}
}
@Test
public void testUnauthorized() throws Exception {
MockWebServer server = mockWebServer();
server.enqueue(new MockResponse().setResponseCode(401).setBody(payloadFromResource("/fault-401.html")));
ProfitBricksApi pbApi = api(server.getUrl("/"));
DataCenterApi api = pbApi.dataCenterApi();
try {
api.clearDataCenter("some-datacenter-id");
fail("Request should have failed");
} catch (Exception ex) {
assertTrue(ex instanceof AuthorizationException, "Exception should be an AuthorizationException");
} finally {
pbApi.close();
server.shutdown();
}
}
}

View File

@ -0,0 +1,57 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.profitbricks.http.filters;
import static org.testng.Assert.assertEquals;
import org.jclouds.http.HttpRequest;
import org.testng.annotations.Test;
/**
* Unit tests for the {@link ProfitBricksSoapMessageEnvelope} class.
*/
@Test(groups = "unit", testName = "ProfitBricksSoapMessageEnvelopeTest")
public class ProfitBricksSoapMessageEnvelopeTest {
private final String SOAP_PREFIX
= "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:ws=\"http://ws.api.profitbricks.com/\">"
+ "<soapenv:Header/>"
+ "<soapenv:Body>";
private final String SOAP_SUFFIX = "</soapenv:Body></soapenv:Envelope>";
private final String endpoint = "https://api.profitbricks.com/1.3";
@Test
public void testPayloadEnclosedWithSoapTags() {
String requestBody = "<ws:getAllDataCenters/>";
String expectedPayload = SOAP_PREFIX.concat(requestBody).concat(SOAP_SUFFIX);
HttpRequest request = HttpRequest.builder().method("POST").endpoint(endpoint).payload(requestBody).build();
ProfitBricksSoapMessageEnvelope soapEnvelope = new ProfitBricksSoapMessageEnvelope();
HttpRequest filtered = soapEnvelope.filter(request);
assertEquals(filtered.getPayload().getRawContent(), expectedPayload);
assertEquals(filtered.getPayload().getContentMetadata().getContentLength(), Long.valueOf(expectedPayload.length()));
}
@Test(expectedExceptions = NullPointerException.class, expectedExceptionsMessageRegExp = ".*must contain payload message.*")
public void testNullRequest() {
HttpRequest request = HttpRequest.builder().method("POST").endpoint(endpoint).build();
new ProfitBricksSoapMessageEnvelope().filter(request);
}
}

View File

@ -0,0 +1,61 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.profitbricks.http.parser;
import static org.jclouds.util.Strings2.toStringAndClose;
import java.io.IOException;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.http.functions.config.SaxParserModule;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import com.google.common.base.Throwables;
import com.google.inject.Guice;
import com.google.inject.Injector;
public abstract class BaseResponseHandlerTest<T> {
protected Injector injector = null;
protected ParseSax.Factory factory;
protected GeneratedHttpRequest request;
protected abstract ParseSax<T> createParser();
@BeforeTest
protected void setUpInjector() {
injector = Guice.createInjector(new SaxParserModule());
factory = injector.getInstance(ParseSax.Factory.class);
assert factory != null;
}
protected String payloadFromResource(String resource) {
try {
return toStringAndClose(getClass().getResourceAsStream(resource));
} catch (IOException e) {
throw Throwables.propagate(e);
}
}
@AfterTest
protected void tearDownInjector() {
factory = null;
injector = null;
}
}

View File

@ -0,0 +1,49 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.profitbricks.http.parser;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.profitbricks.domain.ServiceFault;
import org.testng.annotations.Test;
@Test(groups = "unit", testName = "ServiceFaultResponseHandlerTest")
public class ServiceFaultResponseHandlerTest extends BaseResponseHandlerTest<ServiceFault> {
@Override
protected ParseSax<ServiceFault> createParser() {
return factory.create(injector.getInstance(ServiceFaultResponseHandler.class));
}
@Test
public void testParseSoapServiceFault() {
ParseSax<ServiceFault> parser = createParser();
ServiceFault actual = parser.parse(payloadFromResource("/fault-404.xml"));
assertNotNull(actual, "Parsed content returned null");
ServiceFault expected = ServiceFault.builder()
.faultCode(ServiceFault.FaultCode.RESOURCE_NOT_FOUND)
.httpCode(404)
.message("The requested resource could not be found. Please refer to Request Id : 11122416. [VDC-6-404] The requested data center does not exist or already deleted by the users. ResourceId random-non-existing-id")
.requestId(11122416)
.build();
assertEquals(expected, actual);
}
}

View File

@ -0,0 +1,54 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.profitbricks.http.parser.datacenter;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import javax.xml.parsers.ParserConfigurationException;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.profitbricks.domain.DataCenter;
import org.jclouds.profitbricks.domain.Location;
import org.jclouds.profitbricks.domain.ProvisioningState;
import org.jclouds.profitbricks.http.parser.BaseResponseHandlerTest;
import org.testng.annotations.Test;
@Test(groups = "unit", testName = "DataCenterInfoResponseHandlerTest")
public class DataCenterInfoResponseHandlerTest extends BaseResponseHandlerTest<DataCenter> {
@Override
protected ParseSax<DataCenter> createParser() {
return factory.create(injector.getInstance(DataCenterInfoResponseHandler.class));
}
@Test
public void testParseResponseFromGetDataCenter() throws ParserConfigurationException {
ParseSax<DataCenter> parser = createParser();
DataCenter actual = parser.parse(payloadFromResource("/datacenter/datacenter.xml"));
assertNotNull(actual, "Parsed content returned null");
DataCenter expected = DataCenter.builder()
.id("12345678-abcd-efgh-ijkl-987654321000")
.version(10)
.name("JClouds-DC")
.state(ProvisioningState.AVAILABLE)
.location(Location.US_LAS)
.build();
assertEquals(expected, actual);
}
}

View File

@ -0,0 +1,53 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.profitbricks.http.parser.datacenter;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import java.util.List;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.profitbricks.domain.DataCenter;
import org.jclouds.profitbricks.domain.ProvisioningState;
import org.jclouds.profitbricks.http.parser.BaseResponseHandlerTest;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableList;
@Test(groups = "unit", testName = "DataCenterListResponseHandlerTest")
public class DataCenterListResponseHandlerTest extends BaseResponseHandlerTest<List<DataCenter>> {
@Override
protected ParseSax<List<DataCenter>> createParser() {
return factory.create(injector.getInstance(DataCenterListResponseHandler.class));
}
@Test
public void testParseResponseFromGetAllDataCenter() {
ParseSax<List<DataCenter>> parser = createParser();
List<DataCenter> actual = parser.parse(payloadFromResource("/datacenter/datacenters.xml"));
assertNotNull(actual, "Parsed content returned null");
List<DataCenter> expected = ImmutableList.<DataCenter>of(
DataCenter.builder().id("aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee").name("JClouds-DC").version(10).state(ProvisioningState.AVAILABLE).build(),
DataCenter.builder().id("qqqqqqqq-wwww-rrrr-tttt-yyyyyyyyyyyy").name("Random DC").version(238).state(ProvisioningState.INPROCESS).build()
);
assertEquals(expected, actual);
}
}

View File

@ -0,0 +1,110 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.profitbricks.http.parser.state;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import java.util.LinkedHashMap;
import java.util.Map;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.profitbricks.domain.ProvisioningState;
import org.jclouds.profitbricks.http.parser.BaseResponseHandlerTest;
import org.testng.annotations.Test;
@Test(groups = "unit", testName = "GetProvisioningStateResponseHandlerTest")
public class GetProvisioningStateResponseHandlerTest extends BaseResponseHandlerTest<ProvisioningState> {
@Override
protected ParseSax<ProvisioningState> createParser() {
return factory.create(injector.getInstance(GetProvisioningStateResponseHandler.class));
}
@Test
public void testParseResponseFromGetProvisioningState() {
ParseSax<ProvisioningState> parser = createParser();
for (Map.Entry<ProvisioningState, String> pair : sampleResponses.entrySet()) {
ProvisioningState actual = parser.parse(pair.getValue());
assertNotNull(actual, "Parsed content returned null");
assertEquals(pair.getKey(), actual);
}
}
private final Map<ProvisioningState, String> sampleResponses = new LinkedHashMap<ProvisioningState, String>() {
{
put(ProvisioningState.INACTIVE,
"<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:ws=\"http://ws.api.profitbricks.com/\">\n"
+ " <soapenv:Header/>\n"
+ " <soapenv:Body>\n"
+ " <ws:getDataCenterStateResponse>\n"
+ " <return>INACTIVE</return>\n"
+ " </ws:getDataCenterStateResponse>\n"
+ " </soapenv:Body>\n"
+ "</soapenv:Envelope>");
put(ProvisioningState.INPROCESS,
"<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:ws=\"http://ws.api.profitbricks.com/\">\n"
+ " <soapenv:Header/>\n"
+ " <soapenv:Body>\n"
+ " <ws:getDataCenterStateResponse>\n"
+ " <return>INPROCESS</return>\n"
+ " </ws:getDataCenterStateResponse>\n"
+ " </soapenv:Body>\n"
+ "</soapenv:Envelope>");
put(ProvisioningState.AVAILABLE,
"<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:ws=\"http://ws.api.profitbricks.com/\">\n"
+ " <soapenv:Header/>\n"
+ " <soapenv:Body>\n"
+ " <ws:getDataCenterStateResponse>\n"
+ " <return>AVAILABLE</return>\n"
+ " </ws:getDataCenterStateResponse>\n"
+ " </soapenv:Body>\n"
+ "</soapenv:Envelope>");
put(ProvisioningState.DELETED,
"<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:ws=\"http://ws.api.profitbricks.com/\">\n"
+ " <soapenv:Header/>\n"
+ " <soapenv:Body>\n"
+ " <ws:getDataCenterStateResponse>\n"
+ " <return>DELETED</return>\n"
+ " </ws:getDataCenterStateResponse>\n"
+ " </soapenv:Body>\n"
+ "</soapenv:Envelope>");
put(ProvisioningState.ERROR,
"<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:ws=\"http://ws.api.profitbricks.com/\">\n"
+ " <soapenv:Header/>\n"
+ " <soapenv:Body>\n"
+ " <ws:getDataCenterStateResponse>\n"
+ " <return>ERROR</return>\n"
+ " </ws:getDataCenterStateResponse>\n"
+ " </soapenv:Body>\n"
+ "</soapenv:Envelope>");
put(ProvisioningState.UNRECOGNIZED,
"<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:ws=\"http://ws.api.profitbricks.com/\">\n"
+ " <soapenv:Header/>\n"
+ " <soapenv:Body>\n"
+ " <ws:getDataCenterStateResponse>\n"
+ " <return>MEH</return>\n"
+ " </ws:getDataCenterStateResponse>\n"
+ " </soapenv:Body>\n"
+ "</soapenv:Envelope>");
}
};
}

View File

@ -0,0 +1,88 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.profitbricks.internal;
import static org.jclouds.util.Strings2.toStringAndClose;
import static org.testng.Assert.assertEquals;
import java.io.IOException;
import java.net.URL;
import java.util.Properties;
import java.util.Set;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import org.jclouds.ContextBuilder;
import org.jclouds.http.filters.BasicAuthentication;
import org.jclouds.profitbricks.ProfitBricksApi;
import com.google.common.base.Charsets;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Module;
import com.squareup.okhttp.mockwebserver.MockWebServer;
import com.squareup.okhttp.mockwebserver.RecordedRequest;
/**
* Base class for all ProfitBricks mock test
*/
public class BaseProfitBricksMockTest {
protected static final String authHeader = BasicAuthentication.basic("username", "password");
protected static final String provider = "profitbricks";
protected static final String rootUrl = "/1.3";
private final Set<Module> modules = ImmutableSet.<Module>of();
public BaseProfitBricksMockTest() {
}
public ProfitBricksApi api(URL url) {
return ContextBuilder.newBuilder(provider)
.credentials("username", "password")
.endpoint(url.toString())
.modules(modules)
.overrides(setupProperties())
.buildApi(ProfitBricksApi.class);
}
protected Properties setupProperties() {
return new Properties();
}
public static MockWebServer mockWebServer() throws IOException {
MockWebServer server = new MockWebServer();
server.play();
return server;
}
public byte[] payloadFromResource(String resource) {
try {
return toStringAndClose(getClass().getResourceAsStream(resource)).getBytes(Charsets.UTF_8);
} catch (IOException e) {
throw Throwables.propagate(e);
}
}
protected static void assertRequestHasCommonProperties(final RecordedRequest request) {
assertEquals(request.getMethod(), "POST");
assertEquals(request.getPath(), rootUrl);
assertEquals(request.getHeader(HttpHeaders.AUTHORIZATION), authHeader);
assertEquals(request.getHeader(HttpHeaders.ACCEPT), MediaType.TEXT_XML);
}
}

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<ns2:clearDataCenterResponse xmlns:ns2="http://ws.api.profitbricks.com/">
<return>
<requestId>1143191</requestId>
<dataCenterId>aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee</dataCenterId>
<dataCenterVersion>3</dataCenterVersion>
</return>
</ns2:clearDataCenterResponse>
</S:Body>
</S:Envelope>

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ws="http://ws.api.profitbricks.com/">
<soapenv:Body>
<ws:createDataCenterResponse>
<return>
<requestId>102456</requestId>
<dataCenterId>aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee</dataCenterId>
<dataCenterVersion>1</dataCenterVersion>
<location>de/fra</location>
</return>
</ws:createDataCenterResponse>
</soapenv:Body>
</soapenv:Envelope>

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<ns2:deleteDataCenterResponse xmlns:ns2="http://ws.api.profitbricks.com/">
<return>
<requestId>11411363</requestId>
</return>
</ns2:deleteDataCenterResponse>
</S:Body>
</S:Envelope>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<ns2:getDataCenterStateResponse xmlns:ns2="http://ws.api.profitbricks.com/">
<return>INPROCESS</return>
</ns2:getDataCenterStateResponse>
</S:Body>
</S:Envelope>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<ns2:getDataCenterStateResponse xmlns:ns2="http://ws.api.profitbricks.com/">
<return>AVAILABLE</return>
</ns2:getDataCenterStateResponse>
</S:Body>
</S:Envelope>

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<ns2:updateDataCenterResponse xmlns:ns2="http://ws.api.profitbricks.com/">
<return>
<requestId>1143190</requestId>
<dataCenterId>aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee</dataCenterId>
<dataCenterVersion>2</dataCenterVersion>
</return>
</ns2:updateDataCenterResponse>
</S:Body>
</S:Envelope>

View File

@ -0,0 +1,80 @@
<?xml version="1.0" encoding="UTF-8"?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<ns2:getDataCenterResponse xmlns:ns2="http://ws.api.profitbricks.com/">
<return>
<requestId>10933055</requestId>
<dataCenterId>12345678-abcd-efgh-ijkl-987654321000</dataCenterId>
<dataCenterVersion>10</dataCenterVersion>
<dataCenterName>JClouds-DC</dataCenterName>
<servers>
<dataCenterId>12345678-abcd-efgh-ijkl-987654321000</dataCenterId>
<dataCenterVersion>10</dataCenterVersion>
<serverId>qqqqqqqq-wwww-eeee-rrrr-tttttttttttt</serverId>
<serverName>jnode1</serverName>
<cores>4</cores>
<ram>4096</ram>
<internetAccess>true</internetAccess>
<ips>202.94.38.12</ips>
<connectedStorages>
<bootDevice>true</bootDevice>
<busType>VIRTIO</busType>
<deviceNumber>1</deviceNumber>
<size>40</size>
<storageId>ssssssss-aaaa-ffff-gggg-hhhhhhhhhhhh</storageId>
<storageName>jnode1-disk1</storageName>
</connectedStorages>
<nics>
<dataCenterId>12345678-abcd-efgh-ijkl-987654321000</dataCenterId>
<dataCenterVersion>10</dataCenterVersion>
<nicId>zzzzzzzz-xxxx-cccc-vvvv-bbbbbbbbbbbb</nicId>
<lanId>1</lanId>
<internetAccess>true</internetAccess>
<serverId>12345678-abcd-efgh-ijkl-987654321000</serverId>
<ips>202.94.38.12</ips>
<macAddress>02:01:09:cd:f0:b0</macAddress>
<firewall>`
<active>false</active>
<firewallId>llllllll-kkkk-jjjj-hhhh-gggggggggggg</firewallId>
<firewallId>62383ec1-38c8-486b-8fa2-a3bb0a5edd97</firewallId>
<nicId>zzzzzzzz-xxxx-cccc-vvvv-bbbbbbbbbbbb</nicId>
<provisioningState>AVAILABLE</provisioningState>
</firewall>
<dhcpActive>true</dhcpActive>
<gatewayIp>202.94.38.1</gatewayIp>
<provisioningState>AVAILABLE</provisioningState>
</nics>
<provisioningState>AVAILABLE</provisioningState>
<virtualMachineState>RUNNING</virtualMachineState>
<creationTime>2014-12-04T07:09:23.138Z</creationTime>
<lastModificationTime>2014-12-12T03:08:35.629Z</lastModificationTime>
<osType>LINUX</osType>
<availabilityZone>AUTO</availabilityZone>
<cpuHotPlug>true</cpuHotPlug>
<ramHotPlug>true</ramHotPlug>
<nicHotPlug>true</nicHotPlug>
<nicHotUnPlug>true</nicHotUnPlug>
<discVirtioHotPlug>true</discVirtioHotPlug>
<discVirtioHotUnPlug>true</discVirtioHotUnPlug>
</servers>
<storages>
<dataCenterId>12345678-abcd-efgh-ijkl-987654321000</dataCenterId>
<dataCenterVersion>10</dataCenterVersion>
<storageId>ssssssss-aaaa-ffff-gggg-hhhhhhhhhhhh</storageId>
<size>40</size>
<storageName>jnode1-disk1</storageName>
<mountImage>
<imageId>f0a59a5c-7940-11e4-8053-52540066fee9</imageId>
<imageName>Ubuntu-14.04-LTS-server-2014-12-01</imageName>
</mountImage>
<serverIds>qqqqqqqq-wwww-eeee-rrrr-tttttttttttt</serverIds>
<provisioningState>AVAILABLE</provisioningState>
<creationTime>2014-12-04T07:09:23.138Z</creationTime>
<lastModificationTime>2014-12-12T03:14:48.316Z</lastModificationTime>
</storages>
<provisioningState>AVAILABLE</provisioningState>
<location>us/las</location>
</return>
</ns2:getDataCenterResponse>
</S:Body>
</S:Envelope>

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<ns2:getAllDataCentersResponse xmlns:ns2="http://ws.api.profitbricks.com/">
<return>
<dataCenterId>aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee</dataCenterId>
<dataCenterName>JClouds-DC</dataCenterName>
<dataCenterVersion>10</dataCenterVersion>
<provisioningState>AVAILABLE</provisioningState>
</return>
<return>
<dataCenterId>qqqqqqqq-wwww-rrrr-tttt-yyyyyyyyyyyy</dataCenterId>
<dataCenterName>Random DC</dataCenterName>
<dataCenterVersion>238</dataCenterVersion>
<provisioningState>INPROCESS</provisioningState>
</return>
</ns2:getAllDataCentersResponse>
</S:Body>
</S:Envelope>

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<S:Fault xmlns:ns4="http://www.w3.org/2003/05/soap-envelope">
<faultcode>S:Server</faultcode>
<faultstring>RAM of requested server too small, 256 Mb is minimum</faultstring>
<detail>
<ns2:ProfitbricksServiceFault xmlns:ns2="http://ws.api.profitbricks.com/">
<faultCode>BAD_REQUEST</faultCode>
<httpCode>400</httpCode>
<message>RAM of requested server too small, 256 Mb is minimum</message>
<requestId>1045</requestId>
</ns2:ProfitbricksServiceFault>
</detail>
</S:Fault>
</S:Body>
</S:Envelope>

View File

@ -0,0 +1,43 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" lang="en"/>
<title>Profitbricks | 401 Unauthorized</title>
<base href="/"/>
<link rel="stylesheet" type="text/css" href="css/style.css"/>
<link rel="stylesheet" type="text/css" href="css/content.css"/>
<link rel="stylesheet" type="text/css" href="css/recent_additions.css"/>
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon"/>
</head>
<body>
<div class="head1 h_bg"/>
<div class="head2 h_bg"/>
<div class="head3 h_bg"/>
<div id="wrapper">
<div class="wrapper_inner">
<div id="header">
<a id="logo" href="#">
<img alt="Profitbricks" src="img/logo.png"/>
</a>
</div>
<div id="main">
<div id="right" style="min-height: 550px;">
<div class="article msg">
<h1>Unauthorized</h1>
<img title="" alt="message error" src="img/msg_error.png" class="msg_sign" style="margin: 10px;" height="49" width="49"/>
<div class="container" style="margin:20px 80px !important;">
<p class="bigmargin">This request requires authentication.</p>
</div>
</div>
</div>
<br class="clear"/>
</div>
</div>
</div>
<div id="footer">
<div class="bottom">
<div class="inner"></div>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<S:Fault xmlns:ns4="http://www.w3.org/2003/05/soap-envelope">
<faultcode>S:Server</faultcode>
<faultstring>The requested resource could not be found. Please refer to Request Id : 11122416. [VDC-6-404] The requested data center does not exist or already deleted by the users. ResourceId random-non-existing-id</faultstring>
<detail>
<ns2:ProfitbricksServiceFault xmlns:ns2="http://ws.api.profitbricks.com/">
<faultCode>RESOURCE_NOT_FOUND</faultCode>
<httpCode>404</httpCode>
<message>The requested resource could not be found. Please refer to Request Id : 11122416. [VDC-6-404] The requested data center does not exist or already deleted by the users. ResourceId random-non-existing-id</message>
<requestId>11122416</requestId>
</ns2:ProfitbricksServiceFault>
</detail>
</S:Fault>
</S:Body>
</S:Envelope>