JCLOUDS-1122: Support subnetworks definitions in Google Compute.

This commit is contained in:
Nelson Araujo 2016-08-06 23:33:29 -07:00 committed by Ignasi Barrera
parent db2f86bcec
commit 2ec28df21b
18 changed files with 701 additions and 10 deletions

View File

@ -17,11 +17,13 @@
package org.jclouds.googlecomputeengine; package org.jclouds.googlecomputeengine;
import java.io.Closeable; import java.io.Closeable;
import java.net.URI;
import javax.ws.rs.Path; import javax.ws.rs.Path;
import javax.ws.rs.PathParam; import javax.ws.rs.PathParam;
import org.jclouds.googlecloud.config.CurrentProject; import org.jclouds.googlecloud.config.CurrentProject;
import org.jclouds.googlecomputeengine.domain.Subnetwork;
import org.jclouds.googlecomputeengine.features.AddressApi; import org.jclouds.googlecomputeengine.features.AddressApi;
import org.jclouds.googlecomputeengine.features.AggregatedListApi; import org.jclouds.googlecomputeengine.features.AggregatedListApi;
import org.jclouds.googlecomputeengine.features.BackendServiceApi; import org.jclouds.googlecomputeengine.features.BackendServiceApi;
@ -40,6 +42,8 @@ import org.jclouds.googlecomputeengine.features.ProjectApi;
import org.jclouds.googlecomputeengine.features.RegionApi; import org.jclouds.googlecomputeengine.features.RegionApi;
import org.jclouds.googlecomputeengine.features.RouteApi; import org.jclouds.googlecomputeengine.features.RouteApi;
import org.jclouds.googlecomputeengine.features.SnapshotApi; import org.jclouds.googlecomputeengine.features.SnapshotApi;
import org.jclouds.googlecomputeengine.features.SubnetworkApi;
import org.jclouds.googlecomputeengine.features.TargetHttpProxyApi;
import org.jclouds.googlecomputeengine.features.TargetInstanceApi; import org.jclouds.googlecomputeengine.features.TargetInstanceApi;
import org.jclouds.googlecomputeengine.features.TargetPoolApi; import org.jclouds.googlecomputeengine.features.TargetPoolApi;
import org.jclouds.googlecomputeengine.features.TargetHttpProxyApi; import org.jclouds.googlecomputeengine.features.TargetHttpProxyApi;
@ -47,6 +51,7 @@ import org.jclouds.googlecomputeengine.features.UrlMapApi;
import org.jclouds.googlecomputeengine.features.ZoneApi; import org.jclouds.googlecomputeengine.features.ZoneApi;
import org.jclouds.rest.annotations.Delegate; import org.jclouds.rest.annotations.Delegate;
import org.jclouds.rest.annotations.Endpoint; import org.jclouds.rest.annotations.Endpoint;
import org.jclouds.rest.annotations.EndpointParam;
public interface GoogleComputeEngineApi extends Closeable { public interface GoogleComputeEngineApi extends Closeable {
@ -116,6 +121,11 @@ public interface GoogleComputeEngineApi extends Closeable {
@Path("/global") @Path("/global")
NetworkApi networks(); NetworkApi networks();
@Delegate
@Endpoint(CurrentProject.class)
@Path("/regions/{region}")
SubnetworkApi subnetworksInRegion(@PathParam("region") String region);
@Delegate @Delegate
OperationApi operations(); OperationApi operations();
@ -159,5 +169,4 @@ public interface GoogleComputeEngineApi extends Closeable {
@Endpoint(CurrentProject.class) @Endpoint(CurrentProject.class)
@Path("/global/urlMaps") @Path("/global/urlMaps")
UrlMapApi urlMaps(); UrlMapApi urlMaps();
} }

View File

@ -136,11 +136,17 @@ public final class GoogleComputeEngineServiceAdapter
URI network = URI.create(networks.next()); URI network = URI.create(networks.next());
assert !networks.hasNext() : "Error: Options should specify only one network"; assert !networks.hasNext() : "Error: Options should specify only one network";
Iterator<String> subnetworks = options.getSubnetworks().iterator();
URI subnetwork = subnetworks.hasNext() ? URI.create(subnetworks.next()) : null;
assert !subnetworks.hasNext() : "Error: Options should specify only one subnetwork";
Scheduling scheduling = getScheduling(options); Scheduling scheduling = getScheduling(options);
NewInstance newInstance = new NewInstance.Builder( name, NewInstance newInstance = new NewInstance.Builder(name,
template.getHardware().getUri(), // machineType template.getHardware().getUri(), // machineType
network, network,
subnetwork,
disks) disks)
.description(group) .description(group)
.tags(Tags.create(null, ImmutableList.copyOf(options.getTags()))) .tags(Tags.create(null, ImmutableList.copyOf(options.getTags())))

View File

@ -32,6 +32,7 @@ import org.jclouds.googlecomputeengine.domain.Image;
import org.jclouds.googlecomputeengine.domain.Instance; import org.jclouds.googlecomputeengine.domain.Instance;
import org.jclouds.googlecomputeengine.domain.Network; import org.jclouds.googlecomputeengine.domain.Network;
import org.jclouds.googlecomputeengine.domain.Operation; import org.jclouds.googlecomputeengine.domain.Operation;
import org.jclouds.googlecomputeengine.domain.Subnetwork;
import org.jclouds.javax.annotation.Nullable; import org.jclouds.javax.annotation.Nullable;
import org.jclouds.oauth.v2.filters.OAuthFilter; import org.jclouds.oauth.v2.filters.OAuthFilter;
import org.jclouds.rest.annotations.EndpointParam; import org.jclouds.rest.annotations.EndpointParam;
@ -82,6 +83,10 @@ public interface Resources {
@Path("/stop") @Path("/stop")
Operation stopInstance(@EndpointParam URI selfLink); Operation stopInstance(@EndpointParam URI selfLink);
@Named("Subnetworks:get")
@GET
@Fallback(NullOnNotFoundOr404.class) @Nullable Subnetwork subnetwork(@EndpointParam URI selfLink);
/** Returns a disk by self-link or null if not found. */ /** Returns a disk by self-link or null if not found. */
@Named("Disks:get") @Named("Disks:get")
@GET @GET

View File

@ -0,0 +1,57 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.googlecomputeengine.compute.loaders;
import java.net.URI;
import java.util.concurrent.ExecutionException;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.googlecomputeengine.compute.functions.Resources;
import org.jclouds.googlecomputeengine.domain.Subnetwork;
import org.jclouds.logging.Logger;
import com.google.common.cache.CacheLoader;
@Singleton
public class SubnetworkLoader extends CacheLoader<URI, Subnetwork> {
@Resource
protected Logger logger = Logger.NULL;
private final Resources resources;
@Inject
SubnetworkLoader(Resources resources) {
this.resources = resources;
}
@Override
public Subnetwork load(URI key) throws ExecutionException {
try {
return resources.subnetwork(key);
} catch (Exception e) {
throw new ExecutionException(message(key, e), e);
}
}
public static String message(URI key, Exception e) {
return String.format("could not find image for disk %s: %s", key.toString(), e.getMessage());
}
}

View File

@ -18,12 +18,15 @@ package org.jclouds.googlecomputeengine.compute.options;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
import org.jclouds.compute.options.TemplateOptions; import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.domain.LoginCredentials; import org.jclouds.domain.LoginCredentials;
import org.jclouds.googlecomputeengine.domain.Instance.ServiceAccount; import org.jclouds.googlecomputeengine.domain.Instance.ServiceAccount;
import org.jclouds.scriptbuilder.domain.Statement; import org.jclouds.scriptbuilder.domain.Statement;
import com.google.common.collect.ImmutableSet;
/** Instance options specific to Google Compute Engine. */ /** Instance options specific to Google Compute Engine. */
public final class GoogleComputeEngineTemplateOptions extends TemplateOptions { public final class GoogleComputeEngineTemplateOptions extends TemplateOptions {
@ -32,6 +35,7 @@ public final class GoogleComputeEngineTemplateOptions extends TemplateOptions {
private List<ServiceAccount> serviceAccounts; private List<ServiceAccount> serviceAccounts;
private String bootDiskType; private String bootDiskType;
private boolean preemptible = false; private boolean preemptible = false;
private Set<String> subnetworks;
@Override @Override
public GoogleComputeEngineTemplateOptions clone() { public GoogleComputeEngineTemplateOptions clone() {
@ -134,6 +138,11 @@ public final class GoogleComputeEngineTemplateOptions extends TemplateOptions {
return serviceAccounts; return serviceAccounts;
} }
public Set<String> getSubnetworks() {
return subnetworks;
}
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@ -286,6 +295,22 @@ public final class GoogleComputeEngineTemplateOptions extends TemplateOptions {
return GoogleComputeEngineTemplateOptions.class.cast(super.networks(networks)); return GoogleComputeEngineTemplateOptions.class.cast(super.networks(networks));
} }
/**
* Assigns subnetworks to the machine.
*/
public GoogleComputeEngineTemplateOptions subnetworks(Iterable<String> networks) {
this.subnetworks = ImmutableSet.copyOf(networks);
return this;
}
/**
* Assigns subnetworks to the machine.
*/
public GoogleComputeEngineTemplateOptions subnetworks(String... networks) {
this.subnetworks = ImmutableSet.copyOf(networks);
return this;
}
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */

View File

@ -18,11 +18,13 @@ package org.jclouds.googlecomputeengine.domain;
import java.net.URI; import java.net.URI;
import java.util.Date; import java.util.Date;
import java.util.List;
import org.jclouds.javax.annotation.Nullable; import org.jclouds.javax.annotation.Nullable;
import org.jclouds.json.SerializedNames; import org.jclouds.json.SerializedNames;
import com.google.auto.value.AutoValue; import com.google.auto.value.AutoValue;
import com.google.common.base.Strings;
/** /**
* Represents a network used to enable instance communication. * Represents a network used to enable instance communication.
@ -30,6 +32,12 @@ import com.google.auto.value.AutoValue;
@AutoValue @AutoValue
public abstract class Network { public abstract class Network {
public enum NetworkType {
LegacyNetwork,
AutoSubnetwork,
CustomNetwork,
}
public abstract String id(); public abstract String id();
public abstract Date creationTimestamp(); public abstract Date creationTimestamp();
@ -38,6 +46,8 @@ public abstract class Network {
public abstract String name(); public abstract String name();
public abstract NetworkType type();
@Nullable public abstract String description(); @Nullable public abstract String description();
/** /**
@ -52,10 +62,23 @@ public abstract class Network {
*/ */
@Nullable public abstract String gatewayIPv4(); @Nullable public abstract String gatewayIPv4();
@SerializedNames({ "id", "creationTimestamp", "selfLink", "name", "description", "IPv4Range", "gatewayIPv4" }) @Nullable public abstract List<URI> subnetworks();
public static Network create(String id, Date creationTimestamp, URI selfLink, String name, String description, String rangeIPv4, public static Network create(String id, Date creationTimestamp, URI selfLink, String name, String description, String rangeIPv4,
String gatewayIPv4) { String gatewayIPv4) {
return new AutoValue_Network(id, creationTimestamp, selfLink, name, description, rangeIPv4, gatewayIPv4); return new AutoValue_Network(id, creationTimestamp, selfLink, name, NetworkType.LegacyNetwork, description,
rangeIPv4, gatewayIPv4, null);
}
@SerializedNames({ "id", "creationTimestamp", "selfLink", "name", "description", "IPv4Range", "gatewayIPv4", "autoCreateSubnetworks", "subnetworks" })
public static Network create(String id, Date creationTimestamp, URI selfLink, String name, String description, String rangeIPv4,
String gatewayIPv4, String autoCreateSubnetworks, List<URI> subnetworks) {
NetworkType type;
type = !Strings.isNullOrEmpty(rangeIPv4) ? NetworkType.LegacyNetwork
: (autoCreateSubnetworks.equals("true") ? NetworkType.AutoSubnetwork
: NetworkType.CustomNetwork);
return new AutoValue_Network(id, creationTimestamp, selfLink, name, type, description, rangeIPv4, gatewayIPv4,
subnetworks);
} }
Network() { Network() {

View File

@ -39,6 +39,7 @@ public abstract class NewInstance {
@AutoValue @AutoValue
abstract static class NetworkInterface { abstract static class NetworkInterface {
abstract URI network(); abstract URI network();
@Nullable abstract URI subnetwork();
abstract List<AccessConfig> accessConfigs(); abstract List<AccessConfig> accessConfigs();
@ -46,9 +47,19 @@ public abstract class NewInstance {
return create(network, Arrays.asList(AccessConfig.create(null, Type.ONE_TO_ONE_NAT, null))); return create(network, Arrays.asList(AccessConfig.create(null, Type.ONE_TO_ONE_NAT, null)));
} }
static NetworkInterface create(URI network, URI subnetwork) {
return create(network, subnetwork,
Arrays.asList(AccessConfig.create(null, Type.ONE_TO_ONE_NAT, null)));
}
@SerializedNames({ "network", "accessConfigs" }) @SerializedNames({ "network", "accessConfigs" })
static NetworkInterface create(URI network, List<AccessConfig> accessConfigs) { static NetworkInterface create(URI network, List<AccessConfig> accessConfigs) {
return new AutoValue_NewInstance_NetworkInterface(network, accessConfigs); return new AutoValue_NewInstance_NetworkInterface(network, null, accessConfigs);
}
@SerializedNames({ "network", "subnetwork", "accessConfigs" })
static NetworkInterface create(URI network, URI subnetwork, List<AccessConfig> accessConfigs) {
return new AutoValue_NewInstance_NetworkInterface(network, subnetwork, accessConfigs);
} }
NetworkInterface() { NetworkInterface() {
@ -81,8 +92,18 @@ public abstract class NewInstance {
return create(name, machineType, network, Arrays.asList(AttachDisk.newBootDisk(sourceImage)), null, null); return create(name, machineType, network, Arrays.asList(AttachDisk.newBootDisk(sourceImage)), null, null);
} }
public static NewInstance create(String name, URI machineType, URI network, URI subnetwork, URI sourceImage) {
return create(name, machineType, network, subnetwork, Arrays.asList(AttachDisk.newBootDisk(sourceImage)), null,
null);
}
public static NewInstance create(String name, URI machineType, URI network, List<AttachDisk> disks, public static NewInstance create(String name, URI machineType, URI network, List<AttachDisk> disks,
@Nullable String description, @Nullable Tags tags) { @Nullable String description, @Nullable Tags tags) {
return create(name, machineType, network, null, disks, description, tags);
}
public static NewInstance create(String name, URI machineType, URI network, @Nullable URI subnetwork,
List<AttachDisk> disks, @Nullable String description, @Nullable Tags tags) {
checkArgument(disks.get(0).boot(), "disk 0 must be a boot disk! %s", disks); checkArgument(disks.get(0).boot(), "disk 0 must be a boot disk! %s", disks);
boolean foundBoot = false; boolean foundBoot = false;
for (AttachDisk disk : disks) { for (AttachDisk disk : disks) {
@ -127,6 +148,14 @@ public abstract class NewInstance {
this.disks = disks; this.disks = disks;
} }
public Builder(String name, URI machineType, URI network, URI subnetwork, List<AttachDisk> disks) {
checkNotNull(name, "NewInstance name cannot be null");
this.name = name;
this.machineType = machineType;
this.networkInterfaces = ImmutableList.of(NetworkInterface.create(network, subnetwork));
this.disks = disks;
}
public Builder(String name, URI machineType, URI network, URI sourceImage) { public Builder(String name, URI machineType, URI network, URI sourceImage) {
checkNotNull(name, "NewInstance name cannot be null"); checkNotNull(name, "NewInstance name cannot be null");
this.name = name; this.name = name;
@ -135,6 +164,14 @@ public abstract class NewInstance {
this.disks = Arrays.asList(AttachDisk.newBootDisk(sourceImage)); this.disks = Arrays.asList(AttachDisk.newBootDisk(sourceImage));
} }
public Builder(String name, URI machineType, URI network, URI subnetwork, URI sourceImage) {
checkNotNull(name, "NewInstance name cannot be null");
this.name = name;
this.machineType = machineType;
this.networkInterfaces = ImmutableList.of(NetworkInterface.create(network, subnetwork));
this.disks = Arrays.asList(AttachDisk.newBootDisk(sourceImage));
}
public Builder canIpForward(Boolean canIpForward){ public Builder canIpForward(Boolean canIpForward){
this.canIpForward = canIpForward; this.canIpForward = canIpForward;
return this; return this;

View File

@ -0,0 +1,62 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.googlecomputeengine.domain;
import java.net.URI;
import java.util.Date;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.json.SerializedNames;
import com.google.auto.value.AutoValue;
/**
* Represents a network used to enable instance communication.
*/
@AutoValue
public abstract class Subnetwork {
public abstract String id();
public abstract Date creationTimestamp();
public abstract URI selfLink();
public abstract String name();
@Nullable public abstract String description();
public abstract String gatewayAddress();
public abstract URI network();
public abstract String ipCidrRange();
public abstract URI region();
@SerializedNames({ "id", "creationTimestamp", "selfLink", "name",
"description", "gatewayAddress", "network", "ipCidrRange", "region" })
public static Subnetwork create(String id, Date creationTimestamp, URI selfLink, String name,
String description, String gatewayAddress, URI network,
String ipCidrRange, URI region) {
return new AutoValue_Subnetwork(id, creationTimestamp, selfLink, name, description,
gatewayAddress, network, ipCidrRange, region);
}
Subnetwork() {
}
}

View File

@ -36,6 +36,7 @@ import org.jclouds.googlecomputeengine.domain.ForwardingRule;
import org.jclouds.googlecomputeengine.domain.Instance; import org.jclouds.googlecomputeengine.domain.Instance;
import org.jclouds.googlecomputeengine.domain.MachineType; import org.jclouds.googlecomputeengine.domain.MachineType;
import org.jclouds.googlecomputeengine.domain.Operation; import org.jclouds.googlecomputeengine.domain.Operation;
import org.jclouds.googlecomputeengine.domain.Subnetwork;
import org.jclouds.googlecomputeengine.domain.TargetInstance; import org.jclouds.googlecomputeengine.domain.TargetInstance;
import org.jclouds.googlecomputeengine.domain.TargetPool; import org.jclouds.googlecomputeengine.domain.TargetPool;
import org.jclouds.googlecomputeengine.internal.BaseToIteratorOfListPage; import org.jclouds.googlecomputeengine.internal.BaseToIteratorOfListPage;
@ -498,4 +499,53 @@ public interface AggregatedListApi {
}; };
} }
} }
/**
* Retrieves the list of instance resources available to the specified
* project. By default the list as a maximum size of 100, if no options are
* provided or ListOptions#getMaxResults() has not been set.
*
* @param pageToken
* marks the beginning of the next list page
* @param listOptions
* listing options
* @return a page of the list
*/
@Named("Subnetworks:aggregatedList")
@GET
@Path("/subnetworks")
ListPage<Subnetwork> pageOfSubnetworks(@Nullable @QueryParam("pageToken") String pageToken, ListOptions listOptions);
/** @see #pageOfSubnetworks(String, ListOptions) */
@Named("Subnetworks:aggregatedList")
@GET
@Path("/subnetworks")
@Transform(SubnetworksPages.class)
Iterator<ListPage<Subnetwork>> subnetworks();
/** @see #pageOfSubnetworks(String, ListOptions) */
@Named("Subnetworks:aggregatedList")
@GET
@Path("/subnetworks")
@Transform(SubnetworksPages.class)
Iterator<ListPage<Subnetwork>> subnetworks(ListOptions options);
static final class SubnetworksPages extends BaseToIteratorOfListPage<Subnetwork, SubnetworksPages> {
private final GoogleComputeEngineApi api;
@Inject
SubnetworksPages(GoogleComputeEngineApi api) {
this.api = api;
}
@Override
protected Function<String, ListPage<Subnetwork>> fetchNextPage(final ListOptions options) {
return new Function<String, ListPage<Subnetwork>>() {
@Override
public ListPage<Subnetwork> apply(String pageToken) {
return api.aggregatedList().pageOfSubnetworks(pageToken, options);
}
};
}
}
} }

View File

@ -83,9 +83,7 @@ public interface NetworkApi {
/** /**
* Creates a persistent network resource in the specified project with the specified range and specified gateway. * Creates a persistent network resource in the specified project with the specified range and specified gateway.
* *
* @param networkName the network name * @param options the options to create the network.
* @param IPv4Range the range of the network to be inserted.
* @param gatewayIPv4 the range of the network to be inserted.
* @return an Operation resource. To check on the status of an operation, poll the Operations resource returned to * @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. * you, and look for the status field.
*/ */
@ -126,7 +124,7 @@ public interface NetworkApi {
@Transform(NetworkPages.class) @Transform(NetworkPages.class)
Iterator<ListPage<Network>> list(ListOptions options); Iterator<ListPage<Network>> list(ListOptions options);
static final class NetworkPages extends BaseToIteratorOfListPage<Network, NetworkPages> { final class NetworkPages extends BaseToIteratorOfListPage<Network, NetworkPages> {
private final GoogleComputeEngineApi api; private final GoogleComputeEngineApi api;

View File

@ -0,0 +1,127 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.googlecomputeengine.features;
import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
import java.net.URI;
import java.util.Iterator;
import javax.inject.Inject;
import javax.inject.Named;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
import org.jclouds.googlecloud.domain.ListPage;
import org.jclouds.googlecomputeengine.GoogleComputeEngineApi;
import org.jclouds.googlecomputeengine.domain.Operation;
import org.jclouds.googlecomputeengine.domain.Subnetwork;
import org.jclouds.googlecomputeengine.internal.BaseCallerArg0ToIteratorOfListPage;
import org.jclouds.googlecomputeengine.options.ListOptions;
import org.jclouds.googlecomputeengine.options.SubnetworkCreationOptions;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.oauth.v2.filters.OAuthFilter;
import org.jclouds.rest.annotations.BinderParam;
import org.jclouds.rest.annotations.Delegate;
import org.jclouds.rest.annotations.EndpointParam;
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.SkipEncoding;
import org.jclouds.rest.annotations.Transform;
import org.jclouds.rest.binders.BindToJsonPayload;
import com.google.common.base.Function;
@SkipEncoding({'/', '='})
@RequestFilters(OAuthFilter.class)
@Path("/subnetworks")
@Consumes(APPLICATION_JSON)
public interface SubnetworkApi {
/**
* Returns a network by name or null if not found.
*/
@Named("Subnetworks:get")
@GET
@Path("/{subnetwork}")
@Fallback(NullOnNotFoundOr404.class)
Subnetwork get(@PathParam("subnetwork") String subnetworkName);
/**
* Creates a persistent network resource in the specified project with the specified range and specified gateway.
*
* @param newSubnetwork definition of the subnetwork.
* @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.
*/
@Named("Subnetworks:insert")
@POST
@Produces(APPLICATION_JSON)
Operation createInNetwork(@BinderParam(BindToJsonPayload.class) SubnetworkCreationOptions newSubnetwork);
/** Deletes a network by name and returns the operation in progress, or null if not found. */
@Named("Subnetworks:delete")
@DELETE
@Path("/{subnetwork}")
@Fallback(NullOnNotFoundOr404.class)
Operation delete(@PathParam("subnetwork") String subnetworkName);
/**
* Retrieves the list of network resources available to the specified project.
* By default the list as a maximum size of 100, if no options are provided or ListOptions#getMaxResults() has not
* been set.
*
* @param pageToken marks the beginning of the next list page
* @param listOptions listing options
* @return a page of the list
*/
@Named("Subnetworks:list")
@GET
ListPage<Subnetwork> listPage(@Nullable @QueryParam("pageToken") String pageToken, ListOptions listOptions);
/** @see #listPage(String, ListOptions) */
@Named("Subnetworks:list")
@GET
@Transform(SubnetworkPages.class)
Iterator<ListPage<Subnetwork>> list();
static final class SubnetworkPages extends BaseCallerArg0ToIteratorOfListPage<Subnetwork, SubnetworkPages> {
private final GoogleComputeEngineApi api;
@Inject SubnetworkPages(GoogleComputeEngineApi api) {
this.api = api;
}
@Override protected Function<String, ListPage<Subnetwork>> fetchNextPage(final String region, final ListOptions options) {
return new Function<String, ListPage<Subnetwork>>() {
@Override public ListPage<Subnetwork> apply(String pageToken) {
return api.subnetworksInRegion(region).listPage(pageToken, options);
}
};
}
}
}

View File

@ -0,0 +1,52 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.googlecomputeengine.options;
import static com.google.common.base.Preconditions.checkNotNull;
import java.net.URI;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.json.SerializedNames;
import com.google.auto.value.AutoValue;
/**
* Represents a subnetwork used to enable instance communication.
*/
@AutoValue
public abstract class SubnetworkCreationOptions {
public abstract String name();
@Nullable public abstract String description();
public abstract URI network();
public abstract String ipCidrRange();
public abstract URI region();
@SerializedNames({ "name", "description", "network", "ipCidrRange", "region" })
public static SubnetworkCreationOptions create(String name, String description, URI network,
String ipCidrRange, URI region) {
return new AutoValue_SubnetworkCreationOptions(name, description, network, ipCidrRange, region);
}
SubnetworkCreationOptions() {
}
}

View File

@ -0,0 +1,95 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.googlecomputeengine.features;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertNull;
import java.net.URI;
import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineApiMockTest;
import org.jclouds.googlecomputeengine.options.SubnetworkCreationOptions;
import org.jclouds.googlecomputeengine.parse.ParseSubnetworkListTest;
import org.jclouds.googlecomputeengine.parse.ParseSubnetworkTest;
import org.jclouds.googlecomputeengine.parse.ParseOperationTest;
import org.testng.annotations.Test;
@Test(groups = "unit", testName = "SubnetworkApiMockTest", singleThreaded = true)
public class SubnetworkApiMockTest extends BaseGoogleComputeEngineApiMockTest {
public void get() throws Exception {
server.enqueue(jsonResponse("/subnetwork_get.json"));
assertEquals(subnetworkApi().get("jclouds-test"),
new ParseSubnetworkTest().expected(url("/projects")));
assertSent(server, "GET", "/projects/party/regions/someregion/subnetworks/jclouds-test");
}
public void get_4xx() throws Exception {
server.enqueue(response404());
assertNull(subnetworkApi().get("jclouds-test"));
assertSent(server, "GET", "/projects/party/regions/someregion/subnetworks/jclouds-test");
}
public void insert() throws Exception {
server.enqueue(jsonResponse("/operation.json"));
assertEquals(subnetworkApi().createInNetwork(SubnetworkCreationOptions.create(
"jclouds-test",
"my subnetwork",
URI.create(url("/projects/party/global/networks/mynetwork")),
"10.0.0.0/24",
URI.create(url("/projects/party/regions/someregion")))), new ParseOperationTest().expected(url("/projects")));
assertSent(server, "POST", "/projects/party/regions/someregion/subnetworks",
stringFromResource("/subnetwork_insert.json"));
}
public void delete() throws Exception {
server.enqueue(jsonResponse("/operation.json"));
assertEquals(subnetworkApi().delete("jclouds-test"),
new ParseOperationTest().expected(url("/projects")));
assertSent(server, "DELETE", "/projects/party/regions/someregion/subnetworks/jclouds-test");
}
public void delete_4xx() throws Exception {
server.enqueue(response404());
assertNull(subnetworkApi().delete("jclouds-test"));
assertSent(server, "DELETE", "/projects/party/regions/someregion/subnetworks/jclouds-test");
}
public void list() throws Exception {
server.enqueue(jsonResponse("/subnetwork_list.json"));
assertEquals(subnetworkApi().list().next(), new ParseSubnetworkListTest().expected(url("/projects")));
assertSent(server, "GET", "/projects/party/regions/someregion/subnetworks");
}
public void list_empty() throws Exception {
server.enqueue(jsonResponse("/list_empty.json"));
assertFalse(subnetworkApi().list().hasNext());
assertSent(server, "GET", "/projects/party/regions/someregion/subnetworks");
}
SubnetworkApi subnetworkApi() {
return api().subnetworksInRegion("someregion");
}
}

View File

@ -0,0 +1,51 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.googlecomputeengine.parse;
import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
import javax.ws.rs.Consumes;
import org.jclouds.googlecloud.domain.ForwardingListPage;
import org.jclouds.googlecloud.domain.ListPage;
import org.jclouds.googlecomputeengine.domain.Subnetwork;
import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineParseTest;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableList;
@Test(groups = "unit", testName = "ParseSubnetworkListTest")
public class ParseSubnetworkListTest extends BaseGoogleComputeEngineParseTest<ListPage<Subnetwork>> {
@Override
public String resource() {
return "/network_list.json";
}
@Override @Consumes(APPLICATION_JSON)
public ListPage<Subnetwork> expected() {
return expected(BASE_URL);
}
@Consumes(APPLICATION_JSON)
public ListPage<Subnetwork> expected(String baseUrl) {
return ForwardingListPage.create( //
ImmutableList.of(new ParseSubnetworkTest().expected(baseUrl)), // items
null // nextPageToken
);
}
}

View File

@ -0,0 +1,56 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.googlecomputeengine.parse;
import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
import java.net.URI;
import javax.ws.rs.Consumes;
import org.jclouds.googlecomputeengine.domain.Subnetwork;
import org.jclouds.googlecomputeengine.internal.BaseGoogleComputeEngineParseTest;
import org.testng.annotations.Test;
@Test(groups = "unit", testName = "ParseSubnetworkTest")
public class ParseSubnetworkTest extends BaseGoogleComputeEngineParseTest<Subnetwork> {
@Override
public String resource() {
return "/network_get.json";
}
@Override @Consumes(APPLICATION_JSON)
public Subnetwork expected() {
return expected(BASE_URL);
}
@Consumes(APPLICATION_JSON)
public Subnetwork expected(String baseUrl) {
return Subnetwork.create( //
"5850679262666457680", // id
parse("2016-06-07T14:29:35.476-07:00"), // creationTimestamp
URI.create(baseUrl + "/party/regions/someregion/subnetworks/jclouds-test"), // selfLink
"jclouds-subnetwork-test", // name
"A custom subnetwork for the project", // description
"10.128.0.1",
URI.create(baseUrl + "/party/global/networks/mynetwork"), // network
"10.128.0.0/20", // rangeIPv4
URI.create(baseUrl + "/party/regions/someregion") // region
);
}
}

View File

@ -0,0 +1,12 @@
{
"kind": "compute#subnetwork",
"id": "5850679262666457680",
"creationTimestamp": "2016-06-07T14:29:35.476-07:00",
"gatewayAddress": "10.128.0.1",
"name": "jclouds-subnetwork-test",
"network": "https://www.googleapis.com/compute/v1/projects/party/global/networks/mynetwork",
"ipCidrRange": "10.128.0.0/20",
"region": "https://www.googleapis.com/compute/v1/projects/party/regions/someregion",
"selfLink": "https://www.googleapis.com/compute/v1/projects/party/regions/someregion/subnetworks/jclouds-test",
"description": "A custom subnetwork for the project"
}

View File

@ -0,0 +1,7 @@
{
"name": "jclouds-test",
"description": "my subnetwork",
"network": "https://www.googleapis.com/compute/v1/projects/party/global/networks/mynetwork",
"ipCidrRange": "10.0.0.0/24",
"region": "https://www.googleapis.com/compute/v1/projects/party/regions/someregion"
}

View File

@ -0,0 +1,19 @@
{
"kind": "compute#networkList",
"id": "projects/party/networks",
"selfLink": "https://www.googleapis.com/compute/v1/projects/party/regions/someregion/subnetworks",
"items": [
{
"kind": "compute#subnetwork",
"id": "5850679262666457680",
"creationTimestamp": "2016-06-07T14:29:35.476-07:00",
"gatewayAddress": "10.128.0.1",
"name": "jclouds-subnetwork-test",
"network": "https://www.googleapis.com/compute/v1/projects/party/global/networks/mynetwork",
"ipCidrRange": "10.128.0.0/20",
"region": "https://www.googleapis.com/compute/v1/projects/party/regions/someregion",
"selfLink": "https://www.googleapis.com/compute/v1/projects/party/regions/someregion/subnetworks/jclouds-test",
"description": "A custom subnetwork for the project"
}
]
}