added support for more load balancer operations, extended the main live test

This commit is contained in:
Alex Yarmula 2010-03-02 12:37:00 -08:00
parent 9df9d45859
commit 86471b0a5a
27 changed files with 922 additions and 153 deletions

View File

@ -28,6 +28,8 @@ import org.jclouds.http.HttpCommand;
import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpResponseException; import org.jclouds.http.HttpResponseException;
import java.util.Set;
import static java.lang.String.format; import static java.lang.String.format;
/** /**
@ -37,22 +39,28 @@ public class GoGridResponseException extends HttpResponseException {
private static final long serialVersionUID = 1924589L; private static final long serialVersionUID = 1924589L;
private ErrorResponse error; private Set<ErrorResponse> errors;
public GoGridResponseException(HttpCommand command, HttpResponse response, ErrorResponse error) { public GoGridResponseException(HttpCommand command, HttpResponse response, Set<ErrorResponse> errors) {
super(format("command %s failed with code %s, error [%s]: %s", super(buildMessage(command, response, errors), command, response);
command.toString(), response.getStatusCode(), error.getErrorCode(), this.setErrors(errors);
error.getMessage()),
command, response);
this.setError(error);
} }
public Set<ErrorResponse> getError() {
public ErrorResponse getError() { return errors;
return error;
} }
public void setError(ErrorResponse error) { public void setErrors(Set<ErrorResponse> errors) {
this.error = error; this.errors = errors;
}
private static String buildMessage(HttpCommand command, HttpResponse response, Set<ErrorResponse> errors) {
StringBuilder builder = new StringBuilder();
builder.append(format("command %s failed with code %s. ", command.toString(),
response.getStatusCode()));
for(ErrorResponse error : errors) {
builder.append(format("Error [%s]: %s. ", error.getErrorCode(), error.getMessage()));
}
return builder.toString();
} }
} }

View File

@ -0,0 +1,67 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.gogrid.binders;
import org.jclouds.gogrid.domain.IpPortPair;
import org.jclouds.http.HttpRequest;
import org.jclouds.rest.Binder;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import java.util.List;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static org.jclouds.gogrid.reference.GoGridQueryParams.REAL_IP_LIST_KEY;
/**
* Binds a list of real IPs to the request.
*
* The {@link IpPortPair pairs} must have a {@link IpPortPair#ip} set with a valid
* IP address.
*
* @author Oleksiy Yarmula
*/
public class BindRealIpPortPairsToQueryParams implements Binder {
@SuppressWarnings({"unchecked"})
@Override
public void bindToRequest(HttpRequest request, Object input) {
checkArgument(checkNotNull(request, "request is null") instanceof GeneratedHttpRequest,
"this binder is only valid for GeneratedHttpRequests!");
checkArgument(checkNotNull(input, "input is null") instanceof List,
"this binder is only valid for a List argument");
List<IpPortPair> ipPortPairs = (List<IpPortPair>) input;
GeneratedHttpRequest generatedRequest = (GeneratedHttpRequest) request;
int i= 0;
for(IpPortPair ipPortPair : ipPortPairs) {
checkNotNull(ipPortPair.getIp(), "There must be an IP address defined");
checkNotNull(ipPortPair.getIp().getIp(), "There must be an IP address defined in Ip object");
checkState(ipPortPair.getPort() > 0, "The port number must be a positive integer");
generatedRequest.addQueryParam(REAL_IP_LIST_KEY + i + ".ip",
ipPortPair.getIp().getIp());
generatedRequest.addQueryParam(REAL_IP_LIST_KEY + i + ".port",
String.valueOf(ipPortPair.getPort()));
i++;
}
}
}

View File

@ -0,0 +1,58 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.gogrid.binders;
import org.jclouds.gogrid.domain.IpPortPair;
import org.jclouds.http.HttpRequest;
import org.jclouds.rest.Binder;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import static org.jclouds.gogrid.reference.GoGridQueryParams.VIRTUAL_IP_KEY;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
/**
* Binds a virtual IP to the request.
*
* The {@link IpPortPair} must have a {@link IpPortPair#ip} set with a valid
* IP address.
*
* @author Oleksiy Yarmula
*/
public class BindVirtualIpPortPairToQueryParams implements Binder {
@Override
public void bindToRequest(HttpRequest request, Object input) {
checkArgument(checkNotNull(request, "request is null") instanceof GeneratedHttpRequest,
"this binder is only valid for GeneratedHttpRequests!");
checkArgument(checkNotNull(input, "input is null") instanceof IpPortPair,
"this binder is only valid for a IpPortPair argument");
IpPortPair ipPortPair = (IpPortPair) input;
GeneratedHttpRequest generatedRequest = (GeneratedHttpRequest) request;
checkNotNull(ipPortPair.getIp(), "There must be an IP address defined");
checkNotNull(ipPortPair.getIp().getIp(), "There must be an IP address defined in Ip object");
checkState(ipPortPair.getPort() > 0, "The port number must be a positive integer");
generatedRequest.addQueryParam(VIRTUAL_IP_KEY + "ip", ipPortPair.getIp().getIp());
generatedRequest.addQueryParam(VIRTUAL_IP_KEY + "port", String.valueOf(ipPortPair.getPort()));
}
}

View File

@ -166,6 +166,7 @@ public class GoGridRestClientModule extends AbstractModule {
bindings.put(LoadBalancerPersistenceType.class, new CustomDeserializers.LoadBalancerPersistenceTypeAdapter()); bindings.put(LoadBalancerPersistenceType.class, new CustomDeserializers.LoadBalancerPersistenceTypeAdapter());
bindings.put(LoadBalancerType.class, new CustomDeserializers.LoadBalancerTypeAdapter()); bindings.put(LoadBalancerType.class, new CustomDeserializers.LoadBalancerTypeAdapter());
bindings.put(IpState.class, new CustomDeserializers.IpStateAdapter()); bindings.put(IpState.class, new CustomDeserializers.IpStateAdapter());
bindings.put(JobState.class, new CustomDeserializers.JobStateAdapter());
return bindings; return bindings;
} }

View File

@ -45,6 +45,16 @@ public class Ip implements Comparable<Ip> {
public Ip() { public Ip() {
} }
/**
* Constructs a generic IP address
* without any additional options.
*
* @param ip ip address
*/
public Ip(String ip) {
this.ip = ip;
}
public Ip(long id, String ip, String subnet, boolean isPublic, IpState state) { public Ip(long id, String ip, String subnet, boolean isPublic, IpState state) {
this.id = id; this.id = id;
this.ip = ip; this.ip = ip;

View File

@ -18,7 +18,6 @@
*/ */
package org.jclouds.gogrid.domain; package org.jclouds.gogrid.domain;
import com.google.common.collect.ImmutableMap;
import com.google.common.primitives.Longs; import com.google.common.primitives.Longs;
import com.google.gson.annotations.SerializedName; import com.google.gson.annotations.SerializedName;
@ -44,10 +43,10 @@ public class Job implements Comparable<Job> {
@SerializedName("lastupdatedon") @SerializedName("lastupdatedon")
private Date lastUpdatedOn; private Date lastUpdatedOn;
@SerializedName("currentstate") @SerializedName("currentstate")
private Option currentState; private JobState currentState;
private int attempts; private int attempts;
private String owner; private String owner;
private List<JobState> history; private List<JobProperties> history;
@SerializedName("detail") /*NOTE: as of Feb 28, 10, @SerializedName("detail") /*NOTE: as of Feb 28, 10,
there is a contradiction b/w the name in there is a contradiction b/w the name in
documentation (details) and actual param documentation (details) and actual param
@ -61,8 +60,8 @@ public class Job implements Comparable<Job> {
} }
public Job(long id, Option command, ObjectType objectType, public Job(long id, Option command, ObjectType objectType,
Date createdOn, Date lastUpdatedOn, Option currentState, Date createdOn, Date lastUpdatedOn, JobState currentState,
int attempts, String owner, List<JobState> history, int attempts, String owner, List<JobProperties> history,
Map<String, String> details) { Map<String, String> details) {
this.id = id; this.id = id;
this.command = command; this.command = command;
@ -96,7 +95,7 @@ public class Job implements Comparable<Job> {
return lastUpdatedOn; return lastUpdatedOn;
} }
public Option getCurrentState() { public JobState getCurrentState() {
return currentState; return currentState;
} }
@ -108,7 +107,7 @@ public class Job implements Comparable<Job> {
return owner; return owner;
} }
public List<JobState> getHistory() { public List<JobProperties> getHistory() {
return history; return history;
} }

View File

@ -0,0 +1,103 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.gogrid.domain;
import com.google.gson.annotations.SerializedName;
import java.util.Date;
/**
* State of a job.
*
* @see <a href="http://wiki.gogrid.com/wiki/index.php/API:Job_State_(Object)"/>
*
* @author Oleksiy Yarmula
*/
public class JobProperties {
private long id;
@SerializedName("updatedon")
private Date updatedOn;
private JobState state;
private String note;
/**
* A no-args constructor is required for deserialization
*/
public JobProperties() {
}
public JobProperties(long id, Date updatedOn, JobState state, String note) {
this.id = id;
this.updatedOn = updatedOn;
this.state = state;
this.note = note;
}
public long getId() {
return id;
}
public Date getUpdatedOn() {
return updatedOn;
}
public JobState getState() {
return state;
}
public String getNote() {
return note;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
JobProperties jobState = (JobProperties) o;
if (id != jobState.id) return false;
if (note != null ? !note.equals(jobState.note) : jobState.note != null) return false;
if (state != null ? !state.equals(jobState.state) : jobState.state != null) return false;
if (updatedOn != null ? !updatedOn.equals(jobState.updatedOn) : jobState.updatedOn != null) return false;
return true;
}
@Override
public int hashCode() {
int result = (int) (id ^ (id >>> 32));
result = 31 * result + (updatedOn != null ? updatedOn.hashCode() : 0);
result = 31 * result + (state != null ? state.hashCode() : 0);
result = 31 * result + (note != null ? note.hashCode() : 0);
return result;
}
@Override
public String toString() {
return "JobState{" +
"id=" + id +
", updatedOn=" + updatedOn +
", state=" + state +
", note='" + note + '\'' +
'}';
}
}

View File

@ -18,86 +18,41 @@
*/ */
package org.jclouds.gogrid.domain; package org.jclouds.gogrid.domain;
import com.google.gson.annotations.SerializedName; import org.omg.CORBA.UNKNOWN;
import java.util.Date; import static com.google.common.base.Preconditions.checkNotNull;
/** /**
* State of a job.
*
* @see <a href="http://wiki.gogrid.com/wiki/index.php/API:Job_State_(Object)"/>
*
* @author Oleksiy Yarmula * @author Oleksiy Yarmula
*/ */
public class JobState { public enum JobState {
private long id; QUEUED("Queued", "Change request is new to the system."),
@SerializedName("updatedon") PROCESSING("Processing", "Change request is is transient state...Processing."),
private Date updatedOn; SUCCEEDED("Succeeded", "Change request has succeeded."),
private Option state; FAILED("Failed", "Change request has failed."),
private String note; CANCELED("Canceled", "Change request has been canceled."),
FATAL("Fatal", "Change request had Fatal or Unrecoverable Failure"),
CREATED("Created", "Change request is created but not queued yet"),
UNKNOWN("Unknown", "The state is unknown to JClouds");
/** String name;
* A no-args constructor is required for deserialization String description;
*/ JobState(String name, String description) {
public JobState() { this.name = name;
this.description = description;
}
public JobState(long id, Date updatedOn, Option state, String note) {
this.id = id;
this.updatedOn = updatedOn;
this.state = state;
this.note = note;
}
public long getId() {
return id;
}
public Date getUpdatedOn() {
return updatedOn;
}
public Option getState() {
return state;
}
public String getNote() {
return note;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
JobState jobState = (JobState) o;
if (id != jobState.id) return false;
if (note != null ? !note.equals(jobState.note) : jobState.note != null) return false;
if (state != null ? !state.equals(jobState.state) : jobState.state != null) return false;
if (updatedOn != null ? !updatedOn.equals(jobState.updatedOn) : jobState.updatedOn != null) return false;
return true;
}
@Override
public int hashCode() {
int result = (int) (id ^ (id >>> 32));
result = 31 * result + (updatedOn != null ? updatedOn.hashCode() : 0);
result = 31 * result + (state != null ? state.hashCode() : 0);
result = 31 * result + (note != null ? note.hashCode() : 0);
return result;
} }
@Override @Override
public String toString() { public String toString() {
return "JobState{" + return name;
"id=" + id +
", updatedOn=" + updatedOn +
", state=" + state +
", note='" + note + '\'' +
'}';
} }
public static JobState fromValue(String state) {
for(JobState jobState : values()) {
if(jobState.name.equals(checkNotNull(state))) return jobState;
}
return UNKNOWN;
}
} }

View File

@ -28,7 +28,7 @@ import com.google.gson.annotations.SerializedName;
/** /**
* @author Oleksiy Yarmula * @author Oleksiy Yarmula
*/ */
public class ErrorResponse { public class ErrorResponse implements Comparable<ErrorResponse> {
private String message; private String message;
@SerializedName("errorcode") @SerializedName("errorcode")
@ -52,4 +52,9 @@ public class ErrorResponse {
public String getErrorCode() { public String getErrorCode() {
return errorCode; return errorCode;
} }
@Override
public int compareTo(ErrorResponse o) {
return message.compareTo(o.getMessage());
}
} }

View File

@ -36,23 +36,27 @@ import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.util.SortedSet;
import static com.google.common.base.Preconditions.checkState; import static com.google.common.base.Preconditions.checkState;
/** /**
* Parses {@link org.jclouds.gogrid.domain.internal.ErrorResponse * Parses {@link org.jclouds.gogrid.domain.internal.ErrorResponse
* error response} from a json string. * error response} from a json string.
* *
* GoGrid may return multiple error objects, if multiple errors were found.
*
* @author Oleksiy Yarmula * @author Oleksiy Yarmula
*/ */
@Singleton @Singleton
public class ParseErrorFromJsonResponse extends ParseJson<ErrorResponse> { public class ParseErrorFromJsonResponse extends ParseJson<SortedSet<ErrorResponse>> {
@Inject @Inject
public ParseErrorFromJsonResponse(Gson gson) { public ParseErrorFromJsonResponse(Gson gson) {
super(gson); super(gson);
} }
public ErrorResponse apply(InputStream stream) { public SortedSet<ErrorResponse> apply(InputStream stream) {
Type setType = new TypeToken<GenericResponseContainer<ErrorResponse>>() { Type setType = new TypeToken<GenericResponseContainer<ErrorResponse>>() {
}.getType(); }.getType();
GenericResponseContainer<ErrorResponse> response; GenericResponseContainer<ErrorResponse> response;
@ -61,8 +65,6 @@ public class ParseErrorFromJsonResponse extends ParseJson<ErrorResponse> {
} catch (UnsupportedEncodingException e) { } catch (UnsupportedEncodingException e) {
throw new RuntimeException("jclouds requires UTF-8 encoding", e); throw new RuntimeException("jclouds requires UTF-8 encoding", e);
} }
checkState(response.getList() != null && response.getList().size() == 1, return response.getList();
/*or throw*/ "Expected exactly 1 error object in response");
return Iterables.getOnlyElement(response.getList());
} }
} }

View File

@ -0,0 +1,50 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.gogrid.functions;
import com.google.common.collect.Iterables;
import com.google.gson.Gson;
import org.jclouds.gogrid.domain.LoadBalancer;
import org.jclouds.http.functions.ParseJson;
import javax.inject.Inject;
import java.io.InputStream;
import java.util.SortedSet;
/**
* Parses the single load balancer out of the response.
*
* This class delegates parsing to {@link ParseLoadBalancerListFromJsonResponse}.
*
* @author Oleksiy Yarmula
*/
public class ParseLoadBalancerFromJsonResponse extends ParseJson<LoadBalancer> {
@Inject
public ParseLoadBalancerFromJsonResponse(Gson gson) {
super(gson);
}
public LoadBalancer apply(InputStream stream) {
SortedSet<LoadBalancer> allLoadBalancers =
new ParseLoadBalancerListFromJsonResponse(gson).apply(stream);
return Iterables.getOnlyElement(allLoadBalancers);
}
}

View File

@ -76,4 +76,12 @@ public class CustomDeserializers {
} }
} }
public static class JobStateAdapter implements JsonDeserializer<JobState> {
@Override
public JobState deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext context) throws JsonParseException {
String name = ((JsonObject) jsonElement).get("name").getAsString();
return JobState.fromValue(name);
}
}
} }

View File

@ -35,6 +35,7 @@ import org.jclouds.http.HttpResponseException;
import org.jclouds.rest.AuthorizationException; import org.jclouds.rest.AuthorizationException;
import java.io.InputStream; import java.io.InputStream;
import java.util.Set;
/** /**
* @author Oleksiy Yarmula * @author Oleksiy Yarmula
@ -52,18 +53,18 @@ public class GoGridErrorHandler implements HttpErrorHandler {
@Override @Override
public void handleError(HttpCommand command, HttpResponse response) { public void handleError(HttpCommand command, HttpResponse response) {
Exception exception; Exception exception;
ErrorResponse error = parseErrorFromContentOrNull(response.getContent()); Set<ErrorResponse> errors = parseErrorsFromContentOrNull(response.getContent());
switch (response.getStatusCode()) { switch (response.getStatusCode()) {
default: default:
exception = error != null ? exception = errors != null ?
new GoGridResponseException(command, response, error) : new GoGridResponseException(command, response, errors) :
new HttpResponseException(command, response); new HttpResponseException(command, response);
} }
command.setException(exception); command.setException(exception);
Closeables.closeQuietly(response.getContent()); Closeables.closeQuietly(response.getContent());
} }
ErrorResponse parseErrorFromContentOrNull(InputStream content) { Set<ErrorResponse> parseErrorsFromContentOrNull(InputStream content) {
if (content != null) { if (content != null) {
return errorParser.apply(content); return errorParser.apply(content);
} }

View File

@ -0,0 +1,65 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.gogrid.options;
import org.jclouds.gogrid.domain.LoadBalancerPersistenceType;
import org.jclouds.gogrid.domain.LoadBalancerType;
import org.jclouds.http.options.BaseHttpRequestOptions;
import static com.google.common.base.Preconditions.checkState;
import static org.jclouds.gogrid.reference.GoGridQueryParams.*;
/**
* Optional parameters for adding a load balancer.
*
* @see org.jclouds.gogrid.services.GridLoadBalancerClient#addLoadBalancer
* @see <a href="http://wiki.gogrid.com/wiki/index.php/API:grid.loadbalancer.add"/>
*
* @author Oleksiy Yarmula
*/
public class AddLoadBalancerOptions extends BaseHttpRequestOptions {
public AddLoadBalancerOptions setDescription(String description) {
checkState(!queryParameters.containsKey(DESCRIPTION_KEY), "Can't have duplicate " +
"load balancer description");
queryParameters.put(DESCRIPTION_KEY, description);
return this;
}
public AddLoadBalancerOptions setType(LoadBalancerType loadBalancerType) {
checkState(!queryParameters.containsKey(LOAD_BALANCER_TYPE_KEY), "Can't have duplicate " +
"load balancer type limitation");
queryParameters.put(LOAD_BALANCER_TYPE_KEY, loadBalancerType.toString());
return this;
}
public AddLoadBalancerOptions setPersistenceType(LoadBalancerPersistenceType loadBalancerPersistenceType) {
checkState(!queryParameters.containsKey(LOAD_BALANCER_PERSISTENCE_TYPE_KEY), "Can't have duplicate " +
"load balancer type limitation");
queryParameters.put(LOAD_BALANCER_PERSISTENCE_TYPE_KEY, loadBalancerPersistenceType.toString());
return this;
}
public static class Builder {
public AddLoadBalancerOptions create(LoadBalancerType type,
LoadBalancerPersistenceType persistenceType) {
return new AddLoadBalancerOptions().setType(type).setPersistenceType(persistenceType);
}
}
}

View File

@ -59,6 +59,10 @@ public class GetIpListOptions extends BaseHttpRequestOptions {
public GetIpListOptions limitToType(IpType type) { public GetIpListOptions limitToType(IpType type) {
return new GetIpListOptions().onlyWithType(type); return new GetIpListOptions().onlyWithType(type);
} }
public GetIpListOptions unassignedPublicIps() {
return new GetIpListOptions().onlyWithType(IpType.PUBLIC).onlyUnassigned();
}
} }
} }

View File

@ -18,6 +18,8 @@
*/ */
package org.jclouds.gogrid.options; package org.jclouds.gogrid.options;
import org.jclouds.gogrid.domain.JobState;
import org.jclouds.gogrid.domain.ObjectType;
import org.jclouds.http.options.BaseHttpRequestOptions; import org.jclouds.http.options.BaseHttpRequestOptions;
import java.util.Date; import java.util.Date;
@ -56,15 +58,15 @@ public class GetJobListOptions extends BaseHttpRequestOptions {
return this; return this;
} }
public GetJobListOptions onlyForState(String jobState) { public GetJobListOptions onlyForState(JobState jobState) {
checkState(!queryParameters.containsKey(JOB_STATE_KEY), "Can't have duplicate job state for filtering"); checkState(!queryParameters.containsKey(JOB_STATE_KEY), "Can't have duplicate job state for filtering");
queryParameters.put(JOB_STATE_KEY, jobState); queryParameters.put(JOB_STATE_KEY, jobState.toString());
return this; return this;
} }
public GetJobListOptions onlyForObjectType(String objectType) { public GetJobListOptions onlyForObjectType(ObjectType objectType) {
checkState(!queryParameters.containsKey(JOB_OBJECT_TYPE_KEY), "Can't have duplicate object type for filtering"); checkState(!queryParameters.containsKey(JOB_OBJECT_TYPE_KEY), "Can't have duplicate object type for filtering");
queryParameters.put(JOB_OBJECT_TYPE_KEY, objectType); queryParameters.put(JOB_OBJECT_TYPE_KEY, objectType.toString());
return this; return this;
} }
@ -74,15 +76,27 @@ public class GetJobListOptions extends BaseHttpRequestOptions {
return this; return this;
} }
/*
* This method is intended for testing
*/
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
GetJobListOptions options = (GetJobListOptions) o;
return buildQueryParameters().equals(options.buildQueryParameters());
}
public static class Builder { public static class Builder {
public GetJobListOptions create() { public GetJobListOptions create() {
return new GetJobListOptions(); return new GetJobListOptions();
} }
public GetJobListOptions latestJobForServerByName(String serverName) { public GetJobListOptions latestJobForObjectByName(String serverName) {
return new GetJobListOptions(). return new GetJobListOptions().
maxItemsNumber(1). maxItemsNumber(1).
onlyForObjectType("VirtualServer").
onlyForObjectName(serverName); onlyForObjectName(serverName);
} }
} }

View File

@ -0,0 +1,61 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.gogrid.predicates;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.inject.Inject;
import org.jclouds.gogrid.domain.Job;
import org.jclouds.gogrid.domain.JobState;
import org.jclouds.gogrid.domain.LoadBalancer;
import org.jclouds.gogrid.options.GetJobListOptions;
import org.jclouds.gogrid.services.GridJobClient;
import org.jclouds.logging.Logger;
import javax.annotation.Resource;
import javax.inject.Singleton;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* @author Oleksiy Yarmula
*/
@Singleton
public class LoadBalancerLatestJobCompleted implements Predicate<LoadBalancer> {
protected GridJobClient jobClient;
@Resource
protected Logger logger = Logger.NULL;
@Inject
public LoadBalancerLatestJobCompleted(GridJobClient jobClient) {
this.jobClient = jobClient;
}
@Override
public boolean apply(LoadBalancer loadBalancer) {
checkNotNull(loadBalancer, "Load balancer must be a valid instance");
checkNotNull(loadBalancer.getName(), "Load balancer must be a valid name");
GetJobListOptions jobOptions = new GetJobListOptions.Builder().
latestJobForObjectByName(loadBalancer.getName());
Job latestJob = Iterables.getOnlyElement(jobClient.getJobList(jobOptions));
return JobState.SUCCEEDED.equals(latestJob.getCurrentState());
}
}

View File

@ -22,12 +22,12 @@ import com.google.common.base.Predicate;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.inject.Inject; import com.google.inject.Inject;
import org.jclouds.gogrid.domain.Job; import org.jclouds.gogrid.domain.Job;
import org.jclouds.gogrid.domain.JobState;
import org.jclouds.gogrid.domain.Server; import org.jclouds.gogrid.domain.Server;
import org.jclouds.gogrid.options.GetJobListOptions; import org.jclouds.gogrid.options.GetJobListOptions;
import org.jclouds.gogrid.services.GridJobClient; import org.jclouds.gogrid.services.GridJobClient;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import javax.annotation.Nullable;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.inject.Singleton; import javax.inject.Singleton;
@ -60,8 +60,8 @@ public class ServerLatestJobCompleted implements Predicate<Server> {
checkNotNull(server, "Server must be a valid instance"); checkNotNull(server, "Server must be a valid instance");
checkNotNull(server.getName(), "Server must be a valid name"); checkNotNull(server.getName(), "Server must be a valid name");
GetJobListOptions jobOptions = new GetJobListOptions.Builder(). GetJobListOptions jobOptions = new GetJobListOptions.Builder().
latestJobForServerByName(server.getName()); latestJobForObjectByName(server.getName());
Job latestJob = Iterables.getOnlyElement(jobClient.getJobList(jobOptions)); Job latestJob = Iterables.getOnlyElement(jobClient.getJobList(jobOptions));
return "Succeeded".equals(latestJob.getCurrentState().getName()); return JobState.SUCCEEDED.equals(latestJob.getCurrentState());
} }
} }

View File

@ -55,6 +55,11 @@ public interface GoGridQueryParams {
public static final String IP_STATE_KEY = "ip.state"; public static final String IP_STATE_KEY = "ip.state";
public static final String IP_TYPE_KEY = "ip.type"; public static final String IP_TYPE_KEY = "ip.type";
public static final String LOAD_BALANCER_TYPE_KEY = "loadbalancer.type";
public static final String LOAD_BALANCER_PERSISTENCE_TYPE_KEY = "loadbalancer.persistence";
public static final String VIRTUAL_IP_KEY = "virtualip.";
public static final String REAL_IP_LIST_KEY = "realiplist.";
} }

View File

@ -20,19 +20,27 @@ package org.jclouds.gogrid.services;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
import org.jclouds.gogrid.GoGrid; import org.jclouds.gogrid.GoGrid;
import org.jclouds.gogrid.binders.BindIdsToQueryParams;
import org.jclouds.gogrid.binders.BindNamesToQueryParams;
import org.jclouds.gogrid.binders.BindRealIpPortPairsToQueryParams;
import org.jclouds.gogrid.binders.BindVirtualIpPortPairToQueryParams;
import org.jclouds.gogrid.domain.IpPortPair;
import org.jclouds.gogrid.domain.LoadBalancer; import org.jclouds.gogrid.domain.LoadBalancer;
import org.jclouds.gogrid.filters.SharedKeyLiteAuthentication; import org.jclouds.gogrid.filters.SharedKeyLiteAuthentication;
import org.jclouds.gogrid.functions.ParseLoadBalancerFromJsonResponse;
import org.jclouds.gogrid.functions.ParseLoadBalancerListFromJsonResponse; import org.jclouds.gogrid.functions.ParseLoadBalancerListFromJsonResponse;
import org.jclouds.rest.annotations.Endpoint; import org.jclouds.gogrid.options.AddLoadBalancerOptions;
import org.jclouds.rest.annotations.QueryParams; import org.jclouds.rest.annotations.*;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser;
import javax.ws.rs.GET; import javax.ws.rs.GET;
import javax.ws.rs.Path; import javax.ws.rs.Path;
import javax.ws.rs.QueryParam;
import java.util.List;
import java.util.Set; import java.util.Set;
import static org.jclouds.gogrid.reference.GoGridHeaders.VERSION; import static org.jclouds.gogrid.reference.GoGridHeaders.VERSION;
import static org.jclouds.gogrid.reference.GoGridQueryParams.ID_KEY;
import static org.jclouds.gogrid.reference.GoGridQueryParams.NAME_KEY;
/** /**
* @author Oleksiy Yarmula * @author Oleksiy Yarmula
@ -50,4 +58,46 @@ public interface GridLoadBalancerAsyncClient {
@Path("/grid/loadbalancer/list") @Path("/grid/loadbalancer/list")
ListenableFuture<Set<LoadBalancer>> getLoadBalancerList(); ListenableFuture<Set<LoadBalancer>> getLoadBalancerList();
/**
* @see GridLoadBalancerClient#addLoadBalancer
*/
@GET
@ResponseParser(ParseLoadBalancerFromJsonResponse.class)
@Path("/grid/loadbalancer/add")
ListenableFuture<LoadBalancer> addLoadBalancer(@QueryParam("name") String name,
@BinderParam(BindVirtualIpPortPairToQueryParams.class) IpPortPair virtualIp,
@BinderParam(BindRealIpPortPairsToQueryParams.class) List<IpPortPair> realIps,
AddLoadBalancerOptions... options);
/**
* @see GridLoadBalancerClient#getLoadBalancersByName
*/
@GET
@ResponseParser(ParseLoadBalancerListFromJsonResponse.class)
@Path("/grid/loadbalancer/get")
ListenableFuture<Set<LoadBalancer>> getLoadBalancersByName(@BinderParam(BindNamesToQueryParams.class) String... names);
/**
* @see GridLoadBalancerClient#getLoadBalancersById
*/
@GET
@ResponseParser(ParseLoadBalancerListFromJsonResponse.class)
@Path("/grid/loadbalancer/get")
ListenableFuture<Set<LoadBalancer>> getLoadBalancersById(@BinderParam(BindIdsToQueryParams.class) Long... ids);
/**
* @see GridLoadBalancerClient#
*/
@GET
@ResponseParser(ParseLoadBalancerFromJsonResponse.class)
@Path("/grid/loadbalancer/delete")
ListenableFuture<LoadBalancer> deleteById(@QueryParam(ID_KEY) Long id);
/**
* @see GridLoadBalancerClient#
*/
@GET
@ResponseParser(ParseLoadBalancerFromJsonResponse.class)
@Path("/grid/loadbalancer/delete")
ListenableFuture<LoadBalancer> deleteByName(@QueryParam(NAME_KEY) String name);
} }

View File

@ -19,8 +19,11 @@
package org.jclouds.gogrid.services; package org.jclouds.gogrid.services;
import org.jclouds.concurrent.Timeout; import org.jclouds.concurrent.Timeout;
import org.jclouds.gogrid.domain.IpPortPair;
import org.jclouds.gogrid.domain.LoadBalancer; import org.jclouds.gogrid.domain.LoadBalancer;
import org.jclouds.gogrid.options.AddLoadBalancerOptions;
import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -35,4 +38,67 @@ public interface GridLoadBalancerClient {
* @return load balancers found * @return load balancers found
*/ */
Set<LoadBalancer> getLoadBalancerList(); Set<LoadBalancer> getLoadBalancerList();
/**
* Creates a load balancer with given properties.
*
* @param name name of the load balancer
* @param virtualIp virtual IP with IP address set in
* {@link org.jclouds.gogrid.domain.Ip#ip} and
* port set in {@link IpPortPair#port}
* @param realIps real IPs to bind the virtual IP to, with
* IP address set in
* {@link org.jclouds.gogrid.domain.Ip#ip} and
* port set in {@link IpPortPair#port}
* @param options options that specify load balancer's type (round robin,
* least load), persistence strategy, or description.
* @return created load balancer object
*/
LoadBalancer addLoadBalancer(String name,
IpPortPair virtualIp,
List<IpPortPair> realIps,
AddLoadBalancerOptions... options);
/**
* Returns the load balancer(s) by unique name(s).
*
* Given a name or a set of names, finds one or
* multiple load balancers.
* @param names to get the load balancers
* @return load balancer(s) matching the name(s)
*/
Set<LoadBalancer> getLoadBalancersByName(String... names);
/**
* Returns the load balancer(s) by unique id(s).
*
* Given an id or a set of ids, finds one or
* multiple load balancers.
* @param ids to get the load balancers
* @return load balancer(s) matching the ids
*/
Set<LoadBalancer> getLoadBalancersById(Long... ids);
/**
* Deletes the load balancer by Id
*
* @param id
* id of the load balancer to delete
* @return load balancer before the command is executed
*/
LoadBalancer deleteById(Long id);
/**
* Deletes the load balancer by name;
*
* NOTE: Using this parameter may generate an
* error if one or more load balancers share a
* non-unique name.
*
* @param name
* name of the load balancer to be deleted
*
* @return load balancer before the command is executed
*/
LoadBalancer deleteByName(String name);
} }

View File

@ -20,9 +20,13 @@ package org.jclouds.gogrid;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import org.jclouds.gogrid.domain.*; import org.jclouds.gogrid.domain.*;
import org.jclouds.gogrid.options.AddLoadBalancerOptions;
import org.jclouds.gogrid.options.GetIpListOptions;
import org.jclouds.gogrid.predicates.LoadBalancerLatestJobCompleted;
import org.jclouds.gogrid.predicates.ServerLatestJobCompleted; import org.jclouds.gogrid.predicates.ServerLatestJobCompleted;
import org.jclouds.logging.log4j.config.Log4JLoggingModule; import org.jclouds.logging.log4j.config.Log4JLoggingModule;
import org.jclouds.predicates.RetryablePredicate; import org.jclouds.predicates.RetryablePredicate;
import org.testng.SkipException;
import org.testng.annotations.AfterTest; import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeGroups; import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test; import org.testng.annotations.Test;
@ -31,7 +35,7 @@ import java.util.*;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static org.testng.Assert.assertNotNull; import static org.testng.Assert.*;
import static java.lang.String.format; import static java.lang.String.format;
/** /**
@ -45,12 +49,14 @@ public class GoGridLiveTest {
private GoGridClient client; private GoGridClient client;
private RetryablePredicate<Server> latestJobCompleted; private RetryablePredicate<Server> serverLatestJobCompleted;
private RetryablePredicate<LoadBalancer> loadBalancerLatestJobCompleted;
/** /**
* Keeps track of the servers, created during the tests, * Keeps track of the servers, created during the tests,
* to remove them after all tests complete * to remove them after all tests complete
*/ */
private List<String> serversToDeleteAfterTheTests = new ArrayList<String>(); private List<String> serversToDeleteAfterTheTests = new ArrayList<String>();
private List<String> loadBalancersToDeleteAfterTest = new ArrayList<String>();
@BeforeGroups(groups = { "live" }) @BeforeGroups(groups = { "live" })
public void setupClient() { public void setupClient() {
@ -60,9 +66,12 @@ public class GoGridLiveTest {
client = GoGridContextFactory.createContext(user, password, new Log4JLoggingModule()) client = GoGridContextFactory.createContext(user, password, new Log4JLoggingModule())
.getApi(); .getApi();
serverLatestJobCompleted = new RetryablePredicate<Server>(
latestJobCompleted = new RetryablePredicate<Server>(new ServerLatestJobCompleted(client.getJobServices()), new ServerLatestJobCompleted(client.getJobServices()),
240, 15, TimeUnit.SECONDS); 800, 20, TimeUnit.SECONDS);
loadBalancerLatestJobCompleted = new RetryablePredicate<LoadBalancer>(
new LoadBalancerLatestJobCompleted(client.getJobServices()),
800, 20, TimeUnit.SECONDS);
} }
/** /**
@ -73,7 +82,7 @@ public class GoGridLiveTest {
public void testServerLifecycle() { public void testServerLifecycle() {
int serverCountBeforeTest = client.getServerServices().getServerList().size(); int serverCountBeforeTest = client.getServerServices().getServerList().size();
final String nameOfServer = "ServerCreated" + String.valueOf(new Date().getTime()).substring(8); final String nameOfServer = "Server" + String.valueOf(new Date().getTime()).substring(6);
serversToDeleteAfterTheTests.add(nameOfServer); serversToDeleteAfterTheTests.add(nameOfServer);
Set<Ip> availableIps = client.getIpServices().getUnassignedIpList(); Set<Ip> availableIps = client.getIpServices().getUnassignedIpList();
@ -84,7 +93,7 @@ public class GoGridLiveTest {
"1", "1",
availableIp.getIp()); availableIp.getIp());
assertNotNull(createdServer); assertNotNull(createdServer);
assert latestJobCompleted.apply(createdServer); assert serverLatestJobCompleted.apply(createdServer);
//get server by name //get server by name
Set<Server> response = client.getServerServices().getServersByName(nameOfServer); Set<Server> response = client.getServerServices().getServersByName(nameOfServer);
@ -96,7 +105,7 @@ public class GoGridLiveTest {
Set<Job> jobs = client.getJobServices().getJobsForObjectName(nameOfServer); Set<Job> jobs = client.getJobServices().getJobsForObjectName(nameOfServer);
assert("RestartVirtualServer".equals(Iterables.getLast(jobs).getCommand().getName())); assert("RestartVirtualServer".equals(Iterables.getLast(jobs).getCommand().getName()));
assert latestJobCompleted.apply(createdServer); assert serverLatestJobCompleted.apply(createdServer);
int serverCountAfterAddingOneServer = client.getServerServices().getServerList().size(); int serverCountAfterAddingOneServer = client.getServerServices().getServerList().size();
assert serverCountAfterAddingOneServer == serverCountBeforeTest + 1 : assert serverCountAfterAddingOneServer == serverCountBeforeTest + 1 :
@ -108,7 +117,7 @@ public class GoGridLiveTest {
jobs = client.getJobServices().getJobsForObjectName(nameOfServer); jobs = client.getJobServices().getJobsForObjectName(nameOfServer);
assert("DeleteVirtualServer".equals(Iterables.getLast(jobs).getCommand().getName())); assert("DeleteVirtualServer".equals(Iterables.getLast(jobs).getCommand().getName()));
assert latestJobCompleted.apply(createdServer); assert serverLatestJobCompleted.apply(createdServer);
int serverCountAfterDeletingTheServer = client.getServerServices().getServerList().size(); int serverCountAfterDeletingTheServer = client.getServerServices().getServerList().size();
assert serverCountAfterDeletingTheServer == serverCountBeforeTest : assert serverCountAfterDeletingTheServer == serverCountBeforeTest :
@ -124,7 +133,7 @@ public class GoGridLiveTest {
*/ */
@Test(/*dependsOnMethods = "testServerLifecycle", */ enabled=false) @Test(/*dependsOnMethods = "testServerLifecycle", */ enabled=false)
public void testJobs() { public void testJobs() {
final String nameOfServer = "ServerCreated" + String.valueOf(new Date().getTime()).substring(8); final String nameOfServer = "Server" + String.valueOf(new Date().getTime()).substring(6);
serversToDeleteAfterTheTests.add(nameOfServer); serversToDeleteAfterTheTests.add(nameOfServer);
Set<Ip> availableIps = client.getIpServices().getUnassignedIpList(); Set<Ip> availableIps = client.getIpServices().getUnassignedIpList();
@ -134,7 +143,7 @@ public class GoGridLiveTest {
"1", "1",
Iterables.getLast(availableIps).getIp()); Iterables.getLast(availableIps).getIp());
assert latestJobCompleted.apply(createdServer); assert serverLatestJobCompleted.apply(createdServer);
//restart the server //restart the server
client.getServerServices().power(nameOfServer, PowerCommand.RESTART); client.getServerServices().power(nameOfServer, PowerCommand.RESTART);
@ -163,9 +172,59 @@ public class GoGridLiveTest {
} }
@Test(enabled=false) /**
public void testLoadBalancers() { * Tests common load balancer operations.
Set<LoadBalancer> balancers = client.getLoadBalancerServices().getLoadBalancerList(); * Also verifies IP services and job services.
*/
@Test(enabled=true)
public void testLoadBalancerLifecycle() {
int lbCountBeforeTest = client.getLoadBalancerServices().getLoadBalancerList().size();
final String nameOfLoadBalancer = "LoadBalancer" + String.valueOf(new Date().getTime()).substring(6);
loadBalancersToDeleteAfterTest.add(nameOfLoadBalancer);
GetIpListOptions ipOptions = new GetIpListOptions.Builder().unassignedPublicIps();
Set<Ip> availableIps = client.getIpServices().getIpList(ipOptions);
if(availableIps.size() < 3) throw new SkipException("Not enough available IPs (3 needed) to run the test");
Iterator<Ip> ipIterator = availableIps.iterator();
Ip vip = ipIterator.next();
Ip realIp1 = ipIterator.next();
Ip realIp2 = ipIterator.next();
AddLoadBalancerOptions options = new AddLoadBalancerOptions.Builder().
create(LoadBalancerType.LEAST_CONNECTED, LoadBalancerPersistenceType.SOURCE_ADDRESS);
LoadBalancer createdLoadBalancer = client.getLoadBalancerServices().
addLoadBalancer(nameOfLoadBalancer, new IpPortPair(vip, 80),
Arrays.asList(new IpPortPair(realIp1, 80),
new IpPortPair(realIp2, 80)), options);
assertNotNull(createdLoadBalancer);
assert loadBalancerLatestJobCompleted.apply(createdLoadBalancer);
//get load balancer by name
Set<LoadBalancer> response = client.getLoadBalancerServices().getLoadBalancersByName(nameOfLoadBalancer);
assert (response.size() == 1);
createdLoadBalancer = Iterables.getOnlyElement(response);
assertNotNull(createdLoadBalancer.getRealIpList());
assert createdLoadBalancer.getRealIpList().size() == 2;
assertNotNull(createdLoadBalancer.getVirtualIp());
assertEquals(createdLoadBalancer.getVirtualIp().getIp().getIp(), vip.getIp());
int lbCountAfterAddingOneServer = client.getLoadBalancerServices().getLoadBalancerList().size();
assert lbCountAfterAddingOneServer == lbCountBeforeTest + 1 :
"There should be +1 increase in the number of load balancers since the test started";
//delete the load balancer
client.getLoadBalancerServices().deleteByName(nameOfLoadBalancer);
Set<Job> jobs = client.getJobServices().getJobsForObjectName(nameOfLoadBalancer);
assert("DeleteLoadBalancer".equals(Iterables.getLast(jobs).getCommand().getName()));
assert loadBalancerLatestJobCompleted.apply(createdLoadBalancer);
int lbCountAfterDeletingTheServer = client.getLoadBalancerServices().getLoadBalancerList().size();
assert lbCountAfterDeletingTheServer == lbCountBeforeTest :
"There should be the same # of load balancers as since the test started";
} }
/** /**
@ -181,6 +240,14 @@ public class GoGridLiveTest {
// it's already been deleted - proceed // it's already been deleted - proceed
} }
} }
for(String loadBalancerName : loadBalancersToDeleteAfterTest) {
try {
client.getLoadBalancerServices().deleteByName(loadBalancerName);
} catch(Exception e) {
// it's already been deleted - proceed
}
}
} }
} }

View File

@ -23,6 +23,7 @@
*/ */
package org.jclouds.gogrid.functions; package org.jclouds.gogrid.functions;
import com.google.common.collect.Iterables;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.inject.Guice; import com.google.inject.Guice;
import com.google.inject.Injector; import com.google.inject.Injector;
@ -45,7 +46,7 @@ public class ParseErrorFromJsonResponseTest {
ParseErrorFromJsonResponse parser = new ParseErrorFromJsonResponse(i ParseErrorFromJsonResponse parser = new ParseErrorFromJsonResponse(i
.getInstance(Gson.class)); .getInstance(Gson.class));
ErrorResponse response = parser.apply(is); ErrorResponse response = Iterables.getOnlyElement(parser.apply(is));
assert "No object found that matches your input criteria.".equals(response.getMessage()); assert "No object found that matches your input criteria.".equals(response.getMessage());
assert "IllegalArgumentException".equals(response.getErrorCode()); assert "IllegalArgumentException".equals(response.getErrorCode());
} }

View File

@ -20,18 +20,13 @@ package org.jclouds.gogrid.functions;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.inject.Guice; import com.google.inject.Guice;
import com.google.inject.Injector; import com.google.inject.Injector;
import com.google.inject.Provides; import com.google.inject.Provides;
import com.google.inject.internal.ImmutableMap;
import org.jclouds.Constants; import org.jclouds.Constants;
import org.jclouds.gogrid.config.GoGridContextModule; import org.jclouds.gogrid.config.GoGridContextModule;
import org.jclouds.gogrid.domain.Job; import org.jclouds.gogrid.domain.*;
import org.jclouds.gogrid.domain.JobState;
import org.jclouds.gogrid.domain.ObjectType;
import org.jclouds.gogrid.domain.Option;
import org.jclouds.gogrid.functions.internal.CustomDeserializers; import org.jclouds.gogrid.functions.internal.CustomDeserializers;
import org.jclouds.http.functions.config.ParserModule; import org.jclouds.http.functions.config.ParserModule;
import org.testng.annotations.Test; import org.testng.annotations.Test;
@ -72,16 +67,14 @@ public class ParseJobsFromJsonResponseTest {
ObjectType.VIRTUAL_SERVER, ObjectType.VIRTUAL_SERVER,
new Date(1267404528895L), new Date(1267404528895L),
new Date(1267404538592L), new Date(1267404538592L),
new Option(3L, "Succeeded", "Change request has succeeded."), JobState.SUCCEEDED,
1, 1,
"3116784158f0af2d-24076@api.gogrid.com", "3116784158f0af2d-24076@api.gogrid.com",
Arrays.asList( Arrays.asList(
new JobState(940263L, new Date(1267404528897L), new JobProperties(940263L, new Date(1267404528897L),
new Option(7L, "Created", JobState.CREATED, null),
"Change request is created but not queued yet"), null), new JobProperties(940264L, new Date(1267404528967L),
new JobState(940264L, new Date(1267404528967L), JobState.QUEUED, null)
new Option(1L, "Queued",
"Change request is new to the system."), null)
), ),
details); details);
assertEquals(job, Iterables.getOnlyElement(response)); assertEquals(job, Iterables.getOnlyElement(response));
@ -101,6 +94,7 @@ public class ParseJobsFromJsonResponseTest {
public Map<Class, Object> provideCustomAdapterBindings() { public Map<Class, Object> provideCustomAdapterBindings() {
Map<Class, Object> bindings = Maps.newHashMap(); Map<Class, Object> bindings = Maps.newHashMap();
bindings.put(ObjectType.class, new CustomDeserializers.ObjectTypeAdapter()); bindings.put(ObjectType.class, new CustomDeserializers.ObjectTypeAdapter());
bindings.put(JobState.class, new CustomDeserializers.JobStateAdapter());
return bindings; return bindings;
} }
}); });

View File

@ -0,0 +1,64 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.gogrid.predicates;
import com.google.inject.internal.ImmutableSet;
import org.jclouds.gogrid.domain.Job;
import org.jclouds.gogrid.domain.JobState;
import org.jclouds.gogrid.domain.Server;
import org.jclouds.gogrid.options.GetJobListOptions;
import org.jclouds.gogrid.services.GridJobClient;
import org.testng.annotations.Test;
import static org.easymock.EasyMock.expect;
import static org.easymock.classextension.EasyMock.createMock;
import static org.easymock.classextension.EasyMock.replay;
import static org.testng.Assert.assertTrue;
/**
* @author Oleksiy Yarmula
*/
public class ServerLatestJobCompletedTest {
@Test
public void testPredicate() {
final String serverName = "SERVER_NAME";
Server server = createMock(Server.class);
expect(server.getName()).andStubReturn(serverName);
GetJobListOptions jobOptions = new GetJobListOptions.Builder().
latestJobForObjectByName(serverName);
Job job = createMock(Job.class);
expect(job.getCurrentState()).andReturn(JobState.SUCCEEDED);
GridJobClient client = createMock(GridJobClient.class);
expect(client.getJobList(jobOptions)).
andReturn(ImmutableSet.<Job>of(job));
replay(job);
replay(client);
replay(server);
ServerLatestJobCompleted predicate = new ServerLatestJobCompleted(client);
assertTrue(predicate.apply(server), "The result of the predicate should've been 'true'");
}
}

View File

@ -25,6 +25,8 @@ import com.google.inject.Provides;
import com.google.inject.TypeLiteral; import com.google.inject.TypeLiteral;
import org.jclouds.encryption.EncryptionService; import org.jclouds.encryption.EncryptionService;
import org.jclouds.gogrid.GoGrid; import org.jclouds.gogrid.GoGrid;
import org.jclouds.gogrid.domain.JobState;
import org.jclouds.gogrid.domain.ObjectType;
import org.jclouds.gogrid.filters.SharedKeyLiteAuthentication; import org.jclouds.gogrid.filters.SharedKeyLiteAuthentication;
import org.jclouds.gogrid.functions.ParseJobListFromJsonResponse; import org.jclouds.gogrid.functions.ParseJobListFromJsonResponse;
import org.jclouds.gogrid.options.GetJobListOptions; import org.jclouds.gogrid.options.GetJobListOptions;
@ -54,10 +56,15 @@ public class GridJobAsyncClientTest extends RestClientTest<GridJobAsyncClient> {
GeneratedHttpRequest<GridJobAsyncClient> httpRequest = processor.createRequest(method, GeneratedHttpRequest<GridJobAsyncClient> httpRequest = processor.createRequest(method,
new GetJobListOptions.Builder(). new GetJobListOptions.Builder().
create(). create().
withStartDate(new Date(1267385381770L))); withStartDate(new Date(1267385381770L)).
withEndDate(new Date(1267385382770L)).
onlyForObjectType(ObjectType.VIRTUAL_SERVER).
onlyForState(JobState.PROCESSING));
assertRequestLineEquals(httpRequest, assertRequestLineEquals(httpRequest,
"GET https://api.gogrid.com/api/grid/job/list?v=1.3&startdate=1267385381770 HTTP/1.1"); "GET https://api.gogrid.com/api/grid/job/list?v=1.3&startdate=1267385381770&" +
"enddate=1267385382770&job.objecttype=VirtualServer&" +
"job.state=Processing HTTP/1.1");
assertHeadersEqual(httpRequest, ""); assertHeadersEqual(httpRequest, "");
assertPayloadEquals(httpRequest, null); assertPayloadEquals(httpRequest, null);
@ -70,8 +77,9 @@ public class GridJobAsyncClientTest extends RestClientTest<GridJobAsyncClient> {
assertRequestLineEquals(httpRequest, assertRequestLineEquals(httpRequest,
"GET https://api.gogrid.com/api/grid/job/list?v=1.3&startdate=1267385381770&" + "GET https://api.gogrid.com/api/grid/job/list?v=1.3&startdate=1267385381770&" +
"sig=3f446f171455fbb5574aecff4997b273&api_key=foo " + "enddate=1267385382770&job.objecttype=VirtualServer&" +
"HTTP/1.1"); "job.state=Processing&" +
"sig=3f446f171455fbb5574aecff4997b273&api_key=foo HTTP/1.1");
assertHeadersEqual(httpRequest, ""); assertHeadersEqual(httpRequest, "");
assertPayloadEquals(httpRequest, null); assertPayloadEquals(httpRequest, null);
} }

View File

@ -25,8 +25,14 @@ import com.google.inject.Provides;
import com.google.inject.TypeLiteral; import com.google.inject.TypeLiteral;
import org.jclouds.encryption.EncryptionService; import org.jclouds.encryption.EncryptionService;
import org.jclouds.gogrid.GoGrid; import org.jclouds.gogrid.GoGrid;
import org.jclouds.gogrid.domain.Ip;
import org.jclouds.gogrid.domain.IpPortPair;
import org.jclouds.gogrid.domain.LoadBalancerPersistenceType;
import org.jclouds.gogrid.domain.LoadBalancerType;
import org.jclouds.gogrid.filters.SharedKeyLiteAuthentication; import org.jclouds.gogrid.filters.SharedKeyLiteAuthentication;
import org.jclouds.gogrid.functions.ParseLoadBalancerFromJsonResponse;
import org.jclouds.gogrid.functions.ParseLoadBalancerListFromJsonResponse; import org.jclouds.gogrid.functions.ParseLoadBalancerListFromJsonResponse;
import org.jclouds.gogrid.options.AddLoadBalancerOptions;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import org.jclouds.rest.RestClientTest; import org.jclouds.rest.RestClientTest;
import org.jclouds.rest.internal.GeneratedHttpRequest; import org.jclouds.rest.internal.GeneratedHttpRequest;
@ -38,6 +44,8 @@ import java.io.IOException;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.net.URI; import java.net.URI;
import java.util.Arrays;
import java.util.List;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
@ -47,7 +55,7 @@ import static org.testng.Assert.assertEquals;
public class GridLoadBalancerAsyncClientTest extends RestClientTest<GridLoadBalancerAsyncClient> { public class GridLoadBalancerAsyncClientTest extends RestClientTest<GridLoadBalancerAsyncClient> {
@Test @Test
public void testGetAssignedIpList() throws NoSuchMethodException, IOException { public void testGetLoadBalancerList() throws NoSuchMethodException, IOException {
Method method = GridLoadBalancerAsyncClient.class.getMethod("getLoadBalancerList"); Method method = GridLoadBalancerAsyncClient.class.getMethod("getLoadBalancerList");
GeneratedHttpRequest<GridLoadBalancerAsyncClient> httpRequest = processor.createRequest(method); GeneratedHttpRequest<GridLoadBalancerAsyncClient> httpRequest = processor.createRequest(method);
@ -71,6 +79,101 @@ public class GridLoadBalancerAsyncClientTest extends RestClientTest<GridLoadBala
assertPayloadEquals(httpRequest, null); assertPayloadEquals(httpRequest, null);
} }
@Test
public void testAddLoadBalancer() throws NoSuchMethodException, IOException {
Method method = GridLoadBalancerAsyncClient.class.getMethod("addLoadBalancer",
String.class, IpPortPair.class, List.class, AddLoadBalancerOptions[].class);
GeneratedHttpRequest<GridLoadBalancerAsyncClient> httpRequest = processor.createRequest(method,
"BalanceIt", new IpPortPair(new Ip("127.0.0.1"), 80),
Arrays.asList(new IpPortPair(new Ip("127.0.0.1"), 8080),
new IpPortPair(new Ip("127.0.0.1"), 9090)),
new AddLoadBalancerOptions.Builder().create(LoadBalancerType.LEAST_CONNECTED,
LoadBalancerPersistenceType.SSL_STICKY));
assertRequestLineEquals(httpRequest,
"GET https://api.gogrid.com/api/grid/loadbalancer/" +
"add?v=1.4&name=BalanceIt&loadbalancer.type=Least%20Connect&" +
"loadbalancer.persistence=SSL%20Sticky&realiplist.0.ip=127.0.0.1&" +
"realiplist.0.port=8080&realiplist.1.ip=127.0.0.1&realiplist.1.port=9090&" +
"virtualip.ip=127.0.0.1&virtualip.port=80 HTTP/1.1");
assertHeadersEqual(httpRequest, "");
assertPayloadEquals(httpRequest, null);
assertResponseParserClassEquals(method, httpRequest, ParseLoadBalancerFromJsonResponse.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, null);
checkFilters(httpRequest);
Iterables.getOnlyElement(httpRequest.getFilters()).filter(httpRequest);
assertRequestLineEquals(httpRequest,
"GET https://api.gogrid.com/api/grid/loadbalancer/" +
"add?v=1.4&name=BalanceIt&loadbalancer.type=Least%20Connect&" +
"loadbalancer.persistence=SSL%20Sticky&realiplist.0.ip=127.0.0.1&" +
"realiplist.0.port=8080&realiplist.1.ip=127.0.0.1&realiplist.1.port=9090&" +
"virtualip.ip=127.0.0.1&virtualip.port=80&" +
"sig=3f446f171455fbb5574aecff4997b273&api_key=foo " +
"HTTP/1.1");
assertHeadersEqual(httpRequest, "");
assertPayloadEquals(httpRequest, null);
}
@Test
public void testGetLoadBalancersByName() throws NoSuchMethodException, IOException {
Method method = GridLoadBalancerAsyncClient.class.getMethod("getLoadBalancersByName", String[].class);
GeneratedHttpRequest<GridLoadBalancerAsyncClient> httpRequest = processor.createRequest(method,
"My Load Balancer", "My Load Balancer 2");
assertRequestLineEquals(httpRequest,
"GET https://api.gogrid.com/api/grid/loadbalancer/" +
"get?v=1.4&name=My%20Load%20Balancer&name=My%20Load%20Balancer%202 HTTP/1.1");
assertHeadersEqual(httpRequest, "");
assertPayloadEquals(httpRequest, null);
assertResponseParserClassEquals(method, httpRequest, ParseLoadBalancerListFromJsonResponse.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, null);
checkFilters(httpRequest);
Iterables.getOnlyElement(httpRequest.getFilters()).filter(httpRequest);
assertRequestLineEquals(httpRequest,
"GET https://api.gogrid.com/api/grid/loadbalancer/" +
"get?v=1.4&name=My%20Load%20Balancer&name=My%20Load%20Balancer%202&" +
"sig=3f446f171455fbb5574aecff4997b273&api_key=foo " +
"HTTP/1.1");
assertHeadersEqual(httpRequest, "");
assertPayloadEquals(httpRequest, null);
}
@Test
public void testDeleteLoadBalancerById() throws NoSuchMethodException, IOException {
Method method = GridLoadBalancerAsyncClient.class.getMethod("deleteById", Long.class);
GeneratedHttpRequest<GridLoadBalancerAsyncClient> httpRequest = processor.createRequest(method,
55L);
assertRequestLineEquals(httpRequest,
"GET https://api.gogrid.com/api/grid/loadbalancer/" +
"delete?v=1.4&id=55 HTTP/1.1");
assertHeadersEqual(httpRequest, "");
assertPayloadEquals(httpRequest, null);
assertResponseParserClassEquals(method, httpRequest, ParseLoadBalancerFromJsonResponse.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, null);
checkFilters(httpRequest);
Iterables.getOnlyElement(httpRequest.getFilters()).filter(httpRequest);
assertRequestLineEquals(httpRequest,
"GET https://api.gogrid.com/api/grid/loadbalancer/" +
"delete?v=1.4&id=55&" +
"sig=3f446f171455fbb5574aecff4997b273&api_key=foo " +
"HTTP/1.1");
assertHeadersEqual(httpRequest, "");
assertPayloadEquals(httpRequest, null);
}
@Override @Override
protected void checkFilters(GeneratedHttpRequest<GridLoadBalancerAsyncClient> httpMethod) { protected void checkFilters(GeneratedHttpRequest<GridLoadBalancerAsyncClient> httpMethod) {