Some refactorings and cleanup, namely:

- Moved all relevant null checks into Resource
- Made create firewall use FirewallOptions instead of a Firewall obj
- Consolidated a lot of the HttpRequests in the expect tests to allow for reuse (in compute)
This commit is contained in:
David Ribeiro Alves 2013-02-06 19:06:57 -08:00
parent d6e38116c3
commit b6b4237380
46 changed files with 840 additions and 516 deletions

View File

@ -38,6 +38,7 @@ import org.jclouds.googlecompute.domain.Instance;
import org.jclouds.googlecompute.domain.InstanceTemplate;
import org.jclouds.googlecompute.domain.Operation;
import org.jclouds.googlecompute.domain.Project;
import org.jclouds.googlecompute.options.FirewallOptions;
import org.jclouds.json.config.GsonModule;
import org.jclouds.oauth.v2.domain.ClaimSet;
import org.jclouds.oauth.v2.domain.Header;
@ -75,6 +76,7 @@ public class GoogleComputeParserModule extends AbstractModule {
.put(Project.class, new ProjectTypeAdapter())
.put(Instance.class, new InstanceTypeAdapter())
.put(InstanceTemplate.class, new InstanceTemplateTypeAdapter())
.put(FirewallOptions.class, new FirewallOptionsTypeAdapter())
.put(Rule.class, new RuleTypeAdapter())
.build();
}
@ -132,7 +134,9 @@ public class GoogleComputeParserModule extends AbstractModule {
// deal with network
JsonArray networkInterfaces = new JsonArray();
networkInterfaces.add(context.serialize(src.getNetwork(), InstanceTemplate.Network.class));
for (InstanceTemplate.NetworkInterface networkInterface : template.getNetworkInterfaces()){
networkInterfaces.add(context.serialize(networkInterface, InstanceTemplate.NetworkInterface.class));
}
instance.add("networkInterfaces", networkInterfaces);
// deal with persistent disks
@ -165,6 +169,7 @@ public class GoogleComputeParserModule extends AbstractModule {
image(template.getImage());
tags(template.getTags());
serviceAccounts(template.getServiceAccounts());
networkInterfaces(template.getNetworkInterfaces());
}
}
}
@ -288,6 +293,47 @@ public class GoogleComputeParserModule extends AbstractModule {
}
}
@Singleton
private static class FirewallOptionsTypeAdapter implements JsonSerializer<FirewallOptions> {
@Override
public JsonElement serialize(FirewallOptions src, Type typeOfSrc, JsonSerializationContext context) {
JsonObject firewall = new JsonObject();
if (src.getName() != null) {
firewall.addProperty("name", src.getName());
}
if (src.getNetwork() != null) {
firewall.addProperty("network", src.getNetwork().toString());
}
if (!src.getSourceRanges().isEmpty()) {
firewall.add("sourceRanges", buildArrayOfStrings(src.getSourceRanges()));
}
if (!src.getSourceTags().isEmpty()) {
firewall.add("sourceTags", buildArrayOfStrings(src.getSourceTags()));
}
if (!src.getTargetTags().isEmpty()) {
firewall.add("targetTags", buildArrayOfStrings(src.getTargetTags()));
}
if (!src.getAllowed().isEmpty()) {
JsonArray rules = new JsonArray();
for (Rule rule : src.getAllowed()) {
rules.add(context.serialize(rule, Firewall.Rule.class));
}
firewall.add("allowed", rules);
}
return firewall;
}
}
private static JsonArray buildArrayOfStrings(Set<String> strings) {
JsonArray array = new JsonArray();
for (String string : strings) {
array.add(new JsonPrimitive(string));
}
return array;
}
private static class RuleTypeAdapter implements JsonDeserializer<Firewall.Rule>, JsonSerializer<Firewall.Rule> {
@Override

View File

@ -26,7 +26,6 @@ import java.beans.ConstructorProperties;
import java.net.URI;
import java.util.Date;
import static com.google.common.base.Optional.fromNullable;
import static com.google.common.base.Preconditions.checkNotNull;
/**
@ -48,8 +47,7 @@ public final class Disk extends Resource {
})
private Disk(String id, Date creationTimestamp, URI selfLink, String name, String description,
Integer sizeGb, URI zone, String status) {
super(Kind.DISK, checkNotNull(id, "id of %s", name), fromNullable(creationTimestamp), checkNotNull(selfLink,
"selfLink of %s", name), checkNotNull(name, "name"), fromNullable(description));
super(Kind.DISK, id, creationTimestamp, selfLink, name, description);
this.sizeGb = checkNotNull(sizeGb, "sizeGb of %s", name);
this.zone = checkNotNull(zone, "zone of %s", name);
this.status = checkNotNull(status, "status of %s", name);

View File

@ -32,7 +32,6 @@ import java.util.Set;
import static com.google.common.base.Objects.equal;
import static com.google.common.base.Objects.toStringHelper;
import static com.google.common.base.Optional.fromNullable;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.Range.closed;
@ -61,8 +60,7 @@ public final class Firewall extends Resource {
protected Firewall(String id, Date creationTimestamp, URI selfLink, String name, String description,
URI network, Set<String> sourceRanges, Set<String> sourceTags, Set<String> targetTags,
Set<Rule> allowed) {
super(Kind.FIREWALL, id, fromNullable(creationTimestamp), selfLink, checkNotNull(name, "name"),
fromNullable(description));
super(Kind.FIREWALL, id, creationTimestamp, selfLink, name, description);
this.network = checkNotNull(network, "network of %s", name);
this.sourceRanges = sourceRanges == null ? ImmutableSet.<String>of() : sourceRanges;
this.sourceTags = sourceTags == null ? ImmutableSet.<String>of() : sourceTags;
@ -119,8 +117,11 @@ public final class Firewall extends Resource {
*/
protected Objects.ToStringHelper string() {
return super.string()
.add("network", network).add("sourceRanges", sourceRanges).add("sourceTags",
sourceTags).add("targetTags", targetTags).add("allowed", allowed);
.add("network", network)
.add("sourceRanges", sourceRanges)
.add("sourceTags", sourceTags)
.add("targetTags", targetTags)
.add("allowed", allowed);
}
/**
@ -350,7 +351,7 @@ public final class Firewall extends Resource {
* @see org.jclouds.googlecompute.domain.Firewall.Rule#getIPProtocol()
*/
public Builder IPProtocol(IPProtocol IPProtocol) {
this.ipProtocol = checkNotNull(IPProtocol);
this.ipProtocol = IPProtocol;
return this;
}

View File

@ -51,8 +51,7 @@ public final class Image extends Resource {
})
protected Image(String id, Date creationTimestamp, URI selfLink, String name, String description,
String sourceType, URI preferredKernel, RawDisk rawDisk) {
super(Kind.IMAGE, checkNotNull(id, "id of %s", name), fromNullable(creationTimestamp),
checkNotNull(selfLink, "selfLink of %s", name), checkNotNull(name, "name"), fromNullable(description));
super(Kind.IMAGE, id, creationTimestamp, selfLink, name, description);
this.sourceType = checkNotNull(sourceType, "sourceType of %s", name);
this.preferredKernel = fromNullable(preferredKernel);
this.rawDisk = checkNotNull(rawDisk, "rawDisk of %s", name); ;

View File

@ -70,8 +70,7 @@ public class Instance extends Resource {
Set<String> tags, URI image, URI machineType, Status status, String statusMessage,
URI zone, Set<NetworkInterface> networkInterfaces, Set<AttachedDisk> disks,
Map<String, String> metadata, Set<ServiceAccount> serviceAccounts) {
super(Kind.INSTANCE, checkNotNull(id, "id"), fromNullable(creationTimestamp), checkNotNull(selfLink, "selfLink"),
checkNotNull(name, "name"), fromNullable(description));
super(Kind.INSTANCE, id, creationTimestamp, selfLink, name, description);
this.tags = tags == null ? ImmutableSet.<String>of() : tags;
this.image = checkNotNull(image, "image");
this.machineType = checkNotNull(machineType, "machineType of %s", name);
@ -716,7 +715,7 @@ public class Instance extends Resource {
ONE_TO_ONE_NAT
}
private String name;
private Optional<String> name;
private Type type;
private Optional<String> natIP;
@ -724,7 +723,7 @@ public class Instance extends Resource {
"name", "type", "natIP"
})
private AccessConfig(String name, Type type, String natIP) {
this.name = checkNotNull(name, "name");
this.name = fromNullable(name);
this.type = checkNotNull(type, "type");
this.natIP = fromNullable(natIP);
}
@ -732,7 +731,7 @@ public class Instance extends Resource {
/**
* @return name of this access configuration.
*/
public String getName() {
public Optional<String> getName() {
return name;
}
@ -832,7 +831,7 @@ public class Instance extends Resource {
}
public Builder fromAccessConfig(AccessConfig in) {
return this.name(in.getName())
return this.name(in.getName().orNull())
.type(in.getType())
.natIP(in.getNatIP().orNull());
}

View File

@ -30,6 +30,7 @@ import java.util.Set;
import static com.google.common.base.Objects.equal;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.googlecompute.domain.Instance.NetworkInterface.AccessConfig.Type;
/**
* Optional information for creating an instance.
@ -47,8 +48,7 @@ public class InstanceTemplate {
protected Set<Instance.ServiceAccount> serviceAccounts = Sets.newLinkedHashSet();
protected transient Set<PersistentDisk> disks = Sets.newLinkedHashSet();
protected transient Network network;
protected transient String networkName;
protected transient Set<NetworkInterface> networkInterfaces = Sets.newLinkedHashSet();
protected transient Map<String, String> metadata = Maps.newLinkedHashMap();
protected transient String machineTypeName;
protected transient String zoneName;
@ -163,24 +163,32 @@ public class InstanceTemplate {
/**
* @see org.jclouds.googlecompute.domain.Instance#getNetworkInterfaces()
*/
public InstanceTemplate network(URI network) {
// by default use the provided network and set to obtain an external IP address and not to specify an internal IP
// this behavior can be overriden by using network(Network network)
this.network = new Network(checkNotNull(network, "network"), null,
public InstanceTemplate addNetworkInterface(URI network) {
this.networkInterfaces.add(new NetworkInterface(checkNotNull(network, "network"), null,null));
return this;
}
/**
* @see org.jclouds.googlecompute.domain.Instance#getNetworkInterfaces()
*/
public InstanceTemplate addNetworkInterface(URI network, Type type) {
this.networkInterfaces.add(new NetworkInterface(checkNotNull(network, "network"), null,
ImmutableSet.of(Instance.NetworkInterface.AccessConfig.builder()
.name("external")
.type(Instance.NetworkInterface.AccessConfig.Type.ONE_TO_ONE_NAT)
.build()));
.type(type)
.build())));
return this;
}
private InstanceTemplate network(Network network) {
this.network = network;
/**
* @see org.jclouds.googlecompute.domain.Instance#getNetworkInterfaces()
*/
public InstanceTemplate addNetworkInterface(NetworkInterface networkInterface) {
this.networkInterfaces.add(networkInterface);
return this;
}
public InstanceTemplate networkName(String networkName) {
this.networkName = networkName;
public InstanceTemplate networkInterfaces(Set<NetworkInterface> networkInterfaces) {
this.networkInterfaces = Sets.newLinkedHashSet(networkInterfaces);
return this;
}
@ -264,15 +272,8 @@ public class InstanceTemplate {
/**
* @see org.jclouds.googlecompute.domain.Instance#getNetworkInterfaces()
*/
public Network getNetwork() {
return network;
}
/**
* @see org.jclouds.googlecompute.domain.Instance#getNetworkInterfaces()
*/
public String getNetworkName() {
return networkName;
public Set<NetworkInterface> getNetworkInterfaces() {
return networkInterfaces;
}
/**
@ -314,49 +315,24 @@ public class InstanceTemplate {
return new Builder();
}
public static InstanceTemplate fromInstance(Instance instance) {
return Builder.fromInstance(instance);
}
public static InstanceTemplate fromInstanceTemplate(InstanceTemplate instanceTemplate) {
return Builder.fromInstanceTemplate(instanceTemplate);
}
public static class Builder {
public InstanceTemplate forMachineTypeAndNetwork(URI machineType, URI network) {
return new InstanceTemplate(machineType).network(network);
public InstanceTemplate forMachineType(URI machineType) {
return new InstanceTemplate(machineType);
}
public InstanceTemplate forMachineTypeAndNetwork(URI machineType, Network network) {
return new InstanceTemplate(machineType).network(network);
}
public InstanceTemplate forMachineTypeAndNetwork(String machineTypeName, String networkName) {
return new InstanceTemplate(machineTypeName).networkName(networkName);
}
/**
* Creates instance options based on another instance.
* All properties are the same as the original instance's except:
* - disks (persistent disks are only attached to an instance)
* - networkInterfaces (these are instance specific)
*/
public static InstanceTemplate fromInstance(Instance instance) {
return InstanceTemplate.builder()
.forMachineTypeAndNetwork(instance.getMachineType(),
instance.getNetworkInterfaces().iterator().next().getNetwork())
.description(instance.getDescription().orNull())
.tags(instance.getTags())
.image(instance.getImage())
.metadata(instance.getMetadata())
.zone(instance.getZone())
.serviceAccounts(instance.getServiceAccounts());
public InstanceTemplate forMachineType(String machineTypeName) {
return new InstanceTemplate(machineTypeName);
}
public static InstanceTemplate fromInstanceTemplate(InstanceTemplate instanceTemplate) {
return InstanceTemplate.builder()
.forMachineTypeAndNetwork(instanceTemplate.getMachineType(), instanceTemplate.getNetwork())
.forMachineType(instanceTemplate.getMachineType())
.networkInterfaces(instanceTemplate.getNetworkInterfaces())
.name(instanceTemplate.getName())
.description(instanceTemplate.getDescription())
.zone(instanceTemplate.getZone())
@ -420,17 +396,17 @@ public class InstanceTemplate {
}
}
public static class Network {
public static class NetworkInterface {
private final URI network;
private final String networkIP;
private final Set<Instance.NetworkInterface.AccessConfig> accessConfigs;
public Network(URI network, String networkIP, Set<Instance.NetworkInterface.AccessConfig>
public NetworkInterface(URI network, String networkIP, Set<Instance.NetworkInterface.AccessConfig>
accessConfigs) {
this.networkIP = networkIP;
this.network = checkNotNull(network, "network");
this.accessConfigs = accessConfigs;
this.network = network;
this.accessConfigs = accessConfigs != null ? accessConfigs : ImmutableSet.<Instance.NetworkInterface.AccessConfig>of();
}
public Set<Instance.NetworkInterface.AccessConfig> getAccessConfigs() {
@ -461,7 +437,7 @@ public class InstanceTemplate {
&& equal(tags, other.tags)
&& equal(image, other.image)
&& equal(disks, other.disks)
&& equal(network, other.network)
&& equal(networkInterfaces, other.networkInterfaces)
&& equal(metadata, other.metadata)
&& equal(serviceAccounts, other.serviceAccounts);
} else {
@ -474,7 +450,7 @@ public class InstanceTemplate {
*/
@Override
public int hashCode() {
return Objects.hashCode(description, tags, image, disks, network, metadata, serviceAccounts);
return Objects.hashCode(description, tags, image, disks, networkInterfaces, metadata, serviceAccounts);
}
/**
@ -493,7 +469,7 @@ public class InstanceTemplate {
if (serviceAccounts.size() > 0)
toString.add("serviceAccounts", serviceAccounts);
toString.add("image", image);
toString.add("networkInterfaces", network);
toString.add("networkInterfaces", networkInterfaces);
return toString;
}

View File

@ -25,9 +25,6 @@ import java.beans.ConstructorProperties;
import java.net.URI;
import java.util.Date;
import static com.google.common.base.Optional.fromNullable;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Represents a kernel.
*
@ -41,9 +38,7 @@ public final class Kernel extends Resource {
"id", "creationTimestamp", "selfLink", "name", "description"
})
private Kernel(String id, Date creationTimestamp, URI selfLink, String name, String description) {
super(Kind.KERNEL, checkNotNull(id, "id of %s", name), fromNullable(creationTimestamp),
checkNotNull(selfLink, "selfLink of %s", name), checkNotNull(name, "name"),
fromNullable(description));
super(Kind.KERNEL, id, creationTimestamp, selfLink, name, description);
}
public static Builder builder() {

View File

@ -24,6 +24,7 @@ import com.google.common.base.Optional;
import com.google.common.collect.ImmutableSet;
import org.jclouds.collect.IterableWithMarker;
import java.beans.ConstructorProperties;
import java.net.URI;
import java.util.Iterator;
@ -45,6 +46,9 @@ public class ListPage<T> extends IterableWithMarker<T> {
private final String nextPageToken;
private final Iterable<T> items;
@ConstructorProperties({
"kind", "id", "selfLink", "nextPageToken", "items"
})
protected ListPage(Kind kind, String id, URI selfLink, String nextPageToken, Iterable<T> items) {
this.id = checkNotNull(id, "id");
this.kind = checkNotNull(kind, "kind of %id", id);
@ -72,7 +76,7 @@ public class ListPage<T> extends IterableWithMarker<T> {
@Override
public Iterator<T> iterator() {
return items.iterator();
return checkNotNull(items, "items").iterator();
}
/**

View File

@ -32,7 +32,6 @@ import java.util.Set;
import static com.google.common.base.Objects.equal;
import static com.google.common.base.Objects.toStringHelper;
import static com.google.common.base.Optional.fromNullable;
import static com.google.common.base.Preconditions.checkNotNull;
/**
@ -59,8 +58,7 @@ public final class MachineType extends Resource {
private MachineType(String id, Date creationTimestamp, URI selfLink, String name, String description,
int guestCpus, int memoryMb, int imageSpaceGb, List<EphemeralDisk> ephemeralDisks,
int maximumPersistentDisks, long maximumPersistentDisksSizeGb, Set<String> availableZone) {
super(Kind.MACHINE_TYPE, checkNotNull(id, "id of %s", name), fromNullable(creationTimestamp),
checkNotNull(selfLink, "selfLink of %s", name), checkNotNull(name, "name"), fromNullable(description));
super(Kind.MACHINE_TYPE, id, creationTimestamp, selfLink, name, description);
this.guestCpus = checkNotNull(guestCpus, "guestCpus of %s", name);
this.memoryMb = checkNotNull(memoryMb, "memoryMb of %s", name);
this.imageSpaceGb = checkNotNull(imageSpaceGb, "imageSpaceGb of %s", name);

View File

@ -49,8 +49,7 @@ public final class Network extends Resource {
})
protected Network(String id, Date creationTimestamp, URI selfLink, String name, String description,
String IPv4Range, String gatewayIPv4) {
super(Kind.NETWORK, checkNotNull(id, "id of %s", name), fromNullable(creationTimestamp), checkNotNull(selfLink,
"selfLink of %s", name), checkNotNull(name, "name"), fromNullable(description));
super(Kind.NETWORK, id, creationTimestamp, selfLink, name, description);
this.IPv4Range = checkNotNull(IPv4Range);
this.gatewayIPv4 = fromNullable(gatewayIPv4);
}

View File

@ -69,8 +69,7 @@ public class Operation extends Resource {
String statusMessage, String user, Integer progress, Date insertTime, Date startTime,
Date endTime, Integer httpErrorStatusCode, String httpErrorMessage, String operationType,
List<Error> errors) {
super(Kind.OPERATION, checkNotNull(id, "id of %s", name), fromNullable(creationTimestamp),
checkNotNull(selfLink, "selfLink of %s", name), checkNotNull(name, "name"), fromNullable(description));
super(Kind.OPERATION, id, creationTimestamp, selfLink, name, description);
this.targetLink = checkNotNull(targetLink, "targetLink of %s", name);
this.targetId = fromNullable(targetId);
this.clientOperationId = fromNullable(clientOperationId);
@ -81,7 +80,7 @@ public class Operation extends Resource {
this.insertTime = checkNotNull(insertTime, "insertTime of %s", name);
this.startTime = fromNullable(startTime);
this.endTime = fromNullable(endTime);
this.httpError = httpErrorStatusCode != null ?
this.httpError = httpErrorStatusCode != null && httpErrorStatusCode != 0 ?
Optional.of(HttpResponse.builder()
.statusCode(httpErrorStatusCode)
.message(httpErrorMessage)

View File

@ -33,7 +33,6 @@ import java.util.Set;
import static com.google.common.base.Objects.equal;
import static com.google.common.base.Objects.toStringHelper;
import static com.google.common.base.Optional.fromNullable;
import static com.google.common.base.Preconditions.checkNotNull;
/**
@ -51,8 +50,7 @@ public class Project extends Resource {
protected Project(String id, Date creationTimestamp, URI selfLink, String name, String description,
Map<String, String> commonInstanceMetadata, Set<Quota> quotas, Set<String> externalIpAddresses) {
super(Kind.PROJECT, checkNotNull(id, "id of %s", name), fromNullable(creationTimestamp), checkNotNull(selfLink,
"selfLink of %s", name), checkNotNull(name, "name"), fromNullable(description));
super(Kind.PROJECT, id, creationTimestamp, selfLink, name, description);
this.commonInstanceMetadata = commonInstanceMetadata == null ? ImmutableMap.<String,
String>of() : ImmutableMap.copyOf(commonInstanceMetadata);
this.quotas = quotas == null ? ImmutableSet.<Quota>of() : ImmutableSet.copyOf(quotas);

View File

@ -94,14 +94,14 @@ public class Resource {
@ConstructorProperties({
"kind", "id", "creationTimestamp", "selfLink", "name", "description"
})
protected Resource(Kind kind, String id, Optional<Date> creationTimestamp, URI selfLink, String name,
Optional<String> description) {
protected Resource(Kind kind, String id, Date creationTimestamp, URI selfLink, String name,
String description) {
this.kind = checkNotNull(kind, "kind");
this.id = id;
this.creationTimestamp = creationTimestamp;
this.selfLink = selfLink;
this.id = checkNotNull(id, "id");
this.creationTimestamp = fromNullable(creationTimestamp);
this.selfLink = checkNotNull(selfLink, "selfLink");
this.name = checkNotNull(name, "name");
this.description = description;
this.description = fromNullable(description);
}
/**
@ -152,7 +152,7 @@ public class Resource {
*/
@Override
public int hashCode() {
return Objects.hashCode(kind, id, name);
return Objects.hashCode(kind, name);
}
/**
@ -164,7 +164,6 @@ public class Resource {
if (obj == null || getClass() != obj.getClass()) return false;
Resource that = Resource.class.cast(obj);
return equal(this.kind, that.kind)
&& equal(this.id, that.id)
&& equal(this.name, that.name);
}
@ -259,8 +258,7 @@ public class Resource {
}
public Resource build() {
return new Resource(kind, id, fromNullable(creationTimestamp), selfLink, name,
fromNullable(description));
return new Resource(kind, id, creationTimestamp, selfLink, name, description);
}
public T fromResource(Resource in) {

View File

@ -59,8 +59,7 @@ public final class Zone extends Resource {
})
private Zone(String id, Date creationTimestamp, URI selfLink, String name, String description,
Status status, Set<MaintenanceWindow> maintenanceWindows, Set<String> availableMachineTypes) {
super(Kind.ZONE, checkNotNull(id, "id of %name", name), fromNullable(creationTimestamp),
checkNotNull(selfLink, "selfLink of %name", name), checkNotNull(name, "name"), fromNullable(description));
super(Kind.ZONE, id, creationTimestamp, selfLink, name, description);
this.status = checkNotNull(status, "status of %name", name);
this.maintenanceWindows = maintenanceWindows == null ? ImmutableSet.<MaintenanceWindow>of() : ImmutableSet
.copyOf(maintenanceWindows);

View File

@ -23,9 +23,12 @@ import org.jclouds.collect.PagedIterable;
import org.jclouds.googlecompute.domain.Firewall;
import org.jclouds.googlecompute.domain.ListPage;
import org.jclouds.googlecompute.domain.Operation;
import org.jclouds.googlecompute.options.FirewallOptions;
import org.jclouds.googlecompute.options.ListOptions;
import org.jclouds.javax.annotation.Nullable;
import java.net.URI;
/**
* Provides synchronous access to Firewalls via their REST API.
* <p/>
@ -49,32 +52,33 @@ public interface FirewallApi {
/**
* Creates a firewall resource in the specified project using the data included in the request.
*
*
* @param firewall the firewall to be inserted.
* @param name the name of the firewall to be inserted.
* @param network the network to which to add the firewall
* @param firewallOptions the options of the firewall to add
* @return an Operation resource. To check on the status of an operation, poll the Operations resource returned to
* you, and look for the status field.
*/
Operation create(Firewall firewall);
Operation createInNetwork(String name, URI network, FirewallOptions firewallOptions);
/**
* Updates the specified firewall resource with the data included in the request.
*
* @param firewallName the name firewall to be updated.
* @param firewall the new firewall.
* @param firewallOptions the new firewall.
* @return an Operation resource. To check on the status of an operation, poll the Operations resource returned to
* you, and look for the status field.
*/
Operation update(String firewallName, Firewall firewall);
Operation update(String firewallName, FirewallOptions firewallOptions);
/**
* Updates the specified firewall resource, with patch semantics, with the data included in the request.
*
* @param firewallName the name firewall to be updated.
* @param firewall the new firewall.
* @param firewallOptions the new firewall.
* @return an Operation resource. To check on the status of an operation, poll the Operations resource returned to
* you, and look for the status field.
*/
Operation patch(String firewallName, Firewall firewall);
Operation patch(String firewallName, FirewallOptions firewallOptions);
/**
* Deletes the specified image resource.

View File

@ -26,12 +26,16 @@ import org.jclouds.googlecompute.domain.ListPage;
import org.jclouds.googlecompute.domain.Operation;
import org.jclouds.googlecompute.functions.internal.PATCH;
import org.jclouds.googlecompute.functions.internal.ParseFirewalls;
import org.jclouds.googlecompute.handlers.FirewallBinder;
import org.jclouds.googlecompute.options.FirewallOptions;
import org.jclouds.googlecompute.options.ListOptions;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.oauth.v2.config.OAuthScopes;
import org.jclouds.oauth.v2.filters.OAuthAuthenticator;
import org.jclouds.rest.annotations.BinderParam;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.MapBinder;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser;
import org.jclouds.rest.annotations.SkipEncoding;
@ -49,6 +53,7 @@ import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import java.net.URI;
import static org.jclouds.Fallbacks.EmptyIterableWithMarkerOnNotFoundOr404;
import static org.jclouds.Fallbacks.EmptyPagedIterableOnNotFoundOr404;
@ -80,7 +85,7 @@ public interface FirewallAsyncApi {
ListenableFuture<Firewall> get(@PathParam("firewall") String firewallName);
/**
* @see FirewallApi#create(org.jclouds.googlecompute.domain.Firewall)
* @see FirewallApi#createInNetwork(String, java.net.URI, org.jclouds.googlecompute.options.FirewallOptions)
*/
@Named("Firewalls:insert")
@POST
@ -88,10 +93,13 @@ public interface FirewallAsyncApi {
@Produces(MediaType.APPLICATION_JSON)
@Path("/firewalls")
@OAuthScopes({COMPUTE_SCOPE})
ListenableFuture<Operation> create(@BinderParam(BindToJsonPayload.class) Firewall firewall);
@MapBinder(FirewallBinder.class)
ListenableFuture<Operation> createInNetwork(@PayloadParam("name") String name,
@PayloadParam("network") URI network,
@PayloadParam("options") FirewallOptions firewallOptions);
/**
* @see FirewallApi#update(String, org.jclouds.googlecompute.domain.Firewall)
* @see FirewallApi#update(String, org.jclouds.googlecompute.options.FirewallOptions)
*/
@Named("Firewalls:update")
@PUT
@ -100,10 +108,10 @@ public interface FirewallAsyncApi {
@Path("/firewalls/{firewall}")
@OAuthScopes({COMPUTE_SCOPE})
ListenableFuture<Operation> update(@PathParam("firewall") String firewallName,
@BinderParam(BindToJsonPayload.class) Firewall firewall);
@BinderParam(BindToJsonPayload.class) FirewallOptions firewallOptions);
/**
* @see FirewallApi#patch(String, org.jclouds.googlecompute.domain.Firewall)
* @see FirewallApi#patch(String, org.jclouds.googlecompute.options.FirewallOptions)
*/
@Named("Firewalls:patch")
@PATCH
@ -112,7 +120,7 @@ public interface FirewallAsyncApi {
@Path("/firewalls/{firewall}")
@OAuthScopes({COMPUTE_SCOPE})
ListenableFuture<Operation> patch(@PathParam("firewall") String firewallName,
@BinderParam(BindToJsonPayload.class) Firewall firewall);
@BinderParam(BindToJsonPayload.class) FirewallOptions firewallOptions);
/**
* @see FirewallApi#delete(String)

View File

@ -0,0 +1,61 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecompute.handlers;
import org.jclouds.googlecompute.options.FirewallOptions;
import org.jclouds.http.HttpRequest;
import org.jclouds.rest.MapBinder;
import org.jclouds.rest.binders.BindToJsonPayload;
import javax.inject.Inject;
import java.net.URI;
import java.util.Map;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* @author David Alves
*/
public class FirewallBinder implements MapBinder {
@Inject
private BindToJsonPayload jsonBinder;
/**
* {@inheritDoc}
*/
@Override
public <R extends HttpRequest> R bindToRequest(R request, Map<String, Object> postParams) {
FirewallOptions options = (FirewallOptions) checkNotNull(postParams.get("options"), "firewallOptions");
String name = (String) checkNotNull(postParams.get("name"), "name");
URI network = (URI) checkNotNull(postParams.get("network"), "network");
options.name(name);
options.network(network);
return bindToRequest(request, options);
}
/**
* {@inheritDoc}
*/
@Override
public <R extends HttpRequest> R bindToRequest(R request, Object input) {
return jsonBinder.bindToRequest(request, input);
}
}

View File

@ -29,8 +29,10 @@ import javax.inject.Inject;
import javax.inject.Named;
import java.net.URI;
import java.util.Map;
import java.util.Set;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.googlecompute.domain.InstanceTemplate.NetworkInterface;
/**
* @author David Alves
@ -44,10 +46,6 @@ public class InstanceBinder implements MapBinder {
@Named("machineTypes")
Function<String, URI> machineTypesToURI;
@Inject
@Named("networks")
Function<String, URI> networksToURI;
@Inject
@Named("zones")
Function<String, URI> zonesToURI;
@ -60,9 +58,6 @@ public class InstanceBinder implements MapBinder {
InstanceTemplate template = (InstanceTemplate) checkNotNull(postParams.get("template"), "template");
template.name(checkNotNull(postParams.get("name"), "name").toString());
template.zone(zonesToURI.apply((String) checkNotNull(postParams.get("zone"), "zone")));
if (template.getNetworkName() != null) {
template.network(networksToURI.apply(template.getNetworkName()));
}
if (template.getMachineTypeName() != null) {
template.machineType(machineTypesToURI.apply(template.getMachineTypeName()));

View File

@ -0,0 +1,168 @@
/*
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.googlecompute.options;
import com.google.common.collect.ImmutableSet;
import org.jclouds.googlecompute.domain.Firewall;
import java.net.URI;
import java.util.Set;
/**
* Options to create a firewall.
*
* @see Firewall
* @author David Alves
*/
public class FirewallOptions {
private String name;
private URI network;
private ImmutableSet.Builder<String> sourceRanges = ImmutableSet.builder();
private ImmutableSet.Builder<String> sourceTags = ImmutableSet.builder();
private ImmutableSet.Builder<String> targetTags = ImmutableSet.builder();
private ImmutableSet.Builder<Firewall.Rule> allowed = ImmutableSet.builder();
/**
* @see org.jclouds.googlecompute.domain.Firewall#getAllowed()
*/
public Set<Firewall.Rule> getAllowed() {
return allowed.build();
}
/**
* @see org.jclouds.googlecompute.domain.Firewall#getAllowed()
*/
public FirewallOptions addAllowedRule(Firewall.Rule allowedRule) {
this.allowed.add(allowedRule);
return this;
}
/**
* @see org.jclouds.googlecompute.domain.Firewall#getAllowed()
*/
public FirewallOptions allowedRules(Set<Firewall.Rule> allowedRules) {
this.allowed = ImmutableSet.builder();
this.allowed.addAll(allowedRules);
return this;
}
/**
* @see org.jclouds.googlecompute.domain.Firewall#getName()
*/
public FirewallOptions name(String name) {
this.name = name;
return this;
}
/**
* @see org.jclouds.googlecompute.domain.Firewall#getName()
*/
public String getName() {
return name;
}
/**
* @see org.jclouds.googlecompute.domain.Firewall#getNetwork()
*/
public FirewallOptions network(URI network) {
this.network = network;
return this;
}
/**
* @see org.jclouds.googlecompute.domain.Firewall#getNetwork()
*/
public URI getNetwork() {
return network;
}
/**
* @see org.jclouds.googlecompute.domain.Firewall#getSourceRanges()
*/
public Set<String> getSourceRanges() {
return sourceRanges.build();
}
/**
* @see org.jclouds.googlecompute.domain.Firewall#getSourceRanges()
*/
public FirewallOptions addSourceRange(String sourceRange) {
this.sourceRanges.add(sourceRange);
return this;
}
/**
* @see org.jclouds.googlecompute.domain.Firewall#getSourceRanges()
*/
public FirewallOptions sourceRanges(Set<String> sourceRanges) {
this.sourceRanges = ImmutableSet.builder();
this.sourceRanges.addAll(sourceRanges);
return this;
}
/**
* @see org.jclouds.googlecompute.domain.Firewall#getSourceTags()
*/
public Set<String> getSourceTags() {
return sourceTags.build();
}
/**
* @see org.jclouds.googlecompute.domain.Firewall#getSourceTags()
*/
public FirewallOptions addSourceTag(String sourceTag) {
this.sourceTags.add(sourceTag);
return this;
}
/**
* @see org.jclouds.googlecompute.domain.Firewall#getSourceTags()
*/
public FirewallOptions sourceTags(Set<String> sourceTags) {
this.sourceTags = ImmutableSet.builder();
return this;
}
/**
* @see org.jclouds.googlecompute.domain.Firewall#getTargetTags()
*/
public Set<String> getTargetTags() {
return targetTags.build();
}
/**
* @see org.jclouds.googlecompute.domain.Firewall#getTargetTags()
*/
public FirewallOptions addTargetTag(String targetTag) {
this.targetTags.add(targetTag);
return this;
}
/**
* @see org.jclouds.googlecompute.domain.Firewall#getTargetTags()
*/
public FirewallOptions targetTags(Set<String> targetTags) {
this.targetTags = ImmutableSet.builder();
this.targetTags.addAll(targetTags);
return this;
}
}

View File

@ -19,21 +19,32 @@
package org.jclouds.googlecompute.features;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableSet;
import org.jclouds.googlecompute.domain.Firewall;
import org.jclouds.googlecompute.internal.BaseGoogleComputeApiExpectTest;
import org.jclouds.googlecompute.options.FirewallOptions;
import org.jclouds.googlecompute.parse.ParseFirewallListTest;
import org.jclouds.googlecompute.parse.ParseFirewallTest;
import org.jclouds.googlecompute.parse.ParseOperationTest;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.io.Payload;
import org.testng.annotations.Test;
import javax.ws.rs.core.MediaType;
import java.io.IOException;
import java.net.URI;
import java.util.Set;
import static com.google.common.base.Joiner.on;
import static com.google.common.collect.Iterables.transform;
import static java.lang.String.format;
import static org.jclouds.googlecompute.GoogleComputeConstants.COMPUTE_READONLY_SCOPE;
import static org.jclouds.googlecompute.GoogleComputeConstants.COMPUTE_SCOPE;
import static org.jclouds.googlecompute.domain.Firewall.Rule.IPProtocol;
import static org.jclouds.io.Payloads.newStringPayload;
import static org.jclouds.util.Strings2.toStringAndClose;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
import static org.testng.AssertJUnit.assertNull;
@ -44,80 +55,122 @@ import static org.testng.AssertJUnit.assertNull;
@Test(groups = "unit")
public class FirewallApiExpectTest extends BaseGoogleComputeApiExpectTest {
public void testGetFirewallResponseIs2xx() throws Exception {
HttpRequest get = HttpRequest
public static final HttpRequest GET_FIREWALL_REQUEST = HttpRequest
.builder()
.method("GET")
.endpoint("https://www.googleapis" +
".com/compute/v1beta13/projects/google/firewalls/default-allow-internal")
".com/compute/v1beta13/projects/myproject/firewalls/jclouds-test")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
HttpResponse operationResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/firewall_get.json")).build();
public static HttpResponse GET_FIREWALL_RESPONSE = HttpResponse.builder().statusCode(200)
.payload(staticPayloadFromResource("/firewall_get.json")).build();
public void testGetFirewallResponseIs2xx() throws Exception {
FirewallApi api = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
TOKEN_RESPONSE, get, operationResponse).getFirewallApiForProject("google");
TOKEN_RESPONSE, GET_FIREWALL_REQUEST, GET_FIREWALL_RESPONSE).getFirewallApiForProject("myproject");
assertEquals(api.get("default-allow-internal"),
new ParseFirewallTest().expected());
assertEquals(api.get("jclouds-test"), new ParseFirewallTest().expected());
}
public static Payload firewallPayloadFirewallOfName(String firewallName,
String networkName,
Set<String> sourceRanges,
Set<String> sourceTags,
Set<String> targetTags,
Set<String> portRanges) throws IOException {
Function<String, String> addQuotes = new Function<String, String>() {
@Override
public String apply(String input) {
return "\"" + input + "\"";
}
};
String ports = on(",").skipNulls().join(transform(portRanges, addQuotes));
Payload payload = newStringPayload(
format(toStringAndClose(FirewallApiExpectTest.class.getResourceAsStream("/firewall_insert.json")),
firewallName,
networkName,
on(",").skipNulls().join(transform(sourceRanges, addQuotes)),
on(",").skipNulls().join(transform(sourceTags, addQuotes)),
on(",").skipNulls().join(transform(targetTags, addQuotes)),
ports,
ports));
payload.getContentMetadata().setContentType(MediaType.APPLICATION_JSON);
return payload;
}
public void testGetFirewallResponseIs4xx() throws Exception {
HttpRequest get = HttpRequest
.builder()
.method("GET")
.endpoint("https://www.googleapis" +
".com/compute/v1beta13/projects/google/firewalls/default-allow-internal")
".com/compute/v1beta13/projects/myproject/firewalls/jclouds-test")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
HttpResponse operationResponse = HttpResponse.builder().statusCode(404).build();
FirewallApi api = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
TOKEN_RESPONSE, get, operationResponse).getFirewallApiForProject("google");
TOKEN_RESPONSE, get, operationResponse).getFirewallApiForProject("myproject");
assertNull(api.get("default-allow-internal"));
assertNull(api.get("jclouds-test"));
}
public void testInsertFirewallResponseIs2xx() {
HttpRequest insert = HttpRequest
public void testInsertFirewallResponseIs2xx() throws IOException {
HttpRequest request = HttpRequest
.builder()
.method("POST")
.endpoint("https://www.googleapis.com/compute/v1beta13/projects/myproject/firewalls")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN)
.payload(payloadFromResourceWithContentType("/firewall_insert.json", MediaType.APPLICATION_JSON))
.payload(firewallPayloadFirewallOfName(
"myfw",
"default",
ImmutableSet.<String>of("10.0.1.0/32"),
ImmutableSet.<String>of("tag1"),
ImmutableSet.<String>of("tag2"),
ImmutableSet.<String>of("22", "23-24")))
.build();
HttpResponse insertFirewallResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/operation.json")).build();
FirewallApi api = requestsSendResponses(requestForScopes(COMPUTE_SCOPE),
TOKEN_RESPONSE, insert,
insertFirewallResponse).getFirewallApiForProject("myproject");
TOKEN_RESPONSE, request, insertFirewallResponse).getFirewallApiForProject("myproject");
assertEquals(api.create(Firewall.builder()
.name("myfw")
.network(URI.create("https://www.googleapis.com/compute/v1beta13/projects/myproject/networks/default"))
.addAllowed(Firewall.Rule.builder()
assertEquals(api.createInNetwork("myfw", URI.create("https://www.googleapis" +
".com/compute/v1beta13/projects/myproject/networks/default"),
new FirewallOptions()
.addAllowedRule(Firewall.Rule.builder()
.IPProtocol(IPProtocol.TCP)
.addPort(22)
.addPortRange(23, 24).build())
.addSourceTag("tag1")
.addSourceRange("10.0.1.0/32")
.addTargetTag("tag2")
.build()), new ParseOperationTest().expected());
.addTargetTag("tag2")), new ParseOperationTest().expected());
}
public void testUpdateFirewallResponseIs2xx() {
public void testUpdateFirewallResponseIs2xx() throws IOException {
HttpRequest update = HttpRequest
.builder()
.method("PUT")
.endpoint("https://www.googleapis.com/compute/v1beta13/projects/myproject/firewalls/myfw")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN)
.payload(payloadFromResourceWithContentType("/firewall_insert.json", MediaType.APPLICATION_JSON))
.payload(firewallPayloadFirewallOfName(
"myfw",
"default",
ImmutableSet.<String>of("10.0.1.0/32"),
ImmutableSet.<String>of("tag1"),
ImmutableSet.<String>of("tag2"),
ImmutableSet.<String>of("22", "23-24")))
.build();
HttpResponse updateFirewallResponse = HttpResponse.builder().statusCode(200)
@ -127,27 +180,34 @@ public class FirewallApiExpectTest extends BaseGoogleComputeApiExpectTest {
TOKEN_RESPONSE, update,
updateFirewallResponse).getFirewallApiForProject("myproject");
assertEquals(api.update("myfw", Firewall.builder()
assertEquals(api.update("myfw",
new FirewallOptions()
.name("myfw")
.network(URI.create("https://www.googleapis.com/compute/v1beta13/projects/myproject/networks/default"))
.addAllowed(Firewall.Rule.builder()
.network(URI.create("https://www.googleapis" +
".com/compute/v1beta13/projects/myproject/networks/default"))
.addAllowedRule(Firewall.Rule.builder()
.IPProtocol(IPProtocol.TCP)
.addPort(22)
.addPortRange(23, 24).build())
.addSourceTag("tag1")
.addSourceRange("10.0.1.0/32")
.addTargetTag("tag2")
.build()), new ParseOperationTest().expected());
.addTargetTag("tag2")), new ParseOperationTest().expected());
}
public void testPatchFirewallResponseIs2xx() {
public void testPatchFirewallResponseIs2xx() throws IOException {
HttpRequest update = HttpRequest
.builder()
.method("PATCH")
.endpoint("https://www.googleapis.com/compute/v1beta13/projects/myproject/firewalls/myfw")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN)
.payload(payloadFromResourceWithContentType("/firewall_insert.json", MediaType.APPLICATION_JSON))
.payload(firewallPayloadFirewallOfName(
"myfw",
"default",
ImmutableSet.<String>of("10.0.1.0/32"),
ImmutableSet.<String>of("tag1"),
ImmutableSet.<String>of("tag2"),
ImmutableSet.<String>of("22", "23-24")))
.build();
HttpResponse updateFirewallResponse = HttpResponse.builder().statusCode(200)
@ -157,17 +217,18 @@ public class FirewallApiExpectTest extends BaseGoogleComputeApiExpectTest {
TOKEN_RESPONSE, update,
updateFirewallResponse).getFirewallApiForProject("myproject");
assertEquals(api.patch("myfw", Firewall.builder()
assertEquals(api.patch("myfw",
new FirewallOptions()
.name("myfw")
.network(URI.create("https://www.googleapis.com/compute/v1beta13/projects/myproject/networks/default"))
.addAllowed(Firewall.Rule.builder()
.network(URI.create("https://www.googleapis" +
".com/compute/v1beta13/projects/myproject/networks/default"))
.addAllowedRule(Firewall.Rule.builder()
.IPProtocol(IPProtocol.TCP)
.addPort(22)
.addPortRange(23, 24).build())
.addSourceTag("tag1")
.addSourceRange("10.0.1.0/32")
.addTargetTag("tag2")
.build()), new ParseOperationTest().expected());
.addTargetTag("tag2")), new ParseOperationTest().expected());
}
public void testDeleteFirewallResponseIs2xx() {

View File

@ -24,8 +24,8 @@ import com.google.common.collect.Lists;
import org.jclouds.collect.PagedIterable;
import org.jclouds.googlecompute.domain.Firewall;
import org.jclouds.googlecompute.internal.BaseGoogleComputeApiLiveTest;
import org.jclouds.googlecompute.options.FirewallOptions;
import org.jclouds.googlecompute.options.ListOptions;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import java.util.List;
@ -41,26 +41,10 @@ import static org.testng.Assert.assertNotNull;
public class FirewallApiLiveTest extends BaseGoogleComputeApiLiveTest {
private static final String FIREWALL_NAME = "firewall-api-live-test-firewall";
private static final String FIREWALL_NETWORK_NAME = "firewall-api-live-test-network";
private static final String IPV4_RANGE = "10.0.0.0/8";
private static final int TIME_WAIT = 30;
private Firewall firewall;
@BeforeClass(groups = {"integration", "live"})
public void setupContext() {
super.setupContext();
firewall = Firewall.builder()
.name(FIREWALL_NAME)
.network(getDefaultNetworkUrl(getUserProject()))
.addAllowed(
Firewall.Rule.builder()
.IPProtocol(IPProtocol.TCP)
.addPort(22).build())
.addSourceRange("10.0.0.0/8")
.addSourceTag("tag1")
.addTargetTag("tag2")
.build();
}
private FirewallApi api() {
return context.getApi().getFirewallApiForProject(getUserProject());
}
@ -68,32 +52,51 @@ public class FirewallApiLiveTest extends BaseGoogleComputeApiLiveTest {
@Test(groups = "live")
public void testInsertFirewall() {
assertOperationDoneSucessfully(api().create(firewall), TIME_WAIT);
// need to create the network first
assertOperationDoneSucessfully(context.getApi().getNetworkApiForProject(getUserProject()).createInIPv4Range
(FIREWALL_NETWORK_NAME, IPV4_RANGE), TIME_WAIT);
FirewallOptions firewall = new FirewallOptions()
.addAllowedRule(
Firewall.Rule.builder()
.IPProtocol(IPProtocol.TCP)
.addPort(22).build())
.addSourceRange("10.0.0.0/8")
.addSourceTag("tag1")
.addTargetTag("tag2");
assertOperationDoneSucessfully(api().createInNetwork(FIREWALL_NAME, getNetworkUrl(getUserProject(),
FIREWALL_NETWORK_NAME), firewall), TIME_WAIT);
}
@Test(groups = "live", dependsOnMethods = "testInsertFirewall")
public void testUpdateFirewall() {
// replace 22 with 23
firewall = firewall.toBuilder()
.allowed(ImmutableSet.of(
FirewallOptions firewall = new FirewallOptions()
.name(FIREWALL_NAME)
.network(getNetworkUrl(getUserProject(),FIREWALL_NETWORK_NAME))
.addSourceRange("10.0.0.0/8")
.addSourceTag("tag1")
.addTargetTag("tag2")
.allowedRules(ImmutableSet.of(
Firewall.Rule.builder()
.IPProtocol(IPProtocol.TCP)
.addPort(23)
.build()))
.build();
.build()));
assertOperationDoneSucessfully(api().update(firewall.getName(), firewall), TIME_WAIT);
assertOperationDoneSucessfully(api().update(FIREWALL_NAME, firewall), TIME_WAIT);
}
@Test(groups = "live", dependsOnMethods = "testUpdateFirewall")
public void testPatchFirewall() {
// readd 22 with "patch" semantics
firewall = firewall.toBuilder()
.allowed(ImmutableSet.of(
FirewallOptions firewall = new FirewallOptions()
.name(FIREWALL_NAME)
.network(getNetworkUrl(getUserProject(),FIREWALL_NETWORK_NAME))
.allowedRules(ImmutableSet.of(
Firewall.Rule.builder()
.IPProtocol(IPProtocol.TCP)
.addPort(22)
@ -102,18 +105,36 @@ public class FirewallApiLiveTest extends BaseGoogleComputeApiLiveTest {
.IPProtocol(IPProtocol.TCP)
.addPort(23)
.build()))
.build();
.addSourceRange("10.0.0.0/8")
.addSourceTag("tag1")
.addTargetTag("tag2");
assertOperationDoneSucessfully(api().update(firewall.getName(), firewall), TIME_WAIT);
assertOperationDoneSucessfully(api().update(FIREWALL_NAME, firewall), TIME_WAIT);
}
@Test(groups = "live", dependsOnMethods = "testInsertFirewall")
@Test(groups = "live", dependsOnMethods = "testPatchFirewall")
public void testGetFirewall() {
FirewallOptions patchedFirewall = new FirewallOptions()
.name(FIREWALL_NAME)
.network(getNetworkUrl(getUserProject(), FIREWALL_NETWORK_NAME))
.allowedRules(ImmutableSet.of(
Firewall.Rule.builder()
.IPProtocol(IPProtocol.TCP)
.addPort(22)
.build(),
Firewall.Rule.builder()
.IPProtocol(IPProtocol.TCP)
.addPort(23)
.build()))
.addSourceRange("10.0.0.0/8")
.addSourceTag("tag1")
.addTargetTag("tag2");
Firewall firewall = api().get(FIREWALL_NAME);
assertNotNull(firewall);
assertFirewallEquals(firewall, this.firewall);
assertFirewallEquals(firewall, patchedFirewall);
}
@Test(groups = "live", dependsOnMethods = "testGetFirewall")
@ -126,23 +147,17 @@ public class FirewallApiLiveTest extends BaseGoogleComputeApiLiveTest {
assertEquals(firewallsAsList.size(), 1);
assertFirewallEquals(getOnlyElement(firewallsAsList),
firewall.toBuilder()
.addAllowed(Firewall.Rule.builder()
.IPProtocol(IPProtocol.TCP)
.addPort(23)
.build())
.build());
}
@Test(groups = "live", dependsOnMethods = "testListFirewall")
public void testDeleteFirewall() {
assertOperationDoneSucessfully(api().delete(FIREWALL_NAME), TIME_WAIT);
assertOperationDoneSucessfully(context.getApi().getNetworkApiForProject(getUserProject()).delete
(FIREWALL_NETWORK_NAME), TIME_WAIT);
}
private void assertFirewallEquals(Firewall result, Firewall expected) {
private void assertFirewallEquals(Firewall result, FirewallOptions expected) {
assertEquals(result.getName(), expected.getName());
assertEquals(getOnlyElement(result.getSourceRanges()), getOnlyElement(expected.getSourceRanges()));
assertEquals(getOnlyElement(result.getSourceTags()), getOnlyElement(expected.getSourceTags()));

View File

@ -39,6 +39,17 @@ import static org.testng.AssertJUnit.assertNull;
@Test(groups = "unit")
public class ImageApiExpectTest extends BaseGoogleComputeApiExpectTest {
public static final HttpRequest LIST_PROJECT_IMAGES_REQUEST = HttpRequest
.builder()
.method("GET")
.endpoint("https://www.googleapis" +
".com/compute/v1beta13/projects/myproject/images")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
public static final HttpResponse LIST_PROJECT_IMAGES_RESPONSE = HttpResponse.builder().statusCode(200)
.payload(staticPayloadFromResource("/image_list.json")).build();
public void testGetImageResponseIs2xx() throws Exception {
HttpRequest get = HttpRequest
.builder()
@ -112,37 +123,21 @@ public class ImageApiExpectTest extends BaseGoogleComputeApiExpectTest {
}
public void testListImagesResponseIs2xx() {
HttpRequest list = HttpRequest
.builder()
.method("GET")
.endpoint("https://www.googleapis" +
".com/compute/v1beta13/projects/myproject/images")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
HttpResponse operationResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/image_list.json")).build();
ImageApi imageApi = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
TOKEN_RESPONSE, list, operationResponse).getImageApiForProject("myproject");
TOKEN_RESPONSE, LIST_PROJECT_IMAGES_REQUEST, LIST_PROJECT_IMAGES_RESPONSE).getImageApiForProject
("myproject");
assertEquals(imageApi.listFirstPage().toString(),
new ParseImageListTest().expected().toString());
}
public void testListImagesResponseIs4xx() {
HttpRequest list = HttpRequest
.builder()
.method("GET")
.endpoint("https://www.googleapis" +
".com/compute/v1beta13/projects/myproject/images")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
HttpResponse operationResponse = HttpResponse.builder().statusCode(404).build();
ImageApi imageApi = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
TOKEN_RESPONSE, list, operationResponse).getImageApiForProject("myproject");
TOKEN_RESPONSE, LIST_PROJECT_IMAGES_REQUEST, operationResponse).getImageApiForProject("myproject");
assertTrue(imageApi.list().concat().isEmpty());
}

View File

@ -33,6 +33,7 @@ import org.testng.annotations.Test;
import javax.ws.rs.core.MediaType;
import java.net.URI;
import static java.net.URI.create;
import static org.jclouds.googlecompute.GoogleComputeConstants.COMPUTE_READONLY_SCOPE;
import static org.jclouds.googlecompute.GoogleComputeConstants.COMPUTE_SCOPE;
import static org.testng.Assert.assertEquals;
@ -45,40 +46,50 @@ import static org.testng.AssertJUnit.assertNull;
@Test(groups = "unit")
public class InstanceApiExpectTest extends BaseGoogleComputeApiExpectTest {
public void testGetInstanceResponseIs2xx() throws Exception {
HttpRequest get = HttpRequest
public static final HttpRequest GET_INSTANCE_REQUEST = HttpRequest
.builder()
.method("GET")
.endpoint("https://www.googleapis" +
".com/compute/v1beta13/projects/myproject/instances/test-instance")
".com/compute/v1beta13/projects/myproject/instances/test-1")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
HttpResponse operationResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/instance_get.json")).build();
InstanceApi api = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
TOKEN_RESPONSE, get, operationResponse).getInstanceApiForProject("myproject");
public static final HttpResponse GET_INSTANCE_RESPONSE = HttpResponse.builder().statusCode(200)
.payload(staticPayloadFromResource("/instance_get.json")).build();
assertEquals(api.get("test-instance"),
new ParseInstanceTest().expected());
public static final HttpRequest LIST_INSTANCES_REQUEST = HttpRequest
.builder()
.method("GET")
.endpoint("https://www.googleapis" +
".com/compute/v1beta13/projects/myproject/instances")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
public static final HttpResponse LIST_INSTANCES_RESPONSE = HttpResponse.builder().statusCode(200)
.payload(staticPayloadFromResource("/instance_list.json")).build();
public static final HttpResponse CREATE_INSTANCE_RESPONSE = HttpResponse.builder().statusCode(200)
.payload(staticPayloadFromResource("/operation.json")).build();
public void testGetInstanceResponseIs2xx() throws Exception {
InstanceApi api = requestsSendResponses(
requestForScopes(COMPUTE_READONLY_SCOPE), TOKEN_RESPONSE,
GET_INSTANCE_REQUEST, GET_INSTANCE_RESPONSE).getInstanceApiForProject("myproject");
assertEquals(api.get("test-1"), new ParseInstanceTest().expected());
}
public void testGetInstanceResponseIs4xx() throws Exception {
HttpRequest get = HttpRequest
.builder()
.method("GET")
.endpoint("https://www.googleapis" +
".com/compute/v1beta13/projects/myproject/instances/test-instance")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
HttpResponse operationResponse = HttpResponse.builder().statusCode(404).build();
InstanceApi api = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
TOKEN_RESPONSE, get, operationResponse).getInstanceApiForProject("myproject");
TOKEN_RESPONSE, GET_INSTANCE_REQUEST, operationResponse).getInstanceApiForProject("myproject");
assertNull(api.get("test-instance"));
assertNull(api.get("test-1"));
}
public void testGetInstanceSerialPortOutput() throws Exception {
@ -86,7 +97,7 @@ public class InstanceApiExpectTest extends BaseGoogleComputeApiExpectTest {
.builder()
.method("GET")
.endpoint("https://www.googleapis" +
".com/compute/v1beta13/projects/myproject/instances/test-instance/serialPort")
".com/compute/v1beta13/projects/myproject/instances/test-1/serialPort")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
@ -97,7 +108,7 @@ public class InstanceApiExpectTest extends BaseGoogleComputeApiExpectTest {
InstanceApi api = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
TOKEN_RESPONSE, get, operationResponse).getInstanceApiForProject("myproject");
assertEquals(api.getSerialPortOutput("test-instance"), new ParseInstanceSerialOutputTest().expected());
assertEquals(api.getSerialPortOutput("test-1"), new ParseInstanceSerialOutputTest().expected());
}
public void testInsertInstanceResponseIs2xxNoOptions() {
@ -110,18 +121,15 @@ public class InstanceApiExpectTest extends BaseGoogleComputeApiExpectTest {
.payload(payloadFromResourceWithContentType("/instance_insert_simple.json", MediaType.APPLICATION_JSON))
.build();
HttpResponse insertInstanceResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/operation.json")).build();
InstanceApi api = requestsSendResponses(requestForScopes(COMPUTE_SCOPE),
TOKEN_RESPONSE, insert,
insertInstanceResponse).getInstanceApiForProject("myproject");
CREATE_INSTANCE_RESPONSE).getInstanceApiForProject("myproject");
assertEquals(api.createInZone("test-instance",
InstanceTemplate.builder()
.forMachineTypeAndNetwork("n1-standard-1", "default"),
"us-central1-a"),
new ParseOperationTest().expected());
InstanceTemplate options = InstanceTemplate.builder().forMachineType("n1-standard-1")
.addNetworkInterface(URI.create("https://www.googleapis" +
".com/compute/v1beta13/projects/myproject/networks/default"));
assertEquals(api.createInZone("test-1", options, "us-central1-a"), new ParseOperationTest().expected());
}
public void testInsertInstanceResponseIs2xxAllOptions() {
@ -140,14 +148,19 @@ public class InstanceApiExpectTest extends BaseGoogleComputeApiExpectTest {
InstanceApi api = requestsSendResponses(requestForScopes(COMPUTE_SCOPE),
TOKEN_RESPONSE, insert, insertInstanceResponse).getInstanceApiForProject("myproject");
Instance instance = new ParseInstanceTest().expected();
InstanceTemplate options = new InstanceTemplate.Builder()
.fromInstance(instance)
.network(instance.getNetworkInterfaces().iterator().next().getNetwork())
InstanceTemplate options = InstanceTemplate.builder().forMachineType("n1-standard-1")
.addNetworkInterface(URI.create("https://www.googleapis" +
".com/compute/v1beta13/projects/myproject/networks/default"), Instance.NetworkInterface.AccessConfig.Type.ONE_TO_ONE_NAT)
.description("desc")
.image(URI.create("https://www.googleapis" +
".com/compute/v1beta13/projects/google/images/gcel-12-04-v20121106"))
.addDisk(InstanceTemplate.PersistentDisk.Mode.READ_WRITE,
URI.create("https://www.googleapis.com/compute/v1beta13/projects/myproject/disks/test"));
create("https://www.googleapis.com/compute/v1beta13/projects/myproject/disks/test"))
.addTag("aTag")
.addServiceAccount(Instance.ServiceAccount.builder().email("default").addScopes("myscope").build())
.addMetadata("aKey", "aValue");
assertEquals(api.createInZone(instance.getName(), options, "us-central1-a"),
assertEquals(api.createInZone("test-0", options, "us-central1-a"),
new ParseOperationTest().expected());
}
@ -156,7 +169,7 @@ public class InstanceApiExpectTest extends BaseGoogleComputeApiExpectTest {
.builder()
.method("DELETE")
.endpoint("https://www.googleapis" +
".com/compute/v1beta13/projects/myproject/instances/test-instance")
".com/compute/v1beta13/projects/myproject/instances/test-1")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
@ -166,7 +179,7 @@ public class InstanceApiExpectTest extends BaseGoogleComputeApiExpectTest {
InstanceApi api = requestsSendResponses(requestForScopes(COMPUTE_SCOPE),
TOKEN_RESPONSE, delete, deleteResponse).getInstanceApiForProject("myproject");
assertEquals(api.delete("test-instance"),
assertEquals(api.delete("test-1"),
new ParseOperationTest().expected());
}
@ -175,7 +188,7 @@ public class InstanceApiExpectTest extends BaseGoogleComputeApiExpectTest {
.builder()
.method("DELETE")
.endpoint("https://www.googleapis" +
".com/compute/v1beta13/projects/myproject/instances/test-instance")
".com/compute/v1beta13/projects/myproject/instances/test-1")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
@ -184,23 +197,14 @@ public class InstanceApiExpectTest extends BaseGoogleComputeApiExpectTest {
InstanceApi api = requestsSendResponses(requestForScopes(COMPUTE_SCOPE),
TOKEN_RESPONSE, delete, deleteResponse).getInstanceApiForProject("myproject");
assertNull(api.delete("test-instance"));
assertNull(api.delete("test-1"));
}
public void testListInstancesResponseIs2xx() {
HttpRequest list = HttpRequest
.builder()
.method("GET")
.endpoint("https://www.googleapis" +
".com/compute/v1beta13/projects/myproject/instances")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
HttpResponse operationResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/instance_list.json")).build();
InstanceApi api = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
TOKEN_RESPONSE, list, operationResponse).getInstanceApiForProject("myproject");
InstanceApi api = requestsSendResponses(
requestForScopes(COMPUTE_READONLY_SCOPE), TOKEN_RESPONSE,
LIST_INSTANCES_REQUEST, LIST_INSTANCES_RESPONSE).getInstanceApiForProject("myproject");
assertEquals(api.listFirstPage().toString(),
new ParseInstanceListTest().expected().toString());

View File

@ -39,8 +39,10 @@ import static org.testng.Assert.assertNotNull;
*/
public class InstanceApiLiveTest extends BaseGoogleComputeApiLiveTest {
private static final String INSTANCE_NETWORK_NAME = "instance-api-live-test-network";
private static final String INSTANCE_NAME = "instance-api-live-test-instance";
private static final String DISK_NAME = "instance-live-test-disk";
private static final String IPV4_RANGE = "10.0.0.0/8";
private static final int TIME_WAIT = 600;
private InstanceTemplate instance;
@ -49,8 +51,9 @@ public class InstanceApiLiveTest extends BaseGoogleComputeApiLiveTest {
public void setupContext() {
super.setupContext();
instance = InstanceTemplate.builder()
.forMachineTypeAndNetwork(getDefaultMachineTypekUrl(getUserProject()),
getDefaultNetworkUrl(getUserProject()))
.forMachineType(getDefaultMachineTypekUrl(getUserProject()))
.addNetworkInterface(getNetworkUrl(getUserProject(), INSTANCE_NETWORK_NAME),
Instance.NetworkInterface.AccessConfig.Type.ONE_TO_ONE_NAT)
.addMetadata("mykey", "myvalue")
.addTag("atag")
.description("a description")
@ -65,6 +68,10 @@ public class InstanceApiLiveTest extends BaseGoogleComputeApiLiveTest {
@Test(groups = "live")
public void testInsertInstance() {
// need to create the network first
assertOperationDoneSucessfully(context.getApi().getNetworkApiForProject(getUserProject()).createInIPv4Range
(INSTANCE_NETWORK_NAME, IPV4_RANGE), TIME_WAIT);
assertOperationDoneSucessfully(context.getApi().getDiskApiForProject(getUserProject()).createInZone
("instance-live-test-disk", 1, getDefaultZoneUrl(getUserProject())), TIME_WAIT);
@ -72,15 +79,6 @@ public class InstanceApiLiveTest extends BaseGoogleComputeApiLiveTest {
}
@Test(groups = "live", dependsOnMethods = "testInsertInstance")
public void testInsertInstanceCopy() {
Instance instance = api().get(INSTANCE_NAME);
InstanceTemplate copy = InstanceTemplate.fromInstance(instance);
copy.network(instance.getNetworkInterfaces().iterator().next().getNetwork());
assertOperationDoneSucessfully(api().createInZone(INSTANCE_NAME + "-2", copy, DEFAULT_ZONE_NAME), TIME_WAIT);
}
@Test(groups = "live", dependsOnMethods = "testInsertInstance")
public void testGetInstance() {
@ -103,13 +101,14 @@ public class InstanceApiLiveTest extends BaseGoogleComputeApiLiveTest {
}
@Test(groups = "live", dependsOnMethods = {"testListInstance", "testInsertInstanceCopy"})
@Test(groups = "live", dependsOnMethods = "testListInstance")
public void testDeleteInstance() {
assertOperationDoneSucessfully(api().delete(INSTANCE_NAME), TIME_WAIT);
assertOperationDoneSucessfully(api().delete(INSTANCE_NAME + "-2"), TIME_WAIT);
assertOperationDoneSucessfully(context.getApi().getDiskApiForProject(getUserProject()).delete(DISK_NAME),
TIME_WAIT);
assertOperationDoneSucessfully(context.getApi().getNetworkApiForProject(getUserProject()).delete
(INSTANCE_NETWORK_NAME), TIME_WAIT);
}
private void assertInstanceEquals(Instance result, InstanceTemplate expected) {

View File

@ -37,6 +37,18 @@ import static org.testng.Assert.assertTrue;
@Test(groups = "unit")
public class MachineTypeApiExpectTest extends BaseGoogleComputeApiExpectTest {
public static final HttpRequest LIST_MACHINE_TYPES_REQUEST = HttpRequest
.builder()
.method("GET")
.endpoint("https://www.googleapis.com/compute/v1beta13/projects/myproject/machineTypes")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
public static final HttpResponse LIST_MACHINE_TYPES_RESPONSE = HttpResponse.builder()
.statusCode(200)
.payload(staticPayloadFromResource("/machinetype_list.json"))
.build();
public void testGetMachineTypeResponseIs2xx() throws Exception {
HttpRequest get = HttpRequest
.builder()
@ -74,37 +86,21 @@ public class MachineTypeApiExpectTest extends BaseGoogleComputeApiExpectTest {
}
public void testListMachineTypeNoOptionsResponseIs2xx() throws Exception {
HttpRequest list = HttpRequest
.builder()
.method("GET")
.endpoint("https://www.googleapis" +
".com/compute/v1beta13/projects/myproject/machineTypes")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
HttpResponse operationResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/machinetype_list.json")).build();
MachineTypeApi machineTypeApi = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
TOKEN_RESPONSE, list, operationResponse).getMachineTypeApiForProject("myproject");
TOKEN_RESPONSE, LIST_MACHINE_TYPES_REQUEST, LIST_MACHINE_TYPES_RESPONSE).getMachineTypeApiForProject
("myproject");
assertEquals(machineTypeApi.listFirstPage().toString(),
new ParseMachineTypeListTest().expected().toString());
}
public void testLisOperationWithPaginationOptionsResponseIs4xx() {
HttpRequest list = HttpRequest
.builder()
.method("GET")
.endpoint("https://www.googleapis" +
".com/compute/v1beta13/projects/myproject/machineTypes")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
HttpResponse operationResponse = HttpResponse.builder().statusCode(404).build();
MachineTypeApi machineTypeApi = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
TOKEN_RESPONSE, list, operationResponse).getMachineTypeApiForProject("myproject");
TOKEN_RESPONSE, LIST_MACHINE_TYPES_REQUEST, operationResponse).getMachineTypeApiForProject("myproject");
assertTrue(machineTypeApi.list().concat().isEmpty());
}

View File

@ -41,21 +41,22 @@ import static org.testng.AssertJUnit.assertNull;
@Test(groups = "unit")
public class NetworkApiExpectTest extends BaseGoogleComputeApiExpectTest {
public void testGetNetworkResponseIs2xx() throws Exception {
HttpRequest get = HttpRequest
public static final HttpRequest GET_NETWORK_REQUEST = HttpRequest
.builder()
.method("GET")
.endpoint("https://www.googleapis.com/compute/v1beta13/projects/myproject/networks/default")
.endpoint("https://www.googleapis.com/compute/v1beta13/projects/myproject/networks/jclouds-test")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
HttpResponse operationResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/network_get.json")).build();
public static final HttpResponse GET_NETWORK_RESPONSE = HttpResponse.builder().statusCode(200)
.payload(staticPayloadFromResource("/network_get.json")).build();
public void testGetNetworkResponseIs2xx() throws Exception {
NetworkApi api = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
TOKEN_RESPONSE, get, operationResponse).getNetworkApiForProject("myproject");
TOKEN_RESPONSE, GET_NETWORK_REQUEST, GET_NETWORK_RESPONSE).getNetworkApiForProject("myproject");
assertEquals(api.get("default"),
assertEquals(api.get("jclouds-test"),
new ParseNetworkTest().expected());
}
@ -63,7 +64,7 @@ public class NetworkApiExpectTest extends BaseGoogleComputeApiExpectTest {
HttpRequest get = HttpRequest
.builder()
.method("GET")
.endpoint("https://www.googleapis.com/compute/v1beta13/projects/myproject/networks/default")
.endpoint("https://www.googleapis.com/compute/v1beta13/projects/myproject/networks/jclouds-test")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
@ -72,7 +73,7 @@ public class NetworkApiExpectTest extends BaseGoogleComputeApiExpectTest {
NetworkApi api = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
TOKEN_RESPONSE, get, operationResponse).getNetworkApiForProject("myproject");
assertNull(api.get("default"));
assertNull(api.get("jclouds-test"));
}
public void testInsertNetworkResponseIs2xx() {
@ -100,7 +101,7 @@ public class NetworkApiExpectTest extends BaseGoogleComputeApiExpectTest {
.builder()
.method("DELETE")
.endpoint("https://www.googleapis" +
".com/compute/v1beta13/projects/myproject/networks/default")
".com/compute/v1beta13/projects/myproject/networks/jclouds-test")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
@ -110,7 +111,7 @@ public class NetworkApiExpectTest extends BaseGoogleComputeApiExpectTest {
NetworkApi api = requestsSendResponses(requestForScopes(COMPUTE_SCOPE),
TOKEN_RESPONSE, delete, deleteResponse).getNetworkApiForProject("myproject");
assertEquals(api.delete("default"),
assertEquals(api.delete("jclouds-test"),
new ParseOperationTest().expected());
}
@ -119,7 +120,7 @@ public class NetworkApiExpectTest extends BaseGoogleComputeApiExpectTest {
.builder()
.method("DELETE")
.endpoint("https://www.googleapis" +
".com/compute/v1beta13/projects/myproject/networks/default")
".com/compute/v1beta13/projects/myproject/networks/jclouds-test")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
@ -128,7 +129,7 @@ public class NetworkApiExpectTest extends BaseGoogleComputeApiExpectTest {
NetworkApi api = requestsSendResponses(requestForScopes(COMPUTE_SCOPE),
TOKEN_RESPONSE, delete, deleteResponse).getNetworkApiForProject("myproject");
assertNull(api.delete("default"));
assertNull(api.delete("jclouds-test"));
}
public void testListNetworksResponseIs2xx() {

View File

@ -42,38 +42,33 @@ public class OperationApiExpectTest extends BaseGoogleComputeApiExpectTest {
private static final String OPERATIONS_URL_PREFIX = "https://www.googleapis" +
".com/compute/v1beta13/projects/myproject/operations";
public void testGetOperationResponseIs2xx() throws Exception {
HttpRequest get = HttpRequest
public static final HttpRequest GET_OPERATION_REQUEST = HttpRequest
.builder()
.method("GET")
.endpoint(OPERATIONS_URL_PREFIX + "/operation-1352178598164-4cdcc9d031510-4aa46279")
.endpoint(OPERATIONS_URL_PREFIX + "/operation-1354084865060-4cf88735faeb8-bbbb12cb")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
HttpResponse operationResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/operation.json")).build();
public static final HttpResponse GET_OPERATION_RESPONSE = HttpResponse.builder().statusCode(200)
.payload(staticPayloadFromResource("/operation.json")).build();
public void testGetOperationResponseIs2xx() throws Exception {
OperationApi operationApi = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
TOKEN_RESPONSE, get, operationResponse).getOperationApiForProject("myproject");
TOKEN_RESPONSE, GET_OPERATION_REQUEST, GET_OPERATION_RESPONSE).getOperationApiForProject("myproject");
assertEquals(operationApi.get("operation-1352178598164-4cdcc9d031510-4aa46279"),
assertEquals(operationApi.get("operation-1354084865060-4cf88735faeb8-bbbb12cb"),
new ParseOperationTest().expected());
}
public void testGetOperationResponseIs4xx() throws Exception {
HttpRequest get = HttpRequest
.builder()
.method("GET")
.endpoint(OPERATIONS_URL_PREFIX + "/operation-1352178598164-4cdcc9d031510-4aa46279")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
HttpResponse operationResponse = HttpResponse.builder().statusCode(404).build();
OperationApi operationApi = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
TOKEN_RESPONSE, get, operationResponse).getOperationApiForProject("myproject");
TOKEN_RESPONSE, GET_OPERATION_REQUEST, operationResponse).getOperationApiForProject("myproject");
assertNull(operationApi.get("operation-1352178598164-4cdcc9d031510-4aa46279"));
assertNull(operationApi.get("operation-1354084865060-4cf88735faeb8-bbbb12cb"));
}
public void testDeleteOperationResponseIs2xx() throws Exception {

View File

@ -39,70 +39,62 @@ public class ZoneApiExpectTest extends BaseGoogleComputeApiExpectTest {
public static final String ZONES_URL_PREFIX = "https://www.googleapis.com/compute/v1beta13/projects/google/zones";
public void testGetZoneResponseIs2xx() throws Exception {
HttpRequest get = HttpRequest
public static final HttpRequest GET_ZONE_REQ = HttpRequest
.builder()
.method("GET")
.endpoint(ZONES_URL_PREFIX + "/us-central2-a")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
public static final HttpRequest LIST_ZONES_REQ = HttpRequest
.builder()
.method("GET")
.endpoint(ZONES_URL_PREFIX)
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
public static final HttpResponse LIST_ZONES_RESPONSE = HttpResponse.builder().statusCode(200)
.payload(staticPayloadFromResource("/zone_list.json")).build();
public void testGetZoneResponseIs2xx() throws Exception {
HttpResponse operationResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/zone_get.json")).build();
ZoneApi api = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
TOKEN_RESPONSE, get, operationResponse).getZoneApiForProject("google");
TOKEN_RESPONSE, GET_ZONE_REQ, operationResponse).getZoneApiForProject("google");
assertEquals(api.get("us-central2-a"),
new ParseZoneTest().expected());
}
public void testGetZoneResponseIs4xx() throws Exception {
HttpRequest get = HttpRequest
.builder()
.method("GET")
.endpoint(ZONES_URL_PREFIX + "/us-central2-a")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
HttpResponse operationResponse = HttpResponse.builder().statusCode(404).build();
ZoneApi api = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
TOKEN_RESPONSE, get, operationResponse).getZoneApiForProject("google");
TOKEN_RESPONSE, GET_ZONE_REQ, operationResponse).getZoneApiForProject("google");
assertNull(api.get("us-central2-a"));
}
public void testListZoneNoOptionsResponseIs2xx() throws Exception {
HttpRequest list = HttpRequest
.builder()
.method("GET")
.endpoint(ZONES_URL_PREFIX)
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
HttpResponse operationResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResource("/zone_list.json")).build();
ZoneApi api = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
TOKEN_RESPONSE, list, operationResponse).getZoneApiForProject("google");
TOKEN_RESPONSE, LIST_ZONES_REQ, LIST_ZONES_RESPONSE).getZoneApiForProject("google");
assertEquals(api.listFirstPage().toString(),
new ParseZoneListTest().expected().toString());
}
public void testListZoneWithPaginationOptionsResponseIs4xx() {
HttpRequest list = HttpRequest
.builder()
.method("GET")
.endpoint(ZONES_URL_PREFIX)
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + TOKEN).build();
HttpResponse operationResponse = HttpResponse.builder().statusCode(404).build();
ZoneApi api = requestsSendResponses(requestForScopes(COMPUTE_READONLY_SCOPE),
TOKEN_RESPONSE, list, operationResponse).getZoneApiForProject("google");
TOKEN_RESPONSE, LIST_ZONES_REQ, operationResponse).getZoneApiForProject("google");
assertTrue(api.list().concat().isEmpty());
}

View File

@ -50,10 +50,10 @@ public class BaseGoogleComputeApiLiveTest extends BaseContextLiveTest<RestContex
protected static final String API_URL_PREFIX = "https://www.googleapis.com/compute/v1beta13/projects/";
protected static final String ZONE_API_URL_SUFFIX = "/zones/";
protected static final String DEFAULT_ZONE_NAME = "us-east1-a";
protected static final String DEFAULT_ZONE_NAME = "us-central1-a";
protected static final String NETWORK_API_URL_SUFFIX = "/networks/";
protected static final String DEFAULT_NETWORK_NAME = "default";
protected static final String DEFAULT_NETWORK_NAME = "live-test-network";
protected static final String MACHINE_TYPE_API_URL_SUFFIX = "/machineTypes/";
protected static final String DEFAULT_MACHINE_TYPE_NAME = "n1-standard-1";

View File

@ -18,26 +18,31 @@
*/
package org.jclouds.googlecompute.internal;
import static com.google.common.base.Charsets.UTF_8;
import static com.google.common.io.BaseEncoding.base64Url;
import java.net.URI;
import java.util.Properties;
import javax.ws.rs.core.MediaType;
import com.google.common.base.Joiner;
import com.google.common.base.Supplier;
import com.google.common.base.Throwables;
import com.google.common.base.Ticker;
import com.google.inject.Binder;
import com.google.inject.Module;
import com.google.inject.TypeLiteral;
import org.jclouds.collect.PagedIterable;
import org.jclouds.collect.PagedIterables;
import org.jclouds.googlecompute.domain.ListPage;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.io.Payload;
import org.jclouds.oauth.v2.OAuthConstants;
import org.jclouds.rest.internal.BaseRestApiExpectTest;
import org.jclouds.util.Strings2;
import com.google.common.base.Joiner;
import com.google.common.base.Ticker;
import com.google.inject.Binder;
import com.google.inject.Module;
import javax.ws.rs.core.MediaType;
import java.io.IOException;
import java.net.URI;
import java.util.Properties;
import java.util.concurrent.atomic.AtomicInteger;
import static com.google.common.base.Charsets.UTF_8;
import static com.google.common.io.BaseEncoding.base64Url;
/**
* @author Adrian Cole
@ -78,6 +83,15 @@ public class BaseGoogleComputeExpectTest<T> extends BaseRestApiExpectTest<T> {
return 0;
}
});
// predictable node names
final AtomicInteger suffix = new AtomicInteger();
binder.bind(new TypeLiteral<Supplier<String>>() {
}).toInstance(new Supplier<String>() {
@Override
public String get() {
return suffix.getAndIncrement() + "";
}
});
}
};
}
@ -115,5 +129,14 @@ public class BaseGoogleComputeExpectTest<T> extends BaseRestApiExpectTest<T> {
return PagedIterables.of(list);
}
protected static Payload staticPayloadFromResource(String resource) {
try {
return payloadFromString(Strings2.toStringAndClose(BaseGoogleComputeExpectTest.class.getResourceAsStream
(resource)));
} catch (IOException e) {
throw Throwables.propagate(e);
}
}
}

View File

@ -47,11 +47,10 @@ public class ParseFirewallTest extends BaseGoogleComputeParseTest<Firewall> {
return Firewall.builder()
.id("12862241031274216284")
.creationTimestamp(new SimpleDateFormatDateService().iso8601DateParse("2012-04-13T03:05:02.855"))
.selfLink(URI.create("https://www.googleapis.com/compute/v1beta13/projects/google/firewalls/default" +
"-allow-internal"))
.name("default-allow-internal")
.selfLink(URI.create("https://www.googleapis.com/compute/v1beta13/projects/myproject/firewalls/jclouds-test"))
.name("jclouds-test")
.description("Internal traffic from default allowed")
.network(URI.create("https://www.googleapis.com/compute/v1beta13/projects/google/networks/default"))
.network(URI.create("https://www.googleapis.com/compute/v1beta13/projects/myproject/networks/jclouds-test"))
.addSourceRange("10.0.0.0/8")
.addAllowed(Firewall.Rule.builder()
.IPProtocol(IPProtocol.TCP)

View File

@ -45,11 +45,11 @@ public class ParseInstanceTest extends BaseGoogleComputeParseTest<Instance> {
.id("13051190678907570425")
.creationTimestamp(new SimpleDateFormatDateService().iso8601DateParse("2012-11-25T23:48:20.758"))
.selfLink(URI.create("https://www.googleapis" +
".com/compute/v1beta13/projects/myproject/instances/test-instance"))
".com/compute/v1beta13/projects/myproject/instances/test-0"))
.description("desc")
.name("test-instance")
.name("test-0")
.image(URI.create("https://www.googleapis" +
".com/compute/v1beta13/projects/google/images/ubuntu-12-04-v20120912"))
".com/compute/v1beta13/projects/google/images/gcel-12-04-v20121106"))
.machineType(URI.create("https://www.googleapis.com/compute/v1beta13/projects/myproject/machineTypes/n1" +
"-standard-1"))
.status(Instance.Status.RUNNING)

View File

@ -43,7 +43,7 @@ public class ParseNetworkTest extends BaseGoogleComputeParseTest<Network> {
return Network.builder()
.id("13024414170909937976")
.creationTimestamp(new SimpleDateFormatDateService().iso8601DateParse("2012-10-24T20:13:19.967"))
.selfLink(URI.create("https://www.googleapis.com/compute/v1beta13/projects/myproject/networks/default"))
.selfLink(URI.create("https://www.googleapis.com/compute/v1beta13/projects/myproject/networks/jclouds-test"))
.name("default")
.description("Default network for the project")
.IPv4Range("10.240.0.0/16")

View File

@ -45,8 +45,8 @@ public class ParseOperationTest extends BaseGoogleComputeParseTest<Operation> {
SimpleDateFormatDateService dateService = new SimpleDateFormatDateService();
return Operation.builder().id("13053095055850848306")
.selfLink(URI.create("https://www.googleapis" +
".com/compute/v1beta13/projects/myproject/operations/operation" +
"-1354084865060-4cf88735faeb8-bbbb12cb"))
".com/compute/v1beta13/projects/myproject/operations/operation-1354084865060-4cf88735faeb8" +
"-bbbb12cb"))
.name("operation-1354084865060-4cf88735faeb8-bbbb12cb")
.targetLink(URI.create("https://www.googleapis" +
".com/compute/v1beta13/projects/myproject/instances/instance-api-live" +
@ -57,15 +57,8 @@ public class ParseOperationTest extends BaseGoogleComputeParseTest<Operation> {
.progress(100)
.insertTime(dateService.iso8601DateParse("2012-11-28T06:41:05.060"))
.startTime(dateService.iso8601DateParse("2012-11-28T06:41:05.142"))
.endTime(dateService.iso8601DateParse("2012-11-28T06:41:06.142"))
.operationType("insert")
.httpErrorStatusCode(400)
.httpErrorMessage("BAD REQUEST")
.addError(Operation.Error.builder()
.code("RESOURCE_ALREADY_EXISTS")
.message("The resource " +
"'projects/myproject/instances/instance-api-live-test-instance' already" +
" exists")
.build())
.build();
}
}

View File

@ -3,10 +3,10 @@
"kind": "compute#firewall",
"id": "12862241031274216284",
"creationTimestamp": "2012-04-13T03:05:02.855",
"selfLink": "https://www.googleapis.com/compute/v1beta13/projects/google/firewalls/default-allow-internal",
"name": "default-allow-internal",
"selfLink": "https://www.googleapis.com/compute/v1beta13/projects/myproject/firewalls/jclouds-test",
"name": "jclouds-test",
"description": "Internal traffic from default allowed",
"network": "https://www.googleapis.com/compute/v1beta13/projects/google/networks/default",
"network": "https://www.googleapis.com/compute/v1beta13/projects/myproject/networks/jclouds-test",
"sourceRanges": [
"10.0.0.0/8"
],

View File

@ -1 +1 @@
{"network":"https://www.googleapis.com/compute/v1beta13/projects/myproject/networks/default","sourceRanges":["10.0.1.0/32"],"sourceTags":["tag1"],"targetTags":["tag2"],"allowed":[{"IPProtocol":"tcp","ports":["22","23-24"]}],"kind":"compute#firewall","name":"myfw"}
{"name":"%s","network":"https://www.googleapis.com/compute/v1beta13/projects/myproject/networks/%s","sourceRanges":[%s],"sourceTags":[%s],"targetTags":[%s],"allowed":[{"IPProtocol":"tcp","ports":[%s]}]}

View File

@ -8,10 +8,10 @@
"kind": "compute#firewall",
"id": "12862241031274216284",
"creationTimestamp": "2012-04-13T03:05:02.855",
"selfLink": "https://www.googleapis.com/compute/v1beta13/projects/google/firewalls/default-allow-internal",
"name": "default-allow-internal",
"selfLink": "https://www.googleapis.com/compute/v1beta13/projects/myproject/firewalls/jclouds-test",
"name": "jclouds-test",
"description": "Internal traffic from default allowed",
"network": "https://www.googleapis.com/compute/v1beta13/projects/google/networks/default",
"network": "https://www.googleapis.com/compute/v1beta13/projects/myproject/networks/jclouds-test",
"sourceRanges": [
"10.0.0.0/8"
],

View File

@ -3,9 +3,9 @@
"id": "13051190678907570425",
"description": "desc",
"creationTimestamp": "2012-11-25T23:48:20.758",
"selfLink": "https://www.googleapis.com/compute/v1beta13/projects/myproject/instances/test-instance",
"name": "test-instance",
"image": "https://www.googleapis.com/compute/v1beta13/projects/google/images/ubuntu-12-04-v20120912",
"selfLink": "https://www.googleapis.com/compute/v1beta13/projects/myproject/instances/test-0",
"name": "test-0",
"image": "https://www.googleapis.com/compute/v1beta13/projects/google/images/gcel-12-04-v20121106",
"machineType": "https://www.googleapis.com/compute/v1beta13/projects/myproject/machineTypes/n1-standard-1",
"status": "RUNNING",
"zone": "https://www.googleapis.com/compute/v1beta13/projects/myproject/zones/us-central1-a",

View File

@ -1 +1 @@
{"name":"test-instance","description":"desc","machineType":"https://www.googleapis.com/compute/v1beta13/projects/myproject/machineTypes/n1-standard-1","zone":"https://www.googleapis.com/compute/v1beta13/projects/myproject/zones/us-central1-a","image":"https://www.googleapis.com/compute/v1beta13/projects/google/images/ubuntu-12-04-v20120912","tags":["aTag"],"serviceAccounts":[{"email":"default","scopes":["myscope"]}],"networkInterfaces":[{"network":"https://www.googleapis.com/compute/v1beta13/projects/myproject/networks/default","accessConfigs":[{"name":"external","type":"ONE_TO_ONE_NAT"}]}],"disks":[{"mode":"READ_WRITE","source":"https://www.googleapis.com/compute/v1beta13/projects/myproject/disks/test","type":"PERSISTENT"}],"metadata":{"kind":"compute#metadata","items":[{"key":"aKey","value":"aValue"}]}}
{"name":"test-0","description":"desc","machineType":"https://www.googleapis.com/compute/v1beta13/projects/myproject/machineTypes/n1-standard-1","zone":"https://www.googleapis.com/compute/v1beta13/projects/myproject/zones/us-central1-a","image":"https://www.googleapis.com/compute/v1beta13/projects/google/images/gcel-12-04-v20121106","tags":["aTag"],"serviceAccounts":[{"email":"default","scopes":["myscope"]}],"networkInterfaces":[{"network":"https://www.googleapis.com/compute/v1beta13/projects/myproject/networks/default","accessConfigs":[{"type":"ONE_TO_ONE_NAT"}]}],"disks":[{"mode":"READ_WRITE","source":"https://www.googleapis.com/compute/v1beta13/projects/myproject/disks/test","type":"PERSISTENT"}],"metadata":{"kind":"compute#metadata","items":[{"key":"aKey","value":"aValue"}]}}

View File

@ -1 +1 @@
{"name":"test-instance","machineType":"https://www.googleapis.com/compute/v1beta13/projects/myproject/machineTypes/n1-standard-1","zone":"https://www.googleapis.com/compute/v1beta13/projects/myproject/zones/us-central1-a","tags":[],"serviceAccounts":[],"networkInterfaces":[{"network":"https://www.googleapis.com/compute/v1beta13/projects/myproject/networks/default","accessConfigs":[{"name":"external","type":"ONE_TO_ONE_NAT"}]}]}
{"name":"test-1","machineType":"https://www.googleapis.com/compute/v1beta13/projects/myproject/machineTypes/n1-standard-1","zone":"https://www.googleapis.com/compute/v1beta13/projects/myproject/zones/us-central1-a","tags":[],"serviceAccounts":[],"networkInterfaces":[{"network":"https://www.googleapis.com/compute/v1beta13/projects/myproject/networks/default","accessConfigs":[]}]}

View File

@ -8,9 +8,9 @@
"id": "13051190678907570425",
"description": "desc",
"creationTimestamp": "2012-11-25T23:48:20.758",
"selfLink": "https://www.googleapis.com/compute/v1beta13/projects/myproject/instances/test-instance",
"name": "test-instance",
"image": "https://www.googleapis.com/compute/v1beta13/projects/google/images/ubuntu-12-04-v20120912",
"selfLink": "https://www.googleapis.com/compute/v1beta13/projects/myproject/instances/test-0",
"name": "test-0",
"image": "https://www.googleapis.com/compute/v1beta13/projects/google/images/gcel-12-04-v20121106",
"machineType": "https://www.googleapis.com/compute/v1beta13/projects/myproject/machineTypes/n1-standard-1",
"status": "RUNNING",
"zone": "https://www.googleapis.com/compute/v1beta13/projects/myproject/zones/us-central1-a",

View File

@ -2,7 +2,7 @@
"kind": "compute#network",
"id": "13024414170909937976",
"creationTimestamp": "2012-10-24T20:13:19.967",
"selfLink": "https://www.googleapis.com/compute/v1beta13/projects/myproject/networks/default",
"selfLink": "https://www.googleapis.com/compute/v1beta13/projects/myproject/networks/jclouds-test",
"name": "default",
"description": "Default network for the project",
"IPv4Range": "10.240.0.0/16",

View File

@ -8,7 +8,7 @@
"kind": "compute#network",
"id": "13024414170909937976",
"creationTimestamp": "2012-10-24T20:13:19.967",
"selfLink": "https://www.googleapis.com/compute/v1beta13/projects/myproject/networks/default",
"selfLink": "https://www.googleapis.com/compute/v1beta13/projects/myproject/networks/jclouds-test",
"name": "default",
"description": "Default network for the project",
"IPv4Range": "10.240.0.0/16",

View File

@ -10,15 +10,6 @@
"progress": 100,
"insertTime": "2012-11-28T06:41:05.060",
"startTime": "2012-11-28T06:41:05.142",
"httpErrorStatusCode": 400,
"httpErrorMessage": "BAD REQUEST",
"error": {
"errors": [
{
"code": "RESOURCE_ALREADY_EXISTS",
"message": "The resource 'projects/myproject/instances/instance-api-live-test-instance' already exists"
}
]
},
"endTime": "2012-11-28T06:41:06.142",
"operationType": "insert"
}

View File

@ -0,0 +1,24 @@
{
"kind": "compute#operation",
"id": "13053095055850848306",
"selfLink": "https://www.googleapis.com/compute/v1beta13/projects/myproject/operations/operation-1354084865060-4cf88735faeb8-bbbb12cb",
"name": "operation-1354084865060-4cf88735faeb8-bbbb12cb",
"targetLink": "https://www.googleapis.com/compute/v1beta13/projects/myproject/instances/instance-api-live-test-instance",
"targetId": "13053094017547040099",
"status": "DONE",
"user": "user@developer.gserviceaccount.com",
"progress": 100,
"insertTime": "2012-11-28T06:41:05.060",
"startTime": "2012-11-28T06:41:05.142",
"httpErrorStatusCode": 400,
"httpErrorMessage": "BAD REQUEST",
"error": {
"errors": [
{
"code": "RESOURCE_ALREADY_EXISTS",
"message": "The resource 'projects/myproject/instances/instance-api-live-test-instance' already exists"
}
]
},
"operationType": "insert"
}

View File

@ -15,16 +15,7 @@
"progress": 100,
"insertTime": "2012-11-28T06:41:05.060",
"startTime": "2012-11-28T06:41:05.142",
"httpErrorStatusCode": 400,
"httpErrorMessage": "BAD REQUEST",
"error": {
"errors": [
{
"code": "RESOURCE_ALREADY_EXISTS",
"message": "The resource 'projects/myproject/instances/instance-api-live-test-instance' already exists"
}
]
},
"endTime": "2012-11-28T06:41:06.142",
"operationType": "insert"
}
]